Skip to content

Commit

Permalink
Feat. Quick support, ui (rustdesk#7267)
Browse files Browse the repository at this point in the history
* Feat. QS ui

Signed-off-by: fufesou <[email protected]>

* Remove 'Quick support'

Signed-off-by: fufesou <[email protected]>

* add help card

Signed-off-by: fufesou <[email protected]>

* use addPostFrameCallback to get child size

Signed-off-by: fufesou <[email protected]>

* Fix. qs, set home window size

Signed-off-by: fufesou <[email protected]>

* Qs, set setResizable for settings page

Signed-off-by: fufesou <[email protected]>

* Qs, help cards margin bottom

Signed-off-by: fufesou <[email protected]>

* Qs, online status, padding

Signed-off-by: fufesou <[email protected]>

* Qs, online status, padding

Signed-off-by: fufesou <[email protected]>

* Qs, online status, use margin instead of padding

Signed-off-by: fufesou <[email protected]>

* Qs, fix, start cm window

Signed-off-by: fufesou <[email protected]>

---------

Signed-off-by: fufesou <[email protected]>
  • Loading branch information
fufesou authored Feb 27, 2024
1 parent 1d9b178 commit e6953c8
Show file tree
Hide file tree
Showing 11 changed files with 328 additions and 200 deletions.
37 changes: 28 additions & 9 deletions flutter/lib/common.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1521,6 +1521,9 @@ class LastWindowPosition {
}
}

String get windowFramePrefix =>
bind.isQs() ? "${kWindowPrefix}qs_" : kWindowPrefix;

