Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds time left for chapter and document to the screensaver message options #7897

Merged
merged 6 commits into from Jun 29, 2021

Conversation

IcedEagle
Copy link
Contributor

@IcedEagle IcedEagle commented Jun 28, 2021

Adds options for time left for chapter and document to the screensaver message options.

Adds a Duration Format option to the screensaver message option, for Modern (1h23m) or Classic (1:23) styles to be consistent with the status bar options.

Tested on desktop emulator and Kobo Libra H2O device.

Screenshot from 2021-06-28 01-21-52

Screenshot from 2021-06-28 01-22-51

Screenshot from 2021-06-28 01-23-06

Modern:
Screenshot from 2021-06-28 01-50-49

Classic:
Screenshot from 2021-06-28 01-51-44


This change is Reviewable

@IcedEagle
Copy link
Contributor Author

IcedEagle commented Jun 28, 2021

As a side note, it's not checked in or part of my change, but I was able to test this on the desktop by changing generic/device.lua to support screensaver, and added onPowerEvent calls to ui/uimanager.lua in the isSDL check within UIManager:Init. However, I wasn't really sure the full ramification of that change, so I left it out. It only displayed the screensaver once per launch so clearly some issues there, but it worked well enough for my local testing of the feature though! :)

If there is another way I'm supposed to be able to test the screensaver functionality on PC, I'd love to know the trick!

@Frenzie
Copy link
Member

Frenzie commented Jun 28, 2021

Yes, if you want to play around with it on PC you'd need to add supportsScreensaver (or whatever the exact name is) in device to test it. Since we now distinguish the emulator in the SDL device it can probably be added by default.

Not quite sure what you mean with the powerevent stuff; that sounds neither desired nor necessary. ;-)

@Frenzie Frenzie added this to the 2021.07 milestone Jun 28, 2021
@@ -1902,6 +1902,7 @@ end

function ReaderFooter:getDataFromStatistics(title, pages)
local sec = _("N/A")
-- This is implemented by the Statistics plugin
Copy link
Member

Choose a reason for hiding this comment

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

If a comment along these lines is useful, it should be above over on line 1899. That being said, to me the function above strongly implies it's there in order to be overridden by an actual implementation. :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I will move it up to 1899. When I first started working through how to get the timing data, I got confused as to how this function was working. Having this comment might save someone else a bit of time finding where the override is, or at least, it would have saved me a bit of time.

Comment on lines 240 to 271
text = _("Duration format"),
sub_item_table = {
{
text_func = function()
local util = require("util")
-- sample text to show 1h23m
local return_text = util.secondsToHClock(4980, true)
return T(_("Modern (%1)"), return_text)
end,
checked_func = function()
return G_reader_settings:readSetting("screensaver_duration_format") == "modern"
end,
callback = function()
G_reader_settings:saveSetting("screensaver_duration_format", "modern")
end,
},
{
text_func = function()
local util = require("util")
-- sample text to show 1:23
local return_text = util.secondsToClock(4980, true)
return T(_("Classic (%1)"), return_text)
end,
checked_func = function()
return G_reader_settings:readSetting("screensaver_duration_format") == "classic"
end,
callback = function()
G_reader_settings:saveSetting("screensaver_duration_format", "classic")
end,
},
}
}
Copy link
Member

Choose a reason for hiding this comment

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

Vaguely wondering if it wouldn't be worth merging all of these into a single setting in Date/Time, like what was done for 24h clocks?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I had the same thought when I originally put this in. It would be nice to have a single user setting to control this, and a new util function that returns the clock format based on that user preference so plug-ins wouldn't need to do this logic. To do it right, I would change the plug-in's that use util.secondsToClock or util.secondsToHClock to use this new function, and move the relevant user settings to a new one within Device -> "time and date". It would touch readerfooter, screensaver, bookstatuswidget, readerprogress and statistics. I would also add unit tests for the new util function.

Does this sound reasonable? If so, let me know if you'd prefer I close this PR while I do that work, since it's going to be a bit larger of a change than I originally planned.

Copy link
Member

@NiLuJe NiLuJe Jun 29, 2021

Choose a reason for hiding this comment

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

That sounds perfect, yeah 👍.

I'd be inclined to prefer delaying the PR as a whole, but no strong feelings on that ;).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Latest iteration has this ready for review! Please check it out!

@@ -150,6 +182,8 @@ local function expandSpecial(message, fallback)
ret = string.gsub(ret, "%%T", title)
ret = string.gsub(ret, "%%A", authors)
ret = string.gsub(ret, "%%S", series)
ret = string.gsub(ret, "%%h", time_left_chapter)
ret = string.gsub(ret, "%%H", time_left_document)
Copy link
Member

@NiLuJe NiLuJe Jun 28, 2021

Choose a reason for hiding this comment

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

