Skip to content

BookInfo: add page information#10255

Merged
hius07 merged 10 commits into
koreader:masterfrom
hius07:book-info
Mar 31, 2023
Merged

BookInfo: add page information#10255
hius07 merged 10 commits into
koreader:masterfrom
hius07:book-info

Conversation

@hius07

@hius07 hius07 commented Mar 28, 2023

Copy link
Copy Markdown
Member

(1) Added current page lines and words number (based on #10231 (comment))
(2) Do not show empty book props (former "N/A")

01

02


This change is Reviewable

@poire-z

poire-z commented Mar 28, 2023

Copy link
Copy Markdown
Contributor

(1) Added current page lines and words number (based on #10231 (comment))

Mhhh, I don't think these has anything to do with "Book" information.
As for the code, I did that quickly just for the people who wanted something. I would not have pushed that into KOReader master, because 1) it's not really a needed feature and 2) I'm not certain it will always work and would not get stuck into some infinite loop or messy situation in some edgy pages (ie. with HTML tables, large floats...) where it would go returning all the book text (and 3) if it would get stuck, I don't want to have to fix it and find an alternative solution :)
And I would not want that to somehow stuck/slow/break Book information...

So, if you really want to add them, it better be a "Tap to see nb of lines and words", so I won't ever get that ugly code executed :)

(2) Do not show empty book props (former "N/A")

Somehow, I like these N/A, and seeing all the metadata "names" we support, even if they have no value.
Fictional use case: I remember I've seen somewhere the "year" of the book, I don't see it in Book information I would go look elsewhere. Seeing "Keyword: N/A" may makes me realize I may have seen a year in that field, so I accept it's empty and don't go look for it elsewhere.

Comment on lines -6 to -10
local DocSettings = require("docsettings")
local DocumentRegistry = require("document/documentregistry")
local ImageViewer = require("ui/widget/imageviewer")
local InfoMessage = require("ui/widget/infomessage")
local KeyValuePage = require("ui/widget/keyvaluepage")

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.

Why get rid of these at the top, to go use the uglier local widget = require("ui/widget/keyvaluepage"):new{...} below ?
I don't think there's any risk of require loop here.
I admit I sometime do it when it's a rarely used module, to wait to load it - so it might be fine for ImageViewer and KeyBaluePage - but DocSettings is probably always loaded, so it doesn't really need this treatment.

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.

BookInfo page and its parts (description, cover) may be shown without Docsettings sometimes. So it has been moved to getBookProps where it is used.

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.

The same for KeyValuePage: if we ask to show book description only, it is not needed.

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 understand you do not like require():new and prefer local before?

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.

Yes, but then, why not do the same for InfoMessage and require it in onShowBookCover() and onShowBookDescription(), which are both rarely used?

It's also not the number of times it is used that should make it be at the top, rather how frequent/heavy it is, and if other modules would already have require() it and it is most probably already in memory. ie. for KeyValuePage, readerdictionary.lua does it at the top, so it's already in memory (or soon will be in your "start in file browser").

If you start with doing that, we'll shrink the top of our files quite heavily :)
And require("ui/widget/keyvaluepage"):new{...} is just ugly. It's fine for quick shorthands like needing a function form util.lua, but otherwise, it brings nothing.

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 understand you do not like require():new and prefer local before?

Yes, I would prefer a local = require(...) on one line and the :new{} on the next, it's more readable - and what we mostly use.
(But the little require("util").doSomeSstuff() are small and fine).

Just saying, do not go too crazy with moving them all into where the function they are used. It feels OK for ImaveViewer, which we seldom need, also OK for KeyValuePage even if we do require it at top elsewhere, but DocSettings is so common.

@hius07

hius07 commented Mar 28, 2023

Copy link
Copy Markdown
Member Author

I've tested it on big epubs, fb2 (with footnotes), some html, pdf. It does work well.
Can you share a complicated epub/html to test.

@poire-z

poire-z commented Mar 28, 2023

Copy link
Copy Markdown
Contributor

Can you share a complicated epub/html to test.

I don't remember what books I may have had performance issues in the past.
I remember I had a Wikipedia China.EN.epub, which has big tables at the end - but it's somehow fine on the emulator.
No issue also with an EPUB with multi pages paragraphs (where the author is known to rarely go to a new line :), on the emulator.
But well, we'd need to find just one book and one page in it where it goes bad to forget about it :) but didn't find any, which doesn't mean there isn't any.
I see you added that for PDF: on no-text layer PDFs, would OCR be triggered to detect the lines and words, and could it slow the appearance of the Book info widget ?

Also, when invoked from History, there is a trailing separator at bottom (we didn't get it before) - above where the nb words/lines are not displayed.

It still feels this has nothing to do with Book information. On CRE document's, it's more about some layout info - but then, so is page count... It also feels totally useless to me, and noise in Book information. But it's probably not worth adding a useless menu item somewhere to display these useless info, so it may very well be just the less worse to get them shown in that Book information.

@hius07

hius07 commented Mar 28, 2023

Copy link
Copy Markdown
Member Author

Updates:
-show N/A if the prop is absent
-do not show separator if there is no page info
-do not show page info for scanned pdf
-prettify require

Comment on lines +62 to +48
table.insert(kv_pairs, { _("File date:"), os.date("%Y-%m-%d %H:%M:%S", file_modification) })
table.insert(kv_pairs, { _("Size:"), string.format("%s (%s bytes)", size_f, size_b) })
table.insert(kv_pairs, { _("Last read date:"), os.date("%Y-%m-%d %H:%M:%S", attr.access) })
table.insert(kv_pairs, { _("Date modified:"), os.date("%Y-%m-%d %H:%M:%S", attr.modification) })

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.

The wording is a bit inconsistent (Last read date: vs Date modified:, shouldn't it be Modified date: ?
But I would keep using File date: (modification time is the Linux/Lua technical name for the info ; it's the creation date or the copy date for copied files depending on the tech used to do that copy, or the modification time for PDF with highlights written into them).

But: attr.access may or may not be updated by the OS when the file is read from. And "read from" may be just when extract and cache book info, or fetching book info, and it's not really the "last read date" as we expect it in a book reading application :)
For a field name "Last read date", I would expect the date to come from the doc settings file data.

I think the only valid and interesting info is attr.modification, and it should just be named "File date" to not imply anything else.
(Even if my Windows 10 Explorer shows "Modifié le" ("Modified at" in English I guess) :)

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.

This inconsistency goes from the old FileChooser sorting that I have kept there and here.
There are 3 types of date for sorting.
Does it make sense? Or to keep just modified?

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 see, the 3 linux timestamps I get with:

$ stat frontend/util.lua
Access: 2023-02-20 17:45:06.557652131 +0100
Modify: 2023-03-28 20:40:24.195326654 +0200
Change: 2023-03-28 20:40:24.207326417 +0200
 Birth: 2023-02-20 17:45:06.557652131 +0100 (didn't even know about this one :)

These have some technical meaning in Linux.
On my Linux, I have the filesystem mounted with "noatime" to limit useless writes to disk, so it isn't updated. Real devices (or appimage users) may or may not do that, we can't really know. And no real idea how it works on the FAT32 filesystems on our devices.
Showing them may have different meaning for the users, if they know how their devices work, and the process to transfer books to the devices, so, different users may get different infos from reading these 3 times.
But for most users, it's probably hard to make sense on each of these 3 values - or they may all show the same date.

As for sorting in KOReader, I'm always disappointed when I'm using it and trying the 3 options, to try to see the last files I added - I copy files with Windows Explorer, which preserves timestamp - and depending on how i got the file (old ones on my harddrive keep their old date, downloaded as epub get the time downloaded, downloaded as zip get their time inside the zip when extracted), so it's most often always useless, to me.
I think it was discussed at the time they were added, may be it made some sense to some people, don't remember.

So, dunno :)
If you'll end up keeping showing attr.access, it may be best to use its litteral name, "Last access time" - to distinguish it from "Last read time", which should only be our "last read in KOReader" time, the docsetting date.
Change is most probably = to Modified, so useless.

@NiLuJe or @Frenzie probably have more thoughts about that.

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 think Windows created (birth) and modified are much more useful than access and change time. To me those others aren't useful.

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.

lfs.attributes doesn't provide "birth" date. So, show modification only?

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.

atime will very much be useless 99.99% of the time, so, yeah, +1 for only mentioning mtime ;).

@NiLuJe NiLuJe Mar 29, 2023

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.

And to sate my curiosity about btime, it's a Linux extension, only available when calling statx, which requires Linux 4.11+ & glibc 2.28+ ;).

(It's implemented in stat on BSDs, and apparently ntfs3g, too; but the TLDR; being: nope, can't have it).

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.

btime usually seems to be the same as mtime anyway due to modern programs taking the safe approach (though on Win created usually seems to be maintained)

return #lines, #words
else
local page_boxes = self.ui.document:getTextBoxes(self.ui:getCurrentPage())
if not page_boxes or not page_boxes[1][1].word then return end -- scanned pdf

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.

Is this something happening per book or per page ? Looks like it's when a page contains no word ? So, its possible that on books with mixed text and pictures pages, we'll get to see "Current page lines/words" on some pages and not on others ?
Not sure what is best: showing:hiding, or always showing them, with the possibility of Current page lines: 0 or Current page lines: N/A (which could mean: lines not available on that page, or info about lines not available).

Anyway, you have the same situation in CRE document, ie. for the cover page. It most often shows Lines: 0 but Words: 1 or 2 for such pages. Dunno why 1 or 2 words, may be it grabs bits from prev/next pages. So if deciding about having lines and words, best to trust Lines first.

I think it should be consistent between PDF and CRE.

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.

Done

values_lang = book_props.language
-- Page section
if is_doc then
local lines_nb, words_nb = self:getCurrentPageLinesWordsNumber()

@poire-z poire-z Mar 29, 2023

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.

@Frenzie : what's the grammatically correct name for this function ? (again, singular/plural... :/)

LineWordNumbers
LinesWordsNumbers
LineWordNumber
LinesWordsNumber
NumbersOfLinesAndWords

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.

An option was getCurrentPageNumberOfLinesWords.

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.

Probably LineWordCount?

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.

getCurrentPageLineWordCount or ...LineWordCounts (as it returns 2 numbers) ?

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.

Yes, good point. Let's go with that. ^_^

@hius07

hius07 commented Mar 29, 2023

Copy link
Copy Markdown
Member Author

As for sorting in KOReader, I'm always disappointed when I'm using it and trying the 3 options, to try to see the last files I added - I copy files with Windows Explorer, which preserves timestamp - and depending on how i got the file (old ones on my harddrive keep their old date, downloaded as epub get the time downloaded, downloaded as zip get their time inside the zip when extracted), so it's most often always useless, to me.
I think it was discussed at the time they were added, may be it made some sense to some people, don't remember.

Introduced (with inconsistent wordings) in #2535.


function BookInfo:getCurrentPageLineWordCounts()
if self.ui.rolling then
local Screen = require("device").screen

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.

Oh, this one is nearly everywhere at top of files, and nearly never in a function.

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.

As I understand, require does not double load already loaded module, but it does check every time if the module has been loaded.
So what are the benefits of having all the requires at the top?

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 said it: it does check every time if the module has been loaded.
So, having it at the top avoid that checks every time your function is called. (even if that check time is peanuts/small, it must be just checking if a thing is in a table, and not worth fighting).

But this is not why I insist on these: it's just for consistency, whether it's good or bad, in all our modules, we have many standard require= at top, it's not worth changeing that and start inlining them now as you will edit modules.
(Again, except for heavy or rarely used modules, which are best require()d when they are about to be used.)

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 makes it simple to glance at the top of the file to see what it uses. It's a fairly common pattern for that reason.

Comment on lines +265 to +272
local words = {}
for word in util.gsplit(res.text, "[%s%p]+", false) do
if util.hasCJKChar(word) then
for char in util.gsplit(word, "[\192-\255][\128-\191]+", true) do
table.insert(words, char)
end
else
table.insert(words, word)

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 just increment a counter, instead of accumulating in the table words.

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 will do.

@hius07 hius07 merged commit a3080b0 into koreader:master Mar 31, 2023
@hius07 hius07 added this to the 2023.04 milestone Mar 31, 2023
@hius07 hius07 deleted the book-info branch March 31, 2023 09:59
TranHHoang added a commit to TranHHoang/koreader that referenced this pull request May 26, 2023
KOReader 2023.04 "Solar Panel"

![koreader-2023-04-fs8](https://user-images.githubusercontent.com/202757/234975122-d7739c71-74aa-4cb0-a086-72a4bba70f52.png)

It's been another busy month squashing many bugs. Our Mac users will be happy to hear that I told macOS we've supported HiDPI since long before anyone came up with such terminology (koreader#10341), and that the program can now natively build on M1 devices (koreader#10291).

Solar panel credit: <https://openclipart.org/detail/294030/solar-energy> by gnokii

We'd like to thank all contributors for their efforts. Some highlights since the previous release include:

* Readerzooming: fix use of default settings (koreader#10205) @hius07
* ButtonDialog/ButtonDialogTitle: consistent 'width' handling (koreader#10230) @poire-z
* MovableContainer: add support for anchoring initial position (koreader#10230) @poire-z
* Book map, Page browser: add top left menu (koreader#10230) @poire-z
* Book style tweak: add button with CSS suggestions (koreader#10230) @poire-z
* crengine: fix parsing of multibytes encodings (koreader#10230) @poire-z
* readerstyletweak: update profiles on unregistering in dispatcher (koreader#10247) @hius07
* Filesearcher: add search in book metadata (koreader#10198) @hius07
* Fix: Updated legacy directory, which crashed the program (koreader#10260) @Mochitto
* ReaderLink: allow a forward location stack (koreader#10228) @yparitcher
* BookInfo: add page information (koreader#10255) @hius07
* Center pdf manual zoom mode (koreader#10246) @nairyosangha
* File browser: add Folder Menu (koreader#10275) @hius07
* Calendar view: add options to change start time of days (koreader#10254) @weijiuqiao
* filechooser: fix crash on "unreadable content" (koreader#10283) @hius07
* Sync book statistics: add to dispatcher (koreader#10285) @ptrm
* [plugin] Exporter: use util.getSafeFilename() to remove illegal characters from output filename (koreader#10282) @Mochitto
* readerbookmark: fix writing pdf annotation (koreader#10287) @hius07
* Folder Menu: sign for Home folder (koreader#10288) @hius07
* ListMenu: show mark for books with highlights (koreader#10276) @hius07
* Calendar view's day view: thicker separator at 00:00 (koreader#10289) @poire-z
* PageBrowser: tweak scrolling behaviour at book start/end (koreader#10289) @poire-z
* Make `kodev check` feature complete (koreader#8682) @yparitcher
* macOS: support for M1 building (koreader#10291) @ptrm
* Reader: do not apply font size and spacing out of range (koreader#10295, koreader#10307) @hius07
* File browser: show Folder Menu on long-press on Home icon (koreader#10298) @hius07
* SSH.koplugin: fix cant stop SSH server bug when pid file's stale (koreader#10300) @weijiuqiao
* PM: Optimize task queue handling around standby (koreader#10203) @zwim
* statistic.koplugin: fix today's timeline showing next day when within custom offset (koreader#10299) @weijiuqiao
* ReaderThumbnails: update cached page thumbnail on bookmark note change (koreader#10303) @hius07
* SDL: add multitouch support (koreader#10334) @Frenzie
* SDL: add HiDPI support (koreader#10341) @Frenzie
* BookInfo: fix crash on show cover (koreader#10315) @hius07
* Deal with table.pack corner-cases properly (koreader#10350) @NiLuJe
* Android: add Tagus Gea support (<koreader/android-luajit-launcher#412>) @Alfedi

[Full changelog](koreader/koreader@v2023.03...v2023.04) — [closed milestone issues](https://github.com/koreader/koreader/milestone/63?closed=1)

---

Installation instructions: [Android](https://github.com/koreader/koreader/wiki/Installation-on-Android-devices) • [Cervantes](https://github.com/koreader/koreader/wiki/Installation-on-BQ-devices) • [ChromeOS](https://github.com/koreader/koreader/wiki/Installation-on-Chromebook-devices) • [Kindle](https://github.com/koreader/koreader/wiki/Installation-on-Kindle-devices) • [Kobo](https://github.com/koreader/koreader/wiki/Installation-on-Kobo-devices) • [PocketBook](https://github.com/koreader/koreader/wiki/Installation-on-PocketBook-devices) • [ReMarkable](https://github.com/koreader/koreader/wiki/Installation-on-ReMarkable) • [Desktop Linux](https://github.com/koreader/koreader/wiki/Installation-on-desktop-linux) • [MacOS](https://github.com/koreader/koreader/wiki/Installation-on-MacOS)
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