Skip to content

[ReaderHighlight] preserve highlight when using highlight dialogue#14437

Merged
Frenzie merged 14 commits into
koreader:masterfrom
Commodore64user:high-dial
Oct 14, 2025
Merged

[ReaderHighlight] preserve highlight when using highlight dialogue#14437
Frenzie merged 14 commits into
koreader:masterfrom
Commodore64user:high-dial

Conversation

@Commodore64user

@Commodore64user Commodore64user commented Oct 10, 2025

Copy link
Copy Markdown
Member

This pull request introduces small improvements to the highlighting and clipboard features in the reader module, focusing on better user experience when copying text and performing dictionary lookups from the highlight dialogue. The changes ensure the dialogue is closed whilst preserving the highlighted text.

what's new

  • The onClose method in ReaderHighlight now accepts a keep_highlight parameter, allowing the highlight to persist when needed.
  • After copying selected text to the clipboard, the highlight is kept briefly and cleared after a 0.5 second delay, giving users time to see what was copied.
  • When performing a dictionary lookup, the highlight is preserved, and the lookupDict function now receives the highlight as an argument for better context management.
  • In the QR clipboard plugin, the dismiss callback now keeps the highlight and also delays clearing it by 0.5 seconds, improving user feedback for QR code generation.

This change is Reviewable

@Commodore64user Commodore64user marked this pull request as ready for review October 10, 2025 12:07
Comment thread frontend/apps/reader/modules/readerhighlight.lua Outdated
@poire-z

poire-z commented Oct 10, 2025

Copy link
Copy Markdown
Contributor

(You're not obliged to follow @Frenzie or myself's all suggestions.)

You name it in the code BACKLINK_HIGHLIGHT_DURATION (which reads bad: there is no link followed or backlink), DELAY_CLEAR_HIGHLIGHT_S reads truer.
And it has the _S we have elsewhere to document the unit.

@Commodore64user

Copy link
Copy Markdown
Member Author

(You're not obliged to follow @Frenzie or myself's all suggestions.)

if I don't do as he says, he follows me around teasing me with his Ryzen 7 with zillions of cores that builds emulators in seconds not minutes. ;)

Comment thread frontend/apps/reader/readerui.lua Outdated
Commodore64user and others added 2 commits October 10, 2025 18:32
Co-authored-by: Frans de Jonge <fransdejonge@gmail.com>
@Frenzie

Frenzie commented Oct 10, 2025

Copy link
Copy Markdown
Member

Isn't there another one for if you follow a link / location btw?

@Commodore64user

Copy link
Copy Markdown
Member Author

I believe that's all of them... (don't quote me)

@Frenzie

Frenzie commented Oct 10, 2025

Copy link
Copy Markdown
Member

@poire-z Is the little indicator for where a link points in there?

@poire-z

poire-z commented Oct 10, 2025

Copy link
Copy Markdown
Contributor

It is in there and has a little world of his own:

-- Allow tweaking this marker behaviour with a manual setting:
-- followed_link_marker = false: no marker shown
-- followed_link_marker = true: maker shown and not auto removed
-- followed_link_marker = <number>: removed after <number> seconds
-- (no real need for a menu item, the default is the finest)
local marker_setting
if G_reader_settings:has("followed_link_marker") then
marker_setting = G_reader_settings:readSetting("followed_link_marker")
else
marker_setting = 1 -- default is: shown and removed after 1 second
end

I'd rather not send @Commodore64user on a journey into this world :)
(And it is not a highlight, and works when following link forward too.)

@Frenzie

Frenzie commented Oct 10, 2025

Copy link
Copy Markdown
Member

Alright.

@Commodore64user

Copy link
Copy Markdown
Member Author

I'd rather not send @Commodore64user on a journey into this world :)

unsure if I should be grateful or offended...

callback = function()
this:lookupDict(index)
-- We don't call this:onClose(), same reason as above
this:lookupDict(index, this)

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.

this already there as self.

Comment thread frontend/ui/widget/htmlboxwidget.lua Outdated
end
end
UIManager:scheduleIn(0.5, self.highlight_clear_and_redraw_action)
UIManager:scheduleIn(self.ui.DELAY_CLEAR_HIGHLIGHT_S, self.highlight_clear_and_redraw_action)

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.

Are you sure the widget got proper ui?

