Commit Graph
8051 Commits
Author SHA1 Message Date
MajorTanyaandMitchell Syer ec614bb4c3 Use Apollo GraphQL for Trackers with GraphQL APIs (#3827)
* Add Apollo for GraphQL interactions

* Migrate AniList to use Apollo

* Migrate Shikimori to use Apollo

Not all Shikimori requests can be served by their GraphQL API (notably
they do not offer any mutations), so those remain as-is.

* Migrate Suwayomi to use Apollo

Includes leveraging some slightly newer Suwayomi features,
specifically the Double/Float filter fixes first pre-released in
2.1.1985 on 2025-10-26 and first fully released in 2.1.2100 on
2026-05-08.

Considering the tachiyomix 1.6 extension lib changes were added in
Suwayomi 2.3.2223 on 2026-06-30, I think it is fair to depend on such
sorta-recent behaviour.

* Fix temp migration names and leftovers

* Create ApolloResponse.dataOrElse extension

Because Apollo doesn't throw exceptions and instead just provides them
as response attributes, the current ApolloResponse.awaitSuccess() is
useless and will be removed shortly.

This new extension function should wrap the basic handling of an
ApolloResponse object neatly.

Co-authored-by: Mitchell Syer <6090655+Syer10@users.noreply.github.com>

* Use dataOrElse in AnilistApi.kt

* Use dataOrElse in ShikimoriApi.kt

* Use dataOrElse in SuwayomiApi.kt

* Delete obsolete ApolloCall.awaitSuccess

* Migrate Kitsu to use Apollo

Kitsu has some unfortunate edges in its GraphQL API (such as returning
nonstandard bodies which don't play well with Apollo) but this should
be an equivalent implementation.

* Extract a MangaFragment for AniList

This simplifies the queries and the converters (which can now delegate
to the MangaFragment.toTrackSearch() method internally and adjust the
track as needed).

Also move the toALUser converter to AnilistUtils.kt to keep all
converters together.

Added a scalar-mapper for AL's CountryCode type.

* Minor consistency cleanup of the queries

* Store list entry ID not title ID for Shikimori

* Extract common MangaFragment for Shikimori

Also map the ISO8601Date to a Kotlin String in the service config.

* Map Kitsu's ISO8601DateTime to kotlin.time.Instant

Utilises Apollo's own adapter-core library which provides the mapper.

Requires opting in to ExperimentalTime until the library resolves the
outdated annotation.

Co-authored-by: Mitchell Syer <6090655+Syer10@users.noreply.github.com>

* Replace Kitsu TODO comment

So much for STOPSHIP preventing me shipping this...

* Bump Apollo version to 5.1.0

* Bump apollo-adapters-core to 0.8.0

Freshly released just earlier.
This resolves having to opt in to ExperimentalTime.

* Make new utils internal to align with #3908

* Fix leftover issues from merged #3828

This PR restructured the AniList and Kitsu user objects.

* Bump apollo to 5.2.0

* Remove unused attributes from queries

* Allow custom exception handler in dataOrElse

Enables callers to manually handle specific non-200 responses.

Callers MUST close the `ApolloHttpException.body` attached to the
passed exception to avoid resource and socket leaks.

Defaults to current behaviour of (re)throwing the status code with our
HttpException.

Utilized in KitsuApi.kt to specially handle Kitsu sending a 500 error
response when deleting library IDs not actually in a user's library
and falling back to the "throw as HttpException" if it's any other
error response.

* Rethrow networking/IO exceptions

This helps to avoid masking networking problems as "This isn't in your
list" problems.

Currently, the app shows "Failed to connect to ..." when the remote
server is unreachable (e.g. downtime, DNS block, etc) because that's
the message provided by the ConnectException thrown by Android's
network stack.

This change restores that behaviour, approximately.

Not the most elegant solution but it _should_ avoid false-positive
toasts.

---------

Co-authored-by: Mitchell Syer <6090655+Syer10@users.noreply.github.com>
2026-09-28 10:34:26 +06:00
Mend Renovate 59fdf7e7fa Update dependency androidx.work:work-runtime to v2.12.0 (#4015) 2026-09-28 08:55:38 +06:00
Mend Renovate 7451c228e6 Update Gradle to v9.8.0 (#4016) 2026-09-28 08:55:25 +06:00
AntsyLich 9b5e0ae735 Show an extension's store and install failures in the extension list (#3955) 2026-09-28 08:55:09 +06:00
Mend Renovate 7f4c55176f Update dependency androidx.annotation:annotation to v1.11.0 (#4014) 2026-09-28 08:39:33 +06:00
Mend Renovate 9b4c3115db Update spotless to v8.10.3 (#4013) 2026-09-28 08:39:19 +06:00
Mend Renovate f835398094 Update metro to v1.4.5 (#4012) 2026-09-28 08:39:08 +06:00
Mend Renovate 3542143b40 Update dependency androidx.webkit:webkit to v1.17.1 (#4011) 2026-09-28 08:38:55 +06:00
Mend Renovate ba4c04fe74 Update dependency androidx.core:core to v1.19.1 (#4010) 2026-09-28 08:38:41 +06:00
Mend Renovate 087e38ad47 Update dependency androidx.compose:compose-bom-alpha to v2026.09.01 (#4009) 2026-09-28 08:38:29 +06:00
AntsyLich 09edf7dc8d Keep an installed extension's store current as stores change
Extensions only reload when the set of signing keys changes, so one could keep a store that was removed while another with the same key stayed, or a store's old name. The manager now reassigns each installed extension's store whenever the stores change.
2026-09-28 00:52:24 +06:00
AntsyLich 4f33486aa4 Clean up extension update checking
ExtensionApi only wrapped the store repository and the launch check, which matched updates again on its own. The manager now fetches listings and checks for updates itself with the statuses it already keeps, so the check covers not-loaded extensions and keeps the Extensions tab current from launch. Statuses are derived in one place, and the extension list is split before it's sorted instead of sorted twice.
2026-09-28 00:48:03 +06:00
AntsyLich 2d86a70ce2 Offer updates for extensions that aren't loaded
Extensions that aren't loaded now get updates like loaded ones, which is often what gets them loaded again. They're counted, notified and listed with the other pending updates. Every installed extension, loaded or not, records the added store whose key signed it when it loads.
2026-09-28 00:46:54 +06:00
AntsyLich 0938411053 Install and update extensions only from a store whose signing key matches
Updates come only from stores whose key the installed extension is signed with, the highest version among them. A downloaded apk must be signed with its store's key before it's installed.
2026-09-27 23:41:21 +06:00
AntsyLich ed17ece4e3 Return an entry's categories in display order
An entry's categories came back in whatever order SQLite found them. They're now ordered by position, the same order the library and the category list show.
2026-09-27 23:10:36 +06:00
AntsyLich b74e010bfe Order updates by fetch date in the queries themselves
The updates queries relied on the view's ORDER BY surviving into the query that reads from it, which SQLite doesn't promise. Each now orders by fetch date itself.
2026-09-27 23:10:14 +06:00
AntsyLich 4b48a84ec9 Keep a stored track's remote entry when restoring
Restoring over an existing track took the backup's remote id and library id but kept the stored url and title, pairing one remote entry's id with another's details. The stored track now wins like the rest of an entry's stored data, and the backup only moves its last chapter read forward.
2026-09-27 23:09:32 +06:00
AntsyLich 9a77baedcc Update an existing track in place instead of replacing it
Upserting a track for an entry and tracker that already have one updates that row, instead of the table's REPLACE deleting it and inserting a new one under a new id. Anything keyed to the old id, such as a queued tracking update, keeps working. The query, repository methods and interactor are renamed from insert to upsert to say so.
2026-09-27 23:02:26 +06:00
AntsyLich 2b4b8472bb Open a requested chapter in the reader even if its scanlator is excluded by filter
The reader builds its chapter list with excluded scanlators filtered out, so a chapter opened directly (from a deep link or a notification) whose scanlator is excluded wasn't in the list and failed to open. The requested chapter is now added back when the filter removed it.
2026-09-27 22:56:42 +06:00
AntsyLich 553762fae8 Fix reading history being double counted
Restore groups a backup's history entries by chapter before comparing them with the stored row, so a backup carrying one entry per copy of a duplicated chapter no longer adds its reading time more than once or moves the last read backwards. A removed history entry keeps its 0 instead of becoming NULL, a tracker's start date skips removed history, and the reader clears a session's start time before saving it, so overlapping saves can't count it twice.
2026-09-27 22:55:41 +06:00
AntsyLich 8bfa495f34 Assign category positions inside the database
A new category's position is computed by its insert, one after the highest, so two categories created at once can't take the same one. Inserts take a NewCategory rather than a Category whose id and position would be ignored. Reordering places any category missing from the given order after the rest instead of leaving it at a stale position. Restore still creates missing categories all or none, in backup order, and the create dialog no longer accepts an empty name.
2026-09-27 22:53:09 +06:00
AntsyLich fc5592ff75 Don't bring back extension stores removed during a refresh
A store's refreshed details are written only if the store still exists when its fetch returns, so one removed while its index was loading stays removed. The unused get query becomes contains.
2026-09-27 22:44:15 +06:00
AntsyLich 0044cc73ec Fix stored stub sources not loading and being rewritten on every reload
Stub sources loaded from the database were written into a throwaway copy of the map, so they never reached the source manager. StubSource also becomes a data class, so a stored one compares equal to the same source again and isn't rewritten on every reload.
2026-09-27 22:43:48 +06:00
AntsyLich 6ee529c5aa Apply chapter sync in one transaction
A chapter sync's removals, inserts and updates go through one ChapterRepository.updateFromRemote call, applied atomically. A failure no longer leaves some of a sync's changes written and others missing. Restore folds duplicate chapters in a backup into one before writing, and the chapter deep link looks up the synced chapter afterwards rather than relying on the sync's return value.
2026-09-27 22:41:55 +06:00
AntsyLich 4df0e6b168 Keep category orders unique while reordering
Reordering first moves every category to a temporary negative position, then assigns the final ones, so two categories never share a position mid-update. Deleting a category no longer renumbers the system category.
2026-09-27 22:37:39 +06:00
AntsyLich 986f46c09a Merge manga favorite related fields into favorite_at
Migration 16 replaces favorite, date_added and favorite_modified_at with one nullable favorite_at. A favorite whose date_added is 0 falls back to favorite_modified_at. Manga.favorite and dateAdded become getters derived from it, and restore merges it by taking the earliest non-zero time.
2026-09-27 22:37:02 +06:00
AntsyLich f8fff318ba Build manga and chapter updates with a lambda and track assigned fields
MangaUpdate and ChapterUpdate are built with a lambda that records which fields were assigned, so an update writes only those fields.
2026-09-27 22:36:13 +06:00
AntsyLich 306befb214 Restrict raw database access to the data module
app no longer touches the database directly. Backup restore's queries move into a new RestoreRepository in :data, which restores a batch of entries all or nothing, stopping between entries if cancelled, as before. The remaining direct calls (excluded scanlators, clear database, backup creation, store and category restore) go through their repositories, and the database bindings move from AppBindings into :data.
2026-09-27 22:30:51 +06:00
AntsyLich a4abb6292b Split the universal update queries into case-specific ones
Source-owned fields move out of MangaUpdate/ChapterUpdate into MangaRemoteUpdate/ChapterRemoteUpdate, which only UpdateMangaFromRemote and SyncChaptersWithSource write. Backup restore gets its own updateFromBackup queries for entries and chapters, writing only what a backup carries.
2026-09-27 21:50:38 +06:00
AntsyLich c67a33f3d4 Remove unused sync scaffold
Drops the unused version, is_syncing and last_modified_at columns and their triggers.
2026-09-27 21:47:12 +06:00
Secozzi 532575e29e Fixed entries being incorrectly marked as duplicates when tracked with some trackers (#4008)
If a tracker doesn't set `remote_id`, it defaults to 0 so comparing entries based on `remote_id` when it's 0 doesn't make sense
2026-09-26 22:53:32 +06:00
Chopper f52d890e7f Fix library search when clicking source name in manga info screen (#4002) 2026-09-22 18:10:12 +06:00
449c4e08e7 Translations update from Hosted Weblate (#3987)
* Translated using Weblate (Catalan)

Currently translated at 100.0% (958 of 958 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/ca/

* Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 100.0% (958 of 958 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/zh_Hans/

* Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 100.0% (958 of 958 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/zh_Hans/

---------

Co-authored-by: Eduard Ereza Martínez <eduard@ereza.cat>
Co-authored-by: nay nai <naynaimiaonai@gmail.com>
2026-09-20 21:33:11 +06:00
Mend RenovateandAntsyLich 57666e9207 Update sqldelight to v2.4.0 (#3985)
Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
2026-09-20 15:19:59 +00:00
Mend Renovate 73fef961e9 Update dependency me.zhanghai.android.libarchive:library to v1.1.7 (#3983) 2026-09-20 15:04:35 +00:00
AntsyLich 93a163f96e Only upload Crashlytics mapping file when building for release 2026-09-20 19:56:59 +06:00
AntsyLich 61680580dd Simplify build flags setup with distribution profile 2026-09-20 19:46:27 +06:00
AntsyLich 0de91a9c53 Remove redundant dimens.xm in :app 2026-09-20 16:36:15 +06:00
AntsyLich 2c979d2d32 Enable android.nonTransitiveRClass 2026-09-20 16:32:33 +06:00
AntsyLich 2b9cb4ca5a Refactor GenerateLocalesConfigTask to run when string files updates 2026-09-20 04:58:39 +06:00
AntsyLich 427e105840 Enable Gradle isolated projects 2026-09-20 04:58:39 +06:00
AntsyLich 12fbb13df5 Enable Gradle configuration cache 2026-09-20 04:58:38 +06:00
AntsyLich c69b14c975 Bump compileSdk to 37.2 2026-09-20 04:58:38 +06:00
AntsyLich debab6c261 Enable Gradle Tooling parallelism explicitly
Android Studio disables the backward compatibility that Gradle has for Tooling parallelism https://cs.android.com/search?q=org.gradle.tooling.parallel.ignore-legacy-default%3Dtrue&sq=
2026-09-20 04:58:38 +06:00
Mend Renovate 424bbc53b8 Update coil to v3.6.3 (#3979) 2026-09-20 03:45:51 +06:00
Mend Renovate 71cd94a31d Update dependency ubuntu to v26 (#3986) 2026-09-20 01:11:12 +06:00
MajorTanya 01e3f8c605 Add refresh button to tracker for new profile info (#3828)
* Add refresh button to tracker for new profile info

As-is, allows a user to manually refresh their current user data from
the tracker in order to update Mihon's knowledge of remote settings
(e.g. nickname changes, AL/MB/Kitsu score types, etc.).

* Catch errors to prevent app crashing

Surfaces errors as toasts in the same way library title refreshes do.

* spotless

* [skip ci] Remove leftover debugging logs

* Fix Kitsu user attribute access

* Spotless

* Lowercase Kitsu score type on refresh

Maybe prevent needing another #3887 for this.

* Center tracker vertically name if not logged in

Looks much better than the name being stuck at the top with empty
space below it.

* Don't show Refresh button for Enhanced trackers

* [skip ci] Add changelog entry
2026-09-20 00:35:25 +06:00
Mend Renovate 504ec2afae Update android.gradle to v9.4.1 (#3982) 2026-09-19 16:49:32 +00:00
hosted-weblate[bot]andMajorTanya 385d076d43 Translations update from Hosted Weblate (#3972)
Translated using Weblate (German)

Currently translated at 99.2% (948 of 955 strings)

Translation: Mihon/Mihon
Translate-URL: https://hosted.weblate.org/projects/mihon/mihon/de/

Co-authored-by: MajorTanya <github@majortanya.eu>
2026-09-19 22:39:45 +06:00
Mend Renovate 5848ffb4c4 Update metro to v1.4.4 (#3973) 2026-09-17 13:37:56 +06:00