new mac service and local config

This commit is contained in:
rustdesk 2022-04-26 11:19:45 +08:00
parent 05ac26e5fe
commit 3566b0ee7a
15 changed files with 308 additions and 419 deletions

70
Cargo.lock generated
View File

@ -1168,25 +1168,6 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "fsevent"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6"
dependencies = [
"bitflags",
"fsevent-sys",
]
[[package]]
name = "fsevent-sys"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "fuchsia-cprng" name = "fuchsia-cprng"
version = "0.1.1" version = "0.1.1"
@ -1805,26 +1786,6 @@ dependencies = [
"hashbrown", "hashbrown",
] ]
[[package]]
name = "inotify"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4816c66d2c8ae673df83366c18341538f234a26d65a9ecea5c348b453ac1d02f"
dependencies = [
"bitflags",
"inotify-sys",
"libc",
]
[[package]]
name = "inotify-sys"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "instant" name = "instant"
version = "0.1.12" version = "0.1.12"
@ -2205,18 +2166,6 @@ dependencies = [
"winapi 0.3.9", "winapi 0.3.9",
] ]
[[package]]
name = "mio-extras"
version = "2.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19"
dependencies = [
"lazycell",
"log",
"mio 0.6.23",
"slab",
]
[[package]] [[package]]
name = "mio-named-pipes" name = "mio-named-pipes"
version = "0.1.7" version = "0.1.7"
@ -2368,24 +2317,6 @@ dependencies = [
"minimal-lexical", "minimal-lexical",
] ]
[[package]]
name = "notify"
version = "4.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae03c8c853dba7bfd23e571ff0cff7bc9dceb40a4cd684cd1681824183f45257"
dependencies = [
"bitflags",
"filetime",
"fsevent",
"fsevent-sys",
"inotify",
"libc",
"mio 0.6.23",
"mio-extras",
"walkdir",
"winapi 0.3.9",
]
[[package]] [[package]]
name = "ntapi" name = "ntapi"
version = "0.3.7" version = "0.3.7"
@ -3349,7 +3280,6 @@ dependencies = [
"mac_address", "mac_address",
"machine-uid", "machine-uid",
"magnum-opus", "magnum-opus",
"notify",
"num_cpus", "num_cpus",
"objc", "objc",
"parity-tokio-ipc", "parity-tokio-ipc",

View File

@ -72,7 +72,6 @@ cocoa = "0.24"
dispatch = "0.2" dispatch = "0.2"
core-foundation = "0.9" core-foundation = "0.9"
core-graphics = "0.22" core-graphics = "0.22"
notify = "4.0.17"
include_dir = "0.7.2" include_dir = "0.7.2"
[target.'cfg(target_os = "linux")'.dependencies] [target.'cfg(target_os = "linux")'.dependencies]
psimple = { package = "libpulse-simple-binding", version = "2.25" } psimple = { package = "libpulse-simple-binding", version = "2.25" }

View File

@ -22,10 +22,7 @@ const SERIAL: i32 = 1;
#[cfg(target_os = "macos")] // 128x128 on 160x160 canvas, then shrink to 128, mac looks better with padding #[cfg(target_os = "macos")] // 128x128 on 160x160 canvas, then shrink to 128, mac looks better with padding
pub const ICON: &str = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAAyVBMVEUAAAAAcf8Acf8Acf8Acv8Acf8Acf8Acf8Acf8AcP8Acf8Ab/8AcP8Acf////8AaP/z+f/o8v/k7v/5/v/T5f8AYP/u9v/X6f+hx/+Kuv95pP8Aef/B1/+TwP9xoP8BdP/g6P+Irv9ZmP8Bgf/E3f98q/9sn/+01f+Es/9nm/9Jif8hhv8off/M4P+syP+avP86iP/c7f+xy/9yqf9Om/9hk/9Rjv+60P99tv9fpf88lv8yjf8Tgf8deP+kvP8BiP8NeP8hkP80gP8oj2VLAAAADXRSTlMA7o7qLvnaxZ1FOxYPjH9HWgAABHJJREFUeNrtm+tW4jAQgBfwuu7MtIUWsOUiCCioIIgLiqvr+z/UHq/LJKVkmwTcc/r9E2nzlU4mSTP9lpGRkZGR8VX5cZjfL+yCEXYL+/nDH//U/Pd8DgyTy39Xbv7oIAcWyB0cqbW/sweW2NtRaj8H1sgpGOwUIAH7Bkd7YJW9dXFwAJY5WNP/cmCZQnJvzIN18on5LwfWySXlxEPYAIcad8D6PdiHDbCfIFCADVBIENiFDbCbIACKPPXrZ+cP8E6/0znvP4EymgIEravIRcTxu8HxNSJ60a8W0AYECKrlAN+YwAthCd9wm1Ug6wKzIn5SgRduXfwkqDasCjx0XFzi9PV6zwNcIuhcWBOg+ikySq8C9UD4dEKWBCoOcspvAuLHTo9sCDQiFPHotRM48j8G5gVur1FdAN2uaYEuiz7xFsgEJ2RUoMUakXuBTHHoGxQYOBhHjeUBAefEnMAowFhaLBOKuOemBBbxLRQrH2PBCgMvNCPQGMeevTb9zLrPxz2Mo+QbEaijzPUcOOHMQZkKGRAIPem39+bypREMPTkQW/oCfk866zAkiIFG4yIKRE/aAnfiSd0WrORY6pFdXQEqi9mvAQm0RIOSnoCcZ8vJoz3diCnjRk+g8VP4/fuQDJ2Lxr6WwG0gXs9aTpDzW0vgDBlVUpixR8gYk44AD8FrUKHr8JQJGgIDnoDqoALxmWPQSi9AVVzm8gKUuEPGr/QCvptwJkbSYT/TC4S8C96DGjTj86aHtAI0x2WaBIq0eSYYpRa4EsdWVVwWu9O0Aj6f6dyBMnwEraeOgSYu0wZlauzA47QCbT7DgAQSE+hZWoEBF/BBmWOewNMK3BsSqKUW4MGcWqCSVmDkbvkXGKQOwg6PAUO9oL3xXhA20yaiCjuwYygRVQlUOTWTCf2SuNJTxeFjgaHByGuAIvd8ItdPLTDhS7IuqEE1YSKVOgbayLhSFQhMzYh8hwfBs1r7c505YVIQYEdNoKwxK06MJiyrpUFHiF0NAfCQUVHoiRclIXJIR6C2fqG37pBHvcWpgwzvAtYwkR5UGV2e42UISdBJETl3mg8ouo54Rcnti1/vaT+iuUQBt500Cgo4U10BeHSkk57FB0JjWkKRMWgLUA0lLodtImAQdaMiiri3+gIAPZQoutHNsgKF1aaDMhMyIdBf8Th+Bh8MTjGWCpl5Wv43tDmnF+IUVMrcZgRoiAxhtrloYizNkZaAnF5leglbNhj0wYCAbCDvGb0mP4nib7O7ZlcYQ2m1gPtIZgVgGNNMeaVAaWR+57TrqgtUnm3sHQ+kYeE6fufUubG1ez50FXbPnWgBlgSABmN3TTcsRl2yWkHRrwbiunvk/W2+Mg1hPZplPDeXRbZzStFH15s1QIVd3UImP5z/bHpeeQLvRJ7XLFUffQIlCvqlXETQbgN9/rlYABGosv+Vi9m2Xs639YLGrZd0br+odetlvdsvbN56abfd4vbCzv9Q3v/ygoOV21A4OPpfXvH4Ai+5ZGRkZGRkbJA/t/I0QMzoMiEAAAAASUVORK5CYII= pub const ICON: &str = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAAyVBMVEUAAAAAcf8Acf8Acf8Acv8Acf8Acf8Acf8Acf8AcP8Acf8Ab/8AcP8Acf////8AaP/z+f/o8v/k7v/5/v/T5f8AYP/u9v/X6f+hx/+Kuv95pP8Aef/B1/+TwP9xoP8BdP/g6P+Irv9ZmP8Bgf/E3f98q/9sn/+01f+Es/9nm/9Jif8hhv8off/M4P+syP+avP86iP/c7f+xy/9yqf9Om/9hk/9Rjv+60P99tv9fpf88lv8yjf8Tgf8deP+kvP8BiP8NeP8hkP80gP8oj2VLAAAADXRSTlMA7o7qLvnaxZ1FOxYPjH9HWgAABHJJREFUeNrtm+tW4jAQgBfwuu7MtIUWsOUiCCioIIgLiqvr+z/UHq/LJKVkmwTcc/r9E2nzlU4mSTP9lpGRkZGR8VX5cZjfL+yCEXYL+/nDH//U/Pd8DgyTy39Xbv7oIAcWyB0cqbW/sweW2NtRaj8H1sgpGOwUIAH7Bkd7YJW9dXFwAJY5WNP/cmCZQnJvzIN18on5LwfWySXlxEPYAIcad8D6PdiHDbCfIFCADVBIENiFDbCbIACKPPXrZ+cP8E6/0znvP4EymgIEravIRcTxu8HxNSJ60a8W0AYECKrlAN+YwAthCd9wm1Ug6wKzIn5SgRduXfwkqDasCjx0XFzi9PV6zwNcIuhcWBOg+ikySq8C9UD4dEKWBCoOcspvAuLHTo9sCDQiFPHotRM48j8G5gVur1FdAN2uaYEuiz7xFsgEJ2RUoMUakXuBTHHoGxQYOBhHjeUBAefEnMAowFhaLBOKuOemBBbxLRQrH2PBCgMvNCPQGMeevTb9zLrPxz2Mo+QbEaijzPUcOOHMQZkKGRAIPem39+bypREMPTkQW/oCfk866zAkiIFG4yIKRE/aAnfiSd0WrORY6pFdXQEqi9mvAQm0RIOSnoCcZ8vJoz3diCnjRk+g8VP4/fuQDJ2Lxr6WwG0gXs9aTpDzW0vgDBlVUpixR8gYk44AD8FrUKHr8JQJGgIDnoDqoALxmWPQSi9AVVzm8gKUuEPGr/QCvptwJkbSYT/TC4S8C96DGjTj86aHtAI0x2WaBIq0eSYYpRa4EsdWVVwWu9O0Aj6f6dyBMnwEraeOgSYu0wZlauzA47QCbT7DgAQSE+hZWoEBF/BBmWOewNMK3BsSqKUW4MGcWqCSVmDkbvkXGKQOwg6PAUO9oL3xXhA20yaiCjuwYygRVQlUOTWTCf2SuNJTxeFjgaHByGuAIvd8ItdPLTDhS7IuqEE1YSKVOgbayLhSFQhMzYh8hwfBs1r7c505YVIQYEdNoKwxK06MJiyrpUFHiF0NAfCQUVHoiRclIXJIR6C2fqG37pBHvcWpgwzvAtYwkR5UGV2e42UISdBJETl3mg8ouo54Rcnti1/vaT+iuUQBt500Cgo4U10BeHSkk57FB0JjWkKRMWgLUA0lLodtImAQdaMiiri3+gIAPZQoutHNsgKF1aaDMhMyIdBf8Th+Bh8MTjGWCpl5Wv43tDmnF+IUVMrcZgRoiAxhtrloYizNkZaAnF5leglbNhj0wYCAbCDvGb0mP4nib7O7ZlcYQ2m1gPtIZgVgGNNMeaVAaWR+57TrqgtUnm3sHQ+kYeE6fufUubG1ez50FXbPnWgBlgSABmN3TTcsRl2yWkHRrwbiunvk/W2+Mg1hPZplPDeXRbZzStFH15s1QIVd3UImP5z/bHpeeQLvRJ7XLFUffQIlCvqlXETQbgN9/rlYABGosv+Vi9m2Xs639YLGrZd0br+odetlvdsvbN56abfd4vbCzv9Q3v/ygoOV21A4OPpfXvH4Ai+5ZGRkZGRkbJA/t/I0QMzoMiEAAAAASUVORK5CYII=
"; ";
#[cfg(windows)] // windows, 32x32, bigger very ugly after shrink #[cfg(not(target_os = "macos"))] // 128x128 no padding
pub const ICON: &str = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAolBMVEUAAAAAcf8Acf8Acf8AcP8Acf8Acf8Acf8AcP8Acf/////9/v/7/f+gyv9wr/8Ld/8GdP/A3P+nzv+Qwf9mqv8lhv8UfP+Kvv88k/8zjv/x+P/Y6f/U5//J4f/F3/+x1P+pz/+izP+Cuv9Zov9Qnv9FmP8gg//f7f+42P96tv9fpv8ui//1+f/q8//o8v/Q5f+ax/+Zxv+VxP+Fu/9rrf8rif+x1o3FAAAACXRSTlMAv/RPTPKHioRsIqhAAAABNklEQVQ4y4WT6XaCQAyFB7S2GUD2RaxSKGDV7sv7v1on4djEluL9Ncn5biaZk1FKzSwbRmVbM2V0DRNaGD9Maq6sacBS9jRwpUTw1Ww7SEOvkwQDaeVofQeJ1nrXjgD3pTaqCDCg/xs4OBrlwUGTHvxzoHAx69Y9+Hk5oGdAsCNXSoHfEN1JYEme4KcfvO9WAmtMBNx6jIaCgSPGLbAyvKRhAEcrAxAKTSZiACu+gNSbyWwZeKdQKj91yRXWIOWZTMgATun6EtjgczNQaKMEWD0+xJ6B4AnvECVqdKwYoJ50hIPyw25AANkzpsLB00cYOIUEoHU0uVaQVcMxBwlgVZJ3Orz+3ahH6gP2tBgfYzsZmdo1fGIzRx5Irn2WxKaHeJnKtb/4cS5/PbWACd0oo/n/39/4vwGFYSxtSYV4OAAAAABJRU5ErkJggg==
";
#[cfg(target_os = "linux")] // 128x128 no padding
pub const ICON: &str = "data:image/png;base64,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 pub const ICON: &str = "data:image/png;base64,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
"; ";
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
@ -36,6 +33,7 @@ type Size = (i32, i32, i32, i32);
lazy_static::lazy_static! { lazy_static::lazy_static! {
static ref CONFIG: Arc<RwLock<Config>> = Arc::new(RwLock::new(Config::load())); static ref CONFIG: Arc<RwLock<Config>> = Arc::new(RwLock::new(Config::load()));
static ref CONFIG2: Arc<RwLock<Config2>> = Arc::new(RwLock::new(Config2::load())); static ref CONFIG2: Arc<RwLock<Config2>> = Arc::new(RwLock::new(Config2::load()));
static ref LOCAL_CONFIG: Arc<RwLock<LocalConfig>> = Arc::new(RwLock::new(LocalConfig::load()));
pub static ref ONLINE: Arc<Mutex<HashMap<String, i64>>> = Default::default(); pub static ref ONLINE: Arc<Mutex<HashMap<String, i64>>> = Default::default();
} }
#[cfg(any(target_os = "android", target_os = "ios"))] #[cfg(any(target_os = "android", target_os = "ios"))]
@ -61,7 +59,7 @@ pub enum NetworkType {
ProxySocks, ProxySocks,
} }
#[derive(Debug, Default, Serialize, Deserialize, Clone)] #[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
pub struct Config { pub struct Config {
#[serde(default)] #[serde(default)]
id: String, id: String,
@ -88,12 +86,8 @@ pub struct Socks5Server {
} }
// more variable configs // more variable configs
#[derive(Debug, Default, Serialize, Deserialize, Clone)] #[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
pub struct Config2 { pub struct Config2 {
#[serde(default)]
remote_id: String, // latest used one
#[serde(default)]
size: Size,
#[serde(default)] #[serde(default)]
rendezvous_server: String, rendezvous_server: String,
#[serde(default)] #[serde(default)]
@ -193,14 +187,23 @@ impl Config2 {
Config::load_::<Config2>("2") Config::load_::<Config2>("2")
} }
fn reload(&mut self) { pub fn file() -> PathBuf {
let new_config = Config2::load(); Config::file_("2")
*self = new_config;
} }
fn store(&self) { fn store(&self) {
Config::store_(self, "2"); Config::store_(self, "2");
} }
pub fn get() -> Config2 {
return CONFIG2.read().unwrap().clone();
}
pub fn set(cfg: Config2) {
let mut lock = CONFIG2.write().unwrap();
*lock = cfg;
lock.store();
}
} }
impl Config { impl Config {
@ -222,11 +225,6 @@ impl Config {
cfg cfg
} }
fn reload(&mut self) {
let new_config = Config::load();
*self = new_config;
}
fn store_<T: serde::Serialize>(config: &T, suffix: &str) { fn store_<T: serde::Serialize>(config: &T, suffix: &str) {
let file = Self::file_(suffix); let file = Self::file_(suffix);
if let Err(err) = confy::store_path(file, config) { if let Err(err) = confy::store_path(file, config) {
@ -623,33 +621,6 @@ impl Config {
salt salt
} }
pub fn get_size() -> Size {
CONFIG2.read().unwrap().size
}
pub fn set_size(x: i32, y: i32, w: i32, h: i32) {
let mut config = CONFIG2.write().unwrap();
let size = (x, y, w, h);
if size == config.size || size.2 < 300 || size.3 < 300 {
return;
}
config.size = size;
config.store();
}
pub fn set_remote_id(remote_id: &str) {
let mut config = CONFIG2.write().unwrap();
if remote_id == config.remote_id {
return;
}
config.remote_id = remote_id.into();
config.store();
}
pub fn get_remote_id() -> String {
CONFIG2.read().unwrap().remote_id.clone()
}
pub fn set_socks(socks: Option<Socks5Server>) { pub fn set_socks(socks: Option<Socks5Server>) {
let mut config = CONFIG2.write().unwrap(); let mut config = CONFIG2.write().unwrap();
if config.socks == socks { if config.socks == socks {
@ -670,91 +641,14 @@ impl Config {
} }
} }
pub fn sync_config_to_user<P: AsRef<Path>>(target_username: String, to_dir: P) -> bool { pub fn get() -> Config {
let config1_root_file_path = Config::file_(""); return CONFIG.read().unwrap().clone();
let config1_filename = config1_root_file_path.file_name();
let config2_root_file_path = Config::file_("2");
let config2_filename = config2_root_file_path.file_name();
let config1_to_file_path = to_dir
.as_ref()
.join(PathBuf::from(&config1_filename.unwrap()));
let config2_to_file_path = to_dir
.as_ref()
.join(PathBuf::from(&config2_filename.unwrap()));
log::info!(
"config1_root_path:{}",
&config1_root_file_path.as_path().to_str().unwrap()
);
log::info!(
"config2_root_path:{}",
&config2_root_file_path.as_path().to_str().unwrap()
);
log::info!(
"config1_to_path:{}",
&config1_to_file_path.as_path().to_str().unwrap()
);
log::info!(
"config2_to_path:{}",
&config2_to_file_path.as_path().to_str().unwrap()
);
match std::fs::copy(&config1_root_file_path, &config1_to_file_path) {
Err(e) => log::error!(
"copy config {} to user failed: {}",
config1_filename.unwrap().to_str().unwrap(),
e
),
_ => {}
}
match std::fs::copy(&config2_root_file_path, &config2_to_file_path) {
Err(e) => log::error!(
"copy config {} to user failed: {}",
config2_filename.unwrap().to_str().unwrap(),
e
),
_ => {}
}
let success = std::process::Command::new("chown")
.arg(&target_username.to_string())
.arg(&config1_to_file_path.to_str().unwrap().to_string())
.arg(&config2_to_file_path.to_str().unwrap().to_string())
.spawn()
.is_ok();
if success {
CONFIG.write().unwrap().reload();
CONFIG2.write().unwrap().reload();
}
return success;
} }
pub fn sync_config_to_root<P: AsRef<Path>>(from_file_path: P) -> bool { pub fn set(cfg: Config) {
if let Some(filename) = from_file_path.as_ref().file_name() { let mut lock = CONFIG.write().unwrap();
let to = Config::path(filename); *lock = cfg;
return match std::fs::copy(from_file_path, &to) { lock.store();
Ok(count) => {
if count > 0 {
return std::process::Command::new("chown")
.arg("root")
.arg(&to.to_str().unwrap().to_string())
.spawn()
.is_ok();
}
false
}
Err(e) => {
log::error!("sync_config_to_root failed: {}", e);
false
}
};
}
false
} }
} }
@ -801,9 +695,7 @@ impl PeerConfig {
&& p.extension().map(|p| p.to_str().unwrap_or("")) == Some("toml") && p.extension().map(|p| p.to_str().unwrap_or("")) == Some("toml")
}) })
.map(|p| { .map(|p| {
let t = fs::metadata(p) let t = crate::get_modified_time(&p);
.map(|m| m.modified().unwrap_or(SystemTime::UNIX_EPOCH))
.unwrap_or(SystemTime::UNIX_EPOCH);
let id = p let id = p
.file_stem() .file_stem()
.map(|p| p.to_str().unwrap_or("")) .map(|p| p.to_str().unwrap_or(""))
@ -826,27 +718,84 @@ impl PeerConfig {
} }
#[derive(Debug, Default, Serialize, Deserialize, Clone)] #[derive(Debug, Default, Serialize, Deserialize, Clone)]
pub struct Fav { pub struct LocalConfig {
#[serde(default)] #[serde(default)]
pub peers: Vec<String>, remote_id: String, // latest used one
#[serde(default)]
size: Size,
#[serde(default)]
pub fav: Vec<String>,
#[serde(default)]
options: HashMap<String, String>,
} }
impl Fav { impl LocalConfig {
pub fn load() -> Fav { fn load() -> LocalConfig {
let _ = CONFIG.read().unwrap(); // for lock Config::load_::<LocalConfig>("_local")
match confy::load_path(&Config::file_("_fav")) { }
Ok(fav) => fav,
Err(err) => { fn store(&self) {
log::error!("Failed to load fav: {}", err); Config::store_(self, "_local");
Default::default() }
}
pub fn get_size() -> Size {
LOCAL_CONFIG.read().unwrap().size
}
pub fn set_size(x: i32, y: i32, w: i32, h: i32) {
let mut config = LOCAL_CONFIG.write().unwrap();
let size = (x, y, w, h);
if size == config.size || size.2 < 300 || size.3 < 300 {
return;
}
config.size = size;
config.store();
}
pub fn set_remote_id(remote_id: &str) {
let mut config = LOCAL_CONFIG.write().unwrap();
if remote_id == config.remote_id {
return;
}
config.remote_id = remote_id.into();
config.store();
}
pub fn get_remote_id() -> String {
LOCAL_CONFIG.read().unwrap().remote_id.clone()
}
pub fn set_fav(fav: Vec<String>) {
let mut lock = LOCAL_CONFIG.write().unwrap();
if lock.fav == fav {
return;
}
lock.fav = fav;
lock.store();
}
pub fn get_fav() -> Vec<String> {
LOCAL_CONFIG.read().unwrap().fav.clone()
}
pub fn get_option(k: &str) -> String {
if let Some(v) = LOCAL_CONFIG.read().unwrap().options.get(k) {
v.clone()
} else {
"".to_owned()
} }
} }
pub fn store(peers: Vec<String>) { pub fn set_option(k: String, v: String) {
let f = Fav { peers }; let mut config = LOCAL_CONFIG.write().unwrap();
if let Err(err) = confy::store_path(Config::file_("_fav"), f) { let v2 = if v.is_empty() { None } else { Some(&v) };
log::error!("Failed to store fav: {}", err); if v2 != config.options.get(&k) {
if v2.is_none() {
config.options.remove(&k);
} else {
config.options.insert(k, v);
}
config.store();
} }
} }
} }

View File

@ -187,6 +187,12 @@ pub fn get_version_number(v: &str) -> i64 {
n n
} }
pub fn get_modified_time(path: &std::path::Path) -> SystemTime {
std::fs::metadata(&path)
.map(|m| m.modified().unwrap_or(UNIX_EPOCH))
.unwrap_or(UNIX_EPOCH)
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -465,3 +465,8 @@ pub fn is_ip(id: &str) -> bool {
.unwrap() .unwrap()
.is_match(id) .is_match(id)
} }
#[inline]
pub fn get_app_name() -> &'static str {
hbb_common::config::APP_NAME
}

View File

@ -3,7 +3,7 @@ pub use clipboard::ClipbaordFile;
use hbb_common::{ use hbb_common::{
allow_err, bail, bytes, allow_err, bail, bytes,
bytes_codec::BytesCodec, bytes_codec::BytesCodec,
config::{self, Config}, config::{self, Config, Config2},
futures::StreamExt as _, futures::StreamExt as _,
futures_util::sink::SinkExt, futures_util::sink::SinkExt,
log, timeout, tokio, log, timeout, tokio,
@ -96,15 +96,8 @@ pub enum Data {
Socks(Option<config::Socks5Server>), Socks(Option<config::Socks5Server>),
FS(FS), FS(FS),
Test, Test,
SyncConfigToRootReq { SyncConfig(Option<(Config, Config2)>),
from: String, #[cfg(not(any(target_os = "android", target_os = "ios")))]
},
SyncConfigToRootResp(bool),
SyncConfigToUserReq {
username: String,
to: String,
},
SyncConfigToUserResp(bool),
ClipbaordFile(ClipbaordFile), ClipbaordFile(ClipbaordFile),
ClipboardFileEnabled(bool), ClipboardFileEnabled(bool),
} }
@ -173,6 +166,30 @@ pub async fn new_listener(postfix: &str) -> ResultType<Incoming> {
} }
} }
pub struct CheckIfRestart(String, Vec<String>, String);
impl CheckIfRestart {
pub fn new() -> CheckIfRestart {
CheckIfRestart(
Config::get_option("stop-service"),
Config::get_rendezvous_servers(),
Config::get_option("audio-input"),
)
}
}
impl Drop for CheckIfRestart {
fn drop(&mut self) {
if self.0 != Config::get_option("stop-service")
|| self.1 != Config::get_rendezvous_servers()
{
RendezvousMediator::restart();
}
if self.2 != Config::get_option("audio-input") {
crate::audio_service::restart();
}
}
}
async fn handle(data: Data, stream: &mut Connection) { async fn handle(data: Data, stream: &mut Connection) {
match data { match data {
Data::SystemInfo(_) => { Data::SystemInfo(_) => {
@ -280,21 +297,15 @@ async fn handle(data: Data, stream: &mut Connection) {
let t = Config::get_nat_type(); let t = Config::get_nat_type();
allow_err!(stream.send(&Data::NatType(Some(t))).await); allow_err!(stream.send(&Data::NatType(Some(t))).await);
} }
Data::SyncConfigToRootReq { from } => { Data::SyncConfig(Some((config, config2))) => {
allow_err!( Config::set(config);
stream Config2::set(config2);
.send(&Data::SyncConfigToRootResp(Config::sync_config_to_root( allow_err!(stream.send(&Data::SyncConfig(None)).await);
from
)))
.await
);
} }
Data::SyncConfigToUserReq { username, to } => { Data::SyncConfig(None) => {
allow_err!( allow_err!(
stream stream
.send(&Data::SyncConfigToUserResp(Config::sync_config_to_user( .send(&Data::SyncConfig(Some((Config::get(), Config2::get()))))
username, to
)))
.await .await
); );
} }

View File

@ -1,4 +1,4 @@
use hbb_common::{config::Config, log}; use hbb_common::{config::LocalConfig, log};
use std::ops::Deref; use std::ops::Deref;
mod cn; mod cn;
@ -19,7 +19,7 @@ pub fn translate(name: String) -> String {
} }
pub fn translate_locale(name: String, locale: &str) -> String { pub fn translate_locale(name: String, locale: &str) -> String {
let mut lang = Config::get_option("lang"); let mut lang = LocalConfig::get_option("lang");
if lang.is_empty() { if lang.is_empty() {
lang = locale lang = locale
.split("-") .split("-")

View File

@ -104,11 +104,12 @@ pub fn is_can_screen_recording(prompt: bool) -> bool {
pub fn is_installed_daemon(prompt: bool) -> bool { pub fn is_installed_daemon(prompt: bool) -> bool {
let daemon = format!("{}_service.plist", crate::get_full_name()); let daemon = format!("{}_service.plist", crate::get_full_name());
let agent = format!("{}_server.plist", crate::get_full_name()); let agent = format!("{}_server.plist", crate::get_full_name());
let agent_plist_file = format!("/Library/LaunchAgents/{}", agent);
if !prompt { if !prompt {
if !std::path::Path::new(&format!("/Library/LaunchDaemons/{}", daemon)).exists() { if !std::path::Path::new(&format!("/Library/LaunchDaemons/{}", daemon)).exists() {
return false; return false;
} }
if !std::path::Path::new(&format!("/Library/LaunchAgents/{}", agent)).exists() { if !std::path::Path::new(&agent_plist_file).exists() {
return false; return false;
} }
return true; return true;
@ -123,43 +124,92 @@ pub fn is_installed_daemon(prompt: bool) -> bool {
let agent_plist = PRIVILEGES_SCRIPTS_DIR.get_file(&agent).unwrap(); let agent_plist = PRIVILEGES_SCRIPTS_DIR.get_file(&agent).unwrap();
let agent_plist_body = agent_plist.contents_utf8().unwrap(); let agent_plist_body = agent_plist.contents_utf8().unwrap();
match std::process::Command::new("osascript") std::thread::spawn(move || {
.arg("-e") match std::process::Command::new("osascript")
.arg(install_script_body) .arg("-e")
.arg(daemon_plist_body) .arg(install_script_body)
.arg(agent_plist_body) .arg(daemon_plist_body)
.arg(&get_active_username()) .arg(agent_plist_body)
.spawn() .arg(&get_active_username())
{ .output()
Ok(_) => { {
std::process::exit(0); Err(e) => {
log::error!("run osascript failed: {}", e);
}
_ => {
if std::path::Path::new(&agent_plist_file).exists() {
std::process::Command::new("osascript")
.arg("-e")
.arg(
PRIVILEGES_SCRIPTS_DIR
.get_file("run.scpt")
.unwrap()
.contents_utf8()
.unwrap(),
)
.arg(&format!(
"sleep 0.5; launchctl load -w {}; sleep 0.5; open /Applications/{}.app",
agent_plist_file,
crate::get_app_name()
))
.spawn()
.ok();
std::thread::sleep(std::time::Duration::from_millis(100)); // avoid exit crash
std::process::exit(0);
}
}
} }
Err(e) => { });
log::error!("run osascript failed: {}", e); false
false
}
}
} }
pub fn launch(load: bool) { pub fn uninstall() -> bool {
// to-do: do together with win/linux about refactory start/stop service // to-do: do together with win/linux about refactory start/stop service
if !is_installed() || !is_installed_daemon(false) { if !is_installed_daemon(false) {
return; return false;
}
let mut script_filename = "load.scpt";
if !load {
script_filename = "unload.scpt";
} }
let script_file = PRIVILEGES_SCRIPTS_DIR.get_file(script_filename).unwrap(); let script_file = PRIVILEGES_SCRIPTS_DIR.get_file("uninstall.scpt").unwrap();
let script_body = script_file.contents_utf8().unwrap(); let script_body = script_file.contents_utf8().unwrap();
std::process::Command::new("osascript") std::thread::spawn(move || {
.arg("-e") match std::process::Command::new("osascript")
.arg(script_body) .arg("-e")
.arg(&get_active_username()) .arg(script_body)
.spawn() .arg(&get_active_username())
.ok(); .output()
{
Err(e) => {
log::error!("run osascript failed: {}", e);
}
_ => {
let agent = format!("{}_server.plist", crate::get_full_name());
let agent_plist_file = format!("/Library/LaunchAgents/{}", agent);
if !std::path::Path::new(&agent_plist_file).exists() {
crate::ipc::set_option("stop-service", "Y");
std::process::Command::new("osascript")
.arg("-e")
.arg(
PRIVILEGES_SCRIPTS_DIR
.get_file("run.scpt")
.unwrap()
.contents_utf8()
.unwrap(),
)
.arg(&format!(
"sleep 0.5; launchctl remove {}_server; sleep 0.5; open /Applications/{}.app",
crate::get_full_name(),
crate::get_app_name()
))
.spawn()
.ok();
std::thread::sleep(std::time::Duration::from_millis(100)); // avoid exit crash
std::process::exit(0);
}
}
}
});
true
} }
pub fn get_cursor_pos() -> Option<(i32, i32)> { pub fn get_cursor_pos() -> Option<(i32, i32)> {
@ -352,6 +402,24 @@ pub fn lock_screen() {
pub fn start_os_service() { pub fn start_os_service() {
log::info!("{}", crate::username()); log::info!("{}", crate::username());
std::thread::spawn(move || loop {
let exe = std::env::current_exe().unwrap_or_default();
let tm0 = hbb_common::get_modified_time(&exe);
loop {
std::thread::sleep(std::time::Duration::from_millis(300));
if hbb_common::get_modified_time(&exe) != tm0 {
log::info!("{:?} updated, will restart", exe);
std::process::Command::new("pkill")
.args(&["-f", exe.to_str().unwrap_or("")])
.output()
.ok();
std::process::exit(0); // self not killed by above pkill
}
}
});
if let Err(err) = crate::ipc::start("_service") { if let Err(err) = crate::ipc::start("_service") {
log::error!("Failed to start ipc_service: {}", err); log::error!("Failed to start ipc_service: {}", err);
} }
@ -425,7 +493,7 @@ pub fn is_installed() -> bool {
if let Ok(p) = std::env::current_exe() { if let Ok(p) = std::env::current_exe() {
return p.to_str().unwrap_or_default().contains(&format!( return p.to_str().unwrap_or_default().contains(&format!(
"/Applications/{}.app", "/Applications/{}.app",
hbb_common::config::APP_NAME crate::get_app_name(),
)); ));
} }
false false

View File

@ -1,19 +1,16 @@
on run {daemon_file, agent_file, user} on run {daemon_file, agent_file, user}
set sh1 to "echo " & quoted form of daemon_file & " > /Library/LaunchDaemons/com.carriez.RustDesk_service.plist && chown root:wheel /Library/LaunchDaemons/com.carriez.RustDesk_service.plist;" set sh1 to "echo " & quoted form of daemon_file & " > /Library/LaunchDaemons/com.carriez.RustDesk_service.plist && chown root:wheel /Library/LaunchDaemons/com.carriez.RustDesk_service.plist;"
set sh2 to "echo " & quoted form of agent_file & " > /Library/LaunchAgents/com.carriez.RustDesk_server.plist && chown root:wheel /Library/LaunchAgents/com.carriez.RustDesk_server.plist;" set sh2 to "echo " & quoted form of agent_file & " > /Library/LaunchAgents/com.carriez.RustDesk_server.plist && chown root:wheel /Library/LaunchAgents/com.carriez.RustDesk_server.plist;"
set sh3 to "cp -rf /Users/" & user & "/Library/Preferences/com.carriez.RustDesk/RustDesk.toml /var/root/Library/Preferences/com.carriez.RustDesk/;" set sh3 to "cp -rf /Users/" & user & "/Library/Preferences/com.carriez.RustDesk/RustDesk.toml /var/root/Library/Preferences/com.carriez.RustDesk/;"
set sh4 to "cp -rf /Users/" & user & "/Library/Preferences/com.carriez.RustDesk/RustDesk2.toml /var/root/Library/Preferences/com.carriez.RustDesk/;" set sh4 to "cp -rf /Users/" & user & "/Library/Preferences/com.carriez.RustDesk/RustDesk2.toml /var/root/Library/Preferences/com.carriez.RustDesk/;"
set sh5 to "launchctl unload -w /Library/LaunchAgents/com.carriez.RustDesk_server.plist; launchctl load -w /Library/LaunchDaemons/com.carriez.RustDesk_service.plist;" set sh5 to "launchctl load -w /Library/LaunchDaemons/com.carriez.RustDesk_service.plist;"
set sh6 to "pkill -f rustdesk; launchctl unload -w /Library/LaunchAgents/com.carriez.RustDesk_server.plist; launchctl load -w /Library/LaunchAgents/com.carriez.RustDesk_server.plist; open /Applications/RustDesk.app"
set sh to sh1 & sh2 & sh3 & sh4 & sh5 set sh to sh1 & sh2 & sh3 & sh4 & sh5
do shell script sh with prompt "RustDesk want to install daemon and agent" with administrator privileges do shell script sh with prompt "RustDesk want to install daemon and agent" with administrator privileges
do shell script sh6
end run end run

View File

@ -1,16 +0,0 @@
on run {user}
set sh1 to "cp -rf /Users/" & user & "/Library/Preferences/com.carriez.RustDesk/RustDesk.toml /var/root/Library/Preferences/com.carriez.RustDesk/;"
set sh2 to "cp -rf /Users/" & user & "/Library/Preferences/com.carriez.RustDesk/RustDesk2.toml /var/root/Library/Preferences/com.carriez.RustDesk/;"
set sh3 to "launchctl load -w /Library/LaunchDaemons/com.carriez.rustdesk_service.plist;"
set sh4 to "launchctl load -w /Library/LaunchAgents/com.carriez.rustdesk_server.plist;"
set sh to sh1 & sh2 & sh3
do shell script sh with prompt "RustDesk want to launch daemon" with administrator privileges
do shell script sh4
end run

View File

@ -1,6 +0,0 @@
set sh1 to "launchctl unload -w /Library/LaunchDaemons/com.carriez.rustdesk_service.plist;"
set sh2 to "launchctl unload -w /Library/LaunchAgents/com.carriez.rustdesk_server.plist;"
do shell script sh1 with prompt "RustDesk want to unload daemon" with administrator privileges
do shell script sh2

View File

@ -1,12 +1,10 @@
#[cfg(target_os = "macos")]
use crate::ipc::ConnectionTmpl;
use crate::ipc::Data; use crate::ipc::Data;
use connection::{ConnInner, Connection}; pub use connection::*;
use hbb_common::{ use hbb_common::{
allow_err, allow_err,
anyhow::{anyhow, Context}, anyhow::{anyhow, Context},
bail, bail,
config::{Config, CONNECT_TIMEOUT, RELAY_PORT}, config::{Config, Config2, CONNECT_TIMEOUT, RELAY_PORT},
log, log,
message_proto::*, message_proto::*,
protobuf::{Message as _, ProtobufEnum}, protobuf::{Message as _, ProtobufEnum},
@ -15,10 +13,6 @@ use hbb_common::{
sodiumoxide::crypto::{box_, secretbox, sign}, sodiumoxide::crypto::{box_, secretbox, sign},
timeout, tokio, ResultType, Stream, timeout, tokio, ResultType, Stream,
}; };
#[cfg(target_os = "macos")]
use notify::{watcher, RecursiveMode, Watcher};
#[cfg(target_os = "macos")]
use parity_tokio_ipc::ConnectionClient;
use service::{GenericService, Service, ServiceTmpl, Subscriber}; use service::{GenericService, Service, ServiceTmpl, Subscriber};
use std::{ use std::{
collections::HashMap, collections::HashMap,
@ -339,101 +333,46 @@ async fn sync_and_watch_config_dir() {
return; return;
} }
match crate::ipc::connect(1000, "_service").await { for i in 1..=6 {
Ok(mut conn) => { sleep(i as f32 * 0.3).await;
match sync_config_to_user(&mut conn).await { match crate::ipc::connect(1000, "_service").await {
Err(e) => log::error!("sync config to user failed:{}", e), Ok(mut conn) => {
_ => {} if conn.send(&Data::SyncConfig(None)).await.is_ok() {
} if let Ok(Some(data)) = conn.next_timeout(1000).await {
match data {
tokio::spawn(async move { Data::SyncConfig(Some((config, config2))) => {
log::info!( let _chk = crate::ipc::CheckIfRestart::new();
"watching config dir: {}", Config::set(config);
Config::path("").to_str().unwrap().to_string() Config2::set(config2);
); log::info!("sync config from root");
}
let (tx, rx) = std::sync::mpsc::channel(); _ => {}
let mut watcher = watcher(tx, Duration::from_secs(2)).unwrap(); };
watcher };
.watch(Config::path("").as_path(), RecursiveMode::Recursive) }
.unwrap();
let mut cfg0 = (Config::get(), Config2::get());
loop { loop {
let ev = rx.recv(); sleep(0.3).await;
match ev { let cfg = (Config::get(), Config2::get());
Ok(event) => match event { if cfg != cfg0 {
notify::DebouncedEvent::Write(path) => { cfg0 = cfg;
log::info!( log::info!("config updated, sync to root");
"config file changed, call ipc_service to sync: {}", match conn.send(&Data::SyncConfig(Some(cfg0.clone()))).await {
path.to_str().unwrap().to_string() Err(e) => {
); log::error!("sync config to root failed: {}", e);
match sync_config_to_root(&mut conn, path).await {
Err(e) => log::error!("sync config to root failed: {}", e),
_ => {}
}
} }
x => { _ => {
log::debug!("another {:?}", x) conn.next_timeout(1000).await.ok();
} }
}, }
Err(e) => println!("watch error: {:?}", e),
} }
} }
}); }
} Err(_) => {
Err(_) => { log::info!("#{} try: failed to connect to ipc_service", i);
log::info!("connect ipc_service failed, skip config sync"); }
return;
} }
} }
} log::error!("skipped config sync");
#[cfg(target_os = "macos")]
async fn sync_config_to_user(conn: &mut ConnectionTmpl<ConnectionClient>) -> ResultType<()> {
allow_err!(
conn.send(&Data::SyncConfigToUserReq {
username: crate::username(),
to: Config::path("").to_str().unwrap().to_string(),
})
.await
);
if let Some(data) = conn.next_timeout(2000).await? {
match data {
Data::SyncConfigToUserResp(success) => {
log::info!("copy and reload config dir success: {:?}", success);
}
_ => {}
};
};
Ok(())
}
#[cfg(target_os = "macos")]
async fn sync_config_to_root(
conn: &mut ConnectionTmpl<ConnectionClient>,
from: std::path::PathBuf,
) -> ResultType<()> {
allow_err!(
conn.send(&Data::SyncConfigToRootReq {
from: from.to_str().unwrap().to_string()
})
.await
);
// todo: this code will block outer loop, resolve it later.
// if let Some(data) = conn.next_timeout(2000).await? {
// match data {
// Data::SyncConfigToRootResp(success) => {
// log::info!("copy config to root dir success: {:?}", success);
// }
// x => {
// log::info!("receive another {:?}", x)
// }
// };
// };
Ok(())
} }

View File

@ -8,7 +8,7 @@ use crate::common::SOFTWARE_UPDATE_URL;
use crate::ipc; use crate::ipc;
use hbb_common::{ use hbb_common::{
allow_err, allow_err,
config::{self, Config, Fav, PeerConfig, APP_NAME, ICON}, config::{self, Config, LocalConfig, PeerConfig, APP_NAME, ICON},
log, sleep, log, sleep,
tokio::{self, time}, tokio::{self, time},
}; };
@ -221,11 +221,11 @@ impl UI {
} }
fn get_remote_id(&mut self) -> String { fn get_remote_id(&mut self) -> String {
Config::get_remote_id() LocalConfig::get_remote_id()
} }
fn set_remote_id(&mut self, id: String) { fn set_remote_id(&mut self, id: String) {
Config::set_remote_id(&id); LocalConfig::set_remote_id(&id);
} }
fn goto_install(&mut self) { fn goto_install(&mut self) {
@ -275,7 +275,11 @@ impl UI {
} }
fn get_local_option(&self, key: String) -> String { fn get_local_option(&self, key: String) -> String {
Config::get_option(&key) LocalConfig::get_option(&key)
}
fn set_local_option(&self, key: String, value: String) {
LocalConfig::set_option(key, value);
} }
fn peer_has_password(&self, id: String) -> bool { fn peer_has_password(&self, id: String) -> bool {
@ -353,6 +357,13 @@ impl UI {
} }
fn set_option(&self, key: String, value: String) { fn set_option(&self, key: String, value: String) {
#[cfg(target_os = "macos")]
if &key == "stop-service" {
let is_stop = value == "Y";
if is_stop && crate::platform::macos::uninstall() {
return;
}
}
let mut options = self.2.lock().unwrap(); let mut options = self.2.lock().unwrap();
if value.is_empty() { if value.is_empty() {
options.remove(&key); options.remove(&key);
@ -360,11 +371,6 @@ impl UI {
options.insert(key.clone(), value.clone()); options.insert(key.clone(), value.clone());
} }
ipc::set_options(options.clone()).ok(); ipc::set_options(options.clone()).ok();
#[cfg(target_os = "macos")]
if &key == "stop-service" {
crate::platform::macos::launch(value != "Y");
}
} }
// TODO: ui prompt // TODO: ui prompt
@ -431,11 +437,11 @@ impl UI {
fn save_size(&mut self, x: i32, y: i32, w: i32, h: i32) { fn save_size(&mut self, x: i32, y: i32, w: i32, h: i32) {
crate::server::input_service::fix_key_down_timeout_at_exit(); crate::server::input_service::fix_key_down_timeout_at_exit();
Config::set_size(x, y, w, h); LocalConfig::set_size(x, y, w, h);
} }
fn get_size(&mut self) -> Value { fn get_size(&mut self) -> Value {
let s = Config::get_size(); let s = LocalConfig::get_size();
let mut v = Value::array(0); let mut v = Value::array(0);
v.push(s.0); v.push(s.0);
v.push(s.1); v.push(s.1);
@ -470,7 +476,7 @@ impl UI {
} }
fn get_fav(&self) -> Value { fn get_fav(&self) -> Value {
Value::from_iter(Fav::load().peers) Value::from_iter(LocalConfig::get_fav())
} }
fn store_fav(&self, fav: Value) { fn store_fav(&self, fav: Value) {
@ -482,10 +488,11 @@ impl UI {
} }
} }
}); });
Fav::store(tmp); LocalConfig::set_fav(tmp);
} }
fn get_recent_sessions(&mut self) -> Value { fn get_recent_sessions(&mut self) -> Value {
// to-do: limit number of recent sessions, and remove old peer file
let peers: Vec<Value> = PeerConfig::peers() let peers: Vec<Value> = PeerConfig::peers()
.drain(..) .drain(..)
.map(|p| Self::get_peer_value(p.0, p.2)) .map(|p| Self::get_peer_value(p.0, p.2))
@ -701,6 +708,7 @@ impl sciter::EventHandler for UI {
fn get_options(); fn get_options();
fn get_option(String); fn get_option(String);
fn get_local_option(String); fn get_local_option(String);
fn set_local_option(String, String);
fn get_peer_option(String, String); fn get_peer_option(String, String);
fn peer_has_password(String); fn peer_has_password(String);
fn forget_password(String); fn forget_password(String);
@ -830,7 +838,7 @@ fn check_connect_status(
reconnect: bool, reconnect: bool,
) -> (Arc<Mutex<(i32, bool)>>, Arc<Mutex<HashMap<String, String>>>) { ) -> (Arc<Mutex<(i32, bool)>>, Arc<Mutex<HashMap<String, String>>>) {
let status = Arc::new(Mutex::new((0, false))); let status = Arc::new(Mutex::new((0, false)));
let options = Arc::new(Mutex::new(HashMap::new())); let options = Arc::new(Mutex::new(Config::get_options()));
let cloned = status.clone(); let cloned = status.clone();
let cloned_options = options.clone(); let cloned_options = options.clone();
std::thread::spawn(move || check_connect_status_(reconnect, cloned, cloned_options)); std::thread::spawn(move || check_connect_status_(reconnect, cloned, cloned_options));

View File

@ -66,7 +66,7 @@ class SessionStyle: Reactor.Component {
event click $(span.inactive) { event click $(span.inactive) {
var option = getSessionsStyleOption(this.type); var option = getSessionsStyleOption(this.type);
var sessionsStyle = getSessionsStyle(this.type); var sessionsStyle = getSessionsStyle(this.type);
handler.set_option(option, sessionsStyle == "tile" ? "list" : "tile"); handler.set_local_option(option, sessionsStyle == "tile" ? "list" : "tile");
app.multipleSessions.update(); app.multipleSessions.update();
} }
} }
@ -294,7 +294,7 @@ class MultipleSessions: Reactor.Component {
if (el.id == "lan") { if (el.id == "lan") {
discover(); discover();
} }
handler.set_option('show-sessions-type', el.id || ""); handler.set_local_option('show-sessions-type', el.id || "");
this.stupidUpdate(); this.stupidUpdate();
} }

View File

@ -7,7 +7,7 @@ view.windowMinSize = (500, 300);
var app; var app;
var tmp = handler.get_connect_status(); var tmp = handler.get_connect_status();
var connect_status = tmp[0]; var connect_status = tmp[0];
var service_stopped = false; var service_stopped = handler.get_option("stop-service") == "Y";
var software_update_url = ""; var software_update_url = "";
var key_confirmed = tmp[1]; var key_confirmed = tmp[1];
var system_error = ""; var system_error = "";
@ -368,7 +368,7 @@ class App: Reactor.Component
{is_win && handler.is_installed() && !software_update_url && handler.is_installed_lower_version() ? <UpgradeMe /> : ""} {is_win && handler.is_installed() && !software_update_url && handler.is_installed_lower_version() ? <UpgradeMe /> : ""}
{is_can_screen_recording ? "": <CanScreenRecording />} {is_can_screen_recording ? "": <CanScreenRecording />}
{is_can_screen_recording && !handler.is_process_trusted(false) ? <TrustMe /> : ""} {is_can_screen_recording && !handler.is_process_trusted(false) ? <TrustMe /> : ""}
{is_can_screen_recording && handler.is_process_trusted(false) && handler.is_installed() && !handler.is_installed_daemon(false) ? <InstallDaemon /> : ""} {!service_stopped && is_can_screen_recording && handler.is_process_trusted(false) && handler.is_installed() && !handler.is_installed_daemon(false) ? <InstallDaemon /> : ""}
{system_error ? <SystemError /> : ""} {system_error ? <SystemError /> : ""}
{!system_error && handler.is_login_wayland() && !handler.current_is_wayland() ? <FixWayland /> : ""} {!system_error && handler.is_login_wayland() && !handler.current_is_wayland() ? <FixWayland /> : ""}
{!system_error && handler.current_is_wayland() ? <ModifyDefaultLogin /> : ""} {!system_error && handler.current_is_wayland() ? <ModifyDefaultLogin /> : ""}
@ -772,8 +772,7 @@ function checkConnectStatus() {
var tmp = !!handler.get_option("stop-service"); var tmp = !!handler.get_option("stop-service");
if (tmp != service_stopped) { if (tmp != service_stopped) {
service_stopped = tmp; service_stopped = tmp;
app.connect_status.update(); app.update();
myIdMenu.update();
} }
tmp = handler.get_connect_status(); tmp = handler.get_connect_status();
if (tmp[0] != connect_status) { if (tmp[0] != connect_status) {