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 @@
"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: 16),
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:
......@@ -401,10 +401,10 @@ 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:
......@@ -422,5 +422,5 @@ packages:
source: hosted
version: "1.0.3"
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"
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment