Skip to content

Readerfont: Font test document with new fonts in current session on top#12088

Closed
jonnyl2 wants to merge 18 commits into
koreader:masterfrom
jonnyl2:fonttest
Closed

Readerfont: Font test document with new fonts in current session on top#12088
jonnyl2 wants to merge 18 commits into
koreader:masterfrom
jonnyl2:fonttest

Conversation

@jonnyl2

@jonnyl2 jonnyl2 commented Jun 25, 2024

Copy link
Copy Markdown
Contributor

Font test document lists new fonts on top, if any were loaded in the current session.

Adds a new menu entry in Font settings to generate a font test document for new fonts only.

However, the new menu entry should be conditional on there being new fonts in the current session, and I need help with that.

Some wording has been changed as well (details in commit notes).

Review by @poire-z kindly requested.


This change is Reviewable

jonnyl2 added 2 commits June 25, 2024 16:58
Need help with making new menu entry conditional on new fonts having been added the current session.

"Would you like" is a bit too formal for this context IMO.

"Some sample text" sounds like some random text rather than a predetermined sample.
Created similar function for new fonts only. Changed "read" to "view" (in both functions).
@mergen3107

Copy link
Copy Markdown
Contributor

How about fonts that have been removed? Do you think their font test pages should be kept or purged (with an option?)?

@poire-z

poire-z commented Jun 25, 2024

Copy link
Copy Markdown
Contributor

Not fond of that, it will be useful to you and 2 other people, and you'll often regret not being able to compare new fonts to old fonts.
If really needed, have it available on long-press on that menu item so to not bug users with a useless thingie.
You could also have an option or prompt to put new fonts at start if there are new fonts.
And the code should not be duplicated that much as you did, it could be a parameter to the function to pick all or only new fonts.

@Frenzie

Frenzie commented Jun 25, 2024

Copy link
Copy Markdown
Member

New fonts in current session? Is that a thing we support?

@poire-z

poire-z commented Jun 25, 2024

Copy link
Copy Markdown
Contributor

New fonts met at koreader startup are (optionally?) marked "new" and (optionally?) shown first.
On next koreader restrat, they are no longer considered new.

@Frenzie

Frenzie commented Jun 25, 2024

Copy link
Copy Markdown
Member

Ah right, that way.

@jonnyl2

jonnyl2 commented Jun 26, 2024

Copy link
Copy Markdown
Contributor Author

[poire-z] If really needed, have it available on long-press on that menu item so to not bug users with a useless thingie.

The idea was to have the menu entry only appear when new fonts were loaded in the given session, which I was asking for help with. Then the >99/100 times users have not installed any new fonts, the menu entry wouldn't be available and noone would be bothered by it. But I was having trouble setting up that condition. Is the table newly_added_fonts outside of the scope of the menu set-up function? If that was the issue, what would be the best way to access it? Via an intermediate function? Or making newly_added_fonts global where it is first defined? (Still curious from an educational perspective, although I will probably abandon this PR now.)

And the code should not be duplicated that much as you did, it could be a parameter to the function to pick all or only new fonts.

I was trying that route as well but found that the saving of relatively few lines of code was not worth the complication. Although it is likely I wasn't using the most efficient techniques.

@poire-z

poire-z commented Jun 26, 2024

Copy link
Copy Markdown
Contributor

But I was having trouble setting up that condition. Is the table newly_added_fonts outside of the scope of the menu set-up function? If that was the issue, what would be the best way to access it?

It's a module local variable (so, a kind of global variable inside the module), so it should be accessible from all the methods in readerfont.lua.
I think the problem is a ordering/timing problem: newly_added_fonts is only created later, after self:getFontSettingsTable() is called (both are called inside ReaderFont:setupFaceMenuTable(), but self:getFontSettingsTable() is called before self:sortFaceList(face_list) which build newly_added_fonts.
So, it would need some clever reordering/prebuilding, that I'd rather not think about :)
(The quick - but ugly as the building would not read naturally - solution could be to move this to later and use table.insert(self.face_table, 1, ...) to insert it at start:

table.insert(self.face_table, {
text = _("Font settings"),
sub_item_table = self:getFontSettingsTable(),
})

)

I was trying that route as well but found that the saving of relatively few lines of code was not worth the complication. Although it is likely I wasn't using the most efficient techniques.

It would be bothering from a maintenance stand point, needing us, if we change one function, to not forget to update the second similar function.
The solution would just have been, in the clone (new menu item or hold_callback) of:

table.insert(settings_table, {
text = _("Generate font test document"),
callback = function()
UIManager:show(ConfirmBox:new{
text = _("Would you like to generate an HTML document showing some sample text rendered with each available font?"),
ok_callback = function()
self:buildFontsTestDocument()
end,
})
end,
})

to use self:buildFontsTestDocument(true)
and update the target function to accept that new argument buildFontsTestDocument(only_new_font) - nil if not provided, true if provided) so it changes its behaviour only in the bits where it is required:
function ReaderFont:buildFontsTestDocument()

