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

Add "interface type" setting

parent 0218a3d8
No related branches found
No related tags found
No related merge requests found
Pipeline #4616 failed
...@@ -9,6 +9,9 @@ ...@@ -9,6 +9,9 @@
"settings_title": "Settings", "settings_title": "Settings",
"settings_label_api_url": "API URL:", "settings_label_api_url": "API URL:",
"settings_label_security_token": "Security token:", "settings_label_security_token": "Security token:",
"settings_label_interface_type": "Interface type:",
"interface_type_basic": "basic",
"interface_type_expert": "expert",
"settings_button_save": "Save", "settings_button_save": "Save",
"about_title": "About", "about_title": "About",
......
...@@ -9,6 +9,9 @@ ...@@ -9,6 +9,9 @@
"settings_title": "Paramètres", "settings_title": "Paramètres",
"settings_label_api_url": "URL de l'API :", "settings_label_api_url": "URL de l'API :",
"settings_label_security_token": "Jeton de sécurité :", "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", "settings_button_save": "Enregistrer",
"about_title": "À propos", "about_title": "À propos",
......
...@@ -2,12 +2,14 @@ import 'package:equatable/equatable.dart'; ...@@ -2,12 +2,14 @@ import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart'; import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:random/models/interface_type.dart';
part 'settings_state.dart'; part 'settings_state.dart';
class SettingsCubit extends HydratedCubit<SettingsState> { class SettingsCubit extends HydratedCubit<SettingsState> {
SettingsCubit() : super(const SettingsState()); SettingsCubit() : super(const SettingsState());
String getSetting(String key, [String? defaultValue]) { Object getSetting(String key, [String? defaultValue]) {
if (state.values.keys.contains(key)) { if (state.values.keys.contains(key)) {
return state.values[key] ?? defaultValue ?? ''; return state.values[key] ?? defaultValue ?? '';
} }
...@@ -15,13 +17,27 @@ class SettingsCubit extends HydratedCubit<SettingsState> { ...@@ -15,13 +17,27 @@ class SettingsCubit extends HydratedCubit<SettingsState> {
return defaultValue ?? ''; return defaultValue ?? '';
} }
String getApiUrl() {
return state.apiUrl ?? '';
}
String getSecurityToken() {
return state.securityToken ?? '';
}
InterfaceType getInterfaceType() {
return state.interfaceType ?? InterfaceType.basic;
}
void setValues({ void setValues({
String? apiUrl, String? apiUrl,
String? securityToken, String? securityToken,
InterfaceType? interfaceType,
}) { }) {
emit(SettingsState( emit(SettingsState(
apiUrl: apiUrl != null ? apiUrl : state.apiUrl, apiUrl: apiUrl != null ? apiUrl : state.apiUrl,
securityToken: securityToken != null ? securityToken : state.securityToken, securityToken: securityToken != null ? securityToken : state.securityToken,
interfaceType: interfaceType != null ? interfaceType : state.interfaceType,
)); ));
} }
...@@ -29,10 +45,23 @@ class SettingsCubit extends HydratedCubit<SettingsState> { ...@@ -29,10 +45,23 @@ class SettingsCubit extends HydratedCubit<SettingsState> {
SettingsState? fromJson(Map<String, dynamic> json) { SettingsState? fromJson(Map<String, dynamic> json) {
String apiUrl = json['apiUrl'] as String; String apiUrl = json['apiUrl'] as String;
String securityToken = json['securityToken'] 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( return SettingsState(
apiUrl: apiUrl, apiUrl: apiUrl,
securityToken: securityToken, securityToken: securityToken,
interfaceType: interfaceType,
); );
} }
...@@ -41,6 +70,7 @@ class SettingsCubit extends HydratedCubit<SettingsState> { ...@@ -41,6 +70,7 @@ class SettingsCubit extends HydratedCubit<SettingsState> {
return <String, String>{ return <String, String>{
'apiUrl': state.apiUrl ?? '', 'apiUrl': state.apiUrl ?? '',
'securityToken': state.securityToken ?? '', 'securityToken': state.securityToken ?? '',
'interfaceType': state.interfaceType.toString(),
}; };
} }
} }
...@@ -5,19 +5,23 @@ class SettingsState extends Equatable { ...@@ -5,19 +5,23 @@ class SettingsState extends Equatable {
const SettingsState({ const SettingsState({
this.apiUrl, this.apiUrl,
this.securityToken, this.securityToken,
this.interfaceType,
}); });
final String? apiUrl; final String? apiUrl;
final String? securityToken; final String? securityToken;
final InterfaceType? interfaceType;
@override @override
List<String?> get props => <String?>[ List<String?> get props => <String?>[
apiUrl, apiUrl,
securityToken, securityToken,
interfaceType.toString(),
]; ];
Map<String, String?> get values => <String, String?>{ Map<String, String?> get values => <String, String?>{
'apiUrl': apiUrl, 'apiUrl': apiUrl,
'securityToken': securityToken, '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 { ...@@ -78,9 +78,10 @@ class DemoPage extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
Text('apiUrl: ' + settings.getSetting('apiUrl')), Text('apiUrl: ' + settings.getApiUrl()),
Text('securityToken: ' + settings.getSetting('securityToken')), Text('securityToken: ' + settings.getSecurityToken()),
Text('unknown: ' + settings.getSetting('unknown', 'undefined')), Text('interfaceType: ' + settings.getInterfaceType().toString()),
Text('unknown: ' + settings.getSetting('unknown', 'undefined').toString()),
], ],
); );
}, },
......
...@@ -21,6 +21,8 @@ class SkeletonScreen extends StatefulWidget { ...@@ -21,6 +21,8 @@ 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(),
......
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:unicons/unicons.dart';
import 'package:random/ui/widgets/header_app.dart'; import 'package:random/ui/widgets/header_app.dart';
...@@ -8,13 +7,12 @@ class StandardAppBar extends StatelessWidget implements PreferredSizeWidget { ...@@ -8,13 +7,12 @@ class StandardAppBar extends StatelessWidget implements PreferredSizeWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
print('StandardAppBar - build');
return AppBar( return AppBar(
title: const AppHeader(text: 'app_name'), title: AppHeader(text: 'app_name'),
actions: [ actions: [
IconButton( //
onPressed: () {},
icon: const Icon(UniconsSolid.refresh),
),
], ],
); );
} }
......
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:random/cubit/settings_cubit.dart';
import 'package:random/models/interface_type.dart';
class AppHeader extends StatelessWidget { class AppHeader extends StatelessWidget {
const AppHeader({super.key, required this.text}); const AppHeader({super.key, required this.text});
...@@ -8,10 +12,24 @@ class AppHeader extends StatelessWidget { ...@@ -8,10 +12,24 @@ class AppHeader extends StatelessWidget {
@override @override
Widget build(BuildContext context) { 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( return Text(
tr(text), tr(text) + titleSuffix,
textAlign: TextAlign.start, textAlign: TextAlign.start,
style: Theme.of(context).textTheme.headlineMedium!.apply(fontWeightDelta: 2), style: Theme.of(context).textTheme.headlineMedium!.apply(fontWeightDelta: 2),
); );
},
),
);
} }
} }
...@@ -5,6 +5,8 @@ import 'package:unicons/unicons.dart'; ...@@ -5,6 +5,8 @@ import 'package:unicons/unicons.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/cubit/settings_cubit.dart';
import 'package:random/config/theme.dart';
import 'package:random/models/interface_type.dart';
class SettingsForm extends StatefulWidget { class SettingsForm extends StatefulWidget {
const SettingsForm({super.key}); const SettingsForm({super.key});
...@@ -16,6 +18,7 @@ class SettingsForm extends StatefulWidget { ...@@ -16,6 +18,7 @@ class SettingsForm extends StatefulWidget {
class _SettingsFormState extends State<SettingsForm> { class _SettingsFormState extends State<SettingsForm> {
final apiUrlController = TextEditingController(); final apiUrlController = TextEditingController();
final securityTokenController = TextEditingController(); final securityTokenController = TextEditingController();
final List<Widget> interfaceTypesWidgets = InterfaceTypes.selectWidgets;
@override @override
void dispose() { void dispose() {
...@@ -24,17 +27,26 @@ class _SettingsFormState extends State<SettingsForm> { ...@@ -24,17 +27,26 @@ class _SettingsFormState extends State<SettingsForm> {
super.dispose(); super.dispose();
} }
List<bool> _selectedInterfaceType = <bool>[];
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
SettingsCubit settings = BlocProvider.of<SettingsCubit>(context); SettingsCubit settings = BlocProvider.of<SettingsCubit>(context);
apiUrlController.text = settings.getSetting('apiUrl'); apiUrlController.text = settings.getApiUrl();
securityTokenController.text = settings.getSetting('securityToken'); securityTokenController.text = settings.getSecurityToken();
if (_selectedInterfaceType.length != 2) {
_selectedInterfaceType = <bool>[
settings.getInterfaceType() == InterfaceType.basic,
settings.getInterfaceType() == InterfaceType.expert,
];
}
void saveSettings() { void saveSettings() {
BlocProvider.of<SettingsCubit>(context).setValues( BlocProvider.of<SettingsCubit>(context).setValues(
apiUrl: apiUrlController.text, apiUrl: apiUrlController.text,
securityToken: securityTokenController.text, securityToken: securityTokenController.text,
interfaceType: _selectedInterfaceType[0] ? InterfaceType.basic : InterfaceType.expert,
); );
BlocProvider.of<BottomNavCubit>(context).getDemoPage(); BlocProvider.of<BottomNavCubit>(context).getDemoPage();
...@@ -61,6 +73,27 @@ class _SettingsFormState extends State<SettingsForm> { ...@@ -61,6 +73,27 @@ class _SettingsFormState extends State<SettingsForm> {
), ),
), ),
SizedBox(height: 16), 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: 16),
ElevatedButton( ElevatedButton(
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
......
...@@ -45,10 +45,10 @@ packages: ...@@ -45,10 +45,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: collection name: collection
sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.17.2" version: "1.18.0"
crypto: crypto:
dependency: transitive dependency: transitive
description: description:
...@@ -172,10 +172,10 @@ packages: ...@@ -172,10 +172,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.9.1" version: "1.10.0"
nested: nested:
dependency: transitive dependency: transitive
description: description:
...@@ -401,10 +401,10 @@ packages: ...@@ -401,10 +401,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: web name: web
sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.1.4-beta" version: "0.3.0"
win32: win32:
dependency: transitive dependency: transitive
description: description:
...@@ -422,5 +422,5 @@ packages: ...@@ -422,5 +422,5 @@ packages:
source: hosted source: hosted
version: "1.0.3" version: "1.0.3"
sdks: sdks:
dart: ">=3.1.0-185.0.dev <4.0.0" dart: ">=3.2.0-194.0.dev <4.0.0"
flutter: ">=3.7.0" flutter: ">=3.7.0"
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment