import 'package:bus_infotainment/backend/live_information.dart'; import 'package:bus_infotainment/pages/components/ibus_display.dart'; import 'package:bus_infotainment/tfl_datasets.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'dart:io' show Platform; import 'package:flutter/widgets.dart'; import 'package:flutter_carousel_widget/flutter_carousel_widget.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:shadcn_ui/shadcn_ui.dart'; import 'package:text_scroll/text_scroll.dart'; import '../backend/modules/tube_info.dart'; Color rgb(int r, int g, int b) { return Color.fromRGBO(r, g, b, 1); } class HomePage_Re extends StatefulWidget { @override State createState() => _HomePage_ReState(); } class _HomePage_ReState extends State { Future _shouldRedirectToSetup() async { List perms = []; perms.addAll([ await Permission.manageExternalStorage.isGranted, await Permission.location.isGranted ]); bool shouldRedirectA = !perms.contains(false); bool shouldRedirectB = true; try { Uint8List bytes = await LiveInformation().announcementModule.getBundleBytes(); shouldRedirectB = true; } catch (e) { print("Failed to load bundle"); shouldRedirectB = false; } print("Should redirect to setup: ${shouldRedirectA || shouldRedirectB}"); print("Permissions: $shouldRedirectA"); print("Bundle: $shouldRedirectB"); print("Permissions_indv: $perms"); return !shouldRedirectA || !shouldRedirectB; } @override void initState() { super.initState(); _shouldRedirectToSetup().then((value) { if (value) { Navigator.pushNamed(context, "/setup"); } }); } @override Widget build(BuildContext context) { // TODO: implement build return Scaffold( body: Container( padding: EdgeInsets.all(16), alignment: Alignment.center, child: SizedBox( width: double.infinity, child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Choose mode:", style: TextStyle( fontSize: 32, fontWeight: FontWeight.w600, ) ), SizedBox( height: 16, ), ShadCard( title: Text("Solo mode"), width: double.infinity, description: Text( "Choose this mode if you are only using this device. (No internet required)" ), content: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ SizedBox( height: 4, ), ShadButton.secondary( onPressed: () { Navigator.pushNamed(context, "/routes"); }, text: Text("Continue"), ) ], ), ), SizedBox( height: 16, ), ShadCard( title: Text("Multi mode"), width: double.infinity, description: Text( "Choose this mode if you are using multiple devices. (Internet required)" ), content: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ SizedBox( height: 4, ), ShadButton.secondary( onPressed: () { Navigator.pushNamed(context, "/application"); }, text: Text("Continue"), ) ], ), ) ], ), ) ), ); } } class RoutePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( body: Container( padding: EdgeInsets.all(16), alignment: Alignment.center, child: SizedBox( width: double.infinity, child: Column( mainAxisSize: MainAxisSize.max, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Routes", style: ShadTheme.of(context).textTheme.h1, ), Text( "Nearby routes", style: ShadTheme.of(context).textTheme.h4, ), ExpandableCarousel( options: CarouselOptions( ), items: [ ShadCard( title: Text("Route 34"), content: ShadSelect( options: [ Padding( padding: const EdgeInsets.all(8.0), child: Text("Choose a variant"), ) ], selectedOptionBuilder: (BuildContext context, value) { return Text("Choose a variant"); }, ), padding: EdgeInsets.all(10), ) ], ), Divider(), RouteSearch() ], ), ) ), ); } List _getNearbyRoutes() { final variants = [ "Walthamstow Central to Barnet Church", "Walthamstow Central to Barnet Church", ]; List widgets = []; for (int i = 0; i < variants.length; i++) { widgets.add( ShadOption( value: i, child: Text(variants[i]!), ) ); } return widgets; } } class RouteSearch extends StatefulWidget { @override State createState() => _RouteSearchState(); } class _RouteSearchState extends State { TextEditingController controller = TextEditingController(); @override Widget build(BuildContext context) { List routes = []; for (BusRoute route in LiveInformation().busSequences.routes.values.toList()) { if (controller.text.isNotEmpty && !route.routeNumber.toLowerCase().contains(controller.text.toLowerCase())) { continue; } routes.add(RouteCard(route: route)); } return Expanded( child: Column( children: [ ShadInput( placeholder: Text("Search for a route..."), controller: controller, onChanged: (value) { setState(() { }); }, ), SizedBox( height: 4, ), Expanded( child: GridView.count( crossAxisCount: 3, children: [ ...routes ], ), ) ], ), ); } } class RouteCard extends StatelessWidget { BusRoute route; RouteCard({required this.route}); @override Widget build(BuildContext context) { // TODO: implement build Map variants = {}; for (BusRouteVariant variant in route.routeVariants.values) { String variantLabel = "${variant.busStops.first.formattedStopName} -> ${variant.busStops.last.formattedStopName}"; variants[variantLabel] = ShadOption( value: variant.routeVariant.toString(), child: Text(variantLabel), ); } return AspectRatio( aspectRatio: 1, child: Container( child: ShadButton.secondary( text: Text( "Route \n ${route.routeNumber}", style: ShadTheme.of(context).textTheme.h3 ), padding: EdgeInsets.all(8), width: 105, height: 105, onPressed: () { showShadSheet( side: ShadSheetSide.bottom, context: context, builder: (context) { List variantWidgets = []; for (BusRouteVariant variant in route.routeVariants.values) { String variantLabel = "${variant.busStops.first.formattedStopName} -> ${variant.busStops.last.formattedStopName}"; variantWidgets.add( ShadButton.outline( text: SizedBox( width: 800-490, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text("${variant.busStops.first.formattedStopName} ->"), SizedBox( height: 2, ), Text(variant.busStops.last.formattedStopName) ], ), ), width: double.infinity, height: 50, padding: EdgeInsets.all(8), onPressed: () async { LiveInformation liveInformation = LiveInformation(); await liveInformation.setRouteVariant(variant); liveInformation.announcementModule.queueAnnouncementByRouteVariant(routeVariant: variant); Navigator.pushNamed(context, "/enroute"); }, ) ); variantWidgets.add(SizedBox( height: 4, )); } return ShadSheet( title: Text("Route ${route.routeNumber} - Variants"), content: Container( width: 2000, alignment: Alignment.center, child: Column( children: [ ...variantWidgets ], ), ), padding: EdgeInsets.all(8), ); } ); }, ), ), ); } } class EnRoutePage extends StatelessWidget { @override Widget build(BuildContext context) { // TODO: implement build return Scaffold( body: Column( children: [ Container( padding: EdgeInsets.all(8), child: ibus_display() ), Divider( height: 1, ), ShadButton( text: Text("Route scanner"), onPressed: () { LiveInformation liveInformation = LiveInformation(); TubeLine? line = liveInformation.tubeStations.getClosestLine(liveInformation.getRouteVariant()!); ShadToaster.of(context).show( ShadToast( title: Text("Closest line"), description: Text(line == null ? "No line found" : line.name), duration: Duration(seconds: 5), ) ); }, ), ShadButton( text: Text("dest"), onPressed: () { LiveInformation liveInformation = LiveInformation(); liveInformation.announcementModule.queueAnnouncementByRouteVariant(routeVariant: liveInformation.getRouteVariant()!); }, ) ], ), ); } } /* ShadSelectFormField( options: [ Padding( padding: const EdgeInsets.all(8.0), child: Text("Choose a variant"), ), ...variants.values ], selectedOptionBuilder: (context, value) => value == 'none' ? const Text('Select a verified email to display') : Text(variants.keys.toList()[int.parse(value)-1]!), placeholder: Text("Choose a variant"), ), */