This commit is contained in:
ImBenji
2024-05-17 17:38:37 +01:00
6 changed files with 5734 additions and 358 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -39,7 +39,7 @@ class LiveInformation {
// By default, load the bus sequences from the assets
print("Loading bus sequences from assets");
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")
);
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'));
busSequences = BusSequences.fromCSV(
await rootBundle.loadString("assets/datasets/bus-blinds.csv"),
await rootBundle.loadString("assets/datasets/destinations.json"),
response.body
);
@@ -294,7 +294,7 @@ class LiveInformation {
print("Created room with code $roomCode");
}
Future<void> JoinRoom(String roomCode) async {
Future<void> joinRoom(String roomCode) async {
print("Joining room with code $roomCode");
// Disable host mode
@@ -375,6 +375,45 @@ class LiveInformation {
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;
Future<void> ServerListener(appwrite.RealtimeMessage response) async {
print("Session update");

View File

@@ -175,7 +175,7 @@ class AnnouncementModule extends InfoModule {
bool sendToServer = true
}) async {
if (sendToServer) {
if (sendToServer && _shouldSendToServer()) {
scheduledTime ??= liveInformation.syncedTimeModule.Now().add(Duration(seconds: defaultAnnouncementDelay));
@@ -230,7 +230,7 @@ class AnnouncementModule extends InfoModule {
bool sendToServer = true
}) {
if (sendToServer) {
if (sendToServer && _shouldSendToServer()) {
scheduledTime ??= liveInformation.syncedTimeModule.Now().add(Duration(seconds: defaultAnnouncementDelay));
@@ -260,7 +260,7 @@ class AnnouncementModule extends InfoModule {
bool sendToServer = true
}) async {
if (sendToServer) {
if (sendToServer && _shouldSendToServer()) {
scheduledTime ??= liveInformation.syncedTimeModule.Now().add(Duration(seconds: defaultAnnouncementDelay));
@@ -324,6 +324,14 @@ class AnnouncementModule extends InfoModule {
queue.add(announcement);
}
// Server check
bool _shouldSendToServer() {
bool condition = liveInformation.roomCode != null;
print("Should send to server? " + (condition.toString()));
return condition;
}
// Constants
final List<NamedAnnouncementQueueEntry> manualAnnouncements = [

View File

@@ -231,7 +231,7 @@ class RoutePage extends StatelessWidget {
],
),
if (!kIsWeb)
Text(
"Nearby routes",
style: ShadTheme.of(context).textTheme.h4,
@@ -649,11 +649,23 @@ class _dash extends StatelessWidget {
],
),
),
)
),
// SizedBox(
// height: 8,
// ),
SizedBox(
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(
// title: Text("Stop announcements"),
@@ -961,94 +973,35 @@ class _MultiModeEnrouteState extends State<MultiModeEnroute> {
LiveInformation liveInformation = LiveInformation();
return Scaffold(
return PopScope(
canPop: false,
onPopInvoked: (didPop) {
body: Column(
children: [
if (didPop){
print("Compensating for pop");
liveInformation.leaveRoom();
return;
}
Container(
padding: const EdgeInsets.all(16),
height: 200,
child: ShadCard(
title: liveInformation.isHost ? const Text("Hosting group") : const Text("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: () {
// return;
// Ask the user to confirm if they want to leave the group
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")
],
),
),
title: const Text("Leave group?"),
content: const Text("Are you sure you want to leave the group?"),
actions: [
ShadButton(
text: const Text("Close"),
text: const Text("Leave"),
onPressed: () {
liveInformation.leaveRoom();
Navigator.pop(context);
Navigator.pop(context);
},
),
ShadButton(
text: const Text("Cancel"),
onPressed: () {
Navigator.pop(context);
},
@@ -1057,17 +1010,13 @@ class _MultiModeEnrouteState extends State<MultiModeEnroute> {
);
}
);
},
)
],
);
},
),
],
),
),
),
},
child: Scaffold(
body: Column(
children: [
const Divider(
height: 1,
),
@@ -1121,6 +1070,7 @@ class _MultiModeEnrouteState extends State<MultiModeEnroute> {
children: [
if (!kIsWeb)
Container(
padding: const EdgeInsets.only(
top: 4,
@@ -1313,6 +1263,112 @@ class _MultiModeEnrouteState extends State<MultiModeEnroute> {
width: double.infinity,
),
),
const Divider(
height: 1,
),
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,
),
@@ -1320,6 +1376,7 @@ class _MultiModeEnrouteState extends State<MultiModeEnroute> {
],
),
),
);
}
@@ -1377,7 +1434,7 @@ class _MultiModeJoinState extends State<MultiModeJoin> {
liveInformation.setRouteVariant(null);
await liveInformation.JoinRoom(controller.text);
await liveInformation.joinRoom(controller.text);
Navigator.popAndPushNamed(context, "/multi/enroute");
@@ -1773,6 +1830,11 @@ class MultiModeRegister extends StatelessWidget {
}
class NavigationBar extends StatefulWidget {
final Widget? content;
NavigationBar({this.content = null});
@override
State<NavigationBar> createState() => _NavigationBarState();
}
@@ -1825,7 +1887,7 @@ List<Widget> _getNearbyRoutes({bool multiMode = false}) {
if (kDebugMode) {
currentVector = OSGrid.toNorthingEasting(51.583781262560926, -0.020359583104595073);
// currentVector = OSGrid.toNorthingEasting(51.583781262560926, -0.020359583104595073);
}
for (BusRoute route in busSequences.routes.values) {

View File

@@ -1,5 +1,6 @@
import 'dart:convert';
import 'dart:typed_data';
import 'package:bus_infotainment/audio_cache.dart';
@@ -16,28 +17,24 @@ class BusSequences extends InfoModule {
Map<String, BusDestination> destinations = {};
BusSequences.fromCSV(String destinationsCSV, String busSequencesCSV) {
BusSequences.fromCSV(String destinationsJson, String busSequencesCSV) {
// Init the bus destinations
List<List<String>> destinationRows = CsvConverter().convert(destinationsCSV);
destinationRows.removeAt(0);
Map<String, dynamic> destinationData = jsonDecode(destinationsJson);
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 {
Map<String, dynamic> destinationDetails = destinationData[destinationName];
List<dynamic> entries = destinationRows[i];
// print("Parsing destination row $i: $entries");
String blind = destinationName;
String routeNumber = entries[0].toString();
BusRoute route = routes.containsKey(routeNumber) ? routes[routeNumber]! : BusRoute(routeNumber: routeNumber);
String blind = entries[1].toString();
double lat = double.parse(entries[2].toString());
double long = double.parse(entries[3].toString());
List<String> location = destinationDetails['Location'].split(', ');
double lat = double.parse(location[0]);
double long = double.parse(location[1]);
Vector2 grid = OSGrid.toNorthingEasting(lat, long);
@@ -46,11 +43,10 @@ class BusSequences extends InfoModule {
destination.easting = grid.x;
destination.northing = grid.y;
route.destinations.add(destination);
routes[routeNumber] = route;
destinations[blind] = destination;
} catch (e) {}
} catch (e) {
print("Error parsing destination: $e");
}
}
print("Loaded ${destinations.length} destinations");

View File

@@ -97,6 +97,7 @@ flutter:
- assets/datasets/tube_stations.json
- assets/audio/rail_replacement/
- assets/audio/R_SPECIAL_SERVICE_001.mp3
- assets/datasets/destinations.json
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg