Alot of changes

This commit is contained in:
ImBenji
2024-05-01 12:29:59 +01:00
parent 8cc4016836
commit fc4d3ef898
23 changed files with 1755 additions and 430 deletions

View File

@@ -1,36 +1,47 @@
# Install Operating system and dependencies # Environemnt to install flutter and build web
FROM ubuntu:20.04 FROM debian:latest AS build-env
ENV DEBIAN_FRONTEND noninteractive # install all needed stuff
RUN apt-get update
RUN apt-get install -y curl git unzip
RUN apt-get update # define variables
RUN apt-get install -y curl git wget unzip libgconf-2-4 gdb libstdc++6 libglu1-mesa fonts-droid-fallback lib32stdc++6 python3 ARG FLUTTER_SDK=/usr/local/flutter
RUN apt-get clean ARG FLUTTER_VERSION=3.19.5
ARG APP=/app/
# download Flutter SDK from Flutter Github repo #clone flutter
RUN git clone https://github.com/flutter/flutter.git /usr/local/flutter RUN git clone https://github.com/flutter/flutter.git $FLUTTER_SDK
# change dir to current flutter folder and make a checkout to the specific version
RUN cd $FLUTTER_SDK && git fetch && git checkout $FLUTTER_VERSION
# Set flutter environment path # setup the flutter path as an enviromental variable
ENV PATH="/usr/local/flutter/bin:/usr/local/flutter/bin/cache/dart-sdk/bin:${PATH}" ENV PATH="$FLUTTER_SDK/bin:$FLUTTER_SDK/bin/cache/dart-sdk/bin:${PATH}"
# Run flutter doctor # Start to run Flutter commands
RUN flutter doctor # doctor to see if all was installes ok
RUN flutter doctor -v
# Enable flutter web # create folder to copy source code
RUN flutter channel master RUN mkdir $APP
RUN flutter upgrade # copy source code to folder
RUN flutter config --enable-web COPY . $APP
# stup new folder as the working directory
WORKDIR $APP
# Copy files to container and build # Run build: 1 - clean, 2 - pub get, 3 - build web
RUN mkdir /app/ RUN flutter clean
COPY . /app/ RUN flutter pub get
WORKDIR /app/
RUN flutter build web RUN flutter build web
# Record the exposed port # once heare the app will be compiled and ready to deploy
EXPOSE 5000
# make server startup script executable and start the web server # use nginx to deploy
RUN ["chmod", "+x", "/app/server/server.sh"] FROM nginx:1.25.2-alpine
ENTRYPOINT [ "/app/server/server.sh"] # copy the info of the builded web app to nginx
COPY --from=build-env /app/build/web /usr/share/nginx/html
# Expose and run nginx
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

View File

