Skip to content
Snippets Groups Projects
Commit 75aac28d authored by Benoît Harrault's avatar Benoît Harrault
Browse files

Use navigation tools from flutter_custom_toolbox

parent 07695da4
No related branches found
No related tags found
1 merge request!30Resolve "Use navigation widgets from flutter_custom_toolbox"
Pipeline #7165 passed
This commit is part of merge request !30. Comments created here will be created in the context of that merge request.
Showing
with 127 additions and 443 deletions
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
"about_version": "Version: {version}", "about_version": "Version: {version}",
"page_home": "Home", "page_home": "Home",
"page_player": "Player", "page_plotter": "Plotter",
"page_remote_control": "Control", "page_remote_control": "Control",
"": "" "": ""
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
"about_version": "Version : {version}", "about_version": "Version : {version}",
"page_home": "Accueil", "page_home": "Accueil",
"page_player": "Player", "page_plotter": "Traceur",
"page_remote_control": "Télécommande", "page_remote_control": "Télécommande",
"": "" "": ""
......
Use navigation tools from flutter_custom_toolbox.
Utilisation des outils de navigation entre pages depuis flutter_custom_toolbox.
import 'package:flutter/material.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:plotter/common/ui/pages/home.dart';
import 'package:plotter/common/ui/pages/player.dart';
import 'package:plotter/common/ui/pages/remote_control.dart';
import 'package:plotter/cubit/activity/activity_cubit.dart';
import 'package:plotter/models/activity/activity.dart';
class ActivityPageItem {
final String code;
final Icon icon;
final Widget Function({required Activity currentActivity})? builder;
const ActivityPageItem({
required this.code,
required this.icon,
required this.builder,
});
}
class ActivityPage {
static const bool displayBottomNavBar = true;
static const indexHome = 0;
static final ActivityPageItem pageHome = ActivityPageItem(
code: 'page_home',
icon: Icon(UniconsLine.home),
builder: ({required Activity currentActivity}) {
return PageHome();
},
);
static const indexPlayer = 1;
static final ActivityPageItem pagePlayer = ActivityPageItem(
code: 'page_player',
icon: Icon(UniconsLine.star),
builder: ({required Activity currentActivity}) {
return PagePlayer();
},
);
static const indexRemoteControl = 2;
static final ActivityPageItem pageRemoteControl = ActivityPageItem(
code: 'page_remote_control',
icon: Icon(UniconsLine.star),
builder: ({required Activity currentActivity}) {
return PageRemoteControl();
},
);
static final Map<int, ActivityPageItem> items = {
indexHome: pageHome,
indexPlayer: pagePlayer,
indexRemoteControl: pageRemoteControl,
};
static int defaultPageIndex = indexHome;
static bool isIndexAllowed(int pageIndex) {
return items.keys.contains(pageIndex);
}
static Widget getWidget(int pageIndex) {
return BlocBuilder<ActivityCubit, ActivityState>(
builder: (BuildContext context, ActivityState activityState) {
final Activity currentActivity = activityState.currentActivity;
if (items.keys.contains(pageIndex)) {
return items[pageIndex]?.builder!(currentActivity: currentActivity) ?? Text('oups');
} else {
return getWidget(defaultPageIndex);
}
},
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:plotter/common/ui/screens/about.dart';
import 'package:plotter/common/ui/screens/activity.dart';
import 'package:plotter/common/ui/screens/settings.dart';
class ScreenItem {
final String code;
final Icon icon;
final Widget screen;
const ScreenItem({
required this.code,
required this.icon,
required this.screen,
});
}
class Screen {
static const indexActivity = 0;
static const screenActivity = ScreenItem(
code: 'screen_activity',
icon: Icon(UniconsLine.home),
screen: ScreenActivity(),
);
static const indexSettings = 1;
static const screenSettings = ScreenItem(
code: 'screen_settings',
icon: Icon(UniconsLine.setting),
screen: ScreenSettings(),
);
static const indexAbout = 2;
static const screenAbout = ScreenItem(
code: 'screen_about',
icon: Icon(UniconsLine.info_circle),
screen: ScreenAbout(),
);
static Map<int, ScreenItem> items = {
indexActivity: screenActivity,
indexSettings: screenSettings,
indexAbout: screenAbout,
};
static bool isIndexAllowed(int screenIndex) {
return items.keys.contains(screenIndex);
}
static Widget getWidget(int screenIndex) {
return items[screenIndex]?.screen ?? screenActivity.screen;
}
}
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:plotter/common/config/activity_page.dart';
class NavCubitPage extends HydratedCubit<int> {
NavCubitPage() : super(0);
void updateIndex(int index) {
if (ActivityPage.isIndexAllowed(index)) {
emit(index);
} else {
emit(ActivityPage.indexHome);
}
}
void goToPageHome() {
updateIndex(ActivityPage.indexHome);
}
@override
int fromJson(Map<String, dynamic> json) {
return ActivityPage.indexHome;
}
@override
Map<String, dynamic>? toJson(int state) {
return <String, int>{'index': state};
}
}
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:plotter/common/config/screen.dart';
class NavCubitScreen extends HydratedCubit<int> {
NavCubitScreen() : super(0);
void updateIndex(int index) {
if (Screen.isIndexAllowed(index)) {
emit(index);
} else {
goToScreenActivity();
}
}
void goToScreenActivity() {
emit(Screen.indexActivity);
}
void goToScreenSettings() {
emit(Screen.indexSettings);
}
void goToScreenAbout() {
emit(Screen.indexAbout);
}
@override
int fromJson(Map<String, dynamic> json) {
return Screen.indexActivity;
}
@override
Map<String, dynamic>? toJson(int state) {
return <String, int>{'index': state};
}
}
import 'package:flutter/material.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:plotter/common/config/activity_page.dart';
import 'package:plotter/common/cubit/nav/nav_cubit_pages.dart';
class BottomNavBar extends StatelessWidget {
const BottomNavBar({super.key});
@override
Widget build(BuildContext context) {
return Card(
margin: const EdgeInsets.only(top: 1, right: 4, left: 4),
elevation: 4,
shadowColor: Theme.of(context).colorScheme.shadow,
color: Theme.of(context).colorScheme.surfaceContainerHighest,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16),
topRight: Radius.circular(16),
),
),
child: BlocBuilder<NavCubitPage, int>(builder: (BuildContext context, int state) {
final List<BottomNavigationBarItem> items = [];
ActivityPage.items.forEach((int pageIndex, ActivityPageItem item) {
items.add(BottomNavigationBarItem(
icon: item.icon,
label: tr(item.code),
));
});
return BottomNavigationBar(
currentIndex: state,
onTap: (int index) => BlocProvider.of<NavCubitPage>(context).updateIndex(index),
type: BottomNavigationBarType.fixed,
elevation: 0,
backgroundColor: Colors.transparent,
selectedItemColor: Theme.of(context).colorScheme.primary,
unselectedItemColor: Theme.of(context).textTheme.bodySmall!.color,
items: items,
);
}),
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:plotter/common/config/screen.dart';
import 'package:plotter/common/cubit/nav/nav_cubit_pages.dart';
import 'package:plotter/common/cubit/nav/nav_cubit_screens.dart';
import 'package:plotter/cubit/activity/activity_cubit.dart';
import 'package:plotter/models/activity/activity.dart';
class GlobalAppBar extends StatelessWidget implements PreferredSizeWidget {
const GlobalAppBar({super.key});
@override
Widget build(BuildContext context) {
return BlocBuilder<ActivityCubit, ActivityState>(
builder: (BuildContext context, ActivityState activityState) {
return BlocBuilder<NavCubitScreen, int>(
builder: (BuildContext context, int pageIndex) {
final Activity currentActivity = activityState.currentActivity;
final List<Widget> menuActions = [];
if (currentActivity.isRunning) {
menuActions.add(ActivityButtonQuit(
onPressed: () {},
onLongPress: () {
BlocProvider.of<ActivityCubit>(context).quitActivity();
BlocProvider.of<NavCubitPage>(context).goToPageHome();
},
));
} else {
if (pageIndex == Screen.indexActivity) {
// go to Settings page
menuActions.add(ElevatedButton(
onPressed: () {
BlocProvider.of<NavCubitScreen>(context).goToScreenSettings();
},
style: ElevatedButton.styleFrom(
shape: const CircleBorder(),
),
child: Screen.screenSettings.icon,
));
// go to About page
menuActions.add(ElevatedButton(
onPressed: () {
BlocProvider.of<NavCubitScreen>(context).goToScreenAbout();
},
style: ElevatedButton.styleFrom(
shape: const CircleBorder(),
),
child: Screen.screenAbout.icon,
));
} else {
// back to Home page
menuActions.add(ElevatedButton(
onPressed: () {
BlocProvider.of<NavCubitScreen>(context).goToScreenActivity();
},
style: ElevatedButton.styleFrom(
shape: const CircleBorder(),
),
child: Screen.screenActivity.icon,
));
}
}
return AppBar(
title: const AppHeader(text: 'app_name'),
actions: menuActions,
);
},
);
},
);
}
@override
Size get preferredSize => const Size.fromHeight(50);
}
import 'package:flutter/material.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
class ScreenAbout extends StatelessWidget {
const ScreenAbout({super.key});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
const SizedBox(height: 8),
const AppTitle(text: 'about_title'),
const Text('about_content').tr(),
FutureBuilder<PackageInfo>(
future: PackageInfo.fromPlatform(),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.done:
return const Text('about_version').tr(
namedArgs: {
'version': snapshot.data!.version,
},
);
default:
return const SizedBox();
}
},
),
],
),
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:plotter/common/config/activity_page.dart';
import 'package:plotter/common/cubit/nav/nav_cubit_pages.dart';
class ScreenActivity extends StatelessWidget {
const ScreenActivity({super.key});
@override
Widget build(BuildContext context) {
return BlocBuilder<NavCubitPage, int>(
builder: (BuildContext context, int pageIndex) {
return ActivityPage.getWidget(pageIndex);
},
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
class ScreenSettings extends StatelessWidget {
const ScreenSettings({super.key});
@override
Widget build(BuildContext context) {
return const Padding(
padding: EdgeInsets.symmetric(horizontal: 8),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
SizedBox(height: 8),
AppTitle(text: 'settings_title'),
SizedBox(height: 8),
ApplicationSettingsForm(),
],
),
);
}
}
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart'; import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:plotter/common/cubit/nav/nav_cubit_pages.dart';
import 'package:plotter/cubit/activity/activity_cubit.dart'; import 'package:plotter/cubit/activity/activity_cubit.dart';
import 'package:plotter/ui/pages/home.dart';
import 'package:plotter/ui/pages/plotter.dart';
import 'package:plotter/ui/pages/remote_control.dart';
class ApplicationConfig { class ApplicationConfig {
// plotter type // plotter type
static const String parameterCodePlotterType = 'plotterType'; static const String parameterCodePlotterType = 'plotterType';
...@@ -12,6 +14,11 @@ class ApplicationConfig { ...@@ -12,6 +14,11 @@ class ApplicationConfig {
static const String plotterTypeRadial = 'radial'; static const String plotterTypeRadial = 'radial';
static const String plotterTypeAxial = 'axial'; static const String plotterTypeAxial = 'axial';
// activity pages
static const int activityPageIndexHome = 0;
static const int activityPageIndexPlotter = 1;
static const int activityPageIndexRemoteControl = 2;
static final ApplicationConfigDefinition config = ApplicationConfigDefinition( static final ApplicationConfigDefinition config = ApplicationConfigDefinition(
appTitle: 'Stepper plotter assistant', appTitle: 'Stepper plotter assistant',
activitySettings: [ activitySettings: [
...@@ -34,14 +41,75 @@ class ApplicationConfig { ...@@ -34,14 +41,75 @@ class ApplicationConfig {
], ],
startNewActivity: (BuildContext context) { startNewActivity: (BuildContext context) {
BlocProvider.of<ActivityCubit>(context).startNewActivity(context); BlocProvider.of<ActivityCubit>(context).startNewActivity(context);
BlocProvider.of<NavCubitPage>(context).goToPageHome(); BlocProvider.of<NavCubitPage>(context)
.updateIndex(ApplicationConfig.activityPageIndexPlotter);
},
quitCurrentActivity: (BuildContext context) {
BlocProvider.of<ActivityCubit>(context).quitActivity();
BlocProvider.of<NavCubitPage>(context)
.updateIndex(ApplicationConfig.activityPageIndexHome);
}, },
deleteCurrentActivity: (BuildContext context) { deleteCurrentActivity: (BuildContext context) {
BlocProvider.of<ActivityCubit>(context).deleteSavedActivity(); BlocProvider.of<ActivityCubit>(context).deleteSavedActivity();
}, },
resumeActivity: (BuildContext context) { resumeActivity: (BuildContext context) {
BlocProvider.of<ActivityCubit>(context).resumeSavedActivity(); BlocProvider.of<ActivityCubit>(context).resumeSavedActivity();
BlocProvider.of<NavCubitPage>(context).goToPageHome(); BlocProvider.of<NavCubitPage>(context)
.updateIndex(ApplicationConfig.activityPageIndexPlotter);
}, },
navigation: ApplicationNavigation(
screenActivity: ScreenItem(
code: 'screen_activity',
icon: Icon(UniconsLine.home),
screen: ({required ApplicationConfigDefinition appConfig}) =>
ScreenActivity(appConfig: appConfig),
),
screenSettings: ScreenItem(
code: 'screen_settings',
icon: Icon(UniconsLine.setting),
screen: ({required ApplicationConfigDefinition appConfig}) => ScreenSettings(),
),
screenAbout: ScreenItem(
code: 'screen_about',
icon: Icon(UniconsLine.info_circle),
screen: ({required ApplicationConfigDefinition appConfig}) => ScreenAbout(),
),
displayBottomNavBar: true,
activityPages: {
activityPageIndexHome: ActivityPageItem(
code: 'page_home',
icon: Icon(UniconsLine.home),
builder: ({required ApplicationConfigDefinition appConfig}) {
return BlocBuilder<ActivityCubit, ActivityState>(
builder: (BuildContext context, ActivityState activityState) {
return PageHome();
},
);
},
),
activityPageIndexPlotter: ActivityPageItem(
code: 'page_plotter',
icon: Icon(UniconsLine.robot),
builder: ({required ApplicationConfigDefinition appConfig}) {
return BlocBuilder<ActivityCubit, ActivityState>(
builder: (BuildContext context, ActivityState activityState) {
return PagePlotter();
},
);
},
),
activityPageIndexRemoteControl: ActivityPageItem(
code: 'page_remote_control',
icon: Icon(UniconsLine.pen),
builder: ({required ApplicationConfigDefinition appConfig}) {
return BlocBuilder<ActivityCubit, ActivityState>(
builder: (BuildContext context, ActivityState activityState) {
return PageRemoteControl();
},
);
},
),
},
),
); );
} }
...@@ -4,9 +4,6 @@ import 'package:flutter/material.dart'; ...@@ -4,9 +4,6 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart'; import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:plotter/common/cubit/nav/nav_cubit_pages.dart';
import 'package:plotter/common/cubit/nav/nav_cubit_screens.dart';
import 'package:plotter/config/application_config.dart'; import 'package:plotter/config/application_config.dart';
import 'package:plotter/cubit/activity/activity_cubit.dart'; import 'package:plotter/cubit/activity/activity_cubit.dart';
import 'package:plotter/ui/skeleton.dart'; import 'package:plotter/ui/skeleton.dart';
...@@ -43,7 +40,7 @@ class MyApp extends StatelessWidget { ...@@ -43,7 +40,7 @@ class MyApp extends StatelessWidget {
providers: [ providers: [
// default providers // default providers
BlocProvider<NavCubitPage>( BlocProvider<NavCubitPage>(
create: (context) => NavCubitPage(), create: (context) => NavCubitPage(appConfig: ApplicationConfig.config),
), ),
BlocProvider<NavCubitScreen>( BlocProvider<NavCubitScreen>(
create: (context) => NavCubitScreen(), create: (context) => NavCubitScreen(),
......
File moved
...@@ -4,8 +4,8 @@ import 'package:flutter_custom_toolbox/flutter_toolbox.dart'; ...@@ -4,8 +4,8 @@ import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:plotter/cubit/activity/activity_cubit.dart'; import 'package:plotter/cubit/activity/activity_cubit.dart';
import 'package:plotter/models/activity/activity.dart'; import 'package:plotter/models/activity/activity.dart';
class PagePlayer extends StatelessWidget { class PagePlotter extends StatelessWidget {
const PagePlayer({super.key}); const PagePlotter({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
...@@ -19,7 +19,7 @@ class PagePlayer extends StatelessWidget { ...@@ -19,7 +19,7 @@ class PagePlayer extends StatelessWidget {
children: <Widget>[ children: <Widget>[
const SizedBox(height: 8), const SizedBox(height: 8),
OutlinedText( OutlinedText(
text: '[player]', text: '[plotter]',
fontSize: 50, fontSize: 50,
textColor: Colors.blueAccent, textColor: Colors.blueAccent,
outlineColor: Colors.blueAccent.lighten(20), outlineColor: Colors.blueAccent.lighten(20),
......
File moved
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart'; import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:plotter/common/config/activity_page.dart'; import 'package:plotter/config/application_config.dart';
import 'package:plotter/common/config/screen.dart'; import 'package:plotter/cubit/activity/activity_cubit.dart';
import 'package:plotter/common/cubit/nav/nav_cubit_screens.dart'; import 'package:plotter/models/activity/activity.dart';
import 'package:plotter/common/ui/nav/global_app_bar.dart';
import 'package:plotter/common/ui/nav/bottom_nav_bar.dart';
class SkeletonScreen extends StatelessWidget { class SkeletonScreen extends StatelessWidget {
const SkeletonScreen({super.key}); const SkeletonScreen({super.key});
...@@ -14,22 +12,47 @@ class SkeletonScreen extends StatelessWidget { ...@@ -14,22 +12,47 @@ class SkeletonScreen extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<NavCubitScreen, int>( return BlocBuilder<NavCubitScreen, int>(
builder: (BuildContext context, int screenIndex) { builder: (BuildContext context, int screenIndex) {
return Scaffold( return BlocBuilder<ActivityCubit, ActivityState>(
appBar: const GlobalAppBar(), builder: (BuildContext context, ActivityState activityState) {
extendBodyBehindAppBar: false, return BlocBuilder<NavCubitPage, int>(
body: Material( builder: (BuildContext context, int pageIndex) {
color: Theme.of(context).colorScheme.surface, final Activity currentActivity = activityState.currentActivity;
child: Padding(
padding: const EdgeInsets.only( // autostart activity
top: 8, if (ApplicationConfig.config.autoStartActivity &&
left: 2, (!currentActivity.isRunning)) {
right: 2, ApplicationConfig.config.startNewActivity(context);
), }
child: Screen.getWidget(screenIndex),
), return Scaffold(
), appBar: GlobalAppBar(
backgroundColor: Theme.of(context).colorScheme.surface, appConfig: ApplicationConfig.config,
bottomNavigationBar: ActivityPage.displayBottomNavBar ? const BottomNavBar() : null, pageIndex: pageIndex,
isActivityRunning: currentActivity.isRunning,
),
extendBodyBehindAppBar: false,
body: Material(
color: Theme.of(context).colorScheme.surface,
child: Padding(
padding: const EdgeInsets.only(
top: 8,
left: 2,
right: 2,
),
child: ApplicationConfig.config.navigation.getScreenWidget(
appConfig: ApplicationConfig.config,
screenIndex: screenIndex,
),
),
),
backgroundColor: Theme.of(context).colorScheme.surface,
bottomNavigationBar: ApplicationConfig.config.navigation.displayBottomNavBar
? BottomNavBar(appConfig: ApplicationConfig.config)
: null,
);
},
);
},
); );
}, },
); );
......
...@@ -122,11 +122,11 @@ packages: ...@@ -122,11 +122,11 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
path: "." path: "."
ref: "0.5.0" ref: "0.6.0"
resolved-ref: b8164a50489ba981ea57d9f02e2334f09cb8c6a7 resolved-ref: dfe0f6b7b49f9aa32f085e4a5d3ea320b3611eed
url: "https://git.harrault.fr/android/flutter-toolbox.git" url: "https://git.harrault.fr/android/flutter-toolbox.git"
source: git source: git
version: "0.5.0" version: "0.6.0"
flutter_lints: flutter_lints:
dependency: "direct dev" dependency: "direct dev"
description: description:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment