Move to API v3
This commit is contained in:
		
							parent
							
								
									1f48e868b0
								
							
						
					
					
						commit
						17d8fac893
					
				
					 22 changed files with 3753 additions and 655 deletions
				
			
		| 
						 | 
				
			
			@ -4,7 +4,11 @@ import 'package:http/http.dart' as http;
 | 
			
		|||
import 'package:info_tren/api/common.dart';
 | 
			
		||||
import 'package:info_tren/models.dart';
 | 
			
		||||
 | 
			
		||||
Future<StationData> getStationData(String stationName) async {
 | 
			
		||||
  final response = await http.get(Uri.https(authority, 'v3/stations/$stationName'));
 | 
			
		||||
Future<StationData> getStationData(String stationName, [DateTime? date]) async {
 | 
			
		||||
  final uri = Uri.https(authority, 'v3/stations/$stationName');
 | 
			
		||||
  if (date != null) {
 | 
			
		||||
    uri.queryParameters['date'] = date.toIso8601String();
 | 
			
		||||
  }
 | 
			
		||||
  final response = await http.get(uri);
 | 
			
		||||
  return StationData.fromJson(jsonDecode(response.body));
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,7 @@ 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', {
 | 
			
		||||
  final response = await http.get(Uri.https(authority, 'v3/trains/$trainNumber', {
 | 
			
		||||
    'date': date.toUtc().toIso8601String(),
 | 
			
		||||
  }),);
 | 
			
		||||
  return trainDataFromJson(response.body);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,11 +4,11 @@ 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' hide State;
 | 
			
		||||
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 State;
 | 
			
		||||
import 'package:info_tren/models/train_data.dart' show TrainDataStatusState;
 | 
			
		||||
 | 
			
		||||
typedef TrainDataState = State;
 | 
			
		||||
typedef TrainDataState = TrainDataStatusState;
 | 
			
		||||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
// 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
 | 
			
		||||
// 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';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
// 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
 | 
			
		||||
// 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';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -158,6 +158,7 @@ class _$_StationData implements _StationData {
 | 
			
		|||
  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);
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -167,6 +168,7 @@ class _$_StationData implements _StationData {
 | 
			
		|||
  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);
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
// 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
 | 
			
		||||
// 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';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
// 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
 | 
			
		||||
// 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';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -189,6 +189,7 @@ class _$_StationTrain implements _StationTrain {
 | 
			
		|||
  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);
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
// 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
 | 
			
		||||
// 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';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -121,6 +121,7 @@ class _$_StationsResult implements _StationsResult {
 | 
			
		|||
  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);
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,181 +4,106 @@
 | 
			
		|||
 | 
			
		||||
import 'dart:convert';
 | 
			
		||||
 | 
			
		||||
import 'package:freezed_annotation/freezed_annotation.dart';
 | 
			
		||||
 | 
			
		||||
part 'train_data.freezed.dart';
 | 
			
		||||
part 'train_data.g.dart';
 | 
			
		||||
 | 
			
		||||
TrainData trainDataFromJson(String str) => TrainData.fromJson(json.decode(str));
 | 
			
		||||
 | 
			
		||||
String trainDataToJson(TrainData data) => json.encode(data.toJson());
 | 
			
		||||
 | 
			
		||||
/// Results of scrapping InfoFer website for train info
 | 
			
		||||
class TrainData {
 | 
			
		||||
  TrainData({
 | 
			
		||||
    required this.date,
 | 
			
		||||
    required this.number,
 | 
			
		||||
    required this.operator,
 | 
			
		||||
    required this.rank,
 | 
			
		||||
    required this.route,
 | 
			
		||||
    required this.stations,
 | 
			
		||||
    this.status,
 | 
			
		||||
  });
 | 
			
		||||
@freezed
 | 
			
		||||
class TrainData with _$TrainData {
 | 
			
		||||
  const TrainData._();
 | 
			
		||||
  
 | 
			
		||||
  const factory TrainData({
 | 
			
		||||
    required String rank,
 | 
			
		||||
    required String number,
 | 
			
		||||
    required String date,
 | 
			
		||||
    required String operator,
 | 
			
		||||
    required List<TrainDataGroup> groups,
 | 
			
		||||
  }) = _TrainData;
 | 
			
		||||
 | 
			
		||||
  final String date;
 | 
			
		||||
  final String number;
 | 
			
		||||
  final String operator;
 | 
			
		||||
  final String rank;
 | 
			
		||||
  final Route route;
 | 
			
		||||
  final List<Station> stations;
 | 
			
		||||
  final TrainDataStatus? status;
 | 
			
		||||
  factory TrainData.fromJson(Map<String, dynamic> json) => _$TrainDataFromJson(json);
 | 
			
		||||
  
 | 
			
		||||
  List<TrainDataStation> get stations => groups.first.stations;
 | 
			
		||||
  TrainDataRoute get route => groups.first.route;
 | 
			