/// Save window position and size on exit
/// Note that windowId must be provided if it's subwindow
Future<void> saveWindowPosition(WindowType type, {int? windowId}) async {
Expand All @@ -1536,7 +1539,7 @@ Future<void> saveWindowPosition(WindowType type, {int? windowId}) async {
(Platform.isMacOS && stateGlobal.closeOnFullscreen == true);
setFrameIfMaximized() {
if (isMaximized) {
final pos = bind.getLocalFlutterOption(k: kWindowPrefix + type.name);
final pos = bind.getLocalFlutterOption(k: windowFramePrefix + type.name);
var lpos = LastWindowPosition.loadFromString(pos);
position = Offset(
lpos?.offsetWidth ?? position.dx, lpos?.offsetHeight ?? position.dy);
Expand Down Expand Up @@ -1584,7 +1587,7 @@ Future<void> saveWindowPosition(WindowType type, {int? windowId}) async {
"Saving frame: $windowId: ${pos.width}/${pos.height}, offset:${pos.offsetWidth}/${pos.offsetHeight}, isMaximized:${pos.isMaximized}, isFullscreen:${pos.isFullscreen}");

await bind.setLocalFlutterOption(
k: kWindowPrefix + type.name, v: pos.toString());
k: windowFramePrefix + type.name, v: pos.toString());

if (type == WindowType.RemoteDesktop && windowId != null) {
await _saveSessionWindowPosition(
Expand All @@ -1599,7 +1602,7 @@ Future _saveSessionWindowPosition(WindowType windowType, int windowId,
getPeerPos(String peerId) {
if (isMaximized) {
final peerPos = bind.mainGetPeerFlutterOptionSync(
id: peerId, k: kWindowPrefix + windowType.name);
id: peerId, k: windowFramePrefix + windowType.name);
var lpos = LastWindowPosition.loadFromString(peerPos);
return LastWindowPosition(
lpos?.width ?? pos.offsetWidth,
Expand All @@ -1618,7 +1621,7 @@ Future _saveSessionWindowPosition(WindowType windowType, int windowId,
for (final peerId in remoteList.split(',')) {
bind.mainSetPeerFlutterOptionSync(
id: peerId,
k: kWindowPrefix + windowType.name,
k: windowFramePrefix + windowType.name,
v: getPeerPos(peerId));
}
}
Expand Down Expand Up @@ -1736,14 +1739,14 @@ Future<bool> restoreWindowPosition(WindowType type,
// Because the session may not be read at this time.
if (desktopType == DesktopType.main) {
pos = bind.mainGetPeerFlutterOptionSync(
id: peerId, k: kWindowPrefix + type.name);
id: peerId, k: windowFramePrefix + type.name);
} else {
pos = await bind.sessionGetFlutterOptionByPeerId(
id: peerId, k: kWindowPrefix + type.name);
id: peerId, k: windowFramePrefix + type.name);
}
isRemotePeerPos = pos != null;
}
pos ??= bind.getLocalFlutterOption(k: kWindowPrefix + type.name);
pos ??= bind.getLocalFlutterOption(k: windowFramePrefix + type.name);

var lpos = LastWindowPosition.loadFromString(pos);
if (lpos == null) {
Expand Down Expand Up @@ -1790,9 +1793,13 @@ Future<bool> restoreWindowPosition(WindowType type,
}
if (lpos.isMaximized == true) {
await restorePos();
await windowManager.maximize();
if (!bind.isQs()) {
await windowManager.maximize();
}
} else {
await windowManager.setSize(size);
if (!bind.isQs()) {
await windowManager.setSize(size);
}
await restorePos();
}
return true;
Expand Down Expand Up @@ -3082,3 +3089,15 @@ Widget loadLogo(double size) {
height: size,
));
}

var desktopQsHomeLeftPaneSize = Size(280, 300);
Size getDesktopQsHomeSize() {
final magicWidth = 11.0;
final magicHeight = 8.0;
return desktopQsHomeLeftPaneSize +
Offset(magicWidth, kDesktopRemoteTabBarHeight + magicHeight);
}

Size getDesktopQsSettingsSize() {
return Size(768, 600);
}
256 changes: 139 additions & 117 deletions flutter/lib/desktop/pages/connection_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,144 @@ import '../../common/widgets/autocomplete.dart';
import '../../models/platform_model.dart';
import '../widgets/button.dart';

class OnlineStatusWidget extends StatefulWidget {
const OnlineStatusWidget({Key? key}) : super(key: key);

@override
State<OnlineStatusWidget> createState() => _OnlineStatusWidgetState();
}

/// State for the connection page.
class _OnlineStatusWidgetState extends State<OnlineStatusWidget> {
final _svcStopped = Get.find<RxBool>(tag: 'stop-service');
final _svcIsUsingPublicServer = true.obs;
Timer? _updateTimer;

double get em => 14.0;
double get height => em * 3;

void onUsePublicServerGuide() {
const url = "https://rustdesk.com/pricing.html";
canLaunchUrlString(url).then((can) {
if (can) {
launchUrlString(url);
}
});
}

@override
void initState() {
super.initState();
_updateTimer = periodic_immediate(Duration(seconds: 1), () async {
updateStatus();
});
}

@override
void dispose() {
_updateTimer?.cancel();
super.dispose();
}

@override
Widget build(BuildContext context) {
return Container(
height: height,
child: Obx(() => Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
height: 8,
width: 8,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
color: _svcStopped.value ||
stateGlobal.svcStatus.value == SvcStatus.connecting
? kColorWarn
: (stateGlobal.svcStatus.value == SvcStatus.ready
? Color.fromARGB(255, 50, 190, 166)
: Color.fromARGB(255, 224, 79, 95)),
),
).marginSymmetric(horizontal: em),
Text(
_svcStopped.value
? translate("Service is not running")
: stateGlobal.svcStatus.value == SvcStatus.connecting
? translate("connecting_status")
: stateGlobal.svcStatus.value == SvcStatus.notReady
? translate("not_ready_status")
: translate('Ready'),
style: TextStyle(fontSize: em)),
// stop
Offstage(
offstage: !_svcStopped.value,
child: InkWell(
onTap: () async {
await start_service(true);
},
child: Text(translate("Start service"),
style: TextStyle(
decoration: TextDecoration.underline,
fontSize: em)))
.marginOnly(left: em),
),
// ready && public
Flexible(
child: Offstage(
offstage: !(!_svcStopped.value &&
stateGlobal.svcStatus.value == SvcStatus.ready &&
_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),
),
),
],
),
),
)
],
),
),
)
],
)),
).paddingOnly(right: bind.isQs() ? 8 : 0);
}

updateStatus() async {
final status =
jsonDecode(await bind.mainGetConnectStatus()) as Map<String, dynamic>;
final statusNum = status['status_num'] as int;
final preStatus = stateGlobal.svcStatus.value;
if (statusNum == 0) {
stateGlobal.svcStatus.value = SvcStatus.connecting;
} else if (statusNum == -1) {
stateGlobal.svcStatus.value = SvcStatus.notReady;
} else if (statusNum == 1) {
stateGlobal.svcStatus.value = SvcStatus.ready;
if (preStatus != SvcStatus.ready) {
gFFI.userModel.refreshCurrentUser();
}
} else {
stateGlobal.svcStatus.value = SvcStatus.notReady;
}
_svcIsUsingPublicServer.value = await bind.mainIsUsingPublicServer();
}
}

