1238 lines
No EOL
40 KiB
Dart
1238 lines
No EOL
40 KiB
Dart
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,
|
|
),
|
|
],
|
|
);
|
|
}
|
|
} |