mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-04-20 05:23:18 +03:00
feat/virtual_display_privacy_mode
Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
@@ -1060,7 +1060,7 @@ class _NetworkState extends State<_Network> with AutomaticKeepAliveClientMixin {
|
||||
tmpWrapper() {
|
||||
// Setting page is not modal, oldOptions should only be used when getting options, never when setting.
|
||||
Map<String, dynamic> oldOptions =
|
||||
jsonDecode(bind.mainGetOptionsSync() as String);
|
||||
jsonDecode(bind.mainGetOptionsSync());
|
||||
old(String key) {
|
||||
return (oldOptions[key] ?? '').trim();
|
||||
}
|
||||
@@ -1151,6 +1151,7 @@ class _DisplayState extends State<_Display> {
|
||||
scrollStyle(context),
|
||||
imageQuality(context),
|
||||
codec(context),
|
||||
privacyModeImpl(context),
|
||||
other(context),
|
||||
]).marginOnly(bottom: _kListViewBottomMargin));
|
||||
}
|
||||
@@ -1290,6 +1291,42 @@ class _DisplayState extends State<_Display> {
|
||||
]);
|
||||
}
|
||||
|
||||
Widget privacyModeImpl(BuildContext context) {
|
||||
final supportedPrivacyModeImpls = bind.mainSupportedPrivacyModeImpls();
|
||||
late final List<dynamic> privacyModeImpls;
|
||||
try {
|
||||
privacyModeImpls = jsonDecode(supportedPrivacyModeImpls);
|
||||
} catch (e) {
|
||||
debugPrint('failed to parse supported privacy mode impls, err=$e');
|
||||
return Offstage();
|
||||
}
|
||||
if (privacyModeImpls.length < 2) {
|
||||
return Offstage();
|
||||
}
|
||||
|
||||
final key = 'privacy-mode-impl-key';
|
||||
onChanged(String value) async {
|
||||
await bind.mainSetOption(key: key, value: value);
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
String groupValue = bind.mainGetOptionSync(key: key);
|
||||
if (groupValue.isEmpty) {
|
||||
groupValue = bind.mainDefaultPrivacyModeImpl();
|
||||
}
|
||||
return _Card(
|
||||
title: 'Privacy mode',
|
||||
children: privacyModeImpls.map((impl) {
|
||||
final d = impl as List<dynamic>;
|
||||
return _Radio(context,
|
||||
value: d[0] as String,
|
||||
groupValue: groupValue,
|
||||
label: d[1] as String,
|
||||
onChanged: onChanged);
|
||||
}).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget otherRow(String label, String key) {
|
||||
final value = bind.mainGetUserDefaultOption(key: key) == 'Y';
|
||||
onChanged(bool b) async {
|
||||
|
||||
@@ -17,6 +17,7 @@ import '../../common/widgets/overlay.dart';
|
||||
import '../../common/widgets/remote_input.dart';
|
||||
import '../../common.dart';
|
||||
import '../../common/widgets/dialog.dart';
|
||||
import '../../common/widgets/toolbar.dart';
|
||||
import '../../models/model.dart';
|
||||
import '../../models/desktop_render_texture.dart';
|
||||
import '../../models/platform_model.dart';
|
||||
@@ -281,24 +282,23 @@ class _RemotePageState extends State<RemotePage>
|
||||
},
|
||||
inputModel: _ffi.inputModel,
|
||||
child: getBodyForDesktop(context))),
|
||||
Stack(
|
||||
children: [
|
||||
_ffi.ffiModel.pi.isSet.isTrue &&
|
||||
_ffi.ffiModel.waitForFirstImage.isTrue
|
||||
? emptyOverlay()
|
||||
: () {
|
||||
_ffi.ffiModel.tryShowAndroidActionsOverlay();
|
||||
return Offstage();
|
||||
}(),
|
||||
// Use Overlay to enable rebuild every time on menu button click.
|
||||
_ffi.ffiModel.pi.isSet.isTrue
|
||||
? Overlay(initialEntries: [
|
||||
OverlayEntry(builder: remoteToolbar)
|
||||
])
|
||||
: remoteToolbar(context),
|
||||
_ffi.ffiModel.pi.isSet.isFalse ? emptyOverlay() : Offstage(),
|
||||
],
|
||||
),
|
||||
Stack(
|
||||
children: [
|
||||
_ffi.ffiModel.pi.isSet.isTrue &&
|
||||
_ffi.ffiModel.waitForFirstImage.isTrue
|
||||
? emptyOverlay()
|
||||
: () {
|
||||
_ffi.ffiModel.tryShowAndroidActionsOverlay();
|
||||
return Offstage();
|
||||
}(),
|
||||
// Use Overlay to enable rebuild every time on menu button click.
|
||||
_ffi.ffiModel.pi.isSet.isTrue
|
||||
? Overlay(
|
||||
initialEntries: [OverlayEntry(builder: remoteToolbar)])
|
||||
: remoteToolbar(context),
|
||||
_ffi.ffiModel.pi.isSet.isFalse ? emptyOverlay() : Offstage(),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -309,12 +309,17 @@ class _RemotePageState extends State<RemotePage>
|
||||
final imageReady = _ffi.ffiModel.pi.isSet.isTrue &&
|
||||
_ffi.ffiModel.waitForFirstImage.isFalse;
|
||||
if (imageReady) {
|
||||
// `dismissAll()` is to ensure that the state is clean.
|
||||
// It's ok to call dismissAll() here.
|
||||
_ffi.dialogManager.dismissAll();
|
||||
// Recreate the block state to refresh the state.
|
||||
_blockableOverlayState = BlockableOverlayState();
|
||||
_blockableOverlayState.applyFfi(_ffi);
|
||||
// If the privacy mode(disable physical displays) is switched,
|
||||
// we should not dismiss the dialog immediately.
|
||||
if (DateTime.now().difference(togglePrivacyModeTime) >
|
||||
const Duration(milliseconds: 3000)) {
|
||||
// `dismissAll()` is to ensure that the state is clean.
|
||||
// It's ok to call dismissAll() here.
|
||||
_ffi.dialogManager.dismissAll();
|
||||
// Recreate the block state to refresh the state.
|
||||
_blockableOverlayState = BlockableOverlayState();
|
||||
_blockableOverlayState.applyFfi(_ffi);
|
||||
}
|
||||
// Block the whole `bodyWidget()` when dialog shows.
|
||||
return BlockableOverlay(
|
||||
underlying: bodyWidget(),
|
||||
|
||||
Reference in New Issue
Block a user