@@ -25,7 +25,7 @@ if (flutterVersionName == null) {
android { android {
namespace "com.imbenji.bus_infotainment" namespace "com.imbenji.bus_infotainment"
compileSdkVersion 34 compileSdkVersion 34
ndkVersion flutter.ndkVersion ndkVersion "25.1.8937393"
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8

View File

@@ -35,5 +35,7 @@
</application> </application>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
</manifest> </manifest>

1
assets/version.txt Normal file
View File

@@ -0,0 +1 @@
0.16.0

View File

@@ -67,19 +67,17 @@ class LiveInformation {
syncedTimeModule = SyncedTimeModule(); syncedTimeModule = SyncedTimeModule();
announcementModule = AnnouncementModule(); announcementModule = AnnouncementModule();
// Tracker module is not supported on desktop initTrackerModule();
if (defaultTargetPlatform != TargetPlatform.windows && defaultTargetPlatform != TargetPlatform.linux && defaultTargetPlatform != TargetPlatform.macOS) {
// Tracker module is not supported on web
Permission.location.request().then((value) {
if (value.isGranted) {
trackerModule = TrackerModule();
}
});
}
print("Initialised LiveInformation"); print("Initialised LiveInformation");
} }
Future<void> initTrackerModule() async {
if (await Permission.location.isGranted) {
trackerModule = TrackerModule();
}
}
// Auth // Auth
AuthAPI auth = AuthAPI(); AuthAPI auth = AuthAPI();
@@ -120,7 +118,15 @@ class LiveInformation {
// Cache/Load the audio files // Cache/Load the audio files
await announcementModule await announcementModule
.announcementCache .announcementCache
.loadAnnouncementsFromBytes(await LiveInformation().announcementModule.getBundleBytes(), audioFiles); .loadAnnouncementsFromBytes(await LiveInformation().announcementModule.getBundleBytes(), [
...audioFiles,
if (!routeVariant.busRoute.routeNumber.toLowerCase().startsWith("ul"))
"R_${routeVariant.busRoute.routeNumber}_001.mp3"
else
"R_RAIL_REPLACEMENT_SERVICE_001.mp3",
]
);
} }
// Public methods // Public methods

View File

@@ -88,10 +88,10 @@ class AnnouncementModule extends InfoModule {
if (currentAnnouncement!.audioSources.isNotEmpty) { if (currentAnnouncement!.audioSources.isNotEmpty) {
audioPlayer.loadSource(AudioWrapperAssetSource("assets/audio/5-seconds-of-silence.mp3")); // audioPlayer.loadSource(AudioWrapperAssetSource("assets/audio/5-seconds-of-silence.mp3"));
audioPlayer.play(); // audioPlayer.play();
await Future.delayed(const Duration(milliseconds: 300)); // await Future.delayed(const Duration(milliseconds: 300));
audioPlayer.stop(); // audioPlayer.stop();
// try { // try {
for (AudioWrapperSource source in currentAnnouncement!.audioSources) { for (AudioWrapperSource source in currentAnnouncement!.audioSources) {
@@ -100,6 +100,8 @@ class AnnouncementModule extends InfoModule {
Duration? duration = await audioPlayer.play(); Duration? duration = await audioPlayer.play();
await Future.delayed(duration!); await Future.delayed(duration!);
audioPlayer.stop();
// await Future.delayed(const Duration(milliseconds: 100));
if (currentAnnouncement?.audioSources.last != source) { if (currentAnnouncement?.audioSources.last != source) {
await Future.delayed(const Duration(milliseconds: 100)); await Future.delayed(const Duration(milliseconds: 100));
} }
@@ -256,25 +258,37 @@ class AnnouncementModule extends InfoModule {
); );
return; return;
} }
print("Checkpoint 4");
print(routeVariant);
print("Checkpoint 4.1");
String routeNumber = routeVariant.busRoute.routeNumber; String routeNumber = routeVariant.busRoute.routeNumber;
String destination = routeVariant.destination!.destination; print("Checkpoint 4.2");
String destination = routeVariant.destination?.destination ?? "NullPointerException";
print("Destination: $destination");
print("Checkpoint 4.3");
String audioRoute = "R_${routeVariant.busRoute.routeNumber}_001.mp3"; String audioRoute = "R_${routeVariant.busRoute.routeNumber}_001.mp3";
print("Checkpoint 5");
await announcementCache.loadAnnouncementsFromBytes(await getBundleBytes(), [audioRoute, "R_RAIL_REPLACEMENT_SERVICE_001.mp3"]); await announcementCache.loadAnnouncementsFromBytes(await getBundleBytes(), [audioRoute, "R_RAIL_REPLACEMENT_SERVICE_001.mp3"]);
print("Checkpoint 6");
AudioWrapperSource sourceRoute = !routeNumber.toLowerCase().startsWith("ul") ? AudioWrapperSource sourceRoute = !routeNumber.toLowerCase().startsWith("ul") ?
AudioWrapperByteSource(announcementCache[audioRoute]!) : AudioWrapperByteSource(announcementCache[audioRoute]!) :
AudioWrapperByteSource(announcementCache["R_RAIL_REPLACEMENT_SERVICE_001.mp3"]!); AudioWrapperByteSource(announcementCache["R_RAIL_REPLACEMENT_SERVICE_001.mp3"]!);
print("Checkpoint 6.1");
AudioWrapperSource sourceDestination = AudioWrapperByteSource(await routeVariant.destination!.getAudioBytes()); AudioWrapperSource sourceDestination = AudioWrapperByteSource(await routeVariant.destination!.getAudioBytes());
print("Checkpoint 7");
AnnouncementQueueEntry announcement = AnnouncementQueueEntry( AnnouncementQueueEntry announcement = AnnouncementQueueEntry(
displayText: "$routeNumber to $destination", displayText: "$routeNumber to $destination",
audioSources: [sourceRoute, AudioWrapperAssetSource("audio/to_destination.wav"), sourceDestination], audioSources: [sourceRoute, AudioWrapperAssetSource("audio/to_destination.wav"), sourceDestination],
scheduledTime: scheduledTime scheduledTime: scheduledTime
); );
print("Checkpoint 8");
queue.add(announcement); queue.add(announcement);
} }

View File

@@ -129,6 +129,8 @@ class CommandModule extends InfoModule {
else if (args[0].startsWith("dest")) { else if (args[0].startsWith("dest")) {
// announce destination <RouteNumber> <RouteVariantIndex> <ScheduledTime> // announce destination <RouteNumber> <RouteVariantIndex> <ScheduledTime>
print("Checkpoint 1");
String routeNumber = args[1]; String routeNumber = args[1];
int routeVariantIndex = int.parse(args[2]); int routeVariantIndex = int.parse(args[2]);
@@ -139,9 +141,11 @@ class CommandModule extends InfoModule {
} }
} catch (e) {} } catch (e) {}
print("Checkpoint 2");
BusRoute route = LiveInformation().busSequences.routes[routeNumber]!; BusRoute route = LiveInformation().busSequences.routes[routeNumber]!;
BusRouteVariant routeVariant = route.routeVariants.values.toList()[routeVariantIndex]; BusRouteVariant routeVariant = route.routeVariants.values.toList()[routeVariantIndex];
print("Checkpoint 3");
liveInformation.announcementModule.queueAnnouncementByRouteVariant( liveInformation.announcementModule.queueAnnouncementByRouteVariant(
routeVariant: routeVariant, routeVariant: routeVariant,
scheduledTime: scheduledTime, scheduledTime: scheduledTime,

View File

@@ -4,10 +4,13 @@ import 'package:bus_infotainment/pages/audio_cache_test.dart';
import 'package:bus_infotainment/pages/initial_startup.dart'; import 'package:bus_infotainment/pages/initial_startup.dart';
import 'package:bus_infotainment/pages/tfl_dataset_test.dart'; import 'package:bus_infotainment/pages/tfl_dataset_test.dart';
import 'package:bus_infotainment/backend/live_information.dart'; import 'package:bus_infotainment/backend/live_information.dart';
import 'package:bus_infotainment/remaster/RemasteredMain.dart';
import 'package:bus_infotainment/remaster/dashboard.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:window_manager/window_manager.dart'; import 'package:window_manager/window_manager.dart';
import 'package:bus_infotainment/remaster/InitialStartup.dart' as remaster;
void main() async { void main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
@@ -55,14 +58,20 @@ class MyApp extends StatelessWidget {
// Permission.location.onGrantedCallback(() => null).request(); // Permission.location.onGrantedCallback(() => null).request();
if (true) {
return RemasteredApp();
}
print("Window size: ${MediaQuery.of(context).size}"); print("Window size: ${MediaQuery.of(context).size}");
return MaterialApp( return MaterialApp(
title: 'Flutter Demo', title: 'Flutter Demo',
theme: ThemeData( theme: ThemeData(
useMaterial3: true,
brightness: Brightness.light, brightness: Brightness.light,
/* light theme settings */ /* light theme settings */
), ),
darkTheme: ThemeData( darkTheme: ThemeData(
useMaterial3: true,
brightness: Brightness.dark, brightness: Brightness.dark,
// colorScheme: ColorScheme.dark(), // colorScheme: ColorScheme.dark(),
colorScheme: ColorScheme.fromSeed( colorScheme: ColorScheme.fromSeed(
@@ -77,8 +86,9 @@ class MyApp extends StatelessWidget {
'/home': (context) => const MyHomePage(title: 'Flutter Demo Home Page'), '/home': (context) => const MyHomePage(title: 'Flutter Demo Home Page'),
'/audiocachetest': (context) => AudioCacheTest(), '/audiocachetest': (context) => AudioCacheTest(),
// '/': (context) => TfL_Dataset_Test(), // '/': (context) => TfL_Dataset_Test(),
'/': (context) => InitialStartup(), '/': (context) => remaster.InitialStartup(),
'/application': (context) => TfL_Dataset_Test(), '/application': (context) => TfL_Dataset_Test(),
'/dashboard': (context) => Dashboard(),
}, },
); );

View File

@@ -22,204 +22,206 @@ class pages_Home extends StatelessWidget {
child: Column( child: SingleChildScrollView(
children: [ child: Column(
children: [
Row(
Row(
children: [
Speedometer(),
],
),
Container(
height: 2,
color: Colors.white70,
),
SingleChildScrollView(
child: Column(
children: [ children: [
Container( Speedometer(),
margin: EdgeInsets.all(10), ],
child: Container( ),
decoration: BoxDecoration( Container(
color: Colors.grey.shade900, height: 2,
), color: Colors.white70,
),
child: AnnouncementPicker(
backgroundColor: Colors.grey.shade900, SingleChildScrollView(
outlineColor: Colors.white70, child: Column(
announcements: [ children: [
for (NamedAnnouncementQueueEntry announcement in LiveInformation().announcementModule.manualAnnouncements)
_AnnouncementEntry( Container(
label: announcement.shortName,
index: LiveInformation().announcementModule.manualAnnouncements.indexOf(announcement), margin: EdgeInsets.all(10),
outlineColor: Colors.white70,
onPressed: (){ child: Container(
LiveInformation liveInformation = LiveInformation();
liveInformation.announcementModule.queueAnnounementByInfoIndex( decoration: BoxDecoration(
infoIndex: liveInformation.announcementModule.manualAnnouncements.indexOf(announcement), color: Colors.grey.shade900,
sendToServer: true ),
);
}, child: AnnouncementPicker(
) backgroundColor: Colors.grey.shade900,
], outlineColor: Colors.white70,
announcements: [
for (NamedAnnouncementQueueEntry announcement in LiveInformation().announcementModule.manualAnnouncements)
_AnnouncementEntry(
label: announcement.shortName,
index: LiveInformation().announcementModule.manualAnnouncements.indexOf(announcement),
outlineColor: Colors.white70,
onPressed: (){
LiveInformation liveInformation = LiveInformation();
liveInformation.announcementModule.queueAnnounementByInfoIndex(
infoIndex: liveInformation.announcementModule.manualAnnouncements.indexOf(announcement),
sendToServer: true
);
},
)
],
),
), ),
), ),
), Container(
height: 2,
Container( color: Colors.white70,
height: 2, ),
color: Colors.white70,
), Container(
Container( margin: EdgeInsets.all(10),
margin: EdgeInsets.all(10), child: Container(
decoration: BoxDecoration(
child: Container( color: Colors.grey.shade900,
decoration: BoxDecoration( ),
color: Colors.grey.shade900,
), child: DelegateBuilder<BusRouteVariant>(
delegate: LiveInformation().routeVariantDelegate,
child: DelegateBuilder<BusRouteVariant>( builder: (context, routeVariant) {
delegate: LiveInformation().routeVariantDelegate, print("rebuilt stop announcement picker");
builder: (context, routeVariant) {
print("rebuilt stop announcement picker");
return StopAnnouncementPicker(
routeVariant: routeVariant,
backgroundColor: Colors.grey.shade900,
outlineColor: Colors.white70,
);
},
defaultBuilder: (context) {
BusRouteVariant? routeVariant = LiveInformation().getRouteVariant();
if (routeVariant == null) {
return Container(
color: Colors.grey.shade900,
child: Center(
child: Text(
"No route selected",
style: GoogleFonts.teko(
fontSize: 25,
color: Colors.white70
),
),
),
);
} else {
return StopAnnouncementPicker( return StopAnnouncementPicker(
routeVariant: routeVariant, routeVariant: routeVariant,
backgroundColor: Colors.grey.shade900, backgroundColor: Colors.grey.shade900,
outlineColor: Colors.white70, outlineColor: Colors.white70,
); );
} },
}, defaultBuilder: (context) {
BusRouteVariant? routeVariant = LiveInformation().getRouteVariant();
if (routeVariant == null) {
return Container(
color: Colors.grey.shade900,
child: Center(
child: Text(
"No route selected",
style: GoogleFonts.teko(
fontSize: 25,
color: Colors.white70
),
),
),
);
} else {
return StopAnnouncementPicker(
routeVariant: routeVariant,
backgroundColor: Colors.grey.shade900,
outlineColor: Colors.white70,
);
}
},
),
), ),
), ),
), ElevatedButton(
onPressed: () async {
ElevatedButton( LiveInformation liveInformation = LiveInformation();
onPressed: () async { final commandModule = liveInformation.commandModule;
LiveInformation liveInformation = LiveInformation();
final commandModule = liveInformation.commandModule; // commandModule.executeCommand(
// "announce dest"
// commandModule.executeCommand( // );
// "announce dest"
// ); liveInformation.announcementModule.queueAnnouncementByRouteVariant(
routeVariant: liveInformation.getRouteVariant()!
liveInformation.announcementModule.queueAnnouncementByRouteVariant( );
routeVariant: liveInformation.getRouteVariant()!
); },
child: Text("Announce current destination"),
}, ),
child: Text("Announce current destination"),
),
// Container(
//
// Container( // margin: EdgeInsets.all(20),
// //
// margin: EdgeInsets.all(20), // height: 300-45,
// //
// height: 300-45, // child: ListView(
// //
// child: ListView( // scrollDirection: Axis.vertical,
// //
// scrollDirection: Axis.vertical, // children: [
// //
// children: [ // ElevatedButton(
// // onPressed: () async {
// ElevatedButton( // LiveInformation liveInformation = LiveInformation();
// onPressed: () async { // liveInformation.queueAnnouncement(await liveInformation.getDestinationAnnouncement(liveInformation.getRouteVariant()!, sendToServer: false));
// LiveInformation liveInformation = LiveInformation(); // },
// liveInformation.queueAnnouncement(await liveInformation.getDestinationAnnouncement(liveInformation.getRouteVariant()!, sendToServer: false)); // child: Text("Test announcement"),
// }, // ),
// child: Text("Test announcement"), //
// ), // ElevatedButton(
// // onPressed: () {
// ElevatedButton( // LiveInformation liveInformation = LiveInformation();
// onPressed: () { // liveInformation.updateServer();
// LiveInformation liveInformation = LiveInformation(); // },
// liveInformation.updateServer(); // child: Text("Update server"),
// }, // ),
// child: Text("Update server"), //
// ), // SizedBox(
// //
// SizedBox( // width: 100,
// //
// width: 100, // child: TextField(
// // onChanged: (String value) {
// child: TextField( // LiveInformation liveInformation = LiveInformation();
// onChanged: (String value) { // // liveInformation.documentID = value;
// LiveInformation liveInformation = LiveInformation(); // },
// // liveInformation.documentID = value; // ),
// }, // ),
// ), //
// ), // SizedBox(
// //
// SizedBox( // width: 200,
// //
// width: 200, // child: TextField(
// // onSubmitted: (String value) {
// child: TextField( // LiveInformation liveInformation = LiveInformation();
// onSubmitted: (String value) { // liveInformation.queueAnnouncement(AnnouncementQueueEntry(
// LiveInformation liveInformation = LiveInformation(); // displayText: value,
// liveInformation.queueAnnouncement(AnnouncementQueueEntry( // audioSources: []
// displayText: value, // ));
// audioSources: [] // },
// )); // ),
// }, // ),
// ), //
// ), // ElevatedButton(
// // onPressed: () {
// ElevatedButton( // LiveInformation liveInformation = LiveInformation();
// onPressed: () { // liveInformation.pullServer();
// LiveInformation liveInformation = LiveInformation(); // },
// liveInformation.pullServer(); // child: Text("Pull server"),
// }, // ),
// child: Text("Pull server"), //
// ), // ],
// //
// ], // ),
// //
// ), // ),
//
// ), ],
),
],
), ),
), ],
], ),
) )
); );

View File

@@ -1,7 +1,12 @@
import 'dart:convert';
import 'package:bus_infotainment/backend/live_information.dart';
import 'package:bus_infotainment/pages/settings.dart'; import 'package:bus_infotainment/pages/settings.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'package:shared_preferences/shared_preferences.dart';
class InitialStartup extends StatefulWidget { class InitialStartup extends StatefulWidget {
@@ -9,11 +14,43 @@ class InitialStartup extends StatefulWidget {
State<InitialStartup> createState() => _InitialStartupState(); State<InitialStartup> createState() => _InitialStartupState();
} }
const String Version = "0.2.0"; // Get the current version from /assets/version.txt
Future<String> GetVersion() async {
return await rootBundle.loadString("assets/version.txt");
}
class _InitialStartupState extends State<InitialStartup> { class _InitialStartupState extends State<InitialStartup> {
bool AllowPassage = false; bool AllowPassage = false;
@override
void initState() {
// TODO: implement initState
super.initState();
SharedPreferences.getInstance().then((prefs) {
String? base64String = prefs.getString("announcements");
if (base64String != null) {
print("Found previois announcement file");
Uint8List ByteList = base64Decode(base64String);
LiveInformation().announcementModule.setBundleBytes(ByteList);
Navigator.pushNamed(context, "/application");
} else {
print("No previous announcement file found");
}
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// TODO: implement build // TODO: implement build
@@ -28,6 +65,8 @@ class _InitialStartupState extends State<InitialStartup> {
children: [ children: [
PermissionsSetup(),
SizedBox( SizedBox(
height: 8, height: 8,
), ),
@@ -79,13 +118,29 @@ class _InitialStartupState extends State<InitialStartup> {
height: 8, height: 8,
), ),
Text( FutureBuilder(
"Version $Version", future: GetVersion(),
style: GoogleFonts.inter( builder: (context, snapshot){
fontSize: 12, if (snapshot.hasData){
fontWeight: FontWeight.w400, return Text(
color: Colors.grey "Version ${snapshot.data}",
), style: GoogleFonts.inter(
fontSize: 12,
fontWeight: FontWeight.w400,
color: Colors.grey
),
);
} else {
return Text(
"Version -.-.-",
style: GoogleFonts.inter(
fontSize: 12,
fontWeight: FontWeight.w400,
color: Colors.grey
),
);
}
},
) )
], ],

View File

@@ -1,5 +1,6 @@
import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:bus_infotainment/audio_cache.dart'; import 'package:bus_infotainment/audio_cache.dart';
@@ -7,9 +8,12 @@ import 'package:bus_infotainment/backend/live_information.dart';
import 'package:bus_infotainment/backend/modules/commands.dart'; import 'package:bus_infotainment/backend/modules/commands.dart';
import 'package:bus_infotainment/utils/delegates.dart'; import 'package:bus_infotainment/utils/delegates.dart';
import 'package:file_picker/file_picker.dart'; import 'package:file_picker/file_picker.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:text_scroll/text_scroll.dart'; import 'package:text_scroll/text_scroll.dart';
import 'package:url_launcher/url_launcher_string.dart'; import 'package:url_launcher/url_launcher_string.dart';
@@ -184,10 +188,24 @@ class _AnnouncementUploadState extends State<AnnouncementUpload> {
AnnouncementCache cache = LiveInformation().announcementModule.announcementCache; AnnouncementCache cache = LiveInformation().announcementModule.announcementCache;
LiveInformation().announcementModule.setBundleBytes(result.files[0].bytes!); late Uint8List bytes;
if (kIsWeb) {
bytes = result.files.single.bytes!;
} else {
File file = File(result.files.single.path!);
bytes = file.readAsBytesSync();
}
LiveInformation().announcementModule.setBundleBytes(bytes);
// load a random announcement to ensure that the file is usable // load a random announcement to ensure that the file is usable
await cache.loadAnnouncementsFromBytes(result.files[0].bytes!, ["S_WALTHAMSTOW_CENTRAL_001.mp3"]); await cache.loadAnnouncementsFromBytes(bytes, ["S_WALTHAMSTOW_CENTRAL_001.mp3"]);
print("Loaded announcements"); print("Loaded announcements");
@@ -195,17 +213,60 @@ class _AnnouncementUploadState extends State<AnnouncementUpload> {
}); });
if (!kIsWeb) {
// Use shared preferences to store the file location
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString("AnnouncementsFileLocation", result.files.single.path!);
}
widget.onUploaded(); widget.onUploaded();
} else { } else {
// User canceled the picker // User canceled the picker
} }
}
@override
void initState() {
// TODO: implement initState
super.initState();
if (!kIsWeb) {
SharedPreferences.getInstance().then((prefs) async {
String FileLocation = prefs.getString("AnnouncementsFileLocation")!;
File file = File(FileLocation);
Uint8List bytes = file.readAsBytesSync();
LiveInformation().announcementModule.setBundleBytes(bytes);
AnnouncementCache cache = LiveInformation().announcementModule.announcementCache;
await cache.loadAnnouncementsFromBytes(bytes, ["S_WALTHAMSTOW_CENTRAL_001.mp3"]);
setState(() {
});
print("Loaded announcemends from SharedPrefs");
widget.onUploaded();
});
}
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// TODO: implement build
bool checkPassed = LiveInformation().announcementModule.announcementCache.keys.length != 0;
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(
border: Border.all( border: Border.all(
@@ -224,77 +285,61 @@ class _AnnouncementUploadState extends State<AnnouncementUpload> {
child: Column( child: Column(
children: [ children: [
if (!checkPassed)
Row(
Row( children: [
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( Icon(
Icons.error, Icons.error,
color: Colors.red, color: Colors.red,
size: 18, size: 18,
) ),
else
SizedBox(
width: 4,
),
Transform.translate(
offset: Offset(0, 0),
child: Text(
"NO ANNOUNCEMENTS LOADED",
style: GoogleFonts.interTight(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.white70,
letterSpacing: 0.1,
),
),
)
],
)
else
Row(
children: [
Icon( Icon(
Icons.check, Icons.check_box,
color: Colors.green, color: Colors.green,
size: 18, size: 18,
), ),
SizedBox( SizedBox(
width: 4, width: 4,
), ),
if (LiveInformation().announcementModule.announcementCache.keys.length == 0)
Transform.translate( Transform.translate(
offset: Offset(0, 0), offset: Offset(0, 0),
child: Text( child: Text(
"No announcements", "ANNOUNCEMENTS LOADED",
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( style: GoogleFonts.interTight(
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@@ -303,10 +348,9 @@ class _AnnouncementUploadState extends State<AnnouncementUpload> {
), ),
), ),
) )
],
], ),
),
SizedBox( SizedBox(
height: 8, height: 8,
@@ -368,6 +412,23 @@ class _AnnouncementUploadState extends State<AnnouncementUpload> {
), ),
), ),
if (kIsWeb)
SizedBox(
height: 8,
),
if (kIsWeb)
Text(
"Announcements uploaded on web are not persistent, and will need to be re-uploaded each time the site is loaded.",
style: GoogleFonts.interTight(
fontSize: 12,
fontWeight: FontWeight.w400,
color: Colors.white70,
letterSpacing: 0.1,
height: 1
),
),
SizedBox( SizedBox(
height: 8, height: 8,
), ),
@@ -407,6 +468,153 @@ class _AnnouncementUploadState extends State<AnnouncementUpload> {
} }
} }
class PermissionsSetup extends StatefulWidget {
@override
State<PermissionsSetup> createState() => _PermissionsSetupState();
}
class _PermissionsSetupState extends State<PermissionsSetup> {
List<bool> _hasPermissions = [];
bool get hasPermissions {
return !_hasPermissions.contains(false) && _hasPermissions.length > 0;
}
Future<void> requestPermission() async {
_hasPermissions = [];
print("Requesting location permission");
if (!await Permission.location.isGranted){
PermissionStatus locationStatus = await Permission.location.request();
if (locationStatus.isGranted) {
_hasPermissions.add(true);
LiveInformation().initTrackerModule();
} else {
_hasPermissions.add(false);
}
} else {
_hasPermissions.add(true);
}
print("Gotten result for location permission");
if (!kIsWeb){
print("Requesting storage permissions");
PermissionStatus fileStatus = await Permission.manageExternalStorage.request();
if (fileStatus.isGranted) {
_hasPermissions.add(true);
} else {
_hasPermissions.add(false);
}
} else {
_hasPermissions.add(true);
}
print("Permissions: $_hasPermissions");
setState(() {
});
}
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.white70,
width: 2
),
),
margin: EdgeInsets.symmetric(
horizontal: 8
),
padding: EdgeInsets.all(8),
child: Column(
children: [
Row(
children: [
Icon(
hasPermissions ? Icons.check_box : Icons.error,
color: hasPermissions ? Colors.green : Colors.red,
size: 18,
),
SizedBox(
width: 4,
),
Transform.translate(
offset: Offset(0, 0),
child: Text(
hasPermissions ? "PERMISSIONS GRANTED" : "MISSING PERMISSIONS",
style: GoogleFonts.interTight(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.white70,
letterSpacing: 0.1,
),
),
),
],
),
SizedBox(
height: 8,
),
SizedBox(
height: 32,
width: double.infinity,
child: ElevatedButton(
onPressed: (){
requestPermission();
},
// 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(
"Request permissions",
style: GoogleFonts.interTight(
fontSize: 15,
fontWeight: FontWeight.w600,
color: Colors.white,
letterSpacing: 0.5
)
)
),
)
],
),
);
}
}
enum _LoginType { enum _LoginType {
login, login,
signup signup

View File

@@ -36,7 +36,7 @@ class TfL_Dataset_TestState extends State<TfL_Dataset_Test> {
pages_Home(), pages_Home(),
pages_Routes(), pages_Routes(),
pages_Display(this), pages_Display(this),
pages_Settings(), pages_Settings()
]; ];
} }
@@ -48,6 +48,11 @@ class TfL_Dataset_TestState extends State<TfL_Dataset_Test> {
super.initState(); super.initState();
Future.delayed(Duration.zero, () async { Future.delayed(Duration.zero, () async {
// if in debug mode skip all this
if (kDebugMode)
return;
try { try {
await LiveInformation().announcementModule.getBundleBytes(); await LiveInformation().announcementModule.getBundleBytes();
} catch (e) { } catch (e) {
@@ -90,80 +95,6 @@ class TfL_Dataset_TestState extends State<TfL_Dataset_Test> {
return Scaffold( return Scaffold(
// appBar: !hideUI ? AppBar(
//
// surfaceTintColor: Colors.transparent,
//
// title: Container(
//
// child: Column(
//
// crossAxisAlignment: CrossAxisAlignment.start,
//
// children: [
//
// Text(
// "Bus Infotainment",
// style: GoogleFonts.teko(
// fontSize: 25,
// fontWeight: FontWeight.bold,
// color: Colors.white,
// height: 1,
// ),
// ),
//
// Row(
//
// children: [
//
// Text(
// "Selected: ",
// style: GoogleFonts.teko(
// fontSize: 20,
// fontWeight: FontWeight.w600,
// color: Colors.white,
// height: 1,
// ),
// ),
//
// if (liveInformation.getRouteVariant() != null)
// Container(
//
// decoration: BoxDecoration(
// color: Colors.black,
// ),
//
// padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 2),
//
// child: Text(
// "${liveInformation.getRouteVariant()!.busRoute.routeNumber} to ${liveInformation.getRouteVariant()!.busStops.last.formattedStopName}",
// style: GoogleFonts.montserrat(
// fontSize: 20,
// fontWeight: FontWeight.w500,
// color: Colors.orange.shade900,
// ),
// ),
//
// )
// else
// Text(
// "None",
// style: GoogleFonts.teko(
// fontSize: 20,
// fontWeight: FontWeight.w500,
// color: Colors.white,
// ),
// ),
// ],
//
// )
//
// ],
//
// ),
// ),
// ) : null,
body: Container( body: Container(
width: double.infinity, width: double.infinity,
@@ -259,6 +190,55 @@ class TfL_Dataset_TestState extends State<TfL_Dataset_Test> {
children: [ children: [
if (false)
Expanded(
child: Stack(
children: [
Container(
alignment: Alignment.center,
margin: const EdgeInsets.all(10),
child: Text(
"Dashboard",
style: GoogleFonts.teko(
color: Colors.white70,
fontSize: 20,
fontWeight: FontWeight.bold,
),
)
),
Positioned.fill(
child: ElevatedButton(
onPressed: () {
setState(() {
Navigator.pushNamed(context, "/dashboard");
});
},
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( Expanded(
child: Stack( child: Stack(
children: [ children: [

View File

@@ -0,0 +1,465 @@
import 'dart:io';
import 'package:bus_infotainment/audio_cache.dart';
import 'package:bus_infotainment/backend/live_information.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:shadcn_ui/shadcn_ui.dart';
class InitialStartup extends StatefulWidget {
@override
State<InitialStartup> createState() => _InitialStartupState();
}
class _InitialStartupState extends State<InitialStartup> {
int _page = 0;
@override
Widget build(BuildContext context) {
if (_page == 0 && !kIsWeb) {
_page = 1;
}
return Scaffold(
body: [
_page1(this),
_page2(this),
_page3(this)
][_page],
);
}
void setPage(int page) {
setState(() {
_page = page;
});
}
}
abstract class InitialStartupPage extends StatefulWidget {
_InitialStartupState parent;
InitialStartupPage(this.parent);
}
// Cookies page - only for web
class _page1 extends InitialStartupPage {
_page1(super.parent);
@override
State<_page1> createState() => _page1State();
}
class _page1State extends State<_page1> {
@override
Widget build(BuildContext context) {
// TODO: implement build
return Container(
padding: EdgeInsets.all(32),
alignment: Alignment.center,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Cookies",
style: TextStyle(
fontSize: 32,
fontWeight: FontWeight.w600,
)
),
Text(
"This website uses first-party cookies for the storage of user data. These cookies are necessary for the functioning of the site and help us provide you with a better browsing experience. By using this website, you consent to the use of these cookies.",
textAlign: TextAlign.center,
),
SizedBox(
height: 8,
),
ShadButton(
onPressed: () {
widget.parent.setPage(1);
},
text: Text(
"I understand and agree"
),
)
],
)
);
}
}
// Permission request page
class _page2 extends InitialStartupPage {
_page2(super.parent);
@override
State<_page2> createState() => _page2State();
}
class _page2State extends State<_page2> {
Future<bool> _allPermissionsGranted() async {
List<bool> perms = [];
perms.addAll([
await Permission.manageExternalStorage.isGranted,
await Permission.location.isGranted
]);
return !perms.contains(false);
}
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(16),
alignment: Alignment.center,
child: SizedBox(
width: double.infinity,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Permissions",
style: TextStyle(
fontSize: 32,
fontWeight: FontWeight.w600,
)
),
SizedBox(
height: 16,
),
ShadCard(
width: double.infinity,
title: Text(
"Location",
),
description: Text(
"Your location is required for automatically updating your nearest bus stop."
),
content: Container(
child: Column(
children: [
SizedBox(
height: 4,
),
FutureBuilder(
future: Permission.location.isGranted,
builder: (context, val) {
bool isEnabled = true;
String text = "Request permission";
Color color = Colors.white;
if (val.hasData) {
isEnabled = !val.data!;
}
if (!isEnabled) {
text = "Permission granted!";
color = Colors.green.shade400;
}
return ShadButton(
text: Text(text),
onPressed: () async {
await Permission.location.request();
setState(() {
});
},
enabled: isEnabled,
backgroundColor: color,
);
},
),
],
),
),
),
SizedBox(
height: 16,
),
ShadCard(
width: double.infinity,
title: Text(
"Storage",
),
description: Text(
"Storage access is required to access recorded announcements."
),
content: Container(
child: Column(
children: [
SizedBox(
height: 4,
),
FutureBuilder(
future: Permission.manageExternalStorage.isGranted,
builder: (context, val) {
bool isEnabled = true;
String text = "Request permission";
Color color = Colors.white;
if (val.hasData) {
isEnabled = !val.data!;
}
if (!isEnabled) {
text = "Permission granted!";
color = Colors.green.shade400;
}
return ShadButton(
text: Text(text),
onPressed: () async {
await Permission.manageExternalStorage.request();
setState(() {
});
},
enabled: isEnabled,
backgroundColor: color,
);
},
)
],
),
),
),
SizedBox(
height: 16,
),
FutureBuilder(
future: _allPermissionsGranted(),
builder: (context, val) {
bool isEnabled = true;
String text = "Continue";
Color color = Colors.white;
if (val.hasData) {
isEnabled = val.data!;
}
if (!isEnabled) {
text = "Grant all permissions before continuing";
}
return ShadButton(
text: Text(text),
onPressed: () async {
widget.parent.setPage(2);
},
enabled: isEnabled,
backgroundColor: color,
width: double.infinity,
);
},
)
],
),
)
);
}
}
class _page3 extends InitialStartupPage {
_page3(super.parent);
@override
State<_page3> createState() => _page3State();
}
class _page3State extends State<_page3> {
Future<bool> _announcementsUploaded() async {
try {
Uint8List bytes = await LiveInformation().announcementModule.getBundleBytes();
return true;
} catch (e) {
return false;
}
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Container(
padding: EdgeInsets.all(16),
alignment: Alignment.center,
child: SizedBox(
width: double.infinity,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Prerequisites",
style: TextStyle(
fontSize: 32,
fontWeight: FontWeight.w600,
)
),
SizedBox(
height: 16,
),
ShadCard(
width: double.infinity,
title: Text(
"Announcement files",
),
description: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"You are required to upload the London iBus announcement files. These files can be acquire by submitting a request to TfL under the Freedom of Information Act (2000)"
),
SizedBox(
height: 4,
),
Text(
"Please upload a zip file."
)
],
),
content: Container(
child: Column(
children: [
SizedBox(
height: 4,
),
FutureBuilder(
future: _announcementsUploaded(),
builder: (context, val) {
bool isEnabled = true;
String text = "Upload file";
Color color = Colors.white;
if (val.hasData) {
isEnabled = !val.data!;
}
if (!isEnabled) {
text = "File uploaded!";
color = Colors.green.shade400;
}
return ShadButton(
text: Text(text),
onPressed: () async {
FilePickerResult? result = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowedExtensions: [
"zip"
]
);
if (result != null) {
late Uint8List bytes;
if (kIsWeb) {
bytes = result.files.single.bytes!;
} else {
File file = File(result.files.single.path!);
bytes = file.readAsBytesSync();
}
LiveInformation().announcementModule.setBundleBytes(bytes);
AnnouncementCache cache = LiveInformation().announcementModule.announcementCache;
// load a random announcement to ensure that the file is usable
await cache.loadAnnouncementsFromBytes(bytes, ["S_WALTHAMSTOW_CENTRAL_001.mp3"]);
setState(() {
});
}
},
enabled: isEnabled,
backgroundColor: color,
);
},
)
],
),
),
),
],
),
)
);
}
}

View File

@@ -0,0 +1,26 @@
import 'package:bus_infotainment/remaster/InitialStartup.dart';
import 'package:flutter/material.dart';
import 'package:shadcn_ui/shadcn_ui.dart';
class RemasteredApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return ShadApp(
darkTheme: ShadThemeData(
brightness: Brightness.dark,
colorScheme: ShadSlateColorScheme.dark(),
),
routes: {
'/': (context) => InitialStartup()
},
);
}
}

365
lib/remaster/dashboard.dart Normal file
View File

@@ -0,0 +1,365 @@
import 'package:bus_infotainment/pages/components/ibus_display.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'dart:io' show Platform;
import 'package:flutter/widgets.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:text_scroll/text_scroll.dart';
Color rgb(int r, int g, int b) {
return Color.fromRGBO(r, g, b, 1);
}
class Dashboard extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
backgroundColor: Colors.grey.shade900,
bottomNavigationBar: ((defaultTargetPlatform == TargetPlatform.android || defaultTargetPlatform == TargetPlatform.iOS)) ? null : BottomAppBar(
color: Colors.grey.shade800,
child: Row(
children: [
IconButton(
icon: Icon(Icons.home),
onPressed: () {
Navigator.pushNamed(context, "/dashboard");
},
),
IconButton(
icon: Icon(Icons.search),
onPressed: () {
Navigator.pushNamed(context, "/search");
},
),
IconButton(
icon: Icon(Icons.settings),
onPressed: () {
Navigator.pushNamed(context, "/settings");
},
),
],
),
),
body: Column(
children: [
Container(
margin: EdgeInsets.all(16),
padding: EdgeInsets.all(8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.grey.shade800
),
// height: 100,
child: ibus_display()
),
Expanded(
child: Row(
children: [
if (false)
if (!(defaultTargetPlatform == TargetPlatform.android || defaultTargetPlatform == TargetPlatform.iOS))
NavigationRail(
selectedIndex: 0,
groupAlignment: 1,
destinations: [
NavigationRailDestination(
icon: Icon(Icons.home),
label: Text("Dashboard"),
),
NavigationRailDestination(
icon: Icon(Icons.search),
label: Text("Routes")
),
NavigationRailDestination(
icon: Icon(Icons.settings),
label: Text("Settings")
)
],
),
Expanded(
child: Container(
child: Column(
children: [
Container(
padding: EdgeInsets.symmetric(
horizontal: 16
),
child: IntrinsicHeight(
child: Row(
children: [
Expanded(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.grey.shade800
),
padding: EdgeInsets.all(16),
child: IntrinsicWidth(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Bus Route:",
style: GoogleFonts.interTight(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.white
)
),
SizedBox(
width: 16,
),
Text(
"11",
style: GoogleFonts.interTight(
fontSize: 18,
fontWeight: FontWeight.normal,
color: Colors.white
)
)
],
),
Row(
// mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Destination:",
style: GoogleFonts.interTight(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.white
)
),
const SizedBox(
width: 16,
),
Text(
"Fullham Broadway",
style: GoogleFonts.interTight(
fontSize: 18,
fontWeight: FontWeight.normal,
color: Colors.white
)
)
],
),
const SizedBox(
height: 8,
),
Row(
// mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Next Stop:",
style: GoogleFonts.interTight(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.white
)
),
const SizedBox(
width: 16,
),
Text(
"St Thomas Hospital / County Hall",
style: GoogleFonts.interTight(
fontSize: 18,
fontWeight: FontWeight.normal,
color: Colors.white
),
overflow: TextOverflow.fade,
)
],
),
Row(
// mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Last Stop:",
style: GoogleFonts.interTight(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.white
),
overflow: TextOverflow.fade,
),
const SizedBox(
width: 16,
),
Text(
"Fullham Town Hall",
style: GoogleFonts.interTight(
fontSize: 18,
fontWeight: FontWeight.normal,
color: Colors.white
),
overflow: TextOverflow.fade,
)
],
),
],
),
)
),
),
// SizedBox(
// width: 16,
// ),
//
// Column(
//
// children: [
//
// SizedBox(
//
// width: 150,
//
// child: FloatingActionButton(
// onPressed: () {
//
// },
//
// backgroundColor: Colors.red,
//
// child: Text(
// "Bus Stopping",
// style: GoogleFonts.interTight(
// fontSize: 18,
// fontWeight: FontWeight.bold,
// color: Colors.white
// )
//
// ),
// ),
// ),
//
// SizedBox(
// height: 16
// ),
//
// SizedBox(
//
// width: 150,
// height: 100,
//
// child: FloatingActionButton(
// onPressed: () {
//
// },
//
// backgroundColor: Colors.grey.shade600,
//
// child: Text(
// "Acknowledge Bus Stop",
// style: GoogleFonts.interTight(
// fontSize: 18,
// fontWeight: FontWeight.bold,
// color: Colors.white
// ),
// textAlign: TextAlign.center,
//
// ),
// ),
// )
//
// ],
//
// )
],
),
),
)
],
),
),
)
],
),
),
],
)
);
}
}

View File

@@ -7,7 +7,7 @@ import 'package:bus_infotainment/backend/live_information.dart';
import 'package:bus_infotainment/backend/modules/info_module.dart'; import 'package:bus_infotainment/backend/modules/info_module.dart';
import 'package:bus_infotainment/utils/NameBeautify.dart'; import 'package:bus_infotainment/utils/NameBeautify.dart';
import 'package:bus_infotainment/utils/OrdinanceSurveyUtils.dart'; import 'package:bus_infotainment/utils/OrdinanceSurveyUtils.dart';
import 'package:csv/csv.dart'; import 'package:fast_csv/csv_converter.dart';
import 'package:vector_math/vector_math.dart'; import 'package:vector_math/vector_math.dart';
class BusSequences extends InfoModule { class BusSequences extends InfoModule {
@@ -19,13 +19,16 @@ class BusSequences extends InfoModule {
BusSequences.fromCSV(String destinationsCSV, String busSequencesCSV) { BusSequences.fromCSV(String destinationsCSV, String busSequencesCSV) {
// Init the bus destinations // Init the bus destinations
List<List<dynamic>> destinationRows = const CsvToListConverter().convert(destinationsCSV); List<List<String>> destinationRows = CsvConverter().convert(destinationsCSV);
destinationRows.removeAt(0); destinationRows.removeAt(0);
print("Destination rows: ${destinationRows.length}");
for (int i = 0; i < destinationRows.length; i++) { for (int i = 0; i < destinationRows.length; i++) {
try { try {
List<dynamic> entries = destinationRows[i]; List<dynamic> entries = destinationRows[i];
// print("Parsing destination row $i: $entries");
String routeNumber = entries[0].toString(); String routeNumber = entries[0].toString();
@@ -50,9 +53,11 @@ class BusSequences extends InfoModule {
} catch (e) {} } catch (e) {}
} }
print("Loaded ${destinations.length} destinations");
// Init the bus routes // Init the bus routes
List<List<dynamic>> busSequenceRows = const CsvToListConverter().convert(busSequencesCSV); List<List<dynamic>> busSequenceRows = CsvConverter().convert(busSequencesCSV);
busSequenceRows.removeAt(0); busSequenceRows.removeAt(0);
for (int i = 0; i < busSequenceRows.length; i++) { for (int i = 0; i < busSequenceRows.length; i++) {
@@ -61,20 +66,21 @@ class BusSequences extends InfoModule {
{ {
List<dynamic> entries = busSequenceRows[i]; List<dynamic> entries = busSequenceRows[i];
// print("Parsing bus sequence row $i: $entries");
String routeNumber = entries[0].toString(); String routeNumber = entries[0].toString();
BusRoute route = routes.containsKey(routeNumber) ? routes[routeNumber]! : BusRoute(routeNumber: routeNumber); BusRoute route = routes.containsKey(routeNumber) ? routes[routeNumber]! : BusRoute(routeNumber: routeNumber);
int routeVariant = entries[1]; int routeVariant = int.parse(entries[1]);
BusRouteStop stop = BusRouteStop(); BusRouteStop stop = BusRouteStop();
stop.stopName = entries[6].toString(); stop.stopName = entries[6].toString();
stop.stopCode = entries[4].toString(); stop.stopCode = entries[4].toString();
stop.easting = entries[7]; stop.easting = int.parse(entries[7]);
stop.northing = entries[8]; stop.northing = int.parse(entries[8]);
stop.heading = entries[9] != "" ? entries[9] : -1; stop.heading = int.parse(entries[9] != "" ? entries[9] : "-1");
BusRouteVariant variant = route.routeVariants.containsKey(routeVariant) ? route.routeVariants[routeVariant]! : BusRouteVariant(routeVariant: routeVariant, busRoute: route); BusRouteVariant variant = route.routeVariants.containsKey(routeVariant) ? route.routeVariants[routeVariant]! : BusRouteVariant(routeVariant: routeVariant, busRoute: route);
@@ -90,6 +96,8 @@ class BusSequences extends InfoModule {
} }
} }
print("Loaded ${routes.length} routes");
} }
} }
@@ -164,6 +172,9 @@ class BusRouteVariant {
} }
print("Nearest destination A: $nearestDestinationA, distance: $nearestDistanceA");
print("Nearest destination B: $nearestDestinationB, distance: $nearestDistanceB");
// Choose the nearest destination // Choose the nearest destination
if (nearestDistanceA < nearestDistanceB) { if (nearestDistanceA < nearestDistanceB) {
_destination = nearestDestinationA; _destination = nearestDestinationA;
@@ -172,8 +183,14 @@ class BusRouteVariant {
} }
} }
return _destination; return _destination;
} }
@override
String toString() {
return 'BusRouteVariant{routeVariant: $routeVariant, busRoute: ${busRoute.routeNumber}, busStops: ${busStops.length}, destinations: ${busRoute.destinations.length}}';
}
} }
class BusRouteStop { class BusRouteStop {

View File

@@ -25,7 +25,7 @@ class AudioWrapper {
print("AudioWrapper mode: $mode"); print("AudioWrapper mode: $mode");
// mode = AudioWrapper_Mode.Mobile; mode = AudioWrapper_Mode.Mobile;
} }
justaudio.AudioSource _convertSource_JustAudio(AudioWrapperSource source){ justaudio.AudioSource _convertSource_JustAudio(AudioWrapperSource source){
@@ -126,11 +126,11 @@ class AudioWrapper {
} catch (e) {} } catch (e) {}
_justAudio_AudioPlayer = justaudio.AudioPlayer(); _justAudio_AudioPlayer = justaudio.AudioPlayer();
} else if (mode == AudioWrapper_Mode.Mobile) { } else if (mode == AudioWrapper_Mode.Mobile) {
_audioPlayer_AudioPlayer.stop(); // _audioPlayer_AudioPlayer.stop();
try { try {
_audioPlayer_AudioPlayer.dispose(); // _audioPlayer_AudioPlayer.dispose();
} catch (e) {} } catch (e) {}
_audioPlayer_AudioPlayer = audioplayers.AudioPlayer(); // _audioPlayer_AudioPlayer = audioplayers.AudioPlayer();
} }
} }
@@ -142,12 +142,13 @@ class AudioWrapper {
return AudioWrapper_State.NotPlaying; return AudioWrapper_State.NotPlaying;
} }
} else { } else {
if (_audioPlayer_AudioPlayer.state == audioplayers.PlayerState.playing){ // if (_audioPlayer_AudioPlayer.state == audioplayers.PlayerState.playing){
return AudioWrapper_State.Playing; // return AudioWrapper_State.Playing;
} else { // } else {
return AudioWrapper_State.NotPlaying; // return AudioWrapper_State.NotPlaying;
} // }
} }
return AudioWrapper_State.NotPlaying;
} }
} }

