mirror of
https://github.com/rustdesk/rustdesk.git
synced 2025-05-11 18:36:11 +02:00
Refact. Flutter web, mid commit (#7494)
Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
parent
96e1b5b0f6
commit
85cafda168
33 changed files with 298 additions and 152 deletions
|
@ -635,8 +635,12 @@ closeConnection({String? id}) {
|
||||||
gFFI.chatModel.hideChatOverlay();
|
gFFI.chatModel.hideChatOverlay();
|
||||||
Navigator.popUntil(globalKey.currentContext!, ModalRoute.withName("/"));
|
Navigator.popUntil(globalKey.currentContext!, ModalRoute.withName("/"));
|
||||||
} else {
|
} else {
|
||||||
final controller = Get.find<DesktopTabController>();
|
if (isWeb) {
|
||||||
controller.closeBy(id);
|
Navigator.popUntil(globalKey.currentContext!, ModalRoute.withName("/"));
|
||||||
|
} else {
|
||||||
|
final controller = Get.find<DesktopTabController>();
|
||||||
|
controller.closeBy(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2980,7 +2984,6 @@ Future<bool> setServerConfig(
|
||||||
await bind.mainSetOption(key: 'relay-server', value: config.relayServer);
|
await bind.mainSetOption(key: 'relay-server', value: config.relayServer);
|
||||||
await bind.mainSetOption(key: 'api-server', value: config.apiServer);
|
await bind.mainSetOption(key: 'api-server', value: config.apiServer);
|
||||||
await bind.mainSetOption(key: 'key', value: config.key);
|
await bind.mainSetOption(key: 'key', value: config.key);
|
||||||
|
|
||||||
final newApiServer = await bind.mainGetApiServer();
|
final newApiServer = await bind.mainGetApiServer();
|
||||||
if (oldApiServer.isNotEmpty &&
|
if (oldApiServer.isNotEmpty &&
|
||||||
oldApiServer != newApiServer &&
|
oldApiServer != newApiServer &&
|
||||||
|
|
|
@ -625,7 +625,7 @@ class _DialogVerificationCodeField extends State<DialogVerificationCodeField> {
|
||||||
|
|
||||||
// software secure keyboard will take the focus since flutter 3.13
|
// software secure keyboard will take the focus since flutter 3.13
|
||||||
// request focus again when android account password obtain focus
|
// request focus again when android account password obtain focus
|
||||||
if (Platform.isAndroid && widget.reRequestFocus) {
|
if (isAndroid && widget.reRequestFocus) {
|
||||||
_focusNode.addListener(() {
|
_focusNode.addListener(() {
|
||||||
if (_focusNode.hasFocus) {
|
if (_focusNode.hasFocus) {
|
||||||
_timerReRequestFocus?.cancel();
|
_timerReRequestFocus?.cancel();
|
||||||
|
@ -694,7 +694,7 @@ class _PasswordWidgetState extends State<PasswordWidget> {
|
||||||
}
|
}
|
||||||
// software secure keyboard will take the focus since flutter 3.13
|
// software secure keyboard will take the focus since flutter 3.13
|
||||||
// request focus again when android account password obtain focus
|
// request focus again when android account password obtain focus
|
||||||
if (Platform.isAndroid && widget.reRequestFocus) {
|
if (isAndroid && widget.reRequestFocus) {
|
||||||
_focusNode.addListener(() {
|
_focusNode.addListener(() {
|
||||||
if (_focusNode.hasFocus) {
|
if (_focusNode.hasFocus) {
|
||||||
_timerReRequestFocus?.cancel();
|
_timerReRequestFocus?.cancel();
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:bot_toast/bot_toast.dart';
|
import 'package:bot_toast/bot_toast.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
@ -875,10 +873,10 @@ class RecentPeerCard extends BasePeerCard {
|
||||||
}
|
}
|
||||||
// menuItems.add(await _openNewConnInOptAction(peer.id));
|
// menuItems.add(await _openNewConnInOptAction(peer.id));
|
||||||
menuItems.add(await _forceAlwaysRelayAction(peer.id));
|
menuItems.add(await _forceAlwaysRelayAction(peer.id));
|
||||||
if (Platform.isWindows && peer.platform == kPeerPlatformWindows) {
|
if (isWindows && peer.platform == kPeerPlatformWindows) {
|
||||||
menuItems.add(_rdpAction(context, peer.id));
|
menuItems.add(_rdpAction(context, peer.id));
|
||||||
}
|
}
|
||||||
if (Platform.isWindows) {
|
if (isWindows) {
|
||||||
menuItems.add(_createShortCutAction(peer.id));
|
menuItems.add(_createShortCutAction(peer.id));
|
||||||
}
|
}
|
||||||
menuItems.add(MenuEntryDivider());
|
menuItems.add(MenuEntryDivider());
|
||||||
|
@ -927,10 +925,10 @@ class FavoritePeerCard extends BasePeerCard {
|
||||||
}
|
}
|
||||||
// menuItems.add(await _openNewConnInOptAction(peer.id));
|
// menuItems.add(await _openNewConnInOptAction(peer.id));
|
||||||
menuItems.add(await _forceAlwaysRelayAction(peer.id));
|
menuItems.add(await _forceAlwaysRelayAction(peer.id));
|
||||||
if (Platform.isWindows && peer.platform == kPeerPlatformWindows) {
|
if (isWindows && peer.platform == kPeerPlatformWindows) {
|
||||||
menuItems.add(_rdpAction(context, peer.id));
|
menuItems.add(_rdpAction(context, peer.id));
|
||||||
}
|
}
|
||||||
if (Platform.isWindows) {
|
if (isWindows) {
|
||||||
menuItems.add(_createShortCutAction(peer.id));
|
menuItems.add(_createShortCutAction(peer.id));
|
||||||
}
|
}
|
||||||
menuItems.add(MenuEntryDivider());
|
menuItems.add(MenuEntryDivider());
|
||||||
|
@ -979,11 +977,11 @@ class DiscoveredPeerCard extends BasePeerCard {
|
||||||
}
|
}
|
||||||
// menuItems.add(await _openNewConnInOptAction(peer.id));
|
// menuItems.add(await _openNewConnInOptAction(peer.id));
|
||||||
menuItems.add(await _forceAlwaysRelayAction(peer.id));
|
menuItems.add(await _forceAlwaysRelayAction(peer.id));
|
||||||
if (Platform.isWindows && peer.platform == kPeerPlatformWindows) {
|
if (isWindows && peer.platform == kPeerPlatformWindows) {
|
||||||
menuItems.add(_rdpAction(context, peer.id));
|
menuItems.add(_rdpAction(context, peer.id));
|
||||||
}
|
}
|
||||||
menuItems.add(_wolAction(peer.id));
|
menuItems.add(_wolAction(peer.id));
|
||||||
if (Platform.isWindows) {
|
if (isWindows) {
|
||||||
menuItems.add(_createShortCutAction(peer.id));
|
menuItems.add(_createShortCutAction(peer.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1027,10 +1025,10 @@ class AddressBookPeerCard extends BasePeerCard {
|
||||||
}
|
}
|
||||||
// menuItems.add(await _openNewConnInOptAction(peer.id));
|
// menuItems.add(await _openNewConnInOptAction(peer.id));
|
||||||
// menuItems.add(await _forceAlwaysRelayAction(peer.id));
|
// menuItems.add(await _forceAlwaysRelayAction(peer.id));
|
||||||
if (Platform.isWindows && peer.platform == kPeerPlatformWindows) {
|
if (isWindows && peer.platform == kPeerPlatformWindows) {
|
||||||
menuItems.add(_rdpAction(context, peer.id));
|
menuItems.add(_rdpAction(context, peer.id));
|
||||||
}
|
}
|
||||||
if (Platform.isWindows) {
|
if (isWindows) {
|
||||||
menuItems.add(_createShortCutAction(peer.id));
|
menuItems.add(_createShortCutAction(peer.id));
|
||||||
}
|
}
|
||||||
if (gFFI.abModel.current.canWrite()) {
|
if (gFFI.abModel.current.canWrite()) {
|
||||||
|
@ -1154,10 +1152,10 @@ class MyGroupPeerCard extends BasePeerCard {
|
||||||
}
|
}
|
||||||
// menuItems.add(await _openNewConnInOptAction(peer.id));
|
// menuItems.add(await _openNewConnInOptAction(peer.id));
|
||||||
// menuItems.add(await _forceAlwaysRelayAction(peer.id));
|
// menuItems.add(await _forceAlwaysRelayAction(peer.id));
|
||||||
if (Platform.isWindows && peer.platform == kPeerPlatformWindows) {
|
if (isWindows && peer.platform == kPeerPlatformWindows) {
|
||||||
menuItems.add(_rdpAction(context, peer.id));
|
menuItems.add(_rdpAction(context, peer.id));
|
||||||
}
|
}
|
||||||
if (Platform.isWindows) {
|
if (isWindows) {
|
||||||
menuItems.add(_createShortCutAction(peer.id));
|
menuItems.add(_createShortCutAction(peer.id));
|
||||||
}
|
}
|
||||||
// menuItems.add(MenuEntryDivider());
|
// menuItems.add(MenuEntryDivider());
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
@ -633,8 +632,8 @@ List<TToggleMenu> toolbarKeyboardToggles(FFI ffi) {
|
||||||
|
|
||||||
// swap key
|
// swap key
|
||||||
if (ffiModel.keyboard &&
|
if (ffiModel.keyboard &&
|
||||||
((Platform.isMacOS && pi.platform != kPeerPlatformMacOS) ||
|
((isMacOS && pi.platform != kPeerPlatformMacOS) ||
|
||||||
(!Platform.isMacOS && pi.platform == kPeerPlatformMacOS))) {
|
(!isMacOS && pi.platform == kPeerPlatformMacOS))) {
|
||||||
final option = 'allow_swap_key';
|
final option = 'allow_swap_key';
|
||||||
final value =
|
final value =
|
||||||
bind.sessionGetToggleOptionSync(sessionId: sessionId, arg: option);
|
bind.sessionGetToggleOptionSync(sessionId: sessionId, arg: option);
|
||||||
|
|
|
@ -115,16 +115,16 @@ const double kDefaultQuality = 50;
|
||||||
const double kMaxQuality = 100;
|
const double kMaxQuality = 100;
|
||||||
const double kMaxMoreQuality = 2000;
|
const double kMaxMoreQuality = 2000;
|
||||||
|
|
||||||
double kNewWindowOffset = Platform.isWindows
|
double kNewWindowOffset = isWindows
|
||||||
? 56.0
|
? 56.0
|
||||||
: Platform.isLinux
|
: isLinux
|
||||||
? 50.0
|
? 50.0
|
||||||
: Platform.isMacOS
|
: isMacOS
|
||||||
? 30.0
|
? 30.0
|
||||||
: 50.0;
|
: 50.0;
|
||||||
|
|
||||||
EdgeInsets get kDragToResizeAreaPadding =>
|
EdgeInsets get kDragToResizeAreaPadding =>
|
||||||
!kUseCompatibleUiMode && Platform.isLinux
|
!kUseCompatibleUiMode && isLinux
|
||||||
? stateGlobal.fullscreen.isTrue || stateGlobal.isMaximized.value
|
? stateGlobal.fullscreen.isTrue || stateGlobal.isMaximized.value
|
||||||
? EdgeInsets.zero
|
? EdgeInsets.zero
|
||||||
: EdgeInsets.all(5.0)
|
: EdgeInsets.all(5.0)
|
||||||
|
@ -152,7 +152,7 @@ const kDefaultScrollDuration = Duration(milliseconds: 50);
|
||||||
const kDefaultMouseWheelThrottleDuration = Duration(milliseconds: 50);
|
const kDefaultMouseWheelThrottleDuration = Duration(milliseconds: 50);
|
||||||
const kFullScreenEdgeSize = 0.0;
|
const kFullScreenEdgeSize = 0.0;
|
||||||
const kMaximizeEdgeSize = 0.0;
|
const kMaximizeEdgeSize = 0.0;
|
||||||
var kWindowEdgeSize = Platform.isWindows ? 1.0 : 5.0;
|
var kWindowEdgeSize = isWindows ? 1.0 : 5.0;
|
||||||
const kWindowBorderWidth = 1.0;
|
const kWindowBorderWidth = 1.0;
|
||||||
const kDesktopMenuPadding = EdgeInsets.only(left: 12.0, right: 3.0);
|
const kDesktopMenuPadding = EdgeInsets.only(left: 12.0, right: 3.0);
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:auto_size_text/auto_size_text.dart';
|
import 'package:auto_size_text/auto_size_text.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -231,7 +230,7 @@ class _ConnectionPageState extends State<ConnectionPage>
|
||||||
if (eventName == 'minimize') {
|
if (eventName == 'minimize') {
|
||||||
isWindowMinimized = true;
|
isWindowMinimized = true;
|
||||||
} else if (eventName == 'maximize' || eventName == 'restore') {
|
} else if (eventName == 'maximize' || eventName == 'restore') {
|
||||||
if (isWindowMinimized && Platform.isWindows) {
|
if (isWindowMinimized && isWindows) {
|
||||||
// windows can't update when minimized.
|
// windows can't update when minimized.
|
||||||
Get.forceAppUpdate();
|
Get.forceAppUpdate();
|
||||||
}
|
}
|
||||||
|
|
|
@ -469,7 +469,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
||||||
return buildInstallCard("", systemError, "", () {});
|
return buildInstallCard("", systemError, "", () {});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Platform.isWindows && !bind.isDisableInstallation()) {
|
if (isWindows && !bind.isDisableInstallation()) {
|
||||||
if (!bind.mainIsInstalled()) {
|
if (!bind.mainIsInstalled()) {
|
||||||
return buildInstallCard(
|
return buildInstallCard(
|
||||||
"", bind.isOutgoingOnly() ? "" : "install_tip", "Install",
|
"", bind.isOutgoingOnly() ? "" : "install_tip", "Install",
|
||||||
|
@ -485,7 +485,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
||||||
bind.mainUpdateMe();
|
bind.mainUpdateMe();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if (Platform.isMacOS) {
|
} else if (isMacOS) {
|
||||||
if (!(bind.isOutgoingOnly() ||
|
if (!(bind.isOutgoingOnly() ||
|
||||||
bind.mainIsCanScreenRecording(prompt: false))) {
|
bind.mainIsCanScreenRecording(prompt: false))) {
|
||||||
return buildInstallCard("Permissions", "config_screen", "Configure",
|
return buildInstallCard("Permissions", "config_screen", "Configure",
|
||||||
|
@ -521,7 +521,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
||||||
// watchIsCanRecordAudio = true;
|
// watchIsCanRecordAudio = true;
|
||||||
// });
|
// });
|
||||||
// }
|
// }
|
||||||
} else if (Platform.isLinux) {
|
} else if (isLinux) {
|
||||||
if (bind.isOutgoingOnly()) {
|
if (bind.isOutgoingOnly()) {
|
||||||
return Container();
|
return Container();
|
||||||
}
|
}
|
||||||
|
@ -570,7 +570,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
SystemNavigator.pop(); // Close the application
|
SystemNavigator.pop(); // Close the application
|
||||||
// https://github.com/flutter/flutter/issues/66631
|
// https://github.com/flutter/flutter/issues/66631
|
||||||
if (Platform.isWindows) {
|
if (isWindows) {
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -740,7 +740,7 @@ class _DesktopHomePageState extends State<DesktopHomePage>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (watchIsCanRecordAudio) {
|
if (watchIsCanRecordAudio) {
|
||||||
if (Platform.isMacOS) {
|
if (isMacOS) {
|
||||||
Future.microtask(() async {
|
Future.microtask(() async {
|
||||||
if ((await osxCanRecordAudio() ==
|
if ((await osxCanRecordAudio() ==
|
||||||
PermissionAuthorizeType.authorized)) {
|
PermissionAuthorizeType.authorized)) {
|
||||||
|
|
|
@ -414,7 +414,7 @@ class _GeneralState extends State<_General> {
|
||||||
}
|
}
|
||||||
|
|
||||||
String getDefault() {
|
String getDefault() {
|
||||||
if (Platform.isWindows) return translate('System Sound');
|
if (isWindows) return translate('System Sound');
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -434,7 +434,7 @@ class _GeneralState extends State<_General> {
|
||||||
|
|
||||||
return futureBuilder(future: () async {
|
return futureBuilder(future: () async {
|
||||||
List<String> devices = (await bind.mainGetSoundInputs()).toList();
|
List<String> devices = (await bind.mainGetSoundInputs()).toList();
|
||||||
if (Platform.isWindows) {
|
if (isWindows) {
|
||||||
devices.insert(0, translate('System Sound'));
|
devices.insert(0, translate('System Sound'));
|
||||||
}
|
}
|
||||||
String current = await getValue();
|
String current = await getValue();
|
||||||
|
@ -705,7 +705,7 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
||||||
_OptionCheckBox(
|
_OptionCheckBox(
|
||||||
context, 'Enable recording session', 'enable-record-session',
|
context, 'Enable recording session', 'enable-record-session',
|
||||||
enabled: enabled, fakeValue: fakeValue),
|
enabled: enabled, fakeValue: fakeValue),
|
||||||
if (Platform.isWindows)
|
if (isWindows)
|
||||||
_OptionCheckBox(
|
_OptionCheckBox(
|
||||||
context, 'Enable blocking user input', 'enable-block-input',
|
context, 'Enable blocking user input', 'enable-block-input',
|
||||||
enabled: enabled, fakeValue: fakeValue),
|
enabled: enabled, fakeValue: fakeValue),
|
||||||
|
@ -845,7 +845,7 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
||||||
|
|
||||||
bool value = bind.mainIsShareRdp();
|
bool value = bind.mainIsShareRdp();
|
||||||
return Offstage(
|
return Offstage(
|
||||||
offstage: !(Platform.isWindows && bind.mainIsInstalled()),
|
offstage: !(isWindows && bind.mainIsInstalled()),
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -90,7 +90,7 @@ class _DesktopTabPageState extends State<DesktopTabPage> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)));
|
)));
|
||||||
return Platform.isMacOS || kUseCompatibleUiMode
|
return isMacOS || kUseCompatibleUiMode
|
||||||
? tabWidget
|
? tabWidget
|
||||||
: Obx(
|
: Obx(
|
||||||
() => DragToResizeArea(
|
() => DragToResizeArea(
|
||||||
|
|
|
@ -93,7 +93,7 @@ class _FileManagerPageState extends State<FileManagerPage>
|
||||||
.showLoading(translate('Connecting...'), onCancel: closeConnection);
|
.showLoading(translate('Connecting...'), onCancel: closeConnection);
|
||||||
});
|
});
|
||||||
Get.put(_ffi, tag: 'ft_${widget.id}');
|
Get.put(_ffi, tag: 'ft_${widget.id}');
|
||||||
if (!Platform.isLinux) {
|
if (!isLinux) {
|
||||||
WakelockPlus.enable();
|
WakelockPlus.enable();
|
||||||
}
|
}
|
||||||
debugPrint("File manager page init success with id ${widget.id}");
|
debugPrint("File manager page init success with id ${widget.id}");
|
||||||
|
@ -106,7 +106,7 @@ class _FileManagerPageState extends State<FileManagerPage>
|
||||||
model.close().whenComplete(() {
|
model.close().whenComplete(() {
|
||||||
_ffi.close();
|
_ffi.close();
|
||||||
_ffi.dialogManager.dismissAll();
|
_ffi.dialogManager.dismissAll();
|
||||||
if (!Platform.isLinux) {
|
if (!isLinux) {
|
||||||
WakelockPlus.disable();
|
WakelockPlus.disable();
|
||||||
}
|
}
|
||||||
Get.delete<FFI>(tag: 'ft_${widget.id}');
|
Get.delete<FFI>(tag: 'ft_${widget.id}');
|
||||||
|
@ -1298,7 +1298,7 @@ class _FileManagerViewState extends State<FileManagerView> {
|
||||||
onPointerSignal: (e) {
|
onPointerSignal: (e) {
|
||||||
if (e is PointerScrollEvent) {
|
if (e is PointerScrollEvent) {
|
||||||
final sc = _breadCrumbScroller;
|
final sc = _breadCrumbScroller;
|
||||||
final scale = Platform.isWindows ? 2 : 4;
|
final scale = isWindows ? 2 : 4;
|
||||||
sc.jumpTo(sc.offset + e.scrollDelta.dy / scale);
|
sc.jumpTo(sc.offset + e.scrollDelta.dy / scale);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:desktop_multi_window/desktop_multi_window.dart';
|
import 'package:desktop_multi_window/desktop_multi_window.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -104,7 +103,7 @@ class _FileManagerTabPageState extends State<FileManagerTabPage> {
|
||||||
labelGetter: DesktopTab.tablabelGetter,
|
labelGetter: DesktopTab.tablabelGetter,
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
return Platform.isMacOS || kUseCompatibleUiMode
|
return isMacOS || kUseCompatibleUiMode
|
||||||
? tabWidget
|
? tabWidget
|
||||||
: SubWindowDragToResizeArea(
|
: SubWindowDragToResizeArea(
|
||||||
child: tabWidget,
|
child: tabWidget,
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:desktop_multi_window/desktop_multi_window.dart';
|
import 'package:desktop_multi_window/desktop_multi_window.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -113,7 +112,7 @@ class _PortForwardTabPageState extends State<PortForwardTabPage> {
|
||||||
labelGetter: DesktopTab.tablabelGetter,
|
labelGetter: DesktopTab.tablabelGetter,
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
return Platform.isMacOS || kUseCompatibleUiMode
|
return isMacOS || kUseCompatibleUiMode
|
||||||
? tabWidget
|
? tabWidget
|
||||||
: Obx(
|
: Obx(
|
||||||
() => SubWindowDragToResizeArea(
|
() => SubWindowDragToResizeArea(
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:desktop_multi_window/desktop_multi_window.dart';
|
import 'package:desktop_multi_window/desktop_multi_window.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -125,7 +124,7 @@ class _RemotePageState extends State<RemotePage>
|
||||||
_ffi.dialogManager
|
_ffi.dialogManager
|
||||||
.showLoading(translate('Connecting...'), onCancel: closeConnection);
|
.showLoading(translate('Connecting...'), onCancel: closeConnection);
|
||||||
});
|
});
|
||||||
if (!Platform.isLinux) {
|
if (!isLinux) {
|
||||||
WakelockPlus.enable();
|
WakelockPlus.enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,7 +159,7 @@ class _RemotePageState extends State<RemotePage>
|
||||||
// On windows, we use `focus` way to handle keyboard better.
|
// On windows, we use `focus` way to handle keyboard better.
|
||||||
// Now on Linux, there's some rdev issues which will break the input.
|
// Now on Linux, there's some rdev issues which will break the input.
|
||||||
// We disable the `focus` way for non-Windows temporarily.
|
// We disable the `focus` way for non-Windows temporarily.
|
||||||
if (Platform.isWindows) {
|
if (isWindows) {
|
||||||
_isWindowBlur = true;
|
_isWindowBlur = true;
|
||||||
// unfocus the primary-focus when the whole window is lost focus,
|
// unfocus the primary-focus when the whole window is lost focus,
|
||||||
// and let OS to handle events instead.
|
// and let OS to handle events instead.
|
||||||
|
@ -172,7 +171,7 @@ class _RemotePageState extends State<RemotePage>
|
||||||
void onWindowFocus() {
|
void onWindowFocus() {
|
||||||
super.onWindowFocus();
|
super.onWindowFocus();
|
||||||
// See [onWindowBlur].
|
// See [onWindowBlur].
|
||||||
if (Platform.isWindows) {
|
if (isWindows) {
|
||||||
_isWindowBlur = false;
|
_isWindowBlur = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,10 +181,10 @@ class _RemotePageState extends State<RemotePage>
|
||||||
super.onWindowRestore();
|
super.onWindowRestore();
|
||||||
// On windows, we use `onWindowRestore` way to handle window restore from
|
// On windows, we use `onWindowRestore` way to handle window restore from
|
||||||
// a minimized state.
|
// a minimized state.
|
||||||
if (Platform.isWindows) {
|
if (isWindows) {
|
||||||
_isWindowBlur = false;
|
_isWindowBlur = false;
|
||||||
}
|
}
|
||||||
if (!Platform.isLinux) {
|
if (!isLinux) {
|
||||||
WakelockPlus.enable();
|
WakelockPlus.enable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -194,7 +193,7 @@ class _RemotePageState extends State<RemotePage>
|
||||||
@override
|
@override
|
||||||
void onWindowMaximize() {
|
void onWindowMaximize() {
|
||||||
super.onWindowMaximize();
|
super.onWindowMaximize();
|
||||||
if (!Platform.isLinux) {
|
if (!isLinux) {
|
||||||
WakelockPlus.enable();
|
WakelockPlus.enable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -202,7 +201,7 @@ class _RemotePageState extends State<RemotePage>
|
||||||
@override
|
@override
|
||||||
void onWindowMinimize() {
|
void onWindowMinimize() {
|
||||||
super.onWindowMinimize();
|
super.onWindowMinimize();
|
||||||
if (!Platform.isLinux) {
|
if (!isLinux) {
|
||||||
WakelockPlus.disable();
|
WakelockPlus.disable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -228,7 +227,7 @@ class _RemotePageState extends State<RemotePage>
|
||||||
await SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
|
await SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
|
||||||
overlays: SystemUiOverlay.values);
|
overlays: SystemUiOverlay.values);
|
||||||
}
|
}
|
||||||
if (!Platform.isLinux) {
|
if (!isLinux) {
|
||||||
await WakelockPlus.disable();
|
await WakelockPlus.disable();
|
||||||
}
|
}
|
||||||
await Get.delete<FFI>(tag: widget.id);
|
await Get.delete<FFI>(tag: widget.id);
|
||||||
|
@ -266,7 +265,7 @@ class _RemotePageState extends State<RemotePage>
|
||||||
debugPrint(
|
debugPrint(
|
||||||
"onFocusChange(window active:${!_isWindowBlur}) $imageFocused");
|
"onFocusChange(window active:${!_isWindowBlur}) $imageFocused");
|
||||||
// See [onWindowBlur].
|
// See [onWindowBlur].
|
||||||
if (Platform.isWindows) {
|
if (isWindows) {
|
||||||
if (_isWindowBlur) {
|
if (_isWindowBlur) {
|
||||||
imageFocused = false;
|
imageFocused = false;
|
||||||
Future.delayed(Duration.zero, () {
|
Future.delayed(Duration.zero, () {
|
||||||
|
@ -362,7 +361,7 @@ class _RemotePageState extends State<RemotePage>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// See [onWindowBlur].
|
// See [onWindowBlur].
|
||||||
if (!Platform.isWindows) {
|
if (!isWindows) {
|
||||||
if (!_rawKeyFocusNode.hasFocus) {
|
if (!_rawKeyFocusNode.hasFocus) {
|
||||||
_rawKeyFocusNode.requestFocus();
|
_rawKeyFocusNode.requestFocus();
|
||||||
}
|
}
|
||||||
|
@ -385,7 +384,7 @@ class _RemotePageState extends State<RemotePage>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// See [onWindowBlur].
|
// See [onWindowBlur].
|
||||||
if (!Platform.isWindows) {
|
if (!isWindows) {
|
||||||
_ffi.inputModel.enterOrLeave(false);
|
_ffi.inputModel.enterOrLeave(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -537,7 +536,7 @@ class _ImagePaintState extends State<ImagePaint> {
|
||||||
double getCursorScale() {
|
double getCursorScale() {
|
||||||
var c = Provider.of<CanvasModel>(context);
|
var c = Provider.of<CanvasModel>(context);
|
||||||
var cursorScale = 1.0;
|
var cursorScale = 1.0;
|
||||||
if (Platform.isWindows) {
|
if (isWindows) {
|
||||||
// debug win10
|
// debug win10
|
||||||
if (zoomCursor.value && isViewAdaptive()) {
|
if (zoomCursor.value && isViewAdaptive()) {
|
||||||
cursorScale = s * c.devicePixelRatio;
|
cursorScale = s * c.devicePixelRatio;
|
||||||
|
@ -604,8 +603,8 @@ class _ImagePaintState extends State<ImagePaint> {
|
||||||
c,
|
c,
|
||||||
s,
|
s,
|
||||||
Offset(
|
Offset(
|
||||||
Platform.isLinux ? c.x.toInt().toDouble() : c.x,
|
isLinux ? c.x.toInt().toDouble() : c.x,
|
||||||
Platform.isLinux ? c.y.toInt().toDouble() : c.y,
|
isLinux ? c.y.toInt().toDouble() : c.y,
|
||||||
),
|
),
|
||||||
c.size,
|
c.size,
|
||||||
isViewOriginal())
|
isViewOriginal())
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:io';
|
|
||||||
import 'dart:ui' as ui;
|
import 'dart:ui' as ui;
|
||||||
|
|
||||||
import 'package:desktop_multi_window/desktop_multi_window.dart';
|
import 'package:desktop_multi_window/desktop_multi_window.dart';
|
||||||
|
@ -127,7 +126,7 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
|
||||||
tryMoveToScreenAndSetFullscreen(screenRect);
|
tryMoveToScreenAndSetFullscreen(screenRect);
|
||||||
if (tabController.length == 0) {
|
if (tabController.length == 0) {
|
||||||
// Show the hidden window.
|
// Show the hidden window.
|
||||||
if (Platform.isMacOS && stateGlobal.closeOnFullscreen == true) {
|
if (isMacOS && stateGlobal.closeOnFullscreen == true) {
|
||||||
stateGlobal.setFullscreen(true);
|
stateGlobal.setFullscreen(true);
|
||||||
}
|
}
|
||||||
// Reset the state
|
// Reset the state
|
||||||
|
@ -328,7 +327,7 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return Platform.isMacOS || kUseCompatibleUiMode
|
return isMacOS || kUseCompatibleUiMode
|
||||||
? tabWidget
|
? tabWidget
|
||||||
: Obx(() => SubWindowDragToResizeArea(
|
: Obx(() => SubWindowDragToResizeArea(
|
||||||
key: contentKey,
|
key: contentKey,
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// original cm window in Sciter version.
|
// original cm window in Sciter version.
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:io';
|
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -52,7 +51,7 @@ class _DesktopServerPageState extends State<DesktopServerPage>
|
||||||
@override
|
@override
|
||||||
void onWindowClose() {
|
void onWindowClose() {
|
||||||
Future.wait([gFFI.serverModel.closeAll(), gFFI.close()]).then((_) {
|
Future.wait([gFFI.serverModel.closeAll(), gFFI.close()]).then((_) {
|
||||||
if (Platform.isMacOS) {
|
if (isMacOS) {
|
||||||
RdPlatformChannel.instance.terminate();
|
RdPlatformChannel.instance.terminate();
|
||||||
} else {
|
} else {
|
||||||
windowManager.setPreventClose(false);
|
windowManager.setPreventClose(false);
|
||||||
|
@ -651,7 +650,7 @@ class _PrivilegeBoardState extends State<_PrivilegeBoard> {
|
||||||
translate('Enable recording session'),
|
translate('Enable recording session'),
|
||||||
),
|
),
|
||||||
// only windows support block input
|
// only windows support block input
|
||||||
if (Platform.isWindows)
|
if (isWindows)
|
||||||
buildPermissionIcon(
|
buildPermissionIcon(
|
||||||
client.blockInput,
|
client.blockInput,
|
||||||
Icons.block,
|
Icons.block,
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hbb/common.dart';
|
import 'package:flutter_hbb/common.dart';
|
||||||
import 'package:flutter_hbb/desktop/pages/remote_tab_page.dart';
|
import 'package:flutter_hbb/desktop/pages/remote_tab_page.dart';
|
||||||
|
@ -28,7 +26,7 @@ class DesktopRemoteScreen extends StatelessWidget {
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
// Set transparent background for padding the resize area out of the flutter view.
|
// Set transparent background for padding the resize area out of the flutter view.
|
||||||
// This allows the wallpaper goes through our resize area. (Linux only now).
|
// This allows the wallpaper goes through our resize area. (Linux only now).
|
||||||
backgroundColor: Platform.isLinux ? Colors.transparent : null,
|
backgroundColor: isLinux ? Colors.transparent : null,
|
||||||
body: ConnectionTabPage(
|
body: ConnectionTabPage(
|
||||||
params: params,
|
params: params,
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import 'dart:io';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:flutter_hbb/consts.dart';
|
import 'package:flutter_hbb/consts.dart';
|
||||||
|
@ -175,9 +174,9 @@ String getLocalPlatformForKBLayoutType(String peerPlatform) {
|
||||||
return localPlatform;
|
return localPlatform;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Platform.isWindows) {
|
if (isWindows) {
|
||||||
localPlatform = kPeerPlatformWindows;
|
localPlatform = kPeerPlatformWindows;
|
||||||
} else if (Platform.isLinux) {
|
} else if (isLinux) {
|
||||||
localPlatform = kPeerPlatformLinux;
|
localPlatform = kPeerPlatformLinux;
|
||||||
}
|
}
|
||||||
// to-do: web desktop support ?
|
// to-do: web desktop support ?
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
@ -112,10 +111,10 @@ class _ToolbarTheme {
|
||||||
static const double iconRadius = 8;
|
static const double iconRadius = 8;
|
||||||
static const double elevation = 3;
|
static const double elevation = 3;
|
||||||
|
|
||||||
static double dividerSpaceToAction = Platform.isWindows ? 8 : 14;
|
static double dividerSpaceToAction = isWindows ? 8 : 14;
|
||||||
|
|
||||||
static double menuBorderRadius = Platform.isWindows ? 5.0 : 7.0;
|
static double menuBorderRadius = isWindows ? 5.0 : 7.0;
|
||||||
static EdgeInsets menuPadding = Platform.isWindows
|
static EdgeInsets menuPadding = isWindows
|
||||||
? EdgeInsets.fromLTRB(4, 12, 4, 12)
|
? EdgeInsets.fromLTRB(4, 12, 4, 12)
|
||||||
: EdgeInsets.fromLTRB(6, 14, 6, 14);
|
: EdgeInsets.fromLTRB(6, 14, 6, 14);
|
||||||
static const double menuButtonBorderRadius = 3.0;
|
static const double menuButtonBorderRadius = 3.0;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:io';
|
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
import 'dart:ui' as ui;
|
import 'dart:ui' as ui;
|
||||||
|
|
||||||
|
@ -392,12 +391,12 @@ class DesktopTab extends StatelessWidget {
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Offstage(
|
Offstage(
|
||||||
offstage: !Platform.isMacOS,
|
offstage: !isMacOS,
|
||||||
child: const SizedBox(
|
child: const SizedBox(
|
||||||
width: 78,
|
width: 78,
|
||||||
)),
|
)),
|
||||||
Offstage(
|
Offstage(
|
||||||
offstage: kUseCompatibleUiMode || Platform.isMacOS,
|
offstage: kUseCompatibleUiMode || isMacOS,
|
||||||
child: Row(children: [
|
child: Row(children: [
|
||||||
Offstage(
|
Offstage(
|
||||||
offstage: !showLogo,
|
offstage: !showLogo,
|
||||||
|
@ -585,7 +584,7 @@ class WindowActionPanelState extends State<WindowActionPanel>
|
||||||
notMainWindowClose(WindowController controller) async {
|
notMainWindowClose(WindowController controller) async {
|
||||||
if (widget.tabController.length != 0) {
|
if (widget.tabController.length != 0) {
|
||||||
debugPrint("close not emtpy multiwindow from taskbar");
|
debugPrint("close not emtpy multiwindow from taskbar");
|
||||||
if (Platform.isWindows) {
|
if (isWindows) {
|
||||||
await controller.show();
|
await controller.show();
|
||||||
await controller.focus();
|
await controller.focus();
|
||||||
final res = await widget.onClose?.call() ?? true;
|
final res = await widget.onClose?.call() ?? true;
|
||||||
|
@ -620,7 +619,7 @@ class WindowActionPanelState extends State<WindowActionPanel>
|
||||||
await rustDeskWinManager.unregisterActiveWindow(kMainWindowId);
|
await rustDeskWinManager.unregisterActiveWindow(kMainWindowId);
|
||||||
}
|
}
|
||||||
// macOS specific workaround, the window is not hiding when in fullscreen.
|
// macOS specific workaround, the window is not hiding when in fullscreen.
|
||||||
if (Platform.isMacOS && await windowManager.isFullScreen()) {
|
if (isMacOS && await windowManager.isFullScreen()) {
|
||||||
stateGlobal.closeOnFullscreen ??= true;
|
stateGlobal.closeOnFullscreen ??= true;
|
||||||
await windowManager.setFullScreen(false);
|
await windowManager.setFullScreen(false);
|
||||||
await macOSWindowClose(
|
await macOSWindowClose(
|
||||||
|
@ -634,7 +633,7 @@ class WindowActionPanelState extends State<WindowActionPanel>
|
||||||
} else {
|
} else {
|
||||||
// it's safe to hide the subwindow
|
// it's safe to hide the subwindow
|
||||||
final controller = WindowController.fromWindowId(kWindowId!);
|
final controller = WindowController.fromWindowId(kWindowId!);
|
||||||
if (Platform.isMacOS) {
|
if (isMacOS) {
|
||||||
// onWindowClose() maybe called multiple times because of loopCloseWindow() in remote_tab_page.dart.
|
// onWindowClose() maybe called multiple times because of loopCloseWindow() in remote_tab_page.dart.
|
||||||
// use ??= to make sure the value is set on first call.
|
// use ??= to make sure the value is set on first call.
|
||||||
|
|
||||||
|
@ -670,7 +669,7 @@ class WindowActionPanelState extends State<WindowActionPanel>
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Offstage(
|
Offstage(
|
||||||
offstage: !widget.showMinimize || Platform.isMacOS,
|
offstage: !widget.showMinimize || isMacOS,
|
||||||
child: ActionIcon(
|
child: ActionIcon(
|
||||||
message: 'Minimize',
|
message: 'Minimize',
|
||||||
icon: IconFont.min,
|
icon: IconFont.min,
|
||||||
|
@ -684,7 +683,7 @@ class WindowActionPanelState extends State<WindowActionPanel>
|
||||||
isClose: false,
|
isClose: false,
|
||||||
)),
|
)),
|
||||||
Offstage(
|
Offstage(
|
||||||
offstage: !widget.showMaximize || Platform.isMacOS,
|
offstage: !widget.showMaximize || isMacOS,
|
||||||
child: Obx(() => ActionIcon(
|
child: Obx(() => ActionIcon(
|
||||||
message: stateGlobal.isMaximized.isTrue
|
message: stateGlobal.isMaximized.isTrue
|
||||||
? 'Restore'
|
? 'Restore'
|
||||||
|
@ -698,7 +697,7 @@ class WindowActionPanelState extends State<WindowActionPanel>
|
||||||
isClose: false,
|
isClose: false,
|
||||||
))),
|
))),
|
||||||
Offstage(
|
Offstage(
|
||||||
offstage: !widget.showClose || Platform.isMacOS,
|
offstage: !widget.showClose || isMacOS,
|
||||||
child: ActionIcon(
|
child: ActionIcon(
|
||||||
message: 'Close',
|
message: 'Close',
|
||||||
icon: IconFont.close,
|
icon: IconFont.close,
|
||||||
|
|
|
@ -48,7 +48,7 @@ Future<void> main(List<String> args) async {
|
||||||
if (args.isNotEmpty && args.first == 'multi_window') {
|
if (args.isNotEmpty && args.first == 'multi_window') {
|
||||||
kWindowId = int.parse(args[1]);
|
kWindowId = int.parse(args[1]);
|
||||||
stateGlobal.setWindowId(kWindowId!);
|
stateGlobal.setWindowId(kWindowId!);
|
||||||
if (!Platform.isMacOS) {
|
if (!isMacOS) {
|
||||||
WindowController.fromWindowId(kWindowId!).showTitleBar(false);
|
WindowController.fromWindowId(kWindowId!).showTitleBar(false);
|
||||||
}
|
}
|
||||||
final argument = args[2].isEmpty
|
final argument = args[2].isEmpty
|
||||||
|
|
|
@ -57,6 +57,7 @@ class _RemotePageState extends State<RemotePage> {
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
gFFI.ffiModel.updateEventListener(sessionId, widget.id);
|
||||||
gFFI.start(
|
gFFI.start(
|
||||||
widget.id,
|
widget.id,
|
||||||
password: widget.password,
|
password: widget.password,
|
||||||
|
@ -69,7 +70,6 @@ class _RemotePageState extends State<RemotePage> {
|
||||||
});
|
});
|
||||||
WakelockPlus.enable();
|
WakelockPlus.enable();
|
||||||
_physicalFocusNode.requestFocus();
|
_physicalFocusNode.requestFocus();
|
||||||
gFFI.ffiModel.updateEventListener(sessionId, widget.id);
|
|
||||||
gFFI.inputModel.listenToMouse(true);
|
gFFI.inputModel.listenToMouse(true);
|
||||||
gFFI.qualityMonitorModel.checkShowQualityMonitor(sessionId);
|
gFFI.qualityMonitorModel.checkShowQualityMonitor(sessionId);
|
||||||
keyboardSubscription =
|
keyboardSubscription =
|
||||||
|
|
|
@ -11,8 +11,8 @@ import 'package:texture_rgba_renderer/texture_rgba_renderer.dart'
|
||||||
if (dart.library.html) 'package:flutter_hbb/web/texture_rgba_renderer.dart';
|
if (dart.library.html) 'package:flutter_hbb/web/texture_rgba_renderer.dart';
|
||||||
|
|
||||||
// Feature flutter_texture_render need to be enabled if feature gpucodec is enabled.
|
// Feature flutter_texture_render need to be enabled if feature gpucodec is enabled.
|
||||||
final useTextureRender =
|
final useTextureRender = !isWeb &&
|
||||||
bind.mainHasPixelbufferTextureRender() || bind.mainHasGpuTextureRender();
|
(bind.mainHasPixelbufferTextureRender() || bind.mainHasGpuTextureRender());
|
||||||
|
|
||||||
class _PixelbufferTexture {
|
class _PixelbufferTexture {
|
||||||
int _textureKey = -1;
|
int _textureKey = -1;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hbb/common.dart';
|
import 'package:flutter_hbb/common.dart';
|
||||||
|
@ -292,7 +291,7 @@ class FileController {
|
||||||
name: isLocal ? "local_show_hidden" : "remote_show_hidden"))
|
name: isLocal ? "local_show_hidden" : "remote_show_hidden"))
|
||||||
.isNotEmpty;
|
.isNotEmpty;
|
||||||
options.value.isWindows = isLocal
|
options.value.isWindows = isLocal
|
||||||
? Platform.isWindows
|
? isWindows
|
||||||
: rootState.target?.ffiModel.pi.platform == kPeerPlatformWindows;
|
: rootState.target?.ffiModel.pi.platform == kPeerPlatformWindows;
|
||||||
|
|
||||||
await Future.delayed(Duration(milliseconds: 100));
|
await Future.delayed(Duration(milliseconds: 100));
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
import 'dart:ui' as ui;
|
import 'dart:ui' as ui;
|
||||||
|
@ -1537,7 +1536,7 @@ class CursorData {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_doubleToInt(oldScale) != _doubleToInt(scale)) {
|
if (_doubleToInt(oldScale) != _doubleToInt(scale)) {
|
||||||
if (Platform.isWindows) {
|
if (isWindows) {
|
||||||
data = img2
|
data = img2
|
||||||
.copyResize(
|
.copyResize(
|
||||||
image,
|
image,
|
||||||
|
@ -1616,7 +1615,7 @@ class PredefinedCursor {
|
||||||
data, defaultImg.width, defaultImg.height, ui.PixelFormat.rgba8888);
|
data, defaultImg.width, defaultImg.height, ui.PixelFormat.rgba8888);
|
||||||
|
|
||||||
double scale = 1.0;
|
double scale = 1.0;
|
||||||
if (Platform.isWindows) {
|
if (isWindows) {
|
||||||
data = _image2!.getBytes(order: img2.ChannelOrder.bgra);
|
data = _image2!.getBytes(order: img2.ChannelOrder.bgra);
|
||||||
} else {
|
} else {
|
||||||
data = Uint8List.fromList(img2.encodePng(_image2!));
|
data = Uint8List.fromList(img2.encodePng(_image2!));
|
||||||
|
@ -1841,7 +1840,7 @@ class CursorModel with ChangeNotifier {
|
||||||
Uint8List? data;
|
Uint8List? data;
|
||||||
img2.Image imgOrigin = img2.Image.fromBytes(
|
img2.Image imgOrigin = img2.Image.fromBytes(
|
||||||
width: w, height: h, bytes: rgba.buffer, order: img2.ChannelOrder.rgba);
|
width: w, height: h, bytes: rgba.buffer, order: img2.ChannelOrder.rgba);
|
||||||
if (Platform.isWindows) {
|
if (isWindows) {
|
||||||
data = imgOrigin.getBytes(order: img2.ChannelOrder.bgra);
|
data = imgOrigin.getBytes(order: img2.ChannelOrder.bgra);
|
||||||
} else {
|
} else {
|
||||||
ByteData? imgBytes =
|
ByteData? imgBytes =
|
||||||
|
@ -2200,6 +2199,7 @@ class FFI {
|
||||||
imageModel.id = id;
|
imageModel.id = id;
|
||||||
cursorModel.peerId = id;
|
cursorModel.peerId = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If tabWindowId != null, this session is a "tab -> window" one.
|
// If tabWindowId != null, this session is a "tab -> window" one.
|
||||||
// Else this session is a new one.
|
// Else this session is a new one.
|
||||||
if (tabWindowId == null) {
|
if (tabWindowId == null) {
|
||||||
|
@ -2235,6 +2235,10 @@ class FFI {
|
||||||
textureModel.updateCurrentDisplay(display ?? 0);
|
textureModel.updateCurrentDisplay(display ?? 0);
|
||||||
}
|
}
|
||||||
final stream = bind.sessionStart(sessionId: sessionId, id: id);
|
final stream = bind.sessionStart(sessionId: sessionId, id: id);
|
||||||
|
if (isWeb) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final cb = ffiModel.startEventListener(sessionId, id);
|
final cb = ffiModel.startEventListener(sessionId, id);
|
||||||
|
|
||||||
// Force refresh displays.
|
// Force refresh displays.
|
||||||
|
|
|
@ -111,13 +111,13 @@ class PlatformFFI {
|
||||||
/// Init the FFI class, loads the native Rust core library.
|
/// Init the FFI class, loads the native Rust core library.
|
||||||
Future<void> init(String appType) async {
|
Future<void> init(String appType) async {
|
||||||
_appType = appType;
|
_appType = appType;
|
||||||
final dylib = Platform.isAndroid
|
final dylib = isAndroid
|
||||||
? DynamicLibrary.open('librustdesk.so')
|
? DynamicLibrary.open('librustdesk.so')
|
||||||
: Platform.isLinux
|
: isLinux
|
||||||
? DynamicLibrary.open('librustdesk.so')
|
? DynamicLibrary.open('librustdesk.so')
|
||||||
: Platform.isWindows
|
: isWindows
|
||||||
? DynamicLibrary.open('librustdesk.dll')
|
? DynamicLibrary.open('librustdesk.dll')
|
||||||
: Platform.isMacOS
|
: isMacOS
|
||||||
? DynamicLibrary.open("liblibrustdesk.dylib")
|
? DynamicLibrary.open("liblibrustdesk.dylib")
|
||||||
: DynamicLibrary.process();
|
: DynamicLibrary.process();
|
||||||
debugPrint('initializing FFI $_appType');
|
debugPrint('initializing FFI $_appType');
|
||||||
|
@ -131,11 +131,11 @@ class PlatformFFI {
|
||||||
}
|
}
|
||||||
_ffiBind = RustdeskImpl(dylib);
|
_ffiBind = RustdeskImpl(dylib);
|
||||||
|
|
||||||
if (Platform.isLinux) {
|
if (isLinux) {
|
||||||
// Start a dbus service, no need to await
|
// Start a dbus service, no need to await
|
||||||
_ffiBind.mainStartDbusServer();
|
_ffiBind.mainStartDbusServer();
|
||||||
_ffiBind.mainStartPa();
|
_ffiBind.mainStartPa();
|
||||||
} else if (Platform.isMacOS && isMain) {
|
} else if (isMacOS && isMain) {
|
||||||
// Start ipc service for uri links.
|
// Start ipc service for uri links.
|
||||||
_ffiBind.mainStartIpcUrlServer();
|
_ffiBind.mainStartIpcUrlServer();
|
||||||
}
|
}
|
||||||
|
@ -155,20 +155,20 @@ class PlatformFFI {
|
||||||
String id = 'NA';
|
String id = 'NA';
|
||||||
String name = 'Flutter';
|
String name = 'Flutter';
|
||||||
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
|
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
|
||||||
if (Platform.isAndroid) {
|
if (isAndroid) {
|
||||||
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
|
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
|
||||||
name = '${androidInfo.brand}-${androidInfo.model}';
|
name = '${androidInfo.brand}-${androidInfo.model}';
|
||||||
id = androidInfo.id.hashCode.toString();
|
id = androidInfo.id.hashCode.toString();
|
||||||
androidVersion = androidInfo.version.sdkInt;
|
androidVersion = androidInfo.version.sdkInt;
|
||||||
} else if (Platform.isIOS) {
|
} else if (isIOS) {
|
||||||
IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
|
IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
|
||||||
name = iosInfo.utsname.machine;
|
name = iosInfo.utsname.machine;
|
||||||
id = iosInfo.identifierForVendor.hashCode.toString();
|
id = iosInfo.identifierForVendor.hashCode.toString();
|
||||||
} else if (Platform.isLinux) {
|
} else if (isLinux) {
|
||||||
LinuxDeviceInfo linuxInfo = await deviceInfo.linuxInfo;
|
LinuxDeviceInfo linuxInfo = await deviceInfo.linuxInfo;
|
||||||
name = linuxInfo.name;
|
name = linuxInfo.name;
|
||||||
id = linuxInfo.machineId ?? linuxInfo.id;
|
id = linuxInfo.machineId ?? linuxInfo.id;
|
||||||
} else if (Platform.isWindows) {
|
} else if (isWindows) {
|
||||||
try {
|
try {
|
||||||
// request windows build number to fix overflow on win7
|
// request windows build number to fix overflow on win7
|
||||||
windowsBuildNumber = getWindowsTargetBuildNumber();
|
windowsBuildNumber = getWindowsTargetBuildNumber();
|
||||||
|
@ -180,7 +180,7 @@ class PlatformFFI {
|
||||||
name = "unknown";
|
name = "unknown";
|
||||||
id = "unknown";
|
id = "unknown";
|
||||||
}
|
}
|
||||||
} else if (Platform.isMacOS) {
|
} else if (isMacOS) {
|
||||||
MacOsDeviceInfo macOsInfo = await deviceInfo.macOsInfo;
|
MacOsDeviceInfo macOsInfo = await deviceInfo.macOsInfo;
|
||||||
name = macOsInfo.computerName;
|
name = macOsInfo.computerName;
|
||||||
id = macOsInfo.systemGUID ?? '';
|
id = macOsInfo.systemGUID ?? '';
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hbb/consts.dart';
|
import 'package:flutter_hbb/consts.dart';
|
||||||
|
@ -383,7 +382,7 @@ class ServerModel with ChangeNotifier {
|
||||||
// ugly is here, because for desktop, below is useless
|
// ugly is here, because for desktop, below is useless
|
||||||
await bind.mainStartService();
|
await bind.mainStartService();
|
||||||
updateClientState();
|
updateClientState();
|
||||||
if (Platform.isAndroid) {
|
if (isAndroid) {
|
||||||
WakelockPlus.enable();
|
WakelockPlus.enable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -395,7 +394,7 @@ class ServerModel with ChangeNotifier {
|
||||||
await parent.target?.invokeMethod("stop_service");
|
await parent.target?.invokeMethod("stop_service");
|
||||||
await bind.mainStopService();
|
await bind.mainStopService();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
if (!Platform.isLinux) {
|
if (!isLinux) {
|
||||||
// current linux is not supported
|
// current linux is not supported
|
||||||
WakelockPlus.disable();
|
WakelockPlus.disable();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:desktop_multi_window/desktop_multi_window.dart';
|
import 'package:desktop_multi_window/desktop_multi_window.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hbb/common.dart';
|
import 'package:flutter_hbb/common.dart';
|
||||||
|
@ -60,7 +58,7 @@ class StateGlobal {
|
||||||
_resizeEdgeSize.value =
|
_resizeEdgeSize.value =
|
||||||
isMaximized.isTrue ? kMaximizeEdgeSize : kWindowEdgeSize;
|
isMaximized.isTrue ? kMaximizeEdgeSize : kWindowEdgeSize;
|
||||||
}
|
}
|
||||||
if (!Platform.isMacOS) {
|
if (!isMacOS) {
|
||||||
_windowBorderWidth.value = v ? 0 : kWindowBorderWidth;
|
_windowBorderWidth.value = v ? 0 : kWindowBorderWidth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,7 +82,7 @@ class StateGlobal {
|
||||||
final wc = WindowController.fromWindowId(windowId);
|
final wc = WindowController.fromWindowId(windowId);
|
||||||
wc.setFullscreen(_fullscreen.isTrue).then((_) {
|
wc.setFullscreen(_fullscreen.isTrue).then((_) {
|
||||||
// https://github.com/leanflutter/window_manager/issues/131#issuecomment-1111587982
|
// https://github.com/leanflutter/window_manager/issues/131#issuecomment-1111587982
|
||||||
if (Platform.isWindows && !v) {
|
if (isWindows && !v) {
|
||||||
Future.delayed(Duration.zero, () async {
|
Future.delayed(Duration.zero, () async {
|
||||||
final frame = await wc.getFrame();
|
final frame = await wc.getFrame();
|
||||||
final newRect = Rect.fromLTWH(
|
final newRect = Rect.fromLTWH(
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:desktop_multi_window/desktop_multi_window.dart';
|
import 'package:desktop_multi_window/desktop_multi_window.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
@ -139,7 +138,7 @@ class RustDeskMultiWindowManager {
|
||||||
overrideType: type,
|
overrideType: type,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if (Platform.isMacOS) {
|
if (isMacOS) {
|
||||||
Future.microtask(() => windowController.show());
|
Future.microtask(() => windowController.show());
|
||||||
}
|
}
|
||||||
registerActiveWindow(windowId);
|
registerActiveWindow(windowId);
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_hbb/main.dart';
|
import 'package:flutter_hbb/main.dart';
|
||||||
|
import 'package:flutter_hbb/common.dart';
|
||||||
|
|
||||||
enum SystemWindowTheme { light, dark }
|
enum SystemWindowTheme { light, dark }
|
||||||
|
|
||||||
|
@ -19,7 +18,7 @@ class RdPlatformChannel {
|
||||||
|
|
||||||
/// Change the theme of the system window
|
/// Change the theme of the system window
|
||||||
Future<void> changeSystemWindowTheme(SystemWindowTheme theme) {
|
Future<void> changeSystemWindowTheme(SystemWindowTheme theme) {
|
||||||
assert(Platform.isMacOS);
|
assert(isMacOS);
|
||||||
if (kDebugMode) {
|
if (kDebugMode) {
|
||||||
print(
|
print(
|
||||||
"[Window ${kWindowId ?? 'Main'}] change system window theme to ${theme.name}");
|
"[Window ${kWindowId ?? 'Main'}] change system window theme to ${theme.name}");
|
||||||
|
@ -30,7 +29,7 @@ class RdPlatformChannel {
|
||||||
|
|
||||||
/// Terminate .app manually.
|
/// Terminate .app manually.
|
||||||
Future<void> terminate() {
|
Future<void> terminate() {
|
||||||
assert(Platform.isMacOS);
|
assert(isMacOS);
|
||||||
return _osxMethodChannel.invokeMethod("terminate");
|
return _osxMethodChannel.invokeMethod("terminate");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,12 +78,19 @@ class RustdeskImpl {
|
||||||
required String password,
|
required String password,
|
||||||
required bool isSharedPassword,
|
required bool isSharedPassword,
|
||||||
dynamic hint}) {
|
dynamic hint}) {
|
||||||
throw UnimplementedError();
|
return js.context.callMethod('setByName', [
|
||||||
|
'session_add_sync',
|
||||||
|
jsonEncode({'id': id, 'password': password})
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream<EventToUI> sessionStart(
|
Stream<EventToUI> sessionStart(
|
||||||
{required UuidValue sessionId, required String id, dynamic hint}) {
|
{required UuidValue sessionId, required String id, dynamic hint}) {
|
||||||
throw UnimplementedError();
|
js.context.callMethod('setByName', [
|
||||||
|
'session_start',
|
||||||
|
jsonEncode({'id': id})
|
||||||
|
]);
|
||||||
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool?> sessionGetRemember(
|
Future<bool?> sessionGetRemember(
|
||||||
|
@ -93,17 +100,19 @@ class RustdeskImpl {
|
||||||
|
|
||||||
Future<bool?> sessionGetToggleOption(
|
Future<bool?> sessionGetToggleOption(
|
||||||
{required UuidValue sessionId, required String arg, dynamic hint}) {
|
{required UuidValue sessionId, required String arg, dynamic hint}) {
|
||||||
throw UnimplementedError();
|
return Future(
|
||||||
|
() => sessionGetToggleOptionSync(sessionId: sessionId, arg: arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sessionGetToggleOptionSync(
|
bool sessionGetToggleOptionSync(
|
||||||
{required UuidValue sessionId, required String arg, dynamic hint}) {
|
{required UuidValue sessionId, required String arg, dynamic hint}) {
|
||||||
throw UnimplementedError();
|
return 'true' == js.context.callMethod('getByName', ['option:toggle', arg]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String?> sessionGetOption(
|
Future<String?> sessionGetOption(
|
||||||
{required UuidValue sessionId, required String arg, dynamic hint}) {
|
{required UuidValue sessionId, required String arg, dynamic hint}) {
|
||||||
throw UnimplementedError();
|
return Future(
|
||||||
|
() => js.context.callMethod('getByName', ['option:peer', arg]));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> sessionLogin(
|
Future<void> sessionLogin(
|
||||||
|
@ -122,7 +131,7 @@ class RustdeskImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> sessionClose({required UuidValue sessionId, dynamic hint}) {
|
Future<void> sessionClose({required UuidValue sessionId, dynamic hint}) {
|
||||||
throw UnimplementedError();
|
return Future(() => js.context.callMethod('setByName', ['session_close']));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> sessionRefresh(
|
Future<void> sessionRefresh(
|
||||||
|
@ -165,7 +174,8 @@ class RustdeskImpl {
|
||||||
|
|
||||||
Future<String?> sessionGetFlutterOption(
|
Future<String?> sessionGetFlutterOption(
|
||||||
{required UuidValue sessionId, required String k, dynamic hint}) {
|
{required UuidValue sessionId, required String k, dynamic hint}) {
|
||||||
throw UnimplementedError();
|
return Future(
|
||||||
|
() => js.context.callMethod('getByName', ['option:flutter:peer', k]));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> sessionSetFlutterOption(
|
Future<void> sessionSetFlutterOption(
|
||||||
|
@ -173,12 +183,16 @@ class RustdeskImpl {
|
||||||
required String k,
|
required String k,
|
||||||
required String v,
|
required String v,
|
||||||
dynamic hint}) {
|
dynamic hint}) {
|
||||||
throw UnimplementedError();
|
return Future(() => js.context.callMethod('setByName', [
|
||||||
|
'option:flutter:peer',
|
||||||
|
jsonEncode({'name': k, 'value': v})
|
||||||
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String?> sessionGetFlutterOptionByPeerId(
|
Future<String?> sessionGetFlutterOptionByPeerId(
|
||||||
{required String id, required String k, dynamic hint}) {
|
{required String id, required String k, dynamic hint}) {
|
||||||
return Future.value(null);
|
return Future(
|
||||||
|
() => js.context.callMethod('getByName', ['option:flutter:peer', k]));
|
||||||
}
|
}
|
||||||
|
|
||||||
int getNextTextureKey({dynamic hint}) {
|
int getNextTextureKey({dynamic hint}) {
|
||||||
|
@ -563,26 +577,30 @@ class RustdeskImpl {
|
||||||
|
|
||||||
Future<void> mainSetOption(
|
Future<void> mainSetOption(
|
||||||
{required String key, required String value, dynamic hint}) {
|
{required String key, required String value, dynamic hint}) {
|
||||||
return js.context.callMethod('setByName', [
|
js.context.callMethod('setByName', [
|
||||||
'option',
|
'option',
|
||||||
jsonEncode({'name': key, 'value': value})
|
jsonEncode({'name': key, 'value': value})
|
||||||
]);
|
]);
|
||||||
|
return Future.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get server settings
|
||||||
Future<String> mainGetOptions({dynamic hint}) {
|
Future<String> mainGetOptions({dynamic hint}) {
|
||||||
throw UnimplementedError();
|
return Future(() => mainGetOptionsSync());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get server settings
|
||||||
String mainGetOptionsSync({dynamic hint}) {
|
String mainGetOptionsSync({dynamic hint}) {
|
||||||
throw UnimplementedError();
|
return js.context.callMethod('getByName', ['options']);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> mainSetOptions({required String json, dynamic hint}) {
|
Future<void> mainSetOptions({required String json, dynamic hint}) {
|
||||||
throw UnimplementedError();
|
return Future(() => js.context.callMethod('setByName', ['options', json]));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> mainTestIfValidServer({required String server, dynamic hint}) {
|
Future<String> mainTestIfValidServer({required String server, dynamic hint}) {
|
||||||
throw UnimplementedError();
|
// TODO: implement
|
||||||
|
return Future.value('');
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> mainSetSocks(
|
Future<void> mainSetSocks(
|
||||||
|
@ -652,7 +670,7 @@ class RustdeskImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> mainGetApiServer({dynamic hint}) {
|
Future<String> mainGetApiServer({dynamic hint}) {
|
||||||
throw UnimplementedError();
|
return Future(() => js.context.callMethod('getByName', ['api_server']));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> mainPostRequest(
|
Future<void> mainPostRequest(
|
||||||
|
@ -809,7 +827,11 @@ class RustdeskImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> mainHandleRelayId({required String id, dynamic hint}) {
|
Future<String> mainHandleRelayId({required String id, dynamic hint}) {
|
||||||
throw UnimplementedError();
|
var newId = id;
|
||||||
|
if (id.endsWith("\\r") || id.endsWith("/r")) {
|
||||||
|
newId = id.substring(0, id.length - 2);
|
||||||
|
}
|
||||||
|
return Future.value(newId);
|
||||||
}
|
}
|
||||||
|
|
||||||
String mainGetMainDisplay({dynamic hint}) {
|
String mainGetMainDisplay({dynamic hint}) {
|
||||||
|
|
|
@ -6,10 +6,12 @@
|
||||||
|
|
||||||
- [x] Outgoing
|
- [x] Outgoing
|
||||||
- [ ] Address book
|
- [ ] Address book
|
||||||
|
- [ ] Force relay
|
||||||
|
|
||||||
### Unsupported
|
### Unsupported
|
||||||
|
|
||||||
1. Incoming
|
1. Incoming
|
||||||
2. LAN
|
2. LAN
|
||||||
|
3. Gpu texture render. We use WebGL instead.
|
||||||
|
|
||||||
### No plans
|
### No plans
|
||||||
|
|
|
@ -6,7 +6,7 @@ import * as sha256 from "fast-sha256";
|
||||||
import * as globals from "./globals";
|
import * as globals from "./globals";
|
||||||
import { decompress, mapKey, sleep } from "./common";
|
import { decompress, mapKey, sleep } from "./common";
|
||||||
|
|
||||||
const PORT = 21116;
|
export const PORT = 21116;
|
||||||
const HOSTS = [
|
const HOSTS = [
|
||||||
"rs-sg.rustdesk.com",
|
"rs-sg.rustdesk.com",
|
||||||
"rs-cn.rustdesk.com",
|
"rs-cn.rustdesk.com",
|
||||||
|
@ -15,7 +15,7 @@ const HOSTS = [
|
||||||
let HOST = localStorage.getItem("rendezvous-server") || HOSTS[0];
|
let HOST = localStorage.getItem("rendezvous-server") || HOSTS[0];
|
||||||
const SCHEMA = "ws://";
|
const SCHEMA = "ws://";
|
||||||
|
|
||||||
type MsgboxCallback = (type: string, title: string, text: string) => void;
|
type MsgboxCallback = (type: string, title: string, text: string, link: string) => void;
|
||||||
type DrawCallback = (data: Uint8Array) => void;
|
type DrawCallback = (data: Uint8Array) => void;
|
||||||
//const cursorCanvas = document.createElement("canvas");
|
//const cursorCanvas = document.createElement("canvas");
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ export default class Connection {
|
||||||
this._msgs = [];
|
this._msgs = [];
|
||||||
this._id = "";
|
this._id = "";
|
||||||
this._videoTestSpeed = [0, 0];
|
this._videoTestSpeed = [0, 0];
|
||||||
|
this._options = {};
|
||||||
//this._cursors = {};
|
//this._cursors = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,8 +319,8 @@ export default class Connection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
msgbox(type_: string, title: string, text: string) {
|
msgbox(type_: string, title: string, text: string, link: string = '') {
|
||||||
this._msgbox?.(type_, title, text);
|
this._msgbox?.(type_, title, text, link);
|
||||||
}
|
}
|
||||||
|
|
||||||
draw(frame: any) {
|
draw(frame: any) {
|
||||||
|
@ -541,9 +542,20 @@ export default class Connection {
|
||||||
return this._options[name];
|
return this._options[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getToggleOption(name: string): Boolean {
|
||||||
|
// TODO: more default settings
|
||||||
|
const defaultToggleTrue = [
|
||||||
|
'show-remote-cursor',
|
||||||
|
'privacy-mode',
|
||||||
|
'enable-file-transfer',
|
||||||
|
'allow_swap_key',
|
||||||
|
];
|
||||||
|
return this._options[name] || (defaultToggleTrue.includes(name) ? true : false);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
getStatus(): String {
|
getStatus(): String {
|
||||||
return JSON.stringify({status_num: 10});
|
return JSON.stringify({ status_num: 10 });
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
|
@ -558,8 +570,10 @@ export default class Connection {
|
||||||
}
|
}
|
||||||
this._options["tm"] = new Date().getTime();
|
this._options["tm"] = new Date().getTime();
|
||||||
const peers = globals.getPeers();
|
const peers = globals.getPeers();
|
||||||
peers[this._id] = this._options;
|
if (peers) {
|
||||||
localStorage.setItem("peers", JSON.stringify(peers));
|
peers[this._id] = this._options;
|
||||||
|
localStorage.setItem("peers", JSON.stringify(peers));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inputKey(
|
inputKey(
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import Connection from "./connection";
|
import Connection from "./connection";
|
||||||
|
import PORT from "./connection";
|
||||||
import _sodium from "libsodium-wrappers";
|
import _sodium from "libsodium-wrappers";
|
||||||
import { CursorData } from "./message";
|
import { CursorData } from "./message";
|
||||||
import { loadVp9 } from "./codec";
|
import { loadVp9 } from "./codec";
|
||||||
|
@ -16,11 +17,11 @@ export function isDesktop() {
|
||||||
return !isMobile();
|
return !isMobile();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function msgbox(type, title, text) {
|
export function msgbox(type, title, text, link) {
|
||||||
if (!type || (type == 'error' && !text)) return;
|
if (!type || (type == 'error' && !text)) return;
|
||||||
const text2 = text.toLowerCase();
|
const text2 = text.toLowerCase();
|
||||||
var hasRetry = checkIfRetry(type, title, text) ? 'true' : '';
|
var hasRetry = checkIfRetry(type, title, text) ? 'true' : '';
|
||||||
onGlobalEvent(JSON.stringify({ name: 'msgbox', type, title, text, hasRetry }));
|
onGlobalEvent(JSON.stringify({ name: 'msgbox', type, title, text, link: link ?? '', hasRetry }));
|
||||||
}
|
}
|
||||||
|
|
||||||
function jsonfyForDart(payload) {
|
function jsonfyForDart(payload) {
|
||||||
|
@ -257,13 +258,17 @@ window.setByName = (name, value) => {
|
||||||
value = JSON.parse(value);
|
value = JSON.parse(value);
|
||||||
localStorage.setItem(value.name, value.value);
|
localStorage.setItem(value.name, value.value);
|
||||||
break;
|
break;
|
||||||
case 'option:local':
|
case 'options':
|
||||||
value = JSON.parse(value);
|
value = JSON.parse(value);
|
||||||
localStorage.setItem('option:local:' + value.name, value.value);
|
for (const [key, value] of Object.entries(value)) {
|
||||||
|
localStorage.setItem(key, value);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'option:local':
|
||||||
case 'option:flutter:local':
|
case 'option:flutter:local':
|
||||||
|
case 'option:flutter:peer':
|
||||||
value = JSON.parse(value);
|
value = JSON.parse(value);
|
||||||
localStorage.setItem('option:flutter:local:' + value.name, value.value);
|
localStorage.setItem(name + ':' + value.name, value.value);
|
||||||
break;
|
break;
|
||||||
case 'peer_option':
|
case 'peer_option':
|
||||||
value = JSON.parse(value);
|
value = JSON.parse(value);
|
||||||
|
@ -281,6 +286,14 @@ window.setByName = (name, value) => {
|
||||||
case 'discover':
|
case 'discover':
|
||||||
// TODO: discover
|
// TODO: discover
|
||||||
break;
|
break;
|
||||||
|
case 'session_add_sync':
|
||||||
|
return sessionAdd(value);
|
||||||
|
case 'session_start':
|
||||||
|
sessionStart(value);
|
||||||
|
break;
|
||||||
|
case 'session_close':
|
||||||
|
sessionClose(value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -317,17 +330,32 @@ function _getByName(name, arg) {
|
||||||
return curConn.getOption(arg) || false;
|
return curConn.getOption(arg) || false;
|
||||||
case 'option':
|
case 'option':
|
||||||
return localStorage.getItem(arg);
|
return localStorage.getItem(arg);
|
||||||
|
case 'options':
|
||||||
|
const keys = [
|
||||||
|
'custom-rendezvous-server',
|
||||||
|
'relay-server',
|
||||||
|
'api-server',
|
||||||
|
'key'
|
||||||
|
];
|
||||||
|
const obj = {};
|
||||||
|
keys.forEach(key => {
|
||||||
|
const v = localStorage.getItem(key);
|
||||||
|
if (v) obj[key] = v;
|
||||||
|
});
|
||||||
|
return JSON.stringify(obj);
|
||||||
case 'option:local':
|
case 'option:local':
|
||||||
return localStorage.getItem('option:local:' + arg);
|
|
||||||
case 'option:flutter:local':
|
case 'option:flutter:local':
|
||||||
return localStorage.getItem('option:flutter:local:' + arg);
|
case 'option:flutter:peer':
|
||||||
|
return localStorage.getItem(name + ':' + arg);
|
||||||
case 'image_quality':
|
case 'image_quality':
|
||||||
return curConn.getImageQuality();
|
return curConn.getImageQuality();
|
||||||
case 'translate':
|
case 'translate':
|
||||||
arg = JSON.parse(arg);
|
arg = JSON.parse(arg);
|
||||||
return translate(arg.locale, arg.text);
|
return translate(arg.locale, arg.text);
|
||||||
case 'peer_option':
|
case 'option:peer':
|
||||||
return curConn.getOption(arg);
|
return curConn.getOption(arg);
|
||||||
|
case 'option:toggle':
|
||||||
|
return curConn.getToggleOption(arg);
|
||||||
case 'get_conn_status':
|
case 'get_conn_status':
|
||||||
if (curConn) {
|
if (curConn) {
|
||||||
return curConn.getStatus();
|
return curConn.getStatus();
|
||||||
|
@ -360,6 +388,8 @@ function _getByName(name, arg) {
|
||||||
return localStorage.getItem('peers-recent') ?? '{}';
|
return localStorage.getItem('peers-recent') ?? '{}';
|
||||||
case 'load_lan_peers_sync':
|
case 'load_lan_peers_sync':
|
||||||
return localStorage.getItem('peers-lan') ?? '{}';
|
return localStorage.getItem('peers-lan') ?? '{}';
|
||||||
|
case 'api_server':
|
||||||
|
return getApiServer();
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
@ -391,15 +421,15 @@ window.init = async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getPeers() {
|
export function getPeers() {
|
||||||
return _getJsonObj('peers');
|
return getJsonObj('peers');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getRecentPeers() {
|
export function getRecentPeers() {
|
||||||
return _getJsonObj('peers-recent');
|
return getJsonObj('peers-recent');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getLanPeers() {
|
export function getLanPeers() {
|
||||||
return _getJsonObj('peers-lan');
|
return getJsonObj('peers-lan');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getJsonObj(key) {
|
export function getJsonObj(key) {
|
||||||
|
@ -456,3 +486,94 @@ function removeDiscovered(id) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ========================== peers end ===========================
|
// ========================== peers end ===========================
|
||||||
|
|
||||||
|
// ========================== session begin ==========================
|
||||||
|
function sessionAdd(value) {
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(value);
|
||||||
|
window.curConn?.close();
|
||||||
|
const conn = new Connection();
|
||||||
|
if (data['password']) {
|
||||||
|
// TODO: encrypt password
|
||||||
|
conn.setOption('password', data['password'])
|
||||||
|
} else {
|
||||||
|
conn.setOption('password', undefined);
|
||||||
|
}
|
||||||
|
setConn(conn);
|
||||||
|
return '';
|
||||||
|
} catch (e) {
|
||||||
|
return e.message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function sessionStart(value) {
|
||||||
|
try {
|
||||||
|
const conn = getConn();
|
||||||
|
if (!conn) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = JSON.parse(value);
|
||||||
|
if (data['id']) {
|
||||||
|
startConn(data['id']);
|
||||||
|
} else {
|
||||||
|
msgbox('error', 'Error', 'No id found in session data ' + value, '');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// TODO: better error handling
|
||||||
|
msgbox('error', 'Error', e.message, '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function sessionClose(value) {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
// ========================== session end ===========================
|
||||||
|
|
||||||
|
// ========================== settings begin ==========================
|
||||||
|
function increasePort(host, offset) {
|
||||||
|
function isIPv6(str) {
|
||||||
|
const ipv6Pattern = /^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}$/;
|
||||||
|
return ipv6Pattern.test(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isIPv6(host)) {
|
||||||
|
if (host.startsWith('[')) {
|
||||||
|
let tmp = host.split(']:');
|
||||||
|
if (tmp.length === 2) {
|
||||||
|
let port = parseInt(tmp[1]) || 0;
|
||||||
|
if (port > 0) {
|
||||||
|
return `${tmp[0]}]:${port + offset}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (host.includes(':')) {
|
||||||
|
let tmp = host.split(':');
|
||||||
|
if (tmp.length === 2) {
|
||||||
|
let port = parseInt(tmp[1]) || 0;
|
||||||
|
if (port > 0) {
|
||||||
|
return `${tmp[0]}:${port + offset}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getApiServer() {
|
||||||
|
const api_server = localStorage.getItem('api-server');
|
||||||
|
if (api_server) {
|
||||||
|
return api_server;
|
||||||
|
}
|
||||||
|
|
||||||
|
const custom_rendezvous_server = localStorage.getItem('custom-rendezvous-server');
|
||||||
|
if (custom_rendezvous_server) {
|
||||||
|
let s = increasePort(custom_rendezvous_server, -2);
|
||||||
|
if (s == custom_rendezvous_server) {
|
||||||
|
return `http://${s}:${PORT - 2}`;
|
||||||
|
} else {
|
||||||
|
return `http://${s}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 'https://admin.rustdesk.com';
|
||||||
|
}
|
||||||
|
// ========================== settings end ===========================
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue