* Keep screens loaded while they're hidden and rebuild the library faster
* Count chapters in SQL for the migration list
* Show the extension list sooner and check trust against loaded stores
* Cancel the previous tracker search when searching again
* Write reader progress less often and keep its work off the main thread
* Stop rebuilding the settings search index on every key
* Watch updates for widgets only while one is placed
The query re-ran on every chapter or manga write even with no widget on
the home screen.
* Observe download pages and limit how often their progress updates
* Throttle the library update notification and write fetch data together
* Defer startup work until first use
* Move cover work off the main thread
* Make tracker calls main-safe and token refresh thread-safe
Kitsu, Shikimori and MangaBaka refresh their token under a lock like
MAL, so parallel calls no longer refresh it twice.
* Fix extension threading and make installs cancellable
The store service read response bodies on Main, which failed with
NetworkOnMainThreadException for http stores.
* Move reader work off the main thread and save progress in order
* Serialize the downloader and fix download threading
* Stop blocking on WorkManager status queries
Also removes NotificationReceiver's open chapter action: nothing sends
it, and its handler used runBlocking.
* Start migration jobs on the migrator's dispatcher
They started undispatched, so each ran on the caller's thread until its
first suspension.
* Run screen and view model work on fitting dispatchers
* Launch work that outlives a screen on the app scope
A launch on another dispatcher is dropped if the screen closes before it
starts, which dialogs that dismiss right away often do. Only the UI
follow-up stays on viewModelScope.
* Remove the coroutine helper extensions
They hid which dispatcher and scope a call used, and the GlobalScope
ones hid that it was global.
Replaces the eight ad hoc application lifetime scopes and the GlobalScope
launchUI/launchIO/launchNow helpers with a single injected
CoroutineScope(SupervisorJob() + Dispatchers.IO), qualified by
@AppCoroutineScope.
Every scope this replaces was already on IO, or named IO explicitly, so
call sites keep their dispatcher. The two that need the main thread use
scope.launchUI. Scopes with a real cancellation point keep their own:
HttpPageLoader, ShizukuInstaller and the reader viewers. Only
HttpPageLoader's page list cache save moves to the app scope, since it
runs after recycle() has cancelled the loader's own scope.
NotificationReceiver now holds the broadcast open with goAsync() while
its work runs, so the process isn't torn down mid update.
This reverts the revert of #3403. It was reverted for #3429, where
restore() dropped every download because SourceManager.get() returned
null until the extensions had loaded. That surface suspends since #3869,
so the race is gone.
* Replace java.time APIs with kotlin(x).(date)time
kotlinx-datetime explicitly says in its README that it does not cover
i18n, so we have to stick with using their toJavaX converters wherever
we localise dates and times.
Yes, some of these replacements are... questionable. But I wanted to
try and maximise the replacement for now.
* Bump kotlinx-datetime to 0.8.0
* More kotlin.time/kotlinx-datetime replacements
* Remove redundant init block & make attributes val
* Replace new use of java.time.Instant
* replace the windowInsetsPadding for navigationBarsPadding + statusBarsPadding
* Enabling TYPESAFE_PROJECT_ACCESSORS
* Adding typesafe project accessors in the app module
* Adding typesafe project accessors in the core module
* Adding typesafe project accessors in the core-metadata module
* Adding typesafe project accessors in the data module
* Adding typesafe project accessors in the domain module
* Adding typesafe project accessors in the presentation-core module
* Adding typesafe project accessors in the presentation-widget module
* Adding typesafe project accessors in the source-local module
* Adding typesafe project accessors in the source-api module
* Rolling back
* Changing TYPESAFE_PROJECT_ACCESSORS line
* Removing extra spaces
Includes side effects:
- No longer need to restart app for user agent string change to take effect
- parseAs extension function requires a Json instance in the calling context, which doesn't necessarily need to be the default one provided by Injekt