Skip to content

[Presets] add new presets.lua module and dictionary presets - #13774

Merged
Frenzie merged 41 commits into
koreader:masterfrom
Commodore64user:dict-presets
Jun 20, 2025
Merged

Frenzie merged 41 commits into
koreader:masterfrom
Commodore64user:dict-presets

Conversation

@Commodore64user

@Commodore64user Commodore64user commented May 12, 2025 •

Copy link
Copy Markdown
Member

what's new

This pull request introduces a new unified preset management system for KOReader modules, centralising the creation, loading, updating, and deletion of presets. The changes refactor existing preset handling in ReaderFooter so that any module can use the new Presets module, simplifying code and improving maintainability. Additionally, we add preset functionality to ReaderDictionary and new dispatcher actions are added for loading dictionary and footer presets.

  • Added a new Presets module (frontend/ui/presets.lua) that provides a standardised interface for managing presets across modules, including methods for creating, loading, updating, and deleting presets. It also supports generating menu items and integrating with Dispatcher.
  • Added the option to ReaderDictionary to use the new Presets module for managing dictionary presets, replacing custom logic with standardised methods (createModulePreset, genModulePresetMenuTable, etc.).
  • Refactored ReaderFooter to leverage the Presets module for footer presets, significantly reducing the complexity of preset-related methods.
  • Added new dispatcher actions for loading dictionary and footer presets (load_dictionary_preset and load_footer_preset), enabling gesture or hotkey-based preset switching.
  • Reordering of the dictionary menu. See screenshots below to preview new look.

screenshots

expand for more screenshots

related issues


This change is Reviewable

@Commodore64user

Copy link
Copy Markdown
Member Author

I took the liberty to re-arrange some of these settings, here is a little draft for all to comment on, both presets and priority running side-by-side, left is what it looks like on traditional e-ink, right on android/emulator

should I combine the external dicts into one as well? as I did for "lookup history"

@poire-z

poire-z commented May 12, 2025

Copy link
Copy Markdown
Contributor

No problem with me with the menu reorg.
(No time to look at the code.)

@mergen3107

Copy link
Copy Markdown
Contributor

should I combine the external dicts into one as well?

I don't think it is worth adding another menu just for two items. I would vote for three and more items, otherwise it is more of an obstacle (extra tap) than help

@Commodore64user

Commodore64user commented May 12, 2025 •

Copy link
Copy Markdown
Member Author

would anyone have a clue as to why, status bar presets (without me changing anything yet) crash when one tries to load them on the emulator but NOT when doing it from kindle, both running Version: v2025.04-57-gbb4dafa7e_2025-05-11

./luajit: frontend/apps/reader/modules/readerfooter.lua:2465: attempt to index field 'mode_index' (a nil value)
stack traceback:
        frontend/apps/reader/modules/readerfooter.lua:2465: in function 'applyFooterMode'
        frontend/apps/reader/modules/readerfooter.lua:2036: in function 'loadPreset'
        frontend/apps/reader/modules/readerfooter.lua:1950: in function 'callback'
        frontend/ui/widget/touchmenu.lua:923: in function 'onMenuSelect'
        frontend/ui/widget/touchmenu.lua:217: in function 'handleEvent'
        frontend/ui/widget/container/inputcontainer.lua:266: in function 'handleEvent'
        frontend/ui/widget/container/widgetcontainer.lua:83: in function 'propagateEvent'
        frontend/ui/widget/container/widgetcontainer.lua:101: in function 'handleEvent'
        frontend/ui/widget/container/widgetcontainer.lua:83: in function 'propagateEvent'
        frontend/ui/widget/container/widgetcontainer.lua:101: in function 'handleEvent'
        frontend/ui/widget/container/widgetcontainer.lua:83: in function 'propagateEvent'
        ...
        frontend/ui/widget/focusmanager.lua:451: in function 'handleEvent'
        frontend/ui/widget/container/widgetcontainer.lua:83: in function 'propagateEvent'
        frontend/ui/widget/container/widgetcontainer.lua:101: in function 'handleEvent'
        frontend/ui/uimanager.lua:896: in function 'sendEvent'
        frontend/ui/uimanager.lua:53: in function '__default__'
        frontend/ui/uimanager.lua:1423: in function 'handleInputEvent'
        frontend/ui/uimanager.lua:1523: in function 'handleInput'
        frontend/ui/uimanager.lua:1567: in function 'run'
        reader.lua:265: in main chunk
        [C]: at 0x010a505890