/// Connection page for connecting to a remote peer.
class ConnectionPage extends StatefulWidget {
const ConnectionPage({Key? key}) : super(key: key);
Expand All @@ -34,13 +172,8 @@ class _ConnectionPageState extends State<ConnectionPage>
/// Controller for the id input bar.
final _idController = IDTextEditingController();

Timer? _updateTimer;

final RxBool _idInputFocused = false.obs;

var svcStopped = Get.find<RxBool>(tag: 'stop-service');
var svcIsUsingPublicServer = true.obs;

bool isWindowMinimized = false;
List<Peer> peers = [];

Expand All @@ -60,17 +193,13 @@ class _ConnectionPageState extends State<ConnectionPage>
}
}();
}
_updateTimer = periodic_immediate(Duration(seconds: 1), () async {
updateStatus();
});
Get.put<IDTextEditingController>(_idController);
windowManager.addListener(this);
}

@override
void dispose() {
_idController.dispose();
_updateTimer?.cancel();
windowManager.removeListener(this);
if (Get.isRegistered<IDTextEditingController>()) {
Get.delete<IDTextEditingController>();
Expand Down Expand Up @@ -132,7 +261,7 @@ class _ConnectionPageState extends State<ConnectionPage>
],
).paddingOnly(left: 12.0)),
const Divider(height: 1),
buildStatus()
OnlineStatusWidget()
],
);
}
Expand Down Expand Up @@ -383,111 +512,4 @@ class _ConnectionPageState extends State<ConnectionPage>
return Container(
constraints: const BoxConstraints(maxWidth: 600), child: w);
}

Widget buildStatus() {
final em = 14.0;
return Container(
height: 3 * em,
child: Obx(() => Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
height: 8,
width: 8,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
color: svcStopped.value ||
stateGlobal.svcStatus.value == SvcStatus.connecting
? kColorWarn
: (stateGlobal.svcStatus.value == SvcStatus.ready
? Color.fromARGB(255, 50, 190, 166)
: Color.fromARGB(255, 224, 79, 95)),
),
).marginSymmetric(horizontal: em),
Text(
svcStopped.value
? translate("Service is not running")
: stateGlobal.svcStatus.value == SvcStatus.connecting
? translate("connecting_status")
: stateGlobal.svcStatus.value == SvcStatus.notReady
? translate("not_ready_status")
: translate('Ready'),
style: TextStyle(fontSize: em)),
// stop
Offstage(
offstage: !svcStopped.value,
child: InkWell(
onTap: () async {
await start_service(true);
},
child: Text(translate("Start service"),
style: TextStyle(
decoration: TextDecoration.underline,
fontSize: em)))
.marginOnly(left: em),
),
// ready && public
Flexible(
child: Offstage(
offstage: !(!svcStopped.value &&
stateGlobal.svcStatus.value == SvcStatus.ready &&
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),
),
),
],
),
),
)
],
),
),
)
],
)),
);
}

void onUsePublicServerGuide() {
const url = "https://rustdesk.com/pricing.html";
canLaunchUrlString(url).then((can) {
if (can) {
launchUrlString(url);
}
});
}

updateStatus() async {
final status =
jsonDecode(await bind.mainGetConnectStatus()) as Map<String, dynamic>;
final statusNum = status['status_num'] as int;
final preStatus = stateGlobal.svcStatus.value;
if (statusNum == 0) {
stateGlobal.svcStatus.value = SvcStatus.connecting;
} else if (statusNum == -1) {
stateGlobal.svcStatus.value = SvcStatus.notReady;
} else if (statusNum == 1) {
stateGlobal.svcStatus.value = SvcStatus.ready;
if (preStatus != SvcStatus.ready) {
gFFI.userModel.refreshCurrentUser();
}
} else {
stateGlobal.svcStatus.value = SvcStatus.notReady;
}
svcIsUsingPublicServer.value = await bind.mainIsUsingPublicServer();
}
}
Loading

0 comments on commit e6953c8

Please sign in to comment.