From 667e8834ad686d4e9dd394951a5d4cfe97f09d15 Mon Sep 17 00:00:00 2001 From: Zijie He Date: Mon, 18 Apr 2016 15:38:14 -0700 Subject: [PATCH] Migrate history folder, FileManagerHistory uses own history.lua file and ReadHistory component --- .../apps/filemanager/filemanagerhistory.lua | 31 +---- frontend/apps/reader/readerui.lua | 1 + frontend/docsettings.lua | 35 +++--- frontend/readhistory.lua | 112 ++++++++++++++++++ 4 files changed, 133 insertions(+), 46 deletions(-) create mode 100644 frontend/readhistory.lua diff --git a/frontend/apps/filemanager/filemanagerhistory.lua b/frontend/apps/filemanager/filemanagerhistory.lua index 7dfe9c076..5ab81ef5b 100644 --- a/frontend/apps/filemanager/filemanagerhistory.lua +++ b/frontend/apps/filemanager/filemanagerhistory.lua @@ -1,17 +1,11 @@ local InputContainer = require("ui/widget/container/inputcontainer") local CenterContainer = require("ui/widget/container/centercontainer") local ButtonDialog = require("ui/widget/buttondialog") -local lfs = require("libs/libkoreader-lfs") -local DataStorage = require("datastorage") local UIManager = require("ui/uimanager") -local DocSettings = require("docsettings") local Menu = require("ui/widget/menu") -local joinPath = require("ffi/util").joinPath local Screen = require("device").screen local _ = require("gettext") -local history_dir = DataStorage:getHistoryDir() - local FileManagerHistory = InputContainer:extend{ hist_menu_title = _("History"), } @@ -31,27 +25,8 @@ function FileManagerHistory:addToMainMenu(tab_item_table) end function FileManagerHistory:updateItemTable() - local ReaderUI = require("apps/reader/readerui") - self.hist = {} - - for f in lfs.dir(history_dir) do - local path = joinPath(history_dir, f) - if lfs.attributes(path, "mode") == "file" then - local name = DocSettings:getNameFromHistory(f) - table.insert(self.hist, { - date = lfs.attributes(path, "modification"), - text = name, - histfile = f, - callback = function() - ReaderUI:showReader( - DocSettings:getPathFromHistory(f).. "/" .. name) - end - }) - end - end - table.sort(self.hist, function(v1, v2) return v1.date > v2.date end) - - self.hist_menu:swithItemTable(self.hist_menu_title, self.hist) + self.hist_menu:swithItemTable(self.hist_menu_title, + require("readhistory").hist) end function FileManagerHistory:onSetDimensions(dimen) @@ -65,7 +40,7 @@ function FileManagerHistory:onMenuHold(item) { text = _("Remove this item from history"), callback = function() - os.remove(joinPath(history_dir, item.histfile)) + require("readhistory"):removeItem(item) self._manager:updateItemTable() UIManager:close(self.histfile_dialog) end, diff --git a/frontend/apps/reader/readerui.lua b/frontend/apps/reader/readerui.lua index 1ddeaee52..d3e1f3612 100644 --- a/frontend/apps/reader/readerui.lua +++ b/frontend/apps/reader/readerui.lua @@ -329,6 +329,7 @@ end function ReaderUI:showReader(file) DEBUG("show reader ui") + require("readhistory"):addItem(file) if lfs.attributes(file, "mode") ~= "file" then UIManager:show(InfoMessage:new{ text = T( _("File '%1' does not exist."), file) diff --git a/frontend/docsettings.lua b/frontend/docsettings.lua index da67aa158..9032078c4 100644 --- a/frontend/docsettings.lua +++ b/frontend/docsettings.lua @@ -36,38 +36,37 @@ function DocSettings:purgeDocSettings(doc_path) end function DocSettings:open(docfile) - local history_path - local sidecar_path + -- TODO(zijiehe): Remove history_path, use only sidecar. + local new = { data = {} } + local ok, stored if docfile == ".reader" then -- we handle reader setting as special case - history_path = DataStorage:getDataDir() .. "/settings.reader.lua" + new.history_file = DataStorage:getDataDir() .. "/settings.reader.lua" + + ok, stored = pcall(dofile, new.history_file) else - history_path = self:getHistoryPath(docfile) + new.history_file = self:getHistoryPath(docfile) local sidecar = self:getSidecarDir(docfile) if lfs.attributes(sidecar, "mode") ~= "directory" then lfs.mkdir(sidecar) end - sidecar_path = sidecar.."/"..docfile:match(".*%/(.*)")..".lua" - end - -- construct settings obj - local new = { - history_file = history_path, - sidecar_file = sidecar_path, - data = {} - } - local ok, stored = pcall(dofile, new.sidecar_file or "") - if not ok then - ok, stored = pcall(dofile, new.history_file or "") + new.sidecar_file = sidecar.."/"..docfile:match(".*%/(.*)")..".lua" + + ok, stored = pcall(dofile, new.sidecar_file or "") if not ok then - -- try legacy conf path, for backward compatibility. this also - -- takes care of reader legacy setting - ok, stored = pcall(dofile, docfile..".kpdfview.lua") + ok, stored = pcall(dofile, new.history_file or "") + if not ok then + -- try legacy conf path, for backward compatibility. this also + -- takes care of reader legacy setting + ok, stored = pcall(dofile, docfile..".kpdfview.lua") + end end end if ok and stored then new.data = stored end + return setmetatable(new, { __index = DocSettings}) end diff --git a/frontend/readhistory.lua b/frontend/readhistory.lua new file mode 100644 index 000000000..dd5eb4791 --- /dev/null +++ b/frontend/readhistory.lua @@ -0,0 +1,112 @@ +local lfs = require("libs/libkoreader-lfs") +local DataStorage = require("datastorage") +local DocSettings = require("docsettings") +local joinPath = require("ffi/util").joinPath +local dump = require("dump") + +local history_file = joinPath(DataStorage:getDataDir(), "history.lua") + +local ReadHistory = { + hist = {}, +} + +local function buildEntry(input_time, input_file) + return { + time = input_time, + text = input_file:gsub(".*/", ""), + file = input_file, + callback = function() + local ReaderUI = require("apps/reader/readerui") + ReaderUI:showReader(input_file) + end + } +end + +function ReadHistory:_sort() + table.sort(self.hist, function(l, r) return l.file < r.file end) + -- TODO(zijiehe): Use binary insert instead of a loop to deduplicate. + for i = #self.hist, 2, -1 do + if self.hist[i].file == self.hist[i - 1].file then + table.remove(self.hist, i) + end + end + table.sort(self.hist, function(v1, v2) return v1.time > v2.time end) + -- TODO(zijiehe): Use binary search to find an item when deleting it. + for i = 1, #self.hist, 1 do + self.hist[i].index = i + end +end + +-- Reduces total count in hist list to a reasonable number by removing last +-- several items. +function ReadHistory:_reduce() + while #self.hist > 500 do + table.remove(self.hist, #self.hist) + end +end + +-- Flushes current history table into file. +function ReadHistory:_flush() + local content = {} + for k, v in pairs(self.hist) do + content[k] = { + time = v.time, + file = v.file + } + end + local f = io.open(history_file, "w") + f:write("return " .. dump(content) .. "\n") + f:close() +end + +-- Reads history table from file +function ReadHistory:_read() + local ok, data = pcall(dofile, history_file) + if ok then + for k, v in pairs(data) do + table.insert(self.hist, buildEntry(v.time, v.file)) + end + end +end + +-- Reads history from legacy history folder +function ReadHistory:_readLegacyHistory() + local history_dir = DataStorage:getHistoryDir() + for f in lfs.dir(history_dir) do + local path = joinPath(history_dir, f) + if lfs.attributes(path, "mode") == "file" then + local file = joinPath(DocSettings:getPathFromHistory(f), + DocSettings:getNameFromHistory(f)) + table.insert(self.hist, + buildEntry(lfs.attributes(path, "modification"), file)) + end + end +end + +function ReadHistory:_init() + self:_read() + self:_readLegacyHistory() + self:_sort() + self:_reduce() +end + +function ReadHistory:removeItem(item) + table.remove(self.hist, item.index) + os.remove(DocSettings:getHistoryPath(item.file)) + self:_flush() +end + +function ReadHistory:addItem(file) + if file ~= nil and lfs.attributes(file, "mode") == "file" then + table.insert(self.hist, 1, buildEntry(os.time(), file)) + -- TODO(zijiehe): We do not need to sort if we can use binary insert and + -- binary search. + self:_sort() + self:_reduce() + self:_flush() + end +end + +ReadHistory:_init() + +return ReadHistory