edit: initiating mode_index etc (like in init) solves the crash, but it begs the question. why does it only fail on the emulator? it seems to be an emulator only issue so will keep the loadPreset method alone for now. As far as it goes, I think this is my favourite kind of problem, someone else's ;)

@Commodore64user Commodore64user changed the title [presets_menu] Add dictionary presets [Presets] add new preset.lua module and dictionary presets May 13, 2025
@hius07 hius07 mentioned this pull request May 13, 2025
Comment thread frontend/ui/presets.lua Outdated
@Commodore64user

This comment was marked as outdated.

@Frenzie

Frenzie commented May 13, 2025

Copy link
Copy Markdown
Member

edit: initiating mode_index etc (like in init) solves the crash, but it begs the question. why does it only fail on the emulator? it seems to be an emulator only issue so will keep the loadPreset method alone for now. As far as it goes, I think this is my favourite kind of problem, someone else's ;)

The problem will be that you changed the data structure somewhere along the way during development, or you didn't change it as such but accidentally wrote what's effectively some nonsense to the settings file.

@Commodore64user

Copy link
Copy Markdown
Member Author

I thought so at first, then i created new ones and still kaboom. Not to worry though, hius07 has already been heavily on the case.

@Commodore64user

Copy link
Copy Markdown
Member Author

This must have been how Alfred Nobel felt when he discovered his creation was being used for evil... In good faith, I have added a method to cycle through presets; but heed my warning, it will not make it to ReaderFooter as I still vehemently oppose that idea. Should you, dear reader, wish to shoot thyself in the foot, I have made it significantly easier for you. Nevertheless, I shan’t hand over the gun that shall deliver the wounding shot.

@Commodore64user
Commodore64user force-pushed the dict-presets branch 2 times, most recently from b1634a5 to 163d6e5 Compare May 15, 2025 15:19
add dependency to ReaderFooter and use it

remove unused dependencies

add documentation and move event handler to presets.lua

add missing dependency

fixes to loadPresets

