Merge pull request #1788 from 21pages/fix-flutter-upgrade

Fix flutter upgrade
This commit is contained in:
RustDesk 2022-10-24 01:09:13 +08:00 committed by GitHub
commit a2cb295a11
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 417 additions and 476 deletions

View File

@ -2,6 +2,7 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_hbb/common/widgets/address_book.dart';
@ -9,6 +10,7 @@ import 'package:flutter_hbb/consts.dart';
import 'package:flutter_hbb/desktop/widgets/scroll_wrapper.dart';
import 'package:get/get.dart';
import 'package:url_launcher/url_launcher_string.dart';
import 'package:window_manager/window_manager.dart';
import '../../common.dart';
import '../../common/formatter/id_formatter.dart';
@ -27,7 +29,7 @@ class ConnectionPage extends StatefulWidget {
/// State for the connection page.
class _ConnectionPageState extends State<ConnectionPage>
with SingleTickerProviderStateMixin {
with SingleTickerProviderStateMixin, WindowListener {
/// Controller for the id input bar.
final _idController = IDTextEditingController();
@ -43,6 +45,8 @@ class _ConnectionPageState extends State<ConnectionPage>
var svcStatusCode = 0.obs;
var svcIsUsingPublicServer = true.obs;
bool isWindowMinisized = false;
@override
void initState() {
super.initState();
@ -63,6 +67,7 @@ class _ConnectionPageState extends State<ConnectionPage>
_idInputFocused.value = _idFocusNode.hasFocus;
});
Get.put<RxBool>(svcStopped, tag: 'service-stop');
windowManager.addListener(this);
}
@override
@ -70,9 +75,24 @@ class _ConnectionPageState extends State<ConnectionPage>
_idController.dispose();
_updateTimer?.cancel();
Get.delete<RxBool>(tag: 'service-stop');
windowManager.removeListener(this);
super.dispose();
}
@override
void onWindowEvent(String eventName) {
super.onWindowEvent(eventName);
if (eventName == 'minimize') {
isWindowMinisized = true;
} else if (eventName == 'maximize' || eventName == 'restore') {
if (isWindowMinisized && Platform.isWindows) {
// windows can't update when minisized.
Get.forceAppUpdate();
}
isWindowMinisized = false;
}
}
@override
Widget build(BuildContext context) {
return Column(
@ -282,23 +302,34 @@ class _ConnectionPageState extends State<ConnectionPage>
.marginOnly(left: em),
),
// ready && public
Offstage(
offstage: !(!svcStopped.value &&
svcStatusCode.value == 1 &&
svcIsUsingPublicServer.value),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(', ', style: TextStyle(fontSize: em)),
InkWell(
onTap: onUsePublicServerGuide,
child: Text(
translate('setup_server_tip'),
style: TextStyle(
decoration: TextDecoration.underline, fontSize: em),
),
)
],
Flexible(
child: Offstage(
offstage: !(!svcStopped.value &&
svcStatusCode.value == 1 &&
svcIsUsingPublicServer.value),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(', ', style: TextStyle(fontSize: em)),
Flexible(
child: InkWell(
onTap: onUsePublicServerGuide,
child: Row(
children: [
Flexible(
child: Text(
translate('setup_server_tip'),
style: TextStyle(
decoration: TextDecoration.underline,
fontSize: em),
),
),
],
),
),
)
],
),
),
)
],

View File

