Commit Graph

138 Commits (fadee1f5dc5ffb6cd386a2fdadea4290e174069d)

Author SHA1 Message Date
NiLuJe fadee1f5dc
Clarify our OOP semantics across the codebase (#9586)
Basically:

* Use `extend` for class definitions
* Use `new` for object instantiations

That includes some minor code cleanups along the way:

* Updated `Widget`'s docs to make the semantics clearer.
* Removed `should_restrict_JIT` (it's been dead code since https://github.com/koreader/android-luajit-launcher/pull/283)
* Minor refactoring of LuaSettings/LuaData/LuaDefaults/DocSettings to behave (mostly, they are instantiated via `open` instead of `new`) like everything else and handle inheritance properly (i.e., DocSettings is now a proper LuaSettings subclass).
* Default to `WidgetContainer` instead of `InputContainer` for stuff that doesn't actually setup key/gesture events.
* Ditto for explicit `*Listener` only classes, make sure they're based on `EventListener` instead of something uselessly fancier.
* Unless absolutely necessary, do not store references in class objects, ever; only values. Instead, always store references in instances, to avoid both sneaky inheritance issues, and sneaky GC pinning of stale references.
  * ReaderUI: Fix one such issue with its `active_widgets` array, with critical implications, as it essentially pinned *all* of ReaderUI's modules, including their reference to the `Document` instance (i.e., that was a big-ass leak).
* Terminal: Make sure the shell is killed on plugin teardown.
* InputText: Fix Home/End/Del physical keys to behave sensibly.
* InputContainer/WidgetContainer: If necessary, compute self.dimen at paintTo time (previously, only InputContainers did, which might have had something to do with random widgets unconcerned about input using it as a baseclass instead of WidgetContainer...).
* OverlapGroup: Compute self.dimen at *init* time, because for some reason it needs to do that, but do it directly in OverlapGroup instead of going through a weird WidgetContainer method that it was the sole user of.
* ReaderCropping: Under no circumstances should a Document instance member (here, self.bbox) risk being `nil`ed!
* Kobo: Minor code cleanups.
2 years ago
NiLuJe 62059f8d68
Misc: Get rid of the legacy defaults.lua globals (#9546)
* This removes support for the following deprecated constants: `DTAP_ZONE_FLIPPING`, `DTAP_ZONE_BOOKMARK`, `DCREREADER_CONFIG_DEFAULT_FONT_GAMMA`
* The "Advanced settings" panel now highlights modified values in bold (think about:config in Firefox ;)).
* LuaData: Isolate global table lookup shenanigans, and fix a few issues in unused-in-prod codepaths.
* CodeStyle: Require module locals for Lua/C modules, too.
* ScreenSaver: Actually garbage collect our widget on close (ScreenSaver itself is not an instantiated object).
* DateTimeWidget: Code cleanups to ensure child widgets can be GC'ed.
2 years ago
poire-z a8c81a90c3
ReaderDict: fix use of dicts with ifo with DOS line endings (#9536)
Fixed in upstream sdcv, but we need to also do it in
our parsing of .ifo and picking out dict name.
Also includes minor bump of base/sdcv.
2 years ago
NiLuJe 83a2965d6b
Misc: Unify error logging on network errors (#9523)
Making sure we get the relevant information in the logs, and that the UI feedback (if any), is meaningful and readable.
2 years ago
NiLuJe 13e8213e0a
A random assortment of fixes (#9513)
* Android: Make sure sdcv can find the STL
* DocCache: Be less greedy when serializing to disk, and only do that for the *current* document ;).
* CanvasContext: Explicitly document API quirks.
* Fontlist: Switch the on-disk Persist format to zstd (it's ever so slightly faster).
* Bump base for https://github.com/koreader/koreader-base/pull/1515 (fix #9506)
2 years ago
weijiuqiao cafbf36bb2
Vocabulary builder: store word context, other tweaks and fixes (#9195)
Add a copy button and save word context (off by default), shown
via the three-dot menu of word entries.
Also some db refactoring and minor UI improvements:
- a dedicated book title table in order to shrink db size by storing
  references to title names instead of repeated actual strings,
- alignment of different forms of the "more" button and possible
 clipped words in translations.
- fix plugin name so it can be disabled
2 years ago
weijiuqiao e1b137339c
[feat, plugin] Vocabulary builder (#9132)
Made the old dictionary lookup history into a flashcard-ish vocabulary builder.
2 years ago
NiLuJe ae5b2d68ca
AutoSuspend: Don't send LeaveStandby events from a zombie plugin instance (#9124)
Long story short: the LeaveStandby event is sent via `tickAfterNext`, so if we tear down the plugin right after calling it (in this case, that means that the very input event that wakes the device up from suspend is one that kills ReaderUI or FileManager), what's in UIManager's task queue isn't the actual function, but the anonymous nextTick wrapper constructed by `tickAfterNext` (c.f., 
https://github.com/koreader/koreader/issues/9112#issuecomment-1133999385).

Tweak `UIManager:tickAfterNext` to return a reference to said wrapper, so that we can store it and unschedule that one, too, in `AutoSuspend:onCloseWidget`.

Fix #9112 (many thanks to [@boredhominid](https://github.com/boredhominid) for his help in finding a repro for this ;)).
Re: #8638, as the extra debugging facilities (i.e., ebb81b9845) added during testing might help pinpoint the root issue for that one, too.

Also includes a minor simplification to `UIManager:_checkTasks`, and various other task queue related codepaths (e.g., `WakeupMgr`) ;).
2 years ago
yparitcher 8f316b1e8c
Merge `discardEvents` & `inhibitInput` (#9065)
Rename `discardEvents` to `inhibitInputUntil`
only discard Input events
2 years ago
zwim 9b9cfe29a4
[feat] Replace TimeVal (RIP) with time, fixed point time seconds (#8999) 2 years ago
Philip Chan 107156c0a8
[feat] Non-touch improvements (#8859)
FocusManager: fix round x use y layout
FocusManager: add tab and shift tab focus navigation support
FocusManager: handle Press key by default
FocusManager: make sure selected in instance level
FocusManager: add hold event support
FocusManager: Half move instead of edge move
FocusManager: add keymap override support
FocusManager: refocusWidget will delegate to parent FocusManager
Focusmanager: refocusWidget can execute on next tick
inputtext: can move out of focus on back
inputtext: fix cannot exit for non-touch device
inputtext: fix cannot input text with kindle dx physical keyboard
fontlightwidget: add non-touch support
datetimewidget: add non-touch support
datetimewidget: fix set date failed in kindle DX, fix datetimewidget month range to 1~23 by default
datetimewidget: make hour max value to 23
multiinputdialog: add non-touch support
checkbox: focusable and focus style
virtualkeyboard: no need to press two back to unfocus inputtext
virtualkeyboard: collect FocusManager event key names to let VirtualKeyboard disable them
openwithdialog: add non-touch support
inputdialog: can close via back button
enable all InputDialog and MultiInputDialog can be close by back
keyboardlayoutdialog: non-touch support
readertoc: non touch device can expand/collapse in toc
bookstatuswidget: non touch support
keyvaluepage: non-touch support
calendarview: non-touch support
2 years ago
poire-z 0216493c43 Wikipedia: rework wiki languages internal handling
Fix various issues with stacked Wikipedia lookup results,
and follow up lookups when invoked from Wikipedia lookup
history (where going to a search for language LL would
not use language LL when hitting "Full wikipedia").
2 years ago
poire-z cc4009e88f
ReaderDictionary: merge dict & dict_ext results (#8523)
So the presence of a dict_ext and results from it
are transparent to callers.
(This fixes the warning log when dict_ext is there.)
2 years ago
poire-z 6f2fdd96f8
[chore] Fix a few luacheck errors (#8461) 3 years ago
Aleksa Sarai 3461f8af31
Dictionary: disable fuzzy search when CJK words (#8458)
Fuzzy searching doesn't work with CJK text: with Japanese,
we get large numbers of useless results because sdcv
decides to strip off the wrong part of the word.
It seems unlikely that sdcv correctly handles Korean
or Chinese, so just disable fuzzy searching on all
CJK-containing word lookups.
3 years ago
zwim 89064487b7
ReaderDictionary: Colons in menus (#8431) 3 years ago
Aleksa Sarai de7c1e20c5 languagesupport: check that ui.languagesupport is non-nil
Now that FileManager registers its UI modules in the same way as Reader,
this shouldn't be necessary but this protects us against some other app
creating a ReaderDictionary instance without having ui.languagesupport
registered properly.

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
3 years ago
Aleksa Sarai d0d2d0d1d6
*: luacheck fixes (#8368)
These weren't caught during the Japanese support plugin review.

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
3 years ago
Aleksa Sarai 7c5243667b reader: implement language-support plugin system
This creates a new plugin system which hooks into a handful of reader
operations in order to allow plugins to add language-specific support
where the default reader falls short. The two hooks added are:

 * During hold-without-pan taps, language plugins can modify the
   selection in order to better match what users expect koreader to
   highlight when selecting a single word.

   The vast majority of CJK language words are more than one character,
   but KOReader treats all CJK characters as a single word by default,
   so adding this hook means that readers no longer need to manually
   select the whole word every time they need to look something.

 * During dictionary lookup, language plugins can propose alternative
   candidate words to look up if the selected word could not be found in
   the dictionary.

   This is pretty necessary for Japanese and Korean, both of which are
   highly agglutinative languages and the fuzzy searching system of
   StarDict is simply not usable because often the inflection of the
   word is so much longer than the dictionary form that sdcv decides to
   chop off the actual word and search for the inflection (which yields
   useless results).

This system is of particular interest for readers of CJK languages
(without this, looking up words using KOReader was fairly painful) but
this system is designed to be minimal and language-agnostic enough that
other languages could make use of it by creating their own plugins if
the default "whole word" highlight and fuzzy-search system doesn't match
their needs.

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
3 years ago
Aleksa Sarai dca65a793e readerdictionary: separate out raw sdcv handling from startSdcv
In order to make startSdcv usable for plugins that might need to do
dictionary lookups in order to work, it is necessary to split out the
core of startSdcv into another method which returns the raw data from
sdcv.

In addition, in order to make it possible to amortise the cost of each
lookup (which could be fairly expensive) make it possible to pass
multiple words to rawSdcv at the same time. Sdcv supports passing
multiple words as arguments (which it then looks up in order and returns
a separate JSON array per line for each word) so we just need to tweak
the return style accordingly.

All of the deduplication and dummy results handling remains in startSdcv
because plugins might strongly depend on whether sdcv returned actual
results.

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
3 years ago
Aleksa Sarai 7a0e3d5e68 readerhighlight: remove selected_word and use selected_text everywhere
There were two ways of specifing selected text for a highlight depending
on whether it was a "single word" or text selected using hold-and-pan.
In addition to being a bit more complicated than is necessary, with the
addition of the language support plugin system (where the "single word"
selected might be expanded), it makes more sense to simply use the same
logic and table structure for both cases.

The dictionary lookup special case (hold-without-pan triggering a
dictionary lookup by default) still works as before.

In addition, this patch fixes a minor inefficiency during dictionary
quick lookup -- before this patch, the highlight would be re-selected
because the quick lookup window is run concurrently and tries to fetch
ReaderHighlight.selected_text but this is set to nil immediately after
triggering the lookup. This is unnecessary because :clear() will be
called anyway when the quick pop-up closes, and so clearing this can be
left until then.

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
3 years ago
hius07 1e47cd7e5f
SpinWidget: similar size in portrait and landscape (#8226) 3 years ago
Frans de Jonge 039947886f
Revert "Hyphenation: add custom hyphenation rules (#7746)" (#7785)
This reverts commit f25da5d0d5.
3 years ago
zwim f25da5d0d5
Hyphenation: add custom hyphenation rules (#7746)
The hyphenation of a word can be changed from its default
by long pressing for 3 seconds and selecting 'Hyphenate'.
These overrides are stored in a per-language file, i.e:
koreader/settings/user-German.hyph.
3 years ago
NiLuJe 887138f57f
ReaderDictionary: Handle all dictionaries being disabled better. (#7737)
By showing a warning, instead of not passing any -u flag to sdcv and letting it query *all* dictionaries if FS order...

Co-authored-by: Frans de Jonge <fransdejonge@gmail.com>
3 years ago
hius07 3d713dc34c
Dictionary: disable 'Clean history' when the history is empty (#7636) 3 years ago
NiLuJe 832d915795 SortWidget: More tweaks
* Support cancelling individual moves.

Coopt the cancel button to actually do just that, cancel, instead of close.

* Don't close when hitting the accept button, allowing to chain multiple moves.

Changes are still propagated to the caller on each individual move, though.

* Update the new icons to match our usual stroke width.
3 years ago
NiLuJe 3274183466 Minor Input & TimeVal cleanups
* Input: Don't create a new TimeVal object for input frame timestamps, just promote our existing table by assigning it the `TimeVal` metatable.
* TimeVal: Export (const) `zero` & `huge` TimeVal objects, because they're common enough in our codebase. (NOTE: not actually const, that's a Lua 5.4 feature ;p).
* GestureDetector: Explain the behavior of the `last_tevs` & `first_tevs` tables, and why one needs a new object and not the other.
* Speaking of, simplify the copy method for `first_tevs`, because it doesn't need to create a new TimeVal object, we can just reference the original, it's unique and re-assigned for each frame.
3 years ago
hius07 aef1e271b5
[UX] Search dialogs: don't close when searching with nothing entered (#7501)
File search, Fulltext search, Search dictionary, Search Wikipedia, DictQuickLookup: do nothing when nothing entered and search is pressed.
3 years ago
hius07 052e19ead5
Standardize search/find to search (#7398)
* Change 'Find a file' to 'File search' for consistency

There is 'File search' in the Gesture manager already.
There is 'Fulltext search' in the readermenu.
Some help text added.
3 years ago
NiLuJe 6d53f83286
The great Input/GestureDetector/TimeVal spring cleanup (a.k.a., a saner main loop) (#7415)
* ReaderDictionary: Port delay computations to TimeVal
* ReaderHighlight: Port delay computations to TimeVal
* ReaderView: Port delay computations to TimeVal
* Android: Reset gesture detection state on APP_CMD_TERM_WINDOW.
  This prevents potentially being stuck in bogus gesture states when switching apps.
* GestureDetector:
  * Port delay computations to TimeVal
  * Fixed delay computations to handle time warps (large and negative deltas).
  * Simplified timed callback handling to invalidate timers much earlier, preventing accumulating useless timers that no longer have any chance of ever detecting a gesture.
  * Fixed state clearing to handle the actual effective slots, instead of hard-coding slot 0 & slot 1.
  * Simplified timed callback handling in general, and added support for a timerfd backend for better performance and accuracy.
  * The improved timed callback handling allows us to detect and honor (as much as possible) the three possible clock sources usable by Linux evdev events.
    The only case where synthetic timestamps are used (and that only to handle timed callbacks) is limited to non-timerfd platforms where input events use
    a clock source that is *NOT* MONOTONIC.
    AFAICT, that's pretty much... PocketBook, and that's it?
* Input:
  * Use the <linux/input.h> FFI module instead of re-declaring every constant
  * Fixed (verbose) debug logging of input events to actually translate said constants properly.
  * Completely reset gesture detection state on suspend. This should prevent bogus gesture detection on resume.
  * Refactored the waitEvent loop to make it easier to comprehend (hopefully) and much more efficient.
    Of specific note, it no longer does a crazy select spam every 100µs, instead computing and relying on sane timeouts,
    as afforded by switching the UI event/input loop to the MONOTONIC time base, and the refactored timed callbacks in GestureDetector.
* reMarkable: Stopped enforcing synthetic timestamps on input events, as it should no longer be necessary.
* TimeVal:
  * Refactored and simplified, especially as far as metamethods are concerned (based on <bsd/sys/time.h>).
  * Added a host of new methods to query the various POSIX clock sources, and made :now default to MONOTONIC.
  * Removed the debug guard in __sub, as time going backwards can be a perfectly normal occurrence.
  * New methods:
    * Clock sources: :realtime, :monotonic, :monotonic_coarse, :realtime_coarse, :boottime
    * Utility: :tonumber, :tousecs, :tomsecs, :fromnumber, :isPositive, :isZero
* UIManager:
  * Ported event loop & scheduling to TimeVal, and switched to the MONOTONIC time base.
    This ensures reliable and consistent scheduling, as time is ensured never to go backwards.
  * Added a :getTime() method, that returns a cached TimeVal:now(), updated at the top of every UI frame.
    It's used throughout the codebase to cadge a syscall in circumstances where we are guaranteed that a syscall would return a mostly identical value,
    because very few time has passed.
    The only code left that does live syscalls does it because it's actually necessary for accuracy,
    and the only code left that does that in a REALTIME time base is code that *actually* deals with calendar time (e.g., Statistics).
* DictQuickLookup: Port delay computations to TimeVal
* FootNoteWidget: Port delay computations to TimeVal
* HTMLBoxWidget: Port delay computations to TimeVal
* Notification: Port delay computations to TimeVal
* TextBoxWidget: Port delay computations to TimeVal
* AutoSuspend: Port to TimeVal
* AutoTurn:
  * Fix it so that settings are actually honored.
  * Port to TimeVal
* BackgroundRunner: Port to TimeVal
* Calibre: Port benchmarking code to TimeVal
* BookInfoManager: Removed unnecessary yield in the metadata extraction subprocess now that subprocesses get scheduled properly.

* All in all, these changes reduced the CPU cost of a single tap by a factor of ten (!), and got rid of an insane amount of weird poll/wakeup cycles that must have been hell on CPU schedulers and batteries..
3 years ago
NiLuJe 2f9db25969
Unify LuaSocket usage (#7405)
* Add a new socketutil module with a few helper functions that allow us to:
  * Always use a sane User-Agent (previously, only Wikipedia did so)
  * Set timeouts in an almost sane manner. Doing it explicitly prevents an interaction with KOSync that does crazy stuff I don't even want to try to understand.
* Unified said timeouts based on the request's intended usage (except for Wikipedia, which already had meaningful timeout values).
* Stopped using LuaSec directly, LuaSocket defers to LuaSec sanely on its own. Everything now transparently supports HTTPS without code duplication.
3 years ago
NiLuJe bf6c0cdd6c
LuaSettings: Add a method to initialize a setting properly (#7371)
* LuaSettings/DocSettings: Updated readSetting API to allow proper initialization to default.
Use it to initialize tables, e.g., fixing corner-cases in readerFooter that could prevent settings from being saved.
(Fixes an issue reported on Gitter).
* LuaSettings/DocSettings: Add simpler API than the the flip* ones to toggle boolean settings.
* Update LuaSettings/DocSettigns usage throughout the codebase to use the dedicated boolean methods wher appropriate, and clean up some of the more mind-bending uses.
* FileChooser: Implement an extended default exclusion list (fix #2360)
* ScreenSaver: Refactor to avoid the pile of kludges this was threatening to become. Code should be easier to follow and use, and fallbacks now behave as expected (fix #4418).
3 years ago
poire-z 8a0d798e9e KeyValuePage: configurable items per page
Tweak building to start from items per page instead of
a fixed item height.
Guess the best font size that fit.
Update separator specification from using a "----" to
the now generic separator=true (this allows not wasting
a slot for each separator in the page and not have
only 12 items and 2 small lines in a 14 items page).
3 years ago
Markismus 67ca9c35f5
Prevent sdcv from interpreting search term starting with dash as an option (#7134) 3 years ago
poire-z 9ec3dcb376 ReaderDictionary: fix possible crash with Wikipedia
Also reword some "...canceled" to "...interrupted"
for consistency.
3 years ago
poire-z 6c23d29a8a ReaderDictionary: tweak timings if interrupted quickly
Rework b66d0be3 and 6205f260 by making that simpler
to comprehend:
- If interruption or search result window is shown in
less than 3 secondes: no specific tweak, a tap outside
will dismiss everything instantaneously.
- If done after 3 seconds: show the interruption or result
window, and discard input for a few 100ms.
- UIManager:discardEvents(): increase a bit default delays.
3 years ago
poire-z 02ac2c4ce6 DictQuickLookup: re-add "tap on title" to set as preferred dict
Restore feature removed in c98dfef7: tap on title
to set dict of current result as a preferred dictionary
for this document.
Changes from former implementation:
- trust sdcv for ordering, instead of doing it ourselves
  by looking at the results (which didn't always work)
- allow setting multiple preferred dicts
- order of preference is shown with a number as a prefix
  to the dictionary name in the title
- taping again allows removing it from preferred dicts,
  and taping again allows setting it back as the first
  preferred dict
3 years ago
poire-z 6205f26047 Dict, Trapper: prevent dismissal by past events
Add UIManager:discardEvents(), to allow dropping events
for a period of time.
Default duration of 600ms on eInk, 300ms otherwise.
Used when showing the dict result window, so that a tap
happening just when it's being shown won't discard it.
Used with Trapper:confirm()/:info(), to avoid taps made
in a previous processing to dismiss (and so, select the
cancel action) a ConfirmBox not yet painted/visible.
3 years ago
poire-z aedab2d695 Dict/Wiki lookup: less text cleanup on manual input
Don't cleanup input text as much when entered manually
(or when it's sane) than when coming from book text
selection.
This may allow looking up words like "-suffix", or
do more precise Wikipedia queries.
3 years ago
NiLuJe a5468ba385 Fix opacity of the dictionary window
Brainfart from 6162c287e8

Forgot to zap the original UIManager:show(), so we were stacking two
identical widgets on top of each other, which obviously affected alpha.

Re #7029
3 years ago
poire-z c98dfef7fc DictQuickLookup: various tweaks
- Rework widget layout to avoid implicit (and wrong)
  sizing, using proper padding/margins and correct
  measurements of components.
- Adjust lookup word font size so it's not smaller
  than the definition.
- Tweak small window positionning: keep it centered
  if possible, only move it to keep the highlighted
  word shown when we can.
- Large window: adjust to screen size correctly,
  leaving room for footer.
- Always have a "Close" button at bottom right.
  Former always displayed button "Follow link" will
  be added as a 3rd row in the rare case we select
  a word in a link.
- Replace "tap on lookup word to edit and redo the
  query" with an icon on the right: tap on it to
  edit the queries word, long-press to edit the
  current result word. Only close the current dict
  window when lookup is launched.
- Remove feature "tap on title to set current dict
  as the default dict for this document", as it didn't
  really work, and it was bad UX.
3 years ago
poire-z b66d0be3f9 ReaderDictionary: show nothing if interrupted quickly
If interrupted quickly just after lookup launch, don't
display anything (this might help avoiding refreshes
and the need to dismiss after accidental long-press
when manipulating the device).
3 years ago
poire-z cac7db1a1c InfoMessage: allows being drawn only after a delay
- InfoMessage: add an option show_delay.
- MovableContainer: avoid possible crash when
  not yet painted.
- ReaderDictionary: use show_delay=0.5 instead of
  scheduleIn(0.5n...) (a5b133da) as we need the
  InfoWidget to be known to UIManager to catch tap
  and allow interrupting lookups properly.
- ReaderDictionary: rework handling of no_refresh_on_close
  (6162c287) with proper regions comparisons
3 years ago
Frans de Jonge b8bed49a61
Pass dict_path to dictionary fix_html_func (#7057)
That way images can be made to work in a more generic, portable manner, such as:

```
return function(html, dict_path)
    html = html:gsub('<rref[^>]*>([^<]*%.jpg)</rref>', '<img src="'..dict_path..'res/%1">')
    return html
end
```

Cf. <https://github.com/koreader/koreader/issues/6056>.
3 years ago
Frans de Jonge a5b133dadc
[UX] Wait 0.5s before showing "searching for" dialog (#7012)
Fixes <https://github.com/koreader/koreader/issues/3030>.

Cross-ref to <https://github.com/koreader/koreader/pull/6998>.
3 years ago
Martín Fernández c481c5aa04
move unpackArchive to Device, use native version on android (#6959) 3 years ago
NiLuJe 6162c287e8
ReaderDictionary: Avoid an irritating refresh when dismissing the InfoMessage (#6934)
* ReaderDictionary: Don't refresh when dimissing the lookup info
InfoMessage

Re #6932

* Fix dict_largewindow in Landscape

Have to leave some room for the UI chrome
4 years ago
georgeto f31bd736f7 Allow sorting of dictionaries 4 years ago
NiLuJe 99045b4311
Minor util & ffi/util cleanups (#6657) 4 years ago