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:bus_infotainment/utils/delegates.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_scroll_shadow/flutter_scroll_shadow.dart'; import 'package:network_info_plus/network_info_plus.dart'; import 'package:qr_flutter/qr_flutter.dart'; import 'package:shadcn_ui/shadcn_ui.dart'; class ArcDashboard extends StatefulWidget { @override State createState() => _ArcDashboardState(); } class _ArcDashboardState extends State { _closeDialogueChecker closeDialogWidget = _closeDialogueChecker(); late ListenerReceipt onRouteVariantChange; @override void initState() { // TODO: implement initState super.initState(); onRouteVariantChange = LiveInformation().routeVariantDelegate.addListener((value) { print("Route variant changed"); setState(() { }); }); } @override void dispose() { // TODO: implement dispose super.dispose(); LiveInformation().routeVariantDelegate.removeListener(onRouteVariantChange); } @override Widget build(BuildContext context) { return PopScope( onPopInvoked: (isPop) { try { LiveInformation().leaveRoom(); print("Left room"); } catch (e) { print("Error leaving room: $e"); } }, child: Scaffold( body: Container( child: Row( children: [ const SizedBox( width: 10, ), Container( padding: const EdgeInsets.symmetric( vertical: 10, ), child: IntrinsicWidth( child: Column( children: [ ShadButton.outline( icon: const Icon(Icons.menu), width: double.infinity, border: Border.all( width: 2, color: Colors.grey.shade400, ), padding: const EdgeInsets.all(0), borderRadius: const BorderRadius.all(Radius.circular(10)), onPressed: () { bool multiMode = ModalRoute.of(context)!.settings.name!.contains("multi"); showShadSheet( context: context, side: ShadSheetSide.left, builder: (context) { return ShadSheet( padding: const EdgeInsets.all(0), content: Container( width: 225, height: MediaQuery.of(context).size.height, padding: const EdgeInsets.all(10), child: Column( children: [ Expanded( child: Column( children: [ if (LiveInformation().inRoom) ShadButton( text: Text("Room Information"), onPressed: () { Navigator.pop(context); showShadSheet( context: context, side: ShadSheetSide.left, builder: (context) { return ShadSheet( padding: const EdgeInsets.all(10), content: Column( children: [ Text("Room ID: ${LiveInformation().roomDocumentID}"), Text("IP Address: ${LiveInformation().networkingModule.localIP}"), QrImageView( data: LiveInformation().generateRoomInfo(), size: 270, backgroundColor: Colors.white, ), ShadButton( text: Text("Copy Room Info"), onPressed: () { Clipboard.setData(ClipboardData(text: LiveInformation().generateRoomInfo())); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text("Copied room info to clipboard"), ) ); }, ) ], ), ); } ); }, ) ], ) ), if (!LiveInformation().inRoom) ShadButton( text: Text("Return to route selection"), onPressed: () { Navigator.pop(context); Navigator.pop(context); }, ) else ShadButton( text: Text("Route selection"), onPressed: () { Navigator.popAndPushNamed(context, '/multi/routes'); }, ) ], ), ), ); } ); }, ), 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 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"), enabled: LiveInformation().getRouteVariant() != null, width: double.infinity, borderRadius: const BorderRadius.all(Radius.circular(10)), onPressed: () { showShadSheet( context: context, side: ShadSheetSide.left, builder: (context) { List 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, enabled: false, borderRadius: BorderRadius.all(Radius.circular(10)), ), ShadButton( // text: const Text("Announce Destination"), icon: const Icon(Icons.bus_alert), 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: ModalRoute.of(context)!.settings.name!.contains("multi") ); } }, ), ], ), ), ), 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.popUntil(context, (route) { return route.settings.name == '/multi' || route.settings.name == '/routes'; }); }, ), ) ], ), ), ) ], ), ), ), ); } } 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(() { }); }, ); } }