mirror of
https://github.com/rustdesk/rustdesk.git
synced 2024-12-18 13:37:52 +08:00
Merge pull request #1457 from Heap-Hop/master
Update desktop file transfer and fix sciter can't update connect status bug
This commit is contained in:
commit
c474ac01cc
@ -59,8 +59,11 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
super.initState();
|
super.initState();
|
||||||
_ffi = FFI();
|
_ffi = FFI();
|
||||||
_ffi.connect(widget.id, isFileTransfer: true);
|
_ffi.connect(widget.id, isFileTransfer: true);
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
_ffi.dialogManager
|
||||||
|
.showLoading(translate('Connecting...'), onCancel: closeConnection);
|
||||||
|
});
|
||||||
Get.put(_ffi, tag: 'ft_${widget.id}');
|
Get.put(_ffi, tag: 'ft_${widget.id}');
|
||||||
// _ffi.ffiModel.updateEventListener(widget.id);
|
|
||||||
if (!Platform.isLinux) {
|
if (!Platform.isLinux) {
|
||||||
Wakelock.enable();
|
Wakelock.enable();
|
||||||
}
|
}
|
||||||
@ -117,7 +120,8 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
|
|
||||||
Widget menu({bool isLocal = false}) {
|
Widget menu({bool isLocal = false}) {
|
||||||
return PopupMenuButton<String>(
|
return PopupMenuButton<String>(
|
||||||
icon: Icon(Icons.more_vert),
|
icon: const Icon(Icons.more_vert),
|
||||||
|
splashRadius: 20,
|
||||||
itemBuilder: (context) {
|
itemBuilder: (context) {
|
||||||
return [
|
return [
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
@ -413,6 +417,7 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
/// watch transfer status
|
/// watch transfer status
|
||||||
Widget statusList() {
|
Widget statusList() {
|
||||||
return PreferredSize(
|
return PreferredSize(
|
||||||
|
preferredSize: const Size(200, double.infinity),
|
||||||
child: Container(
|
child: Container(
|
||||||
margin: const EdgeInsets.only(top: 16.0, bottom: 16.0, right: 16.0),
|
margin: const EdgeInsets.only(top: 16.0, bottom: 16.0, right: 16.0),
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
@ -429,8 +434,8 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
children: [
|
children: [
|
||||||
Transform.rotate(
|
Transform.rotate(
|
||||||
angle: item.isRemote ? pi : 0,
|
angle: item.isRemote ? pi : 0,
|
||||||
child: Icon(Icons.send)),
|
child: const Icon(Icons.send)),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
width: 16.0,
|
width: 16.0,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
@ -441,7 +446,7 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
Tooltip(
|
Tooltip(
|
||||||
message: item.jobName,
|
message: item.jobName,
|
||||||
child: Text(
|
child: Text(
|
||||||
'${item.jobName}',
|
item.jobName,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
)),
|
)),
|
||||||
@ -455,7 +460,7 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
offstage:
|
offstage:
|
||||||
item.state != JobState.inProgress,
|
item.state != JobState.inProgress,
|
||||||
child: Text(
|
child: Text(
|
||||||
'${readableFileSize(item.speed) + "/s"} ')),
|
'${"${readableFileSize(item.speed)}/s"} ')),
|
||||||
Offstage(
|
Offstage(
|
||||||
offstage: item.totalSize <= 0,
|
offstage: item.totalSize <= 0,
|
||||||
child: Text(
|
child: Text(
|
||||||
@ -475,10 +480,12 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
model.resumeJob(item.id);
|
model.resumeJob(item.id);
|
||||||
},
|
},
|
||||||
icon: Icon(Icons.restart_alt_rounded)),
|
splashRadius: 20,
|
||||||
|
icon: const Icon(Icons.restart_alt_rounded)),
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.delete),
|
icon: const Icon(Icons.delete),
|
||||||
|
splashRadius: 20,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
model.jobTable.removeAt(index);
|
model.jobTable.removeAt(index);
|
||||||
model.cancelJob(item.id);
|
model.cancelJob(item.id);
|
||||||
@ -500,8 +507,7 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
itemCount: model.jobTable.length,
|
itemCount: model.jobTable.length,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
));
|
||||||
preferredSize: Size(200, double.infinity));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
goBack({bool? isLocal}) {
|
goBack({bool? isLocal}) {
|
||||||
@ -554,9 +560,12 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
model.goHome(isLocal: isLocal);
|
model.goHome(isLocal: isLocal);
|
||||||
},
|
},
|
||||||
icon: Icon(Icons.home_outlined)),
|
icon: const Icon(Icons.home_outlined),
|
||||||
|
splashRadius: 20,
|
||||||
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.arrow_upward),
|
icon: const Icon(Icons.arrow_upward),
|
||||||
|
splashRadius: 20,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
goBack(isLocal: isLocal);
|
goBack(isLocal: isLocal);
|
||||||
},
|
},
|
||||||
@ -622,13 +631,15 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
),
|
),
|
||||||
))
|
))
|
||||||
],
|
],
|
||||||
child: Icon(Icons.search),
|
splashRadius: 20,
|
||||||
|
child: const Icon(Icons.search),
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
model.refresh(isLocal: isLocal);
|
model.refresh(isLocal: isLocal);
|
||||||
},
|
},
|
||||||
icon: Icon(Icons.refresh)),
|
splashRadius: 20,
|
||||||
|
icon: const Icon(Icons.refresh)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
@ -686,6 +697,7 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
splashRadius: 20,
|
||||||
icon: const Icon(Icons.create_new_folder_outlined)),
|
icon: const Icon(Icons.create_new_folder_outlined)),
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
@ -695,7 +707,8 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
await (model.removeAction(items, isLocal: isLocal));
|
await (model.removeAction(items, isLocal: isLocal));
|
||||||
items.clear();
|
items.clear();
|
||||||
},
|
},
|
||||||
icon: Icon(Icons.delete_forever_outlined)),
|
splashRadius: 20,
|
||||||
|
icon: const Icon(Icons.delete_forever_outlined)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -707,7 +720,7 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
},
|
},
|
||||||
icon: Transform.rotate(
|
icon: Transform.rotate(
|
||||||
angle: isLocal ? 0 : pi,
|
angle: isLocal ? 0 : pi,
|
||||||
child: Icon(
|
child: const Icon(
|
||||||
Icons.send,
|
Icons.send,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -360,9 +360,9 @@ class FileModel extends ChangeNotifier {
|
|||||||
Future refresh({bool? isLocal}) async {
|
Future refresh({bool? isLocal}) async {
|
||||||
if (isDesktop) {
|
if (isDesktop) {
|
||||||
isLocal = isLocal ?? _isLocal;
|
isLocal = isLocal ?? _isLocal;
|
||||||
await isLocal
|
isLocal
|
||||||
? openDirectory(currentLocalDir.path, isLocal: isLocal)
|
? await openDirectory(currentLocalDir.path, isLocal: isLocal)
|
||||||
: openDirectory(currentRemoteDir.path, isLocal: isLocal);
|
: await openDirectory(currentRemoteDir.path, isLocal: isLocal);
|
||||||
} else {
|
} else {
|
||||||
await openDirectory(currentDir.path);
|
await openDirectory(currentDir.path);
|
||||||
}
|
}
|
||||||
@ -393,7 +393,7 @@ class FileModel extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint("Failed to openDirectory ${path} :$e");
|
debugPrint("Failed to openDirectory $path: $e");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,8 +326,8 @@ class FfiModel with ChangeNotifier {
|
|||||||
await bind.sessionGetOption(id: peerId, arg: "touch-mode") != '';
|
await bind.sessionGetOption(id: peerId, arg: "touch-mode") != '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (evt['is_file_transfer'] == "true") {
|
if (parent.target != null &&
|
||||||
// TODO is file transfer
|
parent.target!.connType == ConnType.fileTransfer) {
|
||||||
parent.target?.fileModel.onReady();
|
parent.target?.fileModel.onReady();
|
||||||
} else {
|
} else {
|
||||||
_pi.displays = [];
|
_pi.displays = [];
|
||||||
@ -916,6 +916,8 @@ extension ToString on MouseButtons {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum ConnType { defaultConn, fileTransfer, portForward, rdp }
|
||||||
|
|
||||||
/// FFI class for communicating with the Rust core.
|
/// FFI class for communicating with the Rust core.
|
||||||
class FFI {
|
class FFI {
|
||||||
var id = "";
|
var id = "";
|
||||||
@ -924,6 +926,7 @@ class FFI {
|
|||||||
var alt = false;
|
var alt = false;
|
||||||
var command = false;
|
var command = false;
|
||||||
var version = "";
|
var version = "";
|
||||||
|
var connType = ConnType.defaultConn;
|
||||||
|
|
||||||
/// dialogManager use late to ensure init after main page binding [globalKey]
|
/// dialogManager use late to ensure init after main page binding [globalKey]
|
||||||
late final dialogManager = OverlayDialogManager();
|
late final dialogManager = OverlayDialogManager();
|
||||||
@ -1055,9 +1058,11 @@ class FFI {
|
|||||||
double tabBarHeight = 0.0}) {
|
double tabBarHeight = 0.0}) {
|
||||||
assert(!(isFileTransfer && isPortForward), "more than one connect type");
|
assert(!(isFileTransfer && isPortForward), "more than one connect type");
|
||||||
if (isFileTransfer) {
|
if (isFileTransfer) {
|
||||||
id = 'ft_${id}';
|
connType = ConnType.fileTransfer;
|
||||||
|
id = 'ft_$id';
|
||||||
} else if (isPortForward) {
|
} else if (isPortForward) {
|
||||||
id = 'pf_${id}';
|
connType = ConnType.portForward;
|
||||||
|
id = 'pf_$id';
|
||||||
} else {
|
} else {
|
||||||
chatModel.resetClientMode();
|
chatModel.resetClientMode();
|
||||||
canvasModel.id = id;
|
canvasModel.id = id;
|
||||||
@ -1086,7 +1091,7 @@ class FFI {
|
|||||||
// every instance will bind a stream
|
// every instance will bind a stream
|
||||||
this.id = id;
|
this.id = id;
|
||||||
if (isFileTransfer) {
|
if (isFileTransfer) {
|
||||||
this.fileModel.initFileFetcher();
|
fileModel.initFileFetcher();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1665,6 +1665,7 @@ pub async fn handle_login_from_ui(
|
|||||||
/// Interface for client to send data and commands.
|
/// Interface for client to send data and commands.
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait Interface: Send + Clone + 'static + Sized {
|
pub trait Interface: Send + Clone + 'static + Sized {
|
||||||
|
/// Send message data to remote peer.
|
||||||
fn send(&self, data: Data);
|
fn send(&self, data: Data);
|
||||||
fn msgbox(&self, msgtype: &str, title: &str, text: &str);
|
fn msgbox(&self, msgtype: &str, title: &str, text: &str);
|
||||||
fn handle_login_error(&mut self, err: &str) -> bool;
|
fn handle_login_error(&mut self, err: &str) -> bool;
|
||||||
|
@ -269,33 +269,6 @@ impl<T: InvokeUiSession> Remote<T> {
|
|||||||
Some(tx)
|
Some(tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
|
||||||
fn load_last_jobs(&mut self) {
|
|
||||||
self.handler.clear_all_jobs();
|
|
||||||
let pc = self.handler.load_config();
|
|
||||||
if pc.transfer.write_jobs.is_empty() && pc.transfer.read_jobs.is_empty() {
|
|
||||||
// no last jobs
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// TODO: can add a confirm dialog
|
|
||||||
let mut cnt = 1;
|
|
||||||
for job_str in pc.transfer.read_jobs.iter() {
|
|
||||||
if !job_str.is_empty() {
|
|
||||||
self.handler.load_last_job(cnt, job_str);
|
|
||||||
cnt += 1;
|
|
||||||
log::info!("restore read_job: {:?}", job_str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for job_str in pc.transfer.write_jobs.iter() {
|
|
||||||
if !job_str.is_empty() {
|
|
||||||
self.handler.load_last_job(cnt, job_str);
|
|
||||||
cnt += 1;
|
|
||||||
log::info!("restore write_job: {:?}", job_str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.handler.update_transfer_list();
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn handle_msg_from_ui(&mut self, data: Data, peer: &mut Stream) -> bool {
|
async fn handle_msg_from_ui(&mut self, data: Data, peer: &mut Stream) -> bool {
|
||||||
match data {
|
match data {
|
||||||
Data::Close => {
|
Data::Close => {
|
||||||
@ -479,7 +452,6 @@ impl<T: InvokeUiSession> Remote<T> {
|
|||||||
file_num,
|
file_num,
|
||||||
job.files[i].name.clone(),
|
job.files[i].name.clone(),
|
||||||
);
|
);
|
||||||
self.handler.confirm_delete_files(id, file_num);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -768,7 +740,7 @@ impl<T: InvokeUiSession> Remote<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.handler.is_file_transfer() {
|
if self.handler.is_file_transfer() {
|
||||||
self.load_last_jobs();
|
self.handler.load_last_jobs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@ -827,7 +799,7 @@ impl<T: InvokeUiSession> Remote<T> {
|
|||||||
&entries,
|
&entries,
|
||||||
fd.path,
|
fd.path,
|
||||||
false,
|
false,
|
||||||
fd.id > 0,
|
false,
|
||||||
);
|
);
|
||||||
if let Some(job) = fs::get_job(fd.id, &mut self.write_jobs) {
|
if let Some(job) = fs::get_job(fd.id, &mut self.write_jobs) {
|
||||||
log::info!("job set_files: {:?}", entries);
|
log::info!("job set_files: {:?}", entries);
|
||||||
|
@ -366,7 +366,7 @@ pub fn session_get_platform(id: String, is_remote: bool) -> String {
|
|||||||
|
|
||||||
pub fn session_load_last_transfer_jobs(id: String) {
|
pub fn session_load_last_transfer_jobs(id: String) {
|
||||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
||||||
// return session.load_last_jobs();
|
return session.load_last_jobs();
|
||||||
} else {
|
} else {
|
||||||
// a tip for flutter dev
|
// a tip for flutter dev
|
||||||
eprintln!(
|
eprintln!(
|
||||||
|
96
src/ui.rs
96
src/ui.rs
@ -87,7 +87,7 @@ pub fn start(args: &mut [String]) {
|
|||||||
}
|
}
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
if args.len() > 0 && args[0] == "--tray" {
|
if args.len() > 0 && args[0] == "--tray" {
|
||||||
let options = check_connect_status(false).1;
|
let options = crate::ui_interface::check_connect_status(false).1;
|
||||||
crate::tray::start_tray(options);
|
crate::tray::start_tray(options);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -664,79 +664,6 @@ pub fn check_zombie(childs: Childs) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// notice: avoiding create ipc connecton repeatly,
|
|
||||||
// because windows named pipe has serious memory leak issue.
|
|
||||||
#[tokio::main(flavor = "current_thread")]
|
|
||||||
async fn check_connect_status_(
|
|
||||||
reconnect: bool,
|
|
||||||
status: Arc<Mutex<Status>>,
|
|
||||||
options: Arc<Mutex<HashMap<String, String>>>,
|
|
||||||
rx: mpsc::UnboundedReceiver<ipc::Data>,
|
|
||||||
password: Arc<Mutex<String>>,
|
|
||||||
) {
|
|
||||||
let mut key_confirmed = false;
|
|
||||||
let mut rx = rx;
|
|
||||||
let mut mouse_time = 0;
|
|
||||||
let mut id = "".to_owned();
|
|
||||||
loop {
|
|
||||||
if let Ok(mut c) = ipc::connect(1000, "").await {
|
|
||||||
let mut timer = time::interval(time::Duration::from_secs(1));
|
|
||||||
loop {
|
|
||||||
tokio::select! {
|
|
||||||
res = c.next() => {
|
|
||||||
match res {
|
|
||||||
Err(err) => {
|
|
||||||
log::error!("ipc connection closed: {}", err);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Ok(Some(ipc::Data::MouseMoveTime(v))) => {
|
|
||||||
mouse_time = v;
|
|
||||||
status.lock().unwrap().2 = v;
|
|
||||||
}
|
|
||||||
Ok(Some(ipc::Data::Options(Some(v)))) => {
|
|
||||||
*options.lock().unwrap() = v
|
|
||||||
}
|
|
||||||
Ok(Some(ipc::Data::Config((name, Some(value))))) => {
|
|
||||||
if name == "id" {
|
|
||||||
id = value;
|
|
||||||
} else if name == "temporary-password" {
|
|
||||||
*password.lock().unwrap() = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(Some(ipc::Data::OnlineStatus(Some((mut x, c))))) => {
|
|
||||||
if x > 0 {
|
|
||||||
x = 1
|
|
||||||
}
|
|
||||||
key_confirmed = c;
|
|
||||||
*status.lock().unwrap() = (x as _, key_confirmed, mouse_time, id.clone());
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(data) = rx.recv() => {
|
|
||||||
allow_err!(c.send(&data).await);
|
|
||||||
}
|
|
||||||
_ = timer.tick() => {
|
|
||||||
c.send(&ipc::Data::OnlineStatus(None)).await.ok();
|
|
||||||
c.send(&ipc::Data::Options(None)).await.ok();
|
|
||||||
c.send(&ipc::Data::Config(("id".to_owned(), None))).await.ok();
|
|
||||||
c.send(&ipc::Data::Config(("temporary-password".to_owned(), None))).await.ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !reconnect {
|
|
||||||
options
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.insert("ipc-closed".to_owned(), "Y".to_owned());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*status.lock().unwrap() = (-1, key_confirmed, mouse_time, id.clone());
|
|
||||||
sleep(1.).await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(target_os = "linux"))]
|
#[cfg(not(target_os = "linux"))]
|
||||||
fn get_sound_inputs() -> Vec<String> {
|
fn get_sound_inputs() -> Vec<String> {
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
@ -763,27 +690,6 @@ fn get_sound_inputs() -> Vec<String> {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_connect_status(
|
|
||||||
reconnect: bool,
|
|
||||||
) -> (
|
|
||||||
Arc<Mutex<Status>>,
|
|
||||||
Arc<Mutex<HashMap<String, String>>>,
|
|
||||||
mpsc::UnboundedSender<ipc::Data>,
|
|
||||||
Arc<Mutex<String>>,
|
|
||||||
) {
|
|
||||||
let status = Arc::new(Mutex::new((0, false, 0, "".to_owned())));
|
|
||||||
let options = Arc::new(Mutex::new(Config::get_options()));
|
|
||||||
let cloned = status.clone();
|
|
||||||
let cloned_options = options.clone();
|
|
||||||
let (tx, rx) = mpsc::unbounded_channel::<ipc::Data>();
|
|
||||||
let password = Arc::new(Mutex::new(String::default()));
|
|
||||||
let cloned_password = password.clone();
|
|
||||||
std::thread::spawn(move || {
|
|
||||||
check_connect_status_(reconnect, cloned, cloned_options, rx, cloned_password)
|
|
||||||
});
|
|
||||||
(status, options, tx, password)
|
|
||||||
}
|
|
||||||
|
|
||||||
const INVALID_FORMAT: &'static str = "Invalid format";
|
const INVALID_FORMAT: &'static str = "Invalid format";
|
||||||
const UNKNOWN_ERROR: &'static str = "Unknown error";
|
const UNKNOWN_ERROR: &'static str = "Unknown error";
|
||||||
|
|
||||||
|
@ -1055,6 +1055,7 @@ function showSettings() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function checkConnectStatus() {
|
function checkConnectStatus() {
|
||||||
|
handler.check_mouse_time(); // trigger connection status updater
|
||||||
self.timer(1s, function() {
|
self.timer(1s, function() {
|
||||||
var tmp = !!handler.get_option("stop-service");
|
var tmp = !!handler.get_option("stop-service");
|
||||||
if (tmp != service_stopped) {
|
if (tmp != service_stopped) {
|
||||||
|
@ -709,18 +709,15 @@ impl SciterSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_fd(id: i32, entries: &Vec<FileEntry>, only_count: bool) -> Value {
|
pub fn make_fd(id: i32, entries: &Vec<FileEntry>, only_count: bool) -> Value {
|
||||||
log::debug!("make_fd");
|
|
||||||
let mut m = Value::map();
|
let mut m = Value::map();
|
||||||
m.set_item("id", id);
|
m.set_item("id", id);
|
||||||
let mut a = Value::array(0);
|
let mut a = Value::array(0);
|
||||||
let mut n: u64 = 0;
|
let mut n: u64 = 0;
|
||||||
for entry in entries {
|
for entry in entries {
|
||||||
log::debug!("for");
|
|
||||||
n += entry.size;
|
n += entry.size;
|
||||||
if only_count {
|
if only_count {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
log::debug!("for1");
|
|
||||||
let mut e = Value::map();
|
let mut e = Value::map();
|
||||||
e.set_item("name", entry.name.to_owned());
|
e.set_item("name", entry.name.to_owned());
|
||||||
let tmp = entry.entry_type.value();
|
let tmp = entry.entry_type.value();
|
||||||
@ -734,6 +731,5 @@ pub fn make_fd(id: i32, entries: &Vec<FileEntry>, only_count: bool) -> Value {
|
|||||||
}
|
}
|
||||||
m.set_item("num_entries", entries.len() as i32);
|
m.set_item("num_entries", entries.len() as i32);
|
||||||
m.set_item("total_size", n as f64);
|
m.set_item("total_size", n as f64);
|
||||||
log::debug!("make_fd end");
|
|
||||||
m
|
m
|
||||||
}
|
}
|
||||||
|
@ -532,6 +532,32 @@ impl<T: InvokeUiSession> Session<T> {
|
|||||||
pub fn close(&self) {
|
pub fn close(&self) {
|
||||||
self.send(Data::Close);
|
self.send(Data::Close);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn load_last_jobs(&self) {
|
||||||
|
self.clear_all_jobs();
|
||||||
|
let pc = self.load_config();
|
||||||
|
if pc.transfer.write_jobs.is_empty() && pc.transfer.read_jobs.is_empty() {
|
||||||
|
// no last jobs
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// TODO: can add a confirm dialog
|
||||||
|
let mut cnt = 1;
|
||||||
|
for job_str in pc.transfer.read_jobs.iter() {
|
||||||
|
if !job_str.is_empty() {
|
||||||
|
self.load_last_job(cnt, job_str);
|
||||||
|
cnt += 1;
|
||||||
|
log::info!("restore read_job: {:?}", job_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for job_str in pc.transfer.write_jobs.iter() {
|
||||||
|
if !job_str.is_empty() {
|
||||||
|
self.load_last_job(cnt, job_str);
|
||||||
|
cnt += 1;
|
||||||
|
log::info!("restore write_job: {:?}", job_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.update_transfer_list();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait InvokeUiSession: Send + Sync + Clone + 'static + Sized + Default {
|
pub trait InvokeUiSession: Send + Sync + Clone + 'static + Sized + Default {
|
||||||
|
Loading…
Reference in New Issue
Block a user