Repository navigation
feat(ohos): add phone and desktop support with shared responsive UI - #283
Conversation
rssh's core (russh + rusqlite + xterm.js in a WebView) has no OHOS story upstream: Tauri does not ship a HarmonyOS target. This wires the app onto the feat/open-harmony fork (yangyongzhen/tauri @ e3bf6eb1, base 2.11.5, wry/tao ohos branches, openharmony-ability pinned to the 0.3-compatible rev) via [patch.crates-io], with every ohos-specific path behind cfg(target_env = "ohos"): - setup(): resolve the sandbox files dir directly on ohos — app_data_dir() aborts at startup there (no HOME, the linux resolver returns UnknownPath and kills the process before any UI) - official plugins (opener/dialog/fs) have no ohos backend; they moved to a positive-OS target table that excludes ohos and registration is cfg'd out. Frontend save/pick paths degrade until a filePicker bridge exists (phase D) - keyring + PTY/serial/arboard tables exclude ohos (target_os="linux" is true there but none of it links); secrets fall back to the DB file backend exactly like Android - reqwest rides the mobile table on ohos (webpki-roots fallback) - ArkWeb: withGlobalTauri on; guarded in-memory localStorage polyfill inlined before any ES module (the AI store reads it at module load, ArkWeb serves null for it under the tauri:// scheme) - platform.ts recognizes OpenHarmony/HarmonyOS UAs as mobile - build-ohos.sh: env-driven NDK linker/CC setup + cargo tauri ohos build; the crates.io CLI has no ohos subcommand, see script header Desktop verification on the patched stack: cargo check, cargo test (744 passed), vitest (781 passed) all green. Deferred to a DevEco-equipped machine: aws-lc-sys (via russh) cross-compile, xterm.js behavior under ArkWeb (WebGL/IME/long-press), HAP assembly and on-device run.
Covers prerequisites, one-time fork CLI install, DevEco auto-signing, build-ohos.sh usage, the Windows-specific HAP assembly pitfalls (from the verified real-device porting record), on-device install, the exact things this PoC needs answered (xterm.js under ArkWeb), known limitations, and the aws-lc-sys escalation path.
The whole chain now compiles on this macOS host against DevEco's embedded SDK: rust aarch64-unknown-linux-ohos (aws-lc-sys, bundled sqlite and tree-sitter all cross-compile clean), 29MB librssh_lib.so, DevEco project assembly, and a 41MB HAP containing the frontend. What the first four build rounds surfaced and how each is fixed: - capabilities/default.json referenced opener/dialog/fs permissions, which tauri-build rejects on ohos (plugin crates absent). Split into a core capability (all platforms) and capabilities/plugins.json gated to the five plugin platforms. - sftp.rs touched plugin types outside the desktop-only dialogs: FileAccessGuard, fs_open_read/write and the sftp_download_to/ sftp_upload_from commands now compile wherever the plugin table does; ohos gets same-signature stubs returning ohos_file_bridge_pending, so the invoke_handler list stays shared and the frontend gets a clear error instead of a missing command. - external.rs open_external_url: same treatment (ohos_opener_pending). - secret: the KeyringStore re-export needed the same cfg as its mod. - build-ohos.sh: probe DevEco-Studio.app (hyphenated bundle name), require ohrs, tolerate the Windows-only initial-assembly failure, then auto-sync dist into rawfile (the fork never copies it), strip the daemon-dependent cargo hook from entry/hvigorfile.ts, and re-assemble via node hvigorw.js with DEVECO_SDK_HOME derived. Desktop regression: cargo check, cargo test (744), fmt all clean.
ArkWeb serves the app under tauri://localhost where window.localStorage is null; the polyfill was in-memory only, so every restart reset UI state (theme choice, panel layout, plugin toggles). The polyfill now restores its Map from a new ui_state_load command before any app module evaluates (index.html imports the entry dynamically behind __rsshLsReady — store modules read localStorage at import time), and flushes it back debounced through ui_state_save. Rust side is a single atomic-write JSON blob at <data_dir>/ui_state.json with corrupt-file = fresh-start semantics; every platform with a real localStorage runs none of this. Also renames the on_window_event closure arg to _window — on ohos the only use is cfg(desktop) out, which trips an unused-variable warning in the ohos build. Tests: 5 new ui_state roundtrip/corruption cases; suite at 749 green, vitest 781 green, desktop check clean.
hvigor wants the SDK root that CONTAINS the version dir (.../sdk with sdk/default/openharmony below it); peeling only /openharmony left it at .../sdk/default and the re-assembly step died with configuration error 00303312.
Replaces the ohos_file_bridge_pending stubs with a real, picker-free design: transfers stage through the PUBLIC Downloads directory, gated by READ_WRITE_DOWNLOAD_DIRECTORY (declared in module.json5, requested once at startup from EntryAbility via abilityAccessCtrl). - Rust (ohos impls of existing command names, frontend flows shared): sftp_pick_save_path returns Downloads/rssh/<name>, sftp_pick_open_files lists the staged files for upload queueing, download/upload stream to plain paths (no content:// URIs on this target). Huawei moved the public layout across API versions, so the dir resolves by probing known candidates (/storage/Users/currentUser/Download, then /storage/media/100/local/files/Download). - write_text_file: plain command for text exports where plugin-fs is absent; registered everywhere (desktop already exposes equivalent writes through plugin-fs, no new surface). - Frontend: isHarmony export (platform.ts, TDD) — SFTP download rides the invoke-based desktop branch instead of SAF, upload queues every staged file, saveTextFile gains the ohos branch. New i18n key for the empty-stage hint. Verified on the emulator end to end: permission prompt appears at first launch (granted via atm for automation — the system dialog rejects injected taps by design), Settings > Backup > Export writes rssh-config-<ts>.json and the success toast names the file. The SFTP transfer legs need a live session and stay for on-device testing. Desktop regression: 749 rust tests, 782 vitest, check/fmt clean.
The generated ability declared no orientation, so the window (and the webview with it) stayed portrait when the emulator/device rotated.
The ohos pick implementations were compiled into the .so but the invoke_handler entries kept their historical #[cfg(desktop)] — the commands existed and still answered 'Command not found'. The shared pickers (save_path/open_files) now register on both; pick_folder gains an ohos impl (fresh Downloads/rssh/folder-<uuid> target) so directory downloads work too. pick_open_path stays desktop-only — no ohos caller. Found the hard way by the user after two rebuilds; strings on the .so cannot prove command-table membership (no literals), the handler list is the only source of truth.
… error Upload no longer blindly queues everything staged under Downloads/rssh: several files now open an in-app picker list (one file still uploads straight away). Downloads-side, grants reset on app updates/reinstalls and create_dir_all is a no-op stat — so picking now write-probes the staging dir and fails fast with a grant-storage-permission hint instead of a bare EACCES mid-transfer.
Build HarmonyOS from pinned framework sources and reviewed patches in a separate Cargo workspace so desktop, Android, iOS, CLI and headless keep the official dependency graph. Preserve application data and secret paths. Move file selection, file I/O and clipboard access behind shared native commands, with ability plugins for HarmonyOS and official Tauri plugins for the other native platforms. Keep browser and JetBrains handling in the IPC adapter. Remove the prototype UI-state compatibility layer. Cover framework lifecycle and build failure paths, document device checks and the upstream callback metadata leak, and ignore generated artifacts, local build state and signing material. Validation: 817 frontend tests, 750 Rust tests and 22 OHOS build/framework checks passed. Frontend production build, Rust formatting and CLI/server binary checks passed. HarmonyOS release/ArkTS builds and Android/iOS cross-checks passed during the migration; the emulator package was installed and launched for user acceptance testing.
Keep one HarmonyOS package and shared business layer while separating device layout from native capabilities. Add independent desktop windows, authorized multi-file and directory transfers, and capability-probed PTY and serial. Replay pinned framework patches, preserve window/session ownership, order ArkWeb initialization, and use Tauri postMessage IPC without the upstream unsafe request-body reader. Let user authorization dialogs wait for users. Normalize release versions without changing locked dependency versions. Validated with 858 frontend tests, 760 Rust tests, 41 framework tests, 18 build-script tests, CLI/server feature checks, macOS GUI smoke, and the same production HAP on HarmonyOS phone and PC emulators. Device checks cover SSH input, background resume, independent windows, split panes, window controls, multi-file and nested-directory round trips, and 128 KiB IPC data. Production signing and physical USB serial validation remain external release requirements. Headless has automated coverage but no live smoke in this run.
Separate phone and desktop entry HAPs around a shared runtime. Complete serial lifecycle and AssetStore integration, restore module startup, and flush downloads before reporting completion.
Use viewport width for shared layouts, per-pane terminal input controls, and host-reported native capabilities. Define mutually exclusive OS aliases and classify HarmonyOS devices at runtime while preserving independent phone and desktop packages.
Load the real split ArkTS serial modules while mocking only native APIs, and assert that closing waits for pending authorization cleanup. Cover the API 19 fallback and use explicit capture options so input listener teardown works consistently in the Node test runtime.
There was a problem hiding this comment.
🔵 Needs a closer look
It contains unresolved filename and memory-limit regressions alongside extensive native and framework changes requiring device-level validation.
Pull request overview
Adds shared HarmonyOS phone and desktop support while separating responsive layout, input handling, and native host capabilities.
Changes:
- Adds dual HarmonyOS HAP packaging, native integrations, and pinned framework patches.
- Introduces runtime-capability, viewport-layout, and input-device abstractions.
- Expands serial, file, clipboard, window, secret-storage, and regression-test coverage.
File summaries
| File | Description |
|---|---|
| AGENTS.md | Updates platform guidance. |
| BUILD_OHOS.md | Documents HarmonyOS builds. |
| build-ohos.sh | Builds HAPs and App Pack. |
| idea-plugin/src/main/kotlin/sh/rssh/idea/RsshBridge.kt | Updates IDE bridge capabilities. |
| package-lock.json | Updates frontend lock data. |
| package.json | Adds build/test scripts. |
| roadmap.md | Updates HarmonyOS roadmap. |
| scripts/build-ohos.test.mjs | Tests OHOS build orchestration. |
| scripts/prepare-ohos-sources.mjs | Prepares pinned framework sources. |
| scripts/prepare-ohos-sources.test.mjs | Tests source preparation. |
| scripts/prepare-ohos.mjs | Prepares OHOS project files. |
| scripts/prepare-ohos.test.mjs | Tests project preparation. |
| src-tauri/Cargo.lock | Updates Rust dependencies. |
| src-tauri/Cargo.toml | Adds conditional OHOS dependencies. |
| src-tauri/build.rs | Defines platform configuration. |
| src-tauri/capabilities/default.json | Updates Tauri permissions. |
| src-tauri/gen/ohos/.gitignore | Excludes generated OHOS artifacts. |
| src-tauri/gen/ohos/AppScope/app.json5 | Configures the OHOS application. |
| src-tauri/gen/ohos/AppScope/resources/base/element/string.json | Adds application strings. |
| src-tauri/gen/ohos/AppScope/resources/base/media/rssh_icon.png | Adds application branding. |
| src-tauri/gen/ohos/build-profile.json5 | Configures product builds. |
| src-tauri/gen/ohos/code-linter.json5 | Configures OHOS linting. |
| src-tauri/gen/ohos/common/runtime/Index.ets | Exports shared runtime code. |
| src-tauri/gen/ohos/common/runtime/build-profile.json5 | Configures the runtime HAR. |
| src-tauri/gen/ohos/common/runtime/hvigorfile.ts | Defines runtime build tasks. |
| src-tauri/gen/ohos/common/runtime/oh-package-lock.json5 | Locks runtime packages. |
| src-tauri/gen/ohos/common/runtime/oh-package.json5 | Declares runtime packages. |
| src-tauri/gen/ohos/common/runtime/src/main/cpp/types/librssh_lib/Index.d.ts | Declares native bindings. |
| src-tauri/gen/ohos/common/runtime/src/main/cpp/types/librssh_lib/oh-package.json5 | Describes native library package. |
| src-tauri/gen/ohos/common/runtime/src/main/ets/ability/RsshAbility.ets | Implements shared application ability. |
| src-tauri/gen/ohos/common/runtime/src/main/ets/ability/RsshBackupAbility.ets | Adds backup integration. |
| src-tauri/gen/ohos/common/runtime/src/main/ets/plugins/ClipboardPlugin.ets | Implements native clipboard access. |
| src-tauri/gen/ohos/common/runtime/src/main/ets/plugins/FilesAccessPlugin.ets | Implements native file access. |
| src-tauri/gen/ohos/common/runtime/src/main/ets/plugins/RuntimePlugin.ets | Reports host capabilities. |
| src-tauri/gen/ohos/common/runtime/src/main/ets/plugins/SerialPlugin.ets | Exposes native serial operations. |
| src-tauri/gen/ohos/common/runtime/src/main/ets/plugins/serial/BusSerialPort.ets | Implements bus serial support. |
| src-tauri/gen/ohos/common/runtime/src/main/ets/plugins/serial/SerialBackend.ets | Selects serial backends. |
| src-tauri/gen/ohos/common/runtime/src/main/ets/plugins/serial/UsbSerialPort.ets | Implements USB serial support. |
| src-tauri/gen/ohos/common/runtime/src/main/module.json5 | Declares runtime module capabilities. |
| src-tauri/gen/ohos/common/runtime/src/main/resources/base/element/color.json | Adds light theme resources. |
| src-tauri/gen/ohos/common/runtime/src/main/resources/base/element/string.json | Adds runtime strings. |
| src-tauri/gen/ohos/common/runtime/src/main/resources/base/profile/backup_config.json | Configures backups. |
| src-tauri/gen/ohos/common/runtime/src/main/resources/dark/element/color.json | Adds dark theme resources. |
| src-tauri/gen/ohos/hvigor/hvigor-config.json5 | Configures Hvigor. |
| src-tauri/gen/ohos/hvigorfile.ts | Defines root OHOS tasks. |
| src-tauri/gen/ohos/oh-package-lock.json5 | Locks workspace packages. |
| src-tauri/gen/ohos/oh-package.json5 | Declares workspace packages. |
| src-tauri/gen/ohos/products/desktop/build-profile.json5 | Configures desktop HAP builds. |
| src-tauri/gen/ohos/products/desktop/hvigorfile.ts | Defines desktop build tasks. |
| src-tauri/gen/ohos/products/desktop/oh-package-lock.json5 | Locks desktop packages. |
| src-tauri/gen/ohos/products/desktop/oh-package.json5 | Declares desktop packages. |
| src-tauri/gen/ohos/products/desktop/src/main/ets/entryability/EntryAbility.ets | Adds desktop entry ability. |
| src-tauri/gen/ohos/products/desktop/src/main/ets/entrybackupability/EntryBackupAbility.ets | Adds desktop backup entry. |
| src-tauri/gen/ohos/products/desktop/src/main/ets/pages/Index.ets | Adds desktop entry page. |
| src-tauri/gen/ohos/products/desktop/src/main/module.json5 | Declares desktop module. |
| src-tauri/gen/ohos/products/desktop/src/main/resources/base/profile/main_pages.json | Registers desktop pages. |
| src-tauri/gen/ohos/products/phone/build-profile.json5 | Configures phone HAP builds. |
| src-tauri/gen/ohos/products/phone/hvigorfile.ts | Defines phone build tasks. |
| src-tauri/gen/ohos/products/phone/oh-package-lock.json5 | Locks phone packages. |
| src-tauri/gen/ohos/products/phone/oh-package.json5 | Declares phone packages. |
| src-tauri/gen/ohos/products/phone/src/main/ets/entryability/EntryAbility.ets | Adds phone entry ability. |
| src-tauri/gen/ohos/products/phone/src/main/ets/entrybackupability/EntryBackupAbility.ets | Adds phone backup entry. |
| src-tauri/gen/ohos/products/phone/src/main/ets/pages/Index.ets | Adds phone entry page. |
| src-tauri/gen/ohos/products/phone/src/main/module.json5 | Declares phone module. |
| src-tauri/gen/ohos/products/phone/src/main/resources/base/profile/main_pages.json | Registers phone pages. |
| src-tauri/ohos/Cargo.lock | Locks OHOS Rust sources. |
| src-tauri/ohos/overlay.toml | Defines source overlays. |
| src-tauri/ohos/patches/.gitattributes | Configures patch handling. |
| src-tauri/ohos/patches/ability.patch | Adds native ability integration. |
| src-tauri/ohos/patches/tao.patch | Adds OHOS window support. |
| src-tauri/ohos/patches/tauri.patch | Adapts Tauri for OHOS. |
| src-tauri/ohos/patches/wry.patch | Adds ArkWeb lifecycle support. |
| src-tauri/ohos/sources.json | Pins framework sources. |
| src-tauri/ohos/tests/framework-initialization.test.mjs | Tests initialization ordering. |
| src-tauri/ohos/tests/framework-ipc-transport.test.mjs | Tests IPC transport. |
| src-tauri/ohos/tests/framework-lifecycle.test.mjs | Tests lifecycle handling. |
| src-tauri/ohos/tests/framework-patches.test.mjs | Validates framework patches. |
| src-tauri/ohos/tests/framework-picker-timeout.test.mjs | Tests picker timeouts. |
| src-tauri/ohos/tests/framework-waker.test.mjs | Tests event-loop wakeups. |
| src-tauri/ohos/tests/framework-webview.test.mjs | Tests WebView integration. |
| src-tauri/ohos/tests/framework-window-commands.test.mjs | Tests window commands. |
| src-tauri/ohos/tests/framework-windows.test.mjs | Tests native windows. |
| src-tauri/ohos/tests/wry-queue.test.mjs | Tests WebView operation queues. |
| src-tauri/src/ai/commands.rs | Updates AI platform conditions. |
| src-tauri/src/ai/session.rs | Updates AI session conditions. |
| src-tauri/src/ai/skills.rs | Updates AI skill conditions. |
| src-tauri/src/bin/rssh/main.rs | Updates CLI platform handling. |
| src-tauri/src/commands/cli.rs | Gates CLI installation capability. |
| src-tauri/src/commands/clipboard.rs | Adds unified clipboard commands. |
| src-tauri/src/commands/discovery.rs | Updates discovery availability. |
| src-tauri/src/commands/external.rs | Adds unified external-link handling. |
| src-tauri/src/commands/files.rs | Adds unified file operations. |
| src-tauri/src/commands/lifecycle.rs | Updates resource lifecycle handling. |
| src-tauri/src/commands/mod.rs | Registers command modules. |
| src-tauri/src/commands/plugin.rs | Updates plugin capability handling. |
| src-tauri/src/commands/runtime.rs | Reports runtime capabilities. |
| src-tauri/src/commands/serial.rs | Adds serial capability APIs. |
| src-tauri/src/commands/sftp.rs | Integrates unified file access. |
| src-tauri/src/commands/window.rs | Adds native window commands. |
| src-tauri/src/emitter.rs | Updates cross-host event emission. |
| src-tauri/src/error.rs | Makes application errors cloneable. |
| src-tauri/src/lib.rs | Registers commands and plugins. |
| src-tauri/src/ohos/clipboard.rs | Implements OHOS clipboard access. |
| src-tauri/src/ohos/device.rs | Classifies devices and probes PTY. |
| src-tauri/src/ohos/file_descriptor.rs | Manages native descriptors. |
| src-tauri/src/ohos/file_grants.rs | Tracks URI access grants. |
| src-tauri/src/ohos/file_name.rs | Decodes native filenames. |
| src-tauri/src/ohos/files.rs | Implements OHOS file operations. |
| src-tauri/src/ohos/mod.rs | Exports OHOS modules. |
| src-tauri/src/ohos/runtime.rs | Bridges native runtime services. |
| src-tauri/src/ohos/serial.rs | Bridges native serial services. |
| src-tauri/src/secret/keyring_store.rs | Updates keyring conditions. |
| src-tauri/src/secret/mod.rs | Selects OHOS secret storage. |
| src-tauri/src/secret/ohos_asset.rs | Stores master keys in Asset Store. |
| src-tauri/src/server.rs | Adds headless capability adapters. |
| src-tauri/src/server_main.rs | Updates server platform handling. |
| src-tauri/src/ssh/known_hosts.rs | Updates platform paths. |
| src-tauri/src/ssh/sftp.rs | Flushes native download destinations. |
| src-tauri/src/state.rs | Updates shared application state. |
| src-tauri/src/terminal/mod.rs | Exports platform terminal modules. |
| src-tauri/src/terminal/pty.rs | Updates PTY platform support. |
| src-tauri/src/terminal/serial.rs | Splits serial implementations. |
| src-tauri/src/terminal/serial/desktop.rs | Contains desktop serial implementation. |
| src-tauri/tauri.conf.json | Updates asset protocol configuration. |
| src/App.svelte | Adds startup capability barrier. |
| src/global.d.ts | Declares host bridge globals. |
| src/lib/ai/ChatPanel.svelte | Adapts responsive chat layout. |
| src/lib/ai/store.svelte.test.ts | Updates AI store tests. |
| src/lib/clipboard.test.ts | Tests clipboard routing. |
| src/lib/clipboard.ts | Routes clipboard by host. |
| src/lib/components/AppShell.svelte | Applies responsive application layout. |
| src/lib/components/AppearanceSettings.svelte | Updates responsive settings UI. |
| src/lib/components/ConnectionEditor.svelte | Adapts connection editing layout. |
| src/lib/components/ConnectionList.svelte | Adapts connection list layout. |
| src/lib/components/CredentialEditor.svelte | Adapts credential editing layout. |
| src/lib/components/DownloadsScreen.svelte | Adapts downloads layout. |
| src/lib/components/HomeScreen.svelte | Gates features by capabilities. |
| src/lib/components/PlaybackScreen.svelte | Adapts playback layout. |
| src/lib/components/SerialProfileEditor.svelte | Uses serial host capabilities. |
| src/lib/components/SettingsLayout.svelte | Implements responsive settings navigation. |
| src/lib/components/SftpBrowser.svelte | Uses unified file selection. |
| src/lib/components/ShellSettings.svelte | Gates shell capabilities. |
| src/lib/components/ShortcutsScreen.svelte | Adapts shortcuts layout. |
| src/lib/components/TerminalKeybar.svelte | Generalizes terminal key controls. |
| src/lib/components/TerminalPane.svelte | Integrates input and keyboard routing. |
| src/lib/components/WelcomeScreen.svelte | Updates onboarding capabilities. |
| src/lib/components/connection-editor.test.ts | Tests editor behavior. |
| src/lib/components/connection-editor.ts | Updates editor capability logic. |
| src/lib/components/welcome/SceneSync.svelte | Updates platform onboarding. |
| src/lib/i18n/locales/en.ts | Adds English UI strings. |
| src/lib/i18n/locales/zh.ts | Adds Chinese UI strings. |
| src/lib/input.test.ts | Tests input-device tracking. |
| src/lib/input.ts | Tracks touch and pointer input. |
| src/lib/ipc-shim.test.ts | Tests headless host adapters. |
| src/lib/ipc-shim.ts | Adds headless capability bridges. |
| src/lib/ohos-entry-ability.test.ts | Tests OHOS entry wiring. |
| src/lib/ohos-native-plugins.test.ts | Tests native plugin integration. |
| src/lib/ohos-runtime-plugin.test.ts | Tests runtime capability plugin. |
| src/lib/pick-file.ts | Unifies host file picking. |
| src/lib/platform.test.ts | Updates platform-detection tests. |
| src/lib/platform.ts | Removes layout-oriented mobile detection. |
| src/lib/plugins/PluginSide.svelte | Adds responsive plugin controls. |
| src/lib/plugins/PluginStrip.svelte | Adds touch-accessible plugin controls. |
| src/lib/plugins/store.svelte.ts | Gates plugins by capability. |
| src/lib/plugins/store.test.ts | Tests plugin capability behavior. |
| src/lib/save-file.test.ts | Tests unified save routing. |
| src/lib/save-file.ts | Adds host-aware file saving. |
| src/lib/sftp-name.test.ts | Tests upload-name extraction. |
| src/lib/sftp-name.ts | Extracts names from native references. |
| src/lib/soft-keyboard-inset.ts | Renames terminal keyboard references. |
| src/lib/stores/app.svelte.test.ts | Tests responsive app state. |
| src/lib/stores/app.svelte.ts | Adds per-tab terminal controls. |
| src/lib/stores/layout.svelte.test.ts | Tests viewport breakpoints. |
| src/lib/stores/layout.svelte.ts | Tracks viewport layout state. |
| src/lib/stores/runtime.svelte.test.ts | Tests capability loading. |
| src/lib/stores/runtime.svelte.ts | Stores runtime capabilities. |
| src/lib/stores/serial.svelte.ts | Stores serial capabilities. |
| src/lib/terminal/limits.ts | Unifies terminal queue limits. |
| src/lib/terminal/reserved-session-attempt.test.ts | Tests close barriers. |
| src/lib/terminal/reserved-session-attempt.ts | Serializes session replacement. |
| src/lib/terminal/soft-keyboard.test.ts | Tests keyboard lifecycle. |
| src/lib/terminal/soft-keyboard.ts | Generalizes soft-keyboard handling. |
| src/lib/terminal/touch-scroll.test.ts | Tests scrollbar gesture ownership. |
| src/lib/terminal/touch-scroll.ts | Generalizes touch scrolling. |
| src/lib/themes/store.svelte.test.ts | Updates renderer-default tests. |
| src/lib/themes/store.svelte.ts | Selects renderer by touch support. |
| src/main.ts | Installs global input tracking. |
Review details
- Files reviewed: 174/187 changed files
- Comments generated: 2
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Strip only the SAF document root prefix so colons in filenames cannot silently truncate names or cause upload collisions. Keep all hosts on a conservative 32 MiB terminal backlog budget without inferring memory from platform or viewport width.
There was a problem hiding this comment.
🔵 Needs a closer look
Unresolved moderate findings affect OHOS capability detection and terminal modifier cleanup.
Review details
Suppressed comments (5)
Previously missed (1) — in code that hasn't changed since the last review.
src-tauri/src/commands/runtime.rs:67
local_discoveryis unrelated to PTY availability: the discovery implementation invokesdocker/kubectldirectly and the settings page already probes those tools. On an OHOS desktop whereopenptyis unavailable but either CLI is installed, this assignment hides the discovery page and prevents valid discovery; keep this capability independent of the PTY probe (or probe the discovery tools themselves).
src-tauri/src/commands/runtime.rs:71
- On HarmonyOS phone/tablet this drops the native
folder_selectioncapability even when the host reports it.SftpBrowserusesdirectoryTransferto hide folder upload and directory download, while the OHOS file adapter supports these operations independently of device class, so supported mobile pickers will be presented as unsupported. Derive this flag fromdevice.folder_selection(and any picker bridge availability) without forcingpc.
src-tauri/src/ohos/device.rs:42 deviceInfo.deviceTypeis also reported as"pc"by the native window adapter (the OHOS window implementation treats both"2in1"and"pc"as desktop), but this match classifies"pc"asOther.get_runtime_capabilitiestherefore disables PTY, serial, multi-window, window controls, and directory transfer on those HarmonyOS computers even though the desktop HAP is running. Include the"pc"device type in the desktop class.
src/lib/components/TerminalKeybar.svelte:47- These setters mutate global modifier state, but every
TerminalPanemounts its own keybar, including panes for background tabs. Closing any background pane therefore runs this cleanup and clears Ctrl/Alt locks belonging to the still-visible pane, changing active-terminal input unexpectedly. Make modifier cleanup owner-scoped (or only clear when this keybar owns the active modifier slot) instead of unconditionally resetting the global state.
src/lib/components/welcome/SceneSync.svelte:194 - This new platform label bypasses the existing localization layer: the same scene uses
t(...)for every other endpoint, and both locales already define the Android/iOS keys. In the Chinese locale this will render an English-only label, and HarmonyOS has no locale key at all; add the HarmonyOS translation key to both locales and render all three labels throught(...).
- Files reviewed: 174/188 changed files
- Comments generated: 0 new
- Review effort level: Lite
Route file access, clipboard, windows and runtime policy through shared interfaces while keeping OHOS implementations in the sidecar. Preserve opaque file locations, native authorization lifetimes and retryable resource cleanup. Retain ordinary desktop PTY dependencies, synchronize both lockfiles, and add contract coverage for platform adapters. Verify phone and desktop simulator flows against the local Docker SSH fixture.
Use independent UIAbility windows with one application runtime so closing the first window does not destroy its peers. Preserve existing download targets with atomic replacement, report batch failures per file, and retain failed session cleanup for retry.
Disable raw system backups that cannot restore device-bound keys, and reactivate desktop windows through specified UIAbility instances. Wait for session reconciliation and retain background cleanup retries. Keep desktop serial I/O off async workers and enqueue SFTP downloads in bounded batches. Validation: 936 frontend tests, 814 Rust tests, 94 script/framework tests; frontend build, CLI/server checks, formatting, and unsigned phone/desktop HAP packaging passed.
Make closing missing or released sessions idempotent so failed opens cannot block retries. Preserve ownership checks and real cleanup failures, and render readable errors in the shared notification stack. Show auxiliary terminal controls only in compact layouts and size AI message actions by width. Use the host release-update capability for both startup checks and the About screen, including browser clients.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7cb7ebeca3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // std::fs::rename replaces existing files on Unix and Windows. Do not | ||
| // unlink the original first: rename failure must leave it intact. | ||
| std::fs::rename(&self.temporary, &self.destination)?; |
There was a problem hiding this comment.
Use a Windows-capable atomic replacement
When a Windows user downloads over an existing destination, std::fs::rename fails because Windows does not allow it to replace an existing file. Consequently, the completed temporary download is deleted by Drop, the transfer reports an error, and the destination is never updated. Restore a Windows-specific replacement path or use an atomic replacement API that supports existing targets.
AGENTS.md reference: AGENTS.md:L77-L77
Useful? React with 👍 / 👎.
| let pc = device.class() == DeviceClass::Desktop; | ||
| let mut capabilities = RuntimeCapabilities::native(); | ||
| capabilities.serial = pc && device.serial; |
There was a problem hiding this comment.
Honor the serial capability on OHOS mobile devices
On an OHOS phone or tablet where hasSerial() reports the USB serial system capability, device.serial is true but this pc conjunction forces the public capability back to false. Since the connection editor, saved profiles, and terminal entry points all gate on capabilities().serial, the implemented USB serial backend becomes completely unreachable solely because of the device class; expose the probed value and reserve the DeviceClass gate for genuinely desktop-only functions such as extra windows.
AGENTS.md reference: AGENTS.md:L89-L90
Useful? React with 👍 / 👎.
Load ignored signing.local.json through Hvigor's public build-context API so shared product configuration stays portable and signing credentials stay local. Add a placeholder example, setup instructions and regression coverage for signed and unsigned builds.
Keep the HarmonyOS R artwork in RGB format without an alpha channel for AppGallery submission. Other platform icons are unchanged.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f7475094ed
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (!tab) return; | ||
| openCtxMenu(e, tab); |
There was a problem hiding this comment.
Ignore touch context menus on route panes
On a touch or pen device, a long-press anywhere in the Home, Edit, or Forward pane reaches this handler and opens the tab context menu; openCtxMenu then calls preventDefault(), replacing the native text-selection/context menu. The terminal-pane handler immediately above already filters isTouchContextMenu(e), so apply the same input-source check here.
AGENTS.md reference: AGENTS.md:L75-L75
Useful? React with 👍 / 👎.
| capabilities.multi_window = pc && device.multi_window; | ||
| capabilities.window_controls = capabilities.multi_window; | ||
| capabilities.window_pin = capabilities.window_controls && window_label == "main"; | ||
| capabilities.directory_transfer = pc && device.folder_selection; |
There was a problem hiding this comment.
Expose probed folder selection on OHOS mobile
When an OHOS phone or tablet reports folder_selection = true, this pc conjunction still publishes directoryTransfer = false. SftpBrowser consequently hides batch downloads and folder uploads even though the shared OHOS backend implements pick_folder for these devices; use the probed capability rather than the device class.
AGENTS.md reference: AGENTS.md:L77-L77
Useful? React with 👍 / 👎.
HarmonyOS main-window titles also replace the Recent Tasks label. Route title creation and updates through the platform window adapter so OHOS retains RSSH while other desktop hosts preserve content titles. Keep browser and IDE titles host-owned in the IPC shim; unsupported mobile hosts remain gated by window capabilities. CLI behavior is unchanged. Add regressions for both native title policies and frontend dispatch. Validated with 963 frontend tests, 819 Rust tests, formatting checks, and the signed code6 OHOS build. Device acceptance remains pending.
Integrate tab context menus, group terminal accents, and base64 terminal events with the HarmonyOS sidecar and shared platform adapters. Keep asynchronous serial lifecycle handling and apply the new stream encoding to its active headless sink. Preserve width-based keyboard UI and avoid stealing focus when terminal metadata finishes loading. Align SSH test state with the explicit platform configuration. Validation: 1002 frontend tests, 835 Rust tests, 94 OHOS build/framework tests, production frontend build, Rust formatting, GUI/CLI/server checks, and the OHOS release-target library check.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cd2566f90a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (!Number.isInteger(config.baudRate) || config.baudRate <= 0 || | ||
| ![5, 6, 7, 8].includes(config.dataBits) || ![1, 2].includes(config.stopBits) || | ||
| !['none', 'odd', 'even'].includes(config.parity) || | ||
| !['none', 'hardware', 'software'].includes(config.flowControl) || typeof config.xany !== 'boolean') { |
There was a problem hiding this comment.
Enforce the BusManager baud-rate ceiling
On API 26 devices using the BusManager backend, this validation accepts every positive u32, while an empty capability list makes the editor accept values up to 4294967295. Huawei's BusManager serial contract limits arbitrary positive baud rates to 115200, so profiles such as 230400 pass validation and save successfully but every connection attempt fails with error 35700002; reject values above the platform limit for this backend.
Useful? React with 👍 / 👎.
概述
为 RSSH 增加鸿蒙手机/平板和电脑支持。两类设备使用独立的 entry HAP,共用 HAR、Rust 业务核心和前端;构建生成一个 App Pack,按设备类型分发。
OHOS 框架依赖和原生实现放在独立适配层。共享业务代码调用统一接口:布局只由窗口/容器宽度决定,输入按实际事件处理,原生功能由宿主能力查询决定。
主要改动
PickedLocation { location, name },位置保持不透明,名称来自宿主元数据。打开的文件同时持有流和访问授权;保留普通桌面的临时文件与重命名行为,OHOS 适配原生 URI 和文件描述符。isMobile布局分支;触摸、键鼠和软键盘入口独立于断点。终端控制按 tab 注册,避免关闭后台 tab 后影响当前终端输入。terminalPolicy,OHOS 按运行时设备类型区分;桌面输出积压上限为 128 MiB,受限平台为 32 MiB,用户显式 GPU 设置优先。linux、macos、windows、android、ios、ohos条件;Linux 明确排除 OHOS。手机和电脑共用 Rust 库,不伪造编译期 OS。四条入口
验证
./build-ohos.sh --unsigned已生成手机 HAP、电脑 HAP 和 App Pack。这些是本地验收包,尚非商店签名包。%25/%2F文件名完整保留,传输后字节数和 SHA-256 一致。tsc --noEmit仍有 39 条既有诊断,相对本轮重构前 HEAD 的 42 条未新增,不能标记为通过。尚待实机/专项验收
构建与验收说明见 BUILD_OHOS.md。