Then the >99/100 times users have not installed any new fonts

All in all, I think the simplest no-user-choice solution would be to keep that single menu item and function, and to create the sections for the newly fonts first, and later the old fonts. That way, you get them first when opening the sample epub - but you still can compare the text to the old fonts which are later in the book.
This can be the default behaviour or depending on the setting. It would just (dunno :)) need a copy/paste of:

if G_reader_settings:isTrue("font_menu_sort_by_recently_selected") then
return self.fonts_recently_selected
end
-- Otherwise, return face_list as we got it, alphabetically (as sorted by crengine),
-- but still with newly added fonts first
if next(newly_added_fonts) then
local move_idx = 1
for i=1, #face_list do
if newly_added_fonts[face_list[i]] then
table.insert(face_list, move_idx, table.remove(face_list, i))
move_idx = move_idx + 1
end
end
end

just after there:
local face_list = cre.getFontFaces()

with may be some small adaptations.

Looking at the above, I thought this was already what is happening - the last snippet gets the fonts already sorted with newest first (if there are new fonts). But testing that, it looks like it's not the case.
Oh, it's just a matter of:

--- a/frontend/apps/reader/modules/readerfont.lua
+++ b/frontend/apps/reader/modules/readerfont.lua
@@ -888,4 +888,5 @@ a { color: black; }
 ]], _("Available fonts test document"), _("AVAILABLE FONTS")))
     local face_list = cre.getFontFaces()
+    face_list = self:sortFaceList(face_list)
     f:write("<div style='margin: 2em'>\n")
     for _, font_name in ipairs(face_list) do

(Adding some cosmectics like appending "new" in the toc or the titles is probably possible.)

@jonnyl2 jonnyl2 marked this pull request as draft June 26, 2024 13:53
@jonnyl2

jonnyl2 commented Jul 1, 2024

Copy link
Copy Markdown
Contributor Author

@poire-z: Only the new fonts should be on top though, and everything else should still be in alphabetical order (not the recently selected order). So instead of just calling sortFaceList(face_list) I would copy your for-loop from 830-838 and append a " [NEW]" to each new font name (I tried the nerdfont icon but it didn't print correctly in the book):

So we'd get (starting from 888):

]], _("Available fonts test document"), _("AVAILABLE FONTS")))
    local face_list = cre.getFontFaces()
    if next(newly_added_fonts) then
        local move_idx = 1
        for i=1, #face_list do
            if newly_added_fonts[face_list[i]] then
				face_list[i] = face_list[i] .. " [NEW]" 
                table.insert(face_list, move_idx, table.remove(face_list, i))
                move_idx = move_idx + 1
            end
        end
    end

Questions:

  1. Any objections?
  2. Is it okay to duplicate this for-loop or should I make it into a function?

@poire-z

poire-z commented Jul 1, 2024

Copy link
Copy Markdown
Contributor
  1. No objection, looks fine to me
  2. It is ok, it is small (and you add "[NEW]", so it would make that function more clumsy with a param append_new_to_name :)) Just add a comment -- Sort alphabeticaly, with new fonts first (as done in sortFaceList())

@jonnyl2

jonnyl2 commented Jul 1, 2024

Copy link
Copy Markdown
Contributor Author

Thanks. And are you okay with the proposed wording changes? (Remove "Would you like"; change "read" to "view" [edit: "open" works as well].)

@poire-z

poire-z commented Jul 1, 2024

Copy link
Copy Markdown
Contributor

I'm fine with your wording changes. Still to be validated by our Style & Consistency Officer @Frenzie :)
(We may have a few "Would you like..." elsewhere.)

@jonnyl2

jonnyl2 commented Jul 1, 2024

