Skip to content

Commit

Permalink
Auto updating UTC datetime via state provider and timer, fixes #2256
Browse files Browse the repository at this point in the history
  • Loading branch information
gnunicorn committed Oct 22, 2024
1 parent 157cf30 commit 467efb4
Show file tree
Hide file tree
Showing 14 changed files with 94 additions and 36 deletions.
3 changes: 3 additions & 0 deletions app/lib/common/widgets/event/event_selector_drawer.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:acter/features/events/providers/event_providers.dart';
import 'package:acter/features/events/providers/event_type_provider.dart';
import 'package:acter/features/events/widgets/event_item.dart';
import 'package:acter/features/events/widgets/skeletons/event_list_skeleton_widget.dart';
import 'package:atlas_icons/atlas_icons.dart';
Expand Down Expand Up @@ -62,6 +63,8 @@ Future<String?> selectEventDrawer({
itemBuilder: (context, index) => EventItem(
event: calEvents[index],
isShowRsvp: false,
eventType:
ref.read(eventTypeProvider(calEvents[index])),
onTapEventItem: (event) {
Navigator.pop(context, event);
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//ALL UPCOMING EVENTS
import 'package:acter/features/events/actions/get_event_type.dart';
import 'package:acter/features/events/providers/event_type_provider.dart';
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';
Expand All @@ -10,7 +10,7 @@ final eventsToSyncProvider = FutureProvider.autoDispose((ref) async {
// fetch all from all spaces
final allEventList = await ref.watch(allEventListProvider(null).future);
final upcomingAndOngoing = allEventList.where((event) {
final eventType = getEventType(event);
final eventType = ref.watch(eventTypeProvider(event));
return eventType == EventFilters.upcoming ||
eventType == EventFilters.ongoing;
});
Expand Down
19 changes: 19 additions & 0 deletions app/lib/features/datetime/providers/notifiers/now_notifier.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import 'dart:async';

import 'package:flutter_riverpod/flutter_riverpod.dart';

class UtcNowNotifier extends StateNotifier<DateTime> {
late Timer _timer;
UtcNowNotifier() : super(DateTime.now().toUtc()) {
_timer = Timer.periodic(const Duration(seconds: 59), (t) {
state = DateTime.now().toUtc();
});
}

@override
void dispose() {
// TODO: implement dispose
super.dispose();
_timer.cancel();
}
}
7 changes: 7 additions & 0 deletions app/lib/features/datetime/providers/utc_now_provider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import 'package:acter/features/datetime/providers/notifiers/now_notifier.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

/// Provides the "current" UTC datetime, automatically updating at least
/// once a minute
final utcNowProvider =
StateNotifierProvider<UtcNowNotifier, DateTime>((ref) => UtcNowNotifier());
16 changes: 10 additions & 6 deletions app/lib/features/events/pages/event_details_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import 'package:acter/features/attachments/widgets/attachment_section.dart';
import 'package:acter/features/bookmarks/types.dart';
import 'package:acter/features/bookmarks/widgets/bookmark_action.dart';
import 'package:acter/features/comments/widgets/comments_section.dart';
import 'package:acter/features/events/actions/get_event_type.dart';
import 'package:acter/features/events/providers/event_type_provider.dart';
import 'package:acter/features/events/model/keys.dart';
import 'package:acter/features/events/providers/event_providers.dart';
import 'package:acter/features/events/utils/events_utils.dart';
Expand Down Expand Up @@ -127,7 +127,8 @@ class _EventDetailPageConsumerState extends ConsumerState<EventDetailPage> {
final canRedact = ref.watch(canRedactProvider(event));
final membership = ref.watch(roomMembershipProvider(spaceId)).valueOrNull;
final canPostEvent = membership?.canString('CanPostEvent') == true;
final canChangeDate = getEventType(event) == EventFilters.upcoming;
final canChangeDate =
ref.watch(eventTypeProvider(event)) == EventFilters.upcoming;

//Create event actions
List<PopupMenuEntry> actions = [];
Expand Down Expand Up @@ -292,12 +293,13 @@ class _EventDetailPageConsumerState extends ConsumerState<EventDetailPage> {
final spaceId = calendarEvent.roomIdStr();
final membership = ref.watch(roomMembershipProvider(spaceId)).valueOrNull;
final canPostEvent = membership?.canString('CanPostEvent') == true;
final eventType = ref.watch(eventTypeProvider(calendarEvent));

return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Date and Month
EventDateWidget(calendarEvent: calendarEvent),
EventDateWidget(calendarEvent: calendarEvent, eventType: eventType),
// Title, Space, User counts, comments counts and like counts
Expanded(
child: Column(
Expand Down Expand Up @@ -476,7 +478,8 @@ class _EventDetailPageConsumerState extends ConsumerState<EventDetailPage> {
required Color rsvpStatusColor,
bool isSelected = false,
}) {
final canRSVPUpdate = getEventType(calendarEvent) != EventFilters.past;
final canRSVPUpdate =
ref.watch(eventTypeProvider(calendarEvent)) != EventFilters.past;
return Expanded(
child: InkWell(
key: key,
Expand Down Expand Up @@ -518,14 +521,15 @@ class _EventDetailPageConsumerState extends ConsumerState<EventDetailPage> {
.fromNow();

String eventDateTime = '${formatDate(ev)} (${formatTime(ev)})';
final eventType = ref.watch(eventTypeProvider(ev));

String eventTimingTitle = switch (getEventType(ev)) {
String eventTimingTitle = switch (eventType) {
EventFilters.ongoing => '${lang.eventStarted} $agoTime',
EventFilters.upcoming => '${lang.eventStarts} $agoTime',
EventFilters.past => '${lang.eventEnded} $agoTime',
_ => '',
};
final canChangeDate = getEventType(ev) == EventFilters.upcoming;
final canChangeDate = eventType == EventFilters.upcoming;

return Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
Expand Down
2 changes: 2 additions & 0 deletions app/lib/features/events/pages/event_list_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:acter/common/widgets/add_button_with_can_permission.dart';
import 'package:acter/common/widgets/empty_state_widget.dart';
import 'package:acter/common/widgets/space_name_widget.dart';
import 'package:acter/features/events/providers/event_providers.dart';
import 'package:acter/features/events/providers/event_type_provider.dart';
import 'package:acter/features/events/widgets/event_item.dart';
import 'package:acter/features/events/widgets/skeletons/event_list_skeleton_widget.dart';
import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
Expand Down Expand Up @@ -191,6 +192,7 @@ class _EventListPageState extends ConsumerState<EventListPage> {
EventItem(
event: event,
isShowSpaceName: widget.spaceId == null,
eventType: ref.watch(eventTypeProvider(event)),
),
],
),
Expand Down
14 changes: 10 additions & 4 deletions app/lib/features/events/providers/event_providers.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import 'package:acter/features/bookmarks/providers/bookmarks_provider.dart';
import 'package:acter/features/bookmarks/types.dart';
import 'package:acter/features/events/actions/get_event_type.dart';
import 'package:acter/features/events/providers/event_type_provider.dart';
import 'package:acter/features/events/actions/sort_event_list.dart';
import 'package:acter/features/events/providers/notifiers/event_notifiers.dart';
import 'package:acter/features/events/providers/notifiers/rsvp_notifier.dart';
Expand Down Expand Up @@ -43,7 +43,9 @@ final allOngoingEventListProvider = FutureProvider.autoDispose
.family<List<ffi.CalendarEvent>, String?>((ref, spaceId) async {
final allEventList = await ref.watch(allEventListProvider(spaceId).future);
List<ffi.CalendarEvent> allOngoingEventList = allEventList
.where((event) => getEventType(event) == EventFilters.ongoing)
.where(
(event) => ref.watch(eventTypeProvider(event)) == EventFilters.ongoing,
)
.toList();
return sortEventListAscTime(allOngoingEventList);
});
Expand All @@ -69,7 +71,9 @@ final allUpcomingEventListProvider = FutureProvider.autoDispose
.family<List<ffi.CalendarEvent>, String?>((ref, spaceId) async {
final allEventList = await ref.watch(allEventListProvider(spaceId).future);
List<ffi.CalendarEvent> allUpcomingEventList = allEventList
.where((event) => getEventType(event) == EventFilters.upcoming)
.where(
(event) => ref.watch(eventTypeProvider(event)) == EventFilters.upcoming,
)
.toList();
return sortEventListAscTime(allUpcomingEventList);
});
Expand All @@ -95,7 +99,9 @@ final allPastEventListProvider = FutureProvider.autoDispose
.family<List<ffi.CalendarEvent>, String?>((ref, spaceId) async {
final allEventList = await ref.watch(allEventListProvider(spaceId).future);
List<ffi.CalendarEvent> allPastEventList = allEventList
.where((event) => getEventType(event) == EventFilters.past)
.where(
(event) => ref.watch(eventTypeProvider(event)) == EventFilters.past,
)
.toList();
return sortEventListDscTime(allPastEventList);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import 'package:acter/features/datetime/providers/utc_now_provider.dart';
import 'package:acter/features/events/providers/event_providers.dart';
import 'package:acter_flutter_sdk/acter_flutter_sdk.dart';
import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart' as ffi;
import 'package:dart_date/dart_date.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';


EventFilters getEventType(ffi.CalendarEvent event) {
final eventTypeProvider =
Provider.autoDispose.family<EventFilters, ffi.CalendarEvent>((ref, event) {
DateTime eventStartDateTime = toDartDatetime(event.utcStart());
DateTime eventEndDateTime = toDartDatetime(event.utcEnd());
DateTime currentDateTime = DateTime.now().toUTC;
DateTime currentDateTime = ref.read(utcNowProvider);

//Check for event type
if (eventStartDateTime.isBefore(currentDateTime) &&
Expand All @@ -19,4 +20,4 @@ EventFilters getEventType(ffi.CalendarEvent event) {
return EventFilters.past;
}
return EventFilters.all;
}
});
16 changes: 7 additions & 9 deletions app/lib/features/events/widgets/event_date_widget.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import 'package:acter/features/events/actions/get_event_type.dart';
import 'package:acter/features/events/providers/event_providers.dart';
import 'package:acter/features/events/utils/events_utils.dart';
import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
import 'package:flutter/material.dart';

class EventDateWidget extends StatelessWidget {
final CalendarEvent calendarEvent;
final EventFilters eventType;

const EventDateWidget({super.key, required this.calendarEvent});
const EventDateWidget(
{super.key, required this.calendarEvent, required this.eventType,});

@override
Widget build(BuildContext context) {
Expand Down Expand Up @@ -40,11 +41,8 @@ class EventDateWidget extends StatelessWidget {
);
}

Color getColorBasedOnEventType(BuildContext context) {
if (getEventType(calendarEvent) == EventFilters.past) {
return Colors.grey.shade800;
} else {
return Theme.of(context).primaryColor;
}
}
Color getColorBasedOnEventType(BuildContext context) => switch (eventType) {
EventFilters.past => Colors.grey.shade800,
_ => Theme.of(context).primaryColor
};
}
10 changes: 7 additions & 3 deletions app/lib/features/events/widgets/event_item.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import 'package:acter/common/extensions/options.dart';
import 'package:acter/common/providers/room_providers.dart';
import 'package:acter/common/utils/routes.dart';
import 'package:acter/common/widgets/blinking_text.dart';
import 'package:acter/features/events/actions/get_event_type.dart';
import 'package:acter/features/events/providers/event_providers.dart';
import 'package:acter/features/events/utils/events_utils.dart';
import 'package:acter/features/events/widgets/event_date_widget.dart';
Expand All @@ -22,6 +21,7 @@ class EventItem extends StatelessWidget {
final Function(String)? onTapEventItem;
final bool isShowRsvp;
final bool isShowSpaceName;
final EventFilters eventType;

const EventItem({
super.key,
Expand All @@ -30,6 +30,7 @@ class EventItem extends StatelessWidget {
this.onTapEventItem,
this.isShowRsvp = true,
this.isShowSpaceName = false,
required this.eventType,
});

@override
Expand All @@ -53,7 +54,10 @@ class EventItem extends StatelessWidget {
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
EventDateWidget(calendarEvent: event),
EventDateWidget(
calendarEvent: event,
eventType: eventType,
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
Expand All @@ -66,7 +70,7 @@ class EventItem extends StatelessWidget {
),
),
const SizedBox(width: 10),
if (getEventType(event) == EventFilters.ongoing)
if (eventType == EventFilters.ongoing)
_buildHappeningIndication(context),
const SizedBox(width: 10),
if (isShowRsvp) _buildRsvpStatus(context),
Expand Down
7 changes: 5 additions & 2 deletions app/lib/features/home/widgets/my_events.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:acter/common/extensions/options.dart';
import 'package:acter/common/toolkit/buttons/inline_text_button.dart';
import 'package:acter/common/utils/routes.dart';
import 'package:acter/features/events/providers/event_providers.dart';
import 'package:acter/features/events/providers/event_type_provider.dart';
import 'package:acter/features/events/widgets/event_item.dart';
import 'package:acter/features/events/widgets/skeletons/event_list_skeleton_widget.dart';
import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart';
Expand Down Expand Up @@ -45,7 +46,7 @@ class MyEventsSection extends ConsumerWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
sectionHeader(context, sectionTitle),
eventListUI(context, calEvents),
eventListUI(context, ref, calEvents),
],
);
},
Expand Down Expand Up @@ -73,7 +74,8 @@ class MyEventsSection extends ConsumerWidget {
);
}

Widget eventListUI(BuildContext context, List<CalendarEvent> events) {
Widget eventListUI(
BuildContext context, WidgetRef ref, List<CalendarEvent> events) {
final count = limit.map((val) => min(val, events.length)) ?? events.length;
return ListView.builder(
shrinkWrap: true,
Expand All @@ -83,6 +85,7 @@ class MyEventsSection extends ConsumerWidget {
isShowSpaceName: true,
margin: const EdgeInsets.only(bottom: 14),
event: events[index],
eventType: ref.watch(eventTypeProvider(events[index])),
),
);
}
Expand Down
2 changes: 2 additions & 0 deletions app/lib/features/news/pages/add_news_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:acter/common/toolkit/buttons/danger_action_button.dart';
import 'package:acter/common/extensions/options.dart';
import 'package:acter/common/widgets/acter_video_player.dart';
import 'package:acter/common/widgets/html_editor.dart';
import 'package:acter/features/events/providers/event_type_provider.dart';
import 'package:acter/features/events/providers/event_providers.dart';
import 'package:acter/features/events/widgets/event_item.dart';
import 'package:acter/features/events/widgets/skeletons/event_item_skeleton_widget.dart';
Expand Down Expand Up @@ -281,6 +282,7 @@ class AddNewsState extends ConsumerState<AddNewsPage> {
final notifier = ref.read(newsStateProvider.notifier);
await notifier.selectEventToShare(context);
},
eventType: ref.watch(eventTypeProvider(calendarEvent)),
),
);
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:acter/common/actions/open_link.dart';
import 'package:acter/common/toolkit/errors/error_dialog.dart';
import 'package:acter/features/events/providers/event_providers.dart';
import 'package:acter/features/events/providers/event_type_provider.dart';
import 'package:acter/features/events/widgets/event_item.dart';
import 'package:acter/features/events/widgets/skeletons/event_item_skeleton_widget.dart';
import 'package:acter/features/news/model/news_references_model.dart';
Expand Down Expand Up @@ -45,7 +46,10 @@ class NewsSlideActions extends ConsumerWidget {
final lang = L10n.of(context);
final calEventLoader = ref.watch(calendarEventProvider(eventId));
return calEventLoader.when(
data: (calEvent) => EventItem(event: calEvent),
data: (calEvent) => EventItem(
event: calEvent,
eventType: ref.watch(eventTypeProvider(calEvent)),
),
loading: () => const EventItemSkeleton(),
error: (e, s) {
_log.severe('Failed to load cal event', e, s);
Expand Down
Loading

0 comments on commit 467efb4

Please sign in to comment.