Browse Source

Migrate uiDesign to Riverpod

master
Kenneth Bruen 2 years ago
parent
commit
240812e261
Signed by: kbruen
GPG Key ID: C1980A470C3EE5B1
  1. 12
      lib/components/loading/loading.dart
  2. 38
      lib/components/refresh_future_builder.dart
  3. 68
      lib/components/select_train_suggestions/select_train_suggestions.dart
  4. 9
      lib/components/select_train_suggestions/select_train_suggestions_cupertino.dart
  5. 9
      lib/components/select_train_suggestions/select_train_suggestions_material.dart
  6. 55
      lib/main.dart
  7. 23
      lib/pages/about/about_page.dart
  8. 7
      lib/pages/about/about_page_cupertino.dart
  9. 7
      lib/pages/about/about_page_material.dart
  10. 13
      lib/pages/main/main_page.dart
  11. 28
      lib/pages/station_arrdep_page/select_station/select_station.dart
  12. 7
      lib/pages/station_arrdep_page/select_station/select_station_cupertino.dart
  13. 7
      lib/pages/station_arrdep_page/select_station/select_station_material.dart
  14. 79
      lib/pages/station_arrdep_page/view_station/view_station.dart
  15. 27
      lib/pages/station_arrdep_page/view_station/view_station_cupertino.dart
  16. 27
      lib/pages/station_arrdep_page/view_station/view_station_material.dart
  17. 41
      lib/pages/train_info_page/select_train/select_train.dart
  18. 7
      lib/pages/train_info_page/select_train/select_train_cupertino.dart
  19. 7
      lib/pages/train_info_page/select_train/select_train_material.dart
  20. 21
      lib/pages/train_info_page/view_train/train_info.dart
  21. 3
      lib/pages/train_info_page/view_train/train_info_cupertino.dart
  22. 3
      lib/pages/train_info_page/view_train/train_info_material.dart
  23. 43
      lib/providers.dart
  24. 98
      pubspec.lock
  25. 1
      pubspec.yaml

12
lib/components/loading/loading.dart

