Merge pull request #1409 from 21pages/remote-modification

option remote modification
This commit is contained in:
RustDesk 2022-08-31 15:40:57 +08:00 committed by GitHub
commit 1e07a604e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 123 additions and 40 deletions

View File

@ -664,8 +664,6 @@ Future<void> initGlobalFFI() async {
debugPrint("_globalFFI init end"); debugPrint("_globalFFI init end");
// after `put`, can also be globally found by Get.find<FFI>(); // after `put`, can also be globally found by Get.find<FFI>();
Get.put(_globalFFI, permanent: true); Get.put(_globalFFI, permanent: true);
// trigger connection status updater
await bind.mainCheckConnectStatus();
// global shared preference // global shared preference
await Get.putAsync(() => SharedPreferences.getInstance()); await Get.putAsync(() => SharedPreferences.getInstance());
} }

View File

@ -233,7 +233,6 @@ class _ConnectionPageState extends State<ConnectionPage> {
}, },
child: Container( child: Container(
height: 24, height: 24,
width: 72,
alignment: Alignment.center, alignment: Alignment.center,
decoration: BoxDecoration( decoration: BoxDecoration(
color: ftPressed.value color: ftPressed.value
@ -257,7 +256,7 @@ class _ConnectionPageState extends State<ConnectionPage> {
color: ftPressed.value color: ftPressed.value
? MyTheme.color(context).bg ? MyTheme.color(context).bg
: MyTheme.color(context).text), : MyTheme.color(context).text),
), ).marginSymmetric(horizontal: 12),
), ),
)), )),
SizedBox( SizedBox(
@ -272,7 +271,6 @@ class _ConnectionPageState extends State<ConnectionPage> {
onTap: onConnect, onTap: onConnect,
child: Container( child: Container(
height: 24, height: 24,
width: 65,
decoration: BoxDecoration( decoration: BoxDecoration(
color: connPressed.value color: connPressed.value
? MyTheme.accent ? MyTheme.accent
@ -289,12 +287,12 @@ class _ConnectionPageState extends State<ConnectionPage> {
child: Center( child: Center(
child: Text( child: Text(
translate( translate(
"Connection", "Connect",
), ),
style: TextStyle( style: TextStyle(
fontSize: 12, color: MyTheme.color(context).bg), fontSize: 12, color: MyTheme.color(context).bg),
), ),
), ).marginSymmetric(horizontal: 12),
), ),
), ),
), ),

View File

@ -93,7 +93,7 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
body: Obx(() => DesktopTab( body: Obx(() => DesktopTab(
controller: tabController, controller: tabController,
theme: theme, theme: theme,
isMainWindow: false, tabType: DesktopTabType.remoteScreen,
showTabBar: fullscreen.isFalse, showTabBar: fullscreen.isFalse,
onClose: () { onClose: () {
tabController.clear(); tabController.clear();

View File

@ -46,7 +46,7 @@ class _DesktopTabPageState extends State<DesktopTabPage> {
body: DesktopTab( body: DesktopTab(
controller: tabController, controller: tabController,
theme: dark ? TarBarTheme.dark() : TarBarTheme.light(), theme: dark ? TarBarTheme.dark() : TarBarTheme.light(),
isMainWindow: true, tabType: DesktopTabType.main,
tail: ActionIcon( tail: ActionIcon(
message: 'Settings', message: 'Settings',
icon: IconFont.menu, icon: IconFont.menu,

View File

@ -37,7 +37,7 @@ class _FileManagerTabPageState extends State<FileManagerTabPage> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
tabController.onRemove = (_, id) => onRemoveId(id); tabController.onRemove = (_, id) => onRemoveId(id);
rustDeskWinManager.setMethodHandler((call, fromWindowId) async { rustDeskWinManager.setMethodHandler((call, fromWindowId) async {
@ -74,9 +74,9 @@ class _FileManagerTabPageState extends State<FileManagerTabPage> {
body: DesktopTab( body: DesktopTab(
controller: tabController, controller: tabController,
theme: theme, theme: theme,
isMainWindow: false, tabType: DesktopTabType.fileTransfer,
onClose: () { onClose: () {
tabController.clear(); tabController.clear();
}, },
tail: AddButton( tail: AddButton(
theme: theme, theme: theme,

View File

@ -19,11 +19,13 @@ class PortForwardTabPage extends StatefulWidget {
class _PortForwardTabPageState extends State<PortForwardTabPage> { class _PortForwardTabPageState extends State<PortForwardTabPage> {
final tabController = Get.put(DesktopTabController()); final tabController = Get.put(DesktopTabController());
late final bool isRDP;
static final IconData selectedIcon = Icons.forward_sharp; static const IconData selectedIcon = Icons.forward_sharp;
static final IconData unselectedIcon = Icons.forward_outlined; static const IconData unselectedIcon = Icons.forward_outlined;
_PortForwardTabPageState(Map<String, dynamic> params) { _PortForwardTabPageState(Map<String, dynamic> params) {
isRDP = params['isRDP'];
tabController.add(TabInfo( tabController.add(TabInfo(
key: params['id'], key: params['id'],
label: params['id'], label: params['id'],
@ -32,7 +34,7 @@ class _PortForwardTabPageState extends State<PortForwardTabPage> {
page: PortForwardPage( page: PortForwardPage(
key: ValueKey(params['id']), key: ValueKey(params['id']),
id: params['id'], id: params['id'],
isRDP: params['isRDP'], isRDP: isRDP,
))); )));
} }
@ -76,7 +78,7 @@ class _PortForwardTabPageState extends State<PortForwardTabPage> {
body: DesktopTab( body: DesktopTab(
controller: tabController, controller: tabController,
theme: theme, theme: theme,
isMainWindow: false, tabType: isRDP ? DesktopTabType.rdp : DesktopTabType.portForward,
onClose: () { onClose: () {
tabController.clear(); tabController.clear();
}, },

View File

@ -111,7 +111,7 @@ class ConnectionManagerState extends State<ConnectionManager> {
showMaximize: false, showMaximize: false,
showMinimize: false, showMinimize: false,
controller: serverModel.tabController, controller: serverModel.tabController,
isMainWindow: true, tabType: DesktopTabType.cm,
pageViewBuilder: (pageView) => Row(children: [ pageViewBuilder: (pageView) => Row(children: [
Expanded(child: pageView), Expanded(child: pageView),
Consumer<ChatModel>( Consumer<ChatModel>(
@ -294,7 +294,8 @@ class _CmHeaderState extends State<_CmHeader>
Offstage( Offstage(
offstage: client.isFileTransfer, offstage: client.isFileTransfer,
child: IconButton( child: IconButton(
onPressed: () => gFFI.chatModel.toggleCMChatPage(client.id), onPressed: () => checkClickTime(
client.id, () => gFFI.chatModel.toggleCMChatPage(client.id)),
icon: Icon(Icons.message_outlined), icon: Icon(Icons.message_outlined),
), ),
) )
@ -326,7 +327,8 @@ class _PrivilegeBoardState extends State<_PrivilegeBoard> {
BoxDecoration(color: enabled ? MyTheme.accent80 : Colors.grey), BoxDecoration(color: enabled ? MyTheme.accent80 : Colors.grey),
padding: EdgeInsets.all(4.0), padding: EdgeInsets.all(4.0),
child: InkWell( child: InkWell(
onTap: () => onTap?.call(!enabled), onTap: () =>
checkClickTime(widget.client.id, () => onTap?.call(!enabled)),
child: Image( child: Image(
image: icon, image: icon,
width: 50, width: 50,
@ -422,7 +424,8 @@ class _CmControlPanel extends StatelessWidget {
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.redAccent, borderRadius: BorderRadius.circular(10)), color: Colors.redAccent, borderRadius: BorderRadius.circular(10)),
child: InkWell( child: InkWell(
onTap: () => handleDisconnect(context), onTap: () =>
checkClickTime(client.id, () => handleDisconnect(context)),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
@ -447,7 +450,8 @@ class _CmControlPanel extends StatelessWidget {
decoration: BoxDecoration( decoration: BoxDecoration(
color: MyTheme.accent, borderRadius: BorderRadius.circular(10)), color: MyTheme.accent, borderRadius: BorderRadius.circular(10)),
child: InkWell( child: InkWell(
onTap: () => handleAccept(context), onTap: () =>
checkClickTime(client.id, () => handleAccept(context)),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
@ -469,7 +473,8 @@ class _CmControlPanel extends StatelessWidget {
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.grey)), border: Border.all(color: Colors.grey)),
child: InkWell( child: InkWell(
onTap: () => handleDisconnect(context), onTap: () =>
checkClickTime(client.id, () => handleDisconnect(context)),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
@ -572,3 +577,12 @@ Widget clientInfo(Client client) {
), ),
])); ]));
} }
void checkClickTime(int id, Function() callback) async {
var clickCallbackTime = DateTime.now().millisecondsSinceEpoch;
await bind.cmCheckClickTime(connId: id);
Timer(const Duration(milliseconds: 120), () async {
var d = clickCallbackTime - await bind.cmGetClickTime();
if (d > 120) callback();
});
}

View File

@ -1,4 +1,5 @@
import 'dart:io'; import 'dart:io';
import 'dart:async';
import 'dart:math'; import 'dart:math';
import 'package:desktop_multi_window/desktop_multi_window.dart'; import 'package:desktop_multi_window/desktop_multi_window.dart';
@ -6,6 +7,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_hbb/common.dart'; import 'package:flutter_hbb/common.dart';
import 'package:flutter_hbb/consts.dart'; import 'package:flutter_hbb/consts.dart';
import 'package:flutter_hbb/main.dart'; import 'package:flutter_hbb/main.dart';
import 'package:flutter_hbb/models/platform_model.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:scroll_pos/scroll_pos.dart'; import 'package:scroll_pos/scroll_pos.dart';
import 'package:window_manager/window_manager.dart'; import 'package:window_manager/window_manager.dart';
@ -34,6 +36,15 @@ class TabInfo {
required this.page}); required this.page});
} }
enum DesktopTabType {
main,
cm,
remoteScreen,
fileTransfer,
portForward,
rdp,
}
class DesktopTabState { class DesktopTabState {
final List<TabInfo> tabs = []; final List<TabInfo> tabs = [];
final ScrollPosController scrollController = final ScrollPosController scrollController =
@ -64,6 +75,7 @@ class DesktopTabController {
state.update((val) { state.update((val) {
val!.tabs.add(tab); val!.tabs.add(tab);
}); });
state.value.scrollController.itemCount = state.value.tabs.length;
toIndex = state.value.tabs.length - 1; toIndex = state.value.tabs.length - 1;
assert(toIndex >= 0); assert(toIndex >= 0);
} }
@ -96,8 +108,16 @@ class DesktopTabController {
void jumpTo(int index) { void jumpTo(int index) {
state.update((val) { state.update((val) {
val!.selected = index; val!.selected = index;
val.pageController.jumpToPage(index); Future.delayed(Duration.zero, (() {
val.scrollController.scrollToItem(index, center: true, animate: true); if (val.pageController.hasClients) {
val.pageController.jumpToPage(index);
}
if (val.scrollController.hasClients &&
val.scrollController.canScroll &&
val.scrollController.itemCount >= index) {
val.scrollController.scrollToItem(index, center: true, animate: true);
}
}));
}); });
onSelected?.call(index); onSelected?.call(index);
} }
@ -134,6 +154,7 @@ typedef LabelGetter = Rx<String> Function(String key);
class DesktopTab extends StatelessWidget { class DesktopTab extends StatelessWidget {
final Function(String)? onTabClose; final Function(String)? onTabClose;
final TarBarTheme theme; final TarBarTheme theme;
final DesktopTabType tabType;
final bool isMainWindow; final bool isMainWindow;
final bool showTabBar; final bool showTabBar;
final bool showLogo; final bool showLogo;
@ -152,7 +173,7 @@ class DesktopTab extends StatelessWidget {
const DesktopTab({ const DesktopTab({
required this.controller, required this.controller,
required this.isMainWindow, required this.tabType,
this.theme = const TarBarTheme.light(), this.theme = const TarBarTheme.light(),
this.onTabClose, this.onTabClose,
this.showTabBar = true, this.showTabBar = true,
@ -166,7 +187,8 @@ class DesktopTab extends StatelessWidget {
this.onClose, this.onClose,
this.tabBuilder, this.tabBuilder,
this.labelGetter, this.labelGetter,
}); }) : isMainWindow =
tabType == DesktopTabType.main || tabType == DesktopTabType.cm;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -195,11 +217,48 @@ class DesktopTab extends StatelessWidget {
]); ]);
} }
Widget _buildBlock({required Widget child}) {
if (tabType != DesktopTabType.main) {
return child;
}
var block = false.obs;
return Obx(() => MouseRegion(
onEnter: (_) async {
if (!option2bool(
'allow-remote-config-modification',
await bind.mainGetOption(
key: 'allow-remote-config-modification'))) {
var time0 = DateTime.now().millisecondsSinceEpoch;
await bind.mainCheckMouseTime();
Timer(const Duration(milliseconds: 120), () async {
var d = time0 - await bind.mainGetMouseTime();
if (d < 120) {
block.value = true;
}
});
}
},
onExit: (_) => block.value = false,
child: Stack(
children: [
child,
Offstage(
offstage: !block.value,
child: Container(
color: Colors.black.withOpacity(0.5),
)),
],
),
));
}
Widget _buildPageView() { Widget _buildPageView() {
return Obx(() => PageView( return _buildBlock(
controller: state.value.pageController, child: Obx(() => PageView(
children: controller: state.value.pageController,
state.value.tabs.map((tab) => tab.page).toList(growable: false))); children: state.value.tabs
.map((tab) => tab.page)
.toList(growable: false))));
} }
Widget _buildBar() { Widget _buildBar() {

View File

@ -81,6 +81,8 @@ Future<void> initEnv(String appType) async {
void runMainApp(bool startService) async { void runMainApp(bool startService) async {
await initEnv(kAppTypeMain); await initEnv(kAppTypeMain);
// trigger connection status updater
await bind.mainCheckConnectStatus();
if (startService) { if (startService) {
// await windowManager.ensureInitialized(); // await windowManager.ensureInitialized();
// disable tray // disable tray
@ -89,10 +91,11 @@ void runMainApp(bool startService) async {
} }
runApp(App()); runApp(App());
// set window option // set window option
WindowOptions windowOptions = getHiddenTitleBarWindowOptions(const Size(1280, 720)); WindowOptions windowOptions =
getHiddenTitleBarWindowOptions(const Size(1280, 720));
windowManager.waitUntilReadyToShow(windowOptions, () async { windowManager.waitUntilReadyToShow(windowOptions, () async {
await windowManager.show(); await windowManager.show();
await windowManager.focus(); await windowManager.focus();
}); });
} }

View File

@ -22,12 +22,13 @@ use crate::ui_interface;
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
use crate::ui_interface::{change_id, check_connect_status, is_ok_change_id}; use crate::ui_interface::{change_id, check_connect_status, is_ok_change_id};
use crate::ui_interface::{ use crate::ui_interface::{
check_super_user_permission, discover, forget_password, get_api_server, get_app_name, check_mouse_time, check_super_user_permission, discover, forget_password, get_api_server,
get_async_job_status, get_connect_status, get_fav, get_id, get_lan_peers, get_langs, get_app_name, get_async_job_status, get_connect_status, get_fav, get_id, get_lan_peers,
get_license, get_local_option, get_option, get_options, get_peer, get_peer_option, get_socks, get_langs, get_license, get_local_option, get_mouse_time, get_option, get_options, get_peer,
get_sound_inputs, get_uuid, get_version, has_hwcodec, has_rendezvous_service, post_request, get_peer_option, get_socks, get_sound_inputs, get_uuid, get_version, has_hwcodec,
set_local_option, set_option, set_options, set_peer_option, set_permanent_password, set_socks, has_rendezvous_service, post_request, set_local_option, set_option, set_options,
store_fav, test_if_valid_server, update_temporary_password, using_public_server, set_peer_option, set_permanent_password, set_socks, store_fav, test_if_valid_server,
update_temporary_password, using_public_server,
}; };
fn initialize(app_dir: &str) { fn initialize(app_dir: &str) {
@ -472,7 +473,7 @@ pub fn main_get_connect_status() -> String {
pub fn main_check_connect_status() { pub fn main_check_connect_status() {
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(any(target_os = "android", target_os = "ios")))]
check_connect_status(true); check_mouse_time(); // avoid multi calls
} }
pub fn main_is_using_public_server() -> bool { pub fn main_is_using_public_server() -> bool {
@ -764,6 +765,14 @@ pub fn main_check_super_user_permission() -> bool {
check_super_user_permission() check_super_user_permission()
} }
pub fn main_check_mouse_time() {
check_mouse_time();
}
pub fn main_get_mouse_time() -> f64 {
get_mouse_time()
}
pub fn cm_send_chat(conn_id: i32, msg: String) { pub fn cm_send_chat(conn_id: i32, msg: String) {
connection_manager::send_chat(conn_id, msg); connection_manager::send_chat(conn_id, msg);
} }