View File

@@ -0,0 +1,15 @@
import 'package:flutter/foundation.dart';
String WW_AssetSource(String location) {
if (kIsWeb) {
// remove the first character if it is a '/'
if (location.startsWith('/')) {
location = location.substring(1);
}
return "assets/$location";
}
return location;
}

View File

@@ -8,12 +8,12 @@ import Foundation
import audio_session import audio_session
import audioplayers_darwin import audioplayers_darwin
import device_info_plus import device_info_plus
import flutter_tts
import flutter_web_auth_2 import flutter_web_auth_2
import geolocator_apple import geolocator_apple
import just_audio import just_audio
import package_info_plus import package_info_plus
import path_provider_foundation import path_provider_foundation
import rive_common
import screen_retriever import screen_retriever
import shared_preferences_foundation import shared_preferences_foundation
import url_launcher_macos import url_launcher_macos
@@ -24,12 +24,12 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin")) AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin"))
AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin")) AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin"))
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
FlutterTtsPlugin.register(with: registry.registrar(forPlugin: "FlutterTtsPlugin"))
FlutterWebAuth2Plugin.register(with: registry.registrar(forPlugin: "FlutterWebAuth2Plugin")) FlutterWebAuth2Plugin.register(with: registry.registrar(forPlugin: "FlutterWebAuth2Plugin"))
GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin")) GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin"))
JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin")) JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin"))
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
RivePlugin.register(with: registry.registrar(forPlugin: "RivePlugin"))
ScreenRetrieverPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverPlugin")) ScreenRetrieverPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))

