Better handling of tap on invalid/external links

Tap on external urls or invalid links would jump to
document's 1st page. We check first the validity of the
link, and deal with wikipedia links or just show the external
url.
ConfirmBox: allow dismissing/cancelling by taping outside,
to keep UX consistent.
pull/2498/head
poire-z 7 years ago committed by Qingping Hou
parent ee06171c83
commit 97d34c5bb0

@ -5,8 +5,10 @@ local UIManager = require("ui/uimanager")
local Geom = require("ui/geometry")
local Screen = require("device").screen
local Device = require("device")
local logger = require("logger")
local Event = require("ui/event")
local _ = require("gettext")
local T = require("ffi/util").template
local ReaderLink = InputContainer:new{
location_stack = {}
@ -141,13 +143,57 @@ function ReaderLink:onTap(_, ges)
end
function ReaderLink:onGotoLink(link)
logger.dbg("onGotoLink:", link)
if self.ui.document.info.has_pages then
table.insert(self.location_stack, self.ui.paging:getBookLocation())
self.ui:handleEvent(Event:new("GotoPage", link.page + 1))
-- internal pdf links have a "page" attribute, while external ones have an "uri" attribute
if link.page then -- Internal link
logger.dbg("Internal link:", link)
table.insert(self.location_stack, self.ui.paging:getBookLocation())
self.ui:handleEvent(Event:new("GotoPage", link.page + 1))
return true
end
link = link.uri -- external link
else
-- For crengine, internal links may look like :
-- #_doc_fragment_0_Organisation (link from anchor)
-- /body/DocFragment/body/ul[2]/li[5]/text()[3].16 (xpointer from full-text search)
-- If the XPointer does not exist (or is a full url), we will jump to page 1
-- Best to check that this link exists in document with the following,
-- which accepts both of the above legitimate xpointer as input.
if self.ui.document:isXPointerInDocument(link) then
logger.dbg("Internal link:", link)
table.insert(self.location_stack, self.ui.rolling:getBookLocation())
self.ui:handleEvent(Event:new("GotoXPointer", link))
return true
end
end
logger.dbg("External link:", link)
-- Check if it is a wikipedia link
local wiki_lang, wiki_page = link:match([[https?://([^%.]+).wikipedia.org/wiki/([^/]+)]])
if wiki_lang and wiki_page then
logger.dbg("Wikipedia link:", wiki_lang, wiki_page)
-- Ask for user confirmation before launching lookup (on a
-- wikipedia page saved as epub, full of wikipedia links, it's
-- too easy to click on links when wanting to change page...)
local ConfirmBox = require("ui/widget/confirmbox")
UIManager:show(ConfirmBox:new{
text = T(_("Would you like to read this Wikipedia %1 full page?\n\n%2\n"), wiki_lang:upper(), wiki_page:gsub("_", " ")),
cancel_on_tap_outside = true,
ok_callback = function()
UIManager:nextTick(function()
self.ui:handleEvent(Event:new("LookupWikipedia", wiki_page, false, true, wiki_lang))
end)
end
})
else
table.insert(self.location_stack, self.ui.rolling:getBookLocation())
self.ui:handleEvent(Event:new("GotoXPointer", link))
-- local Notification = require("ui/widget/notification")
local InfoMessage = require("ui/widget/infomessage")
UIManager:show(InfoMessage:new{
text = T(_("Invalid or external link:\n%1"), link),
timeout = 1.0,
})
end
-- don't propagate, user will notice and tap elsewhere if he wants to change page
return true
end

@ -22,6 +22,8 @@ local ImageWidget = require("ui/widget/imagewidget")
local TextBoxWidget = require("ui/widget/textboxwidget")
local HorizontalSpan = require("ui/widget/horizontalspan")
local ButtonTable = require("ui/widget/buttontable")
local GestureRange = require("ui/gesturerange")
local Geom = require("ui/geometry")
local UIManager = require("ui/uimanager")
local Device = require("device")
local Screen = Device.screen
@ -44,6 +46,23 @@ local ConfirmBox = InputContainer:new{
}
function ConfirmBox:init()
if Device:isTouchDevice() then
self.ges_events.TapClose = {
GestureRange:new{
ges = "tap",
range = Geom:new{
x = 0, y = 0,
w = Screen:getWidth(),
h = Screen:getHeight(),
}
}
}
end
if Device:hasKeys() then
self.key_events = {
Close = { {"Back"}, doc = "cancel" }
}
end
local content = HorizontalGroup:new{
align = "center",
ImageWidget:new{
@ -110,10 +129,20 @@ function ConfirmBox:onCloseWidget()
end
function ConfirmBox:onClose()
-- Call cancel_callback, parent may expect a choice
self.cancel_callback()
UIManager:close(self)
return true
end
function ConfirmBox:onTapClose(arg, ges)
if ges.pos:notIntersectWith(self[1][1].dimen) then
self:onClose()
return true
end
return false
end
function ConfirmBox:onSelect()
logger.dbg("selected:", self.selected.x)
if self.selected.x == 1 then

Loading…
Cancel
Save