Only tangentially related to the PR, but this whole block could be "simplified" with a replacement table.

e.g.,

local rep = { ["%c"] = currentpage, ["%t"] = totalpages, ... }
ret = ret:gsub("(%%%a)", rep)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you! Wasn't aware of this. Made this change in latest iteration.

Copy link
Member

Choose a reason for hiding this comment

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

Well, it's kind of my bad for not implementing it this way the first time around, thanks ;).

- Added new utility function to pass to different clock formats
- Added unit tests for new utility function
- Updated any plugin that called util.secondsToClock to
use the new util for different duration format
- Add one time migration from footer's duration format
- Removed duration format from footer settings

Manual tests on desktop and Kobo. Verified all plugins look
correct with both modern and classic formats.
@@ -377,10 +377,12 @@ function UIManager:init()
elseif Device:isSDL() then
self.event_handlers["Suspend"] = function()
self:_beforeSuspend()
Device:onPowerEvent("Suspend")
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the onPowerEvent I referred to in an earlier comment. This function is what is needed to actually kick off the screensaver. Without this, it suspends, but no screensaver appears.

Copy link
Member

Choose a reason for hiding this comment

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

if you change the above from Device:isSDL() to Device:isEmulator()[1] and it's probably good to go. Needs further testing though (mainly in the regular AppImage target).

[1] That's a fairly recent addition to distinguish the more recent regular desktop AppImage/Debian package from the emulator.

Copy link
Contributor Author

@IcedEagle IcedEagle Jun 29, 2021

Choose a reason for hiding this comment

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

So I've traced this back to the event handler for Resume not firing when I'd expect on either isSDL or isEmulator (thus not resetting the screen_saver_mode variable, and not showing a screensaver after the first attempt).

What I can do to fix this is to add another event handler in uimanager for Device:isEmulator for the default input event, check if it's in screensaver mode, in which case do a device resume, and then send the input event along.

This seems to work:

    elseif Device:isEmulator() then
        self.event_handlers["Suspend"] = function()
            self:_beforeSuspend()
            Device:onPowerEvent("Suspend")
            Device:simulateSuspend()
        end
        self.event_handlers["Resume"] = function()
            Device:onPowerEvent("Resume")
            Device:simulateResume()
            self:_afterResume()
        end
         **self.event_handlers["__default__"] = function(input_event)
             if Device.screen_saver_mode then
                 self:resume()
            end
            self:sendEvent(input_event)**
         end

Would you prefer I put this in a separate PR at this point? I'm not as confident in my testing of this, though it seems to work fine in my limited tests. I'd also rip out the "Suspend" and "Resume" UI messages which seem pretty useless if the screensaver triggers when expected...

Copy link
Member

Choose a reason for hiding this comment

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

Yes, that definitely doesn't sound related and it'd just hold up this one. ;-)

@IcedEagle
Copy link
Contributor Author

Forgot to submit these earlier. Wanted to take screenshots of the various places I've looked for the updated formats so you can take a look. Not shown are the screensaver and reader footer, because my earlier screenshots should capture those well.

Screenshot from 2021-06-29 03-44-30
Screenshot from 2021-06-29 03-44-34
Screenshot from 2021-06-29 03-45-12
Screenshot from 2021-06-29 03-45-17
Screenshot from 2021-06-29 03-45-25
Screenshot from 2021-06-29 03-45-31
Screenshot from 2021-06-29 03-45-37

Now switching back to Classic format. Should be no different to how it looks today.
Screenshot from 2021-06-29 03-46-32
Screenshot from 2021-06-29 03-46-37
Screenshot from 2021-06-29 03-46-41
Screenshot from 2021-06-29 03-46-47
Screenshot from 2021-06-29 03-46-55

@poire-z
Copy link
Contributor

poire-z commented Jun 29, 2021

Guess I'm really classic, because these modern durations looks really ugly to me in all these pannels.
Just wondering if this duration mode for the footer items might mostly be used to reduce the widths of these durations, and let more room for the other items - and if some people might have used this for the footer, but would still prefer durations everywhere else to be "classic".

(But I personally don't mind, I'll stay classic all around :)

@Frenzie
Copy link
Member

Frenzie commented Jun 29, 2021

I have to wonder if the modern and classic labels might not be reversed… :-P

@IcedEagle
Copy link
Contributor Author

Hah! I'm also someone who will opt to use Classic. Much easier for me to understand. I have it defaulting to use Classic as well for new users, but for existing users the one time migration will use a user's footer's format as their starting default.

@@ -410,7 +410,7 @@ function Device:reboot() end
-- Hardware specific method to initialize network manager module
function Device:initNetworkManager() end

function Device:supportsScreensaver() return false end
function Device:supportsScreensaver() return true end
Copy link
Member

Choose a reason for hiding this comment

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