View File

@@ -17,6 +17,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.4.10" version: "3.4.10"
args:
dependency: transitive
description:
name: args
sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a"
url: "https://pub.dev"
source: hosted
version: "2.5.0"
async: async:
dependency: transitive dependency: transitive
description: description:
@@ -97,6 +105,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.1" version: "2.1.1"
boxy:
dependency: transitive
description:
name: boxy
sha256: eaa774ff591191b86f2eb8e8eae878aec50604404b74388a27e655cf3aadf758
url: "https://pub.dev"
source: hosted
version: "2.2.0"
characters: characters:
dependency: transitive dependency: transitive
description: description:
@@ -169,22 +185,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.0" version: "1.0.0"
csv:
dependency: "direct main"
description:
name: csv
sha256: c6aa2679b2a18cb57652920f674488d89712efaf4d3fdf2e537215b35fc19d6c
url: "https://pub.dev"
source: hosted
version: "6.0.0"
cupertino_icons: cupertino_icons:
dependency: "direct main" dependency: "direct main"
description: description:
name: cupertino_icons name: cupertino_icons
sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.6" version: "1.0.8"
device_info_plus: device_info_plus:
dependency: transitive dependency: transitive
description: description:
@@ -209,6 +217,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.1" version: "1.3.1"
fast_csv:
dependency: "direct main"
description:
name: fast_csv
sha256: "2165aa6b76daa0de168a712a157a78e60fd786257228935dd9d2809fe2ef7d8a"
url: "https://pub.dev"
source: hosted
version: "0.2.11"
ffi: ffi:
dependency: transitive dependency: transitive
description: description:
@@ -229,10 +245,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: file_picker name: file_picker
sha256: d1d0ac3966b36dc3e66eeefb40280c17feb87fa2099c6e22e6a1fc959327bd03 sha256: b6283d7387310ad83bc4f3bc245b75d223a032ae6eba275afcd585de2b9a1476
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.0.0+1" version: "8.0.1"
fixnum: fixnum:
dependency: transitive dependency: transitive
description: description:
@@ -246,6 +262,14 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
flutter_animate:
dependency: transitive
description:
name: flutter_animate
sha256: "7c8a6594a9252dad30cc2ef16e33270b6248c4dedc3b3d06c86c4f3f4dc05ae5"
url: "https://pub.dev"
source: hosted
version: "4.5.0"
flutter_lints: flutter_lints:
dependency: "direct dev" dependency: "direct dev"
description: description:
@@ -254,6 +278,11 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.2" version: "3.0.2"
flutter_localizations:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
flutter_map: flutter_map:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -270,19 +299,27 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.19" version: "2.0.19"
flutter_shaders:
dependency: transitive
description:
name: flutter_shaders
sha256: "02750b545c01ff4d8e9bbe8f27a7731aa3778402506c67daa1de7f5fc3f4befe"
url: "https://pub.dev"
source: hosted
version: "0.1.2"
flutter_svg:
dependency: transitive
description:
name: flutter_svg
sha256: "7b4ca6cf3304575fe9c8ec64813c8d02ee41d2afe60bcfe0678bcb5375d596a2"
url: "https://pub.dev"
source: hosted
version: "2.0.10+1"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" 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: flutter_web_auth_2:
dependency: transitive dependency: transitive
description: description:
@@ -360,6 +397,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.2.1" version: "6.2.1"
graphs:
dependency: transitive
description:
name: graphs
sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19
url: "https://pub.dev"
source: hosted
version: "2.3.1"
html: html:
dependency: transitive dependency: transitive
description: description:
@@ -388,10 +433,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: intl name: intl
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.19.0" version: "0.18.1"
js: js:
dependency: transitive dependency: transitive
description: description:
@@ -488,6 +533,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.0" version: "2.2.0"
lucide_icons_flutter:
dependency: transitive
description:
name: lucide_icons_flutter
sha256: "43b11fa16f243529c538bcb4a1af014c03c177056c0d46039bc4f665320428c6"
url: "https://pub.dev"
source: hosted
version: "1.0.8"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
@@ -520,6 +573,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.0" version: "2.0.0"
modular_ui:
dependency: "direct main"
description:
name: modular_ui
sha256: c7bfa2d509f6b55f45833ea5a46c7b40030c2a3c8fb26f5211eab440235ee99f
url: "https://pub.dev"
source: hosted
version: "0.0.5"
ntp: ntp:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -552,6 +613,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.9.0" version: "1.9.0"
path_parsing:
dependency: transitive
description:
name: path_parsing
sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf
url: "https://pub.dev"
source: hosted
version: "1.0.1"
path_provider: path_provider:
dependency: transitive dependency: transitive
description: description:
@@ -648,6 +717,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.2.1" version: "0.2.1"
petitparser:
dependency: transitive
description:
name: petitparser
sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
url: "https://pub.dev"
source: hosted
version: "6.0.2"
platform: platform:
dependency: transitive dependency: transitive
description: description:
@@ -668,10 +745,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: pointycastle name: pointycastle
sha256: "70fe966348fe08c34bf929582f1d8247d9d9408130723206472b4687227e4333" sha256: "79fbafed02cfdbe85ef3fd06c7f4bc2cbcba0177e61b765264853d4253b21744"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.8.0" version: "3.9.0"
polylabel: polylabel:
dependency: transitive dependency: transitive
description: description:
@@ -688,6 +765,22 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.0" version: "2.1.0"
rive:
dependency: transitive
description:
name: rive
sha256: ec44b6cf7341e21727c4b0e762f4ac82f9a45f7e52df3ebad2d1289a726fbaaf
url: "https://pub.dev"
source: hosted
version: "0.13.1"
rive_common:
dependency: transitive
description:
name: rive_common
sha256: "0f070bc0e764c570abd8b34d744ef30d1292bd4051f2e0951bbda755875fce6a"
url: "https://pub.dev"
source: hosted
version: "0.3.3"
rxdart: rxdart:
dependency: transitive dependency: transitive
description: description:
@@ -704,6 +797,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.1.9" version: "0.1.9"
shadcn_ui:
dependency: "direct main"
description:
name: shadcn_ui
sha256: "06c25555efbabe6d1d6acd6397bff4940e931d53ac3448e3a4f6a2287ab6798d"
url: "https://pub.dev"
source: hosted
version: "0.3.3"
shared_preferences: shared_preferences:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -837,6 +938,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.2.0" version: "0.2.0"
two_dimensional_scrollables:
dependency: transitive
description:
name: two_dimensional_scrollables
sha256: c972f327282149a9018eb629ea848fdbc1acf6eda0969d86317c97ce8e4efa78
url: "https://pub.dev"
source: hosted
version: "0.2.1"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
@@ -921,10 +1030,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_web name: url_launcher_web
sha256: "3692a459204a33e04bc94f5fb91158faf4f2c8903281ddd82915adecdb1a901d" sha256: "8d9e750d8c9338601e709cd0885f95825086bd8b642547f26bda435aade95d8a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.0" version: "2.3.1"
url_launcher_windows: url_launcher_windows:
dependency: transitive dependency: transitive
description: description:
@@ -941,6 +1050,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.4.0" version: "4.4.0"
vector_graphics:
dependency: transitive
description:
name: vector_graphics
sha256: "32c3c684e02f9bc0afb0ae0aa653337a2fe022e8ab064bcd7ffda27a74e288e3"
url: "https://pub.dev"
source: hosted
version: "1.1.11+1"
vector_graphics_codec:
dependency: transitive
description:
name: vector_graphics_codec
sha256: c86987475f162fadff579e7320c7ddda04cd2fdeffbe1129227a85d9ac9e03da
url: "https://pub.dev"
source: hosted
version: "1.1.11+1"
vector_graphics_compiler:
dependency: transitive
description:
name: vector_graphics_compiler
sha256: "12faff3f73b1741a36ca7e31b292ddeb629af819ca9efe9953b70bd63fc8cd81"
url: "https://pub.dev"
source: hosted
version: "1.1.11+1"
vector_math: vector_math:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -985,10 +1118,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: win32_registry name: win32_registry
sha256: "41fd8a189940d8696b1b810efb9abcf60827b6cbfab90b0c43e8439e3a39d85a" sha256: "10589e0d7f4e053f2c61023a31c9ce01146656a70b7b7f0828c0b46d7da2a9bb"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.2" version: "1.1.3"
window_manager: window_manager:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -1021,6 +1154,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.4" version: "1.0.4"
xml:
dependency: transitive
description:
name: xml
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
url: "https://pub.dev"
source: hosted
version: "6.5.0"
sdks: sdks:
dart: ">=3.3.0 <4.0.0" dart: ">=3.3.0 <4.0.0"
flutter: ">=3.19.2" flutter: ">=3.19.2"

