* feat(settings): refactor and implement KOReader Sync settings page
Refactors the KOReader Sync settings section into its own dedicated page and implements the full connection and configuration flow.
The previous implementation in the main server settings was outdated and incomplete. This change aligns the frontend with the latest backend logic and provides a complete user experience.
Key changes include:
- Separated the UI into two states: a login form for initial connection and a configuration panel for existing connections.
- Implemented `connectKoSyncAccount` and `logoutKoSyncAccount` mutations to handle authentication with the KOReader Sync server.
- Updated the `SERVER_SETTINGS` GraphQL fragment to use the new `koreaderSyncStrategyForward` and `koreaderSyncStrategyBackward` fields, removing the deprecated `koreaderSyncStrategy`.
- Moved all KOReader Sync settings from the generic Server Settings page to a dedicated route at `/settings/koreader-sync`.
- Restructured and improved i18n keys for better clarity and consistency.
Ran `yarn gql:codegen` to regenerate GraphQL types and helpers.
* Extract credentials login into component
* Update to server changes and cleanup
---------
Co-authored-by: schroda <50052685+schroda@users.noreply.github.com>
In case the connection got lost and the client reconnected again, there is a possibility that the auth token is expired. This will lead to the subscription to fail due to being unauthorized.
This, however, does not close the connection and the heartbeat messages are still being sent and received.
Thus, after refreshing the token, the connection is still alive but not authorized, which is the same as not having the connection open.
- Reset "requires auth" flag in session storage for reset on tab refresh
- Fix context los for resolving, rejecting queued request
- Process queued requests after successful login
Regression 6636cc66b1fixes#1028
In case it's still unknown if auth is set up on the server, only the initial request to detect this should be sent. Since all other requests will also just fail, they should be blocked until the auth initialization is completed.
While the access token is getting refreshed, no request will succeed since the access token is expired; thus, they should not be sent.
- Retry on all disconnect events
- Retry infinitely
- Cap retry backoff strategy delay at heartbeat interval (20s)
- Recreate client in case reconnecting isn't working
* Add dynamic subpath support for WebUI
- Add SubpathConfig utility for server-side subpath detection
- Configure React Router basename from server config
- Update API base URL handling for subpath compatibility
- Fix asset loading with relative paths
- Add VITE_SUBPATH environment variable for development
- Update locales and manifest paths for subpath support
Closes#174
* Move VITE_SUBPATH interface to vite-env.d.ts
* Ensure production bundle always uses relative base
When opening the reader and going back to the library, the whole category of the previous opened manga gets refetched due to the readers manga query removing the mangas tracker data from the cache which is required in the library
* [Tooling] Create script to update dependencies
* Lock dependency versions
* Update dependencies
Wait for eslint related dependencies to be compatible with v9
* Update local storage functions
* Update local storage hooks
* Add session storage
* Improve storing virtuoso grid snapshot
* Use "useSyncExternalStore" for browser storage access
* Get rid of location replacements in "AppbarSearch"
Use session storage instead to prevent reloading the page all the time due to changing the location
* Get rid of location replacements in "SourceMangas"
Use session storage instead to prevent reloading the page all the time due to changing the location
* Use "fetch" instead of "axios"
Axios does not support prioritizing requests
* Deprioritize image requests
The browser requests images (<img>) with low priority by default.
Due to switching to loading images via axios (f852ce70e7), the image requests had the same priority as other requests and thus blocked e.g. xhr requests
There seems to be cases where the connection is lost without the client being able to reconnect (e.g. active subscription -> system hibernation -> waking up system => not receiving any messages anymore).
* Create permanent subscriptions
The subscriptions have to be permanently open, otherwise, the cache gets outdated.
E.g. in case a view is open, which does not subscribe to the download updates, finished downloads are never received and thus, data of existing chapters/mangas in the cache get outdated
* [Codegen][Tool] Get latest data from cache for automatic chapter deletion after reading
The manga chapters query is on "standby" to prevent the reader from rerender in case the underlying query data updates, which would cause the reader to jump back to the beginning of the last read page.
Thus, when checking if the chapter should be automatically deleted, the data from the query can't be used, since it is outdated.
* Extend "IMangaGridProps" from "DefaultGridProps"
* Move library manga filtering into hook
* Add logic to select mangas
* Add manga actions
* Remove cache only policy for category mangas
Unclear why this was added
* Prevent SelectionFAB from being hidden by the mobile footer
On e.g. the library page, the footer is visible and thus, the fab was not completely visible
* Update categories of manga only after clicking "OK"
Previously, selecting a category resulted in an immediate mutation.
To be able to reuse the "CategorySelect" component to change the categories of multiple mangas at once, this behaviour is not suited.
* Add action to change categories of multiple mangas
* Cancel selection mode after removal from library
The mangas would still be selected and other action could get performed. However, this should only be possible for mangas that are in the library
* Remove unintentionally added console log
Accidentally added with 980da657d9
E.g. in case a manga was already loaded through the category mangas query, the query for that specific manga should not run against the server if it hasn't been executed before