mirror of
https://gitlab.com/famedly/fluffychat.git
synced 2025-02-25 10:50:40 +01:00
feat: Make the main color editable for users
This commit is contained in:
parent
39f7fd6c0b
commit
fcc41a8d1d
@ -1,5 +1,7 @@
|
|||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:matrix/matrix.dart';
|
||||||
|
|
||||||
abstract class AppConfig {
|
abstract class AppConfig {
|
||||||
static String _applicationName = 'FluffyChat';
|
static String _applicationName = 'FluffyChat';
|
||||||
static String get applicationName => _applicationName;
|
static String get applicationName => _applicationName;
|
||||||
@ -9,6 +11,7 @@ abstract class AppConfig {
|
|||||||
static String get defaultHomeserver => _defaultHomeserver;
|
static String get defaultHomeserver => _defaultHomeserver;
|
||||||
static String jitsiInstance = 'https://meet.jit.si/';
|
static String jitsiInstance = 'https://meet.jit.si/';
|
||||||
static double fontSizeFactor = 1;
|
static double fontSizeFactor = 1;
|
||||||
|
static Color chatColor = primaryColor;
|
||||||
static const double messageFontSize = 15.75;
|
static const double messageFontSize = 15.75;
|
||||||
static const bool allowOtherHomeservers = true;
|
static const bool allowOtherHomeservers = true;
|
||||||
static const bool enableRegistration = true;
|
static const bool enableRegistration = true;
|
||||||
@ -54,6 +57,15 @@ abstract class AppConfig {
|
|||||||
static const double columnWidth = 360.0;
|
static const double columnWidth = 360.0;
|
||||||
|
|
||||||
static void loadFromJson(Map<String, dynamic> json) {
|
static void loadFromJson(Map<String, dynamic> json) {
|
||||||
|
if (json['chat_color'] != null) {
|
||||||
|
try {
|
||||||
|
chatColor = Color(json['application_name']);
|
||||||
|
} catch (e) {
|
||||||
|
Logs().w(
|
||||||
|
'Invalid color in config.json! Please make sure to define the color in this format: "0xffdd0000"',
|
||||||
|
e);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (json['application_name'] is String) {
|
if (json['application_name'] is String) {
|
||||||
_applicationName = json['application_name'];
|
_applicationName = json['application_name'];
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ abstract class SettingKeys {
|
|||||||
static const String renderHtml = 'chat.fluffy.renderHtml';
|
static const String renderHtml = 'chat.fluffy.renderHtml';
|
||||||
static const String hideRedactedEvents = 'chat.fluffy.hideRedactedEvents';
|
static const String hideRedactedEvents = 'chat.fluffy.hideRedactedEvents';
|
||||||
static const String hideUnknownEvents = 'chat.fluffy.hideUnknownEvents';
|
static const String hideUnknownEvents = 'chat.fluffy.hideUnknownEvents';
|
||||||
|
static const String chatColor = 'chat.fluffy.chat_color';
|
||||||
static const String sentry = 'sentry';
|
static const String sentry = 'sentry';
|
||||||
static const String theme = 'theme';
|
static const String theme = 'theme';
|
||||||
static const String amoledEnabled = 'amoled_enabled';
|
static const String amoledEnabled = 'amoled_enabled';
|
||||||
|
@ -31,22 +31,23 @@ abstract class FluffyThemes {
|
|||||||
subtitle2: fallbackTextStyle)
|
subtitle2: fallbackTextStyle)
|
||||||
: const TextTheme();
|
: const TextTheme();
|
||||||
|
|
||||||
static ThemeData light = ThemeData(
|
static ThemeData get light => ThemeData(
|
||||||
visualDensity: VisualDensity.standard,
|
visualDensity: VisualDensity.standard,
|
||||||
primaryColorDark: Colors.white,
|
primaryColorDark: Colors.white,
|
||||||
primaryColorLight: const Color(0xff121212),
|
primaryColorLight: const Color(0xff121212),
|
||||||
brightness: Brightness.light,
|
brightness: Brightness.light,
|
||||||
primaryColor: AppConfig.primaryColor,
|
primaryColor: AppConfig.chatColor,
|
||||||
colorScheme: ThemeData.light().colorScheme.copyWith(
|
colorScheme: ThemeData.light().colorScheme.copyWith(
|
||||||
primary: AppConfig.primaryColor,
|
primary: AppConfig.chatColor,
|
||||||
secondary: AppConfig.primaryColor,
|
secondary: AppConfig.chatColor,
|
||||||
secondaryVariant: AppConfig.secondaryColor,
|
secondaryVariant: AppConfig.secondaryColor,
|
||||||
),
|
),
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
secondaryHeaderColor: const Color(0xffeeeffe),
|
secondaryHeaderColor: Colors.blueGrey.shade50,
|
||||||
scaffoldBackgroundColor: Colors.white,
|
scaffoldBackgroundColor: Colors.white,
|
||||||
textTheme: Typography.material2018().black.merge(fallbackTextTheme),
|
textTheme: Typography.material2018().black.merge(fallbackTextTheme),
|
||||||
snackBarTheme: const SnackBarThemeData(behavior: SnackBarBehavior.floating),
|
snackBarTheme:
|
||||||
|
const SnackBarThemeData(behavior: SnackBarBehavior.floating),
|
||||||
pageTransitionsTheme: const PageTransitionsTheme(
|
pageTransitionsTheme: const PageTransitionsTheme(
|
||||||
builders: {
|
builders: {
|
||||||
TargetPlatform.fuchsia: ZoomPageTransitionsBuilder(),
|
TargetPlatform.fuchsia: ZoomPageTransitionsBuilder(),
|
||||||
@ -68,13 +69,13 @@ abstract class FluffyThemes {
|
|||||||
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
floatingActionButtonTheme: const FloatingActionButtonThemeData(
|
floatingActionButtonTheme: FloatingActionButtonThemeData(
|
||||||
backgroundColor: AppConfig.primaryColor,
|
backgroundColor: AppConfig.chatColor,
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
),
|
),
|
||||||
elevatedButtonTheme: ElevatedButtonThemeData(
|
elevatedButtonTheme: ElevatedButtonThemeData(
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
primary: AppConfig.primaryColor,
|
primary: AppConfig.chatColor,
|
||||||
onPrimary: Colors.white,
|
onPrimary: Colors.white,
|
||||||
elevation: 6,
|
elevation: 6,
|
||||||
shadowColor: const Color(0x44000000),
|
shadowColor: const Color(0x44000000),
|
||||||
@ -99,11 +100,11 @@ abstract class FluffyThemes {
|
|||||||
enabledBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: lighten(AppConfig.primaryColor, .51),
|
color: lighten(AppConfig.chatColor, .51),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
filled: true,
|
filled: true,
|
||||||
fillColor: lighten(AppConfig.primaryColor, .51),
|
fillColor: lighten(AppConfig.chatColor, .51),
|
||||||
),
|
),
|
||||||
appBarTheme: const AppBarTheme(
|
appBarTheme: const AppBarTheme(
|
||||||
elevation: 6,
|
elevation: 6,
|
||||||
@ -118,11 +119,11 @@ abstract class FluffyThemes {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
static ThemeData dark = ThemeData.dark().copyWith(
|
static ThemeData get dark => ThemeData.dark().copyWith(
|
||||||
visualDensity: VisualDensity.standard,
|
visualDensity: VisualDensity.standard,
|
||||||
primaryColorDark: const Color(0xff121212),
|
primaryColorDark: const Color(0xff121212),
|
||||||
primaryColorLight: Colors.white,
|
primaryColorLight: Colors.white,
|
||||||
primaryColor: AppConfig.primaryColor,
|
primaryColor: AppConfig.chatColor,
|
||||||
errorColor: const Color(0xFFCF6679),
|
errorColor: const Color(0xFFCF6679),
|
||||||
backgroundColor: Colors.black,
|
backgroundColor: Colors.black,
|
||||||
scaffoldBackgroundColor: Colors.black,
|
scaffoldBackgroundColor: Colors.black,
|
||||||
@ -131,7 +132,7 @@ abstract class FluffyThemes {
|
|||||||
secondary: AppConfig.primaryColorLight,
|
secondary: AppConfig.primaryColorLight,
|
||||||
secondaryVariant: AppConfig.secondaryColor,
|
secondaryVariant: AppConfig.secondaryColor,
|
||||||
),
|
),
|
||||||
secondaryHeaderColor: const Color(0xff232543),
|
secondaryHeaderColor: Colors.blueGrey.shade900,
|
||||||
textTheme: Typography.material2018().white.merge(fallbackTextTheme),
|
textTheme: Typography.material2018().white.merge(fallbackTextTheme),
|
||||||
dialogTheme: DialogTheme(
|
dialogTheme: DialogTheme(
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
@ -160,8 +161,8 @@ abstract class FluffyThemes {
|
|||||||
TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
|
TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
floatingActionButtonTheme: const FloatingActionButtonThemeData(
|
floatingActionButtonTheme: FloatingActionButtonThemeData(
|
||||||
backgroundColor: AppConfig.primaryColor,
|
backgroundColor: AppConfig.chatColor,
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
),
|
),
|
||||||
inputDecorationTheme: InputDecorationTheme(
|
inputDecorationTheme: InputDecorationTheme(
|
||||||
@ -172,13 +173,13 @@ abstract class FluffyThemes {
|
|||||||
enabledBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: FluffyThemes.darken(AppConfig.primaryColor, .31),
|
color: FluffyThemes.darken(AppConfig.chatColor, .31),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
elevatedButtonTheme: ElevatedButtonThemeData(
|
elevatedButtonTheme: ElevatedButtonThemeData(
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
primary: AppConfig.primaryColor,
|
primary: AppConfig.chatColor,
|
||||||
onPrimary: Colors.white,
|
onPrimary: Colors.white,
|
||||||
minimumSize: const Size.fromHeight(48),
|
minimumSize: const Size.fromHeight(48),
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
@ -187,7 +188,8 @@ abstract class FluffyThemes {
|
|||||||
padding: const EdgeInsets.all(12),
|
padding: const EdgeInsets.all(12),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
snackBarTheme: const SnackBarThemeData(behavior: SnackBarBehavior.floating),
|
snackBarTheme:
|
||||||
|
const SnackBarThemeData(behavior: SnackBarBehavior.floating),
|
||||||
appBarTheme: const AppBarTheme(
|
appBarTheme: const AppBarTheme(
|
||||||
elevation: 6,
|
elevation: 6,
|
||||||
systemOverlayStyle: SystemUiOverlayStyle.light,
|
systemOverlayStyle: SystemUiOverlayStyle.light,
|
||||||
|
@ -235,7 +235,7 @@ class ChatView extends StatelessWidget {
|
|||||||
: null,
|
: null,
|
||||||
backgroundColor: Theme.of(context).brightness == Brightness.light
|
backgroundColor: Theme.of(context).brightness == Brightness.light
|
||||||
? FluffyThemes.lighten(Theme.of(context).primaryColor, 0.51)
|
? FluffyThemes.lighten(Theme.of(context).primaryColor, 0.51)
|
||||||
: FluffyThemes.darken(Theme.of(context).primaryColor, 0.325),
|
: FluffyThemes.darken(Theme.of(context).primaryColor, 0.35),
|
||||||
body: Stack(
|
body: Stack(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
if (Matrix.of(context).wallpaper != null)
|
if (Matrix.of(context).wallpaper != null)
|
||||||
|
@ -7,6 +7,7 @@ import 'package:file_picker_cross/file_picker_cross.dart';
|
|||||||
|
|
||||||
import 'package:fluffychat/config/app_config.dart';
|
import 'package:fluffychat/config/app_config.dart';
|
||||||
import 'package:fluffychat/config/setting_keys.dart';
|
import 'package:fluffychat/config/setting_keys.dart';
|
||||||
|
import 'package:fluffychat/config/themes.dart';
|
||||||
import '../../widgets/matrix.dart';
|
import '../../widgets/matrix.dart';
|
||||||
import 'settings_style_view.dart';
|
import 'settings_style_view.dart';
|
||||||
|
|
||||||
@ -35,8 +36,29 @@ class SettingsStyleController extends State<SettingsStyle> {
|
|||||||
setState(() => null);
|
setState(() => null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setChatColor(Color color) async {
|
||||||
|
await Matrix.of(context).store.setItem(
|
||||||
|
SettingKeys.chatColor,
|
||||||
|
color.value.toString(),
|
||||||
|
);
|
||||||
|
AppConfig.chatColor = color;
|
||||||
|
AdaptiveTheme.of(context).setTheme(
|
||||||
|
light: FluffyThemes.light,
|
||||||
|
dark: FluffyThemes.dark,
|
||||||
|
isDefault: true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
AdaptiveThemeMode currentTheme;
|
AdaptiveThemeMode currentTheme;
|
||||||
|
|
||||||
|
static List<Color> customColors = [
|
||||||
|
AppConfig.primaryColor,
|
||||||
|
Colors.blue.shade700,
|
||||||
|
Colors.green.shade700,
|
||||||
|
Colors.pink.shade700,
|
||||||
|
Colors.orange.shade700,
|
||||||
|
];
|
||||||
|
|
||||||
void switchTheme(AdaptiveThemeMode newTheme) {
|
void switchTheme(AdaptiveThemeMode newTheme) {
|
||||||
switch (newTheme) {
|
switch (newTheme) {
|
||||||
case AdaptiveThemeMode.light:
|
case AdaptiveThemeMode.light:
|
||||||
|
@ -16,6 +16,7 @@ class SettingsStyleView extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
controller.currentTheme ??= AdaptiveTheme.of(context).mode;
|
controller.currentTheme ??= AdaptiveTheme.of(context).mode;
|
||||||
|
const colorPickerSize = 32.0;
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: const BackButton(),
|
leading: const BackButton(),
|
||||||
@ -25,6 +26,36 @@ class SettingsStyleView extends StatelessWidget {
|
|||||||
withScrolling: true,
|
withScrolling: true,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
|
Row(
|
||||||
|
children: SettingsStyleController.customColors
|
||||||
|
.map(
|
||||||
|
(color) => Padding(
|
||||||
|
padding: const EdgeInsets.all(12.0),
|
||||||
|
child: InkWell(
|
||||||
|
borderRadius: BorderRadius.circular(colorPickerSize),
|
||||||
|
onTap: () => controller.setChatColor(color),
|
||||||
|
child: Material(
|
||||||
|
color: color,
|
||||||
|
elevation: 6,
|
||||||
|
borderRadius: BorderRadius.circular(colorPickerSize),
|
||||||
|
child: SizedBox(
|
||||||
|
width: colorPickerSize,
|
||||||
|
height: colorPickerSize,
|
||||||
|
child: AppConfig.chatColor.value == color.value
|
||||||
|
? const Center(
|
||||||
|
child: Icon(
|
||||||
|
Icons.check,
|
||||||
|
size: 16,
|
||||||
|
color: Colors.white,
|
||||||
|
))
|
||||||
|
: null),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
const Divider(height: 1),
|
||||||
RadioListTile<AdaptiveThemeMode>(
|
RadioListTile<AdaptiveThemeMode>(
|
||||||
groupValue: controller.currentTheme,
|
groupValue: controller.currentTheme,
|
||||||
value: AdaptiveThemeMode.system,
|
value: AdaptiveThemeMode.system,
|
||||||
@ -86,8 +117,9 @@ class SettingsStyleView extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||||
child: Material(
|
child: Material(
|
||||||
color: Theme.of(context).backgroundColor,
|
color: Theme.of(context).primaryColor,
|
||||||
elevation: 6,
|
elevation: 6,
|
||||||
shadowColor:
|
shadowColor:
|
||||||
Theme.of(context).secondaryHeaderColor.withAlpha(100),
|
Theme.of(context).secondaryHeaderColor.withAlpha(100),
|
||||||
@ -97,6 +129,7 @@ class SettingsStyleView extends StatelessWidget {
|
|||||||
child: Text(
|
child: Text(
|
||||||
'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor',
|
'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
fontSize:
|
fontSize:
|
||||||
AppConfig.messageFontSize * AppConfig.fontSizeFactor,
|
AppConfig.messageFontSize * AppConfig.fontSizeFactor,
|
||||||
),
|
),
|
||||||
|
@ -5,6 +5,7 @@ import 'dart:io';
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:adaptive_theme/adaptive_theme.dart';
|
||||||
import 'package:desktop_notifications/desktop_notifications.dart';
|
import 'package:desktop_notifications/desktop_notifications.dart';
|
||||||
import 'package:flutter_app_lock/flutter_app_lock.dart';
|
import 'package:flutter_app_lock/flutter_app_lock.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
@ -17,6 +18,7 @@ import 'package:universal_html/html.dart' as html;
|
|||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
import 'package:vrouter/vrouter.dart';
|
import 'package:vrouter/vrouter.dart';
|
||||||
|
|
||||||
|
import 'package:fluffychat/config/themes.dart';
|
||||||
import 'package:fluffychat/utils/client_manager.dart';
|
import 'package:fluffychat/utils/client_manager.dart';
|
||||||
import 'package:fluffychat/utils/matrix_sdk_extensions.dart/matrix_locals.dart';
|
import 'package:fluffychat/utils/matrix_sdk_extensions.dart/matrix_locals.dart';
|
||||||
import 'package:fluffychat/utils/platform_infos.dart';
|
import 'package:fluffychat/utils/platform_infos.dart';
|
||||||
@ -477,6 +479,16 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
|
|||||||
store
|
store
|
||||||
.getItemBool(SettingKeys.sendOnEnter, AppConfig.sendOnEnter)
|
.getItemBool(SettingKeys.sendOnEnter, AppConfig.sendOnEnter)
|
||||||
.then((value) => AppConfig.sendOnEnter = value);
|
.then((value) => AppConfig.sendOnEnter = value);
|
||||||
|
store.getItem(SettingKeys.chatColor).then((value) {
|
||||||
|
if (value != null && int.tryParse(value) != null) {
|
||||||
|
AppConfig.chatColor = Color(int.parse(value));
|
||||||
|
AdaptiveTheme.of(context).setTheme(
|
||||||
|
light: FluffyThemes.light,
|
||||||
|
dark: FluffyThemes.dark,
|
||||||
|
isDefault: true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user