View File

@@ -34,9 +34,9 @@ dependencies:
just_audio: ^0.9.36 just_audio: ^0.9.36
just_audio_windows: ^0.2.0 just_audio_windows: ^0.2.0
audioplayers: ^6.0.0 audioplayers: ^6.0.0
csv: ^6.0.0 fast_csv: ^0.2.11
http: ^1.2.1 http: ^1.2.1
google_fonts: ^6.1.0 google_fonts: ^6.2.1
intl: any intl: any
text_scroll: ^0.2.0 text_scroll: ^0.2.0
flutter_map: ^6.1.0 flutter_map: ^6.1.0
@@ -49,8 +49,9 @@ dependencies:
geolocator: ^11.0.0 geolocator: ^11.0.0
vector_math: ^2.1.4 vector_math: ^2.1.4
permission_handler: ^11.3.0 permission_handler: ^11.3.0
flutter_tts: ^4.0.2
file_picker: ^8.0.0+1 file_picker: ^8.0.0+1
shadcn_ui: ^0.3.3
modular_ui: ^0.0.5
# The following adds the Cupertino Icons font to your application. # The following adds the Cupertino Icons font to your application.
@@ -88,6 +89,7 @@ flutter:
- assets/audio/to_destination.wav - assets/audio/to_destination.wav
- assets/datasets/bus-blinds.csv - assets/datasets/bus-blinds.csv
- assets/audio/5-seconds-of-silence.mp3 - assets/audio/5-seconds-of-silence.mp3
- assets/version.txt
# - images/a_dot_burr.jpeg # - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg # - images/a_dot_ham.jpeg

