You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
944 lines
32 KiB
944 lines
32 KiB
import 'package:info_tren/train_info_page/train_info_animation_helpers.dart'; |
|
import 'package:info_tren/train_info_page/train_info_material_DisplayTrainStation.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<TrainInfoMaterial> 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<ProgressReport>( |
|
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: <Widget>[ |
|
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: <Widget>[ |
|
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: <Widget>[ |
|
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<OnDemandTrainData>( |
|
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<List<String>>( |
|
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: <Widget>[ |
|
if (isSmallScreen(context)) |
|
FutureBuilder<List<String>>( |
|
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: <Widget>[ |
|
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: <Widget>[ |
|
Expanded(child: DisplayTrainNextStop(trainData: snapshot.data,)), |
|
Expanded(child: DisplayTrainDestination(trainData: snapshot.data,)), |
|
], |
|
), |
|
), |
|
), |
|
SliverToBoxAdapter( |
|
child: IntrinsicHeight( |
|
child: Row( |
|
children: <Widget>[ |
|
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<List<String>>( |
|
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<String>( |
|
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: <Widget>[ |
|
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<DateTime>( |
|
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: <Widget>[ |
|
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: <Widget>[ |
|
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: <Widget>[ |
|
FutureDisplay<DateTime>( |
|
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: <Widget>[ |
|
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<DateTime>( |
|
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: <Widget>[ |
|
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: <Widget>[ |
|
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<DateTime>( |
|
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: <Widget>[ |
|
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: <Widget>[ |
|
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: <Widget>[ |
|
Text( |
|
"Durata rutei", |
|
style: Theme.of(context).textTheme.body1.copyWith( |
|
fontSize: isSmallScreen(context) ? 16 : 18, |
|
fontWeight: FontWeight.bold, |
|
), |
|
textAlign: TextAlign.center, |
|
), |
|
FutureDisplay<Duration>( |
|
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<List<OnDemandStation>>( |
|
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 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: <Widget>[ |
|
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, |
|
), |
|
], |
|
), |
|
), |
|
), |
|
); |
|
} |
|
}
|
|
|