fix: debug, terminal web (#12375)

Signed-off-by: fufesou <linlong1266@gmail.com>
This commit is contained in:
fufesou
2025-07-22 19:26:50 +08:00
committed by GitHub
parent 9bca5ac000
commit 61194182eb
8 changed files with 73 additions and 15 deletions

View File

@@ -551,7 +551,7 @@ abstract class BasePeerCard extends StatelessWidget {
MenuEntryBase<String> _terminalAction(BuildContext context) { MenuEntryBase<String> _terminalAction(BuildContext context) {
return _connectCommonAction( return _connectCommonAction(
context, context,
translate('Terminal'), '${translate('Terminal')} (beta)',
isTerminal: true, isTerminal: true,
); );
} }
@@ -560,7 +560,7 @@ abstract class BasePeerCard extends StatelessWidget {
MenuEntryBase<String> _terminalRunAsAdminAction(BuildContext context) { MenuEntryBase<String> _terminalRunAsAdminAction(BuildContext context) {
return _connectCommonAction( return _connectCommonAction(
context, context,
translate('Terminal (Run as administrator)'), '${translate('Terminal (Run as administrator)')} (beta)',
isTerminalRunAsAdmin: true, isTerminalRunAsAdmin: true,
); );
} }

View File

@@ -183,7 +183,7 @@ List<TTextMenu> toolbarControls(BuildContext context, String id, FFI ffi) {
); );
v.add( v.add(
TTextMenu( TTextMenu(
child: Text(translate('Terminal')), child: Text('${translate('Terminal')} (beta)'),
onPressed: () => connectWithToken(isTerminal: true)), onPressed: () => connectWithToken(isTerminal: true)),
); );
v.add( v.add(

View File

@@ -563,7 +563,7 @@ class _ConnectionPageState extends State<ConnectionPage>
() => onConnect(isViewCamera: true) () => onConnect(isViewCamera: true)
), ),
( (
'Terminal', '${translate('Terminal')} (beta)',
() => onConnect(isTerminal: true) () => onConnect(isTerminal: true)
), ),
] ]

View File

@@ -378,7 +378,7 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
}, },
), ),
SettingsTile.switchTile( SettingsTile.switchTile(
title: Text('${translate('Adaptive bitrate')} (beta)'), title: Text(translate('Adaptive bitrate')),
initialValue: _enableAbr, initialValue: _enableAbr,
onToggle: isOptionFixed(kOptionEnableAbr) onToggle: isOptionFixed(kOptionEnableAbr)
? null ? null
@@ -540,7 +540,7 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
enhancementsTiles.add(SettingsTile.switchTile( enhancementsTiles.add(SettingsTile.switchTile(
initialValue: _enableStartOnBoot, initialValue: _enableStartOnBoot,
title: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ title: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Text("${translate('Start on boot')} (beta)"), Text(translate('Start on boot')),
Text( Text(
'* ${translate('Start the screen sharing service on boot, requires special permissions')}', '* ${translate('Start the screen sharing service on boot, requires special permissions')}',
style: Theme.of(context).textTheme.bodySmall), style: Theme.of(context).textTheme.bodySmall),

View File

@@ -3214,7 +3214,7 @@ class FFI {
} }
void routeTerminalResponse(Map<String, dynamic> evt) { void routeTerminalResponse(Map<String, dynamic> evt) {
final int terminalId = evt['terminal_id'] ?? 0; final int terminalId = TerminalModel.getTerminalIdFromEvt(evt);
// Route to specific terminal model if it exists // Route to specific terminal model if it exists
final model = _terminalModels[terminalId]; final model = _terminalModels[terminalId];

View File

@@ -165,9 +165,58 @@ class TerminalModel with ChangeNotifier {
} }
} }
static int getTerminalIdFromEvt(Map<String, dynamic> evt) {
if (evt.containsKey('terminal_id')) {
final v = evt['terminal_id'];
if (v is int) {
// Desktop and mobile send terminal_id as an int
return v;
} else if (v is String) {
// Web sends terminal_id as a string
final parsed = int.tryParse(v);
if (parsed != null) {
return parsed;
} else {
debugPrint(
'[TerminalModel] Failed to parse terminal_id as integer: $v. Expected a numeric string.');
return 0;
}
} else {
// Unexpected type, log and handle gracefully
debugPrint(
'[TerminalModel] Unexpected terminal_id type: ${v.runtimeType}, value: $v. Expected int or String.');
return 0;
}
} else {
debugPrint('[TerminalModel] Event does not contain terminal_id');
return 0;
}
}
static bool getSuccessFromEvt(Map<String, dynamic> evt) {
if (evt.containsKey('success')) {
final v = evt['success'];
if (v is bool) {
// Desktop and mobile
return v;
} else if (v is String) {
// Web
return v.toLowerCase() == 'true';
} else {
// Unexpected type, log and handle gracefully
debugPrint(
'[TerminalModel] Unexpected success type: ${v.runtimeType}, value: $v. Expected bool or String.');
return false;
}
} else {
debugPrint('[TerminalModel] Event does not contain success');
return false;
}
}
void handleTerminalResponse(Map<String, dynamic> evt) { void handleTerminalResponse(Map<String, dynamic> evt) {
final String? type = evt['type']; final String? type = evt['type'];
final int evtTerminalId = evt['terminal_id'] ?? 0; final int evtTerminalId = getTerminalIdFromEvt(evt);
// Only handle events for this terminal // Only handle events for this terminal
if (evtTerminalId != terminalId) { if (evtTerminalId != terminalId) {
@@ -193,7 +242,7 @@ class TerminalModel with ChangeNotifier {
} }
void _handleTerminalOpened(Map<String, dynamic> evt) { void _handleTerminalOpened(Map<String, dynamic> evt) {
final bool success = evt['success'] ?? false; final bool success = getSuccessFromEvt(evt);
final String message = evt['message'] ?? ''; final String message = evt['message'] ?? '';
final String? serviceId = evt['service_id']; final String? serviceId = evt['service_id'];

View File

@@ -908,8 +908,18 @@ class RustdeskImpl {
return js.context.callMethod('getByName', ['option:local', key]); return js.context.callMethod('getByName', ['option:local', key]);
} }
// Do not return the real environment variables.
// Use the global variable as the environment variable in web.
String mainGetEnv({required String key, dynamic hint}) { String mainGetEnv({required String key, dynamic hint}) {
throw UnimplementedError("mainGetEnv"); return js.context.callMethod('getByName', ['envvar', key]);
}
// Use the global variable as the environment variable in web.
void mainSetEnv({required String key, String? value, dynamic hint}) {
js.context.callMethod('setByName', [
'envvar',
jsonEncode({'name': key, 'value': value})
]);
} }
Future<void> mainSetLocalOption( Future<void> mainSetLocalOption(
@@ -1960,9 +1970,7 @@ class RustdeskImpl {
} }
Future<void> sessionCloseTerminal( Future<void> sessionCloseTerminal(
{required UuidValue sessionId, {required UuidValue sessionId, required int terminalId, dynamic hint}) {
required int terminalId,
dynamic hint}) {
return Future(() => js.context.callMethod('setByName', [ return Future(() => js.context.callMethod('setByName', [
'close_terminal', 'close_terminal',
jsonEncode({ jsonEncode({

View File

@@ -131,7 +131,7 @@ fn get_or_create_service(
// Ensure cleanup task is running // Ensure cleanup task is running
ensure_cleanup_task(); ensure_cleanup_task();
service.lock().unwrap().reset_status(); service.lock().unwrap().reset_status(is_persistent);
Ok(service) Ok(service)
} }
@@ -600,7 +600,8 @@ impl PersistentTerminalService {
!self.sessions.is_empty() !self.sessions.is_empty()
} }
fn reset_status(&mut self) { fn reset_status(&mut self, is_persistent: bool) {
self.is_persistent = is_persistent;
self.needs_session_sync = true; self.needs_session_sync = true;
for session in self.sessions.values() { for session in self.sessions.values() {
let mut session = session.lock().unwrap(); let mut session = session.lock().unwrap();