View File

@@ -7,10 +7,10 @@
#include "generated_plugin_registrant.h" #include "generated_plugin_registrant.h"
#include <audioplayers_windows/audioplayers_windows_plugin.h> #include <audioplayers_windows/audioplayers_windows_plugin.h>
#include <flutter_tts/flutter_tts_plugin.h>
#include <geolocator_windows/geolocator_windows.h> #include <geolocator_windows/geolocator_windows.h>
#include <just_audio_windows/just_audio_windows_plugin.h> #include <just_audio_windows/just_audio_windows_plugin.h>
#include <permission_handler_windows/permission_handler_windows_plugin.h> #include <permission_handler_windows/permission_handler_windows_plugin.h>
#include <rive_common/rive_plugin.h>
#include <screen_retriever/screen_retriever_plugin.h> #include <screen_retriever/screen_retriever_plugin.h>
#include <url_launcher_windows/url_launcher_windows.h> #include <url_launcher_windows/url_launcher_windows.h>
#include <window_manager/window_manager_plugin.h> #include <window_manager/window_manager_plugin.h>
@@ -19,14 +19,14 @@
void RegisterPlugins(flutter::PluginRegistry* registry) { void RegisterPlugins(flutter::PluginRegistry* registry) {
AudioplayersWindowsPluginRegisterWithRegistrar( AudioplayersWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("AudioplayersWindowsPlugin")); registry->GetRegistrarForPlugin("AudioplayersWindowsPlugin"));
FlutterTtsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FlutterTtsPlugin"));
GeolocatorWindowsRegisterWithRegistrar( GeolocatorWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("GeolocatorWindows")); registry->GetRegistrarForPlugin("GeolocatorWindows"));
JustAudioWindowsPluginRegisterWithRegistrar( JustAudioWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("JustAudioWindowsPlugin")); registry->GetRegistrarForPlugin("JustAudioWindowsPlugin"));
PermissionHandlerWindowsPluginRegisterWithRegistrar( PermissionHandlerWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin")); registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
RivePluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("RivePlugin"));
ScreenRetrieverPluginRegisterWithRegistrar( ScreenRetrieverPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("ScreenRetrieverPlugin")); registry->GetRegistrarForPlugin("ScreenRetrieverPlugin"));
UrlLauncherWindowsRegisterWithRegistrar( UrlLauncherWindowsRegisterWithRegistrar(

View File

@@ -4,10 +4,10 @@
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
audioplayers_windows audioplayers_windows
flutter_tts
geolocator_windows geolocator_windows
just_audio_windows just_audio_windows
permission_handler_windows permission_handler_windows
rive_common
screen_retriever screen_retriever
url_launcher_windows url_launcher_windows
window_manager window_manager