		||||
  TrainDataStatus? get status => groups.first.status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
  factory TrainData.fromJson(Map<String, dynamic> json) => TrainData(
 | 
			
		||||
        date: json["date"],
 | 
			
		||||
        number: json["number"],
 | 
			
		||||
        operator: json["operator"],
 | 
			
		||||
        rank: json["rank"],
 | 
			
		||||
        route: Route.fromJson(json["route"]),
 | 
			
		||||
        stations: List<Station>.from(
 | 
			
		||||
            json["stations"].map((x) => Station.fromJson(x))),
 | 
			
		||||
        status: json["status"] == null
 | 
			
		||||
            ? null
 | 
			
		||||
            : TrainDataStatus.fromJson(json["status"]),
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
  Map<String, dynamic> toJson() => {
 | 
			
		||||
        "date": date,
 | 
			
		||||
        "number": number,
 | 
			
		||||
        "operator": operator,
 | 
			
		||||
        "rank": rank,
 | 
			
		||||
        "route": route.toJson(),
 | 
			
		||||
        "stations": List<dynamic>.from(stations.map((x) => x.toJson())),
 | 
			
		||||
        "status": status?.toJson(),
 | 
			
		||||
      };
 | 
			
		||||
@freezed
 | 
			
		||||
class TrainDataGroup with _$TrainDataGroup {
 | 
			
		||||
  const factory TrainDataGroup({
 | 
			
		||||
    required TrainDataRoute route,
 | 
			
		||||
    required List<TrainDataStation> stations,
 | 
			
		||||
    TrainDataStatus? status,
 | 
			
		||||
  }) = _TrainDataGroup;
 | 
			
		||||
  
 | 
			
		||||
  factory TrainDataGroup.fromJson(Map<String, dynamic> json) => _$TrainDataGroupFromJson(json);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Route of the train
 | 
			
		||||
class Route {
 | 
			
		||||
  Route({
 | 
			
		||||
    required this.from,
 | 
			
		||||
    required this.to,
 | 
			
		||||
  });
 | 
			
		||||
@freezed
 | 
			
		||||
class TrainDataRoute with _$TrainDataRoute {
 | 
			
		||||
  const factory TrainDataRoute({
 | 
			
		||||
    required String from,
 | 
			
		||||
    required String to,
 | 
			
		||||
  }) = _TrainDataRoute;
 | 
			
		||||
 | 
			
		||||
  final String from;
 | 
			
		||||
  final String to;
 | 
			
		||||
 | 
			
		||||
  factory Route.fromJson(Map<String, dynamic> json) => Route(
 | 
			
		||||
        from: json["from"],
 | 
			
		||||
        to: json["to"],
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
  Map<String, dynamic> toJson() => {
 | 
			
		||||
        "from": from,
 | 
			
		||||
        "to": to,
 | 
			
		||||
      };
 | 
			
		||||
  factory TrainDataRoute.fromJson(Map<String, dynamic> json) => _$TrainDataRouteFromJson(json);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Station {
 | 
			
		||||
  Station({
 | 
			
		||||
    this.arrival,
 | 
			
		||||
    this.departure,
 | 
			
		||||
    required this.km,
 | 
			
		||||
    required this.name,
 | 
			
		||||
    this.platform,
 | 
			
		||||
    this.stoppingTime,
 | 
			
		||||
  });
 | 
			
		||||
@freezed
 | 
			
		||||
class TrainDataStation with _$TrainDataStation {
 | 
			
		||||
  const factory TrainDataStation({
 | 
			
		||||
    required String name,
 | 
			
		||||
    required String linkName,
 | 
			
		||||
    required int km,
 | 
			
		||||
    int? stoppingTime,
 | 
			
		||||
    String? platform,
 | 
			
		||||
    StationArrDepTime? arrival,
 | 
			
		||||
    StationArrDepTime? departure,
 | 
			
		||||
    @TrainDataNoteConverter()
 | 
			
		||||
    required List<TrainDataNote> notes,
 | 
			
		||||
  }) = _TrainDataStation;
 | 
			
		||||
 | 
			
		||||
  final StationArrDepTime? arrival;
 | 
			
		||||
  final StationArrDepTime? departure;
 | 
			
		||||
  final int km;
 | 
			
		||||
  final String name;
 | 
			
		||||
  final String? platform;
 | 
			
		||||
  final int? stoppingTime;
 | 
			
		||||
 | 
			
		||||
  factory Station.fromJson(Map<String, dynamic> json) => Station(
 | 
			
		||||
        arrival: json["arrival"] == null
 | 
			
		||||
            ? null
 | 
			
		||||
            : StationArrDepTime.fromJson(json["arrival"]),
 | 
			
		||||
        departure: json["departure"] == null
 | 
			
		||||
            ? null
 | 
			
		||||
            : StationArrDepTime.fromJson(json["departure"]),
 | 
			
		||||
        km: json["km"],
 | 
			
		||||
        name: json["name"],
 | 
			
		||||
        platform: json["platform"],
 | 
			
		||||
        stoppingTime:
 | 
			
		||||
            json["stoppingTime"],
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
  Map<String, dynamic> toJson() => {
 | 
			
		||||
        "arrival": arrival?.toJson(),
 | 
			
		||||
        "departure": departure?.toJson(),
 | 
			
		||||
        "km": km,
 | 
			
		||||
        "name": name,
 | 
			
		||||
        "platform": platform,
 | 
			
		||||
        "stoppingTime": stoppingTime,
 | 
			
		||||
      };
 | 
			
		||||
  factory TrainDataStation.fromJson(Map<String, dynamic> json) => _$TrainDataStationFromJson(json);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class StationArrDepTime {
 | 
			
		||||
  StationArrDepTime({
 | 
			
		||||
    required this.scheduleTime,
 | 
			
		||||
    this.status,
 | 
			
		||||
  });
 | 
			
		||||
@freezed
 | 
			
		||||
class StationArrDepTime with _$StationArrDepTime {
 | 
			
		||||
  const factory StationArrDepTime({
 | 
			
		||||
    required DateTime scheduleTime,
 | 
			
		||||
    StationArrDepTimeStatus? status,
 | 
			
		||||
  }) = _StationArrDepTime;
 | 
			
		||||
 | 
			
		||||
  final DateTime scheduleTime;
 | 
			
		||||
  final StationArrDepTimeStatus? status;
 | 
			
		||||
 | 
			
		||||
  factory StationArrDepTime.fromJson(Map<String, dynamic> json) =>
 | 
			
		||||
      StationArrDepTime(
 | 
			
		||||
        scheduleTime: DateTime.parse(json["scheduleTime"] as String),
 | 
			
		||||
        status: json["status"] == null ? null : StationArrDepTimeStatus.fromJson(json["status"]),
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
  Map<String, dynamic> toJson() => {
 | 
			
		||||
        "scheduleTime": scheduleTime.toIso8601String(),
 | 
			
		||||
        "status": status?.toJson(),
 | 
			
		||||
      };
 | 
			
		||||
  factory StationArrDepTime.fromJson(Map<String, dynamic> json) => _$StationArrDepTimeFromJson(json);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class StationArrDepTimeStatus {
 | 
			
		||||
  StationArrDepTimeStatus({
 | 
			
		||||
    required this.delay,
 | 
			
		||||
    required this.real,
 | 
			
		||||
  });
 | 
			
		||||
@freezed
 | 
			
		||||
class StationArrDepTimeStatus with _$StationArrDepTimeStatus {
 | 
			
		||||
  const factory StationArrDepTimeStatus({
 | 
			
		||||
    required int delay,
 | 
			
		||||
    required bool real,
 | 
			
		||||
    required bool cancelled,
 | 
			
		||||
  }) = _StationArrDepTimeStatus;
 | 
			
		||||
 | 
			
		||||
  final int delay;
 | 
			
		||||
  final bool real;
 | 
			
		||||
 | 
			
		||||
  factory StationArrDepTimeStatus.fromJson(Map<String, dynamic> json) =>
 | 
			
		||||
      StationArrDepTimeStatus(
 | 
			
		||||
        delay: json["delay"],
 | 
			
		||||
        real: json["real"],
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
  Map<String, dynamic> toJson() => {
 | 
			
		||||
        "delay": delay,
 | 
			
		||||
        "real": real,
 | 
			
		||||
      };
 | 
			
		||||
  factory StationArrDepTimeStatus.fromJson(Map<String, dynamic> json) => _$StationArrDepTimeStatusFromJson(json);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class TrainDataStatus {
 | 
			
		||||
  TrainDataStatus({
 | 
			
		||||
    required this.delay,
 | 
			
		||||
    required this.state,
 | 
			
		||||
    required this.station,
 | 
			
		||||
  });
 | 
			
		||||
@freezed
 | 
			
		||||
class TrainDataStatus with _$TrainDataStatus {
 | 
			
		||||
  const TrainDataStatus._();
 | 
			
		||||
 | 
			
		||||
  final int delay;
 | 
			
		||||
  final State state;
 | 
			
		||||
  final String station;
 | 
			
		||||
  const factory TrainDataStatus({
 | 
			
		||||
    required int delay,
 | 
			
		||||
    required String station,
 | 
			
		||||
    required TrainDataStatusState state,
 | 
			
		||||
  }) = _TrainDataStatus;
 | 
			
		||||
 | 
			
		||||
  factory TrainDataStatus.fromJson(Map<String, dynamic> json) =>
 | 
			
		||||
      TrainDataStatus(
 | 
			
		||||
        delay: json["delay"],
 | 
			
		||||
        state: stateValues.map[json["state"]]!,
 | 
			
		||||
        station: json["station"],
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
  Map<String, dynamic> toJson() => {
 | 
			
		||||
        "delay": delay,
 | 
			
		||||
        "state": stateValues.reverse[state],
 | 
			
		||||
        "station": station,
 | 
			
		||||
      };
 | 
			
		||||
  factory TrainDataStatus.fromJson(Map<String, dynamic> json) => _$TrainDataStatusFromJson(json);
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  String toString() {
 | 
			
		||||
| 
						 | 
				
			
			@ -190,38 +115,118 @@ class TrainDataStatus {
 | 
			
		|||
      result += '${delay.abs()} min';
 | 
			
		||||
    }
 | 
			
		||||
    result += ' la ';
 | 
			
		||||
    switch (state) {
 | 
			
		||||
      case State.PASSING:
 | 
			
		||||
        result += 'trecerea fără oprire prin';
 | 
			
		||||
        break;
 | 
			
		||||
      case State.ARRIVAL:
 | 
			
		||||
        result += 'sosirea în';
 | 
			
		||||
        break;
 | 
			
		||||
      case State.DEPARTURE:
 | 
			
		||||
        result += 'plecarea din';
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    result += switch (state) {
 | 
			
		||||
      TrainDataStatusState.passing => 'trecerea fără oprire prin',
 | 
			
		||||
      TrainDataStatusState.arrival => 'sosirea în',
 | 
			
		||||
      TrainDataStatusState.departure => 'plecarea din',
 | 
			
		||||
    };
 | 
			
		||||
    result += station;
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum State { PASSING, ARRIVAL, DEPARTURE }
 | 
			
		||||
enum TrainDataStatusState { passing, arrival, departure }
 | 
			
		||||
 | 
			
		||||
final stateValues = EnumValues({
 | 
			
		||||
  "arrival": State.ARRIVAL,
 | 
			
		||||
  "departure": State.DEPARTURE,
 | 
			
		||||
  "passing": State.PASSING
 | 
			
		||||
});
 | 
			
		||||
abstract class TrainDataNote {
 | 
			
		||||
  final String kind;
 | 
			
		||||
 | 
			
		||||
class EnumValues<T> {
 | 
			
		||||
  Map<String, T> map;
 | 
			
		||||
  Map<T, String>? reverseMap;
 | 
			
		||||
  const TrainDataNote({required this.kind});
 | 
			
		||||
 | 
			
		||||
  EnumValues(this.map);
 | 
			
		||||
  Map<String, dynamic> toJson() => {
 | 
			
		||||
    "kind": kind,
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
  Map<T, String> get reverse {
 | 
			
		||||
    reverseMap ??= map.map((k, v) => MapEntry(v, k));
 | 
			
		||||
    return reverseMap!;
 | 
			
		||||
class TrainDataNoteConverter implements JsonConverter<TrainDataNote, Map<String, dynamic>> {
 | 
			
		||||
  const TrainDataNoteConverter();
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  TrainDataNote fromJson(Map<String, dynamic> json) {
 | 
			
		||||
    return switch(json['kind']) {
 | 
			
		||||
      'trainNumberChange' => TrainDataNoteTrainNumberChange.fromJson(json),
 | 
			
		||||
      'departsAs' => TrainDataNoteDepartsAs.fromJson(json),
 | 
			
		||||
      'detachingWagons' => TrainDataNoteDetachingWagons.fromJson(json),
 | 
			
		||||
      'receivingWagons' => TrainDataNoteReceivingWagons.fromJson(json),
 | 
			
		||||
      _ => TrainDataNoteUnknown.fromJson(json),
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Map<String, dynamic> toJson(TrainDataNote object) {
 | 
			
		||||
    return object.toJson();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@freezed
 | 
			
		||||
class TrainDataNoteTrainNumberChange with _$TrainDataNoteTrainNumberChange implements TrainDataNote {
 | 
			
		||||
  @Implements<TrainDataNote>()
 | 
			
		||||
  const factory TrainDataNoteTrainNumberChange({
 | 
			
		||||
    // base
 | 
			
		||||
    @Default("trainNumberChange")
 | 
			
		||||
    String kind,
 | 
			
		||||
    // impl
 | 
			
		||||
    required String rank,
 | 
			
		||||
    required String number,
 | 
			
		||||
  }) = _TrainDataNoteTrainNumberChange;  
 | 
			
		||||
  
 | 
			
		||||
  factory TrainDataNoteTrainNumberChange.fromJson(Map<String, dynamic> json) => _$TrainDataNoteTrainNumberChangeFromJson(json);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@freezed
 | 
			
		||||
class TrainDataNoteDepartsAs with _$TrainDataNoteDepartsAs implements TrainDataNote {
 | 
			
		||||
  @Implements<TrainDataNote>()
 | 
			
		||||
  const factory TrainDataNoteDepartsAs({
 | 
			
		||||
    // base
 | 
			
		||||
    @Default("departsAs")
 | 
			
		||||
    String kind,
 | 
			
		||||
    // impl
 | 
			
		||||
    required String rank,
 | 
			
		||||
    required String number,
 | 
			
		||||
    required DateTime departureDate,
 | 
			
		||||
  }) = _TrainDataNoteDepartsAs;  
 | 
			
		||||
  
 | 
			
		||||
  factory TrainDataNoteDepartsAs.fromJson(Map<String, dynamic> json) => _$TrainDataNoteDepartsAsFromJson(json);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@freezed
 | 
			
		||||
class TrainDataNoteDetachingWagons with _$TrainDataNoteDetachingWagons implements TrainDataNote {
 | 
			
		||||
  @Implements<TrainDataNote>()
 | 
			
		||||
  const factory TrainDataNoteDetachingWagons({
 | 
			
		||||
    // base
 | 
			
		||||
    @Default("detachingWagons")
 | 
			
		||||
    String kind,
 | 
			
		||||
    // impl
 | 
			
		||||
    required String station,
 | 
			
		||||
  }) = _TrainDataNoteDetachingWagons;  
 | 
			
		||||
  
 | 
			
		||||
  factory TrainDataNoteDetachingWagons.fromJson(Map<String, dynamic> json) => _$TrainDataNoteDetachingWagonsFromJson(json);
 | 
			
		||||
}
 | 
			
		||||
@freezed
 | 
			
		||||
class TrainDataNoteReceivingWagons with _$TrainDataNoteReceivingWagons implements TrainDataNote {
 | 
			
		||||
  @Implements<TrainDataNote>()
 | 
			
		||||
  const factory TrainDataNoteReceivingWagons({
 | 
			
		||||
    // base
 | 
			
		||||
    @Default("receivingWagons")
 | 
			
		||||
    String kind,
 | 
			
		||||
    // impl
 | 
			
		||||
    required String station,
 | 
			
		||||
  }) = _TrainDataNoteReceivingWagons;  
 | 
			
		||||
  
 | 
			
		||||
  factory TrainDataNoteReceivingWagons.fromJson(Map<String, dynamic> json) => _$TrainDataNoteReceivingWagonsFromJson(json);
 | 
			
		||||
}
 | 
			
		||||
  
 | 
			
		||||
@freezed
 | 
			
		||||
class TrainDataNoteUnknown with _$TrainDataNoteUnknown implements TrainDataNote {
 | 
			
		||||
  @Implements<TrainDataNote>()
 | 
			
		||||
  const factory TrainDataNoteUnknown({
 | 
			
		||||
    // base
 | 
			
		||||
    required String kind,
 | 
			
		||||
    // impl
 | 
			
		||||
    required Map<String, dynamic> extra,
 | 
			
		||||
  }) = _TrainDataNoteUnknown;
 | 
			
		||||
  
 | 
			
		||||
  factory TrainDataNoteUnknown.fromJson(Map<String, dynamic> json) => TrainDataNoteUnknown(
 | 
			
		||||
    kind: json['kind'], 
 | 
			
		||||
    extra: Map.from(json)..remove('kind'),
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2365
									
								
								lib/models/train_data.freezed.dart
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2365
									
								
								lib/models/train_data.freezed.dart
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										217
									
								
								lib/models/train_data.g.dart
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										217
									
								
								lib/models/train_data.g.dart
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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,7 +1,7 @@
 | 
			
		|||
// 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
 | 
			
		||||
// 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';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,8 +43,9 @@ class ViewStationPage extends HookConsumerWidget {
 | 
			
		|||
 | 
			
		||||
class ViewStationArguments {
 | 
			
		||||
  final String stationName;
 | 
			
		||||
  final DateTime? date;
 | 
			
		||||
 | 
			
		||||
  const ViewStationArguments({required this.stationName});
 | 
			
		||||
  const ViewStationArguments({required this.stationName, this.date});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
abstract class ViewStationPageShared extends StatelessWidget {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,7 @@
 | 
			
		|||
import 'dart:async';
 | 
			
		||||
 | 
			
		||||
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';
 | 
			
		||||
| 
						 | 
				
			
			@ -9,59 +12,93 @@ import 'package:info_tren/pages/train_info_page/view_train/train_info_fluent.dar
 | 
			
		|||
import 'package:info_tren/pages/train_info_page/view_train/train_info_material.dart';
 | 
			
		||||
import 'package:info_tren/providers.dart';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TrainInfo extends ConsumerWidget {
 | 
			
		||||
class TrainInfo extends HookConsumerWidget {
 | 
			
		||||
  static String routeName = "/trainInfo/display";
 | 
			
		||||
 | 
			
		||||
  const TrainInfo({super.key,});
 | 
			
		||||
  const TrainInfo({
 | 
			
		||||
    super.key,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context, WidgetRef ref) {
 | 
			
		||||
    final uiDesign = ref.watch(uiDesignProvider);
 | 
			
		||||
    final args = ref.watch(trainInfoArgumentsProvider);
 | 
			
		||||
    final trainNumber = args.trainNumber;
 | 
			
		||||
    final date = args.date;
 | 
			
		||||
    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));
 | 
			
		||||
 | 
			
		||||
    return RefreshFutureBuilder<TrainData>(
 | 
			
		||||
      futureCreator: () => getTrain(trainNumber, date: date),
 | 
			
		||||
      builder: (context, refresh, replaceFutureBuilder, snapshot) {
 | 
			
		||||
        void onViewYesterdayTrain() {
 | 
			
		||||
          replaceFutureBuilder(() => getTrain(trainNumber, date: DateTime.now().subtract(const Duration(days: 1))));
 | 
			
		||||
        }
 | 
			
		||||
    Future refresh() async {
 | 
			
		||||
      ref.invalidate(
 | 
			
		||||
        trainInfoProvider(trainNumber: trainNumber, date: requestDate),
 | 
			
		||||
      );
 | 
			
		||||
      await Future.delayed(const Duration(seconds: 1));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        if ([RefreshFutureBuilderState.none, RefreshFutureBuilderState.waiting].contains(snapshot.state)) {
 | 
			
		||||
          return TrainInfoLoading(title: trainNumber.toString(), loadingText: "Se încarcă...",);
 | 
			
		||||
        }
 | 
			
		||||
        else if (snapshot.state == RefreshFutureBuilderState.error) {
 | 
			
		||||
          return TrainInfoError(title: '$trainNumber - Error', error: snapshot.error!, refresh: refresh,);
 | 
			
		||||
        }
 | 
			
		||||
    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:
 | 
			
		||||
            return TrainInfoMaterial(
 | 
			
		||||
              trainData: snapshot.data!, 
 | 
			
		||||
              trainData: data,
 | 
			
		||||
              refresh: refresh,
 | 
			
		||||
              isRefreshing: snapshot.state == RefreshFutureBuilderState.refreshing,
 | 
			
		||||
              isRefreshing: trainDataAsync.isRefreshing,
 | 
			
		||||
              onViewYesterdayTrain: onViewYesterdayTrain,
 | 
			
		||||
            );
 | 
			
		||||
          case UiDesign.CUPERTINO:
 | 
			
		||||
            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: snapshot.data!,
 | 
			
		||||
              trainData: data,
 | 
			
		||||
              refresh: refresh,
 | 
			
		||||
              isRefreshing: snapshot.state == RefreshFutureBuilderState.refreshing,
 | 
			
		||||
              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ă...",
 | 
			
		||||
        );
 | 
			
		||||
      },
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -129,10 +166,12 @@ abstract class TrainInfoLoadingShared extends StatelessWidget {
 | 
			
		|||
  final Widget loadingWidget;
 | 
			
		||||
 | 
			
		||||
  TrainInfoLoadingShared({
 | 
			
		||||
    required this.title, 
 | 
			
		||||
    String? loadingText, 
 | 
			
		||||
    required this.title,
 | 
			
		||||
    String? loadingText,
 | 
			
		||||
    super.key,
 | 
			
		||||
  }) : loadingWidget = Loading(text: loadingText,);
 | 
			
		||||
  }) : loadingWidget = Loading(
 | 
			
		||||
          text: loadingText,
 | 
			
		||||
        );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class TrainInfoError extends ConsumerWidget {
 | 
			
		||||
| 
						 | 
				
			
			@ -181,7 +220,12 @@ abstract class TrainInfoErrorShared extends StatelessWidget {
 | 
			
		|||
  final Object error;
 | 
			
		||||
  final Future Function()? refresh;
 | 
			
		||||
 | 
			
		||||
  const TrainInfoErrorShared({required this.title, required this.error, this.refresh, super.key,});
 | 
			
		||||
  const TrainInfoErrorShared({
 | 
			
		||||
    required this.title,
 | 
			
		||||
    required this.error,
 | 
			
		||||
    this.refresh,
 | 
			
		||||
    super.key,
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class TrainInfoBody extends ConsumerWidget {
 | 
			
		||||
| 
						 | 
				
			
			@ -246,10 +290,15 @@ abstract class TrainInfoBodyShared extends StatelessWidget {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
  const DisplayTrainYesterdayWarningCommon(this.onViewYesterdayTrain, {super.key,});
 | 
			
		||||
  const DisplayTrainYesterdayWarningCommon(
 | 
			
		||||
    this.onViewYesterdayTrain, {
 | 
			
		||||
    super.key,
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1051,8 +1051,8 @@ class DisplayTrainYesterdayWarningCupertino extends DisplayTrainYesterdayWarning
 | 
			
		|||
                const TextSpan(text: '\n'),
 | 
			
		||||
                TextSpan(
 | 
			
		||||
                  text: DisplayTrainYesterdayWarningCommon.seeYesterdayTrain,
 | 
			
		||||
                  style: const TextStyle(
 | 
			
		||||
                    color: CupertinoColors.link,
 | 
			
		||||
                  style: TextStyle(
 | 
			
		||||
                    color: CupertinoTheme.of(context).primaryColor,
 | 
			
		||||
                  ),
 | 
			
		||||
                  recognizer: TapGestureRecognizer()
 | 
			
		||||
                    ..onTap = onViewYesterdayTrain,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,13 +1,18 @@
 | 
			
		|||
import 'package:flutter/cupertino.dart';
 | 
			
		||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
			
		||||
import 'package:info_tren/components/badge/badge.dart';
 | 
			
		||||
import 'package:info_tren/components/cupertino_divider.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 Station station;
 | 
			
		||||
  final TrainDataStation station;
 | 
			
		||||
 | 
			
		||||
  const DisplayTrainStation({required this.station, super.key,});
 | 
			
		||||
  const DisplayTrainStation({
 | 
			
		||||
    required this.station,
 | 
			
		||||
    super.key,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
| 
						 | 
				
			
			@ -15,6 +20,26 @@ class DisplayTrainStation extends StatelessWidget {
 | 
			
		|||
      mainAxisSize: MainAxisSize.min,
 | 
			
		||||
      crossAxisAlignment: CrossAxisAlignment.center,
 | 
			
		||||
      children: <Widget>[
 | 
			
		||||
        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),
 | 
			
		||||
                    ],
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
              );
 | 
			
		||||
            },
 | 
			
		||||
          ),
 | 
			
		||||
          const CupertinoDivider(),
 | 
			
		||||
        ],
 | 
			
		||||
        Row(
 | 
			
		||||
          mainAxisSize: MainAxisSize.max,
 | 
			
		||||
          children: <Widget>[
 | 
			
		||||
| 
						 | 
				
			
			@ -22,42 +47,38 @@ class DisplayTrainStation extends StatelessWidget {
 | 
			
		|||
              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;
 | 
			
		||||
                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;
 | 
			
		||||
                    }
 | 
			
		||||
                    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,
 | 
			
		||||
                    );
 | 
			
		||||
                  }
 | 
			
		||||
                ),
 | 
			
		||||
 | 
			
		||||
                  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(
 | 
			
		||||
| 
						 | 
				
			
			@ -67,7 +88,9 @@ class DisplayTrainStation extends StatelessWidget {
 | 
			
		|||
              flex: 1,
 | 
			
		||||
              child: Align(
 | 
			
		||||
                alignment: Alignment.centerRight,
 | 
			
		||||
                child: station.platform == null ? Container() : Badge(text: station.platform!, caption: 'linia'),
 | 
			
		||||
                child: station.platform == null
 | 
			
		||||
                    ? Container()
 | 
			
		||||
                    : Badge(text: station.platform!, caption: 'linia'),
 | 
			
		||||
              ),
 | 
			
		||||
            ),
 | 
			
		||||
          ],
 | 
			
		||||
| 
						 | 
				
			
			@ -75,16 +98,61 @@ class DisplayTrainStation extends StatelessWidget {
 | 
			
		|||
        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) ...[
 | 
			
		||||
          const CupertinoDivider(),
 | 
			
		||||
          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 Station station;
 | 
			
		||||
  final TrainDataStation station;
 | 
			
		||||
 | 
			
		||||
  const Title({
 | 
			
		||||
    required this.station,
 | 
			
		||||
| 
						 | 
				
			
			@ -96,17 +164,19 @@ class Title extends StatelessWidget {
 | 
			
		|||
    return Text(
 | 
			
		||||
      station.name,
 | 
			
		||||
      style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
			
		||||
        fontSize: 22,
 | 
			
		||||
        fontWeight: MediaQuery.of(context).boldText ? FontWeight.w500 : FontWeight.w300,
 | 
			
		||||
        // fontStyle: items[1] == "ONI" ? FontStyle.italic : FontStyle.normal,
 | 
			
		||||
      ),
 | 
			
		||||
            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 Station station;
 | 
			
		||||
  final TrainDataStation station;
 | 
			
		||||
 | 
			
		||||
  const Time({
 | 
			
		||||
    required this.station,
 | 
			
		||||
| 
						 | 
				
			
			@ -137,21 +207,35 @@ class Time extends StatelessWidget {
 | 
			
		|||
        Text(
 | 
			
		||||
          "→",
 | 
			
		||||
          style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
			
		||||
            fontSize: 22,
 | 
			
		||||
          ),
 | 
			
		||||
                fontSize: 22,
 | 
			
		||||
              ),
 | 
			
		||||
        ),
 | 
			
		||||
        Container(
 | 
			
		||||
          width: 2,
 | 
			
		||||
        ),
 | 
			
		||||
        ArrivalTime(
 | 
			
		||||
          station: station,
 | 
			
		||||
        ),
 | 
			
		||||
        Expanded(
 | 
			
		||||
          child: Container(),
 | 
			
		||||
        ),
 | 
			
		||||
        StopTime(
 | 
			
		||||
          station: station,
 | 
			
		||||
        ),
 | 
			
		||||
        Expanded(
 | 
			
		||||
          child: Container(),
 | 
			
		||||
        ),
 | 
			
		||||
        DepartureTime(
 | 
			
		||||
          station: station,
 | 
			
		||||
        ),
 | 
			
		||||
        Container(
 | 
			
		||||
          width: 2,
 | 
			
		||||
        ),
 | 
			
		||||
        Container(width: 2,),
 | 
			
		||||
        ArrivalTime(station: station,),
 | 
			
		||||
        Expanded(child: Container(),),
 | 
			
		||||
        StopTime(station: station,),
 | 
			
		||||
        Expanded(child: Container(),),
 | 
			
		||||
        DepartureTime(station: station,),
 | 
			
		||||
        Container(width: 2,),
 | 
			
		||||
        Text(
 | 
			
		||||
          "→",
 | 
			
		||||
          style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
			
		||||
            fontSize: 22,
 | 
			
		||||
          ),
 | 
			
		||||
                fontSize: 22,
 | 
			
		||||
              ),
 | 
			
		||||
        ),
 | 
			
		||||
      ],
 | 
			
		||||
    );
 | 
			
		||||
| 
						 | 
				
			
			@ -159,7 +243,7 @@ class Time extends StatelessWidget {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
class ArrivalTime extends ConsumerWidget {
 | 
			
		||||
  final Station station;
 | 
			
		||||
  final TrainDataStation station;
 | 
			
		||||
  final bool finalStation;
 | 
			
		||||
 | 
			
		||||
  const ArrivalTime({
 | 
			
		||||
| 
						 | 
				
			
			@ -179,24 +263,29 @@ class ArrivalTime extends ConsumerWidget {
 | 
			
		|||
          Text(
 | 
			
		||||
            "→",
 | 
			
		||||
            style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
			
		||||
              fontSize: 22,
 | 
			
		||||
            ),
 | 
			
		||||
                  fontSize: 22,
 | 
			
		||||
                ),
 | 
			
		||||
          ),
 | 
			
		||||
          Container(
 | 
			
		||||
            width: 2,
 | 
			
		||||
          ),
 | 
			
		||||
          Container(width: 2,),
 | 
			
		||||
          const Text("sosire la "),
 | 
			
		||||
          ArrivalTime(station: station,),
 | 
			
		||||
          Expanded(child: Container(),),
 | 
			
		||||
          ArrivalTime(
 | 
			
		||||
            station: station,
 | 
			
		||||
          ),
 | 
			
		||||
          Expanded(
 | 
			
		||||
            child: Container(),
 | 
			
		||||
          ),
 | 
			
		||||
        ],
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
    } 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) {
 | 
			
		||||
        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));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -206,19 +295,18 @@ class ArrivalTime extends ConsumerWidget {
 | 
			
		|||
            Text(
 | 
			
		||||
              "${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
 | 
			
		||||
              style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
			
		||||
                decoration: TextDecoration.lineThrough,
 | 
			
		||||
              ),
 | 
			
		||||
                    decoration: TextDecoration.lineThrough,
 | 
			
		||||
                  ),
 | 
			
		||||
            ),
 | 
			
		||||
            Text(
 | 
			
		||||
              "${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}",
 | 
			
		||||
              style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
			
		||||
                color: CupertinoColors.destructiveRed,
 | 
			
		||||
              ),
 | 
			
		||||
                    color: CupertinoColors.destructiveRed,
 | 
			
		||||
                  ),
 | 
			
		||||
            ),
 | 
			
		||||
          ],
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
      } else {
 | 
			
		||||
        final oldDate = time;
 | 
			
		||||
        final newDate = oldDate.add(Duration(minutes: delay));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -228,14 +316,14 @@ class ArrivalTime extends ConsumerWidget {
 | 
			
		|||
            Text(
 | 
			
		||||
              "${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
 | 
			
		||||
              style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
			
		||||
                decoration: TextDecoration.lineThrough,
 | 
			
		||||
              ),
 | 
			
		||||
                    decoration: TextDecoration.lineThrough,
 | 
			
		||||
                  ),
 | 
			
		||||
            ),
 | 
			
		||||
            Text(
 | 
			
		||||
              "${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}",
 | 
			
		||||
              style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
			
		||||
                color: CupertinoColors.systemGreen,
 | 
			
		||||
              ),
 | 
			
		||||
                    color: CupertinoColors.systemGreen,
 | 
			
		||||
                  ),
 | 
			
		||||
            ),
 | 
			
		||||
          ],
 | 
			
		||||
        );
 | 
			
		||||
| 
						 | 
				
			
			@ -245,7 +333,7 @@ class ArrivalTime extends ConsumerWidget {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
class StopTime extends StatelessWidget {
 | 
			
		||||
  final Station station;
 | 
			
		||||
  final TrainDataStation station;
 | 
			
		||||
 | 
			
		||||
  const StopTime({
 | 
			
		||||
    required this.station,
 | 
			
		||||
| 
						 | 
				
			
			@ -275,14 +363,12 @@ class StopTime extends StatelessWidget {
 | 
			
		|||
                minutes ? '1 minut' : '1 secundă',
 | 
			
		||||
                textAlign: TextAlign.center,
 | 
			
		||||
              );
 | 
			
		||||
            }
 | 
			
		||||
            else if (stopsForInt < 20) {
 | 
			
		||||
            } else if (stopsForInt < 20) {
 | 
			
		||||
              return Text(
 | 
			
		||||
                '$stopsForInt ${minutes ?  'minute' : 'seconde'}',
 | 
			
		||||
                '$stopsForInt ${minutes ? 'minute' : 'seconde'}',
 | 
			
		||||
                textAlign: TextAlign.center,
 | 
			
		||||
              );
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
            } else {
 | 
			
		||||
              return Text(
 | 
			
		||||
                '$stopsForInt de ${minutes ? 'minute' : 'secunde'}',
 | 
			
		||||
                textAlign: TextAlign.center,
 | 
			
		||||
| 
						 | 
				
			
			@ -296,7 +382,7 @@ class StopTime extends StatelessWidget {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
class DepartureTime extends ConsumerWidget {
 | 
			
		||||
  final Station station;
 | 
			
		||||
  final TrainDataStation station;
 | 
			
		||||
  final bool firstStation;
 | 
			
		||||
 | 
			
		||||
  const DepartureTime({
 | 
			
		||||
| 
						 | 
				
			
			@ -312,27 +398,32 @@ class DepartureTime extends ConsumerWidget {
 | 
			
		|||
      return Row(
 | 
			
		||||
        crossAxisAlignment: CrossAxisAlignment.center,
 | 
			
		||||
        children: <Widget>[
 | 
			
		||||
          Expanded(child: Container(),),
 | 
			
		||||
          Expanded(
 | 
			
		||||
            child: Container(),
 | 
			
		||||
          ),
 | 
			
		||||
          const Text("plecare la "),
 | 
			
		||||
          DepartureTime(station: station,),
 | 
			
		||||
          Container(width: 2,),
 | 
			
		||||
          DepartureTime(
 | 
			
		||||
            station: station,
 | 
			
		||||
          ),
 | 
			
		||||
          Container(
 | 
			
		||||
            width: 2,
 | 
			
		||||
          ),
 | 
			
		||||
          Text(
 | 
			
		||||
            "→",
 | 
			
		||||
            style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
			
		||||
              fontSize: 22,
 | 
			
		||||
            ),
 | 
			
		||||
                  fontSize: 22,
 | 
			
		||||
                ),
 | 
			
		||||
          ),
 | 
			
		||||
        ],
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
    } 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) {
 | 
			
		||||
        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));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -342,19 +433,18 @@ class DepartureTime extends ConsumerWidget {
 | 
			
		|||
            Text(
 | 
			
		||||
              "${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
 | 
			
		||||
              style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
			
		||||
                decoration: TextDecoration.lineThrough,
 | 
			
		||||
              ),
 | 
			
		||||
                    decoration: TextDecoration.lineThrough,
 | 
			
		||||
                  ),
 | 
			
		||||
            ),
 | 
			
		||||
            Text(
 | 
			
		||||
              "${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}",
 | 
			
		||||
              style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
			
		||||
                color: CupertinoColors.destructiveRed,
 | 
			
		||||
              ),
 | 
			
		||||
                    color: CupertinoColors.destructiveRed,
 | 
			
		||||
                  ),
 | 
			
		||||
            ),
 | 
			
		||||
          ],
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
      } else {
 | 
			
		||||
        final oldDate = time;
 | 
			
		||||
        final newDate = oldDate.add(Duration(minutes: delay));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -364,14 +454,14 @@ class DepartureTime extends ConsumerWidget {
 | 
			
		|||
            Text(
 | 
			
		||||
              "${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
 | 
			
		||||
              style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
			
		||||
                decoration: TextDecoration.lineThrough,
 | 
			
		||||
              ),
 | 
			
		||||
                    decoration: TextDecoration.lineThrough,
 | 
			
		||||
                  ),
 | 
			
		||||
            ),
 | 
			
		||||
            Text(
 | 
			
		||||
              "${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}",
 | 
			
		||||
              style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
			
		||||
                color: CupertinoColors.systemGreen,
 | 
			
		||||
              ),
 | 
			
		||||
                    color: CupertinoColors.systemGreen,
 | 
			
		||||
                  ),
 | 
			
		||||
            ),
 | 
			
		||||
          ],
 | 
			
		||||
        );
 | 
			
		||||
| 
						 | 
				
			
			@ -381,7 +471,7 @@ class DepartureTime extends ConsumerWidget {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
class Delay extends StatelessWidget {
 | 
			
		||||
  final Station station;
 | 
			
		||||
  final TrainDataStation station;
 | 
			
		||||
 | 
			
		||||
  const Delay({
 | 
			
		||||
    required this.station,
 | 
			
		||||
| 
						 | 
				
			
			@ -404,20 +494,19 @@ class Delay extends StatelessWidget {
 | 
			
		|||
      return Text(
 | 
			
		||||
        "$delay ${delay == 1 ? 'minut' : 'minute'} întârziere",
 | 
			
		||||
        style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
			
		||||
          color: CupertinoColors.destructiveRed,
 | 
			
		||||
          fontSize: 14,
 | 
			
		||||
          fontStyle: FontStyle.italic,
 | 
			
		||||
        ),
 | 
			
		||||
              color: CupertinoColors.destructiveRed,
 | 
			
		||||
              fontSize: 14,
 | 
			
		||||
              fontStyle: FontStyle.italic,
 | 
			
		||||
            ),
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    else if (delay < 0) {
 | 
			
		||||
    } else if (delay < 0) {
 | 
			
		||||
      return Text(
 | 
			
		||||
        "${-delay} ${delay == -1 ? 'minut' : 'minute'} mai devreme",
 | 
			
		||||
        style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
			
		||||
          color: CupertinoColors.systemGreen,
 | 
			
		||||
          fontSize: 14,
 | 
			
		||||
          fontStyle: FontStyle.italic,
 | 
			
		||||
        ),
 | 
			
		||||
              color: CupertinoColors.systemGreen,
 | 
			
		||||
              fontSize: 14,
 | 
			
		||||
              fontStyle: FontStyle.italic,
 | 
			
		||||
            ),
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -748,7 +748,7 @@ class DisplayTrainYesterdayWarningFluent
 | 
			
		|||
                TextSpan(
 | 
			
		||||
                  text: DisplayTrainYesterdayWarningCommon.seeYesterdayTrain,
 | 
			
		||||
                  style: TextStyle(
 | 
			
		||||
                    color: Colors.blue,
 | 
			
		||||
                    color: FluentTheme.of(context).accentColor,// Colors.blue,
 | 
			
		||||
                  ),
 | 
			
		||||
                  recognizer: TapGestureRecognizer()
 | 
			
		||||
                    ..onTap = onViewYesterdayTrain,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,37 +1,62 @@
 | 
			
		|||
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 Station station;
 | 
			
		||||
  final TrainDataStation station;
 | 
			
		||||
  final void Function()? onTap;
 | 
			
		||||
 | 
			
		||||
  const DisplayTrainStation({required this.station, this.onTap, super.key,});
 | 
			
		||||
  const DisplayTrainStation({
 | 
			
		||||
    required this.station,
 | 
			
		||||
    this.onTap,
 | 
			
		||||
    super.key,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return 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,
 | 
			
		||||
    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>[
 | 
			
		||||
                    Expanded(
 | 
			
		||||
                      flex: 1,
 | 
			
		||||
                      child: Align(
 | 
			
		||||
                        alignment: Alignment.centerLeft,
 | 
			
		||||
                        child: Builder(
 | 
			
		||||
                            builder: (context) {
 | 
			
		||||
                    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;
 | 
			
		||||
| 
						 | 
				
			
			@ -39,12 +64,10 @@ class DisplayTrainStation extends StatelessWidget {
 | 
			
		|||
                              if (departureStatus == null) {
 | 
			
		||||
                                delay = arrivalStatus?.delay ?? 0;
 | 
			
		||||
                                real = arrivalStatus?.real ?? false;
 | 
			
		||||
                              }
 | 
			
		||||
                              else if (arrivalStatus == null) {
 | 
			
		||||
                              } else if (arrivalStatus == null) {
 | 
			
		||||
                                delay = departureStatus.delay;
 | 
			
		||||
                                real = departureStatus.real;
 | 
			
		||||
                              }
 | 
			
		||||
                              else {
 | 
			
		||||
                              } else {
 | 
			
		||||
                                delay = departureStatus.delay;
 | 
			
		||||
                                real = departureStatus.real;
 | 
			
		||||
                                if (!real && arrivalStatus.real) {
 | 
			
		||||
| 
						 | 
				
			
			@ -64,41 +87,94 @@ class DisplayTrainStation extends StatelessWidget {
 | 
			
		|||
                                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',
 | 
			
		||||
                                  ),
 | 
			
		||||
                                ),
 | 
			
		||||
                        ),
 | 
			
		||||
                      ],
 | 
			
		||||
                    ),
 | 
			
		||||
                    Title(
 | 
			
		||||
                    Time(
 | 
			
		||||
                      station: station,
 | 
			
		||||
                    ),
 | 
			
		||||
                    Expanded(
 | 
			
		||||
                      flex: 1,
 | 
			
		||||
                      child: (station.platform == null)
 | 
			
		||||
                          ? Container()
 | 
			
		||||
                          : Align(
 | 
			
		||||
                        alignment: Alignment.centerRight,
 | 
			
		||||
                        child: Badge(text: station.platform!, caption: 'linia',),
 | 
			
		||||
                    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,
 | 
			
		||||
                    ),
 | 
			
		||||
                  ],
 | 
			
		||||
                ),
 | 
			
		||||
                Time(
 | 
			
		||||
                  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),
 | 
			
		||||
                    ],
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
                Delay(
 | 
			
		||||
                  station: station,
 | 
			
		||||
                ),
 | 
			
		||||
              ],
 | 
			
		||||
            ),
 | 
			
		||||
          );
 | 
			
		||||
        },
 | 
			
		||||
      ),
 | 
			
		||||
              );
 | 
			
		||||
            },
 | 
			
		||||
          ),
 | 
			
		||||
      ],
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Title extends StatelessWidget {
 | 
			
		||||
  final Station station;
 | 
			
		||||
  final TrainDataStation station;
 | 
			
		||||
 | 
			
		||||
  const Title({
 | 
			
		||||
    required this.station,
 | 
			
		||||
| 
						 | 
				
			
			@ -107,20 +183,22 @@ class Title extends StatelessWidget {
 | 
			
		|||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return  Text(
 | 
			
		||||
    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,
 | 
			
		||||
      ),
 | 
			
		||||
            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 Station station;
 | 
			
		||||
  final TrainDataStation station;
 | 
			
		||||
 | 
			
		||||
  const Time({
 | 
			
		||||
    required this.station,
 | 
			
		||||
| 
						 | 
				
			
			@ -151,21 +229,35 @@ class Time extends StatelessWidget {
 | 
			
		|||
        Text(
 | 
			
		||||
          "→",
 | 
			
		||||
          style: FluentTheme.of(context).typography.body?.copyWith(
 | 
			
		||||
            fontSize: 22,
 | 
			
		||||
          ),
 | 
			
		||||
                fontSize: 22,
 | 
			
		||||
              ),
 | 
			
		||||
        ),
 | 
			
		||||
        Container(
 | 
			
		||||
          width: 2,
 | 
			
		||||
        ),
 | 
			
		||||
        ArrivalTime(
 | 
			
		||||
          station: station,
 | 
			
		||||
        ),
 | 
			
		||||
        Expanded(
 | 
			
		||||
          child: Container(),
 | 
			
		||||
        ),
 | 
			
		||||
        StopTime(
 | 
			
		||||
          station: station,
 | 
			
		||||
        ),
 | 
			
		||||
        Expanded(
 | 
			
		||||
          child: Container(),
 | 
			
		||||
        ),
 | 
			
		||||
        DepartureTime(
 | 
			
		||||
          station: station,
 | 
			
		||||
        ),
 | 
			
		||||
        Container(
 | 
			
		||||
          width: 2,
 | 
			
		||||
        ),
 | 
			
		||||
        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,
 | 
			
		||||
          ),
 | 
			
		||||
                fontSize: 22,
 | 
			
		||||
              ),
 | 
			
		||||
        ),
 | 
			
		||||
      ],
 | 
			
		||||
    );
 | 
			
		||||
| 
						 | 
				
			
			@ -173,7 +265,7 @@ class Time extends StatelessWidget {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
class ArrivalTime extends ConsumerWidget {
 | 
			
		||||
  final Station station;
 | 
			
		||||
  final TrainDataStation station;
 | 
			
		||||
  final bool finalStation;
 | 
			
		||||
 | 
			
		||||
  const ArrivalTime({
 | 
			
		||||
| 
						 | 
				
			
			@ -195,24 +287,29 @@ class ArrivalTime extends ConsumerWidget {
 | 
			
		|||
          Text(
 | 
			
		||||
            "→",
 | 
			
		||||
            style: FluentTheme.of(context).typography.body?.copyWith(
 | 
			
		||||
              fontSize: 22,
 | 
			
		||||
            ),
 | 
			
		||||
                  fontSize: 22,
 | 
			
		||||
                ),
 | 
			
		||||
          ),
 | 
			
		||||
          Container(
 | 
			
		||||
            width: 2,
 | 
			
		||||
          ),
 | 
			
		||||
          Container(width: 2,),
 | 
			
		||||
          const Text("sosire la "),
 | 
			
		||||
          ArrivalTime(station: station,),
 | 
			
		||||
          Expanded(child: Container(),),
 | 
			
		||||
          ArrivalTime(
 | 
			
		||||
            station: station,
 | 
			
		||||
          ),
 | 
			
		||||
          Expanded(
 | 
			
		||||
            child: Container(),
 | 
			
		||||
          ),
 | 
			
		||||
        ],
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
    } 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) {
 | 
			
		||||
        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));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -222,20 +319,19 @@ class ArrivalTime extends ConsumerWidget {
 | 
			
		|||
            Text(
 | 
			
		||||
              "${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
 | 
			
		||||
              style: FluentTheme.of(context).typography.body?.copyWith(
 | 
			
		||||
                decoration: TextDecoration.lineThrough,
 | 
			
		||||
              ),
 | 
			
		||||
                    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,
 | 
			
		||||
              ),
 | 
			
		||||
                    // color: Colors.red.shade300,
 | 
			
		||||
                    color: Colors.red.lighter,
 | 
			
		||||
                  ),
 | 
			
		||||
            ),
 | 
			
		||||
          ],
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
      } else {
 | 
			
		||||
        final oldDate = time;
 | 
			
		||||
        final newDate = oldDate.add(Duration(minutes: delay));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -245,15 +341,15 @@ class ArrivalTime extends ConsumerWidget {
 | 
			
		|||
            Text(
 | 
			
		||||
              "${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
 | 
			
		||||
              style: FluentTheme.of(context).typography.body?.copyWith(
 | 
			
		||||
                decoration: TextDecoration.lineThrough,
 | 
			
		||||
              ),
 | 
			
		||||
                    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,
 | 
			
		||||
              ),
 | 
			
		||||
                    // color: Colors.green.shade300,
 | 
			
		||||
                    color: Colors.green.lighter,
 | 
			
		||||
                  ),
 | 
			
		||||
            ),
 | 
			
		||||
          ],
 | 
			
		||||
        );
 | 
			
		||||
| 
						 | 
				
			
			@ -263,7 +359,7 @@ class ArrivalTime extends ConsumerWidget {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
class StopTime extends StatelessWidget {
 | 
			
		||||
  final Station station;
 | 
			
		||||
  final TrainDataStation station;
 | 
			
		||||
 | 
			
		||||
  const StopTime({
 | 
			
		||||
    required this.station,
 | 
			
		||||
| 
						 | 
				
			
			@ -292,14 +388,12 @@ class StopTime extends StatelessWidget {
 | 
			
		|||
                "1 ${minutes ? 'minut' : 'secundă'}",
 | 
			
		||||
                textAlign: TextAlign.center,
 | 
			
		||||
              );
 | 
			
		||||
            }
 | 
			
		||||
            else if (stopsForInt < 20) {
 | 
			
		||||
            } else if (stopsForInt < 20) {
 | 
			
		||||
              return Text(
 | 
			
		||||
                "$stopsForInt ${minutes ? 'minute' : 'secunde'}",
 | 
			
		||||
                textAlign: TextAlign.center,
 | 
			
		||||
              );
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
            } else {
 | 
			
		||||
              return Text(
 | 
			
		||||
                "$stopsForInt de ${minutes ? 'minute' : 'secunde'}",
 | 
			
		||||
                textAlign: TextAlign.center,
 | 
			
		||||
| 
						 | 
				
			
			@ -313,7 +407,7 @@ class StopTime extends StatelessWidget {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
class DepartureTime extends ConsumerWidget {
 | 
			
		||||
  final Station station;
 | 
			
		||||
  final TrainDataStation station;
 | 
			
		||||
  final bool firstStation;
 | 
			
		||||
 | 
			
		||||
  const DepartureTime({
 | 
			
		||||
| 
						 | 
				
			
			@ -332,27 +426,32 @@ class DepartureTime extends ConsumerWidget {
 | 
			
		|||
      return Row(
 | 
			
		||||
        crossAxisAlignment: CrossAxisAlignment.center,
 | 
			
		||||
        children: <Widget>[
 | 
			
		||||
          Expanded(child: Container(),),
 | 
			
		||||
          Expanded(
 | 
			
		||||
            child: Container(),
 | 
			
		||||
          ),
 | 
			
		||||
          const Text("plecare la "),
 | 
			
		||||
          DepartureTime(station: station,),
 | 
			
		||||
          Container(width: 2,),
 | 
			
		||||
          DepartureTime(
 | 
			
		||||
            station: station,
 | 
			
		||||
          ),
 | 
			
		||||
          Container(
 | 
			
		||||
            width: 2,
 | 
			
		||||
          ),
 | 
			
		||||
          Text(
 | 
			
		||||
            "→",
 | 
			
		||||
            style: FluentTheme.of(context).typography.body?.copyWith(
 | 
			
		||||
              fontSize: 22,
 | 
			
		||||
            ),
 | 
			
		||||
                  fontSize: 22,
 | 
			
		||||
                ),
 | 
			
		||||
          ),
 | 
			
		||||
        ],
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
    } 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) {
 | 
			
		||||
        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));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -362,20 +461,19 @@ class DepartureTime extends ConsumerWidget {
 | 
			
		|||
            Text(
 | 
			
		||||
              "${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
 | 
			
		||||
              style: FluentTheme.of(context).typography.body?.copyWith(
 | 
			
		||||
                decoration: TextDecoration.lineThrough,
 | 
			
		||||
              ),
 | 
			
		||||
                    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,
 | 
			
		||||
              ),
 | 
			
		||||
                    // color: Colors.red.shade300,
 | 
			
		||||
                    color: Colors.red.lighter,
 | 
			
		||||
                  ),
 | 
			
		||||
            ),
 | 
			
		||||
          ],
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
      } else {
 | 
			
		||||
        final oldDate = time;
 | 
			
		||||
        final newDate = oldDate.add(Duration(minutes: delay));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -385,15 +483,15 @@ class DepartureTime extends ConsumerWidget {
 | 
			
		|||
            Text(
 | 
			
		||||
              "${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
 | 
			
		||||
              style: FluentTheme.of(context).typography.body?.copyWith(
 | 
			
		||||
                decoration: TextDecoration.lineThrough,
 | 
			
		||||
              ),
 | 
			
		||||
                    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,
 | 
			
		||||
              ),
 | 
			
		||||
                    // color: Colors.green.shade300,
 | 
			
		||||
                    color: Colors.green.lighter,
 | 
			
		||||
                  ),
 | 
			
		||||
            ),
 | 
			
		||||
          ],
 | 
			
		||||
        );
 | 
			
		||||
| 
						 | 
				
			
			@ -402,9 +500,8 @@ class DepartureTime extends ConsumerWidget {
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Delay extends StatelessWidget {
 | 
			
		||||
  final Station station;
 | 
			
		||||
  final TrainDataStation station;
 | 
			
		||||
 | 
			
		||||
  const Delay({
 | 
			
		||||
    required this.station,
 | 
			
		||||
| 
						 | 
				
			
			@ -427,22 +524,21 @@ class Delay extends StatelessWidget {
 | 
			
		|||
      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,
 | 
			
		||||
        ),
 | 
			
		||||
              // color: Colors.red.shade300,
 | 
			
		||||
              color: Colors.red.lighter,
 | 
			
		||||
              fontSize: 14,
 | 
			
		||||
              fontStyle: FontStyle.italic,
 | 
			
		||||
            ),
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    else if (delay < 0) {
 | 
			
		||||
    } 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,
 | 
			
		||||
        ),
 | 
			
		||||
              // color: Colors.green.shade300,
 | 
			
		||||
              color: Colors.green.lighter,
 | 
			
		||||
              fontSize: 14,
 | 
			
		||||
              fontStyle: FontStyle.italic,
 | 
			
		||||
            ),
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,7 +9,11 @@ import 'package:info_tren/pages/train_info_page/view_train/train_info_material_D
 | 
			
		|||
import 'package:info_tren/utils/state_to_string.dart';
 | 
			
		||||
 | 
			
		||||
class TrainInfoLoadingMaterial extends TrainInfoLoadingShared {
 | 
			
		||||
  TrainInfoLoadingMaterial({required super.title, super.loadingText, super.key,});
 | 
			
		||||
  TrainInfoLoadingMaterial({
 | 
			
		||||
    required super.title,
 | 
			
		||||
    super.loadingText,
 | 
			
		||||
    super.key,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
| 
						 | 
				
			
			@ -77,13 +81,34 @@ class TrainInfoMaterial extends TrainInfoShared {
 | 
			
		|||
      builder: (context) {
 | 
			
		||||
        return Scaffold(
 | 
			
		||||
          appBar: isSmallScreen(context)
 | 
			
		||||
            ? null
 | 
			
		||||
            : AppBar(
 | 
			
		||||
                centerTitle: true,
 | 
			
		||||
                title: Text(
 | 
			
		||||
                  "Informații despre ${trainData.rank} ${trainData.number}",
 | 
			
		||||
              ? null
 | 
			
		||||
              : AppBar(
 | 
			
		||||
                  centerTitle: true,
 | 
			
		||||
                  title: Text(
 | 
			
		||||
                    'Informații despre ${trainData.rank} ${trainData.number}',
 | 
			
		||||
                  ),
 | 
			
		||||
                  actions: [
 | 
			
		||||
                    IconButton(
 | 
			
		||||
                      tooltip: 'Reîncarcă',
 | 
			
		||||
                      icon: (isRefreshing ?? false)
 | 
			
		||||
                          ? const Center(
 | 
			
		||||
                            child: SizedBox(
 | 
			
		||||
                                height: 16,
 | 
			
		||||
                                width: 16,
 | 
			
		||||
                                child: CircularProgressIndicator(
 | 
			
		||||
                                  strokeWidth: 2,
 | 
			
		||||
                                ),
 | 
			
		||||
                              ),
 | 
			
		||||
                          )
 | 
			
		||||
                          : const Icon(Icons.refresh),
 | 
			
		||||
                      onPressed: (isRefreshing ?? false)
 | 
			
		||||
                          ? null
 | 
			
		||||
                          : () {
 | 
			
		||||
                              refresh?.call();
 | 
			
		||||
                            },
 | 
			
		||||
                    ),
 | 
			
		||||
                  ],
 | 
			
		||||
                ),
 | 
			
		||||
              ),
 | 
			
		||||
          body: Column(
 | 
			
		||||
            children: <Widget>[
 | 
			
		||||
              if (isSmallScreen(context))
 | 
			
		||||
| 
						 | 
				
			
			@ -172,16 +197,15 @@ class TrainInfoBodyMaterial extends TrainInfoBodyShared {
 | 
			
		|||
                if (onViewYesterdayTrain != null &&
 | 
			
		||||
                    trainData.stations.first.departure!.scheduleTime
 | 
			
		||||
                            .compareTo(DateTime.now()) >
 | 
			
		||||
                        0)
 | 
			
		||||
                  ...[
 | 
			
		||||
                    DisplayTrainYesterdayWarningMaterial(
 | 
			
		||||
                      onViewYesterdayTrain!,
 | 
			
		||||
                    ),
 | 
			
		||||
                    Divider(
 | 
			
		||||
                      color: Colors.white70,
 | 
			
		||||
                      height: isSmallScreen(context) ? 8 : 16,
 | 
			
		||||
                    ),
 | 
			
		||||
                  ],
 | 
			
		||||
                        0) ...[
 | 
			
		||||
                  DisplayTrainYesterdayWarningMaterial(
 | 
			
		||||
                    onViewYesterdayTrain!,
 | 
			
		||||
                  ),
 | 
			
		||||
                  Divider(
 | 
			
		||||
                    color: Colors.white70,
 | 
			
		||||
                    height: isSmallScreen(context) ? 8 : 16,
 | 
			
		||||
                  ),
 | 
			
		||||
                ],
 | 
			
		||||
              ],
 | 
			
		||||
            ),
 | 
			
		||||
          ),
 | 
			
		||||
| 
						 | 
				
			
			@ -193,10 +217,7 @@ class TrainInfoBodyMaterial extends TrainInfoBodyShared {
 | 
			
		|||
                ),
 | 
			
		||||
                SliverToBoxAdapter(
 | 
			
		||||
                  child: Container(
 | 
			
		||||
                    height: MediaQuery
 | 
			
		||||
                        .of(context)
 | 
			
		||||
                        .viewPadding
 | 
			
		||||
                        .bottom,
 | 
			
		||||
                    height: MediaQuery.of(context).viewPadding.bottom,
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
              ],
 | 
			
		||||
| 
						 | 
				
			
			@ -204,8 +225,7 @@ class TrainInfoBodyMaterial extends TrainInfoBodyShared {
 | 
			
		|||
          ),
 | 
			
		||||
        ],
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
    } else {
 | 
			
		||||
      return CustomScrollView(
 | 
			
		||||
        slivers: <Widget>[
 | 
			
		||||
          SliverToBoxAdapter(
 | 
			
		||||
| 
						 | 
				
			
			@ -281,11 +301,11 @@ class TrainInfoBodyMaterial extends TrainInfoBodyShared {
 | 
			
		|||
          ),
 | 
			
		||||
          if (onViewYesterdayTrain != null &&
 | 
			
		||||
              trainData.stations.first.departure!.scheduleTime
 | 
			
		||||
                  .compareTo(DateTime.now()) >
 | 
			
		||||
                      .compareTo(DateTime.now()) >
 | 
			
		||||
                  0) ...[
 | 
			
		||||
            SliverToBoxAdapter(
 | 
			
		||||
              child: DisplayTrainYesterdayWarningMaterial(
 | 
			
		||||
                  onViewYesterdayTrain!),
 | 
			
		||||
              child:
 | 
			
		||||
                  DisplayTrainYesterdayWarningMaterial(onViewYesterdayTrain!),
 | 
			
		||||
            ),
 | 
			
		||||
            SliverToBoxAdapter(
 | 
			
		||||
              child: Divider(
 | 
			
		||||
| 
						 | 
				
			
			@ -299,10 +319,7 @@ class TrainInfoBodyMaterial extends TrainInfoBodyShared {
 | 
			
		|||
          ),
 | 
			
		||||
          SliverToBoxAdapter(
 | 
			
		||||
            child: Container(
 | 
			
		||||
              height: MediaQuery
 | 
			
		||||
                  .of(context)
 | 
			
		||||
                  .viewPadding
 | 
			
		||||
                  .bottom,
 | 
			
		||||
              height: MediaQuery.of(context).viewPadding.bottom,
 | 
			
		||||
            ),
 | 
			
		||||
          ),
 | 
			
		||||
        ],
 | 
			
		||||
| 
						 | 
				
			
			@ -314,7 +331,10 @@ class TrainInfoBodyMaterial extends TrainInfoBodyShared {
 | 
			
		|||
class DisplayTrainID extends StatelessWidget {
 | 
			
		||||
  final TrainData trainData;
 | 
			
		||||
 | 
			
		||||
  const DisplayTrainID({required this.trainData, super.key,});
 | 
			
		||||
  const DisplayTrainID({
 | 
			
		||||
    required this.trainData,
 | 
			
		||||
    super.key,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
| 
						 | 
				
			
			@ -335,7 +355,10 @@ class DisplayTrainID extends StatelessWidget {
 | 
			
		|||
class DisplayTrainOperator extends StatelessWidget {
 | 
			
		||||
  final TrainData trainData;
 | 
			
		||||
 | 
			
		||||
  const DisplayTrainOperator({required this.trainData, super.key,});
 | 
			
		||||
  const DisplayTrainOperator({
 | 
			
		||||
    required this.trainData,
 | 
			
		||||
    super.key,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
| 
						 | 
				
			
			@ -353,7 +376,10 @@ class DisplayTrainOperator extends StatelessWidget {
 | 
			
		|||
class DisplayTrainRoute extends StatelessWidget {
 | 
			
		||||
  final TrainData trainData;
 | 
			
		||||
 | 
			
		||||
  const DisplayTrainRoute({required this.trainData, super.key,});
 | 
			
		||||
  const DisplayTrainRoute({
 | 
			
		||||
    required this.trainData,
 | 
			
		||||
    super.key,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
| 
						 | 
				
			
			@ -418,7 +444,10 @@ class DisplayTrainDeparture extends StatelessWidget {
 | 
			
		|||
class DisplayTrainLastInfo extends StatelessWidget {
 | 
			
		||||
  final TrainData trainData;
 | 
			
		||||
 | 
			
		||||
  const DisplayTrainLastInfo({required this.trainData, super.key,});
 | 
			
		||||
  const DisplayTrainLastInfo({
 | 
			
		||||
    required this.trainData,
 | 
			
		||||
    super.key,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
| 
						 | 
				
			
			@ -610,7 +639,10 @@ class DisplayTrainLastInfo extends StatelessWidget {
 | 
			
		|||
class DisplayTrainDestination extends StatelessWidget {
 | 
			
		||||
  final TrainData trainData;
 | 
			
		||||
 | 
			
		||||
  const DisplayTrainDestination({required this.trainData, super.key,});
 | 
			
		||||
  const DisplayTrainDestination({
 | 
			
		||||
    required this.trainData,
 | 
			
		||||
    super.key,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
| 
						 | 
				
			
			@ -714,7 +746,10 @@ class DisplayTrainDestination extends StatelessWidget {
 | 
			
		|||
class DisplayTrainRouteDistance extends StatelessWidget {
 | 
			
		||||
  final TrainData trainData;
 | 
			
		||||
 | 
			
		||||
  const DisplayTrainRouteDistance({required this.trainData, super.key,});
 | 
			
		||||
  const DisplayTrainRouteDistance({
 | 
			
		||||
    required this.trainData,
 | 
			
		||||
    super.key,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
| 
						 | 
				
			
			@ -751,7 +786,10 @@ class DisplayTrainRouteDistance extends StatelessWidget {
 | 
			
		|||
class DisplayTrainRouteDuration extends StatelessWidget {
 | 
			
		||||
  final TrainData trainData;
 | 
			
		||||
 | 
			
		||||
  const DisplayTrainRouteDuration({required this.trainData, super.key,});
 | 
			
		||||
  const DisplayTrainRouteDuration({
 | 
			
		||||
    required this.trainData,
 | 
			
		||||
    super.key,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
| 
						 | 
				
			
			@ -834,7 +872,10 @@ class DisplayTrainRouteDuration extends StatelessWidget {
 | 
			
		|||
 | 
			
		||||
class DisplayTrainYesterdayWarningMaterial
 | 
			
		||||
    extends DisplayTrainYesterdayWarningCommon {
 | 
			
		||||
  const DisplayTrainYesterdayWarningMaterial(super.onViewYesterdayTrain, {super.key,});
 | 
			
		||||
  const DisplayTrainYesterdayWarningMaterial(
 | 
			
		||||
    super.onViewYesterdayTrain, {
 | 
			
		||||
    super.key,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
| 
						 | 
				
			
			@ -870,7 +911,10 @@ class DisplayTrainYesterdayWarningMaterial
 | 
			
		|||
 | 
			
		||||
class DisplayTrainStations extends StatelessWidget {
 | 
			
		||||
  final TrainData trainData;
 | 
			
		||||
  const DisplayTrainStations({required this.trainData, super.key,});
 | 
			
		||||
  const DisplayTrainStations({
 | 
			
		||||
    required this.trainData,
 | 
			
		||||
    super.key,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
| 
						 | 
				
			
			@ -884,7 +928,8 @@ class DisplayTrainStations extends StatelessWidget {
 | 
			
		|||
              onTap: () {
 | 
			
		||||
                Navigator.of(context).pushNamed(
 | 
			
		||||
                  ViewStationPage.routeName,
 | 
			
		||||
                  arguments: ViewStationArguments(stationName: trainData.stations[index].name),
 | 
			
		||||
                  arguments: ViewStationArguments(
 | 
			
		||||
                      stationName: trainData.stations[index].name),
 | 
			
		||||
                );
 | 
			
		||||
              },
 | 
			
		||||
            ),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,102 +1,178 @@
 | 
			
		|||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:flutter/material.dart' hide Badge;
 | 
			
		||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
			
		||||
import 'package:info_tren/components/train_id_text_span.dart';
 | 
			
		||||
import 'package:info_tren/models.dart';
 | 
			
		||||
import 'package:info_tren/components/badge/badge.dart';
 | 
			
		||||
import 'package:info_tren/pages/train_info_page/view_train/train_info_material.dart';
 | 
			
		||||
import 'package:info_tren/providers.dart';
 | 
			
		||||
 | 
			
		||||
class DisplayTrainStation extends StatelessWidget {
 | 
			
		||||
  final Station station;
 | 
			
		||||
  final TrainDataStation station;
 | 
			
		||||
  final void Function()? onTap;
 | 
			
		||||
 | 
			
		||||
  const DisplayTrainStation({required this.station, this.onTap, super.key,});
 | 
			
		||||
  const DisplayTrainStation({
 | 
			
		||||
    required this.station,
 | 
			
		||||
    this.onTap,
 | 
			
		||||
    super.key,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return Card(
 | 
			
		||||
      child: InkWell(
 | 
			
		||||
        onTap: onTap,
 | 
			
		||||
        child: Padding(
 | 
			
		||||
          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,
 | 
			
		||||
                          );
 | 
			
		||||
                        }
 | 
			
		||||
                      ),
 | 
			
		||||
                    ),
 | 
			
		||||
    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),
 | 
			
		||||
                    ],
 | 
			
		||||
                  ),
 | 
			
		||||
                  Title(
 | 
			
		||||
                ),
 | 
			
		||||
              );
 | 
			
		||||
            },
 | 
			
		||||
          ),
 | 
			
		||||
        Card(
 | 
			
		||||
          child: InkWell(
 | 
			
		||||
            onTap: onTap,
 | 
			
		||||
            child: Padding(
 | 
			
		||||
              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,
 | 
			
		||||
                  ),
 | 
			
		||||
                  Expanded(
 | 
			
		||||
                    flex: 1, 
 | 
			
		||||
                    child: (station.platform == null) 
 | 
			
		||||
                      ? Container() 
 | 
			
		||||
                      : Align(
 | 
			
		||||
                        alignment: Alignment.centerRight,
 | 
			
		||||
                        child: Badge(text: station.platform!, caption: 'linia',),
 | 
			
		||||
                      ),
 | 
			
		||||
                  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,
 | 
			
		||||
                  ),
 | 
			
		||||
                ],
 | 
			
		||||
              ),
 | 
			
		||||
              Time(
 | 
			
		||||
                station: station,
 | 
			
		||||
              ),
 | 
			
		||||
              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 Station station;
 | 
			
		||||
  final TrainDataStation station;
 | 
			
		||||
 | 
			
		||||
  const Title({
 | 
			
		||||
    required this.station,
 | 
			
		||||
| 
						 | 
				
			
			@ -105,20 +181,22 @@ class Title extends StatelessWidget {
 | 
			
		|||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return  Text(
 | 
			
		||||
    return Text(
 | 
			
		||||
      station.name,
 | 
			
		||||
      style: Theme.of(context).textTheme.bodyMedium?.copyWith(
 | 
			
		||||
        fontSize: isSmallScreen(context) ? 18 : 22,
 | 
			
		||||
        fontWeight: MediaQuery.of(context).boldText ? FontWeight.w500 : FontWeight.w300,
 | 
			
		||||
        // fontStyle: items[1] == "ONI" ? FontStyle.italic : FontStyle.normal,
 | 
			
		||||
      ),
 | 
			
		||||
            fontSize: isSmallScreen(context) ? 18 : 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 Station station;
 | 
			
		||||
  final TrainDataStation station;
 | 
			
		||||
 | 
			
		||||
  const Time({
 | 
			
		||||
    required this.station,
 | 
			
		||||
| 
						 | 
				
			
			@ -149,21 +227,35 @@ class Time extends StatelessWidget {
 | 
			
		|||
        Text(
 | 
			
		||||
          "→",
 | 
			
		||||
          style: Theme.of(context).textTheme.bodyMedium?.copyWith(
 | 
			
		||||
            fontSize: isSmallScreen(context) ? 18 : 22,
 | 
			
		||||
          ),
 | 
			
		||||
                fontSize: isSmallScreen(context) ? 18 : 22,
 | 
			
		||||
              ),
 | 
			
		||||
        ),
 | 
			
		||||
        Container(
 | 
			
		||||
          width: 2,
 | 
			
		||||
        ),
 | 
			
		||||
        ArrivalTime(
 | 
			
		||||
          station: station,
 | 
			
		||||
        ),
 | 
			
		||||
        Expanded(
 | 
			
		||||
          child: Container(),
 | 
			
		||||
        ),
 | 
			
		||||
        StopTime(
 | 
			
		||||
          station: station,
 | 
			
		||||
        ),
 | 
			
		||||
        Expanded(
 | 
			
		||||
          child: Container(),
 | 
			
		||||
        ),
 | 
			
		||||
        DepartureTime(
 | 
			
		||||
          station: station,
 | 
			
		||||
        ),
 | 
			
		||||
        Container(
 | 
			
		||||
          width: 2,
 | 
			
		||||
        ),
 | 
			
		||||
        Container(width: 2,),
 | 
			
		||||
        ArrivalTime(station: station,),
 | 
			
		||||
        Expanded(child: Container(),),
 | 
			
		||||
        StopTime(station: station,),
 | 
			
		||||
        Expanded(child: Container(),),
 | 
			
		||||
        DepartureTime(station: station,),
 | 
			
		||||
        Container(width: 2,),
 | 
			
		||||
        Text(
 | 
			
		||||
          "→",
 | 
			
		||||
          style: Theme.of(context).textTheme.bodyMedium?.copyWith(
 | 
			
		||||
            fontSize: isSmallScreen(context) ? 18 : 22,
 | 
			
		||||
          ),
 | 
			
		||||
                fontSize: isSmallScreen(context) ? 18 : 22,
 | 
			
		||||
              ),
 | 
			
		||||
        ),
 | 
			
		||||
      ],
 | 
			
		||||
    );
 | 
			
		||||
| 
						 | 
				
			
			@ -171,7 +263,7 @@ class Time extends StatelessWidget {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
class ArrivalTime extends ConsumerWidget {
 | 
			
		||||
  final Station station;
 | 
			
		||||
  final TrainDataStation station;
 | 
			
		||||
  final bool finalStation;
 | 
			
		||||
 | 
			
		||||
  const ArrivalTime({
 | 
			
		||||
| 
						 | 
				
			
			@ -193,24 +285,29 @@ class ArrivalTime extends ConsumerWidget {
 | 
			
		|||
          Text(
 | 
			
		||||
            "→",
 | 
			
		||||
            style: Theme.of(context).textTheme.bodyMedium?.copyWith(
 | 
			
		||||
              fontSize: isSmallScreen(context) ? 18 : 22,
 | 
			
		||||
            ),
 | 
			
		||||
                  fontSize: isSmallScreen(context) ? 18 : 22,
 | 
			
		||||
                ),
 | 
			
		||||
          ),
 | 
			
		||||
          Container(
 | 
			
		||||
            width: 2,
 | 
			
		||||
          ),
 | 
			
		||||
          Container(width: 2,),
 | 
			
		||||
          const Text("sosire la "),
 | 
			
		||||
          ArrivalTime(station: station,),
 | 
			
		||||
          Expanded(child: Container(),),
 | 
			
		||||
          ArrivalTime(
 | 
			
		||||
            station: station,
 | 
			
		||||
          ),
 | 
			
		||||
          Expanded(
 | 
			
		||||
            child: Container(),
 | 
			
		||||
          ),
 | 
			
		||||
        ],
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
    } 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) {
 | 
			
		||||
        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));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -220,19 +317,18 @@ class ArrivalTime extends ConsumerWidget {
 | 
			
		|||
            Text(
 | 
			
		||||
              "${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
 | 
			
		||||
              style: Theme.of(context).textTheme.bodyMedium?.copyWith(
 | 
			
		||||
                decoration: TextDecoration.lineThrough,
 | 
			
		||||
              ),
 | 
			
		||||
                    decoration: TextDecoration.lineThrough,
 | 
			
		||||
                  ),
 | 
			
		||||
            ),
 | 
			
		||||
            Text(
 | 
			
		||||
              "${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}",
 | 
			
		||||
              style: Theme.of(context).textTheme.bodyMedium?.copyWith(
 | 
			
		||||
                color: Colors.red.shade300,
 | 
			
		||||
              ),
 | 
			
		||||
                    color: Colors.red.shade300,
 | 
			
		||||
                  ),
 | 
			
		||||
            ),
 | 
			
		||||
          ],
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
      } else {
 | 
			
		||||
        final oldDate = time;
 | 
			
		||||
        final newDate = oldDate.add(Duration(minutes: delay));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -242,14 +338,14 @@ class ArrivalTime extends ConsumerWidget {
 | 
			
		|||
            Text(
 | 
			
		||||
              "${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
 | 
			
		||||
              style: Theme.of(context).textTheme.bodyMedium?.copyWith(
 | 
			
		||||
                decoration: TextDecoration.lineThrough,
 | 
			
		||||
              ),
 | 
			
		||||
                    decoration: TextDecoration.lineThrough,
 | 
			
		||||
                  ),
 | 
			
		||||
            ),
 | 
			
		||||
            Text(
 | 
			
		||||
              "${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}",
 | 
			
		||||
              style: Theme.of(context).textTheme.bodyMedium?.copyWith(
 | 
			
		||||
                color: Colors.green.shade300,
 | 
			
		||||
              ),
 | 
			
		||||
                    color: Colors.green.shade300,
 | 
			
		||||
                  ),
 | 
			
		||||
            ),
 | 
			
		||||
          ],
 | 
			
		||||
        );
 | 
			
		||||
| 
						 | 
				
			
			@ -259,7 +355,7 @@ class ArrivalTime extends ConsumerWidget {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
class StopTime extends StatelessWidget {
 | 
			
		||||
  final Station station;
 | 
			
		||||
  final TrainDataStation station;
 | 
			
		||||
 | 
			
		||||
  const StopTime({
 | 
			
		||||
    required this.station,
 | 
			
		||||
| 
						 | 
				
			
			@ -288,14 +384,12 @@ class StopTime extends StatelessWidget {
 | 
			
		|||
                "1 ${minutes ? 'minut' : 'secundă'}",
 | 
			
		||||
                textAlign: TextAlign.center,
 | 
			
		||||
              );
 | 
			
		||||
            }
 | 
			
		||||
            else if (stopsForInt < 20) {
 | 
			
		||||
            } else if (stopsForInt < 20) {
 | 
			
		||||
              return Text(
 | 
			
		||||
                "$stopsForInt ${minutes ? 'minute' : 'secunde'}",
 | 
			
		||||
                textAlign: TextAlign.center,
 | 
			
		||||
              );
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
            } else {
 | 
			
		||||
              return Text(
 | 
			
		||||
                "$stopsForInt de ${minutes ? 'minute' : 'secunde'}",
 | 
			
		||||
                textAlign: TextAlign.center,
 | 
			
		||||
| 
						 | 
				
			
			@ -309,7 +403,7 @@ class StopTime extends StatelessWidget {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
class DepartureTime extends ConsumerWidget {
 | 
			
		||||
  final Station station;
 | 
			
		||||
  final TrainDataStation station;
 | 
			
		||||
  final bool firstStation;
 | 
			
		||||
 | 
			
		||||
  const DepartureTime({
 | 
			
		||||
| 
						 | 
				
			
			@ -328,27 +422,32 @@ class DepartureTime extends ConsumerWidget {
 | 
			
		|||
      return Row(
 | 
			
		||||
        crossAxisAlignment: CrossAxisAlignment.center,
 | 
			
		||||
        children: <Widget>[
 | 
			
		||||
          Expanded(child: Container(),),
 | 
			
		||||
          Expanded(
 | 
			
		||||
            child: Container(),
 | 
			
		||||
          ),
 | 
			
		||||
          const Text("plecare la "),
 | 
			
		||||
          DepartureTime(station: station,),
 | 
			
		||||
          Container(width: 2,),
 | 
			
		||||
          DepartureTime(
 | 
			
		||||
            station: station,
 | 
			
		||||
          ),
 | 
			
		||||
          Container(
 | 
			
		||||
            width: 2,
 | 
			
		||||
          ),
 | 
			
		||||
          Text(
 | 
			
		||||
            "→",
 | 
			
		||||
            style: Theme.of(context).textTheme.bodyMedium?.copyWith(
 | 
			
		||||
              fontSize: 22,
 | 
			
		||||
            ),
 | 
			
		||||
                  fontSize: 22,
 | 
			
		||||
                ),
 | 
			
		||||
          ),
 | 
			
		||||
        ],
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
    } 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) {
 | 
			
		||||
        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));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -358,19 +457,18 @@ class DepartureTime extends ConsumerWidget {
 | 
			
		|||
            Text(
 | 
			
		||||
              "${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
 | 
			
		||||
              style: Theme.of(context).textTheme.bodyMedium?.copyWith(
 | 
			
		||||
                decoration: TextDecoration.lineThrough,
 | 
			
		||||
              ),
 | 
			
		||||
                    decoration: TextDecoration.lineThrough,
 | 
			
		||||
                  ),
 | 
			
		||||
            ),
 | 
			
		||||
            Text(
 | 
			
		||||
              "${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}",
 | 
			
		||||
              style: Theme.of(context).textTheme.bodyMedium?.copyWith(
 | 
			
		||||
                color: Colors.red.shade300,
 | 
			
		||||
              ),
 | 
			
		||||
                    color: Colors.red.shade300,
 | 
			
		||||
                  ),
 | 
			
		||||
            ),
 | 
			
		||||
          ],
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
      } else {
 | 
			
		||||
        final oldDate = time;
 | 
			
		||||
        final newDate = oldDate.add(Duration(minutes: delay));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -380,14 +478,14 @@ class DepartureTime extends ConsumerWidget {
 | 
			
		|||
            Text(
 | 
			
		||||
              "${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
 | 
			
		||||
              style: Theme.of(context).textTheme.bodyMedium?.copyWith(
 | 
			
		||||
                decoration: TextDecoration.lineThrough,
 | 
			
		||||
              ),
 | 
			
		||||
                    decoration: TextDecoration.lineThrough,
 | 
			
		||||
                  ),
 | 
			
		||||
            ),
 | 
			
		||||
            Text(
 | 
			
		||||
              "${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}",
 | 
			
		||||
              style: Theme.of(context).textTheme.bodyMedium?.copyWith(
 | 
			
		||||
                color: Colors.green.shade300,
 | 
			
		||||
              ),
 | 
			
		||||
                    color: Colors.green.shade300,
 | 
			
		||||
                  ),
 | 
			
		||||
            ),
 | 
			
		||||
          ],
 | 
			
		||||
        );
 | 
			
		||||
| 
						 | 
				
			
			@ -396,9 +494,8 @@ class DepartureTime extends ConsumerWidget {
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Delay extends StatelessWidget {
 | 
			
		||||
  final Station station;
 | 
			
		||||
  final TrainDataStation station;
 | 
			
		||||
 | 
			
		||||
  const Delay({
 | 
			
		||||
    required this.station,
 | 
			
		||||
| 
						 | 
				
			
			@ -421,20 +518,19 @@ class Delay extends StatelessWidget {
 | 
			
		|||
      return Text(
 | 
			
		||||
        "$delay ${delay == 1 ? 'minut' : 'minute'} întârziere",
 | 
			
		||||
        style: Theme.of(context).textTheme.bodyMedium?.copyWith(
 | 
			
		||||
          color: Colors.red.shade300,
 | 
			
		||||
          fontSize: 14,
 | 
			
		||||
          fontStyle: FontStyle.italic,
 | 
			
		||||
        ),
 | 
			
		||||
              color: Colors.red.shade300,
 | 
			
		||||
              fontSize: 14,
 | 
			
		||||
              fontStyle: FontStyle.italic,
 | 
			
		||||
            ),
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    else if (delay < 0) {
 | 
			
		||||
    } else if (delay < 0) {
 | 
			
		||||
      return Text(
 | 
			
		||||
        "${-delay} ${delay == -1 ? 'minut' : 'minute'} mai devreme",
 | 
			
		||||
        style: Theme.of(context).textTheme.bodyMedium?.copyWith(
 | 
			
		||||
          color: Colors.green.shade300,
 | 
			
		||||
          fontSize: 14,
 | 
			
		||||
          fontStyle: FontStyle.italic,
 | 
			
		||||
        ),
 | 
			
		||||
              color: Colors.green.shade300,
 | 
			
		||||
              fontSize: 14,
 | 
			
		||||
              fontStyle: FontStyle.italic,
 | 
			
		||||
            ),
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,13 +3,17 @@ 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'),
 | 
			
		||||
);
 | 
			
		||||
| 
						 | 
				
			
			@ -76,8 +80,8 @@ final trainInfoArgumentsProvider = Provider<TrainInfoArguments>(
 | 
			
		|||
  (_) => throw UnimplementedError('Please override in ProviderScope'),
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
final stationDataProvider = FutureProvider.family((ref, String stationName) async {
 | 
			
		||||
  final data = await getStationData(stationName);
 | 
			
		||||
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();
 | 
			
		||||
| 
						 | 
				
			
			@ -93,6 +97,9 @@ final viewStationArgumentsProvider = Provider<ViewStationArguments>(
 | 
			
		|||
);
 | 
			
		||||
final viewStationDataProvider = Provider((ref) {
 | 
			
		||||
  final args = ref.watch(viewStationArgumentsProvider);
 | 
			
		||||
  final data = ref.watch(stationDataProvider(args.stationName));
 | 
			
		||||
  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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										120
									
								
								lib/providers.g.dart
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								lib/providers.g.dart
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
		Loading…
	
	Add table
		
		Reference in a new issue