484 lines
21 KiB
Dart
484 lines
21 KiB
Dart
|
|
import 'package:bus_infotainment/backend/live_information.dart';
|
|
import 'package:bus_infotainment/pages/components/ibus_display.dart';
|
|
import 'package:bus_infotainment/remaster/dashboard.dart';
|
|
import 'package:bus_infotainment/tfl_datasets.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:flutter_scroll_shadow/flutter_scroll_shadow.dart';
|
|
import 'package:shadcn_ui/shadcn_ui.dart';
|
|
|
|
class ArcDashboard extends StatefulWidget {
|
|
|
|
@override
|
|
State<ArcDashboard> createState() => _ArcDashboardState();
|
|
}
|
|
|
|
class _ArcDashboardState extends State<ArcDashboard> {
|
|
_closeDialogueChecker closeDialogWidget = _closeDialogueChecker();
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
|
|
// Force landscape mode
|
|
Future.delayed(Duration(seconds: 1), () {
|
|
SystemChrome.setPreferredOrientations([
|
|
DeviceOrientation.landscapeRight,
|
|
DeviceOrientation.landscapeLeft,
|
|
]);
|
|
});
|
|
|
|
return Scaffold(
|
|
|
|
body: Container(
|
|
child: Row(
|
|
|
|
children: [
|
|
|
|
const SizedBox(
|
|
width: 10,
|
|
),
|
|
|
|
Container(
|
|
padding: const EdgeInsets.symmetric(
|
|
vertical: 10,
|
|
),
|
|
|
|
child: IntrinsicWidth(
|
|
child: Column(
|
|
children: [
|
|
|
|
if (LiveInformation().roomDocumentID != null)
|
|
Tooltip(
|
|
child: ShadButton(
|
|
icon: const Icon(Icons.network_check),
|
|
width: double.infinity,
|
|
onPressed: () {
|
|
showShadSheet(
|
|
context: context,
|
|
builder: (context) {
|
|
return ShadSheet(
|
|
padding: const EdgeInsets.all(10),
|
|
content: Column(
|
|
children: [
|
|
Text("Room ID: ${LiveInformation().roomDocumentID}"),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
);
|
|
},
|
|
),
|
|
message: "Room information",
|
|
),
|
|
|
|
SizedBox(
|
|
height: 220,
|
|
child: RotatedBox(
|
|
quarterTurns: 3,
|
|
child: Column(
|
|
children: [
|
|
ShadButton(
|
|
text: const Text("Manual Announcements"),
|
|
width: double.infinity,
|
|
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
|
onPressed: () {
|
|
|
|
List<Widget> announcements = [];
|
|
|
|
for (var announcement in LiveInformation().announcementModule.manualAnnouncements) {
|
|
|
|
announcements.add(
|
|
ShadButton(
|
|
text: SizedBox(
|
|
width: 200-42,
|
|
child: Text(announcement.shortName),
|
|
),
|
|
onPressed: () {
|
|
|
|
if (closeDialogWidget.closeDialog) {
|
|
Navigator.pop(context);
|
|
}
|
|
|
|
LiveInformation().announcementModule.queueAnnouncementByInfoIndex(
|
|
infoIndex: LiveInformation().announcementModule.manualAnnouncements.indexOf(announcement),
|
|
);
|
|
},
|
|
)
|
|
);
|
|
|
|
}
|
|
|
|
print(announcements.length);
|
|
|
|
showShadSheet(
|
|
context: context,
|
|
side: ShadSheetSide.left,
|
|
|
|
builder: (context) {
|
|
return ShadSheet(
|
|
padding: const EdgeInsets.all(0),
|
|
|
|
content: Container(
|
|
height: MediaQuery.of(context).size.height,
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
SizedBox(
|
|
width: 5,
|
|
),
|
|
Container(
|
|
padding: const EdgeInsets.symmetric(
|
|
vertical: 10,
|
|
),
|
|
alignment: Alignment.bottomCenter,
|
|
height: double.infinity,
|
|
width: 35,
|
|
child: RotatedBox(
|
|
quarterTurns: 3,
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Text(
|
|
"Manual Ann'",
|
|
style: ShadTheme.of(context).textTheme.h3
|
|
),
|
|
SizedBox(
|
|
width: 16,
|
|
),
|
|
Container(
|
|
width: 1,
|
|
height: 200,
|
|
color: Colors.grey,
|
|
),
|
|
],
|
|
),
|
|
|
|
closeDialogWidget
|
|
|
|
],
|
|
),
|
|
),
|
|
),
|
|
Container(
|
|
|
|
// width: 220,
|
|
height: MediaQuery.of(context).size.height,
|
|
|
|
child: Scrollbar(
|
|
thumbVisibility: true,
|
|
child: SingleChildScrollView(
|
|
reverse: true,
|
|
child: Container(
|
|
margin: const EdgeInsets.fromLTRB(
|
|
0,
|
|
10,
|
|
10,
|
|
10
|
|
),
|
|
child: Column(
|
|
children: announcements.reversed.toList(),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
);
|
|
|
|
},
|
|
),
|
|
ShadButton(
|
|
text: const Text("Bus Stop Announcements"),
|
|
width: double.infinity,
|
|
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
|
onPressed: () {
|
|
|
|
showShadSheet(
|
|
context: context,
|
|
side: ShadSheetSide.left,
|
|
|
|
builder: (context) {
|
|
|
|
List<Widget> announcements = [];
|
|
|
|
LiveInformation info = LiveInformation();
|
|
|
|
for (var busStop in info.getRouteVariant()!.busStops) {
|
|
|
|
if (info.trackerModule.nearestStop == busStop) {
|
|
announcements.add(
|
|
ShadButton(
|
|
text: SizedBox(
|
|
width: 200-42,
|
|
child: Text(
|
|
"-> ${busStop.formattedStopName}",
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
),
|
|
backgroundColor: Colors.amber,
|
|
onPressed: () {
|
|
if (closeDialogWidget.closeDialog) {
|
|
Navigator.pop(context);
|
|
}
|
|
LiveInformation().announcementModule.queueAnnounceByAudioName(
|
|
displayText: busStop.formattedStopName,
|
|
audioNames: [busStop.getAudioFileName()],
|
|
);
|
|
},
|
|
)
|
|
);
|
|
} else {
|
|
announcements.add(
|
|
ShadButton(
|
|
text: SizedBox(
|
|
width: 200-42,
|
|
child: Text(
|
|
busStop.formattedStopName,
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
),
|
|
onPressed: () {
|
|
if (closeDialogWidget.closeDialog) {
|
|
Navigator.pop(context);
|
|
}
|
|
LiveInformation().announcementModule.queueAnnounceByAudioName(
|
|
displayText: busStop.formattedStopName,
|
|
audioNames: [busStop.getAudioFileName()],
|
|
);
|
|
},
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
ScrollController controller = ScrollController();
|
|
|
|
// Scroll to the current bus stop
|
|
WidgetsBinding.instance!.addPostFrameCallback((_) {
|
|
|
|
double offset = (info.getRouteVariant()!.busStops.indexOf(info.trackerModule.nearestStop!) * 50);
|
|
|
|
// Offset the offset so that its in the middle of the screen
|
|
offset -= (MediaQuery.of(context).size.height / 2) - 25;
|
|
|
|
// controller.jumpTo(offset);
|
|
});
|
|
|
|
return ShadSheet(
|
|
padding: const EdgeInsets.all(0),
|
|
|
|
content: Container(
|
|
height: MediaQuery.of(context).size.height,
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
SizedBox(
|
|
width: 5,
|
|
),
|
|
Container(
|
|
padding: const EdgeInsets.symmetric(
|
|
vertical: 10,
|
|
),
|
|
alignment: Alignment.bottomCenter,
|
|
height: double.infinity,
|
|
width: 35,
|
|
child: RotatedBox(
|
|
quarterTurns: 3,
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Text(
|
|
"Bus Stops",
|
|
style: ShadTheme.of(context).textTheme.h3
|
|
),
|
|
SizedBox(
|
|
width: 16,
|
|
),
|
|
Container(
|
|
width: 1,
|
|
height: 200,
|
|
color: Colors.grey,
|
|
),
|
|
],
|
|
),
|
|
|
|
closeDialogWidget
|
|
|
|
],
|
|
),
|
|
),
|
|
),
|
|
Container(
|
|
|
|
// width: 220,
|
|
height: MediaQuery.of(context).size.height,
|
|
|
|
child: Scrollbar(
|
|
thumbVisibility: true,
|
|
controller: controller,
|
|
child: SingleChildScrollView(
|
|
reverse: true,
|
|
controller: controller,
|
|
child: Container(
|
|
margin: const EdgeInsets.fromLTRB(
|
|
0,
|
|
10,
|
|
10,
|
|
10
|
|
),
|
|
child: Column(
|
|
children: announcements.reversed.toList(),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
);
|
|
|
|
},
|
|
),
|
|
],
|
|
)
|
|
)
|
|
),
|
|
|
|
const ShadButton(
|
|
icon: Icon(Icons.stop),
|
|
width: double.infinity,
|
|
),
|
|
|
|
ShadButton(
|
|
// text: const Text("Announce Destination"),
|
|
icon: const Icon(Icons.location_on),
|
|
width: double.infinity,
|
|
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
|
onPressed: () {
|
|
LiveInformation info = LiveInformation();
|
|
|
|
BusRouteVariant? routeVariant = info.getRouteVariant();
|
|
|
|
if (routeVariant != null) {
|
|
info.announcementModule.queueAnnouncementByRouteVariant(
|
|
routeVariant: routeVariant,
|
|
sendToServer: false
|
|
);
|
|
}
|
|
|
|
},
|
|
)
|
|
|
|
],
|
|
),
|
|
),
|
|
|
|
),
|
|
|
|
Expanded(
|
|
child: Container(
|
|
|
|
decoration: const BoxDecoration(
|
|
color: Colors.black,
|
|
borderRadius: BorderRadius.all(Radius.circular(10)),
|
|
|
|
),
|
|
|
|
margin: const EdgeInsets.all(10),
|
|
padding: const EdgeInsets.all(10),
|
|
|
|
width: double.infinity,
|
|
height: double.infinity,
|
|
|
|
child: Stack(
|
|
children: [
|
|
Container(
|
|
|
|
alignment: Alignment.center,
|
|
|
|
child: ibus_display(
|
|
hasBorder: false,
|
|
),
|
|
|
|
),
|
|
Container(
|
|
|
|
alignment: Alignment.bottomRight,
|
|
|
|
child: ShadButton.ghost(
|
|
icon: const Icon(Icons.fullscreen),
|
|
padding: const EdgeInsets.all(8),
|
|
onPressed: () {
|
|
Navigator.pushNamed(context, '/display');
|
|
},
|
|
),
|
|
|
|
),
|
|
Container(
|
|
|
|
alignment: Alignment.bottomLeft,
|
|
|
|
child: ShadButton.ghost(
|
|
icon: const Icon(Icons.arrow_back),
|
|
padding: const EdgeInsets.all(8),
|
|
onPressed: () {
|
|
Navigator.pop(context);
|
|
},
|
|
),
|
|
|
|
)
|
|
],
|
|
),
|
|
),
|
|
)
|
|
|
|
],
|
|
|
|
),
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
}
|
|
|
|
class _closeDialogueChecker extends StatefulWidget {
|
|
|
|
bool closeDialog = false;
|
|
|
|
@override
|
|
State<_closeDialogueChecker> createState() => _closeDialogueCheckerState();
|
|
}
|
|
|
|
class _closeDialogueCheckerState extends State<_closeDialogueChecker> {
|
|
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
// TODO: implement build
|
|
return ShadSwitch(
|
|
value: widget.closeDialog,
|
|
enabled: true,
|
|
label: const Text("Close Dialog?"),
|
|
onChanged: (value) {
|
|
widget.closeDialog = value;
|
|
setState(() {
|
|
|
|
});
|
|
|
|
},
|
|
);
|
|
}
|
|
} |