Implemented as an intermediate step in the existing Global Search share intent workflow.
If any source manages to resolve the URI (e.g., a URL, a slug, etc.), the resolved SManga entry
is directly opened. If nothing gets resolved, continue to a Global Search.
* Add private extension install method
Private extensions are put inside private data directory of the running app, so
this kind of extensions can only be used by the running app and not shared with
other apps.
One limitation of private extension is the lack of deeplink handlers (if there's
any) since the extension APK is not installed to the system.
When both kinds of extensions are installed with a same package name, shared
extension (the one installed to the system) will be used unless the version
codes are different. In that case the one with higher version code will be used.
* update
Fix bug of not fetch update if manual library refresh, no auto
If somehow manga missed check period, we would not give new next update cycle and it would forever left behind
* Add support to kotlin.time APIs in the rate limit interceptor.
* Add a missing line break in the doc.
* Move the specific host to the same file.
* Add kotlin.time rule to Proguard and remove specific host rule.
* Mark the old version as deprecated and address review.
* Remove unused import.
* Remove yet another unused import.
* Add Predict Interval Test
* Get mangas next update and interval in library update
* Get next update and interval in backup restore
* Display and set intervals, nextUpdate in Manga Info
* Move logic function to MangeScreen and InfoHeader
Update per suggestion
---------
Co-authored-by: arkon <arkon@users.noreply.github.com>
* refactor: backup and restore to support cross device sync.
* chore: Updated string resources
* refactor: change function name.
* refactor: Use URI SyncHolder.kt not needed anymore.
Pinned only setting is removed in favor of the UI in the global search screen itself, which defaults to pinned only.
This needs more UX improvements, but I'm not really sure what it should be like right now.
* add pinned and available filter chips to global search
* split filter predicate into seperate function
* change the global search available filter to has Results
* reordering of imports
* feat: added migrations.
* feat: create triggers, account for new installs.
* feat: update mappers to include the new field.
* feat: update backupManga and backupChapter.
Include the new fields to be backed up as well.
* feat: add sql query to fetch all manga with `last_favorited_at` field.
* feat: version bump.
* chore: revert and refactor.
* chore: forgot to lower case the field name.
* chore: added getAllManga query as well renamed `fetchMangaWithLastFavorite` to `getMangasWithFavoriteTimestamp`
* chore: oops that's not meant to be there.
* feat: back fill and set last_modified_at to not null.
* chore: remove redundant triggers.
* fix: build error, accidentally removed insert.
* fix: build error, accidentally removed insert.
* refactor: review pointer, make fields not null.
Fixes#9564
Avoids the issue of clearing the cache when the app is backgrounded despite being in the reader.
We could do a job on idle, but we'd still need to be careful around whether the reader is active,
so this is just simpler considering it's a separate activity.
* Serialize whole chapter numbers without decimal point and add library categories to genre
* added Tachiyomi specific ComicInfo Category field
* lint
* implemented requested changes
* Dialog for service tracker removal added, anilist query prepared
* added API delete requests for Mal and Kitsu
* implement and fix tracker delete for anilist, shikimori, mangaupdates
* implement and test mal delete request
* Update to dialog text to reflect current tracker
* finish kitsu api request and block bangumi tracker removal
* Change delete flag into interface, localise strings, clean up logs
* Add shikimori delete compatibility for already existing entries
* update track delete dialog prompt to include checkbox, update strings
* Update i18n/src/main/res/values/strings.xml
Co-authored-by: stevenyomi <95685115+stevenyomi@users.noreply.github.com>
* Update i18n/src/main/res/values/strings.xml
---------
Co-authored-by: unknown <zaghdane@fireflow.de>
Co-authored-by: arkon <arkon@users.noreply.github.com>
Co-authored-by: stevenyomi <95685115+stevenyomi@users.noreply.github.com>
* Refactor updateSuccessState
- Convert to inline function
- Use when for type safety if we add other MangaScreenState types
* Replace equivalent expressions with updateSuccessState
* Replace safe cast in MangaScreen
There seems to be little value in this feature, and juggling flag masks is annoying.
Per-category sorting is still a thing, but could be refactored away from the flag in the feature.
* Replace RxJava in extension installer
Replace common downloadsRelay with Map of individual StateFlows
* Drop RxRelay dependency
* Simplify updateAllExtensions
* Simplify addDownloadState/removeDownloadState
Use immutable Map functions instead of converting to MutableMap
* Add Grace Period value and settings
* Add functions to calculate nextUpdate
* update per review
* Move more into SetMangaUpdateInterval, keep wrapper
The Dialog is handling it anyway, so this doesn't really do anything useful.
We might need to add this back if Dialog actually handles edge-to-edge properly.
* Rename removeFromQueueByPredicate to removeFromQueueIf
Follow-up to PR comment in #9511
* Make Download hashCode stable
Mutating pages would previously change the Download hashCode, which
breaks HashMap lookups.
* Convert Donwloader subscription to coroutine
Replace downloadsRelay with activeDownloadsFlow. Instead of managing
a PublishRelay independent from the queue, derive a Flow of active
downloads directly from the queue StateFlow. (This will allow
updating the queue without pausing the downloader, to be done in a
follow-up PR.)
When a download completes successfully, the downloads is removed from
queueState. This updates activeDownloadsFlow and causes the
downloaderJob start the download job for the next active download.
When a download fails, the download is left in the queue, so
queueState is not modified. To make activeDownloadsFlow update
without a change to queueState, use transformLatest and use the
Download statusFlows to suspend until a download reaches the ERROR
state.
To avoid stopping and starting downloads every time
activeDownloadsFlow emits a new value, maintain a map of current
download Jobs and only start/stop jobs in the difference between
downloadJobs and activeDownloads. To make sure all child download
jobs are cancelled when the top-level downloader job is cancelled,
use supervisorScope.
* Remove obsolete main thread references in Downloader
Thread safety of the queue state used to be guaranteed by running all
queue mutation on the main thread, but this has not been true for
some time. Since the queue state is now backed by a StateFlow,
queueState can be safely updated by any thread.
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
Fetch each source image URL immediately before downloading each image
instead of fetching all URLs and then downloading all images.
Source image URLs may change, so the downloader may fail if there is
too long a delay between fetching the image URL and downloading the
image.
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>
* added chapter swipe
* Rework corner animtion
* Update i18n/src/main/res/values/strings.xml
Co-authored-by: arkon <arkon@users.noreply.github.com>
* Replace LTR/RTL with Start/End layout
* Added label to the animation so the warning will go away
* Getting rid of the swipe threshold setting
* adding disabled option, renaming stuff, other stuff?
* Getting rid of the snackbar
* Getting rid of unecessary strings
* changing enum names as requested
* Renaming Raio to Ratio (I need a better keyboard as well -__-)
* Replacing error with download icon and action
* backup
* minor cleanup
* fixing an nasty edge case
* fixing mistakes in the previous conflict
* space
* fixing bug
fixed bug where the user could dismiss already dismissed item leading to item getting stuck
* fixing lint errors
* fixing lints (hopefully)
* Added "swipe disabled" to the list of actions
* Replacing string value and moving value as requested
* replacing rest of the strings with generic ones
---------
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
* change the directory's name for a download when the chapter's name is only composed of numbers or is blank
* maj in case the chapter name is blank or empty
* clean code
* Show soft keyboard when the text field is composed (a redo)
* Clear focus on text field when soft keyboard is hidden
* Request focus on text field and show soft keyboard
when clear button is clicked
This was effectively DDoSing sources as it does a request for every entry to get the details (primarily a cover image).
The expectation now is that users have to open individual entries to load the details/cover if needed.
This isn't necessary for most sources, which are able to provide covers as part of the listing normally.
* 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.