Compare commits
No commits in common. "0e484bdc16b57af17d3b5667b2aa8927b59e4421" and "240812e26190335c89f1bffeb41f2a4512a1941c" have entirely different histories.
0e484bdc16
...
240812e261
32 changed files with 623 additions and 3128 deletions
|
@ -1,9 +1,3 @@
|
||||||
v2.7.9
|
|
||||||
Add Fluent UI for Windows and Linux.
|
|
||||||
Add split view in landscape when viewing a train.
|
|
||||||
Add error handling and auto refresh when viewing a station's arrivals/departures.
|
|
||||||
General code fixes and migration (freezed, riverpod).
|
|
||||||
|
|
||||||
v2.7.8
|
v2.7.8
|
||||||
Added cancelled trains in departures/arrivals board.
|
Added cancelled trains in departures/arrivals board.
|
||||||
Selecting train in departures/arrivels board chooses appropriate departure date.
|
Selecting train in departures/arrivels board chooses appropriate departure date.
|
||||||
|
|
|
@ -1,5 +1,84 @@
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:info_tren/pages/train_info_page/train_info_constants.dart';
|
import 'package:info_tren/pages/train_info_page/train_info_constants.dart';
|
||||||
|
import 'package:info_tren/pages/train_info_page/view_train/train_info_material.dart';
|
||||||
|
|
||||||
|
class MaterialBadge extends StatelessWidget {
|
||||||
|
final String text;
|
||||||
|
final String caption;
|
||||||
|
final bool isNotScheduled;
|
||||||
|
final bool isOnTime;
|
||||||
|
final bool isDelayed;
|
||||||
|
|
||||||
|
const MaterialBadge({
|
||||||
|
required this.text,
|
||||||
|
required this.caption,
|
||||||
|
this.isNotScheduled = false,
|
||||||
|
this.isOnTime = false,
|
||||||
|
this.isDelayed = false,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
Color foregroundColor = Colors.white70;
|
||||||
|
Color? backgroundColor;
|
||||||
|
|
||||||
|
if (isNotScheduled) {
|
||||||
|
foregroundColor = Colors.orange.shade300;
|
||||||
|
backgroundColor = Colors.orange.shade900.withOpacity(0.3);
|
||||||
|
}
|
||||||
|
else if (isOnTime) {
|
||||||
|
foregroundColor = Colors.green.shade300;
|
||||||
|
backgroundColor = Colors.green.shade900.withOpacity(0.3);
|
||||||
|
}
|
||||||
|
else if (isDelayed) {
|
||||||
|
foregroundColor = Colors.red.shade300;
|
||||||
|
backgroundColor = Colors.red.shade900.withOpacity(0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
border: Border.all(
|
||||||
|
width: 2,
|
||||||
|
color: foregroundColor,
|
||||||
|
),
|
||||||
|
color: backgroundColor,
|
||||||
|
),
|
||||||
|
width: isSmallScreen(context) ? 42 : 48,
|
||||||
|
height: isSmallScreen(context) ? 42 : 48,
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: <Widget>[
|
||||||
|
Expanded(
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
text,
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||||
|
fontSize: isSmallScreen(context) ? 16 : 20,
|
||||||
|
fontWeight: MediaQuery.of(context).boldText ? FontWeight.w400 : FontWeight.w200,
|
||||||
|
color: MediaQuery.of(context).boldText ? Colors.white70 : foregroundColor,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
caption,
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||||
|
fontSize: 10,
|
||||||
|
color: MediaQuery.of(context).boldText ? Colors.white70 : foregroundColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class CupertinoBadge extends StatelessWidget {
|
class CupertinoBadge extends StatelessWidget {
|
||||||
final String text;
|
final String text;
|
|
@ -1,59 +0,0 @@
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
||||||
import 'package:info_tren/components/badge/badge_cupertino.dart';
|
|
||||||
import 'package:info_tren/components/badge/badge_fluent.dart';
|
|
||||||
import 'package:info_tren/components/badge/badge_material.dart';
|
|
||||||
import 'package:info_tren/models.dart';
|
|
||||||
import 'package:info_tren/providers.dart';
|
|
||||||
|
|
||||||
class Badge extends ConsumerWidget {
|
|
||||||
final String text;
|
|
||||||
final String caption;
|
|
||||||
final bool isNotScheduled;
|
|
||||||
final bool isOnTime;
|
|
||||||
final bool isDelayed;
|
|
||||||
|
|
||||||
const Badge({
|
|
||||||
super.key,
|
|
||||||
required this.text,
|
|
||||||
required this.caption,
|
|
||||||
this.isNotScheduled = false,
|
|
||||||
this.isOnTime = false,
|
|
||||||
this.isDelayed = false,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
|
||||||
final uiDesign = ref.watch(uiDesignProvider);
|
|
||||||
|
|
||||||
switch (uiDesign) {
|
|
||||||
case UiDesign.MATERIAL:
|
|
||||||
return MaterialBadge(
|
|
||||||
text: text,
|
|
||||||
caption: caption,
|
|
||||||
isNotScheduled: isNotScheduled,
|
|
||||||
isOnTime: isOnTime,
|
|
||||||
isDelayed: isDelayed,
|
|
||||||
);
|
|
||||||
case UiDesign.CUPERTINO:
|
|
||||||
return CupertinoBadge(
|
|
||||||
text: text,
|
|
||||||
caption: caption,
|
|
||||||
isNotScheduled: isNotScheduled,
|
|
||||||
isOnTime: isOnTime,
|
|
||||||
isDelayed: isDelayed,
|
|
||||||
);
|
|
||||||
case UiDesign.FLUENT:
|
|
||||||
return FluentBadge(
|
|
||||||
text: text,
|
|
||||||
caption: caption,
|
|
||||||
isNotScheduled: isNotScheduled,
|
|
||||||
isOnTime: isOnTime,
|
|
||||||
isDelayed: isDelayed,
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
throw UnmatchedUiDesignException(uiDesign);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,80 +0,0 @@
|
||||||
import 'package:fluent_ui/fluent_ui.dart';
|
|
||||||
|
|
||||||
|
|
||||||
class FluentBadge extends StatelessWidget {
|
|
||||||
final String text;
|
|
||||||
final String caption;
|
|
||||||
final bool isNotScheduled;
|
|
||||||
final bool isOnTime;
|
|
||||||
final bool isDelayed;
|
|
||||||
|
|
||||||
const FluentBadge({
|
|
||||||
required this.text,
|
|
||||||
required this.caption,
|
|
||||||
this.isNotScheduled = false,
|
|
||||||
this.isOnTime = false,
|
|
||||||
this.isDelayed = false,
|
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
Color foregroundColor = FluentTheme.of(context).activeColor;
|
|
||||||
Color? backgroundColor;
|
|
||||||
|
|
||||||
if (isNotScheduled) {
|
|
||||||
foregroundColor = const Color.fromRGBO(225, 175, 30, 1);
|
|
||||||
backgroundColor = const Color.fromRGBO(80, 40, 10, 1);
|
|
||||||
}
|
|
||||||
else if (isOnTime) {
|
|
||||||
foregroundColor = const Color.fromRGBO(130, 175, 65, 1);
|
|
||||||
backgroundColor = const Color.fromRGBO(40, 80, 10, 1);
|
|
||||||
}
|
|
||||||
else if (isDelayed) {
|
|
||||||
foregroundColor = const Color.fromRGBO(225, 75, 30, 1);
|
|
||||||
backgroundColor = const Color.fromRGBO(80, 20, 10, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.all(8),
|
|
||||||
child: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
border: Border.all(
|
|
||||||
width: 2,
|
|
||||||
color: foregroundColor,
|
|
||||||
),
|
|
||||||
color: backgroundColor,
|
|
||||||
// color: CupertinoColors.activeOrange,
|
|
||||||
),
|
|
||||||
width: 48,
|
|
||||||
height: 48,
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: <Widget>[
|
|
||||||
Expanded(
|
|
||||||
child: Center(
|
|
||||||
child: Text(
|
|
||||||
text,
|
|
||||||
style: FluentTheme.of(context).typography.bodyLarge?.copyWith(
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: MediaQuery.of(context).boldText ? FontWeight.w400 : FontWeight.w200,
|
|
||||||
color: MediaQuery.of(context).boldText ? Colors.white : foregroundColor,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
caption,
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
fontSize: 12,
|
|
||||||
color: MediaQuery.of(context).boldText ? Colors.white : foregroundColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,79 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:info_tren/pages/train_info_page/view_train/train_info_material.dart';
|
|
||||||
|
|
||||||
class MaterialBadge extends StatelessWidget {
|
|
||||||
final String text;
|
|
||||||
final String caption;
|
|
||||||
final bool isNotScheduled;
|
|
||||||
final bool isOnTime;
|
|
||||||
final bool isDelayed;
|
|
||||||
|
|
||||||
const MaterialBadge({
|
|
||||||
required this.text,
|
|
||||||
required this.caption,
|
|
||||||
this.isNotScheduled = false,
|
|
||||||
this.isOnTime = false,
|
|
||||||
this.isDelayed = false,
|
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
Color foregroundColor = Colors.white70;
|
|
||||||
Color? backgroundColor;
|
|
||||||
|
|
||||||
if (isNotScheduled) {
|
|
||||||
foregroundColor = Colors.orange.shade300;
|
|
||||||
backgroundColor = Colors.orange.shade900.withOpacity(0.3);
|
|
||||||
}
|
|
||||||
else if (isOnTime) {
|
|
||||||
foregroundColor = Colors.green.shade300;
|
|
||||||
backgroundColor = Colors.green.shade900.withOpacity(0.3);
|
|
||||||
}
|
|
||||||
else if (isDelayed) {
|
|
||||||
foregroundColor = Colors.red.shade300;
|
|
||||||
backgroundColor = Colors.red.shade900.withOpacity(0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.all(8),
|
|
||||||
child: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
border: Border.all(
|
|
||||||
width: 2,
|
|
||||||
color: foregroundColor,
|
|
||||||
),
|
|
||||||
color: backgroundColor,
|
|
||||||
),
|
|
||||||
width: isSmallScreen(context) ? 42 : 48,
|
|
||||||
height: isSmallScreen(context) ? 42 : 48,
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: <Widget>[
|
|
||||||
Expanded(
|
|
||||||
child: Center(
|
|
||||||
child: Text(
|
|
||||||
text,
|
|
||||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
|
||||||
fontSize: isSmallScreen(context) ? 16 : 20,
|
|
||||||
fontWeight: MediaQuery.of(context).boldText ? FontWeight.w400 : FontWeight.w200,
|
|
||||||
color: MediaQuery.of(context).boldText ? Colors.white70 : foregroundColor,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
caption,
|
|
||||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
|
||||||
fontSize: 10,
|
|
||||||
color: MediaQuery.of(context).boldText ? Colors.white70 : foregroundColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,6 @@
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:info_tren/components/loading/loading_cupertino.dart';
|
import 'package:info_tren/components/loading/loading_cupertino.dart';
|
||||||
import 'package:info_tren/components/loading/loading_fluent.dart';
|
|
||||||
import 'package:info_tren/components/loading/loading_material.dart';
|
import 'package:info_tren/components/loading/loading_material.dart';
|
||||||
import 'package:info_tren/models.dart';
|
import 'package:info_tren/models.dart';
|
||||||
import 'package:info_tren/providers.dart';
|
import 'package:info_tren/providers.dart';
|
||||||
|
@ -20,8 +19,6 @@ class Loading extends ConsumerWidget {
|
||||||
return LoadingMaterial(text: text ?? defaultText,);
|
return LoadingMaterial(text: text ?? defaultText,);
|
||||||
case UiDesign.CUPERTINO:
|
case UiDesign.CUPERTINO:
|
||||||
return LoadingCupertino(text: text ?? defaultText,);
|
return LoadingCupertino(text: text ?? defaultText,);
|
||||||
case UiDesign.FLUENT:
|
|
||||||
return LoadingFluent(text: text ?? defaultText,);
|
|
||||||
default:
|
default:
|
||||||
throw UnmatchedUiDesignException(uiDesign);
|
throw UnmatchedUiDesignException(uiDesign);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
import 'package:fluent_ui/fluent_ui.dart';
|
|
||||||
import 'package:info_tren/components/loading/loading.dart';
|
|
||||||
|
|
||||||
class LoadingFluent extends LoadingCommon {
|
|
||||||
const LoadingFluent({required super.text, super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Center(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
const Padding(
|
|
||||||
padding: EdgeInsets.all(8.0),
|
|
||||||
child: ProgressRing(),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Text(text),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -138,10 +138,9 @@ enum RefreshFutureBuilderState {
|
||||||
|
|
||||||
class RefreshFutureBuilderProviderAdapter<T> extends ConsumerWidget {
|
class RefreshFutureBuilderProviderAdapter<T> extends ConsumerWidget {
|
||||||
final Provider<AsyncValue<T>> futureProvider;
|
final Provider<AsyncValue<T>> futureProvider;
|
||||||
final Future Function()? refresh;
|
|
||||||
final Widget Function(BuildContext context, Future Function() refresh, Future Function(Future<T> Function()) replaceFuture, RefreshFutureBuilderSnapshot<T> snapshot) builder;
|
final Widget Function(BuildContext context, Future Function() refresh, Future Function(Future<T> Function()) replaceFuture, RefreshFutureBuilderSnapshot<T> snapshot) builder;
|
||||||
|
|
||||||
const RefreshFutureBuilderProviderAdapter({required this.futureProvider, required this.builder, this.refresh, super.key});
|
const RefreshFutureBuilderProviderAdapter({required this.futureProvider, required this.builder, super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
@ -149,7 +148,7 @@ class RefreshFutureBuilderProviderAdapter<T> extends ConsumerWidget {
|
||||||
|
|
||||||
return builder(
|
return builder(
|
||||||
context,
|
context,
|
||||||
refresh ?? () async {
|
() async {
|
||||||
ref.invalidate(futureProvider);
|
ref.invalidate(futureProvider);
|
||||||
},
|
},
|
||||||
(_) => throw UnimplementedError('Cannot replace the future when adapting a FutureProvider'),
|
(_) => throw UnimplementedError('Cannot replace the future when adapting a FutureProvider'),
|
||||||
|
@ -158,7 +157,7 @@ class RefreshFutureBuilderProviderAdapter<T> extends ConsumerWidget {
|
||||||
? RefreshFutureBuilderSnapshot.refresh(data)
|
? RefreshFutureBuilderSnapshot.refresh(data)
|
||||||
: RefreshFutureBuilderSnapshot.withData(data),
|
: RefreshFutureBuilderSnapshot.withData(data),
|
||||||
error: (error, st) => value.isLoading || value.isRefreshing
|
error: (error, st) => value.isLoading || value.isRefreshing
|
||||||
? RefreshFutureBuilderSnapshot.refreshError(value.hasValue ? value.value : null, value.error, value.stackTrace)
|
? RefreshFutureBuilderSnapshot.refreshError(value.value, value.error, value.stackTrace)
|
||||||
: RefreshFutureBuilderSnapshot.withError(error, st),
|
: RefreshFutureBuilderSnapshot.withError(error, st),
|
||||||
loading: () {
|
loading: () {
|
||||||
if (value.hasValue) {
|
if (value.hasValue) {
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:info_tren/components/select_train_suggestions/select_train_suggestions_cupertino.dart';
|
import 'package:info_tren/components/select_train_suggestions/select_train_suggestions_cupertino.dart';
|
||||||
import 'package:info_tren/components/select_train_suggestions/select_train_suggestions_fluent.dart';
|
|
||||||
import 'package:info_tren/components/select_train_suggestions/select_train_suggestions_material.dart';
|
import 'package:info_tren/components/select_train_suggestions/select_train_suggestions_material.dart';
|
||||||
import 'package:info_tren/models.dart';
|
import 'package:info_tren/models.dart';
|
||||||
import 'package:info_tren/providers.dart';
|
import 'package:info_tren/providers.dart';
|
||||||
|
@ -32,12 +31,6 @@ class SelectTrainSuggestions extends ConsumerWidget {
|
||||||
onTrainSelected: onTrainSelected,
|
onTrainSelected: onTrainSelected,
|
||||||
currentInput: currentInput,
|
currentInput: currentInput,
|
||||||
);
|
);
|
||||||
case UiDesign.FLUENT:
|
|
||||||
return SelectTrainSuggestionsFluent(
|
|
||||||
choices: choices,
|
|
||||||
onTrainSelected: onTrainSelected,
|
|
||||||
currentInput: currentInput,
|
|
||||||
);
|
|
||||||
default:
|
default:
|
||||||
throw UnmatchedUiDesignException(uiDesign);
|
throw UnmatchedUiDesignException(uiDesign);
|
||||||
}
|
}
|
||||||
|
@ -109,12 +102,6 @@ class OperatorAutocompleteSliver extends ConsumerWidget {
|
||||||
operatorName: operatorName,
|
operatorName: operatorName,
|
||||||
train: train,
|
train: train,
|
||||||
);
|
);
|
||||||
case UiDesign.FLUENT:
|
|
||||||
return OperatorAutocompleteTileFluent(
|
|
||||||
onTrainSelected: onTrainSelected,
|
|
||||||
operatorName: operatorName,
|
|
||||||
train: train,
|
|
||||||
);
|
|
||||||
default:
|
default:
|
||||||
throw UnmatchedUiDesignException(uiDesign);
|
throw UnmatchedUiDesignException(uiDesign);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,84 +0,0 @@
|
||||||
import 'package:fluent_ui/fluent_ui.dart';
|
|
||||||
import 'package:info_tren/components/select_train_suggestions/select_train_suggestions.dart';
|
|
||||||
import 'package:info_tren/models.dart';
|
|
||||||
|
|
||||||
class SelectTrainSuggestionsFluent extends SelectTrainSuggestionsShared {
|
|
||||||
const SelectTrainSuggestionsFluent({
|
|
||||||
super.key,
|
|
||||||
required super.choices,
|
|
||||||
required super.onTrainSelected,
|
|
||||||
super.currentInput,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget getUseCurrentInputWidget(String currentInput, void Function(String) onTrainSelected) {
|
|
||||||
return Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: <Widget>[
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(0),
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: <Widget>[
|
|
||||||
Button(
|
|
||||||
child: Text(getUseCurrentInputWidgetText(currentInput)),
|
|
||||||
onPressed: () => onTrainSelected(currentInput),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
),
|
|
||||||
const Divider(),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class OperatorAutocompleteTileFluent extends OperatorAutocompleteTile {
|
|
||||||
const OperatorAutocompleteTileFluent({
|
|
||||||
Key? key,
|
|
||||||
required String operatorName,
|
|
||||||
required void Function(String) onTrainSelected,
|
|
||||||
required TrainsResult train
|
|
||||||
}): super(
|
|
||||||
onTrainSelected: onTrainSelected,
|
|
||||||
operatorName: operatorName,
|
|
||||||
train: train,
|
|
||||||
key: key,
|
|
||||||
);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
GestureDetector(
|
|
||||||
onTap: () {
|
|
||||||
onTrainSelected(train.number);
|
|
||||||
},
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.fromLTRB(16, 4, 16, 4),
|
|
||||||
child: SizedBox(
|
|
||||||
width: double.infinity,
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
||||||
children: <Widget>[
|
|
||||||
Text(
|
|
||||||
operatorName,
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(fontSize: 10, fontWeight: FontWeight.w200),
|
|
||||||
textAlign: TextAlign.left,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
"${train.rank} ${train.number}",
|
|
||||||
textAlign: TextAlign.left,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Divider(),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +1,5 @@
|
||||||
import 'package:fluent_ui/fluent_ui.dart' as f;
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/cupertino.dart' as c;
|
|
||||||
import 'package:flutter/material.dart' as m;
|
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:flutter/widgets.dart';
|
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:info_tren/models.dart';
|
|
||||||
import 'package:info_tren/pages/about/about_page.dart';
|
import 'package:info_tren/pages/about/about_page.dart';
|
||||||
import 'package:info_tren/pages/main/main_page.dart';
|
import 'package:info_tren/pages/main/main_page.dart';
|
||||||
import 'package:info_tren/pages/station_arrdep_page/select_station/select_station.dart';
|
import 'package:info_tren/pages/station_arrdep_page/select_station/select_station.dart';
|
||||||
|
@ -59,59 +54,48 @@ Map<String, WidgetBuilder> get routes => {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
class StartPoint extends ConsumerWidget {
|
class StartPoint extends StatelessWidget {
|
||||||
final String appTitle = 'Info Tren';
|
final String appTitle = 'Info Tren';
|
||||||
|
|
||||||
const StartPoint({super.key});
|
const StartPoint({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context) {
|
||||||
final uiDesign = ref.watch(uiDesignProvider);
|
// if (Platform.isIOS || Platform.isMacOS) {
|
||||||
if (uiDesign == UiDesign.CUPERTINO) {
|
// return AnnotatedRegion(
|
||||||
return AnnotatedRegion(
|
// value: const SystemUiOverlayStyle(
|
||||||
value: const SystemUiOverlayStyle(
|
// statusBarBrightness: Brightness.dark,
|
||||||
statusBarBrightness: c.Brightness.dark,
|
// ),
|
||||||
),
|
// child: CupertinoApp(
|
||||||
child: c.CupertinoApp(
|
// title: appTitle,
|
||||||
title: appTitle,
|
// theme: CupertinoThemeData(
|
||||||
theme: c.CupertinoThemeData(
|
// primaryColor: Colors.blue.shade600,
|
||||||
primaryColor: m.Colors.blue.shade600,
|
// brightness: Brightness.dark,
|
||||||
brightness: c.Brightness.dark,
|
// // textTheme: CupertinoTextThemeData(
|
||||||
// textTheme: CupertinoTextThemeData(
|
// // textStyle: TextStyle(
|
||||||
// textStyle: TextStyle(
|
// // fontFamily: 'Atkinson Hyperlegible',
|
||||||
// fontFamily: 'Atkinson Hyperlegible',
|
// // ),
|
||||||
// ),
|
// // ),
|
||||||
// ),
|
// ),
|
||||||
),
|
// routes: routesByUiDesign(UiDesign.CUPERTINO),
|
||||||
routes: routes,
|
// ),
|
||||||
),
|
// );
|
||||||
);
|
// }
|
||||||
}
|
// else {
|
||||||
else if (uiDesign == UiDesign.FLUENT) {
|
return MaterialApp(
|
||||||
return f.FluentApp(
|
|
||||||
title: appTitle,
|
title: appTitle,
|
||||||
theme: f.ThemeData(
|
theme: ThemeData(
|
||||||
brightness: f.Brightness.dark,
|
primarySwatch: Colors.blue,
|
||||||
accentColor: f.Colors.blue,
|
colorScheme: ColorScheme.fromSwatch(
|
||||||
),
|
brightness: Brightness.dark,
|
||||||
routes: routes,
|
primarySwatch: Colors.blue,
|
||||||
);
|
accentColor: Colors.blue.shade700,
|
||||||
}
|
|
||||||
else {
|
|
||||||
return m.MaterialApp(
|
|
||||||
title: appTitle,
|
|
||||||
theme: m.ThemeData(
|
|
||||||
primarySwatch: m.Colors.blue,
|
|
||||||
colorScheme: m.ColorScheme.fromSwatch(
|
|
||||||
brightness: m.Brightness.dark,
|
|
||||||
primarySwatch: m.Colors.blue,
|
|
||||||
accentColor: m.Colors.blue.shade700,
|
|
||||||
),
|
),
|
||||||
useMaterial3: true,
|
useMaterial3: true,
|
||||||
// fontFamily: 'Atkinson Hyperlegible',
|
// fontFamily: 'Atkinson Hyperlegible',
|
||||||
),
|
),
|
||||||
routes: routes,
|
routes: routes,
|
||||||
);
|
);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
enum UiDesign {
|
enum UiDesign {
|
||||||
MATERIAL,
|
MATERIAL,
|
||||||
CUPERTINO,
|
CUPERTINO
|
||||||
FLUENT,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class UnmatchedUiDesignException implements Exception {
|
class UnmatchedUiDesignException implements Exception {
|
||||||
|
|
|
@ -3,7 +3,6 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:info_tren/models.dart';
|
import 'package:info_tren/models.dart';
|
||||||
import 'package:info_tren/pages/about/about_page.dart';
|
import 'package:info_tren/pages/about/about_page.dart';
|
||||||
import 'package:info_tren/pages/main/main_page_cupertino.dart';
|
import 'package:info_tren/pages/main/main_page_cupertino.dart';
|
||||||
import 'package:info_tren/pages/main/main_page_fluent.dart';
|
|
||||||
import 'package:info_tren/pages/main/main_page_material.dart';
|
import 'package:info_tren/pages/main/main_page_material.dart';
|
||||||
import 'package:info_tren/pages/station_arrdep_page/select_station/select_station.dart';
|
import 'package:info_tren/pages/station_arrdep_page/select_station/select_station.dart';
|
||||||
import 'package:info_tren/pages/train_info_page/select_train/select_train.dart';
|
import 'package:info_tren/pages/train_info_page/select_train/select_train.dart';
|
||||||
|
@ -21,8 +20,6 @@ class MainPage extends ConsumerWidget {
|
||||||
return const MainPageMaterial();
|
return const MainPageMaterial();
|
||||||
case UiDesign.CUPERTINO:
|
case UiDesign.CUPERTINO:
|
||||||
return const MainPageCupertino();
|
return const MainPageCupertino();
|
||||||
case UiDesign.FLUENT:
|
|
||||||
return const MainPageFluent();
|
|
||||||
default:
|
default:
|
||||||
throw UnmatchedUiDesignException(uiDesign);
|
throw UnmatchedUiDesignException(uiDesign);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
import 'package:fluent_ui/fluent_ui.dart';
|
|
||||||
import 'package:info_tren/pages/main/main_page.dart';
|
|
||||||
|
|
||||||
class MainPageFluent extends MainPageShared {
|
|
||||||
const MainPageFluent({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return NavigationView(
|
|
||||||
appBar: NavigationAppBar(
|
|
||||||
automaticallyImplyLeading: false,
|
|
||||||
title: Text(pageTitle),
|
|
||||||
// centerTitle: true,
|
|
||||||
// actions: [
|
|
||||||
// PopupMenuButton<int>(
|
|
||||||
// icon: const Icon(Icons.more_vert),
|
|
||||||
// tooltip: moreOptionsText,
|
|
||||||
// itemBuilder: (_) => popupMenu.asMap().entries.map((e) => PopupMenuItem(
|
|
||||||
// value: e.key,
|
|
||||||
// child: Text(e.value.name),
|
|
||||||
// )).toList(),
|
|
||||||
// onSelected: (index) {
|
|
||||||
// popupMenu[index].action?.call(context);
|
|
||||||
// },
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
),
|
|
||||||
content: SafeArea(
|
|
||||||
child: Center(
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: options.map((option) => HoverButton(
|
|
||||||
onPressed: option.action != null ? () => option.action!(context) : null,
|
|
||||||
builder: (context, states) {
|
|
||||||
return Card(
|
|
||||||
backgroundColor: option.action != null ? (states.isHovering ? FluentTheme.of(context).accentColor.dark : FluentTheme.of(context).accentColor) : null,
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Text(
|
|
||||||
option.name,
|
|
||||||
style: FluentTheme.of(context)
|
|
||||||
.typography
|
|
||||||
.bodyLarge
|
|
||||||
?.copyWith(
|
|
||||||
color:
|
|
||||||
FluentTheme.of(context).activeColor,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Text(option.description!),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
)).map((w) => Padding(
|
|
||||||
padding: const EdgeInsets.fromLTRB(4, 2, 4, 2),
|
|
||||||
child: SizedBox(
|
|
||||||
width: double.infinity,
|
|
||||||
child: w,
|
|
||||||
),
|
|
||||||
)).toList(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,7 +2,6 @@ import 'package:flutter/widgets.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:info_tren/models.dart';
|
import 'package:info_tren/models.dart';
|
||||||
import 'package:info_tren/pages/station_arrdep_page/select_station/select_station_cupertino.dart';
|
import 'package:info_tren/pages/station_arrdep_page/select_station/select_station_cupertino.dart';
|
||||||
import 'package:info_tren/pages/station_arrdep_page/select_station/select_station_fluent.dart';
|
|
||||||
import 'package:info_tren/pages/station_arrdep_page/select_station/select_station_material.dart';
|
import 'package:info_tren/pages/station_arrdep_page/select_station/select_station_material.dart';
|
||||||
import 'package:info_tren/pages/station_arrdep_page/view_station/view_station.dart';
|
import 'package:info_tren/pages/station_arrdep_page/view_station/view_station.dart';
|
||||||
import 'package:info_tren/providers.dart';
|
import 'package:info_tren/providers.dart';
|
||||||
|
@ -21,8 +20,6 @@ class SelectStationPage extends ConsumerWidget {
|
||||||
return const SelectStationPageMaterial();
|
return const SelectStationPageMaterial();
|
||||||
case UiDesign.CUPERTINO:
|
case UiDesign.CUPERTINO:
|
||||||
return const SelectStationPageCupertino();
|
return const SelectStationPageCupertino();
|
||||||
case UiDesign.FLUENT:
|
|
||||||
return const SelectStationPageFluent();
|
|
||||||
default:
|
default:
|
||||||
throw UnmatchedUiDesignException(uiDesign);
|
throw UnmatchedUiDesignException(uiDesign);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
import 'package:fluent_ui/fluent_ui.dart';
|
|
||||||
import 'package:info_tren/pages/station_arrdep_page/select_station/select_station.dart';
|
|
||||||
|
|
||||||
class SelectStationPageFluent extends SelectStationPageShared {
|
|
||||||
const SelectStationPageFluent({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<StatefulWidget> createState() => SelectStationPageStateFluent();
|
|
||||||
}
|
|
||||||
|
|
||||||
class SelectStationPageStateFluent extends SelectStationPageState {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return NavigationView(
|
|
||||||
appBar: const NavigationAppBar(
|
|
||||||
title: Text(SelectStationPageState.pageTitle),
|
|
||||||
// centerTitle: true,
|
|
||||||
),
|
|
||||||
content: SafeArea(
|
|
||||||
bottom: false,
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.max,
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(4),
|
|
||||||
child: TextBox(
|
|
||||||
controller: textEditingController,
|
|
||||||
autofocus: true,
|
|
||||||
placeholder: SelectStationPageState.textFieldLabel,
|
|
||||||
textInputAction: TextInputAction.search,
|
|
||||||
onChanged: onTextChanged,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: ListView.builder(
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
return Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
ListTile(
|
|
||||||
// dense: true,
|
|
||||||
title: Text(filteredStations[index]),
|
|
||||||
onPressed: () => onSuggestionSelected(filteredStations[index]),
|
|
||||||
),
|
|
||||||
const Divider(
|
|
||||||
size: 1,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
itemCount: filteredStations.length,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +1,14 @@
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:info_tren/api/station_data.dart';
|
||||||
import 'package:info_tren/components/refresh_future_builder.dart';
|
import 'package:info_tren/components/refresh_future_builder.dart';
|
||||||
import 'package:info_tren/models.dart';
|
import 'package:info_tren/models.dart';
|
||||||
import 'package:info_tren/pages/station_arrdep_page/view_station/view_station_cupertino.dart';
|
import 'package:info_tren/pages/station_arrdep_page/view_station/view_station_cupertino.dart';
|
||||||
import 'package:info_tren/pages/station_arrdep_page/view_station/view_station_fluent.dart';
|
|
||||||
import 'package:info_tren/pages/station_arrdep_page/view_station/view_station_material.dart';
|
import 'package:info_tren/pages/station_arrdep_page/view_station/view_station_material.dart';
|
||||||
import 'package:info_tren/pages/train_info_page/view_train/train_info.dart';
|
import 'package:info_tren/pages/train_info_page/view_train/train_info.dart';
|
||||||
import 'package:info_tren/providers.dart';
|
import 'package:info_tren/providers.dart';
|
||||||
|
import 'package:info_tren/utils/default_ui_design.dart';
|
||||||
|
|
||||||
class ViewStationPage extends HookConsumerWidget {
|
class ViewStationPage extends HookConsumerWidget {
|
||||||
const ViewStationPage({ super.key, });
|
const ViewStationPage({ super.key, });
|
||||||
|
@ -32,11 +33,6 @@ class ViewStationPage extends HookConsumerWidget {
|
||||||
tab: tab.value,
|
tab: tab.value,
|
||||||
setTab: (newTab) => tab.value = newTab,
|
setTab: (newTab) => tab.value = newTab,
|
||||||
);
|
);
|
||||||
case UiDesign.FLUENT:
|
|
||||||
return ViewStationPageFluent(
|
|
||||||
tab: tab.value,
|
|
||||||
setTab: (newTab) => tab.value = newTab,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,8 +53,6 @@ abstract class ViewStationPageShared extends StatelessWidget {
|
||||||
static const departsTo = 'Pleacă către';
|
static const departsTo = 'Pleacă către';
|
||||||
static const departedTo = 'A plecat către';
|
static const departedTo = 'A plecat către';
|
||||||
static const cancelledDeparture = 'Anulat - către';
|
static const cancelledDeparture = 'Anulat - către';
|
||||||
static const errorText = 'A apărut o eroare';
|
|
||||||
static const retryText = 'Reîncearcă';
|
|
||||||
|
|
||||||
final ViewStationPageTab tab;
|
final ViewStationPageTab tab;
|
||||||
final void Function(ViewStationPageTab) setTab;
|
final void Function(ViewStationPageTab) setTab;
|
||||||
|
@ -84,16 +78,9 @@ abstract class ViewStationPageShared extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Consumer(
|
return RefreshFutureBuilderProviderAdapter(
|
||||||
builder: (context, ref, _) {
|
futureProvider: viewStationDataProvider,
|
||||||
return RefreshFutureBuilderProviderAdapter(
|
builder: buildContent,
|
||||||
futureProvider: viewStationDataProvider,
|
|
||||||
refresh: () async {
|
|
||||||
ref.invalidate(stationDataProvider);
|
|
||||||
},
|
|
||||||
builder: buildContent,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,267 +0,0 @@
|
||||||
import 'dart:math';
|
|
||||||
import 'dart:ui';
|
|
||||||
|
|
||||||
import 'package:fluent_ui/fluent_ui.dart';
|
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
||||||
import 'package:info_tren/components/badge/badge.dart';
|
|
||||||
import 'package:info_tren/components/loading/loading.dart';
|
|
||||||
import 'package:info_tren/components/refresh_future_builder.dart';
|
|
||||||
import 'package:info_tren/models.dart';
|
|
||||||
import 'package:info_tren/pages/station_arrdep_page/view_station/view_station.dart';
|
|
||||||
import 'package:info_tren/providers.dart';
|
|
||||||
|
|
||||||
class ViewStationPageFluent extends ViewStationPageShared {
|
|
||||||
const ViewStationPageFluent({super.key, required super.tab, required super.setTab});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget buildContent(BuildContext context, Future Function() refresh, Future Function(Future<StationData> Function()) _, RefreshFutureBuilderSnapshot<StationData> snapshot) {
|
|
||||||
return NavigationView(
|
|
||||||
appBar: NavigationAppBar(
|
|
||||||
title: Consumer(
|
|
||||||
builder: (context, ref, _) {
|
|
||||||
final stationName = ref.watch(viewStationArgumentsProvider.select((value) => value.stationName));
|
|
||||||
return Text(snapshot.hasData ? snapshot.data!.stationName : stationName);
|
|
||||||
}
|
|
||||||
),
|
|
||||||
),
|
|
||||||
content: snapshot.state == RefreshFutureBuilderState.waiting || snapshot.state == RefreshFutureBuilderState.refreshError
|
|
||||||
? const Loading(text: ViewStationPageShared.loadingText,)
|
|
||||||
: snapshot.state == RefreshFutureBuilderState.error
|
|
||||||
? Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Center(
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Icon(
|
|
||||||
FluentIcons.error,
|
|
||||||
size: 32,
|
|
||||||
color: Colors.red.normal,
|
|
||||||
),
|
|
||||||
const Text(
|
|
||||||
ViewStationPageShared.errorText,
|
|
||||||
style: TextStyle(
|
|
||||||
inherit: true,
|
|
||||||
fontSize: 32,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
snapshot.error.toString(),
|
|
||||||
style: FluentTheme.of(context).typography.subtitle,
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Button(
|
|
||||||
onPressed: () {
|
|
||||||
refresh();
|
|
||||||
},
|
|
||||||
child: const Text(ViewStationPageShared.retryText),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
pane: snapshot.hasData ? NavigationPane(
|
|
||||||
onChanged: onTabChange,
|
|
||||||
selected: tab.index,
|
|
||||||
items: [
|
|
||||||
PaneItem(
|
|
||||||
body: CustomScrollView(
|
|
||||||
slivers: [
|
|
||||||
SliverToBoxAdapter(child: SafeArea(left: false, bottom: false, right: false,child: Container(),),),
|
|
||||||
SliverList(
|
|
||||||
delegate: SliverChildBuilderDelegate(
|
|
||||||
(context, index) {
|
|
||||||
return tab == ViewStationPageTab.arrivals ? buildStationArrivalItem(context, snapshot.data!.arrivals![index]) : buildStationDepartureItem(context, snapshot.data!.departures![index]);
|
|
||||||
},
|
|
||||||
childCount: tab == ViewStationPageTab.arrivals ? snapshot.data!.arrivals?.length ?? 0 : snapshot.data!.departures?.length ?? 0,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
title: const Text(ViewStationPageShared.arrivals),
|
|
||||||
icon: const Icon(FluentIcons.arrow_down_right8),
|
|
||||||
),
|
|
||||||
PaneItem(
|
|
||||||
body: CustomScrollView(
|
|
||||||
slivers: [
|
|
||||||
SliverToBoxAdapter(child: SafeArea(left: false, bottom: false, right: false,child: Container(),),),
|
|
||||||
SliverList(
|
|
||||||
delegate: SliverChildBuilderDelegate(
|
|
||||||
(context, index) {
|
|
||||||
return tab == ViewStationPageTab.arrivals ? buildStationArrivalItem(context, snapshot.data!.arrivals![index]) : buildStationDepartureItem(context, snapshot.data!.departures![index]);
|
|
||||||
},
|
|
||||||
childCount: tab == ViewStationPageTab.arrivals ? snapshot.data!.arrivals?.length ?? 0 : snapshot.data!.departures?.length ?? 0,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
title: const Text(ViewStationPageShared.departures),
|
|
||||||
icon: const Icon(FluentIcons.arrow_up_right8),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
) : null,
|
|
||||||
// bottomNavigationBar: snapshot.hasData ? BottomNavigationBar(
|
|
||||||
// items: const [
|
|
||||||
// BottomNavigationBarItem(
|
|
||||||
// icon: Icon(Icons.arrow_downward),
|
|
||||||
// label: ViewStationPageShared.arrivals,
|
|
||||||
// ),
|
|
||||||
// BottomNavigationBarItem(
|
|
||||||
// icon: Icon(Icons.arrow_upward),
|
|
||||||
// label: ViewStationPageShared.departures,
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// currentIndex: tab.index,
|
|
||||||
// onTap: onTabChange,
|
|
||||||
// ) : null,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget buildStationItem(BuildContext context, StationArrDep item, {required bool arrival}) {
|
|
||||||
return HoverButton(
|
|
||||||
onPressed: () => onTrainTapped(context, item.train),
|
|
||||||
builder: (context, states) {
|
|
||||||
return Container(
|
|
||||||
color: item.status.cancelled
|
|
||||||
? Colors.red.withAlpha(100)
|
|
||||||
: states.isPressing
|
|
||||||
? FluentTheme.of(context).scaffoldBackgroundColor
|
|
||||||
: states.isHovering
|
|
||||||
? FluentTheme.of(context).inactiveBackgroundColor
|
|
||||||
: null,
|
|
||||||
child: Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(8),
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'${item.time.toLocal().hour.toString().padLeft(2, '0')}:${item.time.toLocal().minute.toString().padLeft(2, '0')}',
|
|
||||||
style: TextStyle(
|
|
||||||
inherit: true,
|
|
||||||
fontFeatures: const [
|
|
||||||
FontFeature.tabularFigures(),
|
|
||||||
],
|
|
||||||
decoration: item.status.cancelled || item.status.delay != 0 ? TextDecoration.lineThrough : null,
|
|
||||||
fontSize: item.status.delay != 0 ? 12 : null,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (item.status.delay != 0) Builder(
|
|
||||||
builder: (context) {
|
|
||||||
final newTime = item.time.add(Duration(minutes: item.status.delay));
|
|
||||||
final delay = item.status.delay > 0;
|
|
||||||
|
|
||||||
return Text(
|
|
||||||
'${newTime.toLocal().hour.toString().padLeft(2, '0')}:${newTime.toLocal().minute.toString().padLeft(2, '0')}',
|
|
||||||
style: TextStyle(
|
|
||||||
inherit: true,
|
|
||||||
fontFeatures: const [
|
|
||||||
FontFeature.tabularFigures(),
|
|
||||||
],
|
|
||||||
color: delay ? Colors.red : Colors.green,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: IgnorePointer(
|
|
||||||
child: ListTile(
|
|
||||||
// isThreeLine: item.status.delay != 0,
|
|
||||||
title: Text.rich(
|
|
||||||
TextSpan(
|
|
||||||
children: [
|
|
||||||
TextSpan(
|
|
||||||
text: item.train.rank,
|
|
||||||
style: TextStyle(
|
|
||||||
color: item.train.rank.startsWith('IR') ? const Color.fromARGB(255, 255, 0, 0) : null,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const TextSpan(text: ' '),
|
|
||||||
TextSpan(text: item.train.number,),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
subtitle: Text.rich(
|
|
||||||
TextSpan(
|
|
||||||
children: [
|
|
||||||
TextSpan(
|
|
||||||
text: item.status.cancelled
|
|
||||||
? (arrival ? ViewStationPageShared.cancelledArrival : ViewStationPageShared.cancelledDeparture)
|
|
||||||
: item.time.add(Duration(minutes: max(0, item.status.delay))).compareTo(DateTime.now()) < 0
|
|
||||||
? (arrival ? ViewStationPageShared.arrivedFrom : ViewStationPageShared.departedTo)
|
|
||||||
: (arrival ? ViewStationPageShared.arrivesFrom : ViewStationPageShared.departsTo)
|
|
||||||
),
|
|
||||||
const TextSpan(text: ' '),
|
|
||||||
TextSpan(text: item.train.terminus),
|
|
||||||
if (item.status.delay != 0) ...[
|
|
||||||
const TextSpan(text: '\n'),
|
|
||||||
if (item.status.delay.abs() >= 60) ...[
|
|
||||||
TextSpan(text: (item.status.delay.abs() ~/ 60).toString()),
|
|
||||||
TextSpan(text: item.status.delay.abs() >= 120 ? ' ore' : ' oră'),
|
|
||||||
if (item.status.delay.abs() % 60 != 0)
|
|
||||||
const TextSpan(text: ' și '),
|
|
||||||
],
|
|
||||||
TextSpan(text: (item.status.delay.abs() % 60).toString()),
|
|
||||||
TextSpan(text: item.status.delay.abs() > 1 ? ' minute' : ' minut'),
|
|
||||||
const TextSpan(text: ' '),
|
|
||||||
if (item.status.delay > 0)
|
|
||||||
TextSpan(
|
|
||||||
text: 'întârziere',
|
|
||||||
style: TextStyle(
|
|
||||||
inherit: true,
|
|
||||||
color: Colors.red,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
else
|
|
||||||
TextSpan(
|
|
||||||
text: 'mai devreme',
|
|
||||||
style: TextStyle(
|
|
||||||
inherit: true,
|
|
||||||
color: Colors.green,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (item.status.platform != null)
|
|
||||||
IntrinsicHeight(
|
|
||||||
child: AspectRatio(
|
|
||||||
aspectRatio: 1,
|
|
||||||
child: Badge(
|
|
||||||
text: item.status.platform!,
|
|
||||||
caption: 'Linia',
|
|
||||||
isOnTime: item.status.real && item.status.delay <= 0,
|
|
||||||
isDelayed: item.status.real && item.status.delay > 0,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget buildStationArrivalItem(BuildContext context, StationArrDep item) {
|
|
||||||
return buildStationItem(context, item, arrival: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget buildStationDepartureItem(BuildContext context, StationArrDep item) {
|
|
||||||
return buildStationItem(context, item, arrival: false);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,7 +2,7 @@ import 'dart:math';
|
||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:info_tren/components/badge/badge.dart';
|
import 'package:info_tren/components/badge.dart';
|
||||||
import 'package:info_tren/components/loading/loading.dart';
|
import 'package:info_tren/components/loading/loading.dart';
|
||||||
import 'package:info_tren/components/refresh_future_builder.dart';
|
import 'package:info_tren/components/refresh_future_builder.dart';
|
||||||
import 'package:info_tren/models.dart';
|
import 'package:info_tren/models.dart';
|
||||||
|
@ -27,41 +27,7 @@ class ViewStationPageMaterial extends ViewStationPageShared {
|
||||||
body: snapshot.state == RefreshFutureBuilderState.waiting
|
body: snapshot.state == RefreshFutureBuilderState.waiting
|
||||||
? const Loading(text: ViewStationPageShared.loadingText,)
|
? const Loading(text: ViewStationPageShared.loadingText,)
|
||||||
: snapshot.state == RefreshFutureBuilderState.error
|
: snapshot.state == RefreshFutureBuilderState.error
|
||||||
? Padding(
|
? Container()
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Center(
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
const Icon(
|
|
||||||
Icons.error_outline,
|
|
||||||
size: 32,
|
|
||||||
color: Colors.red,
|
|
||||||
),
|
|
||||||
const Text(
|
|
||||||
ViewStationPageShared.errorText,
|
|
||||||
style: TextStyle(
|
|
||||||
inherit: true,
|
|
||||||
fontSize: 32,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
snapshot.error.toString(),
|
|
||||||
style: Theme.of(context).textTheme.bodySmall,
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: ElevatedButton(
|
|
||||||
onPressed: () {
|
|
||||||
refresh();
|
|
||||||
},
|
|
||||||
child: const Text(ViewStationPageShared.retryText),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: CustomScrollView(
|
: CustomScrollView(
|
||||||
slivers: [
|
slivers: [
|
||||||
SliverToBoxAdapter(child: SafeArea(left: false, bottom: false, right: false,child: Container(),),),
|
SliverToBoxAdapter(child: SafeArea(left: false, bottom: false, right: false,child: Container(),),),
|
||||||
|
@ -205,7 +171,7 @@ class ViewStationPageMaterial extends ViewStationPageShared {
|
||||||
IntrinsicHeight(
|
IntrinsicHeight(
|
||||||
child: AspectRatio(
|
child: AspectRatio(
|
||||||
aspectRatio: 1,
|
aspectRatio: 1,
|
||||||
child: Badge(
|
child: MaterialBadge(
|
||||||
text: item.status.platform!,
|
text: item.status.platform!,
|
||||||
caption: 'Linia',
|
caption: 'Linia',
|
||||||
isOnTime: item.status.real && item.status.delay <= 0,
|
isOnTime: item.status.real && item.status.delay <= 0,
|
||||||
|
|
|
@ -5,7 +5,6 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:info_tren/components/select_train_suggestions/select_train_suggestions.dart';
|
import 'package:info_tren/components/select_train_suggestions/select_train_suggestions.dart';
|
||||||
import 'package:info_tren/models.dart';
|
import 'package:info_tren/models.dart';
|
||||||
import 'package:info_tren/pages/train_info_page/select_train/select_train_cupertino.dart';
|
import 'package:info_tren/pages/train_info_page/select_train/select_train_cupertino.dart';
|
||||||
import 'package:info_tren/pages/train_info_page/select_train/select_train_fluent.dart';
|
|
||||||
import 'package:info_tren/pages/train_info_page/select_train/select_train_material.dart';
|
import 'package:info_tren/pages/train_info_page/select_train/select_train_material.dart';
|
||||||
import 'package:info_tren/pages/train_info_page/view_train/train_info.dart';
|
import 'package:info_tren/pages/train_info_page/view_train/train_info.dart';
|
||||||
import 'package:info_tren/providers.dart';
|
import 'package:info_tren/providers.dart';
|
||||||
|
@ -27,8 +26,6 @@ class SelectTrainPage extends ConsumerWidget {
|
||||||
return const SelectTrainPageMaterial();
|
return const SelectTrainPageMaterial();
|
||||||
case UiDesign.CUPERTINO:
|
case UiDesign.CUPERTINO:
|
||||||
return const SelectTrainPageCupertino();
|
return const SelectTrainPageCupertino();
|
||||||
case UiDesign.FLUENT:
|
|
||||||
return const SelectTrainPageFluent();
|
|
||||||
default:
|
default:
|
||||||
throw UnmatchedUiDesignException(uiDesign);
|
throw UnmatchedUiDesignException(uiDesign);
|
||||||
}
|
}
|
||||||
|
@ -73,11 +70,7 @@ abstract class SelectTrainPageState extends State<SelectTrainPageShared> {
|
||||||
return posInNum1.compareTo(posInNum2);
|
return posInNum1.compareTo(posInNum2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t1.number.length != t2.number.length) {
|
return t1.number.length.compareTo(t2.number.length);
|
||||||
return t1.number.length.compareTo(t2.number.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
return t1.number.compareTo(t2.number);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return filtered;
|
return filtered;
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
import 'package:fluent_ui/fluent_ui.dart';
|
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:info_tren/pages/train_info_page/select_train/select_train.dart';
|
|
||||||
|
|
||||||
class SelectTrainPageFluent extends SelectTrainPageShared {
|
|
||||||
const SelectTrainPageFluent({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<SelectTrainPageShared> createState() => SelectTrainPageStateFluent();
|
|
||||||
}
|
|
||||||
|
|
||||||
class SelectTrainPageStateFluent extends SelectTrainPageState {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return NavigationView(
|
|
||||||
appBar: NavigationAppBar(
|
|
||||||
title: Text(pageTitle),
|
|
||||||
),
|
|
||||||
content: SafeArea(
|
|
||||||
bottom: false,
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.max,
|
|
||||||
children: <Widget>[
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(4),
|
|
||||||
child: TextBox(
|
|
||||||
controller: trainNoController,
|
|
||||||
autofocus: true,
|
|
||||||
placeholder: textFieldLabel,
|
|
||||||
textInputAction: TextInputAction.search,
|
|
||||||
keyboardType: TextInputType.number,
|
|
||||||
onChanged: (_) => onTextChanged(),
|
|
||||||
inputFormatters: [
|
|
||||||
FilteringTextInputFormatter.digitsOnly,
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: suggestionsList,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +1,12 @@
|
||||||
import 'package:flutter/widgets.dart';
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:info_tren/api/train_data.dart';
|
import 'package:info_tren/api/train_data.dart';
|
||||||
import 'package:info_tren/components/loading/loading.dart';
|
import 'package:info_tren/components/loading/loading.dart';
|
||||||
import 'package:info_tren/components/refresh_future_builder.dart';
|
import 'package:info_tren/components/refresh_future_builder.dart';
|
||||||
import 'package:info_tren/models.dart';
|
import 'package:info_tren/models.dart';
|
||||||
import 'package:info_tren/pages/train_info_page/view_train/train_info_cupertino.dart';
|
import 'package:info_tren/pages/train_info_page/view_train/train_info_cupertino.dart';
|
||||||
import 'package:info_tren/pages/train_info_page/view_train/train_info_fluent.dart';
|
|
||||||
import 'package:info_tren/pages/train_info_page/view_train/train_info_material.dart';
|
import 'package:info_tren/pages/train_info_page/view_train/train_info_material.dart';
|
||||||
import 'package:info_tren/providers.dart';
|
import 'package:info_tren/providers.dart';
|
||||||
|
|
||||||
|
@ -29,35 +30,34 @@ class TrainInfo extends ConsumerWidget {
|
||||||
replaceFutureBuilder(() => getTrain(trainNumber, date: DateTime.now().subtract(const Duration(days: 1))));
|
replaceFutureBuilder(() => getTrain(trainNumber, date: DateTime.now().subtract(const Duration(days: 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,);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (uiDesign) {
|
switch (uiDesign) {
|
||||||
case UiDesign.MATERIAL:
|
case UiDesign.MATERIAL:
|
||||||
|
if ([RefreshFutureBuilderState.none, RefreshFutureBuilderState.waiting].contains(snapshot.state)) {
|
||||||
|
return TrainInfoLoadingMaterial(title: trainNumber.toString(), loadingText: "Se încarcă...",);
|
||||||
|
}
|
||||||
|
else if (snapshot.state == RefreshFutureBuilderState.error) {
|
||||||
|
return TrainInfoErrorMaterial(title: '$trainNumber - Error', error: snapshot.error!, refresh: refresh,);
|
||||||
|
}
|
||||||
|
|
||||||
return TrainInfoMaterial(
|
return TrainInfoMaterial(
|
||||||
trainData: snapshot.data!,
|
trainData: snapshot.data!,
|
||||||
refresh: refresh,
|
refresh: refresh,
|
||||||
isRefreshing: snapshot.state == RefreshFutureBuilderState.refreshing,
|
|
||||||
onViewYesterdayTrain: onViewYesterdayTrain,
|
onViewYesterdayTrain: onViewYesterdayTrain,
|
||||||
);
|
);
|
||||||
case UiDesign.CUPERTINO:
|
case UiDesign.CUPERTINO:
|
||||||
|
if ([RefreshFutureBuilderState.none, RefreshFutureBuilderState.waiting].contains(snapshot.state)) {
|
||||||
|
return TrainInfoLoadingCupertino(title: trainNumber.toString(), loadingText: "Se încarcă...",);
|
||||||
|
}
|
||||||
|
else if (snapshot.state == RefreshFutureBuilderState.error) {
|
||||||
|
return TrainInfoErrorCupertino(title: '$trainNumber - Error', error: snapshot.error!, refresh: refresh,);
|
||||||
|
}
|
||||||
|
|
||||||
return TrainInfoCupertino(
|
return TrainInfoCupertino(
|
||||||
trainData: snapshot.data!,
|
trainData: snapshot.data!,
|
||||||
refresh: refresh,
|
refresh: refresh,
|
||||||
isRefreshing: snapshot.state == RefreshFutureBuilderState.refreshing,
|
isRefreshing: snapshot.state == RefreshFutureBuilderState.refreshing,
|
||||||
onViewYesterdayTrain: onViewYesterdayTrain,
|
onViewYesterdayTrain: onViewYesterdayTrain,
|
||||||
);
|
);
|
||||||
case UiDesign.FLUENT:
|
|
||||||
return TrainInfoFluent(
|
|
||||||
trainData: snapshot.data!,
|
|
||||||
refresh: refresh,
|
|
||||||
isRefreshing: snapshot.state == RefreshFutureBuilderState.refreshing,
|
|
||||||
onViewYesterdayTrain: onViewYesterdayTrain,
|
|
||||||
);
|
|
||||||
default:
|
default:
|
||||||
throw UnmatchedUiDesignException(uiDesign);
|
throw UnmatchedUiDesignException(uiDesign);
|
||||||
}
|
}
|
||||||
|
@ -73,176 +73,23 @@ class TrainInfoArguments {
|
||||||
TrainInfoArguments({required this.trainNumber, this.date});
|
TrainInfoArguments({required this.trainNumber, this.date});
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class TrainInfoShared extends StatelessWidget {
|
abstract class TrainInfoLoading extends StatelessWidget {
|
||||||
final TrainData trainData;
|
|
||||||
final Future Function()? refresh;
|
|
||||||
final void Function()? onViewYesterdayTrain;
|
|
||||||
final bool? isRefreshing;
|
|
||||||
|
|
||||||
const TrainInfoShared({
|
|
||||||
super.key,
|
|
||||||
required this.trainData,
|
|
||||||
this.refresh,
|
|
||||||
this.onViewYesterdayTrain,
|
|
||||||
this.isRefreshing,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
class TrainInfoLoading extends ConsumerWidget {
|
|
||||||
final String title;
|
|
||||||
final String? loadingText;
|
|
||||||
|
|
||||||
const TrainInfoLoading({
|
|
||||||
super.key,
|
|
||||||
required this.title,
|
|
||||||
this.loadingText,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
|
||||||
final uiDesign = ref.watch(uiDesignProvider);
|
|
||||||
|
|
||||||
switch (uiDesign) {
|
|
||||||
case UiDesign.MATERIAL:
|
|
||||||
return TrainInfoLoadingMaterial(
|
|
||||||
title: title,
|
|
||||||
loadingText: loadingText,
|
|
||||||
);
|
|
||||||
case UiDesign.CUPERTINO:
|
|
||||||
return TrainInfoLoadingCupertino(
|
|
||||||
title: title,
|
|
||||||
loadingText: loadingText,
|
|
||||||
);
|
|
||||||
case UiDesign.FLUENT:
|
|
||||||
return TrainInfoLoadingFluent(
|
|
||||||
title: title,
|
|
||||||
loadingText: loadingText,
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
throw UnmatchedUiDesignException(uiDesign);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class TrainInfoLoadingShared extends StatelessWidget {
|
|
||||||
final String title;
|
final String title;
|
||||||
final Widget loadingWidget;
|
final Widget loadingWidget;
|
||||||
|
|
||||||
TrainInfoLoadingShared({
|
TrainInfoLoading({
|
||||||
required this.title,
|
required this.title,
|
||||||
String? loadingText,
|
String? loadingText,
|
||||||
super.key,
|
super.key,
|
||||||
}) : loadingWidget = Loading(text: loadingText,);
|
}) : loadingWidget = Loading(text: loadingText,);
|
||||||
}
|
}
|
||||||
|
|
||||||
class TrainInfoError extends ConsumerWidget {
|
abstract class TrainInfoError extends StatelessWidget {
|
||||||
final String title;
|
final String title;
|
||||||
final Object error;
|
final Object error;
|
||||||
final Future Function()? refresh;
|
final Future Function()? refresh;
|
||||||
|
|
||||||
const TrainInfoError({
|
const TrainInfoError({required this.title, required this.error, this.refresh, super.key,});
|
||||||
super.key,
|
|
||||||
required this.title,
|
|
||||||
required this.error,
|
|
||||||
this.refresh,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
|
||||||
final uiDesign = ref.watch(uiDesignProvider);
|
|
||||||
|
|
||||||
switch (uiDesign) {
|
|
||||||
case UiDesign.MATERIAL:
|
|
||||||
return TrainInfoErrorMaterial(
|
|
||||||
title: title,
|
|
||||||
error: error,
|
|
||||||
refresh: refresh,
|
|
||||||
);
|
|
||||||
case UiDesign.CUPERTINO:
|
|
||||||
return TrainInfoErrorCupertino(
|
|
||||||
title: title,
|
|
||||||
error: error,
|
|
||||||
refresh: refresh,
|
|
||||||
);
|
|
||||||
case UiDesign.FLUENT:
|
|
||||||
return TrainInfoErrorFluent(
|
|
||||||
title: title,
|
|
||||||
error: error,
|
|
||||||
refresh: refresh,
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
throw UnmatchedUiDesignException(uiDesign);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class TrainInfoErrorShared extends StatelessWidget {
|
|
||||||
final String title;
|
|
||||||
final Object error;
|
|
||||||
final Future Function()? refresh;
|
|
||||||
|
|
||||||
const TrainInfoErrorShared({required this.title, required this.error, this.refresh, super.key,});
|
|
||||||
}
|
|
||||||
|
|
||||||
class TrainInfoBody extends ConsumerWidget {
|
|
||||||
final TrainData trainData;
|
|
||||||
final void Function()? onViewYesterdayTrain;
|
|
||||||
final Future Function()? refresh;
|
|
||||||
final bool? isRefreshing;
|
|
||||||
|
|
||||||
const TrainInfoBody({
|
|
||||||
required this.trainData,
|
|
||||||
this.onViewYesterdayTrain,
|
|
||||||
this.refresh,
|
|
||||||
this.isRefreshing,
|
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
|
||||||
final uiDesign = ref.watch(uiDesignProvider);
|
|
||||||
|
|
||||||
switch (uiDesign) {
|
|
||||||
case UiDesign.MATERIAL:
|
|
||||||
return TrainInfoBodyMaterial(
|
|
||||||
trainData: trainData,
|
|
||||||
onViewYesterdayTrain: onViewYesterdayTrain,
|
|
||||||
refresh: refresh,
|
|
||||||
isRefreshing: isRefreshing,
|
|
||||||
);
|
|
||||||
case UiDesign.CUPERTINO:
|
|
||||||
return TrainInfoBodyCupertino(
|
|
||||||
trainData: trainData,
|
|
||||||
onViewYesterdayTrain: onViewYesterdayTrain,
|
|
||||||
refresh: refresh,
|
|
||||||
isRefreshing: isRefreshing,
|
|
||||||
);
|
|
||||||
case UiDesign.FLUENT:
|
|
||||||
return TrainInfoBodyFluent(
|
|
||||||
trainData: trainData,
|
|
||||||
onViewYesterdayTrain: onViewYesterdayTrain,
|
|
||||||
refresh: refresh,
|
|
||||||
isRefreshing: isRefreshing,
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
throw UnmatchedUiDesignException(uiDesign);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class TrainInfoBodyShared extends StatelessWidget {
|
|
||||||
final TrainData trainData;
|
|
||||||
final void Function()? onViewYesterdayTrain;
|
|
||||||
final Future Function()? refresh;
|
|
||||||
final bool? isRefreshing;
|
|
||||||
|
|
||||||
const TrainInfoBodyShared({
|
|
||||||
required this.trainData,
|
|
||||||
this.onViewYesterdayTrain,
|
|
||||||
this.refresh,
|
|
||||||
this.isRefreshing,
|
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class DisplayTrainYesterdayWarningCommon extends StatelessWidget {
|
abstract class DisplayTrainYesterdayWarningCommon extends StatelessWidget {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import 'package:info_tren/pages/train_info_page/view_train/train_info.dart';
|
||||||
import 'package:info_tren/pages/train_info_page/view_train/train_info_cupertino_DisplayTrainStation.dart';
|
import 'package:info_tren/pages/train_info_page/view_train/train_info_cupertino_DisplayTrainStation.dart';
|
||||||
import 'package:info_tren/utils/state_to_string.dart';
|
import 'package:info_tren/utils/state_to_string.dart';
|
||||||
|
|
||||||
class TrainInfoLoadingCupertino extends TrainInfoLoadingShared {
|
class TrainInfoLoadingCupertino extends TrainInfoLoading {
|
||||||
TrainInfoLoadingCupertino({required super.title, super.loadingText, super.key,});
|
TrainInfoLoadingCupertino({required super.title, super.loadingText, super.key,});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -26,13 +26,17 @@ class TrainInfoLoadingCupertino extends TrainInfoLoadingShared {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TrainInfoErrorCupertino extends TrainInfoErrorShared {
|
class TrainInfoErrorCupertino extends TrainInfoError {
|
||||||
const TrainInfoErrorCupertino({
|
const TrainInfoErrorCupertino({
|
||||||
required super.error,
|
required Object error,
|
||||||
required super.title,
|
required String title,
|
||||||
super.refresh,
|
Future Function()? refresh,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
}) : super(
|
||||||
|
error: error,
|
||||||
|
title: title,
|
||||||
|
refresh: refresh,
|
||||||
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -60,12 +64,17 @@ class TrainInfoErrorCupertino extends TrainInfoErrorShared {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TrainInfoCupertino extends TrainInfoShared {
|
class TrainInfoCupertino extends StatelessWidget {
|
||||||
|
final TrainData trainData;
|
||||||
|
final Future Function()? refresh;
|
||||||
|
final bool? isRefreshing;
|
||||||
|
final void Function()? onViewYesterdayTrain;
|
||||||
|
|
||||||
const TrainInfoCupertino({
|
const TrainInfoCupertino({
|
||||||
required super.trainData,
|
required this.trainData,
|
||||||
super.refresh,
|
this.refresh,
|
||||||
super.isRefreshing,
|
this.isRefreshing,
|
||||||
super.onViewYesterdayTrain,
|
this.onViewYesterdayTrain,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -84,10 +93,195 @@ class TrainInfoCupertino extends TrainInfoShared {
|
||||||
child: SafeArea(
|
child: SafeArea(
|
||||||
top: false,
|
top: false,
|
||||||
bottom: false,
|
bottom: false,
|
||||||
child: TrainInfoBody(
|
child: Builder(builder: (context) {
|
||||||
trainData: trainData,
|
final topPadding = MediaQuery.of(context).padding.top;
|
||||||
onViewYesterdayTrain: onViewYesterdayTrain,
|
|
||||||
),
|
return NestedScrollView(
|
||||||
|
headerSliverBuilder: (context, innerBoxIsScrolled) {
|
||||||
|
return [
|
||||||
|
// SliverPadding(
|
||||||
|
// padding: EdgeInsets.only(
|
||||||
|
// top: topPadding,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
SliverPersistentHeaderPadding(
|
||||||
|
maxHeight: topPadding,
|
||||||
|
)
|
||||||
|
];
|
||||||
|
},
|
||||||
|
body: Builder(builder: (context) {
|
||||||
|
return CustomScrollView(
|
||||||
|
slivers: <Widget>[
|
||||||
|
if (refresh != null)
|
||||||
|
CupertinoSliverRefreshControl(
|
||||||
|
builder: (context, mode, pulledExtent,
|
||||||
|
refreshTriggerPullDistance, refreshIndicatorExtent) {
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
height: pulledExtent,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
height: min(
|
||||||
|
refreshIndicatorExtent, pulledExtent),
|
||||||
|
child: Center(
|
||||||
|
child: Builder(
|
||||||
|
builder: (context) {
|
||||||
|
if (mode ==
|
||||||
|
RefreshIndicatorMode.inactive) {
|
||||||
|
return Container();
|
||||||
|
} else if (mode ==
|
||||||
|
RefreshIndicatorMode.done) {
|
||||||
|
return const Text('Refreshed!');
|
||||||
|
} else if (mode ==
|
||||||
|
RefreshIndicatorMode.drag) {
|
||||||
|
return Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: const [
|
||||||
|
CupertinoActivityIndicator(
|
||||||
|
animating: false,
|
||||||
|
),
|
||||||
|
Text('Pull to refresh...'),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
} else if (mode ==
|
||||||
|
RefreshIndicatorMode.armed) {
|
||||||
|
return Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: const [
|
||||||
|
CupertinoActivityIndicator(
|
||||||
|
animating: false,
|
||||||
|
),
|
||||||
|
Text('Release to refresh...'),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: const [
|
||||||
|
CupertinoActivityIndicator(),
|
||||||
|
Text('Refreshing'),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Container(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onRefresh: refresh,
|
||||||
|
),
|
||||||
|
DisplayTrainID(
|
||||||
|
trainData: trainData,
|
||||||
|
),
|
||||||
|
DisplayTrainOperator(
|
||||||
|
trainData: trainData,
|
||||||
|
),
|
||||||
|
DisplayTrainRoute(
|
||||||
|
trainData: trainData,
|
||||||
|
),
|
||||||
|
DisplayTrainDeparture(
|
||||||
|
trainData: trainData,
|
||||||
|
),
|
||||||
|
const SliverToBoxAdapter(
|
||||||
|
child: CupertinoDivider(
|
||||||
|
color: foregroundWhite,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
DisplayTrainLastInfo(
|
||||||
|
trainData: trainData,
|
||||||
|
),
|
||||||
|
const SliverToBoxAdapter(
|
||||||
|
child: CupertinoDivider(),
|
||||||
|
),
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: IntrinsicHeight(
|
||||||
|
child: Row(
|
||||||
|
children: <Widget>[
|
||||||
|
// Expanded(
|
||||||
|
// child: DisplayTrainNextStop(trainData: trainData,),
|
||||||
|
// ),
|
||||||
|
Expanded(
|
||||||
|
child: DisplayTrainRouteDuration(
|
||||||
|
trainData: trainData,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Expanded(
|
||||||
|
// child: DisplayTrainDestination(trainData: trainData,),
|
||||||
|
// ),
|
||||||
|
const SizedBox(
|
||||||
|
height: double.infinity,
|
||||||
|
child: CupertinoVerticalDivider(),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: DisplayTrainRouteDistance(
|
||||||
|
trainData: trainData,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// SliverToBoxAdapter(
|
||||||
|
// child: CupertinoDivider(),
|
||||||
|
// ),
|
||||||
|
// SliverToBoxAdapter(
|
||||||
|
// child: IntrinsicHeight(
|
||||||
|
// child: Row(
|
||||||
|
// children: <Widget>[
|
||||||
|
// // Expanded(
|
||||||
|
// // child: DisplayTrainRouteDuration(trainData: trainData,),
|
||||||
|
// // ),
|
||||||
|
// Expanded(child: Container(),),
|
||||||
|
// SizedBox(
|
||||||
|
// height: double.infinity,
|
||||||
|
// child: CupertinoVerticalDivider(),
|
||||||
|
// ),
|
||||||
|
// Expanded(
|
||||||
|
// child: DisplayTrainRouteDistance(trainData: trainData,),
|
||||||
|
// )
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
const SliverToBoxAdapter(
|
||||||
|
child: CupertinoDivider(
|
||||||
|
color: foregroundWhite,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (onViewYesterdayTrain != null && trainData.stations.first.departure!.scheduleTime.compareTo(DateTime.now()) > 0) ...[
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: DisplayTrainYesterdayWarningCupertino(onViewYesterdayTrain!),
|
||||||
|
),
|
||||||
|
const SliverToBoxAdapter(
|
||||||
|
child: CupertinoDivider(
|
||||||
|
color: foregroundWhite,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
DisplayTrainStations(
|
||||||
|
trainData: trainData,
|
||||||
|
),
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: Container(
|
||||||
|
height: MediaQuery.of(context).viewPadding.bottom,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -196,382 +390,31 @@ class TrainInfoCupertino extends TrainInfoShared {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TrainInfoBodyCupertino extends TrainInfoBodyShared {
|
|
||||||
const TrainInfoBodyCupertino({
|
|
||||||
super.key,
|
|
||||||
required super.trainData,
|
|
||||||
super.onViewYesterdayTrain,
|
|
||||||
super.isRefreshing,
|
|
||||||
super.refresh,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final mq = MediaQuery.of(context);
|
|
||||||
final topPadding = mq.padding.top;
|
|
||||||
|
|
||||||
if (mq.orientation == Orientation.landscape && mq.size.width >= 1000) {
|
|
||||||
return Row(
|
|
||||||
mainAxisSize: MainAxisSize.max,
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
constraints: const BoxConstraints(
|
|
||||||
minWidth: 400,
|
|
||||||
maxWidth: 400,
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.max,
|
|
||||||
children: [
|
|
||||||
DisplayTrainID(trainData: trainData),
|
|
||||||
DisplayTrainOperator(trainData: trainData),
|
|
||||||
DisplayTrainRoute(trainData: trainData),
|
|
||||||
DisplayTrainDeparture(trainData: trainData),
|
|
||||||
const CupertinoDivider(
|
|
||||||
color: foregroundWhite,
|
|
||||||
),
|
|
||||||
DisplayTrainLastInfo(trainData: trainData),
|
|
||||||
const CupertinoDivider(),
|
|
||||||
IntrinsicHeight(
|
|
||||||
child: Row(
|
|
||||||
children: <Widget>[
|
|
||||||
// Expanded(
|
|
||||||
// child: DisplayTrainNextStop(trainData: trainData,),
|
|
||||||
// ),
|
|
||||||
Expanded(
|
|
||||||
child: DisplayTrainRouteDuration(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
// Expanded(
|
|
||||||
// child: DisplayTrainDestination(trainData: trainData,),
|
|
||||||
// ),
|
|
||||||
const SizedBox(
|
|
||||||
height: double.infinity,
|
|
||||||
child: CupertinoVerticalDivider(),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: DisplayTrainRouteDistance(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const CupertinoDivider(
|
|
||||||
color: foregroundWhite,
|
|
||||||
),
|
|
||||||
if (onViewYesterdayTrain != null && trainData.stations.first.departure!.scheduleTime.compareTo(DateTime.now()) > 0) ...[
|
|
||||||
DisplayTrainYesterdayWarningCupertino(onViewYesterdayTrain!),
|
|
||||||
const CupertinoDivider(
|
|
||||||
color: foregroundWhite,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: NestedScrollView(
|
|
||||||
headerSliverBuilder: (context, innerBoxIsScrolled) {
|
|
||||||
return [
|
|
||||||
// SliverPadding(
|
|
||||||
// padding: EdgeInsets.only(
|
|
||||||
// top: topPadding,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
SliverPersistentHeaderPadding(
|
|
||||||
maxHeight: topPadding,
|
|
||||||
)
|
|
||||||
];
|
|
||||||
},
|
|
||||||
body: CustomScrollView(
|
|
||||||
slivers: [
|
|
||||||
if (refresh != null)
|
|
||||||
CupertinoSliverRefreshControl(
|
|
||||||
builder: (context, mode, pulledExtent,
|
|
||||||
refreshTriggerPullDistance, refreshIndicatorExtent) {
|
|
||||||
return Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
SizedBox(
|
|
||||||
height: pulledExtent,
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
SizedBox(
|
|
||||||
height: min(
|
|
||||||
refreshIndicatorExtent, pulledExtent),
|
|
||||||
child: Center(
|
|
||||||
child: Builder(
|
|
||||||
builder: (context) {
|
|
||||||
if (mode ==
|
|
||||||
RefreshIndicatorMode.inactive) {
|
|
||||||
return Container();
|
|
||||||
} else if (mode ==
|
|
||||||
RefreshIndicatorMode.done) {
|
|
||||||
return const Text('Refreshed!');
|
|
||||||
} else if (mode ==
|
|
||||||
RefreshIndicatorMode.drag) {
|
|
||||||
return Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: const [
|
|
||||||
CupertinoActivityIndicator(
|
|
||||||
animating: false,
|
|
||||||
),
|
|
||||||
Text('Pull to refresh...'),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
} else if (mode ==
|
|
||||||
RefreshIndicatorMode.armed) {
|
|
||||||
return Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: const [
|
|
||||||
CupertinoActivityIndicator(
|
|
||||||
animating: false,
|
|
||||||
),
|
|
||||||
Text('Release to refresh...'),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: const [
|
|
||||||
CupertinoActivityIndicator(),
|
|
||||||
Text('Refreshing'),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Container(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
onRefresh: refresh,
|
|
||||||
),
|
|
||||||
|
|
||||||
DisplayTrainStations(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: Container(
|
|
||||||
height: MediaQuery.of(context).viewPadding.bottom,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NestedScrollView(
|
|
||||||
headerSliverBuilder: (context, innerBoxIsScrolled) {
|
|
||||||
return [
|
|
||||||
// SliverPadding(
|
|
||||||
// padding: EdgeInsets.only(
|
|
||||||
// top: topPadding,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
SliverPersistentHeaderPadding(
|
|
||||||
maxHeight: topPadding,
|
|
||||||
)
|
|
||||||
];
|
|
||||||
},
|
|
||||||
body: Builder(builder: (context) {
|
|
||||||
return CustomScrollView(
|
|
||||||
slivers: <Widget>[
|
|
||||||
if (refresh != null)
|
|
||||||
CupertinoSliverRefreshControl(
|
|
||||||
builder: (context, mode, pulledExtent,
|
|
||||||
refreshTriggerPullDistance, refreshIndicatorExtent) {
|
|
||||||
return Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
SizedBox(
|
|
||||||
height: pulledExtent,
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
SizedBox(
|
|
||||||
height: min(
|
|
||||||
refreshIndicatorExtent, pulledExtent),
|
|
||||||
child: Center(
|
|
||||||
child: Builder(
|
|
||||||
builder: (context) {
|
|
||||||
if (mode ==
|
|
||||||
RefreshIndicatorMode.inactive) {
|
|
||||||
return Container();
|
|
||||||
} else if (mode ==
|
|
||||||
RefreshIndicatorMode.done) {
|
|
||||||
return const Text('Refreshed!');
|
|
||||||
} else if (mode ==
|
|
||||||
RefreshIndicatorMode.drag) {
|
|
||||||
return Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: const [
|
|
||||||
CupertinoActivityIndicator(
|
|
||||||
animating: false,
|
|
||||||
),
|
|
||||||
Text('Pull to refresh...'),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
} else if (mode ==
|
|
||||||
RefreshIndicatorMode.armed) {
|
|
||||||
return Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: const [
|
|
||||||
CupertinoActivityIndicator(
|
|
||||||
animating: false,
|
|
||||||
),
|
|
||||||
Text('Release to refresh...'),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: const [
|
|
||||||
CupertinoActivityIndicator(),
|
|
||||||
Text('Refreshing'),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Container(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
onRefresh: refresh,
|
|
||||||
),
|
|
||||||
...[
|
|
||||||
DisplayTrainID(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
DisplayTrainOperator(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
DisplayTrainRoute(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
DisplayTrainDeparture(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
const CupertinoDivider(
|
|
||||||
color: foregroundWhite,
|
|
||||||
),
|
|
||||||
DisplayTrainLastInfo(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
const CupertinoDivider(),
|
|
||||||
IntrinsicHeight(
|
|
||||||
child: Row(
|
|
||||||
children: <Widget>[
|
|
||||||
// Expanded(
|
|
||||||
// child: DisplayTrainNextStop(trainData: trainData,),
|
|
||||||
// ),
|
|
||||||
Expanded(
|
|
||||||
child: DisplayTrainRouteDuration(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
// Expanded(
|
|
||||||
// child: DisplayTrainDestination(trainData: trainData,),
|
|
||||||
// ),
|
|
||||||
const SizedBox(
|
|
||||||
height: double.infinity,
|
|
||||||
child: CupertinoVerticalDivider(),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: DisplayTrainRouteDistance(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const CupertinoDivider(
|
|
||||||
color: foregroundWhite,
|
|
||||||
),
|
|
||||||
if (onViewYesterdayTrain != null && trainData.stations.first.departure!.scheduleTime.compareTo(DateTime.now()) > 0) ...[
|
|
||||||
DisplayTrainYesterdayWarningCupertino(onViewYesterdayTrain!),
|
|
||||||
const CupertinoDivider(
|
|
||||||
color: foregroundWhite,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
].map((e) => SliverToBoxAdapter(child: e)),
|
|
||||||
// SliverToBoxAdapter(
|
|
||||||
// child: CupertinoDivider(),
|
|
||||||
// ),
|
|
||||||
// SliverToBoxAdapter(
|
|
||||||
// child: IntrinsicHeight(
|
|
||||||
// child: Row(
|
|
||||||
// children: <Widget>[
|
|
||||||
// // Expanded(
|
|
||||||
// // child: DisplayTrainRouteDuration(trainData: trainData,),
|
|
||||||
// // ),
|
|
||||||
// Expanded(child: Container(),),
|
|
||||||
// SizedBox(
|
|
||||||
// height: double.infinity,
|
|
||||||
// child: CupertinoVerticalDivider(),
|
|
||||||
// ),
|
|
||||||
// Expanded(
|
|
||||||
// child: DisplayTrainRouteDistance(trainData: trainData,),
|
|
||||||
// )
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
DisplayTrainStations(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: Container(
|
|
||||||
height: MediaQuery.of(context).viewPadding.bottom,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DisplayTrainID extends StatelessWidget {
|
class DisplayTrainID extends StatelessWidget {
|
||||||
final TrainData trainData;
|
final TrainData trainData;
|
||||||
const DisplayTrainID({required this.trainData, super.key,});
|
const DisplayTrainID({required this.trainData, super.key,});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Center(
|
return SliverToBoxAdapter(
|
||||||
child: Padding(
|
child: Center(
|
||||||
padding: const EdgeInsets.all(8.0),
|
child: Padding(
|
||||||
child: Text.rich(
|
padding: const EdgeInsets.all(8.0),
|
||||||
TextSpan(
|
child: Text.rich(
|
||||||
children: [
|
TextSpan(
|
||||||
TextSpan(
|
children: [
|
||||||
text: trainData.rank,
|
TextSpan(
|
||||||
style: TextStyle(
|
text: trainData.rank,
|
||||||
color: trainData.rank.startsWith('IR') ? const Color.fromARGB(255, 255, 0, 0) : null,
|
style: TextStyle(
|
||||||
|
color: trainData.rank.startsWith('IR') ? const Color.fromARGB(255, 255, 0, 0) : null,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
const TextSpan(text: ' '),
|
||||||
const TextSpan(text: ' '),
|
TextSpan(text: trainData.number,),
|
||||||
TextSpan(text: trainData.number,),
|
],
|
||||||
],
|
),
|
||||||
),
|
style: CupertinoTheme.of(context).textTheme.navLargeTitleTextStyle,
|
||||||
style: CupertinoTheme.of(context).textTheme.navLargeTitleTextStyle,
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -585,39 +428,41 @@ class DisplayTrainRoute extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Row(
|
return SliverToBoxAdapter(
|
||||||
children: <Widget>[
|
child: Row(
|
||||||
Expanded(
|
children: <Widget>[
|
||||||
child: Center(
|
Expanded(
|
||||||
child: Padding(
|
child: Center(
|
||||||
padding: const EdgeInsets.all(4),
|
child: Padding(
|
||||||
child: Text(
|
padding: const EdgeInsets.all(4),
|
||||||
trainData.route.from,
|
child: Text(
|
||||||
style:
|
trainData.route.from,
|
||||||
CupertinoTheme.of(context).textTheme.textStyle.copyWith(
|
style:
|
||||||
fontSize: 16,
|
CupertinoTheme.of(context).textTheme.textStyle.copyWith(
|
||||||
),
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
const Center(child: Text("-")),
|
||||||
const Center(child: Text("-")),
|
Expanded(
|
||||||
Expanded(
|
child: Center(
|
||||||
child: Center(
|
child: Padding(
|
||||||
child: Padding(
|
padding: const EdgeInsets.all(4),
|
||||||
padding: const EdgeInsets.all(4),
|
child: Text(
|
||||||
child: Text(
|
trainData.route.to,
|
||||||
trainData.route.to,
|
style:
|
||||||
style:
|
CupertinoTheme.of(context).textTheme.textStyle.copyWith(
|
||||||
CupertinoTheme.of(context).textTheme.textStyle.copyWith(
|
fontSize: 16,
|
||||||
fontSize: 16,
|
),
|
||||||
),
|
textAlign: TextAlign.right,
|
||||||
textAlign: TextAlign.right,
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -629,13 +474,15 @@ class DisplayTrainOperator extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Center(
|
return SliverToBoxAdapter(
|
||||||
child: Text(
|
child: Center(
|
||||||
trainData.operator,
|
child: Text(
|
||||||
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
|
trainData.operator,
|
||||||
fontSize: 14,
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
|
||||||
fontStyle: FontStyle.italic,
|
fontSize: 14,
|
||||||
),
|
fontStyle: FontStyle.italic,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -648,16 +495,18 @@ class DisplayTrainDeparture extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Padding(
|
return SliverToBoxAdapter(
|
||||||
padding: const EdgeInsets.all(2),
|
child: Padding(
|
||||||
child: Text(
|
padding: const EdgeInsets.all(2),
|
||||||
// "Plecare în ${dataPlecare.day.toString().padLeft(2, '0')}.${dataPlecare.month.toString().padLeft(2, '0')}.${dataPlecare.year.toString().padLeft(4, '0')}",
|
child: Text(
|
||||||
"Plecare în ${trainData.date}",
|
// "Plecare în ${dataPlecare.day.toString().padLeft(2, '0')}.${dataPlecare.month.toString().padLeft(2, '0')}.${dataPlecare.year.toString().padLeft(4, '0')}",
|
||||||
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
|
"Plecare în ${trainData.date}",
|
||||||
fontStyle: FontStyle.italic,
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
|
||||||
fontWeight: FontWeight.w200,
|
fontStyle: FontStyle.italic,
|
||||||
),
|
fontWeight: FontWeight.w200,
|
||||||
textAlign: TextAlign.center,
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -671,86 +520,90 @@ class DisplayTrainLastInfo extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (trainData.status == null) {
|
if (trainData.status == null) {
|
||||||
return Container();
|
return SliverToBoxAdapter(
|
||||||
|
child: Container(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Column(
|
return SliverToBoxAdapter(
|
||||||
mainAxisSize: MainAxisSize.min,
|
child: Column(
|
||||||
children: <Widget>[
|
mainAxisSize: MainAxisSize.min,
|
||||||
Center(
|
children: <Widget>[
|
||||||
child: Padding(
|
Center(
|
||||||
padding: const EdgeInsets.all(2),
|
child: Padding(
|
||||||
child: Text(
|
padding: const EdgeInsets.all(2),
|
||||||
"Ultima informație",
|
child: Text(
|
||||||
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
|
"Ultima informație",
|
||||||
fontSize: 20,
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
|
||||||
fontWeight: FontWeight.bold,
|
fontSize: 20,
|
||||||
),
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
Row(
|
||||||
Row(
|
children: <Widget>[
|
||||||
children: <Widget>[
|
Padding(
|
||||||
Padding(
|
padding: const EdgeInsets.all(4),
|
||||||
padding: const EdgeInsets.all(4),
|
child: Text(
|
||||||
child: Text(
|
trainData.status!.station,
|
||||||
trainData.status!.station,
|
style: CupertinoTheme.of(context).textTheme.textStyle,
|
||||||
style: CupertinoTheme.of(context).textTheme.textStyle,
|
textAlign: TextAlign.left,
|
||||||
textAlign: TextAlign.left,
|
),
|
||||||
),
|
),
|
||||||
),
|
Expanded(
|
||||||
Expanded(
|
child: Container(),
|
||||||
child: Container(),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(4),
|
|
||||||
child: Text(
|
|
||||||
stateToString(trainData.status!.state),
|
|
||||||
style: CupertinoTheme.of(context).textTheme.textStyle,
|
|
||||||
textAlign: TextAlign.right,
|
|
||||||
),
|
),
|
||||||
),
|
Padding(
|
||||||
],
|
padding: const EdgeInsets.all(4),
|
||||||
),
|
child: Text(
|
||||||
// FutureDisplay<DateTime>(
|
stateToString(trainData.status!.state),
|
||||||
// future: trainData.lastInfo.dateAndTime,
|
style: CupertinoTheme.of(context).textTheme.textStyle,
|
||||||
// builder: (context, dt) {
|
textAlign: TextAlign.right,
|
||||||
// return Text(
|
),
|
||||||
// "Raportat în ${dt.day.toString().padLeft(2, '0')}.${dt.month.toString().padLeft(2, '0')}.${dt.year.toString().padLeft(4, '0')}, la ${dt.hour.toString().padLeft(2, '0')}:${dt.minute.toString().padLeft(2, '0')}",
|
),
|
||||||
// textAlign: TextAlign.center,
|
],
|
||||||
// );
|
),
|
||||||
// },
|
// FutureDisplay<DateTime>(
|
||||||
// ),
|
// future: trainData.lastInfo.dateAndTime,
|
||||||
Builder(
|
// builder: (context, dt) {
|
||||||
builder: (context) {
|
// return Text(
|
||||||
final data = trainData.status!.delay;
|
// "Raportat în ${dt.day.toString().padLeft(2, '0')}.${dt.month.toString().padLeft(2, '0')}.${dt.year.toString().padLeft(4, '0')}, la ${dt.hour.toString().padLeft(2, '0')}:${dt.minute.toString().padLeft(2, '0')}",
|
||||||
|
// textAlign: TextAlign.center,
|
||||||
|
// );
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
Builder(
|
||||||
|
builder: (context) {
|
||||||
|
final data = trainData.status!.delay;
|
||||||
|
|
||||||
if (data == 0) {
|
if (data == 0) {
|
||||||
return Container();
|
return Container();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data > 0) {
|
if (data > 0) {
|
||||||
return Text(
|
return Text(
|
||||||
"$data ${data == 1 ? 'minut' : 'minute'} întârziere",
|
"$data ${data == 1 ? 'minut' : 'minute'} întârziere",
|
||||||
style:
|
style:
|
||||||
CupertinoTheme.of(context).textTheme.textStyle.copyWith(
|
CupertinoTheme.of(context).textTheme.textStyle.copyWith(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: CupertinoColors.destructiveRed,
|
color: CupertinoColors.destructiveRed,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return Text(
|
return Text(
|
||||||
"${-data} ${data == -1 ? 'minut' : 'minute'} mai devreme",
|
"${-data} ${data == -1 ? 'minut' : 'minute'} mai devreme",
|
||||||
style:
|
style:
|
||||||
CupertinoTheme.of(context).textTheme.textStyle.copyWith(
|
CupertinoTheme.of(context).textTheme.textStyle.copyWith(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: CupertinoColors.systemGreen,
|
color: CupertinoColors.systemGreen,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:info_tren/components/badge/badge.dart';
|
import 'package:info_tren/components/badge.dart';
|
||||||
import 'package:info_tren/models.dart';
|
import 'package:info_tren/models.dart';
|
||||||
|
|
||||||
class DisplayTrainStation extends StatelessWidget {
|
class DisplayTrainStation extends StatelessWidget {
|
||||||
|
@ -47,7 +47,7 @@ class DisplayTrainStation extends StatelessWidget {
|
||||||
final isOnTime = delay <= 0 && real == true;
|
final isOnTime = delay <= 0 && real == true;
|
||||||
const isNotScheduled = false;
|
const isNotScheduled = false;
|
||||||
|
|
||||||
return Badge(
|
return CupertinoBadge(
|
||||||
text: station.km.toString(),
|
text: station.km.toString(),
|
||||||
caption: 'km',
|
caption: 'km',
|
||||||
isNotScheduled: isNotScheduled,
|
isNotScheduled: isNotScheduled,
|
||||||
|
@ -65,7 +65,7 @@ class DisplayTrainStation extends StatelessWidget {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
child: Align(
|
child: Align(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: station.platform == null ? Container() : Badge(text: station.platform!, caption: 'linia'),
|
child: station.platform == null ? Container() : CupertinoBadge(text: station.platform!, caption: 'linia'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,807 +0,0 @@
|
||||||
import 'package:fluent_ui/fluent_ui.dart';
|
|
||||||
import 'package:flutter/gestures.dart';
|
|
||||||
import 'package:info_tren/models.dart';
|
|
||||||
import 'package:info_tren/pages/station_arrdep_page/view_station/view_station.dart';
|
|
||||||
import 'package:info_tren/pages/train_info_page/view_train/train_info.dart';
|
|
||||||
import 'package:info_tren/pages/train_info_page/view_train/train_info_fluent_DisplayTrainStation.dart';
|
|
||||||
import 'package:info_tren/utils/state_to_string.dart';
|
|
||||||
|
|
||||||
class TrainInfoLoadingFluent extends TrainInfoLoadingShared {
|
|
||||||
TrainInfoLoadingFluent({required super.title, super.loadingText, super.key,});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return NavigationView(
|
|
||||||
appBar: NavigationAppBar(
|
|
||||||
title: Text(title),
|
|
||||||
),
|
|
||||||
content: Center(
|
|
||||||
child: loadingWidget,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class TrainInfoErrorFluent extends TrainInfoErrorShared {
|
|
||||||
const TrainInfoErrorFluent({
|
|
||||||
required super.error,
|
|
||||||
required super.title,
|
|
||||||
super.refresh,
|
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return NavigationView(
|
|
||||||
appBar: NavigationAppBar(
|
|
||||||
title: Text(title),
|
|
||||||
),
|
|
||||||
content: Center(
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Text(error.toString()),
|
|
||||||
if (refresh != null)
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(8),
|
|
||||||
child: Button(
|
|
||||||
child: const Text('Retry'),
|
|
||||||
onPressed: () => refresh!(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class TrainInfoFluent extends TrainInfoShared {
|
|
||||||
const TrainInfoFluent({
|
|
||||||
super.key,
|
|
||||||
required super.trainData,
|
|
||||||
super.isRefreshing,
|
|
||||||
super.refresh,
|
|
||||||
super.onViewYesterdayTrain,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Builder(
|
|
||||||
builder: (context) {
|
|
||||||
return NavigationView(
|
|
||||||
appBar: NavigationAppBar(
|
|
||||||
title: Text(
|
|
||||||
"Informații despre ${trainData.rank} ${trainData.number}",
|
|
||||||
),
|
|
||||||
actions: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
if (refresh != null) ...[
|
|
||||||
Center(
|
|
||||||
child: SizedBox(
|
|
||||||
height: 32,
|
|
||||||
width: 32,
|
|
||||||
child: IconButton(
|
|
||||||
icon: isRefreshing == true ? const ProgressRing() : const Icon(
|
|
||||||
FluentIcons.refresh,
|
|
||||||
size: 24,
|
|
||||||
),
|
|
||||||
onPressed: isRefreshing == true ? null : () {
|
|
||||||
refresh!();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
content: Column(
|
|
||||||
children: <Widget>[
|
|
||||||
Expanded(
|
|
||||||
child: SafeArea(
|
|
||||||
bottom: false,
|
|
||||||
child: TrainInfoBody(
|
|
||||||
trainData: trainData,
|
|
||||||
onViewYesterdayTrain: onViewYesterdayTrain,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class TrainInfoBodyFluent extends TrainInfoBodyShared {
|
|
||||||
const TrainInfoBodyFluent({
|
|
||||||
super.key,
|
|
||||||
required super.trainData,
|
|
||||||
super.onViewYesterdayTrain,
|
|
||||||
super.refresh,
|
|
||||||
super.isRefreshing,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final mq = MediaQuery.of(context);
|
|
||||||
|
|
||||||
if (mq.orientation == Orientation.landscape && mq.size.width >= 1000) {
|
|
||||||
return Row(
|
|
||||||
mainAxisSize: MainAxisSize.max,
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
constraints: const BoxConstraints(
|
|
||||||
minWidth: 400,
|
|
||||||
maxWidth: 400,
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.max,
|
|
||||||
children: [
|
|
||||||
DisplayTrainID(trainData: trainData),
|
|
||||||
DisplayTrainOperator(trainData: trainData),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 2.0),
|
|
||||||
child: DisplayTrainRoute(trainData: trainData),
|
|
||||||
),
|
|
||||||
DisplayTrainDeparture(trainData: trainData),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: DisplayTrainLastInfo(trainData: trainData),
|
|
||||||
),
|
|
||||||
IntrinsicHeight(
|
|
||||||
child: Row(
|
|
||||||
children: <Widget>[
|
|
||||||
Expanded(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: DisplayTrainRouteDuration(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: DisplayTrainRouteDistance(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Divider(),
|
|
||||||
if (onViewYesterdayTrain != null &&
|
|
||||||
trainData.stations.first.departure!.scheduleTime
|
|
||||||
.compareTo(DateTime.now()) >
|
|
||||||
0)
|
|
||||||
...[
|
|
||||||
DisplayTrainYesterdayWarningFluent(
|
|
||||||
onViewYesterdayTrain!,
|
|
||||||
),
|
|
||||||
const Divider(),
|
|
||||||
],
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: CustomScrollView(
|
|
||||||
slivers: [
|
|
||||||
DisplayTrainStations(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: Container(
|
|
||||||
height: MediaQuery
|
|
||||||
.of(context)
|
|
||||||
.viewPadding
|
|
||||||
.bottom,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return CustomScrollView(
|
|
||||||
slivers: <Widget>[
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: DisplayTrainID(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: DisplayTrainOperator(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SliverPadding(
|
|
||||||
padding: const EdgeInsets.only(left: 2, right: 2),
|
|
||||||
sliver: SliverToBoxAdapter(
|
|
||||||
child: DisplayTrainRoute(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: DisplayTrainDeparture(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: DisplayTrainLastInfo(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: IntrinsicHeight(
|
|
||||||
child: Row(
|
|
||||||
children: <Widget>[
|
|
||||||
Expanded(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: DisplayTrainRouteDuration(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: DisplayTrainRouteDistance(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SliverToBoxAdapter(
|
|
||||||
child: Divider(),
|
|
||||||
),
|
|
||||||
if (onViewYesterdayTrain != null &&
|
|
||||||
trainData.stations.first.departure!.scheduleTime
|
|
||||||
.compareTo(DateTime.now()) >
|
|
||||||
0) ...[
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: DisplayTrainYesterdayWarningFluent(
|
|
||||||
onViewYesterdayTrain!),
|
|
||||||
),
|
|
||||||
const SliverToBoxAdapter(
|
|
||||||
child: Divider(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
DisplayTrainStations(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: Container(
|
|
||||||
height: MediaQuery
|
|
||||||
.of(context)
|
|
||||||
.viewPadding
|
|
||||||
.bottom,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DisplayTrainID extends StatelessWidget {
|
|
||||||
final TrainData trainData;
|
|
||||||
|
|
||||||
const DisplayTrainID({required this.trainData, super.key,});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Text.rich(
|
|
||||||
TextSpan(
|
|
||||||
children: [
|
|
||||||
TextSpan(
|
|
||||||
text: trainData.rank,
|
|
||||||
style: TextStyle(
|
|
||||||
color: trainData.rank.startsWith('IR')
|
|
||||||
? const Color.fromARGB(255, 255, 0, 0)
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const TextSpan(text: ' '),
|
|
||||||
TextSpan(
|
|
||||||
text: trainData.number,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
style: FluentTheme.of(context).typography.title?.copyWith(
|
|
||||||
color: FluentTheme.of(context).typography.body?.color,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DisplayTrainOperator extends StatelessWidget {
|
|
||||||
final TrainData trainData;
|
|
||||||
|
|
||||||
const DisplayTrainOperator({required this.trainData, super.key,});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Text(
|
|
||||||
trainData.operator,
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
fontStyle: FontStyle.italic,
|
|
||||||
fontSize: 14,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DisplayTrainRoute extends StatelessWidget {
|
|
||||||
final TrainData trainData;
|
|
||||||
|
|
||||||
const DisplayTrainRoute({required this.trainData, super.key,});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Row(
|
|
||||||
children: <Widget>[
|
|
||||||
Expanded(
|
|
||||||
child: Center(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(4),
|
|
||||||
child: Text(
|
|
||||||
trainData.route.from,
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
fontSize: 16,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Center(child: Text("-")),
|
|
||||||
Expanded(
|
|
||||||
child: Center(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(4),
|
|
||||||
child: Text(
|
|
||||||
trainData.route.to,
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
fontSize: 16,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.right,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DisplayTrainDeparture extends StatelessWidget {
|
|
||||||
final TrainData trainData;
|
|
||||||
|
|
||||||
const DisplayTrainDeparture({required this.trainData, super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.all(2),
|
|
||||||
child: Text(
|
|
||||||
// "Plecare în ${dataPlecare.day.toString().padLeft(2, '0')}.${dataPlecare.month.toString().padLeft(2, '0')}.${dataPlecare.year.toString().padLeft(4, '0')}",
|
|
||||||
"Plecare în ${trainData.date}",
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
fontStyle: FontStyle.italic,
|
|
||||||
fontWeight: FontWeight.w200,
|
|
||||||
fontSize: 16,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DisplayTrainLastInfo extends StatelessWidget {
|
|
||||||
final TrainData trainData;
|
|
||||||
|
|
||||||
const DisplayTrainLastInfo({required this.trainData, super.key,});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
if (trainData.status == null) {
|
|
||||||
return Container();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Card(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(2),
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: <Widget>[
|
|
||||||
Center(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(2),
|
|
||||||
child: Text(
|
|
||||||
"Ultima informație",
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
fontSize: 22,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Row(
|
|
||||||
children: <Widget>[
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(4),
|
|
||||||
child: Text(
|
|
||||||
trainData.status!.station,
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
fontSize: 18,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.left,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Container(),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(4),
|
|
||||||
child: Text(
|
|
||||||
stateToString(trainData.status!.state),
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
fontSize: 18,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.right,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(2),
|
|
||||||
child: Row(
|
|
||||||
children: <Widget>[
|
|
||||||
Expanded(
|
|
||||||
child: Container(),
|
|
||||||
),
|
|
||||||
Builder(
|
|
||||||
builder: (context) {
|
|
||||||
final data = trainData.status!.delay;
|
|
||||||
if (data == 0) {
|
|
||||||
return Container();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data > 0) {
|
|
||||||
return Text(
|
|
||||||
"$data ${data == 1 ? 'minut' : 'minute'} întârziere",
|
|
||||||
style:
|
|
||||||
FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
fontSize: 16,
|
|
||||||
color: Colors.red.lighter,
|
|
||||||
// color: Colors.red.shade300,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return Text(
|
|
||||||
"${-data} ${data == -1 ? 'minut' : 'minute'} mai devreme",
|
|
||||||
style:
|
|
||||||
FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
fontSize: 16,
|
|
||||||
color: Colors.green.lighter,
|
|
||||||
// color: Colors.green.shade300,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DisplayTrainDestination extends StatelessWidget {
|
|
||||||
final TrainData trainData;
|
|
||||||
|
|
||||||
const DisplayTrainDestination({required this.trainData, super.key,});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final destination = trainData.stations.last;
|
|
||||||
|
|
||||||
return Card(
|
|
||||||
child: Center(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(2),
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: <Widget>[
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(4),
|
|
||||||
child: Text(
|
|
||||||
"Destinația",
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
fontSize: 22,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.fromLTRB(4, 0, 4, 0),
|
|
||||||
child: Text(
|
|
||||||
destination.name,
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Builder(
|
|
||||||
builder: (context) {
|
|
||||||
final arrival = destination.arrival!.scheduleTime.toLocal();
|
|
||||||
final delay =
|
|
||||||
trainData.stations.last.arrival!.status?.delay ?? 0;
|
|
||||||
final arrivalWithDelay =
|
|
||||||
arrival.add(Duration(minutes: delay));
|
|
||||||
final arrivalWithDelayString =
|
|
||||||
'${arrivalWithDelay.hour}:${arrivalWithDelay.minute.toString().padLeft(2, "0")}';
|
|
||||||
// const months = ["ian", "feb", "mar", "apr", "mai", "iun", "iul", "aug", "sep", "oct", "noi", "dec"];
|
|
||||||
|
|
||||||
return Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: <Widget>[
|
|
||||||
// Text(
|
|
||||||
// "în ${arrival.day} ${months[arrival.month - 1]} ${arrival.year}",
|
|
||||||
// style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
|
||||||
// fontSize: isSmallScreen(context) ? 12 : 14,
|
|
||||||
// ),
|
|
||||||
// textAlign: TextAlign.center,
|
|
||||||
// ),
|
|
||||||
Text.rich(
|
|
||||||
TextSpan(
|
|
||||||
text: 'la',
|
|
||||||
children: [
|
|
||||||
const TextSpan(text: ' '),
|
|
||||||
TextSpan(
|
|
||||||
text:
|
|
||||||
'${arrival.hour.toString().padLeft(2, '0')}:${arrival.minute.toString().padLeft(2, '0')}',
|
|
||||||
style: delay == 0
|
|
||||||
? null
|
|
||||||
: const TextStyle(
|
|
||||||
decoration: TextDecoration.lineThrough,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (delay != 0) ...[
|
|
||||||
const TextSpan(text: ' '),
|
|
||||||
TextSpan(
|
|
||||||
text: arrivalWithDelayString,
|
|
||||||
style: TextStyle(
|
|
||||||
color: delay > 0
|
|
||||||
? Colors.red.lighter
|
|
||||||
: Colors.green.lighter,
|
|
||||||
// color: delay > 0
|
|
||||||
// ? Colors.red.shade300
|
|
||||||
// : Colors.green.shade300,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
],
|
|
||||||
),
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
fontSize: 16,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DisplayTrainRouteDistance extends StatelessWidget {
|
|
||||||
final TrainData trainData;
|
|
||||||
|
|
||||||
const DisplayTrainRouteDistance({required this.trainData, super.key,});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Card(
|
|
||||||
child: Center(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(2),
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: <Widget>[
|
|
||||||
Text(
|
|
||||||
"Distanța rutei",
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
fontSize: 22,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
"${trainData.stations.last.km} km",
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
fontSize: 20,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DisplayTrainRouteDuration extends StatelessWidget {
|
|
||||||
final TrainData trainData;
|
|
||||||
|
|
||||||
const DisplayTrainRouteDuration({required this.trainData, super.key,});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Card(
|
|
||||||
child: Center(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(2),
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: <Widget>[
|
|
||||||
Text(
|
|
||||||
"Durata rutei",
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
fontSize: 22,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
Builder(
|
|
||||||
builder: (context) {
|
|
||||||
var duration = trainData.stations.last.arrival!.scheduleTime
|
|
||||||
.difference(
|
|
||||||
trainData.stations.first.departure!.scheduleTime);
|
|
||||||
var durationString = StringBuffer();
|
|
||||||
|
|
||||||
bool firstWritten = false;
|
|
||||||
|
|
||||||
if (duration.inDays > 0) {
|
|
||||||
firstWritten = true;
|
|
||||||
if (duration.inDays == 1) {
|
|
||||||
durationString.write("1 zi");
|
|
||||||
} else {
|
|
||||||
durationString.write("${duration.inDays} zile");
|
|
||||||
}
|
|
||||||
duration -= Duration(days: duration.inDays);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (duration.inHours > 0) {
|
|
||||||
if (firstWritten) {
|
|
||||||
durationString.write(", ");
|
|
||||||
}
|
|
||||||
firstWritten = true;
|
|
||||||
if (duration.inHours == 1) {
|
|
||||||
durationString.write("1 oră");
|
|
||||||
} else {
|
|
||||||
durationString.write("${duration.inHours} ore");
|
|
||||||
}
|
|
||||||
duration -= Duration(hours: duration.inHours);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (duration.inMinutes > 0) {
|
|
||||||
if (firstWritten) {
|
|
||||||
durationString.write(", ");
|
|
||||||
}
|
|
||||||
firstWritten = true;
|
|
||||||
if (duration.inMinutes == 1) {
|
|
||||||
durationString.write("1 minut");
|
|
||||||
} else {
|
|
||||||
durationString.write("${duration.inMinutes} minute");
|
|
||||||
}
|
|
||||||
duration -= Duration(minutes: duration.inMinutes);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Text(
|
|
||||||
durationString.toString(),
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
fontSize: 20,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DisplayTrainYesterdayWarningFluent
|
|
||||||
extends DisplayTrainYesterdayWarningCommon {
|
|
||||||
const DisplayTrainYesterdayWarningFluent(super.onViewYesterdayTrain, {super.key,});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Text.rich(
|
|
||||||
TextSpan(
|
|
||||||
children: [
|
|
||||||
const TextSpan(
|
|
||||||
text: DisplayTrainYesterdayWarningCommon.trainDidNotDepart,
|
|
||||||
),
|
|
||||||
const TextSpan(text: '\n'),
|
|
||||||
TextSpan(
|
|
||||||
text: DisplayTrainYesterdayWarningCommon.seeYesterdayTrain,
|
|
||||||
style: TextStyle(
|
|
||||||
color: Colors.blue,
|
|
||||||
),
|
|
||||||
recognizer: TapGestureRecognizer()
|
|
||||||
..onTap = onViewYesterdayTrain,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DisplayTrainStations extends StatelessWidget {
|
|
||||||
final TrainData trainData;
|
|
||||||
const DisplayTrainStations({required this.trainData, super.key,});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return SliverList(
|
|
||||||
delegate: SliverChildBuilderDelegate(
|
|
||||||
(context, index) {
|
|
||||||
return IndexedSemantics(
|
|
||||||
index: index,
|
|
||||||
child: DisplayTrainStation(
|
|
||||||
station: trainData.stations[index],
|
|
||||||
onTap: () {
|
|
||||||
Navigator.of(context).pushNamed(
|
|
||||||
ViewStationPage.routeName,
|
|
||||||
arguments: ViewStationArguments(stationName: trainData.stations[index].name),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
childCount: trainData.stations.length,
|
|
||||||
addSemanticIndexes: true,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,447 +0,0 @@
|
||||||
import 'package:fluent_ui/fluent_ui.dart';
|
|
||||||
import 'package:info_tren/components/badge/badge.dart';
|
|
||||||
import 'package:info_tren/models.dart';
|
|
||||||
|
|
||||||
class DisplayTrainStation extends StatelessWidget {
|
|
||||||
final Station station;
|
|
||||||
final void Function()? onTap;
|
|
||||||
|
|
||||||
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,
|
|
||||||
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,
|
|
||||||
),
|
|
||||||
Delay(
|
|
||||||
station: station,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Title extends StatelessWidget {
|
|
||||||
final Station station;
|
|
||||||
|
|
||||||
const Title({
|
|
||||||
required this.station,
|
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Text(
|
|
||||||
station.name,
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
fontSize: 22,
|
|
||||||
fontWeight: MediaQuery.of(context).boldText ? FontWeight.w500 : FontWeight.w300,
|
|
||||||
// fontStyle: items[1] == "ONI" ? FontStyle.italic : FontStyle.normal,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Time extends StatelessWidget {
|
|
||||||
final Station station;
|
|
||||||
|
|
||||||
const Time({
|
|
||||||
required this.station,
|
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
if (station.arrival == null) {
|
|
||||||
// Plecare
|
|
||||||
return DepartureTime(
|
|
||||||
station: station,
|
|
||||||
firstStation: true,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (station.departure == null) {
|
|
||||||
// Sosire
|
|
||||||
return ArrivalTime(
|
|
||||||
station: station,
|
|
||||||
finalStation: true,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: <Widget>[
|
|
||||||
Text(
|
|
||||||
"→",
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
fontSize: 22,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Container(width: 2,),
|
|
||||||
ArrivalTime(station: station,),
|
|
||||||
Expanded(child: Container(),),
|
|
||||||
StopTime(station: station,),
|
|
||||||
Expanded(child: Container(),),
|
|
||||||
DepartureTime(station: station,),
|
|
||||||
Container(width: 2,),
|
|
||||||
Text(
|
|
||||||
"→",
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
fontSize: 22,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ArrivalTime extends StatelessWidget {
|
|
||||||
final Station station;
|
|
||||||
final bool finalStation;
|
|
||||||
|
|
||||||
const ArrivalTime({
|
|
||||||
required this.station,
|
|
||||||
this.finalStation = false,
|
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
if (station.arrival == null) {
|
|
||||||
return Container();
|
|
||||||
}
|
|
||||||
if (finalStation) {
|
|
||||||
return Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: <Widget>[
|
|
||||||
Text(
|
|
||||||
"→",
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
fontSize: 22,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Container(width: 2,),
|
|
||||||
const Text("sosire la "),
|
|
||||||
ArrivalTime(station: station,),
|
|
||||||
Expanded(child: Container(),),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
final delay = station.arrival!.status?.delay ?? 0;
|
|
||||||
final time = station.arrival!.scheduleTime.toLocal();
|
|
||||||
|
|
||||||
if (delay == 0) {
|
|
||||||
return Text("${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}");
|
|
||||||
}
|
|
||||||
else if (delay > 0) {
|
|
||||||
final oldDate = time;
|
|
||||||
final newDate = oldDate.add(Duration(minutes: delay));
|
|
||||||
|
|
||||||
return Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: <Widget>[
|
|
||||||
Text(
|
|
||||||
"${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
decoration: TextDecoration.lineThrough,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
"${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}",
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
// color: Colors.red.shade300,
|
|
||||||
color: Colors.red.lighter,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
final oldDate = time;
|
|
||||||
final newDate = oldDate.add(Duration(minutes: delay));
|
|
||||||
|
|
||||||
return Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: <Widget>[
|
|
||||||
Text(
|
|
||||||
"${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
decoration: TextDecoration.lineThrough,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
"${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}",
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
// color: Colors.green.shade300,
|
|
||||||
color: Colors.green.lighter,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class StopTime extends StatelessWidget {
|
|
||||||
final Station station;
|
|
||||||
|
|
||||||
const StopTime({
|
|
||||||
required this.station,
|
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: <Widget>[
|
|
||||||
const Text(
|
|
||||||
"staționează pentru",
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
Builder(
|
|
||||||
builder: (context) {
|
|
||||||
int stopsForInt = station.stoppingTime!;
|
|
||||||
bool minutes = false;
|
|
||||||
if (stopsForInt >= 60) {
|
|
||||||
stopsForInt ~/= 60;
|
|
||||||
minutes = true;
|
|
||||||
}
|
|
||||||
if (stopsForInt == 1) {
|
|
||||||
return Text(
|
|
||||||
"1 ${minutes ? 'minut' : 'secundă'}",
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if (stopsForInt < 20) {
|
|
||||||
return Text(
|
|
||||||
"$stopsForInt ${minutes ? 'minute' : 'secunde'}",
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return Text(
|
|
||||||
"$stopsForInt de ${minutes ? 'minute' : 'secunde'}",
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DepartureTime extends StatelessWidget {
|
|
||||||
final Station station;
|
|
||||||
final bool firstStation;
|
|
||||||
|
|
||||||
const DepartureTime({
|
|
||||||
required this.station,
|
|
||||||
this.firstStation = false,
|
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
if (station.departure == null) {
|
|
||||||
return Container();
|
|
||||||
}
|
|
||||||
if (firstStation) {
|
|
||||||
return Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: <Widget>[
|
|
||||||
Expanded(child: Container(),),
|
|
||||||
const Text("plecare la "),
|
|
||||||
DepartureTime(station: station,),
|
|
||||||
Container(width: 2,),
|
|
||||||
Text(
|
|
||||||
"→",
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
fontSize: 22,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
final delay = station.departure!.status?.delay ?? 0;
|
|
||||||
final time = station.departure!.scheduleTime.toLocal();
|
|
||||||
|
|
||||||
if (delay == 0) {
|
|
||||||
return Text("${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}");
|
|
||||||
}
|
|
||||||
else if (delay > 0) {
|
|
||||||
final oldDate = time;
|
|
||||||
final newDate = oldDate.add(Duration(minutes: delay));
|
|
||||||
|
|
||||||
return Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: <Widget>[
|
|
||||||
Text(
|
|
||||||
"${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
decoration: TextDecoration.lineThrough,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
"${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}",
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
// color: Colors.red.shade300,
|
|
||||||
color: Colors.red.lighter,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
final oldDate = time;
|
|
||||||
final newDate = oldDate.add(Duration(minutes: delay));
|
|
||||||
|
|
||||||
return Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: <Widget>[
|
|
||||||
Text(
|
|
||||||
"${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
decoration: TextDecoration.lineThrough,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
"${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}",
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
// color: Colors.green.shade300,
|
|
||||||
color: Colors.green.lighter,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class Delay extends StatelessWidget {
|
|
||||||
final Station station;
|
|
||||||
|
|
||||||
const Delay({
|
|
||||||
required this.station,
|
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
if (station.arrival?.status == null && station.departure?.status == null) {
|
|
||||||
return Container();
|
|
||||||
}
|
|
||||||
var delay = station.arrival?.status?.delay;
|
|
||||||
if (station.departure?.status?.real == true) {
|
|
||||||
delay = station.departure?.status?.delay;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (delay == 0 || delay == null) {
|
|
||||||
return Container();
|
|
||||||
} else if (delay > 0) {
|
|
||||||
return Text(
|
|
||||||
"$delay ${delay == 1 ? 'minut' : 'minute'} întârziere",
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
// color: Colors.red.shade300,
|
|
||||||
color: Colors.red.lighter,
|
|
||||||
fontSize: 14,
|
|
||||||
fontStyle: FontStyle.italic,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if (delay < 0) {
|
|
||||||
return Text(
|
|
||||||
"${-delay} ${delay == -1 ? 'minut' : 'minute'} mai devreme",
|
|
||||||
style: FluentTheme.of(context).typography.body?.copyWith(
|
|
||||||
// color: Colors.green.shade300,
|
|
||||||
color: Colors.green.lighter,
|
|
||||||
fontSize: 14,
|
|
||||||
fontStyle: FontStyle.italic,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Container();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -7,7 +7,7 @@ import 'package:info_tren/pages/train_info_page/view_train/train_info.dart';
|
||||||
import 'package:info_tren/pages/train_info_page/view_train/train_info_material_DisplayTrainStation.dart';
|
import 'package:info_tren/pages/train_info_page/view_train/train_info_material_DisplayTrainStation.dart';
|
||||||
import 'package:info_tren/utils/state_to_string.dart';
|
import 'package:info_tren/utils/state_to_string.dart';
|
||||||
|
|
||||||
class TrainInfoLoadingMaterial extends TrainInfoLoadingShared {
|
class TrainInfoLoadingMaterial extends TrainInfoLoading {
|
||||||
TrainInfoLoadingMaterial({required super.title, super.loadingText, super.key,});
|
TrainInfoLoadingMaterial({required super.title, super.loadingText, super.key,});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -24,7 +24,7 @@ class TrainInfoLoadingMaterial extends TrainInfoLoadingShared {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TrainInfoErrorMaterial extends TrainInfoErrorShared {
|
class TrainInfoErrorMaterial extends TrainInfoError {
|
||||||
const TrainInfoErrorMaterial({
|
const TrainInfoErrorMaterial({
|
||||||
required super.error,
|
required super.error,
|
||||||
required super.title,
|
required super.title,
|
||||||
|
@ -61,12 +61,15 @@ class TrainInfoErrorMaterial extends TrainInfoErrorShared {
|
||||||
bool isSmallScreen(BuildContext context) =>
|
bool isSmallScreen(BuildContext context) =>
|
||||||
MediaQuery.of(context).size.height <= 425;
|
MediaQuery.of(context).size.height <= 425;
|
||||||
|
|
||||||
class TrainInfoMaterial extends TrainInfoShared {
|
class TrainInfoMaterial extends StatelessWidget {
|
||||||
|
final TrainData trainData;
|
||||||
|
final Future Function()? refresh;
|
||||||
|
final void Function()? onViewYesterdayTrain;
|
||||||
|
|
||||||
const TrainInfoMaterial({
|
const TrainInfoMaterial({
|
||||||
required super.trainData,
|
required this.trainData,
|
||||||
super.refresh,
|
this.refresh,
|
||||||
super.onViewYesterdayTrain,
|
this.onViewYesterdayTrain,
|
||||||
super.isRefreshing,
|
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -76,13 +79,12 @@ class TrainInfoMaterial extends TrainInfoShared {
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: isSmallScreen(context)
|
appBar: isSmallScreen(context)
|
||||||
? null
|
? null
|
||||||
: AppBar(
|
: AppBar(
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
title: Text(
|
title: Text(
|
||||||
"Informații despre ${trainData.rank} ${trainData.number}",
|
"Informații despre ${trainData.rank} ${trainData.number}"),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
body: Column(
|
body: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
if (isSmallScreen(context))
|
if (isSmallScreen(context))
|
||||||
|
@ -91,8 +93,8 @@ class TrainInfoMaterial extends TrainInfoShared {
|
||||||
left: false,
|
left: false,
|
||||||
right: false,
|
right: false,
|
||||||
child: SlimAppBar(
|
child: SlimAppBar(
|
||||||
title: 'INFO TREN - ${trainData.rank} ${trainData.number}',
|
title:
|
||||||
),
|
'INFO TREN - ${trainData.rank} ${trainData.number}'),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: SafeArea(
|
child: SafeArea(
|
||||||
|
@ -100,9 +102,102 @@ class TrainInfoMaterial extends TrainInfoShared {
|
||||||
top: isSmallScreen(context) ? false : true,
|
top: isSmallScreen(context) ? false : true,
|
||||||
child: RefreshIndicator(
|
child: RefreshIndicator(
|
||||||
onRefresh: refresh ?? () async {},
|
onRefresh: refresh ?? () async {},
|
||||||
child: TrainInfoBody(
|
child: CustomScrollView(
|
||||||
trainData: trainData,
|
slivers: <Widget>[
|
||||||
onViewYesterdayTrain: onViewYesterdayTrain,
|
SliverToBoxAdapter(
|
||||||
|
child: DisplayTrainID(
|
||||||
|
trainData: trainData,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: DisplayTrainOperator(
|
||||||
|
trainData: trainData,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SliverPadding(
|
||||||
|
padding: const EdgeInsets.only(left: 2, right: 2),
|
||||||
|
sliver: SliverToBoxAdapter(
|
||||||
|
child: DisplayTrainRoute(
|
||||||
|
trainData: trainData,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: DisplayTrainDeparture(
|
||||||
|
trainData: trainData,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// SliverToBoxAdapter(
|
||||||
|
// child: Divider(
|
||||||
|
// color: Colors.white70,
|
||||||
|
// height: isSmallScreen(context) ? 8 : 16,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: DisplayTrainLastInfo(
|
||||||
|
trainData: trainData,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: IntrinsicHeight(
|
||||||
|
child: Row(
|
||||||
|
children: <Widget>[
|
||||||
|
// Expanded(child: DisplayTrainNextStop(trainData: trainData,)),
|
||||||
|
// Expanded(child: DisplayTrainDestination(trainData: trainData,)),
|
||||||
|
Expanded(
|
||||||
|
child: DisplayTrainRouteDuration(
|
||||||
|
trainData: trainData,
|
||||||
|
)),
|
||||||
|
Expanded(
|
||||||
|
child: DisplayTrainRouteDistance(
|
||||||
|
trainData: trainData,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// SliverToBoxAdapter(
|
||||||
|
// child: IntrinsicHeight(
|
||||||
|
// child: Row(
|
||||||
|
// children: <Widget>[
|
||||||
|
// // Expanded(child: DisplayTrainRouteDuration(trainData: trainData,)),
|
||||||
|
// Expanded(child: Container(),),
|
||||||
|
// Expanded(child: DisplayTrainRouteDistance(trainData: trainData,)),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: Divider(
|
||||||
|
color: Colors.white70,
|
||||||
|
height: isSmallScreen(context) ? 8 : 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (onViewYesterdayTrain != null &&
|
||||||
|
trainData.stations.first.departure!.scheduleTime
|
||||||
|
.compareTo(DateTime.now()) >
|
||||||
|
0) ...[
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: DisplayTrainYesterdayWarningMaterial(
|
||||||
|
onViewYesterdayTrain!),
|
||||||
|
),
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: Divider(
|
||||||
|
color: Colors.white70,
|
||||||
|
height: isSmallScreen(context) ? 8 : 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
DisplayTrainStations(
|
||||||
|
trainData: trainData,
|
||||||
|
),
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: Container(
|
||||||
|
height: MediaQuery.of(context).viewPadding.bottom,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -115,201 +210,6 @@ class TrainInfoMaterial extends TrainInfoShared {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TrainInfoBodyMaterial extends TrainInfoBodyShared {
|
|
||||||
const TrainInfoBodyMaterial({
|
|
||||||
super.key,
|
|
||||||
required super.trainData,
|
|
||||||
super.onViewYesterdayTrain,
|
|
||||||
super.isRefreshing,
|
|
||||||
super.refresh,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final mq = MediaQuery.of(context);
|
|
||||||
|
|
||||||
if (mq.orientation == Orientation.landscape && mq.size.width >= 1000) {
|
|
||||||
return Row(
|
|
||||||
mainAxisSize: MainAxisSize.max,
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
constraints: const BoxConstraints(
|
|
||||||
minWidth: 400,
|
|
||||||
maxWidth: 400,
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.max,
|
|
||||||
children: [
|
|
||||||
DisplayTrainID(trainData: trainData),
|
|
||||||
DisplayTrainOperator(trainData: trainData),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 2.0),
|
|
||||||
child: DisplayTrainRoute(trainData: trainData),
|
|
||||||
),
|
|
||||||
DisplayTrainDeparture(trainData: trainData),
|
|
||||||
DisplayTrainLastInfo(trainData: trainData),
|
|
||||||
IntrinsicHeight(
|
|
||||||
child: Row(
|
|
||||||
children: <Widget>[
|
|
||||||
Expanded(
|
|
||||||
child: DisplayTrainRouteDuration(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: DisplayTrainRouteDistance(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Divider(
|
|
||||||
color: Colors.white70,
|
|
||||||
height: isSmallScreen(context) ? 8 : 16,
|
|
||||||
),
|
|
||||||
if (onViewYesterdayTrain != null &&
|
|
||||||
trainData.stations.first.departure!.scheduleTime
|
|
||||||
.compareTo(DateTime.now()) >
|
|
||||||
0)
|
|
||||||
...[
|
|
||||||
DisplayTrainYesterdayWarningMaterial(
|
|
||||||
onViewYesterdayTrain!,
|
|
||||||
),
|
|
||||||
Divider(
|
|
||||||
color: Colors.white70,
|
|
||||||
height: isSmallScreen(context) ? 8 : 16,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: CustomScrollView(
|
|
||||||
slivers: [
|
|
||||||
DisplayTrainStations(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: Container(
|
|
||||||
height: MediaQuery
|
|
||||||
.of(context)
|
|
||||||
.viewPadding
|
|
||||||
.bottom,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return CustomScrollView(
|
|
||||||
slivers: <Widget>[
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: DisplayTrainID(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: DisplayTrainOperator(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SliverPadding(
|
|
||||||
padding: const EdgeInsets.only(left: 2, right: 2),
|
|
||||||
sliver: SliverToBoxAdapter(
|
|
||||||
child: DisplayTrainRoute(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: DisplayTrainDeparture(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
// SliverToBoxAdapter(
|
|
||||||
// child: Divider(
|
|
||||||
// color: Colors.white70,
|
|
||||||
// height: isSmallScreen(context) ? 8 : 16,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: DisplayTrainLastInfo(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: IntrinsicHeight(
|
|
||||||
child: Row(
|
|
||||||
children: <Widget>[
|
|
||||||
// Expanded(child: DisplayTrainNextStop(trainData: trainData,)),
|
|
||||||
// Expanded(child: DisplayTrainDestination(trainData: trainData,)),
|
|
||||||
Expanded(
|
|
||||||
child: DisplayTrainRouteDuration(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: DisplayTrainRouteDistance(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
// SliverToBoxAdapter(
|
|
||||||
// child: IntrinsicHeight(
|
|
||||||
// child: Row(
|
|
||||||
// children: <Widget>[
|
|
||||||
// // Expanded(child: DisplayTrainRouteDuration(trainData: trainData,)),
|
|
||||||
// Expanded(child: Container(),),
|
|
||||||
// Expanded(child: DisplayTrainRouteDistance(trainData: trainData,)),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: Divider(
|
|
||||||
color: Colors.white70,
|
|
||||||
height: isSmallScreen(context) ? 8 : 16,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (onViewYesterdayTrain != null &&
|
|
||||||
trainData.stations.first.departure!.scheduleTime
|
|
||||||
.compareTo(DateTime.now()) >
|
|
||||||
0) ...[
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: DisplayTrainYesterdayWarningMaterial(
|
|
||||||
onViewYesterdayTrain!),
|
|
||||||
),
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: Divider(
|
|
||||||
color: Colors.white70,
|
|
||||||
height: isSmallScreen(context) ? 8 : 16,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
DisplayTrainStations(
|
|
||||||
trainData: trainData,
|
|
||||||
),
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: Container(
|
|
||||||
height: MediaQuery
|
|
||||||
.of(context)
|
|
||||||
.viewPadding
|
|
||||||
.bottom,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DisplayTrainID extends StatelessWidget {
|
class DisplayTrainID extends StatelessWidget {
|
||||||
final TrainData trainData;
|
final TrainData trainData;
|
||||||
|
|
||||||
|
@ -898,7 +798,7 @@ class DisplayTrainStations extends StatelessWidget {
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(context).pushNamed(
|
Navigator.of(context).pushNamed(
|
||||||
ViewStationPage.routeName,
|
ViewStationPage.routeName,
|
||||||
arguments: ViewStationArguments(stationName: trainData.stations[index].name),
|
arguments: trainData.stations[index].name,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:info_tren/models.dart';
|
import 'package:info_tren/models.dart';
|
||||||
import 'package:info_tren/components/badge/badge.dart';
|
import 'package:info_tren/components/badge.dart';
|
||||||
import 'package:info_tren/pages/train_info_page/view_train/train_info_material.dart';
|
import 'package:info_tren/pages/train_info_page/view_train/train_info_material.dart';
|
||||||
|
|
||||||
class DisplayTrainStation extends StatelessWidget {
|
class DisplayTrainStation extends StatelessWidget {
|
||||||
|
@ -54,7 +54,7 @@ class DisplayTrainStation extends StatelessWidget {
|
||||||
final isOnTime = delay <= 0 && real == true;
|
final isOnTime = delay <= 0 && real == true;
|
||||||
const isNotScheduled = false;
|
const isNotScheduled = false;
|
||||||
|
|
||||||
return Badge(
|
return MaterialBadge(
|
||||||
text: station.km.toString(),
|
text: station.km.toString(),
|
||||||
caption: 'km',
|
caption: 'km',
|
||||||
isNotScheduled: isNotScheduled,
|
isNotScheduled: isNotScheduled,
|
||||||
|
@ -74,7 +74,7 @@ class DisplayTrainStation extends StatelessWidget {
|
||||||
? Container()
|
? Container()
|
||||||
: Align(
|
: Align(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: Badge(text: station.platform!, caption: 'linia',),
|
child: MaterialBadge(text: station.platform!, caption: 'linia',),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import 'dart:async';
|
|
||||||
|
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:info_tren/api/station_data.dart';
|
import 'package:info_tren/api/station_data.dart';
|
||||||
import 'package:info_tren/models.dart';
|
import 'package:info_tren/models.dart';
|
||||||
|
@ -34,18 +32,7 @@ final trainInfoArgumentsProvider = Provider<TrainInfoArguments>(
|
||||||
(_) => throw UnimplementedError('Please override in ProviderScope'),
|
(_) => throw UnimplementedError('Please override in ProviderScope'),
|
||||||
);
|
);
|
||||||
|
|
||||||
final stationDataProvider = FutureProvider.family((ref, String stationName) async {
|
final stationDataProvider = FutureProvider.family((ref, String stationName) => getStationData(stationName));
|
||||||
final data = await getStationData(stationName);
|
|
||||||
|
|
||||||
final timer = Timer(const Duration(minutes: 2), () {
|
|
||||||
ref.invalidateSelf();
|
|
||||||
});
|
|
||||||
ref.onDispose(() {
|
|
||||||
timer.cancel();
|
|
||||||
});
|
|
||||||
|
|
||||||
return data;
|
|
||||||
});
|
|
||||||
final viewStationArgumentsProvider = Provider<ViewStationArguments>(
|
final viewStationArgumentsProvider = Provider<ViewStationArguments>(
|
||||||
(_) => throw UnimplementedError('Please override in ProviderScope'),
|
(_) => throw UnimplementedError('Please override in ProviderScope'),
|
||||||
);
|
);
|
||||||
|
@ -53,4 +40,4 @@ final viewStationDataProvider = Provider((ref) {
|
||||||
final args = ref.watch(viewStationArgumentsProvider);
|
final args = ref.watch(viewStationArgumentsProvider);
|
||||||
final data = ref.watch(stationDataProvider(args.stationName));
|
final data = ref.watch(stationDataProvider(args.stationName));
|
||||||
return data;
|
return data;
|
||||||
}, dependencies: [viewStationArgumentsProvider, stationDataProvider]);
|
});
|
||||||
|
|
|
@ -6,9 +6,6 @@ UiDesign get defaultUiDesign {
|
||||||
if (Platform.isIOS) {
|
if (Platform.isIOS) {
|
||||||
return UiDesign.CUPERTINO;
|
return UiDesign.CUPERTINO;
|
||||||
}
|
}
|
||||||
else if (Platform.isLinux || Platform.isWindows) {
|
|
||||||
return UiDesign.FLUENT;
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
return UiDesign.MATERIAL;
|
return UiDesign.MATERIAL;
|
||||||
}
|
}
|
||||||
|
|
44
pubspec.lock
44
pubspec.lock
|
@ -99,13 +99,6 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.1"
|
version: "2.0.1"
|
||||||
clock:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: clock
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.1.1"
|
|
||||||
code_builder:
|
code_builder:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -169,13 +162,6 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.1"
|
version: "1.0.1"
|
||||||
fluent_ui:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: fluent_ui
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "4.0.3+1"
|
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
|
@ -195,11 +181,6 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.1"
|
version: "2.0.1"
|
||||||
flutter_localizations:
|
|
||||||
dependency: transitive
|
|
||||||
description: flutter
|
|
||||||
source: sdk
|
|
||||||
version: "0.0.0"
|
|
||||||
flutter_riverpod:
|
flutter_riverpod:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -275,13 +256,6 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.2"
|
version: "4.0.2"
|
||||||
intl:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: intl
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.17.0"
|
|
||||||
io:
|
io:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -337,7 +311,7 @@ packages:
|
||||||
name: material_color_utilities
|
name: material_color_utilities
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.5"
|
version: "0.2.0"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -450,13 +424,6 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.0"
|
version: "3.1.0"
|
||||||
recase:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: recase
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "4.1.0"
|
|
||||||
riverpod:
|
riverpod:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -464,13 +431,6 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.2"
|
version: "2.0.2"
|
||||||
scroll_pos:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: scroll_pos
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.3.0"
|
|
||||||
shared_preferences:
|
shared_preferences:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -699,7 +659,7 @@ packages:
|
||||||
name: vector_math
|
name: vector_math
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.2"
|
version: "2.1.4"
|
||||||
watcher:
|
watcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -11,7 +11,7 @@ description: O aplicație de vizualizare a datelor puse la dispoziție de Inform
|
||||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||||
# Read more about iOS versioning at
|
# Read more about iOS versioning at
|
||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
version: 2.7.9
|
version: 2.7.8
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.17.0 <3.0.0"
|
sdk: ">=2.17.0 <3.0.0"
|
||||||
|
@ -33,7 +33,6 @@ dependencies:
|
||||||
freezed_annotation: ^2.2.0
|
freezed_annotation: ^2.2.0
|
||||||
json_annotation: ^4.7.0
|
json_annotation: ^4.7.0
|
||||||
shared_preferences: ^2.0.15
|
shared_preferences: ^2.0.15
|
||||||
fluent_ui: ^4.0.3+1
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
# flutter_test:
|
# flutter_test:
|
||||||
|
|
Loading…
Add table
Reference in a new issue