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
This commit is contained in:
Lukas Müllner 2026-03-04 11:10:18 +01:00
parent a93694728e
commit b0b053ed80

View file

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../main.dart'; import '../main.dart';
import '../services/collection_service.dart'; import '../services/collection_service.dart';
import '../theme/app_colors.dart'; import '../theme/app_colors.dart';
@ -14,9 +15,12 @@ class CollectionsScreen extends StatefulWidget {
} }
class CollectionsScreenState extends State<CollectionsScreen> { class CollectionsScreenState extends State<CollectionsScreen> {
static const _activeCollectionPrefKey = 'active_collection_id';
List<Collection> _collections = []; List<Collection> _collections = [];
bool _isLoading = true; bool _isLoading = true;
String? _error; String? _error;
String? _activeCollectionId;
@override @override
void initState() { void initState() {
@ -35,11 +39,24 @@ class CollectionsScreenState extends State<CollectionsScreen> {
try { try {
final list = await CollectionService.getMyCollections(); 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; if (!mounted) return;
setState(() { setState(() {
_collections = list; _collections = list;
_activeCollectionId = activeId;
_isLoading = false; _isLoading = false;
}); });
if (activeId != null) {
await prefs.setString(_activeCollectionPrefKey, activeId);
}
} catch (e) { } catch (e) {
if (!mounted) return; if (!mounted) return;
setState(() { setState(() {
@ -130,6 +147,7 @@ class CollectionsScreenState extends State<CollectionsScreen> {
} }
void _openCollection(Collection c) { void _openCollection(Collection c) {
_setActiveCollection(c.id);
navigatorKey.currentState!.push( navigatorKey.currentState!.push(
MaterialPageRoute( MaterialPageRoute(
builder: (_) => GarageScreen( builder: (_) => GarageScreen(
@ -149,6 +167,14 @@ class CollectionsScreenState extends State<CollectionsScreen> {
).then((_) => _load()); ).then((_) => _load());
} }
Future<void> _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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@ -267,6 +293,8 @@ class CollectionsScreenState extends State<CollectionsScreen> {
final c = _collections[index]; final c = _collections[index];
return _CollectionCard( return _CollectionCard(
collection: c, collection: c,
isActive: _activeCollectionId == c.id,
onSetActive: () => _setActiveCollection(c.id),
onTap: () => _openCollection(c), onTap: () => _openCollection(c),
onManage: () => _manageCollection(c), onManage: () => _manageCollection(c),
); );
@ -291,11 +319,15 @@ class CollectionsScreenState extends State<CollectionsScreen> {
class _CollectionCard extends StatelessWidget { class _CollectionCard extends StatelessWidget {
final Collection collection; final Collection collection;
final bool isActive;
final VoidCallback onSetActive;
final VoidCallback onTap; final VoidCallback onTap;
final VoidCallback onManage; final VoidCallback onManage;
const _CollectionCard({ const _CollectionCard({
required this.collection, required this.collection,
required this.isActive,
required this.onSetActive,
required this.onTap, required this.onTap,
required this.onManage, 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 Column(
IconButton( children: [
icon: const Icon(Icons.settings_outlined, IconButton(
color: AppColors.textHint), tooltip: isActive ? 'Already active for scan' : 'Set active for scan',
onPressed: onManage, 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,
),
],
), ),
], ],
), ),