diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000000000000000000000000000000000..b0b3e1fe2543143896ee06ae7b9984f8bd038f73 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,18 @@ +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.json] +indent_size = 2 + +[*.yaml] +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false diff --git a/CHANGELOG.md b/CHANGELOG.md index 36a7423b1057efd4d85ddd31675f4ffbcdd1926c..682fc616d5297cc97c57c3e6d1c8b9e627a8e23f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.0 + +- Add ApplicationSettings widgets + ## 0.1.1 - Fix missing exported classes diff --git a/lib/flutter_toolbox.dart b/lib/flutter_toolbox.dart index c6b96a5a1f07c81f8b3485278f0f5b348cdf062a..639b3703ece18a2450e8bc53911808d35fe88580 100644 --- a/lib/flutter_toolbox.dart +++ b/lib/flutter_toolbox.dart @@ -13,6 +13,11 @@ export 'widgets/show_error.dart' show ShowErrorWidget; export 'widgets/styled_button.dart' show StyledButton; export 'widgets/styled_container.dart' show StyledContainer; +export 'settings/application_settings_form.dart' show ApplicationSettingsForm; +export 'settings/application_settings_theme_card.dart' show ApplicationSettingsThemeModeCard; +export 'settings/application_theme_mode_cubit.dart' + show ApplicationThemeModeCubit, ApplicationThemeModeState; + // dependencies export 'package:easy_localization/easy_localization.dart' diff --git a/lib/settings/application_settings_form.dart b/lib/settings/application_settings_form.dart new file mode 100644 index 0000000000000000000000000000000000000000..28a6b8862d36cedd765ec8fe37e65df802d687bb --- /dev/null +++ b/lib/settings/application_settings_form.dart @@ -0,0 +1,62 @@ +import 'package:flutter/material.dart'; + +import 'package:flutter_custom_toolbox/flutter_toolbox.dart'; +import 'package:flutter_custom_toolbox/settings/application_settings_theme_card.dart'; + +class ApplicationSettingsForm extends StatefulWidget { + const ApplicationSettingsForm({super.key}); + + @override + State<ApplicationSettingsForm> createState() => _ApplicationSettingsFormState(); +} + +class _ApplicationSettingsFormState extends State<ApplicationSettingsForm> { + @override + void dispose() { + super.dispose(); + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + } + + @override + Widget build(BuildContext context) { + return Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: <Widget>[ + // Light/dark theme + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: <Widget>[ + const Text('settings_label_theme').tr(), + const Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + ApplicationSettingsThemeModeCard( + mode: ThemeMode.system, + icon: UniconsLine.cog, + ), + ApplicationSettingsThemeModeCard( + mode: ThemeMode.light, + icon: UniconsLine.sun, + ), + ApplicationSettingsThemeModeCard( + mode: ThemeMode.dark, + icon: UniconsLine.moon, + ) + ], + ), + ], + ), + + const SizedBox(height: 16), + ], + ); + } +} diff --git a/lib/settings/application_settings_theme_card.dart b/lib/settings/application_settings_theme_card.dart new file mode 100644 index 0000000000000000000000000000000000000000..c501511fb155f815433ee6c60e8640f25b05f1b4 --- /dev/null +++ b/lib/settings/application_settings_theme_card.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; + +import 'package:flutter_custom_toolbox/flutter_toolbox.dart'; +import 'package:flutter_custom_toolbox/settings/application_theme_mode_cubit.dart'; + +class ApplicationSettingsThemeModeCard extends StatelessWidget { + const ApplicationSettingsThemeModeCard({ + super.key, + required this.mode, + required this.icon, + }); + + final IconData icon; + final ThemeMode mode; + + @override + Widget build(BuildContext context) { + return BlocBuilder<ApplicationThemeModeCubit, ApplicationThemeModeState>( + builder: (BuildContext context, ApplicationThemeModeState state) { + return Card( + elevation: 2, + shadowColor: Theme.of(context).colorScheme.shadow, + color: state.themeMode == mode + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.surface, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(12)), + ), + margin: const EdgeInsets.all(5), + child: InkWell( + onTap: () => BlocProvider.of<ApplicationThemeModeCubit>(context).getTheme( + ApplicationThemeModeState(themeMode: mode), + ), + borderRadius: const BorderRadius.all(Radius.circular(12)), + child: Icon( + icon, + size: 32, + color: state.themeMode != mode + ? Theme.of(context).colorScheme.primary + : Colors.white, + ), + ), + ); + }, + ); + } +} diff --git a/lib/settings/application_theme_mode_cubit.dart b/lib/settings/application_theme_mode_cubit.dart new file mode 100644 index 0000000000000000000000000000000000000000..cd414dab4d921fcdcdd15afd0f2a4b90830e48cb --- /dev/null +++ b/lib/settings/application_theme_mode_cubit.dart @@ -0,0 +1,31 @@ +import 'package:flutter/material.dart'; + +import 'package:flutter_custom_toolbox/flutter_toolbox.dart'; + +part 'application_theme_mode_state.dart'; + +class ApplicationThemeModeCubit extends HydratedCubit<ApplicationThemeModeState> { + ApplicationThemeModeCubit() : super(const ApplicationThemeModeState()); + + void getTheme(ApplicationThemeModeState state) { + emit(state); + } + + @override + ApplicationThemeModeState? fromJson(Map<String, dynamic> json) { + switch (json['themeMode']) { + case 'ThemeMode.dark': + return const ApplicationThemeModeState(themeMode: ThemeMode.dark); + case 'ThemeMode.light': + return const ApplicationThemeModeState(themeMode: ThemeMode.light); + case 'ThemeMode.system': + default: + return const ApplicationThemeModeState(themeMode: ThemeMode.system); + } + } + + @override + Map<String, String>? toJson(ApplicationThemeModeState state) { + return <String, String>{'themeMode': state.themeMode.toString()}; + } +} diff --git a/lib/settings/application_theme_mode_state.dart b/lib/settings/application_theme_mode_state.dart new file mode 100644 index 0000000000000000000000000000000000000000..08337c9fb20fd4e0dec9d871e60a538311d5dfac --- /dev/null +++ b/lib/settings/application_theme_mode_state.dart @@ -0,0 +1,15 @@ +part of 'application_theme_mode_cubit.dart'; + +@immutable +class ApplicationThemeModeState extends Equatable { + const ApplicationThemeModeState({ + this.themeMode, + }); + + final ThemeMode? themeMode; + + @override + List<Object?> get props => <Object?>[ + themeMode, + ]; +} diff --git a/pubspec.yaml b/pubspec.yaml index 8662487bad8d90781cefef58262dfbb3b53b46c0..0ab32bdb1753c868da3da35a85c7c83f28004aea 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: "Flutter custom toolbox for org.benoitharrault.* projects." publish_to: "none" -version: 0.1.1 +version: 0.2.0 homepage: https://git.harrault.fr/android/flutter-toolbox