This commit is contained in:
rustdesk
2023-11-06 20:12:01 +08:00
parent 679a026e72
commit d7e8d4d5c3
64 changed files with 1193 additions and 1082 deletions

View File

@@ -50,6 +50,7 @@ class _ConnectionPageState extends State<ConnectionPage>
return list.sublist(0, n);
}
}
bool isPeersLoading = false;
bool isPeersLoaded = false;
@@ -81,7 +82,7 @@ class _ConnectionPageState extends State<ConnectionPage>
if (Get.isRegistered<IDTextEditingController>()) {
Get.delete<IDTextEditingController>();
}
if (Get.isRegistered<TextEditingController>()){
if (Get.isRegistered<TextEditingController>()) {
Get.delete<TextEditingController>();
}
super.dispose();
@@ -157,9 +158,9 @@ class _ConnectionPageState extends State<ConnectionPage>
await Future.delayed(Duration(milliseconds: 100));
peers = await getAllPeers();
setState(() {
isPeersLoading = false;
isPeersLoaded = true;
});
isPeersLoading = false;
isPeersLoaded = true;
});
}
/// UI for the remote ID TextField.
@@ -177,148 +178,173 @@ class _ConnectionPageState extends State<ConnectionPage>
Row(
children: [
Expanded(
child: AutoSizeText(
translate('Control Remote Desktop'),
maxLines: 1,
style: Theme.of(context)
.textTheme
.titleLarge
?.merge(TextStyle(height: 1)),
),
),
child: Row(
children: [
AutoSizeText(
translate('Control Remote Desktop'),
maxLines: 1,
style: Theme.of(context)
.textTheme
.titleLarge
?.merge(TextStyle(height: 1)),
).marginOnly(right: 4),
Tooltip(
waitDuration: Duration(milliseconds: 0),
message: translate("id_input_tip"),
child: Icon(
Icons.help_outline_outlined,
size: 16,
color: Theme.of(context)
.textTheme
.titleLarge
?.color
?.withOpacity(0.5),
),
),
],
)),
],
).marginOnly(bottom: 15),
Row(
children: [
Expanded(
child:
Autocomplete<Peer>(
optionsBuilder: (TextEditingValue textEditingValue) {
if (textEditingValue.text == '') {
return const Iterable<Peer>.empty();
}
else if (peers.isEmpty && !isPeersLoaded) {
Peer emptyPeer = Peer(
id: '',
username: '',
hostname: '',
alias: '',
platform: '',
tags: [],
hash: '',
forceAlwaysRelay: false,
rdpPort: '',
rdpUsername: '',
loginName: '',
child: Autocomplete<Peer>(
optionsBuilder: (TextEditingValue textEditingValue) {
if (textEditingValue.text == '') {
return const Iterable<Peer>.empty();
} else if (peers.isEmpty && !isPeersLoaded) {
Peer emptyPeer = Peer(
id: '',
username: '',
hostname: '',
alias: '',
platform: '',
tags: [],
hash: '',
forceAlwaysRelay: false,
rdpPort: '',
rdpUsername: '',
loginName: '',
);
return [emptyPeer];
} else {
String textWithoutSpaces =
textEditingValue.text.replaceAll(" ", "");
if (int.tryParse(textWithoutSpaces) != null) {
textEditingValue = TextEditingValue(
text: textWithoutSpaces,
selection: textEditingValue.selection,
);
return [emptyPeer];
}
else {
String textWithoutSpaces = textEditingValue.text.replaceAll(" ", "");
if (int.tryParse(textWithoutSpaces) != null) {
textEditingValue = TextEditingValue(
text: textWithoutSpaces,
selection: textEditingValue.selection,
);
}
String textToFind = textEditingValue.text.toLowerCase();
String textToFind = textEditingValue.text.toLowerCase();
return peers.where((peer) =>
peer.id.toLowerCase().contains(textToFind) ||
peer.username.toLowerCase().contains(textToFind) ||
peer.hostname.toLowerCase().contains(textToFind) ||
peer.alias.toLowerCase().contains(textToFind))
.toList();
return peers
.where((peer) =>
peer.id.toLowerCase().contains(textToFind) ||
peer.username
.toLowerCase()
.contains(textToFind) ||
peer.hostname
.toLowerCase()
.contains(textToFind) ||
peer.alias.toLowerCase().contains(textToFind))
.toList();
}
},
fieldViewBuilder: (
BuildContext context,
TextEditingController fieldTextEditingController,
FocusNode fieldFocusNode,
VoidCallback onFieldSubmitted,
) {
fieldTextEditingController.text = _idController.text;
Get.put<TextEditingController>(fieldTextEditingController);
fieldFocusNode.addListener(() async {
_idInputFocused.value = fieldFocusNode.hasFocus;
if (fieldFocusNode.hasFocus && !isPeersLoading) {
_fetchPeers();
}
},
});
final textLength =
fieldTextEditingController.value.text.length;
// select all to facilitate removing text, just following the behavior of address input of chrome
fieldTextEditingController.selection =
TextSelection(baseOffset: 0, extentOffset: textLength);
return Obx(() => TextField(
autocorrect: false,
enableSuggestions: false,
keyboardType: TextInputType.visiblePassword,
focusNode: fieldFocusNode,
style: const TextStyle(
fontFamily: 'WorkSans',
fontSize: 22,
height: 1.4,
),
maxLines: 1,
cursorColor:
Theme.of(context).textTheme.titleLarge?.color,
decoration: InputDecoration(
filled: false,
counterText: '',
hintText: _idInputFocused.value
? null
: translate('Enter Remote ID'),
contentPadding: const EdgeInsets.symmetric(
horizontal: 15, vertical: 13)),
controller: fieldTextEditingController,
inputFormatters: [IDTextInputFormatter()],
onChanged: (v) {
_idController.id = v;
},
));
},
onSelected: (option) {
setState(() {
_idController.id = option.id;
FocusScope.of(context).unfocus();
});
},
optionsViewBuilder: (BuildContext context,
AutocompleteOnSelected<Peer> onSelected,
Iterable<Peer> options) {
double maxHeight = options.length * 50;
maxHeight = maxHeight > 200 ? 200 : maxHeight;
fieldViewBuilder: (BuildContext context,
TextEditingController fieldTextEditingController,
FocusNode fieldFocusNode ,
VoidCallback onFieldSubmitted,
) {
fieldTextEditingController.text = _idController.text;
Get.put<TextEditingController>(fieldTextEditingController);
fieldFocusNode.addListener(() async {
_idInputFocused.value = fieldFocusNode.hasFocus;
if (fieldFocusNode.hasFocus && !isPeersLoading){
_fetchPeers();
}
});
final textLength = fieldTextEditingController.value.text.length;
// select all to facilitate removing text, just following the behavior of address input of chrome
fieldTextEditingController.selection = TextSelection(baseOffset: 0, extentOffset: textLength);
return Obx(() =>
TextField(
maxLength: 90,
autocorrect: false,
enableSuggestions: false,
keyboardType: TextInputType.visiblePassword,
focusNode: fieldFocusNode,
style: const TextStyle(
fontFamily: 'WorkSans',
fontSize: 22,
height: 1.4,
),
maxLines: 1,
cursorColor: Theme.of(context).textTheme.titleLarge?.color,
decoration: InputDecoration(
filled: false,
counterText: '',
hintText: _idInputFocused.value
? null
: translate('Enter Remote ID'),
contentPadding: const EdgeInsets.symmetric(
horizontal: 15, vertical: 13)),
controller: fieldTextEditingController,
inputFormatters: [IDTextInputFormatter()],
onChanged: (v) {
_idController.id = v;
},
));
},
onSelected: (option) {
setState(() {
_idController.id = option.id;
FocusScope.of(context).unfocus();
});
},
optionsViewBuilder: (BuildContext context, AutocompleteOnSelected<Peer> onSelected, Iterable<Peer> options) {
double maxHeight = options.length * 50;
maxHeight = maxHeight > 200 ? 200 : maxHeight;
return Align(
alignment: Alignment.topLeft,
child: ClipRRect(
return Align(
alignment: Alignment.topLeft,
child: ClipRRect(
borderRadius: BorderRadius.circular(5),
child: Material(
elevation: 4,
child: ConstrainedBox(
constraints: BoxConstraints(
maxHeight: maxHeight,
maxWidth: 319,
),
child: peers.isEmpty && isPeersLoading
? Container(
height: 80,
child: Center(
child: CircularProgressIndicator(
strokeWidth: 2,
),
)
)
: Padding(
padding: const EdgeInsets.only(top: 5),
child: ListView(
children: options.map((peer) => AutocompletePeerTile(onSelect: () => onSelected(peer), peer: peer)).toList(),
elevation: 4,
child: ConstrainedBox(
constraints: BoxConstraints(
maxHeight: maxHeight,
maxWidth: 319,
),
child: peers.isEmpty && isPeersLoading
? Container(
height: 80,
child: Center(
child: CircularProgressIndicator(
strokeWidth: 2,
),
))
: Padding(
padding: const EdgeInsets.only(top: 5),
child: ListView(
children: options
.map((peer) => AutocompletePeerTile(
onSelect: () =>
onSelected(peer),
peer: peer))
.toList(),
),
),
),
),
)),
);
},
)
),
)),
);
},
)),
],
),
Padding(
@@ -329,7 +355,7 @@ class _ConnectionPageState extends State<ConnectionPage>
Button(
isOutline: true,
onTap: () => onConnect(isFileTransfer: true),
text: "Transfer File",
text: "Transfer file",
),
const SizedBox(
width: 17,
@@ -382,7 +408,7 @@ class _ConnectionPageState extends State<ConnectionPage>
onTap: () async {
await start_service(true);
},
child: Text(translate("Start Service"),
child: Text(translate("Start service"),
style: TextStyle(
decoration: TextDecoration.underline,
fontSize: em)))

View File

@@ -632,22 +632,22 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
}).marginOnly(left: _kContentHMargin),
Column(
children: [
_OptionCheckBox(context, 'Enable Keyboard/Mouse', 'enable-keyboard',
_OptionCheckBox(context, 'Enable keyboard/mouse', 'enable-keyboard',
enabled: enabled, fakeValue: fakeValue),
_OptionCheckBox(context, 'Enable Clipboard', 'enable-clipboard',
_OptionCheckBox(context, 'Enable clipboard', 'enable-clipboard',
enabled: enabled, fakeValue: fakeValue),
_OptionCheckBox(
context, 'Enable File Transfer', 'enable-file-transfer',
context, 'Enable file transfer', 'enable-file-transfer',
enabled: enabled, fakeValue: fakeValue),
_OptionCheckBox(context, 'Enable Audio', 'enable-audio',
_OptionCheckBox(context, 'Enable audio', 'enable-audio',
enabled: enabled, fakeValue: fakeValue),
_OptionCheckBox(context, 'Enable TCP Tunneling', 'enable-tunnel',
_OptionCheckBox(context, 'Enable TCP tunneling', 'enable-tunnel',
enabled: enabled, fakeValue: fakeValue),
_OptionCheckBox(
context, 'Enable Remote Restart', 'enable-remote-restart',
context, 'Enable remote restart', 'enable-remote-restart',
enabled: enabled, fakeValue: fakeValue),
_OptionCheckBox(
context, 'Enable Recording Session', 'enable-record-session',
context, 'Enable recording session', 'enable-record-session',
enabled: enabled, fakeValue: fakeValue),
if (Platform.isWindows)
_OptionCheckBox(
@@ -773,7 +773,7 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
bool enabled = !locked;
return _Card(title: 'Security', children: [
shareRdp(context, enabled),
_OptionCheckBox(context, 'Deny LAN Discovery', 'enable-lan-discovery',
_OptionCheckBox(context, 'Deny LAN discovery', 'enable-lan-discovery',
reverse: true, enabled: enabled),
...directIp(context),
whitelist(),
@@ -813,7 +813,7 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
update() => setState(() {});
RxBool applyEnabled = false.obs;
return [
_OptionCheckBox(context, 'Enable Direct IP Access', 'direct-server',
_OptionCheckBox(context, 'Enable direct IP access', 'direct-server',
update: update, enabled: !locked),
() {
// Simple temp wrapper for PR check

View File

@@ -386,7 +386,7 @@ class _ConnectionTabPageState extends State<ConnectionTabPage> {
pi.platform == kPeerPlatformMacOS)) {
menu.add(MenuEntryButton<String>(
childBuilder: (TextStyle? style) => Text(
translate('Restart Remote Device'),
translate('Restart remote device'),
style: style,
),
proc: () => showRestartRemoteDevice(

View File

@@ -592,7 +592,7 @@ class _PrivilegeBoardState extends State<_PrivilegeBoard> {
client.keyboard = enabled;
});
},
translate('Enable Keyboard/Mouse'),
translate('Enable keyboard/mouse'),
),
buildPermissionIcon(
client.clipboard,
@@ -604,7 +604,7 @@ class _PrivilegeBoardState extends State<_PrivilegeBoard> {
client.clipboard = enabled;
});
},
translate('Enable Clipboard'),
translate('Enable clipboard'),
),
buildPermissionIcon(
client.audio,
@@ -616,7 +616,7 @@ class _PrivilegeBoardState extends State<_PrivilegeBoard> {
client.audio = enabled;
});
},
translate('Enable Audio'),
translate('Enable audio'),
),
buildPermissionIcon(
client.file,
@@ -640,7 +640,7 @@ class _PrivilegeBoardState extends State<_PrivilegeBoard> {
client.restart = enabled;
});
},
translate('Enable Remote Restart'),
translate('Enable remote restart'),
),
buildPermissionIcon(
client.recording,
@@ -652,7 +652,7 @@ class _PrivilegeBoardState extends State<_PrivilegeBoard> {
client.recording = enabled;
});
},
translate('Enable Recording Session'),
translate('Enable recording session'),
),
// only windows support block input
if (Platform.isWindows)