Comment thread frontend/ui/widget/textboxwidget.lua
Comment thread frontend/apps/reader/readerui.lua Outdated
end

function ReaderUI:init()
self.DELAY_CLEAR_HIGHLIGHT_S = 0.5

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.

The constant, can be set once in the module, not in instances.

Comment on lines +1359 to +1360
local ReaderUI = require("apps/reader/readerui")
UIManager:scheduleIn(ReaderUI.DELAY_CLEAR_HIGHLIGHT_S, function() lookupCancelled() 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.

That's quite ugly. All this to get a constant, because readerdict can be use in filemanager ?
I'd rather just see 0.5...

@Commodore64user Commodore64user Oct 11, 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.

all that because @hius07 prefers it declared in the module, not as instance variable, but it was working fine everywhere with self.ui.WHATEVER even in FM. ¯\_(ツ)_/¯

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 think he meant you could delare it in here:

local ReaderUI = InputContainer:extend{
name = "ReaderUI",
active_widgets = nil, -- array
-- if we have a parent container, it must be referenced for now
dialog = nil,

and you could access it just like if declared in :init() as self.ui.DELAY_CLEAR_HIGHLIGHT_S.

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.

if that is what he meant, he should have said class variable. That is NOT what he said

@poire-z

poire-z commented Oct 11, 2025

Copy link
Copy Markdown
Contributor

I think this constant has really nothing to do in ReaderUI (except for broader access).
If it relates to highlights, and ReaderHighlight is where hold/long-press is handled, it should be in ReaderHighlight.

callback = function(dialog)
UIManager:close(dialog)
UIManager:scheduleIn(0.5, function() lookupCancelled() end)
UIManager:scheduleIn(self.ui.highlight.DELAY_CLEAR_HIGHLIGHT_S, function() lookupCancelled() end)

@poire-z poire-z Oct 12, 2025

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 codepath be taken if dict invoked from FileBrowser - there would be no self.ui.highlight ?
Same question for dictquicklookup ?

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 catch, this one is actually problematic, the one on dictquick is under a self.highlight so safe...

Comment on lines +1359 to +1360
local delay = self.ui.highlight and self.ui.highlight.DELAY_CLEAR_HIGHLIGHT_S or 0.5
UIManager:scheduleIn(delay, function() lookupCancelled() 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.

What happens if you start a new search in the interval? (Not a new problem, if it is one.)

@Commodore64user Commodore64user Oct 13, 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.

I tried with the current version, and nothing really. There are some factors, finger speed, by the time you start contact with the screen you are almost in the second half of the 0.5 and it clears just as normal and the next crengine selection begins.

As you said, not a new problem, which you can verify as well if you think you have faster fingering speed (FFS) 🫣

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.

I'm asking more what the problem would be if it did happen. If it's just a minor visual glitch it probably doesn't really matter, but if there's some kind of memory race condition it could be more serious.

@Commodore64user

Copy link
Copy Markdown
Member Author

I understand the thinking behind, so what should be done then?

@Frenzie

Frenzie commented Oct 13, 2025

Copy link
Copy Markdown
Member

I'd say probably either add it to https://github.com/koreader/koreader/blob/87445034bd2ddadb524b2db3bfc7d05c657e8546/frontend/ui/size.lua (granted, it's a duration) or just use local DELAY_CLEAR_HIGHLIGHT_S = 0.5. While the latter wouldn't have a single source of truth, it would immediately show up in a search, and I don't really expect the number of them to grow.

@Commodore64user

Copy link
Copy Markdown
Member Author
    -- this should be self.ui.highlight.DELAY_CLEAR_HIGHLIGHT_S, but in FM we don't have access to self.ui
    local delay = 0.5
    UIManager:scheduleIn(delay, function() lookupCancelled() end)

@Frenzie?

@Frenzie

Frenzie commented Oct 13, 2025

Copy link
Copy Markdown
Member

What's the question precisely?

@Commodore64user

Copy link
Copy Markdown
Member Author

Is that better? A suitable alternative? Any other suggestions

@Frenzie

Frenzie commented Oct 13, 2025

Copy link
Copy Markdown
Member

But I mean are you saying are happy with and prefer self.ui.highlight.DELAY_CLEAR_HIGHLIGHT_S in general, and that you'd prefer to keep this instance as an exception?

@Commodore64user

Copy link
Copy Markdown
Member Author

I am saying we keep the self.WHATEVER and use this as the exception for when self is not accessible, that way we get the grep and it sort of explains to anyone reading the code what's happening instead of the simple 0.5

@Frenzie

Frenzie commented Oct 13, 2025

Copy link
Copy Markdown
Member

Hold on, if there's no highlight to clear then why is there any delay at all? Shouldn't that be:

if self.ui then
  -- delay
else
  -- immediate
end

local Screen = Device.screen

local ReaderHighlight = InputContainer:extend{
DELAY_CLEAR_HIGHLIGHT_S = 0.5,

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.

Suggested change
DELAY_CLEAR_HIGHLIGHT_S = 0.5,

@Commodore64user

Commodore64user commented Oct 13, 2025

Copy link
Copy Markdown
Member Author

That is only partially true in one case, searching from FM (or direct searches). In all other cases there are highlights, particular mention to meta-queries which also have highlights to clear

@Frenzie

Frenzie commented Oct 13, 2025

Copy link
Copy Markdown
Member

Alright, just keep it as is then (besides the line that should be removed).

@Commodore64user

Copy link
Copy Markdown
Member Author

On mobile, but wouldn't removing that line mean it never gets declared? Then we are trying to access something that doesn't exist

@Frenzie

Frenzie commented Oct 13, 2025

Copy link
Copy Markdown
Member

Indeed, while on mobile I'd overlooked the comma.

@Commodore64user

Copy link
Copy Markdown
Member Author

have a look @Frenzie, better now?, another thing would be to declare the class variable (constant) in FM as well...

@Frenzie

Frenzie commented Oct 13, 2025

Copy link
Copy Markdown
Member

I think I'd prefer to just do that, but let's see what the others think.

@poire-z

poire-z commented Oct 13, 2025

Copy link
Copy Markdown
Contributor

I think a DELAY_CLEAR_HIGHLIGHT_S has absolutely nothing to do in filemanager.lua where it is not used directly, and would only be used by module far far away (textboxwidget.lua).

Maybe we can put it in that file we have forgotten: https://github.com/koreader/koreader/blob/master/defaults.lua - just because it's used by many unrelated bits, so it can be considered global :)

@Commodore64user

Copy link
Copy Markdown
Member Author

I was about to comment that the FM declaration is actually not very helpful and was a terrible idea. I take it back.

in my opinion, the current form is the best compromise, it is still easily trackable with greps and doesn't bother the widgets with conundrums like "to ui or not to ui"

@Frenzie

Frenzie commented Oct 14, 2025

Copy link
Copy Markdown
Member

Maybe we can put it in that file we have forgotten: https://github.com/koreader/koreader/blob/master/defaults.lua - just because it's used by many unrelated bits, so it can be considered global :)

I already stated my preferred solution in #14437 (comment)

I regret bringing up the subject because I don't like this self.ui business at all.

@Commodore64user

Commodore64user commented Oct 14, 2025

Copy link
Copy Markdown
Member Author

but you first proposed the self.ui though, are you sure adding it to the size file is better? like really?

@hius07

hius07 commented Oct 14, 2025

Copy link
Copy Markdown
Member

I'm also for

UIManager:scheduleIn(G_defaults:readSetting("DELAY_CLEAR_HIGHLIGHT_S"), function()...

@hius07

hius07 commented Oct 14, 2025

Copy link
Copy Markdown
Member

One more

if self.highlight then
local clear_id = self.highlight:getClearId()
UIManager:scheduleIn(0.5, function()
self.highlight:clear(clear_id)
end)
end

@Frenzie

Frenzie commented Oct 14, 2025

Copy link
Copy Markdown
Member

but you first proposed the self.ui though, are you sure adding it to the size file is better? like really?

Well yes, I like that better than sprinkling "we can't access self.ui here" all over the place. :-) But in any case let's go with G_defaults:readSetting("DELAY_CLEAR_HIGHLIGHT_S"); being easy to customize is not a bad thing.

@Frenzie Frenzie added this to the 2025.10 milestone Oct 14, 2025
@Frenzie Frenzie merged commit 6d49c26 into koreader:master Oct 14, 2025
4 checks passed
@Commodore64user Commodore64user deleted the high-dial branch October 14, 2025 13:31
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

Development

Successfully merging this pull request may close these issues.

4 participants