Skip to content

Commit

Permalink
#27: Centralize the timer for the Next Event Time for performance and…
Browse files Browse the repository at this point in the history
… synchronization of event highlighting.
  • Loading branch information
hjtappe committed Dec 15, 2024
1 parent 652fa55 commit 2c1a0d7
Show file tree
Hide file tree
Showing 8 changed files with 215 additions and 111 deletions.
30 changes: 30 additions & 0 deletions lib/data/appProviders/next_event_provider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import 'dart:async';

import 'package:flutter/material.dart';
import 'package:iccm_eu_app/data/dataProviders/events_provider.dart';

class NextEventNotifier {
static final ValueNotifier<DateTime?> nextEventNotifier = ValueNotifier(null);

static Timer? _timer;

static void startTimer(EventsProvider eventsProvider) {
if (_timer != null) {
return;
}

// Initial update
nextEventNotifier.value = eventsProvider.nextStartTime();

stopTimer(); // Cancel any existing timer

_timer = Timer.periodic(const Duration(seconds: 1), (_) {
nextEventNotifier.value = eventsProvider.nextStartTime();
});
}

static void stopTimer() {
_timer?.cancel();
_timer = null;
}
}
8 changes: 8 additions & 0 deletions lib/data/dataProviders/events_provider.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:convert';

import 'package:flutter/foundation.dart';
import 'package:iccm_eu_app/data/appProviders/next_event_provider.dart';
import 'package:iccm_eu_app/data/appProviders/preferences_provider.dart';
import 'package:iccm_eu_app/data/dataProviders/gsheets_provider.dart';
import 'package:iccm_eu_app/data/model/event_data.dart';
Expand Down Expand Up @@ -28,6 +29,12 @@ class EventsProvider with ChangeNotifier {
_populateItemsFromCache();
}

@override
void dispose() {
NextEventNotifier.stopTimer();
super.dispose();
}

