From de98a2b40b5a0195e15ba153f306f28342881032 Mon Sep 17 00:00:00 2001 From: ImBenji <53883070+YesItsBenji@users.noreply.github.com> Date: Wed, 28 Feb 2024 14:19:50 +0000 Subject: [PATCH] More --- lib/pages/home.dart | 276 +++++++++------------------ lib/singletons/live_information.dart | 77 +++++--- lib/utils/audio wrapper.dart | 12 +- 3 files changed, 152 insertions(+), 213 deletions(-) diff --git a/lib/pages/home.dart b/lib/pages/home.dart index de06a1f..3e68309 100644 --- a/lib/pages/home.dart +++ b/lib/pages/home.dart @@ -2,6 +2,8 @@ import 'package:bus_infotainment/pages/components/ibus_display.dart'; import 'package:bus_infotainment/singletons/live_information.dart'; +import 'package:bus_infotainment/tfl_datasets.dart'; +import 'package:bus_infotainment/utils/delegates.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; @@ -64,9 +66,12 @@ class pages_Home extends StatelessWidget { ] ), - child: _QuickAnnouncements_IBUS( + child: ManualAnnouncementPicker( backgroundColor: Colors.grey.shade900, outlineColor: Colors.white70, + announcements: [ + ...LiveInformation().manualAnnouncements + ], ), ), @@ -77,6 +82,38 @@ class pages_Home extends StatelessWidget { color: Colors.white70, ), + Container( + + margin: EdgeInsets.all(20), + + child: Container( + + decoration: BoxDecoration( + color: Colors.grey.shade900, + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.3), + blurRadius: 2, + spreadRadius: 4 + ) + ] + ), + + child: DelegateBuilder( + delegate: LiveInformation().routeVariantDelegate, + builder: (context, routeVariant) { + print("rebuilt stop announcement picker"); + return StopAnnouncementPicker( + routeVariant: routeVariant, + backgroundColor: Colors.grey.shade900, + outlineColor: Colors.white70, + ); + }, + ), + ), + + ), + Container( margin: EdgeInsets.all(20), @@ -153,38 +190,46 @@ class pages_Home extends StatelessWidget { } } -class _QuickAnnouncements_IBUS extends StatefulWidget { +class ManualAnnouncementPicker extends StatefulWidget { final Color backgroundColor; final Color outlineColor; + final List announcements; - _QuickAnnouncements_IBUS({super.key, required this.backgroundColor, required this.outlineColor}); + const ManualAnnouncementPicker({super.key, required this.backgroundColor, required this.outlineColor, required this.announcements}); @override - State<_QuickAnnouncements_IBUS> createState() => _QuickAnnouncementsState_IBUS(); + State createState() => _ManualAnnouncementPickerState(); } -class _QuickAnnouncementsState_IBUS extends State<_QuickAnnouncements_IBUS> { +class _ManualAnnouncementPickerState extends State { - List announcements = []; + List announcementWidgets = []; int _currentIndex = 0; + @override + void initState() { + // TODO: implement initState + super.initState(); - _QuickAnnouncementsState_IBUS() { LiveInformation liveInformation = LiveInformation(); - for (ManualAnnouncementEntry announcement in liveInformation.manualAnnouncements) { - announcements.add( - _QuickAnnouncement_IBUS( + if (widget.announcements.isEmpty){ + return; + } + + for (InformationAnnouncementEntry announcement in widget.announcements!) { + announcementWidgets.add( + _ManualAnnouncementEntry( announcement: announcement, index: liveInformation.manualAnnouncements.indexOf(announcement), outlineColor: Colors.white70 ) ); } - } + } @override @@ -219,8 +264,8 @@ class _QuickAnnouncementsState_IBUS extends State<_QuickAnnouncements_IBUS> { color: widget.outlineColor, ), - if (_currentIndex < announcements.length) - announcements[_currentIndex + 0] + if (_currentIndex < announcementWidgets.length) + announcementWidgets[_currentIndex + 0] else Container( height: 50, @@ -240,8 +285,8 @@ class _QuickAnnouncementsState_IBUS extends State<_QuickAnnouncements_IBUS> { color: widget.outlineColor, ), - if (_currentIndex + 1 < announcements.length) - announcements[_currentIndex + 1] + if (_currentIndex + 1 < announcementWidgets.length) + announcementWidgets[_currentIndex + 1] else Container( height: 50, @@ -261,8 +306,8 @@ class _QuickAnnouncementsState_IBUS extends State<_QuickAnnouncements_IBUS> { color: widget.outlineColor, ), - if (_currentIndex + 2 < announcements.length) - announcements[_currentIndex + 2] + if (_currentIndex + 2 < announcementWidgets.length) + announcementWidgets[_currentIndex + 2] else Container( height: 50, @@ -282,8 +327,8 @@ class _QuickAnnouncementsState_IBUS extends State<_QuickAnnouncements_IBUS> { color: widget.outlineColor, ), - if (_currentIndex + 3 < announcements.length) - announcements[_currentIndex + 3] + if (_currentIndex + 3 < announcementWidgets.length) + announcementWidgets[_currentIndex + 3] else Container( height: 50, @@ -354,7 +399,7 @@ class _QuickAnnouncementsState_IBUS extends State<_QuickAnnouncements_IBUS> { Positioned.fill( child: ElevatedButton( onPressed: () { - _currentIndex = wrap(_currentIndex - 4, 0, announcements.length); + _currentIndex = wrap(_currentIndex - 4, 0, announcementWidgets.length); setState(() {}); print(_currentIndex); }, @@ -407,7 +452,7 @@ class _QuickAnnouncementsState_IBUS extends State<_QuickAnnouncements_IBUS> { Positioned.fill( child: ElevatedButton( onPressed: () { - _currentIndex = wrap(_currentIndex + 4, 0, announcements.length); + _currentIndex = wrap(_currentIndex + 4, 0, announcementWidgets.length); setState(() {}); print(_currentIndex); }, @@ -447,17 +492,40 @@ class _QuickAnnouncementsState_IBUS extends State<_QuickAnnouncements_IBUS> { } } +class StopAnnouncementPicker extends ManualAnnouncementPicker { + final BusRouteVariant routeVariant; + + StopAnnouncementPicker({ + Key? key, + required this.routeVariant, + required Color backgroundColor, + required Color outlineColor, + }) : super( + key: key, + backgroundColor: backgroundColor, + outlineColor: outlineColor, + announcements: [ + for (BusRouteStops stop in routeVariant.busStops) + InformationAnnouncementEntry( + shortName: stop.formattedStopName, + informationText: stop.formattedStopName, + audioSources: [] + ) + ] + ); +} + int wrap(int i, int j, int length) { return ((i - j) % length + length) % length; } -class _QuickAnnouncement_IBUS extends StatelessWidget { +class _ManualAnnouncementEntry extends StatelessWidget { - final ManualAnnouncementEntry announcement; + final InformationAnnouncementEntry announcement; final int index; final Color outlineColor; - _QuickAnnouncement_IBUS({super.key, required this.announcement, required this.index, required this.outlineColor}); + _ManualAnnouncementEntry({super.key, required this.announcement, required this.index, required this.outlineColor}); @override Widget build(BuildContext context) { @@ -541,164 +609,4 @@ class _QuickAnnouncement_IBUS extends StatelessWidget { ); } -} - -class QuickAnnouncement extends StatelessWidget { - - List announcementButtons = []; - - QuickAnnouncement({super.key}){ - - LiveInformation liveInformation = LiveInformation(); - - for (ManualAnnouncementEntry entry in liveInformation.manualAnnouncements) { - announcementButtons.add( - _QuickAnnouncement_Entry(manualAnnouncementEntry: entry) - ); - } - - } - - int _currentIndex = 0; - - @override - Widget build(BuildContext context) { - - List UsingAnnouncements = []; - - for (int i = 0; i < 4; i++) { - - Widget widget = announcementButtons[wrap(_currentIndex + i, 0, announcementButtons.length)]; - - UsingAnnouncements.add(widget); - UsingAnnouncements.add( - SizedBox( - height: 10, - ) - ); - } - - - // TODO: implement build - return Container( - - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(10)), - color: Colors.grey.shade900, - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.3), - blurRadius: 4, - spreadRadius: 4 - ) - ] - ), - - padding: EdgeInsets.all(10), - - child: Column( - - crossAxisAlignment: CrossAxisAlignment.start, - - children: [ - - Row( - children: [ - Container( - - decoration: BoxDecoration( - color: Colors.grey.shade800, - borderRadius: BorderRadius.circular(5), - ), - - padding: EdgeInsets.all(8), - - child: Text( - "Quick Announcements", - style: GoogleFonts.montserrat( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Colors.white, - height: 1 - ), - ), - ), - - // Container - - ElevatedButton( - onPressed: () { - _currentIndex = wrap(_currentIndex + 4, 0, announcementButtons.length); - // setState(() {}); - }, - child: const Icon( - Icons.arrow_back, - color: Colors.white, - ) - ), - - ElevatedButton( - onPressed: () { - _currentIndex = wrap(_currentIndex + 4, 0, announcementButtons.length); - // setState(() {}); - }, - child: const Icon( - Icons.arrow_forward, - color: Colors.white, - ) - ) - - ], - ), - - Container( - margin: EdgeInsets.symmetric(vertical: 10), - height: 1, - color: Colors.grey.shade600, - ), - - ...UsingAnnouncements, - - ], - - ) - ); - } - -} - -class _QuickAnnouncement_Entry extends StatelessWidget { - - final ManualAnnouncementEntry manualAnnouncementEntry; - - const _QuickAnnouncement_Entry({super.key, required this.manualAnnouncementEntry}); - - - - @override - Widget build(BuildContext context) { - // TODO: implement build - return Container( - - decoration: BoxDecoration( - color: Colors.grey.shade800, - borderRadius: BorderRadius.circular(5), - ), - - padding: EdgeInsets.all(8), - - width: double.infinity, - - child: Text( - manualAnnouncementEntry.shortName, - style: GoogleFonts.montserrat( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Colors.white - ), - ), - - ); - } - } \ No newline at end of file diff --git a/lib/singletons/live_information.dart b/lib/singletons/live_information.dart index 3b8cd6d..8316411 100644 --- a/lib/singletons/live_information.dart +++ b/lib/singletons/live_information.dart @@ -60,7 +60,8 @@ class LiveInformation { refreshTimer(); } - Timer refreshTimer() => Timer.periodic(Duration(milliseconds: 100), (timer) { + + Timer refreshTimer() => Timer.periodic(Duration(milliseconds: 50), (timer) { _handleAnnouncementQueue(); }); @@ -78,6 +79,9 @@ class LiveInformation { } void _handleAnnouncementQueue() async { + + int timerInterval = 50; + // print("Handling announcement queue"); if (audioPlayer.state != AudioWrapper_State.Playing) { if (announcementQueue.isNotEmpty) { @@ -88,10 +92,10 @@ class LiveInformation { DateTime now = DateTime.now(); if (announcement.scheduledTime != null) { int milisecondDifference = abs(now.millisecondsSinceEpoch - announcement.scheduledTime!.millisecondsSinceEpoch); - print("Q Difference: ${milisecondDifference}"); - if (milisecondDifference <= 100) { + // print("Q Difference: ${milisecondDifference}"); + if (milisecondDifference <= timerInterval) { // Account for the time lost by the periodic timer - // await Future.delayed(Duration(milliseconds: 100 - milisecondDifference)); + await Future.delayed(Duration(milliseconds: timerInterval - milisecondDifference)); } else { return; } @@ -101,7 +105,7 @@ class LiveInformation { } - announcementDelegate.trigger(announcement); + // announcementDelegate.trigger(announcement); _currentAnnouncement = announcement.displayText; lastAnnouncement = DateTime.now(); @@ -113,7 +117,8 @@ class LiveInformation { await Future.delayed(Duration(milliseconds: 150)); } audioPlayer.stop(); - announcementQueue.removeAt(0); + announcementQueue.remove(announcement); + print("Queue length: ${announcementQueue.length}"); print("Popped announcement queue"); } } @@ -143,12 +148,13 @@ class LiveInformation { } late BusSequences busSequences; - BusRouteVariant? _currentRouteVariant; + EventDelegate routeVariantDelegate = EventDelegate(); void setRouteVariant(BusRouteVariant routeVariant) { _currentRouteVariant = routeVariant; announceRouteVariant(routeVariant); + routeVariantDelegate.trigger(routeVariant); } BusRouteVariant? getRouteVariant() { @@ -181,7 +187,7 @@ class LiveInformation { final databases = appwrite.Databases(auth.client); - if (announcement is ManualAnnouncementEntry) { + if (announcement is InformationAnnouncementEntry) { // 5 sedonds in the future DateTime scheduledTime = DateTime.now().add(Duration(seconds: 5)); @@ -205,83 +211,83 @@ class LiveInformation { } - List manualAnnouncements = [ - ManualAnnouncementEntry( + List manualAnnouncements = [ + InformationAnnouncementEntry( shortName: "Driver Change", informationText: "Driver Change", audioSources: [AudioWrapperAssetSource("audio/manual_announcements/driverchange.mp3")], ), - ManualAnnouncementEntry( + InformationAnnouncementEntry( shortName: "No Standing Upr Deck", informationText: "No standing on the upper deck", audioSources: [AudioWrapperAssetSource("audio/manual_announcements/nostanding.mp3")], ), - ManualAnnouncementEntry( + InformationAnnouncementEntry( shortName: "Face Covering", informationText: "Please wear a face covering!", audioSources: [AudioWrapperAssetSource("audio/manual_announcements/facecovering.mp3")], ), - ManualAnnouncementEntry( + InformationAnnouncementEntry( shortName: "Seats Upstairs", informationText: "Seats are available upstairs", audioSources: [AudioWrapperAssetSource("audio/manual_announcements/seatsupstairs.mp3")], ), - ManualAnnouncementEntry( + InformationAnnouncementEntry( shortName: "Bus Terminates Here", informationText: "Bus terminates here. Please take your belongings with you", audioSources: [AudioWrapperAssetSource("audio/manual_announcements/busterminateshere.mp3")], ), - ManualAnnouncementEntry( + InformationAnnouncementEntry( shortName: "Bus On Diversion", informationText: "Bus on diversion. Please listen for further announcements", audioSources: [AudioWrapperAssetSource("audio/manual_announcements/busondiversion.mp3")], ), - ManualAnnouncementEntry( + InformationAnnouncementEntry( shortName: "Destination Change", informationText: "Destination Changed - please listen for further instructions", audioSources: [AudioWrapperAssetSource("audio/manual_announcements/destinationchange.mp3")], ), - ManualAnnouncementEntry( + InformationAnnouncementEntry( shortName: "Wheelchair Space", informationText: "Wheelchair space requested", audioSources: [AudioWrapperAssetSource("audio/manual_announcements/wheelchairspace1.mp3")], ), - ManualAnnouncementEntry( + InformationAnnouncementEntry( shortName: "Move Down The Bus", informationText: "Please move down the bus", audioSources: [AudioWrapperAssetSource("audio/manual_announcements/movedownthebus.mp3")], ), - ManualAnnouncementEntry( + InformationAnnouncementEntry( shortName: "Next Stop Closed", informationText: "The next bus stop is closed", audioSources: [AudioWrapperAssetSource("audio/manual_announcements/nextstopclosed.wav")], ), - ManualAnnouncementEntry( + InformationAnnouncementEntry( shortName: "CCTV In Operation", informationText: "CCTV is in operation on this bus", audioSources: [AudioWrapperAssetSource("audio/manual_announcements/cctvoperation.mp3")], ), - ManualAnnouncementEntry( + InformationAnnouncementEntry( shortName: "Safe Door Opening", informationText: "Driver will open the doors when it is safe to do so", audioSources: [AudioWrapperAssetSource("audio/manual_announcements/safedooropening.mp3")], ), - ManualAnnouncementEntry( + InformationAnnouncementEntry( shortName: "Buggy Safety", informationText: "For your child's safety, please remain with your buggy", audioSources: [AudioWrapperAssetSource("audio/manual_announcements/buggysafety.mp3")], ), - ManualAnnouncementEntry( + InformationAnnouncementEntry( shortName: "Wheelchair Space 2", informationText: "Wheelchair priority space required", audioSources: [AudioWrapperAssetSource("audio/manual_announcements/wheelchairspace2.mp3")], ), - ManualAnnouncementEntry( + InformationAnnouncementEntry( shortName: "Service Regulation", informationText: "Regulating service - please listen for further information", audioSources: [AudioWrapperAssetSource("audio/manual_announcements/serviceregulation.mp3")], ), - ManualAnnouncementEntry( + InformationAnnouncementEntry( shortName: "Bus Ready To Depart", informationText: "This bus is ready to depart", audioSources: [AudioWrapperAssetSource("audio/manual_announcements/readytodepart.mp3")], @@ -403,7 +409,7 @@ class LiveInformation { for (models.Document doc in manual_q.documents) { int index = doc.data['ManualAnnouncementIndex']; - ManualAnnouncementEntry announcement_clone = ManualAnnouncementEntry( + InformationAnnouncementEntry announcement_clone = InformationAnnouncementEntry( shortName: manualAnnouncements[index].shortName, informationText: manualAnnouncements[index].displayText, audioSources: manualAnnouncements[index].audioSources, @@ -496,4 +502,23 @@ class ManualAnnouncementEntry extends AnnouncementQueueEntry { ); } +class InformationAnnouncementEntry extends AnnouncementQueueEntry { + final String shortName; + + InformationAnnouncementEntry({ + required this.shortName, + required String informationText, + required List audioSources, + DateTime? scheduledTime, + DateTime? timestamp, + bool sendToServer = true, + }) : super( + displayText: informationText, + audioSources: audioSources, + sendToServer: sendToServer, + scheduledTime: scheduledTime, + timestamp: timestamp, + ); +} + var abs = (int value) => value < 0 ? -value : value; \ No newline at end of file diff --git a/lib/utils/audio wrapper.dart b/lib/utils/audio wrapper.dart index 57dfae4..fc3e354 100644 --- a/lib/utils/audio wrapper.dart +++ b/lib/utils/audio wrapper.dart @@ -34,16 +34,18 @@ class AudioWrapper { } Future play(AudioWrapperSource source) async { + + Duration? duration; + if (kIsWeb) { // Use just_audio justaudio.AudioSource audioSource = _convertSource_JustAudio(source); - Duration? duration = await _justAudio_AudioPlayer.setAudioSource(audioSource); + duration = await _justAudio_AudioPlayer.setAudioSource(audioSource); _justAudio_AudioPlayer.play(); - return duration; } else { // Use audioplayers @@ -52,8 +54,12 @@ class AudioWrapper { await _audioPlayer_AudioPlayer.play(audioSource); - return await _audioPlayer_AudioPlayer.getDuration(); + duration = await _audioPlayer_AudioPlayer.getDuration(); } + + + + return duration; } void stop(){