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. 334
      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. 193
      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", "request": "launch",
"type": "dart", "type": "dart",
"deviceId": "iphone" "deviceId": "iphone"
},
{
"name": "macOS",
"request": "launch",
"type": "dart",
"deviceId": "macOS"
},
{
"name": "Samsung",
"request": "launch",
"type": "dart",
"deviceId": "SM"
} }
], ],
"compounds": [ "compounds": [
{ {
"name": "All Devices", "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 v2.3.1
Fixed badge background when arrival is known but not departure 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'; const AUTHORITY = 'scraper.infotren.dcdevelop.xyz';
Future<TrainData> getTrain(String trainNumber) async { 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); return trainDataFromJson(response.body);
} }

2
lib/components/slim_app_bar.dart

@ -18,7 +18,7 @@ class SlimAppBar extends StatelessWidget {
height: size, height: size,
child: Container( child: Container(
color: color:
Theme.of(context).appBarTheme.color ?? Theme.of(context).appBarTheme.backgroundColor ??
Theme.of(context).primaryColor, Theme.of(context).primaryColor,
child: InkWell( child: InkWell(
onTap: (ModalRoute.of(context)?.canPop ?? false) 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) { switch (uiDesign) {
case UiDesign.MATERIAL: case UiDesign.MATERIAL:
if ([RefreshFutureBuilderState.none, RefreshFutureBuilderState.waiting].contains(snapshot.state)) { 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) { else if (snapshot.state == RefreshFutureBuilderState.error) {
return TrainInfoErrorMaterial(title: '$trainNumber - Error', error: snapshot.error!, refresh: refresh,); 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,); return TrainInfoMaterial(trainData: snapshot.data!, refresh: refresh,);
case UiDesign.CUPERTINO: case UiDesign.CUPERTINO:
if ([RefreshFutureBuilderState.none, RefreshFutureBuilderState.waiting].contains(snapshot.state)) { 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) { else if (snapshot.state == RefreshFutureBuilderState.error) {
return TrainInfoErrorCupertino(title: '$trainNumber - Error', error: snapshot.error!, refresh: refresh,); 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: default:
throw UnmatchedUiDesignException(uiDesign); throw UnmatchedUiDesignException(uiDesign);
} }

334
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'; import 'package:info_tren/utils/state_to_string.dart';
class TrainInfoLoadingCupertino extends TrainInfoLoading { 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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -31,7 +35,11 @@ class TrainInfoErrorCupertino extends TrainInfoError {
required Object error, required Object error,
required String title, required String title,
Future Function()? refresh, Future Function()? refresh,
}) : super(error: error, title: title, refresh: refresh,); }) : super(
error: error,
title: title,
refresh: refresh,
);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -62,20 +70,30 @@ class TrainInfoErrorCupertino extends TrainInfoError {
class TrainInfoCupertino extends StatelessWidget { class TrainInfoCupertino extends StatelessWidget {
final TrainData trainData; final TrainData trainData;
final Future Function()? refresh; final Future Function()? refresh;
final bool? isRefreshing;
TrainInfoCupertino({required this.trainData, this.refresh,}); TrainInfoCupertino({
required this.trainData,
this.refresh,
this.isRefreshing,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return CupertinoPageScaffold( return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar( navigationBar: CupertinoNavigationBar(
middle: Text("Informații despre ${trainData.rank} ${trainData.number}"), 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( child: SafeArea(
top: false, top: false,
bottom: false, bottom: false,
child: Builder( child: Builder(builder: (context) {
builder: (context) {
final topPadding = MediaQuery.of(context).padding.top; final topPadding = MediaQuery.of(context).padding.top;
return NestedScrollView( return NestedScrollView(
@ -86,16 +104,18 @@ class TrainInfoCupertino extends StatelessWidget {
// top: topPadding, // top: topPadding,
// ), // ),
// ), // ),
SliverPersistentHeaderPadding(maxHeight: topPadding,) SliverPersistentHeaderPadding(
maxHeight: topPadding,
)
]; ];
}, },
body: Builder( body: Builder(builder: (context) {
builder: (context) {
return CustomScrollView( return CustomScrollView(
slivers: <Widget>[ slivers: <Widget>[
if (refresh != null) if (refresh != null)
CupertinoSliverRefreshControl( CupertinoSliverRefreshControl(
builder: (context, mode, pulledExtent, refreshTriggerPullDistance, refreshIndicatorExtent) { builder: (context, mode, pulledExtent,
refreshTriggerPullDistance, refreshIndicatorExtent) {
return Column( return Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
@ -104,35 +124,40 @@ class TrainInfoCupertino extends StatelessWidget {
child: Column( child: Column(
children: [ children: [
Container( Container(
height: min(refreshIndicatorExtent, pulledExtent), height: min(
refreshIndicatorExtent, pulledExtent),
child: Center( child: Center(
child: Builder( child: Builder(
builder: (context) { builder: (context) {
if (mode == RefreshIndicatorMode.inactive) { if (mode ==
RefreshIndicatorMode.inactive) {
return Container(); return Container();
} } else if (mode ==
else if (mode == RefreshIndicatorMode.done) { RefreshIndicatorMode.done) {
return Text('Refreshed!'); return Text('Refreshed!');
} } else if (mode ==
else if (mode == RefreshIndicatorMode.drag) { RefreshIndicatorMode.drag) {
return Row( return Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
CupertinoActivityIndicator(animating: false,), CupertinoActivityIndicator(
animating: false,
),
Text('Pull to refresh...'), Text('Pull to refresh...'),
], ],
); );
} } else if (mode ==
else if (mode == RefreshIndicatorMode.armed) { RefreshIndicatorMode.armed) {
return Row( return Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
CupertinoActivityIndicator(animating: false,), CupertinoActivityIndicator(
animating: false,
),
Text('Release to refresh...'), Text('Release to refresh...'),
], ],
); );
} } else {
else {
return Row( return Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
@ -145,7 +170,9 @@ class TrainInfoCupertino extends StatelessWidget {
), ),
), ),
), ),
Expanded(child: Container(),), Expanded(
child: Container(),
),
], ],
), ),
), ),
@ -154,16 +181,26 @@ class TrainInfoCupertino extends StatelessWidget {
}, },
onRefresh: refresh, onRefresh: refresh,
), ),
DisplayTrainID(trainData: trainData,), DisplayTrainID(
DisplayTrainOperator(trainData: trainData,), trainData: trainData,
DisplayTrainRoute(trainData: trainData,), ),
DisplayTrainDeparture(trainData: trainData,), DisplayTrainOperator(
trainData: trainData,
),
DisplayTrainRoute(
trainData: trainData,
),
DisplayTrainDeparture(
trainData: trainData,
),
SliverToBoxAdapter( SliverToBoxAdapter(
child: CupertinoDivider( child: CupertinoDivider(
color: FOREGROUND_WHITE, color: FOREGROUND_WHITE,
), ),
), ),
DisplayTrainLastInfo(trainData: trainData,), DisplayTrainLastInfo(
trainData: trainData,
),
SliverToBoxAdapter( SliverToBoxAdapter(
child: CupertinoDivider(), child: CupertinoDivider(),
), ),
@ -175,13 +212,22 @@ class TrainInfoCupertino extends StatelessWidget {
// child: DisplayTrainNextStop(trainData: trainData,), // child: DisplayTrainNextStop(trainData: trainData,),
// ), // ),
Expanded( Expanded(
child: DisplayTrainDestination(trainData: trainData,), child: DisplayTrainRouteDuration(
trainData: trainData,
),
), ),
// Expanded(
// child: DisplayTrainDestination(trainData: trainData,),
// ),
SizedBox( SizedBox(
height: double.infinity, height: double.infinity,
child: CupertinoVerticalDivider(), child: CupertinoVerticalDivider(),
), ),
Expanded(child: DisplayTrainRouteDistance(trainData: trainData,),), Expanded(
child: DisplayTrainRouteDistance(
trainData: trainData,
),
),
], ],
), ),
), ),
@ -223,11 +269,9 @@ class TrainInfoCupertino extends StatelessWidget {
), ),
], ],
); );
} }),
),
); );
} }),
),
), ),
); );
@ -346,8 +390,19 @@ class DisplayTrainID extends StatelessWidget {
child: Center( child: Center(
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Text( child: Text.rich(
"${trainData.rank} ${trainData.number}", 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, style: CupertinoTheme.of(context).textTheme.navLargeTitleTextStyle,
), ),
), ),
@ -366,32 +421,36 @@ class DisplayTrainRoute extends StatelessWidget {
return SliverToBoxAdapter( return SliverToBoxAdapter(
child: Row( child: Row(
children: <Widget>[ children: <Widget>[
Center( Expanded(
child: Center(
child: Padding( child: Padding(
padding: const EdgeInsets.all(4), padding: const EdgeInsets.all(4),
child: Text( child: Text(
trainData.route.from, trainData.route.from,
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( style:
CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 16, fontSize: 16,
), ),
), ),
), ),
), ),
Expanded(child: Container(),), ),
Center(child: Text("-")), Center(child: Text("-")),
Expanded(child: Container(),), Expanded(
Center( child: Center(
child: Padding( child: Padding(
padding: const EdgeInsets.all(4), padding: const EdgeInsets.all(4),
child: Text( child: Text(
trainData.route.to, trainData.route.to,
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( style:
CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 16, fontSize: 16,
), ),
textAlign: TextAlign.right, textAlign: TextAlign.right,
), ),
), ),
), ),
),
], ],
), ),
); );
@ -451,7 +510,9 @@ class DisplayTrainLastInfo extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (trainData.status == null) { if (trainData.status == null) {
return SliverToBoxAdapter(child: Container(),); return SliverToBoxAdapter(
child: Container(),
);
} }
return SliverToBoxAdapter( return SliverToBoxAdapter(
@ -480,7 +541,9 @@ class DisplayTrainLastInfo extends StatelessWidget {
textAlign: TextAlign.left, textAlign: TextAlign.left,
), ),
), ),
Expanded(child: Container(),), Expanded(
child: Container(),
),
Padding( Padding(
padding: const EdgeInsets.all(4), padding: const EdgeInsets.all(4),
child: Text( child: Text(
@ -510,17 +573,18 @@ class DisplayTrainLastInfo extends StatelessWidget {
if (data > 0) { if (data > 0) {
return Text( return Text(
"$data minute întârziere", "$data ${data == 1 ? 'minut' : 'minute'} întârziere",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( style:
CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 14, fontSize: 14,
color: CupertinoColors.destructiveRed, color: CupertinoColors.destructiveRed,
), ),
); );
} } else {
else {
return Text( return Text(
"${-data} minute mai devreme", "${-data} ${data == -1 ? 'minut' : 'minute'} mai devreme",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( style:
CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 12, fontSize: 12,
color: CupertinoColors.activeGreen, color: CupertinoColors.activeGreen,
), ),
@ -649,12 +713,14 @@ class DisplayTrainDestination extends StatelessWidget {
), ),
Builder( Builder(
builder: (context) { 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 delay = trainData.stations.last.arrival!.status?.delay ?? 0;
final parts = arrival.split(':'); // 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 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")}'; final arrivalWithDelayString =
'${arrivalWithDelay.hour}:${arrivalWithDelay.minute.toString().padLeft(2, "0")}';
// const months = ["ian", "feb", "mar", "apr", "mai", "iun", "iul", "aug", "sep", "oct", "noi", "dec"]; // const months = ["ian", "feb", "mar", "apr", "mai", "iun", "iul", "aug", "sep", "oct", "noi", "dec"];
return Column( return Column(
@ -673,8 +739,11 @@ class DisplayTrainDestination extends StatelessWidget {
children: [ children: [
TextSpan(text: ' '), TextSpan(text: ' '),
TextSpan( TextSpan(
text: '$arrival', text:
style: delay == 0 ? null : TextStyle( '${arrival.hour.toString().padLeft(2, "0")}:${arrival.minute.toString().padLeft(2, "0")}',
style: delay == 0
? null
: TextStyle(
decoration: TextDecoration.lineThrough, decoration: TextDecoration.lineThrough,
), ),
), ),
@ -683,14 +752,17 @@ class DisplayTrainDestination extends StatelessWidget {
TextSpan( TextSpan(
text: '$arrivalWithDelayString', text: '$arrivalWithDelayString',
style: TextStyle( 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')}", // "la ${arrival.hour.toString().padLeft(2, '0')}:${arrival.minute.toString().padLeft(2, '0')}",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( style:
CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 14, fontSize: 14,
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
@ -734,76 +806,87 @@ class DisplayTrainRouteDistance extends StatelessWidget {
} }
} }
// class DisplayTrainRouteDuration extends StatelessWidget { class DisplayTrainRouteDuration extends StatelessWidget {
// final TrainData trainData; final TrainData trainData;
//
// DisplayTrainRouteDuration({required this.trainData}); DisplayTrainRouteDuration({required this.trainData});
//
// @override @override
// Widget build(BuildContext context) { Widget build(BuildContext context) {
// return Column( return Column(
// mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
// children: <Widget>[ children: <Widget>[
// Text( Text(
// "Durata rutei", "Durata rutei",
// style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
// fontSize: 18, fontSize: 18,
// fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
// ), ),
// textAlign: TextAlign.center, textAlign: TextAlign.center,
// ), ),
// FutureDisplay<Duration>( Builder(
// future: trainData.routeDuration, builder: (context) {
// builder: (context, duration) { var duration =
// var durationString = StringBuffer(); DateTime.parse(trainData.stations.last.arrival!.scheduleTime)
// .difference(DateTime.parse(
// bool firstWritten = false; trainData.stations.first.departure!.scheduleTime));
// var durationString = StringBuffer();
// if (duration.inDays > 0) {
// firstWritten = true; bool firstWritten = false;
// if (duration.inDays == 1) durationString.write("1 zi");
// else durationString.write("${duration.inDays} zile"); if (duration.inDays > 0) {
// duration -= Duration(days: duration.inDays); firstWritten = true;
// } if (duration.inDays == 1)
// durationString.write("1 zi");
// if (duration.inHours > 0) { else
// if (firstWritten) { durationString.write("${duration.inDays} zile");
// durationString.write(", "); duration -= Duration(days: duration.inDays);
// } }
// firstWritten = true;
// if (duration.inHours == 1) durationString.write("1 oră"); if (duration.inHours > 0) {
// else durationString.write("${duration.inHours} ore"); if (firstWritten) {
// duration -= Duration(hours: duration.inHours); durationString.write(", ");
// } }
// firstWritten = true;
// if (duration.inMinutes > 0) { if (duration.inHours == 1)
// if (firstWritten) { durationString.write("1 oră");
// durationString.write(", "); else
// } durationString.write("${duration.inHours} ore");
// firstWritten = true; duration -= Duration(hours: duration.inHours);
// if (duration.inMinutes == 1) durationString.write("1 minut"); }
// else durationString.write("${duration.inMinutes} minute");
// duration -= Duration(minutes: duration.inMinutes); if (duration.inMinutes > 0) {
// } if (firstWritten) {
// durationString.write(", ");
// return Text( }
// durationString.toString(), firstWritten = true;
// style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( if (duration.inMinutes == 1)
// fontSize: 16, durationString.write("1 minut");
// ), else
// textAlign: TextAlign.center, 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 { class DisplayTrainStations extends StatelessWidget {
final TrainData trainData; final TrainData trainData;
DisplayTrainStations({required this.trainData,}); DisplayTrainStations({
required this.trainData,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -812,8 +895,7 @@ class DisplayTrainStations extends StatelessWidget {
(context, index) { (context, index) {
if (index.isOdd) { if (index.isOdd) {
return CupertinoDivider(); return CupertinoDivider();
} } else {
else {
final itemIndex = index ~/ 2; final itemIndex = index ~/ 2;
return IndexedSemantics( return IndexedSemantics(
child: DisplayTrainStation( 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 isOnTime = delay <= 0 && real == true;
final isNotScheduled = false; final isNotScheduled = false;
return KmBadge( return Badge(
station: station, text: station.km.toString(),
caption: 'km',
isNotScheduled: isNotScheduled, isNotScheduled: isNotScheduled,
isDelayed: isDelayed, isDelayed: isDelayed,
isOnTime: isOnTime, isOnTime: isOnTime,
@ -55,7 +56,11 @@ class DisplayTrainStation extends StatelessWidget {
child: Title( child: Title(
station: station, station: station,
), ),
) ),
if (station.platform == null)
Container(width: 48, height: 48,)
else
Badge(text: station.platform!, caption: 'linia'),
], ],
), ),
Time( Time(
@ -69,14 +74,16 @@ class DisplayTrainStation extends StatelessWidget {
} }
} }
class KmBadge extends StatelessWidget { class Badge extends StatelessWidget {
final Station station; final String text;
final String caption;
final bool isNotScheduled; final bool isNotScheduled;
final bool isOnTime; final bool isOnTime;
final bool isDelayed; final bool isDelayed;
KmBadge({ Badge({
required this.station, required this.text,
required this.caption,
this.isNotScheduled = false, this.isNotScheduled = false,
this.isOnTime = false, this.isOnTime = false,
this.isDelayed = false, this.isDelayed = false,
@ -120,7 +127,7 @@ class KmBadge extends StatelessWidget {
Expanded( Expanded(
child: Center( child: Center(
child: Text( child: Text(
station.km.toString(), text,
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 20, fontSize: 20,
fontWeight: MediaQuery.of(context).boldText ? FontWeight.w400 : FontWeight.w200, fontWeight: MediaQuery.of(context).boldText ? FontWeight.w400 : FontWeight.w200,
@ -131,9 +138,9 @@ class KmBadge extends StatelessWidget {
), ),
), ),
Text( Text(
"km", caption,
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
fontSize: 10, fontSize: 12,
color: MediaQuery.of(context).boldText ? FOREGROUND_WHITE : foregroundColor, color: MediaQuery.of(context).boldText ? FOREGROUND_WHITE : foregroundColor,
), ),
), ),
@ -247,16 +254,13 @@ class ArrivalTime extends StatelessWidget {
} }
else { else {
final delay = station.arrival!.status?.delay ?? 0; final delay = station.arrival!.status?.delay ?? 0;
final time = station.arrival!.scheduleTime; final time = DateTime.parse(station.arrival!.scheduleTime);
if (delay == 0) { if (delay == 0) {
return Text("$time"); return Text("${time.hour.toString().padLeft(2, "0")}:${time.minute.toString().padLeft(2, "0")}");
} }
else if (delay > 0) { else if (delay > 0) {
final splits = time.split(":").map((s) => int.parse(s)).toList(); final oldDate = time;
final now = DateTime.now();
final oldDate = DateTime(now.year, now.month, now.day, splits[0], splits[1]);
final newDate = oldDate.add(Duration(minutes: delay)); final newDate = oldDate.add(Duration(minutes: delay));
return Column( return Column(
@ -278,10 +282,7 @@ class ArrivalTime extends StatelessWidget {
); );
} }
else { else {
final splits = time.split(":").map((s) => int.parse(s)).toList(); final oldDate = time;
final now = DateTime.now();
final oldDate = DateTime(now.year, now.month, now.day, splits[0], splits[1]);
final newDate = oldDate.add(Duration(minutes: delay)); final newDate = oldDate.add(Duration(minutes: delay));
return Column( return Column(
@ -326,21 +327,26 @@ class StopTime extends StatelessWidget {
Builder( Builder(
builder: (context) { builder: (context) {
int stopsForInt = stopsFor; int stopsForInt = stopsFor;
bool minutes = false;
if (stopsForInt >= 60) {
stopsForInt ~/= 60;
minutes = true;
}
if (stopsForInt == 1) { if (stopsForInt == 1) {
return Text( return Text(
"1 minut", minutes ? '1 minut' : '1 secundă',
textAlign: TextAlign.center, textAlign: TextAlign.center,
); );
} }
else if (stopsForInt < 20) { else if (stopsForInt < 20) {
return Text( return Text(
"$stopsFor minute", '$stopsForInt ' + (minutes ? 'minute' : 'seconde'),
textAlign: TextAlign.center, textAlign: TextAlign.center,
); );
} }
else { else {
return Text( return Text(
"$stopsFor de minute", '$stopsForInt de ' + (minutes ? 'minute' : 'secunde'),
textAlign: TextAlign.center, textAlign: TextAlign.center,
); );
} }
@ -381,16 +387,13 @@ class DepartureTime extends StatelessWidget {
} }
else { else {
final delay = station.departure!.status?.delay ?? 0; final delay = station.departure!.status?.delay ?? 0;
final time = station.departure!.scheduleTime; final time = DateTime.parse(station.departure!.scheduleTime);
if (delay == 0) { if (delay == 0) {
return Text("$time"); return Text("${time.hour.toString().padLeft(2, "0")}:${time.minute.toString().padLeft(2, "0")}");
} }
else if (delay > 0) { else if (delay > 0) {
final splits = time.split(":").map((s) => int.parse(s)).toList(); final oldDate = time;
final now = DateTime.now();
final oldDate = DateTime(now.year, now.month, now.day, splits[0], splits[1]);
final newDate = oldDate.add(Duration(minutes: delay)); final newDate = oldDate.add(Duration(minutes: delay));
return Column( return Column(
@ -412,10 +415,7 @@ class DepartureTime extends StatelessWidget {
); );
} }
else { else {
final splits = time.split(":").map((s) => int.parse(s)).toList(); final oldDate = time;
final now = DateTime.now();
final oldDate = DateTime(now.year, now.month, now.day, splits[0], splits[1]);
final newDate = oldDate.add(Duration(minutes: delay)); final newDate = oldDate.add(Duration(minutes: delay));
return Column( return Column(
@ -460,7 +460,7 @@ class Delay extends StatelessWidget {
if (delay == 0 || delay == null) return Container(); if (delay == 0 || delay == null) return Container();
else if (delay > 0) { else if (delay > 0) {
return Text( return Text(
"$delay minute întârziere", "$delay ${delay == 1 ? 'minut' : 'minute'} întârziere",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
color: CupertinoColors.destructiveRed, color: CupertinoColors.destructiveRed,
fontSize: 14, fontSize: 14,
@ -470,7 +470,7 @@ class Delay extends StatelessWidget {
} }
else if (delay < 0) { else if (delay < 0) {
return Text( return Text(
"${-delay} minute mai devreme", "${-delay} ${delay == -1 ? 'minut' : 'minute'} mai devreme",
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
color: CupertinoColors.activeGreen, color: CupertinoColors.activeGreen,
fontSize: 14, fontSize: 14,

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

@ -75,12 +75,18 @@ class TrainInfoMaterial extends StatelessWidget {
body: Column( body: Column(
children: <Widget>[ children: <Widget>[
if (isSmallScreen(context)) if (isSmallScreen(context))
SlimAppBar( SafeArea(
bottom: false,
left: false,
right: false,
child: SlimAppBar(
title: 'INFO TREN - ${trainData.rank} ${trainData.number}' title: 'INFO TREN - ${trainData.rank} ${trainData.number}'
), ),
),
Expanded( Expanded(
child: SafeArea( child: SafeArea(
bottom: false, bottom: false,
top: isSmallScreen(context) ? false : true,
child: RefreshIndicator( child: RefreshIndicator(
onRefresh: refresh ?? () async {}, onRefresh: refresh ?? () async {},
child: CustomScrollView( child: CustomScrollView(
@ -114,7 +120,8 @@ class TrainInfoMaterial extends StatelessWidget {
child: Row( child: Row(
children: <Widget>[ children: <Widget>[
// Expanded(child: DisplayTrainNextStop(trainData: trainData,)), // 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,),), Expanded(child: DisplayTrainRouteDistance(trainData: trainData,),),
], ],
), ),
@ -165,8 +172,19 @@ class DisplayTrainID extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Text( return Text.rich(
"${trainData.rank} ${trainData.number}", 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) style: (isSmallScreen(context)
? Theme.of(context).textTheme.headline4 ? Theme.of(context).textTheme.headline4
: Theme.of(context).textTheme.headline3)?.copyWith( : Theme.of(context).textTheme.headline3)?.copyWith(
@ -205,7 +223,8 @@ class DisplayTrainRoute extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Row( return Row(
children: <Widget>[ children: <Widget>[
Center( Expanded(
child: Center(
child: Padding( child: Padding(
padding: const EdgeInsets.all(4), padding: const EdgeInsets.all(4),
child: Text( child: Text(
@ -216,10 +235,10 @@ class DisplayTrainRoute extends StatelessWidget {
), ),
), ),
), ),
Expanded(child: Container(),), ),
Center(child: Text("-")), Center(child: Text("-")),
Expanded(child: Container(),), Expanded(
Center( child: Center(
child: Padding( child: Padding(
padding: const EdgeInsets.all(4), padding: const EdgeInsets.all(4),
child: Text( child: Text(
@ -231,6 +250,7 @@ class DisplayTrainRoute extends StatelessWidget {
), ),
), ),
), ),
),
], ],
); );
} }
@ -336,7 +356,7 @@ class DisplayTrainLastInfo extends StatelessWidget {
if (data > 0) { if (data > 0) {
return Text( return Text(
"$data minute întârziere", "$data ${data == 1 ? 'minut' : 'minute'} întârziere",
style: Theme.of(context).textTheme.bodyText2?.copyWith( style: Theme.of(context).textTheme.bodyText2?.copyWith(
fontSize: isSmallScreen(context) ? 14 : 16, fontSize: isSmallScreen(context) ? 14 : 16,
color: Colors.red.shade300, color: Colors.red.shade300,
@ -345,7 +365,7 @@ class DisplayTrainLastInfo extends StatelessWidget {
} }
else { else {
return Text( return Text(
"${-data} minute mai devreme", "${-data} ${data == -1 ? 'minut' : 'minute'} mai devreme",
style: Theme.of(context).textTheme.bodyText2?.copyWith( style: Theme.of(context).textTheme.bodyText2?.copyWith(
fontSize: isSmallScreen(context) ? 14 : 16, fontSize: isSmallScreen(context) ? 14 : 16,
color: Colors.green.shade300, color: Colors.green.shade300,
@ -486,11 +506,9 @@ class DisplayTrainDestination extends StatelessWidget {
), ),
Builder( Builder(
builder: (context) { builder: (context) {
final arrival = destination.arrival!.scheduleTime; final arrival = DateTime.parse(destination.arrival!.scheduleTime);
final delay = trainData.stations.last.arrival!.status?.delay ?? 0; final delay = trainData.stations.last.arrival!.status?.delay ?? 0;
final parts = arrival.split(':'); final arrivalWithDelay = arrival.add(Duration(minutes: delay));
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 arrivalWithDelayString = '${arrivalWithDelay.hour}:${arrivalWithDelay.minute.toString().padLeft(2, "0")}';
// const months = ["ian", "feb", "mar", "apr", "mai", "iun", "iul", "aug", "sep", "oct", "noi", "dec"]; // const months = ["ian", "feb", "mar", "apr", "mai", "iun", "iul", "aug", "sep", "oct", "noi", "dec"];
@ -511,7 +529,7 @@ class DisplayTrainDestination extends StatelessWidget {
children: [ children: [
TextSpan(text: ' '), TextSpan(text: ' '),
TextSpan( TextSpan(
text: '$arrival', text: '${arrival.hour.toString().padLeft(2, '0')}:${arrival.minute.toString().padLeft(2, '0')}',
style: delay == 0 ? null : TextStyle( style: delay == 0 ? null : TextStyle(
decoration: TextDecoration.lineThrough, decoration: TextDecoration.lineThrough,
), ),
@ -581,82 +599,81 @@ class DisplayTrainRouteDistance extends StatelessWidget {
} }
} }
// class DisplayTrainRouteDuration extends StatelessWidget { class DisplayTrainRouteDuration extends StatelessWidget {
// final TrainData trainData; final TrainData trainData;
//
// DisplayTrainRouteDuration({required this.trainData}); DisplayTrainRouteDuration({required this.trainData});
//
// @override @override
// Widget build(BuildContext context) { Widget build(BuildContext context) {
// return Card( return Card(
// child: Center( child: Center(
// child: Padding( child: Padding(
// padding: const EdgeInsets.all(2), padding: const EdgeInsets.all(2),
// child: Column( child: Column(
// mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
// children: <Widget>[ children: <Widget>[
// Text( Text(
// "Durata rutei", "Durata rutei",
// style: Theme.of(context).textTheme.bodyText2?.copyWith( style: Theme.of(context).textTheme.bodyText2?.copyWith(
// fontSize: isSmallScreen(context) ? 16 : 18, fontSize: isSmallScreen(context) ? 20 : 22,
// fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
// ), ),
// textAlign: TextAlign.center, textAlign: TextAlign.center,
// ), ),
// FutureDisplay<Duration>( Builder(
// future: trainData.routeDuration, builder: (context) {
// builder: (context, duration) { var duration = DateTime.parse(trainData.stations.last.arrival!.scheduleTime).difference(DateTime.parse(trainData.stations.first.departure!.scheduleTime));
// var durationString = StringBuffer(); var durationString = StringBuffer();
//
// bool firstWritten = false; bool firstWritten = false;
//
// if (duration.inDays > 0) { if (duration.inDays > 0) {
// firstWritten = true; firstWritten = true;
// if (duration.inDays == 1) durationString.write("1 zi"); if (duration.inDays == 1) durationString.write("1 zi");
// else durationString.write("${duration.inDays} zile"); else durationString.write("${duration.inDays} zile");
// duration -= Duration(days: duration.inDays); duration -= Duration(days: duration.inDays);
// } }
//
// if (duration.inHours > 0) { if (duration.inHours > 0) {
// if (firstWritten) { if (firstWritten) {
// durationString.write(", "); durationString.write(", ");
// } }
// firstWritten = true; firstWritten = true;
// if (duration.inHours == 1) durationString.write("1 oră"); if (duration.inHours == 1) durationString.write("1 oră");
// else durationString.write("${duration.inHours} ore"); else durationString.write("${duration.inHours} ore");
// duration -= Duration(hours: duration.inHours); duration -= Duration(hours: duration.inHours);
// } }
//
// if (duration.inMinutes > 0) { if (duration.inMinutes > 0) {
// if (firstWritten) { if (firstWritten) {
// durationString.write(", "); durationString.write(", ");
// } }
// firstWritten = true; firstWritten = true;
// if (duration.inMinutes == 1) durationString.write("1 minut"); if (duration.inMinutes == 1) durationString.write("1 minut");
// else durationString.write("${duration.inMinutes} minute"); else durationString.write("${duration.inMinutes} minute");
// duration -= Duration(minutes: duration.inMinutes); duration -= Duration(minutes: duration.inMinutes);
// } }
//
// return Text( return Text(
// durationString.toString(), durationString.toString(),
// style: Theme.of(context).textTheme.bodyText2?.copyWith( style: Theme.of(context).textTheme.bodyText2?.copyWith(
// fontSize: isSmallScreen(context) ? 14 : 16, fontSize: isSmallScreen(context) ? 18 : 20,
// ), ),
// textAlign: TextAlign.center, textAlign: TextAlign.center,
// ); );
// }, },
// ), ),
// ], ],
// ), ),
// ), ),
// ), ),
// ); );
// } }
// } }
class DisplayTrainStations extends StatelessWidget { class DisplayTrainStations extends StatelessWidget {
final TrainData trainData; final TrainData trainData;
DisplayTrainStations({required this.trainData}); DisplayTrainStations({required this.trainData});
@override @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 isOnTime = delay <= 0 && real == true;
final isNotScheduled = false; final isNotScheduled = false;
return KmBadge( return Badge(
station: station, text: station.km.toString(),
caption: 'km',
isNotScheduled: isNotScheduled, isNotScheduled: isNotScheduled,
isDelayed: isDelayed, isDelayed: isDelayed,
isOnTime: isOnTime, isOnTime: isOnTime,
@ -59,6 +60,10 @@ class DisplayTrainStation extends StatelessWidget {
station: station, 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( Time(
@ -74,14 +79,16 @@ class DisplayTrainStation extends StatelessWidget {
} }
} }
class KmBadge extends StatelessWidget { class Badge extends StatelessWidget {
final Station station; final String text;
final String caption;
final bool isNotScheduled; final bool isNotScheduled;
final bool isOnTime; final bool isOnTime;
final bool isDelayed; final bool isDelayed;
KmBadge({ Badge({
required this.station, required this.text,
required this.caption,
this.isNotScheduled = false, this.isNotScheduled = false,
this.isOnTime = false, this.isOnTime = false,
this.isDelayed = false, this.isDelayed = false,
@ -124,7 +131,7 @@ class KmBadge extends StatelessWidget {
Expanded( Expanded(
child: Center( child: Center(
child: Text( child: Text(
station.km.toString(), text,
style: Theme.of(context).textTheme.bodyText2?.copyWith( style: Theme.of(context).textTheme.bodyText2?.copyWith(
fontSize: isSmallScreen(context) ? 16 : 20, fontSize: isSmallScreen(context) ? 16 : 20,
fontWeight: MediaQuery.of(context).boldText ? FontWeight.w400 : FontWeight.w200, fontWeight: MediaQuery.of(context).boldText ? FontWeight.w400 : FontWeight.w200,
@ -135,7 +142,7 @@ class KmBadge extends StatelessWidget {
), ),
), ),
Text( Text(
"km", caption,
style: Theme.of(context).textTheme.bodyText2?.copyWith( style: Theme.of(context).textTheme.bodyText2?.copyWith(
fontSize: 10, fontSize: 10,
color: MediaQuery.of(context).boldText ? Colors.white70 : foregroundColor, color: MediaQuery.of(context).boldText ? Colors.white70 : foregroundColor,
@ -254,16 +261,13 @@ class ArrivalTime extends StatelessWidget {
} }
else { else {
final delay = station.arrival!.status?.delay ?? 0; final delay = station.arrival!.status?.delay ?? 0;
final time = station.arrival!.scheduleTime; final time = DateTime.parse(station.arrival!.scheduleTime);
if (delay == 0) { if (delay == 0) {
return Text("$time"); return Text("${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}");
} }
else if (delay > 0) { else if (delay > 0) {
final splits = time.split(":").map((s) => int.parse(s)).toList(); final oldDate = time;
final now = DateTime.now();
final oldDate = DateTime(now.year, now.month, now.day, splits[0], splits[1]);
final newDate = oldDate.add(Duration(minutes: delay)); final newDate = oldDate.add(Duration(minutes: delay));
return Column( return Column(
@ -285,10 +289,7 @@ class ArrivalTime extends StatelessWidget {
); );
} }
else { else {
final splits = time.split(":").map((s) => int.parse(s)).toList(); final oldDate = time;
final now = DateTime.now();
final oldDate = DateTime(now.year, now.month, now.day, splits[0], splits[1]);
final newDate = oldDate.add(Duration(minutes: delay)); final newDate = oldDate.add(Duration(minutes: delay));
return Column( return Column(
@ -332,21 +333,26 @@ class StopTime extends StatelessWidget {
Builder( Builder(
builder: (context) { builder: (context) {
int stopsForInt = station.stoppingTime!; int stopsForInt = station.stoppingTime!;
bool minutes = false;
if (stopsForInt >= 60) {
stopsForInt ~/= 60;
minutes = true;
}
if (stopsForInt == 1) { if (stopsForInt == 1) {
return Text( return Text(
"1 minut", "1 " + (minutes ? 'minut' : 'secundă'),
textAlign: TextAlign.center, textAlign: TextAlign.center,
); );
} }
else if (stopsForInt < 20) { else if (stopsForInt < 20) {
return Text( return Text(
"${station.stoppingTime} minute", "$stopsForInt ${minutes ? 'minute' : 'secunde'}",
textAlign: TextAlign.center, textAlign: TextAlign.center,
); );
} }
else { else {
return Text( return Text(
"${station.stoppingTime} de minute", "$stopsForInt de ${minutes ? 'minute' : 'secunde'}",
textAlign: TextAlign.center, textAlign: TextAlign.center,
); );
} }
@ -390,16 +396,13 @@ class DepartureTime extends StatelessWidget {
} }
else { else {
final delay = station.departure!.status?.delay ?? 0; final delay = station.departure!.status?.delay ?? 0;
final time = station.departure!.scheduleTime; final time = DateTime.parse(station.departure!.scheduleTime);
if (delay == 0) { if (delay == 0) {
return Text("$time"); return Text("${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}");
} }
else if (delay > 0) { else if (delay > 0) {
final splits = time.split(":").map((s) => int.parse(s)).toList(); final oldDate = time;
final now = DateTime.now();
final oldDate = DateTime(now.year, now.month, now.day, splits[0], splits[1]);
final newDate = oldDate.add(Duration(minutes: delay)); final newDate = oldDate.add(Duration(minutes: delay));
return Column( return Column(
@ -421,10 +424,7 @@ class DepartureTime extends StatelessWidget {
); );
} }
else { else {
final splits = time.split(":").map((s) => int.parse(s)).toList(); final oldDate = time;
final now = DateTime.now();
final oldDate = DateTime(now.year, now.month, now.day, splits[0], splits[1]);
final newDate = oldDate.add(Duration(minutes: delay)); final newDate = oldDate.add(Duration(minutes: delay));
return Column( return Column(
@ -470,7 +470,7 @@ class Delay extends StatelessWidget {
if (delay == 0 || delay == null) return Container(); if (delay == 0 || delay == null) return Container();
else if (delay > 0) { else if (delay > 0) {
return Text( return Text(
"$delay minute întârziere", "$delay ${delay == 1 ? 'minut' : 'minute'} întârziere",
style: Theme.of(context).textTheme.bodyText2?.copyWith( style: Theme.of(context).textTheme.bodyText2?.copyWith(
color: Colors.red.shade300, color: Colors.red.shade300,
fontSize: 14, fontSize: 14,
@ -480,7 +480,7 @@ class Delay extends StatelessWidget {
} }
else if (delay < 0) { else if (delay < 0) {
return Text( return Text(
"${-delay} minute mai devreme", "${-delay} ${delay == -1 ? 'minut' : 'minute'} mai devreme",
style: Theme.of(context).textTheme.bodyText2?.copyWith( style: Theme.of(context).textTheme.bodyText2?.copyWith(
color: Colors.green.shade300, color: Colors.green.shade300,
fontSize: 14, 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. # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at # Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 2.3.1 version: 2.4.0
environment: environment:
sdk: ">=2.12.0 <3.0.0" sdk: ">=2.12.0 <3.0.0"

Loading…
Cancel
Save