sync同步 - #55
Open
avkiller wants to merge 47 commits into
Open
Conversation
* fix: restrict switch sides to remote desktop sessions Reject switch sides requests outside authenticated remote desktop sessions, and reject switch sides responses that try to carry non-remote login types. Add scope coverage so file transfer, terminal, view camera, and port forward sessions cannot use switch sides. Signed-off-by: 21pages <sunboeasy@gmail.com> * fix review: consume switch sides UUID before rejecting response Signed-off-by: 21pages <sunboeasy@gmail.com> --------- Signed-off-by: 21pages <sunboeasy@gmail.com>
* Fix Adjust Window sizing across DPI and fullscreen transitions
Signed-off-by: 21pages <sunboeasy@gmail.com>
* Use visible screen frame for Adjust Window
Signed-off-by: 21pages <sunboeasy@gmail.com>
* Tolerate floating-point errors in Adjust Window sizing
Signed-off-by: 21pages <sunboeasy@gmail.com>
* Fix review, fix Adjust Window async metric guards
Capture the current screen before awaiting window geometry so one target-frame calculation uses consistent screen metrics.
Return early when adjusting without a context and the Flutter view list is empty, instead of calling views.first after the window or engine may have been torn
down.
Clarify the platform coordinate units used for Adjust Window scaling.
* Fix Adjust Window for maximized Linux windows
Unmaximize Linux remote windows before applying Adjust Window because native setFrame may be ignored while the window is maximized.
* Fix Adjust Window screen refresh guards
Refresh screen metrics before checking Adjust Window availability and again after exiting fullscreen so target-frame calculation uses current window geometry.
Hide Adjust Window on web because resizing relies on desktop window APIs.
* Fix review, handle missing window frame in Adjust Window
Return null when WindowController.getFrame fails so Adjust Window availability checks and resize attempts skip cleanly if the window is hidden or disposed.
---------
Signed-off-by: 21pages <sunboeasy@gmail.com>
Signed-off-by: cuishuang <imcusg@gmail.com>
…5633) `rustdesk --deploy --id ""` (e.g. an unset variable in a deployment script) deploys a blank id, then wipes the local id and unconfirms the key through the IPC config write. The Android deploy flow already guards an empty id (#15146); apply the same guard to the CLI, and reject an empty id at the IPC write boundary the same way the read path was fixed in #15626.
Signed-off-by: Gateslu <lyjbbq@163.com>
…accumulation on macOS (#15623) Signed-off-by: Viktor Kuksgauzen <vkpiar@gmail.com>
Co-authored-by: bmmh1 <bmmh1@users.noreply.github.com>
* fix stale primary display selection Signed-off-by: 21pages <sunboeasy@gmail.com> * fix stale display selection during login and switching - resolve the primary display from the refreshed login snapshot - defer display enumeration until authentication succeeds - read Wayland displays and primary index from the same cache snapshot - reject stale monitor and camera indices during display switching Signed-off-by: 21pages <sunboeasy@gmail.com> * fix inconsistent display snapshots during login - return displays from the same enumeration used to select the primary - avoid re-reading the shared display cache after updating it - use the same converted snapshot during Wayland initialization Signed-off-by: 21pages <sunboeasy@gmail.com> * avoid cloning unchanged display snapshots Signed-off-by: 21pages <sunboeasy@gmail.com> * fix invalid display subset handling Signed-off-by: 21pages <sunboeasy@gmail.com> * minimize code churn in switch_display_to Signed-off-by: 21pages <sunboeasy@gmail.com> --------- Signed-off-by: 21pages <sunboeasy@gmail.com>
* fix: refresh wayland uinput range on compositor layout change The uinput absolute range is computed once at session init. If the compositor layout changes mid-session (monitor scale or position change, or a portal virtual output appearing once capture starts), injected coordinates are rescaled by the stale range and land offset. Poll the live desktop bounding box from the display service loop while subscribed (one wayland roundtrip, throttled to 1.5s, no subprocesses) and re-apply the uinput resolution when it changes. Also read a fresh layout when computing the initial range in check_init, since the cache is not cleared when a session closes through the restore-token path. This is the X component of #15601. The stale advertised origins (the Y component) are not touched here: re-advertising DisplayInfo mid-session trips the portal re-negotiation and can drop displays. Signed-off-by: Cody Harris <codyharris7188@gmail.com> * fix: bound the mouse resolution IPC wait during session init Wrap update_mouse_resolution in the same 3s timeout the periodic refresh uses, so a hung IPC response can't stall check_init. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: build timeout future inside runtime, split linux lazy_static Constructing the timeout future eagerly as the block_on argument panics with 'there is no reactor running'; move it into the async block so it is built inside the runtime context. Also move WAYLAND_UINPUT_RECT into its own cfg-gated lazy_static block, an attribute on a single item inside the shared block does not compile. * fix: confirm uinput mouse device adopted new range before caching rect send_refresh() now waits for the mouse service to ack that it recreated the device with the new range instead of firing and forgetting, and update_mouse_resolution() propagates that result. The layout poller only caches the rect after the device actually adopts the range, so a failed refresh errors and retries on the next check. The ack read is bounded by IPC_REQUEST_TIMEOUT, matching the keyboard get-key-state path. * fix: propagate refresh failures instead of caching a stale range - input_service: error when the custom-mouse downcast fails so the poller retries instead of caching an unconfirmed refresh - uinput: on device recreation failure, keep the current device and the IPC connection and withhold the ack so the client retries, instead of killing the mouse handler * fix: remap injected wayland coords onto the live layout after a monitor moves The range refresh corrects the uinput ABS bounds, but a single-display client sends whole-desktop coordinates offset by the origin of the display it follows, taken from the layout advertised at session init. When another monitor is rescaled or moved that origin shifts, so the coordinate lands offset before it reaches uinput and the range refresh cannot recover it. Snapshot the per-display layout at init, poll the live layout on the existing 1.5s throttle, and when they differ remap each injected move into the followed display's current rectangle (matched by connector name, index fallback when the compositor reports none). No-op and lock-free while the layout is unchanged. --------- Signed-off-by: Cody Harris <codyharris7188@gmail.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: fufesou <linlong1266@gmail.com>
* feat(recording): add visibility and service storage options
- support hide-recording-button in Flutter and Sciter
- allow a custom save directory for Windows service recordings
- sanitize peer IDs used in recording filenames
Tested:
- with hide-recording-button=Y and allow-auto-record-outgoing=Y,
outgoing sessions are recorded automatically while the recording button
remains hidden and cannot be stopped from the UI; verified on Flutter
desktop, Sciter, and Android
- windows-service-video-save-directory takes effect when the Windows client
runs as an installed service
- the Windows controlling side can save recordings for direct IP:port
connections
Signed-off-by: 21pages <sunboeasy@gmail.com>
* update hbb_common
Signed-off-by: 21pages <sunboeasy@gmail.com>
* fix(recording): validate configured save directories
- trim configured recording directory paths
- reject non-absolute paths and fall back to defaults
- warn when a non-empty path is invalid
Signed-off-by: 21pages <sunboeasy@gmail.com>
* fix(recording): validate configured save directories
Signed-off-by: 21pages <sunboeasy@gmail.com>
---------
Signed-off-by: 21pages <sunboeasy@gmail.com>
…15532) * feat(terminal): add Ctrl toggle and Ctrl+X shortcut keys to mobile terminal floating keyboard Signed-off-by: dongrencd <dongrencd@users.noreply.github.com> * refactor(terminal): restructure keyboard layout with collapse button - Move | from Row1 position 3 to Row1 end (aligned with collapse button) - Remove ~ from Row2, add collapse button (∨/∧) after PgDn - Row3: conditional render, add ~ and -, remove trailing placeholders - Collapse state persisted via kOptionEnableShowTerminalCtrlKeys - Row3 defaults to collapsed for compact layout Signed-off-by: dongrencd <dongrencd@users.noreply.github.com> * fix(terminal): restore trailing placeholders in Row3 for alignment Row3 needs trailing placeholders to match Row1/Row2 width (348px) so Ctrl aligns with Tab in Row2 and Esc in Row1. Signed-off-by: dongrencd <dongrencd@users.noreply.github.com> * fix(terminal): update mobile keyboard layout per review Signed-off-by: dong.ren.cd <dong.ren.cd@tcl.com> * fix(terminal): address mobile keyboard review regressions Signed-off-by: dong.ren.cd <dong.ren.cd@tcl.com> * fix(terminal): preserve ctrl-j newline mapping on mobile Signed-off-by: dong.ren.cd <dong.ren.cd@tcl.com> * fix(terminal): preserve pasted input with modifiers Signed-off-by: dong.ren.cd <dong.ren.cd@tcl.com> * fix(terminal): harden mobile modifier and paste input Signed-off-by: dong.ren.cd <dong.ren.cd@tcl.com> * fix(terminal): harden mobile paste shortcut handling Signed-off-by: dong.ren.cd <dong.ren.cd@tcl.com> * fix(terminal): preserve unicode graphemes under ctrl * fix(terminal): avoid modifier scan for inactive locks * fix(terminal): keep default hardware paste shortcuts * fix(terminal): guard hardware paste with modifier locks * fix(terminal): update mobile key button color role --------- Signed-off-by: dongrencd <dongrencd@users.noreply.github.com> Signed-off-by: dong.ren.cd <dong.ren.cd@tcl.com> Co-authored-by: dongrencd <dongrencd@users.noreply.github.com> Co-authored-by: dong.ren.cd <dong.ren.cd@tcl.com>
* fix(macos): prevent remote keyboard focus leaks Gate keyboard grabbing on window, tab, lifecycle, and primary focus state. Release grabs on focus loss or minimize and avoid duplicate grab transitions. Signed-off-by: fufesou <linlong1266@gmail.com> * fix: macos, keyboard focus, comments known issue Signed-off-by: fufesou <linlong1266@gmail.com> * fix: macos, keyboard, fullscreen space switch Signed-off-by: fufesou <linlong1266@gmail.com> * fix: macos, keyboard, focus, relative mouse mode Signed-off-by: fufesou <linlong1266@gmail.com> * fix(macOS): preserve local overlay focus during input recovery Prevent fullscreen and relative-mouse focus recovery from reclaiming remote keyboard input while a local chat or dialog overlay owns focus. Signed-off-by: fufesou <linlong1266@gmail.com> * fix: macos, keyboard, comments trade-off Signed-off-by: fufesou <linlong1266@gmail.com> --------- Signed-off-by: fufesou <linlong1266@gmail.com>
* id whitelist * hbb_common * Update flutter/lib/common/widgets/dialog.dart Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * support wss:// for web client Signed-off-by: 21pages <sunboeasy@gmail.com> * fix: handle ID copying separately and remove whitelist logs Signed-off-by: 21pages <sunboeasy@gmail.com> * fix en translation Signed-off-by: 21pages <sunboeasy@gmail.com> * fix: check switch-side ID whitelist after login initialization Signed-off-by: 21pages <sunboeasy@gmail.com> * track pending 2FA challenge state Signed-off-by: 21pages <sunboeasy@gmail.com> * support Unicode IDs in whitelist settings Signed-off-by: 21pages <sunboeasy@gmail.com> * refactor: unify client ID resolution Signed-off-by: 21pages <sunboeasy@gmail.com> --------- Signed-off-by: 21pages <sunboeasy@gmail.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: 21pages <sunboeasy@gmail.com>
* docs(agents): require minimally invasive, additive-first patches Codify the review feedback from the tray ghost-icon fix: fixes should add self-contained code around existing lines instead of restructuring them, keep platform-specific logic in src/platform/ with fn-local imports, and leave only thin one-line hooks in shared files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(windows): stop duplicate tray icons from piling up (#15689) `check_process("--tray", ..)` is used to decide whether a tray process needs to be spawned, but it can miss one that is already running: it cannot read the command line of an elevated process from a non-elevated one (the installer spawns the tray elevated), and wmic, used by 32-bit builds since #11638, is gone from newer Windows 11. `connection.rs` runs that check once per incoming connection, so every miss added another tray icon and they kept piling up, which is the same blind spot behind #6692. Hold a named mutex in the session namespace as the authoritative single instance guard, so a redundant tray process exits before creating an icon. `ERROR_ACCESS_DENIED` also counts as "already running", since it means the mutex belongs to a tray we may not touch. Also remove the icon before the tray menu's "Stop service" calls uninstall_service(): on success it ends the process with std::process::exit, which skips the destructor that would call Shell_NotifyIcon(NIM_DELETE), so every click left a ghost icon behind. The icon is shown again if stopping the service failed or was cancelled. Ghost icons from the taskkill in the install/update/service flows are left alone here. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(windows): note that update_me's pid lookup can silently find nothing The pids are matched by command line, which comes back empty for a 32-bit build reading 64-bit processes (hence the `wmic` fallback of #11638, and `wmic` is no longer installed by default since Windows 11 24H2) and for a non-elevated process reading an elevated one. `taskkill` matches by image name and still works, but the session lists are then empty, so the restore guard silently restores nothing and the update leaves the user without a tray icon and main window. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(windows): record the confirmed cause of the duplicate tray icons Process Explorer output in #15689 pinned it down: run_after_run_cmds() spawns the tray in the caller's own context, so installing or toggling the service from a RustDesk that was itself started elevated leaves a high integrity tray behind, which a medium integrity main window cannot inspect afterwards. Record where the detection fails exactly, so the next reader doesn't have to rediscover that the executable path, not the command line, is what comes back empty. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
The lock still pinned 7d9a674, the commit rustdesk-org/window_manager#8 reverted. Move it to current main (cf4aef0), which carries the reworked guard for methods called after the toplevel window is destroyed. Edited by hand rather than via pub upgrade: upgrading re-resolved 17 packages, downgrading some and pulling flutter_test and its leak_tracker tree in as new entries, none of which belongs in this change. #15703 Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: pi <pi@m2.local>
…ME.md (#15713) Co-authored-by: pi <pi@m2.local>
….md (#15712) Co-authored-by: pi <pi@m2.local>
* fix(flutter/windows): heal the white window left by a resize around the first frame If the window is resized between the creation of the Flutter surface and the present of the first frame - which is what the PowerToys FancyZones option "Move newly created windows to their last known zone" does - the embedder's resize synchronization enters kResizeStarted and from then on only presents frames that match the new size. A frame already generated for the old size is rejected, nothing schedules a matching one, and the window stays white until a real resize re-enters OnWindowSizeChanged, which resets the resize target and resends the window metrics. Sciter is unaffected: it repaints synchronously on WM_PAINT and has no such handshake. Upstream has no fix (flutter/flutter#159630, open at P3). Recover with a timer armed at creation and re-armed on WM_SHOWWINDOW (covers windows created hidden and shown much later, e.g. the connection manager): until the first frame arrives, kick the engine - first with the cheap ForceRedraw(), which only helps when no resize is pending (it is gated on resize_status_ == kDone), then by nudging the Flutter child window by 1px and back, which re-enters OnWindowSizeChanged and heals the wedge the same way minimize/restore does. Because the first-frame callback fires on frame generation even when the present is rejected, a resize observed before the first frame forces one final child refresh - in practice nearly every window sees a pre-first-frame WM_SIZE, so this acts as a cheap unconditional guarantee. Giving up after 5s is logged. The remote session windows get the same fix in rustdesk_desktop_multi_window. #6756 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * chore(flutter): bump desktop_multi_window for the white-window fix Picks up rustdesk-org/rustdesk_desktop_multi_window#33 (340ca43), the session-window side of the FancyZones white-window workaround. Only the resolved-ref of this one dependency is moved; nothing else is upgraded. #6756 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(flutter/windows): drop a dead guard and log where users can see it Two follow-ups on the force-redraw timer. The resized_before_first_frame_ guard never discriminated. CreateWindow() sends a WM_SIZE before it returns, and WM_NCCREATE has already installed the window pointer by then, so the flag was set during construction - before OnCreate() even arms the timer - and was therefore always true when the first frame arrived. Drop the flag and do the final child refresh unconditionally, which is what the code already did, and say so instead of implying there is an exceptional case. The give-up message went to std::cerr, which lands nowhere on the machines that hit this: main.cpp only attaches a console when the process is started from one or runs under a debugger. Use OutputDebugString so it is actually readable with DebugView in the field. Also note in the comment that the "callback fires on frame generation" premise is not load-bearing - if it only fired on a successful present, the timer would simply keep nudging - so the redundancy is not mistaken for duplication and removed later. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * chore(flutter): bump desktop_multi_window to pick up the follow-ups Moves the pin from the #33 merge (340ca43) to current master (f8c4fce), which adds #34: the dead resized_before_first_frame_ guard is gone and the give-up message goes to OutputDebugString instead of a stderr nobody sees. Keeps the sub-window fix in step with the runner fix in this branch; without it the two would ship the same logic in two different states. Edited by hand, not via pub upgrade - that re-resolves unrelated packages. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
quit_gui() ends the process on Windows (std::process::exit) and macOS (NSApp terminate), but on Linux it calls gtk_main_quit(), which has no effect in the Flutter connection manager: flutter/linux/main.cc runs g_application_run() (GtkApplication), so gtk_main() is never called and the assertion inside gtk_main_quit() just fails. quit_cm() is the only caller that relies on quit_gui() to end the process. The main window path in ipc.rs calls std::process::exit(-1) right after it, and the two remaining call sites are in the Sciter UI, which is not compiled for flutter builds. So a connection manager reaching quit_cm() on Linux kept running while no longer serving the `_cm` ipc endpoint, which also stops the server from reusing it, so the next connection spawns one more. NOTE: this is a fallback, not an explanation for the stale processes of #15698: a client merely disconnecting does not reach quit_cm(), the Flutter side closes the window instead. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
The give-up log added in the white-window follow-ups declared a local named message inside MessageHandler, shadowing its UINT message parameter. MSVC C4457 plus /WX failed both Windows nightly jobs. Point the lock at rustdesk_desktop_multi_window#35 which renames it. https://github.com/rustdesk/rustdesk/actions/runs/30512756157 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(linux): load librustdesk.so relative to the executable The runner and the Dart FFI init loaded the core library by bare name, relying on the runner's $ORIGIN/lib RPATH. Repackaged installs (CachyOS repo, AUR) can lose that RPATH, making the app fail to start with "Failed to load librustdesk.so" unless users add the lib directory to ld.so.conf. Resolve lib/librustdesk.so next to the executable first, then fall back to the loader search path. #14407 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(linux): harden bundled librustdesk.so resolution Address review: bail out when readlink() may have truncated the executable path, and widen the Dart try block so any failure probing the bundled library falls back to the loader search path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: fufesou <linlong1266@gmail.com>
… (EU CRA) (#15732) * Update flutter-build.yml to generate SBOM * SBOM Generation: Also checkout submodules Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> --------- Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Leftover from an abandoned Firebase integration. The file is not referenced anywhere in the repository and is not listed in Runner.xcodeproj, so it was never copied into the app bundle. No Firebase or Google Sign-In pod is present in Podfile/Podfile.lock, nothing calls FirebaseApp.configure(), Info.plist declares no REVERSED_CLIENT_ID URL scheme, and on the Dart side both Firebase.initializeApp() and firebase_analytics stay commented out. Note the values it held were Firebase client configuration (project identifiers and a public OAuth client id), which are public by design and ship inside client binaries -- not secrets. This removes dead weight, it is not a credential rotation. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix(flutter): show error and retry when fetching login options fails The third-party login section of the login dialog was silently hidden whenever /api/login-options could not be fetched (e.g. TLS handshake aborted by a router/ISP scam filter, discussion #15700), leaving users staring at a dialog with no feedback. The pure-Dart HTTP path also had no timeout, so a black-holed connection could hang indefinitely. - let transport errors propagate from queryOidcLoginOptions instead of swallowing them; a non-JSON response still means "no third-party login" so self-hosted servers without this API keep the old behavior - show network_error_tip, a Retry button, and the underlying error in the login dialog so users and supporters can see what failed - bound the Dart HTTP branch with a 15s timeout; the Rust branch keeps its own bounded per-attempt timeouts and is awaited to completion so a retry never races the URL-keyed ASYNC_HTTP_STATUS entry of an abandoned in-flight request Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(flutter): surface currentUser refresh failures that were only logged Non-transport failures of the token auto-login (/api/currentUser) -- a bad HTTP status, a filter's HTML block page, or an error field in the body -- were only debugPrinted, so the address book / group tabs showed nothing and offered no retry. Reuse the existing networkError channel so netWorkErrorWidget shows the error with its Retry button. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(flutter): keep retry row visible with progress while refetching login options Review follow-ups: clicking Retry used to clear the error and hide the row with no pending feedback, which could read as a dead click while the Rust fallback chain runs; keep the row, disable the button, and show the usual LinearProgressIndicator instead. Also raise the Dart HTTP branch timeout to 30s so large web address book pulls on slow links do not newly time out; it still bounds the previously unbounded hang and stays above the Rust side's 12s per-attempt timeout. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * chore: update webpki-roots to latest Mozilla root store 0.26.9 -> 0.26.11 (now a forwarding shim over 1.x, used by tungstenite) 1.0.4 -> 1.0.9 (used by reqwest / hyper-rustls / hbb_common) The 0.26.9 line carried its own root snapshot frozen in early 2025, so the websocket TLS path was building against a stale bundle. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci: weekly workflow to PR webpki-roots root store updates webpki-roots is a transitive dependency, so dependabot's cargo version updates would not cover it. A scheduled job runs cargo update for every webpki-roots instance in each lockfile and opens a PR when the pinned Mozilla root snapshot is behind, keeping root store changes reviewable instead of baking them silently into release builds. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(flutter): hide network tip for server-reported currentUser errors Review follow-up: when /api/currentUser fails with an error the server itself reported (an error field in a JSON body, or an unexpected schema), "Please check your network connection" was misleading. Track whether the surfaced error came from a server response and skip the network tip for those; FormatException (a non-JSON body such as a filter's block page) keeps it, since that still indicates a network or middlebox problem. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(flutter): close timed-out HTTP clients * fix(flutter): flag server-reported errors at the throw site Review follow-up (CodeRabbit). Classifying by `e is! FormatException` mislabeled ambiguous failures: a middlebox block page returning 200 with valid-but-wrong-shape JSON throws a TypeError from fromJson and was shown without the check-your-network tip, though it is a network artifact. Set networkErrorFromServer only at the one site that is certainly server-reported (an error field in the body); every other failure keeps the network tip plus the raw error text. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci: serialize webpki-roots update runs, null-delimit lockfile paths Review follow-up (CodeRabbit). A manual dispatch overlapping the weekly cron could have an older run force-push over the newer branch state; queue runs via a concurrency group without cancel-in-progress. Also iterate lockfiles with git ls-files -z so a path with spaces cannot be word-split, and keep the loop failing the step on any cargo error. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(flutter): improve login retry feedback Use the theme primary color for the Retry button and hide stale error messages while a retry is in progress. Signed-off-by: fufesou <linlong1266@gmail.com> * fix(flutter): surface login option response errors Signed-off-by: fufesou <linlong1266@gmail.com> --------- Signed-off-by: fufesou <linlong1266@gmail.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: fufesou <linlong1266@gmail.com>
* Update nl.rs Updates plus a small improvement to the Dutch language file * Update nl.rs Now including fixes for coderabbit reportings * Update nl.rs Three more fixes re. greptile * Update nl.rs typo 'loskoppelenn' fixed as well
* swtich_code for hbbs to bypass ACL * improve register_switch_grant: skip public server, log at error level Also document why registration is fire-and-forget with no retry: the peer connects within seconds, so a late retry would land after its punch request was already rejected; a failed switch is recovered by the user triggering it again, which registers a fresh grant. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * add timestamp Signed-off-by: 21pages <sunboeasy@gmail.com> * fix(switch-sides): handle grant registration clock skew - retry registration once with the server-provided timestamp - require an explicit accepted response from hbbs - report malformed or incomplete responses Signed-off-by: 21pages <sunboeasy@gmail.com> * fix(switch-sides): register grants with code verifiers - send a derived verifier instead of the raw switch code - use detached signatures for grant registration - add verifier and signed-message tests Signed-off-by: 21pages <sunboeasy@gmail.com> --------- Signed-off-by: 21pages <sunboeasy@gmail.com> Co-authored-by: 21pages <sunboeasy@gmail.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…15753) * fix(android): close outgoing sessions when the task is swiped away Swiping RustDesk away from recents destroys the UI but does not necessarily end the process: when MainService is running (screen share enabled, or started at boot) the process survives, and with it the native io_loop of any active outgoing session. That orphaned io_loop keeps echoing TestDelay (client.rs handle_test_delay runs entirely on the network thread, no UI involved), which keeps refreshing last_recv_time on the controlled side. Its 30s inactivity timeout in server/connection.rs therefore never fires, so the remote session stays established with no UI left to close it, and the peer cannot be reconnected to. Close client sessions from Service.onTaskRemoved, which fires only on explicit task removal -- not on Home or backgrounding, so ordinary backgrounding is unaffected. The service itself keeps running, so incoming connections and the device staying reachable are unchanged. This complements 152c5c7, which covered the route-pop path via dispose(); dispose() does not run when the task is removed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(android): also close sessions on activity destroy Review follow-up. onTaskRemoved only reaches MainService, but the accessibility InputService keeps the process alive on its own: a user with input control enabled and screen sharing off has a surviving process after a swipe while MainService is not running, so the callback never fires and the session still outlives its UI. onTaskRemoved cannot cover that -- InputService is bound by the system, not started, so the callback is not delivered there. Close from MainActivity.onDestroy() as well, which runs while the process is still alive regardless of which service keeps it up. Guarded on isFinishing so a destroy for recreation (configuration change, "don't keep activities") does not tear down a live session. Both paths are idempotent. Also drop the now-wrong "on task removed" wording from the Rust log, which has two distinct callers. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(android): release held keys before draining the session map close_all_sessions drained SESSIONS first, then called release_remote_keys. The release path sends through get_cur_session(), which resolves against SESSIONS, so every generated key-up was dropped after take_remote_keys() had already cleared TO_RELEASE: a key held as the task is removed stays down on the controlled side until its own timeout, with the state lost locally. Release first, while a session is still registered. It is a no-op when no key is held, so the previous is_empty() guard is not needed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* refact(oidc): manually open the browser Signed-off-by: fufesou <linlong1266@gmail.com> * refact(oidc): allow copying OIDC authentication links Signed-off-by: fufesou <linlong1266@gmail.com> * Remove unused translation in ko.rs Signed-off-by: fufesou <linlong1266@gmail.com> * refact(oidc): better hint on browser didn't open Signed-off-by: fufesou <linlong1266@gmail.com> * refact(oidc): login handle exception Signed-off-by: fufesou <linlong1266@gmail.com> * refact(oidc): remove unused translations Signed-off-by: fufesou <linlong1266@gmail.com> * refact(oidc): login handle error Signed-off-by: fufesou <linlong1266@gmail.com> * refact(oidc): login in flight Signed-off-by: fufesou <linlong1266@gmail.com> * refact(translation): move "Continue" to the end of template.rs Signed-off-by: fufesou <linlong1266@gmail.com> * refact(oidc): var rename Signed-off-by: fufesou <linlong1266@gmail.com> * refact(oidc): remove useless "open sign-in page" Signed-off-by: fufesou <linlong1266@gmail.com> * Remove unecessary translation contents Signed-off-by: fufesou <linlong1266@gmail.com> * refact(oidc): better way to show&expand the url Signed-off-by: fufesou <linlong1266@gmail.com> * refact(oidc): better login ui Signed-off-by: fufesou <linlong1266@gmail.com> * fix(oidc): discard stale auth results after cancellation Signed-off-by: fufesou <linlong1266@gmail.com> * fix(oidc): handle auth status query failures safely Signed-off-by: fufesou <linlong1266@gmail.com> * fix(oidc): prevent concurrent login operations - reuse the active login dialog and block duplicate password submissions - cancel only active OIDC operations when closing the dialog - preserve authentication state until failure cancellation succeeds Signed-off-by: fufesou <linlong1266@gmail.com> * fix(oidc): refine login options error feedback Preserve typed errors to hide the network tip for HTTP failures and clarify the login-options API contract. Signed-off-by: fufesou <linlong1266@gmail.com> --------- Signed-off-by: fufesou <linlong1266@gmail.com>
…15726) `request_remote_desktop` and its response handlers call the portal method first and only then subscribe to the resulting Request's `Response` signal, using the object path returned by the call. The comment above `create_session` already describes why that is wrong: > To avoid a race condition between the caller subscribing to the signal > after receiving the reply for the method call and the signal getting > emitted, a convention for Request object paths has been established that > allows the caller to subscribe to the signal before making the method > call. The code then does the opposite of what the comment says. When the portal emits `Response` before our match rule is installed, the signal is dropped and the flow stalls: `request_remote_desktop` spins its 3-minute wait loop and gives up, so the user sees the screen picker again (or a failure) even when a valid restore token would have restored the session silently. Build the request path from our unique bus name plus the `handle_token` we pass in the call arguments, per the Request documentation, and subscribe before calling. Applied to all five portal calls: CreateSession, SelectSources (both the ScreenCast and post-SelectDevices paths), SelectDevices, and Start. The `handle_token` values are unchanged; they are now named locals so the path and the argument cannot drift apart. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
* fix(clipboard): validate files Signed-off-by: fufesou <linlong1266@gmail.com> * fix(clipboard): address file validation review feedback - remove unreachable empty-prefix test assertions - name the shared COM/LPT prefix length - document non-atomic path validation behavior Signed-off-by: fufesou <linlong1266@gmail.com> * update hbb_common Signed-off-by: fufesou <linlong1266@gmail.com> * fix(clipboard): reject traversal in file descriptors - reuse parser validation for outgoing descriptor names - propagate descriptor serialization errors - add regression coverage for parent path components Signed-off-by: fufesou <linlong1266@gmail.com> * fix: clipboard, validate file name length Signed-off-by: fufesou <linlong1266@gmail.com> * fix: clipboard, comments Signed-off-by: fufesou <linlong1266@gmail.com> * fix(clipboard): support multi-root file selections Use each top-level path's parent as its relative root so file descriptors remain safe and relative across different directories. Add regression coverage for multi-root selections. Signed-off-by: fufesou <linlong1266@gmail.com> * fix(clipboard): unix, select multiple items Signed-off-by: fufesou <linlong1266@gmail.com> --------- Signed-off-by: fufesou <linlong1266@gmail.com>
* fix(wayland): scale portal pointer coordinates on niri * perf(wayland): cache portal scaling desktop check
* fix: Harden Windows installer temp command scripts Signed-off-by: fufesou <linlong1266@gmail.com> * fix: restore stop-service after install preparation failure Signed-off-by: fufesou <linlong1266@gmail.com> * fix(windows): preserve special characters in installer paths Handle carets and exclamation marks safely across cmd.exe parsing stages. Add coverage for special-character paths in the elevated installer handoff. Signed-off-by: fufesou <linlong1266@gmail.com> * fix: installer, validate app name Signed-off-by: fufesou <linlong1266@gmail.com> * update tests Signed-off-by: fufesou <linlong1266@gmail.com> * Simple refactor Signed-off-by: fufesou <linlong1266@gmail.com> * Simple refactor Signed-off-by: fufesou <linlong1266@gmail.com> --------- Signed-off-by: fufesou <linlong1266@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.