Merge branch 'rustdesk:master' into master
This commit is contained in:
commit
6e2132c65e
@ -46,7 +46,7 @@ android {
|
|||||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||||
applicationId "com.carriez.flutter_hbb"
|
applicationId "com.carriez.flutter_hbb"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 31
|
targetSdkVersion 33
|
||||||
versionCode flutterVersionCode.toInteger()
|
versionCode flutterVersionCode.toInteger()
|
||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
}
|
}
|
||||||
|
@ -614,6 +614,7 @@ class OverlayDialogManager {
|
|||||||
int _tagCount = 0;
|
int _tagCount = 0;
|
||||||
|
|
||||||
OverlayEntry? _mobileActionsOverlayEntry;
|
OverlayEntry? _mobileActionsOverlayEntry;
|
||||||
|
RxBool mobileActionsOverlayVisible = false.obs;
|
||||||
|
|
||||||
void setOverlayState(OverlayKeyState overlayKeyState) {
|
void setOverlayState(OverlayKeyState overlayKeyState) {
|
||||||
_overlayKeyState = overlayKeyState;
|
_overlayKeyState = overlayKeyState;
|
||||||
@ -780,12 +781,14 @@ class OverlayDialogManager {
|
|||||||
});
|
});
|
||||||
overlayState.insert(overlay);
|
overlayState.insert(overlay);
|
||||||
_mobileActionsOverlayEntry = overlay;
|
_mobileActionsOverlayEntry = overlay;
|
||||||
|
mobileActionsOverlayVisible.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hideMobileActionsOverlay() {
|
void hideMobileActionsOverlay() {
|
||||||
if (_mobileActionsOverlayEntry != null) {
|
if (_mobileActionsOverlayEntry != null) {
|
||||||
_mobileActionsOverlayEntry!.remove();
|
_mobileActionsOverlayEntry!.remove();
|
||||||
_mobileActionsOverlayEntry = null;
|
_mobileActionsOverlayEntry = null;
|
||||||
|
mobileActionsOverlayVisible.value = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -279,7 +279,10 @@ class _RemotePageState extends State<RemotePage>
|
|||||||
_ffi.ffiModel.pi.isSet.isTrue &&
|
_ffi.ffiModel.pi.isSet.isTrue &&
|
||||||
_ffi.ffiModel.waitForFirstImage.isTrue
|
_ffi.ffiModel.waitForFirstImage.isTrue
|
||||||
? emptyOverlay()
|
? emptyOverlay()
|
||||||
: Offstage(),
|
: () {
|
||||||
|
_ffi.ffiModel.tryShowAndroidActionsOverlay();
|
||||||
|
return Offstage();
|
||||||
|
}(),
|
||||||
// Use Overlay to enable rebuild every time on menu button click.
|
// Use Overlay to enable rebuild every time on menu button click.
|
||||||
_ffi.ffiModel.pi.isSet.isTrue
|
_ffi.ffiModel.pi.isSet.isTrue
|
||||||
? Overlay(initialEntries: [
|
? Overlay(initialEntries: [
|
||||||
|
@ -101,6 +101,9 @@ class ToolbarState {
|
|||||||
class _ToolbarTheme {
|
class _ToolbarTheme {
|
||||||
static const Color blueColor = MyTheme.button;
|
static const Color blueColor = MyTheme.button;
|
||||||
static const Color hoverBlueColor = MyTheme.accent;
|
static const Color hoverBlueColor = MyTheme.accent;
|
||||||
|
static Color inactiveColor = Colors.grey[800]!;
|
||||||
|
static Color hoverInactiveColor = Colors.grey[850]!;
|
||||||
|
|
||||||
static const Color redColor = Colors.redAccent;
|
static const Color redColor = Colors.redAccent;
|
||||||
static const Color hoverRedColor = Colors.red;
|
static const Color hoverRedColor = Colors.red;
|
||||||
// kMinInteractiveDimension
|
// kMinInteractiveDimension
|
||||||
@ -543,9 +546,9 @@ class _PinMenu extends StatelessWidget {
|
|||||||
assetName: state.pin ? "assets/pinned.svg" : "assets/unpinned.svg",
|
assetName: state.pin ? "assets/pinned.svg" : "assets/unpinned.svg",
|
||||||
tooltip: state.pin ? 'Unpin Toolbar' : 'Pin Toolbar',
|
tooltip: state.pin ? 'Unpin Toolbar' : 'Pin Toolbar',
|
||||||
onPressed: state.switchPin,
|
onPressed: state.switchPin,
|
||||||
color: state.pin ? _ToolbarTheme.blueColor : Colors.grey[800]!,
|
color: state.pin ? _ToolbarTheme.blueColor : _ToolbarTheme.inactiveColor,
|
||||||
hoverColor:
|
hoverColor:
|
||||||
state.pin ? _ToolbarTheme.hoverBlueColor : Colors.grey[850]!,
|
state.pin ? _ToolbarTheme.hoverBlueColor : _ToolbarTheme.hoverInactiveColor,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -558,13 +561,15 @@ class _MobileActionMenu extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (!ffi.ffiModel.isPeerAndroid) return Offstage();
|
if (!ffi.ffiModel.isPeerAndroid) return Offstage();
|
||||||
return _IconMenuButton(
|
return Obx(()=>_IconMenuButton(
|
||||||
assetName: 'assets/actions_mobile.svg',
|
assetName: 'assets/actions_mobile.svg',
|
||||||
tooltip: 'Mobile Actions',
|
tooltip: 'Mobile Actions',
|
||||||
onPressed: () => ffi.dialogManager.toggleMobileActionsOverlay(ffi: ffi),
|
onPressed: () => ffi.dialogManager.toggleMobileActionsOverlay(ffi: ffi),
|
||||||
color: _ToolbarTheme.blueColor,
|
color: ffi.dialogManager.mobileActionsOverlayVisible.isTrue
|
||||||
hoverColor: _ToolbarTheme.hoverBlueColor,
|
? _ToolbarTheme.blueColor : _ToolbarTheme.inactiveColor,
|
||||||
);
|
hoverColor: ffi.dialogManager.mobileActionsOverlayVisible.isTrue
|
||||||
|
? _ToolbarTheme.hoverBlueColor : _ToolbarTheme.hoverInactiveColor,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,12 +92,16 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
removeSharedStates(widget.id);
|
removeSharedStates(widget.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget emptyOverlay() => BlockableOverlay(
|
// to-do: It should be better to use transparent color instead of the bgColor.
|
||||||
|
// But for now, the transparent color will cause the canvas to be white.
|
||||||
|
// I'm sure that the white color is caused by the Overlay widget in BlockableOverlay.
|
||||||
|
// But I don't know why and how to fix it.
|
||||||
|
Widget emptyOverlay(Color bgColor) => BlockableOverlay(
|
||||||
/// the Overlay key will be set with _blockableOverlayState in BlockableOverlay
|
/// the Overlay key will be set with _blockableOverlayState in BlockableOverlay
|
||||||
/// see override build() in [BlockableOverlay]
|
/// see override build() in [BlockableOverlay]
|
||||||
state: _blockableOverlayState,
|
state: _blockableOverlayState,
|
||||||
underlying: Container(
|
underlying: Container(
|
||||||
color: Colors.transparent,
|
color: bgColor,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -265,10 +269,13 @@ class _RemotePageState extends State<RemotePage> {
|
|||||||
children: [
|
children: [
|
||||||
gFFI.ffiModel.pi.isSet.isTrue &&
|
gFFI.ffiModel.pi.isSet.isTrue &&
|
||||||
gFFI.ffiModel.waitForFirstImage.isTrue
|
gFFI.ffiModel.waitForFirstImage.isTrue
|
||||||
? emptyOverlay()
|
? emptyOverlay(MyTheme.canvasColor)
|
||||||
: Offstage(),
|
: () {
|
||||||
|
gFFI.ffiModel.tryShowAndroidActionsOverlay();
|
||||||
|
return Offstage();
|
||||||
|
}(),
|
||||||
_bottomWidget(),
|
_bottomWidget(),
|
||||||
gFFI.ffiModel.pi.isSet.isFalse ? emptyOverlay() : Offstage(),
|
gFFI.ffiModel.pi.isSet.isFalse ? emptyOverlay(MyTheme.canvasColor) : Offstage(),
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
body: Overlay(
|
body: Overlay(
|
||||||
|
@ -554,23 +554,13 @@ class FfiModel with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final connType = parent.target?.connType;
|
final connType = parent.target?.connType;
|
||||||
|
|
||||||
if (isPeerAndroid) {
|
if (isPeerAndroid) {
|
||||||
_touchMode = true;
|
_touchMode = true;
|
||||||
if (connType == ConnType.defaultConn &&
|
|
||||||
parent.target != null &&
|
|
||||||
parent.target!.ffiModel.permissions['keyboard'] != false) {
|
|
||||||
Timer(
|
|
||||||
const Duration(milliseconds: 100),
|
|
||||||
() => parent.target!.dialogManager
|
|
||||||
.showMobileActionsOverlay(ffi: parent.target!));
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
_touchMode = await bind.sessionGetOption(
|
_touchMode = await bind.sessionGetOption(
|
||||||
sessionId: sessionId, arg: 'touch-mode') !=
|
sessionId: sessionId, arg: 'touch-mode') !=
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connType == ConnType.fileTransfer) {
|
if (connType == ConnType.fileTransfer) {
|
||||||
parent.target?.fileModel.onReady();
|
parent.target?.fileModel.onReady();
|
||||||
} else if (connType == ConnType.defaultConn) {
|
} else if (connType == ConnType.defaultConn) {
|
||||||
@ -616,6 +606,19 @@ class FfiModel with ChangeNotifier {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tryShowAndroidActionsOverlay({int delayMSecs = 10}) {
|
||||||
|
if (isPeerAndroid) {
|
||||||
|
if (parent.target?.connType == ConnType.defaultConn &&
|
||||||
|
parent.target != null &&
|
||||||
|
parent.target!.ffiModel.permissions['keyboard'] != false) {
|
||||||
|
Timer(
|
||||||
|
Duration(milliseconds: delayMSecs),
|
||||||
|
() => parent.target!.dialogManager
|
||||||
|
.showMobileActionsOverlay(ffi: parent.target!));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
handleResolutions(String id, dynamic resolutions) {
|
handleResolutions(String id, dynamic resolutions) {
|
||||||
try {
|
try {
|
||||||
final List<dynamic> dynamicArray = jsonDecode(resolutions as String);
|
final List<dynamic> dynamicArray = jsonDecode(resolutions as String);
|
||||||
|
@ -40,6 +40,8 @@ class ServerModel with ChangeNotifier {
|
|||||||
|
|
||||||
late String _emptyIdShow;
|
late String _emptyIdShow;
|
||||||
late final IDTextEditingController _serverId;
|
late final IDTextEditingController _serverId;
|
||||||
|
final _serverPasswd =
|
||||||
|
TextEditingController(text: translate("Generating ..."));
|
||||||
|
|
||||||
final tabController = DesktopTabController(tabType: DesktopTabType.cm);
|
final tabController = DesktopTabController(tabType: DesktopTabType.cm);
|
||||||
|
|
||||||
@ -61,9 +63,6 @@ class ServerModel with ChangeNotifier {
|
|||||||
|
|
||||||
int get connectStatus => _connectStatus;
|
int get connectStatus => _connectStatus;
|
||||||
|
|
||||||
TextEditingController get _serverPasswd =>
|
|
||||||
TextEditingController(text: translate("Generating ..."));
|
|
||||||
|
|
||||||
String get verificationMethod {
|
String get verificationMethod {
|
||||||
final index = [
|
final index = [
|
||||||
kUseTemporaryPassword,
|
kUseTemporaryPassword,
|
||||||
|
@ -779,12 +779,18 @@ pub fn get_sysinfo() -> serde_json::Value {
|
|||||||
os = format!("{os} - {}", system.os_version().unwrap_or_default());
|
os = format!("{os} - {}", system.os_version().unwrap_or_default());
|
||||||
}
|
}
|
||||||
let hostname = hostname(); // sys.hostname() return localhost on android in my test
|
let hostname = hostname(); // sys.hostname() return localhost on android in my test
|
||||||
serde_json::json!({
|
use serde_json::json;
|
||||||
|
let mut out = json!({
|
||||||
"cpu": format!("{cpu}{num_cpus}/{num_pcpus} cores"),
|
"cpu": format!("{cpu}{num_cpus}/{num_pcpus} cores"),
|
||||||
"memory": format!("{memory}GB"),
|
"memory": format!("{memory}GB"),
|
||||||
"os": os,
|
"os": os,
|
||||||
"hostname": hostname,
|
"hostname": hostname,
|
||||||
})
|
});
|
||||||
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
|
{
|
||||||
|
out["username"] = json!(crate::platform::get_active_username());
|
||||||
|
}
|
||||||
|
out
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -222,6 +222,8 @@ pub fn core_main() -> Option<Vec<String>> {
|
|||||||
log::info!("start --uninstall-service");
|
log::info!("start --uninstall-service");
|
||||||
crate::platform::uninstall_service(false);
|
crate::platform::uninstall_service(false);
|
||||||
} else if args[0] == "--service" {
|
} else if args[0] == "--service" {
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
crate::platform::macos::hide_dock();
|
||||||
log::info!("start --service");
|
log::info!("start --service");
|
||||||
crate::start_os_service();
|
crate::start_os_service();
|
||||||
return None;
|
return None;
|
||||||
|
@ -240,6 +240,11 @@ pub fn uninstall_service(show_new_window: bool) -> bool {
|
|||||||
uninstalled
|
uninstalled
|
||||||
);
|
);
|
||||||
if uninstalled {
|
if uninstalled {
|
||||||
|
if !show_new_window {
|
||||||
|
let _ = crate::ipc::close_all_instances();
|
||||||
|
// leave ipc a little time
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(300));
|
||||||
|
}
|
||||||
crate::ipc::set_option("stop-service", "Y");
|
crate::ipc::set_option("stop-service", "Y");
|
||||||
std::process::Command::new("launchctl")
|
std::process::Command::new("launchctl")
|
||||||
.args(&["remove", &format!("{}_server", crate::get_full_name())])
|
.args(&["remove", &format!("{}_server", crate::get_full_name())])
|
||||||
@ -255,13 +260,6 @@ pub fn uninstall_service(show_new_window: bool) -> bool {
|
|||||||
.spawn()
|
.spawn()
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
std::process::Command::new("pkill")
|
|
||||||
.arg(crate::get_app_name())
|
|
||||||
.status()
|
|
||||||
.ok();
|
|
||||||
let _ = crate::ipc::close_all_instances();
|
|
||||||
// leave ipc a little time
|
|
||||||
std::thread::sleep(std::time::Duration::from_millis(300));
|
|
||||||
quit_gui();
|
quit_gui();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user