feat: usar a cor escolhida tal e qual e opcao de suavizar
- TatuPalette.scheme aceita softenPrimary e passa a usar a seed como primary, onPrimary por contraste e surfaceTint, em vez da paleta tonal do Material 3 - nova opcao AppSettings.softenThemeColor (default false, ou seja cor exacta) - interruptor 'Suavizar cor do tema' em Configuracoes > Aparencia, com l10n en/pt - a opcao e sincronizada via account data (soften_theme_color) e mantida localmente como fallback, tal como a cor do tema - setApplicationAccountColor e updateApplicationAccountConfig preservam o novo campo - um unico sync de account data actualiza cor e opcao - testes de serializacao e round-trip para o novo campo
This commit is contained in:
@@ -7,6 +7,7 @@ import 'dart:async';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:dynamic_color/dynamic_color.dart';
|
||||
import 'package:tatchat/config/setting_keys.dart';
|
||||
import 'package:tatchat/utils/account_config.dart';
|
||||
import 'package:tatchat/utils/color_value.dart';
|
||||
import 'package:material_ui/material_ui.dart';
|
||||
@@ -43,6 +44,9 @@ class ThemeController extends State<ThemeBuilder> {
|
||||
Color? _primaryColor;
|
||||
Color? _localPrimaryColor;
|
||||
Color? _accountPrimaryColor;
|
||||
bool _softenPrimaryColor = false;
|
||||
bool _localSoftenPrimaryColor = false;
|
||||
bool? _accountSoftenPrimaryColor;
|
||||
Client? _accountClient;
|
||||
StreamSubscription<SyncUpdate>? _accountClientSubscription;
|
||||
int _accountClientGeneration = 0;
|
||||
@@ -51,6 +55,8 @@ class ThemeController extends State<ThemeBuilder> {
|
||||
|
||||
Color? get primaryColor => _primaryColor;
|
||||
|
||||
bool get softenPrimaryColor => _softenPrimaryColor;
|
||||
|
||||
static ThemeController of(BuildContext context) =>
|
||||
Provider.of<ThemeController>(context, listen: false);
|
||||
|
||||
@@ -63,6 +69,15 @@ class ThemeController extends State<ThemeBuilder> {
|
||||
});
|
||||
}
|
||||
|
||||
void _updateSoftenPrimaryColor() {
|
||||
if (!mounted) return;
|
||||
final newValue = _accountSoftenPrimaryColor ?? _localSoftenPrimaryColor;
|
||||
if (newValue == _softenPrimaryColor) return;
|
||||
setState(() {
|
||||
_softenPrimaryColor = newValue;
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _loadData(_) async {
|
||||
final preferences = _sharedPreferences ??=
|
||||
await SharedPreferences.getInstance();
|
||||
@@ -76,8 +91,10 @@ class ThemeController extends State<ThemeBuilder> {
|
||||
(value) => value.name == rawThemeMode,
|
||||
);
|
||||
_localPrimaryColor = rawColor == null ? null : Color(rawColor);
|
||||
_localSoftenPrimaryColor = AppSettings.softenThemeColor.value;
|
||||
});
|
||||
_updatePrimaryColor();
|
||||
_updateSoftenPrimaryColor();
|
||||
}
|
||||
|
||||
Future<void> setThemeMode(ThemeMode newThemeMode) async {
|
||||
@@ -108,6 +125,23 @@ class ThemeController extends State<ThemeBuilder> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> setSoftenPrimaryColor(bool soften) async {
|
||||
await AppSettings.softenThemeColor.setItem(soften);
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_localSoftenPrimaryColor = soften;
|
||||
_accountSoftenPrimaryColor = soften;
|
||||
_softenPrimaryColor = soften;
|
||||
});
|
||||
final client = _accountClient;
|
||||
if (client == null) return;
|
||||
try {
|
||||
await client.setApplicationAccountSoftenThemeColor(soften);
|
||||
} catch (err) {
|
||||
Logs().e('TatuChat: failed to sync soften theme color', err);
|
||||
}
|
||||
}
|
||||
|
||||
void setAccountClient(Client? client) {
|
||||
if (!mounted) return;
|
||||
final generation = ++_accountClientGeneration;
|
||||
@@ -115,10 +149,12 @@ class ThemeController extends State<ThemeBuilder> {
|
||||
_accountClientSubscription = null;
|
||||
_accountClient = client;
|
||||
_accountPrimaryColor = null;
|
||||
_accountSoftenPrimaryColor = null;
|
||||
_updatePrimaryColor();
|
||||
_updateSoftenPrimaryColor();
|
||||
if (client == null) return;
|
||||
|
||||
unawaited(_loadAccountClientColor(client, generation));
|
||||
unawaited(_loadAccountClientConfig(client, generation));
|
||||
_accountClientSubscription = client.onSync.stream
|
||||
.where(
|
||||
(sync) =>
|
||||
@@ -129,10 +165,10 @@ class ThemeController extends State<ThemeBuilder> {
|
||||
) ??
|
||||
false,
|
||||
)
|
||||
.listen((_) => _applyAccountClientColor(client, generation));
|
||||
.listen((_) => _applyAccountClientConfig(client, generation));
|
||||
}
|
||||
|
||||
Future<void> _loadAccountClientColor(Client client, int generation) async {
|
||||
Future<void> _loadAccountClientConfig(Client client, int generation) async {
|
||||
final accountDataLoading = client.accountDataLoading;
|
||||
if (accountDataLoading != null) {
|
||||
try {
|
||||
@@ -144,18 +180,21 @@ class ThemeController extends State<ThemeBuilder> {
|
||||
!identical(_accountClient, client)) {
|
||||
return;
|
||||
}
|
||||
_applyAccountClientColor(client, generation);
|
||||
_applyAccountClientConfig(client, generation);
|
||||
}
|
||||
|
||||
void _applyAccountClientColor(Client client, int generation) {
|
||||
void _applyAccountClientConfig(Client client, int generation) {
|
||||
if (!mounted ||
|
||||
generation != _accountClientGeneration ||
|
||||
!identical(_accountClient, client)) {
|
||||
return;
|
||||
}
|
||||
final primaryColor = client.applicationAccountConfig.primaryColor;
|
||||
final config = client.applicationAccountConfig;
|
||||
final primaryColor = config.primaryColor;
|
||||
_accountPrimaryColor = primaryColor == null ? null : Color(primaryColor);
|
||||
_accountSoftenPrimaryColor = config.softenThemeColor;
|
||||
_updatePrimaryColor();
|
||||
_updateSoftenPrimaryColor();
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
Reference in New Issue
Block a user