diff --git a/frontend/ui/elements/common_settings_menu_table.lua b/frontend/ui/elements/common_settings_menu_table.lua index a6ac579ed..4486f26c6 100644 --- a/frontend/ui/elements/common_settings_menu_table.lua +++ b/frontend/ui/elements/common_settings_menu_table.lua @@ -102,6 +102,7 @@ common_settings.time = { end, callback = function() G_reader_settings:saveSetting("duration_format", "classic") + UIManager:broadcastEvent(Event:new("UpdateFooter", true, true)) end, }, { @@ -116,6 +117,7 @@ common_settings.time = { end, callback = function() G_reader_settings:saveSetting("duration_format", "modern") + UIManager:broadcastEvent(Event:new("UpdateFooter", true, true)) end, }, } @@ -566,6 +568,7 @@ common_settings.screenshot = { local Screenshoter = require("ui/widget/screenshoter") Screenshoter:chooseFolder() end, + keep_menu_open = true, } return common_settings diff --git a/frontend/ui/elements/menu_keyboard_layout.lua b/frontend/ui/elements/menu_keyboard_layout.lua index c4f346db8..3ec286b65 100644 --- a/frontend/ui/elements/menu_keyboard_layout.lua +++ b/frontend/ui/elements/menu_keyboard_layout.lua @@ -1,17 +1,70 @@ local CheckButton = require("ui/widget/checkbutton") +local CheckMark = require("ui/widget/checkmark") +local Device = require("device") local FFIUtil = require("ffi/util") +local Font = require("ui/font") local Language = require("ui/language") +local Size = require("ui/size") +local TextWidget = require("ui/widget/textwidget") local UIManager = require("ui/uimanager") local VirtualKeyboard = require("ui/widget/virtualkeyboard") +local Screen = Device.screen +local T = require("ffi/util").template local dbg = require("dbg") +local logger = require("logger") local util = require("util") local _ = require("gettext") local input_dialog, check_button_bold, check_button_border, check_button_compact +-- Returns a string with all selected keyboard layouts (comma separated) and +-- the count of the selectecd layouts. +-- If compact is set, only the abbreviations and the count are returned. +local function getActivatedKeyboards(compact) + local keyboard_layouts = G_reader_settings:readSetting("keyboard_layouts", {}) + local activated_keyboards = {} + for lang, dummy in FFIUtil.orderedPairs(VirtualKeyboard.lang_to_keyboard_layout) do + if util.arrayContains(keyboard_layouts, lang) then + if compact then + table.insert(activated_keyboards, lang) + else + table.insert(activated_keyboards, Language:getLanguageName(lang)) + end + end + end + if #activated_keyboards == 0 then + logger.dbg("menu_keyboard_layout: use default keyboard") + if compact then + return VirtualKeyboard:getKeyboardLayout(), 1 + else + return Language:getLanguageName(VirtualKeyboard:getKeyboardLayout()), 1 + end + end + return table.concat(activated_keyboards, ", "), #activated_keyboards +end + local sub_item_table = { { - text = _("Keyboard layout"), + text_func = function() + local activated_keyboards, nb_keyboards = getActivatedKeyboards() + local item_text = T(_("Keyboard layouts: %1"), activated_keyboards) + + -- get width of text + local tmp = TextWidget:new{ + text = item_text, + face = Font:getFace("cfont"), + } + local item_text_w = tmp:getSize().w + tmp:free() + local checked_widget = CheckMark:new{ -- for layout, to :getSize() + checked = true, + } + if item_text_w >= Screen:getWidth()- 2*Size.padding.default - checked_widget:getSize().w then + item_text = T(_("Keyboard layouts (%1)"), nb_keyboards) + end + + return item_text + end, sub_item_table = {}, }, { @@ -25,12 +78,12 @@ local sub_item_table = { separator = true, }, { - text = _("Keyboard font size"), + text = _("Keyboard settings"), keep_menu_open = true, - callback = function() + callback = function(touchmenu_instance) input_dialog = require("ui/widget/inputdialog"):new{ title = _("Keyboard font size"), - input = tostring(G_reader_settings:readSetting("keyboard_key_font_size") or 22), + input = tostring(G_reader_settings:readSetting("keyboard_key_font_size", VirtualKeyboard.default_label_size)), input_hint = "(16 - 30)", buttons = { { @@ -53,6 +106,7 @@ local sub_item_table = { input_dialog._input_widget:onCloseKeyboard() input_dialog._input_widget:initKeyboard() input_dialog:onShowKeyboard() + if touchmenu_instance then touchmenu_instance:updateItems() end end end, }, @@ -104,18 +158,18 @@ local sub_item_table = { for lang, keyboard_layout in FFIUtil.orderedPairs(VirtualKeyboard.lang_to_keyboard_layout) do table.insert(sub_item_table[1].sub_item_table, { text_func = function() - local text = Language:getLanguageName(lang) + local text = Language:getLanguageName(lang) .. " (" .. string.sub(lang, 1, 2) ..")" if G_reader_settings:readSetting("keyboard_layout_default") == lang then text = text .. " ★" end return text end, checked_func = function() - local keyboard_layouts = G_reader_settings:readSetting("keyboard_layouts") or {} + local keyboard_layouts = G_reader_settings:readSetting("keyboard_layouts", {}) return util.arrayContains(keyboard_layouts, lang) end, callback = function() - local keyboard_layouts = G_reader_settings:readSetting("keyboard_layouts") or {} + local keyboard_layouts = G_reader_settings:readSetting("keyboard_layouts", {}) local layout_index = util.arrayContains(keyboard_layouts, lang) if layout_index then table.remove(keyboard_layouts, layout_index) diff --git a/frontend/ui/widget/keyboardlayoutdialog.lua b/frontend/ui/widget/keyboardlayoutdialog.lua index a6a384c41..966fb4e56 100644 --- a/frontend/ui/widget/keyboardlayoutdialog.lua +++ b/frontend/ui/widget/keyboardlayoutdialog.lua @@ -63,7 +63,7 @@ function KeyboardLayoutDialog:init() local buttons = {} local radio_buttons = {} - local keyboard_layouts = G_reader_settings:readSetting("keyboard_layouts") or {} + local keyboard_layouts = G_reader_settings:readSetting("keyboard_layouts", {}) self.keyboard_state.force_current_layout = true for k, _ in FFIUtil.orderedPairs(self.parent.keyboard.lang_to_keyboard_layout) do local text = Language:getLanguageName(k) .. " (" .. string.sub(k, 1, 2) .. ")" diff --git a/frontend/ui/widget/virtualkeyboard.lua b/frontend/ui/widget/virtualkeyboard.lua index 869d6361a..0d0d25d17 100644 --- a/frontend/ui/widget/virtualkeyboard.lua +++ b/frontend/ui/widget/virtualkeyboard.lua @@ -28,6 +28,8 @@ local keyboard_state = { force_current_layout = false, -- Set to true to get/set current layout (instead of default layout) } +local DEFAULT_LABEL_SIZE = 22 + local VirtualKeyPopup local VirtualKey = InputContainer:new{ @@ -51,7 +53,7 @@ local VirtualKey = InputContainer:new{ } function VirtualKey:init() - local label_font_size = G_reader_settings:readSetting("keyboard_key_font_size") or 22 + local label_font_size = G_reader_settings:readSetting("keyboard_key_font_size", DEFAULT_LABEL_SIZE) self.face = Font:getFace("infont", label_font_size) self.bold = G_reader_settings:isTrue("keyboard_key_bold") if self.keyboard.symbolmode_keys[self.label] ~= nil then @@ -65,7 +67,7 @@ function VirtualKey:init() self.callback = function () local current = G_reader_settings:readSetting("keyboard_layout") local default = G_reader_settings:readSetting("keyboard_layout_default") - local keyboard_layouts = G_reader_settings:readSetting("keyboard_layouts") or {} + local keyboard_layouts = G_reader_settings:readSetting("keyboard_layouts", {}) local next_layout = nil local layout_index = util.arrayContains(keyboard_layouts, current) if layout_index then @@ -284,7 +286,7 @@ function VirtualKey:genKeyboardLayoutKeyChars() "northwest", "west", } - local keyboard_layouts = G_reader_settings:readSetting("keyboard_layouts") or {} + local keyboard_layouts = G_reader_settings:readSetting("keyboard_layouts", {}) local key_chars = { { label = "🌐", }, @@ -663,7 +665,7 @@ function VirtualKeyPopup:init() } }, } - self.tap_interval_override = G_reader_settings:readSetting("ges_tap_interval_on_keyboard") or 0 + self.tap_interval_override = G_reader_settings:readSetting("ges_tap_interval_on_keyboard", 0) self.tap_interval_override = TimeVal:new{ usec = self.tap_interval_override } if Device:hasDPad() then @@ -738,6 +740,7 @@ local VirtualKeyboard = FocusManager:new{ layout = {}, height = nil, + default_label_size = DEFAULT_LABEL_SIZE, bordersize = Size.border.default, padding = 0, key_padding = Size.padding.small, @@ -786,7 +789,7 @@ function VirtualKeyboard:init() self.min_layer = keyboard.min_layer self.max_layer = keyboard.max_layer self:initLayer(self.keyboard_layer) - self.tap_interval_override = G_reader_settings:readSetting("ges_tap_interval_on_keyboard") or 0 + self.tap_interval_override = G_reader_settings:readSetting("ges_tap_interval_on_keyboard", 0) self.tap_interval_override = TimeVal:new{ usec = self.tap_interval_override } if Device:hasDPad() then self.key_events.PressKey = { {"Press"}, doc = "select key" } @@ -802,7 +805,7 @@ end function VirtualKeyboard:getKeyboardLayout() if G_reader_settings:isFalse("keyboard_remember_layout") and not keyboard_state.force_current_layout then local lang = G_reader_settings:readSetting("keyboard_layout_default") - or G_reader_settings:readSetting("keyboard_layout") or "en" + or G_reader_settings:readSetting("keyboard_layout", "en") G_reader_settings:saveSetting("keyboard_layout", lang) end return G_reader_settings:readSetting("keyboard_layout") or G_reader_settings:readSetting("language") diff --git a/frontend/util.lua b/frontend/util.lua index f05f74c87..51ff1e46d 100644 --- a/frontend/util.lua +++ b/frontend/util.lua @@ -147,8 +147,9 @@ end ---- @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'' +---- @treturn string clock string in the form of 1h30'10'' or 1h30m10s function util.secondsToHClock(seconds, withoutSeconds, hmsFormat) + local SECONDS_SYMBOL = "\"" seconds = tonumber(seconds) if seconds == 0 then if withoutSeconds then @@ -161,86 +162,63 @@ function util.secondsToHClock(seconds, withoutSeconds, hmsFormat) if hmsFormat then return T(_("%1s"), "0") else - return "0''" + return "0" .. SECONDS_SYMBOL end end elseif seconds < 60 then if withoutSeconds and seconds < 30 then if hmsFormat then + -- @translators This is the 'm' for minute, like in 30m30s. This is a duration. return T(_("%1m"), "0") else return "0'" end elseif withoutSeconds and seconds >= 30 then if hmsFormat then + -- @translators This is the 'm' for minute, like in 30m30s. This is a duration. return T(_("%1m"), "1") else return "1'" end else if hmsFormat then + -- @translators This is the 'm' for minute and 's' for seconds, like in 30m30s. This is a duration. return T(_("%1m%2s"), "0", string.format("%02d", seconds)) else - return "0'" .. string.format("%02d", seconds) .. "''" + return "0'" .. string.format("%02d", seconds) .. SECONDS_SYMBOL end end else - local round = withoutSeconds and require("optmath").round or passthrough - local hours = string.format("%d", seconds / 3600) - local mins = string.format("%02d", round(seconds % 3600 / 60)) + local time_string = util.secondsToClock(seconds, withoutSeconds) if withoutSeconds then - if mins == "60" then - mins = string.format("%02d", 0) - hours = string.format("%d", hours + 1) - end - if hours == "0" then - -- We can optimize out the % 3600 since the branch ensures we're < than 3600 - mins = string.format("%d", round(seconds / 60)) - if hmsFormat then - return T(_("%1m"), mins) - else - return mins .. "'" - end - end - -- @translators This is the 'h' for hour, like in 1h30. This is a duration. - return T(_("%1h%2"), hours, mins) + time_string = time_string .. ":" + end + if hmsFormat then + -- @translators This is the 'h' for hour, like in 1h30m30s. This is a duration. + time_string = time_string:gsub(":", _("h"), 1) + -- @translators This is the 'm' for minute, like in 1h30m30s. This is a duration. + time_string = time_string:gsub(":", _("m"), 1) + -- @translators This is the 's' for second, like in 1h30m30s. This is a duration. + time_string = time_string:gsub("00" .. _("h"), "") -- delete leading "00h" + time_string = time_string:gsub("^0", "") -- delete leading "0" + return withoutSeconds and time_string or (time_string .. _("s")) else - local secs = string.format("%02d", seconds % 60) - if hours == "0" then - mins = string.format("%d", round(seconds / 60)) - if hmsFormat then - -- @translators This is the 'm' for minute and the 's' for second, like in 1m30s. This is a duration. - return T(_("%1m%2s"), mins, secs) - else - return mins .. "'" .. secs .. "''" - end - end - if hmsFormat then - if secs == "00" then - -- @translators This is the 'h' for hour and the 'm' for minute, like in 1h30m. This is a duration. - return T(_("%1h%2m"), hours, mins) - else - -- @translators This is the 'h' for hour, the 'm' for minute and the 's' for second, like in 1h30m30s. This is a duration. - 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 + -- @translators This is the 'h' for hour, like in 1h30m30s. This is a duration. + time_string = time_string:gsub(":", _("h"), 1) + time_string = time_string:gsub(":", "'", 1) + time_string = time_string:gsub("00" .. _("h"), "") -- delete leading "00h" + time_string = time_string:gsub("^0", "") -- delete leading "0" + return withoutSeconds and time_string or (time_string .. SECONDS_SYMBOL) end end end --- Converts seconds to a clock type (classic or modern), based on the given format preference --- "Classic" format calls secondsToClock, and "Modern" format calls secondsToHClock ----- @string Either "modern" for 1h30' or "classic" for 1:30 ----- @bool withoutSeconds if true 1h30' or 1:30, if false 1h30'10'' or 1:30:10 ----- @bool hmsFormat, modern format only, if true format 1h30m10s ----- @treturn string clock string in the specific format of 1h30', 1h30'10'' or 1:30' +---- @string Either "modern" for 1h30'10" or "classic" for 1:30:10 +---- @bool withoutSeconds if true 1h30' or 1h30m, if false 1h30'10" or 1h30m10s +---- @bool hmsFormat, modern format only, if true format 1h30m or 1h30m10s +---- @treturn string clock string in the specific format of 1h30', 1h30'10" resp. 1h30m, 1h30m10s function util.secondsToClockDuration(format, seconds, withoutSeconds, hmsFormat) if format == "modern" then return util.secondsToHClock(seconds, withoutSeconds, hmsFormat) diff --git a/plugins/autosuspend.koplugin/main.lua b/plugins/autosuspend.koplugin/main.lua index cf6df9925..d2963583e 100644 --- a/plugins/autosuspend.koplugin/main.lua +++ b/plugins/autosuspend.koplugin/main.lua @@ -15,6 +15,7 @@ local TimeVal = require("ui/timeval") local UIManager = require("ui/uimanager") local WidgetContainer = require("ui/widget/container/widgetcontainer") local logger = require("logger") +local util = require("util") local _ = require("gettext") local T = require("ffi/util").template @@ -171,8 +172,17 @@ end function AutoSuspend:addToMainMenu(menu_items) menu_items.autosuspend = { sorting_hint = "device", - text = _("Autosuspend timeout"), - callback = function() + text_func = function() + if self.auto_suspend_timeout_seconds then + local duration_format = G_reader_settings:readSetting("duration_format", "classic") + return T(_("Autosuspend timeout: %1"), + util.secondsToClockDuration(duration_format, self.auto_suspend_timeout_seconds, true)) + else + return _("Autosuspend timeout") + end + end, + keep_menu_open = true, + callback = function(touchmenu_instance) local InfoMessage = require("ui/widget/infomessage") local SpinWidget = require("ui/widget/spinwidget") local autosuspend_spin = SpinWidget:new { @@ -192,6 +202,7 @@ function AutoSuspend:addToMainMenu(menu_items) }) self:_unschedule() self:_start() + if touchmenu_instance then touchmenu_instance:updateItems() end end } UIManager:show(autosuspend_spin) @@ -200,8 +211,17 @@ function AutoSuspend:addToMainMenu(menu_items) if not (Device:canPowerOff() or Device:isEmulator()) then return end menu_items.autoshutdown = { sorting_hint = "device", - text = _("Autoshutdown timeout"), - callback = function() + text_func = function() + if self.autoshutdown_timeout_seconds then + local duration_format = G_reader_settings:readSetting("duration_format", "classic") + return T(_("Autoshutdown timeout: %1"), + util.secondsToClockDuration(duration_format, self.autoshutdown_timeout_seconds, true)) + else + return _("Autoshutdown timeout") + end + end, + keep_menu_open = true, + callback = function(touchmenu_instance) local InfoMessage = require("ui/widget/infomessage") local SpinWidget = require("ui/widget/spinwidget") local autosuspend_spin = SpinWidget:new { @@ -226,6 +246,7 @@ function AutoSuspend:addToMainMenu(menu_items) }) self:_unschedule() self:_start() + if touchmenu_instance then touchmenu_instance:updateItems() end end } UIManager:show(autosuspend_spin) diff --git a/plugins/autoturn.koplugin/main.lua b/plugins/autoturn.koplugin/main.lua index 1d44ece54..d770e4ada 100644 --- a/plugins/autoturn.koplugin/main.lua +++ b/plugins/autoturn.koplugin/main.lua @@ -120,7 +120,7 @@ end function AutoTurn:addToMainMenu(menu_items) menu_items.autoturn = { sorting_hint = "navi", - text_func = function() return self:_enabled() and T(_("Autoturn (%1 s)"), self.autoturn_sec) + text_func = function() return self:_enabled() and T(_("Autoturn: %1 s"), self.autoturn_sec) or _("Autoturn") end, checked_func = function() return self:_enabled() end, callback = function(menu) diff --git a/spec/unit/util_spec.lua b/spec/unit/util_spec.lua index a2c9a0466..66d10bcda 100644 --- a/spec/unit/util_spec.lua +++ b/spec/unit/util_spec.lua @@ -520,15 +520,15 @@ describe("util module", function() util.secondsToHClock(110, true)) assert.is_equal("2'", util.secondsToHClock(120, true)) - assert.is_equal("1h00", + assert.is_equal("1h00'", util.secondsToHClock(3600, true)) - assert.is_equal("1h00", + assert.is_equal("1h00'", util.secondsToHClock(3599, true)) - assert.is_equal("1h00", + assert.is_equal("1h00'", util.secondsToHClock(3570, true)) assert.is_equal("59'", util.secondsToHClock(3569, true)) - assert.is_equal("10h01", + assert.is_equal("10h01'", util.secondsToHClock(36060, true)) end) it("should round seconds to minutes in 0h00m format", function() @@ -538,27 +538,27 @@ describe("util module", function() util.secondsToHClock(90, true, true)) assert.is_equal("2m", util.secondsToHClock(110, true, true)) - assert.is_equal("1h00", + assert.is_equal("1h00m", util.secondsToHClock(3600, true, true)) - assert.is_equal("1h00", + assert.is_equal("1h00m", util.secondsToHClock(3599, true, true)) assert.is_equal("59m", util.secondsToHClock(3569, true, true)) - assert.is_equal("10h01", + assert.is_equal("10h01m", util.secondsToHClock(36060, true, true)) end) it("should convert seconds to 0h00'00'' format", function() - assert.is_equal("0''", + assert.is_equal("0\"", util.secondsToHClock(0)) - assert.is_equal("1'00''", + assert.is_equal("1'00\"", util.secondsToHClock(60)) - assert.is_equal("1'29''", + assert.is_equal("1'29\"", util.secondsToHClock(89)) - assert.is_equal("1'30''", + assert.is_equal("1'30\"", util.secondsToHClock(90)) - assert.is_equal("1'50''", + assert.is_equal("1'50\"", util.secondsToHClock(110)) - assert.is_equal("2'00''", + assert.is_equal("2'00\"", util.secondsToHClock(120)) end) end) @@ -577,7 +577,7 @@ describe("util module", function() it("should pass along withoutSeconds", function() assert.is_equal("10h01m30s", util.secondsToClockDuration("modern", 36090, false, true)) - assert.is_equal("10h02", + assert.is_equal("10h02m", util.secondsToClockDuration("modern", 36090, true, true)) assert.is_equal("10:01:30", util.secondsToClockDuration("classic", 36090, false)) @@ -585,11 +585,13 @@ describe("util module", function() util.secondsToClockDuration("classic", 36090, true)) end) it("should pass along hmsFormat for modern format", function() - assert.is_equal("10h01'30''", + assert.is_equal("10h01'30\"", util.secondsToClockDuration("modern", 36090)) assert.is_equal("10h01m30s", util.secondsToClockDuration("modern", 36090, false, true)) - assert.is_equal("10h02", + assert.is_equal("10h02m", + util.secondsToClockDuration("modern", 36090, true, true)) + assert.is_equal("10h02'", util.secondsToClockDuration("modern", 36090, true, false)) assert.is_equal("10:01:30", util.secondsToClockDuration("classic", 36090, false, true))