|
|
@ -11,14 +11,161 @@ local Translator = require("ui/translator")
|
|
|
|
local UIManager = require("ui/uimanager")
|
|
|
|
local UIManager = require("ui/uimanager")
|
|
|
|
local logger = require("logger")
|
|
|
|
local logger = require("logger")
|
|
|
|
local util = require("util")
|
|
|
|
local util = require("util")
|
|
|
|
|
|
|
|
local ffiUtil = require("ffi/util")
|
|
|
|
local _ = require("gettext")
|
|
|
|
local _ = require("gettext")
|
|
|
|
local C_ = _.pgettext
|
|
|
|
local C_ = _.pgettext
|
|
|
|
local T = require("ffi/util").template
|
|
|
|
local T = require("ffi/util").template
|
|
|
|
local Screen = Device.screen
|
|
|
|
local Screen = Device.screen
|
|
|
|
|
|
|
|
|
|
|
|
local ReaderHighlight = InputContainer:new{}
|
|
|
|
local ReaderHighlight = InputContainer:new{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local function inside_box(pos, box)
|
|
|
|
|
|
|
|
if pos then
|
|
|
|
|
|
|
|
local x, y = pos.x, pos.y
|
|
|
|
|
|
|
|
if box.x <= x and box.y <= y
|
|
|
|
|
|
|
|
and box.x + box.w >= x
|
|
|
|
|
|
|
|
and box.y + box.h >= y then
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local function cleanupSelectedText(text)
|
|
|
|
|
|
|
|
-- Trim spaces and new lines at start and end
|
|
|
|
|
|
|
|
text = text:gsub("^[\n%s]*", "")
|
|
|
|
|
|
|
|
text = text:gsub("[\n%s]*$", "")
|
|
|
|
|
|
|
|
-- Trim spaces around newlines
|
|
|
|
|
|
|
|
text = text:gsub("%s*\n%s*", "\n")
|
|
|
|
|
|
|
|
-- Trim consecutive spaces (that would probably have collapsed
|
|
|
|
|
|
|
|
-- in rendered CreDocuments)
|
|
|
|
|
|
|
|
text = text:gsub("%s%s+", " ")
|
|
|
|
|
|
|
|
return text
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function ReaderHighlight:init()
|
|
|
|
function ReaderHighlight:init()
|
|
|
|
|
|
|
|
self._highlight_buttons = {
|
|
|
|
|
|
|
|
-- highlight and add_note are for the document itself,
|
|
|
|
|
|
|
|
-- so we put them first.
|
|
|
|
|
|
|
|
["01_highlight"] = function(_self)
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
text = _("Highlight"),
|
|
|
|
|
|
|
|
callback = function()
|
|
|
|
|
|
|
|
_self:saveHighlight()
|
|
|
|
|
|
|
|
_self:onClose()
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
enabled = _self.hold_pos ~= nil,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
["02_add_note"] = function(_self)
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
text = _("Add Note"),
|
|
|
|
|
|
|
|
callback = function()
|
|
|
|
|
|
|
|
_self:addNote()
|
|
|
|
|
|
|
|
_self:onClose()
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
enabled = _self.hold_pos ~= nil,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
-- copy and search are internal functions that don't depend on anything,
|
|
|
|
|
|
|
|
-- hence the second line.
|
|
|
|
|
|
|
|
["03_copy"] = function(_self)
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
text = C_("Text", "Copy"),
|
|
|
|
|
|
|
|
enabled = Device:hasClipboard(),
|
|
|
|
|
|
|
|
callback = function()
|
|
|
|
|
|
|
|
Device.input.setClipboardText(cleanupSelectedText(_self.selected_text.text))
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
["04_search"] = function(_self)
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
text = _("Search"),
|
|
|
|
|
|
|
|
callback = function()
|
|
|
|
|
|
|
|
_self:onHighlightSearch()
|
|
|
|
|
|
|
|
_self:onClose()
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
-- then information lookup functions, putting on the left those that
|
|
|
|
|
|
|
|
-- depend on an internet connection.
|
|
|
|
|
|
|
|
["05_wikipedia"] = function(_self)
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
text = _("Wikipedia"),
|
|
|
|
|
|
|
|
callback = function()
|
|
|
|
|
|
|
|
UIManager:scheduleIn(0.1, function()
|
|
|
|
|
|
|
|
_self:lookupWikipedia()
|
|
|
|
|
|
|
|
-- We don't call _self:onClose(), we need the highlight
|
|
|
|
|
|
|
|
-- to still be there, as we may Highlight it from the
|
|
|
|
|
|
|
|
-- dict lookup widget
|
|
|
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
["06_dictionary"] = function(_self)
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
text = _("Dictionary"),
|
|
|
|
|
|
|
|
callback = function()
|
|
|
|
|
|
|
|
_self:onHighlightDictLookup()
|
|
|
|
|
|
|
|
-- We don't call _self:onClose(), same reason as above
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
["07_translate"] = function(_self)
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
text = _("Translate"),
|
|
|
|
|
|
|
|
callback = function()
|
|
|
|
|
|
|
|
_self:translate(_self.selected_text)
|
|
|
|
|
|
|
|
-- We don't call _self:onClose(), so one can still see
|
|
|
|
|
|
|
|
-- the highlighted text when moving the translated
|
|
|
|
|
|
|
|
-- text window, and also if NetworkMgr:promptWifiOn()
|
|
|
|
|
|
|
|
-- is needed, so the user can just tap again on this
|
|
|
|
|
|
|
|
-- button and does not need to select the text again.
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- Text export functions if applicable.
|
|
|
|
|
|
|
|
if not self.ui.document.info.has_pages then
|
|
|
|
|
|
|
|
self:addToHighlightDialog("08_view_html", function(_self)
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
text = _("View HTML"),
|
|
|
|
|
|
|
|
callback = function()
|
|
|
|
|
|
|
|
_self:viewSelectionHTML()
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if Device:canShareText() then
|
|
|
|
|
|
|
|
self:addToHighlightDialog("09_share_text", function(_self)
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
text = _("Share Text"),
|
|
|
|
|
|
|
|
callback = function()
|
|
|
|
|
|
|
|
local text = cleanupSelectedText(_self.selected_text.text)
|
|
|
|
|
|
|
|
-- call self:onClose() before calling the android framework
|
|
|
|
|
|
|
|
_self:onClose()
|
|
|
|
|
|
|
|
Device.doShareText(text)
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- Links
|
|
|
|
|
|
|
|
if self.selected_link ~= nil then
|
|
|
|
|
|
|
|
self:addToHighlightDialog("10_follow_link", function(_self)
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
text = _("Follow Link"),
|
|
|
|
|
|
|
|
callback = function()
|
|
|
|
|
|
|
|
local link = _self.selected_link.link or _self.selected_link
|
|
|
|
|
|
|
|
_self.ui.link:onGotoLink(link)
|
|
|
|
|
|
|
|
_self:onClose()
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
self.ui:registerPostInitCallback(function()
|
|
|
|
self.ui:registerPostInitCallback(function()
|
|
|
|
self.ui.menu:registerToMainMenu(self)
|
|
|
|
self.ui.menu:registerToMainMenu(self)
|
|
|
|
end)
|
|
|
|
end)
|
|
|
@ -239,29 +386,6 @@ function ReaderHighlight:onTap(_, ges)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
local function inside_box(pos, box)
|
|
|
|
|
|
|
|
if pos then
|
|
|
|
|
|
|
|
local x, y = pos.x, pos.y
|
|
|
|
|
|
|
|
if box.x <= x and box.y <= y
|
|
|
|
|
|
|
|
and box.x + box.w >= x
|
|
|
|
|
|
|
|
and box.y + box.h >= y then
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local function cleanupSelectedText(text)
|
|
|
|
|
|
|
|
-- Trim spaces and new lines at start and end
|
|
|
|
|
|
|
|
text = text:gsub("^[\n%s]*", "")
|
|
|
|
|
|
|
|
text = text:gsub("[\n%s]*$", "")
|
|
|
|
|
|
|
|
-- Trim spaces around newlines
|
|
|
|
|
|
|
|
text = text:gsub("%s*\n%s*", "\n")
|
|
|
|
|
|
|
|
-- Trim consecutive spaces (that would probably have collapsed
|
|
|
|
|
|
|
|
-- in rendered CreDocuments)
|
|
|
|
|
|
|
|
text = text:gsub("%s%s+", " ")
|
|
|
|
|
|
|
|
return text
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function ReaderHighlight:onTapPageSavedHighlight(ges)
|
|
|
|
function ReaderHighlight:onTapPageSavedHighlight(ges)
|
|
|
|
local pages = self.view:getCurrentPageList()
|
|
|
|
local pages = self.view:getCurrentPageList()
|
|
|
|
local pos = self.view:screenToPageTransform(ges.pos)
|
|
|
|
local pos = self.view:screenToPageTransform(ges.pos)
|
|
|
@ -512,107 +636,28 @@ function ReaderHighlight:onShowHighlightDialog(page, index)
|
|
|
|
return true
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function ReaderHighlight:addToHighlightDialog(idx, fn_button)
|
|
|
|
|
|
|
|
-- fn_button is a function that takes the ReaderHighlight instance
|
|
|
|
|
|
|
|
-- as argument, and returns a table describing the button to be added.
|
|
|
|
|
|
|
|
self._highlight_buttons[idx] = fn_button
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function ReaderHighlight:removeFromHighlightDialog(idx)
|
|
|
|
|
|
|
|
local button = self._highlight_buttons[idx]
|
|
|
|
|
|
|
|
self._highlight_buttons[idx] = nil
|
|
|
|
|
|
|
|
return button
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function ReaderHighlight:onShowHighlightMenu()
|
|
|
|
function ReaderHighlight:onShowHighlightMenu()
|
|
|
|
local highlight_buttons = {
|
|
|
|
local highlight_buttons = {{}}
|
|
|
|
{
|
|
|
|
|
|
|
|
{
|
|
|
|
local columns = 2
|
|
|
|
text = _("Highlight"),
|
|
|
|
for idx, fn_button in ffiUtil.orderedPairs(self._highlight_buttons) do
|
|
|
|
callback = function()
|
|
|
|
if #highlight_buttons[#highlight_buttons] >= columns then
|
|
|
|
self:saveHighlight()
|
|
|
|
table.insert(highlight_buttons, {})
|
|
|
|
self:onClose()
|
|
|
|
end
|
|
|
|
end,
|
|
|
|
table.insert(highlight_buttons[#highlight_buttons], fn_button(self))
|
|
|
|
enabled = self.hold_pos ~= nil,
|
|
|
|
logger.dbg("ReaderHighlight", idx..": line "..#highlight_buttons..", col "..#highlight_buttons[#highlight_buttons])
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
text = _("Add Note"),
|
|
|
|
|
|
|
|
callback = function()
|
|
|
|
|
|
|
|
self:addNote()
|
|
|
|
|
|
|
|
self:onClose()
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
enabled = self.hold_pos ~= nil,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
text = C_("Text", "Copy"),
|
|
|
|
|
|
|
|
enabled = Device:hasClipboard(),
|
|
|
|
|
|
|
|
callback = function()
|
|
|
|
|
|
|
|
Device.input.setClipboardText(cleanupSelectedText(self.selected_text.text))
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
text = _("View HTML"),
|
|
|
|
|
|
|
|
enabled = not self.ui.document.info.has_pages,
|
|
|
|
|
|
|
|
callback = function()
|
|
|
|
|
|
|
|
self:viewSelectionHTML()
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
text = _("Wikipedia"),
|
|
|
|
|
|
|
|
callback = function()
|
|
|
|
|
|
|
|
UIManager:scheduleIn(0.1, function()
|
|
|
|
|
|
|
|
self:lookupWikipedia()
|
|
|
|
|
|
|
|
-- We don't call self:onClose(), we need the highlight
|
|
|
|
|
|
|
|
-- to still be there, as we may Highlight it from the
|
|
|
|
|
|
|
|
-- dict lookup widget
|
|
|
|
|
|
|
|
end)
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
text = _("Dictionary"),
|
|
|
|
|
|
|
|
callback = function()
|
|
|
|
|
|
|
|
self:onHighlightDictLookup()
|
|
|
|
|
|
|
|
-- We don't call self:onClose(), same reason as above
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
text = _("Translate"),
|
|
|
|
|
|
|
|
callback = function()
|
|
|
|
|
|
|
|
self:translate(self.selected_text)
|
|
|
|
|
|
|
|
-- We don't call self:onClose(), so one can still see
|
|
|
|
|
|
|
|
-- the highlighted text when moving the translated
|
|
|
|
|
|
|
|
-- text window, and also if NetworkMgr:promptWifiOn()
|
|
|
|
|
|
|
|
-- is needed, so the user can just tap again on this
|
|
|
|
|
|
|
|
-- button and does not need to select the text again.
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
text = _("Search"),
|
|
|
|
|
|
|
|
callback = function()
|
|
|
|
|
|
|
|
self:onHighlightSearch()
|
|
|
|
|
|
|
|
UIManager:close(self.highlight_dialog)
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.selected_link ~= nil then
|
|
|
|
|
|
|
|
table.insert(highlight_buttons, { -- for now, a single button in an added row
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
text = _("Follow Link"),
|
|
|
|
|
|
|
|
callback = function()
|
|
|
|
|
|
|
|
local link = self.selected_link.link or self.selected_link
|
|
|
|
|
|
|
|
self.ui.link:onGotoLink(link)
|
|
|
|
|
|
|
|
self:onClose()
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
if Device:canShareText() then
|
|
|
|
|
|
|
|
table.insert(highlight_buttons, {
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
text = _("Share text"),
|
|
|
|
|
|
|
|
callback = function()
|
|
|
|
|
|
|
|
local text = cleanupSelectedText(self.selected_text.text)
|
|
|
|
|
|
|
|
-- call self:onClose() before calling the android framework
|
|
|
|
|
|
|
|
self:onClose()
|
|
|
|
|
|
|
|
Device.doShareText(text)
|
|
|
|
|
|
|
|
end,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
self.highlight_dialog = ButtonDialog:new{
|
|
|
|
self.highlight_dialog = ButtonDialog:new{
|
|
|
|