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

Fix data propagation between widgets

parent 0bf5f2f5
No related branches found
No related tags found
1 merge request!45Resolve "Fix data propagation between widgets"
Pipeline #4648 passed
org.gradle.jvmargs=-Xmx1536M org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true android.useAndroidX=true
android.enableJetifier=true android.enableJetifier=true
app.versionName=1.0.35 app.versionName=1.0.36
app.versionCode=36 app.versionCode=37
...@@ -11,6 +11,10 @@ class DataCubit extends HydratedCubit<DataState> { ...@@ -11,6 +11,10 @@ class DataCubit extends HydratedCubit<DataState> {
emit(state); emit(state);
} }
void updateCounter(int delta) {
emit(DataState(counter: (state.counter ?? 0) + delta));
}
@override @override
DataState? fromJson(Map<String, dynamic> json) { DataState? fromJson(Map<String, dynamic> json) {
int counter = json['counter'] as int; int counter = json['counter'] as int;
......
...@@ -2,11 +2,15 @@ import 'dart:io'; ...@@ -2,11 +2,15 @@ import 'dart:io';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart'; import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:random/config/theme.dart'; import 'package:random/config/theme.dart';
import 'package:random/cubit/bottom_nav_cubit.dart';
import 'package:random/cubit/data_cubit.dart';
import 'package:random/cubit/settings_cubit.dart';
import 'package:random/ui/skeleton.dart'; import 'package:random/ui/skeleton.dart';
void main() async { void main() async {
...@@ -38,14 +42,21 @@ class MyApp extends StatelessWidget { ...@@ -38,14 +42,21 @@ class MyApp extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MaterialApp( return MultiBlocProvider(
title: 'Random application', providers: [
theme: appTheme, BlocProvider<SettingsCubit>(create: (context) => SettingsCubit()),
home: SkeletonScreen(), BlocProvider<BottomNavCubit>(create: (context) => BottomNavCubit()),
localizationsDelegates: context.localizationDelegates, BlocProvider<DataCubit>(create: (context) => DataCubit()),
supportedLocales: context.supportedLocales, ],
locale: context.locale, child: MaterialApp(
debugShowCheckedModeBanner: false, title: 'Random application',
theme: appTheme,
home: SkeletonScreen(),
localizationsDelegates: context.localizationDelegates,
supportedLocales: context.supportedLocales,
locale: context.locale,
debugShowCheckedModeBanner: false,
),
); );
} }
} }
...@@ -21,7 +21,10 @@ class DemoPage extends StatelessWidget { ...@@ -21,7 +21,10 @@ class DemoPage extends StatelessWidget {
SizedBox(height: 8), SizedBox(height: 8),
AppHeader(text: 'TOP'), AppHeader(text: 'TOP'),
SizedBox(height: 20), SizedBox(height: 20),
persistedCounterBlock(), persistedCounterBlock(BlocProvider.of<DataCubit>(context)),
SizedBox(height: 20),
testBlocConsumer(),
testBlocBuilder(),
SizedBox(height: 20), SizedBox(height: 20),
fakeApiCall(), fakeApiCall(),
SizedBox(height: 20), SizedBox(height: 20),
...@@ -31,61 +34,68 @@ class DemoPage extends StatelessWidget { ...@@ -31,61 +34,68 @@ class DemoPage extends StatelessWidget {
); );
} }
Widget persistedCounterBlock() { Widget persistedCounterBlock(DataCubit dataCubit) {
return BlocProvider<DataCubit>( return Row(
create: (BuildContext context) => DataCubit(), mainAxisAlignment: MainAxisAlignment.center,
child: BlocBuilder<DataCubit, DataState>( crossAxisAlignment: CrossAxisAlignment.center,
builder: (BuildContext context, DataState state) { children: [
void updateCounter(int delta) { IconButton(
BlocProvider.of<DataCubit>(context).getData( icon: Icon(UniconsSolid.arrow_circle_down),
DataState(counter: (state.counter ?? 0) + delta), color: appTheme.primaryColor,
); onPressed: () => dataCubit.updateCounter(-1),
} ),
testBlocConsumer(),
return Row( IconButton(
mainAxisAlignment: MainAxisAlignment.center, icon: Icon(UniconsSolid.arrow_circle_up),
crossAxisAlignment: CrossAxisAlignment.center, color: appTheme.primaryColor,
children: [ onPressed: () => dataCubit.updateCounter(1),
IconButton( ),
icon: Icon(UniconsSolid.arrow_circle_down), ],
color: appTheme.primaryColor,
onPressed: () => updateCounter(-1),
),
Padding(
padding: EdgeInsets.all(10),
child: Text(state.counter.toString()),
),
IconButton(
icon: Icon(UniconsSolid.arrow_circle_up),
color: appTheme.primaryColor,
onPressed: () => updateCounter(1),
),
],
);
},
),
); );
} }
Widget fakeApiCall() { Widget fakeApiCall() {
return BlocProvider<SettingsCubit>( return BlocBuilder<SettingsCubit, SettingsState>(
create: (BuildContext context) => SettingsCubit(), builder: (context, settingsSate) {
child: BlocBuilder<SettingsCubit, SettingsState>( return Column(
builder: (BuildContext context, SettingsState state) { mainAxisAlignment: MainAxisAlignment.center,
SettingsCubit settings = BlocProvider.of<SettingsCubit>(context); crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('apiUrl: ' + settingsSate.apiUrl.toString()),
Text('securityToken: ' + (settingsSate.securityToken.toString())),
Text('interfaceType: ' + settingsSate.interfaceType.toString()),
],
);
},
);
}
return Column( Widget testBlocConsumer() {
mainAxisAlignment: MainAxisAlignment.center, return BlocConsumer<DataCubit, DataState>(
crossAxisAlignment: CrossAxisAlignment.center, listener: (context, dataState) {
children: [ // do stuff here based on state
Text('apiUrl: ' + settings.getApiUrl()), },
Text('securityToken: ' + settings.getSecurityToken()), builder: (context, dataState) {
Text('interfaceType: ' + settings.getInterfaceType().toString()), // return widget here based on state
Text('unknown: ' + settings.getSetting('unknown', 'undefined').toString()), return Text('BlocConsumer / ' + dataState.toString());
], },
); );
}, }
),
Widget testBlocListener() {
return BlocListener<DataCubit, DataState>(
listener: (context, dataState) {
// do stuff here based on state
},
);
}
Widget testBlocBuilder() {
return BlocBuilder<DataCubit, DataState>(
builder: (context, dataState) {
// return widget here based on state
return Text('BlocBuilder / ' + dataState.toString());
},
); );
} }
} }
...@@ -3,7 +3,6 @@ import 'package:flutter_bloc/flutter_bloc.dart'; ...@@ -3,7 +3,6 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_swipe/flutter_swipe.dart'; import 'package:flutter_swipe/flutter_swipe.dart';
import 'package:random/cubit/bottom_nav_cubit.dart'; import 'package:random/cubit/bottom_nav_cubit.dart';
import 'package:random/cubit/settings_cubit.dart';
import 'package:random/ui/screens/about_page.dart'; import 'package:random/ui/screens/about_page.dart';
import 'package:random/ui/screens/demo_page.dart'; import 'package:random/ui/screens/demo_page.dart';
import 'package:random/ui/screens/graph_page.dart'; import 'package:random/ui/screens/graph_page.dart';
...@@ -21,8 +20,6 @@ class SkeletonScreen extends StatefulWidget { ...@@ -21,8 +20,6 @@ class SkeletonScreen extends StatefulWidget {
class _SkeletonScreenState extends State<SkeletonScreen> { class _SkeletonScreenState extends State<SkeletonScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
print('SkeletonScreen - build');
const List<Widget> pageNavigation = <Widget>[ const List<Widget> pageNavigation = <Widget>[
DemoPage(), DemoPage(),
GraphPage(), GraphPage(),
...@@ -30,41 +27,28 @@ class _SkeletonScreenState extends State<SkeletonScreen> { ...@@ -30,41 +27,28 @@ class _SkeletonScreenState extends State<SkeletonScreen> {
AboutPage(), AboutPage(),
]; ];
return BlocProvider<SettingsCubit>( return Scaffold(
create: (BuildContext context) => SettingsCubit(), extendBodyBehindAppBar: false,
child: BlocProvider<BottomNavCubit>( appBar: StandardAppBar(),
create: (BuildContext context) => BottomNavCubit(), body: Swiper(
child: BlocBuilder<BottomNavCubit, int>( itemCount: BlocProvider.of<BottomNavCubit>(context).pagesCount,
builder: (BuildContext context, int state) { itemBuilder: (BuildContext context, int index) {
return Scaffold( return pageNavigation.elementAt(index);
extendBodyBehindAppBar: false, },
appBar: StandardAppBar(), pagination: SwiperPagination(
body: Swiper( builder: SwiperCustomPagination(
itemCount: BlocProvider.of<BottomNavCubit>(context).pagesCount, builder: (BuildContext context, SwiperPluginConfig config) {
itemBuilder: (BuildContext context, int index) { return BottomNavBar(swipeController: config.controller);
return AnimatedSwitcher( },
duration: const Duration(milliseconds: 300), ),
child: pageNavigation.elementAt(index),
);
},
pagination: SwiperPagination(
builder: SwiperCustomPagination(
builder: (BuildContext context, SwiperPluginConfig config) {
return BottomNavBar(swipeController: config.controller);
},
),
),
onIndexChanged: (newPageIndex) {
BlocProvider.of<BottomNavCubit>(context).updateIndex(newPageIndex);
},
outer: true,
loop: false,
),
backgroundColor: Theme.of(context).colorScheme.background,
);
},
), ),
onIndexChanged: (newPageIndex) {
BlocProvider.of<BottomNavCubit>(context).updateIndex(newPageIndex);
},
outer: true,
loop: false,
), ),
backgroundColor: Theme.of(context).colorScheme.background,
); );
} }
} }
...@@ -7,8 +7,6 @@ class StandardAppBar extends StatelessWidget implements PreferredSizeWidget { ...@@ -7,8 +7,6 @@ class StandardAppBar extends StatelessWidget implements PreferredSizeWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
print('StandardAppBar - build');
return AppBar( return AppBar(
title: AppHeader(text: 'app_name'), title: AppHeader(text: 'app_name'),
actions: [ actions: [
......
...@@ -2,6 +2,7 @@ import 'package:easy_localization/easy_localization.dart'; ...@@ -2,6 +2,7 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:random/cubit/data_cubit.dart';
import 'package:random/cubit/settings_cubit.dart'; import 'package:random/cubit/settings_cubit.dart';
import 'package:random/models/interface_type.dart'; import 'package:random/models/interface_type.dart';
...@@ -12,24 +13,38 @@ class AppHeader extends StatelessWidget { ...@@ -12,24 +13,38 @@ class AppHeader extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
print('AppHeader - build (' + this.text + ')'); return Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
tr(text),
textAlign: TextAlign.start,
style: Theme.of(context).textTheme.headlineMedium!.apply(fontWeightDelta: 2),
),
SizedBox(width: 2),
expertInterfaceIndicator(),
SizedBox(width: 2),
dataCounterIndicator(),
],
);
}
return BlocProvider<SettingsCubit>( Widget expertInterfaceIndicator() {
create: (BuildContext context) => SettingsCubit(), return BlocBuilder<SettingsCubit, SettingsState>(
child: BlocBuilder<SettingsCubit, SettingsState>( builder: (BuildContext context, SettingsState settingsState) {
builder: (BuildContext context, SettingsState state) { bool isExpert = settingsState.interfaceType == InterfaceType.expert;
SettingsCubit settings = BlocProvider.of<SettingsCubit>(context);
bool isExpert = settings.getInterfaceType() == InterfaceType.expert; return Text(isExpert ? '⭐' : '');
String titleSuffix = isExpert ? ' ⭐' : ''; },
);
}
return Text( Widget dataCounterIndicator() {
tr(text) + titleSuffix, return BlocBuilder<DataCubit, DataState>(
textAlign: TextAlign.start, builder: (context, dataState) {
style: Theme.of(context).textTheme.headlineMedium!.apply(fontWeightDelta: 2), return Text('(' + dataState.counter.toString() + ')');
); },
},
),
); );
} }
} }
...@@ -3,7 +3,7 @@ description: A random application, for testing purpose only. ...@@ -3,7 +3,7 @@ description: A random application, for testing purpose only.
publish_to: 'none' publish_to: 'none'
version: 1.0.35+36 version: 1.0.36+37
environment: environment:
sdk: '^3.0.0' sdk: '^3.0.0'
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment