laptop
This commit is contained in:
5270
assets/datasets/destinations.json
Normal file
5270
assets/datasets/destinations.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -39,7 +39,7 @@ class LiveInformation {
|
|||||||
// By default, load the bus sequences from the assets
|
// By default, load the bus sequences from the assets
|
||||||
print("Loading bus sequences from assets");
|
print("Loading bus sequences from assets");
|
||||||
busSequences = BusSequences.fromCSV(
|
busSequences = BusSequences.fromCSV(
|
||||||
await rootBundle.loadString("assets/datasets/bus-blinds.csv"),
|
await rootBundle.loadString("assets/datasets/destinations.json"),
|
||||||
await rootBundle.loadString("assets/datasets/bus-sequences.csv")
|
await rootBundle.loadString("assets/datasets/bus-sequences.csv")
|
||||||
);
|
);
|
||||||
print("Loaded bus sequences from assets");
|
print("Loaded bus sequences from assets");
|
||||||
@@ -49,7 +49,7 @@ class LiveInformation {
|
|||||||
http.Response response = await http.get(Uri.parse('https://tfl.gov.uk/bus-sequences.csv'));
|
http.Response response = await http.get(Uri.parse('https://tfl.gov.uk/bus-sequences.csv'));
|
||||||
|
|
||||||
busSequences = BusSequences.fromCSV(
|
busSequences = BusSequences.fromCSV(
|
||||||
await rootBundle.loadString("assets/datasets/bus-blinds.csv"),
|
await rootBundle.loadString("assets/datasets/destinations.json"),
|
||||||
response.body
|
response.body
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -294,7 +294,7 @@ class LiveInformation {
|
|||||||
print("Created room with code $roomCode");
|
print("Created room with code $roomCode");
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> JoinRoom(String roomCode) async {
|
Future<void> joinRoom(String roomCode) async {
|
||||||
print("Joining room with code $roomCode");
|
print("Joining room with code $roomCode");
|
||||||
|
|
||||||
// Disable host mode
|
// Disable host mode
|
||||||
@@ -375,6 +375,45 @@ class LiveInformation {
|
|||||||
print("Joined room with code $roomCode");
|
print("Joined room with code $roomCode");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> leaveRoom() async {
|
||||||
|
|
||||||
|
if (roomCode == null) {
|
||||||
|
throw Exception("Not in a room");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isHost) {
|
||||||
|
// Access the database
|
||||||
|
final client = auth.client;
|
||||||
|
final databases = appwrite.Databases(client);
|
||||||
|
|
||||||
|
// Remove any existing documents
|
||||||
|
final existingDocuments = await databases.listDocuments(
|
||||||
|
databaseId: "6633e85400036415ab0f",
|
||||||
|
collectionId: "6633e85d0020f52f3771",
|
||||||
|
queries: [
|
||||||
|
appwrite.Query.search("SessionID", roomCode!)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
for (var document in existingDocuments.documents) {
|
||||||
|
await databases.deleteDocument(
|
||||||
|
databaseId: "6633e85400036415ab0f",
|
||||||
|
collectionId: "6633e85d0020f52f3771",
|
||||||
|
documentId: document.$id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
roomCode = null;
|
||||||
|
roomDocumentID = null;
|
||||||
|
isHost = false;
|
||||||
|
|
||||||
|
_keepAliveConnection?.close();
|
||||||
|
_keepAliveConnection = null;
|
||||||
|
|
||||||
|
// Reset stuff
|
||||||
|
setRouteVariant(null);
|
||||||
|
}
|
||||||
|
|
||||||
String? lastCommand;
|
String? lastCommand;
|
||||||
Future<void> ServerListener(appwrite.RealtimeMessage response) async {
|
Future<void> ServerListener(appwrite.RealtimeMessage response) async {
|
||||||
print("Session update");
|
print("Session update");
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ class AnnouncementModule extends InfoModule {
|
|||||||
bool sendToServer = true
|
bool sendToServer = true
|
||||||
}) async {
|
}) async {
|
||||||
|
|
||||||
if (sendToServer) {
|
if (sendToServer && _shouldSendToServer()) {
|
||||||
|
|
||||||
scheduledTime ??= liveInformation.syncedTimeModule.Now().add(Duration(seconds: defaultAnnouncementDelay));
|
scheduledTime ??= liveInformation.syncedTimeModule.Now().add(Duration(seconds: defaultAnnouncementDelay));
|
||||||
|
|
||||||
@@ -230,7 +230,7 @@ class AnnouncementModule extends InfoModule {
|
|||||||
bool sendToServer = true
|
bool sendToServer = true
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
if (sendToServer) {
|
if (sendToServer && _shouldSendToServer()) {
|
||||||
|
|
||||||
scheduledTime ??= liveInformation.syncedTimeModule.Now().add(Duration(seconds: defaultAnnouncementDelay));
|
scheduledTime ??= liveInformation.syncedTimeModule.Now().add(Duration(seconds: defaultAnnouncementDelay));
|
||||||
|
|
||||||
@@ -260,7 +260,7 @@ class AnnouncementModule extends InfoModule {
|
|||||||
bool sendToServer = true
|
bool sendToServer = true
|
||||||
}) async {
|
}) async {
|
||||||
|
|
||||||
if (sendToServer) {
|
if (sendToServer && _shouldSendToServer()) {
|
||||||
|
|
||||||
scheduledTime ??= liveInformation.syncedTimeModule.Now().add(Duration(seconds: defaultAnnouncementDelay));
|
scheduledTime ??= liveInformation.syncedTimeModule.Now().add(Duration(seconds: defaultAnnouncementDelay));
|
||||||
|
|
||||||
@@ -324,6 +324,14 @@ class AnnouncementModule extends InfoModule {
|
|||||||
queue.add(announcement);
|
queue.add(announcement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Server check
|
||||||
|
bool _shouldSendToServer() {
|
||||||
|
bool condition = liveInformation.roomCode != null;
|
||||||
|
|
||||||
|
print("Should send to server? " + (condition.toString()));
|
||||||
|
return condition;
|
||||||
|
}
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
|
|
||||||
final List<NamedAnnouncementQueueEntry> manualAnnouncements = [
|
final List<NamedAnnouncementQueueEntry> manualAnnouncements = [
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ class RoutePage extends StatelessWidget {
|
|||||||
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
if (!kIsWeb)
|
||||||
Text(
|
Text(
|
||||||
"Nearby routes",
|
"Nearby routes",
|
||||||
style: ShadTheme.of(context).textTheme.h4,
|
style: ShadTheme.of(context).textTheme.h4,
|
||||||
@@ -649,11 +649,23 @@ class _dash extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
|
|
||||||
// SizedBox(
|
SizedBox(
|
||||||
// height: 8,
|
height: 8,
|
||||||
// ),
|
),
|
||||||
|
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
child: ShadButton(
|
||||||
|
text: const Text("Fullscreen display"),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pushNamed(context, "/display");
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.fullscreen),
|
||||||
|
width: double.infinity,
|
||||||
|
),
|
||||||
|
),
|
||||||
//
|
//
|
||||||
// ShadCard(
|
// ShadCard(
|
||||||
// title: Text("Stop announcements"),
|
// title: Text("Stop announcements"),
|
||||||
@@ -961,199 +973,83 @@ class _MultiModeEnrouteState extends State<MultiModeEnroute> {
|
|||||||
LiveInformation liveInformation = LiveInformation();
|
LiveInformation liveInformation = LiveInformation();
|
||||||
|
|
||||||
|
|
||||||
return Scaffold(
|
return PopScope(
|
||||||
|
canPop: false,
|
||||||
|
onPopInvoked: (didPop) {
|
||||||
|
|
||||||
body: Column(
|
if (didPop){
|
||||||
children: [
|
print("Compensating for pop");
|
||||||
|
liveInformation.leaveRoom();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Container(
|
// return;
|
||||||
padding: const EdgeInsets.all(16),
|
// Ask the user to confirm if they want to leave the group
|
||||||
|
showShadDialog(
|
||||||
height: 200,
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
child: ShadCard(
|
return ShadDialog(
|
||||||
title: liveInformation.isHost ? const Text("Hosting group") : const Text("Joined group"),
|
title: const Text("Leave group?"),
|
||||||
border: Border.all(
|
content: const Text("Are you sure you want to leave the group?"),
|
||||||
color: Colors.amber,
|
actions: [
|
||||||
width: 1
|
ShadButton(
|
||||||
),
|
text: const Text("Leave"),
|
||||||
padding: const EdgeInsets.all(16),
|
onPressed: () {
|
||||||
width: double.infinity,
|
liveInformation.leaveRoom();
|
||||||
description: liveInformation.isHost ? const Text(
|
Navigator.pop(context);
|
||||||
"You are hosting a group. \nShare the room code with others to join"
|
Navigator.pop(context);
|
||||||
) : const Text(
|
|
||||||
"You have joined a group."
|
|
||||||
),
|
|
||||||
content: Column(
|
|
||||||
children: [
|
|
||||||
const SizedBox(
|
|
||||||
height: 4,
|
|
||||||
),
|
|
||||||
|
|
||||||
FutureBuilder(
|
|
||||||
future: Future.delayed(const Duration(seconds: 1)),
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
return Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: ShadButton(
|
|
||||||
text: Text(
|
|
||||||
liveInformation.roomCode!,
|
|
||||||
),
|
|
||||||
|
|
||||||
icon: const Icon(Icons.copy),
|
|
||||||
padding: const EdgeInsets.all(8),
|
|
||||||
onPressed: () {
|
|
||||||
Clipboard.setData(ClipboardData(text: liveInformation.roomCode!));
|
|
||||||
ShadToaster.of(context).show(
|
|
||||||
const ShadToast(
|
|
||||||
title: Text("Copied to clipboard"),
|
|
||||||
description: Text("Room code copied to clipboard"),
|
|
||||||
duration: Duration(seconds: 5),
|
|
||||||
)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
ShadButton(
|
|
||||||
icon: const Icon(Icons.qr_code),
|
|
||||||
onPressed: () {
|
|
||||||
showShadDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) {
|
|
||||||
return ShadDialog(
|
|
||||||
title: const Text("QR Code"),
|
|
||||||
content: Container(
|
|
||||||
|
|
||||||
width: 200,
|
|
||||||
height: 225,
|
|
||||||
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
QrImageView(
|
|
||||||
data: liveInformation.roomCode!,
|
|
||||||
size: 200,
|
|
||||||
backgroundColor: Colors.white,
|
|
||||||
),
|
|
||||||
|
|
||||||
const SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
|
||||||
|
|
||||||
Text("Scan QR code to join the group")
|
|
||||||
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
actions: [
|
|
||||||
ShadButton(
|
|
||||||
text: const Text("Close"),
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.pop(context);
|
|
||||||
},
|
|
||||||
)
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
)
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
ShadButton(
|
||||||
|
text: const Text("Cancel"),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
)
|
||||||
],
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
child: Scaffold(
|
||||||
|
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
const Divider(
|
||||||
|
height: 1,
|
||||||
|
),
|
||||||
|
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.all(8),
|
||||||
|
child: ibus_display()
|
||||||
|
),
|
||||||
|
|
||||||
|
const Divider(
|
||||||
|
height: 1,
|
||||||
|
),
|
||||||
|
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.all(8),
|
||||||
|
child: Text(
|
||||||
|
"* Swipe left and right below for more options!",
|
||||||
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
|
|
||||||
const Divider(
|
const Divider(
|
||||||
height: 1,
|
height: 1,
|
||||||
),
|
|
||||||
|
|
||||||
Container(
|
|
||||||
padding: EdgeInsets.all(8),
|
|
||||||
child: ibus_display()
|
|
||||||
),
|
|
||||||
|
|
||||||
const Divider(
|
|
||||||
height: 1,
|
|
||||||
),
|
|
||||||
|
|
||||||
Container(
|
|
||||||
padding: EdgeInsets.all(8),
|
|
||||||
child: Text(
|
|
||||||
"* Swipe left and right below for more options!",
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
),
|
||||||
),
|
|
||||||
|
|
||||||
const Divider(
|
SizedBox(
|
||||||
height: 1,
|
height: 16,
|
||||||
),
|
),
|
||||||
|
|
||||||
SizedBox(
|
Expanded(
|
||||||
height: 16,
|
child: FlutterCarousel(
|
||||||
),
|
items: [
|
||||||
|
Container(
|
||||||
Expanded(
|
|
||||||
child: FlutterCarousel(
|
|
||||||
items: [
|
|
||||||
Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
border: Border.all(
|
|
||||||
color: Colors.white,
|
|
||||||
width: 1
|
|
||||||
),
|
|
||||||
borderRadius: BorderRadius.circular(8)
|
|
||||||
),
|
|
||||||
padding: const EdgeInsets.all(4),
|
|
||||||
margin: const EdgeInsets.only(
|
|
||||||
left: 16,
|
|
||||||
right: 16,
|
|
||||||
),
|
|
||||||
width: double.infinity,
|
|
||||||
|
|
||||||
child: Column(
|
|
||||||
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
|
|
||||||
children: [
|
|
||||||
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
top: 4,
|
|
||||||
left: 8,
|
|
||||||
right: 8,
|
|
||||||
bottom: 4
|
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
"Nearby routes",
|
|
||||||
style: ShadTheme.of(context).textTheme.h4,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (!kIsWeb)
|
|
||||||
Expanded(
|
|
||||||
child: Scrollbar(
|
|
||||||
interactive: true,
|
|
||||||
radius: const Radius.circular(8),
|
|
||||||
thickness: 8,
|
|
||||||
thumbVisibility: true,
|
|
||||||
child: GridView.count(
|
|
||||||
crossAxisCount: 3,
|
|
||||||
children: [
|
|
||||||
..._getNearbyRoutes(multiMode: true)
|
|
||||||
],
|
|
||||||
shrinkWrap: true,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
],
|
|
||||||
)
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
@@ -1166,160 +1062,321 @@ class _MultiModeEnrouteState extends State<MultiModeEnroute> {
|
|||||||
left: 16,
|
left: 16,
|
||||||
right: 16,
|
right: 16,
|
||||||
),
|
),
|
||||||
|
width: double.infinity,
|
||||||
|
|
||||||
child: Expanded(child: RouteSearch(multiMode: true,))
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
border: Border.all(
|
|
||||||
width: 1,
|
|
||||||
color: Colors.white
|
|
||||||
),
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(8))
|
|
||||||
),
|
|
||||||
|
|
||||||
margin: const EdgeInsets.only(
|
|
||||||
left: 16,
|
|
||||||
right: 16,
|
|
||||||
),
|
|
||||||
|
|
||||||
padding: EdgeInsets.all(8),
|
|
||||||
|
|
||||||
child: SingleChildScrollView(
|
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
|
||||||
EasyAnnouncementPicker(
|
|
||||||
announcements: LiveInformation().announcementModule.manualAnnouncements,
|
|
||||||
title: "Manual",
|
|
||||||
outlineColor: ShadTheme.of(context).colorScheme.secondary
|
|
||||||
),
|
|
||||||
|
|
||||||
if (liveInformation.getRouteVariant() != null)
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
SizedBox(
|
|
||||||
height: 16,
|
children: [
|
||||||
|
|
||||||
|
if (!kIsWeb)
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
top: 4,
|
||||||
|
left: 8,
|
||||||
|
right: 8,
|
||||||
|
bottom: 4
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
"Nearby routes",
|
||||||
|
style: ShadTheme.of(context).textTheme.h4,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (!kIsWeb)
|
||||||
|
Expanded(
|
||||||
|
child: Scrollbar(
|
||||||
|
interactive: true,
|
||||||
|
radius: const Radius.circular(8),
|
||||||
|
thickness: 8,
|
||||||
|
thumbVisibility: true,
|
||||||
|
child: GridView.count(
|
||||||
|
crossAxisCount: 3,
|
||||||
|
children: [
|
||||||
|
..._getNearbyRoutes(multiMode: true)
|
||||||
|
],
|
||||||
|
shrinkWrap: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
],
|
||||||
|
)
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(
|
||||||
|
color: Colors.white,
|
||||||
|
width: 1
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.circular(8)
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.all(4),
|
||||||
|
margin: const EdgeInsets.only(
|
||||||
|
left: 16,
|
||||||
|
right: 16,
|
||||||
|
),
|
||||||
|
|
||||||
|
child: Expanded(child: RouteSearch(multiMode: true,))
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(
|
||||||
|
width: 1,
|
||||||
|
color: Colors.white
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(8))
|
||||||
|
),
|
||||||
|
|
||||||
|
margin: const EdgeInsets.only(
|
||||||
|
left: 16,
|
||||||
|
right: 16,
|
||||||
|
),
|
||||||
|
|
||||||
|
padding: EdgeInsets.all(8),
|
||||||
|
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
EasyAnnouncementPicker(
|
||||||
|
announcements: LiveInformation().announcementModule.manualAnnouncements,
|
||||||
|
title: "Manual",
|
||||||
|
outlineColor: ShadTheme.of(context).colorScheme.secondary
|
||||||
),
|
),
|
||||||
|
|
||||||
if (liveInformation.getRouteVariant() != null)
|
if (liveInformation.getRouteVariant() != null)
|
||||||
Container(
|
SizedBox(
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
|
|
||||||
child: StopAnnouncementPicker(
|
if (liveInformation.getRouteVariant() != null)
|
||||||
routeVariant: LiveInformation().getRouteVariant()!,
|
Container(
|
||||||
backgroundColor: Colors.transparent,
|
|
||||||
outlineColor: ShadTheme.of(context).colorScheme.secondary,
|
child: StopAnnouncementPicker(
|
||||||
label: "Bus Stops",
|
routeVariant: LiveInformation().getRouteVariant()!,
|
||||||
)
|
backgroundColor: Colors.transparent,
|
||||||
)
|
outlineColor: ShadTheme.of(context).colorScheme.secondary,
|
||||||
],
|
label: "Bus Stops",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
Container(
|
||||||
Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.transparent,
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
border: Border.all(
|
|
||||||
color: ShadTheme.of(context).colorScheme.primary,
|
|
||||||
width: 1
|
|
||||||
)
|
|
||||||
),
|
|
||||||
margin: const EdgeInsets.only(
|
|
||||||
left: 16,
|
|
||||||
right: 16,
|
|
||||||
),
|
|
||||||
padding: const EdgeInsets.all(4),
|
|
||||||
child: Container(
|
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
borderRadius: BorderRadius.circular(4),
|
borderRadius: BorderRadius.circular(8),
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: ShadTheme.of(context).colorScheme.primary,
|
color: ShadTheme.of(context).colorScheme.primary,
|
||||||
width: 1
|
width: 1
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
child: Column(
|
margin: const EdgeInsets.only(
|
||||||
children: [
|
left: 16,
|
||||||
|
right: 16,
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.all(4),
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.transparent,
|
||||||
|
borderRadius: BorderRadius.circular(4),
|
||||||
|
border: Border.all(
|
||||||
|
color: ShadTheme.of(context).colorScheme.primary,
|
||||||
|
width: 1
|
||||||
|
)
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
|
||||||
|
if (!kIsWeb)
|
||||||
|
AnnouncementEntry(
|
||||||
|
label: "Display next stop",
|
||||||
|
index: 0,
|
||||||
|
outlineColor: ShadTheme.of(context).colorScheme.primary,
|
||||||
|
onPressed: () {
|
||||||
|
LiveInformation liveInformation = LiveInformation();
|
||||||
|
TrackerModule trackerModule = liveInformation.trackerModule;
|
||||||
|
|
||||||
|
BusRouteStop? stop = trackerModule.nearestStop;
|
||||||
|
|
||||||
|
if (stop != null) {
|
||||||
|
liveInformation.announcementModule.queueAnnounceByAudioName(displayText: stop.formattedStopName);
|
||||||
|
} else {
|
||||||
|
ShadToaster.of(context).show(
|
||||||
|
const ShadToast(
|
||||||
|
title: Text("No bus stop found"),
|
||||||
|
description: Text("No bus stop found nearby"),
|
||||||
|
duration: Duration(seconds: 5),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
if (!kIsWeb)
|
||||||
|
Container(
|
||||||
|
height: 1,
|
||||||
|
color: ShadTheme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
|
|
||||||
if (!kIsWeb)
|
|
||||||
AnnouncementEntry(
|
AnnouncementEntry(
|
||||||
label: "Display next stop",
|
label: "Announce destination",
|
||||||
index: 0,
|
index: 1,
|
||||||
outlineColor: ShadTheme.of(context).colorScheme.primary,
|
outlineColor: ShadTheme.of(context).colorScheme.primary,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
LiveInformation liveInformation = LiveInformation();
|
LiveInformation liveInformation = LiveInformation();
|
||||||
TrackerModule trackerModule = liveInformation.trackerModule;
|
liveInformation.announcementModule.queueAnnouncementByRouteVariant(
|
||||||
|
routeVariant:
|
||||||
BusRouteStop? stop = trackerModule.nearestStop;
|
liveInformation.getRouteVariant()!
|
||||||
|
);
|
||||||
if (stop != null) {
|
|
||||||
liveInformation.announcementModule.queueAnnounceByAudioName(displayText: stop.formattedStopName);
|
|
||||||
} else {
|
|
||||||
ShadToaster.of(context).show(
|
|
||||||
const ShadToast(
|
|
||||||
title: Text("No bus stop found"),
|
|
||||||
description: Text("No bus stop found nearby"),
|
|
||||||
duration: Duration(seconds: 5),
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
if (!kIsWeb)
|
Container(
|
||||||
Container(
|
height: 1,
|
||||||
height: 1,
|
color: ShadTheme.of(context).colorScheme.primary,
|
||||||
color: ShadTheme.of(context).colorScheme.primary,
|
),
|
||||||
),
|
],
|
||||||
|
),
|
||||||
AnnouncementEntry(
|
|
||||||
label: "Announce destination",
|
|
||||||
index: 1,
|
|
||||||
outlineColor: ShadTheme.of(context).colorScheme.primary,
|
|
||||||
onPressed: () {
|
|
||||||
LiveInformation liveInformation = LiveInformation();
|
|
||||||
liveInformation.announcementModule.queueAnnouncementByRouteVariant(
|
|
||||||
routeVariant:
|
|
||||||
liveInformation.getRouteVariant()!
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
|
|
||||||
Container(
|
|
||||||
height: 1,
|
|
||||||
color: ShadTheme.of(context).colorScheme.primary,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
options: CarouselOptions(
|
||||||
|
showIndicator: false,
|
||||||
|
viewportFraction: 1,
|
||||||
|
height: double.infinity,
|
||||||
|
enableInfiniteScroll: true
|
||||||
),
|
),
|
||||||
],
|
|
||||||
options: CarouselOptions(
|
|
||||||
showIndicator: false,
|
|
||||||
viewportFraction: 1,
|
|
||||||
height: double.infinity,
|
|
||||||
enableInfiniteScroll: true
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
|
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.all(8),
|
padding: const EdgeInsets.all(8),
|
||||||
child: ShadButton(
|
child: ShadButton(
|
||||||
text: const Text("Fullscreen display"),
|
text: const Text("Fullscreen display"),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pushNamed(context, "/display");
|
Navigator.pushNamed(context, "/display");
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.fullscreen),
|
icon: const Icon(Icons.fullscreen),
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(
|
||||||
|
height: 1,
|
||||||
),
|
),
|
||||||
),
|
|
||||||
const Divider(
|
|
||||||
height: 1,
|
|
||||||
),
|
|
||||||
NavigationBar()
|
|
||||||
],
|
|
||||||
),
|
|
||||||
|
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
|
||||||
|
// height: 200,
|
||||||
|
|
||||||
|
child: ShadCard(
|
||||||
|
title: liveInformation.isHost ? const Text("Currently hosting group") : const Text("Successfully joined group"),
|
||||||
|
border: Border.all(
|
||||||
|
color: Colors.amber,
|
||||||
|
width: 1
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
width: double.infinity,
|
||||||
|
description: liveInformation.isHost ? const Text(
|
||||||
|
"You are hosting a group. \nShare the room code with others to join"
|
||||||
|
) : const Text(
|
||||||
|
"You have joined a group."
|
||||||
|
),
|
||||||
|
content: Column(
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
height: 4,
|
||||||
|
),
|
||||||
|
|
||||||
|
FutureBuilder(
|
||||||
|
future: Future.delayed(const Duration(seconds: 1)),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
return Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: ShadButton(
|
||||||
|
text: Text(
|
||||||
|
liveInformation.roomCode!,
|
||||||
|
),
|
||||||
|
|
||||||
|
icon: const Icon(Icons.copy),
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
onPressed: () {
|
||||||
|
Clipboard.setData(ClipboardData(text: liveInformation.roomCode!));
|
||||||
|
ShadToaster.of(context).show(
|
||||||
|
const ShadToast(
|
||||||
|
title: Text("Copied to clipboard"),
|
||||||
|
description: Text("Room code copied to clipboard"),
|
||||||
|
duration: Duration(seconds: 5),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ShadButton(
|
||||||
|
icon: const Icon(Icons.qr_code),
|
||||||
|
onPressed: () {
|
||||||
|
showShadDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return ShadDialog(
|
||||||
|
title: const Text("QR Code"),
|
||||||
|
content: Container(
|
||||||
|
|
||||||
|
width: 200,
|
||||||
|
height: 225,
|
||||||
|
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
QrImageView(
|
||||||
|
data: liveInformation.roomCode!,
|
||||||
|
size: 200,
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
),
|
||||||
|
|
||||||
|
const SizedBox(
|
||||||
|
height: 8,
|
||||||
|
),
|
||||||
|
|
||||||
|
Text("Scan QR code to join the group")
|
||||||
|
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
ShadButton(
|
||||||
|
text: const Text("Close"),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
const Divider(
|
||||||
|
height: 1,
|
||||||
|
),
|
||||||
|
NavigationBar()
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1377,7 +1434,7 @@ class _MultiModeJoinState extends State<MultiModeJoin> {
|
|||||||
|
|
||||||
liveInformation.setRouteVariant(null);
|
liveInformation.setRouteVariant(null);
|
||||||
|
|
||||||
await liveInformation.JoinRoom(controller.text);
|
await liveInformation.joinRoom(controller.text);
|
||||||
|
|
||||||
Navigator.popAndPushNamed(context, "/multi/enroute");
|
Navigator.popAndPushNamed(context, "/multi/enroute");
|
||||||
|
|
||||||
@@ -1755,6 +1812,11 @@ class MultiModeRegister extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class NavigationBar extends StatefulWidget {
|
class NavigationBar extends StatefulWidget {
|
||||||
|
|
||||||
|
final Widget? content;
|
||||||
|
|
||||||
|
NavigationBar({this.content = null});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<NavigationBar> createState() => _NavigationBarState();
|
State<NavigationBar> createState() => _NavigationBarState();
|
||||||
}
|
}
|
||||||
@@ -1807,7 +1869,7 @@ List<Widget> _getNearbyRoutes({bool multiMode = false}) {
|
|||||||
|
|
||||||
|
|
||||||
if (kDebugMode) {
|
if (kDebugMode) {
|
||||||
currentVector = OSGrid.toNorthingEasting(51.583781262560926, -0.020359583104595073);
|
// currentVector = OSGrid.toNorthingEasting(51.583781262560926, -0.020359583104595073);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (BusRoute route in busSequences.routes.values) {
|
for (BusRoute route in busSequences.routes.values) {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
import 'dart:convert';
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:bus_infotainment/audio_cache.dart';
|
import 'package:bus_infotainment/audio_cache.dart';
|
||||||
@@ -16,28 +17,24 @@ class BusSequences extends InfoModule {
|
|||||||
|
|
||||||
Map<String, BusDestination> destinations = {};
|
Map<String, BusDestination> destinations = {};
|
||||||
|
|
||||||
BusSequences.fromCSV(String destinationsCSV, String busSequencesCSV) {
|
BusSequences.fromCSV(String destinationsJson, String busSequencesCSV) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Init the bus destinations
|
// Init the bus destinations
|
||||||
List<List<String>> destinationRows = CsvConverter().convert(destinationsCSV);
|
Map<String, dynamic> destinationData = jsonDecode(destinationsJson);
|
||||||
destinationRows.removeAt(0);
|
|
||||||
|
|
||||||
print("Destination rows: ${destinationRows.length}");
|
print("Destination rows: ${destinationData.length}");
|
||||||
|
|
||||||
for (int i = 0; i < destinationRows.length; i++) {
|
for (String destinationName in destinationData.keys) {
|
||||||
try {
|
try {
|
||||||
|
Map<String, dynamic> destinationDetails = destinationData[destinationName];
|
||||||
|
|
||||||
List<dynamic> entries = destinationRows[i];
|
String blind = destinationName;
|
||||||
// print("Parsing destination row $i: $entries");
|
|
||||||
|
|
||||||
String routeNumber = entries[0].toString();
|
List<String> location = destinationDetails['Location'].split(', ');
|
||||||
|
double lat = double.parse(location[0]);
|
||||||
BusRoute route = routes.containsKey(routeNumber) ? routes[routeNumber]! : BusRoute(routeNumber: routeNumber);
|
double long = double.parse(location[1]);
|
||||||
|
|
||||||
String blind = entries[1].toString();
|
|
||||||
|
|
||||||
double lat = double.parse(entries[2].toString());
|
|
||||||
double long = double.parse(entries[3].toString());
|
|
||||||
|
|
||||||
Vector2 grid = OSGrid.toNorthingEasting(lat, long);
|
Vector2 grid = OSGrid.toNorthingEasting(lat, long);
|
||||||
|
|
||||||
@@ -46,11 +43,10 @@ class BusSequences extends InfoModule {
|
|||||||
destination.easting = grid.x;
|
destination.easting = grid.x;
|
||||||
destination.northing = grid.y;
|
destination.northing = grid.y;
|
||||||
|
|
||||||
route.destinations.add(destination);
|
|
||||||
|
|
||||||
routes[routeNumber] = route;
|
|
||||||
destinations[blind] = destination;
|
destinations[blind] = destination;
|
||||||
} catch (e) {}
|
} catch (e) {
|
||||||
|
print("Error parsing destination: $e");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
print("Loaded ${destinations.length} destinations");
|
print("Loaded ${destinations.length} destinations");
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ flutter:
|
|||||||
- assets/datasets/tube_stations.json
|
- assets/datasets/tube_stations.json
|
||||||
- assets/audio/rail_replacement/
|
- assets/audio/rail_replacement/
|
||||||
- assets/audio/R_SPECIAL_SERVICE_001.mp3
|
- assets/audio/R_SPECIAL_SERVICE_001.mp3
|
||||||
|
- assets/datasets/destinations.json
|
||||||
|
|
||||||
# - images/a_dot_burr.jpeg
|
# - images/a_dot_burr.jpeg
|
||||||
# - images/a_dot_ham.jpeg
|
# - images/a_dot_ham.jpeg
|
||||||
|
|||||||
Reference in New Issue
Block a user