Copy link
Copy Markdown
Contributor Author

No problem. There's no rush. And before I start updating the commits, I wanted to ask about something else I'd like to add (before you call it useless :) ) -- a 'Compact' version of the font test document, with just a short paragraph and no page breaks. I know one can replace the default one (and manually disable the page breaks), but I think it would be useful to have both. The current one that shows off everything the font has to offer, and a compact one to just quickly compare several fonts at once per screen page, e.g., using the lorem ipsum sample text with some bold and italics thrown in. It could be on long-press or an extra button on the confirmation dialog, so no extra menu entry. Thoughts? Yay or nay?

And one more thing; regarding the sorting of the font list in the menu: if the user selected to have recently selected fonts listed first, I think it would improve the UX if the current font would be listed first in the menu when the document is loaded. At the moment, the current font is often way back in the menu because it might have been a while ago when the font was selected last. And then when the user wants to select one of his top fonts, he first has to go back to page 1 in the menu list. So the idea would be that when a new CRE-doc is opened and the menu table is built, the currently selected font would be considered 'selected' at that moment and be moved to the top spot. Do you agree?

@poire-z

poire-z commented Jul 1, 2024

Copy link
Copy Markdown
Contributor

a compact one to just quickly compare several fonts at once per screen page, e.g., using the lorem ipsum sample text with some bold and italics thrown in. It could be on long-press or an extra button on the confirmation dialog, so no extra menu entry. Thoughts? Yay or nay?

Rather nay. It's shipping another sample file, and making it less obvious which one the user should edit, and adding uneeded complexity for an edge feature. I understand you (and me sometimes) can be bothered with the multiple pages (but it also shows how many line per pages, and if the last line fill the page), but depending on one's needs, it's as easy as replacing the one sample file.
If you need to switch between different sample files, you can easily user-patch ReaderFont:buildFontsTestDocument() and prepend another ConfirmBox question to chose the filename, and update FONT_TEST_USER_SAMPLE_PATH, before calling the orignal function.

if the user selected to have recently selected fonts listed first [...] So the idea would be that when a new CRE-doc is opened and the menu table is built, the currently selected font would be considered 'selected' at that moment and be moved to the top spot. Do you agree?

Seems logical and fine. (I'm not using this option, so I have no experience with the current behaviour, and won't be if you change it :))

@Frenzie

Frenzie commented Jul 2, 2024

Copy link
Copy Markdown
Member

Strings are fine by me, but the entire HTML document is duplicated twice? Can't that be refactored a bit more elegantly?

@jonnyl2

jonnyl2 commented Jul 2, 2024

Copy link
Copy Markdown
Contributor Author

the entire HTML document is duplicated twice? Can't that be refactored a bit more elegantly?

I'll revert that all; we agreed on a different solution (no separate function; just the new fonts listed first when any were found in the current session).

jonnyl2 added 5 commits July 7, 2024 15:55
There's nothing wrong with "Would you like to" per se, but the question becomes a bit long and unwieldy for the first dialog. It's fine for the short second one.
@Frenzie

Frenzie commented Jul 7, 2024

Copy link
Copy Markdown
Member
Checking frontend/apps/reader/modules/readerfont.lua 3 warnings

    frontend/apps/reader/modules/readerfont.lua:890:36: line contains trailing whitespace
    frontend/apps/reader/modules/readerfont.lua:893:31: line contains trailing whitespace
    frontend/apps/reader/modules/readerfont.lua:895:56: line contains trailing whitespace

@jonnyl2 jonnyl2 changed the title Readerfont: Generate font test document for new fonts only Readerfont: Font test document with new fonts in current session on top Jul 7, 2024
@jonnyl2

jonnyl2 commented Jul 8, 2024

Copy link
Copy Markdown
Contributor Author

@Frenzie Thanks, I will track down the whitespaces

@poire-z I'm afraid I need to ask for help with this:

when a new CRE-doc is opened and the menu table is built, the currently selected font would be considered 'selected' at that moment and be moved to the top spot

I tried many things but nothing seems to work. Ideally I'd like the current font move to the top position only when the Font menu is opened (and then the font list immediately refreshed); not when the document is opened. But either one is fine if there's a problem with the 'onMenuOpen' route.

What would be the best approach to achieve this, and at which stage?

Edit: I think I found the solution.

@jonnyl2 jonnyl2 marked this pull request as ready for review July 11, 2024 14:15
@jonnyl2

