Issues:
- Apache implementation relies on methods unavailable on lower Android API levels
- Using input stream implementation doesn't seem to read some files properly, but using
ZipFile implementation still requires reading the entire thing into memory
Closes#9255, sort of. The example is a bad edge case though, where chapter numbers are repeated across versions,
so realistically only the first 113 will appear but the later 113(s) won't despite being "different". Those realistically
should be in different manga entries, not all mixed together, so this is just a crappy source.
* Double tap zoom toggle
Implements a toggle that allows users to disable double tap zoom including QuickScaling for webtoons. Partially resolves#4145
* Update i18n/src/main/res/values/strings.xml
---------
Co-authored-by: arkon <arkon@users.noreply.github.com>
* Extract downloaded archives to tmp folder when loading for viewing
* Generate sequence of entries from ZipInputStream instead of loading entire ZipFile
* Drop duplicate initial call in Preference.asHotFlow
Preference.changes() always starts by returning the current value of
the preference, so asHotFlow calls block twice on the initial value.
Possible breaking change: As implemented, asHotFlow ran block(get())
before returning the flow. After this change, the first call to block
will run within the flow collection. This might cause concurrency
issues if the flow collection is late to execute.
* Inline Preference.asHotFlow
The Preference.changes().onEach().launchIn() pattern is used widely,
so the asHotFlow extension method is redundant.
Inline readImageHeaderSubscription in PageHolder
Inline readImageHeaderSubscription in PagerPageHolder and
WebtoonPageHolder by converting setImage() into a suspend function.
The image processing runs in the loadPageAndProcessStatus
continuation.
Use suspendCancellableCoroutine as a substitute for doOnUnsubscribe
in WebtoonPageHolder.
Closing openStream after the frame.setImage but before the PageHolder
is recycled causes the page display to fail for reasons that are not
currently understood.
Remove subscription handling from WebtoonViewer/WebtoonBaseHolder as
it is no longer used.
Inline statusJob into loadJob, using supervisorScope to load the page
and track status changes in parallel.
- supervisorScope does not complete until both the child loadPage
coroutine and statusFlow.collectLatest have completed.
- Cancelling supervisorScope cancels the child loadPage coroutine and
statusFlow.collectLatest.
- Use supervisorScope instead of coroutineScope to let status
collection continue if loadPage fails.
Inline progressJob into loadJob, using collectLatest's cancellation
to avoid cancelling the progressFlow collection explicitly.
- collectLatest cancels the previous action block when the flow
emits a new value. This means the DOWNLOAD_IMAGE
progressFlow.collectLatest gets automatically cancelled when
statusFlow emits a new state.
Convert launchLoadJob to suspend function, move job launch to caller,
and rename as loadPageAndProcessStatus.
Fixup for e4bc8990 (#8955)
HttpSource.fetchImage() uses Call.asObservableSuccess(), which
cancels the call on unsubscribe. This causes the call to be cancelled
before it is used, leading to a "java.net.SocketException: Socket is
closed" when trying to use the response in putImageToCache().
To fix this, use Call.awaitSuccess() via a new HttpSource.getImage()
suspending function. This addition to source-api is only intended for
app use, so it will not be added to the extensions-api stubs.
Fixes#8881
The actual issue is that the ViewModel migration actually differs between what the current `init` block
and previous `onSave` methods did; where the `init` block does not get triggered on saving the
instance on config changes.
Not entirely sure why onSaveInstanceState was explicitly avoided for config changes before, but we
just do it all the time now and end up updating the requestedPage with the current page.
* Convert downloader Observable to flow
Uses `runInterruptible` to turn the blocking call to `queue.take()`
into a cancellable call.
Flow collection is ended by cancelling the scope in `recycle`. This
means the `HttpPageLoader` can't be reused after calling `recycle`,
but this was true with the `Observable` as well.)
* Convert load Observables to suspending function
Inlining the Observables allows for some simplification of the error
handling. Behavior should be otherwise identical.
* Convert cleanup Completable to coroutine
Uses global `launchIO`, not ideal but similar to previous behavior.
Can't be scheduled on the local `scope` as this runs after `scope` is
cancelled.
* Revert "Recreate reader settings when opening sheet (#8054)"
This reverts commit acb8ab15b2.
* Revert "Fix stacking of Settings menu in the reader on multiple taps (#8002)"
This reverts commit 30ac94181b.
* Fix reader settings sheet not updated
* Fade transition between main navigation tabs
* Shared axis X between screen stacks
Activity transition is using a "close enough" shared axis X xml animation
includes:
* Use coroutines in more places
* Use domain Manga data class and effectively changing the state system
* Replace deprecated onBackPress method
Co-authored-by: arkon <arkon@users.noreply.github.com>
- Remove redundant chapter sorting logic when fetching next chapter(s)
- Remove redundant download queue checks (it'll handle already queued or downloaded items)
- Trigger download ahead when read >= 25% of chapter rather than 20%
- Rely on download cache when checking if next chapter is downloaded to avoid jank (fixes#8328)
* Clean up strings and icons
* fix incorrect usages of label_more
* restore strings and reduce usage of android.R
* removing icon desc of FABs anyway as app's not for visual impaired users
Don't block on cache renewals, but notify library on updates so that the badges show up when ready.
We skip the cache when checking if a chapter is downloaded for the reader assuming that it's a
relatively low cost to check for a single chapter.
(Probably) fixes#8254 / fixes#7847