Merge pull request #1689 from 21pages/persist-chat
persist cm chat page if chat unanswered
This commit is contained in:
commit
2b75c7b361
@ -158,40 +158,26 @@ class ConnectionManagerState extends State<ConnectionManager> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildTab(Client client) {
|
|
||||||
return Tab(
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
SizedBox(
|
|
||||||
width: 80,
|
|
||||||
child: Text(
|
|
||||||
client.name,
|
|
||||||
maxLines: 1,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildConnectionCard(Client client) {
|
Widget buildConnectionCard(Client client) {
|
||||||
return Column(
|
return Consumer<ServerModel>(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
builder: (context, value, child) => Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
key: ValueKey(client.id),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
key: ValueKey(client.id),
|
||||||
_CmHeader(client: client),
|
children: [
|
||||||
client.isFileTransfer ? Offstage() : _PrivilegeBoard(client: client),
|
_CmHeader(client: client),
|
||||||
Expanded(
|
client.isFileTransfer || client.disconnected
|
||||||
child: Align(
|
? Offstage()
|
||||||
alignment: Alignment.bottomCenter,
|
: _PrivilegeBoard(client: client),
|
||||||
child: _CmControlPanel(client: client),
|
Expanded(
|
||||||
))
|
child: Align(
|
||||||
],
|
alignment: Alignment.bottomCenter,
|
||||||
).paddingSymmetric(vertical: 8.0, horizontal: 8.0);
|
child: _CmControlPanel(client: client),
|
||||||
|
))
|
||||||
|
],
|
||||||
|
).paddingSymmetric(vertical: 8.0, horizontal: 8.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AppIcon extends StatelessWidget {
|
class _AppIcon extends StatelessWidget {
|
||||||
@ -249,7 +235,7 @@ class _CmHeaderState extends State<_CmHeader>
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_timer = Timer.periodic(Duration(seconds: 1), (_) {
|
_timer = Timer.periodic(Duration(seconds: 1), (_) {
|
||||||
_time.value = _time.value + 1;
|
if (!client.disconnected) _time.value = _time.value + 1;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,7 +289,10 @@ class _CmHeaderState extends State<_CmHeader>
|
|||||||
FittedBox(
|
FittedBox(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Text(translate("Connected")).marginOnly(right: 8.0),
|
Text(client.disconnected
|
||||||
|
? translate("Disconnected")
|
||||||
|
: translate("Connected"))
|
||||||
|
.marginOnly(right: 8.0),
|
||||||
Obx(() => Text(
|
Obx(() => Text(
|
||||||
formatDurationToTime(Duration(seconds: _time.value))))
|
formatDurationToTime(Duration(seconds: _time.value))))
|
||||||
],
|
],
|
||||||
@ -311,15 +300,14 @@ class _CmHeaderState extends State<_CmHeader>
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Consumer<ServerModel>(
|
Offstage(
|
||||||
builder: (_, model, child) => Offstage(
|
offstage: !client.authorized || client.isFileTransfer,
|
||||||
offstage: !client.authorized || client.isFileTransfer,
|
child: IconButton(
|
||||||
child: IconButton(
|
onPressed: () => checkClickTime(
|
||||||
onPressed: () => checkClickTime(client.id,
|
client.id, () => gFFI.chatModel.toggleCMChatPage(client.id)),
|
||||||
() => gFFI.chatModel.toggleCMChatPage(client.id)),
|
icon: Icon(Icons.message_outlined),
|
||||||
icon: Icon(Icons.message_outlined),
|
),
|
||||||
),
|
)
|
||||||
))
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -435,11 +423,11 @@ class _CmControlPanel extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Consumer<ServerModel>(builder: (_, model, child) {
|
return client.authorized
|
||||||
return client.authorized
|
? client.disconnected
|
||||||
? buildAuthorized(context)
|
? buildDisconnected(context)
|
||||||
: buildUnAuthorized(context);
|
: buildAuthorized(context)
|
||||||
});
|
: buildUnAuthorized(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
buildAuthorized(BuildContext context) {
|
buildAuthorized(BuildContext context) {
|
||||||
@ -468,6 +456,31 @@ class _CmControlPanel extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buildDisconnected(BuildContext context) {
|
||||||
|
return Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Ink(
|
||||||
|
width: 200,
|
||||||
|
height: 40,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: MyTheme.accent, borderRadius: BorderRadius.circular(10)),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () => handleClose(context),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
translate("Close"),
|
||||||
|
style: TextStyle(color: Colors.white),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
buildUnAuthorized(BuildContext context) {
|
buildUnAuthorized(BuildContext context) {
|
||||||
return Row(
|
return Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
@ -527,6 +540,13 @@ class _CmControlPanel extends StatelessWidget {
|
|||||||
final model = Provider.of<ServerModel>(context, listen: false);
|
final model = Provider.of<ServerModel>(context, listen: false);
|
||||||
model.sendLoginResponse(client, true);
|
model.sendLoginResponse(client, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handleClose(BuildContext context) async {
|
||||||
|
await bind.cmRemoveDisconnectedConnection(connId: client.id);
|
||||||
|
if (await bind.cmGetClientsLength() == 0) {
|
||||||
|
windowManager.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkClickTime(int id, Function() callback) async {
|
void checkClickTime(int id, Function() callback) async {
|
||||||
|
@ -376,29 +376,29 @@ class ServerModel with ChangeNotifier {
|
|||||||
} else {
|
} else {
|
||||||
_clients[index].authorized = true;
|
_clients[index].authorized = true;
|
||||||
}
|
}
|
||||||
tabController.add(
|
|
||||||
TabInfo(
|
|
||||||
key: client.id.toString(),
|
|
||||||
label: client.name,
|
|
||||||
closable: false,
|
|
||||||
page: Desktop.buildConnectionCard(client)),
|
|
||||||
authorized: true);
|
|
||||||
scrollToBottom();
|
|
||||||
notifyListeners();
|
|
||||||
} else {
|
} else {
|
||||||
if (_clients.any((c) => c.id == client.id)) {
|
if (_clients.any((c) => c.id == client.id)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_clients.add(client);
|
_clients.add(client);
|
||||||
tabController.add(TabInfo(
|
|
||||||
key: client.id.toString(),
|
|
||||||
label: client.name,
|
|
||||||
closable: false,
|
|
||||||
page: Desktop.buildConnectionCard(client)));
|
|
||||||
scrollToBottom();
|
|
||||||
notifyListeners();
|
|
||||||
if (isAndroid) showLoginDialog(client);
|
|
||||||
}
|
}
|
||||||
|
tabController.add(
|
||||||
|
TabInfo(
|
||||||
|
key: client.id.toString(),
|
||||||
|
label: client.name,
|
||||||
|
closable: false,
|
||||||
|
page: Desktop.buildConnectionCard(client)),
|
||||||
|
authorized: client.authorized);
|
||||||
|
// remove disconnected
|
||||||
|
final index_disconnected = _clients
|
||||||
|
.indexWhere((c) => c.disconnected && c.peerId == client.peerId);
|
||||||
|
if (index_disconnected >= 0) {
|
||||||
|
_clients.removeAt(index_disconnected);
|
||||||
|
tabController.remove(index_disconnected);
|
||||||
|
}
|
||||||
|
scrollToBottom();
|
||||||
|
notifyListeners();
|
||||||
|
if (isAndroid && !client.authorized) showLoginDialog(client);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint("Failed to call loginRequest,error:$e");
|
debugPrint("Failed to call loginRequest,error:$e");
|
||||||
}
|
}
|
||||||
@ -477,38 +477,19 @@ class ServerModel with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onClientAuthorized(Map<String, dynamic> evt) {
|
|
||||||
try {
|
|
||||||
final client = Client.fromJson(jsonDecode(evt['client']));
|
|
||||||
parent.target?.dialogManager.dismissByTag(getLoginDialogTag(client.id));
|
|
||||||
final index = _clients.indexWhere((c) => c.id == client.id);
|
|
||||||
if (index < 0) {
|
|
||||||
_clients.add(client);
|
|
||||||
} else {
|
|
||||||
_clients[index].authorized = true;
|
|
||||||
}
|
|
||||||
tabController.add(
|
|
||||||
TabInfo(
|
|
||||||
key: client.id.toString(),
|
|
||||||
label: client.name,
|
|
||||||
closable: false,
|
|
||||||
page: Desktop.buildConnectionCard(client)),
|
|
||||||
authorized: true);
|
|
||||||
scrollToBottom();
|
|
||||||
notifyListeners();
|
|
||||||
} catch (e) {
|
|
||||||
debugPrint("onClientAuthorized:$e");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void onClientRemove(Map<String, dynamic> evt) {
|
void onClientRemove(Map<String, dynamic> evt) {
|
||||||
try {
|
try {
|
||||||
final id = int.parse(evt['id'] as String);
|
final id = int.parse(evt['id'] as String);
|
||||||
|
final close = (evt['close'] as String) == 'true';
|
||||||
if (_clients.any((c) => c.id == id)) {
|
if (_clients.any((c) => c.id == id)) {
|
||||||
final index = _clients.indexWhere((client) => client.id == id);
|
final index = _clients.indexWhere((client) => client.id == id);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
_clients.removeAt(index);
|
if (close) {
|
||||||
tabController.remove(index);
|
_clients.removeAt(index);
|
||||||
|
tabController.remove(index);
|
||||||
|
} else {
|
||||||
|
_clients[index].disconnected = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
parent.target?.dialogManager.dismissByTag(getLoginDialogTag(id));
|
parent.target?.dialogManager.dismissByTag(getLoginDialogTag(id));
|
||||||
parent.target?.invokeMethod("cancel_notification", id);
|
parent.target?.invokeMethod("cancel_notification", id);
|
||||||
@ -545,6 +526,7 @@ class Client {
|
|||||||
bool file = false;
|
bool file = false;
|
||||||
bool restart = false;
|
bool restart = false;
|
||||||
bool recording = false;
|
bool recording = false;
|
||||||
|
bool disconnected = false;
|
||||||
|
|
||||||
Client(this.id, this.authorized, this.isFileTransfer, this.name, this.peerId,
|
Client(this.id, this.authorized, this.isFileTransfer, this.name, this.peerId,
|
||||||
this.keyboard, this.clipboard, this.audio);
|
this.keyboard, this.clipboard, this.audio);
|
||||||
@ -561,18 +543,20 @@ class Client {
|
|||||||
file = json['file'];
|
file = json['file'];
|
||||||
restart = json['restart'];
|
restart = json['restart'];
|
||||||
recording = json['recording'];
|
recording = json['recording'];
|
||||||
|
disconnected = json['disconnected'];
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
data['id'] = this.id;
|
data['id'] = id;
|
||||||
data['is_start'] = this.authorized;
|
data['is_start'] = authorized;
|
||||||
data['is_file_transfer'] = this.isFileTransfer;
|
data['is_file_transfer'] = isFileTransfer;
|
||||||
data['name'] = this.name;
|
data['name'] = name;
|
||||||
data['peer_id'] = this.peerId;
|
data['peer_id'] = peerId;
|
||||||
data['keyboard'] = this.keyboard;
|
data['keyboard'] = keyboard;
|
||||||
data['clipboard'] = this.clipboard;
|
data['clipboard'] = clipboard;
|
||||||
data['audio'] = this.audio;
|
data['audio'] = audio;
|
||||||
|
data['disconnected'] = disconnected;
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -368,8 +368,11 @@ pub mod connection_manager {
|
|||||||
self.push_event("add_connection", vec![("client", &client_json)]);
|
self.push_event("add_connection", vec![("client", &client_json)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_connection(&self, id: i32) {
|
fn remove_connection(&self, id: i32, close: bool) {
|
||||||
self.push_event("on_client_remove", vec![("id", &id.to_string())]);
|
self.push_event(
|
||||||
|
"on_client_remove",
|
||||||
|
vec![("id", &id.to_string()), ("close", &close.to_string())],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_message(&self, id: i32, text: String) {
|
fn new_message(&self, id: i32, text: String) {
|
||||||
|
@ -779,6 +779,10 @@ pub fn cm_check_clients_length(length: usize) -> Option<String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cm_get_clients_length() -> usize {
|
||||||
|
crate::ui_cm_interface::get_clients_length()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn main_init(app_dir: String) {
|
pub fn main_init(app_dir: String) {
|
||||||
initialize(&app_dir);
|
initialize(&app_dir);
|
||||||
}
|
}
|
||||||
@ -941,6 +945,10 @@ pub fn cm_close_connection(conn_id: i32) {
|
|||||||
crate::ui_cm_interface::close(conn_id);
|
crate::ui_cm_interface::close(conn_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cm_remove_disconnected_connection(conn_id: i32) {
|
||||||
|
crate::ui_cm_interface::remove(conn_id);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn cm_check_click_time(conn_id: i32) {
|
pub fn cm_check_click_time(conn_id: i32) {
|
||||||
crate::ui_cm_interface::check_click_time(conn_id)
|
crate::ui_cm_interface::check_click_time(conn_id)
|
||||||
}
|
}
|
||||||
|
@ -186,6 +186,7 @@ pub enum Data {
|
|||||||
Theme(String),
|
Theme(String),
|
||||||
Language(String),
|
Language(String),
|
||||||
Empty,
|
Empty,
|
||||||
|
Disconnected,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main(flavor = "current_thread")]
|
#[tokio::main(flavor = "current_thread")]
|
||||||
|
@ -366,5 +366,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("elevation_prompt", "以当前用户权限运行软件,可能导致远端在访问本机时,没有足够的权限来操作部分窗口。"),
|
("elevation_prompt", "以当前用户权限运行软件,可能导致远端在访问本机时,没有足够的权限来操作部分窗口。"),
|
||||||
("uac_warning", "暂时无法访问远端设备,因为远端设备正在请求用户账户权限,请等待对方关闭UAC窗口。为避免这个问题,建议在远端设备上安装或者以管理员权限运行本软件。"),
|
("uac_warning", "暂时无法访问远端设备,因为远端设备正在请求用户账户权限,请等待对方关闭UAC窗口。为避免这个问题,建议在远端设备上安装或者以管理员权限运行本软件。"),
|
||||||
("elevated_foreground_window_warning", "暂时无法使用鼠标键盘,因为远端桌面的当前窗口需要更高的权限才能操作, 可以请求对方最小化当前窗口。为避免这个问题,建议在远端设备上安装或者以管理员权限运行本软件。"),
|
("elevated_foreground_window_warning", "暂时无法使用鼠标键盘,因为远端桌面的当前窗口需要更高的权限才能操作, 可以请求对方最小化当前窗口。为避免这个问题,建议在远端设备上安装或者以管理员权限运行本软件。"),
|
||||||
|
("Disconnected", "会话已结束"),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -366,5 +366,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("elevation_prompt", ""),
|
("elevation_prompt", ""),
|
||||||
("uac_warning", ""),
|
("uac_warning", ""),
|
||||||
("elevated_foreground_window_warning", ""),
|
("elevated_foreground_window_warning", ""),
|
||||||
|
("Disconnected", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -366,5 +366,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("elevation_prompt", ""),
|
("elevation_prompt", ""),
|
||||||
("uac_warning", ""),
|
("uac_warning", ""),
|
||||||
("elevated_foreground_window_warning", ""),
|
("elevated_foreground_window_warning", ""),
|
||||||
|
("Disconnected", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -366,5 +366,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("elevation_prompt", ""),
|
("elevation_prompt", ""),
|
||||||
("uac_warning", ""),
|
("uac_warning", ""),
|
||||||
("elevated_foreground_window_warning", ""),
|
("elevated_foreground_window_warning", ""),
|
||||||
|
("Disconnected", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -366,5 +366,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("elevation_prompt", ""),
|
("elevation_prompt", ""),
|
||||||
("uac_warning", ""),
|
("uac_warning", ""),
|
||||||
("elevated_foreground_window_warning", ""),
|
("elevated_foreground_window_warning", ""),
|
||||||
|
("Disconnected", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -366,5 +366,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("elevation_prompt", ""),
|
("elevation_prompt", ""),
|
||||||
("uac_warning", ""),
|
("uac_warning", ""),
|
||||||
("elevated_foreground_window_warning", ""),
|
("elevated_foreground_window_warning", ""),
|
||||||
|
("Disconnected", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -366,5 +366,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("elevation_prompt", ""),
|
("elevation_prompt", ""),
|
||||||
("uac_warning", ""),
|
("uac_warning", ""),
|
||||||
("elevated_foreground_window_warning", ""),
|
("elevated_foreground_window_warning", ""),
|
||||||
|
("Disconnected", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -366,5 +366,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("elevation_prompt", ""),
|
("elevation_prompt", ""),
|
||||||
("uac_warning", ""),
|
("uac_warning", ""),
|
||||||
("elevated_foreground_window_warning", ""),
|
("elevated_foreground_window_warning", ""),
|
||||||
|
("Disconnected", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -366,5 +366,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("elevation_prompt", ""),
|
("elevation_prompt", ""),
|
||||||
("uac_warning", ""),
|
("uac_warning", ""),
|
||||||
("elevated_foreground_window_warning", ""),
|
("elevated_foreground_window_warning", ""),
|
||||||
|
("Disconnected", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -366,5 +366,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("elevation_prompt", ""),
|
("elevation_prompt", ""),
|
||||||
("uac_warning", ""),
|
("uac_warning", ""),
|
||||||
("elevated_foreground_window_warning", ""),
|
("elevated_foreground_window_warning", ""),
|
||||||
|
("Disconnected", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -366,5 +366,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("elevation_prompt", ""),
|
("elevation_prompt", ""),
|
||||||
("uac_warning", ""),
|
("uac_warning", ""),
|
||||||
("elevated_foreground_window_warning", ""),
|
("elevated_foreground_window_warning", ""),
|
||||||
|
("Disconnected", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -366,5 +366,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("elevation_prompt", ""),
|
("elevation_prompt", ""),
|
||||||
("uac_warning", ""),
|
("uac_warning", ""),
|
||||||
("elevated_foreground_window_warning", ""),
|
("elevated_foreground_window_warning", ""),
|
||||||
|
("Disconnected", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -366,5 +366,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("elevation_prompt", ""),
|
("elevation_prompt", ""),
|
||||||
("uac_warning", ""),
|
("uac_warning", ""),
|
||||||
("elevated_foreground_window_warning", ""),
|
("elevated_foreground_window_warning", ""),
|
||||||
|
("Disconnected", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -366,5 +366,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("elevation_prompt", "Monit o podwyższeniu uprawnień"),
|
("elevation_prompt", "Monit o podwyższeniu uprawnień"),
|
||||||
("uac_warning", "Ostrzeżenie UAC"),
|
("uac_warning", "Ostrzeżenie UAC"),
|
||||||
("elevated_foreground_window_warning", "Pierwszoplanowe okno ostrzeżenia o podwyższeniu uprawnień"),
|
("elevated_foreground_window_warning", "Pierwszoplanowe okno ostrzeżenia o podwyższeniu uprawnień"),
|
||||||
|
("Disconnected", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -366,5 +366,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("elevation_prompt", ""),
|
("elevation_prompt", ""),
|
||||||
("uac_warning", ""),
|
("uac_warning", ""),
|
||||||
("elevated_foreground_window_warning", ""),
|
("elevated_foreground_window_warning", ""),
|
||||||
|
("Disconnected", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -366,5 +366,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("elevation_prompt", ""),
|
("elevation_prompt", ""),
|
||||||
("uac_warning", ""),
|
("uac_warning", ""),
|
||||||
("elevated_foreground_window_warning", ""),
|
("elevated_foreground_window_warning", ""),
|
||||||
|
("Disconnected", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -366,5 +366,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("elevation_prompt", ""),
|
("elevation_prompt", ""),
|
||||||
("uac_warning", ""),
|
("uac_warning", ""),
|
||||||
("elevated_foreground_window_warning", ""),
|
("elevated_foreground_window_warning", ""),
|
||||||
|
("Disconnected", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -366,5 +366,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("elevation_prompt", ""),
|
("elevation_prompt", ""),
|
||||||
("uac_warning", ""),
|
("uac_warning", ""),
|
||||||
("elevated_foreground_window_warning", ""),
|
("elevated_foreground_window_warning", ""),
|
||||||
|
("Disconnected", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -366,5 +366,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("elevation_prompt", ""),
|
("elevation_prompt", ""),
|
||||||
("uac_warning", ""),
|
("uac_warning", ""),
|
||||||
("elevated_foreground_window_warning", ""),
|
("elevated_foreground_window_warning", ""),
|
||||||
|
("Disconnected", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -366,5 +366,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("elevation_prompt", ""),
|
("elevation_prompt", ""),
|
||||||
("uac_warning", ""),
|
("uac_warning", ""),
|
||||||
("elevated_foreground_window_warning", ""),
|
("elevated_foreground_window_warning", ""),
|
||||||
|
("Disconnected", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -366,5 +366,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("elevation_prompt", "以當前用戶權限運行軟件,可能導致遠端在訪問本機時,沒有足夠的權限來操作部分窗口。"),
|
("elevation_prompt", "以當前用戶權限運行軟件,可能導致遠端在訪問本機時,沒有足夠的權限來操作部分窗口。"),
|
||||||
("uac_warning", "暂时无法访问远端设备,因为远端设备正在请求用户账户权限,请等待对方关闭UAC窗口。为避免这个问题,建议在远端设备上安装或者以管理员权限运行本软件。"),
|
("uac_warning", "暂时无法访问远端设备,因为远端设备正在请求用户账户权限,请等待对方关闭UAC窗口。为避免这个问题,建议在远端设备上安装或者以管理员权限运行本软件。"),
|
||||||
("elevated_foreground_window_warning", "暫時無法使用鼠標鍵盤,因為遠端桌面的當前窗口需要更高的權限才能操作, 可以請求對方最小化當前窗口。為避免這個問題,建議在遠端設備上安裝或者以管理員權限運行本軟件。"),
|
("elevated_foreground_window_warning", "暫時無法使用鼠標鍵盤,因為遠端桌面的當前窗口需要更高的權限才能操作, 可以請求對方最小化當前窗口。為避免這個問題,建議在遠端設備上安裝或者以管理員權限運行本軟件。"),
|
||||||
|
("Disconnected", "會話已結束"),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -362,5 +362,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Enable LAN Discovery", "Увімкнути пошук локальної мережі"),
|
("Enable LAN Discovery", "Увімкнути пошук локальної мережі"),
|
||||||
("Deny LAN Discovery", "Заборонити виявлення локальної мережі"),
|
("Deny LAN Discovery", "Заборонити виявлення локальної мережі"),
|
||||||
("Write a message", "Написати повідомлення"),
|
("Write a message", "Написати повідомлення"),
|
||||||
|
("Prompt", ""),
|
||||||
|
("elevation_prompt", ""),
|
||||||
|
("uac_warning", ""),
|
||||||
|
("elevated_foreground_window_warning", ""),
|
||||||
|
("Disconnected", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -366,5 +366,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("elevation_prompt", ""),
|
("elevation_prompt", ""),
|
||||||
("uac_warning", ""),
|
("uac_warning", ""),
|
||||||
("elevated_foreground_window_warning", ""),
|
("elevated_foreground_window_warning", ""),
|
||||||
|
("Disconnected", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -95,6 +95,8 @@ pub struct Connection {
|
|||||||
api_server: String,
|
api_server: String,
|
||||||
lr: LoginRequest,
|
lr: LoginRequest,
|
||||||
last_recv_time: Arc<Mutex<Instant>>,
|
last_recv_time: Arc<Mutex<Instant>>,
|
||||||
|
chat_unanswered: bool,
|
||||||
|
close_manually: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Subscriber for ConnInner {
|
impl Subscriber for ConnInner {
|
||||||
@ -184,6 +186,8 @@ impl Connection {
|
|||||||
api_server: "".to_owned(),
|
api_server: "".to_owned(),
|
||||||
lr: Default::default(),
|
lr: Default::default(),
|
||||||
last_recv_time: Arc::new(Mutex::new(Instant::now())),
|
last_recv_time: Arc::new(Mutex::new(Instant::now())),
|
||||||
|
chat_unanswered: false,
|
||||||
|
close_manually: false,
|
||||||
};
|
};
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
@ -246,6 +250,7 @@ impl Connection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ipc::Data::Close => {
|
ipc::Data::Close => {
|
||||||
|
conn.close_manually = true;
|
||||||
let mut misc = Misc::new();
|
let mut misc = Misc::new();
|
||||||
misc.set_close_reason("Closed manually by the peer".into());
|
misc.set_close_reason("Closed manually by the peer".into());
|
||||||
let mut msg_out = Message::new();
|
let mut msg_out = Message::new();
|
||||||
@ -264,6 +269,7 @@ impl Connection {
|
|||||||
let mut msg_out = Message::new();
|
let mut msg_out = Message::new();
|
||||||
msg_out.set_misc(misc);
|
msg_out.set_misc(misc);
|
||||||
conn.send(msg_out).await;
|
conn.send(msg_out).await;
|
||||||
|
conn.chat_unanswered = false;
|
||||||
}
|
}
|
||||||
ipc::Data::SwitchPermission{name, enabled} => {
|
ipc::Data::SwitchPermission{name, enabled} => {
|
||||||
log::info!("Change permission {} -> {}", name, enabled);
|
log::info!("Change permission {} -> {}", name, enabled);
|
||||||
@ -1245,6 +1251,7 @@ impl Connection {
|
|||||||
}
|
}
|
||||||
Some(misc::Union::ChatMessage(c)) => {
|
Some(misc::Union::ChatMessage(c)) => {
|
||||||
self.send_to_cm(ipc::Data::ChatMessage { text: c.text });
|
self.send_to_cm(ipc::Data::ChatMessage { text: c.text });
|
||||||
|
self.chat_unanswered = true;
|
||||||
}
|
}
|
||||||
Some(misc::Union::Option(o)) => {
|
Some(misc::Union::Option(o)) => {
|
||||||
self.update_option(&o).await;
|
self.update_option(&o).await;
|
||||||
@ -1445,7 +1452,15 @@ impl Connection {
|
|||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
lock_screen().await;
|
lock_screen().await;
|
||||||
}
|
}
|
||||||
self.tx_to_cm.send(ipc::Data::Close).ok();
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
|
let data = if self.chat_unanswered && !self.close_manually {
|
||||||
|
ipc::Data::Disconnected
|
||||||
|
} else {
|
||||||
|
ipc::Data::Close
|
||||||
|
};
|
||||||
|
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||||
|
let data = ipc::Data::Close;
|
||||||
|
self.tx_to_cm.send(data).ok();
|
||||||
self.port_forward_socket.take();
|
self.port_forward_socket.take();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
14
src/ui/cm.rs
14
src/ui/cm.rs
@ -38,8 +38,8 @@ impl InvokeUiCM for SciterHandler {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_connection(&self, id: i32) {
|
fn remove_connection(&self, id: i32, close: bool) {
|
||||||
self.call("removeConnection", &make_args!(id));
|
self.call("removeConnection", &make_args!(id, close));
|
||||||
if crate::ui_cm_interface::get_clients_length().eq(&0) {
|
if crate::ui_cm_interface::get_clients_length().eq(&0) {
|
||||||
crate::platform::quit_gui();
|
crate::platform::quit_gui();
|
||||||
}
|
}
|
||||||
@ -109,6 +109,14 @@ impl SciterConnectionManager {
|
|||||||
crate::ui_cm_interface::close(id);
|
crate::ui_cm_interface::close(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn remove_disconnected_connection(&self, id: i32) {
|
||||||
|
crate::ui_cm_interface::remove(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn quit(&self) {
|
||||||
|
crate::platform::quit_gui();
|
||||||
|
}
|
||||||
|
|
||||||
fn authorize(&self, id: i32) {
|
fn authorize(&self, id: i32) {
|
||||||
crate::ui_cm_interface::authorize(id);
|
crate::ui_cm_interface::authorize(id);
|
||||||
}
|
}
|
||||||
@ -133,6 +141,8 @@ impl sciter::EventHandler for SciterConnectionManager {
|
|||||||
fn get_click_time();
|
fn get_click_time();
|
||||||
fn get_icon();
|
fn get_icon();
|
||||||
fn close(i32);
|
fn close(i32);
|
||||||
|
fn remove_disconnected_connection(i32);
|
||||||
|
fn quit();
|
||||||
fn authorize(i32);
|
fn authorize(i32);
|
||||||
fn switch_permission(i32, String, bool);
|
fn switch_permission(i32, String, bool);
|
||||||
fn send_msg(i32, String);
|
fn send_msg(i32, String);
|
||||||
|
@ -26,6 +26,7 @@ class Body: Reactor.Component
|
|||||||
me.sendMsg(msg);
|
me.sendMsg(msg);
|
||||||
};
|
};
|
||||||
var right_style = show_chat ? "" : "display: none";
|
var right_style = show_chat ? "" : "display: none";
|
||||||
|
var disconnected = c.disconnected;
|
||||||
// below size:* is work around for Linux, it alreayd set in css, but not work, shit sciter
|
// below size:* is work around for Linux, it alreayd set in css, but not work, shit sciter
|
||||||
return <div .content style="size:*">
|
return <div .content style="size:*">
|
||||||
<div .left-panel>
|
<div .left-panel>
|
||||||
@ -36,12 +37,12 @@ class Body: Reactor.Component
|
|||||||
<div>
|
<div>
|
||||||
<div .id style="font-weight: bold; font-size: 1.2em;">{c.name}</div>
|
<div .id style="font-weight: bold; font-size: 1.2em;">{c.name}</div>
|
||||||
<div .id>({c.peer_id})</div>
|
<div .id>({c.peer_id})</div>
|
||||||
<div style="margin-top: 1.2em">{translate('Connected')} {" "} <span #time>{getElaspsed(c.time)}</span></div>
|
<div style="margin-top: 1.2em">{disconnected ? translate('Disconnected') : translate('Connected')} {" "} <span #time>{getElaspsed(c.time, c.now)}</span></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div />
|
<div />
|
||||||
{c.is_file_transfer || c.port_forward ? "" : <div>{translate('Permissions')}</div>}
|
{c.is_file_transfer || c.port_forward || disconnected ? "" : <div>{translate('Permissions')}</div>}
|
||||||
{c.is_file_transfer || c.port_forward ? "" : <div> <div .permissions>
|
{c.is_file_transfer || c.port_forward || disconnected ? "" : <div> <div .permissions>
|
||||||
<div class={!c.keyboard ? "disabled" : ""} title={translate('Allow using keyboard and mouse')}><icon .keyboard /></div>
|
<div class={!c.keyboard ? "disabled" : ""} title={translate('Allow using keyboard and mouse')}><icon .keyboard /></div>
|
||||||
<div class={!c.clipboard ? "disabled" : ""} title={translate('Allow using clipboard')}><icon .clipboard /></div>
|
<div class={!c.clipboard ? "disabled" : ""} title={translate('Allow using clipboard')}><icon .clipboard /></div>
|
||||||
<div class={!c.audio ? "disabled" : ""} title={translate('Allow hearing sound')}><icon .audio /></div>
|
<div class={!c.audio ? "disabled" : ""} title={translate('Allow hearing sound')}><icon .audio /></div>
|
||||||
@ -56,7 +57,8 @@ class Body: Reactor.Component
|
|||||||
<div .buttons>
|
<div .buttons>
|
||||||
{auth ? "" : <button .button tabindex="-1" #accept>{translate('Accept')}</button>}
|
{auth ? "" : <button .button tabindex="-1" #accept>{translate('Accept')}</button>}
|
||||||
{auth ? "" : <button .button tabindex="-1" .outline #dismiss>{translate('Dismiss')}</button>}
|
{auth ? "" : <button .button tabindex="-1" .outline #dismiss>{translate('Dismiss')}</button>}
|
||||||
{auth ? <button .button tabindex="-1" #disconnect>{translate('Disconnect')}</button> : ""}
|
{auth && !disconnected ? <button .button tabindex="-1" #disconnect>{translate('Disconnect')}</button> : ""}
|
||||||
|
{auth && disconnected ? <button .button tabindex="-1" #close>{translate('Close')}</button> : ""}
|
||||||
</div>
|
</div>
|
||||||
{c.is_file_transfer || c.port_forward ? "" : <div .chaticon>{svg_chat}</div>}
|
{c.is_file_transfer || c.port_forward ? "" : <div .chaticon>{svg_chat}</div>}
|
||||||
</div>
|
</div>
|
||||||
@ -155,6 +157,25 @@ class Body: Reactor.Component
|
|||||||
handler.close(cid);
|
handler.close(cid);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
event click $(button#close) {
|
||||||
|
var cid = this.cid;
|
||||||
|
if (this.cur >= 0 && this.cur < connections.length){
|
||||||
|
handler.remove_disconnected_connection(cid);
|
||||||
|
connections.splice(this.cur, 1);
|
||||||
|
if (connections.length > 0) {
|
||||||
|
if (this.cur > 0)
|
||||||
|
this.cur -= 1;
|
||||||
|
else
|
||||||
|
this.cur = connections.length - 1;
|
||||||
|
header.update();
|
||||||
|
body.update();
|
||||||
|
} else {
|
||||||
|
handler.quit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$(body).content(<Body />);
|
$(body).content(<Body />);
|
||||||
@ -299,15 +320,26 @@ handler.addConnection = function(id, is_file_transfer, port_forward, peer_id, na
|
|||||||
update();
|
update();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
var idx = -1;
|
||||||
|
connections.map(function(c, i) {
|
||||||
|
if (c.disconnected && c.peer_id == peer_id) idx = i;
|
||||||
|
});
|
||||||
if (!name) name = "NA";
|
if (!name) name = "NA";
|
||||||
connections.push({
|
conn = {
|
||||||
id: id, is_file_transfer: is_file_transfer, peer_id: peer_id,
|
id: id, is_file_transfer: is_file_transfer, peer_id: peer_id,
|
||||||
port_forward: port_forward,
|
port_forward: port_forward,
|
||||||
name: name, authorized: authorized, time: new Date(),
|
name: name, authorized: authorized, time: new Date(), now: new Date(),
|
||||||
keyboard: keyboard, clipboard: clipboard, msgs: [], unreaded: 0,
|
keyboard: keyboard, clipboard: clipboard, msgs: [], unreaded: 0,
|
||||||
audio: audio, file: file, restart: restart, recording: recording
|
audio: audio, file: file, restart: restart, recording: recording,
|
||||||
});
|
disconnected: false
|
||||||
body.cur = connections.length - 1;
|
};
|
||||||
|
if (idx < 0) {
|
||||||
|
connections.push(conn);
|
||||||
|
body.cur = connections.length - 1;
|
||||||
|
} else {
|
||||||
|
connections[idx] = conn;
|
||||||
|
body.cur = idx;
|
||||||
|
}
|
||||||
bring_to_top();
|
bring_to_top();
|
||||||
update();
|
update();
|
||||||
self.timer(1ms, adjustHeader);
|
self.timer(1ms, adjustHeader);
|
||||||
@ -318,15 +350,20 @@ handler.addConnection = function(id, is_file_transfer, port_forward, peer_id, na
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handler.removeConnection = function(id) {
|
handler.removeConnection = function(id, close) {
|
||||||
var i = -1;
|
var i = -1;
|
||||||
connections.map(function(c, idx) {
|
connections.map(function(c, idx) {
|
||||||
if (c.id == id) i = idx;
|
if (c.id == id) i = idx;
|
||||||
});
|
});
|
||||||
if (i < 0) return;
|
if (i < 0) return;
|
||||||
connections.splice(i, 1);
|
if (close) {
|
||||||
|
connections.splice(i, 1);
|
||||||
|
} else {
|
||||||
|
var conn = connections[i];
|
||||||
|
conn.disconnected = true;
|
||||||
|
}
|
||||||
if (connections.length > 0) {
|
if (connections.length > 0) {
|
||||||
if (body.cur >= i && body.cur > 0) body.cur -= 1;
|
if (body.cur >= i && body.cur > 0 && close) body.cur -= 1;
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -361,8 +398,7 @@ function self.ready() {
|
|||||||
view.move(sw - w, 0, w, h);
|
view.move(sw - w, 0, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getElaspsed(time) {
|
function getElaspsed(time, now) {
|
||||||
var now = new Date();
|
|
||||||
var seconds = Date.diff(time, now, #seconds);
|
var seconds = Date.diff(time, now, #seconds);
|
||||||
var hours = seconds / 3600;
|
var hours = seconds / 3600;
|
||||||
var days = hours / 24;
|
var days = hours / 24;
|
||||||
@ -378,11 +414,15 @@ function getElaspsed(time) {
|
|||||||
|
|
||||||
function updateTime() {
|
function updateTime() {
|
||||||
self.timer(1s, function() {
|
self.timer(1s, function() {
|
||||||
|
var now = new Date();
|
||||||
|
connections.map(function(c) {
|
||||||
|
if (!c.disconnected) c.now = now;
|
||||||
|
});
|
||||||
var el = $(#time);
|
var el = $(#time);
|
||||||
if (el) {
|
if (el) {
|
||||||
var c = connections[body.cur];
|
var c = connections[body.cur];
|
||||||
if (c) {
|
if (c && !c.disconnected) {
|
||||||
el.text = getElaspsed(c.time);
|
el.text = getElaspsed(c.time, c.now);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateTime();
|
updateTime();
|
||||||
|
@ -31,6 +31,7 @@ use hbb_common::{
|
|||||||
pub struct Client {
|
pub struct Client {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub authorized: bool,
|
pub authorized: bool,
|
||||||
|
pub disconnected: bool,
|
||||||
pub is_file_transfer: bool,
|
pub is_file_transfer: bool,
|
||||||
pub port_forward: String,
|
pub port_forward: String,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
@ -58,7 +59,7 @@ pub struct ConnectionManager<T: InvokeUiCM> {
|
|||||||
pub trait InvokeUiCM: Send + Clone + 'static + Sized {
|
pub trait InvokeUiCM: Send + Clone + 'static + Sized {
|
||||||
fn add_connection(&self, client: &Client);
|
fn add_connection(&self, client: &Client);
|
||||||
|
|
||||||
fn remove_connection(&self, id: i32);
|
fn remove_connection(&self, id: i32, close: bool);
|
||||||
|
|
||||||
fn new_message(&self, id: i32, text: String);
|
fn new_message(&self, id: i32, text: String);
|
||||||
|
|
||||||
@ -101,6 +102,7 @@ impl<T: InvokeUiCM> ConnectionManager<T> {
|
|||||||
let client = Client {
|
let client = Client {
|
||||||
id,
|
id,
|
||||||
authorized,
|
authorized,
|
||||||
|
disconnected: false,
|
||||||
is_file_transfer,
|
is_file_transfer,
|
||||||
port_forward,
|
port_forward,
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
@ -113,12 +115,24 @@ impl<T: InvokeUiCM> ConnectionManager<T> {
|
|||||||
recording,
|
recording,
|
||||||
tx,
|
tx,
|
||||||
};
|
};
|
||||||
|
CLIENTS
|
||||||
|
.write()
|
||||||
|
.unwrap()
|
||||||
|
.retain(|_, c| !(c.disconnected && c.peer_id == client.peer_id));
|
||||||
|
CLIENTS.write().unwrap().insert(id, client.clone());
|
||||||
self.ui_handler.add_connection(&client);
|
self.ui_handler.add_connection(&client);
|
||||||
CLIENTS.write().unwrap().insert(id, client);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_connection(&self, id: i32) {
|
fn remove_connection(&self, id: i32, close: bool) {
|
||||||
CLIENTS.write().unwrap().remove(&id);
|
if close {
|
||||||
|
CLIENTS.write().unwrap().remove(&id);
|
||||||
|
} else {
|
||||||
|
CLIENTS
|
||||||
|
.write()
|
||||||
|
.unwrap()
|
||||||
|
.get_mut(&id)
|
||||||
|
.map(|c| c.disconnected = true);
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(target_os = "android"))]
|
#[cfg(any(target_os = "android"))]
|
||||||
if CLIENTS
|
if CLIENTS
|
||||||
@ -136,7 +150,7 @@ impl<T: InvokeUiCM> ConnectionManager<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.ui_handler.remove_connection(id);
|
self.ui_handler.remove_connection(id, close);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,6 +181,11 @@ pub fn close(id: i32) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn remove(id: i32) {
|
||||||
|
CLIENTS.write().unwrap().remove(&id);
|
||||||
|
}
|
||||||
|
|
||||||
// server mode send chat to peer
|
// server mode send chat to peer
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn send_chat(id: i32, text: String) {
|
pub fn send_chat(id: i32, text: String) {
|
||||||
@ -243,6 +262,7 @@ pub async fn start_ipc<T: InvokeUiCM>(cm: ConnectionManager<T>) {
|
|||||||
let mut conn_id: i32 = 0;
|
let mut conn_id: i32 = 0;
|
||||||
let (tx, mut rx) = mpsc::unbounded_channel::<Data>();
|
let (tx, mut rx) = mpsc::unbounded_channel::<Data>();
|
||||||
let mut write_jobs: Vec<fs::TransferJob> = Vec::new();
|
let mut write_jobs: Vec<fs::TransferJob> = Vec::new();
|
||||||
|
let mut close = true;
|
||||||
loop {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
res = stream.next() => {
|
res = stream.next() => {
|
||||||
@ -264,6 +284,12 @@ pub async fn start_ipc<T: InvokeUiCM>(cm: ConnectionManager<T>) {
|
|||||||
log::info!("cm ipc connection closed from connection request");
|
log::info!("cm ipc connection closed from connection request");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Data::Disconnected => {
|
||||||
|
close = false;
|
||||||
|
tx_file.send(ClipboardFileData::Enable((conn_id, false))).ok();
|
||||||
|
log::info!("cm ipc connection disconnect");
|
||||||
|
break;
|
||||||
|
}
|
||||||
Data::PrivacyModeState((id, _)) => {
|
Data::PrivacyModeState((id, _)) => {
|
||||||
conn_id = conn_id_tmp;
|
conn_id = conn_id_tmp;
|
||||||
allow_err!(tx.send(data));
|
allow_err!(tx.send(data));
|
||||||
@ -312,7 +338,7 @@ pub async fn start_ipc<T: InvokeUiCM>(cm: ConnectionManager<T>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if conn_id != conn_id_tmp {
|
if conn_id != conn_id_tmp {
|
||||||
cm.remove_connection(conn_id);
|
cm.remove_connection(conn_id, close);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user