jonnyl2 commented Jul 11, 2024

Copy link
Copy Markdown
Contributor Author

@Frenzie How did the base update get in here? Did I do something wrong? :/

@Frenzie

Frenzie commented Jul 11, 2024

Copy link
Copy Markdown
Member

Otherwise it wouldn't be in there, but I don't know what you did.

@jonnyl2 jonnyl2 marked this pull request as draft July 11, 2024 15:54
Comment on lines +342 to +346
sub_item_table_func = function()
-- move currently set font to the top of the list if sorted by recently selected
if G_reader_settings:isTrue("font_menu_sort_by_recently_selected") then
self:addToRecentlySelectedList(self.font_face)
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.

I don't think this is the right place to do that: it's odd that some setting change (or reordering) would happen when one opens a menu :)
But it seems that is what you wanted:

Ideally I'd like the current font move to the top position only when the Font menu is opened (and then the font list immediately refreshed); not when the document is opened.

I'm not sure I understand why you would want that - and not when the document is opened.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Glad you're back :)

I'm not sure I understand why you would want that - and not when the document is opened.

It is to avoid reordering the font list when the user doesn't intend to change the font (or changes it only outside the menu; using a profile or quick menu).

Otherwise, if the user frequently switches between different books that have different fonts, the font list gets reordered each time, even though he never actively changed the font.

The purpose for this reordering is only so that when the user opens the menu, he doesn't find himself somewhere on page 10 of the font list and first has to go back to page 1 to select one of his most recently selected fonts.

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.

So, if one opens 3 books (having each a different font), and he opens the menu, on the next book opening, he will get these 3 fonts first as recently selected, even though he never actively changed the font ? :/
I think you should not touch the recently_selected list.

You probably should try to reorder face_list to move the current font at the first position in between here:

face_list = self:sortFaceList(face_list)
for k, v in ipairs(face_list) do

so this affects only the menu table and the UI.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, this makes sense and I was actually trying this before, but am struggling with the same problem again: how do I get the currently set font at this stage? self.font_face is not defined yet and G_reader_settings:readSetting("cre_font") apparently returns the default font? What do I call here to get the font?

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 could try to move the building of the menu table to later when the settings are read:

--- a/frontend/apps/reader/modules/readerfont.lua
+++ b/frontend/apps/reader/modules/readerfont.lua
@@ -32,5 +32,4 @@ local newly_added_fonts = nil -- not yet filled
 function ReaderFont:init()
     self:registerKeyEvents()
-    self:setupFaceMenuTable()
     self.ui.menu:registerToMainMenu(self)
     -- NOP our own gesture handling
@@ -185,4 +184,6 @@ function ReaderFont:onReadSettings(config)
     self:updateFontFamilyFonts()

+    self:setupFaceMenuTable()
+
     -- Dirty hack: we have to add following call in order to set
     -- m_is_rendered(member of LVDocView) to true. Otherwise position inside

I don't think anything from it is needed before that - but it is to be tested and confirmed by you :)
(The alternative would be to check if self.font_face then do your stuff end, so not have it done on the first call - and later re-call it if font_menu_sort_by_recently_selected=true.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thank you! It works like a charm! Now I just have to figure out how to get rid of the uninvited guests in my PR :/. The problem was that those changes were selected by default in my Github Desktop. I should have unchecked them before committing anything, but I didn't see that.

Comment thread frontend/apps/reader/modules/readerfont.lua
@poire-z

poire-z commented Aug 25, 2024

Copy link
Copy Markdown
Contributor

What's the status of this PR ?
Changes looks good to me, but current PR lags and would restore older version of base & luajit-launcher.
Dunno if/how you can resync it call if you are using github web. You may want to start again from a proper master.

@jonnyl2

jonnyl2 commented Aug 25, 2024

Copy link
Copy Markdown
Contributor Author

I wanted to some more research on Git/Github before I do anything.
Would it perchance be possible for maintainers to only merge readerfont.lua and ignore the other files, or is it not?

You may want to start again from a proper master.

Would that entail a new PR or could this one be salvaged in that case?

@poire-z

poire-z commented Aug 25, 2024

Copy link
Copy Markdown
Contributor

Best to start a new PR from a fresh branch synced with our master, re-applying your changes over the current readerfont.lua (there's been 91c15d5 applied since you started this PR).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants