import 'package:info_tren/train_info_page/train_info_animation_helpers.dart'; import 'package:info_tren/utils/stream_list.dart'; import '../models/train_data.dart'; import './train_info.dart'; import 'package:flutter/material.dart'; class TrainInfoMaterial extends StatefulWidget { final int trainNumber; TrainInfoMaterial({@required this.trainNumber}); @override _TrainInfoMaterialState createState() => _TrainInfoMaterialState(); } class _TrainInfoMaterialState extends State with TrainInfoMixin { @override void initState() { super.initState(); title = widget.trainNumber.toString(); showTrainData = false; requestedData = false; } @override void didChangeDependencies() { super.didChangeDependencies(); if (!requestedData) { requestedData = true; TrainDataWebViewAdapter.of(context).loadTrain(widget.trainNumber).then((value) { setState(() { lookupResult = value; }); if (lookupResult == TrainLookupResult.NOT_FOUND) { Future.delayed(Duration(seconds: 5), () { Navigator.of(context).pop(); }); } else if (lookupResult == TrainLookupResult.FOUND) { Future.delayed(Duration(seconds: 1, milliseconds: 500), () { setState(() { showTrainData = true; }); }); } }); } } @override Widget build(BuildContext context) { if (!showTrainData) { return _TrainInfoMaterialBefore( title: title, lookupResult: lookupResult, ); } else { return _TrainDataMaterialAfter( title: title, ); } } } class _TrainInfoMaterialBefore extends StatefulWidget { final String title; final TrainLookupResult lookupResult; _TrainInfoMaterialBefore({@required this.title, @required this.lookupResult}); @override _TrainInfoMaterialBeforeState createState() => _TrainInfoMaterialBeforeState(); } class _TrainInfoMaterialBeforeState extends State<_TrainInfoMaterialBefore> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( centerTitle: true, title: Text(widget.title ?? ""), ), body: SafeArea( bottom: false, child: StreamBuilder( stream: TrainDataWebViewAdapter.of(context).progressStream, builder: (context, snapshot) { switch (snapshot.connectionState) { case ConnectionState.none: return Container(); case ConnectionState.waiting: return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ CircularProgressIndicator(), Text( "Conectare...", style: Theme.of(context).textTheme.title, ), ], ), ); case ConnectionState.active: break; case ConnectionState.done: Navigator.of(context).pop(); return Container(); } return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ ProgressReportDisplayEntry( key: ValueKey(1), completed: 1 <= snapshot.data.current, waitingText: "Se crează WebView", completedText: "WebView a fost creat", ), ProgressReportDisplayEntry( key: ValueKey(2), completed: 2 <= snapshot.data.current, waitingText: "Se încarcă pagina Informatica Feroviară", completedText: "Pagina Informatica Feroviară a fost încărcată", ), ProgressReportDisplayEntry( key: ValueKey(3), completed: 3 <= snapshot.data.current, waitingText: "Se încarcă informațiile despre tren", completedText: "Informațiile despre tren au fost încărcate", ), if (widget.lookupResult != null) ...[ Container(height: 20,), SizedBox( width: double.infinity, child: AnimatedBackground( animationDuration: Duration(milliseconds: 250), initialColor: Theme.of(context).scaffoldBackgroundColor, backgroundColor: widget.lookupResult == TrainLookupResult.FOUND ? Colors.green : Colors.red, child: Center( child: Row( children: [ Expanded(child: Container(),), if (widget.lookupResult == TrainLookupResult.FOUND) Padding( padding: const EdgeInsets.fromLTRB(8, 8, 0, 8), child: Center( child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(Colors.greenAccent), ) ), ), Padding( padding: const EdgeInsets.all(8.0), child: Text( widget.lookupResult == TrainLookupResult.FOUND ? "Trenul a fost găsit" : widget.lookupResult == TrainLookupResult.NOT_FOUND ? "Trenul nu a fost găsit" : "A apărut o eroare în căutarea trenului", style: Theme.of(context).textTheme.title, ), ), Expanded(child: Container(),), ], ), ), ), ), ], ], ), ); }, ), ), ); } } bool isSmallScreen(BuildContext context) => MediaQuery.of(context).size.height <= 425; class _TrainDataMaterialAfter extends StatefulWidget { final String title; _TrainDataMaterialAfter({@required this.title}); @override _TrainDataMaterialAfterState createState() => _TrainDataMaterialAfterState(); } class _TrainDataMaterialAfterState extends State<_TrainDataMaterialAfter> { @override Widget build(BuildContext context) { return FutureBuilder( future: TrainDataWebViewAdapter.of(context).trainData(onInvalidation: () { Navigator.of(context).pop(); }), builder: (context, snapshot) { if (!snapshot.hasData) { return Scaffold( appBar: AppBar( centerTitle: true, title: Text(widget.title ?? ""), ), body: SafeArea( child: Center( child: CircularProgressIndicator(), ), ), ); } return Scaffold( appBar: isSmallScreen(context) ? null : AppBar( centerTitle: true, title: FutureBuilder>( future: Future.wait([ snapshot.data.rang, snapshot.data.trainNumber ]), builder: (context, snapshot) { if (snapshot.hasData) { return Text("Informații despre ${snapshot.data[0]} ${snapshot.data[1]}"); } else { return Text(widget.title ?? ""); } }, ), ), body: Column( children: [ if (isSmallScreen(context)) FutureBuilder>( future: Future.wait([ snapshot.data.rang, snapshot.data.trainNumber, ]), builder: (context, snapshot) { var title = "INFO TREN"; if (snapshot.hasData) title = "INFO TREN ─ ${snapshot.data[0]} ${snapshot.data[1]}"; return SlimAppBar( title: title, ); } ), Expanded( child: SafeArea( bottom: false, child: CustomScrollView( slivers: [ SliverToBoxAdapter( child: DisplayTrainID(trainData: snapshot.data,), ), SliverToBoxAdapter( child: DisplayTrainOperator(trainData: snapshot.data,), ), SliverPadding( padding: const EdgeInsets.only(left: 2, right: 2), sliver: SliverToBoxAdapter( child: DisplayTrainRoute(trainData: snapshot.data,), ), ), SliverToBoxAdapter( child: DisplayTrainDeparture(trainData: snapshot.data,), ), SliverToBoxAdapter( child: Divider( color: Colors.white70, height: isSmallScreen(context) ? 8 : 16, ), ), SliverToBoxAdapter( child: DisplayTrainLastInfo(trainData: snapshot.data,), ), SliverToBoxAdapter( child: IntrinsicHeight( child: Row( children: [ Expanded(child: DisplayTrainNextStop(trainData: snapshot.data,)), Expanded(child: DisplayTrainDestination(trainData: snapshot.data,)), ], ), ), ), SliverToBoxAdapter( child: IntrinsicHeight( child: Row( children: [ Expanded(child: DisplayTrainRouteDuration(trainData: snapshot.data,)), Expanded(child: DisplayTrainRouteDistance(trainData: snapshot.data,)), ], ), ), ), SliverToBoxAdapter( child: Divider( color: Colors.white70, height: isSmallScreen(context) ? 8 : 16, ), ), DisplayTrainStations( trainData: snapshot.data, pageLoadFuture: TrainDataWebViewAdapter.of(context).nextLoadFuture, ), SliverToBoxAdapter( child: Container( height: MediaQuery.of(context).viewPadding.bottom, ), ), ], ), ), ), ], ), ); }, ); } } class DisplayTrainID extends StatelessWidget { final OnDemandTrainData trainData; DisplayTrainID({@required this.trainData}); @override Widget build(BuildContext context) { return FutureDisplay>( future: Future.wait([ trainData.rang, trainData.trainNumber, ]), builder: (context, list) { return Text( "${list[0]} ${list[1]}", style: (isSmallScreen(context) ? Theme.of(context).textTheme.display1 : Theme.of(context).textTheme.display2).copyWith( color: Theme.of(context).textTheme.body1.color, fontWeight: FontWeight.bold, ), textAlign: TextAlign.center, ); }, ); } } class DisplayTrainOperator extends StatelessWidget { final OnDemandTrainData trainData; DisplayTrainOperator({@required this.trainData}); @override Widget build(BuildContext context) { return FutureDisplay( future: trainData.operator, builder: (context, op) { return Text( op, style: Theme.of(context).textTheme.body1.copyWith( fontStyle: FontStyle.italic, fontSize: isSmallScreen(context) ? 12 : 14, ), textAlign: TextAlign.center, ); }, ); } } class DisplayTrainRoute extends StatelessWidget { final OnDemandTrainData trainData; DisplayTrainRoute({@required this.trainData}); @override Widget build(BuildContext context) { return FutureDisplay( future: Future.wait([trainData.route.from, trainData.route.to]), builder: (context, routePieces) { return Row( children: [ Center( child: Padding( padding: const EdgeInsets.all(4), child: Text( routePieces[0], style: Theme.of(context).textTheme.body1.copyWith( fontSize: 16, ), ), ), ), Expanded(child: Container(),), Center(child: Text("-")), Expanded(child: Container(),), Center( child: Padding( padding: const EdgeInsets.all(4), child: Text( routePieces[1], style: Theme.of(context).textTheme.body1.copyWith( fontSize: 16, ), textAlign: TextAlign.right, ), ), ), ], ); }, ); } } class DisplayTrainDeparture extends StatelessWidget { final OnDemandTrainData trainData; DisplayTrainDeparture({@required this.trainData}); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.all(2), child: FutureDisplay( future: trainData.departureDate, builder: (context, dataPlecare) { return Text( "Plecare în ${dataPlecare.day.toString().padLeft(2, '0')}.${dataPlecare.month.toString().padLeft(2, '0')}.${dataPlecare.year.toString().padLeft(4, '0')}", style: Theme.of(context).textTheme.body1.copyWith( fontStyle: FontStyle.italic, fontWeight: FontWeight.w200, fontSize: isSmallScreen(context) ? 12 : 14, ), textAlign: TextAlign.center, ); }, ), ); } } class DisplayTrainLastInfo extends StatelessWidget { final OnDemandTrainData trainData; DisplayTrainLastInfo({@required this.trainData}); @override Widget build(BuildContext context) { return Card( child: Padding( padding: const EdgeInsets.all(2), child: Column( mainAxisSize: MainAxisSize.min, children: [ Center( child: Padding( padding: const EdgeInsets.all(2), child: Text( "Ultima informație", style: Theme.of(context).textTheme.body1.copyWith( fontSize: isSmallScreen(context) ? 18 : 20, fontWeight: FontWeight.bold, ), ), ), ), Row( children: [ Padding( padding: const EdgeInsets.all(4), child: FutureDisplay( future: trainData.lastInfo.station, builder: (context, station) { return Text( station, style: Theme.of(context).textTheme.body1, textAlign: TextAlign.left, ); }, ), ), Expanded(child: Container(),), Padding( padding: const EdgeInsets.all(4), child: FutureDisplay( future: trainData.lastInfo.event, builder: (context, event) { return Text( event, style: Theme.of(context).textTheme.body1, textAlign: TextAlign.right, ); }, ), ), ], ), Padding( padding: const EdgeInsets.all(2), child: Row( children: [ FutureDisplay( future: trainData.lastInfo.dateAndTime, builder: (context, dt) { return Text( "Raportat în ${dt.day.toString().padLeft(2, '0')}.${dt.month.toString().padLeft(2, '0')}.${dt.year.toString().padLeft(4, '0')}, la ${dt.hour.toString().padLeft(2, '0')}:${dt.minute.toString().padLeft(2, '0')}", textAlign: TextAlign.center, ); }, ), Expanded(child: Container(),), FutureBuilder( initialData: 0, future: trainData.lastInfo.delay, builder: (context, snapshot) { if (snapshot.data == 0) { return Container(); } if (snapshot.data > 0) { return Text( "${snapshot.data} minute întârziere", style: Theme.of(context).textTheme.body1.copyWith( fontSize: 14, color: Color.fromRGBO(200, 30, 15, 1), ), ); } else { return Text( "${-snapshot.data} minute mai devreme", style: Theme.of(context).textTheme.body1.copyWith( fontSize: 12, color: Color.fromRGBO(15, 200, 15, 1), ), ); } }, ), ], ), ), ], ), ), ); } } class DisplayTrainNextStop extends StatelessWidget { final OnDemandTrainData trainData; DisplayTrainNextStop({@required this.trainData}); @override Widget build(BuildContext context) { return FutureBuilder( future: trainData.nextStop.stationName, builder: (context, snapshot) { if (!snapshot.hasData) return Container(height: 0,); return Card( child: Center( child: Padding( padding: const EdgeInsets.all(2), child: Column( mainAxisSize: MainAxisSize.min, children: [ Padding( padding: const EdgeInsets.all(4), child: Text( "Următoarea oprire", style: Theme.of(context).textTheme.body1.copyWith( fontSize: isSmallScreen(context) ? 18 : 20, fontWeight: FontWeight.bold, ), textAlign: TextAlign.center, ), ), FutureDisplay( future: trainData.nextStop.stationName, builder: (context, station) { return Padding( padding: const EdgeInsets.fromLTRB(4, 0, 4, 0), child: Text( station, style: Theme.of(context).textTheme.body1.copyWith( fontSize: isSmallScreen(context) ? 16 : 18, fontWeight: FontWeight.w500, ), textAlign: TextAlign.center, ), ); }, ), FutureDisplay( future: trainData.nextStop.arrival, builder: (context, arrival) { const months = ["ian", "feb", "mar", "apr", "mai", "iun", "iul", "aug", "sep", "oct", "noi", "dec"]; return Column( mainAxisSize: MainAxisSize.min, children: [ Text( "în ${arrival.day} ${months[arrival.month - 1]} ${arrival.year}", style: Theme.of(context).textTheme.body1.copyWith( fontSize: isSmallScreen(context) ? 12 : 14, ), textAlign: TextAlign.center, ), Text( "la ${arrival.hour.toString().padLeft(2, '0')}:${arrival.minute.toString().padLeft(2, '0')}", style: Theme.of(context).textTheme.body1.copyWith( fontSize: isSmallScreen(context) ? 12 : 14, ), textAlign: TextAlign.center, ), ], ); }, ) ], ), ), ), ); } ); } } class DisplayTrainDestination extends StatelessWidget { final OnDemandTrainData trainData; DisplayTrainDestination({@required this.trainData}); @override Widget build(BuildContext context) { return FutureBuilder( future: trainData.destination.stationName, builder: (context, snapshot) { if (!snapshot.hasData) return Container(height: 0,); return Card( child: Center( child: Padding( padding: const EdgeInsets.all(2), child: Column( mainAxisSize: MainAxisSize.min, children: [ Padding( padding: const EdgeInsets.all(4), child: Text( "Destinația", style: Theme.of(context).textTheme.body1.copyWith( fontSize: isSmallScreen(context) ? 18 : 20, fontWeight: FontWeight.bold, ), textAlign: TextAlign.center, ), ), FutureDisplay( future: trainData.destination.stationName, builder: (context, station) { return Padding( padding: const EdgeInsets.fromLTRB(4, 0, 4, 0), child: Text( station, style: Theme.of(context).textTheme.body1.copyWith( fontSize: isSmallScreen(context) ? 16 : 18, fontWeight: FontWeight.w500, ), textAlign: TextAlign.center, ), ); }, ), FutureDisplay( future: trainData.destination.arrival, builder: (context, arrival) { const months = ["ian", "feb", "mar", "apr", "mai", "iun", "iul", "aug", "sep", "oct", "noi", "dec"]; return Column( mainAxisSize: MainAxisSize.min, children: [ Text( "în ${arrival.day} ${months[arrival.month - 1]} ${arrival.year}", style: Theme.of(context).textTheme.body1.copyWith( fontSize: isSmallScreen(context) ? 12 : 14, ), textAlign: TextAlign.center, ), Text( "la ${arrival.hour.toString().padLeft(2, '0')}:${arrival.minute.toString().padLeft(2, '0')}", style: Theme.of(context).textTheme.body1.copyWith( fontSize: isSmallScreen(context) ? 12 : 14, ), textAlign: TextAlign.center, ), ], ); }, ) ], ), ), ), ); } ); } } class DisplayTrainRouteDistance extends StatelessWidget { final OnDemandTrainData trainData; DisplayTrainRouteDistance({@required this.trainData}); @override Widget build(BuildContext context) { return Card( child: Center( child: Padding( padding: const EdgeInsets.all(2), child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( "Distanța rutei", style: Theme.of(context).textTheme.body1.copyWith( fontSize: isSmallScreen(context) ? 16 : 18, fontWeight: FontWeight.bold, ), textAlign: TextAlign.center, ), FutureDisplay( future: trainData.routeDistance, builder: (context, distance) { return Text( "$distance km", style: Theme.of(context).textTheme.body1.copyWith( fontSize: isSmallScreen(context) ? 14 : 16, ), textAlign: TextAlign.center, ); }, ), ], ), ), ), ); } } class DisplayTrainRouteDuration extends StatelessWidget { final OnDemandTrainData trainData; DisplayTrainRouteDuration({@required this.trainData}); @override Widget build(BuildContext context) { return Card( child: Center( child: Padding( padding: const EdgeInsets.all(2), child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( "Durata rutei", style: Theme.of(context).textTheme.body1.copyWith( fontSize: isSmallScreen(context) ? 16 : 18, fontWeight: FontWeight.bold, ), textAlign: TextAlign.center, ), FutureDisplay( future: trainData.routeDuration, builder: (context, duration) { var durationString = StringBuffer(); bool firstWritten = false; if (duration.inDays > 0) { firstWritten = true; if (duration.inDays == 1) durationString.write("1 zi"); else durationString.write("${duration.inDays} zile"); duration -= Duration(days: duration.inDays); } if (duration.inHours > 0) { if (firstWritten) { durationString.write(", "); } firstWritten = true; if (duration.inHours == 1) durationString.write("1 oră"); else durationString.write("${duration.inHours} ore"); duration -= Duration(hours: duration.inHours); } if (duration.inMinutes > 0) { if (firstWritten) { durationString.write(", "); } firstWritten = true; if (duration.inMinutes == 1) durationString.write("1 minut"); else durationString.write("${duration.inMinutes} minute"); duration -= Duration(minutes: duration.inMinutes); } return Text( durationString.toString(), style: Theme.of(context).textTheme.body1.copyWith( fontSize: isSmallScreen(context) ? 14 : 16, ), textAlign: TextAlign.center, ); }, ), ], ), ), ), ); } } class DisplayTrainStations extends StatelessWidget { final OnDemandTrainData trainData; final Future pageLoadFuture; DisplayTrainStations({@required this.trainData, @required this.pageLoadFuture}); @override Widget build(BuildContext context) { return StreamBuilder>( stream: listifyStream(trainData.stations(pageLoadFuture: pageLoadFuture)), builder: (context, snapshot) { if (!snapshot.hasData) { return SliverToBoxAdapter( child: Container(), ); } return SliverList( delegate: SliverChildBuilderDelegate( (context, index) { return IndexedSemantics( child: DisplayTrainStation( station: snapshot.data[index], ), index: index, ); }, childCount: snapshot.data.length, addSemanticIndexes: true, ), ); }, ); } } class DisplayTrainStation extends StatelessWidget { final OnDemandStation station; DisplayTrainStation({@required this.station}); @override Widget build(BuildContext context) { return Card( child: Padding( padding: const EdgeInsets.all(2), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ Row( mainAxisSize: MainAxisSize.max, children: [ Padding( padding: const EdgeInsets.all(8), child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), border: Border.all( width: 2, color: Colors.white70, ), // color: CupertinoColors.activeOrange, ), width: isSmallScreen(context) ? 42 : 48, height: isSmallScreen(context) ? 42 : 48, child: Column( mainAxisSize: MainAxisSize.min, children: [ Expanded( child: Center( child: FutureDisplay( future: station.km, builder: (context, value) { return Text( value.toString(), style: Theme.of(context).textTheme.body1.copyWith( fontSize: isSmallScreen(context) ? 14 : 18, fontWeight: FontWeight.w100, ), textAlign: TextAlign.center, ); }, ), ), ), Text( "km", style: Theme.of(context).textTheme.body1.copyWith(fontSize: 10), ), ], ), ), ), Expanded( child: FutureDisplay>( future: Future.wait([ station.stationName, station.observations ]), builder: (context, items) { return Text( items[0], style: Theme.of(context).textTheme.body1.copyWith( fontSize: isSmallScreen(context) ? 18 : 22, fontWeight: FontWeight.w100, fontStyle: items[1] == "ONI" ? FontStyle.italic : FontStyle.normal, ), textAlign: TextAlign.center, ); }, ) ) ], ), FutureDisplay>( future: Future.wait([ station.arrivalTime, station.stopsFor, station.departureTime ]), builder: (context, items) { if (items[0].isEmpty) { // Plecare return Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded(child: Container(),), Text("plecare la ${items[2]}"), Container(width: 2,), Text( "→", style: Theme.of(context).textTheme.body1.copyWith( fontSize: isSmallScreen(context) ? 18 : 22, ), ), ], ); } if (items[2].isEmpty) { // Sosire return Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( "→", style: Theme.of(context).textTheme.body1.copyWith( fontSize: isSmallScreen(context) ? 18 : 22, ), ), Container(width: 2,), Text("sosire la ${items[0]}"), Expanded(child: Container(),), ], ); } return Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( "→", style: Theme.of(context).textTheme.body1.copyWith( fontSize: isSmallScreen(context) ? 18 : 22, ), ), Container(width: 2,), Text(items[0]), Expanded(child: Container(),), Column( mainAxisSize: MainAxisSize.min, children: [ Builder( builder: (context) { if (items[1].isEmpty || items[1] == "0") { return Container(); } if (items[1] == "1") { return Text( "staționează pentru\n1 minut", textAlign: TextAlign.center, ); } return Text( "staționează pentru\n${items[1]} minute", textAlign: TextAlign.center, ); } ), FutureBuilder( future: station.observations, builder: (context, snapshot) { if (snapshot.data == "ONI") { return Text( "oprire ne-itinerarică", style: Theme.of(context).textTheme.body1.copyWith( fontStyle: FontStyle.italic, ), textAlign: TextAlign.center, ); } return Container(); }, ) ], ), Expanded(child: Container(),), Text(items[2]), Container(width: 2,), Text( "→", style: Theme.of(context).textTheme.body1.copyWith( fontSize: isSmallScreen(context) ? 18 : 22, ), ), ], ); }, ), FutureDisplay( future: station.delay, builder: (context, delay) { if (delay == 0) return Container(); else if (delay > 0) { return Text( "$delay minute întârziere", style: Theme.of(context).textTheme.body1.copyWith( color: Colors.red, fontSize: 12, fontStyle: FontStyle.italic, ), ); } else if (delay < 0) { return Text( "${-delay} minute mai devreme", style: Theme.of(context).textTheme.body1.copyWith( color: Colors.green, fontSize: 12, fontStyle: FontStyle.italic, ), ); } return Container(); }, ) ], ), ), ); } } class SlimAppBar extends StatelessWidget { final String title; final double size; // final Function onBackTap; SlimAppBar({ @required this.title, this.size = 24, // this.onBackTap, }); @override Widget build(BuildContext context) { return SizedBox( width: double.infinity, height: size, child: Container( color: Theme.of(context).appBarTheme?.color ?? Theme.of(context).primaryColor, child: InkWell( onTap: (ModalRoute.of(context)?.canPop ?? false) ? () => Navigator.of(context).pop() : null, child: Row( mainAxisSize: MainAxisSize.max, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Container( height: size, width: size, child: (ModalRoute.of(context)?.canPop ?? false) ? BackButtonIcon() : null, ), Expanded( child: Center( child: Padding( padding: const EdgeInsets.all(2), child: Text( title, textAlign: TextAlign.center, style: Theme.of(context).appBarTheme.textTheme?.caption?.copyWith(color: Theme.of(context).appBarTheme.textTheme?.body1?.color) ?? Theme.of(context).textTheme.caption.copyWith(color: Theme.of(context).textTheme.body1.color), ), ), ), ), Container( height: size, width: size, ), ], ), ), ), ); } }