Skip to content

Commit

Permalink
Merge pull request #2101 from acterglobal/ben-expanding-error-pages
Browse files Browse the repository at this point in the history
Error pages for more sections
  • Loading branch information
gnunicorn authored Aug 28, 2024
2 parents befe585 + 2b5bbd4 commit 37cdef2
Show file tree
Hide file tree
Showing 15 changed files with 530 additions and 133 deletions.
6 changes: 3 additions & 3 deletions app/lib/features/calendar_sync/calendar_sync.dart
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ Future<void> _refreshCalendar(

Future<Event> _updateEventDetails(
CalendarEvent acterEvent,
String? rsvp,
RsvpStatusTag? rsvp,
Event localEvent,
) async {
localEvent.title = acterEvent.title();
Expand All @@ -203,8 +203,8 @@ Future<Event> _updateEventDetails(
UTC,
);
localEvent.status = switch (rsvp) {
'yes' => EventStatus.Confirmed,
'maybe' => EventStatus.Tentative,
RsvpStatusTag.Yes => EventStatus.Confirmed,
RsvpStatusTag.Maybe => EventStatus.Tentative,
_ => EventStatus.None
};
return localEvent;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import 'package:acter/features/events/providers/event_providers.dart';
import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

typedef EventAndRsvp = ({CalendarEvent event, String? rsvp});
typedef EventAndRsvp = ({CalendarEvent event, RsvpStatusTag? rsvp});

final eventsToSyncProvider = FutureProvider.autoDispose((ref) async {
// fetch all from all spaces
Expand All @@ -19,13 +19,12 @@ final eventsToSyncProvider = FutureProvider.autoDispose((ref) async {
for (final event in upcomingAndOngoing) {
final eventId = event.eventId().toString();
final myRsvpStatus = await ref.watch(myRsvpStatusProvider(eventId).future);
final rsvpStatus = myRsvpStatus.statusStr();
if (rsvpStatus != 'no') {
if (myRsvpStatus == RsvpStatusTag.No) {
// we sync all that aren't denied yet
final event = await ref.watch(
calendarEventProvider(eventId).future,
); // ensure we are listening to updates of the events themselves
toSync.add((event: event, rsvp: rsvpStatus));
toSync.add((event: event, rsvp: myRsvpStatus));
}
}
return toSync;
Expand Down
43 changes: 16 additions & 27 deletions app/lib/features/events/pages/event_details_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:acter/common/actions/redact_content.dart';
import 'package:acter/common/actions/report_content.dart';
import 'package:acter/common/providers/common_providers.dart';
import 'package:acter/common/providers/room_providers.dart';
import 'package:acter/common/toolkit/errors/error_page.dart';
import 'package:acter/common/utils/utils.dart';
import 'package:acter/common/widgets/edit_html_description_sheet.dart';
import 'package:acter/common/widgets/edit_title_sheet.dart';
Expand Down Expand Up @@ -72,9 +73,17 @@ class _EventDetailPageConsumerState extends ConsumerState<EventDetailPage> {
],
);
},
error: (e, s) {
_log.severe('Failed to load cal event', e, s);
return Text(L10n.of(context).errorLoadingEventDueTo(e));
error: (error, stack) {
_log.severe('Failed to load cal event', error, stack);
return ErrorPage(
background: const EventDetailsSkeleton(),
error: error,
stack: stack,
textBuilder: L10n.of(context).errorLoadingEventDueTo,
onRetryTap: () {
ref.invalidate(calendarEventProvider(widget.calendarId));
},
);
},
loading: () => const EventDetailsSkeleton(),
),
Expand Down Expand Up @@ -366,27 +375,7 @@ class _EventDetailPageConsumerState extends ConsumerState<EventDetailPage> {
}

Widget _buildEventRsvpActions(CalendarEvent calendarEvent) {
final myRsvpStatus = ref.watch(myRsvpStatusProvider(widget.calendarId));
Set<RsvpStatusTag?> rsvp = <RsvpStatusTag?>{null};
myRsvpStatus.maybeWhen(
data: (data) {
final status = data.statusStr();
if (status != null) {
switch (status) {
case 'yes':
rsvp = <RsvpStatusTag?>{RsvpStatusTag.Yes};
break;
case 'maybe':
rsvp = <RsvpStatusTag?>{RsvpStatusTag.Maybe};
break;
case 'no':
rsvp = <RsvpStatusTag?>{RsvpStatusTag.No};
break;
}
}
},
orElse: () => null,
);
final rsvp = ref.watch(myRsvpStatusProvider(widget.calendarId)).valueOrNull;

return Container(
color: Theme.of(context).colorScheme.surface,
Expand All @@ -400,7 +389,7 @@ class _EventDetailPageConsumerState extends ConsumerState<EventDetailPage> {
iconData: Icons.check,
actionName: L10n.of(context).going,
rsvpStatusColor: Theme.of(context).colorScheme.secondary,
isSelected: rsvp.single == RsvpStatusTag.Yes,
isSelected: rsvp == RsvpStatusTag.Yes,
),
_buildVerticalDivider(),
_buildEventRsvpActionItem(
Expand All @@ -410,7 +399,7 @@ class _EventDetailPageConsumerState extends ConsumerState<EventDetailPage> {
iconData: Icons.close,
actionName: L10n.of(context).notGoing,
rsvpStatusColor: Theme.of(context).colorScheme.error,
isSelected: rsvp.single == RsvpStatusTag.No,
isSelected: rsvp == RsvpStatusTag.No,
),
_buildVerticalDivider(),
_buildEventRsvpActionItem(
Expand All @@ -420,7 +409,7 @@ class _EventDetailPageConsumerState extends ConsumerState<EventDetailPage> {
iconData: Icons.question_mark,
actionName: L10n.of(context).maybe,
rsvpStatusColor: Colors.white,
isSelected: rsvp.single == RsvpStatusTag.Maybe,
isSelected: rsvp == RsvpStatusTag.Maybe,
),
],
),
Expand Down
30 changes: 20 additions & 10 deletions app/lib/features/events/pages/event_list_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'dart:math';

import 'package:acter/common/providers/space_providers.dart';
import 'package:acter/common/toolkit/buttons/primary_action_button.dart';
import 'package:acter/common/toolkit/errors/error_page.dart';
import 'package:acter/common/utils/routes.dart';
import 'package:acter/common/widgets/acter_search_widget.dart';
import 'package:acter/common/widgets/add_button_with_can_permission.dart';
Expand Down Expand Up @@ -34,7 +35,7 @@ class _EventListPageState extends ConsumerState<EventListPage> {

String get searchValue => ref.watch(searchValueProvider);

EventFilters get eventFilterValue => ref.watch(eventFilerProvider);
EventFilters get eventFilterValue => ref.watch(eventFilterProvider);

@override
Widget build(BuildContext context) {
Expand Down Expand Up @@ -85,10 +86,19 @@ class _EventListPageState extends ConsumerState<EventListPage> {
Expanded(
child: calEventsLoader.when(
data: (calEvents) => _buildEventList(calEvents),
error: (e, s) {
_log.severe('Failed to search events in space', e, s);
return Center(
child: Text(L10n.of(context).searchingFailed(e)),
error: (error, stack) {
_log.severe('Failed to search events in space', error, stack);
return ErrorPage(
background: const EventListSkeleton(),
error: error,
stack: stack,
onRetryTap: () {
ref.invalidate(
eventListSearchFilterProvider(
(spaceId: widget.spaceId, searchText: searchValue),
),
);
},
);
},
loading: () => const EventListSkeleton(),
Expand All @@ -109,39 +119,39 @@ class _EventListPageState extends ConsumerState<EventListPage> {
selected: eventFilterValue == EventFilters.all,
label: Text(L10n.of(context).all),
onSelected: (value) => ref
.read(eventFilerProvider.notifier)
.read(eventFilterProvider.notifier)
.state = EventFilters.all,
),
const SizedBox(width: 10),
FilterChip(
selected: eventFilterValue == EventFilters.bookmarked,
label: Text(L10n.of(context).bookmarked),
onSelected: (value) => ref
.read(eventFilerProvider.notifier)
.read(eventFilterProvider.notifier)
.state = EventFilters.bookmarked,
),
const SizedBox(width: 10),
FilterChip(
selected: eventFilterValue == EventFilters.ongoing,
label: Text(L10n.of(context).happeningNow),
onSelected: (value) => ref
.read(eventFilerProvider.notifier)
.read(eventFilterProvider.notifier)
.state = EventFilters.ongoing,
),
const SizedBox(width: 10),
FilterChip(
selected: eventFilterValue == EventFilters.upcoming,
label: Text(L10n.of(context).upcoming),
onSelected: (value) => ref
.read(eventFilerProvider.notifier)
.read(eventFilterProvider.notifier)
.state = EventFilters.upcoming,
),
const SizedBox(width: 10),
FilterChip(
selected: eventFilterValue == EventFilters.past,
label: Text(L10n.of(context).past),
onSelected: (value) => ref
.read(eventFilerProvider.notifier)
.read(eventFilterProvider.notifier)
.state = EventFilters.past,
),
],
Expand Down
12 changes: 6 additions & 6 deletions app/lib/features/events/providers/event_providers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ final calendarEventProvider = AsyncNotifierProvider.autoDispose

//MY RSVP STATUS PROVIDER
final myRsvpStatusProvider = AsyncNotifierProvider.autoDispose
.family<AsyncRsvpStatusNotifier, ffi.OptionRsvpStatus, String>(
.family<AsyncRsvpStatusNotifier, ffi.RsvpStatusTag?, String>(
() => AsyncRsvpStatusNotifier(),
);

Expand Down Expand Up @@ -57,7 +57,7 @@ final myOngoingEventListProvider = FutureProvider.autoDispose
for (final event in allOngoingEventList) {
final myRsvpStatus = await ref
.watch(myRsvpStatusProvider(event.eventId().toString()).future);
if (myRsvpStatus.statusStr() == 'yes') {
if (myRsvpStatus == ffi.RsvpStatusTag.Yes) {
myOngoingEventList.add(event);
}
}
Expand All @@ -83,7 +83,7 @@ final myUpcomingEventListProvider = FutureProvider.autoDispose
for (final event in allUpcomingEventList) {
final myRsvpStatus = await ref
.watch(myRsvpStatusProvider(event.eventId().toString()).future);
if (myRsvpStatus.statusStr() == 'yes') {
if (myRsvpStatus == ffi.RsvpStatusTag.Yes) {
myUpcomingEventList.add(event);
}
}
Expand All @@ -109,7 +109,7 @@ final myPastEventListProvider = FutureProvider.autoDispose
for (final event in allPastEventList) {
final myRsvpStatus = await ref
.watch(myRsvpStatusProvider(event.eventId().toString()).future);
if (myRsvpStatus.statusStr() == 'yes') {
if (myRsvpStatus == ffi.RsvpStatusTag.Yes) {
myPastEventList.add(event);
}
}
Expand All @@ -125,7 +125,7 @@ enum EventFilters {
past,
}

final eventFilerProvider =
final eventFilterProvider =
StateProvider.autoDispose<EventFilters>((ref) => EventFilters.all);

//SEARCH EVENTS
Expand All @@ -138,7 +138,7 @@ final eventListSearchFilterProvider = FutureProvider.autoDispose
List<ffi.CalendarEvent> filteredEventList = [];

//Filter events based on the selection
EventFilters eventFilter = ref.watch(eventFilerProvider);
EventFilters eventFilter = ref.watch(eventFilterProvider);
switch (eventFilter) {
case EventFilters.bookmarked:
{
Expand Down
13 changes: 9 additions & 4 deletions app/lib/features/events/providers/notifiers/rsvp_notifier.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,22 @@ import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart' as ffi;
import 'package:riverpod/riverpod.dart';

class AsyncRsvpStatusNotifier
extends AutoDisposeFamilyAsyncNotifier<ffi.OptionRsvpStatus, String> {
extends AutoDisposeFamilyAsyncNotifier<ffi.RsvpStatusTag?, String> {
late Stream<bool> _listener;

Future<ffi.OptionRsvpStatus> _getMyResponse() async {
Future<ffi.RsvpStatusTag?> _getMyResponse() async {
final client = ref.read(alwaysClientProvider);
final calEvent = await client.waitForCalendarEvent(arg, null);
return await calEvent.respondedByMe();
return switch ((await calEvent.respondedByMe()).statusStr()) {
'yes' => ffi.RsvpStatusTag.Yes,
'no' => ffi.RsvpStatusTag.No,
'maybe' => ffi.RsvpStatusTag.Maybe,
_ => null,
};
}

@override
Future<ffi.OptionRsvpStatus> build(String arg) async {
Future<ffi.RsvpStatusTag?> build(String arg) async {
final client = ref.watch(alwaysClientProvider);
_listener =
client.subscribeStream('$arg::rsvp'); // keep it resident in memory
Expand Down
36 changes: 15 additions & 21 deletions app/lib/features/events/widgets/event_item.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import 'package:acter/features/events/actions/get_event_type.dart';
import 'package:acter/features/events/providers/event_providers.dart';
import 'package:acter/features/events/widgets/event_date_widget.dart';
import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'
show CalendarEvent;
show CalendarEvent, RsvpStatusTag;
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
Expand Down Expand Up @@ -110,8 +110,7 @@ class EventItem extends StatelessWidget {
final eventId = event.eventId().toString();
final rsvpLoader = ref.watch(myRsvpStatusProvider(eventId));
return rsvpLoader.when(
data: (rsvp) {
final status = rsvp.statusStr(); // kebab-case
data: (status) {
final widget = _getRsvpStatus(context, status); // kebab-case
return widget ?? const SizedBox.shrink();
},
Expand All @@ -132,24 +131,19 @@ class EventItem extends StatelessWidget {
);
}

Widget? _getRsvpStatus(BuildContext context, String? status) {
if (status != null) {
switch (status) {
case 'yes':
return Icon(
Icons.check_circle,
color: Theme.of(context).colorScheme.secondary,
);
case 'no':
return Icon(
Icons.cancel,
color: Theme.of(context).colorScheme.error,
);
case 'maybe':
return const Icon(Icons.question_mark_rounded);
}
}
return null;
Widget? _getRsvpStatus(BuildContext context, RsvpStatusTag? status) {
return switch (status) {
RsvpStatusTag.Yes => Icon(
Icons.check_circle,
color: Theme.of(context).colorScheme.secondary,
),
RsvpStatusTag.No => Icon(
Icons.cancel,
color: Theme.of(context).colorScheme.error,
),
RsvpStatusTag.Maybe => const Icon(Icons.question_mark_rounded),
null => null,
};
}

Widget _buildHappeningIndication(BuildContext context) {
Expand Down
Loading

0 comments on commit 37cdef2

Please sign in to comment.