diff --git a/flutter/lib/main.dart b/flutter/lib/main.dart index 68752cf7d..318f9c2cc 100644 --- a/flutter/lib/main.dart +++ b/flutter/lib/main.dart @@ -126,6 +126,7 @@ void runMainApp(bool startService) async { // await windowManager.ensureInitialized(); gFFI.serverModel.startService(); bind.pluginSyncUi(syncTo: kAppTypeMain); + bind.pluginListReload(); } gFFI.userModel.refreshCurrentUser(); runApp(App()); diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart index a91e1dc6f..48e890f4a 100644 --- a/flutter/lib/models/model.dart +++ b/flutter/lib/models/model.dart @@ -231,6 +231,7 @@ class FfiModel with ChangeNotifier { } else if (name == 'fingerprint') { FingerprintState.find(peerId).value = evt['fingerprint'] ?? ''; } else if (name == 'plugin_manager') { + debugPrint('REMOVE ME ==================== plugin_manager $evt'); pluginManager.handleEvent(evt); } else if (name == 'plugin_event') { handlePluginEvent( diff --git a/flutter/lib/plugin/manager.dart b/flutter/lib/plugin/manager.dart index c445efaf0..326b2a5e4 100644 --- a/flutter/lib/plugin/manager.dart +++ b/flutter/lib/plugin/manager.dart @@ -1,6 +1,7 @@ // The plugin manager is a singleton class that manages the plugins. // 1. It merge metadata and the desc of plugins. +import 'dart:convert'; import 'dart:collection'; import 'package:flutter/material.dart'; @@ -211,17 +212,19 @@ class PluginManager with ChangeNotifier { } } - void _handlePluginList(List evt) { + void _handlePluginList(String pluginList) { _plugins.clear(); - - for (var p in evt) { - final plugin = _getPluginFromEvent(p); - if (plugin == null) { - continue; + try { + for (var p in json.decode(pluginList) as List) { + final plugin = _getPluginFromEvent(p); + if (plugin == null) { + continue; + } + _plugins.add(plugin); } - _plugins.add(plugin); + } catch (e) { + debugPrint('Failed to decode plugin list \'$pluginList\''); } - notifyListeners(); } diff --git a/libs/hbb_common/Cargo.toml b/libs/hbb_common/Cargo.toml index e886ad1f5..bff36093f 100644 --- a/libs/hbb_common/Cargo.toml +++ b/libs/hbb_common/Cargo.toml @@ -35,6 +35,7 @@ chrono = "0.4" backtrace = "0.3" libc = "0.2" dlopen = "0.1" +toml = "0.7" [target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies] mac_address = "1.1" @@ -55,5 +56,4 @@ winapi = { version = "0.3", features = ["winuser"] } osascript = "0.3" [dev-dependencies] -toml = "0.7" serde_json = "1.0" diff --git a/libs/hbb_common/src/lib.rs b/libs/hbb_common/src/lib.rs index e80b9e609..ba21edc7e 100644 --- a/libs/hbb_common/src/lib.rs +++ b/libs/hbb_common/src/lib.rs @@ -46,6 +46,7 @@ pub mod keyboard; pub use sysinfo; #[cfg(not(any(target_os = "android", target_os = "ios")))] pub use dlopen; +pub use toml; #[cfg(feature = "quic")] pub type Stream = quic::Connection; diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index 444b3dccb..4d7c21dfd 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -1570,7 +1570,7 @@ pub fn plugin_list_reload() { #[cfg(feature = "plugin_framework")] #[cfg(not(any(target_os = "android", target_os = "ios")))] { - crate::plugin::load_plugin_list(false); + crate::plugin::load_plugin_list(); } } diff --git a/src/plugin/manager.rs b/src/plugin/manager.rs index e1d9ead9b..3d8fbef5a 100644 --- a/src/plugin/manager.rs +++ b/src/plugin/manager.rs @@ -3,7 +3,7 @@ use super::{desc::Meta as PluginMeta, ipc::InstallStatus, *}; use crate::{common::is_server, flutter}; -use hbb_common::{allow_err, bail, log, tokio}; +use hbb_common::{allow_err, bail, config::load_path, log, tokio, toml}; use serde_derive::{Deserialize, Serialize}; use serde_json; use std::{ @@ -21,7 +21,7 @@ lazy_static::lazy_static! { static ref PLUGIN_INFO: Arc>> = Arc::new(Mutex::new(HashMap::new())); } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Default, Serialize, Deserialize)] pub struct ManagerMeta { pub version: String, pub description: String, @@ -45,24 +45,47 @@ pub struct PluginInfo { } static PLUGIN_SOURCE_LOCAL: &str = "local"; -pub(super) static PLUGIN_SOURCE_LOCAL_URL: &str = "plugins"; +#[cfg(not(debug_assertions))] fn get_plugin_source_list() -> Vec { // Only one source for now. vec![PluginSource { name: "rustdesk".to_string(), - #[cfg(debug_assertions)] - url: PLUGIN_SOURCE_LOCAL_URL.to_string(), - #[cfg(not(debug_assertions))] url: "https://github.com/fufesou/rustdesk-plugins".to_string(), description: "".to_string(), }] } +#[cfg(debug_assertions)] +fn get_source_plugins() -> HashMap { + let meta_file = super::get_plugins_dir().unwrap().join("meta.toml"); + let mut plugins = HashMap::new(); + let meta = load_path::(meta_file); + let source = PluginSource { + name: "rustdesk".to_string(), + url: "https://github.com/fufesou/rustdesk-plugins".to_string(), + description: "".to_string(), + }; + for plugin in meta.plugins.iter() { + plugins.insert( + plugin.id.clone(), + PluginInfo { + source: source.clone(), + plugin: plugin.clone(), + installed_version: "".to_string(), + install_time: "".to_string(), + invalid_reason: "".to_string(), + }, + ); + } + plugins +} + +#[cfg(not(debug_assertions))] fn get_source_plugins() -> HashMap { let mut plugins = HashMap::new(); for source in get_plugin_source_list().into_iter() { - let url = format!("{}/meta.json", source.url); + let url = format!("{}/meta.toml", source.url); match reqwest::blocking::get(&url) { Ok(resp) => { if !resp.status().is_success() { @@ -109,16 +132,8 @@ fn send_plugin_list_event(plugins: &HashMap) { } } -pub fn load_plugin_list(load_local: bool) { +pub fn load_plugin_list() { let mut plugin_info_lock = PLUGIN_INFO.lock().unwrap(); - - if load_local { - if is_server() { - allow_err!(super::plugins::load_plugins()); - return; - } - } - let mut plugins = get_source_plugins(); for (id, info) in super::plugins::get_plugin_infos().read().unwrap().iter() { if let Some(p) = plugins.get_mut(id) { @@ -130,7 +145,7 @@ pub fn load_plugin_list(load_local: bool) { PluginInfo { source: PluginSource { name: PLUGIN_SOURCE_LOCAL.to_string(), - url: PLUGIN_SOURCE_LOCAL_URL.to_string(), + url: PLUGIN_SOURCE_LOCAL_DIR.to_string(), description: "".to_string(), }, plugin: info.desc.meta().clone(), @@ -163,9 +178,7 @@ pub fn install_plugin(id: &str) -> ResultType<()> { } } -pub(super) fn remove_plugins() { - -} +pub(super) fn remove_plugins() {} // 1. Add to uninstall list. // 2. Try remove. diff --git a/src/plugin/mod.rs b/src/plugin/mod.rs index cd5e45a38..c539196f0 100644 --- a/src/plugin/mod.rs +++ b/src/plugin/mod.rs @@ -1,4 +1,4 @@ -use hbb_common::{libc, tokio, ResultType}; +use hbb_common::{libc, tokio, ResultType, allow_err, log}; use std::{ env, ffi::{c_char, c_int, c_void, CStr}, @@ -38,6 +38,8 @@ pub const EVENT_ON_CONN_SERVER: &str = "on_conn_server"; pub const EVENT_ON_CONN_CLOSE_CLIENT: &str = "on_conn_close_client"; pub const EVENT_ON_CONN_CLOSE_SERVER: &str = "on_conn_close_server"; +static PLUGIN_SOURCE_LOCAL_DIR: &str = "plugins"; + pub use config::{ManagerConfig, PeerConfig, SharedConfig}; use crate::common::is_server; @@ -91,14 +93,17 @@ pub fn init() { std::thread::spawn(move || manager::start_ipc()); if is_server() { manager::remove_plugins(); + allow_err!(plugins::load_plugins()); } - load_plugin_list(true); + load_plugin_list(); } #[inline] fn get_plugins_dir() -> ResultType { // to-do: linux and macos - Ok(PathBuf::from(env::var("ProgramData")?).join(manager::PLUGIN_SOURCE_LOCAL_URL)) + Ok(PathBuf::from(env::var("ProgramData")?) + .join("RustDesk") + .join(PLUGIN_SOURCE_LOCAL_DIR)) } #[inline]