From e01893ad86373c2757d94f4ca6d043271fde6905 Mon Sep 17 00:00:00 2001 From: Dan Cojocaru Date: Tue, 31 Aug 2021 18:08:51 +0300 Subject: [PATCH] Added ability to view yesterday data for trains that didn't depart yet today --- CHANGELOG.TXT | 4 ++ ios/Runner.xcodeproj/project.pbxproj | 3 ++ lib/api/train_data.dart | 7 ++- lib/components/refresh_future_builder.dart | 8 ++- .../view_station/view_station.dart | 2 +- .../view_station/view_station_cupertino.dart | 2 +- .../view_station/view_station_material.dart | 2 +- .../view_train/train_info.dart | 27 ++++++++-- .../view_train/train_info_cupertino.dart | 52 +++++++++++++++++-- ...in_info_cupertino_DisplayTrainStation.dart | 6 +-- .../view_train/train_info_material.dart | 48 ++++++++++++++++- pubspec.lock | 7 +++ pubspec.yaml | 3 +- 13 files changed, 154 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.TXT b/CHANGELOG.TXT index c89f936..e0d8875 100644 --- a/CHANGELOG.TXT +++ b/CHANGELOG.TXT @@ -1,3 +1,7 @@ +v2.6.0 +Added ability to view yesterday data for trains that didn't depart yet today. +Fixed iOS status bar color. + v2.5.0 Initial arrivals/departures support diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 4a5186f..3e44e8a 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -288,6 +288,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = 2.0.7; + DEVELOPMENT_TEAM = NF9A3KMT8Q; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -417,6 +418,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = 2.0.7; + DEVELOPMENT_TEAM = NF9A3KMT8Q; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -440,6 +442,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = 2.0.7; + DEVELOPMENT_TEAM = NF9A3KMT8Q; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( diff --git a/lib/api/train_data.dart b/lib/api/train_data.dart index da373f9..40d22e1 100644 --- a/lib/api/train_data.dart +++ b/lib/api/train_data.dart @@ -2,7 +2,10 @@ import 'package:http/http.dart' as http; import 'package:info_tren/api/common.dart'; import 'package:info_tren/models/train_data.dart'; -Future getTrain(String trainNumber) async { - final response = await http.get(Uri.https(authority, 'v2/train/$trainNumber')); +Future getTrain(String trainNumber, {DateTime? date}) async { + date ??= DateTime.now(); + final response = await http.get(Uri.https(authority, 'v2/train/$trainNumber', { + 'date': date.toIso8601String(), + }),); return trainDataFromJson(response.body); } \ No newline at end of file diff --git a/lib/components/refresh_future_builder.dart b/lib/components/refresh_future_builder.dart index ac74a94..f03d521 100644 --- a/lib/components/refresh_future_builder.dart +++ b/lib/components/refresh_future_builder.dart @@ -3,7 +3,7 @@ import 'package:flutter/widgets.dart'; class RefreshFutureBuilder extends StatefulWidget { final Future Function()? futureCreator; final T? initialData; - final Widget Function(BuildContext context, Future Function() refresh, RefreshFutureBuilderSnapshot snapshot) builder; + final Widget Function(BuildContext context, Future Function() refresh, Future Function(Future Function()) replaceFuture, RefreshFutureBuilderSnapshot snapshot) builder; const RefreshFutureBuilder({ Key? key, this.futureCreator, this.initialData, required this.builder }) : super(key: key); @@ -84,6 +84,11 @@ class _RefreshFutureBuilderState extends State> { } } + Future replaceFutureCreator(Future Function() newFutureCreator) { + futureCreator = newFutureCreator; + return runFuture(); + } + @override void dispose() { _disposed = true; @@ -95,6 +100,7 @@ class _RefreshFutureBuilderState extends State> { return widget.builder( context, runFuture, + replaceFutureCreator, snapshot, ); } diff --git a/lib/pages/station_arrdep_page/view_station/view_station.dart b/lib/pages/station_arrdep_page/view_station/view_station.dart index 264400b..90c02d9 100644 --- a/lib/pages/station_arrdep_page/view_station/view_station.dart +++ b/lib/pages/station_arrdep_page/view_station/view_station.dart @@ -60,7 +60,7 @@ abstract class ViewStationPageState extends State { futureCreator = () => getStationData(stationName); } - Widget buildContent(BuildContext context, Future Function() refresh, RefreshFutureBuilderSnapshot snapshot); + Widget buildContent(BuildContext context, Future Function() refresh, Future Function(Future Function() newFutureBuilder) _, RefreshFutureBuilderSnapshot snapshot); Widget buildStationArrivalItem(BuildContext context, StationArrival item); Widget buildStationDepartureItem(BuildContext context, StationDeparture item); diff --git a/lib/pages/station_arrdep_page/view_station/view_station_cupertino.dart b/lib/pages/station_arrdep_page/view_station/view_station_cupertino.dart index e497262..686045f 100644 --- a/lib/pages/station_arrdep_page/view_station/view_station_cupertino.dart +++ b/lib/pages/station_arrdep_page/view_station/view_station_cupertino.dart @@ -8,7 +8,7 @@ import 'package:info_tren/pages/station_arrdep_page/view_station/view_station.da class ViewStationPageStateCupertino extends ViewStationPageState { @override - Widget buildContent(BuildContext context, Future Function() refresh, RefreshFutureBuilderSnapshot snapshot) { + Widget buildContent(BuildContext context, Future Function() refresh, Future Function(Future Function()) _, RefreshFutureBuilderSnapshot snapshot) { return CupertinoPageScaffold( navigationBar: CupertinoNavigationBar( middle: Text(snapshot.hasData ? snapshot.data!.stationName : stationName), diff --git a/lib/pages/station_arrdep_page/view_station/view_station_material.dart b/lib/pages/station_arrdep_page/view_station/view_station_material.dart index 4c5202d..93aff9f 100644 --- a/lib/pages/station_arrdep_page/view_station/view_station_material.dart +++ b/lib/pages/station_arrdep_page/view_station/view_station_material.dart @@ -7,7 +7,7 @@ import 'package:info_tren/pages/station_arrdep_page/view_station/view_station.da class ViewStationPageStateMaterial extends ViewStationPageState { @override - Widget buildContent(BuildContext context, Future Function() refresh, RefreshFutureBuilderSnapshot snapshot) { + Widget buildContent(BuildContext context, Future Function() refresh, Future Function(Future Function()) _, RefreshFutureBuilderSnapshot snapshot) { return Scaffold( appBar: AppBar( title: Text(snapshot.hasData ? snapshot.data!.stationName : stationName), diff --git a/lib/pages/train_info_page/view_train/train_info.dart b/lib/pages/train_info_page/view_train/train_info.dart index 42561b5..75bf744 100644 --- a/lib/pages/train_info_page/view_train/train_info.dart +++ b/lib/pages/train_info_page/view_train/train_info.dart @@ -25,7 +25,10 @@ class TrainInfo extends StatelessWidget { return RefreshFutureBuilder( futureCreator: () => getTrain(trainNumber), - builder: (context, refresh, snapshot) { + builder: (context, refresh, replaceFutureBuilder, snapshot) { + void onViewYesterdayTrain() { + replaceFutureBuilder(() => getTrain(trainNumber, date: DateTime.now().subtract(const Duration(days: 1)))); + } switch (uiDesign) { case UiDesign.MATERIAL: @@ -36,7 +39,11 @@ class TrainInfo extends StatelessWidget { return TrainInfoErrorMaterial(title: '$trainNumber - Error', error: snapshot.error!, refresh: refresh,); } - return TrainInfoMaterial(trainData: snapshot.data!, refresh: refresh,); + return TrainInfoMaterial( + trainData: snapshot.data!, + refresh: refresh, + onViewYesterdayTrain: onViewYesterdayTrain, + ); case UiDesign.CUPERTINO: if ([RefreshFutureBuilderState.none, RefreshFutureBuilderState.waiting].contains(snapshot.state)) { return TrainInfoLoadingCupertino(title: trainNumber.toString(), loadingText: "Se încarcă...",); @@ -45,7 +52,12 @@ class TrainInfo extends StatelessWidget { return TrainInfoErrorCupertino(title: '$trainNumber - Error', error: snapshot.error!, refresh: refresh,); } - return TrainInfoCupertino(trainData: snapshot.data!, refresh: refresh, isRefreshing: snapshot.state == RefreshFutureBuilderState.refreshing,); + return TrainInfoCupertino( + trainData: snapshot.data!, + refresh: refresh, + isRefreshing: snapshot.state == RefreshFutureBuilderState.refreshing, + onViewYesterdayTrain: onViewYesterdayTrain, + ); default: throw UnmatchedUiDesignException(uiDesign); } @@ -68,3 +80,12 @@ abstract class TrainInfoError extends StatelessWidget { TrainInfoError({required this.title, required this.error, this.refresh}); } + +abstract class DisplayTrainYesterdayWarningCommon extends StatelessWidget { + static const trainDidNotDepart = 'Acest tren nu a plecat încă din prima gară.'; + static const seeYesterdayTrain = 'Apasă aici pentru a vedea trenul care a plecat ieri.'; + + final void Function() onViewYesterdayTrain; + + DisplayTrainYesterdayWarningCommon(this.onViewYesterdayTrain); +} diff --git a/lib/pages/train_info_page/view_train/train_info_cupertino.dart b/lib/pages/train_info_page/view_train/train_info_cupertino.dart index 10e65ec..a0cf70d 100644 --- a/lib/pages/train_info_page/view_train/train_info_cupertino.dart +++ b/lib/pages/train_info_page/view_train/train_info_cupertino.dart @@ -1,6 +1,7 @@ import 'dart:math'; import 'package:flutter/cupertino.dart'; +import 'package:flutter/gestures.dart'; import 'package:info_tren/components/cupertino_divider.dart'; import 'package:info_tren/components/sliver_persistent_header_padding.dart'; import 'package:info_tren/models/train_data.dart' hide State; @@ -71,11 +72,13 @@ class TrainInfoCupertino extends StatelessWidget { final TrainData trainData; final Future Function()? refresh; final bool? isRefreshing; + final void Function()? onViewYesterdayTrain; TrainInfoCupertino({ required this.trainData, this.refresh, this.isRefreshing, + this.onViewYesterdayTrain, }); @override @@ -259,6 +262,16 @@ class TrainInfoCupertino extends StatelessWidget { color: FOREGROUND_WHITE, ), ), + if (onViewYesterdayTrain != null && trainData.stations.first.departure!.scheduleTime.compareTo(DateTime.now()) > 0) ...[ + SliverToBoxAdapter( + child: DisplayTrainYesterdayWarningCupertino(onViewYesterdayTrain!), + ), + SliverToBoxAdapter( + child: CupertinoDivider( + color: FOREGROUND_WHITE, + ), + ), + ], DisplayTrainStations( trainData: trainData, ), @@ -586,7 +599,7 @@ class DisplayTrainLastInfo extends StatelessWidget { style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( fontSize: 12, - color: CupertinoColors.activeGreen, + color: CupertinoColors.systemGreen, ), ); } @@ -753,8 +766,8 @@ class DisplayTrainDestination extends StatelessWidget { text: '$arrivalWithDelayString', style: TextStyle( color: delay > 0 - ? CupertinoColors.destructiveRed - : CupertinoColors.activeGreen, + ? CupertinoColors.systemRed + : CupertinoColors.systemGreen, ), ), ] @@ -881,6 +894,39 @@ class DisplayTrainRouteDuration extends StatelessWidget { } } +class DisplayTrainYesterdayWarningCupertino extends DisplayTrainYesterdayWarningCommon { + DisplayTrainYesterdayWarningCupertino(void Function() onViewYesterdayTrain) : super(onViewYesterdayTrain); + + @override + Widget build(BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Text.rich( + TextSpan( + children: [ + TextSpan(text: DisplayTrainYesterdayWarningCommon.trainDidNotDepart,), + TextSpan(text: '\n'), + TextSpan( + text: DisplayTrainYesterdayWarningCommon.seeYesterdayTrain, + style: TextStyle( + color: CupertinoColors.link, + ), + recognizer: TapGestureRecognizer() + ..onTap = onViewYesterdayTrain, + ), + ], + ), + textAlign: TextAlign.center, + ), + ), + ], + ); + } +} + class DisplayTrainStations extends StatelessWidget { final TrainData trainData; diff --git a/lib/pages/train_info_page/view_train/train_info_cupertino_DisplayTrainStation.dart b/lib/pages/train_info_page/view_train/train_info_cupertino_DisplayTrainStation.dart index 02d5695..2476696 100644 --- a/lib/pages/train_info_page/view_train/train_info_cupertino_DisplayTrainStation.dart +++ b/lib/pages/train_info_page/view_train/train_info_cupertino_DisplayTrainStation.dart @@ -297,7 +297,7 @@ class ArrivalTime extends StatelessWidget { Text( "${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}", style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( - color: CupertinoColors.activeGreen, + color: CupertinoColors.systemGreen, ), ), ], @@ -430,7 +430,7 @@ class DepartureTime extends StatelessWidget { Text( "${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}", style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( - color: CupertinoColors.activeGreen, + color: CupertinoColors.systemGreen, ), ), ], @@ -472,7 +472,7 @@ class Delay extends StatelessWidget { return Text( "${-delay} ${delay == -1 ? 'minut' : 'minute'} mai devreme", style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( - color: CupertinoColors.activeGreen, + color: CupertinoColors.systemGreen, fontSize: 14, fontStyle: FontStyle.italic, ), diff --git a/lib/pages/train_info_page/view_train/train_info_material.dart b/lib/pages/train_info_page/view_train/train_info_material.dart index 3fecc63..904ff19 100644 --- a/lib/pages/train_info_page/view_train/train_info_material.dart +++ b/lib/pages/train_info_page/view_train/train_info_material.dart @@ -1,3 +1,4 @@ +import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:info_tren/components/slim_app_bar.dart'; import 'package:info_tren/models/train_data.dart' hide State; @@ -60,8 +61,9 @@ bool isSmallScreen(BuildContext context) => MediaQuery.of(context).size.height < class TrainInfoMaterial extends StatelessWidget { final TrainData trainData; final Future Function()? refresh; + final void Function()? onViewYesterdayTrain; - TrainInfoMaterial({required this.trainData, this.refresh,}); + TrainInfoMaterial({required this.trainData, this.refresh, this.onViewYesterdayTrain,}); @override Widget build(BuildContext context) { @@ -144,6 +146,17 @@ class TrainInfoMaterial extends StatelessWidget { height: isSmallScreen(context) ? 8 : 16, ), ), + if (onViewYesterdayTrain != null && trainData.stations.first.departure!.scheduleTime.compareTo(DateTime.now()) > 0) ...[ + SliverToBoxAdapter( + child: DisplayTrainYesterdayWarningMaterial(onViewYesterdayTrain!), + ), + SliverToBoxAdapter( + child: Divider( + color: Colors.white70, + height: isSmallScreen(context) ? 8 : 16, + ), + ), + ], DisplayTrainStations( trainData: trainData, ), @@ -672,6 +685,39 @@ class DisplayTrainRouteDuration extends StatelessWidget { } } +class DisplayTrainYesterdayWarningMaterial extends DisplayTrainYesterdayWarningCommon { + DisplayTrainYesterdayWarningMaterial(void Function() onViewYesterdayTrain) : super(onViewYesterdayTrain); + + @override + Widget build(BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Text.rich( + TextSpan( + children: [ + TextSpan(text: DisplayTrainYesterdayWarningCommon.trainDidNotDepart,), + TextSpan(text: '\n'), + TextSpan( + text: DisplayTrainYesterdayWarningCommon.seeYesterdayTrain, + style: TextStyle( + color: Colors.blue, + ), + recognizer: TapGestureRecognizer() + ..onTap = onViewYesterdayTrain, + ), + ], + ), + textAlign: TextAlign.center, + ), + ), + ], + ); + } +} + class DisplayTrainStations extends StatelessWidget { final TrainData trainData; DisplayTrainStations({required this.trainData}); diff --git a/pubspec.lock b/pubspec.lock index f1474ef..b781aff 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -382,6 +382,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.1" + sprintf: + dependency: "direct main" + description: + name: sprintf + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.0" stack_trace: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index cc37d6c..6baf4ea 100644 --- a/pubspec.yaml +++ b/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.5.0 +version: 2.6.0 environment: sdk: ">=2.12.0 <3.0.0" @@ -27,6 +27,7 @@ dependencies: http: ^0.13.0 cupertino_icons: ^0.1.2 tuple: ^2.0.0 + sprintf: ^6.0.0 flutter_redux: ^0.8.2 dev_dependencies: