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

Merge branch '46-fix-data-propagation-between-widgets' into 'master'

Resolve "Fix data propagation between widgets"

Closes #46

See merge request !45
parents 0bf5f2f5 a5636c7a
No related branches found
No related tags found
1 merge request!45Resolve "Fix data propagation between widgets"
Pipeline #4650 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