@ -321,6 +321,7 @@ class _GeneralState extends State<_General> {
...devices.map((device) => _Radio<String>(context,
value: device,
groupValue: currentDevice,
autoNewLine: false,
label: device, onChanged: (value) {
setDevice(value);
setState(() {});
@ -812,11 +813,7 @@ class _NetworkState extends State<_Network> with AutomaticKeepAliveClientMixin {
AbsorbPointer(
absorbing: locked,
child: Column(children: [
_CardRow(title: 'Server', children: [
_Button('ID/Relay Server', changeServer, enabled: enabled),
_Button('Import Server Conf', importServer,
enabled: enabled),
]),
server(enabled),
_Card(title: 'Proxy', children: [
_Button('Socks5 Proxy', changeSocks5Proxy,
enabled: enabled),
@ -825,6 +822,156 @@ class _NetworkState extends State<_Network> with AutomaticKeepAliveClientMixin {
),
]).marginOnly(bottom: _kListViewBottomMargin));
}
server(bool enabled) {
return _futureBuilder(future: () async {
return await bind.mainGetOptions();
}(), hasData: (data) {
// Setting page is not modal, oldOptions should only be used when getting options, never when setting.
Map<String, dynamic> oldOptions = jsonDecode(data! as String);
old(String key) {
return (oldOptions[key] ?? "").trim();
}
RxString idErrMsg = "".obs;
RxString relayErrMsg = "".obs;
RxString apiErrMsg = "".obs;
var idController =
TextEditingController(text: old('custom-rendezvous-server'));
var relayController = TextEditingController(text: old('relay-server'));
var apiController = TextEditingController(text: old('api-server'));
var keyController = TextEditingController(text: old('key'));
set(String idServer, String relayServer, String apiServer,
String key) async {
idServer = idServer.trim();
relayServer = relayServer.trim();
apiServer = apiServer.trim();
key = key.trim();
if (idServer.isNotEmpty) {
idErrMsg.value =
translate(await bind.mainTestIfValidServer(server: idServer));
if (idErrMsg.isNotEmpty) {
return false;
}
}
if (relayServer.isNotEmpty) {
relayErrMsg.value =
translate(await bind.mainTestIfValidServer(server: relayServer));
if (relayErrMsg.isNotEmpty) {
return false;
}
}
if (apiServer.isNotEmpty) {
if (!apiServer.startsWith('http://') ||
!apiServer.startsWith("https://")) {
apiErrMsg.value =
"${translate("API Server")}: ${translate("invalid_http")}";
return false;
}
}
// should set one by one
await bind.mainSetOption(
key: 'custom-rendezvous-server', value: idServer);
await bind.mainSetOption(key: 'relay-server', value: relayServer);
await bind.mainSetOption(key: 'api-server', value: apiServer);
await bind.mainSetOption(key: 'key', value: key);
return true;
}
submit() async {
bool result = await set(idController.text, relayController.text,
apiController.text, keyController.text);
if (result) {
setState(() {});
showToast(translate('Successful'));
} else {
showToast(translate('Failed'));
}
}
import() {
Clipboard.getData(Clipboard.kTextPlain).then((value) {
TextEditingController mytext = TextEditingController();
String? aNullableString = "";
aNullableString = value?.text;
mytext.text = aNullableString.toString();
if (mytext.text.isNotEmpty) {
try {
Map<String, dynamic> config = jsonDecode(mytext.text);
if (config.containsKey('IdServer')) {
String id = config['IdServer'] ?? '';
String relay = config['RelayServer'] ?? '';
String api = config['ApiServer'] ?? '';
String key = config['Key'] ?? '';
idController.text = id;
relayController.text = relay;
apiController.text = api;
keyController.text = key;
Future<bool> success = set(id, relay, api, key);
success.then((value) {
if (value) {
showToast(
translate('Import server configuration successfully'));
} else {
showToast(translate('Invalid server configuration'));
}
});
} else {
showToast(translate("Invalid server configuration"));
}
} catch (e) {
showToast(translate("Invalid server configuration"));
}
} else {
showToast(translate("Clipboard is empty"));
}
});
}
export() {
Map<String, String> config = {};
config['IdServer'] = idController.text.trim();
config['RelayServer'] = relayController.text.trim();
config['ApiServer'] = apiController.text.trim();
config['Key'] = keyController.text.trim();
Clipboard.setData(ClipboardData(text: jsonEncode(config)));
showToast(translate("Export server configuration successfully"));
}
bool secure = !enabled;
return _Card(title: 'ID/Relay Server', title_suffix: [
Tooltip(
message: translate('Import Server Config'),
child: IconButton(
icon: Icon(Icons.paste, color: Colors.grey),
onPressed: enabled ? import : null),
),
Tooltip(
message: translate('Export Server Config'),
child: IconButton(
icon: Icon(Icons.copy, color: Colors.grey),
onPressed: enabled ? export : null)),
], children: [
Column(
children: [
Obx(() => _LabeledTextField(context, 'ID Server', idController,
idErrMsg.value, enabled, secure)),
Obx(() => _LabeledTextField(context, 'Relay Server',
relayController, relayErrMsg.value, enabled, secure)),
Obx(() => _LabeledTextField(context, 'API Server', apiController,
apiErrMsg.value, enabled, secure)),
_LabeledTextField(
context, 'Key', keyController, "", enabled, secure),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [_Button('Apply', submit, enabled: enabled)],
).marginOnly(top: 15),
],
)
]);
});
}
}
class _Account extends StatefulWidget {
@ -955,63 +1102,37 @@ class _AboutState extends State<_About> {
//#region components
// ignore: non_constant_identifier_names
Widget _Card({required String title, required List<Widget> children}) {
Widget _Card(
{required String title,
required List<Widget> children,
List<Widget>? title_suffix}) {
return Row(
children: [
SizedBox(
width: _kCardFixedWidth,
child: Card(
child: Column(
children: [
Row(
children: [
Text(
translate(title),
textAlign: TextAlign.start,
style: const TextStyle(
fontSize: _kTitleFontSize,
),
),
const Spacer(),
],
).marginOnly(left: _kContentHMargin, top: 10, bottom: 10),
...children
.map((e) => e.marginOnly(top: 4, right: _kContentHMargin)),
],
).marginOnly(bottom: 10),
).marginOnly(left: _kCardLeftMargin, top: 15),
),
],
);
}
Widget _CardRow({required String title, required List<Widget> children}) {
return Row(
children: [
SizedBox(
width: _kCardFixedWidth,
child: Card(
child: Column(
children: [
Row(
children: [
Text(
translate(title),
textAlign: TextAlign.start,
style: const TextStyle(
fontSize: _kTitleFontSize,
),
),
const Spacer(),
],
).marginOnly(left: _kContentHMargin, top: 10, bottom: 10),
Row(children: [
Flexible(
child: SizedBox(
width: _kCardFixedWidth,
child: Card(
child: Column(
children: [
Row(
children: [
Expanded(
child: Text(
translate(title),
textAlign: TextAlign.start,
style: const TextStyle(
fontSize: _kTitleFontSize,
),
)),
...?title_suffix
],
).marginOnly(left: _kContentHMargin, top: 10, bottom: 10),
...children
.map((e) => e.marginOnly(top: 4, right: _kContentHMargin)),
]),
],
).marginOnly(bottom: 10),
).marginOnly(left: _kCardLeftMargin, top: 15),
],
).marginOnly(bottom: 10),
).marginOnly(left: _kCardLeftMargin, top: 15),
),
),
],
);
@ -1085,6 +1206,7 @@ Widget _Radio<T>(BuildContext context,
required T groupValue,
required String label,
required Function(T value) onChanged,
bool autoNewLine = true,
bool enabled = true}) {
var onChange = enabled
? (T? value) {
@ -1099,8 +1221,7 @@ Widget _Radio<T>(BuildContext context,
Radio<T>(value: value, groupValue: groupValue, onChanged: onChange),
Expanded(
child: Text(translate(label),
maxLines: 1,
overflow: TextOverflow.ellipsis,
overflow: autoNewLine ? null : TextOverflow.ellipsis,
style: TextStyle(
fontSize: _kContentFontSize,
color: _disabledTextColor(context, enabled)))
@ -1116,12 +1237,11 @@ Widget _Radio<T>(BuildContext context,
Widget _Button(String label, Function() onPressed,
{bool enabled = true, String? tip}) {
var button = ElevatedButton(
onPressed: enabled ? onPressed : null,
child: Container(
child: Text(
translate(label),
).marginSymmetric(horizontal: 15),
));
onPressed: enabled ? onPressed : null,
child: Text(
translate(label),
).marginSymmetric(horizontal: 15),
);
StatefulWidget child;
if (tip == null) {
child = button;
@ -1138,12 +1258,11 @@ Widget _SubButton(String label, Function() onPressed, [bool enabled = true]) {
return Row(
children: [
ElevatedButton(
onPressed: enabled ? onPressed : null,
child: Container(
child: Text(
translate(label),
).marginSymmetric(horizontal: 15),
)),
onPressed: enabled ? onPressed : null,
child: Text(
translate(label),
).marginSymmetric(horizontal: 15),
),
],
).marginOnly(left: _kContentHSubMargin);
}
@ -1215,34 +1334,72 @@ Widget _lock(
offstage: !locked,
child: Row(
children: [
SizedBox(
width: _kCardFixedWidth,
child: Card(
child: ElevatedButton(
child: SizedBox(
height: 25,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(
Icons.security_sharp,
size: 20,
),
Text(translate(label)).marginOnly(left: 5),
]).marginSymmetric(vertical: 2)),
onPressed: () async {
bool checked = await bind.mainCheckSuperUserPermission();
if (checked) {
onUnlock();
}
},
).marginSymmetric(horizontal: 2, vertical: 4),
).marginOnly(left: _kCardLeftMargin),
).marginOnly(top: 10),
Flexible(
child: SizedBox(
width: _kCardFixedWidth,
child: Card(
child: ElevatedButton(
child: SizedBox(
height: 25,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(
Icons.security_sharp,
size: 20,
),
Text(translate(label)).marginOnly(left: 5),
]).marginSymmetric(vertical: 2)),
onPressed: () async {
bool checked = await bind.mainCheckSuperUserPermission();
if (checked) {
onUnlock();
}
},
).marginSymmetric(horizontal: 2, vertical: 4),
).marginOnly(left: _kCardLeftMargin),
).marginOnly(top: 10),
),
],
));
}
_LabeledTextField(
BuildContext context,
String lable,
TextEditingController controller,
String errorText,
bool enabled,
bool secure) {
return Row(
children: [
Spacer(flex: 1),
Expanded(
flex: 4,
child: Text(
'${translate(lable)}:',
textAlign: TextAlign.right,
style: TextStyle(color: _disabledTextColor(context, enabled)),
),
),
Spacer(flex: 1),
Expanded(
flex: 10,
child: TextField(
controller: controller,
enabled: enabled,
obscureText: secure,
decoration: InputDecoration(
errorText: errorText.isNotEmpty ? errorText : null),
style: TextStyle(
color: _disabledTextColor(context, enabled),
)),
),
Spacer(flex: 1),
],
);
}
// ignore: must_be_immutable
class _ComboBox extends StatelessWidget {
late final List<String> keys;
@ -1312,315 +1469,6 @@ class _ComboBox extends StatelessWidget {
//#region dialogs
void changeServer() async {
Map<String, dynamic> oldOptions = jsonDecode(await bind.mainGetOptions());
String idServer = oldOptions['custom-rendezvous-server'] ?? "";
var idServerMsg = "";
String relayServer = oldOptions['relay-server'] ?? "";
var relayServerMsg = "";
String apiServer = oldOptions['api-server'] ?? "";
var apiServerMsg = "";
var key = oldOptions['key'] ?? "";
var idController = TextEditingController(text: idServer);
var relayController = TextEditingController(text: relayServer);
var apiController = TextEditingController(text: apiServer);
var keyController = TextEditingController(text: key);
var isInProgress = false;
gFFI.dialogManager.show((setState, close) {
submit() async {
setState(() {
idServerMsg = "";
relayServerMsg = "";
apiServerMsg = "";
isInProgress = true;
});
cancel() {
setState(() {
isInProgress = false;
});
}
idServer = idController.text.trim();
relayServer = relayController.text.trim();
apiServer = apiController.text.trim().toLowerCase();
key = keyController.text.trim();
if (idServer.isNotEmpty) {
idServerMsg =
translate(await bind.mainTestIfValidServer(server: idServer));
if (idServerMsg.isEmpty) {
oldOptions['custom-rendezvous-server'] = idServer;
} else {
cancel();
return;
}
} else {
oldOptions['custom-rendezvous-server'] = "";
}
if (relayServer.isNotEmpty) {
relayServerMsg =
translate(await bind.mainTestIfValidServer(server: relayServer));
if (relayServerMsg.isEmpty) {
oldOptions['relay-server'] = relayServer;
} else {
cancel();
return;
}
} else {
oldOptions['relay-server'] = "";
}
if (apiServer.isNotEmpty) {
if (apiServer.startsWith('http://') ||
apiServer.startsWith("https://")) {
oldOptions['api-server'] = apiServer;
return;
} else {
apiServerMsg = translate("invalid_http");
cancel();
return;
}
} else {
oldOptions['api-server'] = "";
}
// ok
oldOptions['key'] = key;
await bind.mainSetOptions(json: jsonEncode(oldOptions));
close();
}
return CustomAlertDialog(
title: Text(translate("ID/Relay Server")),
content: ConstrainedBox(
constraints: const BoxConstraints(minWidth: 500),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 8.0,
),
Row(
children: [
ConstrainedBox(
constraints: const BoxConstraints(minWidth: 100),
child: Text("${translate('ID Server')}:")
.marginOnly(bottom: 16.0)),
const SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
decoration: InputDecoration(
border: const OutlineInputBorder(),
errorText: idServerMsg.isNotEmpty ? idServerMsg : null),
controller: idController,
focusNode: FocusNode()..requestFocus(),
),
),
],
),
const SizedBox(
height: 8.0,
),
Row(
children: [
ConstrainedBox(
constraints: const BoxConstraints(minWidth: 100),
child: Text("${translate('Relay Server')}:")
.marginOnly(bottom: 16.0)),
const SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
decoration: InputDecoration(
border: const OutlineInputBorder(),
errorText:
relayServerMsg.isNotEmpty ? relayServerMsg : null),
controller: relayController,
),
),
],
),
const SizedBox(
height: 8.0,
),
Row(
children: [
ConstrainedBox(
constraints: const BoxConstraints(minWidth: 100),
child: Text("${translate('API Server')}:")
.marginOnly(bottom: 16.0)),
const SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
decoration: InputDecoration(
border: const OutlineInputBorder(),
errorText:
apiServerMsg.isNotEmpty ? apiServerMsg : null),
controller: apiController,
),
),
],
),
const SizedBox(
height: 8.0,
),
Row(
children: [
ConstrainedBox(
constraints: const BoxConstraints(minWidth: 100),
child:
Text("${translate('Key')}:").marginOnly(bottom: 16.0)),
const SizedBox(
width: 24.0,
),
Expanded(
child: TextField(
decoration: const InputDecoration(
border: OutlineInputBorder(),
),
controller: keyController,
),
),
],
),
const SizedBox(
height: 4.0,
),
Offstage(
offstage: !isInProgress, child: const LinearProgressIndicator())
],
),
),
actions: [
TextButton(onPressed: close, child: Text(translate("Cancel"))),
TextButton(onPressed: submit, child: Text(translate("OK"))),
],
onSubmit: submit,
onCancel: close,
);
});
}
void importServer() async {
Future<void> importServerShow(String content) async {
gFFI.dialogManager.show((setState, close) {
return CustomAlertDialog(
title: Text(content),
content: ConstrainedBox(
constraints: const BoxConstraints(minWidth: 500),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 4.0,
),
],
),
),
actions: [
TextButton(onPressed: close, child: Text(translate("OK"))),
],
onCancel: close,
);
});
}
Future<bool> submit(
String idServer, String relayServer, String apiServer, String key) async {
Map<String, dynamic> oldOptions = jsonDecode(await bind.mainGetOptions());
var idServerMsg = "";
var relayServerMsg = "";
if (idServer.isNotEmpty) {
idServerMsg =
translate(await bind.mainTestIfValidServer(server: idServer));
if (idServerMsg.isEmpty) {
oldOptions['custom-rendezvous-server'] = idServer;
} else {
debugPrint('ID Server invalid return');
return false;
}
} else {
oldOptions['custom-rendezvous-server'] = "";
}
if (relayServer.isNotEmpty) {
relayServerMsg =
translate(await bind.mainTestIfValidServer(server: relayServer));
if (relayServerMsg.isEmpty) {
oldOptions['relay-server'] = relayServer;
} else {
debugPrint('Relay Server invalid return');
return false;
}
} else {
oldOptions['relay-server'] = "";
}
if (apiServer.isNotEmpty) {
if (apiServer.startsWith('http://') || apiServer.startsWith("https://")) {
oldOptions['api-server'] = apiServer;
return false;
} else {
debugPrint('invalid_http');
return false;
}
} else {
oldOptions['api-server'] = "";
}
// ok
oldOptions['key'] = key;
await bind.mainSetOptions(json: jsonEncode(oldOptions));
debugPrint("set ID/Realy Server Ok");
return true;
}
Clipboard.getData(Clipboard.kTextPlain).then((value) {
TextEditingController mytext = TextEditingController();
String? aNullableString = "";
aNullableString = value?.text;
mytext.text = aNullableString.toString();
if (mytext.text.isNotEmpty) {
debugPrint('Clipboard is not empty');
try {
Map<String, dynamic> config = jsonDecode(mytext.text);
if (config.containsKey('IdServer') &&
config.containsKey('RelayServer')) {
debugPrint('IdServer: ${config['IdServer']}');
debugPrint('RelayServer: ${config['RelayServer']}');
debugPrint('ApiServer: ${config['ApiServer']}');
debugPrint('Key: ${config['Key']}');
Future<bool> success = submit(config['IdServer'],
config['RelayServer'], config['ApiServer'], config['Key']);
success.then((value) {
if (value) {
importServerShow(
translate('Import server configuration successfully'));
} else {
importServerShow(translate('Invalid server configuration'));
}
});
} else {
debugPrint('invalid config info');
importServerShow(translate("Invalid server configuration"));
}
} catch (e) {
debugPrint('invalid config info');
importServerShow(translate("Invalid server configuration"));
}
} else {
debugPrint('Clipboard is empty');
importServerShow(translate("Clipboard is empty"));
}
});
}
void changeSocks5Proxy() async {
var socks = await bind.mainGetSocks();

View File

@ -181,7 +181,7 @@ class _InstallPageState extends State<InstallPage> with WindowListener {
void install() {
btnEnabled.value = false;
showProgress.value = true;
String args = '--flutter';
String args = '';
if (startmenu.value) args += ' startmenu';
if (desktopicon.value) args += ' desktopicon';
bind.installInstallMe(options: args, path: controller.text);

View File

@ -16,15 +16,6 @@ typedef void (*FUNC_RUSTDESK_FREE_ARGS)( char**, int);
int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
_In_ wchar_t *command_line, _In_ int show_command)
{
// uni links dispatch
HWND hwnd = ::FindWindow(L"FLUTTER_RUNNER_WIN32_WINDOW", L"rustdesk");
if (hwnd != NULL) {
DispatchToUniLinksDesktop(hwnd);
::ShowWindow(hwnd, SW_NORMAL);
::SetForegroundWindow(hwnd);
return EXIT_FAILURE;
}
HINSTANCE hInstance = LoadLibraryA("librustdesk.dll");
if (!hInstance)
{
@ -56,6 +47,16 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
std::vector<std::string> rust_args(c_args, c_args + args_len);
free_c_args(c_args, args_len);
// uni links dispatch
HWND hwnd = ::FindWindow(L"FLUTTER_RUNNER_WIN32_WINDOW", L"rustdesk");
if (hwnd != NULL) {
DispatchToUniLinksDesktop(hwnd);
::ShowWindow(hwnd, SW_NORMAL);
::SetForegroundWindow(hwnd);
return EXIT_FAILURE;
}
// Attach to console when present (e.g., 'flutter run') or create a
// new console when running with a debugger.
if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent())
@ -78,7 +79,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
FlutterWindow window(project);
Win32Window::Point origin(10, 10);
Win32Window::Size size(800, 600);
if (!window.CreateAndShow(L"rustdesk", origin, size))
if (!window.CreateAndShow(L"RustDesk", origin, size))
{
return EXIT_FAILURE;
}

View File

@ -29,8 +29,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Enable TCP Tunneling", "允许建立TCP隧道"),
("IP Whitelisting", "IP白名单"),
("ID/Relay Server", "ID/中继服务器"),
("Import Server Conf", "导入服务器配置"),
("Import Server Config", "导入服务器配置"),
("Export Server Config", "导出服务器配置"),
("Import server configuration successfully", "导入服务器配置信息成功"),
("Export server configuration successfully", "导出服务器配置信息成功"),
("Invalid server configuration", "无效服务器配置,请修改后重新拷贝配置信息到剪贴板后点击此按钮"),
("Clipboard is empty", "拷贝配置信息到剪贴板后点击此按钮,可以自动导入配置"),
("Stop service", "停止服务"),

View File

@ -29,8 +29,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Enable TCP Tunneling", "Povolit TCP tunelování"),
("IP Whitelisting", "Povolování pouze z daných IP adres)"),
("ID/Relay Server", "Identifikátor / předávací (relay) server"),
("Import Server Conf", "Importovat konfiguraci serveru"),
("Import Server Config", "Importovat konfiguraci serveru"),
("Export Server Config", ""),
("Import server configuration successfully", "Konfigurace serveru úspěšně importována"),
("Export server configuration successfully", ""),
("Invalid server configuration", "Neplatná konfigurace serveru"),
("Clipboard is empty", "Schránka je prázdná"),
("Stop service", "Zastavit službu"),

View File

@ -29,8 +29,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Enable TCP Tunneling", "Slå TCP-tunneling til"),
("IP Whitelisting", "IP-udgivelsesliste"),
("ID/Relay Server", "ID/forbindelsesserver"),
("Import Server Conf", "Importér serverkonfiguration"),
("Import Server Config", "Importér serverkonfiguration"),
("Export Server Config", ""),
("Import server configuration successfully", "Importér serverkonfigurationen"),
("Export server configuration successfully", ""),
("Invalid server configuration", "Ugyldig serverkonfiguration"),
("Clipboard is empty", "Udklipsholderen er tom"),
("Stop service", "Sluk for forbindelsesserveren"),

View File

@ -29,8 +29,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Enable TCP Tunneling", "TCP-Tunnel aktivieren"),
("IP Whitelisting", "IP-Whitelist"),
("ID/Relay Server", "ID/Vermittlungsserver"),
("Import Server Conf", "Serverkonfiguration importieren"),
("Import Server Config", "Serverkonfiguration importieren"),
("Export Server Config", ""),
("Import server configuration successfully", "Serverkonfiguration erfolgreich importiert"),
("Export server configuration successfully", ""),
("Invalid server configuration", "Ungültige Serverkonfiguration"),
("Clipboard is empty", "Zwischenablage ist leer"),
("Stop service", "Vermittlungsdienst deaktivieren"),

View File

@ -29,8 +29,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Enable TCP Tunneling", "Ebligi tunelado TCP"),
("IP Whitelisting", "Listo de IP akceptataj"),
("ID/Relay Server", "Identigila/Relajsa servilo"),
("Import Server Conf", "Enporti servilan agordon"),
("Import Server Config", "Enporti servilan agordon"),
("Export Server Config", ""),
("Import server configuration successfully", "Importi servilan agordon sukcese"),
("Export server configuration successfully", ""),
("Invalid server configuration", "Nevalida servila agordo"),
("Clipboard is empty", "La poŝo estas malplena"),
("Stop service", "Haltu servon"),

View File

@ -29,8 +29,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Enable TCP Tunneling", "Habilitar tunel TCP"),
("IP Whitelisting", "Lista blanca de IP"),
("ID/Relay Server", "Servidor ID/Relay"),
("Import Server Conf", "Importar configuración de servidor"),
("Import Server Config", "Importar configuración de servidor"),
("Export Server Config", ""),
("Import server configuration successfully", "Configuración de servidor importada con éxito"),
("Export server configuration successfully", ""),
("Invalid server configuration", "Configuración de servidor inválida"),
("Clipboard is empty", "El portapapeles está vacío"),
("Stop service", "Parar servicio"),

View File

@ -29,8 +29,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Enable TCP Tunneling", "Activer le tunneling TCP"),
("IP Whitelisting", "Liste blanche IP"),
("ID/Relay Server", "ID/Serveur Relais"),
("Import Server Conf", "Importer la configuration du serveur"),
("Import Server Config", "Importer la configuration du serveur"),
("Export Server Config", ""),
("Import server configuration successfully", "Configuration du serveur importée avec succès"),
("Export server configuration successfully", ""),
("Invalid server configuration", "Configuration du serveur non valide"),
("Clipboard is empty", "Presse-papier vide"),
("Stop service", "Arrêter le service"),

View File

@ -29,8 +29,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Enable TCP Tunneling", "TCP Tunneling bekapcsolása"),
("IP Whitelisting", "IP Fehérlista"),
("ID/Relay Server", "ID/Relay Szerver"),
("Import Server Conf", "Szerver Konfiguráció Importálása"),
("Import Server Config", "Szerver Konfiguráció Importálása"),
("Export Server Config", ""),
("Import server configuration successfully", "Szerver konfiguráció sikeresen importálva"),
("Export server configuration successfully", ""),
("Invalid server configuration", "Érvénytelen szerver konfiguráció"),
("Clipboard is empty", "A vágólap üres"),
("Stop service", "Szolgáltatás Kikapcsolása"),

View File

@ -29,8 +29,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Enable TCP Tunneling", "Aktifkan TCP Tunneling"),
("IP Whitelisting", "Daftar Putih IP"),
("ID/Relay Server", "ID/Relay Server"),
("Import Server Conf", "Impor Konfigurasi Server"),
("Import Server Config", "Impor Konfigurasi Server"),
("Export Server Config", ""),
("Import server configuration successfully", "Impor konfigurasi server berhasil"),
("Export server configuration successfully", ""),
("Invalid server configuration", "Konfigurasi server tidak valid"),
("Clipboard is empty", "Papan klip kosong"),
("Stop service", "Hentikan Layanan"),

View File

@ -29,8 +29,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Enable TCP Tunneling", "Abilita tunnel TCP"),
("IP Whitelisting", "IP autorizzati"),
("ID/Relay Server", "Server ID/Relay"),
("Import Server Conf", "Importa configurazione Server"),
("Import Server Config", "Importa configurazione Server"),
("Export Server Config", ""),
("Import server configuration successfully", "Configurazione Server importata con successo"),
("Export server configuration successfully", ""),
("Invalid server configuration", "Configurazione Server non valida"),
("Clipboard is empty", "Gli appunti sono vuoti"),
("Stop service", "Arresta servizio"),

View File

@ -29,8 +29,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Enable TCP Tunneling", "TCPトンネリングを有効化"),
("IP Whitelisting", "IPホワイトリスト"),
("ID/Relay Server", "認証・中継サーバー"),
("Import Server Conf", "サーバー設定をインポート"),
("Import Server Config", "サーバー設定をインポート"),
("Export Server Config", ""),
("Import server configuration successfully", "サーバー設定をインポートしました"),
("Export server configuration successfully", ""),
("Invalid server configuration", "無効なサーバー設定です"),
("Clipboard is empty", "クリップボードは空です"),
("Stop service", "サービスを停止"),

View File

@ -29,8 +29,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Enable TCP Tunneling", "TCP 터널링 활성화"),
("IP Whitelisting", "IP 화이트리스트"),
("ID/Relay Server", "ID/Relay 서버"),
("Import Server Conf", "서버 설정 가져오기"),
("Import Server Config", "서버 설정 가져오기"),
("Export Server Config", ""),
("Import server configuration successfully", "서버 설정 가져오기 성공"),
("Export server configuration successfully", ""),
("Invalid server configuration", "잘못된 서버 설정"),
("Clipboard is empty", "클립보드가 비어있습니다"),
("Stop service", "서비스 중단"),

View File

@ -29,8 +29,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Enable TCP Tunneling", "TCP тунелдеуді қосу"),
("IP Whitelisting", "IP Ақ-тізімі"),
("ID/Relay Server", "ID/Relay сербері"),
("Import Server Conf", "Серверді импорттау"),
("Import Server Config", "Серверді импорттау"),
("Export Server Config", ""),
("Import server configuration successfully", "Сервердің конфигурациясы сәтті импортталды"),
("Export server configuration successfully", ""),
("Invalid server configuration", "Жарамсыз сервердің конфигурациясы"),
("Clipboard is empty", "Көшіру-тақта бос"),
("Stop service", "Сербесті тоқтату"),

View File

@ -29,8 +29,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Enable TCP Tunneling", "Włącz tunelowanie TCP"),
("IP Whitelisting", "Biała lista IP"),
("ID/Relay Server", "Serwer ID/Pośredniczący"),
("Import Server Conf", "Importuj konfigurację serwera"),
("Import Server Config", "Importuj konfigurację serwera"),
("Export Server Config", ""),
("Import server configuration successfully", "Importowanie konfiguracji serwera powiodło się"),
("Export server configuration successfully", ""),
("Invalid server configuration", "Nieprawidłowa konfiguracja serwera"),
("Clipboard is empty", "Schowek jest pusty"),
("Stop service", "Zatrzymaj usługę"),

View File

@ -29,8 +29,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Enable TCP Tunneling", "Activar Túnel TCP"),
("IP Whitelisting", "Whitelist de IP"),
("ID/Relay Server", "Servidor ID/Relay"),
("Import Server Conf", "Importar Configuração do Servidor"),
("Import Server Config", "Importar Configuração do Servidor"),
("Export Server Config", ""),
("Import server configuration successfully", "Configuração do servidor importada com sucesso"),
("Export server configuration successfully", ""),
("Invalid server configuration", "Configuração do servidor inválida"),
("Clipboard is empty", "A área de transferência está vazia"),
("Stop service", "Parar serviço"),

View File

@ -29,8 +29,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Enable TCP Tunneling", "Habilitar Tunelamento TCP"),
("IP Whitelisting", "Whitelist de IP"),
("ID/Relay Server", "Servidor ID/Relay"),
("Import Server Conf", "Importar Configuração do Servidor"),
("Import Server Config", "Importar Configuração do Servidor"),
("Export Server Config", ""),
("Import server configuration successfully", "Configuração do servidor importada com sucesso"),
("Export server configuration successfully", ""),
("Invalid server configuration", "Configuração do servidor inválida"),
("Clipboard is empty", "A área de transferência está vazia"),
("Stop service", "Parar serviço"),

View File

@ -29,8 +29,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Enable TCP Tunneling", "Включить туннелирование TCP"),
("IP Whitelisting", "Список разрешенных IP-адресов"),
("ID/Relay Server", "ID/Сервер ретрансляции"),
("Import Server Conf", "Импортировать конфигурацию сервера"),
("Import Server Config", "Импортировать конфигурацию сервера"),
("Export Server Config", ""),
("Import server configuration successfully", "Конфигурация сервера успешно импортирована"),
("Export server configuration successfully", ""),
("Invalid server configuration", "Недопустимая конфигурация сервера"),
("Clipboard is empty", "Буфер обмена пуст"),
("Stop service", "Остановить службу"),

View File

@ -29,8 +29,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Enable TCP Tunneling", "Povoliť TCP tunelovanie"),
("IP Whitelisting", "Zoznam povolených IP adries"),
("ID/Relay Server", "ID/Prepojovací server"),
("Import Server Conf", "Importovať konfiguráciu servera"),
("Import Server Config", "Importovať konfiguráciu servera"),
("Export Server Config", ""),
("Import server configuration successfully", "Konfigurácia servera bola úspešne importovaná"),
("Export server configuration successfully", ""),
("Invalid server configuration", "Neplatná konfigurácia servera"),
("Clipboard is empty", "Schránka je prázdna"),
("Stop service", "Zastaviť službu"),

View File

@ -29,8 +29,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Enable TCP Tunneling", ""),
("IP Whitelisting", ""),
("ID/Relay Server", ""),
("Import Server Conf", ""),
("Import Server Config", ""),
("Export Server Config", ""),
("Import server configuration successfully", ""),
("Export server configuration successfully", ""),
("Invalid server configuration", ""),
("Clipboard is empty", ""),
("Stop service", ""),

View File

@ -29,8 +29,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Enable TCP Tunneling", "TCP Tüneline izin ver"),
("IP Whitelisting", "İzinli IP listesi"),
("ID/Relay Server", "ID/Relay Sunucusu"),
("Import Server Conf", "Sunucu ayarlarını içe aktar"),
("Import Server Config", "Sunucu ayarlarını içe aktar"),
("Export Server Config", ""),
("Import server configuration successfully", "Sunucu ayarları başarıyla içe aktarıldı"),
("Export server configuration successfully", ""),
("Invalid server configuration", "Geçersiz sunucu ayarı"),
("Clipboard is empty", "Kopyalanan geçici veri boş"),
("Stop service", "Servisi Durdur"),

View File

@ -29,8 +29,11 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Enable TCP Tunneling", "啟用 TCP 通道"),
("IP Whitelisting", "IP 白名單"),
("ID/Relay Server", "ID/轉送伺服器"),
("Import Server Conf", "匯入伺服器設定"),
("Import Server Config", "匯入伺服器設定"),
("Export Server Config", "導出服務器配置"),
("Import server configuration successfully", "匯入伺服器設定成功"),
("Export server configuration successfully", ""),
("Export server configuration successfully", "導出服務器配置信息成功"),
("Invalid server configuration", "無效的伺服器設定"),
("Clipboard is empty", "剪貼簿是空的"),
("Stop service", "停止服務"),

View File

@ -29,8 +29,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Enable TCP Tunneling", "Увімкнути тунелювання TCP"),
("IP Whitelisting", "Список дозволених IP-адрес"),
("ID/Relay Server", "ID/Сервер ретрансляції"),
("Import Server Conf", "Імпортувати конфігурацію сервера"),
("Import Server Config", "Імпортувати конфігурацію сервера"),
("Export Server Config", ""),
("Import server configuration successfully", "Конфігурацію сервера успішно імпортовано"),
("Export server configuration successfully", ""),
("Invalid server configuration", "Недійсна конфігурація сервера"),
("Clipboard is empty", "Буфер обміну порожній"),
("Stop service", "Зупинити службу"),

View File

@ -29,8 +29,10 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Enable TCP Tunneling", "Cho phép TCP Tunneling"),
("IP Whitelisting", "Cho phép IP"),
("ID/Relay Server", "Máy chủ ID/Relay"),
("Import Server Conf", "Nhập cấu hình máy chủ"),
("Import Server Config", "Nhập cấu hình máy chủ"),
("Export Server Config", ""),
("Import server configuration successfully", "Nhập cấu hình máy chủ thành công"),
("Export server configuration successfully", ""),
("Invalid server configuration", "Cấu hình máy chủ không hợp lệ"),
("Clipboard is empty", "Khay nhớ tạm trống"),
("Stop service", "Dừng dịch vụ"),

View File

@ -878,6 +878,25 @@ fn get_install_info_with_subkey(subkey: String) -> (String, String, String, Stri
(subkey, path, start_menu, exe)
}
pub fn copy_exe_cmd(src_exe: &str, _exe: &str, _path: &str) -> String {
#[cfg(feature = "flutter")]
return format!(
"XCOPY \"{}\" \"{}\" /Y /E /H /C /I /K /R /Z",
PathBuf::from(src_exe)
.parent()
.unwrap()
.to_string_lossy()
.to_string(),
_path
);
#[cfg(not(feature = "flutter"))]
return format!(
"copy /Y \"{src_exe}\" \"{exe}\"",
src_exe = src_exe,
exe = _exe
);
}
pub fn update_me() -> ResultType<()> {
let (_, path, _, exe) = get_install_info();
let src_exe = std::env::current_exe()?.to_str().unwrap_or("").to_owned();
@ -887,13 +906,13 @@ pub fn update_me() -> ResultType<()> {
sc stop {app_name}
taskkill /F /IM {broker_exe}
taskkill /F /IM {app_name}.exe
copy /Y \"{src_exe}\" \"{exe}\"
{copy_exe}
\"{src_exe}\" --extract \"{path}\"
sc start {app_name}
{lic}
",
src_exe = src_exe,
exe = exe,
copy_exe = copy_exe_cmd(&src_exe, &exe, &path),
broker_exe = crate::ui::win_privacy::INJECTED_PROCESS_EXE,
path = path,
app_name = crate::get_app_name(),
@ -1038,18 +1057,6 @@ copy /Y \"{tmp_path}\\Uninstall {app_name}.lnk\" \"{start_menu}\\\"
app_name = crate::get_app_name(),
);
}
let mut flutter_copy = Default::default();
if options.contains("--flutter") {
flutter_copy = format!(
"XCOPY \"{}\" \"{}\" /Y /E /H /C /I /K /R /Z",
std::env::current_exe()?
.parent()
.unwrap()
.to_string_lossy()
.to_string(),
path
);
}
let meta = std::fs::symlink_metadata(std::env::current_exe()?)?;
let size = meta.len() / 1024;
@ -1072,13 +1079,14 @@ if exist \"{tmp_path}\\{app_name} Tray.lnk\" del /f /q \"{tmp_path}\\{app_name}
tmp_path = tmp_path,
app_name = crate::get_app_name(),
);
let src_exe = std::env::current_exe()?.to_str().unwrap_or("").to_string();
let cmds = format!(
"
{uninstall_str}
chcp 65001
md \"{path}\"
{flutter_copy}
copy /Y \"{src_exe}\" \"{exe}\"
{copy_exe}
copy /Y \"{ORIGIN_PROCESS_EXE}\" \"{path}\\{broker_exe}\"
\"{src_exe}\" --extract \"{path}\"
reg add {subkey} /f
@ -1111,7 +1119,7 @@ sc delete {app_name}
",
uninstall_str=uninstall_str,
path=path,
src_exe=std::env::current_exe()?.to_str().unwrap_or(""),
src_exe=src_exe,
exe=exe,
ORIGIN_PROCESS_EXE = crate::ui::win_privacy::ORIGIN_PROCESS_EXE,
broker_exe=crate::ui::win_privacy::INJECTED_PROCESS_EXE,
@ -1140,7 +1148,7 @@ sc delete {app_name}
} else {
&dels
},
flutter_copy = flutter_copy,
copy_exe = copy_exe_cmd(&src_exe, &exe, &path),
);
run_cmds(cmds, debug, "install")?;
std::thread::sleep(std::time::Duration::from_millis(2000));
@ -1478,7 +1486,13 @@ pub fn run_uac(exe: &str, arg: &str) -> ResultType<bool> {
}
pub fn check_super_user_permission() -> ResultType<bool> {
run_uac("cmd", "/c /q")
run_uac(
std::env::current_exe()?
.to_string_lossy()
.to_string()
.as_str(),
"--version",
)
}
pub fn elevate(arg: &str) -> ResultType<bool> {