Initial commit: rdgen with GitHub/Gitea dual build backend

This commit is contained in:
naeeo
2026-09-29 19:56:02 +08:00
commit a3686a49d4
103 changed files with 20007 additions and 0 deletions
+29
View File
@@ -0,0 +1,29 @@
diff --git a/src/common.rs b/src/common.rs
index 56361a5da..92b221e9a 100644
--- a/src/common.rs
+++ b/src/common.rs
@@ -1474,15 +1474,15 @@ pub fn read_custom_client(config: &str) {
log::error!("Failed to decode custom client config");
return;
};
- const KEY: &str = "5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=";
- let Some(pk) = get_rs_pk(KEY) else {
- log::error!("Failed to parse public key of custom client");
- return;
- };
- let Ok(data) = sign::verify(&data, &pk) else {
- log::error!("Failed to dec custom client config");
- return;
- };
+ // const KEY: &str = "5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=";
+ // let Some(pk) = get_rs_pk(KEY) else {
+ // log::error!("Failed to parse public key of custom client");
+ // return;
+ // };
+ // let Ok(data) = sign::verify(&data, &pk) else {
+ // log::error!("Failed to dec custom client config");
+ // return;
+ // };
let Ok(mut data) =
serde_json::from_slice::<std::collections::HashMap<String, serde_json::Value>>(&data)
else {
+63
View File
@@ -0,0 +1,63 @@
import os
import shutil
def remove_line_block(filepath, start_phrase, lines_to_remove_after_start):
"""
Removes a starting line and a fixed number of lines immediately following it.
:param filepath: The path to the file to modify.
:param start_phrase: The unique string to identify the first line of the block.
:param lines_to_remove_after_start: The number of lines to remove after the starting line.
"""
# 1. Configuration for the removal logic
# The starting line is: const KEY: &str = "5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=";
# The block contains this line plus 8 following lines, so we want to skip 9 lines in total.
total_lines_to_skip = 1 + lines_to_remove_after_start # 1 (start line) + 8 (following lines) = 9
lines_to_keep = []
skip_count = 0
# 2. Read and filter the file content
try:
with open(filepath, 'r') as file:
for line in file:
# If we are currently in the process of skipping lines, decrement the counter and continue
if skip_count > 0:
skip_count -= 1
continue
# Check if the line matches the start phrase (we use .strip() to ignore indentation/whitespace)
if line.strip().startswith(start_phrase.strip()):
# Start skipping the block (including the current line)
skip_count = total_lines_to_skip - 1
# Note: We subtract 1 because the 'continue' will handle the first line removal immediately
continue
# If we are not skipping, keep the line, but change custom.txt to custom_.txt
line = line.replace("custom.txt", "custom_.txt")
lines_to_keep.append(line)
except FileNotFoundError:
print(f"Error: File not found at {filepath}")
return
# 3. Write the remaining lines back to the file
try:
with open(filepath, 'w') as file:
file.writelines(lines_to_keep)
print(f"Success! Removed the 9-line block starting with '{start_phrase.strip()}' from {filepath}.")
except IOError as e:
print(f"An error occurred while writing to the file: {e}")
def main():
file_path = 'src/common.rs'
start_phrase = 'const KEY: &str = "5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=";'
lines_to_remove_after_start = 8
remove_line_block(file_path, start_phrase, lines_to_remove_after_start)
if __name__ == "__main__":
main()
@@ -0,0 +1,42 @@
diff --git a/packages/flutter/lib/src/material/dropdown_menu.dart b/packages/flutter/lib/src/material/dropdown_menu.dart
index 7e634cd2aa..c1e9acc295 100644
--- a/packages/flutter/lib/src/material/dropdown_menu.dart
+++ b/packages/flutter/lib/src/material/dropdown_menu.dart
@@ -475,7 +475,7 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
final GlobalKey _leadingKey = GlobalKey();
late List<GlobalKey> buttonItemKeys;
final MenuController _controller = MenuController();
- late bool _enableFilter;
+ bool _enableFilter = false;
late List<DropdownMenuEntry<T>> filteredEntries;
List<Widget>? _initialMenu;
int? currentHighlight;
@@ -524,6 +524,11 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
}
_localTextEditingController = widget.controller ?? TextEditingController();
}
+ if (oldWidget.enableFilter != widget.enableFilter) {
+ if (!widget.enableFilter) {
+ _enableFilter = false;
+ }
+ }
if (oldWidget.enableSearch != widget.enableSearch) {
if (!widget.enableSearch) {
currentHighlight = null;
@@ -663,6 +668,7 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
);
currentHighlight = widget.enableSearch ? i : null;
widget.onSelected?.call(entry.value);
+ _enableFilter = false;
}
: null,
requestFocusOnHover: false,
@@ -735,6 +741,8 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
if (_enableFilter) {
filteredEntries = widget.filterCallback?.call(filteredEntries, _localTextEditingController!.text)
?? filter(widget.dropdownMenuEntries, _localTextEditingController!);
+ } else {
+ filteredEntries = widget.dropdownMenuEntries;
}
if (widget.enableSearch) {
+129
View File
@@ -0,0 +1,129 @@
diff --git a/flutter/lib/desktop/pages/desktop_setting_page.dart b/flutter/lib/desktop/pages/desktop_setting_page.dart
index 56a99446c..5991aceed 100644
--- a/flutter/lib/desktop/pages/desktop_setting_page.dart
+++ b/flutter/lib/desktop/pages/desktop_setting_page.dart
@@ -1101,8 +1101,8 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
if (usePassword)
_SubButton('Set permanent password', setPasswordDialog,
permEnabled && !locked),
- // if (usePassword)
- // hide_cm(!locked).marginOnly(left: _kContentHSubMargin - 6),
+ if (usePassword)
+ hide_cm(!locked).marginOnly(left: _kContentHSubMargin - 6),
if (usePassword) radios[2],
]);
})));
diff --git a/flutter/lib/main.dart b/flutter/lib/main.dart
index 3032a2321..66d0d8c26 100644
--- a/flutter/lib/main.dart
+++ b/flutter/lib/main.dart
@@ -245,7 +245,7 @@ void runConnectionManagerScreen() async {
MyTheme.currentThemeMode(),
);
final hide = await bind.cmGetConfig(name: "hide_cm") == 'true';
- gFFI.serverModel.hideCm = hide;
+ // gFFI.serverModel.hideCm = hide;
if (hide) {
await hideCmWindow(isStartup: true);
} else {
diff --git a/flutter/lib/models/server_model.dart b/flutter/lib/models/server_model.dart
index 877576461..4efd6c8b0 100644
--- a/flutter/lib/models/server_model.dart
+++ b/flutter/lib/models/server_model.dart
@@ -32,7 +32,7 @@ class ServerModel with ChangeNotifier {
bool _fileOk = false;
bool _clipboardOk = false;
bool _showElevation = false;
- bool hideCm = false;
+ bool _hideCm = false;
int _connectStatus = 0; // Rendezvous Server status
String _verificationMethod = "";
String _temporaryPasswordLength = "";
@@ -62,6 +62,8 @@ class ServerModel with ChangeNotifier {
bool get clipboardOk => _clipboardOk;
+ bool get hideCm => _hideCm;
+
bool get showElevation => _showElevation;
int get connectStatus => _connectStatus;
@@ -82,12 +84,11 @@ class ServerModel with ChangeNotifier {
setVerificationMethod(String method) async {
await bind.mainSetOption(key: kOptionVerificationMethod, value: method);
- /*
+
if (method != kUsePermanentPassword) {
await bind.mainSetOption(
key: 'allow-hide-cm', value: bool2option('allow-hide-cm', false));
}
- */
}
String get temporaryPasswordLength {
@@ -104,12 +105,11 @@ class ServerModel with ChangeNotifier {
setApproveMode(String mode) async {
await bind.mainSetOption(key: kOptionApproveMode, value: mode);
- /*
+
if (mode != 'password') {
await bind.mainSetOption(
key: 'allow-hide-cm', value: bool2option('allow-hide-cm', false));
}
- */
}
TextEditingController get serverId => _serverId;
@@ -126,7 +126,6 @@ class ServerModel with ChangeNotifier {
_emptyIdShow = translate("Generating ...");
_serverId = IDTextEditingController(text: _emptyIdShow);
- /*
// initital _hideCm at startup
final verificationMethod =
bind.mainGetOptionSync(key: kOptionVerificationMethod);
@@ -137,7 +136,6 @@ class ServerModel with ChangeNotifier {
verificationMethod == kUsePermanentPassword)) {
_hideCm = false;
}
- */
timerCallback() async {
final connectionStatus =
@@ -227,14 +225,14 @@ class ServerModel with ChangeNotifier {
final temporaryPasswordLength =
await bind.mainGetOption(key: "temporary-password-length");
final approveMode = await bind.mainGetOption(key: kOptionApproveMode);
- /*
+
var hideCm = option2bool(
'allow-hide-cm', await bind.mainGetOption(key: 'allow-hide-cm'));
if (!(approveMode == 'password' &&
verificationMethod == kUsePermanentPassword)) {
hideCm = false;
}
- */
+
if (_approveMode != approveMode) {
_approveMode = approveMode;
update = true;
@@ -265,7 +263,7 @@ class ServerModel with ChangeNotifier {
_temporaryPasswordLength = temporaryPasswordLength;
update = true;
}
- /*
+
if (_hideCm != hideCm) {
_hideCm = hideCm;
if (desktopType == DesktopType.cm) {
@@ -277,7 +275,7 @@ class ServerModel with ChangeNotifier {
}
update = true;
}
- */
+
if (update) {
notifyListeners();
}
+32
View File
@@ -0,0 +1,32 @@
import os
def convert_png_to_cpp(input_file, output_file, array_name="g_img"):
if not os.path.exists(input_file):
print(f"Error: {input_file} not found.")
return
with open(input_file, "rb") as f:
data = f.read()
with open(output_file, "w") as f:
f.write('#include "pch.h"\n')
f.write('#include "./img.h"\n\n')
f.write(f"const unsigned char {array_name}[] = {{\n")
for i in range(0, len(data), 20):
chunk = data[i : i + 20]
hex_chunk = [f"0x{b:02x}" for b in chunk]
line = ", ".join(hex_chunk)
if i + 20 < len(data):
f.write(f"{line},\n")
else:
f.write(f"{line}\n")
f.write("};\n\n")
f.write(f"const long long {array_name}Len = sizeof({array_name});\n")
#print(f"Successfully converted {input_file} to {output_file}")
convert_png_to_cpp("privacy.png", "img.cpp")
@@ -0,0 +1,41 @@
diff --git a/flutter/lib/desktop/pages/desktop_home_page.dart b/flutter/lib/desktop/pages/desktop_home_page.dart
index ba724eed5..1604c429f 100644
--- a/flutter/lib/desktop/pages/desktop_home_page.dart
+++ b/flutter/lib/desktop/pages/desktop_home_page.dart
@@ -424,21 +424,21 @@ class _DesktopHomePageState extends State<DesktopHomePage>
}
Widget buildHelpCards(String updateUrl) {
- if (!bind.isCustomClient() &&
- updateUrl.isNotEmpty &&
- !isCardClosed &&
- bind.mainUriPrefixSync().contains('rustdesk')) {
- return buildInstallCard(
- "Status",
- "${translate("new-version-of-{${bind.mainGetAppNameSync()}}-tip")} (${bind.mainGetNewVersion()}).",
- "Click to download", () async {
- final Uri url = Uri.parse('https://rustdesk.com/download');
- await launchUrl(url);
- }, closeButton: true);
- }
- if (systemError.isNotEmpty) {
- return buildInstallCard("", systemError, "", () {});
- }
+ // if (!bind.isCustomClient() &&
+ // updateUrl.isNotEmpty &&
+ // !isCardClosed &&
+ // bind.mainUriPrefixSync().contains('rustdesk')) {
+ // return buildInstallCard(
+ // "Status",
+ // "${translate("new-version-of-{${bind.mainGetAppNameSync()}}-tip")} (${bind.mainGetNewVersion()}).",
+ // "Click to download", () async {
+ // final Uri url = Uri.parse('https://rustdesk.com/download');
+ // await launchUrl(url);
+ // }, closeButton: true);
+ // }
+ // if (systemError.isNotEmpty) {
+ // return buildInstallCard("", systemError, "", () {});
+ // }
if (isWindows && !bind.isDisableInstallation()) {
if (!bind.mainIsInstalled()) {
+13
View File
@@ -0,0 +1,13 @@
diff --git a/flutter/lib/desktop/pages/connection_page.dart b/flutter/lib/desktop/pages/connection_page.dart
index d9dc3eec4..76f386b76 100644
--- a/flutter/lib/desktop/pages/connection_page.dart
+++ b/flutter/lib/desktop/pages/connection_page.dart
@@ -131,7 +131,7 @@ class _OnlineStatusWidgetState extends State<OnlineStatusWidget> {
if (!isIncomingOnly) startServiceWidget(),
// ready && public
// No need to show the guide if is custom client.
- if (!isIncomingOnly) setupServerWidget(),
+ //if (!isIncomingOnly) setupServerWidget(),
],
);
+20
View File
@@ -0,0 +1,20 @@
diff --git a/flutter/lib/common/widgets/peer_card.dart b/flutter/lib/common/widgets/peer_card.dart
index 0a15eb45b..d776dd556 100644
--- a/flutter/lib/common/widgets/peer_card.dart
+++ b/flutter/lib/common/widgets/peer_card.dart
@@ -1328,8 +1328,13 @@ Widget getOnline(double rightPadding, bool online) {
waitDuration: const Duration(seconds: 1),
child: Padding(
padding: EdgeInsets.fromLTRB(0, 4, rightPadding, 4),
- child: CircleAvatar(
- radius: 3, backgroundColor: online ? Colors.green : kColorWarn)));
+ child: online
+ ? CircleAvatar(radius: 3, backgroundColor: Colors.green)
+ : Icon(
+ Icons.close, // Red X for offline (Material Icon)
+ color: Colors.red,
+ size: 12.0, // Adjust size as needed
+ )));
}
Widget build_more(BuildContext context, {bool invert = false}) {