Feature: Add and implement i18n support for theme settings in German and English, refactor AppSettings to DesignSettings, and improve settings UI structure.
This commit is contained in:
@@ -295,8 +295,7 @@ class _DesktopDrawer extends StatelessWidget {
|
||||
child: ListView(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
children: [
|
||||
const _LogoHeader(),
|
||||
const Divider(),
|
||||
// const Divider(),
|
||||
for (var i = 0; i < visibleItems.length; i++)
|
||||
ListTile(
|
||||
selected: i == safeSelected,
|
||||
|
||||
@@ -16,7 +16,7 @@ class DesignSettingsView extends StatelessWidget {
|
||||
final localeModel = context.read<LocaleController>();
|
||||
|
||||
return ChangeNotifierProvider(
|
||||
create: (_) => AppSettingsViewModel(
|
||||
create: (_) => DesignSettingsViewModel(
|
||||
themeModel: themeModel,
|
||||
scaleModel: scaleModel,
|
||||
localeModel: localeModel,
|
||||
@@ -31,12 +31,11 @@ class _AppSettingsContent extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final vm = context.watch<AppSettingsViewModel>();
|
||||
final vm = context.watch<DesignSettingsViewModel>();
|
||||
final isLoading = vm.isLoading;
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
// const PanelHeader(title: 'App-Einstellungen'),
|
||||
if (isLoading)
|
||||
const Expanded(child: Center(child: CircularProgressIndicator()))
|
||||
else
|
||||
@@ -46,8 +45,8 @@ class _AppSettingsContent extends StatelessWidget {
|
||||
children: [
|
||||
_SystemBackgroundSection(),
|
||||
const SizedBox(height: 16),
|
||||
_TextScaleSection(),
|
||||
const SizedBox(height: 16),
|
||||
// _TextScaleSection(),
|
||||
// const SizedBox(height: 16),
|
||||
_LanguageSection(),
|
||||
],
|
||||
),
|
||||
@@ -63,9 +62,42 @@ class _SystemBackgroundSection extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final t = Translations.of(context);
|
||||
final vm = context.watch<AppSettingsViewModel>();
|
||||
final vm = context.watch<DesignSettingsViewModel>();
|
||||
final selected = vm.themeMode;
|
||||
|
||||
final cs = Theme.of(context).colorScheme;
|
||||
final dividerColor = Theme.of(context).dividerColor;
|
||||
|
||||
Widget radioTile({
|
||||
required bool isSelected,
|
||||
required String label,
|
||||
required VoidCallback onTap,
|
||||
}) {
|
||||
return ColoredBox(
|
||||
color: cs.surface,
|
||||
child: ListTile(
|
||||
// contentPadding: const EdgeInsets.symmetric(
|
||||
// // horizontal: 7,
|
||||
// vertical: 0,
|
||||
// ),
|
||||
leading: Icon(
|
||||
isSelected
|
||||
? Icons.radio_button_checked
|
||||
: Icons.radio_button_unchecked,
|
||||
color: isSelected ? cs.primary : null,
|
||||
),
|
||||
title: Text(
|
||||
label,
|
||||
style: isSelected
|
||||
? const TextStyle(fontWeight: FontWeight.w600)
|
||||
: null,
|
||||
),
|
||||
onTap: onTap,
|
||||
selected: isSelected,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -75,32 +107,24 @@ class _SystemBackgroundSection extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
|
||||
ToggleButtons(
|
||||
isSelected: [
|
||||
selected == ThemeMode.system,
|
||||
selected == ThemeMode.dark,
|
||||
selected == ThemeMode.light,
|
||||
],
|
||||
onPressed: (i) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
vm.setThemeMode(ThemeMode.system);
|
||||
break;
|
||||
case 1:
|
||||
vm.setThemeMode(ThemeMode.dark);
|
||||
break;
|
||||
case 2:
|
||||
vm.setThemeMode(ThemeMode.light);
|
||||
break;
|
||||
}
|
||||
},
|
||||
borderRadius: BorderRadius.circular(24),
|
||||
constraints: const BoxConstraints(minHeight: 44, minWidth: 140),
|
||||
children: [
|
||||
_SegItem(icon: Icons.phone_iphone, label: t.settings.app.systemDefault),
|
||||
_SegItem(emoji: '🌙', label: t.settings.app.darkMode),
|
||||
_SegItem(emoji: '☀️', label: t.settings.app.lightMode),
|
||||
],
|
||||
radioTile(
|
||||
isSelected: selected == ThemeMode.system,
|
||||
label: t.settings.app.systemDefault,
|
||||
onTap: () => vm.setThemeMode(ThemeMode.system),
|
||||
),
|
||||
Divider(height: 1, thickness: 1, color: dividerColor),
|
||||
|
||||
radioTile(
|
||||
isSelected: selected == ThemeMode.dark,
|
||||
label: t.settings.app.darkMode,
|
||||
onTap: () => vm.setThemeMode(ThemeMode.dark),
|
||||
),
|
||||
Divider(height: 1, thickness: 1, color: dividerColor),
|
||||
|
||||
radioTile(
|
||||
isSelected: selected == ThemeMode.light,
|
||||
label: t.settings.app.lightMode,
|
||||
onTap: () => vm.setThemeMode(ThemeMode.light),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -137,13 +161,16 @@ class _TextScaleSection extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final t = Translations.of(context);
|
||||
final vm = context.watch<AppSettingsViewModel>();
|
||||
final vm = context.watch<DesignSettingsViewModel>();
|
||||
final selected = vm.textScale;
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(t.settings.app.textSize, style: const TextStyle(fontWeight: FontWeight.w600)),
|
||||
Text(
|
||||
t.settings.app.textSize,
|
||||
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
ToggleButtons(
|
||||
isSelected: [
|
||||
@@ -188,13 +215,16 @@ class _LanguageSection extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final t = Translations.of(context);
|
||||
final vm = context.watch<AppSettingsViewModel>();
|
||||
final vm = context.watch<DesignSettingsViewModel>();
|
||||
final scheme = Theme.of(context).colorScheme;
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(t.settings.app.language, style: Theme.of(context).textTheme.titleMedium),
|
||||
Text(
|
||||
t.settings.app.language,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
DropdownButtonFormField<LanguagePref>(
|
||||
@@ -205,8 +235,14 @@ class _LanguageSection extends StatelessWidget {
|
||||
value: LanguagePref.system,
|
||||
child: Text(t.settings.app.systemDefault),
|
||||
),
|
||||
DropdownMenuItem(value: LanguagePref.de, child: Text(t.settings.app.german)),
|
||||
DropdownMenuItem(value: LanguagePref.en, child: Text(t.settings.app.english)),
|
||||
DropdownMenuItem(
|
||||
value: LanguagePref.de,
|
||||
child: Text(t.settings.app.german),
|
||||
),
|
||||
DropdownMenuItem(
|
||||
value: LanguagePref.en,
|
||||
child: Text(t.settings.app.english),
|
||||
),
|
||||
],
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
|
||||
@@ -3,14 +3,14 @@ import 'package:app/core/ui/controller/scale_controller.dart';
|
||||
import 'package:app/core/ui/controller/theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class AppSettingsViewModel extends ChangeNotifier {
|
||||
class DesignSettingsViewModel extends ChangeNotifier {
|
||||
bool _isLoading = false;
|
||||
|
||||
final ThemeController _theme;
|
||||
final ScaleController _scale;
|
||||
final LocaleController _locale;
|
||||
|
||||
AppSettingsViewModel({
|
||||
DesignSettingsViewModel({
|
||||
required ThemeController themeModel,
|
||||
required ScaleController scaleModel,
|
||||
required LocaleController localeModel,
|
||||
|
||||
Reference in New Issue
Block a user