* 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>
bindgen-0.65 is incompatible with llvm 22, we should upgrade to a
newer bindgen version
error message:
```
error[E0609]: no field `g_w` on type `vpx_codec_enc_cfg`
--> libs/scrap/src/common/vpxcodec.rs:66:19
|
66 | c.g_w = config.width;
| ^^^ unknown field
|
= note: available field is: `_address`
```
* Add initial arm64 build logic
Signed-off-by: Dennis Ameling <dennis@dennisameling.com>
* Upgrade Flutter to 3.44.0 and introduce Windows arm64 in CI
Signed-off-by: Dennis Ameling <dennis@dennisameling.com>
* Bump bridge build to Flutter 3.44 as well
Signed-off-by: Dennis Ameling <dennis@dennisameling.com>
* Fix install flutter step for Win arm64
* Bump install-llvm-action to v2 for arm64 support
* Fix libsodium logic to only install through vcpkg on win arm64
* Fix Flutter installations on Win
* Flutter XCode: only build the current arch as it defaults to universal
Signed-off-by: Dennis Ameling <dennis@dennisameling.com>
* Ensure that we really have arm64 Dart + Flutter engine in CI
Signed-off-by: Dennis Ameling <dennis@dennisameling.com>
* Enable hwcodec feature now that upstream supports building it
Signed-off-by: Dennis Ameling <dennis@dennisameling.com>
* CI: improve logic for getting Flutter arm64 SDK
Signed-off-by: Dennis Ameling <dennis@dennisameling.com>
* Apply PR feedback (only bump Flutter version on Win arm64)
* Exclude MSI build on arm64
* CI: build the MSI for Windows arm64 (WiX v4 ARM64 platform + native CustomActions)
* Address PR feedback
* Update Cargo.toml
* Update Cargo.lock
* Update Cargo.lock
* Add Flutter 3.44 DialogThemeData background colors
Signed-off-by: 21pages <sunboeasy@gmail.com>
---------
Signed-off-by: Dennis Ameling <dennis@dennisameling.com>
Signed-off-by: 21pages <sunboeasy@gmail.com>
Co-authored-by: RustDesk <71636191+rustdesk@users.noreply.github.com>
Co-authored-by: 21pages <sunboeasy@gmail.com>
* feat: Add relative mouse mode
- Add "Relative Mouse Mode" toggle in desktop toolbar and bind to InputModel
- Implement relative mouse movement path: Flutter pointer deltas -> `type: move_relative` -> new `MOUSE_TYPE_MOVE_RELATIVE` in Rust
- In server input service, simulate relative movement via Enigo and keep latest cursor position in sync
- Track pointer-lock center in Flutter (local widget + screen coordinates) and re-center OS cursor after each relative move
- Update pointer-lock center on window move/resize/restore/maximize and when remote display geometry changes
- Hide local cursor when relative mouse mode is active (both Flutter cursor and OS cursor), restore on leave/disable
- On Windows, clip OS cursor to the window rect while in relative mode and release clip when leaving/turning off
- Implement platform helpers: `get_cursor_pos`, `set_cursor_pos`, `show_cursor`, `clip_cursor` (no-op clip/hide on Linux for now)
- Add keyboard shortcut Ctrl+Alt+Shift+M to toggle relative mode (enabled by default, works on all platforms)
- Remove `enable-relative-mouse-shortcut` config option - shortcut is now always available when keyboard permission is granted
- Handle window blur/focus/minimize events to properly release/restore cursor constraints
- Add MOUSE_TYPE_MASK constant and unit tests for mouse event constants
Note: Relative mouse mode state is NOT persisted to config (session-only).
Note: On Linux, show_cursor and clip_cursor are no-ops; cursor hiding is handled by Flutter side.
Signed-off-by: fufesou <linlong1266@gmail.com>
* feat(mouse): relative mouse mode, exit hint
Signed-off-by: fufesou <linlong1266@gmail.com>
* refact(relative mouse): shortcut
Signed-off-by: fufesou <linlong1266@gmail.com>
---------
Signed-off-by: fufesou <linlong1266@gmail.com>
1. Update kcp-sys to send KCP in frames to avoid potential crashes.
2. Fix the issue when the controling side is closed, the kcp connection close is not immediately recognized by the controlled end.
* Unless the controling side receives the close reason, force the sending of the close reason to the controlled end when using KCP, and delay for 30ms to ensure the message is sent successfully.
* Move the CloseReason receiving forward, as this message needs to be received when unauthorized, especially for kcp.
Signed-off-by: 21pages <sunboeasy@gmail.com>