fix(state): scope active collection preference by user with legacy key migration
This commit is contained in:
parent
edacf7ad1a
commit
404ac270f7
4 changed files with 86 additions and 13 deletions
|
|
@ -7,6 +7,7 @@ import 'services/main_collection_sync.dart';
|
|||
import 'screens/login_screen.dart';
|
||||
import 'screens/home_shell.dart';
|
||||
import 'utils/error_utils.dart';
|
||||
import 'utils/preferences_utils.dart';
|
||||
|
||||
// Re-export so other files can `import '../main.dart'` for these.
|
||||
export 'package:supabase_flutter/supabase_flutter.dart'
|
||||
|
|
@ -118,8 +119,6 @@ class AuthGate extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _AuthGateState extends State<AuthGate> {
|
||||
static const _activeCollectionPrefKey = 'active_collection_id';
|
||||
|
||||
bool _isLoading = true;
|
||||
bool _isInPasswordRecoveryFlow = false;
|
||||
Session? _session;
|
||||
|
|
@ -183,7 +182,7 @@ class _AuthGateState extends State<AuthGate> {
|
|||
if (userId == null) return;
|
||||
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final persisted = prefs.getString(_activeCollectionPrefKey);
|
||||
final persisted = await readActiveCollectionId(prefs, userId: userId);
|
||||
|
||||
Future<bool> hasMembership(String collectionId) async {
|
||||
final membership = await supabase
|
||||
|
|
@ -214,11 +213,15 @@ class _AuthGateState extends State<AuthGate> {
|
|||
}
|
||||
|
||||
if (nextActiveId == null) {
|
||||
await prefs.remove(_activeCollectionPrefKey);
|
||||
await clearActiveCollectionId(prefs, userId: userId);
|
||||
return;
|
||||
}
|
||||
|
||||
await prefs.setString(_activeCollectionPrefKey, nextActiveId);
|
||||
await writeActiveCollectionId(
|
||||
prefs,
|
||||
userId: userId,
|
||||
collectionId: nextActiveId,
|
||||
);
|
||||
MainCollectionSync.notifyChanged();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import '../services/collection_service.dart';
|
|||
import '../services/main_collection_sync.dart';
|
||||
import '../theme/app_colors.dart';
|
||||
import '../utils/error_utils.dart';
|
||||
import '../utils/preferences_utils.dart';
|
||||
import 'garage_screen.dart';
|
||||
import 'manage_collection_screen.dart';
|
||||
|
||||
|
|
@ -18,8 +19,6 @@ class CollectionsScreen extends StatefulWidget {
|
|||
|
||||
class CollectionsScreenState extends State<CollectionsScreen>
|
||||
with WidgetsBindingObserver {
|
||||
static const _activeCollectionPrefKey = 'active_collection_id';
|
||||
|
||||
List<Collection> _collections = [];
|
||||
bool _isLoading = true;
|
||||
String? _error;
|
||||
|
|
@ -74,8 +73,13 @@ class CollectionsScreenState extends State<CollectionsScreen>
|
|||
await CollectionService.ensureDefaultCollection();
|
||||
list = await CollectionService.getMyCollections();
|
||||
}
|
||||
final userId = supabase.auth.currentUser?.id;
|
||||
if (userId == null) {
|
||||
throw Exception('You must be signed in to load collections.');
|
||||
}
|
||||
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final persisted = prefs.getString(_activeCollectionPrefKey);
|
||||
final persisted = await readActiveCollectionId(prefs, userId: userId);
|
||||
|
||||
String? activeId = persisted;
|
||||
if (activeId == null && list.isNotEmpty) {
|
||||
|
|
@ -96,7 +100,11 @@ class CollectionsScreenState extends State<CollectionsScreen>
|
|||
});
|
||||
|
||||
if (activeId != null) {
|
||||
await prefs.setString(_activeCollectionPrefKey, activeId);
|
||||
await writeActiveCollectionId(
|
||||
prefs,
|
||||
userId: userId,
|
||||
collectionId: activeId,
|
||||
);
|
||||
if (shouldNotifySync) {
|
||||
MainCollectionSync.notifyChanged();
|
||||
}
|
||||
|
|
@ -218,8 +226,18 @@ class CollectionsScreenState extends State<CollectionsScreen>
|
|||
}
|
||||
|
||||
Future<void> _setActiveCollection(String collectionId) async {
|
||||
final userId = supabase.auth.currentUser?.id;
|
||||
if (userId == null) {
|
||||
showGlobalSnackBar('Please sign in again.', isError: true);
|
||||
return;
|
||||
}
|
||||
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString(_activeCollectionPrefKey, collectionId);
|
||||
await writeActiveCollectionId(
|
||||
prefs,
|
||||
userId: userId,
|
||||
collectionId: collectionId,
|
||||
);
|
||||
if (!mounted) return;
|
||||
setState(() => _activeCollectionId = collectionId);
|
||||
MainCollectionSync.notifyChanged();
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import '../scanner_screen.dart';
|
|||
import '../services/collection_service.dart';
|
||||
import '../services/main_collection_sync.dart';
|
||||
import '../theme/app_colors.dart';
|
||||
import '../utils/preferences_utils.dart';
|
||||
|
||||
class ScanTab extends StatefulWidget {
|
||||
const ScanTab({super.key});
|
||||
|
|
@ -14,7 +15,6 @@ class ScanTab extends StatefulWidget {
|
|||
}
|
||||
|
||||
class ScanTabState extends State<ScanTab> {
|
||||
static const _activeCollectionPrefKey = 'active_collection_id';
|
||||
static const _duplicateCooldown = Duration(seconds: 2);
|
||||
|
||||
bool _isBusy = false;
|
||||
|
|
@ -50,8 +50,13 @@ class ScanTabState extends State<ScanTab> {
|
|||
Future<void> _loadCollections() async {
|
||||
try {
|
||||
final list = await CollectionService.getMyCollections();
|
||||
final userId = supabase.auth.currentUser?.id;
|
||||
if (userId == null) {
|
||||
throw Exception('You must be signed in to load collections.');
|
||||
}
|
||||
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final persistedId = prefs.getString(_activeCollectionPrefKey);
|
||||
final persistedId = await readActiveCollectionId(prefs, userId: userId);
|
||||
|
||||
Collection? selected;
|
||||
if (persistedId != null) {
|
||||
|
|
@ -71,7 +76,11 @@ class ScanTabState extends State<ScanTab> {
|
|||
});
|
||||
|
||||
if (selected != null) {
|
||||
await prefs.setString(_activeCollectionPrefKey, selected.id);
|
||||
await writeActiveCollectionId(
|
||||
prefs,
|
||||
userId: userId,
|
||||
collectionId: selected.id,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
|
|
|
|||
43
lib/utils/preferences_utils.dart
Normal file
43
lib/utils/preferences_utils.dart
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
const _legacyActiveCollectionPrefKey = 'active_collection_id';
|
||||
|
||||
String activeCollectionPrefKeyForUser(String userId) {
|
||||
return 'active_collection_id_$userId';
|
||||
}
|
||||
|
||||
Future<String?> readActiveCollectionId(
|
||||
SharedPreferences prefs, {
|
||||
required String userId,
|
||||
}) async {
|
||||
final scopedKey = activeCollectionPrefKeyForUser(userId);
|
||||
final scopedValue = prefs.getString(scopedKey);
|
||||
if (scopedValue != null && scopedValue.isNotEmpty) {
|
||||
return scopedValue;
|
||||
}
|
||||
|
||||
final legacyValue = prefs.getString(_legacyActiveCollectionPrefKey);
|
||||
if (legacyValue == null || legacyValue.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
|
||||
await prefs.setString(scopedKey, legacyValue);
|
||||
await prefs.remove(_legacyActiveCollectionPrefKey);
|
||||
return legacyValue;
|
||||
}
|
||||
|
||||
Future<void> writeActiveCollectionId(
|
||||
SharedPreferences prefs, {
|
||||
required String userId,
|
||||
required String collectionId,
|
||||
}) {
|
||||
return prefs.setString(activeCollectionPrefKeyForUser(userId), collectionId);
|
||||
}
|
||||
|
||||
Future<void> clearActiveCollectionId(
|
||||
SharedPreferences prefs, {
|
||||
required String userId,
|
||||
}) async {
|
||||
await prefs.remove(activeCollectionPrefKeyForUser(userId));
|
||||
await prefs.remove(_legacyActiveCollectionPrefKey);
|
||||
}
|
||||
Loading…
Reference in a new issue