Files
fuckKomet/lib/utils/theme_provider.dart

1489 lines
54 KiB
Dart

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';
enum AppTheme { system, light, dark, black }
enum ChatWallpaperType { solid, gradient, image, video }
enum TransitionOption { systemDefault, slide }
enum UIMode { both, burgerOnly, panelOnly }
enum MessageBubbleType { solid }
extension MessageBubbleTypeExtension on MessageBubbleType {
String get displayName {
switch (this) {
case MessageBubbleType.solid:
return 'Цвет';
}
}
}
extension TransitionOptionExtension on TransitionOption {
String get displayName {
switch (this) {
case TransitionOption.systemDefault:
return 'Default';
case TransitionOption.slide:
return 'Slide';
}
}
}
extension ChatWallpaperTypeExtension on ChatWallpaperType {
String get displayName {
switch (this) {
case ChatWallpaperType.solid:
return 'Цвет';
case ChatWallpaperType.gradient:
return 'Градиент';
case ChatWallpaperType.image:
return 'Фото';
case ChatWallpaperType.video:
return 'Видео';
}
}
}
class CustomThemePreset {
String id;
String name;
AppTheme appTheme;
Color accentColor;
bool useCustomChatWallpaper;
ChatWallpaperType chatWallpaperType;
Color chatWallpaperColor1;
Color chatWallpaperColor2;
String? chatWallpaperImagePath;
String? chatWallpaperVideoPath;
bool chatWallpaperBlur;
double chatWallpaperBlurSigma;
double chatWallpaperImageBlur;
bool useGlassPanels;
double topBarBlur;
double topBarOpacity;
double bottomBarBlur;
double bottomBarOpacity;
double messageMenuOpacity;
double messageMenuBlur;
double profileDialogBlur;
double profileDialogOpacity;
UIMode uiMode;
bool showSeconds;
double messageBubbleOpacity;
String messageStyle;
double messageBackgroundBlur;
double messageTextOpacity;
double messageShadowIntensity;
double messageBorderRadius;
double messageFontSize;
Color? myBubbleColorLight;
Color? theirBubbleColorLight;
Color? myBubbleColorDark;
Color? theirBubbleColorDark;
MessageBubbleType messageBubbleType;
bool sendOnEnter;
TransitionOption chatTransition;
TransitionOption tabTransition;
TransitionOption messageTransition;
TransitionOption extraTransition;
double messageSlideDistance;
double extraAnimationStrength;
bool animatePhotoMessages;
bool optimizeChats;
bool ultraOptimizeChats;
bool useDesktopLayout;
bool useAutoReplyColor;
Color? customReplyColor;
double mobileChatBottomPadding;
bool ignoreMobileBottomPaddingWhenKeyboard;
// Экспериментальные настройки фона
bool useExperimentalChatsListBackground;
ChatWallpaperType experimentalChatsListBackgroundType;
Color experimentalChatsListBackgroundColor1;
Color experimentalChatsListBackgroundColor2;
String? experimentalChatsListBackgroundImagePath;
ChatWallpaperType drawerTopBackgroundType;
Color drawerTopBackgroundColor1;
Color drawerTopBackgroundColor2;
String? drawerTopBackgroundImagePath;
ChatWallpaperType drawerBottomBackgroundType;
Color drawerBottomBackgroundColor1;
Color drawerBottomBackgroundColor2;
String? drawerBottomBackgroundImagePath;
CustomThemePreset({
required this.id,
required this.name,
this.appTheme = AppTheme.dark,
this.accentColor = Colors.blue,
this.useCustomChatWallpaper = false,
this.chatWallpaperType = ChatWallpaperType.solid,
this.chatWallpaperColor1 = const Color(0xFF101010),
this.chatWallpaperColor2 = const Color(0xFF202020),
this.chatWallpaperImagePath,
this.chatWallpaperVideoPath,
this.chatWallpaperBlur = false,
this.chatWallpaperBlurSigma = 12.0,
this.chatWallpaperImageBlur = 0.0,
this.useGlassPanels = true,
this.topBarBlur = 10.0,
this.topBarOpacity = 0.6,
this.bottomBarBlur = 10.0,
this.bottomBarOpacity = 0.7,
this.messageMenuOpacity = 0.95,
this.messageMenuBlur = 4.0,
this.profileDialogBlur = 12.0,
this.profileDialogOpacity = 0.26,
this.uiMode = UIMode.both,
this.showSeconds = false,
this.messageBubbleOpacity = 0.12,
this.messageStyle = 'glass',
this.messageBackgroundBlur = 0.0,
this.messageTextOpacity = 1.0,
this.messageShadowIntensity = 0.1,
this.messageBorderRadius = 20.0,
this.messageFontSize = 16.0,
this.myBubbleColorLight,
this.theirBubbleColorLight,
this.myBubbleColorDark,
this.theirBubbleColorDark,
this.messageBubbleType = MessageBubbleType.solid,
this.sendOnEnter = false,
this.chatTransition = TransitionOption.systemDefault,
this.tabTransition = TransitionOption.systemDefault,
this.messageTransition = TransitionOption.systemDefault,
this.extraTransition = TransitionOption.systemDefault,
this.messageSlideDistance = 96.0,
this.extraAnimationStrength = 32.0,
this.animatePhotoMessages = false,
this.optimizeChats = false,
this.ultraOptimizeChats = false,
this.useDesktopLayout = true,
this.useAutoReplyColor = true,
this.customReplyColor,
this.mobileChatBottomPadding = 140.0,
this.ignoreMobileBottomPaddingWhenKeyboard = true,
this.useExperimentalChatsListBackground = false,
this.experimentalChatsListBackgroundType = ChatWallpaperType.solid,
this.experimentalChatsListBackgroundColor1 = const Color(0xFF101010),
this.experimentalChatsListBackgroundColor2 = const Color(0xFF202020),
this.experimentalChatsListBackgroundImagePath,
this.drawerTopBackgroundType = ChatWallpaperType.solid,
this.drawerTopBackgroundColor1 = const Color(0xFF1E1E1E),
this.drawerTopBackgroundColor2 = const Color(0xFF2E2E2E),
this.drawerTopBackgroundImagePath,
this.drawerBottomBackgroundType = ChatWallpaperType.solid,
this.drawerBottomBackgroundColor1 = const Color(0xFF1E1E1E),
this.drawerBottomBackgroundColor2 = const Color(0xFF2E2E2E),
this.drawerBottomBackgroundImagePath,
});
factory CustomThemePreset.createDefault() {
return CustomThemePreset(id: 'default', name: 'По умолчанию');
}
CustomThemePreset copyWith({
String? id,
String? name,
AppTheme? appTheme,
Color? accentColor,
bool? useCustomChatWallpaper,
ChatWallpaperType? chatWallpaperType,
Color? chatWallpaperColor1,
Color? chatWallpaperColor2,
String? chatWallpaperImagePath,
String? chatWallpaperVideoPath,
bool? chatWallpaperBlur,
double? chatWallpaperBlurSigma,
double? chatWallpaperImageBlur,
bool? useGlassPanels,
double? topBarBlur,
double? topBarOpacity,
double? bottomBarBlur,
double? bottomBarOpacity,
double? messageMenuOpacity,
double? messageMenuBlur,
double? profileDialogBlur,
double? profileDialogOpacity,
UIMode? uiMode,
bool? showSeconds,
double? messageBubbleOpacity,
String? messageStyle,
double? messageBackgroundBlur,
double? messageTextOpacity,
double? messageShadowIntensity,
double? messageBorderRadius,
double? messageFontSize,
Color? myBubbleColorLight,
Color? theirBubbleColorLight,
Color? myBubbleColorDark,
Color? theirBubbleColorDark,
MessageBubbleType? messageBubbleType,
bool? sendOnEnter,
TransitionOption? chatTransition,
TransitionOption? tabTransition,
TransitionOption? messageTransition,
TransitionOption? extraTransition,
double? messageSlideDistance,
double? extraAnimationStrength,
bool? animatePhotoMessages,
bool? optimizeChats,
bool? ultraOptimizeChats,
bool? useDesktopLayout,
bool? useAutoReplyColor,
Color? customReplyColor,
double? mobileChatBottomPadding,
bool? ignoreMobileBottomPaddingWhenKeyboard,
bool? useExperimentalChatsListBackground,
ChatWallpaperType? experimentalChatsListBackgroundType,
Color? experimentalChatsListBackgroundColor1,
Color? experimentalChatsListBackgroundColor2,
String? experimentalChatsListBackgroundImagePath,
ChatWallpaperType? drawerTopBackgroundType,
Color? drawerTopBackgroundColor1,
Color? drawerTopBackgroundColor2,
String? drawerTopBackgroundImagePath,
ChatWallpaperType? drawerBottomBackgroundType,
Color? drawerBottomBackgroundColor1,
Color? drawerBottomBackgroundColor2,
String? drawerBottomBackgroundImagePath,
}) {
return CustomThemePreset(
id: id ?? this.id,
name: name ?? this.name,
appTheme: appTheme ?? this.appTheme,
accentColor: accentColor ?? this.accentColor,
useCustomChatWallpaper:
useCustomChatWallpaper ?? this.useCustomChatWallpaper,
chatWallpaperType: chatWallpaperType ?? this.chatWallpaperType,
chatWallpaperColor1: chatWallpaperColor1 ?? this.chatWallpaperColor1,
chatWallpaperColor2: chatWallpaperColor2 ?? this.chatWallpaperColor2,
chatWallpaperImagePath:
chatWallpaperImagePath ?? this.chatWallpaperImagePath,
chatWallpaperVideoPath:
chatWallpaperVideoPath ?? this.chatWallpaperVideoPath,
chatWallpaperBlur: chatWallpaperBlur ?? this.chatWallpaperBlur,
chatWallpaperBlurSigma:
chatWallpaperBlurSigma ?? this.chatWallpaperBlurSigma,
chatWallpaperImageBlur:
chatWallpaperImageBlur ?? this.chatWallpaperImageBlur,
useGlassPanels: useGlassPanels ?? this.useGlassPanels,
topBarBlur: topBarBlur ?? this.topBarBlur,
topBarOpacity: topBarOpacity ?? this.topBarOpacity,
bottomBarBlur: bottomBarBlur ?? this.bottomBarBlur,
bottomBarOpacity: bottomBarOpacity ?? this.bottomBarOpacity,
messageMenuOpacity: messageMenuOpacity ?? this.messageMenuOpacity,
messageMenuBlur: messageMenuBlur ?? this.messageMenuBlur,
profileDialogBlur: profileDialogBlur ?? this.profileDialogBlur,
profileDialogOpacity: profileDialogOpacity ?? this.profileDialogOpacity,
uiMode: uiMode ?? this.uiMode,
showSeconds: showSeconds ?? this.showSeconds,
messageBubbleOpacity: messageBubbleOpacity ?? this.messageBubbleOpacity,
messageStyle: messageStyle ?? this.messageStyle,
messageBackgroundBlur:
messageBackgroundBlur ?? this.messageBackgroundBlur,
messageTextOpacity: messageTextOpacity ?? this.messageTextOpacity,
messageShadowIntensity:
messageShadowIntensity ?? this.messageShadowIntensity,
messageBorderRadius: messageBorderRadius ?? this.messageBorderRadius,
messageFontSize: messageFontSize ?? this.messageFontSize,
myBubbleColorLight: myBubbleColorLight ?? this.myBubbleColorLight,
theirBubbleColorLight:
theirBubbleColorLight ?? this.theirBubbleColorLight,
myBubbleColorDark: myBubbleColorDark ?? this.myBubbleColorDark,
theirBubbleColorDark: theirBubbleColorDark ?? this.theirBubbleColorDark,
messageBubbleType: messageBubbleType ?? this.messageBubbleType,
sendOnEnter: sendOnEnter ?? this.sendOnEnter,
chatTransition: chatTransition ?? this.chatTransition,
tabTransition: tabTransition ?? this.tabTransition,
messageTransition: messageTransition ?? this.messageTransition,
extraTransition: extraTransition ?? this.extraTransition,
messageSlideDistance: messageSlideDistance ?? this.messageSlideDistance,
extraAnimationStrength:
extraAnimationStrength ?? this.extraAnimationStrength,
animatePhotoMessages: animatePhotoMessages ?? this.animatePhotoMessages,
optimizeChats: optimizeChats ?? this.optimizeChats,
ultraOptimizeChats: ultraOptimizeChats ?? this.ultraOptimizeChats,
useDesktopLayout: useDesktopLayout ?? this.useDesktopLayout,
useAutoReplyColor: useAutoReplyColor ?? this.useAutoReplyColor,
customReplyColor: customReplyColor ?? this.customReplyColor,
mobileChatBottomPadding:
mobileChatBottomPadding ?? this.mobileChatBottomPadding,
ignoreMobileBottomPaddingWhenKeyboard:
ignoreMobileBottomPaddingWhenKeyboard ??
this.ignoreMobileBottomPaddingWhenKeyboard,
useExperimentalChatsListBackground: useExperimentalChatsListBackground ??
this.useExperimentalChatsListBackground,
experimentalChatsListBackgroundType: experimentalChatsListBackgroundType ??
this.experimentalChatsListBackgroundType,
experimentalChatsListBackgroundColor1: experimentalChatsListBackgroundColor1 ??
this.experimentalChatsListBackgroundColor1,
experimentalChatsListBackgroundColor2: experimentalChatsListBackgroundColor2 ??
this.experimentalChatsListBackgroundColor2,
experimentalChatsListBackgroundImagePath: experimentalChatsListBackgroundImagePath ??
this.experimentalChatsListBackgroundImagePath,
drawerTopBackgroundType: drawerTopBackgroundType ?? this.drawerTopBackgroundType,
drawerTopBackgroundColor1:
drawerTopBackgroundColor1 ?? this.drawerTopBackgroundColor1,
drawerTopBackgroundColor2:
drawerTopBackgroundColor2 ?? this.drawerTopBackgroundColor2,
drawerTopBackgroundImagePath:
drawerTopBackgroundImagePath ?? this.drawerTopBackgroundImagePath,
drawerBottomBackgroundType: drawerBottomBackgroundType ?? this.drawerBottomBackgroundType,
drawerBottomBackgroundColor1:
drawerBottomBackgroundColor1 ?? this.drawerBottomBackgroundColor1,
drawerBottomBackgroundColor2:
drawerBottomBackgroundColor2 ?? this.drawerBottomBackgroundColor2,
drawerBottomBackgroundImagePath:
drawerBottomBackgroundImagePath ?? this.drawerBottomBackgroundImagePath,
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'appTheme': appTheme.index,
'accentColor': accentColor.value,
'useCustomChatWallpaper': useCustomChatWallpaper,
'chatWallpaperType': chatWallpaperType.index,
'chatWallpaperColor1': chatWallpaperColor1.value,
'chatWallpaperColor2': chatWallpaperColor2.value,
'chatWallpaperImagePath': chatWallpaperImagePath,
'chatWallpaperVideoPath': chatWallpaperVideoPath,
'chatWallpaperBlur': chatWallpaperBlur,
'chatWallpaperBlurSigma': chatWallpaperBlurSigma,
'chatWallpaperImageBlur': chatWallpaperImageBlur,
'useGlassPanels': useGlassPanels,
'topBarBlur': topBarBlur,
'topBarOpacity': topBarOpacity,
'bottomBarBlur': bottomBarBlur,
'bottomBarOpacity': bottomBarOpacity,
'messageMenuOpacity': messageMenuOpacity,
'messageMenuBlur': messageMenuBlur,
'profileDialogBlur': profileDialogBlur,
'profileDialogOpacity': profileDialogOpacity,
'uiMode': uiMode.index,
'showSeconds': showSeconds,
'messageBubbleOpacity': messageBubbleOpacity,
'messageStyle': messageStyle,
'messageBackgroundBlur': messageBackgroundBlur,
'messageTextOpacity': messageTextOpacity,
'messageShadowIntensity': messageShadowIntensity,
'messageBorderRadius': messageBorderRadius,
'messageFontSize': messageFontSize,
'myBubbleColorLight': myBubbleColorLight?.value,
'theirBubbleColorLight': theirBubbleColorLight?.value,
'myBubbleColorDark': myBubbleColorDark?.value,
'theirBubbleColorDark': theirBubbleColorDark?.value,
'messageBubbleType': messageBubbleType.index,
'sendOnEnter': sendOnEnter,
'chatTransition': chatTransition.index,
'tabTransition': tabTransition.index,
'messageTransition': messageTransition.index,
'extraTransition': extraTransition.index,
'messageSlideDistance': messageSlideDistance,
'extraAnimationStrength': extraAnimationStrength,
'animatePhotoMessages': animatePhotoMessages,
'optimizeChats': optimizeChats,
'ultraOptimizeChats': ultraOptimizeChats,
'useDesktopLayout': useDesktopLayout,
'useAutoReplyColor': useAutoReplyColor,
'customReplyColor': customReplyColor?.value,
'mobileChatBottomPadding': mobileChatBottomPadding,
'ignoreMobileBottomPaddingWhenKeyboard':
ignoreMobileBottomPaddingWhenKeyboard,
'useExperimentalChatsListBackground': useExperimentalChatsListBackground,
'experimentalChatsListBackgroundType': experimentalChatsListBackgroundType.index,
'experimentalChatsListBackgroundColor1': experimentalChatsListBackgroundColor1.value,
'experimentalChatsListBackgroundColor2': experimentalChatsListBackgroundColor2.value,
'experimentalChatsListBackgroundImagePath': experimentalChatsListBackgroundImagePath,
'drawerTopBackgroundType': drawerTopBackgroundType.index,
'drawerTopBackgroundColor1': drawerTopBackgroundColor1.value,
'drawerTopBackgroundColor2': drawerTopBackgroundColor2.value,
'drawerTopBackgroundImagePath': drawerTopBackgroundImagePath,
'drawerBottomBackgroundType': drawerBottomBackgroundType.index,
'drawerBottomBackgroundColor1': drawerBottomBackgroundColor1.value,
'drawerBottomBackgroundColor2': drawerBottomBackgroundColor2.value,
'drawerBottomBackgroundImagePath': drawerBottomBackgroundImagePath,
};
}
factory CustomThemePreset.fromJson(Map<String, dynamic> json) {
return CustomThemePreset(
id: json['id'] as String,
name: json['name'] as String,
appTheme: AppTheme.values[json['appTheme'] as int? ?? 0],
accentColor: Color(json['accentColor'] as int? ?? Colors.blue.value),
useCustomChatWallpaper: json['useCustomChatWallpaper'] as bool? ?? false,
chatWallpaperType:
ChatWallpaperType.values[json['chatWallpaperType'] as int? ?? 0],
chatWallpaperColor1: Color(
json['chatWallpaperColor1'] as int? ?? const Color(0xFF101010).value,
),
chatWallpaperColor2: Color(
json['chatWallpaperColor2'] as int? ?? const Color(0xFF202020).value,
),
chatWallpaperImagePath: json['chatWallpaperImagePath'] as String?,
chatWallpaperVideoPath: json['chatWallpaperVideoPath'] as String?,
chatWallpaperBlur: json['chatWallpaperBlur'] as bool? ?? false,
chatWallpaperBlurSigma:
(json['chatWallpaperBlurSigma'] as double? ?? 12.0).clamp(0.0, 20.0),
chatWallpaperImageBlur: (json['chatWallpaperImageBlur'] as double? ?? 0.0)
.clamp(0.0, 10.0),
useGlassPanels: json['useGlassPanels'] as bool? ?? true,
topBarBlur: json['topBarBlur'] as double? ?? 10.0,
topBarOpacity: json['topBarOpacity'] as double? ?? 0.6,
bottomBarBlur: json['bottomBarBlur'] as double? ?? 10.0,
bottomBarOpacity: json['bottomBarOpacity'] as double? ?? 0.7,
messageMenuOpacity: json['messageMenuOpacity'] as double? ?? 0.95,
messageMenuBlur: json['messageMenuBlur'] as double? ?? 4.0,
profileDialogBlur: (json['profileDialogBlur'] as double? ?? 12.0).clamp(
0.0,
30.0,
),
profileDialogOpacity: (json['profileDialogOpacity'] as double? ?? 0.26)
.clamp(0.0, 1.0),
uiMode: UIMode.values[json['uiMode'] as int? ?? 0],
showSeconds: json['showSeconds'] as bool? ?? false,
messageBubbleOpacity: (json['messageBubbleOpacity'] as double? ?? 0.12)
.clamp(0.0, 1.0),
messageStyle: json['messageStyle'] as String? ?? 'glass',
messageBackgroundBlur: (json['messageBackgroundBlur'] as double? ?? 0.0)
.clamp(0.0, 10.0),
messageTextOpacity: (json['messageTextOpacity'] as double? ?? 1.0).clamp(
0.1,
1.0,
),
messageShadowIntensity: (json['messageShadowIntensity'] as double? ?? 0.1)
.clamp(0.0, 0.5),
messageBorderRadius: (json['messageBorderRadius'] as double? ?? 20.0)
.clamp(4.0, 50.0),
messageFontSize: json['messageFontSize'] as double? ?? 16.0,
myBubbleColorLight: json['myBubbleColorLight'] != null
? Color(json['myBubbleColorLight'] as int)
: null,
theirBubbleColorLight: json['theirBubbleColorLight'] != null
? Color(json['theirBubbleColorLight'] as int)
: null,
myBubbleColorDark: json['myBubbleColorDark'] != null
? Color(json['myBubbleColorDark'] as int)
: null,
theirBubbleColorDark: json['theirBubbleColorDark'] != null
? Color(json['theirBubbleColorDark'] as int)
: null,
messageBubbleType: () {
final bubbleTypeIndex = json['messageBubbleType'] as int?;
if (bubbleTypeIndex == null) {
return MessageBubbleType.solid;
}
if (bubbleTypeIndex >= MessageBubbleType.values.length) {
return MessageBubbleType.solid;
}
return MessageBubbleType.values[bubbleTypeIndex];
}(),
sendOnEnter: json['sendOnEnter'] as bool? ?? false,
chatTransition:
TransitionOption.values[json['chatTransition'] as int? ?? 0],
tabTransition:
TransitionOption.values[json['tabTransition'] as int? ?? 0],
messageTransition:
TransitionOption.values[json['messageTransition'] as int? ?? 0],
extraTransition:
TransitionOption.values[json['extraTransition'] as int? ?? 0],
messageSlideDistance: (json['messageSlideDistance'] as double? ?? 96.0)
.clamp(1.0, 200.0),
extraAnimationStrength:
(json['extraAnimationStrength'] as double? ?? 32.0).clamp(1.0, 400.0),
animatePhotoMessages: json['animatePhotoMessages'] as bool? ?? false,
optimizeChats: json['optimizeChats'] as bool? ?? false,
ultraOptimizeChats: json['ultraOptimizeChats'] as bool? ?? false,
useDesktopLayout: json['useDesktopLayout'] as bool? ?? false,
useAutoReplyColor: json['useAutoReplyColor'] as bool? ?? true,
customReplyColor: json['customReplyColor'] != null
? Color(json['customReplyColor'] as int)
: null,
mobileChatBottomPadding:
(json['mobileChatBottomPadding'] as double? ?? 140.0).clamp(
60.0,
240.0,
),
ignoreMobileBottomPaddingWhenKeyboard:
json['ignoreMobileBottomPaddingWhenKeyboard'] as bool? ?? true,
useExperimentalChatsListBackground: json['useExperimentalChatsListBackground'] as bool? ?? false,
experimentalChatsListBackgroundType: () {
final index = json['experimentalChatsListBackgroundType'] as int?;
if (index == null || index < 0 || index >= ChatWallpaperType.values.length) {
return ChatWallpaperType.solid;
}
return ChatWallpaperType.values[index];
}(),
experimentalChatsListBackgroundColor1: Color(json['experimentalChatsListBackgroundColor1'] as int? ?? const Color(0xFF101010).value),
experimentalChatsListBackgroundColor2: Color(json['experimentalChatsListBackgroundColor2'] as int? ?? const Color(0xFF202020).value),
experimentalChatsListBackgroundImagePath: json['experimentalChatsListBackgroundImagePath'] as String?,
drawerTopBackgroundType: () {
final index = json['drawerTopBackgroundType'] as int?;
if (index == null || index < 0 || index >= ChatWallpaperType.values.length) {
return ChatWallpaperType.solid;
}
return ChatWallpaperType.values[index];
}(),
drawerTopBackgroundColor1: Color(json['drawerTopBackgroundColor1'] as int? ?? const Color(0xFF1E1E1E).value),
drawerTopBackgroundColor2: Color(json['drawerTopBackgroundColor2'] as int? ?? const Color(0xFF2E2E2E).value),
drawerTopBackgroundImagePath: json['drawerTopBackgroundImagePath'] as String?,
drawerBottomBackgroundType: () {
final index = json['drawerBottomBackgroundType'] as int?;
if (index == null || index < 0 || index >= ChatWallpaperType.values.length) {
return ChatWallpaperType.solid;
}
return ChatWallpaperType.values[index];
}(),
drawerBottomBackgroundColor1: Color(json['drawerBottomBackgroundColor1'] as int? ?? const Color(0xFF1E1E1E).value),
drawerBottomBackgroundColor2: Color(json['drawerBottomBackgroundColor2'] as int? ?? const Color(0xFF2E2E2E).value),
drawerBottomBackgroundImagePath: json['drawerBottomBackgroundImagePath'] as String?,
);
}
}
class ThemeProvider with ChangeNotifier {
CustomThemePreset _activeTheme = CustomThemePreset.createDefault();
List<CustomThemePreset> _savedThemes = [];
Color? _myBubbleColorLight;
Color? _theirBubbleColorLight;
Color? _myBubbleColorDark;
Color? _theirBubbleColorDark;
final Map<int, String> _chatSpecificWallpapers = {};
bool _debugShowPerformanceOverlay = false;
bool _debugShowChatsRefreshPanel = false;
bool _debugShowMessageCount = false;
bool _debugReadOnEnter = true;
bool _debugReadOnAction = true;
bool _blockBypass = false;
bool _highQualityPhotos = true;
AppTheme get appTheme => _activeTheme.appTheme;
Color get accentColor => _activeTheme.accentColor;
ThemeMode get themeMode {
switch (_activeTheme.appTheme) {
case AppTheme.system:
return ThemeMode.system;
case AppTheme.light:
return ThemeMode.light;
case AppTheme.dark:
case AppTheme.black:
return ThemeMode.dark;
}
}
bool get useCustomChatWallpaper => _activeTheme.useCustomChatWallpaper;
ChatWallpaperType get chatWallpaperType => _activeTheme.chatWallpaperType;
Color get chatWallpaperColor1 => _activeTheme.chatWallpaperColor1;
Color get chatWallpaperColor2 => _activeTheme.chatWallpaperColor2;
String? get chatWallpaperImagePath => _activeTheme.chatWallpaperImagePath;
String? get chatWallpaperVideoPath => _activeTheme.chatWallpaperVideoPath;
bool get chatWallpaperBlur => _activeTheme.chatWallpaperBlur;
double get chatWallpaperBlurSigma => _activeTheme.chatWallpaperBlurSigma;
double get chatWallpaperImageBlur => _activeTheme.chatWallpaperImageBlur;
bool get useGlassPanels => _activeTheme.useGlassPanels;
double get topBarBlur => _activeTheme.topBarBlur;
double get topBarOpacity => _activeTheme.topBarOpacity;
double get bottomBarBlur => _activeTheme.bottomBarBlur;
double get bottomBarOpacity => _activeTheme.bottomBarOpacity;
double get messageMenuOpacity => _activeTheme.messageMenuOpacity;
double get messageMenuBlur => _activeTheme.messageMenuBlur;
double get profileDialogBlur => _activeTheme.profileDialogBlur;
double get profileDialogOpacity => _activeTheme.profileDialogOpacity;
UIMode get uiMode => _activeTheme.uiMode;
bool get showSeconds => _activeTheme.showSeconds;
double get messageBubbleOpacity => _activeTheme.messageBubbleOpacity;
String get messageStyle => _activeTheme.messageStyle;
double get messageBackgroundBlur => _activeTheme.messageBackgroundBlur;
double get messageTextOpacity => _activeTheme.messageTextOpacity;
double get messageShadowIntensity => _activeTheme.messageShadowIntensity;
double get messageBorderRadius => _activeTheme.messageBorderRadius;
double get messageFontSize => _activeTheme.messageFontSize;
bool get sendOnEnter => _activeTheme.sendOnEnter;
MessageBubbleType get messageBubbleType => _activeTheme.messageBubbleType;
Color? get myBubbleColorLight => _myBubbleColorLight;
Color? get theirBubbleColorLight => _theirBubbleColorLight;
Color? get myBubbleColorDark => _myBubbleColorDark;
Color? get theirBubbleColorDark => _theirBubbleColorDark;
Color? get myBubbleColor {
if (appTheme == AppTheme.light) return _myBubbleColorLight;
if (appTheme == AppTheme.dark || appTheme == AppTheme.black) {
return _myBubbleColorDark;
}
return null;
}
Color? get theirBubbleColor {
if (appTheme == AppTheme.light) return _theirBubbleColorLight;
if (appTheme == AppTheme.dark || appTheme == AppTheme.black) {
return _theirBubbleColorDark;
}
return null;
}
bool get debugShowBottomBar =>
_activeTheme.uiMode == UIMode.both ||
_activeTheme.uiMode == UIMode.panelOnly;
bool get debugShowBurgerMenu =>
_activeTheme.uiMode == UIMode.both ||
_activeTheme.uiMode == UIMode.burgerOnly;
bool get debugShowPerformanceOverlay => _debugShowPerformanceOverlay;
bool get debugShowChatsRefreshPanel => _debugShowChatsRefreshPanel;
bool get debugShowMessageCount => _debugShowMessageCount;
bool get debugReadOnEnter => _debugReadOnEnter;
bool get debugReadOnAction => _debugReadOnAction;
double get mobileChatBottomPadding => _activeTheme.mobileChatBottomPadding;
bool get ignoreMobileBottomPaddingWhenKeyboard =>
_activeTheme.ignoreMobileBottomPaddingWhenKeyboard;
// Экспериментальные настройки фона
bool get useExperimentalChatsListBackground => _activeTheme.useExperimentalChatsListBackground;
ChatWallpaperType get experimentalChatsListBackgroundType => _activeTheme.experimentalChatsListBackgroundType;
Color get experimentalChatsListBackgroundColor1 => _activeTheme.experimentalChatsListBackgroundColor1;
Color get experimentalChatsListBackgroundColor2 => _activeTheme.experimentalChatsListBackgroundColor2;
String? get experimentalChatsListBackgroundImagePath => _activeTheme.experimentalChatsListBackgroundImagePath;
ChatWallpaperType get drawerTopBackgroundType => _activeTheme.drawerTopBackgroundType;
Color get drawerTopBackgroundColor1 => _activeTheme.drawerTopBackgroundColor1;
Color get drawerTopBackgroundColor2 => _activeTheme.drawerTopBackgroundColor2;
String? get drawerTopBackgroundImagePath => _activeTheme.drawerTopBackgroundImagePath;
ChatWallpaperType get drawerBottomBackgroundType => _activeTheme.drawerBottomBackgroundType;
Color get drawerBottomBackgroundColor1 => _activeTheme.drawerBottomBackgroundColor1;
Color get drawerBottomBackgroundColor2 => _activeTheme.drawerBottomBackgroundColor2;
String? get drawerBottomBackgroundImagePath => _activeTheme.drawerBottomBackgroundImagePath;
TransitionOption get chatTransition => _activeTheme.ultraOptimizeChats
? TransitionOption.systemDefault
: _activeTheme.chatTransition;
TransitionOption get tabTransition => _activeTheme.ultraOptimizeChats
? TransitionOption.systemDefault
: _activeTheme.tabTransition;
TransitionOption get messageTransition => _activeTheme.ultraOptimizeChats
? TransitionOption.systemDefault
: _activeTheme.messageTransition;
TransitionOption get extraTransition => _activeTheme.ultraOptimizeChats
? TransitionOption.systemDefault
: _activeTheme.extraTransition;
double get messageSlideDistance => _activeTheme.messageSlideDistance;
double get extraAnimationStrength => _activeTheme.extraAnimationStrength;
bool get animatePhotoMessages => _activeTheme.ultraOptimizeChats
? false
: _activeTheme.animatePhotoMessages;
bool get optimizeChats => _activeTheme.optimizeChats;
bool get ultraOptimizeChats => _activeTheme.ultraOptimizeChats;
bool get useDesktopLayout => _activeTheme.useDesktopLayout;
bool get useAutoReplyColor => _activeTheme.useAutoReplyColor;
Color? get customReplyColor => _activeTheme.customReplyColor;
bool get highQualityPhotos => _highQualityPhotos;
bool get blockBypass => _blockBypass;
List<CustomThemePreset> get savedThemes => _savedThemes;
CustomThemePreset get activeTheme => _activeTheme;
ThemeProvider() {
loadSettings();
}
Future<void> loadSettings() async {
final prefs = await SharedPreferences.getInstance();
final themesJson = prefs.getStringList('saved_themes') ?? [];
_savedThemes = themesJson
.map((jsonString) {
try {
return CustomThemePreset.fromJson(jsonDecode(jsonString));
} catch (e) {
print('Ошибка загрузки темы: $e');
return null;
}
})
.whereType<CustomThemePreset>()
.toList();
if (_savedThemes.isEmpty) {
_savedThemes.add(CustomThemePreset.createDefault());
}
final activeId =
prefs.getString('active_theme_id') ?? _savedThemes.first.id;
_activeTheme = _savedThemes.firstWhere(
(t) => t.id == activeId,
orElse: () => _savedThemes.first,
);
if (_activeTheme.myBubbleColorLight == null ||
_activeTheme.theirBubbleColorLight == null ||
_activeTheme.myBubbleColorDark == null ||
_activeTheme.theirBubbleColorDark == null) {
_updateBubbleColorsFromAccent(_activeTheme.accentColor);
_activeTheme = _activeTheme.copyWith(
myBubbleColorLight: _myBubbleColorLight,
theirBubbleColorLight: _theirBubbleColorLight,
myBubbleColorDark: _myBubbleColorDark,
theirBubbleColorDark: _theirBubbleColorDark,
);
await _saveActiveTheme();
} else {
_myBubbleColorLight = _activeTheme.myBubbleColorLight;
_theirBubbleColorLight = _activeTheme.theirBubbleColorLight;
_myBubbleColorDark = _activeTheme.myBubbleColorDark;
_theirBubbleColorDark = _activeTheme.theirBubbleColorDark;
}
_debugShowPerformanceOverlay = prefs.getBool('debug_perf_overlay') ?? false;
_debugShowChatsRefreshPanel =
prefs.getBool('debug_show_chats_refresh_panel') ?? false;
_debugShowMessageCount = prefs.getBool('debug_show_message_count') ?? false;
_debugReadOnEnter = prefs.getBool('debug_read_on_enter') ?? true;
_debugReadOnAction = prefs.getBool('debug_read_on_action') ?? true;
_highQualityPhotos = prefs.getBool('high_quality_photos') ?? true;
_blockBypass = prefs.getBool('block_bypass') ?? false;
await loadChatSpecificWallpapers();
notifyListeners();
}
Future<void> _saveThemeListToPrefs() async {
final prefs = await SharedPreferences.getInstance();
final themesJson = _savedThemes
.map((theme) => jsonEncode(theme.toJson()))
.toList();
await prefs.setStringList('saved_themes', themesJson);
}
Future<void> _saveActiveTheme() async {
final index = _savedThemes.indexWhere((t) => t.id == _activeTheme.id);
if (index != -1) {
_savedThemes[index] = _activeTheme;
} else {
_savedThemes.add(_activeTheme);
}
await _saveThemeListToPrefs();
}
Future<void> applyTheme(String themeId) async {
final themeToApply = _savedThemes.firstWhere((t) => t.id == themeId);
_activeTheme = themeToApply;
_myBubbleColorLight = _activeTheme.myBubbleColorLight;
_theirBubbleColorLight = _activeTheme.theirBubbleColorLight;
_myBubbleColorDark = _activeTheme.myBubbleColorDark;
_theirBubbleColorDark = _activeTheme.theirBubbleColorDark;
notifyListeners();
final prefs = await SharedPreferences.getInstance();
await prefs.setString('active_theme_id', themeId);
}
Future<void> saveCurrentThemeAs(String name) async {
final newTheme = _activeTheme.copyWith(
id: DateTime.now().millisecondsSinceEpoch.toString(),
name: name.trim().isEmpty ? 'Новая тема' : name.trim(),
);
_savedThemes.add(newTheme);
await _saveThemeListToPrefs();
await applyTheme(newTheme.id);
}
Future<void> deleteTheme(String themeId) async {
if (themeId == 'default') return;
_savedThemes.removeWhere((t) => t.id == themeId);
if (_activeTheme.id == themeId) {
await applyTheme('default');
} else {
await _saveThemeListToPrefs();
notifyListeners();
}
}
Future<void> renameTheme(String themeId, String newName) async {
if (themeId == 'default') return;
final index = _savedThemes.indexWhere((t) => t.id == themeId);
if (index != -1) {
final String finalName = newName.trim().isEmpty
? _savedThemes[index].name
: newName.trim();
_savedThemes[index] = _savedThemes[index].copyWith(name: finalName);
if (_activeTheme.id == themeId) {
_activeTheme = _activeTheme.copyWith(name: finalName);
}
await _saveThemeListToPrefs();
notifyListeners();
}
}
Future<bool> importThemeFromJson(String jsonString) async {
try {
final Map<String, dynamic> jsonMap = jsonDecode(jsonString);
if (!jsonMap.containsKey('id') || !jsonMap.containsKey('name')) {
debugPrint("Ошибка импорта: JSON не содержит ключи 'id' или 'name'.");
return false;
}
final importedPreset = CustomThemePreset.fromJson(jsonMap);
final newPreset = importedPreset.copyWith(
id: DateTime.now().millisecondsSinceEpoch.toString(),
name: "Импорт: ${importedPreset.name}",
);
_savedThemes.add(newPreset);
await _saveThemeListToPrefs();
notifyListeners();
return true; // Успех
} catch (e) {
debugPrint("Ошибка импорта темы: $e");
return false; // Неудача
}
}
Future<void> setTheme(AppTheme theme) async {
_activeTheme = _activeTheme.copyWith(appTheme: theme);
if (theme != AppTheme.system) {
_updateBubbleColorsFromAccent(_activeTheme.accentColor);
_activeTheme = _activeTheme.copyWith(
myBubbleColorLight: _myBubbleColorLight,
theirBubbleColorLight: _theirBubbleColorLight,
myBubbleColorDark: _myBubbleColorDark,
theirBubbleColorDark: _theirBubbleColorDark,
);
}
notifyListeners();
await _saveActiveTheme();
}
Future<void> setAccentColor(Color color) async {
_updateBubbleColorsFromAccent(color);
_activeTheme = _activeTheme.copyWith(
accentColor: color,
myBubbleColorLight: _myBubbleColorLight,
theirBubbleColorLight: _theirBubbleColorLight,
myBubbleColorDark: _myBubbleColorDark,
theirBubbleColorDark: _theirBubbleColorDark,
);
notifyListeners();
await _saveActiveTheme();
}
Future<void> updateBubbleColorsForSystemTheme(Color systemAccentColor) async {
_updateBubbleColorsFromAccent(systemAccentColor);
notifyListeners();
}
void _updateBubbleColorsFromAccent(Color accent) {
final Color myColorDark = accent;
final hslDark = HSLColor.fromColor(accent);
final double theirSatDark = (hslDark.saturation * 0.4).clamp(0.0, 1.0);
final double theirLightDark = (hslDark.lightness * 0.7).clamp(0.1, 0.85);
final Color theirColorDark = HSLColor.fromAHSL(
hslDark.alpha,
hslDark.hue,
theirSatDark,
theirLightDark,
).toColor();
final hslLight = HSLColor.fromColor(accent);
final double myLightSat = (hslLight.saturation * 0.6).clamp(0.3, 0.7);
final double myLightLight = (hslLight.lightness * 0.3 + 0.6).clamp(
0.6,
0.9,
);
final Color myColorLight = HSLColor.fromAHSL(
hslLight.alpha,
hslLight.hue,
myLightSat,
myLightLight,
).toColor();
// Для светлой темы используем RGB(70, 70, 70) по умолчанию
final Color theirColorLight = const Color(0xFF464646); // RGB(70, 70, 70)
if (_myBubbleColorLight == myColorLight &&
_theirBubbleColorLight == theirColorLight &&
_myBubbleColorDark == myColorDark &&
_theirBubbleColorDark == theirColorDark) {
return;
}
_myBubbleColorLight = myColorLight;
_theirBubbleColorLight = theirColorLight;
_myBubbleColorDark = myColorDark;
_theirBubbleColorDark = theirColorDark;
}
Future<void> setUseGlassPanels(bool value) async {
_activeTheme = _activeTheme.copyWith(useGlassPanels: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setTopBarBlur(double value) async {
_activeTheme = _activeTheme.copyWith(topBarBlur: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setTopBarOpacity(double value) async {
_activeTheme = _activeTheme.copyWith(topBarOpacity: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setBottomBarBlur(double value) async {
_activeTheme = _activeTheme.copyWith(bottomBarBlur: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setBottomBarOpacity(double value) async {
_activeTheme = _activeTheme.copyWith(bottomBarOpacity: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setMessageFontSize(double value) async {
_activeTheme = _activeTheme.copyWith(messageFontSize: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setMyBubbleColorLight(Color? color) async {
_myBubbleColorLight = color;
_activeTheme = _activeTheme.copyWith(myBubbleColorLight: color);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setTheirBubbleColorLight(Color? color) async {
_theirBubbleColorLight = color;
_activeTheme = _activeTheme.copyWith(theirBubbleColorLight: color);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setMyBubbleColorDark(Color? color) async {
_myBubbleColorDark = color;
_activeTheme = _activeTheme.copyWith(myBubbleColorDark: color);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setTheirBubbleColorDark(Color? color) async {
_theirBubbleColorDark = color;
_activeTheme = _activeTheme.copyWith(theirBubbleColorDark: color);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setMessageBubbleType(MessageBubbleType value) async {
_activeTheme = _activeTheme.copyWith(messageBubbleType: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setSendOnEnter(bool value) async {
_activeTheme = _activeTheme.copyWith(sendOnEnter: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setUseCustomChatWallpaper(bool value) async {
_activeTheme = _activeTheme.copyWith(useCustomChatWallpaper: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setChatWallpaperType(ChatWallpaperType type) async {
_activeTheme = _activeTheme.copyWith(chatWallpaperType: type);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setChatWallpaperColor1(Color color) async {
_activeTheme = _activeTheme.copyWith(chatWallpaperColor1: color);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setChatWallpaperColor2(Color color) async {
_activeTheme = _activeTheme.copyWith(chatWallpaperColor2: color);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setChatWallpaperImagePath(String? path) async {
_activeTheme = _activeTheme.copyWith(chatWallpaperImagePath: path);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setChatWallpaperVideoPath(String? path) async {
_activeTheme = _activeTheme.copyWith(chatWallpaperVideoPath: path);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setProfileDialogBlur(double value) async {
_activeTheme = _activeTheme.copyWith(
profileDialogBlur: value.clamp(0.0, 30.0),
);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setProfileDialogOpacity(double value) async {
_activeTheme = _activeTheme.copyWith(
profileDialogOpacity: value.clamp(0.0, 1.0),
);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setChatWallpaperBlur(bool value) async {
_activeTheme = _activeTheme.copyWith(chatWallpaperBlur: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setChatWallpaperBlurSigma(double value) async {
_activeTheme = _activeTheme.copyWith(
chatWallpaperBlurSigma: value.clamp(0.0, 20.0),
);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setChatWallpaperImageBlur(double value) async {
_activeTheme = _activeTheme.copyWith(
chatWallpaperImageBlur: value.clamp(0.0, 10.0),
);
notifyListeners();
await _saveActiveTheme();
}
Future<void> resetChatWallpaperToDefaults() async {
_activeTheme = _activeTheme.copyWith(
useCustomChatWallpaper: false,
chatWallpaperType: ChatWallpaperType.solid,
chatWallpaperColor1: const Color(0xFF101010),
chatWallpaperColor2: const Color(0xFF202020),
chatWallpaperImagePath: null,
chatWallpaperBlur: false,
chatWallpaperImageBlur: 0.0,
);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setChatSpecificWallpaper(int chatId, String? imagePath) async {
if (imagePath == null || imagePath.isEmpty) {
_chatSpecificWallpapers.remove(chatId);
} else {
_chatSpecificWallpapers[chatId] = imagePath;
}
notifyListeners();
final prefs = await SharedPreferences.getInstance();
final key = 'chat_wallpaper_$chatId';
if (imagePath == null || imagePath.isEmpty) {
await prefs.remove(key);
} else {
await prefs.setString(key, imagePath);
}
}
String? getChatSpecificWallpaper(int chatId) {
return _chatSpecificWallpapers[chatId];
}
bool hasChatSpecificWallpaper(int chatId) {
return _chatSpecificWallpapers.containsKey(chatId) &&
_chatSpecificWallpapers[chatId] != null &&
_chatSpecificWallpapers[chatId]!.isNotEmpty;
}
Future<void> loadChatSpecificWallpapers() async {
final prefs = await SharedPreferences.getInstance();
final keys = prefs.getKeys();
_chatSpecificWallpapers.clear();
for (final key in keys) {
if (key.startsWith('chat_wallpaper_')) {
final chatIdStr = key.substring('chat_wallpaper_'.length);
final chatId = int.tryParse(chatIdStr);
if (chatId != null) {
final imagePath = prefs.getString(key);
if (imagePath != null && imagePath.isNotEmpty) {
_chatSpecificWallpapers[chatId] = imagePath;
}
}
}
}
notifyListeners();
}
Future<void> setUIMode(UIMode value) async {
_activeTheme = _activeTheme.copyWith(uiMode: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setShowSeconds(bool value) async {
_activeTheme = _activeTheme.copyWith(showSeconds: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setMessageBubbleOpacity(double value) async {
_activeTheme = _activeTheme.copyWith(
messageBubbleOpacity: value.clamp(0.0, 1.0),
);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setMessageStyle(String value) async {
_activeTheme = _activeTheme.copyWith(messageStyle: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setMessageBackgroundBlur(double value) async {
_activeTheme = _activeTheme.copyWith(
messageBackgroundBlur: value.clamp(0.0, 10.0),
);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setMessageTextOpacity(double value) async {
_activeTheme = _activeTheme.copyWith(
messageTextOpacity: value.clamp(0.1, 1.0),
);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setMessageShadowIntensity(double value) async {
_activeTheme = _activeTheme.copyWith(
messageShadowIntensity: value.clamp(0.0, 0.5),
);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setMessageBorderRadius(double value) async {
_activeTheme = _activeTheme.copyWith(
messageBorderRadius: value.clamp(4.0, 50.0),
);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setMessageMenuOpacity(double value) async {
_activeTheme = _activeTheme.copyWith(messageMenuOpacity: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setMessageMenuBlur(double value) async {
_activeTheme = _activeTheme.copyWith(messageMenuBlur: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setDebugShowPerformanceOverlay(bool value) async {
_debugShowPerformanceOverlay = value;
notifyListeners();
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('debug_perf_overlay', value);
}
Future<void> setDebugShowChatsRefreshPanel(bool value) async {
_debugShowChatsRefreshPanel = value;
notifyListeners();
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('debug_show_chats_refresh_panel', value);
}
Future<void> setDebugShowMessageCount(bool value) async {
_debugShowMessageCount = value;
notifyListeners();
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('debug_show_message_count', value);
}
Future<void> setDebugReadOnEnter(bool value) async {
_debugReadOnEnter = value;
notifyListeners();
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('debug_read_on_enter', value);
}
Future<void> setDebugReadOnAction(bool value) async {
_debugReadOnAction = value;
notifyListeners();
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('debug_read_on_action', value);
}
Future<void> setDebugShowBurgerMenu(bool value) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('debug_show_burger_menu', value);
}
Future<void> setChatTransition(TransitionOption value) async {
_activeTheme = _activeTheme.copyWith(chatTransition: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setTabTransition(TransitionOption value) async {
_activeTheme = _activeTheme.copyWith(tabTransition: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setMessageTransition(TransitionOption value) async {
_activeTheme = _activeTheme.copyWith(messageTransition: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setExtraTransition(TransitionOption value) async {
_activeTheme = _activeTheme.copyWith(extraTransition: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setExtraAnimationStrength(double value) async {
_activeTheme = _activeTheme.copyWith(
extraAnimationStrength: value.clamp(1.0, 400.0),
);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setMessageSlideDistance(double value) async {
_activeTheme = _activeTheme.copyWith(
messageSlideDistance: value.clamp(1.0, 200.0),
);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setAnimatePhotoMessages(bool value) async {
_activeTheme = _activeTheme.copyWith(animatePhotoMessages: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setOptimizeChats(bool value) async {
_activeTheme = _activeTheme.copyWith(
optimizeChats: value,
ultraOptimizeChats: value ? false : _activeTheme.ultraOptimizeChats,
);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setUltraOptimizeChats(bool value) async {
_activeTheme = _activeTheme.copyWith(
ultraOptimizeChats: value,
optimizeChats: value ? false : _activeTheme.optimizeChats,
);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setHighQualityPhotos(bool value) async {
_highQualityPhotos = value;
notifyListeners();
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('high_quality_photos', _highQualityPhotos);
}
Future<void> setBlockBypass(bool value) async {
_blockBypass = value;
notifyListeners();
final prefs = await SharedPreferences.getInstance();
await prefs.setBool('block_bypass', _blockBypass);
}
Future<void> setUseDesktopLayout(bool value) async {
_activeTheme = _activeTheme.copyWith(useDesktopLayout: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setUseAutoReplyColor(bool value) async {
_activeTheme = _activeTheme.copyWith(useAutoReplyColor: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setMobileChatBottomPadding(double value) async {
final clamped = value.clamp(60.0, 240.0);
_activeTheme = _activeTheme.copyWith(
mobileChatBottomPadding: clamped,
);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setIgnoreMobileBottomPaddingWhenKeyboard(bool value) async {
_activeTheme = _activeTheme.copyWith(
ignoreMobileBottomPaddingWhenKeyboard: value,
);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setUseExperimentalChatsListBackground(bool value) async {
_activeTheme = _activeTheme.copyWith(useExperimentalChatsListBackground: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setExperimentalChatsListBackgroundType(ChatWallpaperType value) async {
_activeTheme = _activeTheme.copyWith(experimentalChatsListBackgroundType: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setExperimentalChatsListBackgroundColor1(Color value) async {
_activeTheme = _activeTheme.copyWith(experimentalChatsListBackgroundColor1: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setExperimentalChatsListBackgroundColor2(Color value) async {
_activeTheme = _activeTheme.copyWith(experimentalChatsListBackgroundColor2: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setExperimentalChatsListBackgroundImagePath(String? path) async {
_activeTheme = _activeTheme.copyWith(experimentalChatsListBackgroundImagePath: path);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setDrawerTopBackgroundType(ChatWallpaperType value) async {
_activeTheme = _activeTheme.copyWith(drawerTopBackgroundType: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setDrawerTopBackgroundColor1(Color value) async {
_activeTheme = _activeTheme.copyWith(drawerTopBackgroundColor1: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setDrawerTopBackgroundColor2(Color value) async {
_activeTheme = _activeTheme.copyWith(drawerTopBackgroundColor2: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setDrawerTopBackgroundImagePath(String? path) async {
_activeTheme = _activeTheme.copyWith(drawerTopBackgroundImagePath: path);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setDrawerBottomBackgroundType(ChatWallpaperType value) async {
_activeTheme = _activeTheme.copyWith(drawerBottomBackgroundType: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setDrawerBottomBackgroundColor1(Color value) async {
_activeTheme = _activeTheme.copyWith(drawerBottomBackgroundColor1: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setDrawerBottomBackgroundColor2(Color value) async {
_activeTheme = _activeTheme.copyWith(drawerBottomBackgroundColor2: value);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setDrawerBottomBackgroundImagePath(String? path) async {
_activeTheme = _activeTheme.copyWith(drawerBottomBackgroundImagePath: path);
notifyListeners();
await _saveActiveTheme();
}
Future<void> setCustomReplyColor(Color? color) async {
_activeTheme = _activeTheme.copyWith(customReplyColor: color);
notifyListeners();
await _saveActiveTheme();
}
void toggleTheme() {
if (appTheme == AppTheme.light) {
setTheme(AppTheme.dark);
} else {
setTheme(AppTheme.light);
}
}
Future<void> resetAnimationsToDefault() async {
_activeTheme = _activeTheme.copyWith(
chatTransition: TransitionOption.systemDefault,
tabTransition: TransitionOption.systemDefault,
messageTransition: TransitionOption.systemDefault,
extraTransition: TransitionOption.systemDefault,
messageSlideDistance: 96.0,
extraAnimationStrength: 32.0,
);
notifyListeners();
await _saveActiveTheme();
}
}