From 57f4ff2c68f6857dd9fc2edf5603a8a55284d112 Mon Sep 17 00:00:00 2001 From: hius07 <62179190+hius07@users.noreply.github.com> Date: Sun, 28 May 2023 08:05:48 +0300 Subject: [PATCH] ReaderHighlight: manage overlapped highlights (#10492) --- .../apps/reader/modules/readerbookmark.lua | 37 +++++---- .../apps/reader/modules/readerhighlight.lua | 77 ++++++++++++++++--- spec/unit/readerhighlight_spec.lua | 4 +- 3 files changed, 85 insertions(+), 33 deletions(-) diff --git a/frontend/apps/reader/modules/readerbookmark.lua b/frontend/apps/reader/modules/readerbookmark.lua index 8db2ddf48..15e1ff2b4 100644 --- a/frontend/apps/reader/modules/readerbookmark.lua +++ b/frontend/apps/reader/modules/readerbookmark.lua @@ -24,16 +24,15 @@ local N_ = _.ngettext local Screen = require("device").screen local T = require("ffi/util").template --- mark the type of a bookmark with a symbol + non-expandable space -local DISPLAY_PREFIX = { - highlight = "\u{2592}\u{2002}", -- "medium shade" - note = "\u{F040}\u{2002}", -- "pencil" - bookmark = "\u{F097}\u{2002}", -- "empty bookmark" -} - local ReaderBookmark = InputContainer:extend{ bookmarks_items_per_page_default = 14, bookmarks = nil, + -- mark the type of a bookmark with a symbol + non-expandable space + display_prefix = { + highlight = "\u{2592}\u{2002}", -- "medium shade" + note = "\u{F040}\u{2002}", -- "pencil" + bookmark = "\u{F097}\u{2002}", -- "empty bookmark" + }, } function ReaderBookmark:init() @@ -437,7 +436,7 @@ function ReaderBookmark:onShowBookmark(match_table) item.type = self:getBookmarkType(item) if not match_table or self:doesBookmarkMatchTable(item, match_table) then item.text_orig = item.text or item.notes - item.text = DISPLAY_PREFIX[item.type] .. item.text_orig + item.text = self.display_prefix[item.type] .. item.text_orig item.mandatory = self:getBookmarkPageString(item.page) if (not is_reverse_sorting and i >= curr_page_index) or (is_reverse_sorting and i <= curr_page_index) then item.after_curr_page = true @@ -517,7 +516,7 @@ function ReaderBookmark:onShowBookmark(match_table) if item.type == "bookmark" then bm_view = bm_view .. item.text else - bm_view = bm_view .. DISPLAY_PREFIX["highlight"] .. item.notes + bm_view = bm_view .. bookmark.display_prefix["highlight"] .. item.notes if item.type == "note" then bm_view = bm_view .. "\n\n" .. item.text end @@ -733,12 +732,12 @@ function ReaderBookmark:onShowBookmark(match_table) bm_count = bm_count + 1 end end - dialog_title = T(DISPLAY_PREFIX["highlight"] .. "%1" .. " " .. - DISPLAY_PREFIX["note"] .. "%2" .. " " .. - DISPLAY_PREFIX["bookmark"] .. "%3", hl_count, nt_count, bm_count) + dialog_title = T(bookmark.display_prefix["highlight"] .. "%1" .. " " .. + bookmark.display_prefix["note"] .. "%2" .. " " .. + bookmark.display_prefix["bookmark"] .. "%3", hl_count, nt_count, bm_count) table.insert(buttons, { { - text = DISPLAY_PREFIX["highlight"] .. _("highlights"), + text = bookmark.display_prefix["highlight"] .. _("highlights"), callback = function() UIManager:close(bm_dialog) bm_menu:onClose() @@ -746,7 +745,7 @@ function ReaderBookmark:onShowBookmark(match_table) end, }, { - text = DISPLAY_PREFIX["bookmark"] .. _("page bookmarks"), + text = bookmark.display_prefix["bookmark"] .. _("page bookmarks"), callback = function() UIManager:close(bm_dialog) bm_menu:onClose() @@ -756,7 +755,7 @@ function ReaderBookmark:onShowBookmark(match_table) }) table.insert(buttons, { { - text = DISPLAY_PREFIX["note"] .. _("notes"), + text = bookmark.display_prefix["note"] .. _("notes"), callback = function() UIManager:close(bm_dialog) bm_menu:onClose() @@ -1072,7 +1071,7 @@ function ReaderBookmark:setBookmarkNote(item, from_highlight, is_new_note, new_t end else bookmark.text_orig = bookmark.text - bookmark.text = DISPLAY_PREFIX[bookmark.type] .. bookmark.text + bookmark.text = self.display_prefix[bookmark.type] .. bookmark.text self.refresh() end end, @@ -1152,19 +1151,19 @@ function ReaderBookmark:onSearchBookmark(bm_menu) } input_dialog:addWidget(separator) check_button_highlight = CheckButton:new{ - text = " " .. DISPLAY_PREFIX["highlight"] .. _("highlights"), + text = " " .. self.display_prefix["highlight"] .. _("highlights"), checked = true, parent = input_dialog, } input_dialog:addWidget(check_button_highlight) check_button_note = CheckButton:new{ - text = " " .. DISPLAY_PREFIX["note"] .. _("notes"), + text = " " .. self.display_prefix["note"] .. _("notes"), checked = true, parent = input_dialog, } input_dialog:addWidget(check_button_note) check_button_bookmark = CheckButton:new{ - text = " " .. DISPLAY_PREFIX["bookmark"] .. _("page bookmarks"), + text = " " .. self.display_prefix["bookmark"] .. _("page bookmarks"), checked = true, parent = input_dialog, } diff --git a/frontend/apps/reader/modules/readerhighlight.lua b/frontend/apps/reader/modules/readerhighlight.lua index 6e8a3b2c7..363bbe575 100644 --- a/frontend/apps/reader/modules/readerhighlight.lua +++ b/frontend/apps/reader/modules/readerhighlight.lua @@ -659,6 +659,7 @@ end function ReaderHighlight:onTapPageSavedHighlight(ges) local pages = self.view:getCurrentPageList() local pos = self.view:screenToPageTransform(ges.pos) + local highlights_tapped = {} for _, page in ipairs(pages) do local items = self.view:getPageSavedHighlights(page) if items then @@ -674,13 +675,26 @@ function ReaderHighlight:onTapPageSavedHighlight(ges) else hl_page, hl_i = page, i end - return self:onShowHighlightNoteOrDialog(hl_page, hl_i) + if self.select_mode then + if hl_page == self.highlight_page and hl_i == self.highlight_idx then + -- tap on the first fragment: abort select mode, clear highlight + self.select_mode = false + self:deleteHighlight(hl_page, hl_i) + return true + end + else + table.insert(highlights_tapped, {hl_page, hl_i}) + break + end end end end end end end + if #highlights_tapped > 0 then + return self:showChooseHighlightDialog(highlights_tapped) + end end function ReaderHighlight:onTapXPointerSavedHighlight(ges) @@ -697,6 +711,7 @@ function ReaderHighlight:onTapXPointerSavedHighlight(ges) -- because pos.page isn't super accurate in continuous mode -- (it's the page number for what's it the topleft corner of the screen, -- i.e., often a bit earlier)... + local highlights_tapped = {} for page, items in pairs(self.view.highlight.saved) do if items then for i = 1, #items do @@ -725,7 +740,17 @@ function ReaderHighlight:onTapXPointerSavedHighlight(ges) for index, box in pairs(boxes) do if inside_box(pos, box) then logger.dbg("Tap on highlight") - return self:onShowHighlightNoteOrDialog(page, i) + if self.select_mode then + if page == self.highlight_page and i == self.highlight_idx then + -- tap on the first fragment: abort select mode, clear highlight + self.select_mode = false + self:deleteHighlight(page, i) + return true + end + else + table.insert(highlights_tapped, {page, i}) + break + end end end end @@ -733,6 +758,9 @@ function ReaderHighlight:onTapXPointerSavedHighlight(ges) end end end + if #highlights_tapped > 0 then + return self:showChooseHighlightDialog(highlights_tapped) + end end function ReaderHighlight:updateHighlight(page, index, side, direction, move_by_char) @@ -820,16 +848,42 @@ function ReaderHighlight:updateHighlight(page, index, side, direction, move_by_c UIManager:setDirty(self.dialog, "ui") end -function ReaderHighlight:onShowHighlightNoteOrDialog(page, index) - if self.select_mode then - if page ~= self.highlight_page or index ~= self.highlight_idx then return end - -- tap on the first fragment: abort select mode, clear highlight - self.select_mode = false - self:deleteHighlight(page, index) - return true +function ReaderHighlight:showChooseHighlightDialog(highlights) + if #highlights == 1 then + local page, index = unpack(highlights[1]) + local item = self.view.highlight.saved[page][index] + local bookmark_note = self.ui.bookmark:getBookmarkNote({datetime = item.datetime}) + self:showHighlightNoteOrDialog(page, index, bookmark_note) + else -- overlapped highlights + local dialog + local buttons = {} + for i, v in ipairs(highlights) do + local page, index = unpack(v) + local item = self.view.highlight.saved[page][index] + local bookmark_note = self.ui.bookmark:getBookmarkNote({datetime = item.datetime}) + buttons[i] = {{ + text = (bookmark_note and self.ui.bookmark.display_prefix["note"] + or self.ui.bookmark.display_prefix["highlight"]) .. item.text, + align = "left", + avoid_text_truncation = false, + font_face = "smallinfofont", + font_size = 22, + font_bold = false, + callback = function() + UIManager:close(dialog) + self:showHighlightNoteOrDialog(page, index, bookmark_note) + end, + }} + end + dialog = ButtonDialog:new{ + buttons = buttons, + } + UIManager:show(dialog) end - local item = self.view.highlight.saved[page][index] - local bookmark_note = self.ui.bookmark:getBookmarkNote({datetime = item.datetime}) + return true +end + +function ReaderHighlight:showHighlightNoteOrDialog(page, index, bookmark_note) if bookmark_note then local textviewer textviewer = TextViewer:new{ @@ -860,7 +914,6 @@ function ReaderHighlight:onShowHighlightNoteOrDialog(page, index) else self:onShowHighlightDialog(page, index, true) end - return true end function ReaderHighlight:onShowHighlightDialog(page, index, is_auto_text) diff --git a/spec/unit/readerhighlight_spec.lua b/spec/unit/readerhighlight_spec.lua index 02d3f40bd..85d77a72d 100644 --- a/spec/unit/readerhighlight_spec.lua +++ b/spec/unit/readerhighlight_spec.lua @@ -159,7 +159,7 @@ describe("Readerhighlight module", function() Screen:shot("screenshots/reader_highlight_single_word_pdf.png") end) it("should highlight text", function() - highlight_text(readerui, Geom:new{ x = 260, y = 70 }, Geom:new{ x = 260, y = 150 }) + highlight_text(readerui, Geom:new{ x = 260, y = 170 }, Geom:new{ x = 260, y = 250 }) Screen:shot("screenshots/reader_highlight_text_pdf.png") end) it("should response on tap gesture", function() @@ -250,7 +250,7 @@ describe("Readerhighlight module", function() Screen:shot("screenshots/reader_highlight_single_word_pdf_scroll.png") end) it("should highlight text", function() - highlight_text(readerui, Geom:new{ x = 260, y = 70 }, Geom:new{ x = 260, y = 150 }) + highlight_text(readerui, Geom:new{ x = 260, y = 170 }, Geom:new{ x = 260, y = 250 }) Screen:shot("screenshots/reader_highlight_text_pdf_scroll.png") end) it("should response on tap gesture", function()