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.
1238 lines
40 KiB
1238 lines
40 KiB
import 'package:flutter/cupertino.dart'; |
|
import 'package:info_tren/models/train_data.dart'; |
|
import 'package:info_tren/train_info_page/train_info.dart'; |
|
import 'package:info_tren/train_info_page/train_info_animation_helpers.dart'; |
|
import 'package:info_tren/train_info_page/train_info_constants.dart'; |
|
import 'package:info_tren/utils/stream_list.dart'; |
|
|
|
class TrainInfoCupertino extends StatefulWidget { |
|
final int trainNumber; |
|
|
|
TrainInfoCupertino({@required this.trainNumber}); |
|
|
|
@override |
|
_TrainInfoCupertinoState createState() => _TrainInfoCupertinoState(); |
|
} |
|
|
|
class _TrainInfoCupertinoState extends State<TrainInfoCupertino> 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 _TrainDataCupertinoBefore( |
|
title: title, |
|
lookupResult: lookupResult, |
|
); |
|
} |
|
else { |
|
return _TrainDataCupertinoAfter( |
|
title: title, |
|
); |
|
} |
|
} |
|
} |
|
|
|
class _TrainDataCupertinoBefore extends StatefulWidget { |
|
final String title; |
|
final TrainLookupResult lookupResult; |
|
|
|
_TrainDataCupertinoBefore({ |
|
@required this.title, |
|
@required this.lookupResult, |
|
}); |
|
|
|
@override |
|
__TrainDataCupertinoBeforeState createState() => __TrainDataCupertinoBeforeState(); |
|
} |
|
|
|
class __TrainDataCupertinoBeforeState extends State<_TrainDataCupertinoBefore> { |
|
@override |
|
Widget build(BuildContext context) { |
|
return CupertinoPageScaffold( |
|
navigationBar: CupertinoNavigationBar( |
|
middle: Text(widget.title ?? ""), |
|
), |
|
child: SafeArea( |
|
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>[ |
|
CupertinoActivityIndicator(), |
|
Text( |
|
"Conectare...", |
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
|
fontSize: 18, |
|
fontWeight: FontWeight.bold, |
|
), |
|
), |
|
], |
|
), |
|
); |
|
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: CupertinoTheme.of(context).scaffoldBackgroundColor, |
|
backgroundColor: |
|
widget.lookupResult == TrainLookupResult.FOUND |
|
? BACKGROUND_GREEN |
|
: BACKGROUND_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: CupertinoActivityIndicator() |
|
), |
|
), |
|
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: CupertinoTheme.of(context).textTheme.textStyle.copyWith(fontSize: 20), |
|
), |
|
), |
|
Expanded(child: Container(),), |
|
], |
|
), |
|
), |
|
), |
|
), |
|
], |
|
], |
|
), |
|
); |
|
} |
|
), |
|
), |
|
); |
|
} |
|
} |
|
|
|
class _TrainDataCupertinoAfter extends StatefulWidget { |
|
final String title; |
|
|
|
_TrainDataCupertinoAfter({ |
|
@required this.title, |
|
}); |
|
|
|
@override |
|
__TrainDataCupertinoAfterState createState() => __TrainDataCupertinoAfterState(); |
|
} |
|
|
|
class __TrainDataCupertinoAfterState extends State<_TrainDataCupertinoAfter> { |
|
@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 CupertinoPageScaffold( |
|
navigationBar: CupertinoNavigationBar( |
|
middle: Text(widget.title ?? ""), |
|
), |
|
child: SafeArea( |
|
child: Center( |
|
child: CupertinoActivityIndicator(), |
|
), |
|
), |
|
); |
|
} |
|
|
|
return CupertinoPageScaffold( |
|
navigationBar: CupertinoNavigationBar( |
|
middle: 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 ?? ""); |
|
} |
|
}, |
|
), |
|
), |
|
child: SafeArea( |
|
top: false, |
|
bottom: false, |
|
child: Builder( |
|
builder: (context) { |
|
final topPadding = MediaQuery.of(context).padding.top; |
|
|
|
return CustomScrollView( |
|
slivers: <Widget>[ |
|
SliverToBoxAdapter( |
|
child: Padding( |
|
padding: EdgeInsets.only( |
|
top: topPadding, |
|
), |
|
child: Container(), |
|
), |
|
), |
|
DisplayTrainID(trainData: snapshot.data,), |
|
DisplayTrainOperator(trainData: snapshot.data,), |
|
DisplayTrainRoute(trainData: snapshot.data,), |
|
DisplayTrainDeparture(trainData: snapshot.data,), |
|
SliverToBoxAdapter( |
|
child: CupertinoDivider( |
|
color: FOREGROUND_WHITE, |
|
), |
|
), |
|
DisplayTrainLastInfo(trainData: snapshot.data,), |
|
SliverToBoxAdapter( |
|
child: CupertinoDivider(), |
|
), |
|
SliverToBoxAdapter( |
|
child: IntrinsicHeight( |
|
child: Row( |
|
children: <Widget>[ |
|
Expanded( |
|
child: DisplayTrainNextStop(trainData: snapshot.data,), |
|
), |
|
SizedBox( |
|
height: double.infinity, |
|
child: CupertinoVerticalDivider(), |
|
), |
|
Expanded( |
|
child: DisplayTrainDestination(trainData: snapshot.data,), |
|
) |
|
], |
|
), |
|
), |
|
), |
|
SliverToBoxAdapter( |
|
child: CupertinoDivider(), |
|
), |
|
SliverToBoxAdapter( |
|
child: IntrinsicHeight( |
|
child: Row( |
|
children: <Widget>[ |
|
Expanded( |
|
child: DisplayTrainRouteDuration(trainData: snapshot.data,), |
|
), |
|
SizedBox( |
|
height: double.infinity, |
|
child: CupertinoVerticalDivider(), |
|
), |
|
Expanded( |
|
child: DisplayTrainRouteDistance(trainData: snapshot.data,), |
|
) |
|
], |
|
), |
|
), |
|
), |
|
SliverToBoxAdapter( |
|
child: CupertinoDivider( |
|
color: FOREGROUND_WHITE, |
|
), |
|
), |
|
DisplayTrainStations( |
|
trainData: snapshot.data, |
|
pageLoadFuture: TrainDataWebViewAdapter.of(context).nextLoadFuture, |
|
), |
|
SliverToBoxAdapter( |
|
child: Container( |
|
height: MediaQuery.of(context).viewPadding.bottom, |
|
), |
|
), |
|
], |
|
); |
|
} |
|
), |
|
), |
|
); |
|
}, |
|
); |
|
|
|
// return CupertinoPageScaffold( |
|
// navigationBar: CupertinoNavigationBar( |
|
// middle: Text(title ?? ""), |
|
// ), |
|
// child: SafeArea( |
|
// bottom: false, |
|
// child: FutureBuilder<OnDemandTrainData>( |
|
// future: TrainDataWebViewAdapter.of(context).trainData(onInvalidation: () { |
|
// Navigator.of(context).pop(); |
|
// }), |
|
// builder: (context, snapshot) { |
|
// if (!snapshot.hasData) { |
|
// return Center( |
|
// child: CupertinoActivityIndicator(), |
|
// ); |
|
// } |
|
|
|
// try { |
|
// Future.wait([ |
|
// snapshot.data.rang, |
|
// snapshot.data.trainNumber |
|
// ]).then((values) { |
|
// setState(() { |
|
// title = "Informații despre ${values[0]} ${values[1]}"; |
|
// }); |
|
// }); |
|
|
|
// return CustomScrollView( |
|
// slivers: <Widget>[ |
|
// DisplayTrainID(data: snapshot.data,), |
|
// DisplayTrainOperator(data: snapshot.data,), |
|
// DisplayTrainRoute(data: snapshot.data,), |
|
// DisplayTrainDeparture(data: snapshot.data,), |
|
// SliverToBoxAdapter( |
|
// child: CupertinoDivider( |
|
// color: FOREGROUND_WHITE, |
|
// ), |
|
// ), |
|
// DisplayTrainLastInfo(data: snapshot.data,), |
|
// SliverToBoxAdapter( |
|
// child: CupertinoDivider(), |
|
// ), |
|
// SliverToBoxAdapter( |
|
// child: IntrinsicHeight( |
|
// child: Row( |
|
// children: <Widget>[ |
|
// Expanded( |
|
// child: DisplayTrainNextStop(data: snapshot.data,), |
|
// ), |
|
// SizedBox( |
|
// height: double.infinity, |
|
// child: CupertinoVerticalDivider(), |
|
// ), |
|
// Expanded( |
|
// child: DisplayTrainDestination(data: snapshot.data,), |
|
// ) |
|
// ], |
|
// ), |
|
// ), |
|
// ), |
|
// SliverToBoxAdapter( |
|
// child: CupertinoDivider(), |
|
// ), |
|
// SliverToBoxAdapter( |
|
// child: IntrinsicHeight( |
|
// child: Row( |
|
// children: <Widget>[ |
|
// Expanded( |
|
// child: DisplayTrainRouteDuration(data: snapshot.data,), |
|
// ), |
|
// SizedBox( |
|
// height: double.infinity, |
|
// child: CupertinoVerticalDivider(), |
|
// ), |
|
// Expanded( |
|
// child: DisplayTrainRouteDistance(data: snapshot.data,), |
|
// ) |
|
// ], |
|
// ), |
|
// ), |
|
// ), |
|
// SliverToBoxAdapter( |
|
// child: CupertinoDivider( |
|
// color: FOREGROUND_WHITE, |
|
// ), |
|
// ), |
|
// DisplayTrainStations( |
|
// data: snapshot.data, |
|
// pageLoadFuture: TrainDataWebViewAdapter.of(context).nextLoadFuture, |
|
// ), |
|
// ], |
|
// ); |
|
// } |
|
// on OnDemandInvalidatedException { |
|
// Navigator.of(context).pop(); |
|
// print("Got OnDemandInvalidatedException!"); |
|
// return Container(); |
|
// } |
|
// }, |
|
// ), |
|
// ), |
|
// ); |
|
} |
|
} |
|
|
|
class DisplayTrainID extends StatelessWidget { |
|
final OnDemandTrainData trainData; |
|
DisplayTrainID({@required this.trainData}); |
|
|
|
@override |
|
Widget build(BuildContext context) { |
|
return SliverToBoxAdapter( |
|
child: FutureDisplay( |
|
future: Future.wait([ |
|
trainData.rang, |
|
trainData.trainNumber |
|
]), |
|
builder: (context, datas) { |
|
return Center( |
|
child: Padding( |
|
padding: const EdgeInsets.all(8.0), |
|
child: Text( |
|
"${datas[0]} ${datas[1]}", |
|
style: CupertinoTheme.of(context).textTheme.navLargeTitleTextStyle, |
|
), |
|
), |
|
); |
|
}, |
|
), |
|
); |
|
} |
|
} |
|
|
|
class DisplayTrainRoute extends StatelessWidget { |
|
final OnDemandTrainData trainData; |
|
|
|
DisplayTrainRoute({@required this.trainData}); |
|
|
|
@override |
|
Widget build(BuildContext context) { |
|
return SliverToBoxAdapter( |
|
child: 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: CupertinoTheme.of(context).textTheme.textStyle.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: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
|
fontSize: 16, |
|
), |
|
textAlign: TextAlign.right, |
|
), |
|
), |
|
), |
|
], |
|
); |
|
}, |
|
), |
|
); |
|
} |
|
} |
|
|
|
class DisplayTrainOperator extends StatelessWidget { |
|
final OnDemandTrainData trainData; |
|
|
|
DisplayTrainOperator({@required this.trainData}); |
|
|
|
@override |
|
Widget build(BuildContext context) { |
|
return SliverToBoxAdapter( |
|
child: FutureDisplay( |
|
future: trainData.operator, |
|
builder: (context, operator) { |
|
return Center( |
|
child: Text( |
|
operator, |
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
|
fontSize: 14, |
|
fontStyle: FontStyle.italic, |
|
), |
|
), |
|
); |
|
}, |
|
), |
|
); |
|
} |
|
} |
|
|
|
class DisplayTrainDeparture extends StatelessWidget { |
|
final OnDemandTrainData trainData; |
|
|
|
DisplayTrainDeparture({@required this.trainData}); |
|
|
|
@override |
|
Widget build(BuildContext context) { |
|
return SliverToBoxAdapter( |
|
child: 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: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
|
fontStyle: FontStyle.italic, |
|
fontWeight: FontWeight.w200, |
|
), |
|
textAlign: TextAlign.center, |
|
); |
|
}, |
|
), |
|
), |
|
); |
|
} |
|
} |
|
|
|
class DisplayTrainLastInfo extends StatelessWidget { |
|
final OnDemandTrainData trainData; |
|
|
|
DisplayTrainLastInfo({@required this.trainData}); |
|
|
|
@override |
|
Widget build(BuildContext context) { |
|
return SliverToBoxAdapter( |
|
child: Column( |
|
mainAxisSize: MainAxisSize.min, |
|
children: <Widget>[ |
|
Center( |
|
child: Padding( |
|
padding: const EdgeInsets.all(2), |
|
child: Text( |
|
"Ultima informație", |
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
|
fontSize: 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: CupertinoTheme.of(context).textTheme.textStyle, |
|
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: CupertinoTheme.of(context).textTheme.textStyle, |
|
textAlign: TextAlign.right, |
|
); |
|
}, |
|
), |
|
), |
|
], |
|
), |
|
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, |
|
); |
|
}, |
|
), |
|
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: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
|
fontSize: 14, |
|
color: Color.fromRGBO(200, 30, 15, 1), |
|
), |
|
); |
|
} |
|
else { |
|
return Text( |
|
"${-snapshot.data} minute mai devreme", |
|
style: CupertinoTheme.of(context).textTheme.textStyle.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(); |
|
|
|
return Column( |
|
mainAxisSize: MainAxisSize.min, |
|
children: <Widget>[ |
|
Padding( |
|
padding: const EdgeInsets.all(4), |
|
child: Text( |
|
"Următoarea oprire", |
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
|
fontSize: 20, |
|
fontWeight: FontWeight.bold, |
|
), |
|
textAlign: TextAlign.center, |
|
), |
|
), |
|
CupertinoDivider( |
|
color: Color.fromRGBO(15, 15, 15, 1), |
|
), |
|
FutureDisplay( |
|
future: trainData.nextStop.stationName, |
|
builder: (context, station) { |
|
return Padding( |
|
padding: const EdgeInsets.fromLTRB(4, 0, 4, 0), |
|
child: Text( |
|
station, |
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
|
fontSize: 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: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
|
fontSize: 14, |
|
), |
|
textAlign: TextAlign.center, |
|
), |
|
Text( |
|
"la ${arrival.hour.toString().padLeft(2, '0')}:${arrival.minute.toString().padLeft(2, '0')}", |
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
|
fontSize: 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(); |
|
|
|
return Column( |
|
mainAxisSize: MainAxisSize.min, |
|
children: <Widget>[ |
|
Padding( |
|
padding: const EdgeInsets.all(4), |
|
child: Text( |
|
"Destinația", |
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
|
fontSize: 20, |
|
fontWeight: FontWeight.bold, |
|
), |
|
textAlign: TextAlign.center, |
|
), |
|
), |
|
CupertinoDivider( |
|
color: Color.fromRGBO(15, 15, 15, 1), |
|
), |
|
FutureDisplay( |
|
future: trainData.destination.stationName, |
|
builder: (context, station) { |
|
return Padding( |
|
padding: const EdgeInsets.fromLTRB(4, 0, 4, 0), |
|
child: Text( |
|
station, |
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
|
fontSize: 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: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
|
fontSize: 14, |
|
), |
|
textAlign: TextAlign.center, |
|
), |
|
Text( |
|
"la ${arrival.hour.toString().padLeft(2, '0')}:${arrival.minute.toString().padLeft(2, '0')}", |
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
|
fontSize: 14, |
|
), |
|
textAlign: TextAlign.center, |
|
), |
|
], |
|
); |
|
}, |
|
) |
|
], |
|
); |
|
} |
|
); |
|
} |
|
} |
|
|
|
class DisplayTrainRouteDistance extends StatelessWidget { |
|
final OnDemandTrainData trainData; |
|
|
|
DisplayTrainRouteDistance({@required this.trainData}); |
|
|
|
@override |
|
Widget build(BuildContext context) { |
|
return Column( |
|
mainAxisSize: MainAxisSize.min, |
|
children: <Widget>[ |
|
Text( |
|
"Distanța rutei", |
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
|
fontSize: 18, |
|
fontWeight: FontWeight.bold, |
|
), |
|
textAlign: TextAlign.center, |
|
), |
|
FutureDisplay( |
|
future: trainData.routeDistance, |
|
builder: (context, distance) { |
|
return Text( |
|
"$distance km", |
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
|
fontSize: 16, |
|
), |
|
textAlign: TextAlign.center, |
|
); |
|
}, |
|
), |
|
], |
|
); |
|
} |
|
} |
|
|
|
class DisplayTrainRouteDuration extends StatelessWidget { |
|
final OnDemandTrainData trainData; |
|
|
|
DisplayTrainRouteDuration({@required this.trainData}); |
|
|
|
@override |
|
Widget build(BuildContext context) { |
|
return Column( |
|
mainAxisSize: MainAxisSize.min, |
|
children: <Widget>[ |
|
Text( |
|
"Durata rutei", |
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
|
fontSize: 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: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
|
fontSize: 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) { |
|
if (index.isOdd) { |
|
return CupertinoDivider(); |
|
} |
|
else { |
|
final itemIndex = index ~/ 2; |
|
return IndexedSemantics( |
|
child: DisplayTrainStation( |
|
station: snapshot.data[itemIndex], |
|
), |
|
index: itemIndex, |
|
); |
|
} |
|
}, |
|
childCount: snapshot.data.length * 2 - 1, |
|
addSemanticIndexes: false, |
|
), |
|
); |
|
}, |
|
); |
|
} |
|
} |
|
|
|
class DisplayTrainStation extends StatelessWidget { |
|
final OnDemandStation station; |
|
|
|
DisplayTrainStation({@required this.station}); |
|
|
|
@override |
|
Widget build(BuildContext context) { |
|
return Column( |
|
mainAxisSize: MainAxisSize.min, |
|
crossAxisAlignment: CrossAxisAlignment.center, |
|
children: <Widget>[ |
|
Row( |
|
mainAxisSize: MainAxisSize.max, |
|
children: <Widget>[ |
|
Padding( |
|
padding: const EdgeInsets.all(8), |
|
child: Container( |
|
decoration: BoxDecoration( |
|
borderRadius: BorderRadius.circular(10), |
|
border: Border.all( |
|
width: 2, |
|
color: FOREGROUND_WHITE, |
|
), |
|
// color: CupertinoColors.activeOrange, |
|
), |
|
width: 48, |
|
height: 48, |
|
child: Column( |
|
mainAxisSize: MainAxisSize.min, |
|
children: <Widget>[ |
|
Expanded( |
|
child: Center( |
|
child: FutureDisplay<int>( |
|
future: station.km, |
|
builder: (context, value) { |
|
return Text( |
|
value.toString(), |
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
|
fontSize: 18, |
|
fontWeight: FontWeight.w100, |
|
), |
|
textAlign: TextAlign.center, |
|
); |
|
}, |
|
), |
|
), |
|
), |
|
Text( |
|
"km", |
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(fontSize: 10), |
|
), |
|
], |
|
), |
|
), |
|
), |
|
Expanded( |
|
child: FutureDisplay<List<String>>( |
|
future: Future.wait([ |
|
station.stationName, |
|
station.observations |
|
]), |
|
builder: (context, items) { |
|
return Text( |
|
items[0], |
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
|
fontSize: 22, |
|
fontWeight: FontWeight.w100, |
|
fontStyle: items[1] == "ONI" ? FontStyle.italic : FontStyle.normal, |
|
), |
|
textAlign: TextAlign.center, |
|
); |
|
}, |
|
) |
|
) |
|
], |
|
), |
|
FutureDisplay<List<String>>( |
|
future: Future.wait([ |
|
station.arrivalTime, |
|
station.stopsFor, |
|
station.departureTime |
|
]), |
|
builder: (context, items) { |
|
if (items[0].isEmpty) { |
|
// Plecare |
|
return Row( |
|
crossAxisAlignment: CrossAxisAlignment.center, |
|
children: <Widget>[ |
|
Expanded(child: Container(),), |
|
Text("plecare la ${items[2]}"), |
|
Container(width: 2,), |
|
Text( |
|
"→", |
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
|
fontSize: 22, |
|
), |
|
), |
|
], |
|
); |
|
} |
|
|
|
if (items[2].isEmpty) { |
|
// Sosire |
|
return Row( |
|
crossAxisAlignment: CrossAxisAlignment.center, |
|
children: <Widget>[ |
|
Text( |
|
"→", |
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
|
fontSize: 22, |
|
), |
|
), |
|
Container(width: 2,), |
|
Text("sosire la ${items[0]}"), |
|
Expanded(child: Container(),), |
|
], |
|
); |
|
} |
|
|
|
return Row( |
|
crossAxisAlignment: CrossAxisAlignment.center, |
|
children: <Widget>[ |
|
Text( |
|
"→", |
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
|
fontSize: 22, |
|
), |
|
), |
|
Container(width: 2,), |
|
Text(items[0]), |
|
Expanded(child: Container(),), |
|
Column( |
|
mainAxisSize: MainAxisSize.min, |
|
children: <Widget>[ |
|
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<String>( |
|
future: station.observations, |
|
builder: (context, snapshot) { |
|
if (snapshot.data == "ONI") { |
|
return Text( |
|
"oprire ne-itinerarică", |
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
|
fontStyle: FontStyle.italic, |
|
), |
|
textAlign: TextAlign.center, |
|
); |
|
} |
|
|
|
return Container(); |
|
}, |
|
) |
|
], |
|
), |
|
Expanded(child: Container(),), |
|
Text(items[2]), |
|
Container(width: 2,), |
|
Text( |
|
"→", |
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
|
fontSize: 22, |
|
), |
|
), |
|
], |
|
); |
|
}, |
|
), |
|
FutureDisplay<int>( |
|
future: station.delay, |
|
builder: (context, delay) { |
|
if (delay == 0) return Container(); |
|
|
|
else if (delay > 0) { |
|
return Text( |
|
"$delay minute întârziere", |
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
|
color: CupertinoColors.destructiveRed, |
|
fontSize: 12, |
|
fontStyle: FontStyle.italic, |
|
), |
|
); |
|
} |
|
|
|
else if (delay < 0) { |
|
return Text( |
|
"${-delay} minute mai devreme", |
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
|
color: CupertinoColors.activeGreen, |
|
fontSize: 12, |
|
fontStyle: FontStyle.italic, |
|
), |
|
); |
|
} |
|
|
|
return Container(); |
|
}, |
|
) |
|
], |
|
); |
|
} |
|
} |
|
|
|
class CupertinoDivider extends StatelessWidget { |
|
final Color color; |
|
|
|
CupertinoDivider({Key key, Color color}): |
|
color = color ?? FOREGROUND_DARK_GREY, |
|
super(key: key); |
|
|
|
@override |
|
Widget build(BuildContext context) { |
|
return Column( |
|
mainAxisSize: MainAxisSize.min, |
|
children: <Widget>[ |
|
Container( |
|
height: 1, |
|
), |
|
Container( |
|
height: 1, |
|
decoration: BoxDecoration( |
|
color: color, |
|
), |
|
), |
|
Container( |
|
height: 1, |
|
), |
|
], |
|
); |
|
} |
|
} |
|
|
|
class CupertinoVerticalDivider extends StatelessWidget { |
|
final Color color; |
|
|
|
CupertinoVerticalDivider({Key key, Color color}): |
|
color = color ?? FOREGROUND_DARK_GREY, |
|
super(key: key); |
|
|
|
@override |
|
Widget build(BuildContext context) { |
|
return Row( |
|
mainAxisSize: MainAxisSize.min, |
|
children: <Widget>[ |
|
Container( |
|
width: 1, |
|
), |
|
Container( |
|
width: 1, |
|
decoration: BoxDecoration( |
|
color: color, |
|
), |
|
), |
|
Container( |
|
width: 1, |
|
), |
|
], |
|
); |
|
} |
|
} |