diff --git a/src/client/io_loop.rs b/src/client/io_loop.rs index e61690c32..0913251dd 100644 --- a/src/client/io_loop.rs +++ b/src/client/io_loop.rs @@ -2,6 +2,7 @@ use crate::client::{ Client, CodecFormat, FileManager, MediaData, MediaSender, QualityStatus, MILLI1, SEC30, SERVER_CLIPBOARD_ENABLED, SERVER_FILE_TRANSFER_ENABLED, SERVER_KEYBOARD_ENABLED, }; +use crate::common; #[cfg(not(any(target_os = "android", target_os = "ios")))] use crate::common::{check_clipboard, update_clipboard, ClipboardContext, CLIPBOARD_INTERVAL}; @@ -21,7 +22,7 @@ use hbb_common::tokio::{ sync::mpsc, time::{self, Duration, Instant, Interval}, }; -use hbb_common::{allow_err, message_proto::*}; +use hbb_common::{allow_err, message_proto::*, sleep}; use hbb_common::{fs, log, Stream}; use std::collections::HashMap; @@ -270,7 +271,6 @@ impl Remote { // TODO fn load_last_jobs(&mut self) { - log::info!("start load last jobs"); self.handler.clear_all_jobs(); let pc = self.handler.load_config(); if pc.transfer.write_jobs.is_empty() && pc.transfer.read_jobs.is_empty() { @@ -280,33 +280,17 @@ impl Remote { // TODO: can add a confirm dialog let mut cnt = 1; for job_str in pc.transfer.read_jobs.iter() { - let job: Result = serde_json::from_str(&job_str); - if let Ok(job) = job { - self.handler.add_job( - cnt, - job.to.clone(), - job.remote.clone(), - job.file_num, - job.show_hidden, - false, - ); + if !job_str.is_empty() { + self.handler.load_last_job(cnt, job_str); cnt += 1; - println!("restore read_job: {:?}", job); + log::info!("restore read_job: {:?}", job_str); } } for job_str in pc.transfer.write_jobs.iter() { - let job: Result = serde_json::from_str(&job_str); - if let Ok(job) = job { - self.handler.add_job( - cnt, - job.remote.clone(), - job.to.clone(), - job.file_num, - job.show_hidden, - true, - ); + if !job_str.is_empty() { + self.handler.load_last_job(cnt, job_str); cnt += 1; - println!("restore write_job: {:?}", job); + log::info!("restore write_job: {:?}", job_str); } } self.handler.update_transfer_list(); @@ -373,8 +357,7 @@ impl Remote { to, job.files().len() ); - // let m = make_fd(job.id(), job.files(), true); - // self.handler.call("updateFolderFiles", &make_args!(m)); // TODO + self.handler.update_folder_files(job.id(), job.files(), path,!is_remote, true); #[cfg(not(windows))] let files = job.files().clone(); #[cfg(windows)] @@ -433,8 +416,7 @@ impl Remote { to, job.files().len() ); - // let m = make_fd(job.id(), job.files(), true); - // self.handler.call("updateFolderFiles", &make_args!(m)); + self.handler.update_folder_files(job.id(), job.files(), path,!is_remote, true); job.is_last_job = true; self.read_jobs.push(job); self.timer = time::interval(MILLI1); @@ -546,8 +528,7 @@ impl Remote { } else { match fs::get_recursive_files(&path, include_hidden) { Ok(entries) => { - // let m = make_fd(id, &entries, true); - // self.handler.call("updateFolderFiles", &make_args!(m)); + self.handler.update_folder_files(id, &entries, path.clone(),!is_remote, false); self.remove_jobs .insert(id, RemoveJob::new(entries, path, sep, is_remote)); } @@ -749,28 +730,28 @@ impl Remote { } Some(login_response::Union::PeerInfo(pi)) => { self.handler.handle_peer_info(pi); - // self.check_clipboard_file_context(); - // if !(self.handler.is_file_transfer() - // || self.handler.is_port_forward() - // || !SERVER_CLIPBOARD_ENABLED.load(Ordering::SeqCst) - // || !SERVER_KEYBOARD_ENABLED.load(Ordering::SeqCst) - // || self.handler.lc.read().unwrap().disable_clipboard) - // { - // let txt = self.old_clipboard.lock().unwrap().clone(); - // if !txt.is_empty() { - // let msg_out = crate::create_clipboard_msg(txt); - // let sender = self.sender.clone(); - // tokio::spawn(async move { - // // due to clipboard service interval time - // sleep(common::CLIPBOARD_INTERVAL as f32 / 1_000.).await; - // sender.send(Data::Message(msg_out)).ok(); - // }); - // } - // } + self.check_clipboard_file_context(); + if !(self.handler.is_file_transfer() + || self.handler.is_port_forward() + || !SERVER_CLIPBOARD_ENABLED.load(Ordering::SeqCst) + || !SERVER_KEYBOARD_ENABLED.load(Ordering::SeqCst) + || self.handler.lc.read().unwrap().disable_clipboard) + { + let txt = self.old_clipboard.lock().unwrap().clone(); + if !txt.is_empty() { + let msg_out = crate::create_clipboard_msg(txt); + let sender = self.sender.clone(); + tokio::spawn(async move { + // due to clipboard service interval time + sleep(common::CLIPBOARD_INTERVAL as f32 / 1_000.).await; + sender.send(Data::Message(msg_out)).ok(); + }); + } + } - // if self.handler.is_file_transfer() { - // self.load_last_jobs().await; - // } + if self.handler.is_file_transfer() { + self.load_last_jobs(); + } } _ => {} }, @@ -823,11 +804,7 @@ impl Remote { fs::transform_windows_path(&mut entries); } } - // let mut m = make_fd(fd.id, &entries, fd.id > 0); - // if fd.id <= 0 { - // m.set_item("path", fd.path); - // } - // self.handler.call("updateFolderFiles", &make_args!(m)); + self.handler.update_folder_files(fd.id, &entries, fd.path, false, fd.id > 0); if let Some(job) = fs::get_job(fd.id, &mut self.write_jobs) { log::info!("job set_files: {:?}", entries); job.set_files(entries); diff --git a/src/common.rs b/src/common.rs index 5c387c07e..471d6d4e2 100644 --- a/src/common.rs +++ b/src/common.rs @@ -666,49 +666,3 @@ pub fn make_privacy_mode_msg(state: back_notification::PrivacyModeState) -> Mess msg_out.set_misc(misc); msg_out } - -pub fn make_fd_to_json(fd: FileDirectory) -> String { - use serde_json::json; - let mut fd_json = serde_json::Map::new(); - fd_json.insert("id".into(), json!(fd.id)); - fd_json.insert("path".into(), json!(fd.path)); - - let mut entries = vec![]; - for entry in fd.entries { - let mut entry_map = serde_json::Map::new(); - entry_map.insert("entry_type".into(), json!(entry.entry_type.value())); - entry_map.insert("name".into(), json!(entry.name)); - entry_map.insert("size".into(), json!(entry.size)); - entry_map.insert("modified_time".into(), json!(entry.modified_time)); - entries.push(entry_map); - } - fd_json.insert("entries".into(), json!(entries)); - serde_json::to_string(&fd_json).unwrap_or("".into()) -} - -pub fn make_fd_flutter(id: i32, entries: &Vec, only_count: bool) -> String { - let mut m = serde_json::Map::new(); - m.insert("id".into(), json!(id)); - let mut a = vec![]; - let mut n: u64 = 0; - for entry in entries { - n += entry.size; - if only_count { - continue; - } - let mut e = serde_json::Map::new(); - e.insert("name".into(), json!(entry.name.to_owned())); - let tmp = entry.entry_type.value(); - e.insert("type".into(), json!(if tmp == 0 { 1 } else { tmp })); - e.insert("time".into(), json!(entry.modified_time as f64)); - e.insert("size".into(), json!(entry.size as f64)); - a.push(e); - } - if only_count { - m.insert("num_entries".into(), json!(entries.len() as i32)); - } else { - m.insert("entries".into(), json!(a)); - } - m.insert("total_size".into(), json!(n as f64)); - serde_json::to_string(&m).unwrap_or("".into()) -} diff --git a/src/flutter.rs b/src/flutter.rs index b84e91ce8..a2f03d2ff 100644 --- a/src/flutter.rs +++ b/src/flutter.rs @@ -5,7 +5,10 @@ use std::{ use flutter_rust_bridge::{StreamSink, ZeroCopyBuffer}; -use hbb_common::{bail, config::LocalConfig, message_proto::*, ResultType, rendezvous_proto::ConnType}; +use hbb_common::{ + bail, config::LocalConfig, message_proto::*, rendezvous_proto::ConnType, ResultType, +}; +use serde_json::json; use crate::ui_session_interface::{io_loop, InvokeUi, Session}; @@ -85,6 +88,7 @@ impl InvokeUi for FlutterHandler { self.push_event("permission", vec![(name, &value.to_string())]); } + // unused in flutter fn close_success(&self) {} fn update_quality_status(&self, status: QualityStatus) { @@ -118,7 +122,14 @@ impl InvokeUi for FlutterHandler { } fn job_error(&self, id: i32, err: String, file_num: i32) { - self.push_event("job_error", vec![("id", &id.to_string()), ("err", &err)]); + self.push_event( + "job_error", + vec![ + ("id", &id.to_string()), + ("err", &err), + ("file_num", &file_num.to_string()), + ], + ); } fn job_done(&self, id: i32, file_num: i32) { @@ -128,29 +139,43 @@ impl InvokeUi for FlutterHandler { ); } - fn clear_all_jobs(&self) { - // todo!() + // unused in flutter + fn clear_all_jobs(&self) {} + + fn load_last_job(&self, _cnt: i32, job_json: &str) { + self.push_event("load_last_job", vec![("value", job_json)]); } - fn add_job( + fn update_folder_files( &self, id: i32, + entries: &Vec, path: String, - to: String, - file_num: i32, - show_hidden: bool, - is_remote: bool, + is_local: bool, + only_count: bool, ) { - // todo!() + // TODO opt + if only_count { + self.push_event( + "update_folder_files", + vec![("info", &make_fd_flutter(id, entries, only_count))], + ); + } else { + self.push_event( + "file_dir", + vec![ + ("value", &make_fd_to_json(id, path, entries)), + ("is_local", "false"), + ], + ); + } } - fn update_transfer_list(&self) { - // todo!() - } + // unused in flutter + fn update_transfer_list(&self) {} - fn confirm_delete_files(&self, id: i32, i: i32, name: String) { - // todo!() - } + // unused in flutter // TEST flutter + fn confirm_delete_files(&self, _id: i32, _i: i32, _name: String) {} fn override_file_confirm(&self, id: i32, file_num: i32, to: String, is_upload: bool) { self.push_event( @@ -176,6 +201,7 @@ impl InvokeUi for FlutterHandler { ); } + // unused in flutter fn adapt_size(&self) {} fn on_rgba(&self, data: &[u8]) { @@ -283,11 +309,7 @@ pub fn session_add(id: &str, is_file_transfer: bool, is_port_forward: bool) -> R .unwrap() .initialize(session_id, conn_type); - if let Some(same_id_session) = SESSIONS - .write() - .unwrap() - .insert(id.to_owned(), session) - { + if let Some(same_id_session) = SESSIONS.write().unwrap().insert(id.to_owned(), session) { same_id_session.close(); } @@ -946,30 +968,47 @@ pub fn get_session_id(id: String) -> String { }; } -// async fn start_one_port_forward( -// handler: Session, -// port: i32, -// remote_host: String, -// remote_port: i32, -// receiver: mpsc::UnboundedReceiver, -// key: &str, -// token: &str, -// ) { -// if let Err(err) = crate::port_forward::listen( -// handler.id.clone(), -// String::new(), // TODO -// port, -// handler.clone(), -// receiver, -// key, -// token, -// handler.lc.clone(), -// remote_host, -// remote_port, -// ) -// .await -// { -// handler.on_error(&format!("Failed to listen on {}: {}", port, err)); -// } -// log::info!("port forward (:{}) exit", port); -// } +pub fn make_fd_to_json(id: i32, path: String, entries: &Vec) -> String { + let mut fd_json = serde_json::Map::new(); + fd_json.insert("id".into(), json!(id)); + fd_json.insert("path".into(), json!(path)); + + let mut entries_out = vec![]; + for entry in entries { + let mut entry_map = serde_json::Map::new(); + entry_map.insert("entry_type".into(), json!(entry.entry_type.value())); + entry_map.insert("name".into(), json!(entry.name)); + entry_map.insert("size".into(), json!(entry.size)); + entry_map.insert("modified_time".into(), json!(entry.modified_time)); + entries_out.push(entry_map); + } + fd_json.insert("entries".into(), json!(entries_out)); + serde_json::to_string(&fd_json).unwrap_or("".into()) +} + +pub fn make_fd_flutter(id: i32, entries: &Vec, only_count: bool) -> String { + let mut m = serde_json::Map::new(); + m.insert("id".into(), json!(id)); + let mut a = vec![]; + let mut n: u64 = 0; + for entry in entries { + n += entry.size; + if only_count { + continue; + } + let mut e = serde_json::Map::new(); + e.insert("name".into(), json!(entry.name.to_owned())); + let tmp = entry.entry_type.value(); + e.insert("type".into(), json!(if tmp == 0 { 1 } else { tmp })); + e.insert("time".into(), json!(entry.modified_time as f64)); + e.insert("size".into(), json!(entry.size as f64)); + a.push(e); + } + if only_count { + m.insert("num_entries".into(), json!(entries.len() as i32)); + } else { + m.insert("entries".into(), json!(a)); + } + m.insert("total_size".into(), json!(n as f64)); + serde_json::to_string(&m).unwrap_or("".into()) +} diff --git a/src/flutter_ffi.rs b/src/flutter_ffi.rs index 6a3d19880..032be5b1f 100644 --- a/src/flutter_ffi.rs +++ b/src/flutter_ffi.rs @@ -5,16 +5,14 @@ use std::{ }; use flutter_rust_bridge::{StreamSink, SyncReturn, ZeroCopyBuffer}; -use serde_json::{json, Number, Value}; +use serde_json::json; +use hbb_common::ResultType; use hbb_common::{ - config::{self, Config, LocalConfig, PeerConfig, ONLINE}, + config::{self, LocalConfig, PeerConfig, ONLINE}, fs, log, }; -use hbb_common::{password_security, ResultType}; -use crate::{client::file_trait::FileManager, flutter::{session_add, session_start_}}; -use crate::common::make_fd_to_json; use crate::flutter::connection_manager::{self, get_clients_length, get_clients_state}; use crate::flutter::{self, SESSIONS}; use crate::start_server; @@ -30,6 +28,10 @@ use crate::ui_interface::{ set_peer_option, set_permanent_password, set_socks, store_fav, test_if_valid_server, update_temporary_password, using_public_server, }; +use crate::{ + client::file_trait::FileManager, + flutter::{make_fd_to_json, session_add, session_start_}, +}; fn initialize(app_dir: &str) { *config::APP_DIR.write().unwrap() = app_dir.to_owned(); @@ -110,7 +112,11 @@ pub fn host_stop_system_key_propagate(stopped: bool) { // FIXME: -> ResultType<()> cannot be parsed by frb_codegen // thread 'main' panicked at 'Failed to parse function output type `ResultType<()>`', $HOME\.cargo\git\checkouts\flutter_rust_bridge-ddba876d3ebb2a1e\e5adce5\frb_codegen\src\parser\mod.rs:151:25 -pub fn session_add_sync(id: String, is_file_transfer: bool, is_port_forward: bool) -> SyncReturn { +pub fn session_add_sync( + id: String, + is_file_transfer: bool, + is_port_forward: bool, +) -> SyncReturn { if let Err(e) = session_add(&id, is_file_transfer, is_port_forward) { SyncReturn(format!("Failed to add session with id {}, {}", &id, e)) } else { @@ -346,10 +352,8 @@ pub fn session_create_dir(id: String, act_id: i32, path: String, is_remote: bool } pub fn session_read_local_dir_sync(id: String, path: String, show_hidden: bool) -> String { - if let Some(session) = SESSIONS.read().unwrap().get(&id) { - if let Ok(fd) = fs::read_dir(&fs::get_path(&path), show_hidden) { - return make_fd_to_json(fd); - } + if let Ok(fd) = fs::read_dir(&fs::get_path(&path), show_hidden) { + return make_fd_to_json(fd.id, path, &fd.entries); } "".to_string() } diff --git a/src/ui/file_transfer.tis b/src/ui/file_transfer.tis index f32540b33..38c6321dc 100644 --- a/src/ui/file_transfer.tis +++ b/src/ui/file_transfer.tis @@ -695,7 +695,7 @@ handler.clearAllJobs = function() { file_transfer.job_table.clearAllJobs(); } -handler.addJob = function (id, path, to, file_num, show_hidden, is_remote) { +handler.addJob = function (id, path, to, file_num, show_hidden, is_remote) { // load last job // stdout.println("restore job: " + is_remote); file_transfer.job_table.addJob(id,path,to,file_num,show_hidden,is_remote); } diff --git a/src/ui/remote.rs b/src/ui/remote.rs index 7e2c5cd9c..b377b8583 100644 --- a/src/ui/remote.rs +++ b/src/ui/remote.rs @@ -23,7 +23,9 @@ use clipboard::{ get_rx_clip_client, server_clip_file, }; -use hbb_common::{allow_err, log, message_proto::*, rendezvous_proto::ConnType}; +use hbb_common::{ + allow_err, fs::TransferJobMeta, log, message_proto::*, rendezvous_proto::ConnType, +}; #[cfg(windows)] use crate::clipboard_file::*; @@ -43,7 +45,6 @@ static mut IS_ALT_GR: bool = false; /// SciterHandler /// * element -/// * thread TODO check if flutter need /// * close_state for file path when close #[derive(Clone, Default)] pub struct SciterHandler { @@ -155,16 +156,36 @@ impl InvokeUi for SciterHandler { self.call("clearAllJobs", &make_args!()); } - fn add_job( + fn load_last_job(&self, cnt: i32, job_json: &str) { + let job: Result = serde_json::from_str(job_json); + if let Ok(job) = job { + let path; + let to; + if job.is_remote { + path = job.remote.clone(); + to = job.to.clone(); + } else { + path = job.to.clone(); + to = job.remote.clone(); + } + self.call( + "addJob", + &make_args!(cnt, path, to, job.file_num, job.show_hidden, job.is_remote), + ); + } + } + + fn update_folder_files( &self, id: i32, + entries: &Vec, path: String, - to: String, - file_num: i32, - show_hidden: bool, - is_remote: bool, + _is_local: bool, + only_count: bool, ) { - todo!() + let mut m = make_fd(id, entries, only_count); + m.set_item("path", path); + self.call("updateFolderFiles", &make_args!(m)); } fn update_transfer_list(&self) { @@ -686,15 +707,18 @@ impl SciterSession { } pub fn make_fd(id: i32, entries: &Vec, only_count: bool) -> Value { + log::debug!("make_fd"); let mut m = Value::map(); m.set_item("id", id); let mut a = Value::array(0); let mut n: u64 = 0; for entry in entries { + log::debug!("for"); n += entry.size; if only_count { continue; } + log::debug!("for1"); let mut e = Value::map(); e.set_item("name", entry.name.to_owned()); let tmp = entry.entry_type.value(); @@ -703,11 +727,11 @@ pub fn make_fd(id: i32, entries: &Vec, only_count: bool) -> Value { e.set_item("size", entry.size as f64); a.push(e); } - if only_count { - m.set_item("num_entries", entries.len() as i32); - } else { + if !only_count { m.set_item("entries", a); } + m.set_item("num_entries", entries.len() as i32); m.set_item("total_size", n as f64); + log::debug!("make_fd end"); m } diff --git a/src/ui_session_interface.rs b/src/ui_session_interface.rs index 5ab6089a0..f117aae6d 100644 --- a/src/ui_session_interface.rs +++ b/src/ui_session_interface.rs @@ -1,11 +1,11 @@ -use crate::client::io_loop::Remote; -use crate::client::{ - check_if_retry, handle_hash, handle_login_from_ui, handle_test_delay, - input_os_password, load_config, send_mouse, start_video_audio_threads, FileManager, Key, - LoginConfigHandler, QualityStatus, KEY_MAP, SERVER_KEYBOARD_ENABLED, -}; #[cfg(not(any(target_os = "android", target_os = "ios")))] use crate::client::get_key_state; +use crate::client::io_loop::Remote; +use crate::client::{ + check_if_retry, handle_hash, handle_login_from_ui, handle_test_delay, input_os_password, + load_config, send_mouse, start_video_audio_threads, FileManager, Key, LoginConfigHandler, + QualityStatus, KEY_MAP, SERVER_KEYBOARD_ENABLED, +}; use crate::common; use crate::{client::Data, client::Interface}; use async_trait::async_trait; @@ -19,7 +19,7 @@ use hbb_common::{allow_err, message_proto::*}; use hbb_common::{fs, get_version_number, log, Stream}; use std::collections::HashMap; use std::ops::{Deref, DerefMut}; -use std::sync::atomic::{AtomicUsize, Ordering, AtomicBool}; +use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use std::sync::{Arc, Mutex, RwLock}; /// IS_IN KEYBOARD_HOOKED sciter only @@ -556,18 +556,17 @@ pub trait InvokeUi: Send + Sync + Clone + 'static + Sized + Default { fn job_error(&self, id: i32, err: String, file_num: i32); fn job_done(&self, id: i32, file_num: i32); fn clear_all_jobs(&self); - fn add_job( - &self, - id: i32, - path: String, - to: String, - file_num: i32, - show_hidden: bool, - is_remote: bool, - ); fn new_message(&self, msg: String); fn update_transfer_list(&self); - // fn update_folder_files(&self); // TODO flutter with file_dir and update_folder_files + fn load_last_job(&self, cnt: i32, job_json: &str); + fn update_folder_files( + &self, + id: i32, + entries: &Vec, + path: String, + is_local: bool, + only_count: bool, + ); fn confirm_delete_files(&self, id: i32, i: i32, name: String); fn override_file_confirm(&self, id: i32, file_num: i32, to: String, is_upload: bool); fn update_block_input_state(&self, on: bool); @@ -604,11 +603,19 @@ impl Interface for Session { } fn is_file_transfer(&self) -> bool { - self.lc.read().unwrap().conn_type.eq(&ConnType::FILE_TRANSFER) + self.lc + .read() + .unwrap() + .conn_type + .eq(&ConnType::FILE_TRANSFER) } fn is_port_forward(&self) -> bool { - self.lc.read().unwrap().conn_type.eq(&ConnType::PORT_FORWARD) + self.lc + .read() + .unwrap() + .conn_type + .eq(&ConnType::PORT_FORWARD) } fn is_rdp(&self) -> bool {