Commit Graph

451 Commits

Author SHA1 Message Date
schroda
70f3036f58 Fix NullPointerException (#2056) 2026-05-19 17:05:09 -04:00
schroda
c0618fcc5c Try to keep cached images usable on manga rename (#2052) 2026-05-18 14:17:52 -04:00
schroda
9686f75a2d Fix/losing downloads on manga rename during update (#2051)
* Fix renaming manga download dir

* Simplify manga download dir rename function

---------

Co-authored-by: Mitchell Syer <Syer10@users.noreply.github.com>
2026-05-18 14:05:21 -04:00
schroda
4d5307f15b Fix/chapter list update preserving download state (#2050)
* Fix preserving chapter download state of deleted chapters

* Fix preserving chapter download state of updated chapters
2026-05-18 14:04:49 -04:00
Constantin Piber
779229a48a Fix tests (#2049)
* Fix test setup

* Fix tests

* Disable broken CloudflareTest

* Add a basic test for Android's Looper
2026-05-18 14:04:39 -04:00
schroda
6870922784 Fix chapter update failure db rollback (#2040)
The deletion of chapter data was done in its own transaction. Thus, when the update or insertion failed later on, the deletion was not rolled back

fixes #2031

Co-authored-by: Mitchell Syer <Syer10@users.noreply.github.com>
2026-05-16 19:08:38 -04:00
AeonLucid
a4b647972e Add default pageCount value to fix PSQLException (#2039)
* Add default pageCount value to fix PSQLException

* Update CHANGELOG.md
2026-05-16 19:07:56 -04:00
Constantin Piber
a2f29ec9dc Reset update-flag on uninstall (#2025)
* Reset update-flag on uninstall

If there is an update available when the extension is uninstalled, the
table will still have the update flag, which makes no sense if it is not
installed.

Example:
```
{
  "pkgName": "eu.kanade.tachiyomi.extension.en.comix",
  "name": "Comix",
  "lang": "en",
  "versionCode": 20,
  "versionName": "1.4.20",
  "iconUrl": "/api/v1/extension/icon/tachiyomi-en.comix-v1.4.20.apk",
  "repo": "<hidden>",
  "isNsfw": true,
  "isInstalled": false,
  "isObsolete": false,
  "hasUpdate": true,
  "__typename": "ExtensionType"
},
```

* Update changelog
2026-05-14 11:44:59 -04:00
Mitchell Syer
03a95e6652 Fix New Databases (#2016)
* Standardize toSqlName

* Rename Meta Key db field since KEY is now a reserved name in H2

* Changelog entry

* Use toSqlName

* Forgot this key

* Catch any exception
2026-05-12 17:22:35 -04:00
renovate[bot]
c117d380a3 Update exposed to v1 (major) (#1868)
* Update exposed to v1

* Update Exposed

* Add Kotlinx.DateTime extensions

* Update H2

* Review comments

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Syer10 <syer10@users.noreply.github.com>
2026-05-12 12:53:41 -04:00
Constantin Piber
76686db6a1 [#1974] Uninstall extension completely on install failure (#1975)
* [#1974] Uninstall extension completely on install failure

* Add changelog entry

---------

Co-authored-by: Mitchell Syer <Syer10@users.noreply.github.com>
2026-05-05 10:04:50 -04:00
AwkwardPeak7
031890deb6 extract apk icon (#1966) 2026-05-02 17:21:13 -04:00
ItsGlassPlus1
0f149c9b33 Add JXL container format support (#1951) 2026-05-02 17:21:01 -04:00
Mitchell Syer
146290283f ChildFirstClassLoader (#1873)
* ChildFirstClassLoader

* Lint

* ChildFirstURLClassLoader

* Fix reference
2026-01-29 18:48:33 -05:00
Constantin Piber
02da884f17 fix: Do not return inputStream from conversion & handle conversion error (#1854)
* fix: Do not return `inputStream` from conversion

The returned value must be owned, since the caller closes the input
stream on success

* fix: Assume a conversion error consumes the input stream

e.g. converting an ARGB png to jpeg will throw "bogus colorspace", but
only after the inputstream is consumed. so in case of an exception, we
have to assume that the stream is broken and re-open the page from cache
2026-01-11 16:48:16 -05:00
Constantin Piber
9f60bb8f3e Fix Kitsu to use library_id properly (#1843)
Same as mihonapp/mihon#2609
2026-01-03 12:54:49 -05:00
Mitchell Syer
7eb752654b Shikimori tracker (#1839)
* Shikimori tracker

* Add authUrl and callback

* Add OAuth id and secret
2026-01-03 12:54:30 -05:00
schroda
3b36ec550d Remove koreader sync server address from settings (#1807)
Should have been done with 4dbd9d70d2
2025-12-06 12:38:45 -05:00
renovate[bot]
83c94c044d Update dependency com.pinterest.ktlint:ktlint-cli to v1.8.0 (#1786)
* Update dependency com.pinterest.ktlint:ktlint-cli to v1.8.0

* Format

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Syer10 <syer10@users.noreply.github.com>
2025-12-06 12:37:19 -05:00
FadedSociety
0a7e6cce87 Remote Image Processing (#1684)
* Update ServerConfig.kt

* Update ConversionUtil.kt

* Update Page.kt

* Update ServerConfig.kt

fixed deletions caused by ide

* Update ServerConfig.kt

* Update ServerConfig.kt

* Cleanup

* Post-processing terminology

* More comments

* Lint

* Add known image mimes

* Fix weird mime set/get

* Implement different downloadConversions and serveConversions

* Lint

* Improve Post-Processing massivly

* Fix thumbnail build

* Use Array for headers

* Actually fix headers

* Actually fix headers 2

* Manually parse DownloadConversion

* Cleanup parse

* Fix write

* Update TypeName

* Optimize imports

* Remove header type

* Fix build

---------

Co-authored-by: Syer10 <syer10@users.noreply.github.com>
2025-11-12 16:23:34 -05:00
schroda
8e405e3996 Fix/manga update of title and download folder (#1774)
* Use "move" instead of "renameTo"

* Add additional checks for download folder rename

* Log exception during manga download folder rename
2025-11-08 19:38:35 -05:00
schroda
4dbd9d70d2 Fix/remove koreader-sync credentials from server config (#1758)
* Remove koreader-sync credentials from config

These are supposed to be set via the login/logout mutations and are not meant to be set manually by the user. Thus, they are not really settings and do not belong to the config

* Reduce log levels of KoreaderSyncService
2025-11-01 14:31:07 -04:00
schroda
53c4659044 Optionally allow basic auth fallback for chapter page endpoint (#1757)
Requesting a chapter page while having a non basic auth mode (e.g. ui login) enabled caused the basic auth prompt.
However, this is only supposed to be happen for opds
2025-11-01 14:31:01 -04:00
Mitchell Syer
c9575449da Allow basic auth fallback for OPDS (#1745) 2025-10-26 12:38:02 -04:00
Constantin Piber
bc6e28cabe OPDS: Offer CBZ in older mimetype (#1731)
* OPDS: Offer CBZ in older mimetype

* OPDS: Include length when offering CBZ download

* Disable compression on CBZ endpoint

Zipping a zip

* CBZ download match content type of OPDS

* Move compression disable

* Introduce setting for configuring CBZ mimetype

* Document new option

[no-ci]

* Update server/src/main/kotlin/suwayomi/tachidesk/opds/impl/OpdsEntryBuilder.kt

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

---------

Co-authored-by: Mitchell Syer <Syer10@users.noreply.github.com>
2025-10-24 18:36:59 -04:00
Constantin Piber
68492bf591 Actually set Track ID when updating track (#1726) 2025-10-20 13:56:08 -04:00
schroda
7b5d96189e Feature/automatic backup flags (#1702)
* Add backup flags to auto backups

* Mark ServerConfig properties as deprecated

---------

Co-authored-by: Mitchell Syer <Syer10@users.noreply.github.com>
2025-10-14 19:40:46 -04:00
schroda
8d119fd710 Feature/cleanup backup logic (#1701)
* Extract global metadata backup logic into BackupGlobalMetaHandler

* Extract category backup logic into BackupCategoryHandler

* Extract source backup logic into BackupSourceHandler

* Extract manga backup logic into BackupMangaHandler
2025-10-14 19:37:29 -04:00
schroda
0d79ac68f8 Feature/backup import add backup flags (#1697)
* Add backup flags to backup restore

* Cleanup default backup flags handling

* Optionally exclude manga from backup
2025-10-05 18:52:45 -04:00
Constantin Piber
02aada7f08 [#1676] Reorder source pages (#1683)
Some sources don't properly index their pages in some situations, so
follow Mihon and reindex
2025-10-03 10:38:10 -04:00
Mitchell Syer
fb05371ac2 Add way to exclude settings from backups (#1682)
* Add way to exclude settings from backups

* Exclude flaresolverrEnabled

* Exclude usernames/passwords

* Exclude writing deprecated settings to the backup

* Exclude AuthMode
2025-10-03 10:37:50 -04:00
schroda
9062252939 Fix/server config duplicated types (#1672)
* Move "serverConfig" to "server-config" module

* Remove duplicated types

Unintentionally introduced with 8ef2877040
2025-09-29 11:24:26 -04:00
Soner Köksal
bfccbaf731 Optimize database performance with HikariCP and transaction batching (#1660)
* Optimize database performance with HikariCP and transaction batching

- Add HikariCP-7.0.2 connection pooling with Raspberry Pi optimized settings
- Consolidate database transactions in DirName, ChapterForDownload, and ChapterDownloadHelper
- Remove duplicate queries and unused methods from ChapterForDownload
- Batch database operations to reduce transaction overhead
- Add shared query functions to eliminate redundant database calls
- Configure memory settings for build optimization

Performance improvements:
- DirName functions: 99% faster (29s → 0.1s)
- ChapterDownloadHelper: 99.5% faster (54s → 0.3s)
- ChapterForDownload: 97% faster transaction operations
- Overall system: 75% faster execution time (242s → 60s)

* Fix review comments
2025-09-23 15:54:09 -04:00
Mitchell Syer
fafcaa222c Update Dex2Jar (#1644) 2025-09-15 09:25:20 -04:00
Mitchell Syer
3f4dd2861e Fix pages after refactoring downloads (#1639) 2025-09-09 21:10:27 -04:00
schroda
7db947eba2 Restore server settings first (#1637)
The imported server settings might cause the active database to change.
In case this happens, the backup was restored into the wrong database.
2025-09-09 18:14:47 -04:00
schroda
2b767eb488 Fix/local manga thumbnails handling (#1630)
* Skip thumbnail download for local manga sources

Local manga sources do not require downloading thumbnails as they are stored locally.

* Always update local source manga info when browsing

When making changes to an in library local source manga, a refresh from the source was required to get the latest data.
From a user perspective, this is unexpected behavior that looks like a bug.

If, for example, the thumbnail file extension got changed, the file could not be found anymore and an error was shown in the client. To fix this, a manga refresh was required.
2025-09-09 18:14:01 -04:00
Mitchell Syer
679e2c0da9 Optimize Download Queue (#1627)
* Optimize download Queue

* Lint

* Fix name of DownloadStatus file

* Re-add synchronous status fetch
2025-09-09 18:13:31 -04:00
Zeedif
257e1dd03d refactor(kosync): introduce differentiated sync strategies (#1624)
* refactor(kosync): introduce differentiated sync strategies

Replaces the single `koreaderSyncStrategy` setting with `koreaderSyncStrategyForward` and `koreaderSyncStrategyBackward`. This allows users to define distinct conflict resolution behaviors based on whether the remote progress is newer or older than the local progress.

The `KoreaderSyncStrategy` enum has been simplified to `KoreaderSyncConflictStrategy` with four clear options: `PROMPT`, `KEEP_LOCAL`, `KEEP_REMOTE`, and `DISABLED`. The ambiguous `SILENT` option is removed, as its behavior is now implicitly covered by selecting `KEEP_REMOTE` for forward syncs and `KEEP_LOCAL` for backward syncs.

The legacy `koreaderSyncStrategy` setting is now deprecated and is seamlessly migrated to the new dual-strategy system using `MigratedConfigValue`, ensuring backward compatibility for existing user configurations.

* fix(kosync): correct proto numbers and setting order for sync strategies

* fix(kosync): proto number 78 to 68

* fix(server): migrate KOReader sync strategy during settings cleanup

Add migration logic to convert the old `server.koreaderSyncStrategy` key
into the new `server.koreaderSyncStrategyForward` and
`server.koreaderSyncStrategyBackward` keys during server setup.
2025-09-09 18:12:53 -04:00
Mitchell Syer
dc79b4c90a Support PostgreSQL Databases (#1617)
* Support PostgreSQL Databases

* Set the database Schema

* See if we can test postgres

* Another test

* Disable node container

* Update database when changed

* Simplify test workflow

* Only exit on failed migrations

* Run the first databaseUp sync

* Map the port

* Use absolute path for LD_PRELOAD

* Timeout after 1m

* Open the server in both database configurations

* Only exit on migration failed in ci

* Lint

* Use new ServerConfig configuration
2025-09-02 12:29:09 -04:00
Mitchell Syer
ddedceeded Support null preference keys (#1623) 2025-09-01 17:03:21 -04:00
schroda
8ef2877040 Feature/streamline settings (#1614)
* Cleanup graphql setting mutation

* Validate values read from config

* Generate server-reference.conf files from ServerConfig

* Remove unnecessary enum value handling in config value update

Commit df0078b725 introduced the usage of config4k, which handles enums automatically. Thus, this handling is outdated and not needed anymore

* Generate gql SettingsType from ServerConfig

* Extract settings backup logic

* Generate settings backup files

* Move "group" arg to second position

To make it easier to detect and have it at the same position consistently for all settings.

* Remove setting generation from compilation

* Extract setting generation code into new module

* Extract pure setting generation code into new module

* Remove generated settings files from src tree

* Force each setting to set a default value
2025-09-01 17:02:58 -04:00
schroda
9a33e3808a Feature/graphql settings add jwt settings (#1612)
* Add jwt settings to grapqhl SettingsType

* Sort proto BackupServerSettings by ProtNumber
2025-08-24 12:35:59 -04:00
Zeedif
a5d64be197 fix(kosync): use correct partial hash for binary checksum (#1610)
When generating a hash on-the-fly for the binary checksum method, the code was performing a full MD5 hash of the entire file stream. This was incorrect as the KOReader binary method expects a specific partial hash (reading small chunks at different offsets).

This change ensures that when an in-memory CBZ is created, it is first written to a temporary file. Then, the correct `KoreaderHelper.hashContents()` function is used on that file to generate the partial hash, matching KOReader's logic. The temporary file is deleted immediately after.
2025-08-24 12:35:38 -04:00
Zeedif
f46745d70c feat(kosync): Implement On-the-Fly Deterministic Hashing for KOReader Sync (#1606)
* fix(archive): unify CBZ generation to produce deterministic archives

Previously, CBZ files generated on-the-fly (`FolderProvider`) had a different hash than those created directly (`ArchiveProvider`), even with identical content. This inconsistency was caused by using two different ZIP libraries (`java.util.zip` vs. `org.apache.commons.compress`) and not normalizing file metadata.

This inconsistent hashing breaks binary-based synchronization with external services like KOReader Sync Server, as the same chapter could be identified as a different file on each generation.

This change ensures CBZ generation is fully deterministic by:

- Unifying both providers to use `org.apache.commons.compress`.
- Setting a fixed epoch timestamp (`time = 0L`) for all ZIP entries.
- Explicitly setting the compression method and level to `DEFLATED` with default compression.

This guarantees that a CBZ file for a given chapter will always have the same hash, regardless of how it's generated, resolving synchronization issues.

* feat(kosync): lazily generate and cache CBZ hashes for sync

Previously, KOReader progress sync in binary mode was limited to chapters explicitly downloaded as CBZ files. Chapters stored as folders lacked a hash, preventing them from being synced.

With the recent move to deterministic CBZ generation, it's now possible to create a consistent hash for any downloaded chapter on-the-fly.

This commit enhances the `getOrGenerateChapterHash` function to act as a central point for hash management. If a hash is requested for a downloaded chapter that doesn't have one cached in the database:

1.  It generates the CBZ archive in-memory from the downloaded folder or existing CBZ using `ChapterDownloadHelper.getAsArchiveStream()`.
2.  It calculates the deterministic hash of the generated archive content.
3.  It saves this hash to the `koreader_hash` column in the `Chapter` table for future use.

The cached hash is cleared when the chapter download is deleted, ensuring hashes are only tracked for available content.

This change transparently extends Koreader Sync compatibility to all downloaded chapters, regardless of their storage format, without requiring users to pre-convert their library to CBZ.

* fix: rename getAsArchiveStream to getArchiveStreamWithSize
2025-08-21 19:18:27 -04:00
Constantin Piber
8547159eec Basic JWT implementation (#1524)
* Basic JWT implementation

* Move JWT to UI_LOGIN mode and bring back SIMPLE_LOGIN as before

* Update server/src/main/kotlin/suwayomi/tachidesk/global/impl/util/Jwt.kt

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

* Refresh: Update only access token

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

* Implement JWT Audience

* Store JWT key

Generates the key on startup if not set

* Handle invalid Base64

* Make JWT expiry configurable

* Missing value parse

* Update server/src/main/kotlin/suwayomi/tachidesk/global/impl/util/Jwt.kt

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

* Simplify Duration parsing

* JWT Protect Mutations

* JWT Protect Queries and Subscriptions

* JWT Protect v1 WebSockets

* WebSockets allow sending token via protocol header

* Also respect the `suwayomi-server-token` cookie

* JWT reduce default token expiry

* JWT Support cookie on WebSocket as well

* Lint

* Authenticate graphql subscription via connection_init payload

* WebView: Prefer explicit token over cookie

This hack was implemented because WebView sent `"null"` if no token was
supplied, just don't send a bad token, then we can do this properly

* WebView: Implement basic login dialog if no token supplied

---------

Co-authored-by: Mitchell Syer <Syer10@users.noreply.github.com>
Co-authored-by: schroda <50052685+schroda@users.noreply.github.com>
2025-08-20 18:04:48 -04:00
Zeedif
82ad2fbe80 feat(opds): Enhance KOSync Conflict Handling and Reliability (#1602)
* feat(opds): Enhance KOSync conflict handling and reliability

This commit introduces several improvements to the KOSync integration within the OPDS feed, focusing on fixing bugs, improving network stability, and enhancing user feedback during synchronization conflicts.

- fix(sync): Corrects a KOSync JSON deserialization issue by mapping the `updated_at` field from the server response to the `timestamp` property in the client's data model. This resolves a critical bug where remote progress was being ignored.
- fix(sync): Adds a `Connection: close` header to all KOSync API requests. This prevents `unexpected end of stream` errors by ensuring a fresh connection is used, improving network reliability.
- feat(opds): Resolve sync conflicts by generating separate OPDS entries for local and remote progress. This aligns with the OPDS-PSE specification's implicit design of one stream link per entry. Instead of incorrectly adding multiple links to a single entry, the feed now presents two distinct, clearly labeled entries, allowing users to choose their desired reading position from compatible clients.
- chore(sync): Adds detailed debug logging for KOSync `GET` and `PUT` requests, including request URLs, sent data, and received responses. This improves traceability and makes debugging future issues significantly easier.

* change synced icon

* unnecessary comments removed
2025-08-20 18:03:33 -04:00
Zeedif
a414860626 fix(api): optimize HEAD requests for chapter downloads (#1601)
Previously, handling a HEAD request on the chapter download endpoint was inefficient as it triggered the full CBZ file generation process in-memory just to retrieve metadata like Content-Length and Content-Disposition. This caused unnecessary latency especially for OPDS clients.

This commit introduces a separate, lightweight path for HEAD requests.

- A new `getCbzMetadataForDownload` method is added to `ChapterDownloadHelper` to calculate the filename and file size without generating an archive stream.
- The `ChaptersFilesProvider` interface is updated with a `getArchiveSize()` method, implemented by both `ArchiveProvider` and `FolderProvider`, to retrieve the total size.
- The `MangaController` now differentiates between GET and HEAD methods, invoking the appropriate helper to ensure HEAD requests are served instantly with only the required metadata.
2025-08-20 18:03:26 -04:00
Mitchell Syer
7a0d3a1efe Expose the Source baseUrl (#1585)
* Expose the source baseUrl

* Lint
2025-08-19 15:01:14 -04:00
Zeedif
590e43c827 feat(sync/koreader): Add KOReader reading progress synchronization (#1560)
* feat(sync/koreader): implement reading progress synchronization

This commit introduces a comprehensive integration with KOReader Sync Server to enable two-way synchronization of reading progress.

The core logic is encapsulated in a new `KoreaderSyncService`, which handles authentication, registration, and progress pushing/pulling based on user-defined strategies (LATEST, KOSYNC, SUWAYOMI).

Key changes include:

- A new GraphQL API is added to manage the KOReader Sync connection:
  - `connectKoSyncAccount` mutation provides a simplified flow that attempts to log in and, if the user doesn't exist, automatically registers them.
  - `logoutKoSyncAccount` mutation to clear credentials.
  - `koSyncStatus` query to check the current connection status.

- Reading progress is now synchronized at key points:
  - The `fetchChapterPages` mutation pulls the latest progress from the sync server before loading the reader. It respects the configured sync strategy and updates the local database if necessary.
  - The `updateChapters` and other progress-updating methods now push changes to the sync server automatically.
- OPDS chapter entries also pull the latest progress, ensuring clients receive up-to-date reading status.

- Supporting backend changes have been made:
  - The `Chapter` table is extended with a `koreader_hash` column to uniquely identify documents. A database migration is included.
  - New configuration options are added to `server.conf` to manage the feature (enable, server URL, credentials, strategy, etc.).

* perf(opds): defer KOReader sync to improve chapter feed performance

Removes the KOReader Sync progress-pulling logic from the `createChapterListEntry` function.

The previous implementation triggered a network request to the sync server for every single chapter when generating a list, leading to severe performance issues and slow load times on feeds with many entries.

This change reverts to the more performant approach of always linking to the chapter's metadata feed. The expensive sync operation will be handled within the metadata entry generation instead, ensuring it's only triggered on-demand for a single chapter. This restores the responsiveness of browsing chapter feeds.

* refactor(koreader): Use enums for sync settings and correct OPDS logic

Refactor Koreader Sync settings to use enums instead of raw strings for `checksumMethod` and `strategy`. This improves type safety, prevents typos, and makes the configuration handling more robust.

The changes include:
- Introducing `KoreaderSyncChecksumMethod` and `KoreaderSyncStrategy` enums.
- Updating `ServerConfig`, GraphQL types, and backup models to use these new enums.
- Refactoring `KoreaderSyncService` to work with the enum types.

Additionally, this commit fixes an issue in `OpdsEntryBuilder` where the logic for determining which sync progress to use (local vs. remote) was duplicated. The builder now correctly delegates this decision to `KoreaderSyncService.pullProgress`, which already contains the necessary strategy logic. This centralizes the logic and ensures consistent behavior.

* refactor(koreader): Improve config handling and remove redundant update

This commit combines several refactoring and cleanup tasks:

- **Koreader Sync:** The sync service is updated to use the modern `serverConfig` provider instead of the legacy `GlobalConfigManager`. This aligns it with the current configuration management approach in the project.

- **Download Provider:** A redundant `pageCount` database update is removed from `ChaptersFilesProvider`. This operation was unnecessary because the `getChapterDownloadReady` function, which is called earlier in the download process, already verifies and corrects the page count. This change eliminates a superfluous database write and fixes a related import issue.

* feat(sync/koreader)!: enhance sync strategy and add progress tolerance

This commit overhauls the KOReader synchronization feature to provide more granular control and robustness. The simple on/off toggle has been replaced with a more flexible strategy-based system.

Key changes include:
- Replaced `koreaderSyncEnabled` with a more powerful `koreaderSyncStrategy` enum.
- Introduced new sync strategies: `PROMPT`, `SILENT`, `SEND`, `RECEIVE`, and `DISABLE`, allowing for fine-grained control over the sync direction and conflict resolution.
- Added a `koreaderSyncPercentageTolerance` setting. This prevents unnecessary sync updates for minor progress differences between Suwayomi and KOReader.
- Refactored the `KoreaderSyncService` to implement the new strategies and use the configurable tolerance.
- Updated GraphQL schemas, mutations, and server configuration to remove the old setting and incorporate the new ones.
- Adjusted the backup and restore process to correctly handle the new configuration parameters.
- Modified API endpoints and internal logic to check and apply remote progress based on the selected strategy.

BREAKING CHANGE: The `koreaderSyncEnabled` setting is removed and replaced by a more granular `koreaderSyncStrategy`. The enum values for the strategy have been completely changed, making previous configurations incompatible.

* fix: remove unused imports

* feat(opds, sync): enhance Koreader sync and OPDS conflict handling

This commit introduces significant improvements to the Koreader synchronization feature, focusing on providing a better user experience for handling progress conflicts in both OPDS and GraphQL clients.

Key changes include:

- **OPDS Conflict Resolution:** When a reading progress conflict is detected, the OPDS feed for a chapter now provides two distinct "Read Online" links: one to continue from the local progress and another to continue from the synced progress from the remote device (e.g., "Continue Reading Online (Synced from KOReader)"). This empowers users to choose which progress to follow.

- **GraphQL Sync Conflict Information:** The `fetchChapterPages` GraphQL mutation now includes a `syncConflict` field in its payload. This field provides the remote device name and page number, allowing GraphQL clients to implement a user-facing prompt to resolve sync conflicts.

- **Improved Sync Strategy Handling:**
  - The `connectKoSyncAccount` mutation no longer unconditionally sets the sync strategy to `PROMPT`. It now respects the user's existing setting, preventing accidental configuration changes upon re-login.
  - The default `koreaderSyncStrategy` in the configuration is changed to `DISABLED`, providing a safer and more intuitive default for new users.

- **Refinements & Fixes:**
  - The fallback for the remote device name is now centralized within the KoreaderSyncService, defaulting to "KOReader" if not provided.
  - Renamed `KoreaderSyncStrategy.DISABLE` to `DISABLED` for consistency.
  - Updated i18n strings for OPDS links to be more descriptive and user-friendly.

* refactor(kosync): rename stream page link titles for consistency

* refactor(kosync): return SettingsType in auth mutation payloads

The `connectKoSyncAccount` and `logoutKoSyncAccount` mutations modify server settings (username and userkey) but did not previously return the updated configuration. This forced client applications to manually refetch settings to avoid a stale cache.

This change modifies the payloads for both mutations to include the full `SettingsType`.

By returning the updated settings directly, GraphQL clients like Apollo Client can automatically update their cache, simplifying client-side state management and ensuring the UI always reflects the current server configuration.

Additionally, `clientMutationId` has been added to `KoSyncConnectPayload` for consistency with GraphQL practices, aligning it with the logout mutation.

Refs: #1560

* refactor(kosync): replace KoSyncConnectPayload with ConnectResult in connect method

* fix(kosync): add koreaderSyncPercentageTolerance default setting
2025-08-19 15:00:19 -04:00