diff --git a/frontend/apps/reader/modules/readerfooter.lua b/frontend/apps/reader/modules/readerfooter.lua index 9e0b0496e..477ad1a0b 100644 --- a/frontend/apps/reader/modules/readerfooter.lua +++ b/frontend/apps/reader/modules/readerfooter.lua @@ -15,6 +15,7 @@ local TextWidget = require("ui/widget/textwidget") local UIManager = require("ui/uimanager") local WidgetContainer = require("ui/widget/container/widgetcontainer") local util = require("util") +local T = require("ffi/util").template local _ = require("gettext") local Screen = Device.screen @@ -32,6 +33,31 @@ local MODE = { wifi_status = 10, } +local symbol_prefix = { + letters = { + time = nil, + pages_left = "=>", + battery = "B:", + percentage = "R:", + book_time_to_read = "TB:", + chapter_time_to_read = "TC:", + frontlight = "L:", + mem_usage = "M:", + wifi_status = "W:", + }, + icons = { + time = "⌚", + pages_left = "⇒", + battery = "⚡", + percentage = "⤠", + book_time_to_read = "⏳", + chapter_time_to_read = "⤻", + frontlight = "☼", + mem_usage = "⌨", + wifi_status = "⚟", + } +} + local MODE_NB = 0 local MODE_INDEX = {} for k,v in pairs(MODE) do @@ -42,57 +68,89 @@ end -- functions that generates footer text for each mode local footerTextGeneratorMap = { empty = function() return "" end, - frontlight = function() - if not Device:hasFrontlight() then return "L: NA" end + frontlight = function(footer) + local symbol_type = footer.settings.item_prefix or "icons" + local prefix = symbol_prefix[symbol_type].frontlight local powerd = Device:getPowerDevice() if powerd:isFrontlightOn() then if Device:isCervantes() or Device:isKobo() then - return ("L: %d%%"):format(powerd:frontlightIntensity()) + return (prefix .. " %d%%"):format(powerd:frontlightIntensity()) else - return ("L: %d"):format(powerd:frontlightIntensity()) + return (prefix .. " %d"):format(powerd:frontlightIntensity()) end else - return "L: Off" + return T(_("%1 Off"), prefix) end end, - battery = function() + battery = function(footer) + local symbol_type = footer.settings.item_prefix or "icons" + local prefix = symbol_prefix[symbol_type].battery local powerd = Device:getPowerDevice() - return "B:" .. (powerd:isCharging() and "+" or "") .. powerd:getCapacity() .. "%" + return prefix .. " " .. (powerd:isCharging() and "+" or "") .. powerd:getCapacity() .. "%" end, - time = function() - return os.date("%H:%M") + time = function(footer) + local symbol_type = footer.settings.item_prefix or "icons" + local prefix = symbol_prefix[symbol_type].time + local clock + if footer.settings.time_format == "12" then + clock = os.date("%I:%M%p") + else + clock = os.date("%H:%M") + end + if not prefix then + return clock + else + return prefix .. " " .. clock + end end, page_progress = function(footer) if footer.pageno then return ("%d / %d"):format(footer.pageno, footer.pages) - else + elseif footer.position then return ("%d / %d"):format(footer.position, footer.doc_height) end end, pages_left = function(footer) + local symbol_type = footer.settings.item_prefix or "icons" + local prefix = symbol_prefix[symbol_type].pages_left local left = footer.ui.toc:getChapterPagesLeft( footer.pageno, footer.toc_level) - return "=> " .. (left and left or footer.pages - footer.pageno) + return prefix .. " " .. (left and left or footer.pages - footer.pageno) end, percentage = function(footer) - return ("R:%1.f%%"):format(footer.progress_bar.percentage * 100) + local symbol_type = footer.settings.item_prefix or "icons" + local prefix = symbol_prefix[symbol_type].percentage + local digits = footer.settings.progress_pct_format or "0" + local string_percentage + if not prefix then + string_percentage = "%." .. digits .. "f%%" + else + string_percentage = prefix .. " %." .. digits .. "f%%" + end + return string_percentage:format(footer.progress_bar.percentage * 100) end, book_time_to_read = function(footer) + local symbol_type = footer.settings.item_prefix or "icons" + local prefix = symbol_prefix[symbol_type].book_time_to_read local current_page if footer.view.document.info.has_pages then current_page = footer.ui.paging.current_page else current_page = footer.view.document:getCurrentPage() end - return footer:getDataFromStatistics("TB: ", footer.pages - current_page) + return footer:getDataFromStatistics(prefix .. " ", footer.pages - current_page) end, chapter_time_to_read = function(footer) + local symbol_type = footer.settings.item_prefix or "icons" + local prefix = symbol_prefix[symbol_type].chapter_time_to_read local left = footer.ui.toc:getChapterPagesLeft( footer.pageno, footer.toc_level) return footer:getDataFromStatistics( - "TC: ", (left and left or footer.pages - footer.pageno)) + prefix .. " ", (left and left or footer.pages - footer.pageno)) end, mem_usage = function(footer) + local symbol_type = footer.settings.item_prefix or "icons" + local prefix = symbol_prefix[symbol_type].mem_usage local statm = io.open("/proc/self/statm", "r") if statm then local infos = statm:read("*all") @@ -100,16 +158,18 @@ local footerTextGeneratorMap = { local rss = infos:match("^%S+ (%S+) ") -- we got the nb of 4Kb-pages used, that we convert to Mb rss = math.floor(tonumber(rss) * 4096 / 1024 / 1024) - return ("M:%d"):format(rss) + return (prefix .. " %d"):format(rss) end return "" end, - wifi_status = function() + wifi_status = function(footer) + local symbol_type = footer.settings.item_prefix or "icons" + local prefix = symbol_prefix[symbol_type].wifi_status local NetworkMgr = require("ui/network/manager") if NetworkMgr:isWifiOn() then - return "W:On" + return T(_("%1 On"), prefix) else - return "W:Off" + return T(_("%1 Off"), prefix) end end, } @@ -151,6 +211,7 @@ function ReaderFooter:init() frontlight = false, mem_usage = false, wifi_status = false, + item_prefix = "icons" } if self.settings.disabled then @@ -359,21 +420,40 @@ function ReaderFooter:updateFooterTextGenerator() return true end -local option_titles = { - all_at_once = _("Show all at once"), - reclaim_height = _("Reclaim bar height from bottom margin"), - toc_markers = _("Show chapter markers"), - page_progress = _("Current page"), - time = _("Current time"), - pages_left = _("Pages left in chapter"), - battery = _("Battery status"), - percentage = _("Progress percentage"), - book_time_to_read = _("Book time to read"), - chapter_time_to_read = _("Chapter time to read"), - frontlight = _("Frontlight level"), - mem_usage = _("KOReader memory usage"), - wifi_status = _("Wi-Fi status"), -} +function ReaderFooter:progressPercentage(digits) + local symbol_type = self.settings.item_prefix or "icons" + local prefix = symbol_prefix[symbol_type].percentage + + local string_percentage + if not prefix then + string_percentage = "%." .. digits .. "f%%" + else + string_percentage = prefix .. " %." .. digits .. "f%%" + end + return string_percentage:format(self.progress_bar.percentage * 100) +end + +function ReaderFooter:textOptionTitles(option) + local symbol = self.settings.item_prefix or "icons" + local option_titles = { + all_at_once = _("Show all at once"), + reclaim_height = _("Reclaim bar height from bottom margin"), + toc_markers = _("Show chapter markers"), + page_progress = T(_("Current page (%1)"), "/"), + time = symbol_prefix[symbol].time + and T(_("Current time (%1)"), symbol_prefix[symbol].time) or _("Current time"), + pages_left = T(_("Pages left in chapter (%1)"), symbol_prefix[symbol].pages_left), + battery = T(_("Battery status (%1)"), symbol_prefix[symbol].battery), + percentage = symbol_prefix[symbol].percentage + and T(_("Progress percentage (%1)"), symbol_prefix[symbol].percentage) or ("Progress percentage"), + book_time_to_read = T(_("Book time to read (%1)"),symbol_prefix[symbol].book_time_to_read), + chapter_time_to_read = T(_("Chapter time to read (%1)"), symbol_prefix[symbol].chapter_time_to_read), + frontlight = T(_("Frontlight level (%1)"), symbol_prefix[symbol].frontlight), + mem_usage = T(_("KOReader memory usage (%1)"), symbol_prefix[symbol].mem_usage), + wifi_status = T(_("Wi-Fi status (%1)"), symbol_prefix[symbol].wifi_status), + } + return option_titles[option] +end function ReaderFooter:addToMainMenu(menu_items) local sub_items = {} @@ -400,7 +480,9 @@ function ReaderFooter:addToMainMenu(menu_items) local getMinibarOption = function(option, callback) return { - text = option_titles[option], + text_func = function() + return self:textOptionTitles(option) + end, checked_func = function() return self.settings[option] == true end, @@ -456,13 +538,239 @@ function ReaderFooter:addToMainMenu(menu_items) end, } end - - table.insert(sub_items, - getMinibarOption("all_at_once", self.updateFooterTextGenerator)) - table.insert(sub_items, - getMinibarOption("reclaim_height")) + table.insert(sub_items, { + text = _("Settings"), + sub_item_table = { + getMinibarOption("all_at_once", self.updateFooterTextGenerator), + getMinibarOption("reclaim_height"), + { + text = _("Auto refresh time"), + separator = true, + checked_func = function() + return self.settings.auto_refresh_time == true + end, + -- only enable auto refresh when time is shown + enabled_func = function() return self.settings.time end, + callback = function() + self.settings.auto_refresh_time = not self.settings.auto_refresh_time + G_reader_settings:saveSetting("footer", self.settings) + if self.settings.auto_refresh_time then + self:setupAutoRefreshTime() + else + UIManager:unschedule(self.autoRefreshTime) + self.onCloseDocument = nil + end + end + }, + { + text = _("Alignment"), + enabled_func = function() + return self.settings.disable_progress_bar + end, + sub_item_table = { + { + text = _("Center"), + checked_func = function() + return self.settings.align == "center" or self.settings.align == nil + end, + callback = function() + self.settings.align = "center" + self:updateFooterContainer() + self:resetLayout(true) + self:updateFooter() + UIManager:setDirty(nil, "ui") + end, + }, + { + text = _("Left"), + checked_func = function() + return self.settings.align == "left" + end, + callback = function() + self.settings.align = "left" + self:updateFooterContainer() + self:resetLayout(true) + self:updateFooter() + UIManager:setDirty(nil, "ui") + end, + }, + { + text = _("Right"), + checked_func = function() + return self.settings.align == "right" + end, + callback = function() + self.settings.align = "right" + self:updateFooterContainer() + self:resetLayout(true) + self:updateFooter() + UIManager:setDirty(nil, "ui") + end, + }, + } + }, + { + text = _("Prefix"), + sub_item_table = { + { + text = _("Icons"), + checked_func = function() + return self.settings.item_prefix == "icons" or self.settings.item_prefix == nil + end, + callback = function() + self.settings.item_prefix = "icons" + self:updateFooter() + UIManager:setDirty(nil, "ui") + end, + }, + { + text = _("Letters"), + checked_func = function() + return self.settings.item_prefix == "letters" + end, + callback = function() + self.settings.item_prefix = "letters" + self:updateFooter() + UIManager:setDirty(nil, "ui") + end, + }, + }, + }, + { + text = _("Separator"), + sub_item_table = { + { + text = _("Vertical line") .. " (|)", + checked_func = function() + return self.settings.items_separator == "bar" or self.settings.items_separator == nil + end, + callback = function() + self.settings.items_separator = "bar" + self:updateFooter() + UIManager:setDirty(nil, "ui") + end, + }, + { + text = _("Bullet") .. " (•)", + checked_func = function() + return self.settings.items_separator == "bullet" + end, + callback = function() + self.settings.items_separator = "bullet" + self:updateFooter() + UIManager:setDirty(nil, "ui") + end, + }, + { + text = _("No separator"), + checked_func = function() + return self.settings.items_separator == "none" + end, + callback = function() + self.settings.items_separator = "none" + self:updateFooter() + UIManager:setDirty(nil, "ui") + end, + }, + }, + }, + { + text = _("Progress percentage format"), + sub_item_table = { + { + text = T(_("No decimal point (%1)"), self:progressPercentage(0)), + checked_func = function() + return self.settings.progress_pct_format == "0" or self.settings.progress_pct_format == nil + end, + callback = function() + self.settings.progress_pct_format = "0" + self:updateFooter() + UIManager:setDirty(nil, "ui") + end, + }, + { + text = T(_("1 digit after decimal point (%1)"), self:progressPercentage(1)), + checked_func = function() + return self.settings.progress_pct_format == "1" + end, + callback = function() + self.settings.progress_pct_format = "1" + self:updateFooter() + UIManager:setDirty(nil, "ui") + end, + }, + { + text = T(_("2 digits after decimal point (%1)"), self:progressPercentage(2)), + checked_func = function() + return self.settings.progress_pct_format == "2" + end, + callback = function() + self.settings.progress_pct_format = "2" + self:updateFooter() + UIManager:setDirty(nil, "ui") + end, + }, + }, + }, + { + text = _("Time format"), + sub_item_table = { + { + text = _("24-hour"), + checked_func = function() + return self.settings.time_format == "24" or self.settings.time_format == nil + end, + callback = function() + self.settings.time_format = "24" + self:updateFooter() + UIManager:setDirty(nil, "ui") + end, + }, + { + text = _("12-hour"), + checked_func = function() + return self.settings.time_format == "12" + end, + callback = function() + self.settings.time_format = "12" + self:updateFooter() + UIManager:setDirty(nil, "ui") + end, + }, + } + }, + { + text = _("Durations format"), + sub_item_table = { + { + text = _("Modern"), + checked_func = function() + return self.settings.duration_format == "modern" or self.settings.duration_format == nil + end, + callback = function() + self.settings.duration_format = "modern" + self:updateFooter() + UIManager:setDirty(nil, "ui") + end, + }, + { + text = _("Classic"), + checked_func = function() + return self.settings.duration_format == "classic" + end, + callback = function() + self.settings.duration_format = "classic" + self:updateFooter() + UIManager:setDirty(nil, "ui") + end, + }, + } + }, + } + }) table.insert(sub_items, { text = _("Progress bar"), + separator = true, sub_item_table = { { text = _("Show progress bar"), @@ -478,24 +786,6 @@ function ReaderFooter:addToMainMenu(menu_items) getMinibarOption("toc_markers", self.setTocMarkers), } }) - table.insert(sub_items, { - text = _("Auto refresh time"), - checked_func = function() - return self.settings.auto_refresh_time == true - end, - -- only enable auto refresh when time is shown - enabled_func = function() return self.settings.time end, - callback = function() - self.settings.auto_refresh_time = not self.settings.auto_refresh_time - G_reader_settings:saveSetting("footer", self.settings) - if self.settings.auto_refresh_time then - self:setupAutoRefreshTime() - else - UIManager:unschedule(self.autoRefreshTime) - self.onCloseDocument = nil - end - end - }) table.insert(sub_items, getMinibarOption("page_progress")) table.insert(sub_items, getMinibarOption("time")) table.insert(sub_items, getMinibarOption("pages_left")) @@ -510,50 +800,6 @@ function ReaderFooter:addToMainMenu(menu_items) if Device:isAndroid() then table.insert(sub_items, getMinibarOption("wifi_status")) end - table.insert(sub_items, { - text = _("Alignment"), - sub_item_table = { - { - text = _("Center"), - checked_func = function() - return self.settings.align == "center" or self.settings.align == nil - end, - callback = function() - self.settings.align = "center" - self:updateFooterContainer() - self:resetLayout(true) - self:updateFooter() - UIManager:setDirty(nil, "ui") - end, - }, - { - text = _("Left"), - checked_func = function() - return self.settings.align == "left" - end, - callback = function() - self.settings.align = "left" - self:updateFooterContainer() - self:resetLayout(true) - self:updateFooter() - UIManager:setDirty(nil, "ui") - end, - }, - { - text = _("Right"), - checked_func = function() - return self.settings.align == "right" - end, - callback = function() - self.settings.align = "right" - self:updateFooterContainer() - self:resetLayout(true) - self:updateFooter() - UIManager:setDirty(nil, "ui") - end, - }, - } - }) end -- this method will be updated at runtime based on user setting @@ -561,10 +807,16 @@ function ReaderFooter:genFooterText() end function ReaderFooter:genAllFooterText() local info = {} + local separator = " " + if self.settings.items_separator == "bar" or self.settings.items_separator == nil then + separator = " | " + elseif self.settings.items_separator == "bullet" then + separator = " • " + end for _, gen in ipairs(self.footerTextGenerators) do table.insert(info, gen(self)) end - return table.concat(info, " | ") + return table.concat(info, separator) end -- this method should never get called when footer is disabled @@ -608,7 +860,11 @@ function ReaderFooter:getDataFromStatistics(title, pages) local sec = 'na' local average_time_per_page = self:getAvgTimePerPage() if average_time_per_page then - sec = util.secondsToClock(pages * average_time_per_page, true) + if self.settings.duration_format == "classic" then + sec = util.secondsToClock(pages * average_time_per_page, true) + else + sec = util.secondsToHClock(pages * average_time_per_page, true) + end end return title .. sec end diff --git a/frontend/util.lua b/frontend/util.lua index 8e13305f8..fb9b0eaf2 100644 --- a/frontend/util.lua +++ b/frontend/util.lua @@ -99,6 +99,91 @@ function util.secondsToClock(seconds, withoutSeconds) end end + +-- Converts seconds to a period of time string. + +---- @int seconds number of seconds +---- @bool withoutSeconds if true 1h30', if false 1h30'10'' +---- @bool hmsFormat, if true format 1h30m10s +---- @treturn string clock string in the form of 1h30' or 1h30'10'' +function util.secondsToHClock(seconds, withoutSeconds, hmsFormat) + seconds = tonumber(seconds) + if seconds == 0 then + if withoutSeconds then + if hmsFormat then + return T(_("%1m"), "0") + else + return "0'" + end + else + if hmsFormat then + return T(_("%1s"), "0") + else + return "0''" + end + end + elseif seconds < 60 then + if withoutSeconds and seconds < 30 then + if hmsFormat then + return T(_("%1m"), "0") + else + return "0'" + end + elseif withoutSeconds and seconds >= 30 then + if hmsFormat then + return T(_("%1m"), "1") + else + return "1'" + end + else + if hmsFormat then + return T(_("%1m%2s"), "0", string.format("%02.f", seconds)) + else + return "0'" .. string.format("%02.f", seconds) .. "''" + end + end + else + local round = withoutSeconds and require("optmath").round or math.floor + local hours = string.format("%.f", math.floor(seconds / 3600)) + local mins = string.format("%02.f", round(seconds / 60 - (hours * 60))) + if mins == "60" then + mins = string.format("%02.f", 0) + hours = string.format("%.f", hours + 1) + end + if withoutSeconds then + if hours == "0" then + mins = string.format("%.f", round(seconds / 60)) + return mins .. "'" + end + return T(_("%1h%2"), hours, mins) + end + local secs = string.format("%02.f", math.floor(seconds - hours * 3600 - mins * 60)) + if hours == "0" then + mins = string.format("%.f", round(seconds / 60)) + if hmsFormat then + return T(_("%1m%2s"), mins, secs) + else + return mins .. "'" .. secs .. "''" + end + end + if hmsFormat then + if secs == "00" then + return T(_("%1h%2m"), hours, mins) + else + return T(_("%1h%2m%3s"), hours, mins, secs) + end + + else + if secs == "00" then + return T(_("%1h%2'"), hours, mins) + else + return T(_("%1h%2'%3''"), hours, mins, secs) + end + end + end +end + + --[[-- Compares values in two different tables. diff --git a/spec/unit/readerfooter_spec.lua b/spec/unit/readerfooter_spec.lua index 5e1ffb1db..60721511a 100644 --- a/spec/unit/readerfooter_spec.lua +++ b/spec/unit/readerfooter_spec.lua @@ -19,10 +19,27 @@ describe("Readerfooter module", function() if status_bar then for _, subitem in ipairs(status_bar.sub_item_table) do + if subitem.text_func and subitem.text_func() == menu_title then + subitem.callback() + return + end if subitem.text == menu_title then subitem.callback() return end + if subitem.sub_item_table then + local status_bar_sub_item = subitem.sub_item_table + for _, sub_subitem in ipairs(status_bar_sub_item) do + if sub_subitem.text_func and sub_subitem.text_func() == menu_title then + sub_subitem.callback() + return + end + if sub_subitem.text == menu_title then + sub_subitem.callback() + return + end + end + end end error('Menu item not found: "' .. menu_title .. '"!') end @@ -144,10 +161,10 @@ describe("Readerfooter module", function() local footer = readerui.view.footer footer:onPageUpdate(1) footer:updateFooter() - local timeinfo = footer.textGeneratorMap.time() + local timeinfo = footer.textGeneratorMap.time(footer) local page_count = readerui.document:getPageCount() -- stats has not been initialized here, so we get na TB and TC - assert.are.same('1 / '..page_count..' | '..timeinfo..' | => 0 | B:0% | R:0% | TB: na | TC: na', + assert.are.same('1 / '..page_count..' | '..timeinfo..' | ⇒ 0 | ⚡ 0% | ⤠ 0% | ⏳ na | ⤻ na', footer.footer_text.text) end) @@ -159,9 +176,10 @@ describe("Readerfooter module", function() local readerui = ReaderUI:new{ document = DocumentRegistry:openDocument(sample_pdf), } + local footer = readerui.view.footer readerui.view.footer:updateFooter() - local timeinfo = readerui.view.footer.textGeneratorMap.time() - assert.are.same('1 / 2 | '..timeinfo..' | => 1 | B:0% | R:50% | TB: na | TC: na', + local timeinfo = readerui.view.footer.textGeneratorMap.time(footer) + assert.are.same('1 / 2 | '..timeinfo..' | ⇒ 1 | ⚡ 0% | ⤠ 50% | ⏳ na | ⤻ na', readerui.view.footer.footer_text.text) end) @@ -178,8 +196,8 @@ describe("Readerfooter module", function() footer:addToMainMenu(fake_menu) footer:resetLayout() footer:updateFooter() - local timeinfo = footer.textGeneratorMap.time() - assert.are.same('1 / 2 | '..timeinfo..' | => 1 | B:0% | R:50% | TB: na | TC: na', + local timeinfo = footer.textGeneratorMap.time(footer) + assert.are.same('1 / 2 | '..timeinfo..' | ⇒ 1 | ⚡ 0% | ⤠ 50% | ⏳ na | ⤻ na', footer.footer_text.text) -- disable show all at once, page progress should be on the first @@ -187,36 +205,36 @@ describe("Readerfooter module", function() assert.are.same('1 / 2', footer.footer_text.text) -- disable page progress, time should follow - tapFooterMenu(fake_menu, "Current page") + tapFooterMenu(fake_menu, "Current page".." (/)") assert.are.same(timeinfo, footer.footer_text.text) -- disable time, page left should follow - tapFooterMenu(fake_menu, "Current time") - assert.are.same('=> 1', footer.footer_text.text) + tapFooterMenu(fake_menu, "Current time".." (⌚)") + assert.are.same('⇒ 1', footer.footer_text.text) -- disable page left, battery should follow - tapFooterMenu(fake_menu, "Pages left in chapter") - assert.are.same('B:0%', footer.footer_text.text) + tapFooterMenu(fake_menu, "Pages left in chapter".." (⇒)") + assert.are.same('⚡ 0%', footer.footer_text.text) -- disable battery, percentage should follow - tapFooterMenu(fake_menu, "Battery status") - assert.are.same('R:50%', footer.footer_text.text) + tapFooterMenu(fake_menu, "Battery status".." (⚡)") + assert.are.same('⤠ 50%', footer.footer_text.text) -- disable percentage, book time to read should follow - tapFooterMenu(fake_menu, "Progress percentage") - assert.are.same('TB: na', footer.footer_text.text) + tapFooterMenu(fake_menu, "Progress percentage".." (⤠)") + assert.are.same('⏳ na', footer.footer_text.text) -- disable book time to read, chapter time to read should follow - tapFooterMenu(fake_menu, "Book time to read") - assert.are.same('TC: na', footer.footer_text.text) + tapFooterMenu(fake_menu, "Book time to read".." (⏳)") + assert.are.same('⤻ na', footer.footer_text.text) -- disable chapter time to read, text should be empty - tapFooterMenu(fake_menu, "Chapter time to read") + tapFooterMenu(fake_menu, "Chapter time to read".." (⤻)") assert.are.same('', footer.footer_text.text) -- reenable chapter time to read, text should be chapter time to read - tapFooterMenu(fake_menu, "Chapter time to read") - assert.are.same('TC: na', footer.footer_text.text) + tapFooterMenu(fake_menu, "Chapter time to read".." (⤻)") + assert.are.same('⤻ na', footer.footer_text.text) end) it("should rotate through different modes", function() @@ -265,20 +283,20 @@ describe("Readerfooter module", function() local footer = readerui.view.footer local horizontal_margin = Screen:scaleBySize(10)*2 footer:updateFooter() - assert.is.same(357, footer.text_width) + assert.is.same(352, footer.text_width) assert.is.same(600, footer.progress_bar.width + footer.text_width + horizontal_margin) - assert.is.same(223, footer.progress_bar.width) + assert.is.same(228, footer.progress_bar.width) local old_screen_getwidth = Screen.getWidth Screen.getWidth = function() return 900 end footer:resetLayout() - assert.is.same(357, footer.text_width) + assert.is.same(352, footer.text_width) assert.is.same(900, footer.progress_bar.width + footer.text_width + horizontal_margin) - assert.is.same(523, footer.progress_bar.width) + assert.is.same(528, footer.progress_bar.width) Screen.getWidth = old_screen_getwidth end) @@ -292,12 +310,12 @@ describe("Readerfooter module", function() } local footer = readerui.view.footer footer:onPageUpdate(1) - assert.are.same(215, footer.progress_bar.width) - assert.are.same(365, footer.text_width) + assert.are.same(220, footer.progress_bar.width) + assert.are.same(360, footer.text_width) footer:onPageUpdate(100) - assert.are.same(183, footer.progress_bar.width) - assert.are.same(397, footer.text_width) + assert.are.same(188, footer.progress_bar.width) + assert.are.same(392, footer.text_width) end) it("should support chapter markers", function() @@ -493,15 +511,15 @@ describe("Readerfooter module", function() local fake_menu = {setting = {}} footer:addToMainMenu(fake_menu) - assert.are.same('1 / 2 | => 1', footer.footer_text.text) + assert.are.same('1 / 2 | ⇒ 1', footer.footer_text.text) -- remove mode from footer text - tapFooterMenu(fake_menu, "Pages left in chapter") + tapFooterMenu(fake_menu, "Pages left in chapter".." (⇒)") assert.are.same('1 / 2', footer.footer_text.text) -- add mode to footer text - tapFooterMenu(fake_menu, "Progress percentage") - assert.are.same('1 / 2 | R:50%', footer.footer_text.text) + tapFooterMenu(fake_menu, "Progress percentage".." (⤠)") + assert.are.same('1 / 2 | ⤠ 50%', footer.footer_text.text) end) it("should initialize text mode in all_at_once mode", function() @@ -545,21 +563,21 @@ describe("Readerfooter module", function() assert.is.same(true, footer.has_no_mode) assert.is.same(0, footer.text_width) - tapFooterMenu(fake_menu, "Progress percentage") - assert.are.same('R:0%', footer.footer_text.text) + tapFooterMenu(fake_menu, "Progress percentage".." (⤠)") + assert.are.same('⤠ 0%', footer.footer_text.text) assert.is.same(false, footer.has_no_mode) assert.is.same(footer.footer_text:getSize().w + footer.text_left_margin, footer.text_width) - tapFooterMenu(fake_menu, "Progress percentage") + tapFooterMenu(fake_menu, "Progress percentage".." (⤠)") assert.is.same(true, footer.has_no_mode) -- test in all at once mode - tapFooterMenu(fake_menu, "Progress percentage") + tapFooterMenu(fake_menu, "Progress percentage".." (⤠)") tapFooterMenu(fake_menu, "Show all at once") assert.is.same(false, footer.has_no_mode) - tapFooterMenu(fake_menu, "Progress percentage") + tapFooterMenu(fake_menu, "Progress percentage".." (⤠)") assert.is.same(true, footer.has_no_mode) - tapFooterMenu(fake_menu, "Progress percentage") + tapFooterMenu(fake_menu, "Progress percentage".." (⤠)") assert.is.same(false, footer.has_no_mode) end) diff --git a/spec/unit/util_spec.lua b/spec/unit/util_spec.lua index 68b62d037..3d9706da1 100644 --- a/spec/unit/util_spec.lua +++ b/spec/unit/util_spec.lua @@ -401,6 +401,51 @@ describe("util module", function() end) end) + describe("secondsToHClock()", function() + it("should convert seconds to 0'00'' format", function() + assert.is_equal("0'", + util.secondsToHClock(0, true)) + assert.is_equal("0'", + util.secondsToHClock(29, true)) + assert.is_equal("1'", + util.secondsToHClock(60, true)) + end) + it("should round seconds to minutes in 0h00' format", function() + assert.is_equal("1'", + util.secondsToHClock(89, true)) + assert.is_equal("2'", + util.secondsToHClock(90, true)) + assert.is_equal("2'", + util.secondsToHClock(110, true)) + assert.is_equal("2'", + util.secondsToHClock(120, true)) + assert.is_equal("1h00", + util.secondsToHClock(3600, true)) + assert.is_equal("1h00", + util.secondsToHClock(3599, true)) + assert.is_equal("1h00", + util.secondsToHClock(3570, true)) + assert.is_equal("59'", + util.secondsToHClock(3569, true)) + assert.is_equal("10h01", + util.secondsToHClock(36060, true)) + end) + it("should convert seconds to 0h00'00'' format", function() + assert.is_equal("0''", + util.secondsToHClock(0)) + assert.is_equal("1'00''", + util.secondsToHClock(60)) + assert.is_equal("1'29''", + util.secondsToHClock(89)) + assert.is_equal("1'30''", + util.secondsToHClock(90)) + assert.is_equal("1'50''", + util.secondsToHClock(110)) + assert.is_equal("2'00''", + util.secondsToHClock(120)) + end) + end) + describe("urlEncode() and urlDecode", function() it("should encode string", function() assert.is_equal("Secret_Password123", util.urlEncode("Secret_Password123"))