[codex] Add storage sync settings UI#14
Merged
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
This PR implements the real “Storage & sync” settings surface by introducing persisted sync settings (official vs custom), scoping auth + local cache by sync profile, and wiring new UI actions for reconnecting sync and clearing local data.
Changes:
- Adds
SyncSettingsProviderandStorageSyncControllerto drive Storage & sync settings/UI state. - Updates
PapyrusPowerSyncServiceto support profile-scoped authenticated database paths plus reconnect/clear-cache actions. - Replaces placeholder Storage & sync UI with implemented offline and authenticated experiences, with test coverage for providers, PowerSync service behavior, and UI.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| app/test/providers/sync_settings_provider_test.dart | Adds unit tests for sync settings defaults, persistence, and media storage restrictions. |
| app/test/providers/auth_provider_test.dart | Tests repository replacement behavior when switching servers. |
| app/test/powersync/powersync_service_test.dart | Updates tests for profile-scoped DB paths and adds coverage for clear/reconnect behaviors. |
| app/test/pages/profile_storage_sync_test.dart | Adds widget tests for offline/authenticated Storage & sync UI and actions. |
| app/lib/widgets/statistics/stat_card.dart | Adjusts optional action rendering in a stats card header. |
| app/lib/widgets/shared/eink_page_header.dart | Adjusts optional trailing widget rendering in header. |
| app/lib/widgets/library/selection_header.dart | Adjusts optional actions rendering in selection header. |
| app/lib/widgets/library/bulk_status_sheet.dart | Removes an unused colorScheme local. |
| app/lib/providers/sync_settings_provider.dart | Introduces persisted sync server + media storage settings and profile key derivation. |
| app/lib/providers/auth_provider.dart | Allows swapping auth repositories (used for profile/server switching). |
| app/lib/powersync/storage_sync_controller.dart | Adds a UI/controller layer to compute labels, visibility, and allowed actions. |
| app/lib/powersync/powersync_service.dart | Adds profile/user-scoped DB paths, reconnect, clear guest library, and clear authenticated cache. |
| app/lib/pages/profile_page.dart | Replaces fake Storage & sync controls with the new implemented UI and actions. |
| app/lib/pages/developer_options_page.dart | Removes unused settings UI imports and an unused helper widget. |
| app/lib/main.dart | Wires sync settings provider; scopes token storage; switches active sync profile at runtime. |
| app/lib/auth/token_store.dart | Scopes secure refresh token storage by profile key. |
| app/integration_test/powersync_books_integration_test.dart | Updates integration test DB path resolver for new signature (profile/user scoping). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
202
to
207
| Row( | ||
| mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||
| children: [ | ||
| Text(title, style: textTheme.titleMedium), | ||
| if (action != null) action!, | ||
| ?action, | ||
| ], |
Comment on lines
29
to
35
| child: Row( | ||
| children: [ | ||
| Text(title, style: Theme.of(context).textTheme.headlineMedium?.copyWith(fontWeight: FontWeight.bold)), | ||
| const Spacer(), | ||
| if (trailing != null) trailing!, | ||
| ?trailing, | ||
| ], | ||
| ), |
Comment on lines
41
to
46
| onPressed: _allSelected ? onDeselectAll : onSelectAll, | ||
| child: Text(_allSelected ? 'Deselect all' : 'Select all'), | ||
| ), | ||
| const Spacer(), | ||
| if (actions != null) actions!, | ||
| ?actions, | ||
| ], |
Comment on lines
+53
to
+59
| PapyrusApiConfig get activeApiConfig { | ||
| if (serverType == SyncServerType.official) { | ||
| return officialConfig; | ||
| } | ||
|
|
||
| return PapyrusApiConfig(serverBaseUri: Uri.parse(customApiUrl), powerSyncServiceUri: Uri.parse(customPowerSyncUrl)); | ||
| } |
Comment on lines
+115
to
135
| void _handleSyncSettingsChanged() { | ||
| final nextProfileKey = _syncSettingsProvider.activeProfileKey; | ||
| if (nextProfileKey == _activeProfileKey) { | ||
| return; | ||
| } | ||
|
|
||
| _activeProfileKey = nextProfileKey; | ||
| unawaited(_switchActiveSyncProfile()); | ||
| } | ||
|
|
||
| Future<void> _switchActiveSyncProfile() async { | ||
| _switchingSyncProfile = true; | ||
| try { | ||
| await _powerSyncService.deactivate(clearAuthenticated: false); | ||
| _authRepository = _buildAuthRepository(_syncSettingsProvider.activeApiConfig, _activeProfileKey); | ||
| await _authProvider.replaceRepository(_authRepository, bootstrapNewRepository: !_authProvider.isOfflineMode); | ||
| } finally { | ||
| _switchingSyncProfile = false; | ||
| _syncPowerSyncAuthState(); | ||
| } | ||
| } |
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.
Summary
Notes
Validation