Migrate uiDesign to Riverpod
This commit is contained in:
parent
cb380e802c
commit
240812e261
25 changed files with 464 additions and 184 deletions
|
@ -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,);
|
||||||
|
|
|
@ -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();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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,
|
||||||
);
|
);
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
|
@ -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';
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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),
|
||||||
],
|
],
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -1,23 +1,40 @@
|
||||||
|
|
||||||
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";
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final uiDesign = ref.watch(uiDesignProvider);
|
||||||
|
|
||||||
|
switch(uiDesign) {
|
||||||
|
case UiDesign.MATERIAL:
|
||||||
|
return const SelectTrainPageMaterial();
|
||||||
|
case UiDesign.CUPERTINO:
|
||||||
|
return const SelectTrainPageCupertino();
|
||||||
|
default:
|
||||||
|
throw UnmatchedUiDesignException(uiDesign);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class SelectTrainPageShared extends StatefulWidget {
|
||||||
|
const SelectTrainPageShared({super.key});
|
||||||
|
|
||||||
void onTrainSelected(BuildContext context, String selection) {
|
void onTrainSelected(BuildContext context, String selection) {
|
||||||
selection = selection.characters.takeWhile((char) => List.generate(10, (i) => i.toString()).contains(char)).join();
|
selection = selection.characters.takeWhile((char) => List.generate(10, (i) => i.toString()).contains(char)).join();
|
||||||
Navigator.of(context).pushNamed(
|
Navigator.of(context).pushNamed(
|
||||||
|
@ -25,22 +42,9 @@ class SelectTrainPage extends StatefulWidget {
|
||||||
arguments: TrainInfoArguments(trainNumber: selection),
|
arguments: TrainInfoArguments(trainNumber: selection),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
SelectTrainPageState createState() {
|
|
||||||
final uiDesign = this.uiDesign ?? defaultUiDesign;
|
|
||||||
switch(uiDesign) {
|
|
||||||
case UiDesign.MATERIAL:
|
|
||||||
return SelectTrainPageStateMaterial();
|
|
||||||
case UiDesign.CUPERTINO:
|
|
||||||
return SelectTrainPageStateCupertino();
|
|
||||||
default:
|
|
||||||
throw UnmatchedUiDesignException(uiDesign);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class SelectTrainPageState extends State<SelectTrainPage> {
|
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,
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
Normal file
43
lib/providers.dart
Normal file
|
@ -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
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:
|
||||||
|
|
|
@ -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…
Add table
Reference in a new issue