add message to succesful preset loading from touchmenu
Comment thread frontend/ui/presets.lua Outdated
Comment on lines +199 to +202
if not presets or not next(presets) then
Notification:notify(_("No presets available"), Notification.SOURCE_ALWAYS_SHOW)
return false
end

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello all, I am losing my mind trying to understand why this particular bit of code is running twice (note, the bottom notification doesn't do the same).

Reader_bram-stoker_dracula epub_p79_2025-05-15_203340

    if not presets or not next(presets) then
        local logger = require("logger")
        logger.dbg("About to show no presets notification")
        Notification:notify(_("No presets available"), Notification.SOURCE_ALWAYS_SHOW)
        logger.dbg("After showing no presets notification")
        logger.dbg("AAA No presets available for " .. preset_key)
        return false
    end
DEBUG key event => code: 1073742048 (Ctrl), value: 1, time: 1400855.826972 
DEBUG key event => code: 113 (Q), value: 1, time: 1400856.165875 
DEBUG AutoSuspend: onInputEvent 
DEBUG AutoTurn: onInputEvent 
DEBUG Executing actions for hotkey:  alt_plus_q  in  Reader  with events:  {
  cycle_dictionary_preset = true
} --[[table: 0x0122c60750]] 
DEBUG ReaderDictionary:onCycleDictionaryPresets() called
DEBUG About to show no presets notification
DEBUG show widget: table: 0x01249ce560 
DEBUG setDirty nil from widget table: 0x01249ce560 w/ NO region; dithering: nil 
DEBUG setDirty via a func from widget table: 0x01249ce560 
DEBUG After showing no presets notification 
DEBUG AAA No presets available for dict_presets 
DEBUG ReaderDictionary:onCycleDictionaryPresets() called 
DEBUG About to show no presets notification 
DEBUG show widget: table: 0x01245080c0 
DEBUG setDirty nil from widget table: 0x01245080c0 w/ NO region; dithering: nil 
DEBUG setDirty via a func from widget table: 0x01245080c0 
DEBUG After showing no presets notification 
DEBUG AAA No presets available for dict_presets 
DEBUG painting widget: table: 0x01249ce560 
DEBUG Found font: NotoSansCJKsc-Regular.otf in ./fonts/noto/NotoSansCJKsc-Regular.otf 
DEBUG painting widget: table: 0x01245080c0 
DEBUG _refresh: Enqueued ui update for region 171 5 197 53 dithering: false 
DEBUG _refresh: Enqueued ui update for region 171 5 197 106 dithering: false 
DEBUG refresh on logical rectangle 197x106+171+5 
DEBUG key event => code: 113 (Q), value: 0, time: 1400856.245468 
DEBUG AutoSuspend: onInputEvent 
DEBUG AutoTurn: onInputEvent 
DEBUG key event => code: 1073742048 (Ctrl), value: 0, time: 1400856.456355 

things of interest

  • only one hotkey action being executed
  • two different widget addresses created:
show widget: table: 0x01249ce560
show widget: table: 0x01245080c0
  • two notifications shown, does not happen with any other notification added in this PR
  • removing the SOURCE_ALWAYS_SHOW does not change anything.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Twice cycle in the dispatcher/hotkey action?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But then, when we do have actions to cycle through, only one notification is fired. This is really wierd.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with presets we only run once, only one widget address show widget: table: 0x011f2c90e8

DEBUG key event => code: 1073742048 (Ctrl), value: 1, time: 1520575.126891 
DEBUG key event => code: 113 (Q), value: 1, time: 1520575.897105 
DEBUG AutoSuspend: onInputEvent 
DEBUG AutoTurn: onInputEvent 
DEBUG Executing actions for hotkey:  alt_plus_q  in  Reader  with events:  {
  cycle_dictionary_preset = true
} --[[table: 0x011d8c6ce8]] 
DEBUG show widget: table: 0x011f2c90e8 
DEBUG setDirty nil from widget table: 0x011f2c90e8 w/ NO region; dithering: nil 
DEBUG setDirty via a func from widget table: 0x011f2c90e8 
DEBUG painting widget: table: 0x011f2c90e8 
DEBUG Found font: NotoSansCJKsc-Regular.otf in ./fonts/noto/NotoSansCJKsc-Regular.otf 
DEBUG _refresh: Enqueued ui update for region 151 5 238 53 dithering: false 
DEBUG refresh on logical rectangle 238x53+151+5 
DEBUG key event => code: 113 (Q), value: 0, time: 1520575.901003 
DEBUG AutoSuspend: onInputEvent 
DEBUG AutoTurn: onInputEvent 
DEBUG key event => code: 1073742048 (Ctrl), value: 0, time: 1520575.994968 
DEBUG close widget: table: 0x011f2c90e8 

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DEBUG cyclePresets called from: 
DEBUG stack traceback:
        frontend/ui/presets.lua:143: in function 'handleEvent'
        frontend/ui/widget/container/widgetcontainer.lua:83: in function 'propagateEvent'
        frontend/ui/widget/container/widgetcontainer.lua:101: in function 'handleEvent'
        frontend/ui/uimanager.lua:896: in function 'sendEvent'
        frontend/dispatcher.lua:1217: in function 'execute'
        plugins/hotkeys.koplugin/main.lua:99: in function <plugins/hotkeys.koplugin/main.lua:89>
        [C]: in function 'pcall'
        frontend/pluginloader.lua:62: in function 'handleEvent'
        frontend/ui/widget/container/widgetcontainer.lua:83: in function 'propagateEvent'
        frontend/ui/widget/container/widgetcontainer.lua:101: in function 'handleEvent'
        frontend/ui/uimanager.lua:896: in function 'sendEvent'
        frontend/ui/uimanager.lua:53: in function '__default__'
        frontend/ui/uimanager.lua:1423: in function 'handleInputEvent'
        frontend/ui/uimanager.lua:1523: in function 'handleInput'
        frontend/ui/uimanager.lua:1567: in function 'run'
        reader.lua:265: in main chunk
        [C]: at 0x010c1a4890 

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so it all comes down to return false, the return false propagates the event and runs it another time... mmm return true solves that problem. sigh..

text = _("Download dictionaries"),
sub_item_table_func = function() return self:_genDownloadDictionariesMenu() end,
text = _("Dictionary presets"),
help_text = _("This feature enables you to group (e.g., per language) dictionaries as presets. You can then quickly switch between these presets to change the dictionaries used for lookups. \n\n Note: No other settings are stored in the presets, neither are the actual dictionaries, only a reference to the dictionaries."),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No spaces around the \n\n please. Also an editorial suggestion.

Suggested change
help_text = _("This feature enables you to group (e.g., per language) dictionaries as presets. You can then quickly switch between these presets to change the dictionaries used for lookups. \n\n Note: No other settings are stored in the presets, neither are the actual dictionaries, only a reference to the dictionaries."),
help_text = _("This feature allows you to organize dictionaries into presets (for example, by language). You can quickly switch between these presets to change which dictionaries are used for lookups.\n\nNote: presets only store a reference to the dictionaries, no other settings."),

end
end
UIManager:show(InfoMessage:new{
text = T(_("Some dictionaries from this preset have been deleted or are no longer available (%1 missing): \n\n• %2"),

@Frenzie Frenzie May 16, 2025 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we can avoid sticking that • %2 in this string at all? (I.e., simple concatenation at the end.) If not, no space before the \n\n.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't you think it would be more useful (as a user) to be told straight up which dictionaries are missing instead of having to guess? The idea is also to encourage the user to either "update" the preset or to find out what went wrong with dict X.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Meaning:

T(_("Some dictionaries from this preset have been deleted or are no longer available (%1 missing):"), whatever) .. "\n\n• %2"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also if that %1 missing is a number it should be ngettext.

@Commodore64user Commodore64user May 16, 2025 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but I specifically wrote it so it wouldn't need ngettext, it works for one or many...

edit: or just remove the number

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it works for one or many...

In English. But yes, the less you bother translators with the better.

re-arrange menu order

@Frenzie's string suggestions
@Commodore64user
Commodore64user force-pushed the dict-presets branch 2 times, most recently from f8bcb11 to 5b50c62 Compare May 18, 2025 11:40
Comment thread frontend/ui/presets.lua Outdated
Comment on lines +275 to +280
if module.ui.hotkeys:updatePresetReference(update_key_for_module, preset_name, new_name) then -- luacheck: ignore 542
-- Hotkeys plugin manages its own 'updated' flag.
end
end

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't you just run that without the if? This doesn't really look like a valid ignore use case.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough, will change it

Comment thread frontend/ui/presets.lua Outdated
return
end
if Presets.validateAndSavePreset(new_name, preset_obj, presets[preset_name]) then
presets[preset_name] = nil

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How we usually rename a key in a table?

t[new_key] = t[old_key]
t[old_key] = nil

You break this two connected lines, hiding the saving into other function.
More calls, broken logic. Unnecessary passing of arguments (like dialog_instance).
(Name duplication check should be separated from the caller callback)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's so simple:

text = _("Save"),
callback = function()
local new_name = input_dialog:getInputText()
if new_name == "" or new_name == old_name then return end
if ReadCollection.coll[new_name] then
UIManager:show(InfoMessage:new{
text = T(_("Collection already exists: %1"), new_name),
})
else
UIManager:close(input_dialog)
editCallback(new_name)
end
end,

function FileManagerCollection:renameCollection(item)
local editCallback = function(name)
self.updated_collections[name] = true
ReadCollection:renameCollection(item.name, name)
self.coll_list.item_table[item.idx].text = name
self.coll_list.item_table[item.idx].name = name
self:updateCollListItemTable()
end
self:editCollectionName(editCallback, item.name)
end

(I just rename the menu items. But the preset list is sorted so the menu should be rebuilt, yes)

Comment thread frontend/ui/widget/touchmenu.lua Outdated
local sub_item_table = item.sub_item_table
if item.sub_item_table_func then
sub_item_table = item.sub_item_table_func()
sub_item_table = item.sub_item_table_func(self)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it still needed?


function ReaderDictionary:onShowDictionaryLookup()
local buttons = {}
local preset_names = Presets:getPresets(self.preset_obj)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function.

Comment thread frontend/ui/widget/dictquicklookup.lua Outdated
},
},
}
local preset_names = Presets:getPresets(self.ui.dictionary.preset_config)

@hius07 hius07 Jun 19, 2025 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function.
preset_obj

Comment thread frontend/ui/widget/dictquicklookup.lua Outdated
align = "left",
text = preset_name,
callback = function()
self.ui.dictionary:loadPreset(self.ui.dictionary.preset_config.presets[preset_name], true)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

preset_obj

end
-- then enable only those from the preset that still exist
for _, ifo in ipairs(available_ifos) do
for _, enabled_name in ipairs(preset.enabled_dict_names) do

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid loops doubling and nested loops it's better to use hash table instead of array:

function ReaderDictionary:buildPreset()
    local preset = { enabled_dict_names = {} }
    for _, name in ipairs(self.enabled_dict_names) do
        preset.enabled_dict_names[name] = true
    end
    return preset
end

It's not more expensive, tableDeepCopy iterates over the table in the same way.

And then:

local dicts_disabled, valid_enabled_names = {}, {}
for _, ifo in ipairs(available_ifos) do
    if preset.enabled_dict_names[ifo.name] then
        table.insert(valid_enabled_names, ifo.name)
    else
        dicts_disabled[ifo.file] = true
    end
end

@hius07

hius07 commented Jun 19, 2025 •

Copy link
Copy Markdown
Member

Code duplication:

UIManager:close(dialog_instance)

UIManager:close(dialog_instance)

You can avoid arg passing and close the input dialog once right near
on_success_callback(entered_preset_name, input_dialog)

-- Show a message if any dictionaries from the preset are missing.
if not skip_notification and #preset.enabled_dict_names > #valid_enabled_names then
local missing_dicts = {}
for _, preset_name in ipairs(preset.enabled_dict_names) do

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

preset.enabled_dict_names is now a hash table.
util.tableSize instead of #
pairs instead of ipairs

Comment thread frontend/dispatcher.lua Outdated
toggle_status_bar = {category="none", event="ToggleFooterMode", title=_("Toggle status bar"), reader=true},
toggle_chapter_progress_bar = {category="none", event="ToggleChapterProgressBar", title=_("Toggle chapter progress bar"), reader=true},
load_dictionary_preset = {category="string", event="LoadDictionaryPreset", title=_("Load dictionary preset"), args_func=ReaderDictionary.getPresets, reader=true},
cycle_dictionary_preset = {category="none", event="CycleDictionaryPresets", title=_("Cycle through dictionary presets"), reader=true,},

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can look up dictionaries from the file browser. Maybe allow these actions as well?

Comment thread frontend/ui/widget/dictquicklookup.lua Outdated
@hius07

hius07 commented Jun 20, 2025

Copy link
Copy Markdown
Member

No more comments, thanks.

@Commodore64user
Commodore64user requested a review from poire-z June 20, 2025 11:27
@Frenzie Frenzie added this to the 2025.06 milestone Jun 20, 2025

@poire-z poire-z left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks ok.

end

function ReaderDictionary:loadPreset(preset, skip_notification)
if not preset.enabled_dict_names then return end

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this happen ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

under normal usage, probably not. it's more a safeguard if a preset gets corrupted or a user accidentally deletes the content.

Comment on lines +1569 to +1571
UIManager:show(InfoMessage:new{
text = _("Some dictionaries from this preset have been deleted or are no longer available:") .. "\n\n• " .. table.concat(missing_dicts, "\n• "),
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious: what's the procedure/steps for a user getting this message to get rid of it?

@Commodore64user Commodore64user Jun 20, 2025 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one off, pressing back or tapping outside of the widget.
longer term, (which I assume is what you a getting at here), you would need to add back the same dict or "update" the profile. preset.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

longer term, (which I assume is what you a getting at here)

Right.

you would need to add back the same dict or "update" the profile. preset.

That is this "update" I was wondering about. Ok, I go there, I just "update" and "ok" it ? It will clean it up from the old dict all by itself ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What?

It will run the build function again and not add that missing dict. Effectively removing it from the preset.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, that's what I was asking and the answer I was hoping for.
(It will not crash, or it will not bug because the dict does not exist, or keep it because it doesn't exist, etc...)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good

Comment thread frontend/ui/presets.lua Outdated
Comment on lines +42 to +44
self.preset_obj, -- preset object
_("Create new preset from current settings"), -- optional: custom text for UI menu
function() return self:hasValidSettings() end, -- optional: function to enable/disable creating presets

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(you might want to align the comments)
also probably: optional: function to enable/disable creating presets presets submenu

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(you might not ? :)

@Commodore64user Commodore64user Jun 20, 2025 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean? The function stops you from creating them not from accessing them. At least in the case of reader dict that’s the case

that function specifically enables/disables only the create button

Comment thread frontend/apps/reader/modules/readerdictionary.lua Outdated
Comment thread frontend/ui/widget/dictquicklookup.lua Outdated
@Frenzie

Frenzie commented Jun 20, 2025

Copy link
Copy Markdown
Member

Actually hold off on merging for a second, I still need to fix the docs.

Comment thread frontend/ui/presets.lua Outdated
@Frenzie
Frenzie merged commit 30499e3 into koreader:master Jun 20, 2025
@Frenzie Frenzie changed the title [Presets] add new preset.lua module and dictionary presets [Presets] add new presets.lua module and dictionary presets Jun 20, 2025
@Commodore64user
Commodore64user deleted the dict-presets branch June 20, 2025 22:11
0xstillb pushed a commit to 0xstillb/koreader-thai that referenced this pull request May 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

5 participants