flutter: file-transfer/port forward/rdp support
Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
parent
6c8c3b4a7a
commit
1f137b3542
@ -1547,7 +1547,7 @@ Future<bool> initUniLinks() async {
|
|||||||
if (initialLink == null) {
|
if (initialLink == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return parseRustdeskUri(initialLink);
|
return handleUriLink(uriString: initialLink);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
debugPrintStack(label: "$err");
|
debugPrintStack(label: "$err");
|
||||||
return false;
|
return false;
|
||||||
@ -1568,7 +1568,7 @@ StreamSubscription? listenUniLinks({handleByFlutter = true}) {
|
|||||||
debugPrint("A uri was received: $uri.");
|
debugPrint("A uri was received: $uri.");
|
||||||
if (uri != null) {
|
if (uri != null) {
|
||||||
if (handleByFlutter) {
|
if (handleByFlutter) {
|
||||||
callUniLinksUriHandler(uri);
|
handleUriLink(uri: uri);
|
||||||
} else {
|
} else {
|
||||||
bind.sendUrlScheme(url: uri.toString());
|
bind.sendUrlScheme(url: uri.toString());
|
||||||
}
|
}
|
||||||
@ -1581,90 +1581,142 @@ StreamSubscription? listenUniLinks({handleByFlutter = true}) {
|
|||||||
return sub;
|
return sub;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handle command line arguments
|
enum UriLinkType {
|
||||||
///
|
remoteDesktop,
|
||||||
/// * Returns true if we successfully handle the startup arguments.
|
fileTransfer,
|
||||||
bool checkArguments() {
|
portForward,
|
||||||
if (kBootArgs.isNotEmpty) {
|
rdp,
|
||||||
final ret = parseRustdeskUri(kBootArgs.first);
|
}
|
||||||
if (ret) {
|
|
||||||
return true;
|
// uri link handler
|
||||||
|
bool handleUriLink({List<String>? cmdArgs, Uri? uri, String? uriString}) {
|
||||||
|
List<String>? args;
|
||||||
|
if (cmdArgs != null) {
|
||||||
|
args = cmdArgs;
|
||||||
|
if (args.isNotEmpty && args[0].startsWith(kUniLinksPrefix)) {
|
||||||
|
final uri = Uri.tryParse(args[0]);
|
||||||
|
if (uri != null) {
|
||||||
|
args = urlLinkToCmdArgs(uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (uri != null) {
|
||||||
|
args = urlLinkToCmdArgs(uri);
|
||||||
|
} else if (uriString != null) {
|
||||||
|
final uri = Uri.tryParse(uriString);
|
||||||
|
if (uri != null) {
|
||||||
|
args = urlLinkToCmdArgs(uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// bootArgs:[--connect, 362587269, --switch_uuid, e3d531cc-5dce-41e0-bd06-5d4a2b1eec05]
|
if (args == null) return false;
|
||||||
// check connect args
|
|
||||||
var connectIndex = kBootArgs.indexOf("--connect");
|
UriLinkType? type;
|
||||||
if (connectIndex == -1) {
|
String? id;
|
||||||
return false;
|
String? password;
|
||||||
}
|
String? switchUuid;
|
||||||
String? id =
|
bool? forceRelay;
|
||||||
kBootArgs.length <= connectIndex + 1 ? null : kBootArgs[connectIndex + 1];
|
for (int i = 0; i < args.length; i++) {
|
||||||
String? password =
|
switch (args[i]) {
|
||||||
kBootArgs.length <= connectIndex + 2 ? null : kBootArgs[connectIndex + 2];
|
case '--connect':
|
||||||
if (password != null && password.startsWith("--")) {
|
case '--play':
|
||||||
password = null;
|
type = UriLinkType.remoteDesktop;
|
||||||
}
|
id = args[i + 1];
|
||||||
final switchUuidIndex = kBootArgs.indexOf("--switch_uuid");
|
i++;
|
||||||
String? switchUuid = kBootArgs.length <= switchUuidIndex + 1
|
break;
|
||||||
? null
|
case '--file-transfer':
|
||||||
: kBootArgs[switchUuidIndex + 1];
|
type = UriLinkType.fileTransfer;
|
||||||
if (id != null) {
|
id = args[i + 1];
|
||||||
if (id.startsWith(kUniLinksPrefix)) {
|
i++;
|
||||||
return parseRustdeskUri(id);
|
break;
|
||||||
} else {
|
case '--port-forward':
|
||||||
// remove "--connect xxx" in the `bootArgs` array
|
type = UriLinkType.portForward;
|
||||||
kBootArgs.removeAt(connectIndex);
|
id = args[i + 1];
|
||||||
kBootArgs.removeAt(connectIndex);
|
i++;
|
||||||
// fallback to peer id
|
break;
|
||||||
Future.delayed(Duration.zero, () {
|
case '--rdp':
|
||||||
rustDeskWinManager.newRemoteDesktop(id,
|
type = UriLinkType.rdp;
|
||||||
password: password, switch_uuid: switchUuid);
|
id = args[i + 1];
|
||||||
});
|
i++;
|
||||||
return true;
|
break;
|
||||||
|
case '--password':
|
||||||
|
password = args[i + 1];
|
||||||
|
i++;
|
||||||
|
break;
|
||||||
|
case '--switch_uuid':
|
||||||
|
switchUuid = args[i + 1];
|
||||||
|
i++;
|
||||||
|
break;
|
||||||
|
case '--relay':
|
||||||
|
forceRelay = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (type != null && id != null) {
|
||||||
|
switch (type) {
|
||||||
|
case UriLinkType.remoteDesktop:
|
||||||
|
Future.delayed(Duration.zero, () {
|
||||||
|
rustDeskWinManager.newRemoteDesktop(id!,
|
||||||
|
password: password,
|
||||||
|
switch_uuid: switchUuid,
|
||||||
|
forceRelay: forceRelay);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case UriLinkType.fileTransfer:
|
||||||
|
Future.delayed(Duration.zero, () {
|
||||||
|
rustDeskWinManager.newFileTransfer(id!,
|
||||||
|
password: password, forceRelay: forceRelay);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case UriLinkType.portForward:
|
||||||
|
Future.delayed(Duration.zero, () {
|
||||||
|
rustDeskWinManager.newPortForward(id!, false,
|
||||||
|
password: password, forceRelay: forceRelay);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case UriLinkType.rdp:
|
||||||
|
Future.delayed(Duration.zero, () {
|
||||||
|
rustDeskWinManager.newPortForward(id!, true,
|
||||||
|
password: password, forceRelay: forceRelay);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse `rustdesk://` unilinks
|
List<String>? urlLinkToCmdArgs(Uri uri) {
|
||||||
///
|
String? command;
|
||||||
/// Returns true if we successfully handle the uri provided.
|
String? id;
|
||||||
/// [Functions]
|
|
||||||
/// 1. New Connection: rustdesk://connection/new/your_peer_id
|
|
||||||
bool parseRustdeskUri(String uriPath) {
|
|
||||||
final uri = Uri.tryParse(uriPath);
|
|
||||||
if (uri == null) {
|
|
||||||
debugPrint("uri is not valid: $uriPath");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return callUniLinksUriHandler(uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// uri handler
|
|
||||||
///
|
|
||||||
/// Returns true if we successfully handle the uri provided.
|
|
||||||
bool callUniLinksUriHandler(Uri uri) {
|
|
||||||
debugPrint("uni links called: $uri");
|
|
||||||
// new connection
|
|
||||||
String peerId;
|
|
||||||
if (uri.authority == "connection" && uri.path.startsWith("/new/")) {
|
if (uri.authority == "connection" && uri.path.startsWith("/new/")) {
|
||||||
peerId = uri.path.substring("/new/".length);
|
// For compatibility
|
||||||
} else if (uri.authority == "connect") {
|
command = '--connect';
|
||||||
peerId = uri.path.substring(1);
|
id = uri.path.substring("/new/".length);
|
||||||
} else if (uri.authority.length > 2 && uri.path.length <= 1) {
|
} else if (['connect', "play", 'file-transfer', 'port-forward', 'rdp']
|
||||||
// "/" or ""
|
.contains(uri.authority)) {
|
||||||
peerId = uri.authority;
|
command = '--${uri.authority}';
|
||||||
} else {
|
if (uri.path.length > 1) {
|
||||||
return false;
|
id = uri.path.substring(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var param = uri.queryParameters;
|
|
||||||
String? switch_uuid = param["switch_uuid"];
|
List<String> args = List.empty(growable: true);
|
||||||
String? password = param["password"];
|
if (command != null && id != null) {
|
||||||
Future.delayed(Duration.zero, () {
|
args.add(command);
|
||||||
rustDeskWinManager.newRemoteDesktop(peerId,
|
args.add(id);
|
||||||
password: password, switch_uuid: switch_uuid);
|
var param = uri.queryParameters;
|
||||||
});
|
String? password = param["password"];
|
||||||
return true;
|
if (password != null) args.addAll(['--password', password]);
|
||||||
|
String? switch_uuid = param["switch_uuid"];
|
||||||
|
if (switch_uuid != null) args.addAll(['--switch_uuid', switch_uuid]);
|
||||||
|
if (param["relay"] != null) args.add("--relay");
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
connectMainDesktop(String id,
|
connectMainDesktop(String id,
|
||||||
|
@ -52,10 +52,12 @@ class FileManagerPage extends StatefulWidget {
|
|||||||
const FileManagerPage(
|
const FileManagerPage(
|
||||||
{Key? key,
|
{Key? key,
|
||||||
required this.id,
|
required this.id,
|
||||||
|
required this.password,
|
||||||
required this.tabController,
|
required this.tabController,
|
||||||
this.forceRelay})
|
this.forceRelay})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
final String id;
|
final String id;
|
||||||
|
final String? password;
|
||||||
final bool? forceRelay;
|
final bool? forceRelay;
|
||||||
final DesktopTabController tabController;
|
final DesktopTabController tabController;
|
||||||
|
|
||||||
@ -79,7 +81,10 @@ class _FileManagerPageState extends State<FileManagerPage>
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_ffi = FFI();
|
_ffi = FFI();
|
||||||
_ffi.start(widget.id, isFileTransfer: true, forceRelay: widget.forceRelay);
|
_ffi.start(widget.id,
|
||||||
|
isFileTransfer: true,
|
||||||
|
password: widget.password,
|
||||||
|
forceRelay: widget.forceRelay);
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
_ffi.dialogManager
|
_ffi.dialogManager
|
||||||
.showLoading(translate('Connecting...'), onCancel: closeConnection);
|
.showLoading(translate('Connecting...'), onCancel: closeConnection);
|
||||||
|
@ -44,6 +44,7 @@ class _FileManagerTabPageState extends State<FileManagerTabPage> {
|
|||||||
page: FileManagerPage(
|
page: FileManagerPage(
|
||||||
key: ValueKey(params['id']),
|
key: ValueKey(params['id']),
|
||||||
id: params['id'],
|
id: params['id'],
|
||||||
|
password: params['password'],
|
||||||
tabController: tabController,
|
tabController: tabController,
|
||||||
forceRelay: params['forceRelay'],
|
forceRelay: params['forceRelay'],
|
||||||
)));
|
)));
|
||||||
@ -72,6 +73,7 @@ class _FileManagerTabPageState extends State<FileManagerTabPage> {
|
|||||||
page: FileManagerPage(
|
page: FileManagerPage(
|
||||||
key: ValueKey(id),
|
key: ValueKey(id),
|
||||||
id: id,
|
id: id,
|
||||||
|
password: args['password'],
|
||||||
tabController: tabController,
|
tabController: tabController,
|
||||||
forceRelay: args['forceRelay'],
|
forceRelay: args['forceRelay'],
|
||||||
)));
|
)));
|
||||||
|
@ -28,11 +28,13 @@ class PortForwardPage extends StatefulWidget {
|
|||||||
const PortForwardPage(
|
const PortForwardPage(
|
||||||
{Key? key,
|
{Key? key,
|
||||||
required this.id,
|
required this.id,
|
||||||
|
required this.password,
|
||||||
required this.tabController,
|
required this.tabController,
|
||||||
required this.isRDP,
|
required this.isRDP,
|
||||||
this.forceRelay})
|
this.forceRelay})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
final String id;
|
final String id;
|
||||||
|
final String password;
|
||||||
final DesktopTabController tabController;
|
final DesktopTabController tabController;
|
||||||
final bool isRDP;
|
final bool isRDP;
|
||||||
final bool? forceRelay;
|
final bool? forceRelay;
|
||||||
@ -55,6 +57,7 @@ class _PortForwardPageState extends State<PortForwardPage>
|
|||||||
_ffi = FFI();
|
_ffi = FFI();
|
||||||
_ffi.start(widget.id,
|
_ffi.start(widget.id,
|
||||||
isPortForward: true,
|
isPortForward: true,
|
||||||
|
password: widget.password,
|
||||||
forceRelay: widget.forceRelay,
|
forceRelay: widget.forceRelay,
|
||||||
isRdp: widget.isRDP);
|
isRdp: widget.isRDP);
|
||||||
Get.put(_ffi, tag: 'pf_${widget.id}');
|
Get.put(_ffi, tag: 'pf_${widget.id}');
|
||||||
|
@ -43,6 +43,7 @@ class _PortForwardTabPageState extends State<PortForwardTabPage> {
|
|||||||
page: PortForwardPage(
|
page: PortForwardPage(
|
||||||
key: ValueKey(params['id']),
|
key: ValueKey(params['id']),
|
||||||
id: params['id'],
|
id: params['id'],
|
||||||
|
password: params['password'],
|
||||||
tabController: tabController,
|
tabController: tabController,
|
||||||
isRDP: isRDP,
|
isRDP: isRDP,
|
||||||
forceRelay: params['forceRelay'],
|
forceRelay: params['forceRelay'],
|
||||||
@ -77,6 +78,7 @@ class _PortForwardTabPageState extends State<PortForwardTabPage> {
|
|||||||
page: PortForwardPage(
|
page: PortForwardPage(
|
||||||
key: ValueKey(args['id']),
|
key: ValueKey(args['id']),
|
||||||
id: id,
|
id: id,
|
||||||
|
password: args['password'],
|
||||||
isRDP: isRDP,
|
isRDP: isRDP,
|
||||||
tabController: tabController,
|
tabController: tabController,
|
||||||
forceRelay: args['forceRelay'],
|
forceRelay: args['forceRelay'],
|
||||||
|
@ -134,7 +134,7 @@ void runMainApp(bool startService) async {
|
|||||||
// Check the startup argument, if we successfully handle the argument, we keep the main window hidden.
|
// Check the startup argument, if we successfully handle the argument, we keep the main window hidden.
|
||||||
final handledByUniLinks = await initUniLinks();
|
final handledByUniLinks = await initUniLinks();
|
||||||
debugPrint("handled by uni links: $handledByUniLinks");
|
debugPrint("handled by uni links: $handledByUniLinks");
|
||||||
if (handledByUniLinks || checkArguments()) {
|
if (handledByUniLinks || handleUriLink(cmdArgs: kBootArgs)) {
|
||||||
windowManager.hide();
|
windowManager.hide();
|
||||||
} else {
|
} else {
|
||||||
windowManager.show();
|
windowManager.show();
|
||||||
|
@ -248,7 +248,7 @@ class FfiModel with ChangeNotifier {
|
|||||||
|
|
||||||
onUrlSchemeReceived(Map<String, dynamic> evt) {
|
onUrlSchemeReceived(Map<String, dynamic> evt) {
|
||||||
final url = evt['url'].toString().trim();
|
final url = evt['url'].toString().trim();
|
||||||
if (url.startsWith(kUniLinksPrefix) && parseRustdeskUri(url)) {
|
if (url.startsWith(kUniLinksPrefix) && handleUriLink(uriString: url)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (url) {
|
switch (url) {
|
||||||
|
@ -84,10 +84,12 @@ class RustDeskMultiWindowManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<dynamic> newFileTransfer(String remoteId, {bool? forceRelay}) async {
|
Future<dynamic> newFileTransfer(String remoteId,
|
||||||
|
{String? password, bool? forceRelay}) async {
|
||||||
var msg = jsonEncode({
|
var msg = jsonEncode({
|
||||||
"type": WindowType.FileTransfer.index,
|
"type": WindowType.FileTransfer.index,
|
||||||
"id": remoteId,
|
"id": remoteId,
|
||||||
|
"password": password,
|
||||||
"forceRelay": forceRelay,
|
"forceRelay": forceRelay,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -117,11 +119,12 @@ class RustDeskMultiWindowManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<dynamic> newPortForward(String remoteId, bool isRDP,
|
Future<dynamic> newPortForward(String remoteId, bool isRDP,
|
||||||
{bool? forceRelay}) async {
|
{String? password, bool? forceRelay}) async {
|
||||||
final msg = jsonEncode({
|
final msg = jsonEncode({
|
||||||
"type": WindowType.PortForward.index,
|
"type": WindowType.PortForward.index,
|
||||||
"id": remoteId,
|
"id": remoteId,
|
||||||
"isRDP": isRDP,
|
"isRDP": isRDP,
|
||||||
|
"password": password,
|
||||||
"forceRelay": forceRelay,
|
"forceRelay": forceRelay,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -19,15 +19,23 @@ pub fn core_main() -> Option<Vec<String>> {
|
|||||||
let mut _is_elevate = false;
|
let mut _is_elevate = false;
|
||||||
let mut _is_run_as_system = false;
|
let mut _is_run_as_system = false;
|
||||||
let mut _is_quick_support = false;
|
let mut _is_quick_support = false;
|
||||||
let mut _is_flutter_connect = false;
|
let mut _is_flutter_invoke_new_connection = false;
|
||||||
let mut arg_exe = Default::default();
|
let mut arg_exe = Default::default();
|
||||||
for arg in std::env::args() {
|
for arg in std::env::args() {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
arg_exe = arg;
|
arg_exe = arg;
|
||||||
} else if i > 0 {
|
} else if i > 0 {
|
||||||
#[cfg(feature = "flutter")]
|
#[cfg(feature = "flutter")]
|
||||||
if arg == "--connect" || arg == "--play" {
|
if [
|
||||||
_is_flutter_connect = true;
|
"--connect",
|
||||||
|
"--play",
|
||||||
|
"--file-transfer",
|
||||||
|
"--port-forward",
|
||||||
|
"--rdp",
|
||||||
|
]
|
||||||
|
.contains(&arg.as_str())
|
||||||
|
{
|
||||||
|
_is_flutter_invoke_new_connection = true;
|
||||||
}
|
}
|
||||||
if arg == "--elevate" {
|
if arg == "--elevate" {
|
||||||
_is_elevate = true;
|
_is_elevate = true;
|
||||||
@ -63,7 +71,7 @@ pub fn core_main() -> Option<Vec<String>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(feature = "flutter")]
|
#[cfg(feature = "flutter")]
|
||||||
if _is_flutter_connect {
|
if _is_flutter_invoke_new_connection {
|
||||||
return core_main_invoke_new_connection(std::env::args());
|
return core_main_invoke_new_connection(std::env::args());
|
||||||
}
|
}
|
||||||
let click_setup = cfg!(windows) && args.is_empty() && crate::common::is_setup(&arg_exe);
|
let click_setup = cfg!(windows) && args.is_empty() && crate::common::is_setup(&arg_exe);
|
||||||
@ -318,38 +326,48 @@ fn import_config(path: &str) {
|
|||||||
/// If it returns [`Some`], then the process will continue, and flutter gui will be started.
|
/// If it returns [`Some`], then the process will continue, and flutter gui will be started.
|
||||||
#[cfg(feature = "flutter")]
|
#[cfg(feature = "flutter")]
|
||||||
fn core_main_invoke_new_connection(mut args: std::env::Args) -> Option<Vec<String>> {
|
fn core_main_invoke_new_connection(mut args: std::env::Args) -> Option<Vec<String>> {
|
||||||
args.position(|element| {
|
let mut authority = None;
|
||||||
return element == "--connect" || element == "--play";
|
let mut id = None;
|
||||||
})?;
|
let mut param_array = vec![];
|
||||||
let mut peer_id = args.next().unwrap_or("".to_string());
|
while let Some(arg) = args.next() {
|
||||||
if peer_id.is_empty() {
|
match arg.as_str() {
|
||||||
eprintln!("please provide a valid peer id");
|
"--connect" | "--play" | "--file-transfer" | "--port-forward" | "--rdp" => {
|
||||||
return None;
|
authority = Some((&arg.to_string()[2..]).to_owned());
|
||||||
}
|
id = args.next();
|
||||||
let app_name = crate::get_app_name();
|
}
|
||||||
let ext = format!(".{}", app_name.to_lowercase());
|
"--password" => {
|
||||||
if peer_id.ends_with(&ext) {
|
if let Some(password) = args.next() {
|
||||||
peer_id = peer_id.replace(&ext, "");
|
param_array.push(format!("password={password}"));
|
||||||
}
|
}
|
||||||
let mut switch_uuid = None;
|
}
|
||||||
while let Some(item) = args.next() {
|
"--relay" => {
|
||||||
if item == "--switch_uuid" {
|
param_array.push(format!("relay=true"));
|
||||||
switch_uuid = args.next();
|
}
|
||||||
|
// inner
|
||||||
|
"--switch_uuid" => {
|
||||||
|
if let Some(switch_uuid) = args.next() {
|
||||||
|
param_array.push(format!("switch_uuid={switch_uuid}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut param_array = vec![];
|
let mut uni_links = Default::default();
|
||||||
if switch_uuid.is_some() {
|
if let Some(authority) = authority {
|
||||||
let switch_uuid = switch_uuid.map_or("".to_string(), |p| format!("switch_uuid={}", p));
|
if let Some(mut id) = id {
|
||||||
param_array.push(switch_uuid);
|
let app_name = crate::get_app_name();
|
||||||
|
let ext = format!(".{}", app_name.to_lowercase());
|
||||||
|
if id.ends_with(&ext) {
|
||||||
|
id = id.replace(&ext, "");
|
||||||
|
}
|
||||||
|
let params = param_array.join("&");
|
||||||
|
let params_flag = if params.is_empty() { "" } else { "?" };
|
||||||
|
uni_links = format!("rustdesk://{}/{}{}{}", authority, id, params_flag, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if uni_links.is_empty() {
|
||||||
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let params = param_array.join("&");
|
|
||||||
let params_flag = if params.is_empty() { "" } else { "?" };
|
|
||||||
#[allow(unused)]
|
|
||||||
let uni_links = format!(
|
|
||||||
"rustdesk://connection/new/{}{}{}",
|
|
||||||
peer_id, params_flag, params
|
|
||||||
);
|
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
return try_send_by_dbus(uni_links);
|
return try_send_by_dbus(uni_links);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user