Merge pull request #545 from Kingtous/feat/file_transfer_option_mobile
feat: [mobile] more precise control method for transfering files
This commit is contained in:
commit
31a40538dc
@ -37,8 +37,8 @@ class MyTheme {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final ButtonStyle flatButtonStyle = TextButton.styleFrom(
|
final ButtonStyle flatButtonStyle = TextButton.styleFrom(
|
||||||
minimumSize: Size(88, 36),
|
minimumSize: Size(0, 36),
|
||||||
padding: EdgeInsets.symmetric(horizontal: 16.0),
|
padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 10.0),
|
||||||
shape: const RoundedRectangleBorder(
|
shape: const RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(2.0)),
|
borderRadius: BorderRadius.all(Radius.circular(2.0)),
|
||||||
),
|
),
|
||||||
|
@ -144,6 +144,28 @@ class FileModel extends ChangeNotifier {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
overrideFileConfirm(Map<String, dynamic> evt) async {
|
||||||
|
final resp = await showFileConfirmDialog(
|
||||||
|
translate("Overwrite"), "${evt['read_path']}", true);
|
||||||
|
if (false == resp) {
|
||||||
|
cancelJob(int.tryParse(evt['id']) ?? 0);
|
||||||
|
} else {
|
||||||
|
var msg = Map()
|
||||||
|
..['id'] = evt['id']
|
||||||
|
..['file_num'] = evt['file_num']
|
||||||
|
..['is_upload'] = evt['is_upload']
|
||||||
|
..['remember'] = fileConfirmCheckboxRemember.toString();
|
||||||
|
if (resp == null) {
|
||||||
|
// skip
|
||||||
|
msg['need_override'] = 'false';
|
||||||
|
} else {
|
||||||
|
// overwrite
|
||||||
|
msg['need_override'] = 'true';
|
||||||
|
}
|
||||||
|
FFI.setByName("set_confirm_override_file", jsonEncode(msg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
jobReset() {
|
jobReset() {
|
||||||
_jobProgress.clear();
|
_jobProgress.clear();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
@ -253,6 +275,7 @@ class FileModel extends ChangeNotifier {
|
|||||||
"id": _jobId.toString(),
|
"id": _jobId.toString(),
|
||||||
"path": from.path,
|
"path": from.path,
|
||||||
"to": PathUtil.join(toPath, from.name, isWindows),
|
"to": PathUtil.join(toPath, from.name, isWindows),
|
||||||
|
"file_num": "0",
|
||||||
"show_hidden": showHidden.toString(),
|
"show_hidden": showHidden.toString(),
|
||||||
"is_remote": (!(items.isLocal!)).toString()
|
"is_remote": (!(items.isLocal!)).toString()
|
||||||
};
|
};
|
||||||
@ -391,6 +414,63 @@ class FileModel extends ChangeNotifier {
|
|||||||
useAnimation: false);
|
useAnimation: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool fileConfirmCheckboxRemember = false;
|
||||||
|
|
||||||
|
Future<bool?> showFileConfirmDialog(
|
||||||
|
String title, String content, bool showCheckbox) async {
|
||||||
|
fileConfirmCheckboxRemember = false;
|
||||||
|
return await DialogManager.show<bool?>(
|
||||||
|
(setState, Function(bool? v) close) => CustomAlertDialog(
|
||||||
|
title: Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.warning, color: Colors.red),
|
||||||
|
SizedBox(width: 20),
|
||||||
|
Text(title)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
content: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
translate(
|
||||||
|
"This file exists, skip or overwrite this file?"),
|
||||||
|
style: TextStyle(fontWeight: FontWeight.bold)),
|
||||||
|
SizedBox(height: 5),
|
||||||
|
Text(content),
|
||||||
|
showCheckbox
|
||||||
|
? CheckboxListTile(
|
||||||
|
contentPadding: const EdgeInsets.all(0),
|
||||||
|
dense: true,
|
||||||
|
controlAffinity: ListTileControlAffinity.leading,
|
||||||
|
title: Text(
|
||||||
|
translate("Do this for all conflicts"),
|
||||||
|
),
|
||||||
|
value: fileConfirmCheckboxRemember,
|
||||||
|
onChanged: (v) {
|
||||||
|
if (v == null) return;
|
||||||
|
setState(() => fileConfirmCheckboxRemember = v);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
: SizedBox.shrink()
|
||||||
|
]),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
style: flatButtonStyle,
|
||||||
|
onPressed: () => close(false),
|
||||||
|
child: Text(translate("Cancel"))),
|
||||||
|
TextButton(
|
||||||
|
style: flatButtonStyle,
|
||||||
|
onPressed: () => close(null),
|
||||||
|
child: Text(translate("Skip"))),
|
||||||
|
TextButton(
|
||||||
|
style: flatButtonStyle,
|
||||||
|
onPressed: () => close(true),
|
||||||
|
child: Text(translate("OK"))),
|
||||||
|
]),
|
||||||
|
useAnimation: false);
|
||||||
|
}
|
||||||
|
|
||||||
sendRemoveFile(String path, int fileNum, bool isLocal) {
|
sendRemoveFile(String path, int fileNum, bool isLocal) {
|
||||||
final msg = {
|
final msg = {
|
||||||
"id": _jobId.toString(),
|
"id": _jobId.toString(),
|
||||||
|
@ -156,6 +156,8 @@ class FfiModel with ChangeNotifier {
|
|||||||
FFI.fileModel.jobDone(evt);
|
FFI.fileModel.jobDone(evt);
|
||||||
} else if (name == 'job_error') {
|
} else if (name == 'job_error') {
|
||||||
FFI.fileModel.jobError(evt);
|
FFI.fileModel.jobError(evt);
|
||||||
|
} else if (name == 'override_file_confirm') {
|
||||||
|
FFI.fileModel.overrideFileConfirm(evt);
|
||||||
} else if (name == 'try_start_without_auth') {
|
} else if (name == 'try_start_without_auth') {
|
||||||
FFI.serverModel.loginRequest(evt);
|
FFI.serverModel.loginRequest(evt);
|
||||||
} else if (name == 'on_client_authorized') {
|
} else if (name == 'on_client_authorized') {
|
||||||
|
@ -544,6 +544,7 @@ impl TransferJob {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_file_confirmed(&mut self, file_confirmed: bool) {
|
pub fn set_file_confirmed(&mut self, file_confirmed: bool) {
|
||||||
|
log::info!("id: {}, file_confirmed: {}", self.id, file_confirmed);
|
||||||
self.file_confirmed = file_confirmed;
|
self.file_confirmed = file_confirmed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -580,8 +581,7 @@ impl TransferJob {
|
|||||||
self.set_file_confirmed(true);
|
self.set_file_confirmed(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(file_transfer_send_confirm_request::Union::offset_blk(offset)) => {
|
Some(file_transfer_send_confirm_request::Union::offset_blk(_offset)) => {
|
||||||
log::debug!("file confirmed");
|
|
||||||
self.set_file_confirmed(true);
|
self.set_file_confirmed(true);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
241
src/mobile.rs
241
src/mobile.rs
@ -5,6 +5,7 @@ use hbb_common::{
|
|||||||
compress::decompress,
|
compress::decompress,
|
||||||
config::{Config, LocalConfig},
|
config::{Config, LocalConfig},
|
||||||
fs, log,
|
fs, log,
|
||||||
|
fs::{can_enable_overwrite_detection, new_send_confirm, DigestCheckResult, get_string},
|
||||||
message_proto::*,
|
message_proto::*,
|
||||||
protobuf::Message as _,
|
protobuf::Message as _,
|
||||||
rendezvous_proto::ConnType,
|
rendezvous_proto::ConnType,
|
||||||
@ -14,6 +15,7 @@ use hbb_common::{
|
|||||||
time::{self, Duration, Instant, Interval},
|
time::{self, Duration, Instant, Interval},
|
||||||
},
|
},
|
||||||
Stream,
|
Stream,
|
||||||
|
get_version_number
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, VecDeque},
|
collections::{HashMap, VecDeque},
|
||||||
@ -192,9 +194,18 @@ impl Session {
|
|||||||
Self::send_msg_static(msg_out);
|
Self::send_msg_static(msg_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_files(id: i32, path: String, to: String, include_hidden: bool, is_remote: bool) {
|
pub fn send_files(id: i32, path: String, to: String, file_num: i32, include_hidden: bool, is_remote: bool) {
|
||||||
if let Some(session) = SESSION.write().unwrap().as_mut() {
|
if let Some(session) = SESSION.write().unwrap().as_mut() {
|
||||||
session.send_files(id, path, to, include_hidden, is_remote);
|
session.send_files(id, path, to, file_num, include_hidden, is_remote);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_confirm_override_file(id: i32, file_num: i32, need_override: bool, remember: bool, is_upload: bool) {
|
||||||
|
if let Some(session) = SESSION.read().unwrap().as_ref() {
|
||||||
|
if let Some(sender) = session.sender.read().unwrap().as_ref() {
|
||||||
|
log::info!("confirm file transfer, job: {}, need_override: {}", id, need_override);
|
||||||
|
sender.send(Data::SetConfirmOverrideFile((id, file_num, need_override, remember, is_upload))).ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -660,6 +671,88 @@ impl Connection {
|
|||||||
Some(file_response::Union::error(e)) => {
|
Some(file_response::Union::error(e)) => {
|
||||||
self.handle_job_status(e.id, e.file_num, Some(e.error));
|
self.handle_job_status(e.id, e.file_num, Some(e.error));
|
||||||
}
|
}
|
||||||
|
Some(file_response::Union::digest(digest)) => {
|
||||||
|
if digest.is_upload {
|
||||||
|
if let Some(job) = fs::get_job(digest.id, &mut self.read_jobs) {
|
||||||
|
if let Some(file) = job.files().get(digest.file_num as usize) {
|
||||||
|
let read_path = get_string(&job.join(&file.name));
|
||||||
|
let overwrite_strategy = job.default_overwrite_strategy();
|
||||||
|
if let Some(overwrite) = overwrite_strategy {
|
||||||
|
let req = FileTransferSendConfirmRequest {
|
||||||
|
id: digest.id,
|
||||||
|
file_num: digest.file_num,
|
||||||
|
union: Some(if overwrite {
|
||||||
|
file_transfer_send_confirm_request::Union::offset_blk(0)
|
||||||
|
} else {
|
||||||
|
file_transfer_send_confirm_request::Union::skip(
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
job.confirm(&req);
|
||||||
|
let msg = new_send_confirm(req);
|
||||||
|
allow_err!(peer.send(&msg).await);
|
||||||
|
} else {
|
||||||
|
self.handle_override_file_confirm(digest.id, digest.file_num, read_path, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let Some(job) = fs::get_job(digest.id, &mut self.write_jobs) {
|
||||||
|
if let Some(file) = job.files().get(digest.file_num as usize) {
|
||||||
|
let write_path = get_string(&job.join(&file.name));
|
||||||
|
let overwrite_strategy = job.default_overwrite_strategy();
|
||||||
|
match fs::is_write_need_confirmation(&write_path, &digest) {
|
||||||
|
Ok(res) => match res {
|
||||||
|
DigestCheckResult::IsSame => {
|
||||||
|
let msg= new_send_confirm(FileTransferSendConfirmRequest {
|
||||||
|
id: digest.id,
|
||||||
|
file_num: digest.file_num,
|
||||||
|
union: Some(file_transfer_send_confirm_request::Union::skip(true)),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
self.session.send_msg(msg);
|
||||||
|
}
|
||||||
|
DigestCheckResult::NeedConfirm(digest) => {
|
||||||
|
if let Some(overwrite) = overwrite_strategy {
|
||||||
|
let msg = new_send_confirm(
|
||||||
|
FileTransferSendConfirmRequest {
|
||||||
|
id: digest.id,
|
||||||
|
file_num: digest.file_num,
|
||||||
|
union: Some(if overwrite {
|
||||||
|
file_transfer_send_confirm_request::Union::offset_blk(0)
|
||||||
|
} else {
|
||||||
|
file_transfer_send_confirm_request::Union::skip(true)
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
self.session.send_msg(msg);
|
||||||
|
} else {
|
||||||
|
self.handle_override_file_confirm(digest.id, digest.file_num, write_path.to_string(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DigestCheckResult::NoSuchFile => {
|
||||||
|
let msg = new_send_confirm(
|
||||||
|
FileTransferSendConfirmRequest {
|
||||||
|
id: digest.id,
|
||||||
|
file_num: digest.file_num,
|
||||||
|
union: Some(file_transfer_send_confirm_request::Union::offset_blk(0)),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
self.session.send_msg(msg);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(err) => {
|
||||||
|
println!("error recving digest: {}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
Some(message::Union::misc(misc)) => match misc.union {
|
Some(message::Union::misc(misc)) => match misc.union {
|
||||||
@ -713,6 +806,14 @@ impl Connection {
|
|||||||
self.audio_handler.handle_frame(frame);
|
self.audio_handler.handle_frame(frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some(message::Union::file_action(action)) => match action.union {
|
||||||
|
Some(file_action::Union::send_confirm(c)) => {
|
||||||
|
if let Some(job) = fs::get_job(c.id, &mut self.read_jobs) {
|
||||||
|
job.confirm(&c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -732,14 +833,29 @@ impl Connection {
|
|||||||
Data::Message(msg) => {
|
Data::Message(msg) => {
|
||||||
allow_err!(peer.send(&msg).await);
|
allow_err!(peer.send(&msg).await);
|
||||||
}
|
}
|
||||||
Data::SendFiles((id, path, to, include_hidden, is_remote)) => {
|
Data::SendFiles((id, path, to, file_num, include_hidden, is_remote)) => {
|
||||||
|
// in mobile, can_enable_override_detection is always true
|
||||||
|
let od = true;
|
||||||
if is_remote {
|
if is_remote {
|
||||||
log::debug!("New job {}, write to {} from remote {}", id, to, path);
|
log::debug!("New job {}, write to {} from remote {}", id, to, path);
|
||||||
self.write_jobs
|
self.write_jobs
|
||||||
.push(fs::TransferJob::new_write(id, to, Vec::new()));
|
.push(fs::TransferJob::new_write(id,
|
||||||
allow_err!(peer.send(&fs::new_send(id, path, include_hidden)).await);
|
path.clone(),
|
||||||
|
to,
|
||||||
|
file_num,
|
||||||
|
include_hidden,
|
||||||
|
is_remote,
|
||||||
|
Vec::new(),
|
||||||
|
true));
|
||||||
|
allow_err!(peer.send(&fs::new_send(id, path, file_num, include_hidden)).await);
|
||||||
} else {
|
} else {
|
||||||
match fs::TransferJob::new_read(id, path.clone(), include_hidden) {
|
match fs::TransferJob::new_read(id,
|
||||||
|
to.clone(),
|
||||||
|
path.clone(),
|
||||||
|
file_num,
|
||||||
|
include_hidden,
|
||||||
|
is_remote,
|
||||||
|
true) {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
self.handle_job_status(id, -1, Some(err.to_string()));
|
self.handle_job_status(id, -1, Some(err.to_string()));
|
||||||
}
|
}
|
||||||
@ -754,7 +870,7 @@ impl Connection {
|
|||||||
let files = job.files().clone();
|
let files = job.files().clone();
|
||||||
self.read_jobs.push(job);
|
self.read_jobs.push(job);
|
||||||
self.timer = time::interval(MILLI1);
|
self.timer = time::interval(MILLI1);
|
||||||
allow_err!(peer.send(&fs::new_receive(id, to, files)).await);
|
allow_err!(peer.send(&fs::new_receive(id, to, file_num, files)).await);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -861,6 +977,45 @@ impl Connection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Data::SetConfirmOverrideFile((id, file_num, need_override, remember, is_upload)) => {
|
||||||
|
if is_upload {
|
||||||
|
if let Some(job) = fs::get_job(id, &mut self.read_jobs) {
|
||||||
|
if remember {
|
||||||
|
job.set_overwrite_strategy(Some(need_override));
|
||||||
|
}
|
||||||
|
job.confirm(&FileTransferSendConfirmRequest {
|
||||||
|
id,
|
||||||
|
file_num,
|
||||||
|
union: if need_override {
|
||||||
|
Some(file_transfer_send_confirm_request::Union::offset_blk(0))
|
||||||
|
} else {
|
||||||
|
Some(file_transfer_send_confirm_request::Union::skip(true))
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let Some(job) = fs::get_job(id, &mut self.write_jobs) {
|
||||||
|
if remember {
|
||||||
|
job.set_overwrite_strategy(Some(need_override));
|
||||||
|
}
|
||||||
|
let mut msg = Message::new();
|
||||||
|
let mut file_action = FileAction::new();
|
||||||
|
file_action.set_send_confirm(FileTransferSendConfirmRequest {
|
||||||
|
id,
|
||||||
|
file_num,
|
||||||
|
union: if need_override {
|
||||||
|
Some(file_transfer_send_confirm_request::Union::offset_blk(0))
|
||||||
|
} else {
|
||||||
|
Some(file_transfer_send_confirm_request::Union::skip(true))
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
msg.set_file_action(file_action);
|
||||||
|
self.session.send_msg(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
@ -932,6 +1087,13 @@ impl Connection {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_override_file_confirm(&mut self, id: i32, file_num: i32, read_path: String, is_upload: bool) {
|
||||||
|
self.session.push_event(
|
||||||
|
"override_file_confirm",
|
||||||
|
vec![("id", &id.to_string()), ("file_num", &file_num.to_string()), ("read_path", &read_path), ("is_upload", &is_upload.to_string())]
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_fd_to_json(fd: FileDirectory) -> String {
|
pub fn make_fd_to_json(fd: FileDirectory) -> String {
|
||||||
@ -970,14 +1132,14 @@ pub mod connection_manager {
|
|||||||
use hbb_common::{
|
use hbb_common::{
|
||||||
allow_err,
|
allow_err,
|
||||||
config::Config,
|
config::Config,
|
||||||
fs, log,
|
fs::{self, new_send_confirm, DigestCheckResult, get_string}, log,
|
||||||
message_proto::*,
|
message_proto::*,
|
||||||
protobuf::Message as _,
|
protobuf::Message as _,
|
||||||
tokio::{
|
tokio::{
|
||||||
self,
|
self,
|
||||||
sync::mpsc::{UnboundedReceiver, UnboundedSender},
|
sync::mpsc::{UnboundedReceiver, UnboundedSender},
|
||||||
task::spawn_blocking,
|
task::spawn_blocking,
|
||||||
},
|
}, fs::is_write_need_confirmation,
|
||||||
};
|
};
|
||||||
use scrap::android::call_main_service_set_by_name;
|
use scrap::android::call_main_service_set_by_name;
|
||||||
use serde_derive::Serialize;
|
use serde_derive::Serialize;
|
||||||
@ -1180,11 +1342,18 @@ pub mod connection_manager {
|
|||||||
ipc::FS::NewWrite {
|
ipc::FS::NewWrite {
|
||||||
path,
|
path,
|
||||||
id,
|
id,
|
||||||
|
file_num,
|
||||||
mut files,
|
mut files,
|
||||||
} => {
|
} => {
|
||||||
|
// in mobile, can_enable_override_detection is always true
|
||||||
|
let od = true;
|
||||||
WRITE_JOBS.lock().unwrap().push(fs::TransferJob::new_write(
|
WRITE_JOBS.lock().unwrap().push(fs::TransferJob::new_write(
|
||||||
id,
|
id,
|
||||||
|
"".to_string(),
|
||||||
path,
|
path,
|
||||||
|
file_num,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
files
|
files
|
||||||
.drain(..)
|
.drain(..)
|
||||||
.map(|f| FileEntry {
|
.map(|f| FileEntry {
|
||||||
@ -1193,6 +1362,7 @@ pub mod connection_manager {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
|
true
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
ipc::FS::CancelWrite { id } => {
|
ipc::FS::CancelWrite { id } => {
|
||||||
@ -1234,6 +1404,59 @@ pub mod connection_manager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ipc::FS::CheckDigest {
|
||||||
|
id,
|
||||||
|
file_num,
|
||||||
|
file_size,
|
||||||
|
last_modified,
|
||||||
|
is_upload,
|
||||||
|
} => {
|
||||||
|
if let Some(job) = fs::get_job(id, &mut *WRITE_JOBS.lock().unwrap()) {
|
||||||
|
let mut req = FileTransferSendConfirmRequest {
|
||||||
|
id,
|
||||||
|
file_num,
|
||||||
|
union: Some(file_transfer_send_confirm_request::Union::offset_blk(0)),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
let digest = FileTransferDigest {
|
||||||
|
id,
|
||||||
|
file_num,
|
||||||
|
last_modified,
|
||||||
|
file_size,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
if let Some(file) = job.files().get(file_num as usize) {
|
||||||
|
let path = get_string(&job.join(&file.name));
|
||||||
|
match is_write_need_confirmation(&path, &digest) {
|
||||||
|
Ok(digest_result) => {
|
||||||
|
match digest_result {
|
||||||
|
DigestCheckResult::IsSame => {
|
||||||
|
req.set_skip(true);
|
||||||
|
let msg_out = new_send_confirm(req);
|
||||||
|
send_raw(msg_out, &tx);
|
||||||
|
}
|
||||||
|
DigestCheckResult::NeedConfirm(mut digest) => {
|
||||||
|
// upload to server, but server has the same file, request
|
||||||
|
digest.is_upload = is_upload;
|
||||||
|
let mut msg_out = Message::new();
|
||||||
|
let mut fr = FileResponse::new();
|
||||||
|
fr.set_digest(digest);
|
||||||
|
msg_out.set_file_response(fr);
|
||||||
|
send_raw(msg_out, &tx);
|
||||||
|
}
|
||||||
|
DigestCheckResult::NoSuchFile => {
|
||||||
|
let msg_out = new_send_confirm(req);
|
||||||
|
send_raw(msg_out, &tx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
send_raw(fs::new_error(id, err, file_num), &tx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -324,12 +324,14 @@ unsafe extern "C" fn set_by_name(name: *const c_char, value: *const c_char) {
|
|||||||
Some(id),
|
Some(id),
|
||||||
Some(path),
|
Some(path),
|
||||||
Some(to),
|
Some(to),
|
||||||
|
Some(file_num),
|
||||||
Some(show_hidden),
|
Some(show_hidden),
|
||||||
Some(is_remote),
|
Some(is_remote),
|
||||||
) = (
|
) = (
|
||||||
m.get("id"),
|
m.get("id"),
|
||||||
m.get("path"),
|
m.get("path"),
|
||||||
m.get("to"),
|
m.get("to"),
|
||||||
|
m.get("file_num"),
|
||||||
m.get("show_hidden"),
|
m.get("show_hidden"),
|
||||||
m.get("is_remote"),
|
m.get("is_remote"),
|
||||||
) {
|
) {
|
||||||
@ -337,12 +339,38 @@ unsafe extern "C" fn set_by_name(name: *const c_char, value: *const c_char) {
|
|||||||
id.parse().unwrap_or(0),
|
id.parse().unwrap_or(0),
|
||||||
path.to_owned(),
|
path.to_owned(),
|
||||||
to.to_owned(),
|
to.to_owned(),
|
||||||
|
file_num.parse().unwrap_or(0),
|
||||||
show_hidden.eq("true"),
|
show_hidden.eq("true"),
|
||||||
is_remote.eq("true"),
|
is_remote.eq("true"),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
"set_confirm_override_file" => {
|
||||||
|
if let Ok(m) = serde_json::from_str::<HashMap<String, String>>(value) {
|
||||||
|
if let (
|
||||||
|
Some(id),
|
||||||
|
Some(file_num),
|
||||||
|
Some(need_override),
|
||||||
|
Some(remember),
|
||||||
|
Some(is_upload),
|
||||||
|
) = (
|
||||||
|
m.get("id"),
|
||||||
|
m.get("file_num"),
|
||||||
|
m.get("need_override"),
|
||||||
|
m.get("remember"),
|
||||||
|
m.get("is_upload")
|
||||||
|
) {
|
||||||
|
Session::set_confirm_override_file(
|
||||||
|
id.parse().unwrap_or(0),
|
||||||
|
file_num.parse().unwrap_or(0),
|
||||||
|
need_override.eq("true"),
|
||||||
|
remember.eq("true"),
|
||||||
|
is_upload.eq("true"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
"remove_file" => {
|
"remove_file" => {
|
||||||
if let Ok(m) = serde_json::from_str::<HashMap<String, String>>(value) {
|
if let Ok(m) = serde_json::from_str::<HashMap<String, String>>(value) {
|
||||||
if let (
|
if let (
|
||||||
|
@ -7,8 +7,6 @@ use crate::common::update_clipboard;
|
|||||||
use crate::{common::MOBILE_INFO2, mobile::connection_manager::start_channel};
|
use crate::{common::MOBILE_INFO2, mobile::connection_manager::start_channel};
|
||||||
use crate::{ipc, VERSION};
|
use crate::{ipc, VERSION};
|
||||||
use hbb_common::fs::can_enable_overwrite_detection;
|
use hbb_common::fs::can_enable_overwrite_detection;
|
||||||
use hbb_common::log::debug;
|
|
||||||
use hbb_common::message_proto::file_transfer_send_confirm_request::Union;
|
|
||||||
use hbb_common::{
|
use hbb_common::{
|
||||||
config::Config,
|
config::Config,
|
||||||
fs,
|
fs,
|
||||||
@ -23,7 +21,6 @@ use hbb_common::{
|
|||||||
},
|
},
|
||||||
tokio_util::codec::{BytesCodec, Framed},
|
tokio_util::codec::{BytesCodec, Framed},
|
||||||
};
|
};
|
||||||
use libc::{printf, send};
|
|
||||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||||
use scrap::android::call_input_service_mouse_input;
|
use scrap::android::call_input_service_mouse_input;
|
||||||
use serde_json::{json, value::Value};
|
use serde_json::{json, value::Value};
|
||||||
|
10
src/ui/cm.rs
10
src/ui/cm.rs
@ -8,15 +8,13 @@ use hbb_common::fs::{
|
|||||||
can_enable_overwrite_detection, get_string, is_write_need_confirmation, new_send_confirm,
|
can_enable_overwrite_detection, get_string, is_write_need_confirmation, new_send_confirm,
|
||||||
DigestCheckResult,
|
DigestCheckResult,
|
||||||
};
|
};
|
||||||
use hbb_common::log::log;
|
|
||||||
use hbb_common::{
|
use hbb_common::{
|
||||||
allow_err,
|
allow_err,
|
||||||
config::Config,
|
config::Config,
|
||||||
fs, get_version_number, log,
|
fs, get_version_number, log,
|
||||||
message_proto::*,
|
message_proto::*,
|
||||||
protobuf::Message as _,
|
protobuf::Message as _,
|
||||||
tokio::{self, sync::mpsc, task::spawn_blocking},
|
tokio::{self, sync::mpsc, task::spawn_blocking}
|
||||||
ResultType,
|
|
||||||
};
|
};
|
||||||
use sciter::{make_args, Element, Value, HELEMENT};
|
use sciter::{make_args, Element, Value, HELEMENT};
|
||||||
use std::{
|
use std::{
|
||||||
@ -278,9 +276,9 @@ impl ConnectionManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ipc::FS::WriteOffset {
|
ipc::FS::WriteOffset {
|
||||||
id,
|
id: _,
|
||||||
file_num,
|
file_num: _,
|
||||||
offset_blk,
|
offset_blk: _,
|
||||||
} => {}
|
} => {}
|
||||||
},
|
},
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
|
@ -21,14 +21,13 @@ use clipboard::{
|
|||||||
};
|
};
|
||||||
use enigo::{self, Enigo, KeyboardControllable};
|
use enigo::{self, Enigo, KeyboardControllable};
|
||||||
use hbb_common::fs::{
|
use hbb_common::fs::{
|
||||||
can_enable_overwrite_detection, get_string, is_file_exists, new_send_confirm,
|
can_enable_overwrite_detection, get_string, new_send_confirm,
|
||||||
DigestCheckResult, RemoveJobMeta, get_job,
|
DigestCheckResult, RemoveJobMeta, get_job,
|
||||||
};
|
};
|
||||||
use hbb_common::log::log;
|
|
||||||
use hbb_common::{
|
use hbb_common::{
|
||||||
allow_err,
|
allow_err,
|
||||||
config::{self, Config, LocalConfig, PeerConfig},
|
config::{Config, LocalConfig, PeerConfig},
|
||||||
fs, get_version_number, log,
|
fs, log,
|
||||||
message_proto::{permission_info::Permission, *},
|
message_proto::{permission_info::Permission, *},
|
||||||
protobuf::Message as _,
|
protobuf::Message as _,
|
||||||
rendezvous_proto::ConnType,
|
rendezvous_proto::ConnType,
|
||||||
@ -46,8 +45,7 @@ use hbb_common::{config::TransferSerde, fs::TransferJobMeta};
|
|||||||
use crate::clipboard_file::*;
|
use crate::clipboard_file::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
client::*,
|
client::*,
|
||||||
common::{self, check_clipboard, update_clipboard, ClipboardContext, CLIPBOARD_INTERVAL},
|
common::{self, check_clipboard, update_clipboard, ClipboardContext, CLIPBOARD_INTERVAL}
|
||||||
VERSION,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type Video = AssetPtr<video_destination>;
|
type Video = AssetPtr<video_destination>;
|
||||||
@ -1345,7 +1343,7 @@ impl RemoveJob {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen_meta(&self) -> RemoveJobMeta {
|
pub fn _gen_meta(&self) -> RemoveJobMeta {
|
||||||
RemoveJobMeta {
|
RemoveJobMeta {
|
||||||
path: self.path.clone(),
|
path: self.path.clone(),
|
||||||
is_remote: self.is_remote,
|
is_remote: self.is_remote,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user