mirror of
https://github.com/koreader/koreader.git
synced 2025-12-13 20:36:53 +01:00
Annotations, part 1 (#11563)
New format to handle annotations (page bookmarks, highlights, notes) and store them in the book metadata files.
This commit is contained in:
@@ -73,11 +73,18 @@ end
|
|||||||
-- Purge doc settings except kept
|
-- Purge doc settings except kept
|
||||||
function filemanagerutil.resetDocumentSettings(file)
|
function filemanagerutil.resetDocumentSettings(file)
|
||||||
local settings_to_keep = {
|
local settings_to_keep = {
|
||||||
|
annotations = true,
|
||||||
|
annotations_paging = true,
|
||||||
|
annotations_rolling = true,
|
||||||
bookmarks = true,
|
bookmarks = true,
|
||||||
|
bookmarks_paging = true,
|
||||||
|
bookmarks_rolling = true,
|
||||||
bookmarks_sorted_20220106 = true,
|
bookmarks_sorted_20220106 = true,
|
||||||
bookmarks_version = true,
|
bookmarks_version = true,
|
||||||
cre_dom_version = true,
|
cre_dom_version = true,
|
||||||
highlight = true,
|
highlight = true,
|
||||||
|
highlight_paging = true,
|
||||||
|
highlight_rolling = true,
|
||||||
highlights_imported = true,
|
highlights_imported = true,
|
||||||
last_page = true,
|
last_page = true,
|
||||||
last_xpointer = true,
|
last_xpointer = true,
|
||||||
|
|||||||
425
frontend/apps/reader/modules/readerannotation.lua
Normal file
425
frontend/apps/reader/modules/readerannotation.lua
Normal file
@@ -0,0 +1,425 @@
|
|||||||
|
local WidgetContainer = require("ui/widget/container/widgetcontainer")
|
||||||
|
local logger = require("logger")
|
||||||
|
local _ = require("gettext")
|
||||||
|
local T = require("ffi/util").template
|
||||||
|
|
||||||
|
local ReaderAnnotation = WidgetContainer:extend{
|
||||||
|
annotations = nil, -- array sorted by annotation position order, ascending
|
||||||
|
}
|
||||||
|
|
||||||
|
-- build, read, save
|
||||||
|
|
||||||
|
function ReaderAnnotation:buildAnnotation(bm, highlights, init)
|
||||||
|
-- bm: associated single bookmark ; highlights: tables with all highlights
|
||||||
|
local note = bm.text
|
||||||
|
if note == "" then
|
||||||
|
note = nil
|
||||||
|
end
|
||||||
|
local chapter = bm.chapter
|
||||||
|
local hl, pageno = self:getHighlightByDatetime(highlights, bm.datetime)
|
||||||
|
if init then
|
||||||
|
if note and self.ui.bookmark:isBookmarkAutoText(bm) then
|
||||||
|
note = nil
|
||||||
|
end
|
||||||
|
if chapter == nil then
|
||||||
|
chapter = self.ui.toc:getTocTitleByPage(bm.page)
|
||||||
|
end
|
||||||
|
pageno = self.ui.paging and bm.page or self.document:getPageFromXPointer(bm.page)
|
||||||
|
end
|
||||||
|
if not hl then -- page bookmark or orphaned bookmark
|
||||||
|
hl = {}
|
||||||
|
if bm.highlighted then -- orphaned bookmark
|
||||||
|
hl.drawer = self.view.highlight.saved_drawer
|
||||||
|
hl.color = self.view.highlight.saved_color
|
||||||
|
if self.ui.paging then
|
||||||
|
if bm.pos0.page == bm.pos1.page then
|
||||||
|
hl.pboxes = self.document:getPageBoxesFromPositions(bm.page, bm.pos0, bm.pos1)
|
||||||
|
else -- multi-page highlight, restore the first box only
|
||||||
|
hl.pboxes = self.document:getPageBoxesFromPositions(bm.page, bm.pos0, bm.pos0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if self.ui.paging then
|
||||||
|
-- old single-page reflow highlights do not have page in position
|
||||||
|
if not bm.pos0.page then
|
||||||
|
bm.pos0.page = bm.page
|
||||||
|
bm.pos1.page = bm.page
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return { -- annotation
|
||||||
|
datetime = bm.datetime, -- creation time, not changeable
|
||||||
|
drawer = hl.drawer, -- highlight drawer
|
||||||
|
color = hl.color, -- highlight color
|
||||||
|
text = bm.notes, -- highlighted text, editable
|
||||||
|
text_edited = hl.edited, -- true if highlighted text has been edited
|
||||||
|
note = note, -- user's note, editable
|
||||||
|
chapter = chapter, -- book chapter title
|
||||||
|
pageno = pageno, -- book page number
|
||||||
|
page = bm.page, -- highlight location, xPointer or number (pdf)
|
||||||
|
pos0 = bm.pos0, -- highlight start position, xPointer (== page) or table (pdf)
|
||||||
|
pos1 = bm.pos1, -- highlight end position, xPointer or table (pdf)
|
||||||
|
pboxes = hl.pboxes, -- pdf pboxes, used only and changeable by addMarkupAnnotation
|
||||||
|
ext = hl.ext, -- pdf multi-page highlight
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
function ReaderAnnotation:getHighlightByDatetime(highlights, datetime)
|
||||||
|
for pageno, page_highlights in pairs(highlights) do
|
||||||
|
for _, highlight in ipairs(page_highlights) do
|
||||||
|
if highlight.datetime == datetime then
|
||||||
|
return highlight, pageno
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function ReaderAnnotation:getAnnotationsFromBookmarksHighlights(bookmarks, highlights, init)
|
||||||
|
local annotations = {}
|
||||||
|
for i = #bookmarks, 1, -1 do
|
||||||
|
table.insert(annotations, self:buildAnnotation(bookmarks[i], highlights, init))
|
||||||
|
end
|
||||||
|
if init then
|
||||||
|
self:sortItems(annotations)
|
||||||
|
end
|
||||||
|
return annotations
|
||||||
|
end
|
||||||
|
|
||||||
|
function ReaderAnnotation:onReadSettings(config)
|
||||||
|
local annotations = config:readSetting("annotations")
|
||||||
|
if annotations then
|
||||||
|
-- KOHighlights may set this key when it has merged annotations from different sources:
|
||||||
|
-- we want to make sure they are updated and sorted
|
||||||
|
local needs_update = config:isTrue("annotations_externally_modified")
|
||||||
|
local needs_sort -- if incompatible annotations were built of old highlights/bookmarks
|
||||||
|
-- Annotation formats in crengine and mupdf are incompatible.
|
||||||
|
local has_annotations = #annotations > 0
|
||||||
|
local annotations_type = has_annotations and type(annotations[1].page)
|
||||||
|
if self.ui.rolling and annotations_type ~= "string" then -- incompatible format loaded, or empty
|
||||||
|
if has_annotations then -- backup incompatible format if not empty
|
||||||
|
config:saveSetting("annotations_paging", annotations)
|
||||||
|
end
|
||||||
|
-- load compatible format
|
||||||
|
annotations = config:readSetting("annotations_rolling") or {}
|
||||||
|
config:delSetting("annotations_rolling")
|
||||||
|
needs_sort = true
|
||||||
|
elseif self.ui.paging and annotations_type ~= "number" then
|
||||||
|
if has_annotations then
|
||||||
|
config:saveSetting("annotations_rolling", annotations)
|
||||||
|
end
|
||||||
|
annotations = config:readSetting("annotations_paging") or {}
|
||||||
|
config:delSetting("annotations_paging")
|
||||||
|
needs_sort = true
|
||||||
|
end
|
||||||
|
self.annotations = annotations
|
||||||
|
if needs_update or needs_sort then
|
||||||
|
if self.ui.rolling then
|
||||||
|
self.ui:registerPostInitCallback(function()
|
||||||
|
self:updatedAnnotations(needs_update, needs_sort)
|
||||||
|
end)
|
||||||
|
else
|
||||||
|
self:updatedAnnotations(needs_update, needs_sort)
|
||||||
|
end
|
||||||
|
config:delSetting("annotations_externally_modified")
|
||||||
|
end
|
||||||
|
else -- first run
|
||||||
|
if self.ui.rolling then
|
||||||
|
self.ui:registerPostInitCallback(function()
|
||||||
|
self:migrateToAnnotations(config)
|
||||||
|
end)
|
||||||
|
else
|
||||||
|
self:migrateToAnnotations(config)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function ReaderAnnotation:migrateToAnnotations(config)
|
||||||
|
local bookmarks = config:readSetting("bookmarks") or {}
|
||||||
|
local highlights = config:readSetting("highlight") or {}
|
||||||
|
|
||||||
|
if config:hasNot("highlights_imported") then
|
||||||
|
-- before 2014, saved highlights were not added to bookmarks when they were created.
|
||||||
|
for page, hls in pairs(highlights) do
|
||||||
|
for _, hl in ipairs(hls) do
|
||||||
|
local hl_page = self.ui.paging and page or hl.pos0
|
||||||
|
-- highlights saved by some old versions don't have pos0 field
|
||||||
|
-- we just ignore those highlights
|
||||||
|
if hl_page then
|
||||||
|
local item = {
|
||||||
|
datetime = hl.datetime,
|
||||||
|
highlighted = true,
|
||||||
|
notes = hl.text,
|
||||||
|
page = hl_page,
|
||||||
|
pos0 = hl.pos0,
|
||||||
|
pos1 = hl.pos1,
|
||||||
|
}
|
||||||
|
if self.ui.paging then
|
||||||
|
item.pos0.page = page
|
||||||
|
item.pos1.page = page
|
||||||
|
end
|
||||||
|
table.insert(bookmarks, item)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Bookmarks/highlights formats in crengine and mupdf are incompatible.
|
||||||
|
local has_bookmarks = #bookmarks > 0
|
||||||
|
local bookmarks_type = has_bookmarks and type(bookmarks[1].page)
|
||||||
|
if self.ui.rolling then
|
||||||
|
if bookmarks_type == "string" then -- compatible format loaded, check for incompatible old backup
|
||||||
|
if config:has("bookmarks_paging") then -- save incompatible old backup
|
||||||
|
local bookmarks_paging = config:readSetting("bookmarks_paging")
|
||||||
|
local highlights_paging = config:readSetting("highlight_paging")
|
||||||
|
local annotations = self:getAnnotationsFromBookmarksHighlights(bookmarks_paging, highlights_paging)
|
||||||
|
config:saveSetting("annotations_paging", annotations)
|
||||||
|
config:delSetting("bookmarks_paging")
|
||||||
|
config:delSetting("highlight_paging")
|
||||||
|
end
|
||||||
|
else -- incompatible format loaded, or empty
|
||||||
|
if has_bookmarks then -- save incompatible format if not empty
|
||||||
|
local annotations = self:getAnnotationsFromBookmarksHighlights(bookmarks, highlights)
|
||||||
|
config:saveSetting("annotations_paging", annotations)
|
||||||
|
end
|
||||||
|
-- load compatible format
|
||||||
|
bookmarks = config:readSetting("bookmarks_rolling") or {}
|
||||||
|
highlights = config:readSetting("highlight_rolling") or {}
|
||||||
|
config:delSetting("bookmarks_rolling")
|
||||||
|
config:delSetting("highlight_rolling")
|
||||||
|
end
|
||||||
|
else -- self.ui.paging
|
||||||
|
if bookmarks_type == "number" then
|
||||||
|
if config:has("bookmarks_rolling") then
|
||||||
|
local bookmarks_rolling = config:readSetting("bookmarks_rolling")
|
||||||
|
local highlights_rolling = config:readSetting("highlight_rolling")
|
||||||
|
local annotations = self:getAnnotationsFromBookmarksHighlights(bookmarks_rolling, highlights_rolling)
|
||||||
|
config:saveSetting("annotations_rolling", annotations)
|
||||||
|
config:delSetting("bookmarks_rolling")
|
||||||
|
config:delSetting("highlight_rolling")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if has_bookmarks then
|
||||||
|
local annotations = self:getAnnotationsFromBookmarksHighlights(bookmarks, highlights)
|
||||||
|
config:saveSetting("annotations_rolling", annotations)
|
||||||
|
end
|
||||||
|
bookmarks = config:readSetting("bookmarks_paging") or {}
|
||||||
|
highlights = config:readSetting("highlight_paging") or {}
|
||||||
|
config:delSetting("bookmarks_paging")
|
||||||
|
config:delSetting("highlight_paging")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self.annotations = self:getAnnotationsFromBookmarksHighlights(bookmarks, highlights, true)
|
||||||
|
end
|
||||||
|
|
||||||
|
function ReaderAnnotation:onDocumentRerendered()
|
||||||
|
self.needs_update = true
|
||||||
|
end
|
||||||
|
|
||||||
|
function ReaderAnnotation:onCloseDocument()
|
||||||
|
self:updatePageNumbers()
|
||||||
|
end
|
||||||
|
|
||||||
|
function ReaderAnnotation:onSaveSettings()
|
||||||
|
self:updatePageNumbers()
|
||||||
|
self.ui.doc_settings:saveSetting("annotations", self.annotations)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- items handling
|
||||||
|
|
||||||
|
function ReaderAnnotation:updatePageNumbers()
|
||||||
|
if self.needs_update and self.ui.rolling then -- triggered by ReaderRolling on document layout change
|
||||||
|
for _, item in ipairs(self.annotations) do
|
||||||
|
item.pageno = self.document:getPageFromXPointer(item.page)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self.needs_update = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function ReaderAnnotation:sortItems(items)
|
||||||
|
if #items > 1 then
|
||||||
|
local sort_func = self.ui.rolling and function(a, b) return self:isItemInPositionOrderRolling(a, b) end
|
||||||
|
or function(a, b) return self:isItemInPositionOrderPaging(a, b) end
|
||||||
|
table.sort(items, sort_func)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function ReaderAnnotation:updatedAnnotations(needs_update, needs_sort)
|
||||||
|
if needs_update then
|
||||||
|
self.needs_update = true
|
||||||
|
self:updatePageNumbers()
|
||||||
|
needs_sort = true
|
||||||
|
end
|
||||||
|
if needs_sort then
|
||||||
|
self:sortItems(self.annotations)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function ReaderAnnotation:updateItemByXPointer(item)
|
||||||
|
-- called by ReaderRolling:checkXPointersAndProposeDOMVersionUpgrade()
|
||||||
|
local chapter = self.ui.toc:getTocTitleByPage(item.page)
|
||||||
|
if chapter == "" then
|
||||||
|
chapter = nil
|
||||||
|
end
|
||||||
|
if not item.drawer then -- page bookmark
|
||||||
|
item.text = chapter and T(_("in %1"), chapter) or nil
|
||||||
|
end
|
||||||
|
item.chapter = chapter
|
||||||
|
item.pageno = self.document:getPageFromXPointer(item.page)
|
||||||
|
end
|
||||||
|
|
||||||
|
function ReaderAnnotation:isItemInPositionOrderRolling(a, b)
|
||||||
|
local a_page = self.document:getPageFromXPointer(a.page)
|
||||||
|
local b_page = self.document:getPageFromXPointer(b.page)
|
||||||
|
if a_page == b_page then -- both items in the same page
|
||||||
|
if a.drawer and b.drawer then -- both items are highlights, compare positions
|
||||||
|
local compare_xp = self.document:compareXPointers(a.page, b.page)
|
||||||
|
if compare_xp then
|
||||||
|
if compare_xp == 0 then -- both highlights with the same start, compare ends
|
||||||
|
compare_xp = self.document:compareXPointers(a.pos1, b.pos1)
|
||||||
|
if compare_xp then
|
||||||
|
return compare_xp > 0
|
||||||
|
end
|
||||||
|
logger.warn("Invalid xpointer in highlight:", a.pos1, b.pos1)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return compare_xp > 0
|
||||||
|
end
|
||||||
|
-- if compare_xp is nil, some xpointer is invalid and "a" will be sorted first to page 1
|
||||||
|
logger.warn("Invalid xpointer in highlight:", a.page, b.page)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return not a.drawer -- have page bookmarks before highlights
|
||||||
|
end
|
||||||
|
return a_page < b_page
|
||||||
|
end
|
||||||
|
|
||||||
|
function ReaderAnnotation:isItemInPositionOrderPaging(a, b)
|
||||||
|
if a.page == b.page then -- both items in the same page
|
||||||
|
if a.drawer and b.drawer then -- both items are highlights, compare positions
|
||||||
|
local is_reflow = self.document.configurable.text_wrap -- save reflow mode
|
||||||
|
self.document.configurable.text_wrap = 0 -- native positions
|
||||||
|
-- sort start and end positions of each highlight
|
||||||
|
local a_start, a_end, b_start, b_end, result
|
||||||
|
if self.document:comparePositions(a.pos0, a.pos1) > 0 then
|
||||||
|
a_start, a_end = a.pos0, a.pos1
|
||||||
|
else
|
||||||
|
a_start, a_end = a.pos1, a.pos0
|
||||||
|
end
|
||||||
|
if self.document:comparePositions(b.pos0, b.pos1) > 0 then
|
||||||
|
b_start, b_end = b.pos0, b.pos1
|
||||||
|
else
|
||||||
|
b_start, b_end = b.pos1, b.pos0
|
||||||
|
end
|
||||||
|
-- compare start positions
|
||||||
|
local compare_pos = self.document:comparePositions(a_start, b_start)
|
||||||
|
if compare_pos == 0 then -- both highlights with the same start, compare ends
|
||||||
|
result = self.document:comparePositions(a_end, b_end) > 0
|
||||||
|
else
|
||||||
|
result = compare_pos > 0
|
||||||
|
end
|
||||||
|
self.document.configurable.text_wrap = is_reflow -- restore reflow mode
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
return not a.drawer -- have page bookmarks before highlights
|
||||||
|
end
|
||||||
|
return a.page < b.page
|
||||||
|
end
|
||||||
|
|
||||||
|
function ReaderAnnotation:getItemIndex(item, no_binary)
|
||||||
|
local doesMatch
|
||||||
|
if item.datetime then
|
||||||
|
doesMatch = function(a, b)
|
||||||
|
return a.datetime == b.datetime
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if self.ui.rolling then
|
||||||
|
doesMatch = function(a, b)
|
||||||
|
if a.text ~= b.text or a.pos0 ~= b.pos0 or a.pos1 ~= b.pos1 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
else
|
||||||
|
doesMatch = function(a, b)
|
||||||
|
if a.text ~= b.text or a.pos0.page ~= b.pos0.page
|
||||||
|
or a.pos0.x ~= b.pos0.x or a.pos1.x ~= b.pos1.x
|
||||||
|
or a.pos0.y ~= b.pos0.y or a.pos1.y ~= b.pos1.y then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not no_binary then
|
||||||
|
local isInOrder = self.ui.rolling and self.isItemInPositionOrderRolling or self.isItemInPositionOrderPaging
|
||||||
|
local _start, _end, _middle = 1, #self.annotations
|
||||||
|
while _start <= _end do
|
||||||
|
_middle = bit.rshift(_start + _end, 1)
|
||||||
|
local v = self.annotations[_middle]
|
||||||
|
if doesMatch(item, v) then
|
||||||
|
return _middle
|
||||||
|
elseif isInOrder(self, item, v) then
|
||||||
|
_end = _middle - 1
|
||||||
|
else
|
||||||
|
_start = _middle + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for i, v in ipairs(self.annotations) do
|
||||||
|
if doesMatch(item, v) then
|
||||||
|
return i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function ReaderAnnotation:getInsertionIndex(item)
|
||||||
|
local isInOrder = self.ui.rolling and self.isItemInPositionOrderRolling or self.isItemInPositionOrderPaging
|
||||||
|
local _start, _end, _middle, direction = 1, #self.annotations, 1, 0
|
||||||
|
while _start <= _end do
|
||||||
|
_middle = bit.rshift(_start + _end, 1)
|
||||||
|
if isInOrder(self, item, self.annotations[_middle]) then
|
||||||
|
_end, direction = _middle - 1, 0
|
||||||
|
else
|
||||||
|
_start, direction = _middle + 1, 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return _middle + direction
|
||||||
|
end
|
||||||
|
|
||||||
|
function ReaderAnnotation:addItem(item)
|
||||||
|
item.datetime = os.date("%Y-%m-%d %H:%M:%S")
|
||||||
|
item.pageno = self.ui.paging and item.page or self.document:getPageFromXPointer(item.page)
|
||||||
|
local index = self:getInsertionIndex(item)
|
||||||
|
table.insert(self.annotations, index, item)
|
||||||
|
return index
|
||||||
|
end
|
||||||
|
|
||||||
|
-- info
|
||||||
|
|
||||||
|
function ReaderAnnotation:hasAnnotations()
|
||||||
|
return #self.annotations > 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function ReaderAnnotation:getNumberOfAnnotations()
|
||||||
|
return #self.annotations
|
||||||
|
end
|
||||||
|
|
||||||
|
function ReaderAnnotation:getNumberOfHighlightsAndNotes() -- for Statistics plugin
|
||||||
|
local highlights = 0
|
||||||
|
local notes = 0
|
||||||
|
for _, item in ipairs(self.annotations) do
|
||||||
|
if item.drawer then
|
||||||
|
if item.note then
|
||||||
|
notes = notes + 1
|
||||||
|
else
|
||||||
|
highlights = highlights + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return highlights, notes
|
||||||
|
end
|
||||||
|
|
||||||
|
return ReaderAnnotation
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -219,7 +219,7 @@ local footerTextGeneratorMap = {
|
|||||||
bookmark_count = function(footer)
|
bookmark_count = function(footer)
|
||||||
local symbol_type = footer.settings.item_prefix
|
local symbol_type = footer.settings.item_prefix
|
||||||
local prefix = symbol_prefix[symbol_type].bookmark_count
|
local prefix = symbol_prefix[symbol_type].bookmark_count
|
||||||
local bookmark_count = footer.ui.bookmark:getNumberOfBookmarks()
|
local bookmark_count = footer.ui.annotation:getNumberOfAnnotations()
|
||||||
if footer.settings.all_at_once and footer.settings.hide_empty_generators and bookmark_count == 0 then
|
if footer.settings.all_at_once and footer.settings.hide_empty_generators and bookmark_count == 0 then
|
||||||
return ""
|
return ""
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ local Geom = require("ui/geometry")
|
|||||||
local InfoMessage = require("ui/widget/infomessage")
|
local InfoMessage = require("ui/widget/infomessage")
|
||||||
local InputContainer = require("ui/widget/container/inputcontainer")
|
local InputContainer = require("ui/widget/container/inputcontainer")
|
||||||
local Notification = require("ui/widget/notification")
|
local Notification = require("ui/widget/notification")
|
||||||
|
local RadioButtonWidget = require("ui/widget/radiobuttonwidget")
|
||||||
local TextViewer = require("ui/widget/textviewer")
|
local TextViewer = require("ui/widget/textviewer")
|
||||||
local Translator = require("ui/translator")
|
local Translator = require("ui/translator")
|
||||||
local UIManager = require("ui/uimanager")
|
local UIManager = require("ui/uimanager")
|
||||||
@@ -73,11 +74,11 @@ function ReaderHighlight:init()
|
|||||||
["02_highlight"] = function(this)
|
["02_highlight"] = function(this)
|
||||||
return {
|
return {
|
||||||
text = _("Highlight"),
|
text = _("Highlight"),
|
||||||
|
enabled = this.hold_pos ~= nil,
|
||||||
callback = function()
|
callback = function()
|
||||||
this:saveHighlight(true)
|
this:saveHighlight(true)
|
||||||
this:onClose()
|
this:onClose()
|
||||||
end,
|
end,
|
||||||
enabled = this.hold_pos ~= nil,
|
|
||||||
}
|
}
|
||||||
end,
|
end,
|
||||||
["03_copy"] = function(this)
|
["03_copy"] = function(this)
|
||||||
@@ -96,11 +97,11 @@ function ReaderHighlight:init()
|
|||||||
["04_add_note"] = function(this)
|
["04_add_note"] = function(this)
|
||||||
return {
|
return {
|
||||||
text = _("Add note"),
|
text = _("Add note"),
|
||||||
|
enabled = this.hold_pos ~= nil,
|
||||||
callback = function()
|
callback = function()
|
||||||
this:addNote()
|
this:addNote()
|
||||||
this:onClose()
|
this:onClose()
|
||||||
end,
|
end,
|
||||||
enabled = this.hold_pos ~= nil,
|
|
||||||
}
|
}
|
||||||
end,
|
end,
|
||||||
-- then information lookup functions, putting on the left those that
|
-- then information lookup functions, putting on the left those that
|
||||||
@@ -127,11 +128,11 @@ function ReaderHighlight:init()
|
|||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
end,
|
end,
|
||||||
["07_translate"] = function(this, page, index)
|
["07_translate"] = function(this, index)
|
||||||
return {
|
return {
|
||||||
text = _("Translate"),
|
text = _("Translate"),
|
||||||
callback = function()
|
callback = function()
|
||||||
this:translate(this.selected_text, page, index)
|
this:translate(index)
|
||||||
-- We don't call this:onClose(), so one can still see
|
-- We don't call this:onClose(), so one can still see
|
||||||
-- the highlighted text when moving the translated
|
-- the highlighted text when moving the translated
|
||||||
-- text window, and also if NetworkMgr:promptWifiOn()
|
-- text window, and also if NetworkMgr:promptWifiOn()
|
||||||
@@ -429,7 +430,7 @@ function ReaderHighlight:addToMainMenu(menu_items)
|
|||||||
self.view.highlight.lighten_factor = spin.value
|
self.view.highlight.lighten_factor = spin.value
|
||||||
UIManager:setDirty(self.dialog, "ui")
|
UIManager:setDirty(self.dialog, "ui")
|
||||||
if touchmenu_instance then touchmenu_instance:updateItems() end
|
if touchmenu_instance then touchmenu_instance:updateItems() end
|
||||||
end
|
end,
|
||||||
}
|
}
|
||||||
UIManager:show(spin_widget)
|
UIManager:show(spin_widget)
|
||||||
end,
|
end,
|
||||||
@@ -455,7 +456,7 @@ function ReaderHighlight:addToMainMenu(menu_items)
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
UIManager:show(require("ui/widget/radiobuttonwidget"):new{
|
UIManager:show(RadioButtonWidget:new{
|
||||||
title_text = _("Note marker"),
|
title_text = _("Note marker"),
|
||||||
width_factor = 0.5,
|
width_factor = 0.5,
|
||||||
keep_shown_on_apply = true,
|
keep_shown_on_apply = true,
|
||||||
@@ -475,7 +476,7 @@ function ReaderHighlight:addToMainMenu(menu_items)
|
|||||||
})
|
})
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
if self.document.info.has_pages then
|
if self.ui.paging then
|
||||||
menu_items.panel_zoom_options = {
|
menu_items.panel_zoom_options = {
|
||||||
text = _("Panel zoom (manga/comic)"),
|
text = _("Panel zoom (manga/comic)"),
|
||||||
sub_item_table = self:genPanelZoomMenu(),
|
sub_item_table = self:genPanelZoomMenu(),
|
||||||
@@ -563,7 +564,7 @@ function ReaderHighlight:addToMainMenu(menu_items)
|
|||||||
callback = function(spin)
|
callback = function(spin)
|
||||||
G_reader_settings:saveSetting("highlight_long_hold_threshold_s", spin.value)
|
G_reader_settings:saveSetting("highlight_long_hold_threshold_s", spin.value)
|
||||||
if touchmenu_instance then touchmenu_instance:updateItems() end
|
if touchmenu_instance then touchmenu_instance:updateItems() end
|
||||||
end
|
end,
|
||||||
}
|
}
|
||||||
UIManager:show(items)
|
UIManager:show(items)
|
||||||
end,
|
end,
|
||||||
@@ -671,6 +672,7 @@ function ReaderHighlight:clear(clear_id)
|
|||||||
end
|
end
|
||||||
self.is_word_selection = false
|
self.is_word_selection = false
|
||||||
self.selected_text_start_xpointer = nil
|
self.selected_text_start_xpointer = nil
|
||||||
|
self.gest_pos = nil
|
||||||
if self.hold_pos then
|
if self.hold_pos then
|
||||||
self.hold_pos = nil
|
self.hold_pos = nil
|
||||||
self.selected_text = nil
|
self.selected_text = nil
|
||||||
@@ -693,8 +695,8 @@ function ReaderHighlight:onTapSelectModeIcon()
|
|||||||
cancel_text = _("Close"),
|
cancel_text = _("Close"),
|
||||||
ok_callback = function()
|
ok_callback = function()
|
||||||
self.select_mode = false
|
self.select_mode = false
|
||||||
self:deleteHighlight(self.highlight_page, self.highlight_idx)
|
self:deleteHighlight(self.highlight_idx)
|
||||||
end
|
end,
|
||||||
})
|
})
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
@@ -706,7 +708,7 @@ function ReaderHighlight:onTap(_, ges)
|
|||||||
-- ReaderHighlight:clear can only return true if self.hold_pos was set anyway.
|
-- ReaderHighlight:clear can only return true if self.hold_pos was set anyway.
|
||||||
local cleared = self.hold_pos and self:clear()
|
local cleared = self.hold_pos and self:clear()
|
||||||
-- We only care about potential taps on existing highlights, not on taps that closed a highlight menu.
|
-- We only care about potential taps on existing highlights, not on taps that closed a highlight menu.
|
||||||
if not cleared and ges then
|
if not cleared and ges and self.ui.annotation:hasAnnotations() then
|
||||||
if self.ui.paging then
|
if self.ui.paging then
|
||||||
return self:onTapPageSavedHighlight(ges)
|
return self:onTapPageSavedHighlight(ges)
|
||||||
else
|
else
|
||||||
@@ -720,31 +722,24 @@ function ReaderHighlight:onTapPageSavedHighlight(ges)
|
|||||||
local pos = self.view:screenToPageTransform(ges.pos)
|
local pos = self.view:screenToPageTransform(ges.pos)
|
||||||
local highlights_tapped = {}
|
local highlights_tapped = {}
|
||||||
for _, page in ipairs(pages) do
|
for _, page in ipairs(pages) do
|
||||||
local items = self.view:getPageSavedHighlights(page)
|
local items = self:getPageSavedHighlights(page)
|
||||||
if items then
|
for i, item in ipairs(items) do
|
||||||
for i, item in ipairs(items) do
|
local boxes = self.ui.document:getPageBoxesFromPositions(page, item.pos0, item.pos1)
|
||||||
local boxes = self.ui.document:getPageBoxesFromPositions(page, item.pos0, item.pos1)
|
if boxes then
|
||||||
if boxes then
|
for __, box in ipairs(boxes) do
|
||||||
for _, box in ipairs(boxes) do
|
if inside_box(pos, box) then
|
||||||
if inside_box(pos, box) then
|
logger.dbg("Tap on highlight")
|
||||||
logger.dbg("Tap on highlight")
|
local hl_i = item.parent or i -- parent exists in multi-page highlight only
|
||||||
local hl_page, hl_i
|
if self.select_mode then
|
||||||
if item.parent then -- multi-page highlight
|
if hl_i == self.highlight_idx then
|
||||||
hl_page, hl_i = unpack(item.parent)
|
-- tap on the first fragment: abort select mode, clear highlight
|
||||||
else
|
self.select_mode = false
|
||||||
hl_page, hl_i = page, i
|
self:deleteHighlight(hl_i)
|
||||||
end
|
return true
|
||||||
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
|
||||||
|
else
|
||||||
|
table.insert(highlights_tapped, hl_i)
|
||||||
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -761,7 +756,6 @@ function ReaderHighlight:onTapXPointerSavedHighlight(ges)
|
|||||||
-- showing menu...). We might want to cache these boxes per page (and
|
-- showing menu...). We might want to cache these boxes per page (and
|
||||||
-- clear that cache when page layout change or highlights are added
|
-- clear that cache when page layout change or highlights are added
|
||||||
-- or removed).
|
-- or removed).
|
||||||
local cur_view_top, cur_view_bottom
|
|
||||||
local pos = self.view:screenToPageTransform(ges.pos)
|
local pos = self.view:screenToPageTransform(ges.pos)
|
||||||
-- NOTE: By now, pos.page is set, but if a highlight spans across multiple pages,
|
-- NOTE: By now, pos.page is set, but if a highlight spans across multiple pages,
|
||||||
-- it's stored under the hash of its *starting* point,
|
-- it's stored under the hash of its *starting* point,
|
||||||
@@ -770,46 +764,39 @@ function ReaderHighlight:onTapXPointerSavedHighlight(ges)
|
|||||||
-- because pos.page isn't super accurate in continuous mode
|
-- 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,
|
-- (it's the page number for what's it the topleft corner of the screen,
|
||||||
-- i.e., often a bit earlier)...
|
-- i.e., often a bit earlier)...
|
||||||
|
-- Even in page mode, it's safer to use pos and ui.dimen.h
|
||||||
|
-- than pages' xpointers pos, even if ui.dimen.h is a bit
|
||||||
|
-- larger than pages' heights
|
||||||
|
local cur_view_top = self.document:getCurrentPos()
|
||||||
|
local cur_view_bottom
|
||||||
|
if self.view.view_mode == "page" and self.document:getVisiblePageCount() > 1 then
|
||||||
|
cur_view_bottom = cur_view_top + 2 * self.ui.dimen.h
|
||||||
|
else
|
||||||
|
cur_view_bottom = cur_view_top + self.ui.dimen.h
|
||||||
|
end
|
||||||
local highlights_tapped = {}
|
local highlights_tapped = {}
|
||||||
for page, items in pairs(self.view.highlight.saved) do
|
for hl_i, item in ipairs(self.ui.annotation.annotations) do
|
||||||
if items then
|
if item.drawer then
|
||||||
for i = 1, #items do
|
-- document:getScreenBoxesFromPositions() is expensive, so we
|
||||||
local item = items[i]
|
-- first check this item is on current page
|
||||||
local pos0, pos1 = item.pos0, item.pos1
|
local start_pos = self.document:getPosFromXPointer(item.pos0)
|
||||||
-- document:getScreenBoxesFromPositions() is expensive, so we
|
local end_pos = self.document:getPosFromXPointer(item.pos1)
|
||||||
-- first check this item is on current page
|
if start_pos <= cur_view_bottom and end_pos >= cur_view_top then
|
||||||
if not cur_view_top then
|
local boxes = self.ui.document:getScreenBoxesFromPositions(item.pos0, item.pos1, true) -- get_segments=true
|
||||||
-- Even in page mode, it's safer to use pos and ui.dimen.h
|
if boxes then
|
||||||
-- than pages' xpointers pos, even if ui.dimen.h is a bit
|
for _, box in ipairs(boxes) do
|
||||||
-- larger than pages' heights
|
if inside_box(pos, box) then
|
||||||
cur_view_top = self.ui.document:getCurrentPos()
|
logger.dbg("Tap on highlight")
|
||||||
if self.view.view_mode == "page" and self.ui.document:getVisiblePageCount() > 1 then
|
if self.select_mode then
|
||||||
cur_view_bottom = cur_view_top + 2 * self.ui.dimen.h
|
if hl_i == self.highlight_idx then
|
||||||
else
|
-- tap on the first fragment: abort select mode, clear highlight
|
||||||
cur_view_bottom = cur_view_top + self.ui.dimen.h
|
self.select_mode = false
|
||||||
end
|
self:deleteHighlight(hl_i)
|
||||||
end
|
return true
|
||||||
local spos0 = self.ui.document:getPosFromXPointer(pos0)
|
|
||||||
local spos1 = self.ui.document:getPosFromXPointer(pos1)
|
|
||||||
local start_pos = math.min(spos0, spos1)
|
|
||||||
local end_pos = math.max(spos0, spos1)
|
|
||||||
if start_pos <= cur_view_bottom and end_pos >= cur_view_top then
|
|
||||||
local boxes = self.ui.document:getScreenBoxesFromPositions(pos0, pos1, true) -- get_segments=true
|
|
||||||
if boxes then
|
|
||||||
for index, box in pairs(boxes) do
|
|
||||||
if inside_box(pos, box) then
|
|
||||||
logger.dbg("Tap on highlight")
|
|
||||||
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
|
||||||
|
else
|
||||||
|
table.insert(highlights_tapped, hl_i)
|
||||||
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -822,10 +809,9 @@ function ReaderHighlight:onTapXPointerSavedHighlight(ges)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:updateHighlight(page, index, side, direction, move_by_char)
|
function ReaderHighlight:updateHighlight(index, side, direction, move_by_char)
|
||||||
if self.ui.paging then return end
|
local highlight = self.ui.annotation.annotations[index]
|
||||||
local highlight = self.view.highlight.saved[page][index]
|
local highlight_before = util.tableDeepCopy(highlight)
|
||||||
local highlight_time = highlight.datetime
|
|
||||||
local highlight_beginning = highlight.pos0
|
local highlight_beginning = highlight.pos0
|
||||||
local highlight_end = highlight.pos1
|
local highlight_end = highlight.pos1
|
||||||
if side == 0 then -- we move pos0
|
if side == 0 then -- we move pos0
|
||||||
@@ -846,7 +832,10 @@ function ReaderHighlight:updateHighlight(page, index, side, direction, move_by_c
|
|||||||
if updated_highlight_beginning then
|
if updated_highlight_beginning then
|
||||||
local order = self.ui.document:compareXPointers(updated_highlight_beginning, highlight_end)
|
local order = self.ui.document:compareXPointers(updated_highlight_beginning, highlight_end)
|
||||||
if order and order > 0 then -- only if beginning did not go past end
|
if order and order > 0 then -- only if beginning did not go past end
|
||||||
self.view.highlight.saved[page][index].pos0 = updated_highlight_beginning
|
highlight.pos0 = updated_highlight_beginning
|
||||||
|
highlight.page = updated_highlight_beginning
|
||||||
|
highlight.chapter = self.ui.toc:getTocTitleByPage(updated_highlight_beginning)
|
||||||
|
highlight.pageno = self.document:getPageFromXPointer(updated_highlight_beginning)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else -- we move pos1
|
else -- we move pos1
|
||||||
@@ -867,23 +856,16 @@ function ReaderHighlight:updateHighlight(page, index, side, direction, move_by_c
|
|||||||
if updated_highlight_end then
|
if updated_highlight_end then
|
||||||
local order = self.ui.document:compareXPointers(highlight_beginning, updated_highlight_end)
|
local order = self.ui.document:compareXPointers(highlight_beginning, updated_highlight_end)
|
||||||
if order and order > 0 then -- only if end did not go back past beginning
|
if order and order > 0 then -- only if end did not go back past beginning
|
||||||
self.view.highlight.saved[page][index].pos1 = updated_highlight_end
|
highlight.pos1 = updated_highlight_end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local new_beginning = self.view.highlight.saved[page][index].pos0
|
local new_beginning = highlight.pos0
|
||||||
local new_end = self.view.highlight.saved[page][index].pos1
|
local new_end = highlight.pos1
|
||||||
local new_text = self.ui.document:getTextFromXPointers(new_beginning, new_end)
|
local new_text = self.ui.document:getTextFromXPointers(new_beginning, new_end)
|
||||||
local new_chapter = self.ui.toc:getTocTitleByPage(new_beginning)
|
highlight.text = cleanupSelectedText(new_text)
|
||||||
self.view.highlight.saved[page][index].text = cleanupSelectedText(new_text)
|
self.ui:handleEvent(Event:new("AnnotationsModified", { highlight, highlight_before }))
|
||||||
self.view.highlight.saved[page][index].chapter = new_chapter
|
|
||||||
local new_highlight = self.view.highlight.saved[page][index]
|
|
||||||
self.ui.bookmark:updateBookmark({
|
|
||||||
page = highlight_beginning,
|
|
||||||
datetime = highlight_time,
|
|
||||||
updated_highlight = new_highlight
|
|
||||||
})
|
|
||||||
if side == 0 then
|
if side == 0 then
|
||||||
-- Ensure we show the page with the new beginning of highlight
|
-- Ensure we show the page with the new beginning of highlight
|
||||||
if not self.ui.document:isXPointerInCurrentPage(new_beginning) then
|
if not self.ui.document:isXPointerInCurrentPage(new_beginning) then
|
||||||
@@ -909,20 +891,15 @@ end
|
|||||||
|
|
||||||
function ReaderHighlight:showChooseHighlightDialog(highlights)
|
function ReaderHighlight:showChooseHighlightDialog(highlights)
|
||||||
if #highlights == 1 then
|
if #highlights == 1 then
|
||||||
local page, index = unpack(highlights[1])
|
self:showHighlightNoteOrDialog(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
|
else -- overlapped highlights
|
||||||
local dialog
|
local dialog
|
||||||
local buttons = {}
|
local buttons = {}
|
||||||
for i, v in ipairs(highlights) do
|
for i, index in ipairs(highlights) do
|
||||||
local page, index = unpack(v)
|
local item = self.ui.annotation.annotations[index]
|
||||||
local item = self.view.highlight.saved[page][index]
|
|
||||||
local bookmark_note = self.ui.bookmark:getBookmarkNote({datetime = item.datetime})
|
|
||||||
buttons[i] = {{
|
buttons[i] = {{
|
||||||
text = (bookmark_note and self.ui.bookmark.display_prefix["note"]
|
text = (item.note and self.ui.bookmark.display_prefix["note"]
|
||||||
or self.ui.bookmark.display_prefix["highlight"]) .. item.text,
|
or self.ui.bookmark.display_prefix["highlight"]) .. item.text,
|
||||||
align = "left",
|
align = "left",
|
||||||
avoid_text_truncation = false,
|
avoid_text_truncation = false,
|
||||||
font_face = "smallinfofont",
|
font_face = "smallinfofont",
|
||||||
@@ -930,7 +907,7 @@ function ReaderHighlight:showChooseHighlightDialog(highlights)
|
|||||||
font_bold = false,
|
font_bold = false,
|
||||||
callback = function()
|
callback = function()
|
||||||
UIManager:close(dialog)
|
UIManager:close(dialog)
|
||||||
self:showHighlightNoteOrDialog(page, index, bookmark_note)
|
self:showHighlightNoteOrDialog(index)
|
||||||
end,
|
end,
|
||||||
}}
|
}}
|
||||||
end
|
end
|
||||||
@@ -942,7 +919,8 @@ function ReaderHighlight:showChooseHighlightDialog(highlights)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:showHighlightNoteOrDialog(page, index, bookmark_note)
|
function ReaderHighlight:showHighlightNoteOrDialog(index)
|
||||||
|
local bookmark_note = self.ui.annotation.annotations[index].note
|
||||||
if bookmark_note then
|
if bookmark_note then
|
||||||
local textviewer
|
local textviewer
|
||||||
textviewer = TextViewer:new{
|
textviewer = TextViewer:new{
|
||||||
@@ -957,14 +935,14 @@ function ReaderHighlight:showHighlightNoteOrDialog(page, index, bookmark_note)
|
|||||||
text = _("Delete highlight"),
|
text = _("Delete highlight"),
|
||||||
callback = function()
|
callback = function()
|
||||||
UIManager:close(textviewer)
|
UIManager:close(textviewer)
|
||||||
self:deleteHighlight(page, index)
|
self:deleteHighlight(index)
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text = _("Edit highlight"),
|
text = _("Edit highlight"),
|
||||||
callback = function()
|
callback = function()
|
||||||
UIManager:close(textviewer)
|
UIManager:close(textviewer)
|
||||||
self:onShowHighlightDialog(page, index, false)
|
self:onShowHighlightDialog(index)
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -972,17 +950,18 @@ function ReaderHighlight:showHighlightNoteOrDialog(page, index, bookmark_note)
|
|||||||
}
|
}
|
||||||
UIManager:show(textviewer)
|
UIManager:show(textviewer)
|
||||||
else
|
else
|
||||||
self:onShowHighlightDialog(page, index, true)
|
self:onShowHighlightDialog(index)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:onShowHighlightDialog(page, index, is_auto_text)
|
function ReaderHighlight:onShowHighlightDialog(index)
|
||||||
|
local item = self.ui.annotation.annotations[index]
|
||||||
local buttons = {
|
local buttons = {
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
text = _("Delete"),
|
text = _("Delete"),
|
||||||
callback = function()
|
callback = function()
|
||||||
self:deleteHighlight(page, index)
|
self:deleteHighlight(index)
|
||||||
UIManager:close(self.edit_highlight_dialog)
|
UIManager:close(self.edit_highlight_dialog)
|
||||||
self.edit_highlight_dialog = nil
|
self.edit_highlight_dialog = nil
|
||||||
end,
|
end,
|
||||||
@@ -990,15 +969,15 @@ function ReaderHighlight:onShowHighlightDialog(page, index, is_auto_text)
|
|||||||
{
|
{
|
||||||
text = C_("Highlight", "Style"),
|
text = C_("Highlight", "Style"),
|
||||||
callback = function()
|
callback = function()
|
||||||
self:editHighlightStyle(page, index)
|
self:editHighlightStyle(index)
|
||||||
UIManager:close(self.edit_highlight_dialog)
|
UIManager:close(self.edit_highlight_dialog)
|
||||||
self.edit_highlight_dialog = nil
|
self.edit_highlight_dialog = nil
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text = is_auto_text and _("Add note") or _("Edit note"),
|
text = item.note and _("Edit note") or _("Add note"),
|
||||||
callback = function()
|
callback = function()
|
||||||
self:editHighlight(page, index)
|
self:editHighlight(index)
|
||||||
UIManager:close(self.edit_highlight_dialog)
|
UIManager:close(self.edit_highlight_dialog)
|
||||||
self.edit_highlight_dialog = nil
|
self.edit_highlight_dialog = nil
|
||||||
end,
|
end,
|
||||||
@@ -1006,8 +985,8 @@ function ReaderHighlight:onShowHighlightDialog(page, index, is_auto_text)
|
|||||||
{
|
{
|
||||||
text = "…",
|
text = "…",
|
||||||
callback = function()
|
callback = function()
|
||||||
self.selected_text = self.view.highlight.saved[page][index]
|
self.selected_text = util.tableDeepCopy(item)
|
||||||
self:onShowHighlightMenu(page, index)
|
self:onShowHighlightMenu(index)
|
||||||
UIManager:close(self.edit_highlight_dialog)
|
UIManager:close(self.edit_highlight_dialog)
|
||||||
self.edit_highlight_dialog = nil
|
self.edit_highlight_dialog = nil
|
||||||
end,
|
end,
|
||||||
@@ -1016,7 +995,7 @@ function ReaderHighlight:onShowHighlightDialog(page, index, is_auto_text)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.ui.rolling then
|
if self.ui.rolling then
|
||||||
local enabled = not self.view.highlight.saved[page][index].edited
|
local enabled = not item.text_edited
|
||||||
local start_prev = "◁▒▒"
|
local start_prev = "◁▒▒"
|
||||||
local start_next = "▷▒▒"
|
local start_next = "▷▒▒"
|
||||||
local end_prev = "▒▒◁"
|
local end_prev = "▒▒◁"
|
||||||
@@ -1031,10 +1010,10 @@ function ReaderHighlight:onShowHighlightDialog(page, index, is_auto_text)
|
|||||||
text = start_prev,
|
text = start_prev,
|
||||||
enabled = enabled,
|
enabled = enabled,
|
||||||
callback = function()
|
callback = function()
|
||||||
self:updateHighlight(page, index, 0, -1, false)
|
self:updateHighlight(index, 0, -1, false)
|
||||||
end,
|
end,
|
||||||
hold_callback = function()
|
hold_callback = function()
|
||||||
self:updateHighlight(page, index, 0, -1, true)
|
self:updateHighlight(index, 0, -1, true)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
@@ -1042,10 +1021,10 @@ function ReaderHighlight:onShowHighlightDialog(page, index, is_auto_text)
|
|||||||
text = start_next,
|
text = start_next,
|
||||||
enabled = enabled,
|
enabled = enabled,
|
||||||
callback = function()
|
callback = function()
|
||||||
self:updateHighlight(page, index, 0, 1, false)
|
self:updateHighlight(index, 0, 1, false)
|
||||||
end,
|
end,
|
||||||
hold_callback = function()
|
hold_callback = function()
|
||||||
self:updateHighlight(page, index, 0, 1, true)
|
self:updateHighlight(index, 0, 1, true)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
@@ -1053,26 +1032,26 @@ function ReaderHighlight:onShowHighlightDialog(page, index, is_auto_text)
|
|||||||
text = end_prev,
|
text = end_prev,
|
||||||
enabled = enabled,
|
enabled = enabled,
|
||||||
callback = function()
|
callback = function()
|
||||||
self:updateHighlight(page, index, 1, -1, false)
|
self:updateHighlight(index, 1, -1, false)
|
||||||
end,
|
end,
|
||||||
hold_callback = function()
|
hold_callback = function()
|
||||||
self:updateHighlight(page, index, 1, -1, true)
|
self:updateHighlight(index, 1, -1, true)
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text = end_next,
|
text = end_next,
|
||||||
enabled = enabled,
|
enabled = enabled,
|
||||||
callback = function()
|
callback = function()
|
||||||
self:updateHighlight(page, index, 1, 1, false)
|
self:updateHighlight(index, 1, 1, false)
|
||||||
end,
|
end,
|
||||||
hold_callback = function()
|
hold_callback = function()
|
||||||
self:updateHighlight(page, index, 1, 1, true)
|
self:updateHighlight(index, 1, 1, true)
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
self.edit_highlight_dialog = ButtonDialog:new{
|
self.edit_highlight_dialog = ButtonDialog:new{
|
||||||
buttons = buttons
|
buttons = buttons,
|
||||||
}
|
}
|
||||||
UIManager:show(self.edit_highlight_dialog)
|
UIManager:show(self.edit_highlight_dialog)
|
||||||
return true
|
return true
|
||||||
@@ -1090,7 +1069,7 @@ function ReaderHighlight:removeFromHighlightDialog(idx)
|
|||||||
return button
|
return button
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:onShowHighlightMenu(page, index)
|
function ReaderHighlight:onShowHighlightMenu(index)
|
||||||
if not self.selected_text then
|
if not self.selected_text then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -1099,7 +1078,7 @@ function ReaderHighlight:onShowHighlightMenu(page, index)
|
|||||||
|
|
||||||
local columns = 2
|
local columns = 2
|
||||||
for idx, fn_button in ffiUtil.orderedPairs(self._highlight_buttons) do
|
for idx, fn_button in ffiUtil.orderedPairs(self._highlight_buttons) do
|
||||||
local button = fn_button(self, page, index)
|
local button = fn_button(self, index)
|
||||||
if not button.show_in_highlight_dialog_func or button.show_in_highlight_dialog_func() then
|
if not button.show_in_highlight_dialog_func or button.show_in_highlight_dialog_func() then
|
||||||
if #highlight_buttons[#highlight_buttons] >= columns then
|
if #highlight_buttons[#highlight_buttons] >= columns then
|
||||||
table.insert(highlight_buttons, {})
|
table.insert(highlight_buttons, {})
|
||||||
@@ -1198,12 +1177,12 @@ function ReaderHighlight:_resetHoldTimer(clear)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:onTogglePanelZoomSetting(arg, ges)
|
function ReaderHighlight:onTogglePanelZoomSetting(arg, ges)
|
||||||
if not self.document.info.has_pages then return end
|
if self.ui.rolling then return end
|
||||||
self.panel_zoom_enabled = not self.panel_zoom_enabled
|
self.panel_zoom_enabled = not self.panel_zoom_enabled
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:onToggleFallbackTextSelection(arg, ges)
|
function ReaderHighlight:onToggleFallbackTextSelection(arg, ges)
|
||||||
if not self.document.info.has_pages then return end
|
if self.ui.rolling then return end
|
||||||
self.panel_zoom_fallback_to_text_selection = not self.panel_zoom_fallback_to_text_selection
|
self.panel_zoom_fallback_to_text_selection = not self.panel_zoom_fallback_to_text_selection
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1229,7 +1208,7 @@ function ReaderHighlight:onPanelZoom(arg, ges)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:onHold(arg, ges)
|
function ReaderHighlight:onHold(arg, ges)
|
||||||
if self.document.info.has_pages and self.panel_zoom_enabled then
|
if self.ui.paging and self.panel_zoom_enabled then
|
||||||
local res = self:onPanelZoom(arg, ges)
|
local res = self:onPanelZoom(arg, ges)
|
||||||
if res or not self.panel_zoom_fallback_to_text_selection then
|
if res or not self.panel_zoom_fallback_to_text_selection then
|
||||||
return res
|
return res
|
||||||
@@ -1548,20 +1527,20 @@ function ReaderHighlight:viewSelectionHTML(debug_view, no_css_files_buttons)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:translate(selected_text, page, index)
|
function ReaderHighlight:translate(index)
|
||||||
if self.ui.rolling then
|
if self.ui.rolling then
|
||||||
-- Extend the selected text to include any punctuation at start or end,
|
-- Extend the selected text to include any punctuation at start or end,
|
||||||
-- which may give a better translation with the added context.
|
-- which may give a better translation with the added context.
|
||||||
local extended_text = self.ui.document:extendXPointersToSentenceSegment(selected_text.pos0, selected_text.pos1)
|
local extended_text = self.ui.document:extendXPointersToSentenceSegment(self.selected_text.pos0, self.selected_text.pos1)
|
||||||
if extended_text then
|
if extended_text then
|
||||||
selected_text = extended_text
|
self.selected_text = extended_text
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if #selected_text.text > 0 then
|
if #self.selected_text.text > 0 then
|
||||||
self:onTranslateText(selected_text.text, page, index)
|
self:onTranslateText(self.selected_text.text, index)
|
||||||
-- or we will do OCR
|
-- or we will do OCR
|
||||||
elseif self.hold_pos then
|
elseif self.hold_pos then
|
||||||
local text = self.ui.document:getOCRText(self.hold_pos.page, selected_text)
|
local text = self.ui.document:getOCRText(self.hold_pos.page, self.selected_text)
|
||||||
logger.dbg("OCRed text:", text)
|
logger.dbg("OCRed text:", text)
|
||||||
if text and text ~= "" then
|
if text and text ~= "" then
|
||||||
self:onTranslateText(text)
|
self:onTranslateText(text)
|
||||||
@@ -1572,14 +1551,9 @@ function ReaderHighlight:translate(selected_text, page, index)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
dbg:guard(ReaderHighlight, "translate",
|
|
||||||
function(self, selected_text)
|
|
||||||
assert(selected_text ~= nil,
|
|
||||||
"translate must not be called with nil selected_text!")
|
|
||||||
end)
|
|
||||||
|
|
||||||
function ReaderHighlight:onTranslateText(text, page, index)
|
function ReaderHighlight:onTranslateText(text, index)
|
||||||
Translator:showTranslation(text, true, nil, nil, true, page, index)
|
Translator:showTranslation(text, true, nil, nil, true, index)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:onTranslateCurrentPage()
|
function ReaderHighlight:onTranslateCurrentPage()
|
||||||
@@ -1661,7 +1635,7 @@ function ReaderHighlight:onHoldRelease()
|
|||||||
self:addNote()
|
self:addNote()
|
||||||
self:onClose()
|
self:onClose()
|
||||||
elseif default_highlight_action == "translate" then
|
elseif default_highlight_action == "translate" then
|
||||||
self:translate(self.selected_text)
|
self:translate()
|
||||||
elseif default_highlight_action == "wikipedia" then
|
elseif default_highlight_action == "wikipedia" then
|
||||||
self:lookupWikipedia()
|
self:lookupWikipedia()
|
||||||
self:onClose()
|
self:onClose()
|
||||||
@@ -1751,137 +1725,45 @@ function ReaderHighlight:highlightFromHoldPos()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:onHighlight()
|
function ReaderHighlight:saveHighlight(extend_to_sentence)
|
||||||
self:saveHighlight()
|
logger.dbg("save highlight")
|
||||||
end
|
|
||||||
|
|
||||||
function ReaderHighlight:onUnhighlight(bookmark_item)
|
|
||||||
local page
|
|
||||||
local sel_text
|
|
||||||
local sel_pos0
|
|
||||||
local datetime
|
|
||||||
local idx
|
|
||||||
if bookmark_item then -- called from Bookmarks menu onHold
|
|
||||||
page = bookmark_item.page
|
|
||||||
sel_text = bookmark_item.notes
|
|
||||||
sel_pos0 = bookmark_item.pos0
|
|
||||||
datetime = bookmark_item.datetime
|
|
||||||
else -- called from DictQuickLookup Unhighlight button
|
|
||||||
--- @fixme: is this self.hold_pos access safe?
|
|
||||||
page = self.hold_pos.page
|
|
||||||
sel_text = cleanupSelectedText(self.selected_text.text)
|
|
||||||
sel_pos0 = self.selected_text.pos0
|
|
||||||
end
|
|
||||||
if self.ui.paging then -- We can safely use page
|
|
||||||
-- As we may have changed spaces and hyphens handling in the extracted
|
|
||||||
-- text over the years, check text identities with them removed
|
|
||||||
local sel_text_cleaned = sel_text:gsub("[ -]", ""):gsub("\u{00AD}", "")
|
|
||||||
for index = 1, #self.view.highlight.saved[page] do
|
|
||||||
local highlight = self.view.highlight.saved[page][index]
|
|
||||||
-- pos0 are tables and can't be compared directly, except when from
|
|
||||||
-- DictQuickLookup where these are the same object.
|
|
||||||
-- If bookmark_item provided, just check datetime
|
|
||||||
if ( (datetime == nil and highlight.pos0 == sel_pos0) or
|
|
||||||
(datetime ~= nil and highlight.datetime == datetime) ) then
|
|
||||||
if highlight.text:gsub("[ -]", ""):gsub("\u{00AD}", "") == sel_text_cleaned then
|
|
||||||
idx = index
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else -- page is a xpointer
|
|
||||||
-- The original page could be found in bookmark_item.text, but
|
|
||||||
-- no more if it has been renamed: we need to loop through all
|
|
||||||
-- highlights on all page slots
|
|
||||||
for p, highlights in pairs(self.view.highlight.saved) do
|
|
||||||
for index = 1, #highlights do
|
|
||||||
local highlight = highlights[index]
|
|
||||||
-- pos0 are strings and can be compared directly
|
|
||||||
if highlight.text == sel_text and (
|
|
||||||
(datetime == nil and highlight.pos0 == sel_pos0) or
|
|
||||||
(datetime ~= nil and highlight.datetime == datetime)) then
|
|
||||||
page = p -- this is the original page slot
|
|
||||||
idx = index
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if idx then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if idx then
|
|
||||||
logger.dbg("found highlight to delete on page", page, idx)
|
|
||||||
self:deleteHighlight(page, idx, bookmark_item)
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function ReaderHighlight:getHighlightByDatetime(datetime)
|
|
||||||
for page, highlights in pairs(self.view.highlight.saved) do
|
|
||||||
for _, highlight in ipairs(highlights) do
|
|
||||||
if highlight.datetime == datetime then
|
|
||||||
return highlight
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function ReaderHighlight:getHighlightBookmarkItem()
|
|
||||||
if self.hold_pos and not self.selected_text then
|
if self.hold_pos and not self.selected_text then
|
||||||
self:highlightFromHoldPos()
|
self:highlightFromHoldPos()
|
||||||
end
|
end
|
||||||
if self.selected_text and self.selected_text.pos0 and self.selected_text.pos1 then
|
if self.selected_text and self.selected_text.pos0 and self.selected_text.pos1 then
|
||||||
return {
|
local pg_or_xp
|
||||||
|
if self.ui.rolling then
|
||||||
|
if extend_to_sentence then
|
||||||
|
local extended_text = self.ui.document:extendXPointersToSentenceSegment(self.selected_text.pos0, self.selected_text.pos1)
|
||||||
|
if extended_text then
|
||||||
|
self.selected_text = extended_text
|
||||||
|
end
|
||||||
|
end
|
||||||
|
pg_or_xp = self.selected_text.pos0
|
||||||
|
else
|
||||||
|
pg_or_xp = self.selected_text.pos0.page
|
||||||
|
end
|
||||||
|
local item = {
|
||||||
page = self.ui.paging and self.selected_text.pos0.page or self.selected_text.pos0,
|
page = self.ui.paging and self.selected_text.pos0.page or self.selected_text.pos0,
|
||||||
pos0 = self.selected_text.pos0,
|
pos0 = self.selected_text.pos0,
|
||||||
pos1 = self.selected_text.pos1,
|
pos1 = self.selected_text.pos1,
|
||||||
notes = cleanupSelectedText(self.selected_text.text),
|
|
||||||
highlighted = true,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function ReaderHighlight:saveHighlight(extend_to_sentence)
|
|
||||||
self.ui:handleEvent(Event:new("AddHighlight"))
|
|
||||||
logger.dbg("save highlight")
|
|
||||||
if self.selected_text and self.selected_text.pos0 and self.selected_text.pos1 then
|
|
||||||
if extend_to_sentence and self.ui.rolling then
|
|
||||||
local extended_text = self.ui.document:extendXPointersToSentenceSegment(self.selected_text.pos0, self.selected_text.pos1)
|
|
||||||
if extended_text then
|
|
||||||
self.selected_text = extended_text
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local page = self.ui.paging and self.selected_text.pos0.page or self.ui.document:getPageFromXPointer(self.selected_text.pos0)
|
|
||||||
if not self.view.highlight.saved[page] then
|
|
||||||
self.view.highlight.saved[page] = {}
|
|
||||||
end
|
|
||||||
local datetime = os.date("%Y-%m-%d %H:%M:%S")
|
|
||||||
local pg_or_xp = self.ui.paging and page or self.selected_text.pos0
|
|
||||||
local chapter_name = self.ui.toc:getTocTitleByPage(pg_or_xp)
|
|
||||||
local hl_item = {
|
|
||||||
datetime = datetime,
|
|
||||||
text = cleanupSelectedText(self.selected_text.text),
|
text = cleanupSelectedText(self.selected_text.text),
|
||||||
pos0 = self.selected_text.pos0,
|
|
||||||
pos1 = self.selected_text.pos1,
|
|
||||||
pboxes = self.selected_text.pboxes,
|
|
||||||
ext = self.selected_text.ext,
|
|
||||||
drawer = self.view.highlight.saved_drawer,
|
drawer = self.view.highlight.saved_drawer,
|
||||||
chapter = chapter_name,
|
chapter = self.ui.toc:getTocTitleByPage(pg_or_xp),
|
||||||
}
|
}
|
||||||
table.insert(self.view.highlight.saved[page], hl_item)
|
if self.ui.paging then
|
||||||
local bookmark_item = self:getHighlightBookmarkItem()
|
item.pboxes = self.selected_text.pboxes
|
||||||
if bookmark_item then
|
item.ext = self.selected_text.ext
|
||||||
bookmark_item.datetime = datetime
|
self:writePdfAnnotation("save", item)
|
||||||
bookmark_item.chapter = chapter_name
|
|
||||||
self.ui.bookmark:addBookmark(bookmark_item)
|
|
||||||
end
|
end
|
||||||
self:writePdfAnnotation("save", page, hl_item)
|
local index = self.ui.annotation:addItem(item)
|
||||||
return page, #self.view.highlight.saved[page]
|
self.view.footer:onUpdateFooter(self.view.footer_visible)
|
||||||
|
self.ui:handleEvent(Event:new("AnnotationsModified", { item, nb_highlights_added = 1 }))
|
||||||
|
return index
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:writePdfAnnotation(action, page, item, content)
|
function ReaderHighlight:writePdfAnnotation(action, item, content)
|
||||||
if self.ui.rolling or G_reader_settings:readSetting("save_document") == "disable" then
|
if self.ui.rolling or G_reader_settings:readSetting("save_document") == "disable" then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -1897,24 +1779,10 @@ function ReaderHighlight:writePdfAnnotation(action, page, item, content)
|
|||||||
end
|
end
|
||||||
local can_write
|
local can_write
|
||||||
if item.pos0.page == item.pos1.page then -- single-page highlight
|
if item.pos0.page == item.pos1.page then -- single-page highlight
|
||||||
local item_
|
can_write = doAction(action, item.pos0.page, item, content)
|
||||||
if item.pboxes then
|
|
||||||
item_ = item
|
|
||||||
else -- called from bookmarks to write bookmark note to annotation
|
|
||||||
for _, hl in ipairs(self.view.highlight.saved[page]) do
|
|
||||||
if hl.datetime == item.datetime then
|
|
||||||
item_ = {pboxes = hl.pboxes}
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
can_write = doAction(action, page, item_, content)
|
|
||||||
else -- multi-page highlight
|
else -- multi-page highlight
|
||||||
local is_reflow = self.ui.document.configurable.text_wrap
|
|
||||||
for hl_page = item.pos0.page, item.pos1.page do
|
for hl_page = item.pos0.page, item.pos1.page do
|
||||||
self.ui.document.configurable.text_wrap = 0
|
|
||||||
local hl_part = self:getSavedExtendedHighlightPage(item, hl_page)
|
local hl_part = self:getSavedExtendedHighlightPage(item, hl_page)
|
||||||
self.ui.document.configurable.text_wrap = is_reflow
|
|
||||||
can_write = doAction(action, hl_page, hl_part, content)
|
can_write = doAction(action, hl_page, hl_part, content)
|
||||||
if can_write == false then break end
|
if can_write == false then break end
|
||||||
if action == "save" then -- update pboxes from quadpoints
|
if action == "save" then -- update pboxes from quadpoints
|
||||||
@@ -1934,14 +1802,6 @@ If you wish your highlights to be saved in the document, just move it to a writa
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:addNote(text)
|
|
||||||
local page, index = self:saveHighlight(true)
|
|
||||||
if text then self:clear() end
|
|
||||||
self:editHighlight(page, index, true, text)
|
|
||||||
UIManager:close(self.edit_highlight_dialog)
|
|
||||||
self.edit_highlight_dialog = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function ReaderHighlight:lookupWikipedia()
|
function ReaderHighlight:lookupWikipedia()
|
||||||
if self.selected_text then
|
if self.selected_text then
|
||||||
self.ui:handleEvent(Event:new("LookupWikipedia", cleanupSelectedText(self.selected_text.text)))
|
self.ui:handleEvent(Event:new("LookupWikipedia", cleanupSelectedText(self.selected_text.text)))
|
||||||
@@ -1970,59 +1830,48 @@ function ReaderHighlight:onHighlightDictLookup()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:deleteHighlight(page, i, bookmark_item)
|
function ReaderHighlight:deleteHighlight(index)
|
||||||
logger.dbg("delete highlight", page, i)
|
logger.dbg("delete highlight", index)
|
||||||
-- The per-page table is a pure array
|
local item = self.ui.annotation.annotations[index]
|
||||||
local removed = table.remove(self.view.highlight.saved[page], i)
|
self:writePdfAnnotation("delete", item)
|
||||||
-- But the main, outer table is a hash, so clear the table for this page if there are no longer any highlights on it
|
self.ui.bookmark:removeItemByIndex(index)
|
||||||
if #self.view.highlight.saved[page] == 0 then
|
|
||||||
self.view.highlight.saved[page] = nil
|
|
||||||
end
|
|
||||||
if bookmark_item then
|
|
||||||
self.ui.bookmark:removeBookmark(bookmark_item)
|
|
||||||
else
|
|
||||||
self.ui.bookmark:removeBookmark({
|
|
||||||
page = self.ui.paging and page or removed.pos0,
|
|
||||||
datetime = removed.datetime,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
self:writePdfAnnotation("delete", page, removed)
|
|
||||||
UIManager:setDirty(self.dialog, "ui")
|
UIManager:setDirty(self.dialog, "ui")
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:editHighlight(page, i, is_new_note, text)
|
function ReaderHighlight:addNote(text)
|
||||||
local item = self.view.highlight.saved[page][i]
|
local index = self:saveHighlight(true)
|
||||||
self.ui.bookmark:setBookmarkNote({
|
if text then -- called from Translator to save translation to note
|
||||||
page = self.ui.paging and page or item.pos0,
|
self:clear()
|
||||||
datetime = item.datetime,
|
end
|
||||||
}, true, is_new_note, text)
|
self:editHighlight(index, true, text)
|
||||||
|
UIManager:close(self.edit_highlight_dialog)
|
||||||
|
self.edit_highlight_dialog = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:editHighlightStyle(page, i)
|
function ReaderHighlight:editHighlight(index, is_new_note, text)
|
||||||
local item = self.view.highlight.saved[page][i]
|
self.ui.bookmark:setBookmarkNote(index, is_new_note, text)
|
||||||
|
end
|
||||||
|
|
||||||
|
function ReaderHighlight:editHighlightStyle(index)
|
||||||
|
local item = self.ui.annotation.annotations[index]
|
||||||
local apply_drawer = function(drawer)
|
local apply_drawer = function(drawer)
|
||||||
self:writePdfAnnotation("delete", page, item)
|
self:writePdfAnnotation("delete", item)
|
||||||
item.drawer = drawer
|
item.drawer = drawer
|
||||||
if self.ui.paging then
|
if self.ui.paging then
|
||||||
self:writePdfAnnotation("save", page, item)
|
self:writePdfAnnotation("save", item)
|
||||||
local bm_note = self.ui.bookmark:getBookmarkNote(item)
|
if item.note then
|
||||||
if bm_note then
|
self:writePdfAnnotation("content", item, item.note)
|
||||||
self:writePdfAnnotation("content", page, item, bm_note)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
UIManager:setDirty(self.dialog, "ui")
|
UIManager:setDirty(self.dialog, "ui")
|
||||||
self.ui:handleEvent(Event:new("BookmarkUpdated",
|
self.ui:handleEvent(Event:new("AnnotationsModified", { item }))
|
||||||
self.ui.bookmark:getBookmarkForHighlight({
|
|
||||||
page = self.ui.paging and page or item.pos0,
|
|
||||||
datetime = item.datetime,
|
|
||||||
})))
|
|
||||||
end
|
end
|
||||||
self:showHighlightStyleDialog(apply_drawer, item.drawer)
|
self:showHighlightStyleDialog(apply_drawer, item.drawer)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:showHighlightStyleDialog(caller_callback, item_drawer)
|
function ReaderHighlight:showHighlightStyleDialog(caller_callback, item_drawer)
|
||||||
local default_drawer, keep_shown_on_apply
|
local default_drawer, keep_shown_on_apply
|
||||||
if item_drawer then -- called from editHighlightStyle
|
if item_drawer then -- called from ReaderHighlight:editHighlightStyle()
|
||||||
default_drawer = self.view.highlight.saved_drawer or
|
default_drawer = self.view.highlight.saved_drawer or
|
||||||
G_reader_settings:readSetting("highlight_drawing_style", "lighten")
|
G_reader_settings:readSetting("highlight_drawing_style", "lighten")
|
||||||
keep_shown_on_apply = true
|
keep_shown_on_apply = true
|
||||||
@@ -2037,7 +1886,6 @@ function ReaderHighlight:showHighlightStyleDialog(caller_callback, item_drawer)
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
local RadioButtonWidget = require("ui/widget/radiobuttonwidget")
|
|
||||||
UIManager:show(RadioButtonWidget:new{
|
UIManager:show(RadioButtonWidget:new{
|
||||||
title_text = _("Highlight style"),
|
title_text = _("Highlight style"),
|
||||||
width_factor = 0.5,
|
width_factor = 0.5,
|
||||||
@@ -2051,14 +1899,14 @@ function ReaderHighlight:showHighlightStyleDialog(caller_callback, item_drawer)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:startSelection()
|
function ReaderHighlight:startSelection()
|
||||||
self.highlight_page, self.highlight_idx = self:saveHighlight()
|
self.highlight_idx = self:saveHighlight()
|
||||||
self.select_mode = true
|
self.select_mode = true
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:extendSelection()
|
function ReaderHighlight:extendSelection()
|
||||||
-- item1 - starting fragment (saved), item2 - ending fragment (currently selected)
|
-- item1 - starting fragment (saved), item2 - ending fragment (currently selected)
|
||||||
-- new extended highlight includes item1, item2 and the text between them
|
-- new extended highlight includes item1, item2 and the text between them
|
||||||
local item1 = self.view.highlight.saved[self.highlight_page][self.highlight_idx]
|
local item1 = self.ui.annotation.annotations[self.highlight_idx]
|
||||||
local item2_pos0, item2_pos1 = self.selected_text.pos0, self.selected_text.pos1
|
local item2_pos0, item2_pos1 = self.selected_text.pos0, self.selected_text.pos1
|
||||||
-- getting starting and ending positions, text and pboxes of extended highlight
|
-- getting starting and ending positions, text and pboxes of extended highlight
|
||||||
local new_pos0, new_pos1, new_text, new_pboxes, ext
|
local new_pos0, new_pos1, new_text, new_pboxes, ext
|
||||||
@@ -2106,7 +1954,7 @@ function ReaderHighlight:extendSelection()
|
|||||||
-- true to draw
|
-- true to draw
|
||||||
new_text = self.ui.document:getTextFromXPointers(new_pos0, new_pos1, true)
|
new_text = self.ui.document:getTextFromXPointers(new_pos0, new_pos1, true)
|
||||||
end
|
end
|
||||||
self:deleteHighlight(self.highlight_page, self.highlight_idx) -- starting fragment
|
self:deleteHighlight(self.highlight_idx) -- starting fragment
|
||||||
self.selected_text = {
|
self.selected_text = {
|
||||||
text = new_text,
|
text = new_text,
|
||||||
pos0 = new_pos0,
|
pos0 = new_pos0,
|
||||||
@@ -2126,7 +1974,10 @@ function ReaderHighlight:getExtendedHighlightPage(pos0, pos1, cur_page)
|
|||||||
local page_boxes = self.ui.document:getTextBoxes(page)
|
local page_boxes = self.ui.document:getTextBoxes(page)
|
||||||
if page == pos0.page then
|
if page == pos0.page then
|
||||||
-- first page (from the start of highlight to the end of the page)
|
-- first page (from the start of highlight to the end of the page)
|
||||||
item.pos0 = pos0
|
item.pos0 = {
|
||||||
|
x = pos0.x,
|
||||||
|
y = pos0.y,
|
||||||
|
}
|
||||||
item.pos1 = {
|
item.pos1 = {
|
||||||
x = page_boxes[#page_boxes][#page_boxes[#page_boxes]].x1,
|
x = page_boxes[#page_boxes][#page_boxes[#page_boxes]].x1,
|
||||||
y = page_boxes[#page_boxes][#page_boxes[#page_boxes]].y1,
|
y = page_boxes[#page_boxes][#page_boxes[#page_boxes]].y1,
|
||||||
@@ -2147,7 +1998,10 @@ function ReaderHighlight:getExtendedHighlightPage(pos0, pos1, cur_page)
|
|||||||
x = page_boxes[1][1].x0,
|
x = page_boxes[1][1].x0,
|
||||||
y = page_boxes[1][1].y0,
|
y = page_boxes[1][1].y0,
|
||||||
}
|
}
|
||||||
item.pos1 = pos1
|
item.pos1 = {
|
||||||
|
x = pos1.x,
|
||||||
|
y = pos1.y,
|
||||||
|
}
|
||||||
end
|
end
|
||||||
item.pos0.page = page
|
item.pos0.page = page
|
||||||
item.pos1.page = page
|
item.pos1.page = page
|
||||||
@@ -2159,44 +2013,53 @@ function ReaderHighlight:getExtendedHighlightPage(pos0, pos1, cur_page)
|
|||||||
return item
|
return item
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Returns one page of saved multi-page highlight
|
-- Returns the list of highlights in page.
|
||||||
|
-- The list includes full single-page highlights and parts of multi-page highlights.
|
||||||
-- (For pdf documents only)
|
-- (For pdf documents only)
|
||||||
function ReaderHighlight:getSavedExtendedHighlightPage(hl_or_bm, page, index)
|
function ReaderHighlight:getPageSavedHighlights(page)
|
||||||
local highlight
|
local highlights = {}
|
||||||
if hl_or_bm.ext then
|
for index, highlight in ipairs(self.ui.annotation.annotations) do
|
||||||
highlight = hl_or_bm
|
if highlight.drawer and highlight.pos0.page <= page and page <= highlight.pos1.page then
|
||||||
else -- called from bookmark, need to find the corresponding highlight
|
if highlight.ext then -- multi-page highlight
|
||||||
for _, hl in ipairs(self.view.highlight.saved[hl_or_bm.page]) do
|
local item = self:getSavedExtendedHighlightPage(highlight, page, index)
|
||||||
if hl.datetime == hl_or_bm.datetime then
|
table.insert(highlights, item)
|
||||||
highlight = hl
|
else
|
||||||
break
|
table.insert(highlights, highlight)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local item = {}
|
return highlights
|
||||||
item.datetime = highlight.datetime
|
end
|
||||||
item.drawer = highlight.drawer
|
|
||||||
item.pos0 = highlight.ext[page].pos0
|
-- Returns one page of saved multi-page highlight
|
||||||
item.pos0.zoom = highlight.pos0.zoom
|
-- (For pdf documents only)
|
||||||
|
function ReaderHighlight:getSavedExtendedHighlightPage(highlight, page, index)
|
||||||
|
local item = {
|
||||||
|
datetime = highlight.datetime,
|
||||||
|
drawer = highlight.drawer,
|
||||||
|
text = highlight.text,
|
||||||
|
page = highlight.page,
|
||||||
|
pos0 = highlight.ext[page].pos0,
|
||||||
|
pos1 = highlight.ext[page].pos1,
|
||||||
|
pboxes = highlight.ext[page].pboxes,
|
||||||
|
parent = index,
|
||||||
|
}
|
||||||
|
item.pos0.zoom = highlight.pos0.zoom
|
||||||
item.pos0.rotation = highlight.pos0.rotation
|
item.pos0.rotation = highlight.pos0.rotation
|
||||||
item.pos1 = highlight.ext[page].pos1
|
item.pos1.zoom = highlight.pos0.zoom
|
||||||
item.pos1.zoom = highlight.pos0.zoom
|
|
||||||
item.pos1.rotation = highlight.pos0.rotation
|
item.pos1.rotation = highlight.pos0.rotation
|
||||||
item.pboxes = highlight.ext[page].pboxes
|
|
||||||
item.parent = {highlight.pos0.page, index}
|
|
||||||
return item
|
return item
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderHighlight:onReadSettings(config)
|
function ReaderHighlight:onReadSettings(config)
|
||||||
self.view.highlight.saved_drawer = config:readSetting("highlight_drawer")
|
self.view.highlight.saved_drawer = config:readSetting("highlight_drawer")
|
||||||
or G_reader_settings:readSetting("highlight_drawing_style") or self.view.highlight.saved_drawer
|
or G_reader_settings:readSetting("highlight_drawing_style") or self.view.highlight.saved_drawer
|
||||||
self.view.highlight.disabled = G_reader_settings:has("default_highlight_action")
|
self.view.highlight.disabled = G_reader_settings:readSetting("default_highlight_action") == "nothing"
|
||||||
and G_reader_settings:readSetting("default_highlight_action") == "nothing"
|
|
||||||
|
|
||||||
self.allow_corner_scroll = G_reader_settings:nilOrTrue("highlight_corner_scroll")
|
self.allow_corner_scroll = G_reader_settings:nilOrTrue("highlight_corner_scroll")
|
||||||
|
|
||||||
-- panel zoom settings isn't supported in EPUB
|
-- panel zoom settings isn't supported in EPUB
|
||||||
if self.document.info.has_pages then
|
if self.ui.paging then
|
||||||
local ext = util.getFileNameSuffix(self.ui.document.file)
|
local ext = util.getFileNameSuffix(self.ui.document.file)
|
||||||
G_reader_settings:initializeExtSettings("panel_zoom_enabled", {cbz = true, cbt = true})
|
G_reader_settings:initializeExtSettings("panel_zoom_enabled", {cbz = true, cbt = true})
|
||||||
G_reader_settings:initializeExtSettings("panel_zoom_fallback_to_text_selection", {pdf = true})
|
G_reader_settings:initializeExtSettings("panel_zoom_fallback_to_text_selection", {pdf = true})
|
||||||
@@ -2231,6 +2094,8 @@ function ReaderHighlight:onClose()
|
|||||||
self:clear()
|
self:clear()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- dpad/keys support
|
||||||
|
|
||||||
function ReaderHighlight:onHighlightPress()
|
function ReaderHighlight:onHighlightPress()
|
||||||
if self._current_indicator_pos then
|
if self._current_indicator_pos then
|
||||||
if not self._start_indicator_highlight then
|
if not self._start_indicator_highlight then
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ ReaderLink is an abstraction for document-specific link interfaces.
|
|||||||
]]
|
]]
|
||||||
|
|
||||||
local BD = require("ui/bidi")
|
local BD = require("ui/bidi")
|
||||||
local ButtonDialogTitle = require("ui/widget/buttondialogtitle")
|
local ButtonDialog = require("ui/widget/buttondialog")
|
||||||
local ConfirmBox = require("ui/widget/confirmbox")
|
local ConfirmBox = require("ui/widget/confirmbox")
|
||||||
local Device = require("device")
|
local Device = require("device")
|
||||||
local DocumentRegistry = require("document/documentregistry")
|
local DocumentRegistry = require("document/documentregistry")
|
||||||
@@ -118,7 +118,7 @@ function ReaderLink:init()
|
|||||||
end)
|
end)
|
||||||
if G_reader_settings:isTrue("opening_page_location_stack") then
|
if G_reader_settings:isTrue("opening_page_location_stack") then
|
||||||
-- Add location at book opening to stack
|
-- Add location at book opening to stack
|
||||||
self.ui:registerPostReadyCallback(function()
|
self.ui:registerPostReaderReadyCallback(function()
|
||||||
self:addCurrentLocationToStack()
|
self:addCurrentLocationToStack()
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@@ -858,7 +858,7 @@ end
|
|||||||
|
|
||||||
function ReaderLink:onGoToExternalLink(link_url)
|
function ReaderLink:onGoToExternalLink(link_url)
|
||||||
local buttons, title = self:getButtonsForExternalLinkDialog(link_url)
|
local buttons, title = self:getButtonsForExternalLinkDialog(link_url)
|
||||||
self.external_link_dialog = ButtonDialogTitle:new{
|
self.external_link_dialog = ButtonDialog:new{
|
||||||
title = title,
|
title = title,
|
||||||
buttons = buttons,
|
buttons = buttons,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ function ReaderRolling:init()
|
|||||||
self.valid_cache_rendering_hash = self.ui.document:getDocumentRenderingHash(false)
|
self.valid_cache_rendering_hash = self.ui.document:getDocumentRenderingHash(false)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
table.insert(self.ui.postReaderCallback, function()
|
table.insert(self.ui.postReaderReadyCallback, function()
|
||||||
self:updatePos()
|
self:updatePos()
|
||||||
-- Disable crengine internal history, with required redraw
|
-- Disable crengine internal history, with required redraw
|
||||||
self.ui.document:enableInternalHistory(false)
|
self.ui.document:enableInternalHistory(false)
|
||||||
@@ -234,7 +234,7 @@ function ReaderRolling:onReadSettings(config)
|
|||||||
-- And check if we can migrate to a newest DOM version after
|
-- And check if we can migrate to a newest DOM version after
|
||||||
-- the book is loaded (unless the user told us not to).
|
-- the book is loaded (unless the user told us not to).
|
||||||
if config:nilOrFalse("cre_keep_old_dom_version") then
|
if config:nilOrFalse("cre_keep_old_dom_version") then
|
||||||
self.ui:registerPostReadyCallback(function()
|
self.ui:registerPostReaderReadyCallback(function()
|
||||||
self:checkXPointersAndProposeDOMVersionUpgrade()
|
self:checkXPointersAndProposeDOMVersionUpgrade()
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@@ -1029,9 +1029,9 @@ function ReaderRolling:onUpdatePos(force)
|
|||||||
if self.batched_update_count > 0 then
|
if self.batched_update_count > 0 then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if self.ui.postReaderCallback ~= nil then -- ReaderUI:init() not yet done
|
if self.ui.postReaderReadyCallback ~= nil then -- ReaderUI:init() not yet done
|
||||||
-- Don't schedule any updatePos as long as ReaderUI:init() is
|
-- Don't schedule any updatePos as long as ReaderUI:init() is
|
||||||
-- not finished (one will be called in the ui.postReaderCallback
|
-- not finished (one will be called in the ui.postReaderReadyCallback
|
||||||
-- we have set above) to avoid multiple refreshes.
|
-- we have set above) to avoid multiple refreshes.
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
@@ -1129,7 +1129,7 @@ function ReaderRolling:onRedrawCurrentView()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function ReaderRolling:onSetDimensions(dimen)
|
function ReaderRolling:onSetDimensions(dimen)
|
||||||
if self.ui.postReaderCallback ~= nil then
|
if self.ui.postReaderReadyCallback ~= nil then
|
||||||
-- ReaderUI:init() not yet done: just set document dimensions
|
-- ReaderUI:init() not yet done: just set document dimensions
|
||||||
self.ui.document:setViewDimen(Screen:getSize())
|
self.ui.document:setViewDimen(Screen:getSize())
|
||||||
-- (what's done in the following else is done elsewhere by
|
-- (what's done in the following else is done elsewhere by
|
||||||
@@ -1445,25 +1445,12 @@ function ReaderRolling:checkXPointersAndProposeDOMVersionUpgrade()
|
|||||||
local applyFuncToXPointersSlots = function(func)
|
local applyFuncToXPointersSlots = function(func)
|
||||||
-- Last position
|
-- Last position
|
||||||
func(self, "xpointer", "last position in book")
|
func(self, "xpointer", "last position in book")
|
||||||
-- Bookmarks
|
-- Annotations
|
||||||
if self.ui.bookmark and self.ui.bookmark.bookmarks and #self.ui.bookmark.bookmarks > 0 then
|
if self.ui.annotation and self.ui.annotation.annotations and #self.ui.annotation.annotations > 0 then
|
||||||
local slots = { "page", "pos0", "pos1" }
|
local slots = { "page", "pos0", "pos1" }
|
||||||
for _, bookmark in ipairs(self.ui.bookmark.bookmarks) do
|
for _, item in ipairs(self.ui.annotation.annotations) do
|
||||||
for _, slot in ipairs(slots) do
|
for _, slot in ipairs(slots) do
|
||||||
func(bookmark, slot, bookmark.notes or "bookmark")
|
func(item, slot, item.text or "annotation")
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- Highlights
|
|
||||||
if self.view.highlight and self.view.highlight.saved then
|
|
||||||
local slots = { "pos0", "pos1" }
|
|
||||||
for page, items in pairs(self.view.highlight.saved) do
|
|
||||||
if items and #items > 0 then
|
|
||||||
for _, highlight in ipairs(items) do
|
|
||||||
for _, slot in ipairs(slots) do
|
|
||||||
func(highlight, slot, highlight.text or "highlight")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1509,6 +1496,9 @@ function ReaderRolling:checkXPointersAndProposeDOMVersionUpgrade()
|
|||||||
local new_xp = normalized_xpointers[xp]
|
local new_xp = normalized_xpointers[xp]
|
||||||
if new_xp then
|
if new_xp then
|
||||||
obj[slot] = new_xp
|
obj[slot] = new_xp
|
||||||
|
if slot == "page" then
|
||||||
|
self.ui.annotation:updateItemByXPointer(obj)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
-- Let lost/not-found XPointer be. There is a small chance that
|
-- Let lost/not-found XPointer be. There is a small chance that
|
||||||
-- it will be found (it it was made before the boxing code moved
|
-- it will be found (it it was made before the boxing code moved
|
||||||
|
|||||||
@@ -186,11 +186,11 @@ function ReaderThumbnail:removeFromCache(hash_subs, remove_only_non_matching)
|
|||||||
return nb_removed, size_removed
|
return nb_removed, size_removed
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderThumbnail:resetCachedPagesForBookmarks(...)
|
function ReaderThumbnail:resetCachedPagesForBookmarks(annotations)
|
||||||
-- Multiple bookmarks may be provided
|
-- Multiple bookmarks may be provided
|
||||||
local start_page, end_page
|
local start_page, end_page
|
||||||
for i = 1, select("#", ...) do
|
for i = 1, #annotations do
|
||||||
local bm = select(i, ...)
|
local bm = annotations[i]
|
||||||
if self.ui.rolling then
|
if self.ui.rolling then
|
||||||
-- Look at all properties that may be xpointers
|
-- Look at all properties that may be xpointers
|
||||||
for _, k in ipairs({"page", "pos0", "pos1"}) do
|
for _, k in ipairs({"page", "pos0", "pos1"}) do
|
||||||
@@ -537,9 +537,6 @@ end
|
|||||||
ReaderThumbnail.onDocumentRerendered = ReaderThumbnail.resetCache
|
ReaderThumbnail.onDocumentRerendered = ReaderThumbnail.resetCache
|
||||||
ReaderThumbnail.onDocumentPartiallyRerendered = ReaderThumbnail.resetCache
|
ReaderThumbnail.onDocumentPartiallyRerendered = ReaderThumbnail.resetCache
|
||||||
-- Emitted When adding/removing/updating bookmarks and highlights
|
-- Emitted When adding/removing/updating bookmarks and highlights
|
||||||
ReaderThumbnail.onBookmarkAdded = ReaderThumbnail.resetCachedPagesForBookmarks
|
ReaderThumbnail.onAnnotationsModified = ReaderThumbnail.resetCachedPagesForBookmarks
|
||||||
ReaderThumbnail.onBookmarkRemoved = ReaderThumbnail.resetCachedPagesForBookmarks
|
|
||||||
ReaderThumbnail.onBookmarkUpdated = ReaderThumbnail.resetCachedPagesForBookmarks
|
|
||||||
ReaderThumbnail.onBookmarkEdited = ReaderThumbnail.resetCachedPagesForBookmarks
|
|
||||||
|
|
||||||
return ReaderThumbnail
|
return ReaderThumbnail
|
||||||
|
|||||||
@@ -95,7 +95,6 @@ function ReaderView:init()
|
|||||||
temp_drawer = "invert",
|
temp_drawer = "invert",
|
||||||
temp = {},
|
temp = {},
|
||||||
saved_drawer = "lighten",
|
saved_drawer = "lighten",
|
||||||
saved = {},
|
|
||||||
indicator = nil, -- geom: non-touch highlight position indicator: {x = 50, y=50}
|
indicator = nil, -- geom: non-touch highlight position indicator: {x = 50, y=50}
|
||||||
}
|
}
|
||||||
self.page_states = {}
|
self.page_states = {}
|
||||||
@@ -522,6 +521,7 @@ function ReaderView:drawTempHighlight(bb, x, y)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function ReaderView:drawSavedHighlight(bb, x, y)
|
function ReaderView:drawSavedHighlight(bb, x, y)
|
||||||
|
if #self.ui.annotation.annotations == 0 then return end
|
||||||
if self.ui.paging then
|
if self.ui.paging then
|
||||||
self:drawPageSavedHighlight(bb, x, y)
|
self:drawPageSavedHighlight(bb, x, y)
|
||||||
else
|
else
|
||||||
@@ -529,45 +529,18 @@ function ReaderView:drawSavedHighlight(bb, x, y)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Returns the list of highlights in page.
|
|
||||||
-- The list includes full single-page highlights and parts of multi-page highlights.
|
|
||||||
function ReaderView:getPageSavedHighlights(page)
|
|
||||||
local highlights = {}
|
|
||||||
local is_reflow = self.document.configurable.text_wrap
|
|
||||||
self.document.configurable.text_wrap = 0
|
|
||||||
for page_num, page_highlights in pairs(self.highlight.saved) do
|
|
||||||
for i, highlight in ipairs(page_highlights) do
|
|
||||||
-- old single-page reflow highlights do not have page in position
|
|
||||||
local pos0_page = highlight.pos0.page or page_num
|
|
||||||
local pos1_page = highlight.pos1.page or page_num
|
|
||||||
if pos0_page <= page and page <= pos1_page then
|
|
||||||
if pos0_page == pos1_page then -- single-page highlight
|
|
||||||
table.insert(highlights, highlight)
|
|
||||||
else -- multi-page highlight
|
|
||||||
local item = self.ui.highlight:getSavedExtendedHighlightPage(highlight, page, i)
|
|
||||||
table.insert(highlights, item)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
self.document.configurable.text_wrap = is_reflow
|
|
||||||
return highlights
|
|
||||||
end
|
|
||||||
|
|
||||||
function ReaderView:drawPageSavedHighlight(bb, x, y)
|
function ReaderView:drawPageSavedHighlight(bb, x, y)
|
||||||
local pages = self:getCurrentPageList()
|
local pages = self:getCurrentPageList()
|
||||||
for _, page in ipairs(pages) do
|
for _, page in ipairs(pages) do
|
||||||
local items = self:getPageSavedHighlights(page)
|
local items = self.ui.highlight:getPageSavedHighlights(page)
|
||||||
for _, item in ipairs(items) do
|
for _, item in ipairs(items) do
|
||||||
local boxes = self.document:getPageBoxesFromPositions(page, item.pos0, item.pos1)
|
local boxes = self.document:getPageBoxesFromPositions(page, item.pos0, item.pos1)
|
||||||
if boxes then
|
if boxes then
|
||||||
local drawer = item.drawer or self.highlight.saved_drawer
|
local draw_note_mark = item.note and self.highlight.note_mark
|
||||||
local draw_note_mark = self.highlight.note_mark and
|
|
||||||
self.ui.bookmark:getBookmarkNote({datetime = item.datetime})
|
|
||||||
for _, box in ipairs(boxes) do
|
for _, box in ipairs(boxes) do
|
||||||
local rect = self:pageToScreenTransform(page, box)
|
local rect = self:pageToScreenTransform(page, box)
|
||||||
if rect then
|
if rect then
|
||||||
self:drawHighlightRect(bb, x, y, rect, drawer, draw_note_mark)
|
self:drawHighlightRect(bb, x, y, rect, item.drawer, draw_note_mark)
|
||||||
if draw_note_mark and self.highlight.note_mark == "sidemark" then
|
if draw_note_mark and self.highlight.note_mark == "sidemark" then
|
||||||
draw_note_mark = false -- side mark in the first line only
|
draw_note_mark = false -- side mark in the first line only
|
||||||
end
|
end
|
||||||
@@ -583,48 +556,38 @@ function ReaderView:drawXPointerSavedHighlight(bb, x, y)
|
|||||||
-- showing menu...). We might want to cache these boxes per page (and
|
-- showing menu...). We might want to cache these boxes per page (and
|
||||||
-- clear that cache when page layout change or highlights are added
|
-- clear that cache when page layout change or highlights are added
|
||||||
-- or removed).
|
-- or removed).
|
||||||
local cur_view_top, cur_view_bottom
|
-- Even in page mode, it's safer to use pos and ui.dimen.h
|
||||||
for _, items in pairs(self.highlight.saved) do
|
-- than pages' xpointers pos, even if ui.dimen.h is a bit
|
||||||
if items then
|
-- larger than pages' heights
|
||||||
for j = 1, #items do
|
local cur_view_top = self.document:getCurrentPos()
|
||||||
local item = items[j]
|
local cur_view_bottom
|
||||||
local pos0, pos1 = item.pos0, item.pos1
|
if self.view_mode == "page" and self.document:getVisiblePageCount() > 1 then
|
||||||
-- document:getScreenBoxesFromPositions() is expensive, so we
|
cur_view_bottom = cur_view_top + 2 * self.ui.dimen.h
|
||||||
-- first check this item is on current page
|
else
|
||||||
if not cur_view_top then
|
cur_view_bottom = cur_view_top + self.ui.dimen.h
|
||||||
-- Even in page mode, it's safer to use pos and ui.dimen.h
|
end
|
||||||
-- than pages' xpointers pos, even if ui.dimen.h is a bit
|
for _, item in ipairs(self.ui.annotation.annotations) do
|
||||||
-- larger than pages' heights
|
if item.drawer then
|
||||||
cur_view_top = self.document:getCurrentPos()
|
-- document:getScreenBoxesFromPositions() is expensive, so we
|
||||||
if self.view_mode == "page" and self.document:getVisiblePageCount() > 1 then
|
-- first check if this item is on current page
|
||||||
cur_view_bottom = cur_view_top + 2 * self.ui.dimen.h
|
local start_pos = self.document:getPosFromXPointer(item.pos0)
|
||||||
else
|
local end_pos = self.document:getPosFromXPointer(item.pos1)
|
||||||
cur_view_bottom = cur_view_top + self.ui.dimen.h
|
if start_pos <= cur_view_bottom and end_pos >= cur_view_top then
|
||||||
|
local boxes = self.document:getScreenBoxesFromPositions(item.pos0, item.pos1, true) -- get_segments=true
|
||||||
|
if boxes then
|
||||||
|
local draw_note_mark = item.note and self.highlight.note_mark
|
||||||
|
for _, box in ipairs(boxes) do
|
||||||
|
if box.h ~= 0 then
|
||||||
|
self:drawHighlightRect(bb, x, y, box, item.drawer, draw_note_mark)
|
||||||
|
if draw_note_mark and self.highlight.note_mark == "sidemark" then
|
||||||
|
draw_note_mark = false -- side mark in the first line only
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local spos0 = self.document:getPosFromXPointer(pos0)
|
end
|
||||||
local spos1 = self.document:getPosFromXPointer(pos1)
|
|
||||||
local start_pos = math.min(spos0, spos1)
|
|
||||||
local end_pos = math.max(spos0, spos1)
|
|
||||||
if start_pos <= cur_view_bottom and end_pos >= cur_view_top then
|
|
||||||
local boxes = self.document:getScreenBoxesFromPositions(pos0, pos1, true) -- get_segments=true
|
|
||||||
if boxes then
|
|
||||||
local drawer = item.drawer or self.highlight.saved_drawer
|
|
||||||
local draw_note_mark = self.highlight.note_mark and
|
|
||||||
self.ui.bookmark:getBookmarkNote({datetime = item.datetime})
|
|
||||||
for _, box in ipairs(boxes) do
|
|
||||||
if box.h ~= 0 then
|
|
||||||
self:drawHighlightRect(bb, x, y, box, drawer, draw_note_mark)
|
|
||||||
if draw_note_mark and self.highlight.note_mark == "sidemark" then
|
|
||||||
draw_note_mark = false -- side mark in the first line only
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end -- end for each box
|
|
||||||
end -- end if boxes
|
|
||||||
end
|
|
||||||
end -- end for each highlight
|
|
||||||
end
|
end
|
||||||
end -- end for all saved highlight
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderView:drawHighlightRect(bb, _x, _y, rect, drawer, draw_note_mark)
|
function ReaderView:drawHighlightRect(bb, _x, _y, rect, drawer, draw_note_mark)
|
||||||
@@ -914,40 +877,6 @@ function ReaderView:onReadSettings(config)
|
|||||||
self:resetLayout()
|
self:resetLayout()
|
||||||
local page_scroll = config:readSetting("kopt_page_scroll") or self.document.configurable.page_scroll
|
local page_scroll = config:readSetting("kopt_page_scroll") or self.document.configurable.page_scroll
|
||||||
self.page_scroll = page_scroll == 1 and true or false
|
self.page_scroll = page_scroll == 1 and true or false
|
||||||
self.highlight.saved = config:readSetting("highlight", {})
|
|
||||||
-- Highlight formats in crengine and mupdf are incompatible.
|
|
||||||
-- Backup highlights when the document is opened with incompatible engine.
|
|
||||||
local page, page_highlights
|
|
||||||
while true do -- remove empty tables for pages without highlights and get the first page with highlights
|
|
||||||
page, page_highlights = next(self.highlight.saved)
|
|
||||||
if not page or #page_highlights > 0 then
|
|
||||||
break -- we're done (there is none, or there is some usable)
|
|
||||||
else
|
|
||||||
self.highlight.saved[page] = nil -- clean it up while we're at it, and find another one
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if page_highlights then
|
|
||||||
local highlight_type = type(page_highlights[1].pos0)
|
|
||||||
if self.ui.rolling and highlight_type == "table" then
|
|
||||||
config:saveSetting("highlight_paging", self.highlight.saved)
|
|
||||||
self.highlight.saved = config:readSetting("highlight_rolling", {})
|
|
||||||
config:saveSetting("highlight", self.highlight.saved)
|
|
||||||
config:delSetting("highlight_rolling")
|
|
||||||
elseif self.ui.paging and highlight_type == "string" then
|
|
||||||
config:saveSetting("highlight_rolling", self.highlight.saved)
|
|
||||||
self.highlight.saved = config:readSetting("highlight_paging", {})
|
|
||||||
config:saveSetting("highlight", self.highlight.saved)
|
|
||||||
config:delSetting("highlight_paging")
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if self.ui.rolling and config:has("highlight_rolling") then
|
|
||||||
self.highlight.saved = config:readSetting("highlight_rolling")
|
|
||||||
config:delSetting("highlight_rolling")
|
|
||||||
elseif self.ui.paging and config:has("highlight_paging") then
|
|
||||||
self.highlight.saved = config:readSetting("highlight_paging")
|
|
||||||
config:delSetting("highlight_paging")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
self.inverse_reading_order = config:isTrue("inverse_reading_order") or G_reader_settings:isTrue("inverse_reading_order")
|
self.inverse_reading_order = config:isTrue("inverse_reading_order") or G_reader_settings:isTrue("inverse_reading_order")
|
||||||
self.page_overlap_enable = config:isTrue("show_overlap_enable") or G_reader_settings:isTrue("page_overlap_enable") or G_defaults:readSetting("DSHOWOVERLAP")
|
self.page_overlap_enable = config:isTrue("show_overlap_enable") or G_reader_settings:isTrue("page_overlap_enable") or G_defaults:readSetting("DSHOWOVERLAP")
|
||||||
self.page_overlap_style = config:readSetting("page_overlap_style") or G_reader_settings:readSetting("page_overlap_style") or "dim"
|
self.page_overlap_style = config:readSetting("page_overlap_style") or G_reader_settings:readSetting("page_overlap_style") or "dim"
|
||||||
@@ -1107,7 +1036,6 @@ function ReaderView:onSaveSettings()
|
|||||||
if G_reader_settings:nilOrFalse("lock_rotation") then
|
if G_reader_settings:nilOrFalse("lock_rotation") then
|
||||||
self.document.configurable.rotation_mode = Screen:getRotationMode() -- will be saved by ReaderConfig
|
self.document.configurable.rotation_mode = Screen:getRotationMode() -- will be saved by ReaderConfig
|
||||||
end
|
end
|
||||||
self.ui.doc_settings:saveSetting("highlight", self.highlight.saved)
|
|
||||||
self.ui.doc_settings:saveSetting("inverse_reading_order", self.inverse_reading_order)
|
self.ui.doc_settings:saveSetting("inverse_reading_order", self.inverse_reading_order)
|
||||||
self.ui.doc_settings:saveSetting("show_overlap_enable", self.page_overlap_enable)
|
self.ui.doc_settings:saveSetting("show_overlap_enable", self.page_overlap_enable)
|
||||||
self.ui.doc_settings:saveSetting("page_overlap_style", self.page_overlap_style)
|
self.ui.doc_settings:saveSetting("page_overlap_style", self.page_overlap_style)
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ local LanguageSupport = require("languagesupport")
|
|||||||
local Notification = require("ui/widget/notification")
|
local Notification = require("ui/widget/notification")
|
||||||
local PluginLoader = require("pluginloader")
|
local PluginLoader = require("pluginloader")
|
||||||
local ReaderActivityIndicator = require("apps/reader/modules/readeractivityindicator")
|
local ReaderActivityIndicator = require("apps/reader/modules/readeractivityindicator")
|
||||||
|
local ReaderAnnotation = require("apps/reader/modules/readerannotation")
|
||||||
local ReaderBack = require("apps/reader/modules/readerback")
|
local ReaderBack = require("apps/reader/modules/readerback")
|
||||||
local ReaderBookmark = require("apps/reader/modules/readerbookmark")
|
local ReaderBookmark = require("apps/reader/modules/readerbookmark")
|
||||||
local ReaderConfig = require("apps/reader/modules/readerconfig")
|
local ReaderConfig = require("apps/reader/modules/readerconfig")
|
||||||
@@ -83,7 +84,7 @@ local ReaderUI = InputContainer:extend{
|
|||||||
password = nil,
|
password = nil,
|
||||||
|
|
||||||
postInitCallback = nil,
|
postInitCallback = nil,
|
||||||
postReaderCallback = nil,
|
postReaderReadyCallback = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
function ReaderUI:registerModule(name, ui_module, always_active)
|
function ReaderUI:registerModule(name, ui_module, always_active)
|
||||||
@@ -102,8 +103,8 @@ function ReaderUI:registerPostInitCallback(callback)
|
|||||||
table.insert(self.postInitCallback, callback)
|
table.insert(self.postInitCallback, callback)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderUI:registerPostReadyCallback(callback)
|
function ReaderUI:registerPostReaderReadyCallback(callback)
|
||||||
table.insert(self.postReaderCallback, callback)
|
table.insert(self.postReaderReadyCallback, callback)
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderUI:init()
|
function ReaderUI:init()
|
||||||
@@ -116,7 +117,7 @@ function ReaderUI:init()
|
|||||||
Device:setIgnoreInput(true) -- Avoid ANRs on Android with unprocessed events.
|
Device:setIgnoreInput(true) -- Avoid ANRs on Android with unprocessed events.
|
||||||
|
|
||||||
self.postInitCallback = {}
|
self.postInitCallback = {}
|
||||||
self.postReaderCallback = {}
|
self.postReaderReadyCallback = {}
|
||||||
-- if we are not the top level dialog ourselves, it must be given in the table
|
-- if we are not the top level dialog ourselves, it must be given in the table
|
||||||
if not self.dialog then
|
if not self.dialog then
|
||||||
self.dialog = self
|
self.dialog = self
|
||||||
@@ -182,6 +183,12 @@ function ReaderUI:init()
|
|||||||
view = self.view,
|
view = self.view,
|
||||||
ui = self
|
ui = self
|
||||||
})
|
})
|
||||||
|
self:registerModule("annotation", ReaderAnnotation:new{
|
||||||
|
dialog = self.dialog,
|
||||||
|
view = self.view,
|
||||||
|
ui = self,
|
||||||
|
document = self.document,
|
||||||
|
})
|
||||||
-- reader goto controller
|
-- reader goto controller
|
||||||
-- "goto" being a dirty keyword in Lua?
|
-- "goto" being a dirty keyword in Lua?
|
||||||
self:registerModule("gotopage", ReaderGoto:new{
|
self:registerModule("gotopage", ReaderGoto:new{
|
||||||
@@ -491,10 +498,10 @@ function ReaderUI:init()
|
|||||||
-- Need the same event for PDF document
|
-- Need the same event for PDF document
|
||||||
self:handleEvent(Event:new("ReaderReady", self.doc_settings))
|
self:handleEvent(Event:new("ReaderReady", self.doc_settings))
|
||||||
|
|
||||||
for _,v in ipairs(self.postReaderCallback) do
|
for _,v in ipairs(self.postReaderReadyCallback) do
|
||||||
v()
|
v()
|
||||||
end
|
end
|
||||||
self.postReaderCallback = nil
|
self.postReaderReadyCallback = nil
|
||||||
|
|
||||||
Device:setIgnoreInput(false) -- Allow processing of events (on Android).
|
Device:setIgnoreInput(false) -- Allow processing of events (on Android).
|
||||||
Input:inhibitInputUntil(0.2)
|
Input:inhibitInputUntil(0.2)
|
||||||
@@ -584,6 +591,7 @@ end
|
|||||||
function ReaderUI:showReader(file, provider, seamless)
|
function ReaderUI:showReader(file, provider, seamless)
|
||||||
logger.dbg("show reader ui")
|
logger.dbg("show reader ui")
|
||||||
|
|
||||||
|
file = ffiUtil.realpath(file)
|
||||||
if lfs.attributes(file, "mode") ~= "file" then
|
if lfs.attributes(file, "mode") ~= "file" then
|
||||||
UIManager:show(InfoMessage:new{
|
UIManager:show(InfoMessage:new{
|
||||||
text = T(_("File '%1' does not exist."), BD.filepath(file))
|
text = T(_("File '%1' does not exist."), BD.filepath(file))
|
||||||
|
|||||||
@@ -503,14 +503,14 @@ Show translated text in TextViewer, with alternate translations
|
|||||||
@string source_lang[opt="auto"] (`"en"`, `"fr"`, `…`) or `"auto"` to auto-detect source language
|
@string source_lang[opt="auto"] (`"en"`, `"fr"`, `…`) or `"auto"` to auto-detect source language
|
||||||
@string target_lang[opt] (`"en"`, `"fr"`, `…`)
|
@string target_lang[opt] (`"en"`, `"fr"`, `…`)
|
||||||
--]]
|
--]]
|
||||||
function Translator:showTranslation(text, detailed_view, source_lang, target_lang, from_highlight, page, index)
|
function Translator:showTranslation(text, detailed_view, source_lang, target_lang, from_highlight, index)
|
||||||
if Device:hasClipboard() then
|
if Device:hasClipboard() then
|
||||||
Device.input.setClipboardText(text)
|
Device.input.setClipboardText(text)
|
||||||
end
|
end
|
||||||
|
|
||||||
local NetworkMgr = require("ui/network/manager")
|
local NetworkMgr = require("ui/network/manager")
|
||||||
if NetworkMgr:willRerunWhenOnline(function()
|
if NetworkMgr:willRerunWhenOnline(function()
|
||||||
self:showTranslation(text, detailed_view, source_lang, target_lang, from_highlight, page, index)
|
self:showTranslation(text, detailed_view, source_lang, target_lang, from_highlight, index)
|
||||||
end) then
|
end) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@@ -519,11 +519,11 @@ function Translator:showTranslation(text, detailed_view, source_lang, target_lan
|
|||||||
-- translation service query.
|
-- translation service query.
|
||||||
local Trapper = require("ui/trapper")
|
local Trapper = require("ui/trapper")
|
||||||
Trapper:wrap(function()
|
Trapper:wrap(function()
|
||||||
self:_showTranslation(text, detailed_view, source_lang, target_lang, from_highlight, page, index)
|
self:_showTranslation(text, detailed_view, source_lang, target_lang, from_highlight, index)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Translator:_showTranslation(text, detailed_view, source_lang, target_lang, from_highlight, page, index)
|
function Translator:_showTranslation(text, detailed_view, source_lang, target_lang, from_highlight, index)
|
||||||
if not target_lang then
|
if not target_lang then
|
||||||
target_lang = self:getTargetLanguage()
|
target_lang = self:getTargetLanguage()
|
||||||
end
|
end
|
||||||
@@ -632,8 +632,8 @@ function Translator:_showTranslation(text, detailed_view, source_lang, target_la
|
|||||||
UIManager:close(textviewer)
|
UIManager:close(textviewer)
|
||||||
UIManager:close(ui.highlight.highlight_dialog)
|
UIManager:close(ui.highlight.highlight_dialog)
|
||||||
ui.highlight.highlight_dialog = nil
|
ui.highlight.highlight_dialog = nil
|
||||||
if page then
|
if index then
|
||||||
ui.highlight:editHighlight(page, index, false, text_main)
|
ui.highlight:editHighlight(index, false, text_main)
|
||||||
else
|
else
|
||||||
ui.highlight:addNote(text_main)
|
ui.highlight:addNote(text_main)
|
||||||
end
|
end
|
||||||
@@ -645,8 +645,8 @@ function Translator:_showTranslation(text, detailed_view, source_lang, target_la
|
|||||||
UIManager:close(textviewer)
|
UIManager:close(textviewer)
|
||||||
UIManager:close(ui.highlight.highlight_dialog)
|
UIManager:close(ui.highlight.highlight_dialog)
|
||||||
ui.highlight.highlight_dialog = nil
|
ui.highlight.highlight_dialog = nil
|
||||||
if page then
|
if index then
|
||||||
ui.highlight:editHighlight(page, index, false, text_all)
|
ui.highlight:editHighlight(index, false, text_all)
|
||||||
else
|
else
|
||||||
ui.highlight:addNote(text_all)
|
ui.highlight:addNote(text_all)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -65,11 +65,6 @@ local DictQuickLookup = InputContainer:extend{
|
|||||||
rotated_update_wiki_languages_on_close = nil,
|
rotated_update_wiki_languages_on_close = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
local highlight_strings = {
|
|
||||||
highlight =_("Highlight"),
|
|
||||||
unhighlight = _("Unhighlight"),
|
|
||||||
}
|
|
||||||
|
|
||||||
function DictQuickLookup.getWikiSaveEpubDefaultDir()
|
function DictQuickLookup.getWikiSaveEpubDefaultDir()
|
||||||
local dir = G_reader_settings:readSetting("home_dir") or filemanagerutil.getDefaultDir()
|
local dir = G_reader_settings:readSetting("home_dir") or filemanagerutil.getDefaultDir()
|
||||||
if dir:sub(-1) ~= "/" then
|
if dir:sub(-1) ~= "/" then
|
||||||
@@ -438,19 +433,13 @@ function DictQuickLookup:init()
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id = "highlight",
|
id = "highlight",
|
||||||
text = self:getHighlightText(),
|
text = _("Highlight"),
|
||||||
enabled = not self:isDocless() and self.highlight ~= nil,
|
enabled = not self:isDocless() and self.highlight ~= nil,
|
||||||
callback = function()
|
callback = function()
|
||||||
if self:getHighlightText() == highlight_strings.highlight then
|
self.save_highlight = not self.save_highlight
|
||||||
self.ui:handleEvent(Event:new("Highlight"))
|
|
||||||
else
|
|
||||||
self.ui:handleEvent(Event:new("Unhighlight"))
|
|
||||||
end
|
|
||||||
-- Just update, repaint and refresh *this* button
|
-- Just update, repaint and refresh *this* button
|
||||||
local this = self.button_table:getButtonById("highlight")
|
local this = self.button_table:getButtonById("highlight")
|
||||||
if not this then return end
|
this:setText(self.save_highlight and _("Unhighlight") or _("Highlight"), this.width)
|
||||||
this:enableDisable(self.highlight ~= nil)
|
|
||||||
this:setText(self:getHighlightText(), this.width)
|
|
||||||
this:refresh()
|
this:refresh()
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
@@ -953,22 +942,6 @@ function DictQuickLookup:onShow()
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function DictQuickLookup:getHighlightedItem()
|
|
||||||
if self:isDocless() then return end
|
|
||||||
return self.ui.highlight:getHighlightBookmarkItem()
|
|
||||||
end
|
|
||||||
|
|
||||||
function DictQuickLookup:getHighlightText()
|
|
||||||
local item = self:getHighlightedItem()
|
|
||||||
if not item then
|
|
||||||
return highlight_strings.highlight, false
|
|
||||||
elseif self.ui.bookmark:isBookmarkAdded(item) then
|
|
||||||
return highlight_strings.unhighlight, false
|
|
||||||
else
|
|
||||||
return highlight_strings.highlight, true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function DictQuickLookup:isPrevDictAvaiable()
|
function DictQuickLookup:isPrevDictAvaiable()
|
||||||
return self.dict_index > 1
|
return self.dict_index > 1
|
||||||
end
|
end
|
||||||
@@ -1150,13 +1123,19 @@ function DictQuickLookup:onClose(no_clear)
|
|||||||
self.ui:handleEvent(Event:new("UpdateWikiLanguages", self.wiki_languages))
|
self.ui:handleEvent(Event:new("UpdateWikiLanguages", self.wiki_languages))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if self.highlight and not no_clear then
|
|
||||||
-- delay unhighlight of selection, so we can see where we stopped when
|
if self.save_highlight then
|
||||||
-- back from our journey into dictionary or wikipedia
|
self.highlight:saveHighlight()
|
||||||
local clear_id = self.highlight:getClearId()
|
self.highlight:clear()
|
||||||
UIManager:scheduleIn(0.5, function()
|
else
|
||||||
self.highlight:clear(clear_id)
|
if self.highlight and not no_clear then
|
||||||
end)
|
-- delay unhighlight of selection, so we can see where we stopped when
|
||||||
|
-- back from our journey into dictionary or wikipedia
|
||||||
|
local clear_id = self.highlight:getClearId()
|
||||||
|
UIManager:scheduleIn(0.5, function()
|
||||||
|
self.highlight:clear(clear_id)
|
||||||
|
end)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -57,8 +57,14 @@ function CoverMenu:updateCache(file, status, do_create, pages)
|
|||||||
local percent_finished = doc_settings:readSetting("percent_finished")
|
local percent_finished = doc_settings:readSetting("percent_finished")
|
||||||
local summary = doc_settings:readSetting("summary")
|
local summary = doc_settings:readSetting("summary")
|
||||||
status = summary and summary.status
|
status = summary and summary.status
|
||||||
local highlight = doc_settings:readSetting("highlight")
|
local has_highlight
|
||||||
local has_highlight = highlight and next(highlight) and true
|
local annotations = doc_settings:readSetting("annotations")
|
||||||
|
if annotations then
|
||||||
|
has_highlight = #annotations > 0
|
||||||
|
else
|
||||||
|
local highlight = doc_settings:readSetting("highlight")
|
||||||
|
has_highlight = highlight and next(highlight) and true
|
||||||
|
end
|
||||||
self.cover_info_cache[file] = table.pack(pages, percent_finished, status, has_highlight) -- may be a sparse array
|
self.cover_info_cache[file] = table.pack(pages, percent_finished, status, has_highlight) -- may be a sparse array
|
||||||
else
|
else
|
||||||
if self.cover_info_cache and self.cover_info_cache[file] then
|
if self.cover_info_cache and self.cover_info_cache[file] then
|
||||||
|
|||||||
@@ -235,6 +235,23 @@ function MyClipping:getImage(image)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function MyClipping:parseAnnotations(annotations, book)
|
||||||
|
for _, item in ipairs(annotations) do
|
||||||
|
if item.drawer then
|
||||||
|
local clipping = {
|
||||||
|
sort = "highlight",
|
||||||
|
page = item.pageno,
|
||||||
|
time = self:getTime(item.datetime),
|
||||||
|
text = self:getText(item.text),
|
||||||
|
note = self:getText(item.note),
|
||||||
|
chapter = item.chapter,
|
||||||
|
drawer = item.drawer,
|
||||||
|
}
|
||||||
|
table.insert(book, { clipping })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function MyClipping:parseHighlight(highlights, bookmarks, book)
|
function MyClipping:parseHighlight(highlights, bookmarks, book)
|
||||||
--DEBUG("book", book.file)
|
--DEBUG("book", book.file)
|
||||||
|
|
||||||
@@ -249,13 +266,14 @@ function MyClipping:parseHighlight(highlights, bookmarks, book)
|
|||||||
local orphan_highlights = {}
|
local orphan_highlights = {}
|
||||||
for page, items in pairs(highlights) do
|
for page, items in pairs(highlights) do
|
||||||
for _, item in ipairs(items) do
|
for _, item in ipairs(items) do
|
||||||
local clipping = {}
|
local clipping = {
|
||||||
clipping.page = page
|
sort = "highlight",
|
||||||
clipping.sort = "highlight"
|
page = page,
|
||||||
clipping.time = self:getTime(item.datetime or "")
|
time = self:getTime(item.datetime or ""),
|
||||||
clipping.text = self:getText(item.text)
|
text = self:getText(item.text),
|
||||||
clipping.chapter = item.chapter
|
chapter = item.chapter,
|
||||||
clipping.drawer = item.drawer
|
drawer = item.drawer,
|
||||||
|
}
|
||||||
local bookmark_found = false
|
local bookmark_found = false
|
||||||
for _, bookmark in pairs(bookmarks) do
|
for _, bookmark in pairs(bookmarks) do
|
||||||
if bookmark.datetime == item.datetime then
|
if bookmark.datetime == item.datetime then
|
||||||
@@ -316,9 +334,13 @@ end
|
|||||||
|
|
||||||
function MyClipping:getClippingsFromBook(clippings, doc_path)
|
function MyClipping:getClippingsFromBook(clippings, doc_path)
|
||||||
local doc_settings = DocSettings:open(doc_path)
|
local doc_settings = DocSettings:open(doc_path)
|
||||||
local highlights = doc_settings:readSetting("highlight")
|
local highlights, bookmarks
|
||||||
if not highlights then return end
|
local annotations = doc_settings:readSetting("annotations")
|
||||||
local bookmarks = doc_settings:readSetting("bookmarks")
|
if annotations == nil then
|
||||||
|
highlights = doc_settings:readSetting("highlight")
|
||||||
|
if highlights == nil then return end
|
||||||
|
bookmarks = doc_settings:readSetting("bookmarks")
|
||||||
|
end
|
||||||
local props = doc_settings:readSetting("doc_props")
|
local props = doc_settings:readSetting("doc_props")
|
||||||
props = FileManagerBookInfo.extendProps(props, doc_path)
|
props = FileManagerBookInfo.extendProps(props, doc_path)
|
||||||
local title, author = self:getTitleAuthor(doc_path, props)
|
local title, author = self:getTitleAuthor(doc_path, props)
|
||||||
@@ -326,8 +348,13 @@ function MyClipping:getClippingsFromBook(clippings, doc_path)
|
|||||||
file = doc_path,
|
file = doc_path,
|
||||||
title = title,
|
title = title,
|
||||||
author = author,
|
author = author,
|
||||||
|
number_of_pages = doc_settings:readSetting("doc_pages"),
|
||||||
}
|
}
|
||||||
self:parseHighlight(highlights, bookmarks, clippings[title])
|
if annotations then
|
||||||
|
self:parseAnnotations(annotations, clippings[title])
|
||||||
|
else
|
||||||
|
self:parseHighlight(highlights, bookmarks, clippings[title])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function MyClipping:parseHistory()
|
function MyClipping:parseHistory()
|
||||||
@@ -361,7 +388,7 @@ function MyClipping:parseCurrentDoc(view)
|
|||||||
output_filename = util.getSafeFilename(title),
|
output_filename = util.getSafeFilename(title),
|
||||||
number_of_pages = view.document.info.number_of_pages,
|
number_of_pages = view.document.info.number_of_pages,
|
||||||
}
|
}
|
||||||
self:parseHighlight(view.highlight.saved, view.ui.bookmark.bookmarks, clippings[title])
|
self:parseAnnotations(view.ui.annotation.annotations, clippings[title])
|
||||||
return clippings
|
return clippings
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -156,6 +156,7 @@ end
|
|||||||
|
|
||||||
--- Parse and export highlights from the currently opened document.
|
--- Parse and export highlights from the currently opened document.
|
||||||
function Exporter:exportCurrentNotes()
|
function Exporter:exportCurrentNotes()
|
||||||
|
self.ui.annotation:updatePageNumbers()
|
||||||
local clippings = self:getDocumentClippings()
|
local clippings = self:getDocumentClippings()
|
||||||
self:exportClippings(clippings)
|
self:exportClippings(clippings)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ function ReaderStatistics:initData()
|
|||||||
|
|
||||||
self.data.pages = self.document:getPageCount()
|
self.data.pages = self.document:getPageCount()
|
||||||
-- Update these numbers to what's actually stored in the settings
|
-- Update these numbers to what's actually stored in the settings
|
||||||
self.data.highlights, self.data.notes = self.ui.bookmark:getNumberOfHighlightsAndNotes()
|
self.data.highlights, self.data.notes = self.ui.annotation:getNumberOfHighlightsAndNotes()
|
||||||
self.id_curr_book = self:getIdBookDB()
|
self.id_curr_book = self:getIdBookDB()
|
||||||
self.book_read_pages, self.book_read_time = self:getPageTimeTotalStats(self.id_curr_book)
|
self.book_read_pages, self.book_read_time = self:getPageTimeTotalStats(self.id_curr_book)
|
||||||
if self.book_read_pages > 0 then
|
if self.book_read_pages > 0 then
|
||||||
@@ -2727,27 +2727,14 @@ function ReaderStatistics:onCloseDocument()
|
|||||||
self:insertDB()
|
self:insertDB()
|
||||||
end
|
end
|
||||||
|
|
||||||
function ReaderStatistics:onAddHighlight()
|
function ReaderStatistics:onAnnotationsModified(annotations)
|
||||||
if self.settings.is_enabled then
|
if self.settings.is_enabled then
|
||||||
self.data.highlights = self.data.highlights + 1
|
if annotations.nb_highlights_added then
|
||||||
end
|
self.data.highlights = self.data.highlights + annotations.nb_highlights_added
|
||||||
end
|
end
|
||||||
|
if annotations.nb_notes_added then
|
||||||
function ReaderStatistics:onDelHighlight()
|
self.data.notes = self.data.notes + annotations.nb_notes_added
|
||||||
if self.settings.is_enabled then
|
end
|
||||||
self.data.highlights = self.data.highlights - 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function ReaderStatistics:onAddNote()
|
|
||||||
if self.settings.is_enabled then
|
|
||||||
self.data.notes = self.data.notes + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function ReaderStatistics:onDelNote()
|
|
||||||
if self.settings.is_enabled then
|
|
||||||
self.data.notes = self.data.notes - 1
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ describe("ReaderBookmark module", function()
|
|||||||
readerui.highlight:onHoldPan(nil, { pos = pos1 })
|
readerui.highlight:onHoldPan(nil, { pos = pos1 })
|
||||||
readerui.highlight:onHoldRelease()
|
readerui.highlight:onHoldRelease()
|
||||||
assert.truthy(readerui.highlight.highlight_dialog)
|
assert.truthy(readerui.highlight.highlight_dialog)
|
||||||
readerui.highlight:onHighlight()
|
readerui.highlight:saveHighlight()
|
||||||
UIManager:nextTick(function()
|
UIManager:nextTick(function()
|
||||||
UIManager:close(readerui.highlight.highlight_dialog)
|
UIManager:close(readerui.highlight.highlight_dialog)
|
||||||
UIManager:close(readerui)
|
UIManager:close(readerui)
|
||||||
@@ -67,17 +67,6 @@ describe("ReaderBookmark module", function()
|
|||||||
UIManager:show(readerui)
|
UIManager:show(readerui)
|
||||||
readerui.rolling:onGotoPage(10)
|
readerui.rolling:onGotoPage(10)
|
||||||
end)
|
end)
|
||||||
it("should compare bookmarks properly", function()
|
|
||||||
assert.truthy(readerui.bookmark:isBookmarkSame(
|
|
||||||
{ notes = 'foo', page = 1, pos0 = 0, pos1 = 2, },
|
|
||||||
{ notes = 'foo', page = 1, pos0 = 0, pos1 = 2, }))
|
|
||||||
assert.falsy(readerui.bookmark:isBookmarkSame(
|
|
||||||
{ notes = 'foo', page = 1, pos0 = 0, pos1 = 2, },
|
|
||||||
{ notes = 'bar', page = 1, pos0 = 0, pos1 = 2, }))
|
|
||||||
assert.falsy(readerui.bookmark:isBookmarkSame(
|
|
||||||
{ notes = 'foo0', page = 1, pos0 = 0, pos1 = 0, },
|
|
||||||
{ notes = 'foo', page = 1, pos0 = 0, pos1 = 2, }))
|
|
||||||
end)
|
|
||||||
it("should show dogear after toggling non-bookmarked page", function()
|
it("should show dogear after toggling non-bookmarked page", function()
|
||||||
assert.falsy(readerui.view.dogear_visible)
|
assert.falsy(readerui.view.dogear_visible)
|
||||||
toggler_dogear(readerui)
|
toggler_dogear(readerui)
|
||||||
@@ -90,7 +79,7 @@ describe("ReaderBookmark module", function()
|
|||||||
Screen:shot("screenshots/reader_bookmark_nodogear_epub.png")
|
Screen:shot("screenshots/reader_bookmark_nodogear_epub.png")
|
||||||
assert.falsy(readerui.view.dogear_visible)
|
assert.falsy(readerui.view.dogear_visible)
|
||||||
end)
|
end)
|
||||||
it("should sort bookmarks with descending page numbers", function()
|
it("should sort bookmarks with ascending page numbers", function()
|
||||||
local pages = {1, 20, 5, 30, 10, 40, 15, 25, 35, 45}
|
local pages = {1, 20, 5, 30, 10, 40, 15, 25, 35, 45}
|
||||||
for _, page in ipairs(pages) do
|
for _, page in ipairs(pages) do
|
||||||
readerui.rolling:onGotoPage(page)
|
readerui.rolling:onGotoPage(page)
|
||||||
@@ -99,11 +88,11 @@ describe("ReaderBookmark module", function()
|
|||||||
readerui.bookmark:onShowBookmark()
|
readerui.bookmark:onShowBookmark()
|
||||||
show_bookmark_menu(readerui)
|
show_bookmark_menu(readerui)
|
||||||
Screen:shot("screenshots/reader_bookmark_10marks_epub.png")
|
Screen:shot("screenshots/reader_bookmark_10marks_epub.png")
|
||||||
assert.are.same(10, #readerui.bookmark.bookmarks)
|
assert.are.same(10, #readerui.annotation.annotations)
|
||||||
|
assert.are.same(15, readerui.document:getPageFromXPointer(readerui.annotation.annotations[4].page))
|
||||||
end)
|
end)
|
||||||
it("should keep descending page numbers after removing bookmarks", function()
|
it("should keep descending page numbers after removing bookmarks", function()
|
||||||
local pages = {1, 30, 10, 40, 20}
|
local pages = {1, 30, 10, 40, 20}
|
||||||
readerui.bookmark.bookmarks = {}
|
|
||||||
for _, page in ipairs(pages) do
|
for _, page in ipairs(pages) do
|
||||||
readerui.rolling:onGotoPage(page)
|
readerui.rolling:onGotoPage(page)
|
||||||
toggler_dogear(readerui)
|
toggler_dogear(readerui)
|
||||||
@@ -111,7 +100,7 @@ describe("ReaderBookmark module", function()
|
|||||||
readerui.bookmark:onShowBookmark()
|
readerui.bookmark:onShowBookmark()
|
||||||
show_bookmark_menu(readerui)
|
show_bookmark_menu(readerui)
|
||||||
Screen:shot("screenshots/reader_bookmark_5marks_epub.png")
|
Screen:shot("screenshots/reader_bookmark_5marks_epub.png")
|
||||||
assert.are.same(5, #readerui.bookmark.bookmarks)
|
assert.are.same(5, #readerui.annotation.annotations)
|
||||||
end)
|
end)
|
||||||
it("should add bookmark by highlighting", function()
|
it("should add bookmark by highlighting", function()
|
||||||
highlight_text(readerui,
|
highlight_text(readerui,
|
||||||
@@ -120,18 +109,18 @@ describe("ReaderBookmark module", function()
|
|||||||
readerui.bookmark:onShowBookmark()
|
readerui.bookmark:onShowBookmark()
|
||||||
show_bookmark_menu(readerui)
|
show_bookmark_menu(readerui)
|
||||||
Screen:shot("screenshots/reader_bookmark_6marks_epub.png")
|
Screen:shot("screenshots/reader_bookmark_6marks_epub.png")
|
||||||
assert.are.same(6, #readerui.bookmark.bookmarks)
|
assert.are.same(6, #readerui.annotation.annotations)
|
||||||
end)
|
end)
|
||||||
it("should get previous bookmark for certain page", function()
|
it("should get previous bookmark for certain page", function()
|
||||||
local xpointer = readerui.document:getXPointer()
|
local xpointer = readerui.document:getXPointer()
|
||||||
local bm_xpointer = readerui.bookmark:getPreviousBookmarkedPage(xpointer)
|
local bm_xpointer = readerui.bookmark:getPreviousBookmarkedPage(xpointer)
|
||||||
assert.are.same(6, #readerui.bookmark.bookmarks)
|
assert.are.same(6, #readerui.annotation.annotations)
|
||||||
assert.are.same(1, readerui.document:getPageFromXPointer(bm_xpointer))
|
assert.are.same(5, readerui.document:getPageFromXPointer(bm_xpointer))
|
||||||
end)
|
end)
|
||||||
it("should get next bookmark for certain page", function()
|
it("should get next bookmark for certain page", function()
|
||||||
local xpointer = readerui.document:getXPointer()
|
local xpointer = readerui.document:getXPointer()
|
||||||
local bm_xpointer = readerui.bookmark:getNextBookmarkedPage(xpointer)
|
local bm_xpointer = readerui.bookmark:getNextBookmarkedPage(xpointer)
|
||||||
assert.are.same(20, readerui.document:getPageFromXPointer(bm_xpointer))
|
assert.are.same(15, readerui.document:getPageFromXPointer(bm_xpointer))
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@@ -154,34 +143,6 @@ describe("ReaderBookmark module", function()
|
|||||||
UIManager:show(readerui)
|
UIManager:show(readerui)
|
||||||
readerui.paging:onGotoPage(10)
|
readerui.paging:onGotoPage(10)
|
||||||
end)
|
end)
|
||||||
it("should does bookmark comparison properly", function()
|
|
||||||
assert.truthy(readerui.bookmark:isBookmarkSame(
|
|
||||||
{ notes = 'foo', pos0 = { page = 1 , x = 2, y = 3},
|
|
||||||
pos1 = { page = 1, x = 20, y = 3 }, },
|
|
||||||
{ notes = 'foo', pos0 = { page = 1 , x = 2, y = 3},
|
|
||||||
pos1 = { page = 1, x = 20, y = 3 }, }))
|
|
||||||
assert.falsy(readerui.bookmark:isBookmarkSame(
|
|
||||||
{ notes = 'foo', page = 1, pos0 = 0, pos1 = 2, },
|
|
||||||
{ notes = 'foo', page = 1, pos1 = 2, }))
|
|
||||||
assert.falsy(readerui.bookmark:isBookmarkSame(
|
|
||||||
{ notes = 'foo', page = 1, pos0 = 0, pos1 = 2, },
|
|
||||||
{ notes = 'foo', page = 1, pos0 = 2, }))
|
|
||||||
assert.falsy(readerui.bookmark:isBookmarkSame(
|
|
||||||
{ notes = 'foo', pos0 = { page = 1 , x = 2, y = 3},
|
|
||||||
pos1 = { page = 1, x = 20, y = 3 }, },
|
|
||||||
{ notes = 'foo', pos0 = { page = 2 , x = 2, y = 3},
|
|
||||||
pos1 = { page = 1, x = 20, y = 3 }, }))
|
|
||||||
assert.falsy(readerui.bookmark:isBookmarkSame(
|
|
||||||
{ notes = 'foo', pos0 = { page = 1 , x = 1, y = 3},
|
|
||||||
pos1 = { page = 1, x = 20, y = 3 }, },
|
|
||||||
{ notes = 'foo', pos0 = { page = 1 , x = 2, y = 3},
|
|
||||||
pos1 = { page = 1, x = 20, y = 3 }, }))
|
|
||||||
assert.falsy(readerui.bookmark:isBookmarkSame(
|
|
||||||
{ notes = 'foo', pos0 = { page = 1 , x = 1, y = 3},
|
|
||||||
pos1 = { page = 1, x = 20, y = 3 }, },
|
|
||||||
{ notes = 'foo', pos0 = { page = 1 , x = 1, y = 3},
|
|
||||||
pos1 = { page = 1, x = 20, y = 2 }, }))
|
|
||||||
end)
|
|
||||||
it("should show dogear after toggling non-bookmarked page", function()
|
it("should show dogear after toggling non-bookmarked page", function()
|
||||||
toggler_dogear(readerui)
|
toggler_dogear(readerui)
|
||||||
Screen:shot("screenshots/reader_bookmark_dogear_pdf.png")
|
Screen:shot("screenshots/reader_bookmark_dogear_pdf.png")
|
||||||
@@ -192,7 +153,7 @@ describe("ReaderBookmark module", function()
|
|||||||
Screen:shot("screenshots/reader_bookmark_nodogear_pdf.png")
|
Screen:shot("screenshots/reader_bookmark_nodogear_pdf.png")
|
||||||
assert.truthy(not readerui.view.dogear_visible)
|
assert.truthy(not readerui.view.dogear_visible)
|
||||||
end)
|
end)
|
||||||
it("should sort bookmarks with descending page numbers", function()
|
it("should sort bookmarks with ascending page numbers", function()
|
||||||
local pages = {1, 20, 5, 30, 10, 40, 15, 25, 35, 45}
|
local pages = {1, 20, 5, 30, 10, 40, 15, 25, 35, 45}
|
||||||
for _, page in ipairs(pages) do
|
for _, page in ipairs(pages) do
|
||||||
readerui.paging:onGotoPage(page)
|
readerui.paging:onGotoPage(page)
|
||||||
@@ -201,7 +162,8 @@ describe("ReaderBookmark module", function()
|
|||||||
readerui.bookmark:onShowBookmark()
|
readerui.bookmark:onShowBookmark()
|
||||||
show_bookmark_menu(readerui)
|
show_bookmark_menu(readerui)
|
||||||
Screen:shot("screenshots/reader_bookmark_10marks_pdf.png")
|
Screen:shot("screenshots/reader_bookmark_10marks_pdf.png")
|
||||||
assert.are.same(10, #readerui.bookmark.bookmarks)
|
assert.are.same(10, #readerui.annotation.annotations)
|
||||||
|
assert.are.same(15, readerui.annotation.annotations[4].page)
|
||||||
end)
|
end)
|
||||||
it("should keep descending page numbers after removing bookmarks", function()
|
it("should keep descending page numbers after removing bookmarks", function()
|
||||||
local pages = {1, 30, 10, 40, 20}
|
local pages = {1, 30, 10, 40, 20}
|
||||||
@@ -212,14 +174,14 @@ describe("ReaderBookmark module", function()
|
|||||||
readerui.bookmark:onShowBookmark()
|
readerui.bookmark:onShowBookmark()
|
||||||
show_bookmark_menu(readerui)
|
show_bookmark_menu(readerui)
|
||||||
Screen:shot("screenshots/reader_bookmark_5marks_pdf.png")
|
Screen:shot("screenshots/reader_bookmark_5marks_pdf.png")
|
||||||
assert.are.same(5, #readerui.bookmark.bookmarks)
|
assert.are.same(5, #readerui.annotation.annotations)
|
||||||
end)
|
end)
|
||||||
it("should add bookmark by highlighting", function()
|
it("should add bookmark by highlighting", function()
|
||||||
highlight_text(readerui, Geom:new{ x = 260, y = 70 }, Geom:new{ x = 260, y = 150 })
|
highlight_text(readerui, Geom:new{ x = 260, y = 70 }, Geom:new{ x = 260, y = 150 })
|
||||||
readerui.bookmark:onShowBookmark()
|
readerui.bookmark:onShowBookmark()
|
||||||
show_bookmark_menu(readerui)
|
show_bookmark_menu(readerui)
|
||||||
Screen:shot("screenshots/reader_bookmark_6marks_pdf.png")
|
Screen:shot("screenshots/reader_bookmark_6marks_pdf.png")
|
||||||
assert.are.same(6, #readerui.bookmark.bookmarks)
|
assert.are.same(6, #readerui.annotation.annotations)
|
||||||
end)
|
end)
|
||||||
it("should get previous bookmark for certain page", function()
|
it("should get previous bookmark for certain page", function()
|
||||||
assert.are.same(5, readerui.bookmark:getPreviousBookmarkedPage(10))
|
assert.are.same(5, readerui.bookmark:getPreviousBookmarkedPage(10))
|
||||||
@@ -227,31 +189,5 @@ describe("ReaderBookmark module", function()
|
|||||||
it("should get next bookmark for certain page", function()
|
it("should get next bookmark for certain page", function()
|
||||||
assert.are.same(15, readerui.bookmark:getNextBookmarkedPage(10))
|
assert.are.same(15, readerui.bookmark:getNextBookmarkedPage(10))
|
||||||
end)
|
end)
|
||||||
it("should search/add bookmarks properly", function()
|
|
||||||
-- clear bookmarks created by previous tests
|
|
||||||
readerui.bookmark.bookmarks = {}
|
|
||||||
local p1 = { x = 0, y = 0, page = 100 }
|
|
||||||
local bm1 = { notes = 'foo', page = 10,
|
|
||||||
pos0 = { x = 0, y = 0, page = 100 }, pos1 = p1, }
|
|
||||||
assert.falsy(readerui.bookmark:isBookmarkAdded(bm1))
|
|
||||||
readerui.bookmark:addBookmark(bm1)
|
|
||||||
assert.are.same(readerui.bookmark.bookmarks, {bm1})
|
|
||||||
|
|
||||||
local bm2 = { notes = 'foo', page = 1,
|
|
||||||
pos0 = { x = 0, y = 0, page = 1 }, pos1 = p1, }
|
|
||||||
assert.falsy(readerui.bookmark:isBookmarkAdded(bm2))
|
|
||||||
readerui.bookmark:addBookmark(bm2)
|
|
||||||
assert.are.same({bm1, bm2}, readerui.bookmark.bookmarks)
|
|
||||||
|
|
||||||
local bm3 = { notes = 'foo', page = 5,
|
|
||||||
pos0 = { x = 0, y = 0, page = 5 }, pos1 = p1, }
|
|
||||||
assert.falsy(readerui.bookmark:isBookmarkAdded(bm3))
|
|
||||||
readerui.bookmark:addBookmark(bm3)
|
|
||||||
assert.are.same({bm1, bm3, bm2}, readerui.bookmark.bookmarks)
|
|
||||||
|
|
||||||
assert.truthy(readerui.bookmark:isBookmarkAdded(bm1))
|
|
||||||
assert.truthy(readerui.bookmark:isBookmarkAdded(bm2))
|
|
||||||
assert.truthy(readerui.bookmark:isBookmarkAdded(bm3))
|
|
||||||
end)
|
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ describe("Readerhighlight module", function()
|
|||||||
|
|
||||||
readerui.highlight:onHold(nil, { pos = pos0 })
|
readerui.highlight:onHold(nil, { pos = pos0 })
|
||||||
readerui.highlight:onHoldRelease()
|
readerui.highlight:onHoldRelease()
|
||||||
readerui.highlight:onHighlight()
|
readerui.highlight:saveHighlight()
|
||||||
|
|
||||||
assert.spy(s).was_called()
|
assert.spy(s).was_called()
|
||||||
assert.spy(s).was_called_with(match.is_ref(readerui.languagesupport),
|
assert.spy(s).was_called_with(match.is_ref(readerui.languagesupport),
|
||||||
@@ -50,7 +50,7 @@ describe("Readerhighlight module", function()
|
|||||||
assert.truthy(readerui.highlight.highlight_dialog)
|
assert.truthy(readerui.highlight.highlight_dialog)
|
||||||
assert.truthy(UIManager._window_stack[next_slot].widget
|
assert.truthy(UIManager._window_stack[next_slot].widget
|
||||||
== readerui.highlight.highlight_dialog)
|
== readerui.highlight.highlight_dialog)
|
||||||
readerui.highlight:onHighlight()
|
readerui.highlight:saveHighlight()
|
||||||
UIManager:scheduleIn(1, function()
|
UIManager:scheduleIn(1, function()
|
||||||
UIManager:close(readerui.highlight.highlight_dialog)
|
UIManager:close(readerui.highlight.highlight_dialog)
|
||||||
UIManager:close(readerui)
|
UIManager:close(readerui)
|
||||||
@@ -64,7 +64,7 @@ describe("Readerhighlight module", function()
|
|||||||
readerui.highlight:onHold(nil, { pos = pos0 })
|
readerui.highlight:onHold(nil, { pos = pos0 })
|
||||||
readerui.highlight:onHoldPan(nil, { pos = pos1 })
|
readerui.highlight:onHoldPan(nil, { pos = pos1 })
|
||||||
readerui.highlight:onHoldRelease()
|
readerui.highlight:onHoldRelease()
|
||||||
readerui.highlight:onHighlight()
|
readerui.highlight:saveHighlight()
|
||||||
readerui.highlight:clear()
|
readerui.highlight:clear()
|
||||||
UIManager:close(readerui.highlight.highlight_dialog)
|
UIManager:close(readerui.highlight.highlight_dialog)
|
||||||
readerui.highlight:onTap(nil, { pos = pos2 })
|
readerui.highlight:onTap(nil, { pos = pos2 })
|
||||||
@@ -106,12 +106,13 @@ describe("Readerhighlight module", function()
|
|||||||
end)
|
end)
|
||||||
after_each(function()
|
after_each(function()
|
||||||
readerui.highlight:clear()
|
readerui.highlight:clear()
|
||||||
|
readerui.annotation.annotations = {}
|
||||||
end)
|
end)
|
||||||
it("should highlight single word", function()
|
it("should highlight single word", function()
|
||||||
highlight_single_word(readerui, Geom:new{ x = 400, y = 70 })
|
highlight_single_word(readerui, Geom:new{ x = 400, y = 70 })
|
||||||
Screen:shot("screenshots/reader_highlight_single_word_epub.png")
|
Screen:shot("screenshots/reader_highlight_single_word_epub.png")
|
||||||
assert.spy(selection_spy).was_called()
|
assert.spy(selection_spy).was_called()
|
||||||
assert.truthy(readerui.view.highlight.saved[page])
|
assert.truthy(#readerui.annotation.annotations == 1)
|
||||||
end)
|
end)
|
||||||
it("should highlight text", function()
|
it("should highlight text", function()
|
||||||
highlight_text(readerui,
|
highlight_text(readerui,
|
||||||
@@ -119,7 +120,7 @@ describe("Readerhighlight module", function()
|
|||||||
Geom:new{ x = 400, y = 170 })
|
Geom:new{ x = 400, y = 170 })
|
||||||
Screen:shot("screenshots/reader_highlight_text_epub.png")
|
Screen:shot("screenshots/reader_highlight_text_epub.png")
|
||||||
assert.spy(selection_spy).was_called()
|
assert.spy(selection_spy).was_called()
|
||||||
assert.truthy(readerui.view.highlight.saved[page])
|
assert.truthy(#readerui.annotation.annotations == 1)
|
||||||
end)
|
end)
|
||||||
it("should response on tap gesture", function()
|
it("should response on tap gesture", function()
|
||||||
tap_highlight_text(readerui,
|
tap_highlight_text(readerui,
|
||||||
@@ -154,6 +155,7 @@ describe("Readerhighlight module", function()
|
|||||||
end)
|
end)
|
||||||
after_each(function()
|
after_each(function()
|
||||||
readerui.highlight:clear()
|
readerui.highlight:clear()
|
||||||
|
readerui.annotation.annotations = {}
|
||||||
end)
|
end)
|
||||||
it("should response on tap gesture #nocov", function()
|
it("should response on tap gesture #nocov", function()
|
||||||
tap_highlight_text(readerui,
|
tap_highlight_text(readerui,
|
||||||
@@ -165,10 +167,12 @@ describe("Readerhighlight module", function()
|
|||||||
it("should highlight single word", function()
|
it("should highlight single word", function()
|
||||||
highlight_single_word(readerui, Geom:new{ x = 260, y = 70 })
|
highlight_single_word(readerui, Geom:new{ x = 260, y = 70 })
|
||||||
Screen:shot("screenshots/reader_highlight_single_word_pdf.png")
|
Screen:shot("screenshots/reader_highlight_single_word_pdf.png")
|
||||||
|
assert.truthy(#readerui.annotation.annotations == 1)
|
||||||
end)
|
end)
|
||||||
it("should highlight text", function()
|
it("should highlight text", function()
|
||||||
highlight_text(readerui, Geom:new{ x = 260, y = 170 }, Geom:new{ x = 260, y = 250 })
|
highlight_text(readerui, Geom:new{ x = 260, y = 170 }, Geom:new{ x = 260, y = 250 })
|
||||||
Screen:shot("screenshots/reader_highlight_text_pdf.png")
|
Screen:shot("screenshots/reader_highlight_text_pdf.png")
|
||||||
|
assert.truthy(#readerui.annotation.annotations == 1)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
describe("for scanned page without text layer", function()
|
describe("for scanned page without text layer", function()
|
||||||
@@ -179,6 +183,7 @@ describe("Readerhighlight module", function()
|
|||||||
end)
|
end)
|
||||||
after_each(function()
|
after_each(function()
|
||||||
readerui.highlight:clear()
|
readerui.highlight:clear()
|
||||||
|
readerui.annotation.annotations = {}
|
||||||
end)
|
end)
|
||||||
it("should respond to tap gesture #nocov", function()
|
it("should respond to tap gesture #nocov", function()
|
||||||
tap_highlight_text(readerui, Geom:new{ x = 260, y = 70 }, Geom:new{ x = 260, y = 150 }, Geom:new{ x = 280, y = 110 })
|
tap_highlight_text(readerui, Geom:new{ x = 260, y = 70 }, Geom:new{ x = 260, y = 150 }, Geom:new{ x = 280, y = 110 })
|
||||||
@@ -187,10 +192,12 @@ describe("Readerhighlight module", function()
|
|||||||
it("should highlight single word", function()
|
it("should highlight single word", function()
|
||||||
highlight_single_word(readerui, Geom:new{ x = 260, y = 70 })
|
highlight_single_word(readerui, Geom:new{ x = 260, y = 70 })
|
||||||
Screen:shot("screenshots/reader_highlight_single_word_pdf_scanned.png")
|
Screen:shot("screenshots/reader_highlight_single_word_pdf_scanned.png")
|
||||||
|
assert.truthy(#readerui.annotation.annotations == 1)
|
||||||
end)
|
end)
|
||||||
it("should highlight text", function()
|
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 = 70 }, Geom:new{ x = 260, y = 150 })
|
||||||
Screen:shot("screenshots/reader_highlight_text_pdf_scanned.png")
|
Screen:shot("screenshots/reader_highlight_text_pdf_scanned.png")
|
||||||
|
assert.truthy(#readerui.annotation.annotations == 1)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
describe("for reflowed page", function()
|
describe("for reflowed page", function()
|
||||||
@@ -202,6 +209,7 @@ describe("Readerhighlight module", function()
|
|||||||
end)
|
end)
|
||||||
after_each(function()
|
after_each(function()
|
||||||
readerui.highlight:clear()
|
readerui.highlight:clear()
|
||||||
|
readerui.annotation.annotations = {}
|
||||||
readerui.document.configurable.text_wrap = 0
|
readerui.document.configurable.text_wrap = 0
|
||||||
UIManager:close(readerui) -- close to flush settings
|
UIManager:close(readerui) -- close to flush settings
|
||||||
-- We haven't torn it down yet
|
-- We haven't torn it down yet
|
||||||
@@ -214,10 +222,12 @@ describe("Readerhighlight module", function()
|
|||||||
it("should highlight single word", function()
|
it("should highlight single word", function()
|
||||||
highlight_single_word(readerui, Geom:new{ x = 260, y = 70 })
|
highlight_single_word(readerui, Geom:new{ x = 260, y = 70 })
|
||||||
Screen:shot("screenshots/reader_highlight_single_word_pdf_reflowed.png")
|
Screen:shot("screenshots/reader_highlight_single_word_pdf_reflowed.png")
|
||||||
|
assert.truthy(#readerui.annotation.annotations == 1)
|
||||||
end)
|
end)
|
||||||
it("should highlight text", function()
|
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 = 70 }, Geom:new{ x = 260, y = 150 })
|
||||||
Screen:shot("screenshots/reader_highlight_text_pdf_reflowed.png")
|
Screen:shot("screenshots/reader_highlight_text_pdf_reflowed.png")
|
||||||
|
assert.truthy(#readerui.annotation.annotations == 1)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
@@ -247,6 +257,7 @@ describe("Readerhighlight module", function()
|
|||||||
end)
|
end)
|
||||||
after_each(function()
|
after_each(function()
|
||||||
readerui.highlight:clear()
|
readerui.highlight:clear()
|
||||||
|
readerui.annotation.annotations = {}
|
||||||
end)
|
end)
|
||||||
it("should highlight single word", function()
|
it("should highlight single word", function()
|
||||||
highlight_single_word(readerui, Geom:new{ x = 260, y = 70 })
|
highlight_single_word(readerui, Geom:new{ x = 260, y = 70 })
|
||||||
@@ -255,6 +266,7 @@ describe("Readerhighlight module", function()
|
|||||||
it("should highlight text", function()
|
it("should highlight text", function()
|
||||||
highlight_text(readerui, Geom:new{ x = 260, y = 170 }, Geom:new{ x = 260, y = 250 })
|
highlight_text(readerui, Geom:new{ x = 260, y = 170 }, Geom:new{ x = 260, y = 250 })
|
||||||
Screen:shot("screenshots/reader_highlight_text_pdf_scroll.png")
|
Screen:shot("screenshots/reader_highlight_text_pdf_scroll.png")
|
||||||
|
assert.truthy(#readerui.annotation.annotations == 1)
|
||||||
end)
|
end)
|
||||||
it("should response on tap gesture", function()
|
it("should response on tap gesture", function()
|
||||||
tap_highlight_text(readerui,
|
tap_highlight_text(readerui,
|
||||||
@@ -262,6 +274,7 @@ describe("Readerhighlight module", function()
|
|||||||
Geom:new{ x = 260, y = 150 },
|
Geom:new{ x = 260, y = 150 },
|
||||||
Geom:new{ x = 280, y = 110 })
|
Geom:new{ x = 280, y = 110 })
|
||||||
Screen:shot("screenshots/reader_tap_highlight_text_pdf_scroll.png")
|
Screen:shot("screenshots/reader_tap_highlight_text_pdf_scroll.png")
|
||||||
|
assert.truthy(#readerui.annotation.annotations == 1)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
describe("for scanned page without text layer", function()
|
describe("for scanned page without text layer", function()
|
||||||
@@ -273,14 +286,17 @@ describe("Readerhighlight module", function()
|
|||||||
end)
|
end)
|
||||||
after_each(function()
|
after_each(function()
|
||||||
readerui.highlight:clear()
|
readerui.highlight:clear()
|
||||||
|
readerui.annotation.annotations = {}
|
||||||
end)
|
end)
|
||||||
it("should highlight single word", function()
|
it("should highlight single word", function()
|
||||||
highlight_single_word(readerui, Geom:new{ x = 260, y = 70 })
|
highlight_single_word(readerui, Geom:new{ x = 260, y = 70 })
|
||||||
Screen:shot("screenshots/reader_highlight_single_word_pdf_scanned_scroll.png")
|
Screen:shot("screenshots/reader_highlight_single_word_pdf_scanned_scroll.png")
|
||||||
|
assert.truthy(#readerui.annotation.annotations == 1)
|
||||||
end)
|
end)
|
||||||
it("should highlight text", function()
|
it("should highlight text", function()
|
||||||
highlight_text(readerui, Geom:new{x = 192, y = 186}, Geom:new{x = 280, y = 186})
|
highlight_text(readerui, Geom:new{x = 192, y = 186}, Geom:new{x = 280, y = 186})
|
||||||
Screen:shot("screenshots/reader_highlight_text_pdf_scanned_scroll.png")
|
Screen:shot("screenshots/reader_highlight_text_pdf_scanned_scroll.png")
|
||||||
|
assert.truthy(#readerui.annotation.annotations == 1)
|
||||||
end)
|
end)
|
||||||
it("should response on tap gesture", function()
|
it("should response on tap gesture", function()
|
||||||
tap_highlight_text(readerui, Geom:new{ x = 260, y = 70 }, Geom:new{ x = 260, y = 150 }, Geom:new{ x = 280, y = 110 })
|
tap_highlight_text(readerui, Geom:new{ x = 260, y = 70 }, Geom:new{ x = 260, y = 150 }, Geom:new{ x = 280, y = 110 })
|
||||||
@@ -296,6 +312,7 @@ describe("Readerhighlight module", function()
|
|||||||
end)
|
end)
|
||||||
after_each(function()
|
after_each(function()
|
||||||
readerui.highlight:clear()
|
readerui.highlight:clear()
|
||||||
|
readerui.annotation.annotations = {}
|
||||||
readerui.document.configurable.text_wrap = 0
|
readerui.document.configurable.text_wrap = 0
|
||||||
UIManager:close(readerui) -- close to flush settings
|
UIManager:close(readerui) -- close to flush settings
|
||||||
-- We haven't torn it down yet
|
-- We haven't torn it down yet
|
||||||
@@ -304,10 +321,12 @@ describe("Readerhighlight module", function()
|
|||||||
it("should highlight single word", function()
|
it("should highlight single word", function()
|
||||||
highlight_single_word(readerui, Geom:new{ x = 260, y = 70 })
|
highlight_single_word(readerui, Geom:new{ x = 260, y = 70 })
|
||||||
Screen:shot("screenshots/reader_highlight_single_word_pdf_reflowed_scroll.png")
|
Screen:shot("screenshots/reader_highlight_single_word_pdf_reflowed_scroll.png")
|
||||||
|
assert.truthy(#readerui.annotation.annotations == 1)
|
||||||
end)
|
end)
|
||||||
it("should highlight text", function()
|
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 = 70 }, Geom:new{ x = 260, y = 150 })
|
||||||
Screen:shot("screenshots/reader_highlight_text_pdf_reflowed_scroll.png")
|
Screen:shot("screenshots/reader_highlight_text_pdf_reflowed_scroll.png")
|
||||||
|
assert.truthy(#readerui.annotation.annotations == 1)
|
||||||
end)
|
end)
|
||||||
it("should response on tap gesture", function()
|
it("should response on tap gesture", function()
|
||||||
tap_highlight_text(readerui, Geom:new{ x = 260, y = 70 }, Geom:new{ x = 260, y = 150 }, Geom:new{ x = 280, y = 110 })
|
tap_highlight_text(readerui, Geom:new{ x = 260, y = 70 }, Geom:new{ x = 260, y = 150 }, Geom:new{ x = 280, y = 110 })
|
||||||
|
|||||||
Reference in New Issue
Block a user