Alot of changes
This commit is contained in:
61
Dockerfile
61
Dockerfile
@@ -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;"]
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
1
assets/version.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
0.16.0
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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(),
|
||||||
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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"),
|
//
|
||||||
// ),
|
// ],
|
||||||
//
|
//
|
||||||
// ],
|
// ),
|
||||||
//
|
//
|
||||||
// ),
|
// ),
|
||||||
//
|
|
||||||
// ),
|
],
|
||||||
|
),
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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: [
|
||||||
|
|||||||
465
lib/remaster/InitialStartup.dart
Normal file
465
lib/remaster/InitialStartup.dart
Normal 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,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
],
|
||||||
|
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
26
lib/remaster/RemasteredMain.dart
Normal file
26
lib/remaster/RemasteredMain.dart
Normal 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
365
lib/remaster/dashboard.dart
Normal 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,
|
||||||
|
//
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// )
|
||||||
|
//
|
||||||
|
// ],
|
||||||
|
//
|
||||||
|
// )
|
||||||
|
|
||||||
|
],
|
||||||
|
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
],
|
||||||
|
|
||||||
|
),
|
||||||
|
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
],
|
||||||
|
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
15
lib/utils/web_workarrounds.dart
Normal file
15
lib/utils/web_workarrounds.dart
Normal 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;
|
||||||
|
}
|
||||||
@@ -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"))
|
||||||
|
|||||||
197
pubspec.lock
197
pubspec.lock
@@ -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"
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user