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

Add "interface type" setting

parent 0218a3d8
Branches
Tags
1 merge request!42Resolve "Add some state tests"
Pipeline #4619 passed
This commit is part of merge request !42. Comments created here will be created in the context of that merge request.
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
app.versionName=1.0.32
app.versionCode=33
app.versionName=1.0.33
app.versionCode=34
......@@ -9,6 +9,9 @@
"settings_title": "Settings",
"settings_label_api_url": "API URL:",
"settings_label_security_token": "Security token:",
"settings_label_interface_type": "Interface type:",
"interface_type_basic": "basic",
"interface_type_expert": "expert",
"settings_button_save": "Save",
"about_title": "About",
......
......@@ -9,6 +9,9 @@
"settings_title": "Paramètres",
"settings_label_api_url": "URL de l'API :",
"settings_label_security_token": "Jeton de sécurité :",
"settings_label_interface_type": "Type d'interface :",
"interface_type_basic": "simple",
"interface_type_expert": "expert",
"settings_button_save": "Enregistrer",
"about_title": "À propos",
......
......@@ -2,12 +2,14 @@ import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:random/models/interface_type.dart';
part 'settings_state.dart';
class SettingsCubit extends HydratedCubit<SettingsState> {
SettingsCubit() : super(const SettingsState());
String getSetting(String key, [String? defaultValue]) {
Object getSetting(String key, [String? defaultValue]) {
if (state.values.keys.contains(key)) {
return state.values[key] ?? defaultValue ?? '';
}
......@@ -15,13 +17,27 @@ class SettingsCubit extends HydratedCubit<SettingsState> {
return defaultValue ?? '';
}
String getApiUrl() {
return state.apiUrl ?? '';
}
String getSecurityToken() {
return state.securityToken ?? '';
}
InterfaceType getInterfaceType() {
return state.interfaceType ?? InterfaceType.basic;
}
void setValues({
String? apiUrl,
String? securityToken,
InterfaceType? interfaceType,
}) {
emit(SettingsState(
apiUrl: apiUrl != null ? apiUrl : state.apiUrl,
securityToken: securityToken != null ? securityToken : state.securityToken,
interfaceType: interfaceType != null ? interfaceType : state.interfaceType,
));
}
......@@ -29,10 +45,23 @@ class SettingsCubit extends HydratedCubit<SettingsState> {
SettingsState? fromJson(Map<String, dynamic> json) {
String apiUrl = json['apiUrl'] as String;
String securityToken = json['securityToken'] as String;
InterfaceType interfaceType;
switch (json['interfaceType'] as String) {
case 'InterfaceType.basic':
interfaceType = InterfaceType.basic;
break;
case 'InterfaceType.expert':
interfaceType = InterfaceType.expert;
break;
default:
interfaceType = InterfaceType.basic;
}
return SettingsState(
apiUrl: apiUrl,
securityToken: securityToken,
interfaceType: interfaceType,
);
}
......@@ -41,6 +70,7 @@ class SettingsCubit extends HydratedCubit<SettingsState> {
return <String, String>{
'apiUrl': state.apiUrl ?? '',
'securityToken': state.securityToken ?? '',
'interfaceType': state.interfaceType.toString(),
};
}
}
......@@ -5,19 +5,23 @@ class SettingsState extends Equatable {
const SettingsState({
this.apiUrl,
this.securityToken,
this.interfaceType,
});
final String? apiUrl;
final String? securityToken;
final InterfaceType? interfaceType;
@override
List<String?> get props => <String?>[
apiUrl,
securityToken,
interfaceType.toString(),
];
Map<String, String?> get values => <String, String?>{
'apiUrl': apiUrl,
'securityToken': securityToken,
'interfaceType': interfaceType.toString(),
};
}
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
enum InterfaceType {
basic,
expert,
}
class InterfaceTypes {
static List<Widget> selectWidgets = <Widget>[
Text('interface_type_basic').tr(),
Text('interface_type_expert').tr(),
];
}
......@@ -78,9 +78,10 @@ class DemoPage extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('apiUrl: ' + settings.getSetting('apiUrl')),
Text('securityToken: ' + settings.getSetting('securityToken')),
Text('unknown: ' + settings.getSetting('unknown', 'undefined')),
Text('apiUrl: ' + settings.getApiUrl()),
Text('securityToken: ' + settings.getSecurityToken()),
Text('interfaceType: ' + settings.getInterfaceType().toString()),
Text('unknown: ' + settings.getSetting('unknown', 'undefined').toString()),
],
);
},
......
......@@ -21,6 +21,8 @@ class SkeletonScreen extends StatefulWidget {
class _SkeletonScreenState extends State<SkeletonScreen> {
@override
Widget build(BuildContext context) {
print('SkeletonScreen - build');
const List<Widget> pageNavigation = <Widget>[
DemoPage(),
GraphPage(),
......
import 'package:flutter/material.dart';
import 'package:unicons/unicons.dart';
import 'package:random/ui/widgets/header_app.dart';
......@@ -8,13 +7,12 @@ class StandardAppBar extends StatelessWidget implements PreferredSizeWidget {
@override
Widget build(BuildContext context) {
print('StandardAppBar - build');
return AppBar(
title: const AppHeader(text: 'app_name'),
title: AppHeader(text: 'app_name'),
actions: [
IconButton(
onPressed: () {},
icon: const Icon(UniconsSolid.refresh),
),
//
],
);
}
......
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:random/cubit/settings_cubit.dart';
import 'package:random/models/interface_type.dart';
class AppHeader extends StatelessWidget {
const AppHeader({super.key, required this.text});
......@@ -8,10 +12,24 @@ class AppHeader extends StatelessWidget {
@override
Widget build(BuildContext context) {
print('AppHeader - build (' + this.text + ')');
return BlocProvider<SettingsCubit>(
create: (BuildContext context) => SettingsCubit(),
child: BlocBuilder<SettingsCubit, SettingsState>(
builder: (BuildContext context, SettingsState state) {
SettingsCubit settings = BlocProvider.of<SettingsCubit>(context);
bool isExpert = settings.getInterfaceType() == InterfaceType.expert;
String titleSuffix = isExpert ? ' ⭐' : '';
return Text(
tr(text),
tr(text) + titleSuffix,
textAlign: TextAlign.start,
style: Theme.of(context).textTheme.headlineMedium!.apply(fontWeightDelta: 2),
);
},
),
);
}
}
......@@ -5,6 +5,8 @@ import 'package:unicons/unicons.dart';
import 'package:random/cubit/bottom_nav_cubit.dart';
import 'package:random/cubit/settings_cubit.dart';
import 'package:random/config/theme.dart';
import 'package:random/models/interface_type.dart';
class SettingsForm extends StatefulWidget {
const SettingsForm({super.key});
......@@ -16,6 +18,7 @@ class SettingsForm extends StatefulWidget {
class _SettingsFormState extends State<SettingsForm> {
final apiUrlController = TextEditingController();
final securityTokenController = TextEditingController();
final List<Widget> interfaceTypesWidgets = InterfaceTypes.selectWidgets;
@override
void dispose() {
......@@ -24,17 +27,26 @@ class _SettingsFormState extends State<SettingsForm> {
super.dispose();
}
List<bool> _selectedInterfaceType = <bool>[];
@override
Widget build(BuildContext context) {
SettingsCubit settings = BlocProvider.of<SettingsCubit>(context);
apiUrlController.text = settings.getSetting('apiUrl');
securityTokenController.text = settings.getSetting('securityToken');
apiUrlController.text = settings.getApiUrl();
securityTokenController.text = settings.getSecurityToken();
if (_selectedInterfaceType.length != 2) {
_selectedInterfaceType = <bool>[
settings.getInterfaceType() == InterfaceType.basic,
settings.getInterfaceType() == InterfaceType.expert,
];
}
void saveSettings() {
BlocProvider.of<SettingsCubit>(context).setValues(
apiUrl: apiUrlController.text,
securityToken: securityTokenController.text,
interfaceType: _selectedInterfaceType[0] ? InterfaceType.basic : InterfaceType.expert,
);
BlocProvider.of<BottomNavCubit>(context).getDemoPage();
......@@ -61,6 +73,27 @@ class _SettingsFormState extends State<SettingsForm> {
),
),
SizedBox(height: 16),
Text('settings_label_interface_type').tr(),
ToggleButtons(
direction: Axis.horizontal,
onPressed: (int index) {
setState(() {
_selectedInterfaceType = index == 0 ? [true, false] : [false, true];
});
},
borderRadius: const BorderRadius.all(Radius.circular(8)),
selectedBorderColor: appTheme.primaryColor,
selectedColor: appTheme.colorScheme.onSecondary,
fillColor: appTheme.colorScheme.secondary,
color: appTheme.primaryColor,
constraints: const BoxConstraints(
minHeight: 40.0,
minWidth: 80.0,
),
isSelected: _selectedInterfaceType,
children: interfaceTypesWidgets,
),
SizedBox(height: 20),
ElevatedButton(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
......
......@@ -45,10 +45,10 @@ packages:
dependency: transitive
description:
name: collection
sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
url: "https://pub.dev"
source: hosted
version: "1.17.2"
version: "1.18.0"
crypto:
dependency: transitive
description:
......@@ -172,10 +172,10 @@ packages:
dependency: transitive
description:
name: meta
sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
url: "https://pub.dev"
source: hosted
version: "1.9.1"
version: "1.10.0"
nested:
dependency: transitive
description:
......@@ -188,10 +188,10 @@ packages:
dependency: "direct main"
description:
name: package_info_plus
sha256: "7e76fad405b3e4016cd39d08f455a4eb5199723cf594cd1b8916d47140d93017"
sha256: "88bc797f44a94814f2213db1c9bd5badebafdfb8290ca9f78d4b9ee2a3db4d79"
url: "https://pub.dev"
source: hosted
version: "4.2.0"
version: "5.0.1"
package_info_plus_platform_interface:
dependency: transitive
description:
......@@ -268,18 +268,18 @@ packages:
dependency: transitive
description:
name: plugin_platform_interface
sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d
sha256: f4f88d4a900933e7267e2b353594774fc0d07fb072b47eedcd5b54e1ea3269f8
url: "https://pub.dev"
source: hosted
version: "2.1.6"
version: "2.1.7"
provider:
dependency: transitive
description:
name: provider
sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f
sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096"
url: "https://pub.dev"
source: hosted
version: "6.0.5"
version: "6.1.1"
shared_preferences:
dependency: transitive
description:
......@@ -324,10 +324,10 @@ packages:
dependency: transitive
description:
name: shared_preferences_web
sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf
sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21"
url: "https://pub.dev"
source: hosted
version: "2.2.1"
version: "2.2.2"
shared_preferences_windows:
dependency: transitive
description:
......@@ -401,18 +401,18 @@ packages:
dependency: transitive
description:
name: web
sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
url: "https://pub.dev"
source: hosted
version: "0.1.4-beta"
version: "0.3.0"
win32:
dependency: transitive
description:
name: win32
sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3"
sha256: "7c99c0e1e2fa190b48d25c81ca5e42036d5cac81430ef249027d97b0935c553f"
url: "https://pub.dev"
source: hosted
version: "5.0.9"
version: "5.1.0"
xdg_directories:
dependency: transitive
description:
......@@ -422,5 +422,5 @@ packages:
source: hosted
version: "1.0.3"
sdks:
dart: ">=3.1.0-185.0.dev <4.0.0"
flutter: ">=3.7.0"
dart: ">=3.2.0 <4.0.0"
flutter: ">=3.16.0"
......@@ -3,7 +3,7 @@ description: A random application, for testing purpose only.
publish_to: 'none'
version: 1.0.32+33
version: 1.0.33+34
environment:
sdk: '^3.0.0'
......@@ -18,7 +18,7 @@ dependencies:
path_provider: ^2.0.11
hydrated_bloc: ^9.0.0
unicons: ^2.1.1
package_info_plus: ^4.2.0
package_info_plus: ^5.0.1
flutter:
uses-material-design: false
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment