diff --git a/flutter/lib/cm_main.dart b/flutter/lib/cm_main.dart index a92edd194..422e7aa26 100644 --- a/flutter/lib/cm_main.dart +++ b/flutter/lib/cm_main.dart @@ -24,7 +24,5 @@ void main(List args) async { gFFI.serverModel.clients .add(Client(3, false, false, "UserD", "441123123", true, false, false)); runApp(GetMaterialApp( - debugShowCheckedModeBanner: false, - theme: MyTheme.initialTheme(), - home: DesktopServerPage())); + debugShowCheckedModeBanner: false, home: DesktopServerPage())); } diff --git a/flutter/lib/common.dart b/flutter/lib/common.dart index bd16fa4c5..06d901368 100644 --- a/flutter/lib/common.dart +++ b/flutter/lib/common.dart @@ -193,25 +193,40 @@ class MyTheme { ); static changeTo(bool dark) { - Get.find().setString("darkTheme", dark ? "Y" : ""); - Get.changeTheme(dark ? MyTheme.darkTheme : MyTheme.lightTheme); - Get.forceAppUpdate(); + if (Get.isDarkMode != dark) { + Get.find().setString("darkTheme", dark ? "Y" : ""); + Get.changeThemeMode(dark ? ThemeMode.dark : ThemeMode.light); + if (desktopType == DesktopType.main) { + bind.mainChangeTheme(dark: dark); + } + } } static bool _themeInitialed = false; - static ThemeData initialTheme({bool mainPage = 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(); + dark = "Y" == Get.find().getString("darkTheme"); } else { dark = WidgetsBinding.instance.platformDispatcher.platformBrightness == Brightness.dark; Get.find().setString("darkTheme", dark ? "Y" : ""); } _themeInitialed = true; - return dark ? MyTheme.darkTheme : MyTheme.lightTheme; + return dark ? ThemeMode.dark : ThemeMode.light; + } + + static registerEventHandler() { + if (desktopType != DesktopType.main) { + platformFFI.registerEventHandler('theme', 'theme-$desktopType', (evt) { + String? dark = evt['dark']; + if (dark != null) { + changeTo(dark == 'true'); + } + }); + } } static ColorThemeExtension color(BuildContext context) { @@ -232,8 +247,7 @@ class ThemeModeNotifier { } bool isDarkTheme() { - final isDark = "Y" == Get.find().getString("darkTheme"); - return isDark; + return Get.isDarkMode; } final ButtonStyle flatButtonStyle = TextButton.styleFrom( diff --git a/flutter/lib/consts.dart b/flutter/lib/consts.dart index 95a6faaa2..e48c85b0d 100644 --- a/flutter/lib/consts.dart +++ b/flutter/lib/consts.dart @@ -5,6 +5,8 @@ const String kAppTypeMain = "main"; const String kAppTypeDesktopRemote = "remote"; const String kAppTypeDesktopFileTransfer = "file transfer"; const String kAppTypeDesktopPortForward = "port forward"; +const String kAppTypeDesktopRDP = "rdp"; + const String kTabLabelHomePage = "Home"; const String kTabLabelSettingPage = "Settings"; diff --git a/flutter/lib/main.dart b/flutter/lib/main.dart index a25ed7027..2ca1d3e51 100644 --- a/flutter/lib/main.dart +++ b/flutter/lib/main.dart @@ -79,6 +79,7 @@ Future initEnv(String appType) async { await initGlobalFFI(); // await Firebase.initializeApp(); refreshCurrentUser(); + MyTheme.registerEventHandler(); } void runMainApp(bool startService) async { @@ -113,7 +114,9 @@ void runRemoteScreen(Map argument) async { navigatorKey: globalKey, debugShowCheckedModeBanner: false, title: 'RustDesk - Remote Desktop', - theme: MyTheme.initialTheme(), + theme: MyTheme.lightTheme, + darkTheme: MyTheme.darkTheme, + themeMode: MyTheme.initialThemeMode(), home: DesktopRemoteScreen( params: argument, ), @@ -131,7 +134,9 @@ void runFileTransferScreen(Map argument) async { navigatorKey: globalKey, debugShowCheckedModeBanner: false, title: 'RustDesk - File Transfer', - theme: MyTheme.initialTheme(), + theme: MyTheme.lightTheme, + darkTheme: MyTheme.darkTheme, + themeMode: MyTheme.initialThemeMode(), home: DesktopFileTransferScreen(params: argument), navigatorObservers: [ // FirebaseAnalyticsObserver(analytics: analytics), @@ -148,7 +153,9 @@ void runPortForwardScreen(Map argument) async { navigatorKey: globalKey, debugShowCheckedModeBanner: false, title: 'RustDesk - Port Forward', - theme: MyTheme.initialTheme(), + theme: MyTheme.lightTheme, + darkTheme: MyTheme.darkTheme, + themeMode: MyTheme.initialThemeMode(), home: DesktopPortForwardScreen(params: argument), navigatorObservers: [ // FirebaseAnalyticsObserver(analytics: analytics), @@ -172,7 +179,9 @@ void runConnectionManagerScreen() async { ]); runApp(GetMaterialApp( debugShowCheckedModeBanner: false, - theme: MyTheme.initialTheme(), + theme: MyTheme.lightTheme, + darkTheme: MyTheme.darkTheme, + themeMode: MyTheme.initialThemeMode(), home: DesktopServerPage(), builder: _keepScaleBuilder())); } @@ -225,7 +234,9 @@ class _AppState extends State { navigatorKey: globalKey, debugShowCheckedModeBanner: false, title: 'RustDesk', - theme: MyTheme.initialTheme(mainPage: true), + theme: MyTheme.lightTheme, + darkTheme: MyTheme.darkTheme, + themeMode: MyTheme.initialThemeMode(mainPage: true), home: isDesktop ? const DesktopTabPage() : !isAndroid diff --git a/src/flutter.rs b/src/flutter.rs index 4be998027..ffabef1a9 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -17,6 +17,8 @@ use crate::{client::*, flutter_ffi::EventToUI}; pub(super) const APP_TYPE_MAIN: &str = "main"; pub(super) const APP_TYPE_DESKTOP_REMOTE: &str = "remote"; pub(super) const APP_TYPE_DESKTOP_FILE_TRANSFER: &str = "file transfer"; +pub(super) const APP_TYPE_DESKTOP_PORT_FORWARD: &str = "port forward"; +pub(super) const APP_TYPE_DESKTOP_RDP: &str = "rdp"; lazy_static::lazy_static! { pub static ref SESSIONS: RwLock>> = Default::default(); @@ -376,6 +378,10 @@ pub mod connection_manager { vec![("id", &id.to_string()), ("text", &text)], ); } + + fn change_theme(&self, dark: bool) { + self.push_event("theme", vec![("dark", &dark.to_string())]); + } } impl FlutterHandler { diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index 977c03197..13966e07c 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -23,7 +23,7 @@ use crate::ui_interface::{ get_app_name, get_async_job_status, get_connect_status, get_fav, get_id, get_lan_peers, get_langs, get_license, get_local_option, get_mouse_time, get_option, get_options, get_peer, get_peer_option, get_socks, get_sound_inputs, get_uuid, get_version, has_hwcodec, - has_rendezvous_service, post_request, set_local_option, set_option, set_options, + has_rendezvous_service, post_request, send_to_cm, set_local_option, set_option, set_options, set_peer_option, set_permanent_password, set_socks, store_fav, test_if_valid_server, update_temporary_password, using_public_server, }; @@ -659,6 +659,23 @@ pub fn main_load_lan_peers() { }; } +pub fn main_change_theme(dark: bool) { + let apps = vec![ + flutter::APP_TYPE_DESKTOP_REMOTE, + flutter::APP_TYPE_DESKTOP_FILE_TRANSFER, + flutter::APP_TYPE_DESKTOP_PORT_FORWARD, + flutter::APP_TYPE_DESKTOP_RDP, + ]; + + for app in apps { + if let Some(s) = flutter::GLOBAL_EVENT_STREAM.read().unwrap().get(app) { + let data = HashMap::from([("name", "theme".to_owned()), ("dark", dark.to_string())]); + s.add(serde_json::ser::to_string(&data).unwrap_or("".to_owned())); + }; + } + send_to_cm(&crate::ipc::Data::Theme(dark)); +} + pub fn session_add_port_forward( id: String, local_port: i32, diff --git a/src/ipc.rs b/src/ipc.rs index 0bdc3f43b..3d289e499 100644 --- a/src/ipc.rs +++ b/src/ipc.rs @@ -182,6 +182,7 @@ pub enum Data { #[cfg(not(any(target_os = "android", target_os = "ios", feature = "cli")))] Mouse(DataMouse), Control(DataControl), + Theme(bool), Empty, } diff --git a/src/ui/cm.rs b/src/ui/cm.rs index 2b1e3e791..615718e4a 100644 --- a/src/ui/cm.rs +++ b/src/ui/cm.rs @@ -47,6 +47,10 @@ impl InvokeUiCM for SciterHandler { fn new_message(&self, id: i32, text: String) { self.call("newMessage", &make_args!(id, text)); } + + fn change_theme(&self, _dark: bool) { + // TODO + } } impl SciterHandler { diff --git a/src/ui_cm_interface.rs b/src/ui_cm_interface.rs index d416fdd63..92724bb25 100644 --- a/src/ui_cm_interface.rs +++ b/src/ui_cm_interface.rs @@ -60,6 +60,8 @@ pub trait InvokeUiCM: Send + Clone + 'static + Sized { fn remove_connection(&self, id: i32); fn new_message(&self, id: i32, text: String); + + fn change_theme(&self, dark: bool); } impl Deref for ConnectionManager { @@ -280,6 +282,9 @@ pub async fn start_ipc(cm: ConnectionManager) { .send(ClipboardFileData::Enable((conn_id, enabled))) .ok(); } + Data::Theme(dark) => { + cm.change_theme(dark); + } _ => { } diff --git a/src/ui_interface.rs b/src/ui_interface.rs index 186381ce4..c7b743ccb 100644 --- a/src/ui_interface.rs +++ b/src/ui_interface.rs @@ -373,7 +373,8 @@ pub fn get_mouse_time() -> f64 { } pub fn check_mouse_time() { - #[cfg(not(any(target_os = "android", target_os = "ios")))]{ + #[cfg(not(any(target_os = "android", target_os = "ios")))] + { let sender = SENDER.lock().unwrap(); allow_err!(sender.send(ipc::Data::MouseMoveTime(0))); } @@ -779,6 +780,13 @@ pub(crate) async fn check_connect_status_(reconnect: bool, rx: mpsc::UnboundedRe } } +#[tokio::main(flavor = "current_thread")] +pub(crate) async fn send_to_cm(data: &ipc::Data) { + if let Ok(mut c) = ipc::connect(1000, "_cm").await { + c.send(data).await.ok(); + } +} + const INVALID_FORMAT: &'static str = "Invalid format"; const UNKNOWN_ERROR: &'static str = "Unknown error";