From 3967ba0346593b5ad18810caaa3b773a8e9c48c6 Mon Sep 17 00:00:00 2001 From: chrox Date: Mon, 23 Jun 2014 22:11:12 +0800 Subject: [PATCH 1/2] sort plugins in path order --- frontend/apps/reader/pluginloader.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/apps/reader/pluginloader.lua b/frontend/apps/reader/pluginloader.lua index a06fabc0d..ef26ce20d 100644 --- a/frontend/apps/reader/pluginloader.lua +++ b/frontend/apps/reader/pluginloader.lua @@ -19,7 +19,7 @@ function PluginLoader:loadPlugins() local package_cpath = package.cpath package.path = path.."/?.lua;"..package.path package.cpath = path.."/lib/?.so;"..package.cpath - local ok, module = pcall(require, "main") + local ok, module = pcall(dofile, mainfile) if not ok then DEBUG("Error when loading", mainfile, module) end @@ -37,6 +37,8 @@ function PluginLoader:loadPlugins() package.cpath = package.cpath..";"..plugin.path.."/lib/?.so" end + table.sort(self.plugins, function(v1,v2) return v1.path < v2.path end) + return self.plugins end From 26f5a4731e72e008532db222bdcb9282073a6d13 Mon Sep 17 00:00:00 2001 From: chrox Date: Mon, 23 Jun 2014 22:33:11 +0800 Subject: [PATCH 2/2] add peer-to-peer file sharing plugin ZSync --- frontend/apps/reader/readerui.lua | 1 + frontend/ui/message/filemessagequeue.lua | 45 +++ frontend/ui/message/messagequeue.lua | 85 ++++++ frontend/ui/message/zyremessagequeue.lua | 41 +++ frontend/ui/uimanager.lua | 56 +++- koreader-base | 2 +- plugins/zsync.koplugin/client.cfg | 6 + plugins/zsync.koplugin/main.lua | 369 +++++++++++++++++++++++ plugins/zsync.koplugin/server.cfg | 9 + reader.lua | 10 +- 10 files changed, 605 insertions(+), 19 deletions(-) create mode 100644 frontend/ui/message/filemessagequeue.lua create mode 100644 frontend/ui/message/messagequeue.lua create mode 100644 frontend/ui/message/zyremessagequeue.lua create mode 100644 plugins/zsync.koplugin/client.cfg create mode 100644 plugins/zsync.koplugin/main.lua create mode 100644 plugins/zsync.koplugin/server.cfg diff --git a/frontend/apps/reader/readerui.lua b/frontend/apps/reader/readerui.lua index d401564e3..049e37fcb 100644 --- a/frontend/apps/reader/readerui.lua +++ b/frontend/apps/reader/readerui.lua @@ -301,6 +301,7 @@ end function ReaderUI:onClose() DEBUG("closing reader") self:saveSettings() + self:handleEvent(Event:new("CloseReader")) if self.document ~= nil then self.document:close() self.document = nil diff --git a/frontend/ui/message/filemessagequeue.lua b/frontend/ui/message/filemessagequeue.lua new file mode 100644 index 000000000..6e8a8d557 --- /dev/null +++ b/frontend/ui/message/filemessagequeue.lua @@ -0,0 +1,45 @@ +local ffi = require("ffi") +local DEBUG = require("dbg") +local util = require("ffi/util") +local Event = require("ui/event") +local MessageQueue = require("ui/message/messagequeue") + +local dummy = require("ffi/zeromq_h") +local filemq = ffi.load("libs/libfmq.so.1") + +local FileMessageQueue = MessageQueue:new{ + client = nil, + server = nil, +} + +function FileMessageQueue:init() + if self.client ~= nil then + self.fmq_recv = filemq.fmq_client_recv_nowait + self.filemq = self.client + elseif self.server ~= nil then + self.fmq_recv = filemq.fmq_server_recv_nowait + self.filemq = self.server + end +end + +function FileMessageQueue:stop() + if self.client ~= nil then + DEBUG("stop filemq client") + filemq.fmq_client_destroy(ffi.new('fmq_client_t *[1]', self.client)) + end + if self.server ~= nil then + DEBUG("stop filemq server") + filemq.fmq_server_destroy(ffi.new('fmq_server_t *[1]', self.server)) + end +end + +function FileMessageQueue:waitEvent() + local msg = self.fmq_recv(self.filemq) + while msg ~= nil do + table.insert(self.messages, msg) + msg = self.fmq_recv(self.filemq) + end + return self:handleZMsgs(self.messages) +end + +return FileMessageQueue diff --git a/frontend/ui/message/messagequeue.lua b/frontend/ui/message/messagequeue.lua new file mode 100644 index 000000000..beafc38b1 --- /dev/null +++ b/frontend/ui/message/messagequeue.lua @@ -0,0 +1,85 @@ +local ffi = require("ffi") +local util = require("ffi/util") +local Event = require("ui/event") +local DEBUG = require("dbg") + +local dummy = require("ffi/zeromq_h") +local czmq = ffi.load("libs/libczmq.so.1") +local zyre = ffi.load("libs/libzyre.so.1") + +local MessageQueue = {} + +function MessageQueue:new(o) + o = o or {} + setmetatable(o, self) + self.__index = self + if o.init then o:init() end + self.messages = {} + return o +end + +function MessageQueue:init() +end + +function MessageQueue:start() +end + +function MessageQueue:stop() +end + +function MessageQueue:waitEvent() +end + +function MessageQueue:handleZMsgs(messages) + local function drop_message() + if czmq.zmsg_size(messages[1]) == 0 then + czmq.zmsg_destroy(ffi.new('zmsg_t *[1]', messages[1])) + table.remove(messages, 1) + end + end + local function pop_string() + local str_p = czmq.zmsg_popstr(messages[1]) + local message_size = czmq.zmsg_size(messages[1]) + local res = ffi.string(str_p) + czmq.zstr_free(ffi.new('char *[1]', str_p)) + drop_message() + return res + end + local function pop_header() + local header = {} + local frame = czmq.zmsg_pop(messages[1]) + if frame ~= nil then + local hash = czmq.zhash_unpack(frame) + czmq.zframe_destroy(ffi.new('zframe_t *[1]', frame)) + if hash ~= nil then + local value, key = czmq.zhash_first(hash), czmq.zhash_cursor(hash) + while value ~= nil and key ~= nil do + header[ffi.string(key)] = ffi.string(value) + value, key = czmq.zhash_next(hash), czmq.zhash_cursor(hash) + end + czmq.zhash_destroy(ffi.new('zhash_t *[1]', hash)) + end + end + drop_message() + return header + end + if #messages == 0 then return end + local message_size = czmq.zmsg_size(messages[1]) + local command = pop_string() + DEBUG("ØMQ message", command) + if command == "ENTER" and #messages >= 4 then + local id = pop_string() + local name = pop_string() + local header = pop_header() + local endpoint = pop_string() + --DEBUG(id, name, header, endpoint) + return Event:new("ZyreEnter", id, name, header, endpoint) + elseif command == "DELIVER" then + local filename = pop_string() + local fullname = pop_string() + --DEBUG("received", filename) + return Event:new("FileDeliver", filename, fullname) + end +end + +return MessageQueue diff --git a/frontend/ui/message/zyremessagequeue.lua b/frontend/ui/message/zyremessagequeue.lua new file mode 100644 index 000000000..5c0fa07c5 --- /dev/null +++ b/frontend/ui/message/zyremessagequeue.lua @@ -0,0 +1,41 @@ +local ffi = require("ffi") +local DEBUG = require("dbg") +local util = require("ffi/util") +local Event = require("ui/event") +local MessageQueue = require("ui/message/messagequeue") + +local dummy = require("ffi/zeromq_h") +local zyre = ffi.load("libs/libzyre.so.1") + +local ZyreMessageQueue = MessageQueue:new{ + header = {}, +} + +function ZyreMessageQueue:start() + self.node = zyre.zyre_new() + for key, value in pairs(self.header) do + zyre.zyre_set_header(self.node, key, value) + end + zyre.zyre_set_verbose(self.node) + zyre.zyre_start(self.node) + zyre.zyre_join(self.node, "GLOBAL") +end + +function ZyreMessageQueue:stop() + if self.node ~= nil then + DEBUG("stop zyre node") + zyre.zyre_stop(self.node) + zyre.zyre_destroy(ffi.new('zyre_t *[1]', self.node)) + end +end + +function ZyreMessageQueue:waitEvent() + local msg = zyre.zyre_recv_nowait(self.node) + while msg ~= nil do + table.insert(self.messages, msg) + msg = zyre.zyre_recv_nowait(self.node) + end + return self:handleZMsgs(self.messages) +end + +return ZyreMessageQueue diff --git a/frontend/ui/uimanager.lua b/frontend/ui/uimanager.lua index af3bcae67..7b82c8252 100644 --- a/frontend/ui/uimanager.lua +++ b/frontend/ui/uimanager.lua @@ -11,16 +11,16 @@ Screen:init() -- initialize the input handling Input:init() -local WAVEFORM_MODE_INIT = 0x0 -- Screen goes to white (clears) -local WAVEFORM_MODE_DU = 0x1 -- Grey->white/grey->black -local WAVEFORM_MODE_GC16 = 0x2 -- High fidelity (flashing) -local WAVEFORM_MODE_GC4 = WAVEFORM_MODE_GC16 -- For compatibility -local WAVEFORM_MODE_GC16_FAST = 0x3 -- Medium fidelity -local WAVEFORM_MODE_A2 = 0x4 -- Faster but even lower fidelity -local WAVEFORM_MODE_GL16 = 0x5 -- High fidelity from white transition -local WAVEFORM_MODE_GL16_FAST = 0x6 -- Medium fidelity from white transition -local WAVEFORM_MODE_AUTO = 0x101 - +local WAVEFORM_MODE_INIT = 0x0 -- Screen goes to white (clears) +local WAVEFORM_MODE_DU = 0x1 -- Grey->white/grey->black +local WAVEFORM_MODE_GC16 = 0x2 -- High fidelity (flashing) +local WAVEFORM_MODE_GC4 = WAVEFORM_MODE_GC16 -- For compatibility +local WAVEFORM_MODE_GC16_FAST = 0x3 -- Medium fidelity +local WAVEFORM_MODE_A2 = 0x4 -- Faster but even lower fidelity +local WAVEFORM_MODE_GL16 = 0x5 -- High fidelity from white transition +local WAVEFORM_MODE_GL16_FAST = 0x6 -- Medium fidelity from white transition +local WAVEFORM_MODE_AUTO = 0x101 + -- there is only one instance of this local UIManager = { default_refresh_type = 0, -- 0 for partial refresh, 1 for full refresh @@ -42,7 +42,8 @@ local UIManager = { _running = true, _window_stack = {}, _execution_stack = {}, - _dirty = {} + _dirty = {}, + _zeromqs = {}, } -- For the Kobo Aura an offset is needed, because the bezel make the visible screen smaller. @@ -139,9 +140,26 @@ function UIManager:setDirty(widget, refresh_type) self._dirty[widget] = refresh_type end +function UIManager:insertZMQ(zeromq) + table.insert(self._zeromqs, zeromq) + return zeromq +end + +function UIManager:removeZMQ(zeromq) + for i = #self._zeromqs, 1, -1 do + if self._zeromqs[i] == zeromq then + table.remove(self._zeromqs, i) + end + end +end + -- signal to quit function UIManager:quit() self._running = false + for i = #self._zeromqs, 1, -1 do + self._zeromqs[i]:stop() + table.remove(self._zeromqs, i) + end end -- transmit an event to registered widgets @@ -216,6 +234,7 @@ function UIManager:run() -- stop when we have no window to show if #self._window_stack == 0 then DEBUG("no dialog left to show, would loop endlessly") + self:quit() return nil end @@ -295,8 +314,19 @@ function UIManager:run() -- note that we will skip that if in the meantime we have tasks that are ready to run local input_event = nil if not wait_until then - -- no pending task, wait endlessly - input_event = Input:waitEvent() + if #self._zeromqs > 0 then + -- pending message queue, wait 100ms for input + input_event = Input:waitEvent(1000*100) + if input_event and input_event.handler == "onInputError" then + for _, zeromq in ipairs(self._zeromqs) do + input_event = zeromq:waitEvent() + if input_event then break end + end + end + else + -- no pending task, wait endlessly + input_event = Input:waitEvent() + end elseif wait_until[1] > now[1] or wait_until[1] == now[1] and wait_until[2] > now[2] then local wait_for = { s = wait_until[1] - now[1], us = wait_until[2] - now[2] } diff --git a/koreader-base b/koreader-base index 995dbe75d..7108ec4fd 160000 --- a/koreader-base +++ b/koreader-base @@ -1 +1 @@ -Subproject commit 995dbe75d9a5325ce93cd04486b0a1fe20143197 +Subproject commit 7108ec4fd145d32d7abe32c25f5811001f5f570c diff --git a/plugins/zsync.koplugin/client.cfg b/plugins/zsync.koplugin/client.cfg new file mode 100644 index 000000000..84e83b4c8 --- /dev/null +++ b/plugins/zsync.koplugin/client.cfg @@ -0,0 +1,6 @@ +# Configure server for plain access +# +client + heartbeat = 1 # Interval in seconds + resync = 1 + diff --git a/plugins/zsync.koplugin/main.lua b/plugins/zsync.koplugin/main.lua new file mode 100644 index 000000000..544c18dcf --- /dev/null +++ b/plugins/zsync.koplugin/main.lua @@ -0,0 +1,369 @@ +local FileManagerHistory = require("apps/filemanager/filemanagerhistory") +local FileManagerMenu = require("apps/filemanager/filemanagermenu") +local InputContainer = require("ui/widget/container/inputcontainer") +local FrameContainer = require("ui/widget/container/framecontainer") +local FileManager = require("apps/filemanager/filemanager") +local VerticalGroup = require("ui/widget/verticalgroup") +local VerticalSpan = require("ui/widget/verticalspan") +local ButtonDialog = require("ui/widget/buttondialog") +local FileChooser = require("ui/widget/filechooser") +local InfoMessage = require("ui/widget/infomessage") +local TextWidget = require("ui/widget/textwidget") +local DocSettings = require("docsettings") +local UIManager = require("ui/uimanager") +local Screen = require("ui/screen") +local Event = require("ui/event") +local Font = require("ui/font") +local DEBUG = require("dbg") +local _ = require("gettext") +local util = require("ffi/util") +-- lfs + +local ffi = require("ffi") +ffi.cdef[[ +int remove(const char *); +int rmdir(const char *); +]] + +local dummy = require("ffi/zeromq_h") +local ZSync = InputContainer:new{ +} + +function ZSync:init() + self.ui.menu:registerToMainMenu(self) + self.outbox = self.path.."/outbox" + self.server_config = self.path.."/server.cfg" + self.client_config = self.path.."/client.cfg" +end + +function ZSync:addToMainMenu(tab_item_table) + table.insert(tab_item_table.plugins, { + text = _("ZSync"), + sub_item_table = { + { + text_func = function() + return not self.filemq_server + and _("Publish this document") + or _("Stop publisher") + end, + enabled_func = function() + return self.filemq_client == nil + end, + callback = function() + if not self.filemq_server then + self:publish() + else + self:unpublish() + end + end + }, + { + text_func = function() + return not self.filemq_client + and _("Subscribe documents") + or _("Stop subscriber") + end, + enabled_func = function() + return self.filemq_server == nil + end, + callback = function() + if not self.filemq_client then + self:subscribe() + else + self:unsubscribe() + end + end + } + } + }) +end + +function ZSync:initServerZyreMQ() + local ZyreMessageQueue = require("ui/message/zyremessagequeue") + if self.zyre_messagequeue == nil then + self.server_zyre = ZyreMessageQueue:new{ + header = {["FILEMQ-SERVER"] = tostring(self.fmq_port)}, + } + self.server_zyre:start() + self.zyre_messagequeue = UIManager:insertZMQ(self.server_zyre) + end +end + +function ZSync:initClientZyreMQ() + local ZyreMessageQueue = require("ui/message/zyremessagequeue") + if self.zyre_messagequeue == nil then + self.client_zyre = ZyreMessageQueue:new{} + self.client_zyre:start() + self.zyre_messagequeue = UIManager:insertZMQ(self.client_zyre) + end +end + +function ZSync:initServerFileMQ(outboxes) + local FileMessageQueue = require("ui/message/filemessagequeue") + local filemq = ffi.load("libs/libfmq.so.1") + if self.file_messagequeue == nil then + self.filemq_server = filemq.fmq_server_new() + self.file_messagequeue = UIManager:insertZMQ(FileMessageQueue:new{ + server = self.filemq_server + }) + self.fmq_port = filemq.fmq_server_bind(self.filemq_server, "tcp://*:*") + filemq.fmq_server_configure(self.filemq_server, self.server_config) + filemq.fmq_server_set_anonymous(self.filemq_server, true) + end + UIManager:scheduleIn(1, function() + for _, outbox in ipairs(outboxes) do + DEBUG("publish", outbox.path, outbox.alias) + filemq.fmq_server_publish(self.filemq_server, outbox.path, outbox.alias) + end + end) +end + +function ZSync:initClientFileMQ(inbox) + local FileMessageQueue = require("ui/message/filemessagequeue") + local filemq = ffi.load("libs/libfmq.so.1") + if self.file_messagequeue == nil then + self.filemq_client = filemq.fmq_client_new() + self.file_messagequeue = UIManager:insertZMQ(FileMessageQueue:new{ + client = self.filemq_client + }) + filemq.fmq_client_configure(self.filemq_client, self.client_config) + end + UIManager:scheduleIn(1, function() + filemq.fmq_client_set_inbox(self.filemq_client, inbox) + end) +end + +local function clearDirectory(dir, rmdir) + for f in lfs.dir(dir) do + local path = dir.."/"..f + local mode = lfs.attributes(path, "mode") + if mode == "file" then + ffi.C.remove(path) + elseif mode == "directory" and f ~= "." and f ~= ".." then + clearDirectory(path, true) + end + end + if rmdir then + ffi.C.rmdir(dir) + end +end + +local function mklink(path, filename) + local basename = filename:match(".*/(.*)") or filename + local linkname = path .. "/" .. basename .. ".ln" + local linkfile = io.open(linkname, "w") + if linkfile then + linkfile:write(filename .. "\n") + linkfile:close() + end +end + +function ZSync:getOutboxes(files) + lfs.mkdir(self.outbox) + clearDirectory(self.outbox) + local outboxes = {} + for _, filename in ipairs(files) do + local mode = lfs.attributes(filename, "mode") + if mode == "file" then + mklink(self.outbox, filename) + elseif mode == "directory" then + local basename = filename:match(".*/(.*)") or filename + table.insert(outboxes, { + path = filename, + alias = "/" .. basename, + }) + end + end + table.insert(outboxes, { + path = self.outbox, + alias = "/", + }) + return outboxes +end + +function ZSync:publish() + DEBUG("publish document", self.view.document.file) + local file = self.view.document.file + local outboxes = self:getOutboxes({file}) + -- init filemq first to get filemq port + self:initServerFileMQ(outboxes) + self:initServerZyreMQ() +end + +function ZSync:unpublish() + DEBUG("ZSync unpublish") + clearDirectory(self.outbox) + self:stopZyreMQ() + self:stopFileMQ() +end + +local InboxChooser = InputContainer:new{ + title = _("Choose inbox"), + dimen = Screen:getSize(), + exclude_dirs = {"%.sdr$"}, +} + +function InboxChooser:init() + self.show_parent = self.show_parent or self + local banner = VerticalGroup:new{ + TextWidget:new{ + face = Font:getFace("tfont", 24), + text = _("Choose inbox"), + }, + VerticalSpan:new{ width = Screen:scaleByDPI(10) } + } + + local g_show_hidden = G_reader_settings:readSetting("show_hidden") + local show_hidden = g_show_hidden == nil and DSHOWHIDDENFILES or g_show_hidden + local root_path = G_reader_settings:readSetting("lastdir") or lfs.currentdir() + local file_chooser = FileChooser:new{ + -- remeber to adjust the height when new item is added to the group + path = root_path, + show_parent = self.show_parent, + show_hidden = show_hidden, + height = Screen:getHeight() - banner:getSize().h, + is_popout = false, + is_borderless = true, + dir_filter = function(dirname) + for _, pattern in ipairs(self.exclude_dirs) do + if dirname:match(pattern) then return end + end + return true + end, + file_filter = function(filename) end, + close_callback = function() UIManager:close(self) end, + } + + local on_close_chooser = function() self:onClose() end + local on_confirm_inbox = function(inbox) self:onConfirm(inbox) end + + function file_chooser:onFileHold(dir) + self.chooser_dialog = self + self.button_dialog = ButtonDialog:new{ + buttons = { + { + { + text = _("Confirm"), + callback = function() + UIManager:close(self.button_dialog) + on_confirm_inbox(dir) + on_close_chooser() + end, + }, + { + text = _("Cancel"), + callback = function() + UIManager:close(self.button_dialog) + on_close_chooser() + end, + }, + }, + }, + } + UIManager:show(self.button_dialog) + return true + end + + self[1] = FrameContainer:new{ + padding = 0, + bordersize = 0, + background = 0, + VerticalGroup:new{ + banner, + file_chooser, + } + } +end + +function InboxChooser:onClose() + UIManager:close(self) + return true +end + +function InboxChooser:onConfirm(inbox) + if inbox:sub(-3, -1) == "/.." then + inbox = inbox:sub(1, -4) + end + G_reader_settings:saveSetting("lastdir", inbox) + self.zsync:onChooseInbox(inbox) + return true +end + +function ZSync:onChooseInbox(inbox) + DEBUG("choose inbox", inbox) + self.inbox = inbox + -- init zyre first for filemq endpoint + self:initClientZyreMQ() + self:initClientFileMQ(inbox) + return true +end + +function ZSync:subscribe() + DEBUG("subscribe documents") + self.inbox_chooser = InboxChooser:new{zsync = self} + UIManager:show(self.inbox_chooser) +end + +function ZSync:unsubscribe() + DEBUG("ZSync unsubscribe") + self:stopFileMQ() + self:stopZyreMQ() +end + +function ZSync:onZyreEnter(id, name, header, endpoint) + local filemq = ffi.load("libs/libfmq.so.1") + if header and endpoint and header["FILEMQ-SERVER"] then + self.server_zyre_endpoint = endpoint + local port = header["FILEMQ-SERVER"] + local host = endpoint:match("(.*:)") or "*:" + local fmq_server_endpoint = host..port + DEBUG("connect filemq server at", fmq_server_endpoint) + -- wait for filemq server setup befor connecting + UIManager:scheduleIn(2, function() + filemq.fmq_client_set_resync(self.filemq_client, true) + filemq.fmq_client_subscribe(self.filemq_client, "/") + filemq.fmq_client_connect(self.filemq_client, fmq_server_endpoint) + end) + end + return true +end + +function ZSync:onFileDeliver(filename, fullname) + UIManager:show(InfoMessage:new{ + text = _("Received file:") .. "\n" .. filename, + timeout = 1, + }) +end + +--[[ +-- We assume that ZSync is running in either server mode or client mode +-- but never both. The zyre_messagequeue may be a server_zyre or client_zyre. +-- And the file_messagequeue may be a filemq_server or filemq_client. +--]] +function ZSync:stopZyreMQ() + if self.zyre_messagequeue then + self.zyre_messagequeue:stop() + UIManager:removeZMQ(self.zyre_messagequeue) + self.zyre_messagequeue = nil + self.server_zyre = nil + self.client_zyre = nil + end +end + +function ZSync:stopFileMQ() + if self.file_messagequeue then + self.file_messagequeue:stop() + UIManager:removeZMQ(self.file_messagequeue) + self.file_messagequeue = nil + self.filemq_server = nil + self.filemq_client = nil + end +end + +function ZSync:onCloseReader() + self:stopZyreMQ() + self:stopFileMQ() +end + +return ZSync + diff --git a/plugins/zsync.koplugin/server.cfg b/plugins/zsync.koplugin/server.cfg new file mode 100644 index 000000000..767f1ef7e --- /dev/null +++ b/plugins/zsync.koplugin/server.cfg @@ -0,0 +1,9 @@ +# Configure server to allow anonymous access +# +server + monitor = 1 # Check mount points + heartbeat = 1 # Heartbeat to clients + +security + echo = I: server accepts anonymous access + anonymous = 1 diff --git a/reader.lua b/reader.lua index 917f2dff5..64ae72c1e 100755 --- a/reader.lua +++ b/reader.lua @@ -24,13 +24,14 @@ if lang_locale then _.changeLang(lang_locale) end +local DocumentRegistry = require("document/documentregistry") +local FileManager = require("apps/filemanager/filemanager") +local InfoMessage = require("ui/widget/infomessage") local UIManager = require("ui/uimanager") local Menu = require("ui/widget/menu") -local InfoMessage = require("ui/widget/infomessage") -local DocumentRegistry = require("document/documentregistry") -local DEBUG = require("dbg") local Device = require("ui/device") local Screen = require("ui/screen") +local DEBUG = require("dbg") local ReaderUI = require("apps/reader/readerui") @@ -98,12 +99,11 @@ function doShowReaderUI(file, pass) end function showHomePage(path) - local FileManager = require("apps/filemanager/filemanager") + G_reader_settings:saveSetting("lastdir", path) UIManager:show(FileManager:new{ dimen = Screen:getSize(), root_path = path, onExit = function() - exitReader() UIManager:quit() end })