Feat: Add Google Drive cloud sync for multi-device sync#17
Open
kmhmubin wants to merge 21 commits into
Open
Conversation
…epository and AppSettings
…s and UI components
…cting library privacy visibility settings on the notificiation - only show the updated info if the spicy shelf is visible or hide it from update notificaiton screen
- Added SyncManager for managing sync operations with Google Drive. - Created SyncModels to define data structures for sync settings and payloads. - Introduced SyncNotifier for handling sync progress notifications. - Developed SyncStatusTracker to maintain sync execution state. - Implemented SyncWorker for background sync tasks using WorkManager. - Added StorageSyncSection UI component for managing sync settings and actions. - Created GoogleDriveLoginActivity to handle OAuth redirects and token storage.
…rs in HistoryRepository
…s and settings changes
What was wrong: - Novery skipped applying remote data when the remote payload had the same deviceId. That can break multi-device sync if device ids are duplicated/restored or stale Drive metadata is returned. - Sync restore was using backup-style replacement behavior instead of sync-style merge behavior. - Library merge could keep stale unread/progress state. - Bookmark sync could duplicate bookmarks because bookmark ids are local auto-generated ids. - Google Drive file lookup did not explicitly pull the newest modified sync file if duplicate sync files existed. Changes made: - Always merge and apply remote payload when a remote payload exists. - Sync restore now uses mergeWithExisting = true. - Library entries are merged field-by-field: remote-only books are inserted, newer reading position wins, chapter counts/read indexes are preserved correctly. - Read chapters are unioned through existing REPLACE insert behavior, so Device B should mark Device A’s read chapters as read after sync. - Bookmark restore now de-dupes by stable bookmark content key. - Google Drive now orders remote sync files by modifiedTime desc.
- Storage sync card now refreshes sync settings on screen resume, so after Google sign-in it should immediately switch from Sign in to the signed-in sync actions. - Added refreshSyncSettings() so UI can reload persisted sync state, including lastSyncTimestamp and Google Drive token state. - Reader sync now stores a stable character offset in the library record for cloud sync, instead of only a pixel offset. - Reader restore now falls back to synced library position when local per-chapter scroll cache does not exist, so another device can resume inside the synced chapter instead of starting at 0%.
- Removed the manual thread/pipe Drive upload path and replaced it with buffered gzip upload to avoid hangs/leaks on low-end devices. - Prevented concurrent sync jobs with a process-level mutex. - Changed manual sync enqueue policy from REPLACE to KEEP so active sync work is not interrupted. - Sanitized sync/sign-in error messages so raw OAuth/network exception details are not exposed. - Reduced Google Drive OAuth scope to DRIVE_APPDATA only. - Made sync notifications private/low-priority. - Remote purge now deletes duplicate sync files too. - Upload now prunes duplicate remote sync payload files. - Fixed reading stats merge restore so auto-generated Room IDs do not create duplicate stats rows.
- Automatic sync now runs as normal WorkManager background work. - Manual sync still uses foreground progress notification and cancel action. - Sync notifications are now non-fatal, so notification permission/state cannot crash the worker.
- Use a shared PreferencesManager instance for consistent sync state - Refresh sync settings after Google Drive token changes - Ensure manual sync reads fresh settings before enqueueing work - Avoid redundant token refresh during a normal Drive sync - Require battery-not-low for automatic sync jobs - Harden OAuth callback state validation
…-sync # Conflicts: # app/src/main/java/com/emptycastle/novery/data/local/dao/HistoryDao.kt # app/src/main/java/com/emptycastle/novery/data/repository/HistoryRepository.kt # app/src/main/java/com/emptycastle/novery/data/repository/LibraryRepository.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Users can now sign in with Google Drive and sync their library, reading progress, bookmarks, history, stats, and settings across devices. The sync data is stored in Google Drive’s hidden app data folder, so it does not appear in the user’s normal Drive files.
What’s Included
Safety / Privacy
appDataFolder, not user-visible Drive storage.drive.appdatascope only.Release Setup Needed
For release builds, the maintainer needs to configure Google Cloud OAuth:
API & Services->Library->Google Drive APIand clickEnable.API & Services->OAuth consent screen.Add or remove scopes..../auth/drive.appdataand.../auth/drive.fileAPI & Services->Credentials.Create credentials->OAuth client ID.Android.Novery Android Release.com.emptycastle.noverykeytool -printcert -jarfile app-standard-universal-release.apkCustom URL scheme.com.emptycastle.novery.google.oauthclient_secrets.jsonapp/src/main/assets/client_secrets.jsonapp/src/main/assets/client_secrets.jsonduring the build.For release builds, this file should be provided by the maintainer or CI build process. It should not include personal testing credentials.
Testing
Tested on physical Android devices: