mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
Allows adjusting highlight start and end (#4582)
Adds arrow buttons under Delete|Edit. Tap to move by word, hold to move by char.
This commit is contained in:
@@ -443,6 +443,24 @@ function ReaderBookmark:removeBookmark(item)
|
||||
logger.warn("removeBookmark: full scan search didn't find bookmark")
|
||||
end
|
||||
|
||||
function ReaderBookmark:updateBookmark(item)
|
||||
for i=1, #self.bookmarks do
|
||||
if item.datetime == self.bookmarks[i].datetime and item.page == self.bookmarks[i].page then
|
||||
local page = self.ui.document:getPageFromXPointer(item.updated_highlight.pos0)
|
||||
local new_text = item.updated_highlight.text
|
||||
self.bookmarks[i].page = item.updated_highlight.pos0
|
||||
self.bookmarks[i].pos0 = item.updated_highlight.pos0
|
||||
self.bookmarks[i].pos1 = item.updated_highlight.pos1
|
||||
self.bookmarks[i].notes = item.updated_highlight.text
|
||||
self.bookmarks[i].text = T(_("Page %1 %2 @ %3"), page,
|
||||
new_text,
|
||||
item.updated_highlight.datetime)
|
||||
self.bookmarks[i].datetime = item.updated_highlight.datetime
|
||||
self:onSaveSettings()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ReaderBookmark:renameBookmark(item, from_highlight)
|
||||
if from_highlight then
|
||||
-- Called by ReaderHighlight:editHighlight, we need to find the bookmark
|
||||
|
||||
@@ -248,27 +248,139 @@ function ReaderHighlight:onTapXPointerSavedHighlight(ges)
|
||||
end
|
||||
end
|
||||
|
||||
function ReaderHighlight:updateHighlight(page, index, side, direction, move_by_char)
|
||||
if self.ui.document.info.has_pages then -- we do this only if it's epub file
|
||||
return
|
||||
end
|
||||
|
||||
local highlight = self.view.highlight.saved[page][index]
|
||||
local highlight_time = highlight.datetime
|
||||
local highlight_beginning = highlight.pos0
|
||||
local highlight_end = highlight.pos1
|
||||
if side == 0 then -- we move pos0
|
||||
if direction == 1 then -- move highlight to the right
|
||||
local updated_highlight_beginning
|
||||
if move_by_char then
|
||||
updated_highlight_beginning = self.ui.document:getNextVisibleChar(highlight_beginning)
|
||||
else
|
||||
updated_highlight_beginning = self.ui.document:getNextVisibleWordStart(highlight_beginning)
|
||||
end
|
||||
if updated_highlight_beginning then -- in theory crengine could return nil
|
||||
self.view.highlight.saved[page][index].pos0 = updated_highlight_beginning
|
||||
end
|
||||
else -- move highlight to the left
|
||||
local updated_highlight_beginning
|
||||
if move_by_char then
|
||||
updated_highlight_beginning = self.ui.document:getPrevVisibleChar(highlight_beginning)
|
||||
else
|
||||
updated_highlight_beginning = self.ui.document:getPrevVisibleWordStart(highlight_beginning)
|
||||
end
|
||||
if updated_highlight_beginning then
|
||||
self.view.highlight.saved[page][index].pos0 = updated_highlight_beginning
|
||||
end
|
||||
end
|
||||
else -- we move pos1
|
||||
if direction == 1 then -- move highlight to the right
|
||||
local updated_highlight_end
|
||||
if move_by_char then
|
||||
updated_highlight_end = self.ui.document:getNextVisibleChar(highlight_end)
|
||||
else
|
||||
updated_highlight_end = self.ui.document:getNextVisibleWordEnd(highlight_end)
|
||||
end
|
||||
if updated_highlight_end then
|
||||
self.view.highlight.saved[page][index].pos1 = updated_highlight_end
|
||||
end
|
||||
else -- move highlight to the left
|
||||
local updated_highlight_end
|
||||
if move_by_char then
|
||||
updated_highlight_end = self.ui.document:getPrevVisibleChar(highlight_end)
|
||||
else
|
||||
updated_highlight_end = self.ui.document:getPrevVisibleWordEnd(highlight_end)
|
||||
end
|
||||
if updated_highlight_end then
|
||||
self.view.highlight.saved[page][index].pos1 = updated_highlight_end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local new_beginning = self.view.highlight.saved[page][index].pos0
|
||||
local new_end = self.view.highlight.saved[page][index].pos1
|
||||
local new_text = self.ui.document:getTextFromXPointers(new_beginning, new_end)
|
||||
self.view.highlight.saved[page][index].text = new_text
|
||||
local new_highlight = self.view.highlight.saved[page][index]
|
||||
self.ui.bookmark:updateBookmark({
|
||||
page = highlight_beginning,
|
||||
datetime = highlight_time,
|
||||
updated_highlight = new_highlight
|
||||
}, true)
|
||||
UIManager:setDirty(self.dialog, "ui")
|
||||
end
|
||||
|
||||
function ReaderHighlight:onShowHighlightDialog(page, index)
|
||||
self.edit_highlight_dialog = ButtonDialog:new{
|
||||
buttons = {
|
||||
local buttons = {
|
||||
{
|
||||
{
|
||||
{
|
||||
text = _("Delete"),
|
||||
callback = function()
|
||||
self:deleteHighlight(page, index)
|
||||
-- other part outside of the dialog may be dirty
|
||||
UIManager:close(self.edit_highlight_dialog, "ui")
|
||||
end,
|
||||
},
|
||||
{
|
||||
text = _("Edit"),
|
||||
callback = function()
|
||||
self:editHighlight(page, index)
|
||||
UIManager:close(self.edit_highlight_dialog)
|
||||
end,
|
||||
},
|
||||
text = _("Delete"),
|
||||
callback = function()
|
||||
self:deleteHighlight(page, index)
|
||||
-- other part outside of the dialog may be dirty
|
||||
UIManager:close(self.edit_highlight_dialog, "ui")
|
||||
end,
|
||||
},
|
||||
},
|
||||
{
|
||||
text = _("Edit"),
|
||||
callback = function()
|
||||
self:editHighlight(page, index)
|
||||
UIManager:close(self.edit_highlight_dialog)
|
||||
end,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if not self.ui.document.info.has_pages then
|
||||
table.insert(buttons, {
|
||||
{
|
||||
text = _("◁⇱"),
|
||||
callback = function()
|
||||
self:updateHighlight(page, index, 0, -1, false)
|
||||
end,
|
||||
hold_callback = function()
|
||||
self:updateHighlight(page, index, 0, -1, true)
|
||||
return true
|
||||
end
|
||||
},
|
||||
{
|
||||
text = _("⇱▷"),
|
||||
callback = function()
|
||||
self:updateHighlight(page, index, 0, 1, false)
|
||||
end,
|
||||
hold_callback = function()
|
||||
self:updateHighlight(page, index, 0, 1, true)
|
||||
return true
|
||||
end
|
||||
},
|
||||
{
|
||||
text = _("◁⇲"),
|
||||
callback = function()
|
||||
self:updateHighlight(page, index, 1, -1, false)
|
||||
end,
|
||||
hold_callback = function()
|
||||
self:updateHighlight(page, index, 1, -1, true)
|
||||
end
|
||||
},
|
||||
{
|
||||
text = _("⇲▷"),
|
||||
callback = function()
|
||||
self:updateHighlight(page, index, 1, 1, false)
|
||||
end,
|
||||
hold_callback = function()
|
||||
self:updateHighlight(page, index, 1, 1, true)
|
||||
end
|
||||
}
|
||||
})
|
||||
end
|
||||
self.edit_highlight_dialog = ButtonDialog:new{
|
||||
buttons = buttons
|
||||
}
|
||||
UIManager:show(self.edit_highlight_dialog)
|
||||
return true
|
||||
@@ -900,7 +1012,6 @@ function ReaderHighlight:deleteHighlight(page, i, bookmark_item)
|
||||
end
|
||||
|
||||
function ReaderHighlight:editHighlight(page, i)
|
||||
logger.info("edit highlight", page, i)
|
||||
local item = self.view.highlight.saved[page][i]
|
||||
self.ui.bookmark:renameBookmark({
|
||||
page = self.ui.document.info.has_pages and page or item.pos0,
|
||||
|
||||
@@ -306,6 +306,30 @@ function CreDocument:getScreenBoxesFromPositions(pos0, pos1, get_segments)
|
||||
return line_boxes
|
||||
end
|
||||
|
||||
function CreDocument:getNextVisibleWordStart(xp)
|
||||
return self._document:getNextVisibleWordStart(xp)
|
||||
end
|
||||
|
||||
function CreDocument:getNextVisibleWordEnd(xp)
|
||||
return self._document:getNextVisibleWordEnd(xp)
|
||||
end
|
||||
|
||||
function CreDocument:getPrevVisibleWordStart(xp)
|
||||
return self._document:getPrevVisibleWordStart(xp)
|
||||
end
|
||||
|
||||
function CreDocument:getPrevVisibleWordEnd(xp)
|
||||
return self._document:getPrevVisibleWordEnd(xp)
|
||||
end
|
||||
|
||||
function CreDocument:getPrevVisibleChar(xp)
|
||||
return self._document:getPrevVisibleChar(xp)
|
||||
end
|
||||
|
||||
function CreDocument:getNextVisibleChar(xp)
|
||||
return self._document:getNextVisibleChar(xp)
|
||||
end
|
||||
|
||||
function CreDocument:drawCurrentView(target, x, y, rect, pos)
|
||||
if self.buffer and (self.buffer.w ~= rect.w or self.buffer.h ~= rect.h) then
|
||||
self.buffer:free()
|
||||
@@ -428,6 +452,10 @@ function CreDocument:getTextFromXPointer(xp)
|
||||
end
|
||||
end
|
||||
|
||||
function CreDocument:getTextFromXPointers(pos0, pos1)
|
||||
return self._document:getTextFromXPointers(pos0, pos1)
|
||||
end
|
||||
|
||||
function CreDocument:getHTMLFromXPointer(xp, flags, from_final_parent)
|
||||
if xp then
|
||||
return self._document:getHTMLFromXPointer(xp, flags, from_final_parent)
|
||||
|
||||
@@ -102,6 +102,13 @@ function Button:init()
|
||||
range = self.dimen,
|
||||
},
|
||||
doc = "Hold Button",
|
||||
},
|
||||
-- Safe-guard for when used inside a MovableContainer
|
||||
HoldReleaseSelectButton = {
|
||||
GestureRange:new{
|
||||
ges = "hold_release",
|
||||
range = self.dimen,
|
||||
},
|
||||
}
|
||||
}
|
||||
end
|
||||
@@ -240,4 +247,16 @@ function Button:onHoldSelectButton()
|
||||
return true
|
||||
end
|
||||
|
||||
function Button:onHoldReleaseSelectButton()
|
||||
-- Safe-guard for when used inside a MovableContainer,
|
||||
-- which would handle HoldRelease and process it like
|
||||
-- a Hold if we wouldn't return true here
|
||||
if self.enabled and self.hold_callback then
|
||||
return true
|
||||
elseif self.hold_input or type(self.hold_input_func) == "function" then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
return Button
|
||||
|
||||
@@ -53,6 +53,7 @@ function ButtonTable:init()
|
||||
text = btn_entry.text,
|
||||
enabled = btn_entry.enabled,
|
||||
callback = btn_entry.callback,
|
||||
hold_callback = btn_entry.hold_callback,
|
||||
width = (self.width - sizer_space)/column_cnt,
|
||||
max_width = (self.width - sizer_space)/column_cnt - 2*self.sep_width - 2*self.padding,
|
||||
bordersize = 0,
|
||||
|
||||
Reference in New Issue
Block a user