Unintended leftover from the Emu/SDL shenanigans?

Copy link
Member

Choose a reason for hiding this comment

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

You can pretty much do the same for the emulator with

function Emulator:supportsScreensaver() return true end

in https://github.com/koreader/koreader/blob/master/frontend/device/sdl/device.lua#L338

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I will remove this since it's not necessary for the PR.

if last_migration_date < 202100629 then
logger.info("Performing one-time migration for 202100629")

local footer = G_reader_settings:child("footer")
Copy link
Member

@NiLuJe NiLuJe Jun 29, 2021

Choose a reason for hiding this comment

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

Congratulations for being the first actual user of the child method ^^.

Copy link
Member

@NiLuJe NiLuJe left a comment

Choose a reason for hiding this comment

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

:lgtm:, thanks!

(Short of the Device:Generic question above).

@IcedEagle
Copy link
Contributor Author

IcedEagle commented Jun 29, 2021

:lgtm:, thanks!

(Short of the Device:Generic question above).

Thank you! Made the change to remove the two files that had unrelated changes to the emulator from this PR.

@pazos pazos merged commit ba65dc1 into koreader:master Jun 29, 2021
@IcedEagle IcedEagle deleted the read-progress-screensaver branch June 29, 2021 23:51
@poire-z
Copy link
Contributor

poire-z commented Jul 21, 2021

I have it defaulting to use Classic as well for new users, but for existing users the one time migration will use a user's footer's format as their starting default.

Dunno if it's just me, but on my 2 devices (Kobo, Android phone), where I don't remember having ever seen the modern (2"30') anywhere, I got to see it everywhere after some recent update that must have included this PR/migration.
I don't use any "time remaining" footer item, so may be the default for it was "modern" (haven't checked if it's the case - it's possible I did try it at some point and left it be "modern", dunno) - but having that default now propagate to everywhere feels a bit radical :)

@NiLuJe
Copy link
Member

NiLuJe commented Jul 21, 2021

FWIW, I started from a fresh setup on the Elipsa (@ 2021.06-40), and it defaults to Classic.

@poire-z
Copy link
Contributor

poire-z commented Jul 21, 2021

It seems the footer had it "modern" by default:

items_separator = "bar",
progress_pct_format = "0",
duration_format = "modern",
progress_margin = false,
}

I think you made some migration/cleanup of readerfooter not too long ago when you transfer the app defaults into the user footer settings - and then this picks that user prefered setting (while it was only a default being propagated, not a user preference :)).
Dunno if this is what triggers what I get, and if on a fresh setup, the ordering of this makes it default to "classic" ?

@NiLuJe
Copy link
Member

NiLuJe commented Jul 21, 2021

I think you made some migration/cleanup of readerfooter not too long ago when you transfer the app defaults into the user footer settings

True, but the new code (post this PR) shouldn't honor that setting remnant anymore, it only checks the "new" consolidated setting:

function ReaderFooter:getDataFromStatistics(title, pages)
local sec = _("N/A")
local average_time_per_page = self:getAvgTimePerPage()
local user_duration_format = G_reader_settings:readSetting("duration_format", "classic")
if average_time_per_page then
sec = util.secondsToClockDuration(user_duration_format, pages * average_time_per_page, true)
end
return title .. sec
end

(And, IIRC, that does indeed default to classic now).

@IcedEagle
Copy link
Contributor Author

@poire-z @NiLuJe If modern was the default, and people never changed it or used the time in the footer to notice it, it might have been better to not have handled any migration and just start everyone on Classic to keep consistent throughout more of the UI. Sorry, that didn't occur to me before, but probably would have been a better trade off in migrating.

Ideally we can just point people towards the new setting to flip it back, however if folks wanted, we could do a one-time migration and reset everyone back to classic, which anecdotally seems to be the far more popular option anyway.

-- 20210629, Moves Duration Format to Date Time settings for other plugins to use, https://github.com/koreader/koreader/pull/7897
if last_migration_date < 20210629 then
logger.info("Performing one-time migration for 20210629")
local footer = G_reader_settings:child("footer")
if footer and footer:has("duration_format") then
local user_format = footer:readSetting("duration_format")
G_reader_settings:saveSetting("duration_format", user_format)
footer:delSetting("duration_format")
end
end

@NiLuJe
Copy link
Member

NiLuJe commented Jul 21, 2021

Oh, right, the upgrade path picked up the "modern" default from the footer, didn't quite think of that ^^.

No strong feelings about it, but if we hear about it, why not?

@Frenzie
Copy link
Member

Frenzie commented Jul 21, 2021

I also found this an unpleasant surprise. I thought it was my own fault somehow.

poire-z pushed a commit that referenced this pull request Jul 23, 2021
Reset unwanted migration of this setting to "modern"
done with #7897.
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.

None yet

5 participants