From b0b053ed80e3a3c2c8c5bbc2291d40dfd2f0d757 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20M=C3=BCllner?= Date: Wed, 4 Mar 2026 11:10:18 +0100 Subject: [PATCH] feat(collections): add active scan collection indicator and quick switch - Load and display persisted active collection in Collections list - Add Active badge for the currently selected scan destination - Add quick action to set any collection as active for scanner workflow - Auto-set active collection when opening a collection details view --- lib/screens/collections_screen.dart | 71 +++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 5 deletions(-) diff --git a/lib/screens/collections_screen.dart b/lib/screens/collections_screen.dart index f64b8b7..be5f0f6 100644 --- a/lib/screens/collections_screen.dart +++ b/lib/screens/collections_screen.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import '../main.dart'; import '../services/collection_service.dart'; import '../theme/app_colors.dart'; @@ -14,9 +15,12 @@ class CollectionsScreen extends StatefulWidget { } class CollectionsScreenState extends State { + static const _activeCollectionPrefKey = 'active_collection_id'; + List _collections = []; bool _isLoading = true; String? _error; + String? _activeCollectionId; @override void initState() { @@ -35,11 +39,24 @@ class CollectionsScreenState extends State { try { final list = await CollectionService.getMyCollections(); + final prefs = await SharedPreferences.getInstance(); + final persisted = prefs.getString(_activeCollectionPrefKey); + + String? activeId = persisted; + if (activeId != null && !list.any((c) => c.id == activeId)) { + activeId = list.isNotEmpty ? list.first.id : null; + } + if (!mounted) return; setState(() { _collections = list; + _activeCollectionId = activeId; _isLoading = false; }); + + if (activeId != null) { + await prefs.setString(_activeCollectionPrefKey, activeId); + } } catch (e) { if (!mounted) return; setState(() { @@ -130,6 +147,7 @@ class CollectionsScreenState extends State { } void _openCollection(Collection c) { + _setActiveCollection(c.id); navigatorKey.currentState!.push( MaterialPageRoute( builder: (_) => GarageScreen( @@ -149,6 +167,14 @@ class CollectionsScreenState extends State { ).then((_) => _load()); } + Future _setActiveCollection(String collectionId) async { + final prefs = await SharedPreferences.getInstance(); + await prefs.setString(_activeCollectionPrefKey, collectionId); + if (!mounted) return; + setState(() => _activeCollectionId = collectionId); + showGlobalSnackBar('Active scan collection set.'); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -267,6 +293,8 @@ class CollectionsScreenState extends State { final c = _collections[index]; return _CollectionCard( collection: c, + isActive: _activeCollectionId == c.id, + onSetActive: () => _setActiveCollection(c.id), onTap: () => _openCollection(c), onManage: () => _manageCollection(c), ); @@ -291,11 +319,15 @@ class CollectionsScreenState extends State { class _CollectionCard extends StatelessWidget { final Collection collection; + final bool isActive; + final VoidCallback onSetActive; final VoidCallback onTap; final VoidCallback onManage; const _CollectionCard({ required this.collection, + required this.isActive, + required this.onSetActive, required this.onTap, required this.onManage, }); @@ -377,17 +409,46 @@ class _CollectionCard extends StatelessWidget { ), ), ), + const SizedBox(width: 8), + if (isActive) + Container( + padding: const EdgeInsets.symmetric( + horizontal: 8, vertical: 2), + decoration: BoxDecoration( + color: AppColors.success.withValues(alpha: 0.14), + borderRadius: BorderRadius.circular(6), + ), + child: const Text( + 'Active', + style: TextStyle( + fontSize: 11, + fontWeight: FontWeight.w600, + color: AppColors.success, + ), + ), + ), ], ), ], ), ), - // Manage button - IconButton( - icon: const Icon(Icons.settings_outlined, - color: AppColors.textHint), - onPressed: onManage, + Column( + children: [ + IconButton( + tooltip: isActive ? 'Already active for scan' : 'Set active for scan', + icon: Icon( + isActive ? Icons.my_location : Icons.location_searching, + color: isActive ? AppColors.success : AppColors.textHint, + ), + onPressed: isActive ? null : onSetActive, + ), + IconButton( + icon: const Icon(Icons.settings_outlined, + color: AppColors.textHint), + onPressed: onManage, + ), + ], ), ], ),