Switch to "lingui" for better DX.
Tried to persist existing languages as much as possible.
Removed "vite-plugin-node-polyfills" because it's incompatible with "lingui"
After all pages had been loaded, the revalidation request of the first page caused the loading placeholder to not disappear anymore.
This was only a visual bug and did not affect the actual functionality.
* 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>
The server is not requesting these images through an extension; thus, it is not a problem to send them directly to the server since there is no problem of getting the server "stuck" due to extension rate limits.
Improves the image request logic by making it possible to check if an image is cached.
In case an image is cached, it does not need to be put into the image queue because it won't be sent to the server.
When scrolling really fast, the delta value could increase, which leads to incorrect trackpad detection, because the delta value is not consistent over consecutive scroll events
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.
In case the tab gets resumed, it does not get fully reloaded but does reexecute js.
This caused the initial timestamp to get overwritten and lead to the forced reload detection to be incorrect, because it assumed that the app just got loaded.
- 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