2017-06-17 05:44:29 +02:00
--[[
ReaderUI is an abstraction for a reader interface .
It works using data gathered from a document interface .
] ] --
local Cache = require ( " cache " )
2014-08-24 15:16:01 +08:00
local ConfirmBox = require ( " ui/widget/confirmbox " )
2014-10-30 19:42:18 +01:00
local Device = require ( " device " )
2017-06-17 05:44:29 +02:00
local DocSettings = require ( " docsettings " )
local DocumentRegistry = require ( " document/documentregistry " )
2013-10-18 22:38:07 +02:00
local Event = require ( " ui/event " )
2017-07-01 12:11:44 +02:00
local FileManagerBookInfo = require ( " apps/filemanager/filemanagerbookinfo " )
2017-06-17 05:44:29 +02:00
local FileManagerHistory = require ( " apps/filemanager/filemanagerhistory " )
local InfoMessage = require ( " ui/widget/infomessage " )
local InputContainer = require ( " ui/widget/container/inputcontainer " )
local InputDialog = require ( " ui/widget/inputdialog " )
local PluginLoader = require ( " pluginloader " )
local ReaderActivityIndicator = require ( " apps/reader/modules/readeractivityindicator " )
2018-03-31 21:19:31 +02:00
local ReaderBack = require ( " apps/reader/modules/readerback " )
2014-04-02 16:59:17 -04:00
local ReaderBookmark = require ( " apps/reader/modules/readerbookmark " )
local ReaderConfig = require ( " apps/reader/modules/readerconfig " )
local ReaderCoptListener = require ( " apps/reader/modules/readercoptlistener " )
2017-06-17 05:44:29 +02:00
local ReaderCropping = require ( " apps/reader/modules/readercropping " )
local ReaderDictionary = require ( " apps/reader/modules/readerdictionary " )
local ReaderFont = require ( " apps/reader/modules/readerfont " )
local ReaderFrontLight = require ( " apps/reader/modules/readerfrontlight " )
local ReaderGoto = require ( " apps/reader/modules/readergoto " )
2014-04-02 16:59:17 -04:00
local ReaderHinting = require ( " apps/reader/modules/readerhinting " )
local ReaderHighlight = require ( " apps/reader/modules/readerhighlight " )
local ReaderHyphenation = require ( " apps/reader/modules/readerhyphenation " )
2017-06-17 05:44:29 +02:00
local ReaderKoptListener = require ( " apps/reader/modules/readerkoptlistener " )
2014-04-02 16:59:17 -04:00
local ReaderLink = require ( " apps/reader/modules/readerlink " )
2017-06-17 05:44:29 +02:00
local ReaderMenu = require ( " apps/reader/modules/readermenu " )
local ReaderPanning = require ( " apps/reader/modules/readerpanning " )
local ReaderRotation = require ( " apps/reader/modules/readerrotation " )
local ReaderPaging = require ( " apps/reader/modules/readerpaging " )
local ReaderRolling = require ( " apps/reader/modules/readerrolling " )
local ReaderSearch = require ( " apps/reader/modules/readersearch " )
2016-02-02 19:38:14 +02:00
local ReaderStatus = require ( " apps/reader/modules/readerstatus " )
2018-05-12 23:24:43 +02:00
local ReaderStyleTweak = require ( " apps/reader/modules/readerstyletweak " )
2017-06-17 05:44:29 +02:00
local ReaderToc = require ( " apps/reader/modules/readertoc " )
local ReaderTypeset = require ( " apps/reader/modules/readertypeset " )
local ReaderView = require ( " apps/reader/modules/readerview " )
local ReaderWikipedia = require ( " apps/reader/modules/readerwikipedia " )
local ReaderZooming = require ( " apps/reader/modules/readerzooming " )
local Screenshoter = require ( " ui/widget/screenshoter " )
local UIManager = require ( " ui/uimanager " )
local lfs = require ( " libs/libkoreader-lfs " )
local logger = require ( " logger " )
2018-03-21 20:10:35 +01:00
local util = require ( " util " )
2017-06-17 05:44:29 +02:00
local _ = require ( " gettext " )
local Screen = require ( " device " ) . screen
local T = require ( " ffi/util " ) . template
2012-05-19 00:50:26 +02:00
2013-10-18 22:38:07 +02:00
local ReaderUI = InputContainer : new {
2016-08-12 14:05:18 +08:00
name = " ReaderUI " ,
2014-03-13 21:52:43 +08:00
active_widgets = { } ,
2012-05-19 00:50:26 +02:00
2014-03-13 21:52:43 +08:00
-- if we have a parent container, it must be referenced for now
dialog = nil ,
2012-05-19 00:50:26 +02:00
2014-03-13 21:52:43 +08:00
-- the document interface
document = nil ,
2012-06-12 00:35:13 +08:00
2014-03-13 21:52:43 +08:00
-- password for document unlock
password = nil ,
2013-01-13 10:22:33 +08:00
2014-03-13 21:52:43 +08:00
postInitCallback = nil ,
2017-03-24 12:02:17 -07:00
postReaderCallback = nil ,
2012-05-19 00:50:26 +02:00
}
2016-02-04 10:24:39 -08:00
function ReaderUI : registerModule ( name , ui_module , always_active )
if name then self [ name ] = ui_module end
2016-08-12 14:05:18 +08:00
ui_module.name = " reader " .. name
2016-02-04 10:24:39 -08:00
table.insert ( always_active and self.active_widgets or self , ui_module )
2014-10-09 17:41:23 +08:00
end
function ReaderUI : registerPostInitCallback ( callback )
table.insert ( self.postInitCallback , callback )
end
2017-03-24 12:02:17 -07:00
function ReaderUI : registerPostReadyCallback ( callback )
table.insert ( self.postReaderCallback , callback )
end
2012-05-19 00:50:26 +02:00
function ReaderUI : init ( )
2017-03-23 11:40:42 -07:00
-- cap screen refresh on pan to 2 refreshes per second
local pan_rate = Screen.eink and 2.0 or 30.0
2014-03-13 21:52:43 +08:00
self.postInitCallback = { }
2017-03-24 12:02:17 -07:00
self.postReaderCallback = { }
2014-03-13 21:52:43 +08:00
-- if we are not the top level dialog ourselves, it must be given in the table
if not self.dialog then
self.dialog = self
end
2012-06-26 17:05:09 +08:00
2018-03-14 22:16:38 +01:00
self.doc_settings = DocSettings : open ( self.document . file )
2014-06-10 15:57:10 +08:00
if Device : hasKeys ( ) then
2018-03-14 22:16:38 +01:00
self.key_events . Home = { { " Home " } , doc = " open file browser " }
2014-03-13 21:52:43 +08:00
end
2012-12-31 21:22:45 -05:00
2014-03-13 21:52:43 +08:00
-- a view container (so it must be child #1!)
2016-12-04 15:42:22 -08:00
-- all paintable widgets need to be a child of reader view
2014-10-09 17:41:23 +08:00
self : registerModule ( " view " , ReaderView : new {
2014-03-13 21:52:43 +08:00
dialog = self.dialog ,
dimen = self.dimen ,
ui = self ,
document = self.document ,
2014-10-09 17:41:23 +08:00
} )
-- goto link controller
self : registerModule ( " link " , ReaderLink : new {
2014-03-13 21:52:43 +08:00
dialog = self.dialog ,
2014-10-09 17:41:23 +08:00
view = self.view ,
2014-03-13 21:52:43 +08:00
ui = self ,
document = self.document ,
} )
-- text highlight
2014-10-09 17:41:23 +08:00
self : registerModule ( " highlight " , ReaderHighlight : new {
2014-03-13 21:52:43 +08:00
dialog = self.dialog ,
2014-10-09 17:41:23 +08:00
view = self.view ,
2014-03-13 21:52:43 +08:00
ui = self ,
document = self.document ,
} )
-- menu widget should be registered after link widget and highlight widget
-- so that taps on link and highlight areas won't popup reader menu
2014-10-09 17:41:23 +08:00
-- reader menu controller
self : registerModule ( " menu " , ReaderMenu : new {
view = self.view ,
ui = self
} )
2014-03-13 21:52:43 +08:00
-- rotation controller
2014-10-09 17:41:23 +08:00
self : registerModule ( " rotation " , ReaderRotation : new {
2014-03-13 21:52:43 +08:00
dialog = self.dialog ,
2014-10-09 17:41:23 +08:00
view = self.view ,
2014-03-13 21:52:43 +08:00
ui = self
} )
-- Table of content controller
2014-10-09 17:41:23 +08:00
self : registerModule ( " toc " , ReaderToc : new {
2014-03-13 21:52:43 +08:00
dialog = self.dialog ,
2014-10-09 17:41:23 +08:00
view = self.view ,
2014-03-13 21:52:43 +08:00
ui = self
2014-10-09 17:41:23 +08:00
} )
2014-03-13 21:52:43 +08:00
-- bookmark controller
2014-10-09 17:41:23 +08:00
self : registerModule ( " bookmark " , ReaderBookmark : new {
2014-03-13 21:52:43 +08:00
dialog = self.dialog ,
2014-10-09 17:41:23 +08:00
view = self.view ,
2014-03-13 21:52:43 +08:00
ui = self
} )
-- reader goto controller
2014-10-09 17:41:23 +08:00
-- "goto" being a dirty keyword in Lua?
self : registerModule ( " gotopage " , ReaderGoto : new {
2014-03-13 21:52:43 +08:00
dialog = self.dialog ,
2014-10-09 17:41:23 +08:00
view = self.view ,
2014-03-13 21:52:43 +08:00
ui = self ,
document = self.document ,
} )
-- dictionary
2014-10-09 17:41:23 +08:00
self : registerModule ( " dictionary " , ReaderDictionary : new {
2014-03-13 21:52:43 +08:00
dialog = self.dialog ,
2014-10-09 17:41:23 +08:00
view = self.view ,
2014-03-13 21:52:43 +08:00
ui = self ,
document = self.document ,
} )
2014-08-20 14:41:45 +08:00
-- wikipedia
2014-10-09 17:41:23 +08:00
self : registerModule ( " wikipedia " , ReaderWikipedia : new {
2014-08-20 14:41:45 +08:00
dialog = self.dialog ,
2014-10-09 17:41:23 +08:00
view = self.view ,
2014-08-20 14:41:45 +08:00
ui = self ,
document = self.document ,
} )
2014-03-13 21:52:43 +08:00
-- screenshot controller
2016-01-03 00:47:01 -08:00
self : registerModule ( " screenshot " , Screenshoter : new {
prefix = ' Reader ' ,
2014-03-13 21:52:43 +08:00
dialog = self.dialog ,
2014-10-09 17:41:23 +08:00
view = self.view ,
2014-03-13 21:52:43 +08:00
ui = self
2014-10-09 17:41:23 +08:00
} , true )
2014-03-13 21:52:43 +08:00
-- frontlight controller
if Device : hasFrontlight ( ) then
2014-10-09 17:41:23 +08:00
self : registerModule ( " frontlight " , ReaderFrontLight : new {
2014-03-13 21:52:43 +08:00
dialog = self.dialog ,
2014-10-09 17:41:23 +08:00
view = self.view ,
2014-03-13 21:52:43 +08:00
ui = self
} )
end
2018-03-21 20:10:35 +01:00
-- configurable controller
2014-03-13 21:52:43 +08:00
if self.document . info.configurable then
-- config panel controller
2014-10-09 17:41:23 +08:00
self : registerModule ( " config " , ReaderConfig : new {
2014-03-13 21:52:43 +08:00
configurable = self.document . configurable ,
options = self.document . options ,
dialog = self.dialog ,
2014-10-09 17:41:23 +08:00
view = self.view ,
2014-03-13 21:52:43 +08:00
ui = self
} )
2014-10-09 17:41:23 +08:00
if self.document . info.has_pages then
-- kopt option controller
self : registerModule ( " koptlistener " , ReaderKoptListener : new {
dialog = self.dialog ,
view = self.view ,
ui = self ,
document = self.document ,
} )
else
2014-03-13 21:52:43 +08:00
-- cre option controller
2014-10-09 17:41:23 +08:00
self : registerModule ( " crelistener " , ReaderCoptListener : new {
2014-03-13 21:52:43 +08:00
dialog = self.dialog ,
2014-10-09 17:41:23 +08:00
view = self.view ,
2014-03-13 21:52:43 +08:00
ui = self ,
document = self.document ,
} )
end
2014-10-09 17:41:23 +08:00
-- activity indicator when some configurations take long take to affect
self : registerModule ( " activityindicator " , ReaderActivityIndicator : new {
dialog = self.dialog ,
view = self.view ,
ui = self ,
document = self.document ,
} )
2014-03-13 21:52:43 +08:00
end
-- for page specific controller
if self.document . info.has_pages then
-- cropping controller
2014-10-09 17:41:23 +08:00
self : registerModule ( " cropping " , ReaderCropping : new {
2014-03-13 21:52:43 +08:00
dialog = self.dialog ,
2014-10-09 17:41:23 +08:00
view = self.view ,
2014-03-13 21:52:43 +08:00
ui = self ,
document = self.document ,
} )
-- paging controller
2014-10-09 17:41:23 +08:00
self : registerModule ( " paging " , ReaderPaging : new {
2017-03-23 11:40:42 -07:00
pan_rate = pan_rate ,
2014-03-13 21:52:43 +08:00
dialog = self.dialog ,
2014-10-09 17:41:23 +08:00
view = self.view ,
2014-03-13 21:52:43 +08:00
ui = self
} )
-- zooming controller
2014-10-09 17:41:23 +08:00
self : registerModule ( " zooming " , ReaderZooming : new {
2014-03-13 21:52:43 +08:00
dialog = self.dialog ,
2014-10-09 17:41:23 +08:00
view = self.view ,
2014-03-13 21:52:43 +08:00
ui = self
2014-10-09 17:41:23 +08:00
} )
2014-03-13 21:52:43 +08:00
-- panning controller
2014-10-09 17:41:23 +08:00
self : registerModule ( " panning " , ReaderPanning : new {
2014-03-13 21:52:43 +08:00
dialog = self.dialog ,
2014-10-09 17:41:23 +08:00
view = self.view ,
2014-03-13 21:52:43 +08:00
ui = self
} )
-- hinting controller
2014-10-09 17:41:23 +08:00
self : registerModule ( " hinting " , ReaderHinting : new {
2014-03-13 21:52:43 +08:00
dialog = self.dialog ,
2014-10-09 17:41:23 +08:00
zoom = self.zooming ,
view = self.view ,
2014-03-13 21:52:43 +08:00
ui = self ,
document = self.document ,
} )
else
2014-08-28 13:22:31 +08:00
-- make sure we render document first before calling any callback
2014-10-09 17:41:23 +08:00
self : registerPostInitCallback ( function ( )
2018-01-03 09:43:49 +01:00
if not self.document : loadDocument ( ) then
self : dealWithLoadDocumentFailure ( )
end
2016-01-16 19:33:16 +01:00
2016-02-07 14:03:53 -08:00
-- used to read additional settings after the document has been
-- loaded (but not rendered yet)
2016-01-16 19:33:16 +01:00
self : handleEvent ( Event : new ( " PreRenderDocument " , self.doc_settings ) )
2014-08-28 13:22:31 +08:00
self.document : render ( )
2014-03-13 21:52:43 +08:00
end )
2018-05-12 23:24:43 +02:00
-- styletweak controller (must be before typeset controller)
self : registerModule ( " styletweak " , ReaderStyleTweak : new {
dialog = self.dialog ,
view = self.view ,
ui = self
} )
2014-03-13 21:52:43 +08:00
-- typeset controller
2014-10-09 17:41:23 +08:00
self : registerModule ( " typeset " , ReaderTypeset : new {
2014-03-13 21:52:43 +08:00
dialog = self.dialog ,
2014-10-09 17:41:23 +08:00
view = self.view ,
2014-03-13 21:52:43 +08:00
ui = self
} )
-- font menu
2014-10-09 17:41:23 +08:00
self : registerModule ( " font " , ReaderFont : new {
2014-03-13 21:52:43 +08:00
dialog = self.dialog ,
2014-10-09 17:41:23 +08:00
view = self.view ,
2014-03-13 21:52:43 +08:00
ui = self
2014-10-09 17:41:23 +08:00
} )
2014-03-13 21:52:43 +08:00
-- hyphenation menu
2014-10-09 17:41:23 +08:00
self : registerModule ( " hyphenation " , ReaderHyphenation : new {
2014-03-13 21:52:43 +08:00
dialog = self.dialog ,
2014-10-09 17:41:23 +08:00
view = self.view ,
2014-03-13 21:52:43 +08:00
ui = self
2014-10-09 17:41:23 +08:00
} )
2014-03-13 21:52:43 +08:00
-- rolling controller
2014-10-09 17:41:23 +08:00
self : registerModule ( " rolling " , ReaderRolling : new {
2017-03-23 11:40:42 -07:00
pan_rate = pan_rate ,
2014-03-13 21:52:43 +08:00
dialog = self.dialog ,
2014-10-09 17:41:23 +08:00
view = self.view ,
2014-03-13 21:52:43 +08:00
ui = self
} )
2016-06-27 23:00:49 +08:00
self.disable_double_tap = G_reader_settings : readSetting ( " disable_double_tap " ) ~= false
2014-03-13 21:52:43 +08:00
end
2018-03-31 21:19:31 +02:00
-- back location stack
self : registerModule ( " back " , ReaderBack : new {
ui = self ,
view = self.view ,
} )
2014-11-05 12:28:11 +08:00
-- fulltext search
self : registerModule ( " search " , ReaderSearch : new {
dialog = self.dialog ,
view = self.view ,
ui = self
} )
2016-03-06 21:52:53 -08:00
-- book status
2016-02-02 19:38:14 +02:00
self : registerModule ( " status " , ReaderStatus : new {
ui = self ,
document = self.document ,
2016-02-12 16:55:02 +02:00
view = self.view ,
2016-02-02 19:38:14 +02:00
} )
2016-03-06 21:52:53 -08:00
-- history view
self : registerModule ( " history " , FileManagerHistory : new {
dialog = self.dialog ,
ui = self ,
} )
2017-07-01 12:11:44 +02:00
-- book info
self : registerModule ( " bookinfo " , FileManagerBookInfo : new {
dialog = self.dialog ,
document = self.document ,
ui = self ,
} )
2014-04-23 21:57:48 +08:00
-- koreader plugins
2017-04-20 23:37:04 -07:00
for _ , plugin_module in ipairs ( PluginLoader : loadPlugins ( ) ) do
local ok , plugin_or_err = PluginLoader : createPluginInstance (
plugin_module ,
{
dialog = self.dialog ,
view = self.view ,
ui = self ,
document = self.document ,
} )
if ok then
self : registerModule ( plugin_module.name , plugin_or_err )
logger.info ( " RD loaded plugin " , plugin_module.name ,
" at " , plugin_module.path )
end
2014-04-23 21:57:48 +08:00
end
2014-03-13 21:52:43 +08:00
-- we only read settings after all the widgets are initialized
self : handleEvent ( Event : new ( " ReadSettings " , self.doc_settings ) )
2013-01-13 10:22:33 +08:00
2014-03-13 21:52:43 +08:00
for _ , v in ipairs ( self.postInitCallback ) do
v ( )
end
2017-03-24 12:02:17 -07:00
self.postInitCallback = nil
2016-02-12 16:55:02 +02:00
2017-07-01 11:41:27 +02:00
-- Now that document is loaded, store book metadata in settings
-- (so that filemanager can use it from sideCar file to display
-- Book information).
2017-08-20 12:43:52 +02:00
self.doc_settings : saveSetting ( " doc_props " , self.document : getProps ( ) )
2017-07-01 11:41:27 +02:00
2016-06-03 01:31:46 -07:00
-- After initialisation notify that document is loaded and rendered
2016-02-12 16:55:02 +02:00
-- CREngine only reports correct page count after rendering is done
-- Need the same event for PDF document
self : handleEvent ( Event : new ( " ReaderReady " , self.doc_settings ) )
2017-03-24 12:02:17 -07:00
for _ , v in ipairs ( self.postReaderCallback ) do
v ( )
end
self.postReaderCallback = nil
2012-05-19 00:50:26 +02:00
end
2017-06-17 05:44:29 +02:00
function ReaderUI : showFileManager ( )
local FileManager = require ( " apps/filemanager/filemanager " )
local QuickStart = require ( " ui/quickstart " )
2017-10-13 18:43:02 +02:00
local last_dir
2017-06-17 05:44:29 +02:00
local last_file = G_reader_settings : readSetting ( " lastfile " )
-- ignore quickstart guide as last_file so we can go back to home dir
if last_file and last_file ~= QuickStart.quickstart_filename then
2017-10-13 18:43:02 +02:00
last_dir = last_file : match ( " (.*)/ " )
2017-06-17 05:44:29 +02:00
end
if FileManager.instance then
2017-10-13 18:43:02 +02:00
FileManager.instance : reinit ( last_dir , last_file )
2017-06-17 05:44:29 +02:00
else
2017-10-13 18:43:02 +02:00
FileManager : showFiles ( last_dir , last_file )
2017-06-17 05:44:29 +02:00
end
end
2018-02-02 21:21:52 +01:00
function ReaderUI : showReader ( file , provider )
2016-12-29 00:10:38 -08:00
logger.dbg ( " show reader ui " )
2016-04-18 15:38:14 -07:00
require ( " readhistory " ) : addItem ( file )
2018-02-02 21:21:52 +01:00
2014-09-03 12:09:25 +08:00
if lfs.attributes ( file , " mode " ) ~= " file " then
UIManager : show ( InfoMessage : new {
2016-04-23 21:09:50 -07:00
text = T ( _ ( " File '%1' does not exist. " ) , file )
2014-09-03 12:09:25 +08:00
} )
return
end
2018-02-02 21:21:52 +01:00
-- prevent crash due to incompatible bookmarks
-- @TODO split bookmarks from metadata and do per-engine in conversion
provider = provider or DocumentRegistry : getProvider ( file )
if provider.provider then
local doc_settings = DocSettings : open ( file )
local bookmarks = doc_settings : readSetting ( " bookmarks " ) or { }
if # bookmarks >= 1 and
( ( provider.provider == " crengine " and type ( bookmarks [ 1 ] . page ) == " number " ) or
( provider.provider == " mupdf " and type ( bookmarks [ 1 ] . page ) == " string " ) ) then
UIManager : show ( ConfirmBox : new {
text = T ( _ ( " The document '%1' with bookmarks or highlights was previously opened with a different engine. To prevent issues, bookmarks need to be deleted before continuing. " ) ,
file ) ,
ok_text = _ ( " Delete " ) ,
ok_callback = function ( )
doc_settings : delSetting ( " bookmarks " )
doc_settings : close ( )
self : showReaderCoroutine ( file , provider )
end ,
cancel_callback = self.showFileManager ,
} )
else
self : showReaderCoroutine ( file , provider )
end
end
end
function ReaderUI : showReaderCoroutine ( file , provider )
2014-09-03 12:09:25 +08:00
UIManager : show ( InfoMessage : new {
2016-04-23 21:09:50 -07:00
text = T ( _ ( " Opening file '%1'. " ) , file ) ,
2016-04-23 23:09:31 +08:00
timeout = 0.0 ,
2014-09-03 12:09:25 +08:00
} )
2016-04-23 21:09:50 -07:00
-- doShowReader might block for a long time, so force repaint here
UIManager : forceRePaint ( )
2016-03-05 12:37:45 -08:00
UIManager : nextTick ( function ( )
2016-12-29 00:10:38 -08:00
logger.dbg ( " creating coroutine for showing reader " )
2015-10-06 21:18:07 +08:00
local co = coroutine.create ( function ( )
2018-02-02 21:21:52 +01:00
self : doShowReader ( file , provider )
2015-10-06 21:18:07 +08:00
end )
2015-12-23 00:01:43 -08:00
local ok , err = coroutine.resume ( co )
2016-01-03 00:56:55 -08:00
if err ~= nil or ok == false then
2016-03-17 21:52:57 -07:00
io.stderr : write ( ' [!] doShowReader coroutine crashed: \n ' )
io.stderr : write ( debug.traceback ( co , err , 1 ) )
2016-03-05 12:37:45 -08:00
UIManager : quit ( )
2015-12-23 00:01:43 -08:00
end
2015-10-06 21:18:07 +08:00
end )
2014-09-03 12:09:25 +08:00
end
2016-05-02 22:35:18 -07:00
local _running_instance = nil
2018-02-02 21:21:52 +01:00
function ReaderUI : doShowReader ( file , provider )
2016-12-29 00:10:38 -08:00
logger.info ( " opening file " , file )
2014-10-28 18:09:22 +08:00
-- keep only one instance running
2016-05-02 22:35:18 -07:00
if _running_instance then
_running_instance : onClose ( )
2014-10-28 18:09:22 +08:00
end
2018-02-02 21:21:52 +01:00
local document = DocumentRegistry : openDocument ( file , provider )
2014-09-03 12:09:25 +08:00
if not document then
UIManager : show ( InfoMessage : new {
2017-06-17 05:44:29 +02:00
text = _ ( " No reader engine for this file or invalid file. " )
2014-09-03 12:09:25 +08:00
} )
2017-06-17 05:44:29 +02:00
self : showFileManager ( )
2014-09-03 12:09:25 +08:00
return
end
2015-10-06 21:18:07 +08:00
if document.is_locked then
2016-12-29 00:10:38 -08:00
logger.info ( " document is locked " )
2015-10-06 21:18:07 +08:00
self._coroutine = coroutine.running ( ) or self._coroutine
self : unlockDocumentWithPassword ( document )
if coroutine.running ( ) then
local unlock_success = coroutine.yield ( )
if not unlock_success then
2017-06-17 05:44:29 +02:00
self : showFileManager ( )
2015-10-06 21:18:07 +08:00
return
end
end
end
2014-09-03 12:09:25 +08:00
G_reader_settings : saveSetting ( " lastfile " , file )
local reader = ReaderUI : new {
dimen = Screen : getSize ( ) ,
2018-03-17 23:02:32 +01:00
covers_fullscreen = true , -- hint for UIManager:_repaint()
2014-09-03 12:09:25 +08:00
document = document ,
}
2018-03-21 20:10:35 +01:00
local title = reader.document : getProps ( ) . title
if title ~= " " then
Screen : setWindowTitle ( title )
else
local _ , filename = util.splitFilePathName ( file )
Screen : setWindowTitle ( filename )
end
2014-09-03 12:09:25 +08:00
UIManager : show ( reader )
2016-05-02 22:35:18 -07:00
_running_instance = reader
2014-09-03 12:09:25 +08:00
end
2016-02-17 00:06:55 -08:00
function ReaderUI : _getRunningInstance ( )
2016-05-02 22:35:18 -07:00
return _running_instance
2016-02-17 00:06:55 -08:00
end
2015-10-06 21:18:07 +08:00
function ReaderUI : unlockDocumentWithPassword ( document , try_again )
2016-12-29 00:10:38 -08:00
logger.dbg ( " show input password dialog " )
2015-10-06 21:18:07 +08:00
self.password_dialog = InputDialog : new {
title = try_again and _ ( " Password is incorrect, try again? " )
or _ ( " Input document password " ) ,
buttons = {
{
{
text = _ ( " Cancel " ) ,
enabled = true ,
callback = function ( )
self : closeDialog ( )
coroutine.resume ( self._coroutine )
end ,
} ,
{
text = _ ( " OK " ) ,
enabled = true ,
callback = function ( )
local success = self : onVerifyPassword ( document )
self : closeDialog ( )
if success then
coroutine.resume ( self._coroutine , success )
else
self : unlockDocumentWithPassword ( document , true )
end
end ,
} ,
} ,
} ,
text_type = " password " ,
}
UIManager : show ( self.password_dialog )
2018-03-30 12:46:36 +02:00
self.password_dialog : onShowKeyboard ( )
2015-10-06 21:18:07 +08:00
end
function ReaderUI : onVerifyPassword ( document )
local password = self.password_dialog : getInputText ( )
return document : unlock ( password )
end
function ReaderUI : closeDialog ( )
self.password_dialog : onClose ( )
UIManager : close ( self.password_dialog )
end
2016-12-03 22:57:57 -08:00
function ReaderUI : onScreenResize ( dimen )
2014-03-13 21:52:43 +08:00
self.dimen = dimen
2016-12-03 22:57:57 -08:00
self : updateTouchZonesOnScreenResize ( dimen )
2012-06-13 00:14:23 +08:00
end
2013-12-27 23:18:16 +08:00
function ReaderUI : saveSettings ( )
2014-03-13 21:52:43 +08:00
self : handleEvent ( Event : new ( " SaveSettings " ) )
self.doc_settings : flush ( )
2014-07-03 20:43:17 +08:00
G_reader_settings : flush ( )
2013-12-27 23:18:16 +08:00
end
2014-06-08 17:56:52 +08:00
function ReaderUI : onFlushSettings ( )
self : saveSettings ( )
end
2014-08-24 15:16:01 +08:00
function ReaderUI : closeDocument ( )
self.document : close ( )
self.document = nil
end
2015-03-09 20:20:32 +08:00
function ReaderUI : notifyCloseDocument ( )
self : handleEvent ( Event : new ( " CloseDocument " ) )
2014-08-24 15:16:01 +08:00
if self.document : isEdited ( ) then
2016-07-14 10:38:00 -07:00
local setting = G_reader_settings : readSetting ( " save_document " )
if setting == " always " then
self : closeDocument ( )
elseif setting == " disable " then
self.document : discardChange ( )
self : closeDocument ( )
else
UIManager : show ( ConfirmBox : new {
text = _ ( " Do you want to save this document? " ) ,
2017-08-21 09:19:24 +02:00
ok_text = _ ( " Save " ) ,
cancel_text = _ ( " Don't save " ) ,
2016-07-14 10:38:00 -07:00
ok_callback = function ( )
self : closeDocument ( )
end ,
cancel_callback = function ( )
self.document : discardChange ( )
self : closeDocument ( )
end ,
} )
end
2014-08-24 15:16:01 +08:00
else
self : closeDocument ( )
end
end
2012-05-19 00:50:26 +02:00
function ReaderUI : onClose ( )
2016-12-29 00:10:38 -08:00
logger.dbg ( " closing reader " )
2017-08-25 18:55:44 +02:00
-- if self.dialog is us, we'll have our onFlushSettings() called
-- by UIManager:close() below, so avoid double save
if self.dialog ~= self then
self : saveSettings ( )
end
2014-03-13 21:52:43 +08:00
if self.document ~= nil then
2016-12-29 00:10:38 -08:00
logger.dbg ( " closing document " )
2015-03-09 20:20:32 +08:00
self : notifyCloseDocument ( )
2014-03-13 21:52:43 +08:00
end
2014-12-01 14:39:41 +00:00
UIManager : close ( self.dialog , " full " )
2014-05-15 19:41:10 +08:00
-- serialize last used items for later launch
Cache : serialize ( )
2016-05-02 22:35:18 -07:00
if _running_instance == self then
_running_instance = nil
2016-02-16 22:36:40 -08:00
end
2012-05-19 00:50:26 +02:00
end
2018-01-03 09:43:49 +01:00
function ReaderUI : dealWithLoadDocumentFailure ( )
-- Sadly, we had to delay loadDocument() to about now, so we only
-- know now this document is not valid or recognized.
-- We can't do much more than crash properly here (still better than
-- going on and segfaulting when calling other methods on unitiliazed
-- _document)
-- We must still remove it from lastfile and history (as it has
-- already been added there) so that koreader don't crash again
-- at next launch...
local readhistory = require ( " readhistory " )
readhistory : removeItemByPath ( self.document . file )
if G_reader_settings : readSetting ( " lastfile " ) == self.document . file then
G_reader_settings : saveSetting ( " lastfile " , # readhistory.hist > 0 and readhistory.hist [ 1 ] . file or nil )
end
-- As we are in a coroutine, we can pause and show an InfoMessage before exiting
local _coroutine = coroutine.running ( )
if coroutine then
logger.warn ( " crengine failed recognizing or parsing this file: unsupported or invalid document " )
UIManager : show ( InfoMessage : new {
text = _ ( " Failed recognizing or parsing this file: unsupported or invalid document. \n KOReader will exit now. " ) ,
dismiss_callback = function ( )
coroutine.resume ( _coroutine , false )
end ,
} )
coroutine.yield ( ) -- pause till InfoMessage is dismissed
end
-- We have to error and exit the coroutine anyway to avoid any segfault
error ( " crengine failed recognizing or parsing this file: unsupported or invalid document " )
end
2018-03-14 22:16:38 +01:00
function ReaderUI : onHome ( )
2018-04-09 09:22:16 +02:00
self : onClose ( )
self : showFileManager ( )
return true
2018-03-14 22:16:38 +01:00
end
2013-10-18 22:38:07 +02:00
return ReaderUI