From 86d83e12b0675f6a454846f95949ae999d188a12 Mon Sep 17 00:00:00 2001 From: csf Date: Wed, 21 Sep 2022 23:32:59 +0800 Subject: [PATCH] opt: dark theme, add follow system mode --- flutter/lib/common.dart | 60 +++++++++++++------ .../desktop/pages/desktop_setting_page.dart | 30 ++++++---- .../lib/desktop/pages/port_forward_page.dart | 2 +- flutter/lib/main.dart | 31 ++++++---- flutter/lib/mobile/pages/settings_page.dart | 4 +- src/flutter.rs | 4 +- src/flutter_ffi.rs | 4 +- src/ipc.rs | 2 +- src/ui/cm.rs | 2 +- src/ui_cm_interface.rs | 2 +- 10 files changed, 89 insertions(+), 52 deletions(-) diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index 0b56e9f1a..365ce3dd5 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -197,30 +197,39 @@ class MyTheme { ], ); - static changeTo(bool dark) { - if (isDarkTheme() != dark) { - Get.find().setString("darkTheme", dark ? "Y" : ""); - Get.changeThemeMode(dark ? ThemeMode.dark : ThemeMode.light); + static ThemeMode getThemeModePreference() { + return themeModeFromString( + Get.find().getString("themeMode") ?? ""); + } + + static void changeDarkMode(ThemeMode mode) { + final preference = getThemeModePreference(); + if (preference != mode) { + if (mode == ThemeMode.system) { + Get.find().setString("themeMode", ""); + } else { + Get.find() + .setString("themeMode", mode.toShortString()); + } + Get.changeThemeMode(mode); if (desktopType == DesktopType.main) { - bind.mainChangeTheme(dark: dark); + bind.mainChangeTheme(dark: currentThemeMode().toShortString()); } } } - static bool _themeInitialed = false; - - static ThemeMode initialThemeMode({bool mainPage = false}) { - bool dark; - // Brightnesss is always light on windows, Flutter 3.0.5 - if (_themeInitialed || !mainPage || Platform.isWindows) { - dark = isDarkTheme(); + static ThemeMode currentThemeMode() { + final preference = getThemeModePreference(); + if (preference == ThemeMode.system) { + if (WidgetsBinding.instance.platformDispatcher.platformBrightness == + Brightness.light) { + return ThemeMode.light; + } else { + return ThemeMode.dark; + } } else { - dark = WidgetsBinding.instance.platformDispatcher.platformBrightness == - Brightness.dark; - Get.find().setString("darkTheme", dark ? "Y" : ""); + return preference; } - _themeInitialed = true; - return dark ? ThemeMode.dark : ThemeMode.light; } static ColorThemeExtension color(BuildContext context) { @@ -230,10 +239,23 @@ class MyTheme { static TabbarTheme tabbar(BuildContext context) { return Theme.of(context).extension()!; } + + static ThemeMode themeModeFromString(String v) { + switch (v) { + case "light": + return ThemeMode.light; + case "dark": + return ThemeMode.dark; + default: + return ThemeMode.system; + } + } } -bool isDarkTheme() { - return "Y" == Get.find().getString("darkTheme"); +extension ParseToString on ThemeMode { + String toShortString() { + return toString().split('.').last; + } } final ButtonStyle flatButtonStyle = TextButton.styleFrom( diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart index f79d58b50..5ab3b9a51 100644 --- a/flutter/lib/desktop/pages/desktop_setting_page.dart +++ b/flutter/lib/desktop/pages/desktop_setting_page.dart @@ -205,22 +205,28 @@ class _GeneralState extends State<_General> { } Widget theme() { - change() { - MyTheme.changeTo(!isDarkTheme()); + final current = MyTheme.getThemeModePreference().toShortString(); + onChanged(String value) { + MyTheme.changeDarkMode(MyTheme.themeModeFromString(value)); setState(() {}); } return _Card(title: 'Theme', children: [ - GestureDetector( - onTap: change, - child: Row( - children: [ - Checkbox(value: isDarkTheme(), onChanged: (_) => change()) - .marginOnly(right: 5), - Expanded(child: Text(translate('Dark Theme'))), - ], - ).marginOnly(left: _kCheckBoxLeftMargin), - ) + _Radio(context, + value: "light", + groupValue: current, + label: "Light", + onChanged: onChanged), + _Radio(context, + value: "dark", + groupValue: current, + label: "Dark", + onChanged: onChanged), + _Radio(context, + value: "system", + groupValue: current, + label: "Follow System", + onChanged: onChanged), ]); } diff --git a/flutter/lib/desktop/pages/port_forward_page.dart b/flutter/lib/desktop/pages/port_forward_page.dart index 49946cc56..28aa8d3cf 100644 --- a/flutter/lib/desktop/pages/port_forward_page.dart +++ b/flutter/lib/desktop/pages/port_forward_page.dart @@ -247,7 +247,7 @@ class _PortForwardPageState extends State height: _kRowHeight, decoration: BoxDecoration( color: index % 2 == 0 - ? isDarkTheme() + ? MyTheme.currentThemeMode() == ThemeMode.dark ? const Color(0xFF202020) : const Color(0xFFF4F5F6) : MyTheme.color(context).bg), diff --git a/flutter/lib/main.dart b/flutter/lib/main.dart index 8f04846e9..a8df504d1 100644 --- a/flutter/lib/main.dart +++ b/flutter/lib/main.dart @@ -120,7 +120,7 @@ void runRemoteScreen(Map argument) async { title: 'RustDesk - Remote Desktop', theme: MyTheme.lightTheme, darkTheme: MyTheme.darkTheme, - themeMode: MyTheme.initialThemeMode(), + themeMode: MyTheme.currentThemeMode(), home: DesktopRemoteScreen( params: argument, ), @@ -146,7 +146,7 @@ void runFileTransferScreen(Map argument) async { title: 'RustDesk - File Transfer', theme: MyTheme.lightTheme, darkTheme: MyTheme.darkTheme, - themeMode: MyTheme.initialThemeMode(), + themeMode: MyTheme.currentThemeMode(), home: DesktopFileTransferScreen(params: argument), localizationsDelegates: const [ GlobalMaterialLocalizations.delegate, @@ -171,7 +171,7 @@ void runPortForwardScreen(Map argument) async { title: 'RustDesk - Port Forward', theme: MyTheme.lightTheme, darkTheme: MyTheme.darkTheme, - themeMode: MyTheme.initialThemeMode(), + themeMode: MyTheme.currentThemeMode(), home: DesktopPortForwardScreen(params: argument), localizationsDelegates: const [ GlobalMaterialLocalizations.delegate, @@ -196,7 +196,7 @@ void runConnectionManagerScreen() async { debugShowCheckedModeBanner: false, theme: MyTheme.lightTheme, darkTheme: MyTheme.darkTheme, - themeMode: MyTheme.initialThemeMode(), + themeMode: MyTheme.currentThemeMode(), localizationsDelegates: const [ GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, @@ -233,12 +233,21 @@ class _AppState extends State { void initState() { super.initState(); WidgetsBinding.instance.window.onPlatformBrightnessChanged = () { + final userPreference = MyTheme.getThemeModePreference(); + if (userPreference != ThemeMode.system) return; WidgetsBinding.instance.handlePlatformBrightnessChanged(); - var system = - WidgetsBinding.instance.platformDispatcher.platformBrightness; - var current = isDarkTheme() ? Brightness.dark : Brightness.light; - if (current != system) { - MyTheme.changeTo(system == Brightness.dark); + final systemIsDark = + WidgetsBinding.instance.platformDispatcher.platformBrightness == + Brightness.dark; + final ThemeMode to; + if (systemIsDark) { + to = ThemeMode.dark; + } else { + to = ThemeMode.light; + } + Get.changeThemeMode(to); + if (desktopType == DesktopType.main) { + bind.mainChangeTheme(dark: to.toShortString()); } }; } @@ -263,7 +272,7 @@ class _AppState extends State { title: 'RustDesk', theme: MyTheme.lightTheme, darkTheme: MyTheme.darkTheme, - themeMode: MyTheme.initialThemeMode(mainPage: true), + themeMode: MyTheme.currentThemeMode(), home: isDesktop ? const DesktopTabPage() : !isAndroid @@ -309,7 +318,7 @@ _registerEventHandler() { platformFFI.registerEventHandler('theme', 'theme', (evt) async { String? dark = evt['dark']; if (dark != null) { - MyTheme.changeTo(dark == 'true'); + MyTheme.changeDarkMode(MyTheme.themeModeFromString(dark)); } }); platformFFI.registerEventHandler('language', 'language', (_) async { diff --git a/flutter/lib/mobile/pages/settings_page.dart b/flutter/lib/mobile/pages/settings_page.dart index dc3a153d7..6f986ee78 100644 --- a/flutter/lib/mobile/pages/settings_page.dart +++ b/flutter/lib/mobile/pages/settings_page.dart @@ -60,7 +60,7 @@ class _SettingsState extends State with WidgetsBindingObserver { _enableAbr = enableAbrRes; } - _enableAbr = isDarkTheme(); + // _isDarkMode = MyTheme.currentDarkMode(); // TODO if (update) { setState(() {}); @@ -184,7 +184,7 @@ class _SettingsState extends State with WidgetsBindingObserver { onToggle: (v) { setState(() { _isDarkMode = !_isDarkMode; - MyTheme.changeTo(_isDarkMode); + // MyTheme.changeDarkMode(_isDarkMode); // TODO }); }, ) diff --git a/src/flutter.rs b/src/flutter.rs index 566576b5d..fea412c23 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -379,8 +379,8 @@ pub mod connection_manager { ); } - fn change_theme(&self, dark: bool) { - self.push_event("theme", vec![("dark", &dark.to_string())]); + fn change_theme(&self, dark: String) { + self.push_event("theme", vec![("dark", &dark)]); } fn change_language(&self) { diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index 0579ac272..f41108895 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -692,10 +692,10 @@ fn main_broadcast_message(data: &HashMap<&str, &str>) { } } -pub fn main_change_theme(dark: bool) { +pub fn main_change_theme(dark: String) { main_broadcast_message(&HashMap::from([ ("name", "theme"), - ("dark", &dark.to_string()), + ("dark", &dark), ])); send_to_cm(&crate::ipc::Data::Theme(dark)); } diff --git a/src/ipc.rs b/src/ipc.rs index 2d841755b..36f6b9c1f 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -182,7 +182,7 @@ pub enum Data { #[cfg(not(any(target_os = "android", target_os = "ios", feature = "cli")))] Mouse(DataMouse), Control(DataControl), - Theme(bool), + Theme(String), Language(String), Empty, } diff --git a/src/ui/cm.rs b/src/ui/cm.rs index c5f64699a..959141da6 100644 --- a/src/ui/cm.rs +++ b/src/ui/cm.rs @@ -48,7 +48,7 @@ impl InvokeUiCM for SciterHandler { self.call("newMessage", &make_args!(id, text)); } - fn change_theme(&self, _dark: bool) { + fn change_theme(&self, _dark: String) { // TODO } diff --git a/src/ui_cm_interface.rs b/src/ui_cm_interface.rs index a7082e9ee..e4dbf80fb 100644 --- a/src/ui_cm_interface.rs +++ b/src/ui_cm_interface.rs @@ -61,7 +61,7 @@ pub trait InvokeUiCM: Send + Clone + 'static + Sized { fn new_message(&self, id: i32, text: String); - fn change_theme(&self, dark: bool); + fn change_theme(&self, dark: String); fn change_language(&self); }