From a3b8900047605967fdb0bf7acebdaa0ec804e123 Mon Sep 17 00:00:00 2001 From: Herwig Birke Date: Tue, 4 Nov 2025 13:06:01 +0100 Subject: [PATCH] =?UTF-8?q?Igelliste=20sortiert,=20Notification=20bei=20?= =?UTF-8?q?=C3=84nderungen=20auf=20Detail=20Screen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/features/igel/data/igel_repository.dart | 5 +++- .../igel/presentation/igel_detail_screen.dart | 9 +++++++ .../igel/presentation/share_bottom_sheet.dart | 24 +++++++++++++++---- .../igel/presentation/share_igel_page.dart | 2 +- lib/main.dart | 6 +++++ 5 files changed, 40 insertions(+), 6 deletions(-) diff --git a/lib/features/igel/data/igel_repository.dart b/lib/features/igel/data/igel_repository.dart index 2d89c76..83a538c 100644 --- a/lib/features/igel/data/igel_repository.dart +++ b/lib/features/igel/data/igel_repository.dart @@ -9,7 +9,10 @@ class IgelRepository { Future> list() async { final res = await api.get('/igel'); final list = (res as List).cast>(); - return list.map(Igel.fromMap).toList(); + final items = list.map(Igel.fromMap).toList(); + // Sortiere nach Name (fallunabhängig, A→Z) + items.sort((a, b) => a.name.toLowerCase().compareTo(b.name.toLowerCase())); + return items; } Future create(String name, diff --git a/lib/features/igel/presentation/igel_detail_screen.dart b/lib/features/igel/presentation/igel_detail_screen.dart index 4ae9e8a..2b6d085 100644 --- a/lib/features/igel/presentation/igel_detail_screen.dart +++ b/lib/features/igel/presentation/igel_detail_screen.dart @@ -123,6 +123,15 @@ class _IgelDetailState extends ConsumerState { _shareService = ShareService(baseUrl: base); _loadAll(); + + // Rebuild when text fields change so _basicsChanged updates and Save becomes enabled. + void onAnyTextChanged() { + if (mounted) setState(() {}); + } + nameC.addListener(onAnyTextChanged); + featureC.addListener(onAnyTextChanged); + noteC.addListener(onAnyTextChanged); + locationC.addListener(onAnyTextChanged); } @override diff --git a/lib/features/igel/presentation/share_bottom_sheet.dart b/lib/features/igel/presentation/share_bottom_sheet.dart index 82643f0..553349e 100644 --- a/lib/features/igel/presentation/share_bottom_sheet.dart +++ b/lib/features/igel/presentation/share_bottom_sheet.dart @@ -24,6 +24,7 @@ class _ShareBottomSheetState extends State { final _emailCtrl = TextEditingController(); String _role = 'viewer'; Future>? _future; + final ScrollController _scrollCtrl = ScrollController(); @override void initState() { @@ -63,6 +64,13 @@ class _ShareBottomSheetState extends State { await _reload(); } + @override + void dispose() { + _scrollCtrl.dispose(); + _emailCtrl.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { final canInvite = widget.accessRole == AccessRole.owner; @@ -111,10 +119,16 @@ class _ShareBottomSheetState extends State { if (items.isEmpty) { return const Center(child: Text('Keine Freigaben')); } - return ListView.separated( + return ScrollConfiguration( + behavior: ScrollConfiguration.of(context).copyWith(scrollbars: false), + child: Scrollbar( + controller: _scrollCtrl, + child: ListView.separated( + controller: _scrollCtrl, + primary: false, itemCount: items.length, separatorBuilder: (_, __) => const Divider(height: 1), - itemBuilder: (ctx, i) { + itemBuilder: (ctx, i) { final s = items[i]; // Priorität: pending -> invitedEmail, accepted -> targetEmail @@ -126,7 +140,7 @@ class _ShareBottomSheetState extends State { ? s.targetEmail! : 'Unbekannt'); - return ListTile( + return ListTile( leading: Icon( s.status == 'accepted' ? Icons.check_circle_outline @@ -158,7 +172,9 @@ class _ShareBottomSheetState extends State { ], ), ); - }, + }, + ), + ), ); }, ), diff --git a/lib/features/igel/presentation/share_igel_page.dart b/lib/features/igel/presentation/share_igel_page.dart index 0caea61..c7401b4 100644 --- a/lib/features/igel/presentation/share_igel_page.dart +++ b/lib/features/igel/presentation/share_igel_page.dart @@ -69,7 +69,7 @@ class _SharedIgelPageState extends State { subtitle: Text('Rolle: ${it.role} · Owner: $ownerLabel'), onTap: () { // Detail öffnen; 'from=shared' sorgt dafür, dass der Back-Button wieder hierher führt - context.push('/igel/${it.id}?role=${it.role}&from=shared}'); + context.push('/igel/${it.id}?role=${it.role}&from=shared'); }, ); }, diff --git a/lib/main.dart b/lib/main.dart index 9df80ce..12f27c2 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -38,6 +38,12 @@ class AppScrollBehavior extends MaterialScrollBehavior { PointerDeviceKind.trackpad, PointerDeviceKind.unknown, }; + + // Disable automatic Scrollbar wrapping; use explicit Scrollbars where needed. + @override + Widget buildScrollbar(BuildContext context, Widget child, ScrollableDetails details) { + return child; + } } void main() {