Browse Source

Moved to api v2

tmp v2.4.0
Dan Cojocaru 3 years ago
parent
commit
44d229f0f6
Signed by: kbruen
GPG Key ID: 818A889458EDC937
  1. 18
      .vscode/launch.json
  2. 4
      CHANGELOG.TXT
  3. 2
      lib/api/train_data.dart
  4. 2
      lib/components/slim_app_bar.dart
  5. 6
      lib/pages/train_info_page/view_train/train_info.dart
  6. 662
      lib/pages/train_info_page/view_train/train_info_cupertino.dart
  7. 70
      lib/pages/train_info_page/view_train/train_info_cupertino_DisplayTrainStation.dart
  8. 221
      lib/pages/train_info_page/view_train/train_info_material.dart
  9. 66
      lib/pages/train_info_page/view_train/train_info_material_DisplayTrainStation.dart
  10. 2
      pubspec.yaml

18
.vscode/launch.json vendored

@ -26,12 +26,28 @@
"request": "launch",
"type": "dart",
"deviceId": "iphone"
},
{
"name": "macOS",
"request": "launch",
"type": "dart",
"deviceId": "macOS"
},
{
"name": "Samsung",
"request": "launch",
"type": "dart",
"deviceId": "SM"
}
],
"compounds": [
{
"name": "All Devices",
"configurations": ["Android Emulator", "iPhone"]
"configurations": ["Android Emulator", "iPhone", "macOS"]
},
{
"name": "Mac + Samsung",
"configurations": ["macOS", "Samsung"]
}
]
}

4
CHANGELOG.TXT

@ -1,3 +1,7 @@
v2.4.0
Moved to api v2
Added support for any train number, including train numbers starting with 0
v2.3.1
Fixed badge background when arrival is known but not departure

2
lib/api/train_data.dart

@ -4,6 +4,6 @@ import 'package:info_tren/models/train_data.dart';
const AUTHORITY = 'scraper.infotren.dcdevelop.xyz';
Future<TrainData> getTrain(String trainNumber) async {
final response = await http.get(Uri.https(AUTHORITY, 'train/$trainNumber'));
final response = await http.get(Uri.https(AUTHORITY, 'v2/train/$trainNumber'));
return trainDataFromJson(response.body);
}

2
lib/components/slim_app_bar.dart