void updateCache() {
if (EventsProvider.showTestDataOption() &&
PreferencesProvider.useTestDataNotifier.value) {
Expand Down Expand Up @@ -77,6 +84,7 @@ class EventsProvider with ChangeNotifier {
_fillCacheItemIds();
_saveCache();
_populateItemsFromCache();
NextEventNotifier.startTimer(this);
notifyListeners();
}

Expand Down
33 changes: 20 additions & 13 deletions lib/pages/event_details_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:iccm_eu_app/components/speaker_list_tile.dart';
import 'package:iccm_eu_app/components/track_list_tile.dart';
import 'package:iccm_eu_app/components/url_button.dart';
import 'package:iccm_eu_app/controls/nav_bar.dart';
import 'package:iccm_eu_app/data/appProviders/next_event_provider.dart';
import 'package:iccm_eu_app/data/dataProviders/events_provider.dart';
import 'package:iccm_eu_app/data/dataProviders/favorites_provider.dart';
import 'package:iccm_eu_app/data/dataProviders/rooms_provider.dart';
Expand Down Expand Up @@ -225,14 +226,14 @@ class EventDetailsPage extends StatelessWidget {
if (item.surveyUrl != null &&
item.surveyUrl!.startsWith('https://'))
Column(
children: [
UrlButton(
title: 'Survey URL',
url: item.surveyUrl,
withQrCode: true,
),
children: [
UrlButton(
title: 'Survey URL',
url: item.surveyUrl,
withQrCode: true,
),

]
]
)
else
SizedBox.shrink(),
Expand All @@ -255,12 +256,18 @@ class EventDetailsPage extends StatelessWidget {
.textTheme
.headlineSmall,
),
ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: parallelEvents.length,
itemBuilder: (context, index) {
return EventListTile(item: parallelEvents[index]);
ValueListenableBuilder<DateTime?>(
valueListenable: NextEventNotifier.nextEventNotifier,
builder: (context, nextEventTime, _) {
return ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: parallelEvents.length,
itemBuilder: (context, index) {
return EventListTile(
item: parallelEvents[index]);
},
);
},
),
],
Expand Down
14 changes: 10 additions & 4 deletions lib/pages/events_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_week_view/flutter_week_view.dart';
import 'package:iccm_eu_app/components/app_bar_countdown.dart';
import 'package:iccm_eu_app/components/event_list_tile.dart';
import 'package:iccm_eu_app/data/appProviders/next_event_provider.dart';
import 'package:iccm_eu_app/data/appProviders/preferences_provider.dart';
import 'package:iccm_eu_app/data/dataProviders/events_provider.dart';
import 'package:iccm_eu_app/data/dataProviders/rooms_provider.dart';
Expand Down Expand Up @@ -275,10 +276,15 @@ class EventListState extends State<EventList> {
} else {
items = itemList.items();
}
return ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return EventListTile(item: items[index]);
return ValueListenableBuilder<DateTime?>(
valueListenable: NextEventNotifier.nextEventNotifier,
builder: (context, nextEventTime, _) {
return ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return EventListTile(item: items[index]);
},
);
},
);
},
Expand Down
105 changes: 61 additions & 44 deletions lib/pages/home_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:iccm_eu_app/components/event_list_tile.dart';
import 'package:iccm_eu_app/components/url_button.dart';
import 'package:iccm_eu_app/data/appProviders/next_event_provider.dart';
import 'package:iccm_eu_app/data/dataProviders/events_provider.dart';
import 'package:iccm_eu_app/data/dataProviders/home_provider.dart';
import 'package:iccm_eu_app/data/model/event_data.dart';
Expand Down Expand Up @@ -60,11 +61,12 @@ class HomePageState extends State<HomePage> {

@override
Widget build(BuildContext context) {
final EventsProvider eventsProvider = Provider.of<EventsProvider>(context);
final EventsProvider eventsProvider =
Provider.of<EventsProvider>(context, listen: false);
_nextEventTime = eventsProvider.nextStartTime();
if (_remainingDuration <= Duration.zero) {
_upcomingEvents = eventsProvider.filterPastEvents(withCurrent: false).
take(5).toList();
take(5).toList();
}

return Scaffold(
Expand All @@ -75,32 +77,37 @@ class HomePageState extends State<HomePage> {
body: CustomScrollView(
slivers: [
SliverAppBar(
expandedHeight: MediaQuery.of(context).size.height * 0.3, // 30% of screen height
expandedHeight: MediaQuery
.of(context)
.size
.height * 0.3, // 30% of screen height
flexibleSpace: FlexibleSpaceBar(
collapseMode: CollapseMode.parallax,
background: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
return Consumer<HomeProvider>(
builder: (context, itemProvider, child) {
final itemList = itemProvider.items();
if (itemList.isEmpty) {
return const Center(
child: Text('Loading dynamic content...'),
builder: (BuildContext context, BoxConstraints constraints) {
return Consumer<HomeProvider>(
builder: (context, itemProvider, child) {
final itemList = itemProvider.items();
if (itemList.isEmpty) {
return const Center(
child: Text('Loading dynamic content...'),
);
}
final item = itemList.first;
return CachedNetworkImage(
imageUrl: item.imageUrl,
fit: BoxFit.cover,
width: constraints.maxWidth,
height: constraints.maxHeight,
placeholder: (context,
url) => const CircularProgressIndicator(),
errorWidget: (context, url, error) =>
const Icon(Icons.error),
colorBlendMode: BlendMode.srcIn,
);
}
final item = itemList.first;
return CachedNetworkImage(
imageUrl: item.imageUrl,
fit: BoxFit.cover,
width: constraints.maxWidth,
height: constraints.maxHeight,
placeholder: (context, url) => const CircularProgressIndicator(),
errorWidget: (context, url, error) => const Icon(Icons.error),
colorBlendMode: BlendMode.srcIn,
);
},
);
}
},
);
}
),
),
),
Expand All @@ -110,7 +117,7 @@ class HomePageState extends State<HomePage> {
final itemList = itemProvider.items();
if (itemList.isEmpty) {
return const Center(
child: Text('Loading dynamic content...'),
child: Text('Loading dynamic content...'),
);
}
final item = itemList.first; // Use the first item
Expand All @@ -122,12 +129,18 @@ class HomePageState extends State<HomePage> {
const SizedBox(height: 16.0),
Text(
item.name,
style: Theme.of(context).textTheme.titleLarge,
style: Theme
.of(context)
.textTheme
.titleLarge,
),
const SizedBox(height: 8.0),
Text(
item.details,
style: Theme.of(context).textTheme.bodyMedium,
style: Theme
.of(context)
.textTheme
.bodyMedium,
),
if (item.nowPageUrl != null &&
item.nowPageUrl!.startsWith('https://'))
Expand All @@ -152,23 +165,27 @@ class HomePageState extends State<HomePage> {
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
final isFirstItem = index == 0;
return Column( // Wrap the list item and Divider in a Column
children: [
if (isFirstItem) const Divider(),
Consumer<EventsProvider>(
builder: (context, itemList, child) {
return EventListTile(
item: _upcomingEvents[index],
);
},
),
],
);
},
childCount: _upcomingEvents.length,
delegate: SliverChildBuilderDelegate((context, index) {
final isFirstItem = index == 0;
return ValueListenableBuilder<DateTime?>(
valueListenable: NextEventNotifier.nextEventNotifier,
builder: (context, nextEventTime, _) {
return Column( // Wrap the list item and Divider in a Column
children: [
if (isFirstItem) const Divider(),
Consumer<EventsProvider>(
builder: (context, itemList, child) {
return EventListTile(
item: _upcomingEvents[index],
);
},
),
],
);
},
);
},
childCount: _upcomingEvents.length,
),
),
],
Expand Down
37 changes: 23 additions & 14 deletions lib/pages/room_details_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import 'package:flutter/material.dart';
import 'package:iccm_eu_app/components/event_list_tile.dart';
import 'package:iccm_eu_app/components/image_carousel.dart';
import 'package:iccm_eu_app/controls/nav_bar.dart';
import 'package:iccm_eu_app/data/appProviders/next_event_provider.dart';
import 'package:iccm_eu_app/data/dataProviders/events_provider.dart';
import 'package:iccm_eu_app/data/model/event_data.dart';
import 'package:iccm_eu_app/data/model/room_data.dart';
import 'package:provider/provider.dart';

Expand All @@ -16,13 +16,6 @@ class RoomDetailsPage extends StatelessWidget {

@override
Widget build(BuildContext context) {
EventsProvider eventsProvider = Provider.of<EventsProvider>(
context,
listen: false,
);
List<EventData> listItems = eventsProvider.eventsByRoom(
name: item.name,
);
List<String> imageUrls = [];
if (item.imageUrl.startsWith('https://')) {
imageUrls.add(item.imageUrl);
Expand Down Expand Up @@ -53,12 +46,28 @@ class RoomDetailsPage extends StatelessWidget {
Text(item.details,
style: Theme.of(context).textTheme.bodyMedium,
),
ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: listItems.length,
itemBuilder: (context, index) {
return EventListTile(item: listItems[index]);
Consumer<EventsProvider>(
builder: (context, itemProvider, child) {
final itemList = itemProvider.eventsByRoom(
name: item.name,
);
if (itemList.isEmpty) {
return SizedBox.shrink();
} else {
return ValueListenableBuilder<DateTime?>(
valueListenable: NextEventNotifier.nextEventNotifier,
builder: (context, nextEventTime, _) {
return ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: itemList.length,
itemBuilder: (context, index) {
return EventListTile(item: itemList[index]);
},
);
},
);
}
},
),
],
Expand Down
Loading

0 comments on commit 2c1a0d7

Please sign in to comment.