-
-
Save sebdelsol/494c897446deefe6995d8e38adc0a4b6 to your computer and use it in GitHub Desktop.
| -- **MOVED to https://github.com/sebdelsol/KOReader.patches** | |
| -- KOReader userpatch to show info in the file manager title bar | |
| -- based on https://gist.github.com/hius07/c53bc1ed00e0490cb1a0709c5ed6e735#file-2-fm-title-info-lua | |
| -- Menu added in the File browser menu (1st icon) to change all the settings and rearrange the items in the title bar | |
| -- Items added: Custom text, Brightness Level, Warmth Level, Up time, Time spent awake, Time in suspend | |
| -- Settings added: Auto refresh clock, Custom separator, Number of spaces around separator, Show wifi when disabled, Show frontlight when off, Show path | |
| -- Fix screen rotation (path was disappearing) | |
| -- Arrange items reorders the items the menu | |
| local BD = require("ui/bidi") | |
| local Device = require("device") | |
| local FileManager = require("apps/filemanager/filemanager") | |
| local FileManagerMenu = require("apps/filemanager/filemanagermenu") | |
| local FileManagerMenuOrder = require("ui/elements/filemanager_menu_order") | |
| local InputDialog = require("ui/widget/inputdialog") | |
| local NetworkMgr = require("ui/network/manager") | |
| local SortWidget = require("ui/widget/sortwidget") | |
| local SpinWidget = require("ui/widget/spinwidget") | |
| local UIManager = require("ui/uimanager") | |
| local datetime = require("datetime") | |
| local time = require("ui/time") | |
| local T = require("ffi/util").template | |
| local _ = require("gettext") | |
| local Screen = Device.screen | |
| local logger = require("logger") | |
| -- Title bar config | |
| local separators = { | |
| bar = "|", | |
| bullet = "•", | |
| dot = "·", | |
| en_dash = "-", | |
| em_dash = "—", | |
| none = "", | |
| } | |
| local config_default = { | |
| -- items | |
| show = { | |
| wifi = true, | |
| memory = false, | |
| storage = false, | |
| custom_text = false, | |
| clock = true, | |
| battery = true, | |
| frontlight = false, | |
| frontlight_warmth = false, | |
| up_time = false, | |
| awake_time = false, | |
| suspend_time = false, | |
| }, | |
| -- items order | |
| order = { | |
| "wifi", | |
| "memory", | |
| "storage", | |
| "custom_text", | |
| "clock", | |
| "battery", | |
| "frontlight", | |
| "frontlight_warmth", | |
| "up_time", | |
| "awake_time", | |
| "suspend_time", | |
| }, | |
| -- settings | |
| custom_text = "KOReader", | |
| separator = "dot", | |
| separator_space = 1, | |
| separator_custom = "*", | |
| show_path = true, | |
| auto_refresh_clock = true, | |
| wifi_show_disabled = false, | |
| frontlight_show_off = true, | |
| bold = false, | |
| } | |
| local function load_and_update_config() | |
| local config = G_reader_settings:readSetting("filemanager_title_bar", config_default) | |
| local updated = false | |
| local function compare_and_update_config(config_to_browse, config_to_compare) | |
| for setting, setting_value in pairs(config_to_browse) do | |
| if type(setting_value) ~= "table" then -- only the settings | |
| if config_to_compare[setting] == nil then -- missing ? | |
| updated = true | |
| if config_to_compare == config then -- missing in config: add it | |
| config[setting] = setting_value | |
| else -- missing in config_default: remove it | |
| config[setting] = nil | |
| end | |
| end | |
| end | |
| end | |
| for item, item_value in pairs(config_to_browse.show) do | |
| if config_to_compare.show[item] == nil then -- missing ? | |
| updated = true | |
| if config_to_compare == config then -- missing in config: add it | |
| config.show[item] = item_value | |
| table.insert(config.order, item) | |
| else -- missing in config_default: remove it | |
| config.show[item] = nil | |
| for i, _item in ipairs(config.order) do | |
| if _item == item then | |
| table.remove(config.order, i) | |
| break | |
| end | |
| end | |
| end | |
| end | |
| end | |
| end | |
| compare_and_update_config(config, config_default) | |
| compare_and_update_config(config_default, config) | |
| if updated then logger.info("Updated title bar config", config) end | |
| separators.custom = config.separator_custom | |
| return config | |
| end | |
| local config = load_and_update_config() | |
| -- Title bar update | |
| local genItemText = { | |
| custom_text = function() return config.custom_text end, | |
| clock = function() return datetime.secondsToHour(os.time(), G_reader_settings:isTrue("twelve_hour_clock")) end, | |
| wifi = function() return NetworkMgr:isWifiOn() and "" or (config.wifi_show_disabled and "") end, | |
| frontlight_warmth = function() | |
| if Device:hasNaturalLight() then | |
| local prefix = "💡" | |
| local powerd = Device:getPowerDevice() | |
| if powerd:isFrontlightOn() then | |
| local warmth = powerd:frontlightWarmth() | |
| if warmth then return (prefix .. "%d%%"):format(warmth) end | |
| else | |
| return config.frontlight_show_off and T(_("%1Off"), prefix) | |
| end | |
| end | |
| end, | |
| frontlight = function() | |
| if Device:hasFrontlight() then | |
| local prefix = "☼" | |
| local powerd = Device:getPowerDevice() | |
| if powerd:isFrontlightOn() then | |
| if Device:isCervantes() or Device:isKobo() then | |
| return (prefix .. "%d%%"):format(powerd:frontlightIntensity()) | |
| else | |
| return (prefix .. "%d"):format(powerd:frontlightIntensity()) | |
| end | |
| else | |
| return config.frontlight_show_off and T(_("%1Off"), prefix) | |
| end | |
| end | |
| end, | |
| battery = function() | |
| if Device:hasBattery() then | |
| local powerd = Device:getPowerDevice() | |
| local batt_lvl = powerd:getCapacity() | |
| local batt_symbol = powerd:getBatterySymbol(powerd:isCharged(), powerd:isCharging(), batt_lvl) | |
| local text = BD.wrap(batt_symbol) .. BD.wrap(batt_lvl .. "%") | |
| if Device:hasAuxBattery() and powerd:isAuxBatteryConnected() then | |
| local aux_batt_lvl = powerd:getAuxCapacity() | |
| local aux_batt_symbol = | |
| powerd:getBatterySymbol(powerd:isAuxCharged(), powerd:isAuxCharging(), aux_batt_lvl) | |
| text = text .. " " .. BD.wrap("+") .. BD.wrap(aux_batt_symbol) .. BD.wrap(aux_batt_lvl .. "%") | |
| end | |
| return text | |
| end | |
| end, | |
| up_time = function(self) | |
| local SystemStat = self:_getSystemStat() | |
| if SystemStat then | |
| local uptime = time.boottime_or_realtime_coarse() - SystemStat.start_monotonic_time | |
| return "⏻" .. datetime.secondsToClockDuration("modern", time.to_s(uptime), true, false, true) -- ⏽ | |
| end | |
| end, | |
| awake_time = function(self) | |
| local SystemStat = self:_getSystemStat() | |
| if SystemStat and (Device:canSuspend() or Device:canStandby()) then | |
| local uptime = time.boottime_or_realtime_coarse() - SystemStat.start_monotonic_time | |
| local suspend = Device:canSuspend() and Device.total_suspend_time or 0 | |
| local standby = Device:canStandby() and Device.total_standby_time or 0 | |
| local awake = uptime - suspend - standby | |
| return "☀️" .. datetime.secondsToClockDuration("modern", time.to_s(awake), true, false, true) -- ☀☉⚡☀️ | |
| end | |
| end, | |
| suspend_time = function(self) | |
| local SystemStat = self:_getSystemStat() | |
| if SystemStat and Device:canSuspend() then | |
| local suspend = Device.total_suspend_time | |
| return "⏾" .. datetime.secondsToClockDuration("modern", time.to_s(suspend), true, false, true) -- ⏾💤😴⏸️ | |
| end | |
| end, | |
| storage = function(self) | |
| local SystemStat = self:_getSystemStat() | |
| if SystemStat then | |
| SystemStat.kv_pairs = {} | |
| SystemStat:appendStorageInfo() | |
| return SystemStat.kv_pairs[3][2] -- available storage | |
| end | |
| end, | |
| memory = function() | |
| local statm = io.open("/proc/self/statm", "r") | |
| if statm then | |
| local _, rss = statm:read("*number", "*number") | |
| statm:close() | |
| return rss and ("%d"):format(math.floor(rss / 256)) | |
| end | |
| end, | |
| } | |
| -- get SystemStat | |
| function FileManager:_getSystemStat() | |
| if self.systemstat then | |
| local userpatch = require("userpatch") | |
| return userpatch.getUpValue(self.systemstat.addToMainMenu, "SystemStat") | |
| end | |
| end | |
| -- handle close : need to remove schedule update for clock auto refresh | |
| local orig_FileManager_onClose = FileManager.onClose | |
| FileManager.onClose = function(self) | |
| orig_FileManager_onClose(self) | |
| UIManager:unschedule(self.updateTitleBarTitle) | |
| end | |
| -- handle screen rotation | |
| local orig_FileManager_onSetRotationMode = FileManager.onSetRotationMode | |
| FileManager.onSetRotationMode = function(self, mode) | |
| orig_FileManager_onSetRotationMode(self, mode) | |
| self:updateTitleBarTitle() | |
| end | |
| -- redraw the title bar | |
| function FileManager:updateTitleBarTitle() | |
| if self.title_bar == nil then return end | |
| local titlebar_texts = {} | |
| for _, item in ipairs(config.order) do | |
| if config.show[item] then | |
| local text = genItemText[item](self) | |
| if text then table.insert(titlebar_texts, text) end | |
| end | |
| end | |
| -- logger.info("FileManager:updateTitleBarTitle CALLED") | |
| local font_has_changed | |
| local not_bold_font = self.title_bar.info_text_face | |
| if config.bold then | |
| font_has_changed = self.title_bar.title_face == not_bold_font | |
| else | |
| font_has_changed = self.title_bar.title_face ~= not_bold_font | |
| end | |
| if font_has_changed then | |
| if config.bold then | |
| self.title_bar.title_face = nil | |
| self.title_bar.bottom_v_padding = self._title_bar_bottom_v_padding_saved | |
| else | |
| self.title_bar.title_face = not_bold_font | |
| self.title_bar.bottom_v_padding = self._title_bar_bottom_v_padding_saved + Screen:scaleBySize(5) | |
| end | |
| self.title_bar:clear() | |
| self.title_bar:init() | |
| end | |
| local spaces = string.rep(" ", config.separator_space) | |
| local seperator = spaces .. (separators[config.separator] or "") .. spaces | |
| self.title_bar:setTitle(table.concat(titlebar_texts, seperator)) | |
| self:updateTitleBarPath(config.show_path and self._title_bar_path_saved or "") | |
| -- autorefresh time | |
| UIManager:unschedule(self.updateTitleBarTitle) | |
| if config.show.clock and config.auto_refresh_clock then | |
| UIManager:scheduleIn(61 - tonumber(os.date("%S")), self.updateTitleBarTitle, self) | |
| end | |
| end | |
| FileManager.onNetworkConnected = FileManager.updateTitleBarTitle | |
| FileManager.onNetworkDisconnected = FileManager.updateTitleBarTitle | |
| FileManager.onCharging = FileManager.updateTitleBarTitle | |
| FileManager.onNotCharging = FileManager.updateTitleBarTitle | |
| FileManager.onResume = FileManager.updateTitleBarTitle | |
| FileManager.onTimeFormatChanged = FileManager.updateTitleBarTitle | |
| FileManager.onFrontlightStateChanged = FileManager.updateTitleBarTitle | |
| function FileManager:onPathChanged(path) | |
| -- logger.info("FileManager:onPathChanged CALLED") | |
| if not self._title_bar_bottom_v_padding_saved then | |
| self._title_bar_bottom_v_padding_saved = self.title_bar.bottom_v_padding | |
| end | |
| self._title_bar_path_saved = path | |
| self:updateTitleBarTitle() -- updateTitleBarPath done in updateTitleBarTitle | |
| end | |
| -- Title bar menu | |
| function FileManagerMenu:_title_bar_input_text(touchmenu_instance, title, input, onChanged) | |
| local text_dialog | |
| text_dialog = InputDialog:new { | |
| title = title, | |
| input = input, | |
| buttons = { | |
| { | |
| { | |
| text = _("Cancel"), | |
| id = "close", | |
| callback = function() UIManager:close(text_dialog) end, | |
| }, | |
| { | |
| text = _("Set"), | |
| is_enter_default = true, | |
| callback = function() | |
| onChanged(text_dialog:getInputText()) | |
| UIManager:close(text_dialog) | |
| touchmenu_instance:updateItems() | |
| self.ui:updateTitleBarTitle() | |
| end, | |
| }, | |
| }, | |
| }, | |
| } | |
| UIManager:show(text_dialog) | |
| text_dialog:onShowKeyboard() | |
| end | |
| -- Separators | |
| local setting_menu_texts | |
| function FileManagerMenu:_set_title_bar_separator_space(touchmenu_instance) | |
| local spin_widget = SpinWidget:new { | |
| title_text = setting_menu_texts.separator_space(true), | |
| value = config.separator_space, | |
| value_min = 1, | |
| value_step = 1, | |
| value_max = 5, | |
| callback = function(spin) | |
| config.separator_space = spin.value | |
| touchmenu_instance:updateItems() | |
| self.ui:updateTitleBarTitle() | |
| end, | |
| } | |
| UIManager:show(spin_widget) | |
| end | |
| function FileManagerMenu:_set_title_bar_custom_separator_text(touchmenu_instance) | |
| self:_title_bar_input_text(touchmenu_instance, _("Enter a custom separator"), separators.custom, function(text) | |
| config.separator_custom = text | |
| separators.custom = text | |
| end) | |
| end | |
| local separator_menu_texts = { | |
| dot = _("Dot"), | |
| bullet = _("Bullet"), | |
| en_dash = _("En dash"), | |
| em_dash = _("Em dash"), | |
| bar = _("Vertical bar"), | |
| none = _("No separator"), | |
| custom = function(concise) return concise and _("Custom separator") or _("Custom separator (long-press to edit)") end, | |
| } | |
| local separators_menu_help_text_funcs = { | |
| custom = FileManagerMenu._set_title_bar_custom_separator_text, | |
| } | |
| local separators_order = { | |
| "dot", | |
| "bullet", | |
| "en_dash", | |
| "em_dash", | |
| "bar", | |
| "custom", | |
| "none", | |
| } | |
| local function get_separator_menu_texts(separator, concise) | |
| text = separator_menu_texts[separator] | |
| if type(text) == "function" then text = text(concise) end | |
| local spaces = string.rep(" ", config.separator_space) | |
| local seperator = separators[config.separator] or "" | |
| return T(text .. " '" .. spaces .. "%1" .. spaces .. "'", separators[separator]) | |
| end | |
| function FileManagerMenu:_get_title_bar_separators_submenu() | |
| local items = {} | |
| for _, separator in ipairs(separators_order) do | |
| local help_text_func = separators_menu_help_text_funcs[separator] | |
| table.insert(items, { | |
| text_func = function() return get_separator_menu_texts(separator) end, | |
| help_text_func = help_text_func | |
| and function(touchmenu_instance) help_text_func(self, touchmenu_instance) end, | |
| checked_func = function() return config.separator == separator end, | |
| callback = function(touchmenu_instance) | |
| config.separator = separator | |
| touchmenu_instance:updateItems() | |
| self.ui:updateTitleBarTitle() | |
| end, | |
| }) | |
| end | |
| items[#items].separator = true | |
| table.insert(items, { | |
| text_func = setting_menu_texts.separator_space, | |
| keep_menu_open = true, | |
| callback = function(touchmenu_instance) self:_set_title_bar_separator_space(touchmenu_instance) end, | |
| }) | |
| return items | |
| end | |
| -- items | |
| function FileManagerMenu:_set_title_bar_custom_text(touchmenu_instance) | |
| self:_title_bar_input_text( | |
| touchmenu_instance, | |
| _("Enter a custom text"), | |
| config.custom_text or "", | |
| function(text) config.custom_text = text end | |
| ) | |
| end | |
| local item_menu_texts = { | |
| wifi = _("Wifi"), | |
| memory = _("Memory"), | |
| storage = _("Storage"), | |
| clock = _("Clock"), | |
| battery = _("Battery"), | |
| frontlight = _("Brightness level"), | |
| frontlight_warmth = _("Warmth level"), | |
| up_time = _("Up time"), | |
| awake_time = _("Time spent awake"), | |
| suspend_time = _("Time in suspend"), | |
| custom_text = function(concise) | |
| return concise and _("Custom text") or T(_("Custom text (long-press to edit): '%1'"), config.custom_text) | |
| end, | |
| } | |
| local item_menu_help_texts = { | |
| memory = _("RAM used, MiB"), | |
| storage = _("Free storage, requires SystemStat plugin"), | |
| custom_text = FileManagerMenu._set_title_bar_custom_text, | |
| } | |
| function FileManagerMenu:_title_bar_arrange_items(item_table_rebuild) | |
| return { | |
| text = _("Arrange title bar items"), | |
| keep_menu_open = true, | |
| enabled_func = function() | |
| local show_count = 0 -- count shown items | |
| for _, item in ipairs(config.order) do | |
| show_count = show_count + (config.show[item] and 1 or 0) | |
| if show_count >= 1 then return true end | |
| end | |
| return false | |
| end, | |
| callback = function(touchmenu_instance) | |
| local item_table = {} | |
| for _, item in ipairs(config.order) do | |
| local text = item_menu_texts[item] | |
| table.insert(item_table, { | |
| text = type(text) == "function" and text(true) or text, | |
| orig_item = item, | |
| dim = not config.show[item], | |
| }) | |
| end | |
| local sort_item | |
| sort_item = SortWidget:new { | |
| title = _("Arrange title bar items"), | |
| item_table = item_table, | |
| callback = function() | |
| for i, item in ipairs(item_table) do | |
| config.order[i] = item.orig_item | |
| end | |
| if item_table_rebuild then -- rebuild the item_table, so the items in the menu are reordered | |
| touchmenu_instance.item_table = item_table_rebuild() | |
| touchmenu_instance:updateItems() | |
| end | |
| self.ui:updateTitleBarTitle() | |
| UIManager:setDirty(nil, "ui") | |
| end, | |
| } | |
| UIManager:show(sort_item) | |
| end, | |
| } | |
| end | |
| function FileManagerMenu:_get_title_bar_item(item) | |
| local text = item_menu_texts[item] | |
| local help_text = item_menu_help_texts[item] | |
| return { | |
| text = type(text) == "string" and text, | |
| text_func = type(text) == "function" and function() return text() end, | |
| help_text = type(help_text) == "string" and help_text, | |
| help_text_func = type(help_text) == "function" | |
| and function(touchmenu_instance) help_text(self, touchmenu_instance) end, | |
| checked_func = function() return config.show[item] end, | |
| callback = function(touchmenu_instance) | |
| config.show[item] = not config.show[item] | |
| touchmenu_instance:updateItems() | |
| self.ui:updateTitleBarTitle() | |
| end, | |
| } | |
| end | |
| -- settings | |
| setting_menu_texts = { -- already declared above | |
| auto_refresh_clock = _("Auto refresh clock"), | |
| show_path = _("Show file browser path"), | |
| wifi_show_disabled = _("Show wifi status even when disabled"), | |
| frontlight_show_off = _("Show frontlight when off"), | |
| bold = _("Bold font"), | |
| separator = function() return T(_("Item separator: %1"), get_separator_menu_texts(config.separator, true)) end, | |
| custom_text = function() return T(_("Custom text: '%1'"), config.custom_text) end, | |
| separator_space = function(concise) | |
| return concise and _("Number of spaces around separator") | |
| or T(_("Number of spaces around separator: %1"), config.separator_space) | |
| end, | |
| } | |
| local setting_menu_callback = { | |
| custom_text = FileManagerMenu._set_title_bar_custom_text, | |
| separator_space = FileManagerMenu._set_title_bar_separator_space, | |
| } | |
| local setting_submenu_items = { | |
| separator = FileManagerMenu._get_title_bar_separators_submenu, | |
| } | |
| local setting_menu_enable_func = { | |
| auto_refresh_clock = function() return config.show.clock end, | |
| wifi_show_disabled = function() return config.show.wifi end, | |
| frontlight_show_off = function() return config.show.frontlight or config.show.frontlight_warmth end, | |
| custom_text = function() return config.show.custom_text end, | |
| } | |
| local setting_menu_order = { | |
| "bold", | |
| "wifi_show_disabled", | |
| "frontlight_show_off", | |
| "auto_refresh_clock", | |
| "show_path", | |
| "custom_text", | |
| "separator", | |
| } | |
| function FileManagerMenu:_get_title_bar_setting(setting) | |
| local text = setting_menu_texts[setting] | |
| local submenu = setting_submenu_items[setting] | |
| local enabled_func = setting_menu_enable_func[setting] | |
| local callback_func = setting_menu_callback[setting] | |
| return { | |
| text = type(text) == "string" and text, | |
| text_func = type(text) == "function" and function() return text() end, | |
| enabled_func = enabled_func and function() return enabled_func() end, | |
| checked_func = not (submenu or callback_func) and function() return config[setting] end, | |
| callback = not submenu and function(touchmenu_instance) | |
| if callback_func then | |
| callback_func(self, touchmenu_instance) | |
| else | |
| config[setting] = not config[setting] | |
| touchmenu_instance:updateItems() | |
| end | |
| self.ui:updateTitleBarTitle() | |
| end, | |
| keep_menu_open = callback_func ~= nil, | |
| sub_item_table = submenu and submenu(self), | |
| } | |
| end | |
| -- Patch title bar menu | |
| local orig_FileManagerMenu_setUpdateItemTable = FileManagerMenu.setUpdateItemTable | |
| FileManagerMenu.setUpdateItemTable = function(self) | |
| orig_FileManagerMenu_setUpdateItemTable(self) | |
| local buttons = FileManagerMenuOrder["KOMenu:menu_buttons"] | |
| for i, button in ipairs(buttons) do | |
| if button == "filemanager_settings" then | |
| logger.info("Add title bar options in the file manager settings menu") | |
| local setting_table = {} | |
| for _, setting in ipairs(setting_menu_order) do | |
| table.insert(setting_table, self:_get_title_bar_setting(setting)) | |
| end | |
| local sub_item_table_func | |
| sub_item_table_func = function() | |
| local _table = { | |
| { | |
| text = _("Configure title bar"), | |
| sub_item_table = setting_table, | |
| }, | |
| self:_title_bar_arrange_items(sub_item_table_func), | |
| } | |
| _table[#_table].separator = true | |
| for _, item in ipairs(config.order) do | |
| table.insert(_table, self:_get_title_bar_item(item)) | |
| end | |
| return _table | |
| end | |
| table.insert(self.tab_item_table[i], 1, { | |
| text = _("Title bar"), | |
| separator = true, | |
| sub_item_table_func = sub_item_table_func, | |
| }) | |
| break | |
| end | |
| end | |
| end |
you're right. It's done. Tx.
Is there a way to change the font?
I've to check that. It uses the default UI font. Should it uses its own font, whatever the UI one is ?
If you want to change all the UI fonts, which would be a more consistent solution UX wise, you can use this user patch.
Nice, thankyou for the repo. There is something similar for https://github.com/kiwidude68/calibre_plugins who compiled all his calibre plugins in one repo.
Maybe create your own thread at https://www.mobileread.com/forums/forumdisplay.php?f=276 for more user visibility/feedback?
with something like "My custom user patch collection" title?
Also please do add any foss license file to the repo.
Oh I always forget about that. Tx for reminding me
I've tried to reproduce the bug (on a Kindle as well). In the file manager, I toggled on the title bar with the clock visible and enabled Auto refresh clock. However, I wasn't able to reproduce the bug. By the way, the clock placement doesn't align with the title bar: It should be centered.
Is there a way to change the font?
There this new user patch : 2-ui-font.lua that allows to change the UI font.

Small correction "Show file
managerbrowser path".In the UI they prefer to call it file browser everywhere. koreader/koreader#13305 (comment) e.g. go to "Main > Help > Menu search" and check search result with keyword manager vs browser.