@ -18,7 +18,7 @@ class SlimAppBar extends StatelessWidget {
height: size,
child: Container(
color:
Theme.of(context).appBarTheme.color ??
Theme.of(context).appBarTheme.backgroundColor ??
Theme.of(context).primaryColor,
child: InkWell(
onTap: (ModalRoute.of(context)?.canPop ?? false)

6
lib/pages/train_info_page/view_train/train_info.dart

@ -30,7 +30,7 @@ class TrainInfo extends StatelessWidget {
switch (uiDesign) {
case UiDesign.MATERIAL:
if ([RefreshFutureBuilderState.none, RefreshFutureBuilderState.waiting].contains(snapshot.state)) {
return TrainInfoLoadingMaterial(title: trainNumber.toString(),);
return TrainInfoLoadingMaterial(title: trainNumber.toString(), loadingText: "Se încarcă...",);
}
else if (snapshot.state == RefreshFutureBuilderState.error) {
return TrainInfoErrorMaterial(title: '$trainNumber - Error', error: snapshot.error!, refresh: refresh,);
@ -39,13 +39,13 @@ class TrainInfo extends StatelessWidget {
return TrainInfoMaterial(trainData: snapshot.data!, refresh: refresh,);
case UiDesign.CUPERTINO:
if ([RefreshFutureBuilderState.none, RefreshFutureBuilderState.waiting].contains(snapshot.state)) {
return TrainInfoLoadingCupertino(title: trainNumber.toString(),);
return TrainInfoLoadingCupertino(title: trainNumber.toString(), loadingText: "Se încarcă...",);
}
else if (snapshot.state == RefreshFutureBuilderState.error) {
return TrainInfoErrorCupertino(title: '$trainNumber - Error', error: snapshot.error!, refresh: refresh,);
}
return TrainInfoCupertino(trainData: snapshot.data!, refresh: refresh,);
return TrainInfoCupertino(trainData: snapshot.data!, refresh: refresh, isRefreshing: snapshot.state == RefreshFutureBuilderState.refreshing,);
default:
throw UnmatchedUiDesignException(uiDesign);
}

662
lib/pages/train_info_page/view_train/train_info_cupertino.dart

@ -11,7 +11,11 @@ import 'package:info_tren/pages/train_info_page/view_train/train_info_cupertino_
import 'package:info_tren/utils/state_to_string.dart';
class TrainInfoLoadingCupertino extends TrainInfoLoading {
TrainInfoLoadingCupertino({required String title, String? loadingText}) : super(title: title, loadingText: loadingText, uiDesign: UiDesign.CUPERTINO);
TrainInfoLoadingCupertino({required String title, String? loadingText})
: super(
title: title,
loadingText: loadingText,
uiDesign: UiDesign.CUPERTINO);
@override
Widget build(BuildContext context) {
@ -28,10 +32,14 @@ class TrainInfoLoadingCupertino extends TrainInfoLoading {
class TrainInfoErrorCupertino extends TrainInfoError {
TrainInfoErrorCupertino({
required Object error,
required Object error,
required String title,
Future Function()? refresh,
}) : super(error: error, title: title, refresh: refresh,);
}) : super(
error: error,
title: title,
refresh: refresh,
);
@override
Widget build(BuildContext context) {
@ -62,174 +70,210 @@ class TrainInfoErrorCupertino extends TrainInfoError {
class TrainInfoCupertino extends StatelessWidget {
final TrainData trainData;
final Future Function()? refresh;
final bool? isRefreshing;
TrainInfoCupertino({required this.trainData, this.refresh,});
TrainInfoCupertino({
required this.trainData,
this.refresh,
this.isRefreshing,
});
@override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text("Informații despre ${trainData.rank} ${trainData.number}"),
),
child: SafeArea(
top: false,
bottom: false,
child: Builder(
builder: (context) {
final topPadding = MediaQuery.of(context).padding.top;
return NestedScrollView(
headerSliverBuilder: (context, innerBoxIsScrolled) {
return [
// SliverPadding(
// padding: EdgeInsets.only(
// top: topPadding,
// ),
// ),
SliverPersistentHeaderPadding(maxHeight: topPadding,)
];
},
body: Builder(
builder: (context) {
return CustomScrollView(
slivers: <Widget>[
if (refresh != null)
CupertinoSliverRefreshControl(
builder: (context, mode, pulledExtent, refreshTriggerPullDistance, refreshIndicatorExtent) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
height: pulledExtent,
child: Column(
children: [
Container(
height: min(refreshIndicatorExtent, pulledExtent),
child: Center(
child: Builder(
builder: (context) {
if (mode == RefreshIndicatorMode.inactive) {
return Container();
}
else if (mode == RefreshIndicatorMode.done) {
return Text('Refreshed!');
}
else if (mode == RefreshIndicatorMode.drag) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
CupertinoActivityIndicator(animating: false,),
Text('Pull to refresh...'),
],
);
}
else if (mode == RefreshIndicatorMode.armed) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
CupertinoActivityIndicator(animating: false,),
Text('Release to refresh...'),
],
);
}
else {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
CupertinoActivityIndicator(),
Text('Refreshing'),
],
);
}
},
),
),
),
Expanded(child: Container(),),
],
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text("Informații despre ${trainData.rank} ${trainData.number}"),
trailing: refresh == null ? null : isRefreshing == true ? CupertinoActivityIndicator() : CupertinoButton(
padding: const EdgeInsets.all(0),
alignment: Alignment.center,
child: Icon(CupertinoIcons.refresh),
onPressed: () => refresh!(),
),
),
child: SafeArea(
top: false,
bottom: false,
child: Builder(builder: (context) {
final topPadding = MediaQuery.of(context).padding.top;
return NestedScrollView(
headerSliverBuilder: (context, innerBoxIsScrolled) {
return [
// SliverPadding(
// padding: EdgeInsets.only(
// top: topPadding,
// ),
// ),
SliverPersistentHeaderPadding(
maxHeight: topPadding,
)
];
},
body: Builder(builder: (context) {
return CustomScrollView(
slivers: <Widget>[
if (refresh != null)
CupertinoSliverRefreshControl(
builder: (context, mode, pulledExtent,
refreshTriggerPullDistance, refreshIndicatorExtent) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
height: pulledExtent,
child: Column(
children: [
Container(
height: min(
refreshIndicatorExtent, pulledExtent),
child: Center(
child: Builder(
builder: (context) {
if (mode ==
RefreshIndicatorMode.inactive) {
return Container();
} else if (mode ==
RefreshIndicatorMode.done) {
return Text('Refreshed!');
} else if (mode ==
RefreshIndicatorMode.drag) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
CupertinoActivityIndicator(
animating: false,
),
Text('Pull to refresh...'),
],
);
} else if (mode ==
RefreshIndicatorMode.armed) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
CupertinoActivityIndicator(
animating: false,
),
Text('Release to refresh...'),
],
);
} else {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
CupertinoActivityIndicator(),
Text('Refreshing'),
],
);
}
},
),
),
],
);
},
onRefresh: refresh,
),
DisplayTrainID(trainData: trainData,),
DisplayTrainOperator(trainData: trainData,),
DisplayTrainRoute(trainData: trainData,),
DisplayTrainDeparture(trainData: trainData,),
SliverToBoxAdapter(
child: CupertinoDivider(
color: FOREGROUND_WHITE,
),
),
DisplayTrainLastInfo(trainData: trainData,),
SliverToBoxAdapter(
child: CupertinoDivider(),
),
SliverToBoxAdapter(
child: IntrinsicHeight(
child: Row(
children: <Widget>[
// Expanded(
// child: DisplayTrainNextStop(trainData: trainData,),
// ),
Expanded(
child: DisplayTrainDestination(trainData: trainData,),
),
SizedBox(
height: double.infinity,
child: CupertinoVerticalDivider(),
Expanded(
child: Container(),
),
Expanded(child: DisplayTrainRouteDistance(trainData: trainData,),),
],
),
),
),
// SliverToBoxAdapter(
// child: CupertinoDivider(),
// ),
// SliverToBoxAdapter(
// child: IntrinsicHeight(
// child: Row(
// children: <Widget>[
// // Expanded(
// // child: DisplayTrainRouteDuration(trainData: trainData,),
// // ),
// Expanded(child: Container(),),
// SizedBox(
// height: double.infinity,
// child: CupertinoVerticalDivider(),
// ),
// Expanded(
// child: DisplayTrainRouteDistance(trainData: trainData,),
// )
// ],
// ),
// ),
],
);
},
onRefresh: refresh,
),
DisplayTrainID(
trainData: trainData,
),
DisplayTrainOperator(
trainData: trainData,
),
DisplayTrainRoute(
trainData: trainData,
),
DisplayTrainDeparture(
trainData: trainData,
),
SliverToBoxAdapter(
child: CupertinoDivider(
color: FOREGROUND_WHITE,
),
),
DisplayTrainLastInfo(
trainData: trainData,
),
SliverToBoxAdapter(
child: CupertinoDivider(),
),
SliverToBoxAdapter(
child: IntrinsicHeight(
child: Row(
children: <Widget>[
// Expanded(
// child: DisplayTrainNextStop(trainData: trainData,),
// ),
SliverToBoxAdapter(
child: CupertinoDivider(
color: FOREGROUND_WHITE,
Expanded(
child: DisplayTrainRouteDuration(
trainData: trainData,
),
),
DisplayTrainStations(
trainData: trainData,
// Expanded(
// child: DisplayTrainDestination(trainData: trainData,),
// ),
SizedBox(
height: double.infinity,
child: CupertinoVerticalDivider(),
),
SliverToBoxAdapter(
child: Container(
height: MediaQuery.of(context).viewPadding.bottom,
Expanded(
child: DisplayTrainRouteDistance(
trainData: trainData,
),
),
],
);
}
),
),
),
);
}
),
),
);
// SliverToBoxAdapter(
// child: CupertinoDivider(),
// ),
// SliverToBoxAdapter(
// child: IntrinsicHeight(
// child: Row(
// children: <Widget>[
// // Expanded(
// // child: DisplayTrainRouteDuration(trainData: trainData,),
// // ),
// Expanded(child: Container(),),
// SizedBox(
// height: double.infinity,
// child: CupertinoVerticalDivider(),
// ),
// Expanded(
// child: DisplayTrainRouteDistance(trainData: trainData,),
// )
// ],
// ),
// ),
// ),
SliverToBoxAdapter(
child: CupertinoDivider(
color: FOREGROUND_WHITE,
),
),
DisplayTrainStations(
trainData: trainData,
),
SliverToBoxAdapter(
child: Container(
height: MediaQuery.of(context).viewPadding.bottom,
),
),
],
);
}),
);
}),
),
);
// return CupertinoPageScaffold(
// navigationBar: CupertinoNavigationBar(
@ -343,11 +387,22 @@ class DisplayTrainID extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SliverToBoxAdapter(
child: Center(
child: Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"${trainData.rank} ${trainData.number}",
child: Text.rich(
TextSpan(
children: [
TextSpan(
text: trainData.rank,
style: TextStyle(
color: trainData.rank.startsWith('IR') ? Color.fromARGB(255, 255, 0, 0) : null,
),
),
TextSpan(text: ' '),
TextSpan(text: trainData.number,),
],
),
style: CupertinoTheme.of(context).textTheme.navLargeTitleTextStyle,
),
),
@ -364,31 +419,35 @@ class DisplayTrainRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SliverToBoxAdapter(
child: Row(
child: Row(
children: <Widget>[
Center(
child: Padding(
padding: const EdgeInsets.all(4),
child: Text(
trainData.route.from,
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 16,
Expanded(
child: Center(
child: Padding(
padding: const EdgeInsets.all(4),
child: Text(
trainData.route.from,
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(
trainData.route.to,
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 16,
Expanded(
child: Center(
child: Padding(
padding: const EdgeInsets.all(4),
child: Text(
trainData.route.to,
style:
CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 16,
),
textAlign: TextAlign.right,
),
textAlign: TextAlign.right,
),
),
),
@ -410,9 +469,9 @@ class DisplayTrainOperator extends StatelessWidget {
child: Text(
trainData.operator,
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 14,
fontStyle: FontStyle.italic,
),
fontSize: 14,
fontStyle: FontStyle.italic,
),
),
),
);
@ -433,9 +492,9 @@ class DisplayTrainDeparture extends StatelessWidget {
// "Plecare în ${dataPlecare.day.toString().padLeft(2, '0')}.${dataPlecare.month.toString().padLeft(2, '0')}.${dataPlecare.year.toString().padLeft(4, '0')}",
"Plecare în ${trainData.date}",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontStyle: FontStyle.italic,
fontWeight: FontWeight.w200,
),
fontStyle: FontStyle.italic,
fontWeight: FontWeight.w200,
),
textAlign: TextAlign.center,
),
),
@ -451,7 +510,9 @@ class DisplayTrainLastInfo extends StatelessWidget {
@override
Widget build(BuildContext context) {
if (trainData.status == null) {
return SliverToBoxAdapter(child: Container(),);
return SliverToBoxAdapter(
child: Container(),
);
}
return SliverToBoxAdapter(
@ -464,9 +525,9 @@ class DisplayTrainLastInfo extends StatelessWidget {
child: Text(
"Ultima informație",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 20,
fontWeight: FontWeight.bold,
),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
),
@ -480,10 +541,12 @@ class DisplayTrainLastInfo extends StatelessWidget {
textAlign: TextAlign.left,
),
),
Expanded(child: Container(),),
Expanded(
child: Container(),
),
Padding(
padding: const EdgeInsets.all(4),
child: Text(
child: Text(
stateToString(trainData.status!.state),
style: CupertinoTheme.of(context).textTheme.textStyle,
textAlign: TextAlign.right,
@ -510,20 +573,21 @@ class DisplayTrainLastInfo extends StatelessWidget {
if (data > 0) {
return Text(
"$data minute întârziere",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 14,
color: CupertinoColors.destructiveRed,
),
"$data ${data == 1 ? 'minut' : 'minute'} întârziere",
style:
CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 14,
color: CupertinoColors.destructiveRed,
),
);
}
else {
} else {
return Text(
"${-data} minute mai devreme",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 12,
color: CupertinoColors.activeGreen,
),
"${-data} ${data == -1 ? 'minut' : 'minute'} mai devreme",
style:
CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 12,
color: CupertinoColors.activeGreen,
),
);
}
},
@ -545,7 +609,7 @@ class DisplayTrainLastInfo extends StatelessWidget {
// future: trainData.nextStop.stationName,
// builder: (context, snapshot) {
// if (!snapshot.hasData) return Container();
//
//
// return Column(
// mainAxisSize: MainAxisSize.min,
// children: <Widget>[
@ -627,9 +691,9 @@ class DisplayTrainDestination extends StatelessWidget {
child: Text(
"Destinația",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 20,
fontWeight: FontWeight.bold,
),
fontSize: 20,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
),
@ -641,20 +705,22 @@ class DisplayTrainDestination extends StatelessWidget {
child: Text(
trainData.stations.last.name,
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 18,
fontWeight: FontWeight.w500,
),
fontSize: 18,
fontWeight: FontWeight.w500,
),
textAlign: TextAlign.center,
),
),
Builder(
builder: (context) {
final arrival = trainData.stations.last.arrival!.scheduleTime;
final arrival =
DateTime.parse(trainData.stations.last.arrival!.scheduleTime);
final delay = trainData.stations.last.arrival!.status?.delay ?? 0;
final parts = arrival.split(':');
final arrivalDT = DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day, int.parse(parts[0]), int.parse(parts[1]));
final arrivalWithDelay = arrivalDT.add(Duration(minutes: delay));
final arrivalWithDelayString = '${arrivalWithDelay.hour}:${arrivalWithDelay.minute.toString().padLeft(2, "0")}';
// final parts = arrival.split(':');
// final arrivalDT = DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day, int.parse(parts[0]), int.parse(parts[1]));
final arrivalWithDelay = arrival.add(Duration(minutes: delay));
final arrivalWithDelayString =
'${arrivalWithDelay.hour}:${arrivalWithDelay.minute.toString().padLeft(2, "0")}';
// const months = ["ian", "feb", "mar", "apr", "mai", "iun", "iul", "aug", "sep", "oct", "noi", "dec"];
return Column(
@ -673,26 +739,32 @@ class DisplayTrainDestination extends StatelessWidget {
children: [
TextSpan(text: ' '),
TextSpan(
text: '$arrival',
style: delay == 0 ? null : TextStyle(
decoration: TextDecoration.lineThrough,
),
text:
'${arrival.hour.toString().padLeft(2, "0")}:${arrival.minute.toString().padLeft(2, "0")}',
style: delay == 0
? null
: TextStyle(
decoration: TextDecoration.lineThrough,
),
),
if (delay != 0) ...[
TextSpan(text: ' '),
TextSpan(
text: '$arrivalWithDelayString',
style: TextStyle(
color: delay > 0 ? CupertinoColors.destructiveRed : CupertinoColors.activeGreen,
color: delay > 0
? CupertinoColors.destructiveRed
: CupertinoColors.activeGreen,
),
),
]
],
),
// "la ${arrival.hour.toString().padLeft(2, '0')}:${arrival.minute.toString().padLeft(2, '0')}",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 14,
),
style:
CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 14,
),
textAlign: TextAlign.center,
),
],
@ -717,16 +789,16 @@ class DisplayTrainRouteDistance extends StatelessWidget {
Text(
"Distanța rutei",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 18,
fontWeight: FontWeight.bold,
),
fontSize: 18,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
Text(
"${trainData.stations.last.km} km",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 16,
),
fontSize: 16,
),
textAlign: TextAlign.center,
),
],
@ -734,76 +806,87 @@ class DisplayTrainRouteDistance extends StatelessWidget {
}
}
// class DisplayTrainRouteDuration extends StatelessWidget {
// final TrainData 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 DisplayTrainRouteDuration extends StatelessWidget {
final TrainData 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,
),
Builder(
builder: (context) {
var duration =
DateTime.parse(trainData.stations.last.arrival!.scheduleTime)
.difference(DateTime.parse(
trainData.stations.first.departure!.scheduleTime));
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 TrainData trainData;
DisplayTrainStations({required this.trainData,});
DisplayTrainStations({
required this.trainData,
});
@override
Widget build(BuildContext context) {
@ -812,8 +895,7 @@ class DisplayTrainStations extends StatelessWidget {
(context, index) {
if (index.isOdd) {
return CupertinoDivider();
}
else {
} else {
final itemIndex = index ~/ 2;
return IndexedSemantics(
child: DisplayTrainStation(

70
lib/pages/train_info_page/view_train/train_info_cupertino_DisplayTrainStation.dart

@ -43,8 +43,9 @@ class DisplayTrainStation extends StatelessWidget {
final isOnTime = delay <= 0 && real == true;
final isNotScheduled = false;
return KmBadge(
station: station,
return Badge(
text: station.km.toString(),
caption: 'km',
isNotScheduled: isNotScheduled,
isDelayed: isDelayed,
isOnTime: isOnTime,
@ -55,7 +56,11 @@ class DisplayTrainStation extends StatelessWidget {
child: Title(
station: station,
),
)
),
if (station.platform == null)
Container(width: 48, height: 48,)
else
Badge(text: station.platform!, caption: 'linia'),
],
),
Time(
@ -69,14 +74,16 @@ class DisplayTrainStation extends StatelessWidget {
}
}
class KmBadge extends StatelessWidget {
final Station station;
class Badge extends StatelessWidget {
final String text;
final String caption;
final bool isNotScheduled;
final bool isOnTime;
final bool isDelayed;
KmBadge({
required this.station,
Badge({
required this.text,
required this.caption,
this.isNotScheduled = false,
this.isOnTime = false,
this.isDelayed = false,
@ -120,7 +127,7 @@ class KmBadge extends StatelessWidget {
Expanded(
child: Center(
child: Text(
station.km.toString(),
text,
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 20,
fontWeight: MediaQuery.of(context).boldText ? FontWeight.w400 : FontWeight.w200,
@ -131,9 +138,9 @@ class KmBadge extends StatelessWidget {
),
),
Text(
"km",
caption,
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 10,
fontSize: 12,
color: MediaQuery.of(context).boldText ? FOREGROUND_WHITE : foregroundColor,
),
),
@ -247,16 +254,13 @@ class ArrivalTime extends StatelessWidget {
}
else {
final delay = station.arrival!.status?.delay ?? 0;
final time = station.arrival!.scheduleTime;
final time = DateTime.parse(station.arrival!.scheduleTime);
if (delay == 0) {
return Text("$time");
return Text("${time.hour.toString().padLeft(2, "0")}:${time.minute.toString().padLeft(2, "0")}");
}
else if (delay > 0) {
final splits = time.split(":").map((s) => int.parse(s)).toList();
final now = DateTime.now();
final oldDate = DateTime(now.year, now.month, now.day, splits[0], splits[1]);
final oldDate = time;
final newDate = oldDate.add(Duration(minutes: delay));
return Column(
@ -278,10 +282,7 @@ class ArrivalTime extends StatelessWidget {
);
}
else {
final splits = time.split(":").map((s) => int.parse(s)).toList();
final now = DateTime.now();
final oldDate = DateTime(now.year, now.month, now.day, splits[0], splits[1]);
final oldDate = time;
final newDate = oldDate.add(Duration(minutes: delay));
return Column(
@ -326,21 +327,26 @@ class StopTime extends StatelessWidget {
Builder(
builder: (context) {
int stopsForInt = stopsFor;
bool minutes = false;
if (stopsForInt >= 60) {
stopsForInt ~/= 60;
minutes = true;
}
if (stopsForInt == 1) {
return Text(
"1 minut",
minutes ? '1 minut' : '1 secundă',
textAlign: TextAlign.center,
);
}
else if (stopsForInt < 20) {
return Text(
"$stopsFor minute",
'$stopsForInt ' + (minutes ? 'minute' : 'seconde'),
textAlign: TextAlign.center,
);
}
else {
return Text(
"$stopsFor de minute",
'$stopsForInt de ' + (minutes ? 'minute' : 'secunde'),
textAlign: TextAlign.center,
);
}
@ -381,16 +387,13 @@ class DepartureTime extends StatelessWidget {
}
else {
final delay = station.departure!.status?.delay ?? 0;
final time = station.departure!.scheduleTime;
final time = DateTime.parse(station.departure!.scheduleTime);
if (delay == 0) {
return Text("$time");
return Text("${time.hour.toString().padLeft(2, "0")}:${time.minute.toString().padLeft(2, "0")}");
}
else if (delay > 0) {
final splits = time.split(":").map((s) => int.parse(s)).toList();
final now = DateTime.now();
final oldDate = DateTime(now.year, now.month, now.day, splits[0], splits[1]);
final oldDate = time;
final newDate = oldDate.add(Duration(minutes: delay));
return Column(
@ -412,10 +415,7 @@ class DepartureTime extends StatelessWidget {
);
}
else {
final splits = time.split(":").map((s) => int.parse(s)).toList();
final now = DateTime.now();
final oldDate = DateTime(now.year, now.month, now.day, splits[0], splits[1]);
final oldDate = time;
final newDate = oldDate.add(Duration(minutes: delay));
return Column(
@ -460,7 +460,7 @@ class Delay extends StatelessWidget {
if (delay == 0 || delay == null) return Container();
else if (delay > 0) {
return Text(
"$delay minute întârziere",
"$delay ${delay == 1 ? 'minut' : 'minute'} întârziere",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
color: CupertinoColors.destructiveRed,
fontSize: 14,
@ -470,7 +470,7 @@ class Delay extends StatelessWidget {
}
else if (delay < 0) {
return Text(
"${-delay} minute mai devreme",
"${-delay} ${delay == -1 ? 'minut' : 'minute'} mai devreme",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
color: CupertinoColors.activeGreen,
fontSize: 14,

221
lib/pages/train_info_page/view_train/train_info_material.dart

@ -75,12 +75,18 @@ class TrainInfoMaterial extends StatelessWidget {
body: Column(
children: <Widget>[
if (isSmallScreen(context))
SlimAppBar(
title: 'INFO TREN - ${trainData.rank} ${trainData.number}'
SafeArea(
bottom: false,
left: false,
right: false,
child: SlimAppBar(
title: 'INFO TREN - ${trainData.rank} ${trainData.number}'
),
),
Expanded(
child: SafeArea(
bottom: false,
top: isSmallScreen(context) ? false : true,
child: RefreshIndicator(
onRefresh: refresh ?? () async {},
child: CustomScrollView(
@ -114,7 +120,8 @@ class TrainInfoMaterial extends StatelessWidget {
child: Row(
children: <Widget>[
// Expanded(child: DisplayTrainNextStop(trainData: trainData,)),
Expanded(child: DisplayTrainDestination(trainData: trainData,)),
// Expanded(child: DisplayTrainDestination(trainData: trainData,)),
Expanded(child: DisplayTrainRouteDuration(trainData: trainData,)),
Expanded(child: DisplayTrainRouteDistance(trainData: trainData,),),
],
),
@ -165,8 +172,19 @@ class DisplayTrainID extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Text(
"${trainData.rank} ${trainData.number}",
return Text.rich(
TextSpan(
children: [
TextSpan(
text: trainData.rank,
style: TextStyle(
color: trainData.rank.startsWith('IR') ? Color.fromARGB(255, 255, 0, 0) : null,
),
),
TextSpan(text: ' '),
TextSpan(text: trainData.number,),
],
),
style: (isSmallScreen(context)
? Theme.of(context).textTheme.headline4
: Theme.of(context).textTheme.headline3)?.copyWith(
@ -205,29 +223,31 @@ class DisplayTrainRoute extends StatelessWidget {
Widget build(BuildContext context) {
return Row(
children: <Widget>[
Center(
child: Padding(
padding: const EdgeInsets.all(4),
child: Text(
trainData.route.from,
style: Theme.of(context).textTheme.bodyText2?.copyWith(
fontSize: 16,
Expanded(
child: Center(
child: Padding(
padding: const EdgeInsets.all(4),
child: Text(
trainData.route.from,
style: Theme.of(context).textTheme.bodyText2?.copyWith(
fontSize: 16,
),
),
),
),
),
Expanded(child: Container(),),
Center(child: Text("-")),
Expanded(child: Container(),),
Center(
child: Padding(
padding: const EdgeInsets.all(4),
child: Text(
trainData.route.to,
style: Theme.of(context).textTheme.bodyText2?.copyWith(
fontSize: 16,
Expanded(
child: Center(
child: Padding(
padding: const EdgeInsets.all(4),
child: Text(
trainData.route.to,
style: Theme.of(context).textTheme.bodyText2?.copyWith(
fontSize: 16,
),
textAlign: TextAlign.right,
),
textAlign: TextAlign.right,
),
),
),
@ -336,7 +356,7 @@ class DisplayTrainLastInfo extends StatelessWidget {
if (data > 0) {
return Text(
"$data minute întârziere",
"$data ${data == 1 ? 'minut' : 'minute'} întârziere",
style: Theme.of(context).textTheme.bodyText2?.copyWith(
fontSize: isSmallScreen(context) ? 14 : 16,
color: Colors.red.shade300,
@ -345,7 +365,7 @@ class DisplayTrainLastInfo extends StatelessWidget {
}
else {
return Text(
"${-data} minute mai devreme",
"${-data} ${data == -1 ? 'minut' : 'minute'} mai devreme",
style: Theme.of(context).textTheme.bodyText2?.copyWith(
fontSize: isSmallScreen(context) ? 14 : 16,
color: Colors.green.shade300,
@ -486,11 +506,9 @@ class DisplayTrainDestination extends StatelessWidget {
),
Builder(
builder: (context) {
final arrival = destination.arrival!.scheduleTime;
final arrival = DateTime.parse(destination.arrival!.scheduleTime);
final delay = trainData.stations.last.arrival!.status?.delay ?? 0;
final parts = arrival.split(':');
final arrivalDT = DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day, int.parse(parts[0]), int.parse(parts[1]));
final arrivalWithDelay = arrivalDT.add(Duration(minutes: delay));
final arrivalWithDelay = arrival.add(Duration(minutes: delay));
final arrivalWithDelayString = '${arrivalWithDelay.hour}:${arrivalWithDelay.minute.toString().padLeft(2, "0")}';
// const months = ["ian", "feb", "mar", "apr", "mai", "iun", "iul", "aug", "sep", "oct", "noi", "dec"];
@ -511,7 +529,7 @@ class DisplayTrainDestination extends StatelessWidget {
children: [
TextSpan(text: ' '),
TextSpan(
text: '$arrival',
text: '${arrival.hour.toString().padLeft(2, '0')}:${arrival.minute.toString().padLeft(2, '0')}',
style: delay == 0 ? null : TextStyle(
decoration: TextDecoration.lineThrough,
),
@ -581,82 +599,81 @@ class DisplayTrainRouteDistance extends StatelessWidget {
}
}
// class DisplayTrainRouteDuration extends StatelessWidget {
// final TrainData 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.bodyText2?.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.bodyText2?.copyWith(
// fontSize: isSmallScreen(context) ? 14 : 16,
// ),
// textAlign: TextAlign.center,
// );
// },
// ),
// ],
// ),
// ),
// ),
// );
// }
// }
class DisplayTrainRouteDuration extends StatelessWidget {
final TrainData 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.bodyText2?.copyWith(
fontSize: isSmallScreen(context) ? 20 : 22,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
Builder(
builder: (context) {
var duration = DateTime.parse(trainData.stations.last.arrival!.scheduleTime).difference(DateTime.parse(trainData.stations.first.departure!.scheduleTime));
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.bodyText2?.copyWith(
fontSize: isSmallScreen(context) ? 18 : 20,
),
textAlign: TextAlign.center,
);
},
),
],
),
),
),
);
}
}
class DisplayTrainStations extends StatelessWidget {
final TrainData trainData;
DisplayTrainStations({required this.trainData});
@override

66
lib/pages/train_info_page/view_train/train_info_material_DisplayTrainStation.dart

@ -46,8 +46,9 @@ class DisplayTrainStation extends StatelessWidget {
final isOnTime = delay <= 0 && real == true;
final isNotScheduled = false;
return KmBadge(
station: station,
return Badge(
text: station.km.toString(),
caption: 'km',
isNotScheduled: isNotScheduled,
isDelayed: isDelayed,
isOnTime: isOnTime,
@ -59,6 +60,10 @@ class DisplayTrainStation extends StatelessWidget {
station: station,
),
),
if (station.platform == null)
Container(width: isSmallScreen(context) ? 42 : 48, height: isSmallScreen(context) ? 42 : 48,)
else
Badge(text: station.platform!, caption: 'linia',),
],
),
Time(
@ -74,14 +79,16 @@ class DisplayTrainStation extends StatelessWidget {
}
}
class KmBadge extends StatelessWidget {
final Station station;
class Badge extends StatelessWidget {
final String text;
final String caption;
final bool isNotScheduled;
final bool isOnTime;
final bool isDelayed;
KmBadge({
required this.station,
Badge({
required this.text,
required this.caption,
this.isNotScheduled = false,
this.isOnTime = false,
this.isDelayed = false,
@ -124,7 +131,7 @@ class KmBadge extends StatelessWidget {
Expanded(
child: Center(
child: Text(
station.km.toString(),
text,
style: Theme.of(context).textTheme.bodyText2?.copyWith(
fontSize: isSmallScreen(context) ? 16 : 20,
fontWeight: MediaQuery.of(context).boldText ? FontWeight.w400 : FontWeight.w200,
@ -135,7 +142,7 @@ class KmBadge extends StatelessWidget {
),
),
Text(
"km",
caption,
style: Theme.of(context).textTheme.bodyText2?.copyWith(
fontSize: 10,
color: MediaQuery.of(context).boldText ? Colors.white70 : foregroundColor,
@ -254,16 +261,13 @@ class ArrivalTime extends StatelessWidget {
}
else {
final delay = station.arrival!.status?.delay ?? 0;
final time = station.arrival!.scheduleTime;
final time = DateTime.parse(station.arrival!.scheduleTime);
if (delay == 0) {
return Text("$time");
return Text("${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}");
}
else if (delay > 0) {
final splits = time.split(":").map((s) => int.parse(s)).toList();
final now = DateTime.now();
final oldDate = DateTime(now.year, now.month, now.day, splits[0], splits[1]);
final oldDate = time;
final newDate = oldDate.add(Duration(minutes: delay));
return Column(
@ -285,10 +289,7 @@ class ArrivalTime extends StatelessWidget {
);
}
else {
final splits = time.split(":").map((s) => int.parse(s)).toList();
final now = DateTime.now();
final oldDate = DateTime(now.year, now.month, now.day, splits[0], splits[1]);
final oldDate = time;
final newDate = oldDate.add(Duration(minutes: delay));
return Column(
@ -332,21 +333,26 @@ class StopTime extends StatelessWidget {
Builder(
builder: (context) {
int stopsForInt = station.stoppingTime!;
bool minutes = false;
if (stopsForInt >= 60) {
stopsForInt ~/= 60;
minutes = true;
}
if (stopsForInt == 1) {
return Text(
"1 minut",
"1 " + (minutes ? 'minut' : 'secundă'),
textAlign: TextAlign.center,
);
}
else if (stopsForInt < 20) {
return Text(
"${station.stoppingTime} minute",
"$stopsForInt ${minutes ? 'minute' : 'secunde'}",
textAlign: TextAlign.center,
);
}
else {
return Text(
"${station.stoppingTime} de minute",
"$stopsForInt de ${minutes ? 'minute' : 'secunde'}",
textAlign: TextAlign.center,
);
}
@ -390,16 +396,13 @@ class DepartureTime extends StatelessWidget {
}
else {
final delay = station.departure!.status?.delay ?? 0;
final time = station.departure!.scheduleTime;
final time = DateTime.parse(station.departure!.scheduleTime);
if (delay == 0) {
return Text("$time");
return Text("${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}");
}
else if (delay > 0) {
final splits = time.split(":").map((s) => int.parse(s)).toList();
final now = DateTime.now();
final oldDate = DateTime(now.year, now.month, now.day, splits[0], splits[1]);
final oldDate = time;
final newDate = oldDate.add(Duration(minutes: delay));
return Column(
@ -421,10 +424,7 @@ class DepartureTime extends StatelessWidget {
);
}
else {
final splits = time.split(":").map((s) => int.parse(s)).toList();
final now = DateTime.now();
final oldDate = DateTime(now.year, now.month, now.day, splits[0], splits[1]);
final oldDate = time;
final newDate = oldDate.add(Duration(minutes: delay));
return Column(
@ -470,7 +470,7 @@ class Delay extends StatelessWidget {
if (delay == 0 || delay == null) return Container();
else if (delay > 0) {
return Text(
"$delay minute întârziere",
"$delay ${delay == 1 ? 'minut' : 'minute'} întârziere",
style: Theme.of(context).textTheme.bodyText2?.copyWith(
color: Colors.red.shade300,
fontSize: 14,
@ -480,7 +480,7 @@ class Delay extends StatelessWidget {
}
else if (delay < 0) {
return Text(
"${-delay} minute mai devreme",
"${-delay} ${delay == -1 ? 'minut' : 'minute'} mai devreme",
style: Theme.of(context).textTheme.bodyText2?.copyWith(
color: Colors.green.shade300,
fontSize: 14,

2
pubspec.yaml

@ -11,7 +11,7 @@ description: O aplicație de vizualizare a datelor puse la dispoziție de Inform
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 2.3.1
version: 2.4.0
environment:
sdk: ">=2.12.0 <3.0.0"

Loading…
Cancel
Save