Compare commits
25 Commits
Author | SHA1 | Date |
---|---|---|
Kenneth Bruen | f0ccf59db9 | 1 year ago |
Kenneth Bruen | cc7caffffa | 1 year ago |
Kenneth Bruen | 17d8fac893 | 1 year ago |
Kenneth Bruen | 1f48e868b0 | 1 year ago |
Kenneth Bruen | 9d2871405d | 2 years ago |
Kenneth Bruen | 9637551d7a | 2 years ago |
Kenneth Bruen | 2456f7cbda | 2 years ago |
Kenneth Bruen | 0f39a30921 | 2 years ago |
Kenneth Bruen | 1e4ca0c61b | 2 years ago |
Kenneth Bruen | 1269a93624 | 2 years ago |
Kenneth Bruen | a5615fe3cb | 2 years ago |
Kenneth Bruen | 342b870e93 | 2 years ago |
Kenneth Bruen | 0647f260db | 2 years ago |
Kenneth Bruen | 0e484bdc16 | 2 years ago |
Kenneth Bruen | da983871e2 | 2 years ago |
Kenneth Bruen | 8ddac141d7 | 2 years ago |
Kenneth Bruen | aea7647c89 | 2 years ago |
Kenneth Bruen | e19d761f4d | 2 years ago |
Kenneth Bruen | 240812e261 | 2 years ago |
Kenneth Bruen | cb380e802c | 2 years ago |
Kenneth Bruen | 2ac04cba02 | 2 years ago |
Kenneth Bruen | 6b33fcb01c | 2 years ago |
Kenneth Bruen | 50dd6c19c9 | 2 years ago |
Kenneth Bruen | 3c68cf7164 | 2 years ago |
Kenneth Bruen | 7fcbdc18bd | 2 years ago |
133 changed files with 12315 additions and 2200 deletions
File diff suppressed because one or more lines are too long
@ -0,0 +1,34 @@
|
||||
PODS: |
||||
- Flutter (1.0.0) |
||||
- package_info_plus (0.4.5): |
||||
- Flutter |
||||
- shared_preferences_ios (0.0.1): |
||||
- Flutter |
||||
- url_launcher_ios (0.0.1): |
||||
- Flutter |
||||
|
||||
DEPENDENCIES: |
||||
- Flutter (from `Flutter`) |
||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) |
||||
- shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`) |
||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) |
||||
|
||||
EXTERNAL SOURCES: |
||||
Flutter: |
||||
:path: Flutter |
||||
package_info_plus: |
||||
:path: ".symlinks/plugins/package_info_plus/ios" |
||||
shared_preferences_ios: |
||||
:path: ".symlinks/plugins/shared_preferences_ios/ios" |
||||
url_launcher_ios: |
||||
:path: ".symlinks/plugins/url_launcher_ios/ios" |
||||
|
||||
SPEC CHECKSUMS: |
||||
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 |
||||
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e |
||||
shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad |
||||
url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de |
||||
|
||||
PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3 |
||||
|
||||
COCOAPODS: 1.11.3 |
@ -1,11 +1,11 @@
|
||||
import 'package:http/http.dart' as http; |
||||
import 'package:info_tren/api/common.dart'; |
||||
import 'package:info_tren/models/train_data.dart'; |
||||
import 'package:info_tren/models.dart'; |
||||
|
||||
Future<TrainData> getTrain(String trainNumber, {DateTime? date}) async { |
||||
date ??= DateTime.now(); |
||||
final response = await http.get(Uri.https(authority, 'v2/train/$trainNumber', { |
||||
'date': date.toIso8601String(), |
||||
final response = await http.get(Uri.https(authority, 'v3/trains/$trainNumber', { |
||||
'date': date.toUtc().toIso8601String(), |
||||
}),); |
||||
return trainDataFromJson(response.body); |
||||
} |
@ -0,0 +1,59 @@
|
||||
import 'package:flutter/cupertino.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
import 'package:hooks_riverpod/hooks_riverpod.dart'; |
||||
import 'package:info_tren/components/badge/badge_cupertino.dart'; |
||||
import 'package:info_tren/components/badge/badge_fluent.dart'; |
||||
import 'package:info_tren/components/badge/badge_material.dart'; |
||||
import 'package:info_tren/models.dart'; |
||||
import 'package:info_tren/providers.dart'; |
||||
|
||||
class Badge extends ConsumerWidget { |
||||
final String text; |
||||
final String caption; |
||||
final bool isNotScheduled; |
||||
final bool isOnTime; |
||||
final bool isDelayed; |
||||
|
||||
const Badge({ |
||||
super.key, |
||||
required this.text, |
||||
required this.caption, |
||||
this.isNotScheduled = false, |
||||
this.isOnTime = false, |
||||
this.isDelayed = false, |
||||
}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context, WidgetRef ref) { |
||||
final uiDesign = ref.watch(uiDesignProvider); |
||||
|
||||
switch (uiDesign) { |
||||
case UiDesign.MATERIAL: |
||||
return MaterialBadge( |
||||
text: text, |
||||
caption: caption, |
||||
isNotScheduled: isNotScheduled, |
||||
isOnTime: isOnTime, |
||||
isDelayed: isDelayed, |
||||
); |
||||
case UiDesign.CUPERTINO: |
||||
return CupertinoBadge( |
||||
text: text, |
||||
caption: caption, |
||||
isNotScheduled: isNotScheduled, |
||||
isOnTime: isOnTime, |
||||
isDelayed: isDelayed, |
||||
); |
||||
case UiDesign.FLUENT: |
||||
return FluentBadge( |
||||
text: text, |
||||
caption: caption, |
||||
isNotScheduled: isNotScheduled, |
||||
isOnTime: isOnTime, |
||||
isDelayed: isDelayed, |
||||
); |
||||
default: |
||||
throw UnmatchedUiDesignException(uiDesign); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,80 @@
|
||||
import 'package:flutter/cupertino.dart'; |
||||
import 'package:info_tren/pages/train_info_page/train_info_constants.dart'; |
||||
|
||||
class CupertinoBadge extends StatelessWidget { |
||||
final String text; |
||||
final String caption; |
||||
final bool isNotScheduled; |
||||
final bool isOnTime; |
||||
final bool isDelayed; |
||||
|
||||
const CupertinoBadge({ |
||||
required this.text, |
||||
required this.caption, |
||||
this.isNotScheduled = false, |
||||
this.isOnTime = false, |
||||
this.isDelayed = false, |
||||
super.key, |
||||
}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
Color foregroundColor = foregroundWhite; |
||||
Color? backgroundColor; |
||||
|
||||
if (isNotScheduled) { |
||||
foregroundColor = const Color.fromRGBO(225, 175, 30, 1); |
||||
backgroundColor = const Color.fromRGBO(80, 40, 10, 1); |
||||
} |
||||
else if (isOnTime) { |
||||
foregroundColor = const Color.fromRGBO(130, 175, 65, 1); |
||||
backgroundColor = const Color.fromRGBO(40, 80, 10, 1); |
||||
} |
||||
else if (isDelayed) { |
||||
foregroundColor = const Color.fromRGBO(225, 75, 30, 1); |
||||
backgroundColor = const Color.fromRGBO(80, 20, 10, 1); |
||||
} |
||||
|
||||
return Padding( |
||||
padding: const EdgeInsets.all(8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
borderRadius: BorderRadius.circular(10), |
||||
border: Border.all( |
||||
width: 2, |
||||
color: foregroundColor, |
||||
), |
||||
color: backgroundColor, |
||||
// color: CupertinoColors.activeOrange, |
||||
), |
||||
width: 48, |
||||
height: 48, |
||||
child: Column( |
||||
mainAxisSize: MainAxisSize.min, |
||||
children: <Widget>[ |
||||
Expanded( |
||||
child: Center( |
||||
child: Text( |
||||
text, |
||||
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
||||
fontSize: 20, |
||||
fontWeight: MediaQuery.of(context).boldText ? FontWeight.w400 : FontWeight.w200, |
||||
color: MediaQuery.of(context).boldText ? foregroundWhite : foregroundColor, |
||||
), |
||||
textAlign: TextAlign.center, |
||||
), |
||||
), |
||||
), |
||||
Text( |
||||
caption, |
||||
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( |
||||
fontSize: 12, |
||||
color: MediaQuery.of(context).boldText ? foregroundWhite : foregroundColor, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,80 @@
|
||||
import 'package:fluent_ui/fluent_ui.dart'; |
||||
|
||||
|
||||
class FluentBadge extends StatelessWidget { |
||||
final String text; |
||||
final String caption; |
||||
final bool isNotScheduled; |
||||
final bool isOnTime; |
||||
final bool isDelayed; |
||||
|
||||
const FluentBadge({ |
||||
required this.text, |
||||
required this.caption, |
||||
this.isNotScheduled = false, |
||||
this.isOnTime = false, |
||||
this.isDelayed = false, |
||||
super.key, |
||||
}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
Color foregroundColor = FluentTheme.of(context).activeColor; |
||||
Color? backgroundColor; |
||||
|
||||
if (isNotScheduled) { |
||||
foregroundColor = const Color.fromRGBO(225, 175, 30, 1); |
||||
backgroundColor = const Color.fromRGBO(80, 40, 10, 1); |
||||
} |
||||
else if (isOnTime) { |
||||
foregroundColor = const Color.fromRGBO(130, 175, 65, 1); |
||||
backgroundColor = const Color.fromRGBO(40, 80, 10, 1); |
||||
} |
||||
else if (isDelayed) { |
||||
foregroundColor = const Color.fromRGBO(225, 75, 30, 1); |
||||
backgroundColor = const Color.fromRGBO(80, 20, 10, 1); |
||||
} |
||||
|
||||
return Padding( |
||||
padding: const EdgeInsets.all(8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
borderRadius: BorderRadius.circular(10), |
||||
border: Border.all( |
||||
width: 2, |
||||
color: foregroundColor, |
||||
), |
||||
color: backgroundColor, |
||||
// color: CupertinoColors.activeOrange, |
||||
), |
||||
width: 48, |
||||
height: 48, |
||||
child: Column( |
||||
mainAxisSize: MainAxisSize.min, |
||||
children: <Widget>[ |
||||
Expanded( |
||||
child: Center( |
||||
child: Text( |
||||
text, |
||||
style: FluentTheme.of(context).typography.bodyLarge?.copyWith( |
||||
fontSize: 20, |
||||
fontWeight: MediaQuery.of(context).boldText ? FontWeight.w400 : FontWeight.w200, |
||||
color: MediaQuery.of(context).boldText ? Colors.white : foregroundColor, |
||||
), |
||||
textAlign: TextAlign.center, |
||||
), |
||||
), |
||||
), |
||||
Text( |
||||
caption, |
||||
style: FluentTheme.of(context).typography.body?.copyWith( |
||||
fontSize: 12, |
||||
color: MediaQuery.of(context).boldText ? Colors.white : foregroundColor, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,79 @@
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:info_tren/pages/train_info_page/view_train/train_info_material.dart'; |
||||
|
||||
class MaterialBadge extends StatelessWidget { |
||||
final String text; |
||||
final String caption; |
||||
final bool isNotScheduled; |
||||
final bool isOnTime; |
||||
final bool isDelayed; |
||||
|
||||
const MaterialBadge({ |
||||
required this.text, |
||||
required this.caption, |
||||
this.isNotScheduled = false, |
||||
this.isOnTime = false, |
||||
this.isDelayed = false, |
||||
super.key, |
||||
}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
Color foregroundColor = Colors.white70; |
||||
Color? backgroundColor; |
||||
|
||||
if (isNotScheduled) { |
||||
foregroundColor = Colors.orange.shade300; |
||||
backgroundColor = Colors.orange.shade900.withOpacity(0.3); |
||||
} |
||||
else if (isOnTime) { |
||||
foregroundColor = Colors.green.shade300; |
||||
backgroundColor = Colors.green.shade900.withOpacity(0.3); |
||||
} |
||||
else if (isDelayed) { |
||||
foregroundColor = Colors.red.shade300; |
||||
backgroundColor = Colors.red.shade900.withOpacity(0.3); |
||||
} |
||||
|
||||
return Padding( |
||||
padding: const EdgeInsets.all(8), |
||||
child: Container( |
||||
decoration: BoxDecoration( |
||||
borderRadius: BorderRadius.circular(10), |
||||
border: Border.all( |
||||
width: 2, |
||||
color: foregroundColor, |
||||
), |
||||
color: backgroundColor, |
||||
), |
||||
width: isSmallScreen(context) ? 42 : 48, |
||||
height: isSmallScreen(context) ? 42 : 48, |
||||
child: Column( |
||||
mainAxisSize: MainAxisSize.min, |
||||
children: <Widget>[ |
||||
Expanded( |
||||
child: Center( |
||||
child: Text( |
||||
text, |
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith( |
||||
fontSize: isSmallScreen(context) ? 16 : 20, |
||||
fontWeight: MediaQuery.of(context).boldText ? FontWeight.w400 : FontWeight.w200, |
||||
color: MediaQuery.of(context).boldText ? Colors.white70 : foregroundColor, |
||||
), |
||||
textAlign: TextAlign.center, |
||||
), |
||||
), |
||||
), |
||||
Text( |
||||
caption, |
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith( |
||||
fontSize: 10, |
||||
color: MediaQuery.of(context).boldText ? Colors.white70 : foregroundColor, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,26 @@
|
||||
import 'package:fluent_ui/fluent_ui.dart'; |
||||
import 'package:info_tren/components/loading/loading.dart'; |
||||
|
||||
class LoadingFluent extends LoadingCommon { |
||||
const LoadingFluent({required super.text, super.key}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Center( |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
mainAxisSize: MainAxisSize.min, |
||||
children: [ |
||||
const Padding( |
||||
padding: EdgeInsets.all(8.0), |
||||
child: ProgressRing(), |
||||
), |
||||
Padding( |
||||
padding: const EdgeInsets.all(8.0), |
||||
child: Text(text), |
||||
), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,85 @@
|
||||
import 'package:fluent_ui/fluent_ui.dart'; |
||||
import 'package:info_tren/components/select_train_suggestions/select_train_suggestions.dart'; |
||||
import 'package:info_tren/components/train_id_text_span.dart'; |
||||
import 'package:info_tren/models.dart'; |
||||
|
||||
class SelectTrainSuggestionsFluent extends SelectTrainSuggestionsShared { |
||||
const SelectTrainSuggestionsFluent({ |
||||
super.key, |
||||
required super.choices, |
||||
required super.onTrainSelected, |
||||
super.currentInput, |
||||
}); |
||||
|
||||
@override |
||||
Widget getUseCurrentInputWidget(String currentInput, void Function(String) onTrainSelected) { |
||||
return Column( |
||||
mainAxisSize: MainAxisSize.min, |
||||
children: <Widget>[ |
||||
Padding( |
||||
padding: const EdgeInsets.all(0), |
||||
child: Column( |
||||
mainAxisSize: MainAxisSize.min, |
||||
children: <Widget>[ |
||||
Button( |
||||
child: Text(getUseCurrentInputWidgetText(currentInput)), |
||||
onPressed: () => onTrainSelected(currentInput), |
||||
), |
||||
], |
||||
) |
||||
), |
||||
const Divider(), |
||||
], |
||||
); |
||||
} |
||||
} |
||||
|
||||
class OperatorAutocompleteTileFluent extends OperatorAutocompleteTile { |
||||
const OperatorAutocompleteTileFluent({ |
||||
Key? key, |
||||
required String operatorName, |
||||
required void Function(String) onTrainSelected, |
||||
required TrainsResult train |
||||
}): super( |
||||
onTrainSelected: onTrainSelected, |
||||
operatorName: operatorName, |
||||
train: train, |
||||
key: key, |
||||
); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Column( |
||||
mainAxisSize: MainAxisSize.min, |
||||
children: [ |
||||
GestureDetector( |
||||
onTap: () { |
||||
onTrainSelected(train.number); |
||||
}, |
||||
child: Padding( |
||||
padding: const EdgeInsets.fromLTRB(16, 4, 16, 4), |
||||
child: SizedBox( |
||||
width: double.infinity, |
||||
child: Column( |
||||
mainAxisSize: MainAxisSize.min, |
||||
crossAxisAlignment: CrossAxisAlignment.stretch, |
||||
children: <Widget>[ |
||||
Text( |
||||
operatorName, |
||||
style: FluentTheme.of(context).typography.body?.copyWith(fontSize: 10, fontWeight: FontWeight.w200), |
||||
textAlign: TextAlign.left, |
||||
), |
||||
Text.rich( |
||||
trainIdSpan(rank: train.rank, number: train.number), |
||||
textAlign: TextAlign.left, |
||||
), |
||||
], |
||||
), |
||||
), |
||||
), |
||||
), |
||||
const Divider(), |
||||
], |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,39 @@
|
||||
import 'package:flutter/gestures.dart'; |
||||
import 'package:flutter/rendering.dart'; |
||||
|
||||
TextSpan trainIdSpan({ |
||||
required String rank, |
||||
required String number, |
||||
Locale? locale, |
||||
MouseCursor? mouseCursor, |
||||
void Function(PointerEnterEvent)? onEnter, |
||||
void Function(PointerExitEvent)? onExit, |
||||
GestureRecognizer? recognizer, |
||||
String? semanticsLabel, |
||||
bool? spellOut, |
||||
TextStyle? style, |
||||
}) => TextSpan( |
||||
children: [ |
||||
TextSpan( |
||||
text: rank, |
||||
style: TextStyle( |
||||
inherit: true, |
||||
color: rank.startsWith('IC') |
||||
? const Color.fromARGB(255, 0, 255, 0) |
||||
: rank.startsWith('IR') |
||||
? const Color.fromARGB(255, 255, 0, 0) |
||||
: null, |
||||
), |
||||
), |
||||
const TextSpan(text: ' '), |
||||
TextSpan(text: number), |
||||
], |
||||
locale: locale, |
||||
mouseCursor: mouseCursor, |
||||
onEnter: onEnter, |
||||
onExit: onExit, |
||||
recognizer: recognizer, |
||||
semanticsLabel: semanticsLabel, |
||||
spellOut: spellOut, |
||||
style: style, |
||||
); |
@ -0,0 +1,14 @@
|
||||
export 'package:info_tren/models/changelog_entry.dart'; |
||||
export 'package:info_tren/models/station_arrdep.dart'; |
||||
export 'package:info_tren/models/station_data.dart'; |
||||
export 'package:info_tren/models/station_status.dart'; |
||||
export 'package:info_tren/models/station_train.dart'; |
||||
export 'package:info_tren/models/stations_result.dart'; |
||||
export 'package:info_tren/models/train_data.dart'; |
||||
export 'package:info_tren/models/trains_result.dart'; |
||||
export 'package:info_tren/models/ui_design.dart'; |
||||
export 'package:info_tren/models/ui_timezone.dart'; |
||||
|
||||
import 'package:info_tren/models/train_data.dart' show TrainDataStatusState; |
||||
|
||||
typedef TrainDataState = TrainDataStatusState; |
@ -0,0 +1,18 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart'; |
||||
import 'package:info_tren/models.dart'; |
||||
|
||||
part 'station_arrdep.g.dart'; |
||||
part 'station_arrdep.freezed.dart'; |
||||
|
||||
@freezed |
||||
class StationArrDep with _$StationArrDep { |
||||
const factory StationArrDep({ |
||||
required int? stoppingTime, |
||||
required DateTime time, |
||||
required StationTrain train, |
||||
required StationStatus status, |
||||
}) = _StationArrDep; |
||||
|
||||
factory StationArrDep.fromJson(Map<String, dynamic> json) => _$StationArrDepFromJson(json); |
||||
} |
||||
|
@ -0,0 +1,241 @@
|
||||
// coverage:ignore-file |
||||
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||
// ignore_for_file: type=lint |
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark |
||||
|
||||
part of 'station_arrdep.dart'; |
||||
|
||||
// ************************************************************************** |
||||
// FreezedGenerator |
||||
// ************************************************************************** |
||||
|
||||
T _$identity<T>(T value) => value; |
||||
|
||||
final _privateConstructorUsedError = UnsupportedError( |
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); |
||||
|
||||
StationArrDep _$StationArrDepFromJson(Map<String, dynamic> json) { |
||||
return _StationArrDep.fromJson(json); |
||||
} |
||||
|
||||
/// @nodoc |
||||
mixin _$StationArrDep { |
||||
int? get stoppingTime => throw _privateConstructorUsedError; |
||||
DateTime get time => throw _privateConstructorUsedError; |
||||
StationTrain get train => throw _privateConstructorUsedError; |
||||
StationStatus get status => throw _privateConstructorUsedError; |
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError; |
||||
@JsonKey(ignore: true) |
||||
$StationArrDepCopyWith<StationArrDep> get copyWith => |
||||
throw _privateConstructorUsedError; |
||||
} |
||||
|
||||
/// @nodoc |
||||
abstract class $StationArrDepCopyWith<$Res> { |
||||
factory $StationArrDepCopyWith( |
||||
StationArrDep value, $Res Function(StationArrDep) then) = |
||||
_$StationArrDepCopyWithImpl<$Res, StationArrDep>; |
||||
@useResult |
||||
$Res call( |
||||
{int? stoppingTime, |
||||
DateTime time, |
||||
StationTrain train, |
||||
StationStatus status}); |
||||
|
||||
$StationTrainCopyWith<$Res> get train; |
||||
$StationStatusCopyWith<$Res> get status; |
||||
} |
||||
|
||||
/// @nodoc |
||||
class _$StationArrDepCopyWithImpl<$Res, $Val extends StationArrDep> |
||||
implements $StationArrDepCopyWith<$Res> { |
||||
_$StationArrDepCopyWithImpl(this._value, this._then); |
||||
|
||||
// ignore: unused_field |
||||
final $Val _value; |
||||
// ignore: unused_field |
||||
final $Res Function($Val) _then; |
||||
|
||||
@pragma('vm:prefer-inline') |
||||
@override |
||||
$Res call({ |
||||
Object? stoppingTime = freezed, |
||||
Object? time = null, |
||||
Object? train = null, |
||||
Object? status = null, |
||||
}) { |
||||
return _then(_value.copyWith( |
||||
stoppingTime: freezed == stoppingTime |
||||
? _value.stoppingTime |
||||
: stoppingTime // ignore: cast_nullable_to_non_nullable |
||||
as int?, |
||||
time: null == time |
||||
? _value.time |
||||
: time // ignore: cast_nullable_to_non_nullable |
||||
as DateTime, |
||||
train: null == train |
||||
? _value.train |
||||
: train // ignore: cast_nullable_to_non_nullable |
||||
as StationTrain, |
||||
status: null == status |
||||
? _value.status |
||||
: status // ignore: cast_nullable_to_non_nullable |
||||
as StationStatus, |
||||
) as $Val); |
||||
} |
||||
|
||||
@override |
||||
@pragma('vm:prefer-inline') |
||||
$StationTrainCopyWith<$Res> get train { |
||||
return $StationTrainCopyWith<$Res>(_value.train, (value) { |
||||
return _then(_value.copyWith(train: value) as $Val); |
||||
}); |
||||
} |
||||
|
||||
@override |
||||
@pragma('vm:prefer-inline') |
||||
$StationStatusCopyWith<$Res> get status { |
||||
return $StationStatusCopyWith<$Res>(_value.status, (value) { |
||||
return _then(_value.copyWith(status: value) as $Val); |
||||
}); |
||||
} |
||||
} |
||||
|
||||
/// @nodoc |
||||
abstract class _$$_StationArrDepCopyWith<$Res> |
||||
implements $StationArrDepCopyWith<$Res> { |
||||
factory _$$_StationArrDepCopyWith( |
||||
_$_StationArrDep value, $Res Function(_$_StationArrDep) then) = |
||||
__$$_StationArrDepCopyWithImpl<$Res>; |
||||
@override |
||||
@useResult |
||||
$Res call( |
||||
{int? stoppingTime, |
||||
DateTime time, |
||||
StationTrain train, |
||||
StationStatus status}); |
||||
|
||||
@override |
||||
$StationTrainCopyWith<$Res> get train; |
||||
@override |
||||
$StationStatusCopyWith<$Res> get status; |
||||
} |
||||
|
||||
/// @nodoc |
||||
class __$$_StationArrDepCopyWithImpl<$Res> |
||||
extends _$StationArrDepCopyWithImpl<$Res, _$_StationArrDep> |
||||
implements _$$_StationArrDepCopyWith<$Res> { |
||||
__$$_StationArrDepCopyWithImpl( |
||||
_$_StationArrDep _value, $Res Function(_$_StationArrDep) _then) |
||||
: super(_value, _then); |
||||
|
||||
@pragma('vm:prefer-inline') |
||||
@override |
||||
$Res call({ |
||||
Object? stoppingTime = freezed, |
||||
Object? time = null, |
||||
Object? train = null, |
||||
Object? status = null, |
||||
}) { |
||||
return _then(_$_StationArrDep( |
||||
stoppingTime: freezed == stoppingTime |
||||
? _value.stoppingTime |
||||
: stoppingTime // ignore: cast_nullable_to_non_nullable |
||||
as int?, |
||||
time: null == time |
||||
? _value.time |
||||
: time // ignore: cast_nullable_to_non_nullable |
||||
as DateTime, |
||||
train: null == train |
||||
? _value.train |
||||
: train // ignore: cast_nullable_to_non_nullable |
||||
as StationTrain, |
||||
status: null == status |
||||
? _value.status |
||||
: status // ignore: cast_nullable_to_non_nullable |
||||
as StationStatus, |
||||
)); |
||||
} |
||||
} |
||||
|
||||
/// @nodoc |
||||
@JsonSerializable() |
||||
class _$_StationArrDep implements _StationArrDep { |
||||
const _$_StationArrDep( |
||||
{required this.stoppingTime, |
||||
required this.time, |
||||
required this.train, |
||||
required this.status}); |
||||
|
||||
factory _$_StationArrDep.fromJson(Map<String, dynamic> json) => |
||||
_$$_StationArrDepFromJson(json); |
||||
|
||||
@override |
||||
final int? stoppingTime; |
||||
@override |
||||
final DateTime time; |
||||
@override |
||||
final StationTrain train; |
||||
@override |
||||
final StationStatus status; |
||||
|
||||
@override |
||||
String toString() { |
||||
return 'StationArrDep(stoppingTime: $stoppingTime, time: $time, train: $train, status: $status)'; |
||||
} |
||||
|
||||
@override |
||||
bool operator ==(dynamic other) { |
||||
return identical(this, other) || |
||||
(other.runtimeType == runtimeType && |
||||
other is _$_StationArrDep && |
||||
(identical(other.stoppingTime, stoppingTime) || |
||||
other.stoppingTime == stoppingTime) && |
||||
(identical(other.time, time) || other.time == time) && |
||||
(identical(other.train, train) || other.train == train) && |
||||
(identical(other.status, status) || other.status == status)); |
||||
} |
||||
|
||||
@JsonKey(ignore: true) |
||||
@override |
||||
int get hashCode => |
||||
Object.hash(runtimeType, stoppingTime, time, train, status); |
||||
|
||||
@JsonKey(ignore: true) |
||||
@override |
||||
@pragma('vm:prefer-inline') |
||||
_$$_StationArrDepCopyWith<_$_StationArrDep> get copyWith => |
||||
__$$_StationArrDepCopyWithImpl<_$_StationArrDep>(this, _$identity); |
||||
|
||||
@override |
||||
Map<String, dynamic> toJson() { |
||||
return _$$_StationArrDepToJson( |
||||
this, |
||||
); |
||||
} |
||||
} |
||||
|
||||
abstract class _StationArrDep implements StationArrDep { |
||||
const factory _StationArrDep( |
||||
{required final int? stoppingTime, |
||||
required final DateTime time, |
||||
required final StationTrain train, |
||||
required final StationStatus status}) = _$_StationArrDep; |
||||
|
||||
factory _StationArrDep.fromJson(Map<String, dynamic> json) = |
||||
_$_StationArrDep.fromJson; |
||||
|
||||
@override |
||||
int? get stoppingTime; |
||||
@override |
||||
DateTime get time; |
||||
@override |
||||
StationTrain get train; |
||||
@override |
||||
StationStatus get status; |
||||
@override |
||||
@JsonKey(ignore: true) |
||||
_$$_StationArrDepCopyWith<_$_StationArrDep> get copyWith => |
||||
throw _privateConstructorUsedError; |
||||
} |
@ -0,0 +1,23 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||
|
||||
part of 'station_arrdep.dart'; |
||||
|
||||
// ************************************************************************** |
||||
// JsonSerializableGenerator |
||||
// ************************************************************************** |
||||
|
||||
_$_StationArrDep _$$_StationArrDepFromJson(Map<String, dynamic> json) => |
||||
_$_StationArrDep( |
||||
stoppingTime: json['stoppingTime'] as int?, |
||||
time: DateTime.parse(json['time'] as String), |
||||
train: StationTrain.fromJson(json['train'] as Map<String, dynamic>), |
||||
status: StationStatus.fromJson(json['status'] as Map<String, dynamic>), |
||||
); |
||||
|
||||
Map<String, dynamic> _$$_StationArrDepToJson(_$_StationArrDep instance) => |
||||
<String, dynamic>{ |
||||
'stoppingTime': instance.stoppingTime, |
||||
'time': instance.time.toIso8601String(), |
||||
'train': instance.train, |
||||
'status': instance.status, |
||||
}; |
@ -1,68 +1,17 @@
|
||||
import 'package:json_annotation/json_annotation.dart'; |
||||
import 'package:freezed_annotation/freezed_annotation.dart'; |
||||
import 'package:info_tren/models.dart'; |
||||
|
||||
part 'station_data.g.dart'; |
||||
part 'station_data.freezed.dart'; |
||||
|
||||
@JsonSerializable() |
||||
class StationData { |
||||
final String date; |
||||
final String stationName; |
||||
final List<StationArrival>? arrivals; |
||||
final List<StationDeparture>? departures; |
||||
|
||||
const StationData({required this.date, required this.stationName, required this.arrivals, required this.departures}); |
||||
@freezed |
||||
class StationData with _$StationData { |
||||
const factory StationData({ |
||||
required String date, |
||||
required String stationName, |
||||
required List<StationArrDep>? arrivals, |
||||
required List<StationArrDep>? departures, |
||||
}) = _StationData; |
||||
|
||||
factory StationData.fromJson(Map<String, dynamic> json) => _$StationDataFromJson(json); |
||||
Map<String, dynamic> toJson() => _$StationDataToJson(this); |
||||
} |
||||
|
||||
@JsonSerializable() |
||||
class StationArrival { |
||||
final int? stoppingTime; |
||||
final DateTime time; |
||||
final StationTrainArr train; |
||||
|
||||
const StationArrival({required this.stoppingTime, required this.time, required this.train,}); |
||||
|
||||
factory StationArrival.fromJson(Map<String, dynamic> json) => _$StationArrivalFromJson(json); |
||||
Map<String, dynamic> toJson() => _$StationArrivalToJson(this); |
||||
} |
||||
|
||||
@JsonSerializable() |
||||
class StationDeparture { |
||||
final int? stoppingTime; |
||||
final DateTime time; |
||||
final StationTrainDep train; |
||||
|
||||
const StationDeparture({required this.stoppingTime, required this.time, required this.train,}); |
||||
|
||||
factory StationDeparture.fromJson(Map<String, dynamic> json) => _$StationDepartureFromJson(json); |
||||
Map<String, dynamic> toJson() => _$StationDepartureToJson(this); |
||||
} |
||||
|
||||
@JsonSerializable() |
||||
class StationTrainArr { |
||||
final String rank; |
||||
final String number; |
||||
final String operator; |
||||
final String origin; |
||||
final List<String>? route; |
||||
|
||||
StationTrainArr({required this.rank, required this.number, required this.operator, required this.origin, this.route,}); |
||||
|
||||
factory StationTrainArr.fromJson(Map<String, dynamic> json) => _$StationTrainArrFromJson(json); |
||||
Map<String, dynamic> toJson() => _$StationTrainArrToJson(this); |
||||
} |
||||
|
||||
@JsonSerializable() |
||||
class StationTrainDep { |
||||
final String rank; |
||||
final String number; |
||||
final String operator; |
||||
final String destination; |
||||
final List<String>? route; |
||||
|
||||
StationTrainDep({required this.rank, required this.number, required this.operator, required this.destination, this.route,}); |
||||
|
||||
factory StationTrainDep.fromJson(Map<String, dynamic> json) => _$StationTrainDepFromJson(json); |
||||
Map<String, dynamic> toJson() => _$StationTrainDepToJson(this); |
||||
} |
||||
|
@ -0,0 +1,239 @@
|
||||
// coverage:ignore-file |
||||
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||
// ignore_for_file: type=lint |
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark |
||||
|
||||
part of 'station_data.dart'; |
||||
|
||||
// ************************************************************************** |
||||
// FreezedGenerator |
||||
// ************************************************************************** |
||||
|
||||
T _$identity<T>(T value) => value; |
||||
|
||||
final _privateConstructorUsedError = UnsupportedError( |
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); |
||||
|
||||
StationData _$StationDataFromJson(Map<String, dynamic> json) { |
||||
return _StationData.fromJson(json); |
||||
} |
||||
|
||||
/// @nodoc |
||||
mixin _$StationData { |
||||
String get date => throw _privateConstructorUsedError; |
||||
String get stationName => throw _privateConstructorUsedError; |
||||
List<StationArrDep>? get arrivals => throw _privateConstructorUsedError; |
||||
List<StationArrDep>? get departures => throw _privateConstructorUsedError; |
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError; |
||||
@JsonKey(ignore: true) |
||||
$StationDataCopyWith<StationData> get copyWith => |
||||
throw _privateConstructorUsedError; |
||||
} |
||||
|
||||
/// @nodoc |
||||
abstract class $StationDataCopyWith<$Res> { |
||||
factory $StationDataCopyWith( |
||||
StationData value, $Res Function(StationData) then) = |
||||
_$StationDataCopyWithImpl<$Res, StationData>; |
||||
@useResult |
||||
$Res call( |
||||
{String date, |
||||
String stationName, |
||||
List<StationArrDep>? arrivals, |
||||
List<StationArrDep>? departures}); |
||||
} |
||||
|
||||
/// @nodoc |
||||
class _$StationDataCopyWithImpl<$Res, $Val extends StationData> |
||||
implements $StationDataCopyWith<$Res> { |
||||
_$StationDataCopyWithImpl(this._value, this._then); |
||||
|
||||
// ignore: unused_field |
||||
final $Val _value; |
||||
// ignore: unused_field |
||||
final $Res Function($Val) _then; |
||||
|
||||
@pragma('vm:prefer-inline') |
||||
@override |
||||
$Res call({ |
||||
Object? date = null, |
||||
Object? stationName = null, |
||||
Object? arrivals = freezed, |
||||
Object? departures = freezed, |
||||
}) { |
||||
return _then(_value.copyWith( |
||||
date: null == date |
||||
? _value.date |
||||
: date // ignore: cast_nullable_to_non_nullable |
||||
as String, |
||||
stationName: null == stationName |
||||
? _value.stationName |
||||
: stationName // ignore: cast_nullable_to_non_nullable |
||||
as String, |
||||
arrivals: freezed == arrivals |
||||
? _value.arrivals |
||||
: arrivals // ignore: cast_nullable_to_non_nullable |
||||
as List<StationArrDep>?, |
||||
departures: freezed == departures |
||||
? _value.departures |
||||
: departures // ignore: cast_nullable_to_non_nullable |
||||
as List<StationArrDep>?, |
||||
) as $Val); |
||||
} |
||||
} |
||||
|
||||
/// @nodoc |
||||
abstract class _$$_StationDataCopyWith<$Res> |
||||
implements $StationDataCopyWith<$Res> { |
||||
factory _$$_StationDataCopyWith( |
||||
_$_StationData value, $Res Function(_$_StationData) then) = |
||||
__$$_StationDataCopyWithImpl<$Res>; |
||||
@override |
||||
@useResult |
||||
$Res call( |
||||
{String date, |
||||
String stationName, |
||||
List<StationArrDep>? arrivals, |
||||
List<StationArrDep>? departures}); |
||||
} |
||||
|
||||
/// @nodoc |
||||
class __$$_StationDataCopyWithImpl<$Res> |
||||
extends _$StationDataCopyWithImpl<$Res, _$_StationData> |
||||
implements _$$_StationDataCopyWith<$Res> { |
||||
__$$_StationDataCopyWithImpl( |
||||
_$_StationData _value, $Res Function(_$_StationData) _then) |
||||
: super(_value, _then); |
||||
|
||||
@pragma('vm:prefer-inline') |
||||
@override |
||||
$Res call({ |
||||
Object? date = null, |
||||
Object? stationName = null, |
||||
Object? arrivals = freezed, |
||||
Object? departures = freezed, |
||||
}) { |
||||
return _then(_$_StationData( |
||||
date: null == date |
||||
? _value.date |
||||
: date // ignore: cast_nullable_to_non_nullable |
||||
as String, |
||||
stationName: null == stationName |
||||
? _value.stationName |
||||
: stationName // ignore: cast_nullable_to_non_nullable |
||||
as String, |
||||
arrivals: freezed == arrivals |
||||
? _value._arrivals |
||||
: arrivals // ignore: cast_nullable_to_non_nullable |
||||
as List<StationArrDep>?, |
||||
departures: freezed == departures |
||||
? _value._departures |
||||
: departures // ignore: cast_nullable_to_non_nullable |
||||
as List<StationArrDep>?, |
||||
)); |
||||
} |
||||
} |
||||
|
||||
/// @nodoc |
||||
@JsonSerializable() |
||||
class _$_StationData implements _StationData { |
||||
const _$_StationData( |
||||
{required this.date, |
||||
required this.stationName, |
||||
required final List<StationArrDep>? arrivals, |
||||
required final List<StationArrDep>? departures}) |
||||
: _arrivals = arrivals, |
||||
_departures = departures; |
||||
|
||||
factory _$_StationData.fromJson(Map<String, dynamic> json) => |
||||
_$$_StationDataFromJson(json); |
||||
|
||||
@override |
||||
final String date; |
||||
@override |
||||
final String stationName; |
||||
final List<StationArrDep>? _arrivals; |
||||
@override |
||||
List<StationArrDep>? get arrivals { |
||||
final value = _arrivals; |
||||
if (value == null) return null; |
||||
if (_arrivals is EqualUnmodifiableListView) return _arrivals; |
||||
// ignore: implicit_dynamic_type |
||||
return EqualUnmodifiableListView(value); |
||||
} |
||||
|
||||
final List<StationArrDep>? _departures; |
||||
@override |
||||
List<StationArrDep>? get departures { |
||||
final value = _departures; |
||||
if (value == null) return null; |
||||
if (_departures is EqualUnmodifiableListView) return _departures; |
||||
// ignore: implicit_dynamic_type |
||||
return EqualUnmodifiableListView(value); |
||||
} |
||||
|
||||
@override |
||||
String toString() { |
||||
return 'StationData(date: $date, stationName: $stationName, arrivals: $arrivals, departures: $departures)'; |
||||
} |
||||
|
||||
@override |
||||
bool operator ==(dynamic other) { |
||||
return identical(this, other) || |
||||
(other.runtimeType == runtimeType && |
||||
other is _$_StationData && |
||||
(identical(other.date, date) || other.date == date) && |
||||
(identical(other.stationName, stationName) || |
||||
other.stationName == stationName) && |
||||
const DeepCollectionEquality().equals(other._arrivals, _arrivals) && |
||||
const DeepCollectionEquality() |
||||
.equals(other._departures, _departures)); |
||||
} |
||||
|
||||
@JsonKey(ignore: true) |
||||
@override |
||||
int get hashCode => Object.hash( |
||||
runtimeType, |
||||
date, |
||||
stationName, |
||||
const DeepCollectionEquality().hash(_arrivals), |
||||
const DeepCollectionEquality().hash(_departures)); |
||||
|
||||
@JsonKey(ignore: true) |
||||
@override |
||||
@pragma('vm:prefer-inline') |
||||
_$$_StationDataCopyWith<_$_StationData> get copyWith => |
||||
__$$_StationDataCopyWithImpl<_$_StationData>(this, _$identity); |
||||
|
||||
@override |
||||
Map<String, dynamic> toJson() { |
||||
return _$$_StationDataToJson( |
||||
this, |
||||
); |
||||
} |
||||
} |
||||
|
||||
abstract class _StationData implements StationData { |
||||
const factory _StationData( |
||||
{required final String date, |
||||
required final String stationName, |
||||
required final List<StationArrDep>? arrivals, |
||||
required final List<StationArrDep>? departures}) = _$_StationData; |
||||
|
||||
factory _StationData.fromJson(Map<String, dynamic> json) = |
||||
_$_StationData.fromJson; |
||||
|
||||
@override |
||||
String get date; |
||||
@override |
||||
String get stationName; |
||||
@override |
||||
List<StationArrDep>? get arrivals; |
||||
@override |
||||
List<StationArrDep>? get departures; |
||||
@override |
||||
@JsonKey(ignore: true) |
||||
_$$_StationDataCopyWith<_$_StationData> get copyWith => |
||||
throw _privateConstructorUsedError; |
||||
} |
@ -0,0 +1,17 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart'; |
||||
|
||||
part 'station_status.g.dart'; |
||||
part 'station_status.freezed.dart'; |
||||
|
||||
@freezed |
||||
class StationStatus with _$StationStatus { |
||||
const factory StationStatus({ |
||||
required int delay, |
||||
required bool real, |
||||
required bool cancelled, |
||||
required String? platform, |
||||
}) = _StationStatus; |
||||
|
||||
factory StationStatus.fromJson(Map<String, dynamic> json) => _$StationStatusFromJson(json); |
||||
} |
||||
|
@ -0,0 +1,210 @@
|
||||
// coverage:ignore-file |
||||
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||
// ignore_for_file: type=lint |
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark |
||||
|
||||
part of 'station_status.dart'; |
||||
|
||||
// ************************************************************************** |
||||
// FreezedGenerator |
||||
// ************************************************************************** |
||||
|
||||
T _$identity<T>(T value) => value; |
||||
|
||||
final _privateConstructorUsedError = UnsupportedError( |
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); |
||||
|
||||
StationStatus _$StationStatusFromJson(Map<String, dynamic> json) { |
||||
return _StationStatus.fromJson(json); |
||||
} |
||||
|
||||
/// @nodoc |
||||
mixin _$StationStatus { |
||||
int get delay => throw _privateConstructorUsedError; |
||||
bool get real => throw _privateConstructorUsedError; |
||||
bool get cancelled => throw _privateConstructorUsedError; |
||||
String? get platform => throw _privateConstructorUsedError; |
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError; |
||||
@JsonKey(ignore: true) |
||||
$StationStatusCopyWith<StationStatus> get copyWith => |
||||
throw _privateConstructorUsedError; |
||||
} |
||||
|
||||
/// @nodoc |
||||
abstract class $StationStatusCopyWith<$Res> { |
||||
factory $StationStatusCopyWith( |
||||
StationStatus value, $Res Function(StationStatus) then) = |
||||
_$StationStatusCopyWithImpl<$Res, StationStatus>; |
||||
@useResult |
||||
$Res call({int delay, bool real, bool cancelled, String? platform}); |
||||
} |
||||
|
||||
/// @nodoc |
||||
class _$StationStatusCopyWithImpl<$Res, $Val extends StationStatus> |
||||
implements $StationStatusCopyWith<$Res> { |
||||
_$StationStatusCopyWithImpl(this._value, this._then); |
||||
|
||||
// ignore: unused_field |
||||
final $Val _value; |
||||
// ignore: unused_field |
||||
final $Res Function($Val) _then; |
||||
|
||||
@pragma('vm:prefer-inline') |
||||
@override |
||||
$Res call({ |
||||
Object? delay = null, |
||||
Object? real = null, |
||||
Object? cancelled = null, |
||||
Object? platform = freezed, |
||||
}) { |
||||
return _then(_value.copyWith( |
||||
delay: null == delay |
||||
? _value.delay |
||||
: delay // ignore: cast_nullable_to_non_nullable |
||||
as int, |
||||
real: null == real |
||||
? _value.real |
||||
: real // ignore: cast_nullable_to_non_nullable |
||||
as bool, |
||||
cancelled: null == cancelled |
||||
? _value.cancelled |
||||
: cancelled // ignore: cast_nullable_to_non_nullable |
||||
as bool, |
||||
platform: freezed == platform |
||||
? _value.platform |
||||
: platform // ignore: cast_nullable_to_non_nullable |
||||
as String?, |
||||
) as $Val); |
||||
} |
||||
} |
||||
|
||||
/// @nodoc |
||||
abstract class _$$_StationStatusCopyWith<$Res> |
||||
implements $StationStatusCopyWith<$Res> { |
||||
factory _$$_StationStatusCopyWith( |
||||
_$_StationStatus value, $Res Function(_$_StationStatus) then) = |
||||
__$$_StationStatusCopyWithImpl<$Res>; |
||||
@override |
||||
@useResult |
||||
$Res call({int delay, bool real, bool cancelled, String? platform}); |
||||
} |
||||
|
||||
/// @nodoc |
||||
class __$$_StationStatusCopyWithImpl<$Res> |
||||
extends _$StationStatusCopyWithImpl<$Res, _$_StationStatus> |
||||
implements _$$_StationStatusCopyWith<$Res> { |
||||
__$$_StationStatusCopyWithImpl( |
||||
_$_StationStatus _value, $Res Function(_$_StationStatus) _then) |
||||
: super(_value, _then); |
||||
|
||||
@pragma('vm:prefer-inline') |
||||
@override |
||||
$Res call({ |
||||
Object? delay = null, |
||||
Object? real = null, |
||||
Object? cancelled = null, |
||||
Object? platform = freezed, |
||||
}) { |
||||
return _then(_$_StationStatus( |
||||
delay: null == delay |
||||
? _value.delay |
||||
: delay // ignore: cast_nullable_to_non_nullable |
||||
as int, |
||||
real: null == real |
||||
? _value.real |
||||
: real // ignore: cast_nullable_to_non_nullable |
||||
as bool, |
||||
cancelled: null == cancelled |
||||
? _value.cancelled |
||||
: cancelled // ignore: cast_nullable_to_non_nullable |
||||
as bool, |
||||
platform: freezed == platform |
||||
? _value.platform |
||||
: platform // ignore: cast_nullable_to_non_nullable |
||||
as String?, |
||||
)); |
||||
} |
||||
} |
||||
|
||||
/// @nodoc |
||||
@JsonSerializable() |
||||
class _$_StationStatus implements _StationStatus { |
||||
const _$_StationStatus( |
||||
{required this.delay, |
||||
required this.real, |
||||
required this.cancelled, |
||||
required this.platform}); |
||||
|
||||
factory _$_StationStatus.fromJson(Map<String, dynamic> json) => |
||||
_$$_StationStatusFromJson(json); |
||||
|
||||
@override |
||||
final int delay; |
||||
@override |
||||
final bool real; |
||||
@override |
||||
final bool cancelled; |
||||
@override |
||||
final String? platform; |
||||
|
||||
@override |
||||
String toString() { |
||||
return 'StationStatus(delay: $delay, real: $real, cancelled: $cancelled, platform: $platform)'; |
||||
} |
||||
|
||||
@override |
||||
bool operator ==(dynamic other) { |
||||
return identical(this, other) || |
||||
(other.runtimeType == runtimeType && |
||||
other is _$_StationStatus && |
||||
(identical(other.delay, delay) || other.delay == delay) && |
||||
(identical(other.real, real) || other.real == real) && |
||||
(identical(other.cancelled, cancelled) || |
||||
other.cancelled == cancelled) && |
||||
(identical(other.platform, platform) || |
||||
other.platform == platform)); |
||||
} |
||||
|
||||
@JsonKey(ignore: true) |
||||
@override |
||||
int get hashCode => |
||||
Object.hash(runtimeType, delay, real, cancelled, platform); |
||||
|
||||
@JsonKey(ignore: true) |
||||
@override |
||||
@pragma('vm:prefer-inline') |
||||
_$$_StationStatusCopyWith<_$_StationStatus> get copyWith => |
||||
__$$_StationStatusCopyWithImpl<_$_StationStatus>(this, _$identity); |
||||
|
||||
@override |
||||
Map<String, dynamic> toJson() { |
||||
return _$$_StationStatusToJson( |
||||
this, |
||||
); |
||||
} |
||||
} |
||||
|
||||
abstract class _StationStatus implements StationStatus { |
||||
const factory _StationStatus( |
||||
{required final int delay, |
||||
required final bool real, |
||||
required final bool cancelled, |
||||
required final String? platform}) = _$_StationStatus; |
||||
|
||||
factory _StationStatus.fromJson(Map<String, dynamic> json) = |
||||
_$_StationStatus.fromJson; |
||||
|
||||
@override |
||||
int get delay; |
||||
@override |
||||
bool get real; |
||||
@override |
||||
bool get cancelled; |
||||
@override |
||||
String? get platform; |
||||
@override |
||||
@JsonKey(ignore: true) |
||||
_$$_StationStatusCopyWith<_$_StationStatus> get copyWith => |
||||
throw _privateConstructorUsedError; |
||||
} |
@ -0,0 +1,23 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||
|
||||
part of 'station_status.dart'; |
||||
|
||||
// ************************************************************************** |
||||
// JsonSerializableGenerator |
||||
// ************************************************************************** |
||||
|
||||
_$_StationStatus _$$_StationStatusFromJson(Map<String, dynamic> json) => |
||||
_$_StationStatus( |
||||
delay: json['delay'] as int, |
||||
real: json['real'] as bool, |
||||
cancelled: json['cancelled'] as bool, |
||||
platform: json['platform'] as String?, |
||||
); |
||||
|
||||
Map<String, dynamic> _$$_StationStatusToJson(_$_StationStatus instance) => |
||||
<String, dynamic>{ |
||||
'delay': instance.delay, |
||||
'real': instance.real, |
||||
'cancelled': instance.cancelled, |
||||
'platform': instance.platform, |
||||
}; |
@ -0,0 +1,19 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart'; |
||||
|
||||
part 'station_train.g.dart'; |
||||
part 'station_train.freezed.dart'; |
||||
|
||||
@freezed |
||||
class StationTrain with _$StationTrain { |
||||
const factory StationTrain({ |
||||
required String rank, |
||||
required String number, |
||||
required String operator, |
||||
required String terminus, |
||||
List<String>? route, |
||||
required DateTime departureDate, |
||||
}) = _StationTrain; |
||||
|
||||
factory StationTrain.fromJson(Map<String, dynamic> json) => _$StationTrainFromJson(json); |
||||
} |
||||
|
@ -0,0 +1,268 @@
|
||||
// coverage:ignore-file |
||||
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||
// ignore_for_file: type=lint |
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark |
||||
|
||||
part of 'station_train.dart'; |
||||
|
||||
// ************************************************************************** |
||||
// FreezedGenerator |
||||
// ************************************************************************** |
||||
|
||||
T _$identity<T>(T value) => value; |
||||
|
||||
final _privateConstructorUsedError = UnsupportedError( |
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); |
||||
|
||||
StationTrain _$StationTrainFromJson(Map<String, dynamic> json) { |
||||
return _StationTrain.fromJson(json); |
||||
} |
||||
|
||||
/// @nodoc |
||||
mixin _$StationTrain { |
||||
String get rank => throw _privateConstructorUsedError; |
||||
String get number => throw _privateConstructorUsedError; |
||||
String get operator => throw _privateConstructorUsedError; |
||||
String get terminus => throw _privateConstructorUsedError; |
||||
List<String>? get route => throw _privateConstructorUsedError; |
||||
DateTime get departureDate => throw _privateConstructorUsedError; |
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError; |
||||
@JsonKey(ignore: true) |
||||
$StationTrainCopyWith<StationTrain> get copyWith => |
||||
throw _privateConstructorUsedError; |
||||
} |
||||
|
||||
/// @nodoc |
||||
abstract class $StationTrainCopyWith<$Res> { |
||||
factory $StationTrainCopyWith( |
||||
StationTrain value, $Res Function(StationTrain) then) = |
||||
_$StationTrainCopyWithImpl<$Res, StationTrain>; |
||||
@useResult |
||||
$Res call( |
||||
{String rank, |
||||
String number, |
||||
String operator, |
||||
String terminus, |
||||
List<String>? route, |
||||
DateTime departureDate}); |
||||
} |
||||
|
||||
/// @nodoc |
||||
class _$StationTrainCopyWithImpl<$Res, $Val extends StationTrain> |
||||
implements $StationTrainCopyWith<$Res> { |
||||
_$StationTrainCopyWithImpl(this._value, this._then); |
||||
|
||||
// ignore: unused_field |
||||
final $Val _value; |
||||
// ignore: unused_field |
||||
final $Res Function($Val) _then; |
||||
|
||||
@pragma('vm:prefer-inline') |
||||
@override |
||||
$Res call({ |
||||
Object? rank = null, |
||||
Object? number = null, |
||||
Object? operator = null, |
||||
Object? terminus = null, |
||||
Object? route = freezed, |
||||
Object? departureDate = null, |
||||
}) { |
||||
return _then(_value.copyWith( |
||||
rank: null == rank |
||||
? _value.rank |
||||
: rank // ignore: cast_nullable_to_non_nullable |
||||
as String, |
||||
number: null == number |
||||
? _value.number |
||||
: number // ignore: cast_nullable_to_non_nullable |
||||
as String, |
||||
operator: null == operator |
||||
? _value.operator |
||||
: operator // ignore: cast_nullable_to_non_nullable |
||||
as String, |
||||
terminus: null == terminus |
||||
? _value.terminus |
||||
: terminus // ignore: cast_nullable_to_non_nullable |
||||
as String, |
||||
route: freezed == route |
||||
? _value.route |
||||
: route // ignore: cast_nullable_to_non_nullable |
||||
as List<String>?, |
||||
departureDate: null == departureDate |
||||
? _value.departureDate |
||||
: departureDate // ignore: cast_nullable_to_non_nullable |
||||
as DateTime, |
||||
) as $Val); |
||||
} |
||||
} |
||||
|
||||
/// @nodoc |
||||
abstract class _$$_StationTrainCopyWith<$Res> |
||||
implements $StationTrainCopyWith<$Res> { |
||||
factory _$$_StationTrainCopyWith( |
||||
_$_StationTrain value, $Res Function(_$_StationTrain) then) = |
||||
__$$_StationTrainCopyWithImpl<$Res>; |
||||
@override |
||||
@useResult |
||||
$Res call( |
||||
{String rank, |
||||
String number, |
||||
String operator, |
||||
String terminus, |
||||
List<String>? route, |
||||
DateTime departureDate}); |
||||
} |
||||
|
||||
/// @nodoc |
||||
class __$$_StationTrainCopyWithImpl<$Res> |
||||
extends _$StationTrainCopyWithImpl<$Res, _$_StationTrain> |
||||
implements _$$_StationTrainCopyWith<$Res> { |
||||
__$$_StationTrainCopyWithImpl( |
||||
_$_StationTrain _value, $Res Function(_$_StationTrain) _then) |
||||
: super(_value, _then); |
||||
|
||||
@pragma('vm:prefer-inline') |
||||
@override |
||||
$Res call({ |
||||
Object? rank = null, |
||||
Object? number = null, |
||||
Object? operator = null, |
||||
Object? terminus = null, |
||||
Object? route = freezed, |
||||
Object? departureDate = null, |
||||
}) { |
||||
return _then(_$_StationTrain( |
||||
rank: null == rank |
||||
? _value.rank |
||||
: rank // ignore: cast_nullable_to_non_nullable |
||||
as String, |
||||
number: null == number |
||||
? _value.number |
||||
: number // ignore: cast_nullable_to_non_nullable |
||||
as String, |
||||
operator: null == operator |
||||
? _value.operator |
||||
: operator // ignore: cast_nullable_to_non_nullable |
||||
as String, |
||||
terminus: null == terminus |
||||
? _value.terminus |
||||
: terminus // ignore: cast_nullable_to_non_nullable |
||||
as String, |
||||
route: freezed == route |
||||
? _value._route |
||||
: route // ignore: cast_nullable_to_non_nullable |
||||
as List<String>?, |
||||
departureDate: null == departureDate |
||||
? _value.departureDate |
||||
: departureDate // ignore: cast_nullable_to_non_nullable |
||||
as DateTime, |
||||
)); |
||||
} |
||||
} |
||||
|
||||
/// @nodoc |
||||
@JsonSerializable() |
||||
class _$_StationTrain implements _StationTrain { |
||||
const _$_StationTrain( |
||||
{required this.rank, |
||||
required this.number, |
||||
required this.operator, |
||||
required this.terminus, |
||||
final List<String>? route, |
||||
required this.departureDate}) |
||||
: _route = route; |
||||
|
||||
factory _$_StationTrain.fromJson(Map<String, dynamic> json) => |
||||
_$$_StationTrainFromJson(json); |
||||
|
||||
@override |
||||
final String rank; |
||||
@override |
||||
final String number; |
||||
@override |
||||
final String operator; |
||||
@override |
||||
final String terminus; |
||||
final List<String>? _route; |
||||
@override |
||||
List<String>? get route { |
||||
final value = _route; |
||||
if (value == null) return null; |
||||
if (_route is EqualUnmodifiableListView) return _route; |
||||
// ignore: implicit_dynamic_type |
||||
return EqualUnmodifiableListView(value); |
||||
} |
||||
|
||||
@override |
||||
final DateTime departureDate; |
||||
|
||||
@override |
||||
String toString() { |
||||
return 'StationTrain(rank: $rank, number: $number, operator: $operator, terminus: $terminus, route: $route, departureDate: $departureDate)'; |
||||
} |
||||
|
||||
@override |
||||
bool operator ==(dynamic other) { |
||||
return identical(this, other) || |
||||
(other.runtimeType == runtimeType && |
||||
other is _$_StationTrain && |
||||
(identical(other.rank, rank) || other.rank == rank) && |
||||
(identical(other.number, number) || other.number == number) && |
||||
(identical(other.operator, operator) || |
||||
other.operator == operator) && |
||||
(identical(other.terminus, terminus) || |
||||
other.terminus == terminus) && |
||||
const DeepCollectionEquality().equals(other._route, _route) && |
||||
(identical(other.departureDate, departureDate) || |
||||
other.departureDate == departureDate)); |
||||
} |
||||
|
||||
@JsonKey(ignore: true) |
||||
@override |
||||
int get hashCode => Object.hash(runtimeType, rank, number, operator, terminus, |
||||
const DeepCollectionEquality().hash(_route), departureDate); |
||||
|
||||
@JsonKey(ignore: true) |
||||
@override |
||||
@pragma('vm:prefer-inline') |
||||
_$$_StationTrainCopyWith<_$_StationTrain> get copyWith => |
||||
__$$_StationTrainCopyWithImpl<_$_StationTrain>(this, _$identity); |
||||
|
||||
@override |
||||
Map<String, dynamic> toJson() { |
||||
return _$$_StationTrainToJson( |
||||
this, |
||||
); |
||||
} |
||||
} |
||||
|
||||
abstract class _StationTrain implements StationTrain { |
||||
const factory _StationTrain( |
||||
{required final String rank, |
||||
required final String number, |
||||
required final String operator, |
||||
required final String terminus, |
||||
final List<String>? route, |
||||
required final DateTime departureDate}) = _$_StationTrain; |
||||
|
||||
factory _StationTrain.fromJson(Map<String, dynamic> json) = |
||||
_$_StationTrain.fromJson; |
||||
|
||||
@override |
||||
String get rank; |
||||
@override |
||||
String get number; |
||||
@override |
||||
String get operator; |
||||
@override |
||||
String get terminus; |
||||
@override |
||||
List<String>? get route; |
||||
@override |
||||
DateTime get departureDate; |
||||
@override |
||||
@JsonKey(ignore: true) |
||||
_$$_StationTrainCopyWith<_$_StationTrain> get copyWith => |
||||
throw _privateConstructorUsedError; |
||||
} |
@ -0,0 +1,28 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||
|
||||
part of 'station_train.dart'; |
||||
|
||||
// ************************************************************************** |
||||
// JsonSerializableGenerator |
||||
// ************************************************************************** |
||||
|
||||
_$_StationTrain _$$_StationTrainFromJson(Map<String, dynamic> json) => |
||||
_$_StationTrain( |
||||
rank: json['rank'] as String, |
||||
number: json['number'] as String, |
||||
operator: json['operator'] as String, |
||||
terminus: json['terminus'] as String, |
||||
route: |
||||
(json['route'] as List<dynamic>?)?.map((e) => e as String).toList(), |
||||
departureDate: DateTime.parse(json['departureDate'] as String), |
||||
); |
||||
|
||||
Map<String, dynamic> _$$_StationTrainToJson(_$_StationTrain instance) => |
||||
<String, dynamic>{ |
||||
'rank': instance.rank, |
||||
'number': instance.number, |
||||
'operator': instance.operator, |
||||
'terminus': instance.terminus, |
||||
'route': instance.route, |
||||
'departureDate': instance.departureDate.toIso8601String(), |
||||
}; |
@ -1,14 +1,14 @@
|
||||
import 'package:json_annotation/json_annotation.dart'; |
||||
import 'package:freezed_annotation/freezed_annotation.dart'; |
||||
|
||||
part 'stations_result.g.dart'; |
||||
part 'stations_result.freezed.dart'; |
||||
|
||||
@JsonSerializable() |
||||
class StationsResult { |
||||
final String name; |
||||
final List<String>? stoppedAtBy; |
||||
|
||||
const StationsResult({required this.name, this.stoppedAtBy}); |
||||
@freezed |
||||
class StationsResult with _$StationsResult { |
||||
const factory StationsResult({ |
||||
required String name, |
||||
List<String>? stoppedAtBy, |
||||
}) = _StationsResult; |
||||
|
||||
factory StationsResult.fromJson(Map<String, dynamic> json) => _$StationsResultFromJson(json); |
||||
Map<String, dynamic> toJson() => _$StationsResultToJson(this); |
||||
} |
||||
|
@ -0,0 +1,179 @@
|
||||
// coverage:ignore-file |
||||
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||
// ignore_for_file: type=lint |
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark |
||||
|
||||
part of 'stations_result.dart'; |
||||
|
||||
// ************************************************************************** |
||||
// FreezedGenerator |
||||
// ************************************************************************** |
||||
|
||||
T _$identity<T>(T value) => value; |
||||
|
||||
final _privateConstructorUsedError = UnsupportedError( |
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); |
||||
|
||||
StationsResult _$StationsResultFromJson(Map<String, dynamic> json) { |
||||
return _StationsResult.fromJson(json); |
||||
} |
||||
|
||||
/// @nodoc |
||||
mixin _$StationsResult { |
||||
String get name => throw _privateConstructorUsedError; |
||||
List<String>? get stoppedAtBy => throw _privateConstructorUsedError; |
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError; |
||||
@JsonKey(ignore: true) |
||||
$StationsResultCopyWith<StationsResult> get copyWith => |
||||
throw _privateConstructorUsedError; |
||||
} |
||||
|
||||
/// @nodoc |
||||
abstract class $StationsResultCopyWith<$Res> { |
||||
factory $StationsResultCopyWith( |
||||
StationsResult value, $Res Function(StationsResult) then) = |
||||
_$StationsResultCopyWithImpl<$Res, StationsResult>; |
||||
@useResult |
||||
$Res call({String name, List<String>? stoppedAtBy}); |
||||
} |
||||
|
||||
/// @nodoc |
||||
class _$StationsResultCopyWithImpl<$Res, $Val extends StationsResult> |
||||
implements $StationsResultCopyWith<$Res> { |
||||
_$StationsResultCopyWithImpl(this._value, this._then); |
||||
|
||||
// ignore: unused_field |
||||
final $Val _value; |
||||
// ignore: unused_field |
||||
final $Res Function($Val) _then; |
||||
|
||||
@pragma('vm:prefer-inline') |
||||
@override |
||||
$Res call({ |
||||
Object? name = null, |
||||
Object? stoppedAtBy = freezed, |
||||
}) { |
||||
return _then(_value.copyWith( |
||||
name: null == name |
||||
? _value.name |
||||
: name // ignore: cast_nullable_to_non_nullable |
||||
as String, |
||||
stoppedAtBy: freezed == stoppedAtBy |
||||
? _value.stoppedAtBy |
||||
: stoppedAtBy // ignore: cast_nullable_to_non_nullable |
||||
as List<String>?, |
||||
) as $Val); |
||||
} |
||||
} |
||||
|
||||
/// @nodoc |
||||
abstract class _$$_StationsResultCopyWith<$Res> |
||||
implements $StationsResultCopyWith<$Res> { |
||||
factory _$$_StationsResultCopyWith( |
||||
_$_StationsResult value, $Res Function(_$_StationsResult) then) = |
||||
__$$_StationsResultCopyWithImpl<$Res>; |
||||
@override |
||||
@useResult |
||||
$Res call({String name, List<String>? stoppedAtBy}); |
||||
} |
||||
|
||||
/// @nodoc |
||||
class __$$_StationsResultCopyWithImpl<$Res> |
||||
extends _$StationsResultCopyWithImpl<$Res, _$_StationsResult> |
||||
implements _$$_StationsResultCopyWith<$Res> { |
||||
__$$_StationsResultCopyWithImpl( |
||||
_$_StationsResult _value, $Res Function(_$_StationsResult) _then) |
||||
: super(_value, _then); |
||||
|
||||
@pragma('vm:prefer-inline') |
||||
@override |
||||
$Res call({ |
||||
Object? name = null, |
||||
Object? stoppedAtBy = freezed, |
||||
}) { |
||||
return _then(_$_StationsResult( |
||||
name: null == name |
||||
? _value.name |
||||
: name // ignore: cast_nullable_to_non_nullable |
||||
as String, |
||||
stoppedAtBy: freezed == stoppedAtBy |
||||
? _value._stoppedAtBy |
||||
: stoppedAtBy // ignore: cast_nullable_to_non_nullable |
||||
as List<String>?, |
||||
)); |
||||
} |
||||
} |
||||
|
||||
/// @nodoc |
||||
@JsonSerializable() |
||||
class _$_StationsResult implements _StationsResult { |
||||
const _$_StationsResult({required this.name, final List<String>? stoppedAtBy}) |
||||
: _stoppedAtBy = stoppedAtBy; |
||||
|
||||
factory _$_StationsResult.fromJson(Map<String, dynamic> json) => |
||||
_$$_StationsResultFromJson(json); |
||||
|
||||
@override |
||||
final String name; |
||||
final List<String>? _stoppedAtBy; |
||||
@override |
||||
List<String>? get stoppedAtBy { |
||||
final value = _stoppedAtBy; |
||||
if (value == null) return null; |
||||
if (_stoppedAtBy is EqualUnmodifiableListView) return _stoppedAtBy; |
||||
// ignore: implicit_dynamic_type |
||||
return EqualUnmodifiableListView(value); |
||||
} |
||||
|
||||
@override |
||||
String toString() { |
||||
return 'StationsResult(name: $name, stoppedAtBy: $stoppedAtBy)'; |
||||
} |
||||
|
||||
@override |
||||
bool operator ==(dynamic other) { |
||||
return identical(this, other) || |
||||
(other.runtimeType == runtimeType && |
||||
other is _$_StationsResult && |
||||
(identical(other.name, name) || other.name == name) && |
||||
const DeepCollectionEquality() |
||||
.equals(other._stoppedAtBy, _stoppedAtBy)); |
||||
} |
||||
|
||||
@JsonKey(ignore: true) |
||||
@override |
||||
int get hashCode => Object.hash( |
||||
runtimeType, name, const DeepCollectionEquality().hash(_stoppedAtBy)); |
||||
|
||||
@JsonKey(ignore: true) |
||||
@override |
||||
@pragma('vm:prefer-inline') |
||||
_$$_StationsResultCopyWith<_$_StationsResult> get copyWith => |
||||
__$$_StationsResultCopyWithImpl<_$_StationsResult>(this, _$identity); |
||||
|
||||
@override |
||||
Map<String, dynamic> toJson() { |
||||
return _$$_StationsResultToJson( |
||||
this, |
||||
); |
||||
} |
||||
} |
||||
|
||||
abstract class _StationsResult implements StationsResult { |
||||
const factory _StationsResult( |
||||
{required final String name, |
||||
final List<String>? stoppedAtBy}) = _$_StationsResult; |
||||
|
||||
factory _StationsResult.fromJson(Map<String, dynamic> json) = |
||||
_$_StationsResult.fromJson; |
||||
|
||||
@override |
||||
String get name; |
||||
@override |
||||
List<String>? get stoppedAtBy; |
||||
@override |
||||
@JsonKey(ignore: true) |
||||
_$$_StationsResultCopyWith<_$_StationsResult> get copyWith => |
||||
throw _privateConstructorUsedError; |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,217 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||
|
||||
part of 'train_data.dart'; |
||||
|
||||
// ************************************************************************** |
||||
// JsonSerializableGenerator |
||||
// ************************************************************************** |
||||
|
||||
_$_TrainData _$$_TrainDataFromJson(Map<String, dynamic> json) => _$_TrainData( |
||||
rank: json['rank'] as String, |
||||
number: json['number'] as String, |
||||
date: json['date'] as String, |
||||
operator: json['operator'] as String, |
||||
groups: (json['groups'] as List<dynamic>) |
||||
.map((e) => TrainDataGroup.fromJson(e as Map<String, dynamic>)) |
||||
.toList(), |
||||
); |
||||
|
||||
Map<String, dynamic> _$$_TrainDataToJson(_$_TrainData instance) => |
||||
<String, dynamic>{ |
||||
'rank': instance.rank, |
||||
'number': instance.number, |
||||
'date': instance.date, |
||||
'operator': instance.operator, |
||||
'groups': instance.groups, |
||||
}; |
||||
|
||||
_$_TrainDataGroup _$$_TrainDataGroupFromJson(Map<String, dynamic> json) => |
||||
_$_TrainDataGroup( |
||||
route: TrainDataRoute.fromJson(json['route'] as Map<String, dynamic>), |
||||
stations: (json['stations'] as List<dynamic>) |
||||
.map((e) => TrainDataStation.fromJson(e as Map<String, dynamic>)) |
||||
.toList(), |
||||
status: json['status'] == null |
||||
? null |
||||
: TrainDataStatus.fromJson(json['status'] as Map<String, dynamic>), |
||||
); |
||||
|
||||
Map<String, dynamic> _$$_TrainDataGroupToJson(_$_TrainDataGroup instance) => |
||||
<String, dynamic>{ |
||||
'route': instance.route, |
||||
'stations': instance.stations, |
||||
'status': instance.status, |
||||
}; |
||||
|
||||
_$_TrainDataRoute _$$_TrainDataRouteFromJson(Map<String, dynamic> json) => |
||||
_$_TrainDataRoute( |
||||
from: json['from'] as String, |
||||
to: json['to'] as String, |
||||
); |
||||
|
||||
Map<String, dynamic> _$$_TrainDataRouteToJson(_$_TrainDataRoute instance) => |
||||
<String, dynamic>{ |
||||
'from': instance.from, |
||||
'to': instance.to, |
||||
}; |
||||
|
||||
_$_TrainDataStation _$$_TrainDataStationFromJson(Map<String, dynamic> json) => |
||||
_$_TrainDataStation( |
||||
name: json['name'] as String, |
||||
linkName: json['linkName'] as String, |
||||
km: json['km'] as int, |
||||
stoppingTime: json['stoppingTime'] as int?, |
||||
platform: json['platform'] as String?, |
||||
arrival: json['arrival'] == null |
||||
? null |
||||
: StationArrDepTime.fromJson(json['arrival'] as Map<String, dynamic>), |
||||
departure: json['departure'] == null |
||||
? null |
||||
: StationArrDepTime.fromJson( |
||||
json['departure'] as Map<String, dynamic>), |
||||
notes: (json['notes'] as List<dynamic>) |
||||
.map((e) => const TrainDataNoteConverter() |
||||
.fromJson(e as Map<String, dynamic>)) |
||||
.toList(), |
||||
); |
||||
|
||||
Map<String, dynamic> _$$_TrainDataStationToJson(_$_TrainDataStation instance) => |
||||
<String, dynamic>{ |
||||
'name': instance.name, |
||||
'linkName': instance.linkName, |
||||
'km': instance.km, |
||||
'stoppingTime': instance.stoppingTime, |
||||
'platform': instance.platform, |
||||
'arrival': instance.arrival, |
||||
'departure': instance.departure, |
||||
'notes': |
||||
instance.notes.map(const TrainDataNoteConverter().toJson).toList(), |
||||
}; |
||||
|
||||
_$_StationArrDepTime _$$_StationArrDepTimeFromJson(Map<String, dynamic> json) => |
||||
_$_StationArrDepTime( |
||||
scheduleTime: DateTime.parse(json['scheduleTime'] as String), |
||||
status: json['status'] == null |
||||
? null |
||||
: StationArrDepTimeStatus.fromJson( |
||||
json['status'] as Map<String, dynamic>), |
||||
); |
||||
|
||||
Map<String, dynamic> _$$_StationArrDepTimeToJson( |
||||
_$_StationArrDepTime instance) => |
||||
<String, dynamic>{ |
||||
'scheduleTime': instance.scheduleTime.toIso8601String(), |
||||
'status': instance.status, |
||||
}; |
||||
|
||||
_$_StationArrDepTimeStatus _$$_StationArrDepTimeStatusFromJson( |
||||
Map<String, dynamic> json) => |
||||
_$_StationArrDepTimeStatus( |
||||
delay: json['delay'] as int, |
||||
real: json['real'] as bool, |
||||
cancelled: json['cancelled'] as bool, |
||||
); |
||||
|
||||
Map<String, dynamic> _$$_StationArrDepTimeStatusToJson( |
||||
_$_StationArrDepTimeStatus instance) => |
||||
<String, dynamic>{ |
||||
'delay': instance.delay, |
||||
'real': instance.real, |
||||
'cancelled': instance.cancelled, |
||||
}; |
||||
|
||||
_$_TrainDataStatus _$$_TrainDataStatusFromJson(Map<String, dynamic> json) => |
||||
_$_TrainDataStatus( |
||||
delay: json['delay'] as int, |
||||
station: json['station'] as String, |
||||
state: $enumDecode(_$TrainDataStatusStateEnumMap, json['state']), |
||||
); |
||||
|
||||
Map<String, dynamic> _$$_TrainDataStatusToJson(_$_TrainDataStatus instance) => |
||||
<String, dynamic>{ |
||||
'delay': instance.delay, |
||||
'station': instance.station, |
||||
'state': _$TrainDataStatusStateEnumMap[instance.state]!, |
||||
}; |
||||
|
||||
const _$TrainDataStatusStateEnumMap = { |
||||
TrainDataStatusState.passing: 'passing', |
||||
TrainDataStatusState.arrival: 'arrival', |
||||
TrainDataStatusState.departure: 'departure', |
||||
}; |
||||
|
||||
_$_TrainDataNoteTrainNumberChange _$$_TrainDataNoteTrainNumberChangeFromJson( |
||||
Map<String, dynamic> json) => |
||||
_$_TrainDataNoteTrainNumberChange( |
||||
kind: json['kind'] as String? ?? "trainNumberChange", |
||||
rank: json['rank'] as String, |
||||
number: json['number'] as String, |
||||
); |
||||
|
||||
Map<String, dynamic> _$$_TrainDataNoteTrainNumberChangeToJson( |
||||
_$_TrainDataNoteTrainNumberChange instance) => |
||||
<String, dynamic>{ |
||||
'kind': instance.kind, |
||||
'rank': instance.rank, |
||||
'number': instance.number, |
||||
}; |
||||
|
||||
_$_TrainDataNoteDepartsAs _$$_TrainDataNoteDepartsAsFromJson( |
||||
Map<String, dynamic> json) => |
||||
_$_TrainDataNoteDepartsAs( |
||||
kind: json['kind'] as String? ?? "departsAs", |
||||
rank: json['rank'] as String, |
||||
number: json['number'] as String, |
||||
departureDate: DateTime.parse(json['departureDate'] as String), |
||||
); |
||||
|
||||
Map<String, dynamic> _$$_TrainDataNoteDepartsAsToJson( |
||||
_$_TrainDataNoteDepartsAs instance) => |
||||
<String, dynamic>{ |
||||
'kind': instance.kind, |
||||
'rank': instance.rank, |
||||
'number': instance.number, |
||||
'departureDate': instance.departureDate.toIso8601String(), |
||||
}; |
||||
|
||||
_$_TrainDataNoteDetachingWagons _$$_TrainDataNoteDetachingWagonsFromJson( |
||||
Map<String, dynamic> json) => |
||||
_$_TrainDataNoteDetachingWagons( |
||||
kind: json['kind'] as String? ?? "detachingWagons", |
||||
station: json['station'] as String, |
||||
); |
||||
|
||||
Map<String, dynamic> _$$_TrainDataNoteDetachingWagonsToJson( |
||||
_$_TrainDataNoteDetachingWagons instance) => |
||||
<String, dynamic>{ |
||||
'kind': instance.kind, |
||||
'station': instance.station, |
||||
}; |
||||
|
||||
_$_TrainDataNoteReceivingWagons _$$_TrainDataNoteReceivingWagonsFromJson( |
||||
Map<String, dynamic> json) => |
||||
_$_TrainDataNoteReceivingWagons( |
||||
kind: json['kind'] as String? ?? "receivingWagons", |
||||
station: json['station'] as String, |
||||
); |
||||
|
||||
Map<String, dynamic> _$$_TrainDataNoteReceivingWagonsToJson( |
||||
_$_TrainDataNoteReceivingWagons instance) => |
||||
<String, dynamic>{ |
||||
'kind': instance.kind, |
||||
'station': instance.station, |
||||
}; |
||||
|
||||
_$_TrainDataNoteUnknown _$$_TrainDataNoteUnknownFromJson( |
||||
Map<String, dynamic> json) => |
||||
_$_TrainDataNoteUnknown( |
||||
kind: json['kind'] as String, |
||||
extra: json['extra'] as Map<String, dynamic>, |
||||
); |
||||
|
||||
Map<String, dynamic> _$$_TrainDataNoteUnknownToJson( |
||||
_$_TrainDataNoteUnknown instance) => |
||||
<String, dynamic>{ |
||||
'kind': instance.kind, |
||||
'extra': instance.extra, |
||||
}; |
@ -1,19 +1,15 @@
|
||||
import 'package:json_annotation/json_annotation.dart'; |
||||
import 'package:freezed_annotation/freezed_annotation.dart'; |
||||
|
||||
part 'trains_result.g.dart'; |
||||
part 'trains_result.freezed.dart'; |
||||
|
||||
@JsonSerializable() |
||||
class TrainsResult { |
||||
final String rank; |
||||
final String number; |
||||
final String company; |
||||
|
||||
const TrainsResult({ |
||||
required this.rank, |
||||
required this.number, |
||||
required this.company, |
||||
}); |
||||
@freezed |
||||
class TrainsResult with _$TrainsResult { |
||||
const factory TrainsResult({ |
||||
required String rank, |
||||
required String number, |
||||
required String company, |
||||
}) = _TrainsResult; |
||||
|
||||
factory TrainsResult.fromJson(Map<String, dynamic> json) => _$TrainsResultFromJson(json); |
||||
Map<String, dynamic> toJson() => _$TrainsResultToJson(this); |
||||
} |
@ -0,0 +1,187 @@
|
||||
// coverage:ignore-file |
||||
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||
// ignore_for_file: type=lint |
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark |
||||
|
||||
part of 'trains_result.dart'; |
||||
|
||||
// ************************************************************************** |
||||
// FreezedGenerator |
||||
// ************************************************************************** |
||||
|
||||
T _$identity<T>(T value) => value; |
||||
|
||||
final _privateConstructorUsedError = UnsupportedError( |
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); |
||||
|
||||
TrainsResult _$TrainsResultFromJson(Map<String, dynamic> json) { |
||||
return _TrainsResult.fromJson(json); |
||||
} |
||||
|
||||
/// @nodoc |
||||
mixin _$TrainsResult { |
||||
String get rank => throw _privateConstructorUsedError; |
||||
String get number => throw _privateConstructorUsedError; |
||||
String get company => throw _privateConstructorUsedError; |
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError; |
||||
@JsonKey(ignore: true) |
||||
$TrainsResultCopyWith<TrainsResult> get copyWith => |
||||
throw _privateConstructorUsedError; |
||||
} |
||||
|
||||
/// @nodoc |
||||
abstract class $TrainsResultCopyWith<$Res> { |
||||
factory $TrainsResultCopyWith( |
||||
TrainsResult value, $Res Function(TrainsResult) then) = |
||||
_$TrainsResultCopyWithImpl<$Res, TrainsResult>; |
||||
@useResult |
||||
$Res call({String rank, String number, String company}); |
||||
} |
||||
|
||||
/// @nodoc |
||||
class _$TrainsResultCopyWithImpl<$Res, $Val extends TrainsResult> |
||||
implements $TrainsResultCopyWith<$Res> { |
||||
_$TrainsResultCopyWithImpl(this._value, this._then); |
||||
|
||||
// ignore: unused_field |
||||
final $Val _value; |
||||
// ignore: unused_field |
||||
final $Res Function($Val) _then; |
||||
|
||||
@pragma('vm:prefer-inline') |
||||
@override |
||||
$Res call({ |
||||
Object? rank = null, |
||||
Object? number = null, |
||||
Object? company = null, |
||||
}) { |
||||
return _then(_value.copyWith( |
||||
rank: null == rank |
||||
? _value.rank |
||||
: rank // ignore: cast_nullable_to_non_nullable |
||||
as String, |
||||
number: null == number |
||||
? _value.number |
||||
: number // ignore: cast_nullable_to_non_nullable |
||||
as String, |
||||
company: null == company |
||||
? _value.company |
||||
: company // ignore: cast_nullable_to_non_nullable |
||||
as String, |
||||
) as $Val); |
||||
} |
||||
} |
||||
|
||||
/// @nodoc |
||||
abstract class _$$_TrainsResultCopyWith<$Res> |
||||
implements $TrainsResultCopyWith<$Res> { |
||||
factory _$$_TrainsResultCopyWith( |
||||
_$_TrainsResult value, $Res Function(_$_TrainsResult) then) = |
||||
__$$_TrainsResultCopyWithImpl<$Res>; |
||||
@override |
||||
@useResult |
||||
$Res call({String rank, String number, String company}); |
||||
} |
||||
|
||||
/// @nodoc |
||||
class __$$_TrainsResultCopyWithImpl<$Res> |
||||
extends _$TrainsResultCopyWithImpl<$Res, _$_TrainsResult> |
||||
implements _$$_TrainsResultCopyWith<$Res> { |
||||
__$$_TrainsResultCopyWithImpl( |
||||
_$_TrainsResult _value, $Res Function(_$_TrainsResult) _then) |
||||
: super(_value, _then); |
||||
|
||||
@pragma('vm:prefer-inline') |
||||
@override |
||||
$Res call({ |
||||
Object? rank = null, |
||||
Object? number = null, |
||||
Object? company = null, |
||||
}) { |
||||
return _then(_$_TrainsResult( |
||||
rank: null == rank |
||||
? _value.rank |
||||
: rank // ignore: cast_nullable_to_non_nullable |
||||
as String, |
||||
number: null == number |
||||
? _value.number |
||||
: number // ignore: cast_nullable_to_non_nullable |
||||
as String, |
||||
company: null == company |
||||
? _value.company |
||||
: company // ignore: cast_nullable_to_non_nullable |
||||
as String, |
||||
)); |
||||
} |
||||
} |
||||
|
||||
/// @nodoc |
||||
@JsonSerializable() |
||||
class _$_TrainsResult implements _TrainsResult { |
||||
const _$_TrainsResult( |
||||
{required this.rank, required this.number, required this.company}); |
||||
|
||||
factory _$_TrainsResult.fromJson(Map<String, dynamic> json) => |
||||
_$$_TrainsResultFromJson(json); |
||||
|
||||
@override |
||||
final String rank; |
||||
@override |
||||
final String number; |
||||
@override |
||||
final String company; |
||||
|
||||
@override |
||||
String toString() { |
||||
return 'TrainsResult(rank: $rank, number: $number, company: $company)'; |
||||
} |
||||
|
||||
@override |
||||
bool operator ==(dynamic other) { |
||||
return identical(this, other) || |
||||
(other.runtimeType == runtimeType && |
||||
other is _$_TrainsResult && |
||||
(identical(other.rank, rank) || other.rank == rank) && |
||||
(identical(other.number, number) || other.number == number) && |
||||
(identical(other.company, company) || other.company == company)); |
||||
} |
||||
|
||||
@JsonKey(ignore: true) |
||||
@override |
||||
int get hashCode => Object.hash(runtimeType, rank, number, company); |
||||
|
||||
@JsonKey(ignore: true) |
||||
@override |
||||
@pragma('vm:prefer-inline') |
||||
_$$_TrainsResultCopyWith<_$_TrainsResult> get copyWith => |
||||
__$$_TrainsResultCopyWithImpl<_$_TrainsResult>(this, _$identity); |
||||
|
||||
@override |
||||
Map<String, dynamic> toJson() { |
||||
return _$$_TrainsResultToJson( |
||||
this, |
||||
); |
||||
} |
||||
} |
||||
|
||||
abstract class _TrainsResult implements TrainsResult { |
||||
const factory _TrainsResult( |
||||
{required final String rank, |
||||
required final String number, |
||||
required final String company}) = _$_TrainsResult; |
||||
|
||||
factory _TrainsResult.fromJson(Map<String, dynamic> json) = |
||||
_$_TrainsResult.fromJson; |
||||
|
||||
@override |
||||
String get rank; |
||||
@override |
||||
String get number; |
||||
@override |
||||
String get company; |
||||
@override |
||||
@JsonKey(ignore: true) |
||||
_$$_TrainsResultCopyWith<_$_TrainsResult> get copyWith => |
||||
throw _privateConstructorUsedError; |
||||
} |
@ -0,0 +1,94 @@
|
||||
import 'package:timezone/timezone.dart' as tz; |
||||
|
||||
enum UiTimeZoneType { |
||||
ro, |
||||
local, |
||||
utc, |
||||
iana, |
||||
} |
||||
|
||||
extension UITimeZoneTypeName on UiTimeZoneType { |
||||
String get userInterfaceName => (const { |
||||
UiTimeZoneType.iana: 'Fus orar IANA', |
||||
UiTimeZoneType.local: 'Local', |
||||
UiTimeZoneType.ro: 'România', |
||||
UiTimeZoneType.utc: 'UTC', |
||||
})[this]!; |
||||
} |
||||
|
||||
const Map<UiTimeZoneType, UiTimeZone Function(String)> fromSerStringConstructors = { |
||||
UiTimeZoneType.ro: RoUiTimeZone.fromSerString, |
||||
UiTimeZoneType.local: LocalUiTimeZone.fromSerString, |
||||
UiTimeZoneType.utc: UtcUiTimeZone.fromSerString, |
||||
UiTimeZoneType.iana: IanaUiTimeZone.fromSerString, |
||||
}; |
||||
|
||||
abstract class UiTimeZone { |
||||
final UiTimeZoneType type; |
||||
|
||||
const UiTimeZone({required this.type}); |
||||
|
||||
DateTime convertDateTime(DateTime dt); |
||||
|
||||
factory UiTimeZone.fromSerString(String ser) { |
||||
final arr = ser.split('\n'); |
||||
return fromSerStringConstructors.map((key, value) => MapEntry(key.name, value))[arr[0]]!(ser); |
||||
} |
||||
|
||||
String toSerString() { |
||||
return '${type.name}\n'; |
||||
} |
||||
} |
||||
|
||||
class RoUiTimeZone extends UiTimeZone { |
||||
static final roTz = tz.getLocation('Europe/Bucharest'); |
||||
|
||||
const RoUiTimeZone() : super(type: UiTimeZoneType.ro); |
||||
|
||||
factory RoUiTimeZone.fromSerString(String ser) => const RoUiTimeZone(); |
||||
|
||||
@override |
||||
DateTime convertDateTime(DateTime dt) { |
||||
return tz.TZDateTime.from(dt, roTz); |
||||
} |
||||
} |
||||
|
||||
class LocalUiTimeZone extends UiTimeZone { |
||||
const LocalUiTimeZone() : super(type: UiTimeZoneType.local); |
||||
|
||||
factory LocalUiTimeZone.fromSerString(String ser) => LocalUiTimeZone(); |
||||
|
||||
@override |
||||
DateTime convertDateTime(DateTime dt) => dt.toLocal(); |
||||
} |
||||
|
||||
class UtcUiTimeZone extends UiTimeZone { |
||||
const UtcUiTimeZone() : super(type: UiTimeZoneType.utc); |
||||
|
||||
factory UtcUiTimeZone.fromSerString(String ser) => UtcUiTimeZone(); |
||||
|
||||
@override |
||||
DateTime convertDateTime(DateTime dt) => dt.toUtc(); |
||||
} |
||||
|
||||
class IanaUiTimeZone extends UiTimeZone { |
||||
late final tz.Location location; |
||||
|
||||
IanaUiTimeZone({required String ianaName}): super(type: UiTimeZoneType.iana) { |
||||
location = tz.getLocation(ianaName); |
||||
} |
||||
|
||||
factory IanaUiTimeZone.fromSerString(String ser) => IanaUiTimeZone( |
||||
ianaName: ser.split('\n').skip(1).join('\n'), |
||||
); |
||||
|
||||
@override |
||||
DateTime convertDateTime(DateTime dt) { |
||||
return tz.TZDateTime.from(dt, location); |
||||
} |
||||
|
||||
@override |
||||
String toSerString() { |
||||
return '${type.name}\n${location.name}'; |
||||
} |
||||
} |
@ -0,0 +1,198 @@
|
||||
import 'package:fluent_ui/fluent_ui.dart'; |
||||
import 'package:flutter/services.dart'; |
||||
import 'package:info_tren/pages/about/about_page.dart'; |
||||
import 'package:url_launcher/url_launcher.dart'; |
||||
|
||||
class AboutPageFluent extends AboutPageShared { |
||||
const AboutPageFluent({super.key}); |
||||
|
||||
@override |
||||
State<AboutPageShared> createState() => AboutPageStateFluent(); |
||||
} |
||||
|
||||
class AboutPageStateFluent extends AboutPageState<AboutPageFluent> { |
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return NavigationView( |
||||
appBar: NavigationAppBar( |
||||
title: Text(pageTitle), |
||||
), |
||||
content: SingleChildScrollView( |
||||
child: Column( |
||||
mainAxisSize: MainAxisSize.min, |
||||
crossAxisAlignment: CrossAxisAlignment.stretch, |
||||
children: [ |
||||
Center( |
||||
child: Text( |
||||
'Info Tren', |
||||
style: FluentTheme.of(context).typography.display, |
||||
), |
||||
), |
||||
if (packageInfo != null) |
||||
Center( |
||||
child: Text( |
||||
packageInfo!.packageName, |
||||
style: FluentTheme.of(context).typography.caption, |
||||
), |
||||
), |
||||
// ListTile( |
||||
// title: Text(versionTitleText), |
||||
// subtitle: localChangelog.isEmpty ? null : Text(localChangelog.first.title), |
||||
// ), |
||||
const Divider(), |
||||
for (final log in mergedChangelogs) ...[ |
||||
Padding( |
||||
padding: const EdgeInsets.fromLTRB(8, 8, 8, 0), |
||||
child: Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
Expanded( |
||||
child: Text( |
||||
log.version.toString(), |
||||
style: FluentTheme.of(context).typography.title, |
||||
), |
||||
), |
||||
if (localChangelog.isNotEmpty && log.version == localChangelog.first.version) |
||||
Container( |
||||
decoration: BoxDecoration( |
||||
border: Border.all( |
||||
color: FluentTheme.of(context).inactiveColor, |
||||
width: 1, |
||||
), |
||||
borderRadius: BorderRadius.circular(20), |
||||
), |
||||
child: Padding( |
||||
padding: const EdgeInsets.all(4), |
||||
child: Text( |
||||
currentVersionText, |
||||
style: const TextStyle( |
||||
inherit: true, |
||||
), |
||||
), |
||||
), |
||||
), |
||||
if (remoteChangelog.isNotEmpty && log.version == remoteChangelog.first.version && (localChangelog.isEmpty || localChangelog.first.version != log.version)) |
||||
Container( |
||||
decoration: BoxDecoration( |
||||
border: Border.all( |
||||
color: Colors.green, |
||||
width: 1, |
||||
), |
||||
borderRadius: BorderRadius.circular(20), |
||||
), |
||||
child: Padding( |
||||
padding: const EdgeInsets.all(4), |
||||
child: Text( |
||||
latestVersionText, |
||||
style: TextStyle( |
||||
inherit: true, |
||||
color: Colors.green, |
||||
), |
||||
), |
||||
), |
||||
), |
||||
if (AboutPageState.download == 'apk' && log.apkLink != null) |
||||
GestureDetector( |
||||
onSecondaryTap: () { |
||||
Clipboard.setData(ClipboardData(text: log.apkLink!.toString())); |
||||
// ScaffoldMessenger.of(context).showSnackBar(const SnackBar( |
||||
// content: Text('Link copied to clipboard'), |
||||
// )); |
||||
}, |
||||
onLongPress: () { |
||||
Clipboard.setData(ClipboardData(text: log.apkLink!.toString())); |
||||
// ScaffoldMessenger.of(context).showSnackBar(const SnackBar( |
||||
// content: Text('Link copied to clipboard'), |
||||
// )); |
||||
}, |
||||
onTap: () { |
||||
launchUrl( |
||||
log.apkLink!, |
||||
mode: LaunchMode.externalApplication, |
||||
); |
||||
}, |
||||
behavior: HitTestBehavior.translucent, |
||||
child: const Tooltip( |
||||
message: 'Download APK', |
||||
child: Padding( |
||||
padding: EdgeInsets.all(4), |
||||
child: Icon(FluentIcons.download), |
||||
), |
||||
), |
||||
), |
||||
if (AboutPageState.download == 'linux' && log.linuxLink != null) |
||||
GestureDetector( |
||||
onSecondaryTap: () { |
||||
Clipboard.setData(ClipboardData(text: log.linuxLink!.toString())); |
||||
// ScaffoldMessenger.of(context).showSnackBar(const SnackBar( |
||||
// content: Text('Link copied to clipboard'), |
||||
// )); |
||||
}, |
||||
onLongPress: () { |
||||
Clipboard.setData(ClipboardData(text: log.linuxLink!.toString())); |
||||
// ScaffoldMessenger.of(context).showSnackBar(const SnackBar( |
||||
// content: Text('Link copied to clipboard'), |
||||
// )); |
||||
}, |
||||
onTap: () { |
||||
launchUrl( |
||||
log.linuxLink!, |
||||
mode: LaunchMode.externalApplication, |
||||
); |
||||
}, |
||||
behavior: HitTestBehavior.translucent, |
||||
child: const Tooltip( |
||||
message: 'Download Linux ZIP', |
||||
child: Padding( |
||||
padding: EdgeInsets.all(4), |
||||
child: Icon(FluentIcons.download), |
||||
), |
||||
), |
||||
), |
||||
if (AboutPageState.download == 'windows' && log.windowsLink != null) |
||||
GestureDetector( |
||||
onSecondaryTap: () { |
||||
Clipboard.setData(ClipboardData(text: log.windowsLink!.toString())); |
||||
// ScaffoldMessenger.of(context).showSnackBar(const SnackBar( |
||||
// content: Text('Link copied to clipboard'), |
||||
// )); |
||||
}, |
||||
onLongPress: () { |
||||
Clipboard.setData(ClipboardData(text: log.windowsLink!.toString())); |
||||
// ScaffoldMessenger.of(context).showSnackBar(const SnackBar( |
||||
// content: Text('Link copied to clipboard'), |
||||
// )); |
||||
}, |
||||
onTap: () { |
||||
launchUrl( |
||||
log.windowsLink!, |
||||
mode: LaunchMode.externalApplication, |
||||
); |
||||
}, |
||||
behavior: HitTestBehavior.translucent, |
||||
child: const Tooltip( |
||||
message: 'Download Windows App ZIP', |
||||
child: Padding( |
||||
padding: EdgeInsets.all(4), |
||||
child: Icon(FluentIcons.download), |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
Padding( |
||||
padding: const EdgeInsets.all(8.0), |
||||
child: RichText( |
||||
text: TextSpan( |
||||
text: log.description, |
||||
), |
||||
), |
||||
), |
||||
], |
||||
], |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,89 @@
|
||||
import 'package:fluent_ui/fluent_ui.dart'; |
||||
import 'package:info_tren/pages/main/main_page.dart'; |
||||
|
||||
class MainPageFluent extends MainPageShared { |
||||
const MainPageFluent({super.key}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return NavigationView( |
||||
appBar: NavigationAppBar( |
||||
automaticallyImplyLeading: false, |
||||
title: Text(pageTitle), |
||||
actions: Row( |
||||
mainAxisSize: MainAxisSize.min, |
||||
children: popupMenu.map((i) => Center( |
||||
child: SizedBox( |
||||
width: 32, |
||||
height: 32, |
||||
child: IconButton( |
||||
icon: Icon({ |
||||
'Setări': FluentIcons.settings, |
||||
'Despre aplicație': FluentIcons.info, |
||||
}[i.name]), |
||||
onPressed: i.action != null ? () => i.action!(context) : null, |
||||
), |
||||
), |
||||
)).toList(), |
||||
), |
||||
// centerTitle: true, |
||||
// actions: [ |
||||
// PopupMenuButton<int>( |
||||
// icon: const Icon(Icons.more_vert), |
||||
// tooltip: moreOptionsText, |
||||
// itemBuilder: (_) => popupMenu.asMap().entries.map((e) => PopupMenuItem( |
||||
// value: e.key, |
||||
// child: Text(e.value.name), |
||||
// )).toList(), |
||||
// onSelected: (index) { |
||||
// popupMenu[index].action?.call(context); |
||||
// }, |
||||
// ), |
||||
// ], |
||||
), |
||||
content: SafeArea( |
||||
child: Center( |
||||
child: Column( |
||||
mainAxisSize: MainAxisSize.min, |
||||
children: options.map((option) => HoverButton( |
||||
onPressed: option.action != null ? () => option.action!(context) : null, |
||||
builder: (context, states) { |
||||
return Card( |
||||
backgroundColor: option.action != null ? (states.isHovering ? FluentTheme.of(context).accentColor.dark : FluentTheme.of(context).accentColor) : null, |
||||
child: Column( |
||||
children: [ |
||||
Padding( |
||||
padding: const EdgeInsets.all(8.0), |
||||
child: Text( |
||||
option.name, |
||||
style: FluentTheme.of(context) |
||||
.typography |
||||
.bodyLarge |
||||
?.copyWith( |
||||
color: |
||||
FluentTheme.of(context).activeColor, |
||||
), |
||||
textAlign: TextAlign.center, |
||||
), |
||||
), |
||||
Padding( |
||||
padding: const EdgeInsets.all(8.0), |
||||
child: Text(option.description!), |
||||
), |
||||
], |
||||
), |
||||
); |
||||
}, |
||||
)).map((w) => Padding( |
||||
padding: const EdgeInsets.fromLTRB(4, 2, 4, 2), |
||||
child: SizedBox( |
||||
width: double.infinity, |
||||
child: w, |
||||
), |
||||
)).toList(), |
||||
), |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,38 @@
|
||||
import 'package:flutter/widgets.dart'; |
||||
import 'package:hooks_riverpod/hooks_riverpod.dart'; |
||||
import 'package:info_tren/models.dart'; |
||||
import 'package:info_tren/pages/settings/settings_page_cupertino.dart'; |
||||
import 'package:info_tren/pages/settings/settings_page_fluent.dart'; |
||||
import 'package:info_tren/pages/settings/settings_page_material.dart'; |
||||
import 'package:info_tren/providers.dart'; |
||||
|
||||
class SettingsPage extends ConsumerWidget { |
||||
const SettingsPage({super.key,}); |
||||
|
||||
static const String routeName = '/settings'; |
||||
|
||||
@override |
||||
Widget build(BuildContext context, WidgetRef ref) { |
||||
final uiDesign = ref.watch(uiDesignProvider); |
||||
|
||||
switch (uiDesign) { |
||||
case UiDesign.MATERIAL: |
||||
return const SettingsPageMaterial(); |
||||
case UiDesign.CUPERTINO: |
||||
return const SettingsPageCupertino(); |
||||
case UiDesign.FLUENT: |
||||
return const SettingsPageFluent(); |
||||
default: |
||||
throw UnmatchedUiDesignException(uiDesign); |
||||
} |
||||
} |
||||
} |
||||
|
||||
abstract class SettingsPageShared extends StatelessWidget { |
||||
final String pageTitle = 'Setări'; |
||||
final String appearanceTitle = 'Aspect'; |
||||
final String timeZoneTitle = 'Fus orar'; |
||||
|
||||
const SettingsPageShared({super.key}); |
||||
|
||||
} |
@ -0,0 +1,96 @@
|
||||
import 'package:flutter/cupertino.dart'; |
||||
import 'package:hooks_riverpod/hooks_riverpod.dart'; |
||||
import 'package:info_tren/models.dart'; |
||||
import 'package:info_tren/pages/settings/setings_page.dart'; |
||||
import 'package:info_tren/providers.dart'; |
||||
|
||||
class SettingsPageCupertino extends SettingsPageShared { |
||||
const SettingsPageCupertino({super.key,}); |
||||
|
||||
Future<T?> singleChoice<T>({required BuildContext context, required List<T> choices, required String Function(T) labelBuilder, String? title}) async { |
||||
return await showCupertinoModalPopup<T>( |
||||
context: context, |
||||
builder: (context) { |
||||
return CupertinoActionSheet( |
||||
title: title != null ? Text(title) : null, |
||||
actions: choices.map((c) => CupertinoActionSheetAction( |
||||
onPressed: () { |
||||
Navigator.of(context).pop(c); |
||||
}, |
||||
child: Text(labelBuilder(c)), |
||||
)).toList(), |
||||
cancelButton: CupertinoActionSheetAction( |
||||
child: const Text('Anulare'), |
||||
onPressed: () { |
||||
Navigator.of(context).pop(); |
||||
}, |
||||
), |
||||
); |
||||
}, |
||||
); |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return CupertinoPageScaffold( |
||||
navigationBar: CupertinoNavigationBar( |
||||
previousPageTitle: 'Info Tren', |
||||
middle: Text(pageTitle), |
||||
), |
||||
child: Builder( |
||||
builder: (context) { |
||||
final mq = MediaQuery.of(context); |
||||
return SingleChildScrollView( |
||||
child: Column( |
||||
children: [ |
||||
SizedBox( |
||||
height: mq.padding.top, |
||||
), |
||||
Consumer( |
||||
builder: (context, ref, _) { |
||||
final currentUiDesign = ref.watch(uiDesignProvider); |
||||
return CupertinoListTile( |
||||
title: Text(appearanceTitle), |
||||
trailing: Text(currentUiDesign.userInterfaceName), |
||||
onTap: () async { |
||||
final choice = await singleChoice( |
||||
context: context, |
||||
choices: UiDesign.values, |
||||
labelBuilder: (UiDesign ud) => ud.userInterfaceName, |
||||
title: appearanceTitle, |
||||
); |
||||
if (choice != null) { |
||||
ref.read(uiDesignProvider.notifier).set(choice); |
||||
} |
||||
}, |
||||
); |
||||
}, |
||||
), |
||||
Consumer( |
||||
builder: (context, ref, _) { |
||||
final currentTZ = ref.watch(uiTimeZoneProvider); |
||||
return CupertinoListTile( |
||||
title: Text(timeZoneTitle), |
||||
trailing: Text(currentTZ.type.userInterfaceName), |
||||
onTap: () async { |
||||
final choice = await singleChoice( |
||||
context: context, |
||||
choices: UiTimeZoneType.values.where((tz) => tz != UiTimeZoneType.iana).toList(), |
||||
labelBuilder: (UiTimeZoneType utzt) => utzt.userInterfaceName, |
||||
title: timeZoneTitle, |
||||
); |
||||
if (choice != null) { |
||||
ref.read(uiTimeZoneProvider.notifier).set(UiTimeZone.fromSerString('${choice.name}\n')); |
||||
} |
||||
}, |
||||
); |
||||
}, |
||||
), |
||||
], |
||||
), |
||||
); |
||||
}, |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,65 @@
|
||||
import 'package:fluent_ui/fluent_ui.dart'; |
||||
import 'package:hooks_riverpod/hooks_riverpod.dart'; |
||||
import 'package:info_tren/models.dart'; |
||||
import 'package:info_tren/pages/settings/setings_page.dart'; |
||||
import 'package:info_tren/providers.dart'; |
||||
|
||||
class SettingsPageFluent extends SettingsPageShared { |
||||
const SettingsPageFluent({super.key,}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return NavigationView( |
||||
appBar: NavigationAppBar( |
||||
title: Text(pageTitle), |
||||
), |
||||
content: SingleChildScrollView( |
||||
child: Column( |
||||
children: [ |
||||
Consumer( |
||||
builder: (context, ref, _) { |
||||
final currentUiDesign = ref.watch(uiDesignProvider); |
||||
return ListTile( |
||||
title: Text(appearanceTitle), |
||||
trailing: ComboBox<UiDesign>( |
||||
items: UiDesign.values.map((d) => ComboBoxItem( |
||||
value: d, |
||||
child: Text(d.userInterfaceName), |
||||
)).toList(), |
||||
value: currentUiDesign, |
||||
onChanged: (newUiDesign) { |
||||
ref.read(uiDesignProvider.notifier).set(newUiDesign); |
||||
}, |
||||
), |
||||
); |
||||
}, |
||||
), |
||||
Consumer( |
||||
builder: (context, ref, _) { |
||||
final currentTZ = ref.watch(uiTimeZoneProvider); |
||||
return ListTile( |
||||
title: Text(timeZoneTitle), |
||||
trailing: ComboBox<UiTimeZoneType>( |
||||
items: UiTimeZoneType.values.where((tz) => tz != UiTimeZoneType.iana).map((tzt) => ComboBoxItem( |
||||
value: tzt, |
||||
child: Text(tzt.userInterfaceName), |
||||
)).toList(), |
||||
value: currentTZ.type, |
||||
onChanged: (newTZ) { |
||||
if (newTZ != null) { |
||||
ref.read(uiTimeZoneProvider.notifier).set(UiTimeZone.fromSerString('${newTZ.name}\n')); |
||||
} |
||||
else { |
||||
ref.read(uiTimeZoneProvider.notifier).set(null); |
||||
} |
||||
}, |
||||
), |
||||
); |
||||
}, |
||||
), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,66 @@
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:hooks_riverpod/hooks_riverpod.dart'; |
||||
import 'package:info_tren/models.dart'; |
||||
import 'package:info_tren/pages/settings/setings_page.dart'; |
||||
import 'package:info_tren/providers.dart'; |
||||
|
||||
class SettingsPageMaterial extends SettingsPageShared { |
||||
const SettingsPageMaterial({super.key,}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Scaffold( |
||||
appBar: AppBar( |
||||
title: Text(pageTitle), |
||||
centerTitle: true, |
||||
), |
||||
body: SingleChildScrollView( |
||||
child: Column( |
||||
children: [ |
||||
Consumer( |
||||
builder: (context, ref, _) { |
||||
final currentUiDesign = ref.watch(uiDesignProvider); |
||||
return ListTile( |
||||
title: Text(appearanceTitle), |
||||
trailing: DropdownButton<UiDesign>( |
||||
items: UiDesign.values.map((d) => DropdownMenuItem( |
||||
value: d, |
||||
child: Text(d.userInterfaceName), |
||||
)).toList(), |
||||
value: currentUiDesign, |
||||
onChanged: (newUiDesign) { |
||||
ref.read(uiDesignProvider.notifier).set(newUiDesign); |
||||
}, |
||||
), |
||||
); |
||||
}, |
||||
), |
||||
Consumer( |
||||
builder: (context, ref, _) { |
||||
final currentTZ = ref.watch(uiTimeZoneProvider); |
||||
return ListTile( |
||||
title: Text(timeZoneTitle), |
||||
trailing: DropdownButton<UiTimeZoneType>( |
||||
items: UiTimeZoneType.values.where((tz) => tz != UiTimeZoneType.iana).map((tzt) => DropdownMenuItem( |
||||
value: tzt, |
||||
child: Text(tzt.userInterfaceName), |
||||
)).toList(), |
||||
value: currentTZ.type, |
||||
onChanged: (newTZ) { |
||||
if (newTZ != null) { |
||||
ref.read(uiTimeZoneProvider.notifier).set(UiTimeZone.fromSerString('${newTZ.name}\n')); |
||||
} |
||||
else { |
||||
ref.read(uiTimeZoneProvider.notifier).set(null); |
||||
} |
||||
}, |
||||
), |
||||
); |
||||
}, |
||||
), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,59 @@
|
||||
import 'package:fluent_ui/fluent_ui.dart'; |
||||
import 'package:info_tren/pages/station_arrdep_page/select_station/select_station.dart'; |
||||
|
||||
class SelectStationPageFluent extends SelectStationPageShared { |
||||
const SelectStationPageFluent({super.key}); |
||||
|
||||
@override |
||||
State<StatefulWidget> createState() => SelectStationPageStateFluent(); |
||||
} |
||||
|
||||
class SelectStationPageStateFluent extends SelectStationPageState { |
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return NavigationView( |
||||
appBar: const NavigationAppBar( |
||||
title: Text(SelectStationPageState.pageTitle), |
||||
// centerTitle: true, |
||||
), |
||||
content: SafeArea( |
||||
bottom: false, |
||||
child: Column( |
||||
mainAxisSize: MainAxisSize.max, |
||||
children: [ |
||||
Padding( |
||||
padding: const EdgeInsets.all(4), |
||||
child: TextBox( |
||||
controller: textEditingController, |
||||
autofocus: true, |
||||
placeholder: SelectStationPageState.textFieldLabel, |
||||
textInputAction: TextInputAction.search, |
||||
onChanged: onTextChanged, |
||||
), |
||||
), |
||||
Expanded( |
||||
child: ListView.builder( |
||||
itemBuilder: (context, index) { |
||||
return Column( |
||||
mainAxisSize: MainAxisSize.min, |
||||
children: [ |
||||
ListTile( |
||||
// dense: true, |
||||
title: Text(filteredStations[index]), |
||||
onPressed: () => onSuggestionSelected(filteredStations[index]), |
||||
), |
||||
const Divider( |
||||
size: 1, |
||||
), |
||||
], |
||||
); |
||||
}, |
||||
itemCount: filteredStations.length, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,264 @@
|
||||
import 'dart:math'; |
||||
import 'dart:ui'; |
||||
|
||||
import 'package:fluent_ui/fluent_ui.dart'; |
||||
import 'package:hooks_riverpod/hooks_riverpod.dart'; |
||||
import 'package:info_tren/components/badge/badge.dart'; |
||||
import 'package:info_tren/components/loading/loading.dart'; |
||||
import 'package:info_tren/components/refresh_future_builder.dart'; |
||||
import 'package:info_tren/components/train_id_text_span.dart'; |
||||
import 'package:info_tren/models.dart'; |
||||
import 'package:info_tren/pages/station_arrdep_page/view_station/view_station.dart'; |
||||
import 'package:info_tren/providers.dart'; |
||||
|
||||
class ViewStationPageFluent extends ViewStationPageShared { |
||||
const ViewStationPageFluent({super.key, required super.tab, required super.setTab}); |
||||
|
||||
@override |
||||
Widget buildContent(BuildContext context, Future Function() refresh, Future Function(Future<StationData> Function()) _, RefreshFutureBuilderSnapshot<StationData> snapshot) { |
||||
return NavigationView( |
||||
appBar: NavigationAppBar( |
||||
title: Consumer( |
||||
builder: (context, ref, _) { |
||||
final stationName = ref.watch(viewStationArgumentsProvider.select((value) => value.stationName)); |
||||
return Text(snapshot.hasData ? snapshot.data!.stationName : stationName); |
||||
} |
||||
), |
||||
), |
||||
content: snapshot.state == RefreshFutureBuilderState.waiting || snapshot.state == RefreshFutureBuilderState.refreshError |
||||
? const Loading(text: ViewStationPageShared.loadingText,) |
||||
: snapshot.state == RefreshFutureBuilderState.error |
||||
? Padding( |
||||
padding: const EdgeInsets.all(8.0), |
||||
child: Center( |
||||
child: Column( |
||||
mainAxisSize: MainAxisSize.min, |
||||
children: [ |
||||
Icon( |
||||
FluentIcons.error, |
||||
size: 32, |
||||
color: Colors.red.normal, |
||||
), |
||||
const Text( |
||||
ViewStationPageShared.errorText, |
||||
style: TextStyle( |
||||
inherit: true, |
||||
fontSize: 32, |
||||
), |
||||
), |
||||
Text( |
||||
snapshot.error.toString(), |
||||
style: FluentTheme.of(context).typography.subtitle, |
||||
), |
||||
Padding( |
||||
padding: const EdgeInsets.all(8.0), |
||||
child: Button( |
||||
onPressed: () { |
||||
refresh(); |
||||
}, |
||||
child: const Text(ViewStationPageShared.retryText), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
) |
||||
: null, |
||||
pane: snapshot.hasData ? NavigationPane( |
||||
onChanged: onTabChange, |
||||
selected: tab.index, |
||||
items: [ |
||||
PaneItem( |
||||
body: CustomScrollView( |
||||
slivers: [ |
||||
SliverToBoxAdapter(child: SafeArea(left: false, bottom: false, right: false,child: Container(),),), |
||||
SliverList( |
||||
delegate: SliverChildBuilderDelegate( |
||||
(context, index) { |
||||
return tab == ViewStationPageTab.arrivals ? buildStationArrivalItem(context, snapshot.data!.arrivals![index]) : buildStationDepartureItem(context, snapshot.data!.departures![index]); |
||||
}, |
||||
childCount: tab == ViewStationPageTab.arrivals ? snapshot.data!.arrivals?.length ?? 0 : snapshot.data!.departures?.length ?? 0, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
title: const Text(ViewStationPageShared.arrivals), |
||||
icon: const Icon(FluentIcons.arrow_down_right8), |
||||
), |
||||
PaneItem( |
||||
body: CustomScrollView( |
||||
slivers: [ |
||||
SliverToBoxAdapter(child: SafeArea(left: false, bottom: false, right: false,child: Container(),),), |
||||
SliverList( |
||||
delegate: SliverChildBuilderDelegate( |
||||
(context, index) { |
||||
return tab == ViewStationPageTab.arrivals ? buildStationArrivalItem(context, snapshot.data!.arrivals![index]) : buildStationDepartureItem(context, snapshot.data!.departures![index]); |
||||
}, |
||||
childCount: tab == ViewStationPageTab.arrivals ? snapshot.data!.arrivals?.length ?? 0 : snapshot.data!.departures?.length ?? 0, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
title: const Text(ViewStationPageShared.departures), |
||||
icon: const Icon(FluentIcons.arrow_up_right8), |
||||
), |
||||
], |
||||
) : null, |
||||
// bottomNavigationBar: snapshot.hasData ? BottomNavigationBar( |
||||
// items: const [ |
||||
// BottomNavigationBarItem( |
||||
// icon: Icon(Icons.arrow_downward), |
||||
// label: ViewStationPageShared.arrivals, |
||||
// ), |
||||
// BottomNavigationBarItem( |
||||
// icon: Icon(Icons.arrow_upward), |
||||
// label: ViewStationPageShared.departures, |
||||
// ), |
||||
// ], |
||||
// currentIndex: tab.index, |
||||
// onTap: onTabChange, |
||||
// ) : null, |
||||
); |
||||
} |
||||
|
||||
Widget buildStationItem(BuildContext context, StationArrDep item, {required bool arrival}) { |
||||
return HoverButton( |
||||
onPressed: () => onTrainTapped(context, item.train), |
||||
builder: (context, states) { |
||||
return Container( |
||||
color: item.status.cancelled |
||||
? Colors.red.withAlpha(100) |
||||
: states.isPressing |
||||
? FluentTheme.of(context).scaffoldBackgroundColor |
||||
: states.isHovering |
||||
? FluentTheme.of(context).inactiveBackgroundColor |
||||
: null, |
||||
child: Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
Padding( |
||||
padding: const EdgeInsets.all(8), |
||||
child: Column( |
||||
mainAxisSize: MainAxisSize.min, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: [ |
||||
Consumer( |
||||
builder: (context, ref, _) { |
||||
final tz = ref.watch(uiTimeZoneProvider); |
||||
final time = tz.convertDateTime(item.time); |
||||
return Text( |
||||
'${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}', |
||||
style: TextStyle( |
||||
inherit: true, |
||||
fontFeatures: const [ |
||||
FontFeature.tabularFigures(), |
||||
], |
||||
decoration: item.status.cancelled || item.status.delay != 0 ? TextDecoration.lineThrough : null, |
||||
fontSize: item.status.delay != 0 ? 12 : null, |
||||
), |
||||
); |
||||
}, |
||||
), |
||||
if (item.status.delay != 0) Consumer( |
||||
builder: (context, ref, _) { |
||||
final tz = ref.watch(uiTimeZoneProvider); |
||||
final newTime = tz.convertDateTime(item.time.add(Duration(minutes: item.status.delay))); |
||||
final delay = item.status.delay > 0; |
||||
|
||||
return Text( |
||||
'${newTime.hour.toString().padLeft(2, '0')}:${newTime.minute.toString().padLeft(2, '0')}', |
||||
style: TextStyle( |
||||
inherit: true, |
||||
fontFeatures: const [ |
||||
FontFeature.tabularFigures(), |
||||
], |
||||
color: delay ? Colors.red : Colors.green, |
||||
), |
||||
); |
||||
}, |
||||
), |
||||
], |
||||
), |
||||
), |
||||
Expanded( |
||||
child: IgnorePointer( |
||||
child: ListTile( |
||||
// isThreeLine: item.status.delay != 0, |
||||
title: Text.rich( |
||||
trainIdSpan(rank: item.train.rank, number: item.train.number), |
||||
), |
||||
subtitle: Text.rich( |
||||
TextSpan( |
||||
children: [ |
||||
TextSpan( |
||||
text: item.status.cancelled |
||||
? (arrival ? ViewStationPageShared.cancelledArrival : ViewStationPageShared.cancelledDeparture) |
||||
: item.time.add(Duration(minutes: max(0, item.status.delay))).compareTo(DateTime.now()) < 0 |
||||
? (arrival ? ViewStationPageShared.arrivedFrom : ViewStationPageShared.departedTo) |
||||
: (arrival ? ViewStationPageShared.arrivesFrom : ViewStationPageShared.departsTo) |
||||
), |
||||
const TextSpan(text: ' '), |
||||
TextSpan(text: item.train.terminus), |
||||
if (item.status.delay != 0) ...[ |
||||
const TextSpan(text: '\n'), |
||||
if (item.status.delay.abs() >= 60) ...[ |
||||
TextSpan(text: (item.status.delay.abs() ~/ 60).toString()), |
||||
TextSpan(text: item.status.delay.abs() >= 120 ? ' ore' : ' oră'), |
||||
if (item.status.delay.abs() % 60 != 0) |
||||
const TextSpan(text: ' și '), |
||||
], |
||||
TextSpan(text: (item.status.delay.abs() % 60).toString()), |
||||
TextSpan(text: item.status.delay.abs() > 1 ? ' minute' : ' minut'), |
||||
const TextSpan(text: ' '), |
||||
if (item.status.delay > 0) |
||||
TextSpan( |
||||
text: 'întârziere', |
||||
style: TextStyle( |
||||
inherit: true, |
||||
color: Colors.red, |
||||
), |
||||
) |
||||
else |
||||
TextSpan( |
||||
text: 'mai devreme', |
||||
style: TextStyle( |
||||
inherit: true, |
||||
color: Colors.green, |
||||
), |
||||
), |
||||
], |
||||
], |
||||
), |
||||
), |
||||
), |
||||
), |
||||
), |
||||
if (item.status.platform != null) |
||||
IntrinsicHeight( |
||||
child: AspectRatio( |
||||
aspectRatio: 1, |
||||
child: Badge( |
||||
text: item.status.platform!, |
||||
caption: 'Linia', |
||||
isOnTime: item.status.real && item.status.delay <= 0, |
||||
isDelayed: item.status.real && item.status.delay > 0, |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
); |
||||
}, |
||||
); |
||||
} |
||||
|
||||
@override |
||||
Widget buildStationArrivalItem(BuildContext context, StationArrDep item) { |
||||
return buildStationItem(context, item, arrival: true); |
||||
} |
||||
|
||||
@override |
||||
Widget buildStationDepartureItem(BuildContext context, StationArrDep item) { |
||||
return buildStationItem(context, item, arrival: false); |
||||
} |
||||
} |
@ -0,0 +1,46 @@
|
||||
import 'package:fluent_ui/fluent_ui.dart'; |
||||
import 'package:flutter/services.dart'; |
||||
import 'package:info_tren/pages/train_info_page/select_train/select_train.dart'; |
||||
|
||||
class SelectTrainPageFluent extends SelectTrainPageShared { |
||||
const SelectTrainPageFluent({super.key}); |
||||
|
||||
@override |
||||
State<SelectTrainPageShared> createState() => SelectTrainPageStateFluent(); |
||||
} |
||||
|
||||
class SelectTrainPageStateFluent extends SelectTrainPageState { |
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return NavigationView( |
||||
appBar: NavigationAppBar( |
||||
title: Text(pageTitle), |
||||
), |
||||
content: SafeArea( |
||||
bottom: false, |
||||
child: Column( |
||||
mainAxisSize: MainAxisSize.max, |
||||
children: <Widget>[ |
||||
Padding( |
||||
padding: const EdgeInsets.all(4), |
||||
child: TextBox( |
||||
controller: trainNoController, |
||||
autofocus: true, |
||||
placeholder: textFieldLabel, |
||||
textInputAction: TextInputAction.search, |
||||
keyboardType: TextInputType.number, |
||||
onChanged: (_) => onTextChanged(), |
||||
inputFormatters: [ |
||||
FilteringTextInputFormatter.digitsOnly, |
||||
], |
||||
), |
||||
), |
||||
Expanded( |
||||
child: suggestionsList, |
||||
), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
@ -1,10 +1,10 @@
|
||||
import 'dart:ui'; |
||||
|
||||
const BACKGROUND_GREEN = Color.fromRGBO(5, 66, 10, 1); |
||||
const FOREGROUND_GREEN = Color.fromRGBO(20, 180, 50, 1); |
||||
const backgroundGreen = Color.fromRGBO(5, 66, 10, 1); |
||||
const foregroundGreen = Color.fromRGBO(20, 180, 50, 1); |
||||
|
||||
const BACKGROUND_RED = Color.fromRGBO(66, 10, 5, 1); |
||||
const backgroundRed = Color.fromRGBO(66, 10, 5, 1); |
||||
|
||||
const FOREGROUND_WHITE = Color.fromRGBO(240, 250, 240, 1); |
||||
const foregroundWhite = Color.fromRGBO(240, 250, 240, 1); |
||||
|
||||
const FOREGROUND_DARK_GREY = Color.fromRGBO(55, 55, 55, 1); |
||||
const foregroundDarkGrey = Color.fromRGBO(55, 55, 55, 1); |
@ -1,91 +1,304 @@
|
||||
import 'dart:async'; |
||||
|
||||
import 'package:flutter/material.dart'; |
||||
import 'package:flutter/cupertino.dart'; |
||||
import 'package:flutter/widgets.dart'; |
||||
import 'package:flutter_hooks/flutter_hooks.dart'; |
||||
import 'package:hooks_riverpod/hooks_riverpod.dart'; |
||||
import 'package:info_tren/api/train_data.dart'; |
||||
import 'package:info_tren/components/loading/loading.dart'; |
||||
import 'package:info_tren/components/refresh_future_builder.dart'; |
||||
import 'package:info_tren/models/train_data.dart'; |
||||
import 'package:info_tren/models/ui_design.dart'; |
||||
import 'package:info_tren/models.dart'; |
||||
import 'package:info_tren/pages/train_info_page/view_train/train_info_cupertino.dart'; |
||||
import 'package:info_tren/pages/train_info_page/view_train/train_info_fluent.dart'; |
||||
import 'package:info_tren/pages/train_info_page/view_train/train_info_material.dart'; |
||||
import 'package:info_tren/utils/default_ui_design.dart'; |
||||
import 'package:info_tren/providers.dart'; |
||||
|
||||
|
||||
class TrainInfo extends StatelessWidget { |
||||
class TrainInfo extends HookConsumerWidget { |
||||
static String routeName = "/trainInfo/display"; |
||||
|
||||
final UiDesign? uiDesign; |
||||
final String trainNumber; |
||||
|
||||
TrainInfo({Key? key, required this.trainNumber, this.uiDesign}): super(key: key); |
||||
const TrainInfo({ |
||||
super.key, |
||||
}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
final uiDesign = this.uiDesign ?? defaultUiDesign; |
||||
|
||||
return RefreshFutureBuilder<TrainData>( |
||||
futureCreator: () => getTrain(trainNumber), |
||||
builder: (context, refresh, replaceFutureBuilder, snapshot) { |
||||
void onViewYesterdayTrain() { |
||||
replaceFutureBuilder(() => getTrain(trainNumber, date: DateTime.now().subtract(const Duration(days: 1)))); |
||||
} |
||||
Widget build(BuildContext context, WidgetRef ref) { |
||||
final uiDesign = ref.watch(uiDesignProvider); |
||||
final args = ref.watch(trainInfoArgumentsProvider); |
||||
final trainNumber = args.trainNumber; |
||||
final viewYesterday = useState(false); |
||||
final date = args.date ?? |
||||
DateTime.now().copyWith( |
||||
hour: 12, |
||||
minute: 0, |
||||
second: 0, |
||||
millisecond: 0, |
||||
microsecond: 0, |
||||
); |
||||
final requestDate = |
||||
viewYesterday.value ? date.subtract(const Duration(days: 1)) : date; |
||||
final trainDataAsync = ref |
||||
.watch(trainInfoProvider(trainNumber: trainNumber, date: requestDate)); |
||||
|
||||
Future refresh() async { |
||||
ref.invalidate( |
||||
trainInfoProvider(trainNumber: trainNumber, date: requestDate), |
||||
); |
||||
await Future.delayed(const Duration(seconds: 1)); |
||||
} |
||||
|
||||
void onViewYesterdayTrain() { |
||||
viewYesterday.value = !viewYesterday.value; |
||||
} |
||||
|
||||
useEffect(() { |
||||
final handle = Timer.periodic(const Duration(minutes: 1), (timer) { |
||||
refresh(); |
||||
}); |
||||
return () { |
||||
handle.cancel(); |
||||
}; |
||||
}); |
||||
|
||||
return trainDataAsync.when( |
||||
data: (data) { |
||||
switch (uiDesign) { |
||||
case UiDesign.MATERIAL: |
||||
if ([RefreshFutureBuilderState.none, RefreshFutureBuilderState.waiting].contains(snapshot.state)) { |
||||
return TrainInfoLoadingMaterial(title: trainNumber.toString(), loadingText: "Se încarcă...",); |
||||
} |
||||
else if (snapshot.state == RefreshFutureBuilderState.error) { |
||||
return TrainInfoErrorMaterial(title: '$trainNumber - Error', error: snapshot.error!, refresh: refresh,); |
||||
} |
||||
|
||||
return TrainInfoMaterial( |
||||
trainData: snapshot.data!, |
||||
trainData: data, |
||||
refresh: refresh, |
||||
isRefreshing: trainDataAsync.isRefreshing, |
||||
onViewYesterdayTrain: onViewYesterdayTrain, |
||||
); |
||||
case UiDesign.CUPERTINO: |
||||
if ([RefreshFutureBuilderState.none, RefreshFutureBuilderState.waiting].contains(snapshot.state)) { |
||||
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, |
||||
isRefreshing: snapshot.state == RefreshFutureBuilderState.refreshing, |
||||
trainData: data, |
||||
refresh: refresh, |
||||
isRefreshing: trainDataAsync.isRefreshing, |
||||
onViewYesterdayTrain: onViewYesterdayTrain, |
||||
); |
||||
case UiDesign.FLUENT: |
||||
return TrainInfoFluent( |
||||
trainData: data, |
||||
refresh: refresh, |
||||
isRefreshing: trainDataAsync.isRefreshing, |
||||
onViewYesterdayTrain: onViewYesterdayTrain, |
||||
); |
||||
default: |
||||
throw UnmatchedUiDesignException(uiDesign); |
||||
} |
||||
}, |
||||
error: (e, st) { |
||||
return TrainInfoError( |
||||
title: '$trainNumber - Error', |
||||
error: e, |
||||
refresh: refresh, |
||||
); |
||||
}, |
||||
loading: () { |
||||
return TrainInfoLoading( |
||||
title: trainNumber.toString(), |
||||
loadingText: "Se încarcă...", |
||||
); |
||||
}, |
||||
); |
||||
} |
||||
} |
||||
|
||||
abstract class TrainInfoLoading extends StatelessWidget { |
||||
class TrainInfoArguments { |
||||
final String trainNumber; |
||||
final DateTime? date; |
||||
|
||||
TrainInfoArguments({required this.trainNumber, this.date}); |
||||
} |
||||
|
||||
abstract class TrainInfoShared extends StatelessWidget { |
||||
final TrainData trainData; |
||||
final Future Function()? refresh; |
||||
final void Function()? onViewYesterdayTrain; |
||||
final bool? isRefreshing; |
||||
|
||||
const TrainInfoShared({ |
||||
super.key, |
||||
required this.trainData, |
||||
this.refresh, |
||||
this.onViewYesterdayTrain, |
||||
this.isRefreshing, |
||||
}); |
||||
} |
||||
|
||||
class TrainInfoLoading extends ConsumerWidget { |
||||
final String title; |
||||
final String? loadingText; |
||||
|
||||
const TrainInfoLoading({ |
||||
super.key, |
||||
required this.title, |
||||
this.loadingText, |
||||
}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context, WidgetRef ref) { |
||||
final uiDesign = ref.watch(uiDesignProvider); |
||||
|
||||
switch (uiDesign) { |
||||
case UiDesign.MATERIAL: |
||||
return TrainInfoLoadingMaterial( |
||||
title: title, |
||||
loadingText: loadingText, |
||||
); |
||||
case UiDesign.CUPERTINO: |
||||
return TrainInfoLoadingCupertino( |
||||
title: title, |
||||
loadingText: loadingText, |
||||
); |
||||
case UiDesign.FLUENT: |
||||
return TrainInfoLoadingFluent( |
||||
title: title, |
||||
loadingText: loadingText, |
||||
); |
||||
default: |
||||
throw UnmatchedUiDesignException(uiDesign); |
||||
} |
||||
} |
||||
} |
||||
|
||||
abstract class TrainInfoLoadingShared extends StatelessWidget { |
||||
final String title; |
||||
final Widget loadingWidget; |
||||
|
||||
TrainInfoLoading({required this.title, String? loadingText, UiDesign? uiDesign}) : loadingWidget = Loading(uiDesign: uiDesign, text: loadingText,); |
||||
TrainInfoLoadingShared({ |
||||
required this.title, |
||||
String? loadingText, |
||||
super.key, |
||||
}) : loadingWidget = Loading( |
||||
text: loadingText, |
||||
); |
||||
} |
||||
|
||||
class TrainInfoError extends ConsumerWidget { |
||||
final String title; |
||||
final Object error; |
||||
final Future Function()? refresh; |
||||
|
||||
const TrainInfoError({ |
||||
super.key, |
||||
required this.title, |
||||
required this.error, |
||||
this.refresh, |
||||
}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context, WidgetRef ref) { |
||||
final uiDesign = ref.watch(uiDesignProvider); |
||||
|
||||
switch (uiDesign) { |
||||
case UiDesign.MATERIAL: |
||||
return TrainInfoErrorMaterial( |
||||
title: title, |
||||
error: error, |
||||
refresh: refresh, |
||||
); |
||||
case UiDesign.CUPERTINO: |
||||
return TrainInfoErrorCupertino( |
||||
title: title, |
||||
error: error, |
||||
refresh: refresh, |
||||
); |
||||
case UiDesign.FLUENT: |
||||
return TrainInfoErrorFluent( |
||||
title: title, |
||||
error: error, |
||||
refresh: refresh, |
||||
); |
||||
default: |
||||
throw UnmatchedUiDesignException(uiDesign); |
||||
} |
||||
} |
||||
} |
||||
|
||||
abstract class TrainInfoError extends StatelessWidget { |
||||
abstract class TrainInfoErrorShared extends StatelessWidget { |
||||
final String title; |
||||
final Object error; |
||||
final Future Function()? refresh; |
||||
|
||||
TrainInfoError({required this.title, required this.error, this.refresh}); |
||||
const TrainInfoErrorShared({ |
||||
required this.title, |
||||
required this.error, |
||||
this.refresh, |
||||
super.key, |
||||
}); |
||||
} |
||||
|
||||
class TrainInfoBody extends ConsumerWidget { |
||||
final TrainData trainData; |
||||
final void Function()? onViewYesterdayTrain; |
||||
final Future Function()? refresh; |
||||
final bool? isRefreshing; |
||||
|
||||
const TrainInfoBody({ |
||||
required this.trainData, |
||||
this.onViewYesterdayTrain, |
||||
this.refresh, |
||||
this.isRefreshing, |
||||
super.key, |
||||
}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context, WidgetRef ref) { |
||||
final uiDesign = ref.watch(uiDesignProvider); |
||||
|
||||
switch (uiDesign) { |
||||
case UiDesign.MATERIAL: |
||||
return TrainInfoBodyMaterial( |
||||
trainData: trainData, |
||||
onViewYesterdayTrain: onViewYesterdayTrain, |
||||
refresh: refresh, |
||||
isRefreshing: isRefreshing, |
||||
); |
||||
case UiDesign.CUPERTINO: |
||||
return TrainInfoBodyCupertino( |
||||
trainData: trainData, |
||||
onViewYesterdayTrain: onViewYesterdayTrain, |
||||
refresh: refresh, |
||||
isRefreshing: isRefreshing, |
||||
); |
||||
case UiDesign.FLUENT: |
||||
return TrainInfoBodyFluent( |
||||
trainData: trainData, |
||||
onViewYesterdayTrain: onViewYesterdayTrain, |
||||
refresh: refresh, |
||||
isRefreshing: isRefreshing, |
||||
); |
||||
default: |
||||
throw UnmatchedUiDesignException(uiDesign); |
||||
} |
||||
} |
||||
} |
||||
|
||||
abstract class TrainInfoBodyShared extends StatelessWidget { |
||||
final TrainData trainData; |
||||
final void Function()? onViewYesterdayTrain; |
||||
final Future Function()? refresh; |
||||
final bool? isRefreshing; |
||||
|
||||
const TrainInfoBodyShared({ |
||||
required this.trainData, |
||||
this.onViewYesterdayTrain, |
||||
this.refresh, |
||||
this.isRefreshing, |
||||
super.key, |
||||
}); |
||||
} |
||||
|
||||
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.'; |
||||
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); |
||||
const DisplayTrainYesterdayWarningCommon( |
||||
this.onViewYesterdayTrain, { |
||||
super.key, |
||||
}); |
||||
} |
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,793 @@
|
||||
import 'package:fluent_ui/fluent_ui.dart'; |
||||
import 'package:flutter/gestures.dart'; |
||||
import 'package:info_tren/components/train_id_text_span.dart'; |
||||
import 'package:info_tren/models.dart'; |
||||
import 'package:info_tren/pages/station_arrdep_page/view_station/view_station.dart'; |
||||
import 'package:info_tren/pages/train_info_page/view_train/train_info.dart'; |
||||
import 'package:info_tren/pages/train_info_page/view_train/train_info_fluent_DisplayTrainStation.dart'; |
||||
import 'package:info_tren/utils/state_to_string.dart'; |
||||
|
||||
class TrainInfoLoadingFluent extends TrainInfoLoadingShared { |
||||
TrainInfoLoadingFluent({required super.title, super.loadingText, super.key,}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return NavigationView( |
||||
appBar: NavigationAppBar( |
||||
title: Text(title), |
||||
), |
||||
content: Center( |
||||
child: loadingWidget, |
||||
), |
||||
); |
||||
} |
||||
} |
||||
|
||||
class TrainInfoErrorFluent extends TrainInfoErrorShared { |
||||
const TrainInfoErrorFluent({ |
||||
required super.error, |
||||
required super.title, |
||||
super.refresh, |
||||
super.key, |
||||
}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return NavigationView( |
||||
appBar: NavigationAppBar( |
||||
title: Text(title), |
||||
), |
||||
content: Center( |
||||
child: Column( |
||||
mainAxisSize: MainAxisSize.min, |
||||
children: [ |
||||
Text(error.toString()), |
||||
if (refresh != null) |
||||
Padding( |
||||
padding: const EdgeInsets.all(8), |
||||
child: Button( |
||||
child: const Text('Retry'), |
||||
onPressed: () => refresh!(), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
||||
|
||||
class TrainInfoFluent extends TrainInfoShared { |
||||
const TrainInfoFluent({ |
||||
super.key, |
||||
required super.trainData, |
||||
super.isRefreshing, |
||||
super.refresh, |
||||
super.onViewYesterdayTrain, |
||||
}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Builder( |
||||
builder: (context) { |
||||
return NavigationView( |
||||
appBar: NavigationAppBar( |
||||
title: Text( |
||||
"Informații despre ${trainData.rank} ${trainData.number}", |
||||
), |
||||
actions: Row( |
||||
mainAxisSize: MainAxisSize.min, |
||||
children: [ |
||||
if (refresh != null) ...[ |
||||
Center( |
||||
child: SizedBox( |
||||
height: 32, |
||||
width: 32, |
||||
child: IconButton( |
||||
icon: isRefreshing == true ? const ProgressRing() : const Icon( |
||||
FluentIcons.refresh, |
||||
size: 24, |
||||
), |
||||
onPressed: isRefreshing == true ? null : () { |
||||
refresh!(); |
||||
}, |
||||
), |
||||
), |
||||
), |
||||
], |
||||
], |
||||
), |
||||
), |
||||
content: Column( |
||||
children: <Widget>[ |
||||
Expanded( |
||||
child: SafeArea( |
||||
bottom: false, |
||||
child: TrainInfoBody( |
||||
trainData: trainData, |
||||
onViewYesterdayTrain: onViewYesterdayTrain, |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
); |
||||
}, |
||||
); |
||||
} |
||||
} |
||||
|
||||
class TrainInfoBodyFluent extends TrainInfoBodyShared { |
||||
const TrainInfoBodyFluent({ |
||||
super.key, |
||||
required super.trainData, |
||||
super.onViewYesterdayTrain, |
||||
super.refresh, |
||||
super.isRefreshing, |
||||
}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
final mq = MediaQuery.of(context); |
||||
|
||||
if (mq.orientation == Orientation.landscape && mq.size.width >= 1000) { |
||||
return Row( |
||||
mainAxisSize: MainAxisSize.max, |
||||
children: [ |
||||
Container( |
||||
constraints: const BoxConstraints( |
||||
minWidth: 400, |
||||
maxWidth: 400, |
||||
), |
||||
child: Column( |
||||
mainAxisSize: MainAxisSize.max, |
||||
children: [ |
||||
DisplayTrainID(trainData: trainData), |
||||
DisplayTrainOperator(trainData: trainData), |
||||
Padding( |
||||
padding: const EdgeInsets.symmetric(horizontal: 2.0), |
||||
child: DisplayTrainRoute(trainData: trainData), |
||||
), |
||||
DisplayTrainDeparture(trainData: trainData), |
||||
Padding( |
||||
padding: const EdgeInsets.all(8.0), |
||||
child: DisplayTrainLastInfo(trainData: trainData), |
||||
), |
||||
IntrinsicHeight( |
||||
child: Row( |
||||
children: <Widget>[ |
||||
Expanded( |
||||
child: Padding( |
||||
padding: const EdgeInsets.all(8.0), |
||||
child: DisplayTrainRouteDuration( |
||||
trainData: trainData, |
||||
), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: Padding( |
||||
padding: const EdgeInsets.all(8.0), |
||||
child: DisplayTrainRouteDistance( |
||||
trainData: trainData, |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
const Divider(), |
||||
if (onViewYesterdayTrain != null && |
||||
trainData.stations.first.departure!.scheduleTime |
||||
.compareTo(DateTime.now()) > |
||||
0) |
||||
...[ |
||||
DisplayTrainYesterdayWarningFluent( |
||||
onViewYesterdayTrain!, |
||||
), |
||||
const Divider(), |
||||
], |
||||
], |
||||
), |
||||
), |
||||
Expanded( |
||||
child: CustomScrollView( |
||||
slivers: [ |
||||
DisplayTrainStations( |
||||
trainData: trainData, |
||||
), |
||||
SliverToBoxAdapter( |
||||
child: Container( |
||||
height: MediaQuery |
||||
.of(context) |
||||
.viewPadding |
||||
.bottom, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
], |
||||
); |
||||
} |
||||
else { |
||||
return CustomScrollView( |
||||
slivers: <Widget>[ |
||||
SliverToBoxAdapter( |
||||
child: DisplayTrainID( |
||||
trainData: trainData, |
||||
), |
||||
), |
||||
SliverToBoxAdapter( |
||||
child: DisplayTrainOperator( |
||||
trainData: trainData, |
||||
), |
||||
), |
||||
SliverPadding( |
||||
padding: const EdgeInsets.only(left: 2, right: 2), |
||||
sliver: SliverToBoxAdapter( |
||||
child: DisplayTrainRoute( |
||||
trainData: trainData, |
||||
), |
||||
), |
||||
), |
||||
SliverToBoxAdapter( |
||||
child: DisplayTrainDeparture( |
||||
trainData: trainData, |
||||
), |
||||
), |
||||
SliverToBoxAdapter( |
||||
child: DisplayTrainLastInfo( |
||||
trainData: trainData, |
||||
), |
||||
), |
||||
SliverToBoxAdapter( |
||||
child: IntrinsicHeight( |
||||
child: Row( |
||||
children: <Widget>[ |
||||
Expanded( |
||||
child: Padding( |
||||
padding: const EdgeInsets.all(8.0), |
||||
child: DisplayTrainRouteDuration( |
||||
trainData: trainData, |
||||
), |
||||
), |
||||
), |
||||
Expanded( |
||||
child: Padding( |
||||
padding: const EdgeInsets.all(8.0), |
||||
child: DisplayTrainRouteDistance( |
||||
trainData: trainData, |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
), |
||||
const SliverToBoxAdapter( |
||||
child: Divider(), |
||||
), |
||||
if (onViewYesterdayTrain != null && |
||||
trainData.stations.first.departure!.scheduleTime |
||||
.compareTo(DateTime.now()) > |
||||
0) ...[ |
||||
SliverToBoxAdapter( |
||||
child: DisplayTrainYesterdayWarningFluent( |
||||
onViewYesterdayTrain!), |
||||
), |
||||
const SliverToBoxAdapter( |
||||
child: Divider(), |
||||
), |
||||
], |
||||
DisplayTrainStations( |
||||
trainData: trainData, |
||||
), |
||||
SliverToBoxAdapter( |
||||
child: Container( |
||||
height: MediaQuery |
||||
.of(context) |
||||
.viewPadding |
||||
.bottom, |
||||
), |
||||
), |
||||
], |
||||
); |
||||
} |
||||
} |
||||
} |
||||
|
||||
class DisplayTrainID extends StatelessWidget { |
||||
final TrainData trainData; |
||||
|
||||
const DisplayTrainID({required this.trainData, super.key,}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Text.rich( |
||||
trainIdSpan(rank: trainData.rank, number: trainData.number), |
||||
style: FluentTheme.of(context).typography.title?.copyWith( |
||||
color: FluentTheme.of(context).typography.body?.color, |
||||
fontWeight: FontWeight.bold, |
||||
), |
||||
textAlign: TextAlign.center, |
||||
); |
||||
} |
||||
} |
||||
|
||||
class DisplayTrainOperator extends StatelessWidget { |
||||
final TrainData trainData; |
||||
|
||||
const DisplayTrainOperator({required this.trainData, super.key,}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Text( |
||||
trainData.operator, |
||||
style: FluentTheme.of(context).typography.body?.copyWith( |
||||
fontStyle: FontStyle.italic, |
||||
fontSize: 14, |
||||
), |
||||
textAlign: TextAlign.center, |
||||
); |
||||
} |
||||
} |
||||
|
||||
class DisplayTrainRoute extends StatelessWidget { |
||||
final TrainData trainData; |
||||
|
||||
const DisplayTrainRoute({required this.trainData, super.key,}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Row( |
||||
children: <Widget>[ |
||||
Expanded( |
||||
child: Center( |
||||
child: Padding( |
||||
padding: const EdgeInsets.all(4), |
||||
child: Text( |
||||
trainData.route.from, |
||||
style: FluentTheme.of(context).typography.body?.copyWith( |
||||
fontSize: 16, |
||||
), |
||||
), |
||||
), |
||||
), |
||||
), |
||||
const Center(child: Text("-")), |
||||
Expanded( |
||||
child: Center( |
||||
child: Padding( |
||||
padding: const EdgeInsets.all(4), |
||||
child: Text( |
||||
trainData.route.to, |
||||
style: FluentTheme.of(context).typography.body?.copyWith( |
||||
fontSize: 16, |
||||
), |
||||
textAlign: TextAlign.right, |
||||
), |
||||
), |
||||
), |
||||
), |
||||
], |
||||
); |
||||
} |
||||
} |
||||
|
||||
class DisplayTrainDeparture extends StatelessWidget { |
||||
final TrainData trainData; |
||||
|
||||
const DisplayTrainDeparture({required this.trainData, super.key}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Padding( |
||||
padding: const EdgeInsets.all(2), |
||||
child: Text( |
||||
// "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: FluentTheme.of(context).typography.body?.copyWith( |
||||
fontStyle: FontStyle.italic, |
||||
fontWeight: FontWeight.w200, |
||||
fontSize: 16, |
||||
), |
||||
textAlign: TextAlign.center, |
||||
), |
||||
); |
||||
} |
||||
} |
||||
|
||||
class DisplayTrainLastInfo extends StatelessWidget { |
||||
final TrainData trainData; |
||||
|
||||
const DisplayTrainLastInfo({required this.trainData, super.key,}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
if (trainData.status == null) { |
||||
return Container(); |
||||
} |
||||
|
||||
return Card( |
||||
child: Padding( |
||||
padding: const EdgeInsets.all(2), |
||||
child: Column( |
||||
mainAxisSize: MainAxisSize.min, |
||||
children: <Widget>[ |
||||
Center( |
||||
child: Padding( |
||||
padding: const EdgeInsets.all(2), |
||||
child: Text( |
||||
"Ultima informație", |
||||
style: FluentTheme.of(context).typography.body?.copyWith( |
||||
fontSize: 22, |
||||
fontWeight: FontWeight.bold, |
||||
), |
||||
), |
||||
), |
||||
), |
||||
Row( |
||||
children: <Widget>[ |
||||
Padding( |
||||
padding: const EdgeInsets.all(4), |
||||
child: Text( |
||||
trainData.status!.station, |
||||
style: FluentTheme.of(context).typography.body?.copyWith( |
||||
fontSize: 18, |
||||
), |
||||
textAlign: TextAlign.left, |
||||
), |
||||
), |
||||
Expanded( |
||||
child: Container(), |
||||
), |
||||
Padding( |
||||
padding: const EdgeInsets.all(4), |
||||
child: Text( |
||||
stateToString(trainData.status!.state), |
||||
style: FluentTheme.of(context).typography.body?.copyWith( |
||||
fontSize: 18, |
||||
), |
||||
textAlign: TextAlign.right, |
||||
), |
||||
), |
||||
], |
||||
), |
||||
Padding( |
||||
padding: const EdgeInsets.all(2), |
||||
child: Row( |
||||
children: <Widget>[ |
||||
Expanded( |
||||
child: Container(), |
||||
), |
||||
Builder( |
||||
builder: (context) { |
||||
final data = trainData.status!.delay; |
||||
if (data == 0) { |
||||
return Container(); |
||||
} |
||||
|
||||
if (data > 0) { |
||||
return Text( |
||||
"$data ${data == 1 ? 'minut' : 'minute'} întârziere", |
||||
style: |
||||
FluentTheme.of(context).typography.body?.copyWith( |
||||
fontSize: 16, |
||||
color: Colors.red.lighter, |
||||
// color: Colors.red.shade300, |
||||
), |
||||
); |
||||
} else { |
||||
return Text( |
||||
"${-data} ${data == -1 ? 'minut' : 'minute'} mai devreme", |
||||
style: |
||||
FluentTheme.of(context).typography.body?.copyWith( |
||||
fontSize: 16, |
||||
color: Colors.green.lighter, |
||||
// color: Colors.green.shade300, |
||||
), |
||||
); |
||||
} |
||||
}, |
||||
), |
||||
], |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
||||
|
||||
class DisplayTrainDestination extends StatelessWidget { |
||||
final TrainData trainData; |
||||
|
||||
const DisplayTrainDestination({required this.trainData, super.key,}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
final destination = trainData.stations.last; |
||||
|
||||
return Card( |
||||
child: Center( |
||||
child: Padding( |
||||
padding: const EdgeInsets.all(2), |
||||
child: Column( |
||||
mainAxisSize: MainAxisSize.min, |
||||
children: <Widget>[ |
||||
Padding( |
||||
padding: const EdgeInsets.all(4), |
||||
child: Text( |
||||
"Destinația", |
||||
style: FluentTheme.of(context).typography.body?.copyWith( |
||||
fontSize: 22, |
||||
fontWeight: FontWeight.bold, |
||||
), |
||||
textAlign: TextAlign.center, |
||||
), |
||||
), |
||||
Padding( |
||||
padding: const EdgeInsets.fromLTRB(4, 0, 4, 0), |
||||
child: Text( |
||||
destination.name, |
||||
style: FluentTheme.of(context).typography.body?.copyWith( |
||||
fontSize: 20, |
||||
fontWeight: FontWeight.w500, |
||||
), |
||||
textAlign: TextAlign.center, |
||||
), |
||||
), |
||||
Builder( |
||||
builder: (context) { |
||||
final arrival = destination.arrival!.scheduleTime.toLocal(); |
||||
final delay = |
||||
trainData.stations.last.arrival!.status?.delay ?? 0; |
||||
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( |
||||
mainAxisSize: MainAxisSize.min, |
||||
children: <Widget>[ |
||||
// Text( |
||||
// "în ${arrival.day} ${months[arrival.month - 1]} ${arrival.year}", |
||||
// style: Theme.of(context).textTheme.bodyText2?.copyWith( |
||||
// fontSize: isSmallScreen(context) ? 12 : 14, |
||||
// ), |
||||
// textAlign: TextAlign.center, |
||||
// ), |
||||
Text.rich( |
||||
TextSpan( |
||||
text: 'la', |
||||
children: [ |
||||
const TextSpan(text: ' '), |
||||
TextSpan( |
||||
text: |
||||
'${arrival.hour.toString().padLeft(2, '0')}:${arrival.minute.toString().padLeft(2, '0')}', |
||||
style: delay == 0 |
||||
? null |
||||
: const TextStyle( |
||||
decoration: TextDecoration.lineThrough, |
||||
), |
||||
), |
||||
if (delay != 0) ...[ |
||||
const TextSpan(text: ' '), |
||||
TextSpan( |
||||
text: arrivalWithDelayString, |
||||
style: TextStyle( |
||||
color: delay > 0 |
||||
? Colors.red.lighter |
||||
: Colors.green.lighter, |
||||
// color: delay > 0 |
||||
// ? Colors.red.shade300 |
||||
// : Colors.green.shade300, |
||||
), |
||||
), |
||||
] |
||||
], |
||||
), |
||||
style: FluentTheme.of(context).typography.body?.copyWith( |
||||
fontSize: 16, |
||||
), |
||||
textAlign: TextAlign.center, |
||||
), |
||||
], |
||||
); |
||||
}, |
||||
) |
||||
], |
||||
), |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
||||
|
||||
class DisplayTrainRouteDistance extends StatelessWidget { |
||||
final TrainData trainData; |
||||
|
||||
const DisplayTrainRouteDistance({required this.trainData, super.key,}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Card( |
||||
child: Center( |
||||
child: Padding( |
||||
padding: const EdgeInsets.all(2), |
||||
child: Column( |
||||
mainAxisSize: MainAxisSize.min, |
||||
children: <Widget>[ |
||||
Text( |
||||
"Distanța rutei", |
||||
style: FluentTheme.of(context).typography.body?.copyWith( |
||||
fontSize: 22, |
||||
fontWeight: FontWeight.bold, |
||||
), |
||||
textAlign: TextAlign.center, |
||||
), |
||||
Text( |
||||
"${trainData.stations.last.km} km", |
||||
style: FluentTheme.of(context).typography.body?.copyWith( |
||||
fontSize: 20, |
||||
), |
||||
textAlign: TextAlign.center, |
||||
), |
||||
], |
||||
), |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
||||
|
||||
class DisplayTrainRouteDuration extends StatelessWidget { |
||||
final TrainData trainData; |
||||
|
||||
const DisplayTrainRouteDuration({required this.trainData, super.key,}); |
||||
|
||||
@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: FluentTheme.of(context).typography.body?.copyWith( |
||||
fontSize: 22, |
||||
fontWeight: FontWeight.bold, |
||||
), |
||||
textAlign: TextAlign.center, |
||||
), |
||||
Builder( |
||||
builder: (context) { |
||||
var duration = trainData.stations.last.arrival!.scheduleTime |
||||
.difference( |
||||
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: FluentTheme.of(context).typography.body?.copyWith( |
||||
fontSize: 20, |
||||
), |
||||
textAlign: TextAlign.center, |
||||
); |
||||
}, |
||||
), |
||||
], |
||||
), |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
||||
|
||||
class DisplayTrainYesterdayWarningFluent |
||||
extends DisplayTrainYesterdayWarningCommon { |
||||
const DisplayTrainYesterdayWarningFluent(super.onViewYesterdayTrain, {super.key,}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Column( |
||||
mainAxisSize: MainAxisSize.min, |
||||
children: [ |
||||
Padding( |
||||
padding: const EdgeInsets.all(8.0), |
||||
child: Text.rich( |
||||
TextSpan( |
||||
children: [ |
||||
const TextSpan( |
||||
text: DisplayTrainYesterdayWarningCommon.trainDidNotDepart, |
||||
), |
||||
const TextSpan(text: '\n'), |
||||
TextSpan( |
||||
text: DisplayTrainYesterdayWarningCommon.seeYesterdayTrain, |
||||
style: TextStyle( |
||||
color: FluentTheme.of(context).accentColor,// Colors.blue, |
||||
), |
||||
recognizer: TapGestureRecognizer() |
||||
..onTap = onViewYesterdayTrain, |
||||
), |
||||
], |
||||
), |
||||
textAlign: TextAlign.center, |
||||
), |
||||
), |
||||
], |
||||
); |
||||
} |
||||
} |
||||
|
||||
class DisplayTrainStations extends StatelessWidget { |
||||
final TrainData trainData; |
||||
const DisplayTrainStations({required this.trainData, super.key,}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return SliverList( |
||||
delegate: SliverChildBuilderDelegate( |
||||
(context, index) { |
||||
return IndexedSemantics( |
||||
index: index, |
||||
child: DisplayTrainStation( |
||||
station: trainData.stations[index], |
||||
onTap: () { |
||||
Navigator.of(context).pushNamed( |
||||
ViewStationPage.routeName, |
||||
arguments: ViewStationArguments(stationName: trainData.stations[index].name), |
||||
); |
||||
}, |
||||
), |
||||
); |
||||
}, |
||||
childCount: trainData.stations.length, |
||||
addSemanticIndexes: true, |
||||
), |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,547 @@
|
||||
import 'package:fluent_ui/fluent_ui.dart'; |
||||
import 'package:hooks_riverpod/hooks_riverpod.dart'; |
||||
import 'package:info_tren/components/badge/badge.dart'; |
||||
import 'package:info_tren/components/train_id_text_span.dart'; |
||||
import 'package:info_tren/models.dart'; |
||||
import 'package:info_tren/providers.dart'; |
||||
|
||||
class DisplayTrainStation extends StatelessWidget { |
||||
final TrainDataStation station; |
||||
final void Function()? onTap; |
||||
|
||||
const DisplayTrainStation({ |
||||
required this.station, |
||||
this.onTap, |
||||
super.key, |
||||
}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Column( |
||||
mainAxisSize: MainAxisSize.min, |
||||
children: [ |
||||
if (station.notes.whereType<TrainDataNoteDepartsAs>().isNotEmpty) |
||||
Builder( |
||||
builder: (context) { |
||||
final note = |
||||
station.notes.whereType<TrainDataNoteDepartsAs>().first; |
||||
return Padding( |
||||
padding: const EdgeInsets.all(2.0), |
||||
child: Text.rich( |
||||
TextSpan( |
||||
children: [ |
||||
const TextSpan(text: 'Trenul pleacă cu numărul '), |
||||
trainIdSpan(rank: note.rank, number: note.number), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
}, |
||||
), |
||||
Padding( |
||||
padding: const EdgeInsets.all(2), |
||||
child: HoverButton( |
||||
onPressed: onTap, |
||||
builder: (context, states) { |
||||
return Card( |
||||
padding: const EdgeInsets.all(2), |
||||
child: Column( |
||||
mainAxisSize: MainAxisSize.min, |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: <Widget>[ |
||||
Row( |
||||
mainAxisSize: MainAxisSize.max, |
||||
children: <Widget>[ |
||||
Expanded( |
||||
flex: 1, |
||||
child: Align( |
||||
alignment: Alignment.centerLeft, |
||||
child: Builder(builder: (context) { |
||||
final departureStatus = station.departure?.status; |
||||
final arrivalStatus = station.arrival?.status; |
||||
int delay; |
||||
bool real; |
||||
if (departureStatus == null) { |
||||
delay = arrivalStatus?.delay ?? 0; |
||||
real = arrivalStatus?.real ?? false; |
||||
} else if (arrivalStatus == null) { |
||||
delay = departureStatus.delay; |
||||
real = departureStatus.real; |
||||
} else { |
||||
delay = departureStatus.delay; |
||||
real = departureStatus.real; |
||||
if (!real && arrivalStatus.real) { |
||||
delay = arrivalStatus.delay; |
||||
real = arrivalStatus.real; |
||||
} |
||||
} |
||||
|
||||
final isDelayed = delay > 0 && real == true; |
||||
final isOnTime = delay <= 0 && real == true; |
||||
const isNotScheduled = false; |
||||
|
||||
return Badge( |
||||
text: station.km.toString(), |
||||
caption: 'km', |
||||
isNotScheduled: isNotScheduled, |
||||
isDelayed: isDelayed, |
||||
isOnTime: isOnTime, |
||||
); |
||||
}), |
||||
), |
||||
), |
||||
Title( |
||||
station: station, |
||||
), |
||||
Expanded( |
||||
flex: 1, |
||||
child: (station.platform == null) |
||||
? Container() |
||||
: Align( |
||||
alignment: Alignment.centerRight, |
||||
child: Badge( |
||||
text: station.platform!, |
||||
caption: 'linia', |
||||
), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
Time( |
||||
station: station, |
||||
), |
||||
if (station.notes |
||||
.whereType<TrainDataNoteDetachingWagons>() |
||||
.isNotEmpty) |
||||
Builder( |
||||
builder: (context) { |
||||
final note = station.notes |
||||
.whereType<TrainDataNoteDetachingWagons>() |
||||
.first; |
||||
return Text( |
||||
'Trenul detașează vagoane către ${note.station}', |
||||
textAlign: TextAlign.center, |
||||
); |
||||
}, |
||||
), |
||||
if (station.notes |
||||
.whereType<TrainDataNoteReceivingWagons>() |
||||
.isNotEmpty) |
||||
Builder( |
||||
builder: (context) { |
||||
final note = station.notes |
||||
.whereType<TrainDataNoteReceivingWagons>() |
||||
.first; |
||||
return Text( |
||||
'Trenul primește vagoane de la ${note.station}', |
||||
textAlign: TextAlign.center, |
||||
); |
||||
}, |
||||
), |
||||
Delay( |
||||
station: station, |
||||
), |
||||
], |
||||
), |
||||
); |
||||
}, |
||||
), |
||||
), |
||||
if (station.notes |
||||
.whereType<TrainDataNoteTrainNumberChange>() |
||||
.isNotEmpty) |
||||
Builder( |
||||
builder: (context) { |
||||
final note = station.notes |
||||
.whereType<TrainDataNoteTrainNumberChange>() |
||||
.first; |
||||
return Padding( |
||||
padding: const EdgeInsets.all(2.0), |
||||
child: Text.rich( |
||||
TextSpan( |
||||
children: [ |
||||
const TextSpan(text: 'Trenul își schimbă numărul în '), |
||||
trainIdSpan(rank: note.rank, number: note.number), |
||||
], |
||||
), |
||||
), |
||||
); |
||||
}, |
||||
), |
||||
], |
||||
); |
||||
} |
||||
} |
||||
|
||||
class Title extends StatelessWidget { |
||||
final TrainDataStation station; |
||||
|
||||
const Title({ |
||||
required this.station, |
||||
super.key, |
||||
}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Text( |
||||
station.name, |
||||
style: FluentTheme.of(context).typography.body?.copyWith( |
||||
fontSize: 22, |
||||
fontWeight: MediaQuery.of(context).boldText |
||||
? FontWeight.w500 |
||||
: FontWeight.w300, |
||||
// fontStyle: items[1] == "ONI" ? FontStyle.italic : FontStyle.normal, |
||||
), |
||||
textAlign: TextAlign.center, |
||||
); |
||||
} |
||||
} |
||||
|
||||
class Time extends StatelessWidget { |
||||
final TrainDataStation station; |
||||
|
||||
const Time({ |
||||
required this.station, |
||||
super.key, |
||||
}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
if (station.arrival == null) { |
||||
// Plecare |
||||
return DepartureTime( |
||||
station: station, |
||||
firstStation: true, |
||||
); |
||||
} |
||||
|
||||
if (station.departure == null) { |
||||
// Sosire |
||||
return ArrivalTime( |
||||
station: station, |
||||
finalStation: true, |
||||
); |
||||
} |
||||
|
||||
return Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: <Widget>[ |
||||
Text( |
||||
"→", |
||||
style: FluentTheme.of(context).typography.body?.copyWith( |
||||
fontSize: 22, |
||||
), |
||||
), |
||||
Container( |
||||
width: 2, |
||||
), |
||||
ArrivalTime( |
||||
station: station, |
||||
), |
||||
Expanded( |
||||
child: Container(), |
||||
), |
||||
StopTime( |
||||
station: station, |
||||
), |
||||
Expanded( |
||||
child: Container(), |
||||
), |
||||
DepartureTime( |
||||
station: station, |
||||
), |
||||
Container( |
||||
width: 2, |
||||
), |
||||
Text( |
||||
"→", |
||||
style: FluentTheme.of(context).typography.body?.copyWith( |
||||
fontSize: 22, |
||||
), |
||||
), |
||||
], |
||||
); |
||||
} |
||||
} |
||||
|
||||
class ArrivalTime extends ConsumerWidget { |
||||
final TrainDataStation station; |
||||
final bool finalStation; |
||||
|
||||
const ArrivalTime({ |
||||
required this.station, |
||||
this.finalStation = false, |
||||
super.key, |
||||
}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context, WidgetRef ref) { |
||||
final tz = ref.watch(uiTimeZoneProvider); |
||||
if (station.arrival == null) { |
||||
return Container(); |
||||
} |
||||
if (finalStation) { |
||||
return Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: <Widget>[ |
||||
Text( |
||||
"→", |
||||
style: FluentTheme.of(context).typography.body?.copyWith( |
||||
fontSize: 22, |
||||
), |
||||
), |
||||
Container( |
||||
width: 2, |
||||
), |
||||
const Text("sosire la "), |
||||
ArrivalTime( |
||||
station: station, |
||||
), |
||||
Expanded( |
||||
child: Container(), |
||||
), |
||||
], |
||||
); |
||||
} else { |
||||
final delay = station.arrival!.status?.delay ?? 0; |
||||
final time = tz.convertDateTime(station.arrival!.scheduleTime); |
||||
|
||||
if (delay == 0) { |
||||
return Text( |
||||
"${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}"); |
||||
} else if (delay > 0) { |
||||
final oldDate = time; |
||||
final newDate = oldDate.add(Duration(minutes: delay)); |
||||
|
||||
return Column( |
||||
mainAxisSize: MainAxisSize.min, |
||||
children: <Widget>[ |
||||
Text( |
||||
"${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}", |
||||
style: FluentTheme.of(context).typography.body?.copyWith( |
||||
decoration: TextDecoration.lineThrough, |
||||
), |
||||
), |
||||
Text( |
||||
"${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}", |
||||
style: FluentTheme.of(context).typography.body?.copyWith( |
||||
// color: Colors.red.shade300, |
||||
color: Colors.red.lighter, |
||||
), |
||||
), |
||||
], |
||||
); |
||||
} else { |
||||
final oldDate = time; |
||||
final newDate = oldDate.add(Duration(minutes: delay)); |
||||
|
||||
return Column( |
||||
mainAxisSize: MainAxisSize.min, |
||||
children: <Widget>[ |
||||
Text( |
||||
"${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}", |
||||
style: FluentTheme.of(context).typography.body?.copyWith( |
||||
decoration: TextDecoration.lineThrough, |
||||
), |
||||
), |
||||
Text( |
||||
"${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}", |
||||
style: FluentTheme.of(context).typography.body?.copyWith( |
||||
// color: Colors.green.shade300, |
||||
color: Colors.green.lighter, |
||||
), |
||||
), |
||||
], |
||||
); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
class StopTime extends StatelessWidget { |
||||
final TrainDataStation station; |
||||
|
||||
const StopTime({ |
||||
required this.station, |
||||
super.key, |
||||
}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
return Column( |
||||
mainAxisSize: MainAxisSize.min, |
||||
children: <Widget>[ |
||||
const Text( |
||||
"staționează pentru", |
||||
textAlign: TextAlign.center, |
||||
), |
||||
Builder( |
||||
builder: (context) { |
||||
int stopsForInt = station.stoppingTime!; |
||||
bool minutes = false; |
||||
if (stopsForInt >= 60) { |
||||
stopsForInt ~/= 60; |
||||
minutes = true; |
||||
} |
||||
if (stopsForInt == 1) { |
||||
return Text( |
||||
"1 ${minutes ? 'minut' : 'secundă'}", |
||||
textAlign: TextAlign.center, |
||||
); |
||||
} else if (stopsForInt < 20) { |
||||
return Text( |
||||
"$stopsForInt ${minutes ? 'minute' : 'secunde'}", |
||||
textAlign: TextAlign.center, |
||||
); |
||||
} else { |
||||
return Text( |
||||
"$stopsForInt de ${minutes ? 'minute' : 'secunde'}", |
||||
textAlign: TextAlign.center, |
||||
); |
||||
} |
||||
}, |
||||
) |
||||
], |
||||
); |
||||
} |
||||
} |
||||
|
||||
class DepartureTime extends ConsumerWidget { |
||||
final TrainDataStation station; |
||||
final bool firstStation; |
||||
|
||||
const DepartureTime({ |
||||
required this.station, |
||||
this.firstStation = false, |
||||
super.key, |
||||
}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context, WidgetRef ref) { |
||||
final tz = ref.watch(uiTimeZoneProvider); |
||||
if (station.departure == null) { |
||||
return Container(); |
||||
} |
||||
if (firstStation) { |
||||
return Row( |
||||
crossAxisAlignment: CrossAxisAlignment.center, |
||||
children: <Widget>[ |
||||
Expanded( |
||||
child: Container(), |
||||
), |
||||
const Text("plecare la "), |
||||
DepartureTime( |
||||
station: station, |
||||
), |
||||
Container( |
||||
width: 2, |
||||
), |
||||
Text( |
||||
"→", |
||||
style: FluentTheme.of(context).typography.body?.copyWith( |
||||
fontSize: 22, |
||||
), |
||||
), |
||||
], |
||||
); |
||||
} else { |
||||
final delay = station.departure!.status?.delay ?? 0; |
||||
final time = tz.convertDateTime(station.departure!.scheduleTime); |
||||
|
||||
if (delay == 0) { |
||||
return Text( |
||||
"${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}"); |
||||
} else if (delay > 0) { |
||||
final oldDate = time; |
||||
final newDate = oldDate.add(Duration(minutes: delay)); |
||||
|
||||
return Column( |
||||
mainAxisSize: MainAxisSize.min, |
||||
children: <Widget>[ |
||||
Text( |
||||
"${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}", |
||||
style: FluentTheme.of(context).typography.body?.copyWith( |
||||
decoration: TextDecoration.lineThrough, |
||||
), |
||||
), |
||||
Text( |
||||
"${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}", |
||||
style: FluentTheme.of(context).typography.body?.copyWith( |
||||
// color: Colors.red.shade300, |
||||
color: Colors.red.lighter, |
||||
), |
||||
), |
||||
], |
||||
); |
||||
} else { |
||||
final oldDate = time; |
||||
final newDate = oldDate.add(Duration(minutes: delay)); |
||||
|
||||
return Column( |
||||
mainAxisSize: MainAxisSize.min, |
||||
children: <Widget>[ |
||||
Text( |
||||
"${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}", |
||||
style: FluentTheme.of(context).typography.body?.copyWith( |
||||
decoration: TextDecoration.lineThrough, |
||||
), |
||||
), |
||||
Text( |
||||
"${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}", |
||||
style: FluentTheme.of(context).typography.body?.copyWith( |
||||
// color: Colors.green.shade300, |
||||
color: Colors.green.lighter, |
||||
), |
||||
), |
||||
], |
||||
); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
class Delay extends StatelessWidget { |
||||
final TrainDataStation station; |
||||
|
||||
const Delay({ |
||||
required this.station, |
||||
super.key, |
||||
}); |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
if (station.arrival?.status == null && station.departure?.status == null) { |
||||
return Container(); |
||||
} |
||||
var delay = station.arrival?.status?.delay; |
||||
if (station.departure?.status?.real == true) { |
||||
delay = station.departure?.status?.delay; |
||||
} |
||||
|
||||
if (delay == 0 || delay == null) { |
||||
return Container(); |
||||
} else if (delay > 0) { |
||||
return Text( |
||||
"$delay ${delay == 1 ? 'minut' : 'minute'} întârziere", |
||||
style: FluentTheme.of(context).typography.body?.copyWith( |
||||
// color: Colors.red.shade300, |
||||
color: Colors.red.lighter, |
||||
fontSize: 14, |
||||
fontStyle: FontStyle.italic, |
||||
), |
||||
); |
||||
} else if (delay < 0) { |
||||
return Text( |
||||
"${-delay} ${delay == -1 ? 'minut' : 'minute'} mai devreme", |
||||
style: FluentTheme.of(context).typography.body?.copyWith( |
||||
// color: Colors.green.shade300, |
||||
color: Colors.green.lighter, |
||||
fontSize: 14, |
||||
fontStyle: FontStyle.italic, |
||||
), |
||||
); |
||||
} |
||||
|
||||
return Container(); |
||||
} |
||||
} |
@ -0,0 +1,105 @@
|
||||
import 'dart:async'; |
||||
import 'dart:developer'; |
||||
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart'; |
||||
import 'package:info_tren/api/station_data.dart'; |
||||
import 'package:info_tren/api/train_data.dart'; |
||||
import 'package:info_tren/models.dart'; |
||||
import 'package:info_tren/pages/station_arrdep_page/view_station/view_station.dart'; |
||||
import 'package:info_tren/pages/train_info_page/view_train/train_info.dart'; |
||||
import 'package:info_tren/utils/default_ui_design.dart'; |
||||
import 'package:info_tren/utils/iterable_extensions.dart'; |
||||
import 'package:riverpod_annotation/riverpod_annotation.dart'; |
||||
import 'package:shared_preferences/shared_preferences.dart'; |
||||
|
||||
part 'providers.g.dart'; |
||||
|
||||
final sharedPreferencesProvider = Provider<SharedPreferences>( |
||||
(_) => throw UnimplementedError('Please override in ProviderScope'), |
||||
); |
||||
|
||||
class UiDesignNotifier extends StateNotifier<UiDesign> { |
||||
final SharedPreferences sharedPreferences; |
||||
|
||||
UiDesignNotifier({required this.sharedPreferences,}) : super(UiDesign.MATERIAL) { |
||||
final stored = sharedPreferences.getString('uiDesign'); |
||||
final design = UiDesign.values.where((element) => element.name == stored).firstOrNull ?? defaultUiDesign; |
||||
state = design; |
||||
} |
||||
|
||||
void set(UiDesign? design) async { |
||||
if (design != null) { |
||||
await sharedPreferences.setString('uiDesign', design.name); |
||||
} |
||||
else { |
||||
await sharedPreferences.remove('uiDesign'); |
||||
} |
||||
state = design ?? defaultUiDesign; |
||||
} |
||||
} |
||||
final uiDesignProvider = StateNotifierProvider<UiDesignNotifier, UiDesign>( |
||||
(ref) => UiDesignNotifier( |
||||
sharedPreferences: ref.watch(sharedPreferencesProvider), |
||||
), |
||||
dependencies: [sharedPreferencesProvider], |
||||
); |
||||
|
||||
class UiTimeZoneNotifier extends StateNotifier<UiTimeZone> { |
||||
final SharedPreferences sharedPreferences; |
||||
|
||||
UiTimeZoneNotifier({required this.sharedPreferences,}) : super(const RoUiTimeZone()) { |
||||
final stored = sharedPreferences.getString('uiTimeZone'); |
||||
if (stored != null) { |
||||
try { |
||||
state = UiTimeZone.fromSerString(stored); |
||||
} |
||||
catch (e) { |
||||
log('Invalid UiTimeZone ser: $stored, error: $e', level: 1000); |
||||
} |
||||
} |
||||
} |
||||
|
||||
void set(UiTimeZone? timeZone) async { |
||||
if (timeZone != null) { |
||||
await sharedPreferences.setString('uiTimeZone', timeZone.toSerString()); |
||||
} |
||||
else { |
||||
await sharedPreferences.remove('uiTimeZone'); |
||||
} |
||||
state = timeZone ?? const LocalUiTimeZone(); |
||||
} |
||||
} |
||||
final uiTimeZoneProvider = StateNotifierProvider<UiTimeZoneNotifier, UiTimeZone>( |
||||
(ref) => UiTimeZoneNotifier( |
||||
sharedPreferences: ref.watch(sharedPreferencesProvider), |
||||
), |
||||
dependencies: [sharedPreferencesProvider], |
||||
); |
||||
|
||||
final trainInfoArgumentsProvider = Provider<TrainInfoArguments>( |
||||
(_) => throw UnimplementedError('Please override in ProviderScope'), |
||||
); |
||||
|
||||
final stationDataProvider = FutureProvider.family((ref, ViewStationArguments args) async { |
||||
final data = await getStationData(args.stationName, args.date); |
||||
|
||||
final timer = Timer(const Duration(minutes: 2), () { |
||||
ref.invalidateSelf(); |
||||
}); |
||||
ref.onDispose(() { |
||||
timer.cancel(); |
||||
}); |
||||
|
||||
return data; |
||||
}); |
||||
final viewStationArgumentsProvider = Provider<ViewStationArguments>( |
||||
(_) => throw UnimplementedError('Please override in ProviderScope'), |
||||
); |
||||
final viewStationDataProvider = Provider((ref) { |
||||
final args = ref.watch(viewStationArgumentsProvider); |
||||
final data = ref.watch(stationDataProvider(args)); |
||||
return data; |
||||
}, dependencies: [viewStationArgumentsProvider, stationDataProvider]); |
||||
|
||||
@Riverpod(keepAlive: true) |
||||
Future<TrainData> trainInfo(TrainInfoRef ref, {required String trainNumber, DateTime? date}) => getTrain(trainNumber, date: date); |
@ -0,0 +1,120 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND |
||||
|
||||
part of 'providers.dart'; |
||||
|
||||
// ************************************************************************** |
||||
// RiverpodGenerator |
||||
// ************************************************************************** |
||||
|
||||
String _$trainInfoHash() => r'd25aabc3ba656acf6497ec6831e11892178b22c9'; |
||||
|
||||
/// Copied from Dart SDK |
||||
class _SystemHash { |
||||
_SystemHash._(); |
||||
|
||||
static int combine(int hash, int value) { |
||||
// ignore: parameter_assignments |
||||
hash = 0x1fffffff & (hash + value); |
||||
// ignore: parameter_assignments |
||||
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); |
||||
return hash ^ (hash >> 6); |
||||
} |
||||
|
||||
static int finish(int hash) { |
||||
// ignore: parameter_assignments |
||||
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); |
||||
// ignore: parameter_assignments |
||||
hash = hash ^ (hash >> 11); |
||||
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); |
||||
} |
||||
} |
||||
|
||||
typedef TrainInfoRef = FutureProviderRef<TrainData>; |
||||
|
||||
/// See also [trainInfo]. |
||||
@ProviderFor(trainInfo) |
||||
const trainInfoProvider = TrainInfoFamily(); |
||||
|
||||
/// See also [trainInfo]. |
||||
class TrainInfoFamily extends Family<AsyncValue<TrainData>> { |
||||
/// See also [trainInfo]. |
||||
const TrainInfoFamily(); |
||||
|
||||
/// See also [trainInfo]. |
||||
TrainInfoProvider call({ |
||||
required String trainNumber, |
||||
DateTime? date, |
||||
}) { |
||||
return TrainInfoProvider( |
||||
trainNumber: trainNumber, |
||||
date: date, |
||||
); |
||||
} |
||||
|
||||
@override |
||||
TrainInfoProvider getProviderOverride( |
||||
covariant TrainInfoProvider provider, |
||||
) { |
||||
return call( |
||||
trainNumber: provider.trainNumber, |
||||
date: provider.date, |
||||
); |
||||
} |
||||
|
||||
static const Iterable<ProviderOrFamily>? _dependencies = null; |
||||
|
||||
@override |
||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies; |
||||
|
||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null; |
||||
|
||||
@override |
||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies => |
||||
_allTransitiveDependencies; |
||||
|
||||
@override |
||||
String? get name => r'trainInfoProvider'; |
||||
} |
||||
|
||||
/// See also [trainInfo]. |
||||
class TrainInfoProvider extends FutureProvider<TrainData> { |
||||
/// See also [trainInfo]. |
||||
TrainInfoProvider({ |
||||
required this.trainNumber, |
||||
this.date, |
||||
}) : super.internal( |
||||
(ref) => trainInfo( |
||||
ref, |
||||
trainNumber: trainNumber, |
||||
date: date, |
||||
), |
||||
from: trainInfoProvider, |
||||
name: r'trainInfoProvider', |
||||
debugGetCreateSourceHash: |
||||
const bool.fromEnvironment('dart.vm.product') |
||||
? null |
||||
: _$trainInfoHash, |
||||
dependencies: TrainInfoFamily._dependencies, |
||||
allTransitiveDependencies: TrainInfoFamily._allTransitiveDependencies, |
||||
); |
||||
|
||||
final String trainNumber; |
||||
final DateTime? date; |
||||
|
||||
@override |
||||
bool operator ==(Object other) { |
||||
return other is TrainInfoProvider && |
||||
other.trainNumber == trainNumber && |
||||
other.date == date; |
||||
} |
||||
|
||||
@override |
||||
int get hashCode { |
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode); |
||||
hash = _SystemHash.combine(hash, trainNumber.hashCode); |
||||
hash = _SystemHash.combine(hash, date.hashCode); |
||||
|
||||
return _SystemHash.finish(hash); |
||||
} |
||||
} |
||||
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions |
@ -1,11 +1,14 @@
|
||||
import 'dart:io'; |
||||
|
||||
import 'package:info_tren/models/ui_design.dart'; |
||||
import 'package:info_tren/models.dart'; |
||||
|
||||
UiDesign get defaultUiDesign { |
||||
if (Platform.isIOS) { |
||||
return UiDesign.CUPERTINO; |
||||
} |
||||
else if (Platform.isLinux || Platform.isWindows) { |
||||
return UiDesign.FLUENT; |
||||
} |
||||
else { |
||||
return UiDesign.MATERIAL; |
||||
} |
||||
|
@ -1,12 +1,7 @@
|
||||
import 'package:info_tren/models/train_data.dart'; |
||||
import 'package:info_tren/models.dart'; |
||||
|
||||
String stateToString(State state) { |
||||
switch(state) { |
||||
case State.PASSING: |
||||
return 'trecere fără oprire'; |
||||
case State.ARRIVAL: |
||||
return 'sosire'; |
||||
case State.DEPARTURE: |
||||
return 'plecare'; |
||||
} |
||||
} |
||||
String stateToString(TrainDataState state) => switch (state) { |
||||
TrainDataState.passing => 'trecere fără oprire', |
||||
TrainDataState.arrival => 'sosire', |
||||
TrainDataState.departure => 'plecare', |
||||
}; |
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue