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
android.useAndroidX=true
android.enableJetifier=true
app.versionName=1.0.35
app.versionCode=36
app.versionName=1.0.36
app.versionCode=37
......@@ -11,6 +11,10 @@ class DataCubit extends HydratedCubit<DataState> {
emit(state);
}
void updateCounter(int delta) {
emit(DataState(counter: (state.counter ?? 0) + delta));
}
@override
DataState? fromJson(Map<String, dynamic> json) {
int counter = json['counter'] as int;
......
......@@ -2,11 +2,15 @@ import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hive/hive.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:path_provider/path_provider.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';
void main() async {
......@@ -38,14 +42,21 @@ class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Random application',
theme: appTheme,
home: SkeletonScreen(),
localizationsDelegates: context.localizationDelegates,
supportedLocales: context.supportedLocales,
locale: context.locale,
debugShowCheckedModeBanner: false,
return MultiBlocProvider(
providers: [
BlocProvider<SettingsCubit>(create: (context) => SettingsCubit()),
BlocProvider<BottomNavCubit>(create: (context) => BottomNavCubit()),
BlocProvider<DataCubit>(create: (context) => DataCubit()),
],
child: MaterialApp(
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 {
SizedBox(height: 8),
AppHeader(text: 'TOP'),
SizedBox(height: 20),
persistedCounterBlock(),
persistedCounterBlock(BlocProvider.of<DataCubit>(context)),
SizedBox(height: 20),
testBlocConsumer(),
testBlocBuilder(),
SizedBox(height: 20),
fakeApiCall(),
SizedBox(height: 20),
......@@ -31,61 +34,68 @@ class DemoPage extends StatelessWidget {
);
}
Widget persistedCounterBlock() {
return BlocProvider<DataCubit>(
create: (BuildContext context) => DataCubit(),
child: BlocBuilder<DataCubit, DataState>(
builder: (BuildContext context, DataState state) {
void updateCounter(int delta) {
BlocProvider.of<DataCubit>(context).getData(
DataState(counter: (state.counter ?? 0) + delta),
);
}
return Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
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 persistedCounterBlock(DataCubit dataCubit) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
IconButton(
icon: Icon(UniconsSolid.arrow_circle_down),
color: appTheme.primaryColor,
onPressed: () => dataCubit.updateCounter(-1),
),
testBlocConsumer(),
IconButton(
icon: Icon(UniconsSolid.arrow_circle_up),
color: appTheme.primaryColor,
onPressed: () => dataCubit.updateCounter(1),
),
],
);
}
Widget fakeApiCall() {
return BlocProvider<SettingsCubit>(
create: (BuildContext context) => SettingsCubit(),
child: BlocBuilder<SettingsCubit, SettingsState>(
builder: (BuildContext context, SettingsState state) {
SettingsCubit settings = BlocProvider.of<SettingsCubit>(context);
return BlocBuilder<SettingsCubit, SettingsState>(
builder: (context, settingsSate) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('apiUrl: ' + settingsSate.apiUrl.toString()),
Text('securityToken: ' + (settingsSate.securityToken.toString())),
Text('interfaceType: ' + settingsSate.interfaceType.toString()),
],
);
},
);
}
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('apiUrl: ' + settings.getApiUrl()),
Text('securityToken: ' + settings.getSecurityToken()),
Text('interfaceType: ' + settings.getInterfaceType().toString()),
Text('unknown: ' + settings.getSetting('unknown', 'undefined').toString()),
],
);
},
),
Widget testBlocConsumer() {
return BlocConsumer<DataCubit, DataState>(
listener: (context, dataState) {
// do stuff here based on state
},
builder: (context, dataState) {
// return widget here based on state
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';
import 'package:flutter_swipe/flutter_swipe.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/demo_page.dart';
import 'package:random/ui/screens/graph_page.dart';
......@@ -21,8 +20,6 @@ class SkeletonScreen extends StatefulWidget {
class _SkeletonScreenState extends State<SkeletonScreen> {
@override
Widget build(BuildContext context) {
print('SkeletonScreen - build');
const List<Widget> pageNavigation = <Widget>[
DemoPage(),
GraphPage(),
......@@ -30,41 +27,28 @@ class _SkeletonScreenState extends State<SkeletonScreen> {
AboutPage(),
];
return BlocProvider<SettingsCubit>(
create: (BuildContext context) => SettingsCubit(),
child: BlocProvider<BottomNavCubit>(
create: (BuildContext context) => BottomNavCubit(),
child: BlocBuilder<BottomNavCubit, int>(
builder: (BuildContext context, int state) {
return Scaffold(
extendBodyBehindAppBar: false,
appBar: StandardAppBar(),
body: Swiper(
itemCount: BlocProvider.of<BottomNavCubit>(context).pagesCount,
itemBuilder: (BuildContext context, int index) {
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,
);
},
return Scaffold(
extendBodyBehindAppBar: false,
appBar: StandardAppBar(),
body: Swiper(
itemCount: BlocProvider.of<BottomNavCubit>(context).pagesCount,
itemBuilder: (BuildContext context, int index) {
return 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,
);
}
}
......@@ -7,8 +7,6 @@ class StandardAppBar extends StatelessWidget implements PreferredSizeWidget {
@override
Widget build(BuildContext context) {
print('StandardAppBar - build');
return AppBar(
title: AppHeader(text: 'app_name'),
actions: [
......
......@@ -2,6 +2,7 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.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/models/interface_type.dart';
......@@ -12,24 +13,38 @@ class AppHeader extends StatelessWidget {
@override
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>(
create: (BuildContext context) => SettingsCubit(),
child: BlocBuilder<SettingsCubit, SettingsState>(
builder: (BuildContext context, SettingsState state) {
SettingsCubit settings = BlocProvider.of<SettingsCubit>(context);
Widget expertInterfaceIndicator() {
return BlocBuilder<SettingsCubit, SettingsState>(
builder: (BuildContext context, SettingsState settingsState) {
bool isExpert = settingsState.interfaceType == InterfaceType.expert;
bool isExpert = settings.getInterfaceType() == InterfaceType.expert;
String titleSuffix = isExpert ? ' ⭐' : '';
return Text(isExpert ? '⭐' : '');
},
);
}
return Text(
tr(text) + titleSuffix,
textAlign: TextAlign.start,
style: Theme.of(context).textTheme.headlineMedium!.apply(fontWeightDelta: 2),
);
},
),
Widget dataCounterIndicator() {
return BlocBuilder<DataCubit, DataState>(
builder: (context, dataState) {
return Text('(' + dataState.counter.toString() + ')');
},
);
}
}
......@@ -3,7 +3,7 @@ description: A random application, for testing purpose only.
publish_to: 'none'
version: 1.0.35+36
version: 1.0.36+37
environment:
sdk: '^3.0.0'
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment