diff --git a/assets/audio/5-seconds-of-silence.mp3 b/assets/audio/5-seconds-of-silence.mp3 new file mode 100644 index 0000000..866abc7 Binary files /dev/null and b/assets/audio/5-seconds-of-silence.mp3 differ diff --git a/lib/audio_cache.dart b/lib/audio_cache.dart index ed17ff6..450fb02 100644 --- a/lib/audio_cache.dart +++ b/lib/audio_cache.dart @@ -27,9 +27,7 @@ class AudioCache { class AnnouncementCache extends AudioCache { - String _assetLocation = "assets/ibus_recordings.zip"; - - Future loadAnnouncements(List announcements) async { + Future loadAnnouncementsFromBytes(Uint8List bytes, List announcements) async { List _announements = []; @@ -45,7 +43,7 @@ class AnnouncementCache extends AudioCache { return; } - final bytes = await rootBundle.load(_assetLocation); + // final bytes = await rootBundle.load(_assetLocation); final archive = ZipDecoder().decodeBytes(bytes.buffer.asUint8List()); for (final file in archive) { @@ -62,11 +60,11 @@ class AnnouncementCache extends AudioCache { } } - Future loadAllAnnouncements() async { + Future loadAllAnnouncementsFromBytes(Uint8List bytes) async { print("Loading all announcements."); - final bytes = await rootBundle.load(_assetLocation); + // final bytes = await rootBundle.load(_assetLocation); final archive = ZipDecoder().decodeBytes(bytes.buffer.asUint8List()); print("Done decoding zip file."); @@ -88,5 +86,4 @@ class AnnouncementCache extends AudioCache { print("Done loading all announcements."); } - } \ No newline at end of file diff --git a/lib/auth/auth_api.dart b/lib/auth/auth_api.dart index f233938..35afc2e 100644 --- a/lib/auth/auth_api.dart +++ b/lib/auth/auth_api.dart @@ -120,7 +120,7 @@ class AuthAPI extends ChangeNotifier { }) async { try { - final session = await account.createEmailSession( + final session = await account.createEmailPasswordSession( email: email, password: password, ); diff --git a/lib/backend/live_information.dart b/lib/backend/live_information.dart index b59de26..bf59652 100644 --- a/lib/backend/live_information.dart +++ b/lib/backend/live_information.dart @@ -68,11 +68,16 @@ class LiveInformation { announcementModule = AnnouncementModule(); // Tracker module is not supported on desktop - if (defaultTargetPlatform != TargetPlatform.windows || defaultTargetPlatform != TargetPlatform.linux || defaultTargetPlatform != TargetPlatform.macOS) { + if (defaultTargetPlatform != TargetPlatform.windows && defaultTargetPlatform != TargetPlatform.linux && defaultTargetPlatform != TargetPlatform.macOS) { // Tracker module is not supported on web - await Permission.location.request(); - trackerModule = TrackerModule(); + Permission.location.request().then((value) { + if (value.isGranted) { + trackerModule = TrackerModule(); + } + }); } + + print("Initialised LiveInformation"); } // Auth @@ -115,7 +120,7 @@ class LiveInformation { // Cache/Load the audio files await announcementModule .announcementCache - .loadAnnouncements(audioFiles); + .loadAnnouncementsFromBytes(await LiveInformation().announcementModule.getBundleBytes(), audioFiles); } // Public methods diff --git a/lib/backend/modules/announcement.dart b/lib/backend/modules/announcement.dart index f79525d..623c9c9 100644 --- a/lib/backend/modules/announcement.dart +++ b/lib/backend/modules/announcement.dart @@ -7,6 +7,8 @@ import 'package:bus_infotainment/backend/live_information.dart'; import 'package:bus_infotainment/tfl_datasets.dart'; import 'package:bus_infotainment/utils/audio%20wrapper.dart'; import 'package:bus_infotainment/utils/delegates.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; import 'info_module.dart'; @@ -19,6 +21,28 @@ class AnnouncementModule extends InfoModule { refreshTimer(); } + // Files + String _bundleLocation = "assets/ibus_recordings.zip"; + Uint8List? _bundleBytes; + void setBundleBytes(Uint8List bytes) { + _bundleBytes = bytes; + } + Future getBundleBytes() async { + + if (_bundleBytes != null) { + return _bundleBytes!; + } else { + + if (kIsWeb) { + throw Exception("Cannot load bundle bytes on web"); + } + + final bytes = await rootBundle.load(_bundleLocation); + return bytes.buffer.asUint8List(); + } + + } + // Queue List queue = []; AnnouncementQueueEntry? currentAnnouncement; @@ -63,23 +87,34 @@ class AnnouncementModule extends InfoModule { onAnnouncement.trigger(currentAnnouncement!); if (currentAnnouncement!.audioSources.isNotEmpty) { - try { + + audioPlayer.loadSource(AudioWrapperAssetSource("assets/audio/5-seconds-of-silence.mp3")); + audioPlayer.play(); + await Future.delayed(const Duration(milliseconds: 300)); + audioPlayer.stop(); + + // try { for (AudioWrapperSource source in currentAnnouncement!.audioSources) { + try { + await audioPlayer.loadSource(source); - await audioPlayer.loadSource(source); - - Duration? duration = await audioPlayer.play(); - await Future.delayed(duration!); - if (currentAnnouncement?.audioSources.last != source) { - await Future.delayed(const Duration(milliseconds: 100)); + Duration? duration = await audioPlayer.play(); + await Future.delayed(duration!); + if (currentAnnouncement?.audioSources.last != source) { + await Future.delayed(const Duration(milliseconds: 100)); + } + } catch (e) { + // Do nothing + // print("Error playing announcement: $e on ${currentAnnouncement?.displayText}"); + await Future.delayed(const Duration(seconds: 1)); } } - audioPlayer.stop(); + // audioPlayer.stop(); - } catch (e) { - // Do nothing - print("Error playing announcement: $e"); - } + // } catch (e) { + // // Do nothing + // print("Error playing announcement: $e on ${currentAnnouncement?.displayTex}"); + // } } else { if (queue.isNotEmpty) { await Future.delayed(const Duration(seconds: 5)); @@ -153,7 +188,7 @@ class AnnouncementModule extends InfoModule { } // Cache the announcements - await announcementCache.loadAnnouncements(audioNames); + await announcementCache.loadAnnouncementsFromBytes((await getBundleBytes())!, audioNames); List sources = []; @@ -227,7 +262,7 @@ class AnnouncementModule extends InfoModule { String audioRoute = "R_${routeVariant.busRoute.routeNumber}_001.mp3"; - await announcementCache.loadAnnouncements([audioRoute, "R_RAIL_REPLACEMENT_SERVICE_001.mp3"]); + await announcementCache.loadAnnouncementsFromBytes(await getBundleBytes(), [audioRoute, "R_RAIL_REPLACEMENT_SERVICE_001.mp3"]); AudioWrapperSource sourceRoute = !routeNumber.toLowerCase().startsWith("ul") ? AudioWrapperByteSource(announcementCache[audioRoute]!) : diff --git a/lib/backend/modules/synced_time.dart b/lib/backend/modules/synced_time.dart index 7b7ae92..101007b 100644 --- a/lib/backend/modules/synced_time.dart +++ b/lib/backend/modules/synced_time.dart @@ -15,14 +15,17 @@ class SyncedTimeModule extends InfoModule { } Timer refreshTimer() => Timer.periodic(const Duration(seconds: 10), (timer) async { - var res = await http.get(Uri.parse('http://worldtimeapi.org/api/timezone/Europe/London')); - if (res.statusCode == 200) { - var json = jsonDecode(res.body); - DateTime time = DateTime.parse(json['datetime']); - timeOffset = time.millisecondsSinceEpoch - DateTime.now().millisecondsSinceEpoch; - lastUpdate = DateTime.now(); - print("Time offset: $timeOffset"); - } else { + + try { + var res = await http.get(Uri.parse('http://worldtimeapi.org/api/timezone/Europe/London')); + if (res.statusCode == 200) { + var json = jsonDecode(res.body); + DateTime time = DateTime.parse(json['datetime']); + timeOffset = time.millisecondsSinceEpoch - DateTime.now().millisecondsSinceEpoch; + lastUpdate = DateTime.now(); + print("Time offset: $timeOffset"); + } + } catch (e) { print("Failed to get time from worldtimeapi.org"); } }); diff --git a/lib/backend/modules/tracker.dart b/lib/backend/modules/tracker.dart index 1961c3e..650433f 100644 --- a/lib/backend/modules/tracker.dart +++ b/lib/backend/modules/tracker.dart @@ -8,25 +8,29 @@ import 'package:bus_infotainment/backend/modules/info_module.dart'; import 'package:bus_infotainment/tfl_datasets.dart'; import 'package:bus_infotainment/utils/OrdinanceSurveyUtils.dart'; import 'package:bus_infotainment/utils/audio%20wrapper.dart'; +import 'package:flutter/foundation.dart'; import 'package:geolocator/geolocator.dart'; import 'package:vector_math/vector_math.dart'; class TrackerModule extends InfoModule { - + // Constructor TrackerModule() { locationStream(); - Geolocator.getLastKnownPosition().then((Position? position) { - this._position = position; - updateNearestStop(); - }); + if (!kIsWeb) + { + Geolocator.getLastKnownPosition().then((Position? position) { + this._position = position; + updateNearestStop(); + }); + } liveInformation.routeVariantDelegate.addListener((routeVariant) { print("Route variant changed"); updateNearestStop(); }); } - + // Location Tracker - will update the recorded location when the user moves. Position? _position; Position? get position => _position; @@ -45,6 +49,7 @@ class TrackerModule extends InfoModule { updateNearestStop(); }); + // Location Refresher - will update the recorded location periodically. Timer refreshTimer() => Timer.periodic(Duration(seconds: 1), (timer) async { _position = await Geolocator.getCurrentPosition(); }); @@ -52,6 +57,7 @@ class TrackerModule extends InfoModule { BusRouteStop? nearestStop; bool hasArrived = false; + Future updateNearestStop() async { if (liveInformation.getRouteVariant() == null) { return; diff --git a/lib/main.dart b/lib/main.dart index 58ed02d..1546c82 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:bus_infotainment/pages/audio_cache_test.dart'; +import 'package:bus_infotainment/pages/initial_startup.dart'; import 'package:bus_infotainment/pages/tfl_dataset_test.dart'; import 'package:bus_infotainment/backend/live_information.dart'; import 'package:flutter/foundation.dart'; @@ -26,9 +27,13 @@ void main() async { }); } + + LiveInformation liveInformation = LiveInformation(); await liveInformation.initialize(); + runApp(const MyApp()); + // Disalow screen to turn off on android await SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky); // Disalow landscape mode @@ -37,7 +42,7 @@ void main() async { DeviceOrientation.portraitDown, ]); - runApp(const MyApp()); + } class MyApp extends StatelessWidget { @@ -71,7 +76,9 @@ class MyApp extends StatelessWidget { routes: { '/home': (context) => const MyHomePage(title: 'Flutter Demo Home Page'), '/audiocachetest': (context) => AudioCacheTest(), - '/': (context) => TfL_Dataset_Test(), + // '/': (context) => TfL_Dataset_Test(), + '/': (context) => InitialStartup(), + '/application': (context) => TfL_Dataset_Test(), }, ); diff --git a/lib/pages/audio_cache_test.dart b/lib/pages/audio_cache_test.dart index 3881e24..3126d08 100644 --- a/lib/pages/audio_cache_test.dart +++ b/lib/pages/audio_cache_test.dart @@ -27,7 +27,7 @@ class AudioCacheTest extends StatelessWidget { body: Container( child: FutureBuilder( - future: _announcementCache.loadAllAnnouncements(), + future: Future.delayed(Duration(seconds: 1)), //todo builder: (BuildContext context, AsyncSnapshot snapshot) { if (snapshot.connectionState == ConnectionState.done) { diff --git a/lib/pages/components/ibus_display.dart b/lib/pages/components/ibus_display.dart index 99693a4..f764ce1 100644 --- a/lib/pages/components/ibus_display.dart +++ b/lib/pages/components/ibus_display.dart @@ -140,7 +140,7 @@ class _ibus_displayState extends State { width: 32*4*3, child: TextScroll( _padString(topLine), - velocity: Velocity(pixelsPerSecond: Offset(120, 0)), + velocity: Velocity(pixelsPerSecond: Offset(180, 0)), style: const TextStyle( fontSize: 20, color: Colors.orange, diff --git a/lib/pages/home.dart b/lib/pages/home.dart index 285995b..8b58eae 100644 --- a/lib/pages/home.dart +++ b/lib/pages/home.dart @@ -248,27 +248,40 @@ class _SpeedometerState extends State { } + Timer? reloadTimer; + @override void initState() { // TODO: implement initState super.initState(); - Timer.periodic(Duration(milliseconds: 250), (timer) { + reloadTimer = Timer.periodic(Duration(milliseconds: 250), (timer) { - Position? newPosition = LiveInformation().trackerModule.position; + try { + Position? newPosition = LiveInformation().trackerModule.position; - speed = newPosition?.speed ?? 0; + speed = newPosition?.speed ?? 0; - arrivalTime -= 0.25; - arrivalTime = arrivalTime < 0 ? 0 : arrivalTime; + arrivalTime -= 0.25; + arrivalTime = arrivalTime < 0 ? 0 : arrivalTime; - setState(() { + setState(() { - }); + }); + } catch (e) { + // print(e); + } }); } + @override + void dispose() { + // TODO: implement dispose + super.dispose(); + reloadTimer?.cancel(); + } + @override Widget build(BuildContext context) { // TODO: implement build diff --git a/lib/pages/initial_startup.dart b/lib/pages/initial_startup.dart new file mode 100644 index 0000000..cfdd048 --- /dev/null +++ b/lib/pages/initial_startup.dart @@ -0,0 +1,100 @@ + +import 'package:bus_infotainment/pages/settings.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; + +class InitialStartup extends StatefulWidget { + + @override + State createState() => _InitialStartupState(); +} + +const String Version = "0.2.0"; + +class _InitialStartupState extends State { + bool AllowPassage = false; + + @override + Widget build(BuildContext context) { + // TODO: implement build + return Scaffold( + body: Container( + + alignment: Alignment.center, + + child: Column( + + mainAxisSize: MainAxisSize.min, + + children: [ + + SizedBox( + height: 8, + ), + + AnnouncementUpload( + onUploaded: () { + AllowPassage = true; + setState(() { + + }); + }, + + ), + + if (AllowPassage) + Container( + + margin: EdgeInsets.all(8), + + height: 32, + width: double.infinity, + child: ElevatedButton( + onPressed: (){ + Navigator.pushNamed(context, "/application"); + }, + + // make the corner radius 4, background color match the theme, and text colour white, fill to width of parent + style: ElevatedButton.styleFrom( + backgroundColor: Colors.green, + // foregroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4) + ), + ), + + child: Text( + "Continue to application...", + style: GoogleFonts.interTight( + fontSize: 15, + fontWeight: FontWeight.w600, + color: Colors.white, + letterSpacing: 0.5 + ) + ) + ), + ), + + SizedBox( + height: 8, + ), + + Text( + "Version $Version", + style: GoogleFonts.inter( + fontSize: 12, + fontWeight: FontWeight.w400, + color: Colors.grey + ), + ) + + ], + + + + ) + + ), + ); + } +} \ No newline at end of file diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index 24bd460..23d0144 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -1,8 +1,12 @@ +import 'dart:io'; + +import 'package:bus_infotainment/audio_cache.dart'; import 'package:bus_infotainment/backend/live_information.dart'; import 'package:bus_infotainment/backend/modules/commands.dart'; import 'package:bus_infotainment/utils/delegates.dart'; +import 'package:file_picker/file_picker.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; @@ -71,20 +75,75 @@ class _pages_SettingsState extends State { child: SingleChildScrollView( child: Column( - + + crossAxisAlignment: CrossAxisAlignment.start, + children: [ - + + SizedBox( + height: 8 + ), + + AnnouncementUpload(), + + SizedBox( + height: 8 + ), + Container( - margin: const EdgeInsets.all(8), + margin: EdgeInsets.symmetric( + horizontal: 8 + ), + child: SettingsField( + label: "Announce distance", + defaultValue: "150m", + ) + ), + + SizedBox( + height: 8 + ), + + Container( + margin: EdgeInsets.symmetric( + horizontal: 8 + ), + child: SettingsField( + label: "Announce time", + defaultValue: "10s", + ) + ), + + Container( + + margin: EdgeInsets.only( + left: 8, + top: 2 + ), + + child: Text( + "Console", + style: GoogleFonts.teko( + fontSize: 24 + ), + ), + ), + + Container( + margin: const EdgeInsets.symmetric( + horizontal: 8 + ), child: Console() ), + if (false) Container( height: 2, width: double.infinity, color: Colors.white70, ), + if (false) Container( padding: const EdgeInsets.all(8), @@ -101,6 +160,253 @@ class _pages_SettingsState extends State { } } +class AnnouncementUpload extends StatefulWidget { + + Function onUploaded = () {}; + + AnnouncementUpload({Key? key, this.onUploaded = _defaultOnUploaded}) : super(key: key); + + static void _defaultOnUploaded() {} + + @override + State createState() => _AnnouncementUploadState(); +} + +class _AnnouncementUploadState extends State { + + Future UploadButtonPressed() async { + + // Pick the file + FilePickerResult? result = await FilePicker.platform.pickFiles(); + + if (result != null) { + print("Got file"); + + AnnouncementCache cache = LiveInformation().announcementModule.announcementCache; + + LiveInformation().announcementModule.setBundleBytes(result.files[0].bytes!); + + // load a random announcement to ensure that the file is usable + await cache.loadAnnouncementsFromBytes(result.files[0].bytes!, ["S_WALTHAMSTOW_CENTRAL_001.mp3"]); + + print("Loaded announcements"); + + setState(() { + + }); + + widget.onUploaded(); + + } else { + // User canceled the picker + } + + } + + @override + Widget build(BuildContext context) { + // TODO: implement build + return Container( + decoration: BoxDecoration( + border: Border.all( + color: Colors.white70, + width: 2 + ), + ), + + margin: EdgeInsets.symmetric( + horizontal: 8 + ), + padding: EdgeInsets.all(8), + + // height: 100, + + child: Column( + + children: [ + + Row( + + children: [ + + Icon( + Icons.error, + color: Colors.red, + size: 18, + ), + + SizedBox( + width: 4, + ), + + Transform.translate( + offset: Offset(0, 0), + child: Text( + "IMPORTANT", + style: GoogleFonts.interTight( + fontSize: 18, + fontWeight: FontWeight.bold, + color: Colors.white70, + letterSpacing: 0.1, + ), + ), + ) + + ], + + ), + + Row( + + children: [ + + if (LiveInformation().announcementModule.announcementCache.keys.length == 0) + Icon( + Icons.error, + color: Colors.red, + size: 18, + ) + else + Icon( + Icons.check, + color: Colors.green, + size: 18, + ), + + SizedBox( + width: 4, + ), + + if (LiveInformation().announcementModule.announcementCache.keys.length == 0) + Transform.translate( + offset: Offset(0, 0), + child: Text( + "No announcements", + style: GoogleFonts.interTight( + fontSize: 18, + fontWeight: FontWeight.bold, + color: Colors.white70, + letterSpacing: 0.1, + ), + ), + ) + else + Transform.translate( + offset: Offset(0, 0), + child: Text( + "Announcements loaded successfully", + style: GoogleFonts.interTight( + fontSize: 18, + fontWeight: FontWeight.bold, + color: Colors.white70, + letterSpacing: 0.1, + ), + ), + ) + + ], + + ), + + SizedBox( + height: 8, + ), + + Text( + "Disclaimer: It is illegal to redistribute Transport for London's intellectual property. Even if it were permissible, the files are too large to be packaged into a website...", + style: GoogleFonts.interTight( + fontSize: 12, + fontWeight: FontWeight.w400, + color: Colors.white70, + letterSpacing: 0.1, + height: 1 + ), + ), + + SizedBox( + height: 8, + ), + + Text( + "...because of these reasons, you will have to provide the announcement files yourself.", + style: GoogleFonts.interTight( + fontSize: 12, + fontWeight: FontWeight.w400, + color: Colors.white70, + letterSpacing: 0.1, + height: 1 + ), + ), + + SizedBox( + height: 8, + ), + + Text( + "A ZIP file should be provided containg audio files with the correct naming scheme (e.g. S_WALTHAMSTOW_CENTRAL_001.mp3).", + style: GoogleFonts.interTight( + fontSize: 12, + fontWeight: FontWeight.w400, + color: Colors.white70, + letterSpacing: 0.1, + height: 1 + ), + ), + + SizedBox( + height: 8, + ), + + Text( + "No specific folder structure is required. The files will be sorted and indexed.", + style: GoogleFonts.interTight( + fontSize: 12, + fontWeight: FontWeight.w400, + color: Colors.white70, + letterSpacing: 0.1, + height: 1 + ), + ), + + SizedBox( + height: 8, + ), + + SizedBox( + height: 32, + width: double.infinity, + child: ElevatedButton( + onPressed: (){ + UploadButtonPressed(); + }, + + // make the corner radius 4, background color match the theme, and text colour white, fill to width of parent + style: ElevatedButton.styleFrom( + backgroundColor: Theme.of(context).colorScheme.primary, + foregroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4) + ), + ), + + child: Text( + "Upload file", + style: GoogleFonts.interTight( + fontSize: 15, + fontWeight: FontWeight.w600, + color: Colors.white, + letterSpacing: 0.5 + ) + ) + ), + ), + ], + + ) + ); + } +} + enum _LoginType { login, signup @@ -808,4 +1114,148 @@ class _ConsoleState extends State { ), ); } +} + +class SettingsField extends StatelessWidget { + + String label = "Untitled Field"; + + T defaultValue; + + SettingsField({super.key, this.label = "Untitled Field", required this.defaultValue}); + + + + @override + Widget build(BuildContext context) { + // TODO: implement build + return Container( + decoration: BoxDecoration( + border: Border.all( + color: Colors.white70, + width: 2 + ), + ), + + height: 50, + + padding: EdgeInsets.all(4), + + child: Row( + + children: [ + + SizedBox( + width: 4 + ), + + Text( + label, + style: GoogleFonts.teko( + fontSize: 25, + height: 1, + letterSpacing: 0.02, + color: Colors.white70 + ), + ), + + SizedBox( + width: 8 + ), + + Expanded( + child: Container( + + height: double.infinity, + + alignment: Alignment.center, + + decoration: BoxDecoration( + + border: Border.all( + color: Colors.white70, + width: 2 + ) + + ), + + child: Text( + defaultValue.toString(), + style: GoogleFonts.teko( + fontSize: 25, + height: 1 + ) + ) + + ), + ), + + SizedBox( + width: 4 + ), + + AspectRatio( + aspectRatio: 1, + child: Stack( + children: [ + Container( + + height: double.infinity, + width: double.infinity, + + decoration: BoxDecoration( + + border: Border.all( + color: Colors.white70, + width: 2 + ) + + ), + + child: Icon( + Icons.edit, + color: Colors.white70, + size: 20, + ) + + ), + + Container( + + padding: EdgeInsets.all(2), + + child: Positioned.fill( + child: ElevatedButton( + onPressed: () { + + }, + + style: ElevatedButton.styleFrom( + backgroundColor: Colors.transparent, + shadowColor: Colors.transparent, + surfaceTintColor: Colors.transparent, + foregroundColor: Colors.transparent, + + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(0), + ), + + ), + + child: Container() + ), + ), + ) + + ], + ) + ) + + ], + + ) + + ); + } + } \ No newline at end of file diff --git a/lib/pages/tfl_dataset_test.dart b/lib/pages/tfl_dataset_test.dart index 397d59f..556683b 100644 --- a/lib/pages/tfl_dataset_test.dart +++ b/lib/pages/tfl_dataset_test.dart @@ -42,6 +42,21 @@ class TfL_Dataset_TestState extends State { ibus_display _ibus_display = ibus_display(); + @override + void initState() { + // TODO: implement initState + super.initState(); + + Future.delayed(Duration.zero, () async { + try { + await LiveInformation().announcementModule.getBundleBytes(); + } catch (e) { + Navigator.popAndPushNamed(context, "/"); + print("Sent back to initial startup"); + } + }); + } + @override Widget build(BuildContext context) { @@ -56,7 +71,7 @@ class TfL_Dataset_TestState extends State { if (defaultTargetPlatform == TargetPlatform.android) { shouldCurve = true; - } else { + } else if (defaultTargetPlatform == TargetPlatform.windows && !kIsWeb){ rotated = _selectedIndex == 2; print("Window size: ${MediaQuery.of(context).size}"); @@ -156,295 +171,289 @@ class TfL_Dataset_TestState extends State { child: RotatedBox( quarterTurns: rotated ? 3 : 0, - child: FittedBox( + child: Container( - alignment: Alignment.topCenter, - fit: BoxFit.fitWidth, + constraints: const BoxConstraints( + maxWidth: 411.4, + maxHeight: 850.3, + ), child: Container( - constraints: const BoxConstraints( - maxWidth: 411.4, - maxHeight: 850.3, + decoration: BoxDecoration( + borderRadius: shouldCurve ? const BorderRadius.only( + bottomLeft: Radius.circular(15), + bottomRight: Radius.circular(15), + ) : null, + border: Border.all( + color: Colors.white70, + width: 2, + ), + color: Colors.grey.shade900, ), - child: Container( + margin: const EdgeInsets.all(6), - decoration: BoxDecoration( - borderRadius: shouldCurve ? const BorderRadius.only( - bottomLeft: Radius.circular(15), - bottomRight: Radius.circular(15), - ) : null, - border: Border.all( - color: Colors.white70, - width: 2, + + child: Column( + + children: [ + + if (!hideUI) + Container( + + margin: const EdgeInsets.all(6), + + child: _ibus_display, ), - color: Colors.grey.shade900, - ), - margin: const EdgeInsets.all(6), + if (!hideUI) + Container( + width: double.infinity, + height: 2, + color: Colors.white70, + ), + Expanded( + child: Container( - child: Column( + margin: const EdgeInsets.all(8), - children: [ + decoration: BoxDecoration( + border: Border.all( + color: Colors.white70, + width: 2, + ), + color: Colors.grey.shade900, + borderRadius: hideUI && shouldCurve ? const BorderRadius.only( + bottomLeft: Radius.circular(7), + bottomRight: Radius.circular(7), + ) : null, + ), - if (!hideUI) - Container( + child: ClipRRect( - margin: const EdgeInsets.all(6), - - child: _ibus_display, - ), - - if (!hideUI) - Container( - width: double.infinity, - height: 2, - color: Colors.white70, - ), - - Expanded( - child: Container( - - margin: const EdgeInsets.all(8), - - decoration: BoxDecoration( - border: Border.all( - color: Colors.white70, - width: 2, - ), - color: Colors.grey.shade900, - borderRadius: hideUI && shouldCurve ? const BorderRadius.only( - bottomLeft: Radius.circular(7), - bottomRight: Radius.circular(7), - ) : null, + // curved corners + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(7), + bottomRight: Radius.circular(7), ), - child: ClipRRect( - - // curved corners - borderRadius: BorderRadius.only( - bottomLeft: Radius.circular(7), - bottomRight: Radius.circular(7), - ), - - child: Pages[_selectedIndex], - ) - ), + child: Pages[_selectedIndex], + ) ), + ), - if (!hideUI) - Container( - width: double.infinity, - height: 2, - color: Colors.white70, - ), + if (!hideUI) + Container( + width: double.infinity, + height: 2, + color: Colors.white70, + ), - if (!hideUI) - Container( - height: 50, + if (!hideUI) + Container( + height: 50, - child: Row( + child: Row( - children: [ + children: [ - Expanded( - child: Stack( - children: [ - Container( - alignment: Alignment.center, - margin: const EdgeInsets.all(10), - child: Text( - "Home", - style: GoogleFonts.teko( - color: Colors.white70, - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ) - ), - Positioned.fill( - child: ElevatedButton( - onPressed: () { - setState(() { - _selectedIndex = 0; - }); - }, - - style: ElevatedButton.styleFrom( - backgroundColor: Colors.transparent, - shadowColor: Colors.transparent, - surfaceTintColor: Colors.transparent, - foregroundColor: Colors.transparent, - - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(0), - ), - - ), - - child: Container() - ), - ) - ], - ), - ), - - Container( - width: 2, - height: double.infinity, - color: Colors.white70, - ), - - Expanded( - child: Stack( - children: [ - Container( + Expanded( + child: Stack( + children: [ + Container( alignment: Alignment.center, margin: const EdgeInsets.all(10), child: Text( - "Routes", + "Home", style: GoogleFonts.teko( color: Colors.white70, fontSize: 20, fontWeight: FontWeight.bold, ), ) - ), - Positioned.fill( - child: ElevatedButton( - onPressed: () { - setState(() { - _selectedIndex = 1; - }); - }, + ), + Positioned.fill( + child: ElevatedButton( + onPressed: () { + setState(() { + _selectedIndex = 0; + }); + }, - style: ElevatedButton.styleFrom( - backgroundColor: Colors.transparent, - shadowColor: Colors.transparent, - surfaceTintColor: Colors.transparent, - foregroundColor: Colors.transparent, - - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(0), - ), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.transparent, + shadowColor: Colors.transparent, + surfaceTintColor: Colors.transparent, + foregroundColor: Colors.transparent, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(0), ), - child: Container() + ), + + child: Container() + ), + ) + ], + ), + ), + + Container( + width: 2, + height: double.infinity, + color: Colors.white70, + ), + + Expanded( + child: Stack( + children: [ + Container( + alignment: Alignment.center, + margin: const EdgeInsets.all(10), + child: Text( + "Routes", + style: GoogleFonts.teko( + color: Colors.white70, + fontSize: 20, + fontWeight: FontWeight.bold, ), ) - ], - ), - ), + ), + Positioned.fill( + child: ElevatedButton( + onPressed: () { + setState(() { + _selectedIndex = 1; + }); + }, - Container( - width: 2, - height: double.infinity, - color: Colors.white70, - ), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.transparent, + shadowColor: Colors.transparent, + surfaceTintColor: Colors.transparent, + foregroundColor: Colors.transparent, - Expanded( - child: Stack( - children: [ - Container( - alignment: Alignment.center, - margin: const EdgeInsets.all(10), - child: Text( - "Display", - style: GoogleFonts.teko( - color: Colors.white70, - fontSize: 20, - fontWeight: FontWeight.bold, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(0), ), - ) + + ), + + child: Container() ), - Positioned.fill( - child: ElevatedButton( - onPressed: () { - setState(() { - _selectedIndex = 2; - }); - }, + ) + ], + ), + ), - style: ElevatedButton.styleFrom( - backgroundColor: Colors.transparent, - shadowColor: Colors.transparent, - surfaceTintColor: Colors.transparent, - foregroundColor: Colors.transparent, + Container( + width: 2, + height: double.infinity, + color: Colors.white70, + ), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(0), - ), + Expanded( + child: Stack( + children: [ + Container( + alignment: Alignment.center, + margin: const EdgeInsets.all(10), + child: Text( + "Display", + style: GoogleFonts.teko( + color: Colors.white70, + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ) + ), + Positioned.fill( + child: ElevatedButton( + onPressed: () { + setState(() { + _selectedIndex = 2; + }); + }, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.transparent, + shadowColor: Colors.transparent, + surfaceTintColor: Colors.transparent, + foregroundColor: Colors.transparent, + + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(0), ), - child: Container() - ), - ) - ], - ), - ), + ), - Container( - width: 2, - height: double.infinity, - color: Colors.white70, - ), - - Expanded( - child: Stack( - children: [ - Container( - alignment: Alignment.center, - margin: const EdgeInsets.all(10), - child: Text( - "Settings", - style: GoogleFonts.teko( - color: Colors.white70, - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ) + child: Container() ), - Positioned.fill( - child: ElevatedButton( - onPressed: () { - setState(() { - _selectedIndex = 3; - }); - }, + ) + ], + ), + ), - style: ElevatedButton.styleFrom( - backgroundColor: Colors.transparent, - shadowColor: Colors.transparent, - surfaceTintColor: Colors.transparent, - foregroundColor: Colors.transparent, + Container( + width: 2, + height: double.infinity, + color: Colors.white70, + ), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(0), - ), + Expanded( + child: Stack( + children: [ + Container( + alignment: Alignment.center, + margin: const EdgeInsets.all(10), + child: Text( + "Settings", + style: GoogleFonts.teko( + color: Colors.white70, + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ) + ), + Positioned.fill( + child: ElevatedButton( + onPressed: () { + setState(() { + _selectedIndex = 3; + }); + }, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.transparent, + shadowColor: Colors.transparent, + surfaceTintColor: Colors.transparent, + foregroundColor: Colors.transparent, + + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(0), ), - child: Container() - ), - ) - ], - ), + ), + + child: Container() + ), + ) + ], ), + ), - ], + ], - ), - ) + ), + ) - ], + ], - ) - ), + ) ), ), ), diff --git a/lib/tfl_datasets.dart b/lib/tfl_datasets.dart index cacf7ac..23eee8f 100644 --- a/lib/tfl_datasets.dart +++ b/lib/tfl_datasets.dart @@ -258,7 +258,7 @@ class BusDestination { print("Audio name B: $audioNameB"); print("Audio name C: $audioNameC"); - await LiveInformation().announcementModule.announcementCache.loadAnnouncements([audioNameA, audioNameB, audioNameC]); + await LiveInformation().announcementModule.announcementCache.loadAnnouncementsFromBytes(await LiveInformation().announcementModule.getBundleBytes(), [audioNameA, audioNameB, audioNameC]); Uint8List? audioBytesA = LiveInformation().announcementModule.announcementCache[audioNameA]; Uint8List? audioBytesB = LiveInformation().announcementModule.announcementCache[audioNameB]; diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 3e8cf8a..58c12ea 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -8,6 +8,7 @@ import Foundation import audio_session import audioplayers_darwin import device_info_plus +import flutter_tts import flutter_web_auth_2 import geolocator_apple import just_audio @@ -23,6 +24,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin")) AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin")) DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) + FlutterTtsPlugin.register(with: registry.registrar(forPlugin: "FlutterTtsPlugin")) FlutterWebAuth2Plugin.register(with: registry.registrar(forPlugin: "FlutterWebAuth2Plugin")) GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin")) JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin")) diff --git a/pubspec.lock b/pubspec.lock index 109d35a..d101904 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,10 +5,10 @@ packages: dependency: "direct main" description: name: appwrite - sha256: "1a602cfc6122ec9f179403b44526ff60a6baac9a8f4e8578061fc5e85df67211" + sha256: "335faac24642aaf66627c21ce26a5c64bcbc3911e624c61b9dfbe0eec7be1342" url: "https://pub.dev" source: hosted - version: "11.0.1" + version: "12.0.1" archive: dependency: "direct main" description: @@ -29,66 +29,66 @@ packages: dependency: transitive description: name: audio_session - sha256: "6fdf255ed3af86535c96452c33ecff1245990bb25a605bfb1958661ccc3d467f" + sha256: a49af9981eec5d7cd73b37bacb6ee73f8143a6a9f9bd5b6021e6c346b9b6cf4e url: "https://pub.dev" source: hosted - version: "0.1.18" + version: "0.1.19" audioplayers: dependency: "direct main" description: name: audioplayers - sha256: c05c6147124cd63e725e861335a8b4d57300b80e6e92cea7c145c739223bbaef + sha256: "752039d6aa752597c98ec212e9759519061759e402e7da59a511f39d43aa07d2" url: "https://pub.dev" source: hosted - version: "5.2.1" + version: "6.0.0" audioplayers_android: dependency: transitive description: name: audioplayers_android - sha256: b00e1a0e11365d88576320ec2d8c192bc21f1afb6c0e5995d1c57ae63156acb5 + sha256: de576b890befe27175c2f511ba8b742bec83765fa97c3ce4282bba46212f58e4 url: "https://pub.dev" source: hosted - version: "4.0.3" + version: "5.0.0" audioplayers_darwin: dependency: transitive description: name: audioplayers_darwin - sha256: "3034e99a6df8d101da0f5082dcca0a2a99db62ab1d4ddb3277bed3f6f81afe08" + sha256: e507887f3ff18d8e5a10a668d7bedc28206b12e10b98347797257c6ae1019c3b url: "https://pub.dev" source: hosted - version: "5.0.2" + version: "6.0.0" audioplayers_linux: dependency: transitive description: name: audioplayers_linux - sha256: "60787e73fefc4d2e0b9c02c69885402177e818e4e27ef087074cf27c02246c9e" + sha256: "3d3d244c90436115417f170426ce768856d8fe4dfc5ed66a049d2890acfa82f9" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "4.0.0" audioplayers_platform_interface: dependency: transitive description: name: audioplayers_platform_interface - sha256: "365c547f1bb9e77d94dd1687903a668d8f7ac3409e48e6e6a3668a1ac2982adb" + sha256: "6834dd48dfb7bc6c2404998ebdd161f79cd3774a7e6779e1348d54a3bfdcfaa5" url: "https://pub.dev" source: hosted - version: "6.1.0" + version: "7.0.0" audioplayers_web: dependency: transitive description: name: audioplayers_web - sha256: "22cd0173e54d92bd9b2c80b1204eb1eb159ece87475ab58c9788a70ec43c2a62" + sha256: db8fc420dadf80da18e2286c18e746fb4c3b2c5adbf0c963299dde046828886d url: "https://pub.dev" source: hosted - version: "4.1.0" + version: "5.0.0" audioplayers_windows: dependency: transitive description: name: audioplayers_windows - sha256: "9536812c9103563644ada2ef45ae523806b0745f7a78e89d1b5fb1951de90e1a" + sha256: "8605762dddba992138d476f6a0c3afd9df30ac5b96039929063eceed416795c2" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "4.0.0" boolean_selector: dependency: transitive description: @@ -145,6 +145,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.8" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "55d7b444feb71301ef6b8838dbc1ae02e63dd48c8773f3810ff53bb1e2945b32" + url: "https://pub.dev" + source: hosted + version: "0.3.4+1" crypto: dependency: transitive description: @@ -165,10 +173,10 @@ packages: dependency: "direct main" description: name: csv - sha256: "63ed2871dd6471193dffc52c0e6c76fb86269c00244d244297abbb355c84a86e" + sha256: c6aa2679b2a18cb57652920f674488d89712efaf4d3fdf2e537215b35fc19d6c url: "https://pub.dev" source: hosted - version: "5.1.1" + version: "6.0.0" cupertino_icons: dependency: "direct main" description: @@ -205,10 +213,10 @@ packages: dependency: transitive description: name: ffi - sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" + sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.2" file: dependency: transitive description: @@ -217,6 +225,14 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.0" + file_picker: + dependency: "direct main" + description: + name: file_picker + sha256: d1d0ac3966b36dc3e66eeefb40280c17feb87fa2099c6e22e6a1fc959327bd03 + url: "https://pub.dev" + source: hosted + version: "8.0.0+1" fixnum: dependency: transitive description: @@ -234,10 +250,10 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 + sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1" url: "https://pub.dev" source: hosted - version: "2.0.3" + version: "3.0.2" flutter_map: dependency: "direct main" description: @@ -246,27 +262,43 @@ packages: url: "https://pub.dev" source: hosted version: "6.1.0" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: "8cf40eebf5dec866a6d1956ad7b4f7016e6c0cc69847ab946833b7d43743809f" + url: "https://pub.dev" + source: hosted + version: "2.0.19" flutter_test: dependency: "direct dev" description: flutter source: sdk version: "0.0.0" + flutter_tts: + dependency: "direct main" + description: + name: flutter_tts + sha256: aed2a00c48c43af043ed81145fd8503ddd793dafa7088ab137dbef81a703e53d + url: "https://pub.dev" + source: hosted + version: "4.0.2" flutter_web_auth_2: dependency: transitive description: name: flutter_web_auth_2 - sha256: "0da41e631a368e02366fc1a9b79dd8da191e700a836878bc54466fff51c07df2" + sha256: "3ea3a0cc539ca74319f4f2f7484f62742fe5b2ff9a0fca37575426d6e6f07901" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "3.1.1" flutter_web_auth_2_platform_interface: dependency: transitive description: name: flutter_web_auth_2_platform_interface - sha256: f6fa7059ff3428c19cd756c02fef8eb0147131c7e64591f9060c90b5ab84f094 + sha256: e8669e262005a8354389ba2971f0fc1c36188481234ff50d013aaf993f30f739 url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "3.1.0" flutter_web_plugins: dependency: transitive description: flutter @@ -284,18 +316,18 @@ packages: dependency: transitive description: name: geolocator_android - sha256: "136f1c97e1903366393bda514c5d9e98843418baea52899aa45edae9af8a5cd6" + sha256: f15d1536cd01b1399578f1da1eb5d566e7a718db6a3648f2c24d2e2f859f0692 url: "https://pub.dev" source: hosted - version: "4.5.2" + version: "4.5.4" geolocator_apple: dependency: transitive description: name: geolocator_apple - sha256: "2f2d4ee16c4df269e93c0e382be075cc01d5db6703c3196e4af20a634fe49ef4" + sha256: bc2aca02423ad429cb0556121f56e60360a2b7d694c8570301d06ea0c00732fd url: "https://pub.dev" source: hosted - version: "2.3.6" + version: "2.3.7" geolocator_platform_interface: dependency: transitive description: @@ -316,18 +348,18 @@ packages: dependency: transitive description: name: geolocator_windows - sha256: a92fae29779d5c6dc60e8411302f5221ade464968fe80a36d330e80a71f087af + sha256: "53da08937d07c24b0d9952eb57a3b474e29aae2abf9dd717f7e1230995f13f0e" url: "https://pub.dev" source: hosted - version: "0.2.2" + version: "0.2.3" google_fonts: dependency: "direct main" description: name: google_fonts - sha256: f0b8d115a13ecf827013ec9fc883390ccc0e87a96ed5347a3114cac177ef18e8 + sha256: b1ac0fe2832c9cc95e5e88b57d627c5e68c223b9657f4b96e1487aa9098c7b82 url: "https://pub.dev" source: hosted - version: "6.1.0" + version: "6.2.1" html: dependency: transitive description: @@ -340,10 +372,10 @@ packages: dependency: "direct main" description: name: http - sha256: "4c3f04bfb64d3efd508d06b41b825542f08122d30bda4933fb95c069d22a4fa3" + sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "1.2.1" http_parser: dependency: transitive description: @@ -364,18 +396,18 @@ packages: dependency: transitive description: name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf url: "https://pub.dev" source: hosted - version: "0.6.7" + version: "0.7.1" just_audio: dependency: "direct main" description: name: just_audio - sha256: b607cd1a43bac03d85c3aaee00448ff4a589ef2a77104e3d409889ff079bf823 + sha256: b7cb6bbf3750caa924d03f432ba401ec300fd90936b3f73a9b33d58b1e96286b url: "https://pub.dev" source: hosted - version: "0.9.36" + version: "0.9.37" just_audio_platform_interface: dependency: transitive description: @@ -404,18 +436,42 @@ packages: dependency: transitive description: name: latlong2 - sha256: "18712164760cee655bc790122b0fd8f3d5b3c36da2cb7bf94b68a197fbb0811b" + sha256: "98227922caf49e6056f91b6c56945ea1c7b166f28ffcd5fb8e72fc0b453cc8fe" url: "https://pub.dev" source: hosted - version: "0.9.0" + version: "0.9.1" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + url: "https://pub.dev" + source: hosted + version: "10.0.0" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + url: "https://pub.dev" + source: hosted + version: "2.0.1" lints: dependency: transitive description: name: lints - sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" + sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "3.0.0" lists: dependency: transitive description: @@ -428,34 +484,34 @@ packages: dependency: transitive description: name: logger - sha256: "6bbb9d6f7056729537a4309bda2e74e18e5d9f14302489cc1e93f33b3fe32cac" + sha256: "8c94b8c219e7e50194efc8771cd0e9f10807d8d3e219af473d89b06cc2ee4e04" url: "https://pub.dev" source: hosted - version: "2.0.2+1" + version: "2.2.0" matcher: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted - version: "0.12.16" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.8.0" meta: dependency: transitive description: name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.0" mgrs_dart: dependency: transitive description: @@ -492,26 +548,26 @@ packages: dependency: transitive description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.0" path_provider: dependency: transitive description: name: path_provider - sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b + sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161 url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.3" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668" + sha256: a248d8146ee5983446bf03ed5ea8f6533129a12b11f12057ad1b4a67a2b3b41d url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.4" path_provider_foundation: dependency: transitive description: @@ -548,10 +604,10 @@ packages: dependency: "direct main" description: name: permission_handler - sha256: "74e962b7fad7ff75959161bb2c0ad8fe7f2568ee82621c9c2660b751146bfe44" + sha256: "18bf33f7fefbd812f37e72091a15575e72d5318854877e0e4035a24ac1113ecb" url: "https://pub.dev" source: hosted - version: "11.3.0" + version: "11.3.1" permission_handler_android: dependency: transitive description: @@ -564,10 +620,10 @@ packages: dependency: transitive description: name: permission_handler_apple - sha256: bdafc6db74253abb63907f4e357302e6bb786ab41465e8635f362ee71fd8707b + sha256: e9ad66020b89ff1b63908f247c2c6f931c6e62699b756ef8b3c4569350cd8662 url: "https://pub.dev" source: hosted - version: "9.4.0" + version: "9.4.4" permission_handler_html: dependency: transitive description: @@ -580,10 +636,10 @@ packages: dependency: transitive description: name: permission_handler_platform_interface - sha256: "23dfba8447c076ab5be3dee9ceb66aad345c4a648f0cac292c77b1eb0e800b78" + sha256: "48d4fcf201a1dad93ee869ab0d4101d084f49136ec82a8a06ed9cfeacab9fd20" url: "https://pub.dev" source: hosted - version: "4.2.0" + version: "4.2.1" permission_handler_windows: dependency: transitive description: @@ -612,10 +668,10 @@ packages: dependency: transitive description: name: pointycastle - sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29" + sha256: "70fe966348fe08c34bf929582f1d8247d9d9408130723206472b4687227e4333" url: "https://pub.dev" source: hosted - version: "3.7.4" + version: "3.8.0" polylabel: dependency: transitive description: @@ -652,18 +708,18 @@ packages: dependency: "direct main" description: name: shared_preferences - sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02" + sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180 url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.3" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06" + sha256: "1ee8bf911094a1b592de7ab29add6f826a7331fb854273d55918693d5364a1f2" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.2" shared_preferences_foundation: dependency: transitive description: @@ -692,10 +748,10 @@ packages: dependency: transitive description: name: shared_preferences_web - sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21" + sha256: "9aee1089b36bd2aafe06582b7d7817fd317ef05fc30e6ba14bff247d0933042a" url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.3.0" shared_preferences_windows: dependency: transitive description: @@ -817,26 +873,26 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: "0ecc004c62fd3ed36a2ffcbe0dd9700aee63bd7532d0b642a488b1ec310f492e" + sha256: "6ce1e04375be4eed30548f10a315826fd933c1e493206eab82eed01f438c8d2e" url: "https://pub.dev" source: hosted - version: "6.2.5" + version: "6.2.6" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: d4ed0711849dd8e33eb2dd69c25db0d0d3fdc37e0a62e629fe32f57a22db2745 + sha256: "360a6ed2027f18b73c8d98e159dda67a61b7f2e0f6ec26e86c3ada33b0621775" url: "https://pub.dev" source: hosted - version: "6.3.0" + version: "6.3.1" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "75bb6fe3f60070407704282a2d295630cab232991eb52542b18347a8a941df03" + sha256: "9149d493b075ed740901f3ee844a38a00b33116c7c5c10d7fb27df8987fb51d5" url: "https://pub.dev" source: hosted - version: "6.2.4" + version: "6.2.5" url_launcher_linux: dependency: transitive description: @@ -865,10 +921,10 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: fff0932192afeedf63cdd50ecbb1bc825d31aed259f02bb8dba0f3b729a5e88b + sha256: "3692a459204a33e04bc94f5fb91158faf4f2c8903281ddd82915adecdb1a901d" url: "https://pub.dev" source: hosted - version: "2.2.3" + version: "2.3.0" url_launcher_windows: dependency: transitive description: @@ -881,10 +937,10 @@ packages: dependency: "direct main" description: name: uuid - sha256: cd210a09f7c18cbe5a02511718e0334de6559871052c90a90c0cca46a4aa81c8 + sha256: "814e9e88f21a176ae1359149021870e87f7cddaf633ab678a5d2b0bff7fd1ba8" url: "https://pub.dev" source: hosted - version: "4.3.3" + version: "4.4.0" vector_math: dependency: "direct main" description: @@ -893,30 +949,38 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + url: "https://pub.dev" + source: hosted + version: "13.0.0" web: dependency: transitive description: name: web - sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" url: "https://pub.dev" source: hosted - version: "0.3.0" + version: "0.5.1" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b + sha256: "58c6666b342a38816b2e7e50ed0f1e261959630becd4c879c4f26bfa14aa5a42" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.5" win32: dependency: transitive description: name: win32 - sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8" + sha256: "0a989dc7ca2bb51eac91e8fd00851297cfffd641aa7538b165c62637ca0eaa4a" url: "https://pub.dev" source: hosted - version: "5.2.0" + version: "5.4.0" win32_registry: dependency: transitive description: @@ -958,5 +1022,5 @@ packages: source: hosted version: "1.0.4" sdks: - dart: ">=3.2.0 <4.0.0" - flutter: ">=3.16.0" + dart: ">=3.3.0 <4.0.0" + flutter: ">=3.19.2" diff --git a/pubspec.yaml b/pubspec.yaml index b456929..f778d80 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -33,14 +33,14 @@ dependencies: archive: ^3.1.2 just_audio: ^0.9.36 just_audio_windows: ^0.2.0 - audioplayers: ^5.2.1 - csv: ^5.1.1 - http: any + audioplayers: ^6.0.0 + csv: ^6.0.0 + http: ^1.2.1 google_fonts: ^6.1.0 intl: any text_scroll: ^0.2.0 flutter_map: ^6.1.0 - appwrite: ^11.0.1 + appwrite: ^12.0.1 shared_preferences: ^2.2.2 url_launcher: ^6.2.2 ntp: ^2.0.0 @@ -49,6 +49,8 @@ dependencies: geolocator: ^11.0.0 vector_math: ^2.1.4 permission_handler: ^11.3.0 + flutter_tts: ^4.0.2 + file_picker: ^8.0.0+1 # The following adds the Cupertino Icons font to your application. @@ -64,7 +66,7 @@ dev_dependencies: # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. - flutter_lints: ^2.0.0 + flutter_lints: ^3.0.2 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec @@ -79,12 +81,13 @@ flutter: # To add assets to your application, add an assets section, like this: assets: - - assets/ibus_recordings.zip +# - assets/ibus_recordings.zip - assets/datasets/bus-sequences.csv - assets/fonts/ibus/london-buses-ibus.ttf - assets/audio/manual_announcements/ - assets/audio/to_destination.wav - assets/datasets/bus-blinds.csv + - assets/audio/5-seconds-of-silence.mp3 # - images/a_dot_burr.jpeg # - images/a_dot_ham.jpeg diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 24fcf1e..4ba1456 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -7,6 +7,7 @@ #include "generated_plugin_registrant.h" #include +#include #include #include #include @@ -18,6 +19,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { AudioplayersWindowsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("AudioplayersWindowsPlugin")); + FlutterTtsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FlutterTtsPlugin")); GeolocatorWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("GeolocatorWindows")); JustAudioWindowsPluginRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index a9dab9a..b8b98c6 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST audioplayers_windows + flutter_tts geolocator_windows just_audio_windows permission_handler_windows