From 33525a80a05464b94b48c8dbeaa4867f76e6e71f Mon Sep 17 00:00:00 2001 From: weijiuqiao <59040746+weijiuqiao@users.noreply.github.com> Date: Sat, 14 Sep 2024 20:09:49 +0800 Subject: [PATCH] VocabBuilder.koplugin: better handling of word context (#12469) Closes #12465. --- plugins/vocabbuilder.koplugin/db.lua | 25 ++++++++++++++++++------- plugins/vocabbuilder.koplugin/main.lua | 11 +++++++++-- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/plugins/vocabbuilder.koplugin/db.lua b/plugins/vocabbuilder.koplugin/db.lua index 070117329..ed76629fb 100644 --- a/plugins/vocabbuilder.koplugin/db.lua +++ b/plugins/vocabbuilder.koplugin/db.lua @@ -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 diff --git a/plugins/vocabbuilder.koplugin/main.lua b/plugins/vocabbuilder.koplugin/main.lua index 826f43df1..898113ee8 100644 --- a/plugins/vocabbuilder.koplugin/main.lua +++ b/plugins/vocabbuilder.koplugin/main.lua @@ -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