Files
maps_bookmarks/lib/pages/collections_list_page.dart
T
2026-04-13 15:59:46 +02:00

208 lines
6.7 KiB
Dart

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../l10n/app_localizations.dart';
import '../model/collection.dart';
import '../service/bookmarks_provider.dart';
import '../service/shared_link_provider.dart';
import '../service/storage.dart';
import '../widgets/collection_page_widgets/list_item_actions_widget.dart'
show ListItemActionsWidget;
import '../widgets/create_bookmark_collection_dialog.dart';
import 'collection_page.dart';
import 'search_page.dart' show SearchPage;
import 'settings_page.dart';
class CollectionsListPage extends StatefulWidget {
const CollectionsListPage({super.key});
static const String routeName = '/collections';
@override
State<CollectionsListPage> createState() => _CollectionsListPageState();
}
class _CollectionsListPageState extends State<CollectionsListPage> {
bool addingNewBookmark = false;
var bookmarkCountMap = <int, int>{};
int selectedCollectionId = -1;
Widget bottomSheetBuilder(BuildContext context) {
final titleTextFieldController = TextEditingController(
text: context
.read<SharedLinkProvider>()
.currentMapsLinkMetadata!
.placeName,
);
return SizedBox(
height: 200,
child: TextField(controller: titleTextFieldController),
);
}
void onAddButtonPressed() => showDialog(
context: context,
builder: (context) =>
CreateBookmarkCollectionDialog(onSavePressed: onCollectionSaved),
);
void onCollectionSaved(Collection collection) {
Storage.addOrUpdateCollection(collection);
setState(() {});
}
Widget collectionsListItemBuilder(
BuildContext context,
Collection collection,
) {
final selected = selectedCollectionId == collection.id;
return ListTile(
title: Text(collection.name),
onTap: () {
if (selected) {
deselectCollection();
setState(() {});
} else if (selectedCollectionId != -1 && !selected) {
selectedCollectionId = collection.id;
setState(() {});
} else {
navigateToCollection(collection.id);
}
},
onLongPress: () => addingNewBookmark
? null
: setState(() {
selectedCollectionId = collection.id;
}),
leading: const Icon(Icons.list_rounded),
selected: selected,
trailing: Text(
bookmarkCountMap[collection.id]?.toString() ?? '0',
style: Theme.of(context).textTheme.bodyMedium,
),
);
}
void navigateToCollection(int collectionId) {
BookmarksProvider.selectedCollectionId = collectionId;
Navigator.pushNamed(context, CollectionPage.routeName);
}
void onEditCollection(Collection selectedCollection) => showDialog(
context: context,
builder: (context) => CreateBookmarkCollectionDialog(
selectedCollection: selectedCollection,
onSavePressed: onCollectionSaved,
),
).whenComplete(deselectCollection);
@override
Widget build(BuildContext context) {
final collections = Storage.loadCollections();
bookmarkCountMap = Storage.loadPerCollectionBookmarkCount();
addingNewBookmark =
Provider.of<SharedLinkProvider>(context).currentMapsLinkMetadata !=
null;
return PopScope(
canPop: selectedCollectionId == -1,
onPopInvokedWithResult: (didPop, result) {
if (didPop == false) deselectCollection();
},
child: Scaffold(
appBar: AppBar(
title: addingNewBookmark
? Text(AppLocalizations.of(context)!.chooseCollection)
: Text(AppLocalizations.of(context)!.collections),
actions: [
if (addingNewBookmark)
TextButton(
onPressed: () => Provider.of<SharedLinkProvider>(
context,
listen: false,
).removeCurrentMapsLink(),
child: Text(AppLocalizations.of(context)!.cancel),
)
else
IconButton(
onPressed: () =>
Navigator.of(context).pushNamed(SearchPage.routeName),
icon: Icon(Icons.search_rounded),
),
if (!addingNewBookmark)
IconButton(
onPressed: () =>
Navigator.of(context).pushNamed(SettingsPage.routeName),
icon: Icon(Icons.settings_rounded),
),
],
),
bottomNavigationBar: addingNewBookmark
? Container(
decoration: BoxDecoration(
borderRadius: BorderRadiusGeometry.circular(12),
color: Theme.of(context).colorScheme.surfaceContainer,
),
height: 100,
child: Padding(
padding: EdgeInsetsGeometry.fromLTRB(
MediaQuery.of(context).size.width * 0.05,
15,
MediaQuery.of(context).size.width * 0.05,
MediaQuery.of(context).viewInsets.bottom,
),
child: Text(
Provider.of<SharedLinkProvider>(
context,
).currentMapsLinkMetadata!.placeName,
),
),
)
: selectedCollectionId > 0
? ListItemActionsWidget(
onDeletePressed: onDeleteCollectionPressed,
onCancelPressed: deselectCollection,
onEditPressed: () => onEditCollection(
collections.firstWhere(
(element) => element.id == selectedCollectionId,
),
),
)
: null,
floatingActionButton: FloatingActionButton(
onPressed: onAddButtonPressed,
child: Icon(Icons.add),
),
body: collections.isNotEmpty
? Center(
child: SizedBox(
width: MediaQuery.of(context).size.width * 0.9,
child: ListView.separated(
itemBuilder: (context, index) => collectionsListItemBuilder(
context,
collections.elementAt(index),
),
itemCount: collections.length,
separatorBuilder: (context, index) => SizedBox(height: 10),
),
),
)
: Center(
child: Text(AppLocalizations.of(context)!.tipCreateCollections),
),
),
);
}
void onDeleteCollectionPressed() {
Storage.deleteCollectionById(
selectedCollectionId,
).whenComplete(() => deselectCollection());
}
void deselectCollection() {
selectedCollectionId = -1;
setState(() {});
}
}