@ -1,19 +1,19 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.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_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/utils/default_ui_design.dart'; import 'package:info_tren/providers.dart';
class Loading extends StatelessWidget { class Loading extends ConsumerWidget {
static const defaultText = 'Loading...'; static const defaultText = 'Loading...';
final UiDesign? uiDesign;
final String? text; final String? text;
const Loading({ Key? key, this.text, this.uiDesign }) : super(key: key); const Loading({ super.key, this.text, });
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context, WidgetRef ref) {
final uiDesign = this.uiDesign ?? defaultUiDesign; final uiDesign = ref.watch(uiDesignProvider);
switch (uiDesign) { switch (uiDesign) {
case UiDesign.MATERIAL: case UiDesign.MATERIAL:
return LoadingMaterial(text: text ?? defaultText,); return LoadingMaterial(text: text ?? defaultText,);

38
lib/components/refresh_future_builder.dart

@ -1,4 +1,5 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
class RefreshFutureBuilder<T> extends StatefulWidget { class RefreshFutureBuilder<T> extends StatefulWidget {
final Future<T> Function()? futureCreator; final Future<T> Function()? futureCreator;
@ -134,3 +135,40 @@ enum RefreshFutureBuilderState {
refreshing, refreshing,
refreshError, refreshError,
} }
class RefreshFutureBuilderProviderAdapter<T> extends ConsumerWidget {
final Provider<AsyncValue<T>> futureProvider;
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, super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final value = ref.watch(futureProvider);
return builder(
context,
() async {
ref.invalidate(futureProvider);
},
(_) => throw UnimplementedError('Cannot replace the future when adapting a FutureProvider'),
value.when(
data: (data) => value.isLoading || value.isRefreshing
? RefreshFutureBuilderSnapshot.refresh(data)
: RefreshFutureBuilderSnapshot.withData(data),
error: (error, st) => value.isLoading || value.isRefreshing
? RefreshFutureBuilderSnapshot.refreshError(value.value, value.error, value.stackTrace)
: RefreshFutureBuilderSnapshot.withError(error, st),
loading: () {
if (value.hasValue) {
return RefreshFutureBuilderSnapshot.refresh(value.value, value.error, value.stackTrace);
}
else if (value.hasError) {
return RefreshFutureBuilderSnapshot.refreshError(value.value, value.error, value.stackTrace);
}
return const RefreshFutureBuilderSnapshot.waiting();
},
),
);
}
}

68
lib/components/select_train_suggestions/select_train_suggestions.dart

@ -1,50 +1,70 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.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_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/utils/default_ui_design.dart'; import 'package:info_tren/utils/default_ui_design.dart';
class SelectTrainSuggestions extends StatefulWidget { class SelectTrainSuggestions extends ConsumerWidget {
final UiDesign? uiDesign;
final List<TrainsResult> choices; final List<TrainsResult> choices;
final String? currentInput; final String? currentInput;
final void Function(String trainNumber) onTrainSelected; final void Function(String trainNumber) onTrainSelected;
const SelectTrainSuggestions({Key? key, required this.uiDesign, required this.choices, this.currentInput, required this.onTrainSelected }) : super(key: key); const SelectTrainSuggestions({required this.choices, this.currentInput, required this.onTrainSelected, super.key, });
@override @override
SelectTrainSuggestionsState createState() { Widget build(BuildContext context, WidgetRef ref) {
final uiDesign = this.uiDesign ?? defaultUiDesign; final uiDesign = ref.watch(uiDesignProvider);
switch(uiDesign) { switch(uiDesign) {
case UiDesign.MATERIAL: case UiDesign.MATERIAL:
return SelectTrainSuggestionsStateMaterial(); return SelectTrainSuggestionsMaterial(
choices: choices,
onTrainSelected: onTrainSelected,
currentInput: currentInput,
);
case UiDesign.CUPERTINO: case UiDesign.CUPERTINO:
return SelectTrainSuggestionsStateCupertino(); return SelectTrainSuggestionsCupertino(
choices: choices,
onTrainSelected: onTrainSelected,
currentInput: currentInput,
);
default: default:
throw UnmatchedUiDesignException(uiDesign); throw UnmatchedUiDesignException(uiDesign);
} }
} }
} }
abstract class SelectTrainSuggestionsState extends State<SelectTrainSuggestions> { abstract class SelectTrainSuggestionsShared extends StatelessWidget {
String getUseCurrentInputWidgetText(String currentInput) => 'Caută trenul cu numărul ${widget.currentInput}'; String getUseCurrentInputWidgetText(String currentInput) => 'Caută trenul cu numărul $currentInput';
Widget getUseCurrentInputWidget(String currentInput, void Function(String) onTrainSelected); Widget getUseCurrentInputWidget(String currentInput, void Function(String) onTrainSelected);
final List<TrainsResult> choices;
final String? currentInput;
final void Function(String trainNumber) onTrainSelected;
const SelectTrainSuggestionsShared({
required this.choices,
this.currentInput,
required this.onTrainSelected,
super.key,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var slivers = widget.choices.map((c) => c.company).toSet().map((operator) => OperatorAutocompleteSliver( var slivers = choices.map((c) => c.company).toSet().map((operator) => OperatorAutocompleteSliver(
uiDesign: widget.uiDesign,
operatorName: operator, operatorName: operator,
trains: widget.choices.where((c) => c.company == operator).toList(), trains: choices.where((c) => c.company == operator).toList(),
onTrainSelected: widget.onTrainSelected, onTrainSelected: onTrainSelected,
)).toList(); )).toList();
return CustomScrollView( return CustomScrollView(
slivers: <Widget>[ slivers: <Widget>[
...slivers, ...slivers,
SliverToBoxAdapter( SliverToBoxAdapter(
child: widget.currentInput != null && int.tryParse(widget.currentInput!) != null ? getUseCurrentInputWidget(widget.currentInput!, widget.onTrainSelected) : Container(), child: currentInput != null && int.tryParse(currentInput!) != null ? getUseCurrentInputWidget(currentInput!, onTrainSelected) : Container(),
), ),
SliverToBoxAdapter( SliverToBoxAdapter(
child: Container( child: Container(
@ -56,16 +76,19 @@ abstract class SelectTrainSuggestionsState extends State<SelectTrainSuggestions>
} }
} }
class OperatorAutocompleteSliver extends StatelessWidget { class OperatorAutocompleteSliver extends ConsumerWidget {
final UiDesign? uiDesign;
final String operatorName; final String operatorName;
final List<TrainsResult> trains; final List<TrainsResult> trains;
final void Function(String) onTrainSelected; final void Function(String) onTrainSelected;
const OperatorAutocompleteSliver({ Key? key, required this.uiDesign, required this.operatorName, required this.trains, required this.onTrainSelected }) : super(key: key); const OperatorAutocompleteSliver({
super.key,
required this.operatorName,
required this.trains,
required this.onTrainSelected,
});
Widget mapTrainToItem(TrainsResult train) { Widget mapTrainToItem(TrainsResult train, UiDesign uiDesign) {
final uiDesign = this.uiDesign ?? defaultUiDesign;
switch (uiDesign) { switch (uiDesign) {
case UiDesign.MATERIAL: case UiDesign.MATERIAL:
return OperatorAutocompleteTileMaterial( return OperatorAutocompleteTileMaterial(
@ -85,7 +108,8 @@ class OperatorAutocompleteSliver extends StatelessWidget {
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context, WidgetRef ref) {
final uiDesign = ref.watch(uiDesignProvider);
if (trains.isEmpty) { if (trains.isEmpty) {
return SliverToBoxAdapter(child: Container(),); return SliverToBoxAdapter(child: Container(),);
} }
@ -93,14 +117,14 @@ class OperatorAutocompleteSliver extends StatelessWidget {
return SliverPrototypeExtentList( return SliverPrototypeExtentList(
prototypeItem: Column( prototypeItem: Column(
children: <Widget>[ children: <Widget>[
mapTrainToItem(const TrainsResult(company: 'Company', number: '123', rank: 'R')), mapTrainToItem(const TrainsResult(company: 'Company', number: '123', rank: 'R'), uiDesign),
], ],
), ),
delegate: SliverChildBuilderDelegate( delegate: SliverChildBuilderDelegate(
(context, index) { (context, index) {
return Column( return Column(
children: <Widget>[ children: <Widget>[
mapTrainToItem(trains[index]), mapTrainToItem(trains[index], uiDesign),
], ],
); );
}, },

9
lib/components/select_train_suggestions/select_train_suggestions_cupertino.dart

@ -3,7 +3,14 @@ import 'package:info_tren/components/cupertino_divider.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';
class SelectTrainSuggestionsStateCupertino extends SelectTrainSuggestionsState { class SelectTrainSuggestionsCupertino extends SelectTrainSuggestionsShared {
const SelectTrainSuggestionsCupertino({
super.key,
required super.choices,
required super.onTrainSelected,
super.currentInput,
});
@override @override
Widget getUseCurrentInputWidget(String currentInput, void Function(String) onTrainSelected) { Widget getUseCurrentInputWidget(String currentInput, void Function(String) onTrainSelected) {
return Column( return Column(

9
lib/components/select_train_suggestions/select_train_suggestions_material.dart

@ -2,7 +2,14 @@ import 'package:flutter/material.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';
class SelectTrainSuggestionsStateMaterial extends SelectTrainSuggestionsState { class SelectTrainSuggestionsMaterial extends SelectTrainSuggestionsShared {
const SelectTrainSuggestionsMaterial({
super.key,
required super.choices,
required super.onTrainSelected,
super.currentInput,
});
@override @override
Widget getUseCurrentInputWidget(String currentInput, void Function(String) onTrainSelected) { Widget getUseCurrentInputWidget(String currentInput, void Function(String) onTrainSelected) {
return Column( return Column(

55
lib/main.dart

@ -1,54 +1,55 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:info_tren/models.dart'; import 'package:hooks_riverpod/hooks_riverpod.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';
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/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/pages/train_info_page/select_train/select_train.dart'; import 'package:info_tren/pages/train_info_page/select_train/select_train.dart';
import 'package:info_tren/providers.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() async {
final sharedPreferences = await SharedPreferences.getInstance();
void main() {
runApp( runApp(
const StartPoint(), ProviderScope(
overrides: [
sharedPreferencesProvider.overrideWithValue(sharedPreferences),
],
child: const StartPoint(),
),
); );
} }
Map<String, WidgetBuilder> routesByUiDesign(UiDesign uiDesign) => { Map<String, WidgetBuilder> get routes => {
Navigator.defaultRouteName: (context) { Navigator.defaultRouteName: (context) {
return MainPage( return const MainPage();
uiDesign: uiDesign,
);
}, },
AboutPage.routeName: (context) { AboutPage.routeName: (context) {
return AboutPage( return const AboutPage();
uiDesign: uiDesign,
);
}, },
SelectTrainPage.routeName: (context) { SelectTrainPage.routeName: (context) {
return SelectTrainPage( return const SelectTrainPage();
uiDesign: uiDesign,
);
}, },
TrainInfo.routeName: (context) { TrainInfo.routeName: (context) {
final args = ModalRoute.of(context)!.settings.arguments as TrainInfoArguments; final args = ModalRoute.of(context)!.settings.arguments as TrainInfoArguments;
return TrainInfo( return ProviderScope(
trainNumber: args.trainNumber, overrides: [
date: args.date, trainInfoArgumentsProvider.overrideWithValue(args),
uiDesign: uiDesign, ],
child: const TrainInfo(),
); );
}, },
SelectStationPage.routeName: (context) { SelectStationPage.routeName: (context) {
return SelectStationPage( return const SelectStationPage();
uiDesign: uiDesign,
);
}, },
ViewStationPage.routeName: (context) { ViewStationPage.routeName: (context) {
return ViewStationPage( final args = ModalRoute.of(context)!.settings.arguments as ViewStationArguments;
stationName: ModalRoute.of(context)!.settings.arguments as String, return ProviderScope(
uiDesign: uiDesign, overrides: [
viewStationArgumentsProvider.overrideWithValue(args),
],
child: const ViewStationPage(),
); );
}, },
}; };
@ -93,7 +94,7 @@ class StartPoint extends StatelessWidget {
useMaterial3: true, useMaterial3: true,
// fontFamily: 'Atkinson Hyperlegible', // fontFamily: 'Atkinson Hyperlegible',
), ),
routes: routesByUiDesign(UiDesign.MATERIAL), routes: routes,
); );
// } // }
} }

23
lib/pages/about/about_page.dart

@ -1,34 +1,37 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:info_tren/api/releases.dart'; import 'package:info_tren/api/releases.dart';
import 'package:info_tren/models.dart'; import 'package:info_tren/models.dart';
import 'package:info_tren/pages/about/about_page_cupertino.dart'; import 'package:info_tren/pages/about/about_page_cupertino.dart';
import 'package:info_tren/pages/about/about_page_material.dart'; import 'package:info_tren/pages/about/about_page_material.dart';
import 'package:info_tren/utils/default_ui_design.dart'; import 'package:info_tren/providers.dart';
import 'package:package_info_plus/package_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart';
class AboutPage extends StatefulWidget { class AboutPage extends ConsumerWidget {
final UiDesign? uiDesign; const AboutPage({super.key});
const AboutPage({Key? key, this.uiDesign}) : super(key: key);
static String routeName = '/about'; static String routeName = '/about';
@override @override
State<StatefulWidget> createState() { Widget build(BuildContext context, WidgetRef ref) {
final uiDesign = this.uiDesign ?? defaultUiDesign; final uiDesign = ref.watch(uiDesignProvider);
switch (uiDesign) { switch (uiDesign) {
case UiDesign.MATERIAL: case UiDesign.MATERIAL:
return AboutPageStateMaterial(); return const AboutPageMaterial();
case UiDesign.CUPERTINO: case UiDesign.CUPERTINO:
return AboutPageStateCupertino(); return const AboutPageCupertino();
default: default:
throw UnmatchedUiDesignException(uiDesign); throw UnmatchedUiDesignException(uiDesign);
} }
} }
} }
abstract class AboutPageState extends State<AboutPage> { abstract class AboutPageShared extends StatefulWidget {
const AboutPageShared({super.key});
}
abstract class AboutPageState extends State<AboutPageShared> {
static const String download = String.fromEnvironment('DOWNLOAD'); static const String download = String.fromEnvironment('DOWNLOAD');
final String pageTitle = 'Despre aplicație'; final String pageTitle = 'Despre aplicație';

7
lib/pages/about/about_page_cupertino.dart

@ -3,6 +3,13 @@ import 'package:info_tren/components/cupertino_divider.dart';
import 'package:info_tren/pages/about/about_page.dart'; import 'package:info_tren/pages/about/about_page.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
class AboutPageCupertino extends StatefulWidget {
const AboutPageCupertino({super.key});
@override
State<AboutPageShared> createState() => AboutPageStateCupertino();
}
class AboutPageStateCupertino extends AboutPageState { class AboutPageStateCupertino extends AboutPageState {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

7
lib/pages/about/about_page_material.dart

@ -3,6 +3,13 @@ import 'package:flutter/services.dart';
import 'package:info_tren/pages/about/about_page.dart'; import 'package:info_tren/pages/about/about_page.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
class AboutPageMaterial extends StatefulWidget {
const AboutPageMaterial({super.key});
@override
State<AboutPageShared> createState() => AboutPageStateMaterial();
}
class AboutPageStateMaterial extends AboutPageState { class AboutPageStateMaterial extends AboutPageState {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

13
lib/pages/main/main_page.dart

@ -1,20 +1,19 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.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/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_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';
import 'package:info_tren/utils/default_ui_design.dart'; import 'package:info_tren/providers.dart';
class MainPage extends StatelessWidget { class MainPage extends ConsumerWidget {
final UiDesign? uiDesign; const MainPage({super.key,});
const MainPage({ Key? key, this.uiDesign }) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context, WidgetRef ref) {
final uiDesign = this.uiDesign ?? defaultUiDesign; final uiDesign = ref.watch(uiDesignProvider);
switch (uiDesign) { switch (uiDesign) {
case UiDesign.MATERIAL: case UiDesign.MATERIAL:

28
lib/pages/station_arrdep_page/select_station/select_station.dart

@ -1,33 +1,36 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.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_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/utils/default_ui_design.dart'; import 'package:info_tren/providers.dart';
import 'package:info_tren/api/stations.dart' as api_stations; import 'package:info_tren/api/stations.dart' as api_stations;
class SelectStationPage extends StatefulWidget { class SelectStationPage extends ConsumerWidget {
final UiDesign? uiDesign; const SelectStationPage({ super.key });
const SelectStationPage({ Key? key, this.uiDesign }) : super(key: key);
static String routeName = '/stationArrDep/selectStation'; static String routeName = '/stationArrDep/selectStation';
@override @override
SelectStationPageState createState() { Widget build(BuildContext context, WidgetRef ref) {
final uiDesign = this.uiDesign ?? defaultUiDesign; final uiDesign = ref.watch(uiDesignProvider);
switch (uiDesign) { switch (uiDesign) {
case UiDesign.MATERIAL: case UiDesign.MATERIAL:
return SelectStationPageStateMaterial(); return const SelectStationPageMaterial();
case UiDesign.CUPERTINO: case UiDesign.CUPERTINO:
return SelectStationPageStateCupertino(); return const SelectStationPageCupertino();
default: default:
throw UnmatchedUiDesignException(uiDesign); throw UnmatchedUiDesignException(uiDesign);
} }
} }
} }
abstract class SelectStationPageState extends State<SelectStationPage> { abstract class SelectStationPageShared extends StatefulWidget {
const SelectStationPageShared({super.key});
}
abstract class SelectStationPageState extends State<SelectStationPageShared> {
static const pageTitle = 'Plecări/sosiri stație'; static const pageTitle = 'Plecări/sosiri stație';
static const textFieldLabel = 'Numele stației'; static const textFieldLabel = 'Numele stației';
static const roToEn = { static const roToEn = {
@ -77,7 +80,10 @@ abstract class SelectStationPageState extends State<SelectStationPage> {
} }
void onSuggestionSelected(String suggestion) { void onSuggestionSelected(String suggestion) {
Navigator.of(context).pushNamed(ViewStationPage.routeName, arguments: suggestion); Navigator.of(context).pushNamed(
ViewStationPage.routeName,
arguments: ViewStationArguments(stationName: suggestion),
);
} }
} }

7
lib/pages/station_arrdep_page/select_station/select_station_cupertino.dart

@ -2,6 +2,13 @@ import 'package:flutter/cupertino.dart';
import 'package:info_tren/components/cupertino_divider.dart'; import 'package:info_tren/components/cupertino_divider.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';
class SelectStationPageCupertino extends SelectStationPageShared {
const SelectStationPageCupertino({super.key});
@override
State<StatefulWidget> createState() => SelectStationPageStateCupertino();
}
class SelectStationPageStateCupertino extends SelectStationPageState { class SelectStationPageStateCupertino extends SelectStationPageState {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

7
lib/pages/station_arrdep_page/select_station/select_station_material.dart

@ -1,6 +1,13 @@
import 'package:flutter/material.dart'; import 'package:flutter/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';
class SelectStationPageMaterial extends SelectStationPageShared {
const SelectStationPageMaterial({super.key});
@override
State<StatefulWidget> createState() => SelectStationPageStateMaterial();
}
class SelectStationPageStateMaterial extends SelectStationPageState { class SelectStationPageStateMaterial extends SelectStationPageState {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

79
lib/pages/station_arrdep_page/view_station/view_station.dart

@ -1,33 +1,49 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:info_tren/api/station_data.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_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/utils/default_ui_design.dart'; import 'package:info_tren/utils/default_ui_design.dart';
class ViewStationPage extends StatefulWidget { class ViewStationPage extends HookConsumerWidget {
final UiDesign? uiDesign; const ViewStationPage({ super.key, });
final String stationName;
const ViewStationPage({ Key? key, required this.stationName, this.uiDesign }) : super(key: key);
static String routeName = '/stationArrDep/viewStation'; static String routeName = '/stationArrDep/viewStation';
ValueNotifier<ViewStationPageTab> useTab() => useState(ViewStationPageTab.departures);
@override @override
ViewStationPageState createState() { Widget build(BuildContext context, WidgetRef ref) {
final uiDesign = this.uiDesign ?? defaultUiDesign; final tab = useTab();
final uiDesign = ref.watch(uiDesignProvider);
switch (uiDesign) { switch (uiDesign) {
case UiDesign.MATERIAL: case UiDesign.MATERIAL:
return ViewStationPageStateMaterial(); return ViewStationPageMaterial(
tab: tab.value,
setTab: (newTab) => tab.value = newTab,
);
case UiDesign.CUPERTINO: case UiDesign.CUPERTINO:
return ViewStationPageStateCupertino(); return ViewStationPageCupertino(
tab: tab.value,
setTab: (newTab) => tab.value = newTab,
);
} }
} }
} }
abstract class ViewStationPageState extends State<ViewStationPage> { class ViewStationArguments {
final String stationName;
const ViewStationArguments({required this.stationName});
}
abstract class ViewStationPageShared extends StatelessWidget {
static const arrivals = 'Sosiri'; static const arrivals = 'Sosiri';
static const departures = 'Plecări'; static const departures = 'Plecări';
static const loadingText = 'Se încarcă...'; static const loadingText = 'Se încarcă...';
@ -38,42 +54,15 @@ abstract class ViewStationPageState extends State<ViewStationPage> {
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';
ViewStationPageTab tab = ViewStationPageTab.departures; final ViewStationPageTab tab;
late String stationName; final void Function(ViewStationPageTab) setTab;
late Future<StationData> Function() futureCreator; const ViewStationPageShared({required this.tab, required this.setTab, super.key});
@override
void initState() {
initData();
super.initState();
}
@override
void didChangeDependencies() {
if (stationName != widget.stationName) {
setState(() {
initData();
});
}
super.didChangeDependencies();
}
void initData() {
stationName = widget.stationName;
futureCreator = () => getStationData(stationName);
}
Widget buildContent(BuildContext context, Future Function() refresh, Future Function(Future<StationData> Function() newFutureBuilder) _, RefreshFutureBuilderSnapshot<StationData> snapshot); Widget buildContent(BuildContext context, Future Function() refresh, Future Function(Future<StationData> Function() newFutureBuilder) _, RefreshFutureBuilderSnapshot<StationData> snapshot);
Widget buildStationArrivalItem(BuildContext context, StationArrDep item); Widget buildStationArrivalItem(BuildContext context, StationArrDep item);
Widget buildStationDepartureItem(BuildContext context, StationArrDep item); Widget buildStationDepartureItem(BuildContext context, StationArrDep item);
void onTabChange(int index) { void onTrainTapped(BuildContext context, StationTrain train) {
setState(() {
tab = ViewStationPageTab.values[index];
});
}
void onTrainTapped(StationTrain train) {
Navigator.of(context).pushNamed( Navigator.of(context).pushNamed(
TrainInfo.routeName, TrainInfo.routeName,
arguments: TrainInfoArguments( arguments: TrainInfoArguments(
@ -83,10 +72,14 @@ abstract class ViewStationPageState extends State<ViewStationPage> {
); );
} }
void onTabChange (int index) {
setTab(ViewStationPageTab.values[index]);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return RefreshFutureBuilder( return RefreshFutureBuilderProviderAdapter(
futureCreator: futureCreator, futureProvider: viewStationDataProvider,
builder: buildContent, builder: buildContent,
); );
} }

27
lib/pages/station_arrdep_page/view_station/view_station_cupertino.dart

@ -1,27 +1,36 @@
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:hooks_riverpod/hooks_riverpod.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/components/sliver_persistent_header_padding.dart'; import 'package:info_tren/components/sliver_persistent_header_padding.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.dart'; import 'package:info_tren/pages/station_arrdep_page/view_station/view_station.dart';
import 'package:info_tren/providers.dart';
class ViewStationPageCupertino extends ViewStationPageShared {
const ViewStationPageCupertino({super.key, required super.tab, required super.setTab});
class ViewStationPageStateCupertino extends ViewStationPageState {
@override @override
Widget buildContent(BuildContext context, Future Function() refresh, Future Function(Future<StationData> Function()) _, RefreshFutureBuilderSnapshot<StationData> snapshot) { Widget buildContent(BuildContext context, Future Function() refresh, Future Function(Future<StationData> Function()) _, RefreshFutureBuilderSnapshot<StationData> snapshot) {
return CupertinoPageScaffold( return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar( navigationBar: CupertinoNavigationBar(
middle: Text(snapshot.hasData ? snapshot.data!.stationName : stationName), middle: Consumer(
builder: (context, ref, _) {
final stationName = ref.watch(viewStationArgumentsProvider.select((value) => value.stationName));
return Text(snapshot.hasData ? snapshot.data!.stationName : stationName);
}
),
), ),
child: snapshot.hasData ? CupertinoTabScaffold( child: snapshot.hasData ? CupertinoTabScaffold(
tabBar: CupertinoTabBar( tabBar: CupertinoTabBar(
items: const [ items: const [
BottomNavigationBarItem( BottomNavigationBarItem(
icon: Icon(CupertinoIcons.arrow_down), icon: Icon(CupertinoIcons.arrow_down),
label: ViewStationPageState.arrivals, label: ViewStationPageShared.arrivals,
), ),
BottomNavigationBarItem( BottomNavigationBarItem(
icon: Icon(CupertinoIcons.arrow_up), icon: Icon(CupertinoIcons.arrow_up),
label: ViewStationPageState.departures, label: ViewStationPageShared.departures,
), ),
], ],
onTap: onTabChange, onTap: onTabChange,
@ -47,14 +56,14 @@ class ViewStationPageStateCupertino extends ViewStationPageState {
), ),
); );
}, },
) : snapshot.state == RefreshFutureBuilderState.waiting ? Loading(text: ViewStationPageState.loadingText, uiDesign: widget.uiDesign,) : Container(), ) : snapshot.state == RefreshFutureBuilderState.waiting ? const Loading(text: ViewStationPageShared.loadingText,) : Container(),
); );
} }
@override @override
Widget buildStationArrivalItem(BuildContext context, StationArrDep item) { Widget buildStationArrivalItem(BuildContext context, StationArrDep item) {
return GestureDetector( return GestureDetector(
onTap: () => onTrainTapped(item.train), onTap: () => onTrainTapped(context, item.train),
child: CupertinoFormRow( child: CupertinoFormRow(
prefix: Text.rich( prefix: Text.rich(
TextSpan( TextSpan(
@ -73,7 +82,7 @@ class ViewStationPageStateCupertino extends ViewStationPageState {
helper: Text.rich( helper: Text.rich(
TextSpan( TextSpan(
children: [ children: [
const TextSpan(text: ViewStationPageState.arrivesFrom), const TextSpan(text: ViewStationPageShared.arrivesFrom),
const TextSpan(text: ' '), const TextSpan(text: ' '),
TextSpan(text: item.train.terminus), TextSpan(text: item.train.terminus),
], ],
@ -87,7 +96,7 @@ class ViewStationPageStateCupertino extends ViewStationPageState {
@override @override
Widget buildStationDepartureItem(BuildContext context, StationArrDep item) { Widget buildStationDepartureItem(BuildContext context, StationArrDep item) {
return GestureDetector( return GestureDetector(
onTap: () => onTrainTapped(item.train), onTap: () => onTrainTapped(context, item.train),
child: CupertinoFormRow( child: CupertinoFormRow(
prefix: Text.rich( prefix: Text.rich(
TextSpan( TextSpan(
@ -106,7 +115,7 @@ class ViewStationPageStateCupertino extends ViewStationPageState {
helper: Text.rich( helper: Text.rich(
TextSpan( TextSpan(
children: [ children: [
const TextSpan(text: ViewStationPageState.departsTo), const TextSpan(text: ViewStationPageShared.departsTo),
const TextSpan(text: ' '), const TextSpan(text: ' '),
TextSpan(text: item.train.terminus), TextSpan(text: item.train.terminus),
], ],

27
lib/pages/station_arrdep_page/view_station/view_station_material.dart

@ -1,22 +1,31 @@
import 'dart:math'; 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:info_tren/components/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';
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';
class ViewStationPageMaterial extends ViewStationPageShared {
const ViewStationPageMaterial({super.key, required super.tab, required super.setTab});
class ViewStationPageStateMaterial extends ViewStationPageState {
@override @override
Widget buildContent(BuildContext context, Future Function() refresh, Future Function(Future<StationData> Function()) _, RefreshFutureBuilderSnapshot<StationData> snapshot) { Widget buildContent(BuildContext context, Future Function() refresh, Future Function(Future<StationData> Function()) _, RefreshFutureBuilderSnapshot<StationData> snapshot) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text(snapshot.hasData ? snapshot.data!.stationName : stationName), title: Consumer(
builder: (context, ref, _) {
final stationName = ref.watch(viewStationArgumentsProvider.select((value) => value.stationName));
return Text(snapshot.hasData ? snapshot.data!.stationName : stationName);
}
),
centerTitle: true, centerTitle: true,
), ),
body: snapshot.state == RefreshFutureBuilderState.waiting body: snapshot.state == RefreshFutureBuilderState.waiting
? Loading(text: ViewStationPageState.loadingText, uiDesign: widget.uiDesign,) ? const Loading(text: ViewStationPageShared.loadingText,)
: snapshot.state == RefreshFutureBuilderState.error : snapshot.state == RefreshFutureBuilderState.error
? Container() ? Container()
: CustomScrollView( : CustomScrollView(
@ -36,11 +45,11 @@ class ViewStationPageStateMaterial extends ViewStationPageState {
items: const [ items: const [
BottomNavigationBarItem( BottomNavigationBarItem(
icon: Icon(Icons.arrow_downward), icon: Icon(Icons.arrow_downward),
label: ViewStationPageState.arrivals, label: ViewStationPageShared.arrivals,
), ),
BottomNavigationBarItem( BottomNavigationBarItem(
icon: Icon(Icons.arrow_upward), icon: Icon(Icons.arrow_upward),
label: ViewStationPageState.departures, label: ViewStationPageShared.departures,
), ),
], ],
currentIndex: tab.index, currentIndex: tab.index,
@ -51,7 +60,7 @@ class ViewStationPageStateMaterial extends ViewStationPageState {
Widget buildStationItem(BuildContext context, StationArrDep item, {required bool arrival}) { Widget buildStationItem(BuildContext context, StationArrDep item, {required bool arrival}) {
return InkWell( return InkWell(
onTap: () => onTrainTapped(item.train), onTap: () => onTrainTapped(context, item.train),
child: Container( child: Container(
color: item.status.cancelled ? Colors.red.withAlpha(100) : null, color: item.status.cancelled ? Colors.red.withAlpha(100) : null,
child: Row( child: Row(
@ -117,10 +126,10 @@ class ViewStationPageStateMaterial extends ViewStationPageState {
children: [ children: [
TextSpan( TextSpan(
text: item.status.cancelled text: item.status.cancelled
? (arrival ? ViewStationPageState.cancelledArrival : ViewStationPageState.cancelledDeparture) ? (arrival ? ViewStationPageShared.cancelledArrival : ViewStationPageShared.cancelledDeparture)
: item.time.add(Duration(minutes: max(0, item.status.delay))).compareTo(DateTime.now()) < 0 : item.time.add(Duration(minutes: max(0, item.status.delay))).compareTo(DateTime.now()) < 0
? (arrival ? ViewStationPageState.arrivedFrom : ViewStationPageState.departedTo) ? (arrival ? ViewStationPageShared.arrivedFrom : ViewStationPageShared.departedTo)
: (arrival ? ViewStationPageState.arrivesFrom : ViewStationPageState.departsTo) : (arrival ? ViewStationPageShared.arrivesFrom : ViewStationPageShared.departsTo)
), ),
const TextSpan(text: ' '), const TextSpan(text: ' '),
TextSpan(text: item.train.terminus), TextSpan(text: item.train.terminus),

41
lib/pages/train_info_page/select_train/select_train.dart

@ -1,46 +1,50 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
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_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/utils/default_ui_design.dart'; import 'package:info_tren/providers.dart';
import 'package:info_tren/api/trains.dart' as api_trains; import 'package:info_tren/api/trains.dart' as api_trains;
typedef TrainSelectedCallback = Function(int trainNumber); typedef TrainSelectedCallback = Function(int trainNumber);
class SelectTrainPage extends StatefulWidget { class SelectTrainPage extends ConsumerWidget {
final UiDesign? uiDesign; const SelectTrainPage({super.key});
const SelectTrainPage({Key? key, this.uiDesign}) : super(key: key);
static String routeName = "/trainInfo/selectTrain"; static String routeName = "/trainInfo/selectTrain";
void onTrainSelected(BuildContext context, String selection) {
selection = selection.characters.takeWhile((char) => List.generate(10, (i) => i.toString()).contains(char)).join();
Navigator.of(context).pushNamed(
TrainInfo.routeName,
arguments: TrainInfoArguments(trainNumber: selection),
);
}
@override @override
SelectTrainPageState createState() { Widget build(BuildContext context, WidgetRef ref) {
final uiDesign = this.uiDesign ?? defaultUiDesign; final uiDesign = ref.watch(uiDesignProvider);
switch(uiDesign) { switch(uiDesign) {
case UiDesign.MATERIAL: case UiDesign.MATERIAL:
return SelectTrainPageStateMaterial(); return const SelectTrainPageMaterial();
case UiDesign.CUPERTINO: case UiDesign.CUPERTINO:
return SelectTrainPageStateCupertino(); return const SelectTrainPageCupertino();
default: default:
throw UnmatchedUiDesignException(uiDesign); throw UnmatchedUiDesignException(uiDesign);
} }
} }
} }
abstract class SelectTrainPageState extends State<SelectTrainPage> { abstract class SelectTrainPageShared extends StatefulWidget {
const SelectTrainPageShared({super.key});
void onTrainSelected(BuildContext context, String selection) {
selection = selection.characters.takeWhile((char) => List.generate(10, (i) => i.toString()).contains(char)).join();
Navigator.of(context).pushNamed(
TrainInfo.routeName,
arguments: TrainInfoArguments(trainNumber: selection),
);
}
}
abstract class SelectTrainPageState extends State<SelectTrainPageShared> {
final String pageTitle = 'Informații despre tren'; final String pageTitle = 'Informații despre tren';
final String textFieldLabel = 'Numărul trenului'; final String textFieldLabel = 'Numărul trenului';
@ -102,7 +106,6 @@ abstract class SelectTrainPageState extends State<SelectTrainPage> {
} }
Widget get suggestionsList => SelectTrainSuggestions( Widget get suggestionsList => SelectTrainSuggestions(
uiDesign: widget.uiDesign,
choices: filteredTrains, choices: filteredTrains,
onTrainSelected: (trainNumber) => widget.onTrainSelected(context, trainNumber), onTrainSelected: (trainNumber) => widget.onTrainSelected(context, trainNumber),
currentInput: trainNoController.text, currentInput: trainNoController.text,

7
lib/pages/train_info_page/select_train/select_train_cupertino.dart

@ -2,6 +2,13 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.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';
class SelectTrainPageCupertino extends SelectTrainPageShared {
const SelectTrainPageCupertino({super.key});
@override
State<SelectTrainPageShared> createState() => SelectTrainPageStateCupertino();
}
class SelectTrainPageStateCupertino extends SelectTrainPageState { class SelectTrainPageStateCupertino extends SelectTrainPageState {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

7
lib/pages/train_info_page/select_train/select_train_material.dart

@ -2,6 +2,13 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.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';
class SelectTrainPageMaterial extends SelectTrainPageShared {
const SelectTrainPageMaterial({super.key});
@override
State<SelectTrainPageShared> createState() => SelectTrainPageStateMaterial();
}
class SelectTrainPageStateMaterial extends SelectTrainPageState { class SelectTrainPageStateMaterial extends SelectTrainPageState {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

21
lib/pages/train_info_page/view_train/train_info.dart

@ -1,27 +1,27 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.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_material.dart'; import 'package:info_tren/pages/train_info_page/view_train/train_info_material.dart';
import 'package:info_tren/utils/default_ui_design.dart'; import 'package:info_tren/providers.dart';
class TrainInfo extends StatelessWidget { class TrainInfo extends ConsumerWidget {
static String routeName = "/trainInfo/display"; static String routeName = "/trainInfo/display";
final UiDesign? uiDesign; const TrainInfo({super.key,});
final String trainNumber;
final DateTime? date;
const TrainInfo({Key? key, required this.trainNumber, this.date, this.uiDesign}): super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context, WidgetRef ref) {
final uiDesign = this.uiDesign ?? defaultUiDesign; final uiDesign = ref.watch(uiDesignProvider);
final args = ref.watch(trainInfoArgumentsProvider);
final trainNumber = args.trainNumber;
final date = args.date;
return RefreshFutureBuilder<TrainData>( return RefreshFutureBuilder<TrainData>(
futureCreator: () => getTrain(trainNumber, date: date), futureCreator: () => getTrain(trainNumber, date: date),
@ -80,9 +80,8 @@ abstract class TrainInfoLoading extends StatelessWidget {
TrainInfoLoading({ TrainInfoLoading({
required this.title, required this.title,
String? loadingText, String? loadingText,
UiDesign? uiDesign,
super.key, super.key,
}) : loadingWidget = Loading(uiDesign: uiDesign, text: loadingText,); }) : loadingWidget = Loading(text: loadingText,);
} }
abstract class TrainInfoError extends StatelessWidget { abstract class TrainInfoError extends StatelessWidget {

3
lib/pages/train_info_page/view_train/train_info_cupertino.dart

@ -11,8 +11,7 @@ import 'package:info_tren/pages/train_info_page/view_train/train_info_cupertino_
import 'package:info_tren/utils/state_to_string.dart'; import 'package:info_tren/utils/state_to_string.dart';
class TrainInfoLoadingCupertino extends TrainInfoLoading { class TrainInfoLoadingCupertino extends TrainInfoLoading {
TrainInfoLoadingCupertino({required super.title, super.loadingText, super.key,}) TrainInfoLoadingCupertino({required super.title, super.loadingText, super.key,});
: super(uiDesign: UiDesign.CUPERTINO);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

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

@ -8,8 +8,7 @@ import 'package:info_tren/pages/train_info_page/view_train/train_info_material_D
import 'package:info_tren/utils/state_to_string.dart'; import 'package:info_tren/utils/state_to_string.dart';
class TrainInfoLoadingMaterial extends TrainInfoLoading { class TrainInfoLoadingMaterial extends TrainInfoLoading {
TrainInfoLoadingMaterial({required super.title, super.loadingText, super.key,}) TrainInfoLoadingMaterial({required super.title, super.loadingText, super.key,});
: super(uiDesign: UiDesign.MATERIAL);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

43
lib/providers.dart

@ -0,0 +1,43 @@
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:info_tren/api/station_data.dart';
import 'package:info_tren/models.dart';
import 'package:info_tren/pages/station_arrdep_page/view_station/view_station.dart';
import 'package:info_tren/pages/train_info_page/view_train/train_info.dart';
import 'package:info_tren/utils/default_ui_design.dart';
import 'package:info_tren/utils/iterable_extensions.dart';
import 'package:shared_preferences/shared_preferences.dart';
final sharedPreferencesProvider = Provider<SharedPreferences>(
(_) => throw UnimplementedError('Please override in ProviderScope'),
);
final uiDesignProvider = Provider((ref) {
final sharedPreferences = ref.watch(sharedPreferencesProvider);
final stored = sharedPreferences.getString('uiDesign');
final design = UiDesign.values.where((element) => element.name == stored).firstOrNull ?? defaultUiDesign;
return design;
});
Future<void> setUiDesign(Ref ref, UiDesign? design) async {
final sharedPreferences = ref.watch(sharedPreferencesProvider);
if (design != null) {
await sharedPreferences.setString('uiDesign', design.name);
}
else {
await sharedPreferences.remove('uiDesign');
}
ref.invalidate(uiDesignProvider);
}
final trainInfoArgumentsProvider = Provider<TrainInfoArguments>(
(_) => throw UnimplementedError('Please override in ProviderScope'),
);
final stationDataProvider = FutureProvider.family((ref, String stationName) => getStationData(stationName));
final viewStationArgumentsProvider = Provider<ViewStationArguments>(
(_) => throw UnimplementedError('Please override in ProviderScope'),
);
final viewStationDataProvider = Provider((ref) {
final args = ref.watch(viewStationArgumentsProvider);
final data = ref.watch(stationDataProvider(args.stationName));
return data;
});

98
pubspec.lock

@ -354,6 +354,34 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.8.2" version: "1.8.2"
path_provider_linux:
dependency: transitive
description:
name: path_provider_linux
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.7"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.5"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.3"
platform:
dependency: transitive
description:
name: platform
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.0"
plugin_platform_interface: plugin_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -368,6 +396,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.5.1" version: "1.5.1"
process:
dependency: transitive
description:
name: process
url: "https://pub.dartlang.org"
source: hosted
version: "4.2.4"
pub_semver: pub_semver:
dependency: transitive dependency: transitive
description: description:
@ -396,6 +431,62 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.2" version: "2.0.2"
shared_preferences:
dependency: "direct main"
description:
name: shared_preferences
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.15"
shared_preferences_android:
dependency: transitive
description:
name: shared_preferences_android
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.14"
shared_preferences_ios:
dependency: transitive
description:
name: shared_preferences_ios
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
shared_preferences_linux:
dependency: transitive
description:
name: shared_preferences_linux
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
shared_preferences_macos:
dependency: transitive
description:
name: shared_preferences_macos
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.4"
shared_preferences_platform_interface:
dependency: transitive
description:
name: shared_preferences_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
shared_preferences_web:
dependency: transitive
description:
name: shared_preferences_web
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.4"
shared_preferences_windows:
dependency: transitive
description:
name: shared_preferences_windows
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
shelf: shelf:
dependency: transitive dependency: transitive
description: description:
@ -590,6 +681,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.0.1" version: "3.0.1"
xdg_directories:
dependency: transitive
description:
name: xdg_directories
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.0+2"
yaml: yaml:
dependency: transitive dependency: transitive
description: description:

1
pubspec.yaml

@ -32,6 +32,7 @@ dependencies:
hooks_riverpod: ^2.0.2 hooks_riverpod: ^2.0.2
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
dev_dependencies: dev_dependencies:
# flutter_test: # flutter_test:

Loading…
Cancel
Save