From 09a170871b3bf280808f82d5c7d9c96e3a320985 Mon Sep 17 00:00:00 2001 From: alexdivadi Date: Fri, 20 Feb 2026 16:11:59 -0600 Subject: [PATCH 1/3] fix: on open notification screen --- lib/core/common/widgets/any_step_app_bar.dart | 4 +- .../widgets/dashboard_calendar_card.dart | 192 +++++++++--------- .../event_detail/event_detail_screen.dart | 19 +- .../data/notification_repository.dart | 33 +-- 4 files changed, 128 insertions(+), 120 deletions(-) diff --git a/lib/core/common/widgets/any_step_app_bar.dart b/lib/core/common/widgets/any_step_app_bar.dart index 39c2173..01508a6 100644 --- a/lib/core/common/widgets/any_step_app_bar.dart +++ b/lib/core/common/widgets/any_step_app_bar.dart @@ -5,6 +5,7 @@ class AnyStepAppBar extends StatelessWidget implements PreferredSizeWidget { super.key, this.title, this.actions, + this.leading, this.showBackArrow = true, this.surfaceTint, this.bottom, @@ -12,6 +13,7 @@ class AnyStepAppBar extends StatelessWidget implements PreferredSizeWidget { final Widget? title; final List? actions; + final Widget? leading; final bool showBackArrow; final Color? surfaceTint; final PreferredSizeWidget? bottom; @@ -25,7 +27,7 @@ class AnyStepAppBar extends StatelessWidget implements PreferredSizeWidget { backgroundColor: Colors.transparent, elevation: 0, actions: actions, - leading: null, + leading: leading, // titleTextStyle: AnyStepTextStyles.title.copyWith( // color: Theme.of(context).colorScheme.onSurface, // ), diff --git a/lib/core/features/dashboard/presentation/widgets/dashboard_calendar_card.dart b/lib/core/features/dashboard/presentation/widgets/dashboard_calendar_card.dart index e3d6455..3e3fdc8 100644 --- a/lib/core/features/dashboard/presentation/widgets/dashboard_calendar_card.dart +++ b/lib/core/features/dashboard/presentation/widgets/dashboard_calendar_card.dart @@ -43,90 +43,88 @@ class _DashboardCalendarCardState extends ConsumerState { child: Card( child: Padding( padding: const EdgeInsets.all(AnyStepSpacing.md16), - child: eventsAsync.when( - loading: () => SizedBox( - height: 380, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: const [ - SizedBox(height: AnyStepSpacing.md14), - Center(child: AnyStepShimmer(height: 24, width: 140)), - SizedBox(height: AnyStepSpacing.sm10), - AnyStepShimmer(height: 280), - SizedBox(height: AnyStepSpacing.md12), - AnyStepShimmer(height: 16, width: 220), - SizedBox(height: AnyStepSpacing.sm8), - AnyStepShimmer(height: 16, width: 180), - ], + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TableCalendar( + firstDay: DateTime.now().subtract(const Duration(days: 365)), + lastDay: DateTime.now().add(const Duration(days: 365)), + focusedDay: _focusedDay, + selectedDayPredicate: (day) => isSameDay(day, _selectedDay), + eventLoader: (day) { + final data = eventsAsync.value; + if (data == null) return const []; + final key = DateTime(day.year, day.month, day.day); + return data.where((event) { + return event.startTime.year == key.year && + event.startTime.month == key.month && + event.startTime.day == key.day; + }).toList(); + }, + onDaySelected: (selectedDay, focusedDay) { + setState(() { + _selectedDay = selectedDay; + _focusedDay = focusedDay; + }); + }, + onPageChanged: (focusedDay) { + setState(() => _focusedDay = focusedDay); + }, + calendarStyle: CalendarStyle( + todayDecoration: BoxDecoration( + color: Theme.of(context).colorScheme.primary.withAlpha(80), + shape: BoxShape.circle, + ), + selectedDecoration: BoxDecoration( + color: Theme.of(context).colorScheme.primary, + shape: BoxShape.circle, + ), + markerDecoration: BoxDecoration( + color: Theme.of(context).colorScheme.secondary, + shape: BoxShape.circle, + ), + markersMaxCount: 3, + ), + headerStyle: HeaderStyle( + titleCentered: true, + formatButtonVisible: false, + leftChevronIcon: Icon( + Icons.chevron_left, + color: Theme.of(context).iconTheme.color, + ), + rightChevronIcon: Icon( + Icons.chevron_right, + color: Theme.of(context).iconTheme.color, + ), + ), ), - ), - error: (e, st) => SizedBox(height: 380, child: Center(child: Text(loc.failedToLoad))), - data: (events) { - final eventsByDay = >{}; - for (final event in events) { - final dateKey = DateTime( - event.startTime.year, - event.startTime.month, - event.startTime.day, - ); - eventsByDay.putIfAbsent(dateKey, () => []).add(event); - } - final selected = _selectedDay ?? _focusedDay; - final selectedKey = DateTime(selected.year, selected.month, selected.day); - final selectedEvents = eventsByDay[selectedKey] ?? const []; + const SizedBox(height: AnyStepSpacing.md12), + eventsAsync.when( + loading: () => Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: const [ + AnyStepShimmer(height: 16, width: 220), + SizedBox(height: AnyStepSpacing.sm8), + AnyStepShimmer(height: 16, width: 180), + ], + ), + error: (_, __) => Text(loc.failedToLoad), + data: (events) { + final eventsByDay = >{}; + for (final event in events) { + final dateKey = DateTime( + event.startTime.year, + event.startTime.month, + event.startTime.day, + ); + eventsByDay.putIfAbsent(dateKey, () => []).add(event); + } + final selected = _selectedDay ?? _focusedDay; + final selectedKey = DateTime(selected.year, selected.month, selected.day); + final selectedEvents = eventsByDay[selectedKey] ?? const []; - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - TableCalendar( - firstDay: DateTime.now().subtract(const Duration(days: 365)), - lastDay: DateTime.now().add(const Duration(days: 365)), - focusedDay: _focusedDay, - selectedDayPredicate: (day) => isSameDay(day, _selectedDay), - eventLoader: (day) { - final key = DateTime(day.year, day.month, day.day); - return eventsByDay[key] ?? const []; - }, - onDaySelected: (selectedDay, focusedDay) { - setState(() { - _selectedDay = selectedDay; - _focusedDay = focusedDay; - }); - }, - onPageChanged: (focusedDay) { - setState(() => _focusedDay = focusedDay); - }, - calendarStyle: CalendarStyle( - todayDecoration: BoxDecoration( - color: Theme.of(context).colorScheme.primary.withAlpha(80), - shape: BoxShape.circle, - ), - selectedDecoration: BoxDecoration( - color: Theme.of(context).colorScheme.primary, - shape: BoxShape.circle, - ), - markerDecoration: BoxDecoration( - color: Theme.of(context).colorScheme.secondary, - shape: BoxShape.circle, - ), - markersMaxCount: 3, - ), - headerStyle: HeaderStyle( - titleCentered: true, - formatButtonVisible: false, - leftChevronIcon: Icon( - Icons.chevron_left, - color: Theme.of(context).iconTheme.color, - ), - rightChevronIcon: Icon( - Icons.chevron_right, - color: Theme.of(context).iconTheme.color, - ), - ), - ), - const SizedBox(height: AnyStepSpacing.md12), - if (selectedEvents.isEmpty) - Container( + if (selectedEvents.isEmpty) { + return Container( width: double.infinity, padding: const EdgeInsets.all(AnyStepSpacing.md12), decoration: BoxDecoration( @@ -137,21 +135,21 @@ class _DashboardCalendarCardState extends ConsumerState { loc.dashboardNoEventsCalendar, style: Theme.of(context).textTheme.bodySmall, ), - ) - else - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - for (final event in selectedEvents.take(3)) - Padding( - padding: const EdgeInsets.only(bottom: AnyStepSpacing.sm8), - child: _EventRow(event: event), - ), - ], - ), - ], - ); - }, + ); + } + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + for (final event in selectedEvents.take(3)) + Padding( + padding: const EdgeInsets.only(bottom: AnyStepSpacing.sm8), + child: _EventRow(event: event), + ), + ], + ); + }, + ), + ], ), ), ), diff --git a/lib/core/features/events/presentation/event_detail/event_detail_screen.dart b/lib/core/features/events/presentation/event_detail/event_detail_screen.dart index 1b66a7d..8270c9e 100644 --- a/lib/core/features/events/presentation/event_detail/event_detail_screen.dart +++ b/lib/core/features/events/presentation/event_detail/event_detail_screen.dart @@ -65,13 +65,22 @@ class _EventDetailScreenState extends ConsumerState { final userAsync = ref.watch(currentUserStreamProvider); final loc = AppLocalizations.of(context); + final leading = context.canPop() + ? null + : IconButton( + icon: const Icon(Icons.chevron_left), + onPressed: () { + context.go(EventFeedScreen.path); + }, + ); + return eventAsync.when( loading: () => AnyStepScaffold( - appBar: AnyStepAppBar(title: Text(loc.eventDetailTitle)), + appBar: AnyStepAppBar(title: Text(loc.eventDetailTitle), leading: leading), body: const Center(child: AnyStepLoadingIndicator()), ), error: (e, st) => AnyStepScaffold( - appBar: AnyStepAppBar(title: Text(loc.eventDetailTitle)), + appBar: AnyStepAppBar(title: Text(loc.eventDetailTitle), leading: leading), body: RefreshIndicator( onRefresh: () async => ref.invalidate(getEventProvider(widget.id)), child: ScrollableCenteredContent(child: AnyStepErrorWidget()), @@ -103,10 +112,7 @@ class _EventDetailScreenState extends ConsumerState { } }, itemBuilder: (context) => [ - PopupMenuItem( - value: _EventDetailMenuAction.share, - child: Text(loc.shareAction), - ), + PopupMenuItem(value: _EventDetailMenuAction.share, child: Text(loc.shareAction)), if (!isPast) PopupMenuItem( value: _EventDetailMenuAction.addToCalendar, @@ -125,6 +131,7 @@ class _EventDetailScreenState extends ConsumerState { appBar: AnyStepAppBar( title: Text(loc.eventDetailTitle), actions: isPast ? null : actions, + leading: leading, ), body: MaxWidthContainer( child: SafeArea( diff --git a/lib/core/features/notifications/data/notification_repository.dart b/lib/core/features/notifications/data/notification_repository.dart index 116afa4..c482587 100644 --- a/lib/core/features/notifications/data/notification_repository.dart +++ b/lib/core/features/notifications/data/notification_repository.dart @@ -13,6 +13,14 @@ import 'package:flutter/foundation.dart'; part 'notification_repository.g.dart'; +/// TODO: +/// 1. Implement IRepository in NotificationRepository +/// 2. Create a provider to fetch and paginate user notifications (scoped by user_id == usermodel.id aka authState sub), sorted by created at date +/// 3. Create a listview similar to event feed. Handle showing read and unread states. +/// 4. When the user clicks on a notification it should open a notification detail screen and automatically mark the notification as read. +/// +/// Entrypoint: Dashboard appbar action IconButton, pushes route. Only visible for authenticated users. + const String _eventIdKey = 'event_id'; String _eventDetailPath(int id) => '/events/$id'; @@ -21,9 +29,9 @@ class NotificationRepository { required FirebaseMessaging messaging, required GoRouter router, required SupabaseClient supabase, - }) : _messaging = messaging, - _router = router, - _supabase = supabase; + }) : _messaging = messaging, + _router = router, + _supabase = supabase; final FirebaseMessaging _messaging; final GoRouter _router; @@ -95,10 +103,7 @@ class NotificationRepository { content: Text(body.isEmpty ? title : '$title\n$body'), action: eventId == null ? null - : SnackBarAction( - label: 'Open', - onPressed: () => _router.go(_eventDetailPath(eventId)), - ), + : SnackBarAction(label: 'Open', onPressed: () => _router.go(_eventDetailPath(eventId))), ), ); } @@ -134,20 +139,16 @@ class NotificationRepository { if (user == null) return; try { final platform = _platformLabel(); - await _supabase.from('user_fcm_tokens').upsert( - { - 'user_id': user.id, - 'token': token, - 'platform': platform, - }, - onConflict: 'token', - ); + await _supabase.from('user_fcm_tokens').upsert({ + 'user_id': user.id, + 'token': token, + 'platform': platform, + }, onConflict: 'token'); Log.i('Synced FCM token for user ${user.id} ($platform)'); } catch (e, st) { Log.e('Failed to sync FCM token', e, st); } } - } String _platformLabel() { From e32113cc96c7da15e96a98f511b40c50b2a95483 Mon Sep 17 00:00:00 2001 From: alexdivadi Date: Fri, 20 Feb 2026 16:40:11 -0600 Subject: [PATCH 2/3] feat: android notification icon --- android/app/src/main/AndroidManifest.xml | 3 +++ .../res/drawable-hdpi/ic_stat_notification.png | Bin 0 -> 1155 bytes .../res/drawable-mdpi/ic_stat_notification.png | Bin 0 -> 624 bytes .../res/drawable-xhdpi/ic_stat_notification.png | Bin 0 -> 1659 bytes .../res/drawable-xxhdpi/ic_stat_notification.png | Bin 0 -> 3162 bytes .../drawable-xxxhdpi/ic_stat_notification.png | Bin 0 -> 4346 bytes 6 files changed, 3 insertions(+) create mode 100644 android/app/src/main/res/drawable-hdpi/ic_stat_notification.png create mode 100644 android/app/src/main/res/drawable-mdpi/ic_stat_notification.png create mode 100644 android/app/src/main/res/drawable-xhdpi/ic_stat_notification.png create mode 100644 android/app/src/main/res/drawable-xxhdpi/ic_stat_notification.png create mode 100644 android/app/src/main/res/drawable-xxxhdpi/ic_stat_notification.png diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 132750f..9610a4a 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -49,6 +49,9 @@ + To7fOMxk6NOCeXn1vPUsH8Y4P6D3QWvR>fAc4XhO zJ9EU$IYwibEsSv-pO2n@okaild2!*XPtX7S-}imq@A+-d@A+pcr5xqu?PZ3St&8SO36EAMxEX zScE7)M~x^!i1GdrumoC#H@#*SU04+=!%dh2n-EnVqbOETZ5AIIT-BcWB^1Ir@b4ke z0v^KeusYUCv4Zk=NmqChEL4;EGSr3tpf~h{-EabKON^Bg3kvS~ffp!VRHChL8}n-cOo_16eFk} z_qPOv`5!+6tug_0o!1+}cK8N#R}nmbyNG&|L{yBRJ}me%=ptieD-3|X@CTS>qzXfa0cQ6qQ^i8k^L0T;5h!JE#G_{+B z7yZfH07in=vECRz#?3#_2JV5?yEtk3#|ZkKh3A8H#+2Rxor0is%vWI?SiKK|)*BB0 z!!HOrp3^+s5F^MMvoKiUBJ{?6LHir@@K#-QoIbsCmv6|b4R(T4A zPzpbSS*D0#unQ~+y3@*TjGaNyot$d8Ax4mKq8MvY_ptai=4@p)#l5CgbeCDFdr!e! z1ReU^f-HKb^-{34SRY`0zE(6$XJL-uw*3Mj8t##4IY~MXx^gmS8R8>v_^D?OM@-68)Q>aMRZ>2v=Br-PMhyBHUqd{A?rI zLI`rlp9S_p2K918T~ZO(Y|;#5Gw=f6-;Gt8Mv!%A3iQ)L;EBUt=Q?;aa?7v|mB0!_ z?Trx?B`Bn{&6hopZLIs0?W+6N3$VYo-?pu_Lc51;_>zLG%oe@bL4bwv0Jv?qpLs;m zWtN8Xa2!FNL=ul!3%Pk3%z5DMuMjQaHsR;i;1S3@&*RV%1RYJRh8trA=?;5k@f4wT zHiPc6NSb}#qdPrJo=1>-T;dTc$i2zqa$7L7w2HzEX8UNx%mCxclgN4mc_2tUVg(r+ z9)mmxnoYV(ml!X$9$r_d?Z|1^kaSbcDvlE5Lu8sQ#!tagKJO0>lKpAMKFQ|I9~u(1 ztrg9eMv%eW3p_Nsqrbm~=Y6kjiTRNswS|I}6lJzqt@FV;?S4P6LrT8NQopcrDg5M6|jh(QX8 zAO#768eyO)A>y|fB7qSae(*@2zdu|zp)=#W3qS6AGxwbToOA9y*Sg?h1OkC5mOX?_ z7>D<;YFSpm$=q^Ufb&S!jKNK~WY+&=et^KJlf4^(I-I-!KP-cyxuFOk8IgTE5nBPi zJ_O@bh=nWg%LuhGH^49gzk?C*VLS=bFaYx=g73^Na1FBUqHv1fDh@&+0xm->L_-H; zK|Rhlf{CCD<9pC(9O}PPl>{sB7+Mk0t~zzNiQpEN>u?d8zz6S4L@Im_0()Ks-eQ;m zosbTnUyFrN8&cjQ^%EJL@?-E`9!oN1SIpQOmG zbFFhDkjFYTwn5NkqdFvmYSWA87dt^W0{3yCOGo{t6x0A0;EfT`VLWpWiagx#0*2OppdfxmWNuXo4wX0jO-hJG&q0000< KMNUMnLSTYF`3FS+ literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-xhdpi/ic_stat_notification.png b/android/app/src/main/res/drawable-xhdpi/ic_stat_notification.png new file mode 100644 index 0000000000000000000000000000000000000000..4d12ba0da96cd6bce93b57538e50e74b96fe3c9b GIT binary patch literal 1659 zcmV->288*EP)_JC?vf;pLX53HxJKq-`BO?f4a8M?&p1;`@XN=_qu=A_51y<`>kw}xV5yj zY|kwl;3QZ9@4&)JrSeVUuGZbIlJce)uhI9wQLt6G_Zp7P@F4#VbgPESO9U&pyMPl*=5=x;|auffqZd;8~v z@qFx$h?WA^R6R9?fU~&s^RPv(2Mt>UPTcmeH{|>s}Xy&j)ZE1k0cc z%tOS=7!gq}#OPj2=MMz~e&Tp1JP0qr=P)=Jtk4T#GtlJ}aXj=vz?9Y$FqY2y=L~4% z^KGE8VHo$9zaexN4$g%$;bz!8Tw{Ri(3%2#f~P_!aH7tHIiSJ4;3>EZ-hgLdHTYya z`u9`>__Rv5SQk2*p66r44`HOepR3W+a5CsFPH5vqGcBU8)V&FE6X0v;f?q z9i1+QY{_imvvc4+=nWqQ0f%wC9gcy^;W^O7j)N27Q|Mkc#fTB0F^##ATgvAX;4}CN zgZA?`ms$fBtvi2qgD2ocFaX*0(wL~N(G5ayyOO_67cK^4gG;Oa?%e3bd22b( zzs;RwMcK3>MnD4{PXi~gfk|J!25tnGN=MYmYw~s}j0D|A*HYl2a0ED)Iw9agj)hx{ z0CWC#b3N)V2B!sJ&VL4Il#|@i-W~LPmscn9fw^nDA;2ZLaElS(NIL4ekN*5DWD)iQ zKI`j>mtVF7g&Qc@;7X%u*kKy})$B^3up{Gb)=C`2-8M zSOM0*19QDPn)}0Oa3ZgQAHk>d3rqro+H`RFwRuf@1Sr06ixuE#8<=cPUgN+5j9J3d z>A`1HYSRhJ&FOqUlJ8x5O*6I$*PYAp`VAh)>>OkCXMNq&L053}_XUHRf*c@opBZpC zTm~k4yTM|N{xygweTaGjS+59j#nEldZ+3#Kz*WUGVs@y?6sr4J+!zPmgKuF>Ohy_l z0OKqnP3m?Gf?SCvVw57*w-9-a36_-E1orpI(07AJ;@s%F9BPDavct`UHkBF`G*dYk>=+pFmg= zAE8f+e4CY64+NM#tZyOhP~^{GI$;eE{jwv40Bc&eQmoL7%I5u-fC=1rV76)L= zef9#xr_})wQ7=291yp<5;imbX6+-Y<2F2}glxR{gN)y7>2&+%QFE7l@@_r*w5OCi8fws?0dZ^JYMM7^C+c?to(A9G1`ht5|^R$OjeSza2{tiE(3-y;l%gTNZXSmDlI zR7)X17tzNX!0kedc6aRD!1Z0QwXj<$?u$MQZZ}%+cZpqrRGvbBfy-?{N4QoqXz6Y< zFn-6YKdsiGU!&RYn(ax!f6CR`bnZrtt$~ zm(Ki6lL-hSbSERNOQpGy^T8$5-8t8N-wT&|k?~(o<8KxY>Of_l0>uCT002ovPDHLk FV1lovBxe8s literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-xxhdpi/ic_stat_notification.png b/android/app/src/main/res/drawable-xxhdpi/ic_stat_notification.png new file mode 100644 index 0000000000000000000000000000000000000000..3a19ea30dcf27a725a39de809f1bdef586736448 GIT binary patch literal 3162 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 literal 0 HcmV?d00001 From ef922d41e6f2dd884f7ebb1c5c43ddf9b02b09b1 Mon Sep 17 00:00:00 2001 From: alexdivadi Date: Fri, 20 Feb 2026 16:47:05 -0600 Subject: [PATCH 3/3] fix: address auto-populate --- .../location/presentation/any_step_address_form.dart | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/core/features/location/presentation/any_step_address_form.dart b/lib/core/features/location/presentation/any_step_address_form.dart index 0eb7101..badf4fe 100644 --- a/lib/core/features/location/presentation/any_step_address_form.dart +++ b/lib/core/features/location/presentation/any_step_address_form.dart @@ -298,11 +298,8 @@ class _AnyStepAddressFormState extends ConsumerState { _debounce?.cancel(); _addressId = null; form.fields[widget.addressIdFieldName]?.didChange(null); - if (widget.showNameField) { - final nameValue = parsed.name ?? prediction.mainText ?? prediction.description; - form.fields[widget.nameFieldName]?.didChange(nameValue); - } - form.fields['street']?.didChange(parsed.street); + final streetText = parsed.street.isNotEmpty ? parsed.street : prediction.mainText ?? ''; + form.fields['street']?.didChange(streetText); form.fields['streetSecondary']?.didChange(parsed.streetSecondary); form.fields['city']?.didChange(parsed.city); form.fields['state']?.didChange(parsed.state); @@ -311,7 +308,7 @@ class _AnyStepAddressFormState extends ConsumerState { _placeName = parsed.name; _latitude = parsed.latitude; _longitude = parsed.longitude; - _streetController.text = parsed.street.isNotEmpty ? parsed.street : prediction.description; + _streetController.text = streetText; _streetController.selection = TextSelection.fromPosition( TextPosition(offset: _streetController.text.length), );