2
0
mirror of https://github.com/koreader/koreader synced 2024-11-10 01:10:34 +00:00

VocabBuilder.koplugin: better handling of word context (#12469)

Closes #12465.
This commit is contained in:
weijiuqiao 2024-09-14 20:09:49 +08:00 committed by GitHub
parent 04aa0cbde3
commit 33525a80a0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 27 additions and 9 deletions

View File

@ -6,7 +6,7 @@ local logger = require("logger")
local db_location = DataStorage:getSettingsDir() .. "/vocabulary_builder.sqlite3"
local DB_SCHEMA_VERSION = 20221002
local DB_SCHEMA_VERSION = 20240905
local VOCABULARY_DB_SCHEMA = [[
-- To store looked up words
CREATE TABLE IF NOT EXISTS "vocabulary" (
@ -19,6 +19,7 @@ local VOCABULARY_DB_SCHEMA = [[
"prev_context" TEXT,
"next_context" TEXT,
"streak_count" INTEGER NOT NULL DEFAULT 0,
"highlight" TEXT,
PRIMARY KEY("word")
);
CREATE TABLE IF NOT EXISTS "title" (
@ -98,6 +99,10 @@ function VocabularyBuilder:createDB()
UPDATE vocabulary SET streak_count = review_count; ]])
if not ok then log(re) end
end
if db_version < 20240905 then
ok, re = pcall(db_conn.exec, db_conn, "ALTER TABLE vocabulary ADD highlight TEXT;")
if not ok then log(re) end
end
db_conn:exec("CREATE INDEX IF NOT EXISTS title_id_index ON vocabulary(title_id);")
-- Update version
@ -170,6 +175,7 @@ function VocabularyBuilder:_select_items(items, start_idx, reload_time, search_t
item.review_count = math.max(0, tonumber(results.review_count[i]))
item.streak_count = math.max(0, tonumber(results.streak_count[i]))
item.book_title = results.name[i] or ""
item.highlight = results.highlight[i]
item.create_time = tonumber( results.create_time[i])
item.review_time = nil --use this field to flag change
item.due_time = tonumber(results.due_time[i])
@ -278,17 +284,18 @@ function VocabularyBuilder:insertOrUpdate(entry)
stmt:step()
stmt:clearbind():reset()
stmt = conn:prepare([[INSERT INTO vocabulary (word, title_id, create_time, due_time, review_time, prev_context, next_context)
VALUES (?, (SELECT id FROM title WHERE name = ?), ?, ?, ?, ?, ?)
stmt = conn:prepare([[INSERT INTO vocabulary (word, title_id, create_time, due_time, review_time, prev_context, next_context, highlight)
VALUES (?, (SELECT id FROM title WHERE name = ?), ?, ?, ?, ?, ?, ?)
ON CONFLICT(word) DO UPDATE SET title_id = excluded.title_id,
create_time = excluded.create_time,
review_count = MAX(review_count-1, 0),
streak_count = 0,
due_time = ?,
prev_context = ifnull(excluded.prev_context, prev_context),
next_context = ifnull(excluded.next_context, next_context);]]);
next_context = ifnull(excluded.next_context, next_context),
highlight = ifnull(excluded.highlight, highlight);]]);
stmt:bind(entry.word, entry.book_title, entry.time, entry.time+300, entry.time,
entry.prev_context, entry.next_context, entry.time+300)
entry.prev_context, entry.next_context, entry.highlight, entry.time+300)
stmt:step()
stmt:clearbind():reset()
conn:close()
@ -396,6 +403,9 @@ function VocabularyBuilder.onSync(local_path, cached_path, income_path)
return true
end
-- Handle possible inconsistensies in db version
pcall(conn_income.exec, conn_income, "ALTER TABLE vocabulary ADD highlight TEXT;")
local sql = "attach '" .. income_path:gsub("'", "''") .."' as income_db;"
-- then we try to open cached db
local conn_cached = SQ3.open(cached_path)
@ -451,8 +461,8 @@ function VocabularyBuilder.onSync(local_path, cached_path, income_path)
-- Then we merge the income_db's contents into the local db
INSERT INTO vocabulary
(word, create_time, review_time, due_time, review_count, prev_context, next_context, title_id, streak_count)
SELECT word, create_time, review_time, due_time, review_count, prev_context, next_context, title_id, streak_count
(word, create_time, review_time, due_time, review_count, prev_context, next_context, title_id, streak_count, highlight)
SELECT word, create_time, review_time, due_time, review_count, prev_context, next_context, title_id, streak_count, highlight
FROM income_db.vocabulary WHERE true
ON CONFLICT(word) DO UPDATE SET
due_time = MAX(due_time, excluded.due_time),
@ -462,6 +472,7 @@ function VocabularyBuilder.onSync(local_path, cached_path, income_path)
END,
prev_context = ifnull(excluded.prev_context, prev_context),
next_context = ifnull(excluded.next_context, next_context),
highlight = ifnull(excluded.highlight, highlight),
streak_count = CASE
WHEN review_time > excluded.review_time THEN streak_count
ELSE excluded.streak_count

View File

@ -504,6 +504,7 @@ Individual word info dialogue widget
--]]--
local WordInfoDialog = FocusManager:extend{
title = nil,
highlighted_word = nil,
book_title = nil,
dates = nil,
padding = Size.padding.large,
@ -642,7 +643,7 @@ function WordInfoDialog:init()
VerticalSpan:new{width= Size.padding.default},
has_context and
TextBoxWidget:new{
text = "..." .. (self.prev_context or ""):gsub("\n", " ") .. "" ..self.title.."" .. (self.next_context or ""):gsub("\n", " ") .. "...",
text = "..." .. (self.prev_context or ""):gsub("\n", " ") .. "" ..(self.highlighted_word or self.title).."" .. (self.next_context or ""):gsub("\n", " ") .. "...",
width = width,
face = Font:getFace("smallffont"),
alignment = self.title_align or "left",
@ -1041,6 +1042,7 @@ end
function VocabItemWidget:showMore()
local dialogue = WordInfoDialog:new{
title = self.item.word,
highlighted_word = self.item.highlight,
book_title = self.item.book_title,
dates = _("Added on") .. " " .. os.date("%Y-%m-%d", self.item.create_time) .. " | " ..
_("Review scheduled at") .. " " .. os.date("%Y-%m-%d %H:%M", self.item.due_time),
@ -2068,15 +2070,20 @@ function VocabBuilder:onWordLookedUp(word, title, is_manual)
if self.widget and self.widget.current_lookup_word == word then return true end
local prev_context
local next_context
local highlight
if settings.with_context and self.ui.highlight then
prev_context, next_context = self.ui.highlight:getSelectedWordContext(15)
if self.ui.highlight.selected_text and self.ui.highlight.selected_text.text then
highlight = util.cleanupSelectedText(self.ui.highlight.selected_text.text)
end
end
DB:insertOrUpdate({
book_title = title,
time = os.time(),
word = word,
prev_context = prev_context,
next_context = next_context
next_context = next_context,
highlight = highlight ~= word and highlight or nil
})
return true
end