import 'package:bus_infotainment/pages/components/ibus_display.dart'; import 'package:bus_infotainment/singletons/live_information.dart'; import 'package:bus_infotainment/tfl_datasets.dart'; import 'package:bus_infotainment/utils/audio%20wrapper.dart'; import 'package:bus_infotainment/utils/delegates.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; class pages_Home extends StatelessWidget { const pages_Home({super.key}); @override Widget build(BuildContext context) { return Container( child: Column( children: [ Container( height: 2, color: Colors.white70, ), Container( decoration: BoxDecoration( color: Colors.grey.shade900, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.3), blurRadius: 2, spreadRadius: 4 ) ] ), margin: EdgeInsets.all(20), child: ibus_display(), ), Container( height: 2, color: Colors.white70, ), Container( margin: EdgeInsets.all(20), child: Container( decoration: BoxDecoration( color: Colors.grey.shade900, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.3), blurRadius: 2, spreadRadius: 4 ) ] ), child: ManualAnnouncementPicker( backgroundColor: Colors.grey.shade900, outlineColor: Colors.white70, announcements: [ ...LiveInformation().manualAnnouncements ], ), ), ), Container( height: 2, color: Colors.white70, ), Container( margin: EdgeInsets.all(20), child: Container( decoration: BoxDecoration( color: Colors.grey.shade900, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.3), blurRadius: 2, spreadRadius: 4 ) ] ), child: DelegateBuilder( delegate: LiveInformation().routeVariantDelegate, 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( routeVariant: routeVariant, backgroundColor: Colors.grey.shade900, outlineColor: Colors.white70, ); } }, ), ), ), // Container( // // margin: EdgeInsets.all(20), // // height: 300-45, // // child: ListView( // // scrollDirection: Axis.vertical, // // children: [ // // ElevatedButton( // onPressed: () async { // LiveInformation liveInformation = LiveInformation(); // liveInformation.queueAnnouncement(await liveInformation.getDestinationAnnouncement(liveInformation.getRouteVariant()!, sendToServer: false)); // }, // child: Text("Test announcement"), // ), // // ElevatedButton( // onPressed: () { // LiveInformation liveInformation = LiveInformation(); // liveInformation.updateServer(); // }, // child: Text("Update server"), // ), // // SizedBox( // // width: 100, // // child: TextField( // onChanged: (String value) { // LiveInformation liveInformation = LiveInformation(); // // liveInformation.documentID = value; // }, // ), // ), // // SizedBox( // // width: 200, // // child: TextField( // onSubmitted: (String value) { // LiveInformation liveInformation = LiveInformation(); // liveInformation.queueAnnouncement(AnnouncementQueueEntry( // displayText: value, // audioSources: [] // )); // }, // ), // ), // // ElevatedButton( // onPressed: () { // LiveInformation liveInformation = LiveInformation(); // liveInformation.pullServer(); // }, // child: Text("Pull server"), // ), // // ], // // ), // // ), ], ) ); } } class ManualAnnouncementPicker extends StatefulWidget { final Color backgroundColor; final Color outlineColor; final List announcements; const ManualAnnouncementPicker({super.key, required this.backgroundColor, required this.outlineColor, required this.announcements}); @override State createState() => _ManualAnnouncementPickerState(); } class _ManualAnnouncementPickerState extends State { List announcementWidgets = []; int _currentIndex = 0; @override void initState() { // TODO: implement initState super.initState(); LiveInformation liveInformation = LiveInformation(); if (widget.announcements.isEmpty){ return; } int i = 0; for (NamedAnnouncementQueueEntry announcement in widget.announcements!) { announcementWidgets.add( _ManualAnnouncementEntry( announcement: announcement, index: i, outlineColor: Colors.white70 ) ); i++; } } @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( color: widget.backgroundColor, border: Border.all( color: widget.outlineColor, width: 2 ), ), padding: const EdgeInsets.all(4), width: double.infinity, constraints: const BoxConstraints( maxWidth: 400 ), child: Column( children: [ Container( height: 2, color: widget.outlineColor, ), if (_currentIndex < announcementWidgets.length) announcementWidgets[_currentIndex + 0] else Container( height: 50, decoration: BoxDecoration( color: widget.backgroundColor, border: Border.symmetric( vertical: BorderSide( color: widget.outlineColor, width: 2 ) ), ), ), Container( height: 2, color: widget.outlineColor, ), if (_currentIndex + 1 < announcementWidgets.length) announcementWidgets[_currentIndex + 1] else Container( height: 50, decoration: BoxDecoration( color: widget.backgroundColor, border: Border.symmetric( vertical: BorderSide( color: widget.outlineColor, width: 2 ) ), ), ), Container( height: 2, color: widget.outlineColor, ), if (_currentIndex + 2 < announcementWidgets.length) announcementWidgets[_currentIndex + 2] else Container( height: 50, decoration: BoxDecoration( color: widget.backgroundColor, border: Border.symmetric( vertical: BorderSide( color: widget.outlineColor, width: 2 ) ), ), ), Container( height: 2, color: widget.outlineColor, ), if (_currentIndex + 3 < announcementWidgets.length) announcementWidgets[_currentIndex + 3] else Container( height: 50, decoration: BoxDecoration( color: widget.backgroundColor, border: Border.symmetric( vertical: BorderSide( color: widget.outlineColor, width: 2 ) ), ), ), Container( height: 2, color: widget.outlineColor, ), Container( height: 40, decoration: BoxDecoration( color: widget.backgroundColor, border: Border.symmetric( vertical: BorderSide( color: widget.outlineColor, width: 2 ) ), ), alignment: Alignment.centerRight, child: Row( mainAxisSize: MainAxisSize.min, children: [ Container( width: 40, height: 40, decoration: BoxDecoration( color: widget.backgroundColor, border: Border.symmetric( vertical: BorderSide( color: widget.outlineColor, width: 2 ) ), ), margin: const EdgeInsets.symmetric( horizontal: 4 ), child: Container( child: Stack( children: [ Container( width: 40, height: 40, child: Icon( Icons.arrow_upward, color: widget.outlineColor, ), ), Positioned.fill( child: ElevatedButton( onPressed: () { _currentIndex = wrap(_currentIndex - 4, 0, announcementWidgets.length); setState(() {}); print(_currentIndex); }, style: ElevatedButton.styleFrom( backgroundColor: Colors.transparent, shadowColor: Colors.transparent, surfaceTintColor: Colors.transparent, foregroundColor: Colors.transparent, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(0), ), ), child: const Text(""), ), ) ], ), ) ), Container( width: 40, height: 40, decoration: BoxDecoration( color: widget.backgroundColor, border: Border.symmetric( vertical: BorderSide( color: widget.outlineColor, width: 2 ) ), ), margin: const EdgeInsets.symmetric( horizontal: 4 ), child: Container( child: Stack( children: [ Container( width: 40, height: 40, child: Icon( Icons.arrow_downward, color: widget.outlineColor, ), ), Positioned.fill( child: ElevatedButton( onPressed: () { _currentIndex = wrap(_currentIndex + 4, 0, announcementWidgets.length); setState(() {}); print(_currentIndex); }, style: ElevatedButton.styleFrom( backgroundColor: Colors.transparent, shadowColor: Colors.transparent, surfaceTintColor: Colors.transparent, foregroundColor: Colors.transparent, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(0), ), ), child: const Text(""), ), ) ], ), ) ), ] ), ), Container( height: 2, color: widget.outlineColor, ), ] ), ); } } class StopAnnouncementPicker extends ManualAnnouncementPicker { final BusRouteVariant routeVariant; StopAnnouncementPicker({ Key? key, required this.routeVariant, required Color backgroundColor, required Color outlineColor, }) : super( key: key, backgroundColor: backgroundColor, outlineColor: outlineColor, announcements: [ for (BusRouteStops stop in routeVariant.busStops) ManualAnnouncementEntry( shortName: stop.formattedStopName, informationText: stop.formattedStopName, audioSources: [ // AudioWrapperByteSource( // LiveInformation().announcementCache[stop.getAudioFileName()] // ) ] ) ] ); } int wrap(int i, int j, int length) { return ((i - j) % length + length) % length; } class _ManualAnnouncementEntry extends StatelessWidget { final NamedAnnouncementQueueEntry announcement; final int index; final Color outlineColor; _ManualAnnouncementEntry({super.key, required this.announcement, required this.index, required this.outlineColor}); @override Widget build(BuildContext context) { return Stack( children: [ Container( decoration: BoxDecoration( color: Colors.transparent, border: Border.symmetric( vertical: BorderSide( color: outlineColor, width: 2 ) ), ), padding: const EdgeInsets.symmetric( horizontal: 10, vertical: 5 ), width: double.infinity, child: Transform.translate( offset: Offset(0, 4), child: Row( children: [ Text( announcement.shortName, style: GoogleFonts.teko( fontSize: 25, color: outlineColor, ) ), Expanded( child: Container( alignment: Alignment.centerRight, child: Text( (index+1).toString(), style: GoogleFonts.teko( fontSize: 25, color: outlineColor, ) ), ), ) ], ), ) ), Positioned.fill( child: ElevatedButton( onPressed: () { LiveInformation liveInformation = LiveInformation(); liveInformation.queueAnnouncement(announcement); }, style: ElevatedButton.styleFrom( backgroundColor: Colors.transparent, shadowColor: Colors.transparent, surfaceTintColor: Colors.transparent, foregroundColor: Colors.transparent, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(0), ), ), child: const Text("More"), ), ) ], ); } }