feat: 增加GPU监控和自动检测是否远程环境修复向日葵远程的时候白屏问题#139
Open
capkten wants to merge 180 commits into
Open
Conversation
fix: 修复ssh密钥认证连接失败
…nux 桌面集成 Security fixes / 安全修复: - jeff141#12 Windows 命令注入: open_with_os 改用 ShellExecuteW + sanitize_filename - jeff141#10 编辑会话密码回显: 不再回填真实密码, 留空保留原密码 - jeff141#8 密码内存清零: 新增 Secret 类型(zeroize), Drop 清零 + Debug 脱敏 Features / 新增: - jeff141#9 完整 i18n: 中/英双语, 运行时实时切换(Slint @tr + bundled .po + Rust t()) - 私钥文件选择器 + .pub 容错 + 路径统一 / - Linux: meatshell.desktop + install-linux.sh + xdg_app_id(Wayland 图标) - README 截图(docs/screenshots, 敏感信息已打码) 详见 CHANGELOG.md / see CHANGELOG.md for details. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The fullwidth plus (U+FF0B +) had no glyph in the Latin font Slint picks for English text, so it rendered as a tofu box. Use an ASCII "+" instead (renders in any font; Chinese button now shows "+ 新建会话"). 全角加号在英文(拉丁字体)语境下没有字形 → 豆腐块。改用 ASCII "+",任何字体都能 渲染;中文按钮也相应改为 "+ 新建会话"。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add an "Import ~/.ssh/config" button on the welcome page. Parses the standard SSH config (Host / HostName / User / Port / IdentityFile; wildcard `Host *` blocks skipped) and adds each host as a session, skipping duplicates by alias or host+user. Hosts with an IdentityFile default to key auth. Includes a unit test. 欢迎页新增「导入 ~/.ssh/config」按钮:解析标准 SSH 配置(Host/HostName/User/ Port/IdentityFile,跳过 `Host *` 通配块),将主机加为会话并按别名或 host+user 去 重;带 IdentityFile 的默认密钥认证。含单元测试。 Also: bump to v0.2.3, update CHANGELOG. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Move the SSH-config import action out of the welcome header (cleaner) into the gear/settings menu as a third item next to language toggle and About. The import result hint still shows in the Quick-connect header. 把导入操作从欢迎页头部(挤在新建会话旁不够美观)移到齿轮设置菜单,作为第三个菜单 项,与语言切换、关于并列;导入结果提示仍显示在快速连接栏。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add .github/workflows/release.yml: builds native binaries for Windows (x86_64), Linux (x86_64), and macOS (arm64 + x86_64) via a matrix. Installs the Slint/rfd/GTK system deps on the Linux runner. On a `v*` tag it attaches the archives to a GitHub Release; on manual dispatch it uploads workflow artifacts. 新增三平台(Windows/Linux/macOS arm64+x86)构建发布工作流;Linux runner 自动安装 Slint/rfd/GTK 依赖;打 v* tag 自动建 Release 并上传产物。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This reverts commit 3688f1c.
install-linux.sh now picks up the `meatshell` binary sitting next to it (the release-package layout) when no argument is given, falling back to the source-tree ./target/release path only when there's no sibling binary. Also auto-chmod +x the binary. README (zh/en) gains a Download & install section covering the GitHub Actions builds for Windows / Linux / macOS. install-linux.sh 默认用同目录的 meatshell(发布包布局),无参数即可装;源码树下 才回退到 ./target/release。并自动给二进制加可执行权限。README 中英补充三平台下载 与 Linux 傻瓜式安装说明。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
GitHub Actions only runs workflows under .github/workflows/. The release workflow had ended up at .github/release.yml (which GitHub treats as a release- notes config, not a workflow), so it never triggered. Move it back. GitHub Actions 只运行 .github/workflows/ 下的工作流;文件被放到了 .github/ release.yml(被当成 release notes 配置,不是 workflow),不会触发。移回正确位置。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
text-muted (#6b6f7a) was only ~3.4:1 on the dark background — below WCAG AA — so placeholders, secondary labels and disk details were hard to read. Brighten text-muted to #9196a3 and text-secondary slightly to #b4b9c4. text-muted 在深色背景上对比度仅 ~3.4:1(低于 WCAG AA),占位符/次要标签/磁盘明细 偏暗看不清。提亮 text-muted 与 text-secondary。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Connections can now tunnel through a SOCKS5 (socks5://) or HTTP CONNECT (http://) proxy with optional user:pass@ credentials, for network-restricted environments. Resolved from the per-session "Proxy" field, falling back to the $ALL_PROXY environment variable; empty = direct. src/proxy.rs establishes the tunneled TcpStream (tokio-socks for SOCKS5, a hand-rolled HTTP CONNECT) and the existing connection code hands it to russh's connect_stream. Verified end-to-end: meatshell -> local SOCKS5 proxy -> server, both shell and SFTP. 新增 SSH/SFTP 经 SOCKS5 / HTTP CONNECT 代理(支持 user:pass@ 认证),用于网络受限 环境。会话「代理」字段优先,留空则用 $ALL_PROXY,再空直连。已端到端验证: meatshell -> 本地 SOCKS5 代理 -> 服务器,shell 与 SFTP 均走代理。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
jeff141#16 (perf): pipelined SFTP upload — keep ~32 WRITE requests in flight on a dedicated raw SFTP channel instead of write-and-wait, hiding RTT (was ~15x slower than scp). Verified: 3 MB upload, remote md5 matches local exactly. jeff141#18 (bug): dragging the SFTP panel up cleared recent terminal output, because vt100's set_size truncates the grid from the bottom. Before shrinking, save the top rows to scrollback and scroll so the bottom (recent) rows stay visible. jeff141#15 (security): debug logs recorded raw SSH keystroke bytes (could include passwords); log only the byte length now (ssh.rs + app.rs). jeff141#16 上传流水线(并发 32 个 WRITE,藏住 RTT,原比 scp 慢约 15 倍);已验证 3MB 上传 远端 md5 与本地完全一致。jeff141#18 上拉面板清空输出(vt100 缩小从底部截断),改为缩小前 存顶部行入回滚并滚动保留底部。jeff141#15 debug 日志不再记录原始按键(可能含密码)。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- 新增 format_mem_mib():总内存 >=1GiB 时自动用 GiB 单位显示 - StatRow detail 文本固定宽度改为 min-width + stretch,不再被进度条挤压 - 大数值(>=100G)或整数G值省略小数点,进一步缩短字符串长度 - detail min-width 从 56px 提升至 64px
The earlier jeff141#15 fix only covered the byte-length log site. Two more leaks remained in wire_key_input: send_key logged the raw key string at debug level, and the [KEY_DIAG] IME diagnostic logged Shift-typed key code points at info level (no RUST_LOG required). Both could expose password characters. Add redact_key(): reveals only C0/C1 control code points (the IME markers the diagnostics rely on) and masks every printable character. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add two non-SSH transports that reuse the full terminal pipeline: - Serial (src/serial.rs): opens COM3 / /dev/ttyUSB0 via the serialport crate (blocking reader thread + spawn_blocking writes), configurable baud / data bits / stop bits / parity / flow control. Closes jeff141#14. - Telnet (src/telnet.rs): TCP with RFC 854 IAC option negotiation (suppress-go-ahead, echo, NAWS window size), strips IAC from the data stream, escapes 0xFF in input, re-sends NAWS on resize, and tunnels through the existing SOCKS5/HTTP proxy. Closes jeff141#17. Session gains a kind field (ssh/serial/telnet) plus serial settings; old configs default to ssh. The session dialog gets a connection-type selector and per-kind fields. Serial/Telnet have no SFTP or resource monitor, so those panels are hidden/labelled accordingly. CI installs libudev-dev for the serialport crate on Linux. Verified: telnet end-to-end against a local echo server (IAC stripped, bidirectional input/output), serial worker error path (open COM99 -> localized error in terminal), and all three dialog modes render correctly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…n shrink The previous shrink fix scrolled the screen up by the full row delta and saved that many top rows to scrollback. When the grid was not full (a fresh shell with a few prompt lines and blank space below), this pushed the real content off the top into history, leaving a blank screen with the cursor stranded at the top; rapid up/down dragging repeated it until the prompt was gone. Now scroll up only by max(0, cursor_row+1 - new_rows): rows below the cursor are unused blanks and truncate for free, so content and the prompt stay put and rapid resizing is stable. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Selection endpoints were stored as visible-window rows, so when the view auto-scrolled during a drag (dragging past the bottom edge of a short terminal to select more than one screen of scrollback) the anchor could not stay pinned to content that scrolled off-window. Releasing then copied only the final visible window, losing everything above it — so a top-to-bottom selection of scrolled-back output never captured all of it. Store the anchor and focus as absolute (combined_row, col) indices over the virtual history+live buffer. vis_to_abs maps a visible row to its absolute index for the current view; selection_rects_visible clips highlights to the window; extract_selection_text reads the whole selection from the combined buffer regardless of the current scroll position. Auto-scroll now just moves the view and re-points the focus at the edge row, leaving the absolute anchor fixed. Removes the old visible-coordinate helpers. Unit tests cover the visible<->absolute mapping, history+live extraction, view-independence of a copy, and highlight clipping. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
SFTP delete is irreversible (no trash), so a misclick on the context-menu Delete item could silently destroy a file. Gate it behind an in-app ConfirmDialog (ui/confirm_dialog.slint) styled to match the rest of meatshell — a dark card over a dimmed backdrop, like SessionDialog, with a red destructive button and the full path shown. The confirmation lives in the UI layer: the context-menu delete now opens the modal and stashes the target; the existing Rust delete only fires on confirm. Backdrop click or Cancel dismisses without deleting. Verified end-to-end: Delete opens the themed dialog; the red button removes the file (status "已删除…", row disappears); Cancel/backdrop leaves it intact. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The download path was built directly from the server-supplied name via base_name(), so a malicious SFTP server could craft a name with path separators, shell-special characters, or a Windows reserved device name (CON, NUL, COM1, ...) to write outside the chosen directory or target a device. The open/edit flow already ran names through sanitize_filename(); the download path did not. Run downloads through sanitize_filename, and harden that helper to also neutralise Windows reserved device names (reserved case-insensitively and even with an extension) and strip leading whitespace, while preserving Unix dotfiles. Unit tests cover separators/traversal, special chars, reserved names, whitespace trimming, and the empty fallback. Closes jeff141#26. (jeff141#24, the resize-churn cursor bug, was already fixed by the cursor-based shrink change.) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The sidebar monitor runs a small loop over an SSH exec channel parsing /proc and df output. Three hardenings against a malicious/compromised server (which controls that output and the shell environment): 1. PATH hijacking: prepend "PATH=/usr/bin:/bin:/usr/sbin:/sbin; export PATH" to the monitor command so a server with a tampered PATH or BASH_ENV cannot shadow awk/cat/df/sleep. A fixed PATH is more portable than hardcoding one absolute path per tool; monitoring is best-effort either way. 2. Unbounded buffer: the reassembly buffer grew until the __MSTICK__ marker arrived. A server that streams data and never emits the marker could grow it without limit. Cap the leftover tail at 1 MiB and drop it past that. 3. Parser robustness: a server can put arbitrary values in /proc/stat, /proc/net/dev and df output. Sum CPU jiffies and the KiB->bytes multiply with saturating arithmetic (no debug overflow panic), and cap interfaces and filesystems at 64 per sample so a flood of fabricated rows cannot swamp the parser or sidebar. Unit tests cover df saturation, CPU overflow values, and the interface cap. Verified live that the PATH-reset monitor still reports CPU/mem/swap/net/disk. Closes jeff141#27. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Uses linuxdeploy + linuxdeploy-plugin-appimage (APPIMAGE_EXTRACT_AND_RUN=1 so no FUSE needed in CI). Produces a single-file portable executable alongside the existing .tar.gz; both are uploaded as workflow artifacts and attached to GitHub Releases. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…on-error) `--plugin appimage` conflicts with `--output appimage`; the output plugin is invoked automatically by --output. Also added `continue-on-error: true` so a future AppImage failure can't take the regular .tar.gz down with it. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds an image crate dependency (Linux-only, png feature only) and a set_window_icon helper that decodes the bundled 512x512 PNG at startup and hands it to slint::Window::set_window_icon. This makes the Wayland/ X11 dock show the correct icon when running the AppImage without AppImageLauncher, or the bare binary without install-linux.sh. Windows keeps its icon from the linked .ico; macOS from the app bundle -- neither is affected. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
slint::Window has no set_window_icon method; replace with the winit equivalent accessed via with_winit_window. Works on X11 sessions (sets _NET_WM_ICON); is a no-op on Wayland by design. 修复 Linux 窗口图标:改用 winit API,slint::Window 并无 set_window_icon 方法,改为通过 with_winit_window 调用 winit 的同名 方法。X11 会话下生效(写入 _NET_WM_ICON);Wayland 下为空操作,符合预期。
Passwords in sessions.json are no longer stored in plaintext. On first launch a random 256-bit key is written to secret.key in the same config directory (mode 0600 on Unix). Each non-empty password is encrypted with ChaCha20-Poly1305 (random 96-bit nonce per value) and stored as "enc:v1:<base64url(nonce||ciphertext)>". Legacy plaintext passwords from older installs are kept as-is in memory and silently re-encrypted on the next save — no user action required. Copying sessions.json alone is no longer sufficient to read credentials. 新增:密码静态加密,改用 ChaCha20-Poly1305 存储 sessions.json 中的密码不再明文保存。首次启动时在配置目录生成随机 256 位密钥文件 secret.key(Unix 下权限 0600)。每个非空密码使用 ChaCha20-Poly1305(每次随机 96 位 nonce)加密后以 "enc:v1:<base64url(nonce||密文)>" 格式写入 JSON。 旧版本的明文密码加载后保持原样,下次保存配置时自动加密,无需用户操作。 单独拿走 sessions.json 已无法还原密码。
- Add reactive light/dark theme system with sun/moon toggle button; defaults to system preference (dark-light crate), persisted in config - Redesign ANSI 16-color palette: separate fg (ANSI16_LIGHT) and bg (ANSI16_LIGHT_BG) tables for light mode so slot-7 white stays readable as text while TUI background fills render as light pastels - Add HSL-based transform for true-color (24-bit) backgrounds in light mode: dark RGB backgrounds (L < 0.45) are remapped to light pastels, making btop/htop/vim feel native to the light theme - Add symmetric darken_light_fg() transform: light RGB foregrounds (L >= 0.55) are darkened so btop text stays readable on white background - Store raw vt100::Color in HistSpan; convert at render time so theme switching retroactively recolors the entire scrollback history - Bump version to 0.2.5 feat: 新增浅色/深色主题,TUI 程序自适应配色 - 添加响应式浅色/深色主题切换,顶栏太阳/月亮按钮一键切换; 启动时跟随系统设置(dark-light crate),偏好持久化到配置文件 - 重设计 ANSI 16 色调色板:浅色模式下前景(ANSI16_LIGHT)与背景 (ANSI16_LIGHT_BG)使用独立映射表,确保 slot-7 白色作为文字仍 可读,TUI 填充块渲染为浅色粉彩风格 - 对真彩色(24-bit)背景添加 HSL 亮度重映射:浅色模式下深色 RGB 背景(亮度 L < 0.45)自动映射为浅色,btop/htop/vim 在浅色主题下 视觉风格统一 - 添加对称的 darken_light_fg():浅色 RGB 前景(L ≥ 0.55)压暗, 确保 btop 文字在白色背景上可读 - HistSpan 改为存储原始 vt100::Color,渲染时再转换颜色,切换主题 可即时重绘整个历史滚动缓冲区 - 版本升至 0.2.5
jeff141#98) The OSC7-anchored suppression discarded everything before the injected hook's OSC 7 — which also wiped the server's login banner/MOTD, making the terminal look cleared (as if Ctrl+L). Now locate the echoed command by a short un-wrappable prefix and delete only from the start of its line through the OSC 7, keeping any MOTD printed above it. Falls back to the size cap if the command isn't found. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add left/right scroll arrows to the tab bar that appear only when the tabs overflow the available width, complementing the drag/trackpad scrolling. They are absolute overlays (not layout items) and overflow is measured from the bar's own width, so toggling them can't feed back into the layout and form a binding loop. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…jeff141#103) - Command input box now supports Ctrl+A (start), Ctrl+E (end), Ctrl+K (kill to end) and Ctrl+U (kill to start), matching readline/bash. Ctrl+A there now means "start of line" instead of select-all (fine for a single-line box). - Settings menu gains a "Shortcuts / 快捷键" item (second-to-last) opening a centered dialog that lists the terminal and command-box shortcuts. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a thin scrollbar on the right edge of the terminal, shown only when there's scrollback (and not on the alternate screen). The render now exposes scroll-max (history depth) and scroll-offset (0 = live bottom); the thumb sizes/positions from them, and clicking or dragging the track jumps to an absolute offset via a new terminal-scroll-to callback. Complements wheel scrolling so users don't have to spin the wheel through long output. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
### Added / 新增 - **Searchable command-history dropdown (jeff141#101).** The command-history list is now filterable — type in the search box to narrow entries instantly, then click or press Enter to run the match. **命令历史下拉支持搜索 (jeff141#101)。** 历史列表新增搜索框,输入关键字即可实时过滤, 点击或回车直接执行匹配项。 - **Readline keys in the command box + shortcuts reference (jeff141#103).** The command box now honours common readline bindings (Ctrl+A/E/K/U/W, Alt+B/F/D/Backspace, etc.) for fast inline editing; a keyboard-shortcuts reference panel is also added so users can discover available bindings at a glance. **命令输入框支持 Readline 快捷键 + 快捷键参考 (jeff141#103)。** 命令框现在支持常见 readline 绑定(Ctrl+A/E/K/U/W、Alt+B/F/D/Backspace 等)进行快速行内编辑; 另加快捷键参考面板,方便用户一览可用组合键。 - **Scroll arrows when tabs overflow (jeff141#122).** When open tabs exceed the tab bar width, left/right arrow buttons appear so users can scroll through the hidden tabs instead of losing access to them. **标签溢出时显示滚动箭头 (jeff141#122)。** 当打开的标签超出标签栏宽度时,左右箭头 按钮出现,可滚动查看被遮挡的标签。 - **Slim scrollbar for the terminal output area (jeff141#103).** The terminal's vertical scrollbar is now a thin, auto-hiding overlay that doesn't eat into the column count, giving more screen real estate to the actual output. **终端输出区窄滚动条 (jeff141#103)。** 终端纵向滚动条改为细窄的自动隐藏覆盖层, 不再占用列数,把更多屏幕空间留给实际输出。 ### Fixed / 修复 - **Preserve the MOTD/banner when hiding the injected setup line (jeff141#98).** The previous approach stripped too aggressively and could swallow the server's MOTD/banner that arrives before the shell prompt; the matcher now only discards the single injected line, leaving the banner intact. **隐藏注入设置行时保留 MOTD/横幅 (jeff141#98)。** 之前的做法剥离过度,会把 shell 提示符 之前到达的服务器 MOTD/横幅一并吞掉;现在匹配器仅丢弃注入的那一行,横幅原样保留。 - **Reserve space for toolbar icons + scroll overflowing tabs (jeff141#122).** The tab bar now leaves a right margin so the last tab's close button isn't hidden behind the toolbar icons; tabs that still overflow are scrollable. **为工具栏图标预留空间 + 溢出标签可滚动 (jeff141#122)。** 标签栏右侧留出余量, 最后一个标签的关闭按钮不再被工具栏图标遮挡;仍然溢出的标签可滚动查看。
jeff141#116) 会话(连接)数量超过窗口可见高度时,之前无法滚动看到下面的连接。现在让快速连接 卡片填满剩余高度,并把会话/分组列表放进可滚动视图(ScrollView),溢出时出现滚动条。 When there were more connections than fit the window, the lower ones were unreachable. The Quick-connect card now fills the remaining height and its session/group list lives in a ScrollView, so it scrolls (with a scrollbar) on overflow. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
SFTP 命令循环是串行的:上传/下载在循环里被 await,长传输会把后面的「列目录/ 切目录」命令阻塞住,导致传输时无法切换目录。现在把 SftpSession 与连接句柄包进 Arc,上传/下载放到独立 tokio 任务里跑,命令循环空出来,切目录的 ListDir 能与 传输并发执行(SFTP 单通道支持请求流水线)。 The SFTP command loop is sequential — uploads/downloads were awaited inline, so a long transfer blocked subsequent list/switch-directory commands. Wrap the SftpSession and connection handle in Arc and run transfers on their own tokio task, freeing the loop so a ListDir runs concurrently with the transfer (SFTP pipelines requests over the one channel). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
端口转发可以多条规则,之前无法区分。给 PortForward 加了可选的名称字段:转发编辑器 新增「名称(可选)」输入,已添加的规则在列表里以高亮标签显示名称,便于区分不同服务。 旧配置无该字段时按空名兼容(serde default)。 Port forwards can have several rules that were hard to tell apart. Add an optional name to PortForward: the editor gets a "Name (optional)" field and each saved rule shows its name as a highlighted label in the list. Backward compatible with old configs via serde default. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…eff141#118) 新增「界面缩放」设置(设置→界面,80%–200%),实时生效、持久化保存。Theme 里加了 ui-scale 系数,字号、间距、圆角都乘以它,因此整个界面(含图标字形)随之放大/缩小, 解决"图标/文字太小"的反馈。终端字体仍由其单独的字号设置控制,不受影响。 (注:此方案缩放的是 Theme 尺寸令牌;少量硬编码 px 的容器不随缩放,极端比例下可能略紧。) Add a "UI scale" setting (Settings → Interface, 80%–200%) that applies live and persists. A ui-scale factor in Theme multiplies all font sizes, spacing and radii, so the whole interface (including icon glyphs) grows/shrinks — addressing the "icons/text too small" feedback. The terminal font keeps its own size setting. (Note: this scales Theme size tokens; a few hard-coded-px containers don't follow, so they may feel tight at extreme scales.) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
jeff141#100) SFTP 面板每行加了复选框,可勾选多个文件/文件夹。勾选后工具栏出现「✓N」计数和 两个按钮:批量下载(选一个目标文件夹,全部下载进去)、批量删除(走删除确认弹窗 的批量模式)。选择状态以模型为准(每个 entry 的 selected 标记),切换目录/刷新时 自动清空。 Each row in the SFTP panel gains a checkbox for selecting multiple files/folders. Once anything is checked, the toolbar shows a "✓N" count plus two actions: batch download (pick one destination folder, all go there) and batch delete (through the delete-confirm dialog in batch mode). Selection lives in the model (a per-entry `selected` flag) and clears on navigation/refresh. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…otice (jeff141#100) - 多选下载改为远端 tar 打包成单个压缩包再下载,下载后删除临时包, 根治并发传输丢文件的问题;单选仍按普通文件下载、不压缩。 - 下载空文件夹时提示「空文件夹」而非创建空目录。 - 远端文件名经单引号转义后再拼入 tar/rm 命令,避免恶意服务端命令注入。 - Multi-select download now tars the selection into one archive on the remote, downloads it, then removes the temp — fixing the concurrent transfer that dropped files; a single selection still downloads as a plain, uncompressed file. - Downloading an empty folder reports "Empty folder" instead of creating an empty local directory. - Server-supplied names are single-quote escaped before tar/rm to avoid command injection from a malicious server. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…i-checked, plain tar named after first file (jeff141#100) - 之前打包只挂在工具栏「下载选中」按钮上,右键/单文件下载仍逐个下载。 现改为:只要勾选了 ≥2 项,右键、行内按钮、工具栏的任何"下载"动作都 打包整组(下载后自动清空勾选);勾 0/1 项时仍按点中的单文件下载。 - 压缩包改为纯 tar(不再 gzip),更快——用户不在意体积。 - 压缩包以第一个文件名命名,如 11.txt → 11等文件.tar(经文件名净化)。 - Archiving used to be wired only to the toolbar "download selected" button, so right-click / single-file download still pulled files one by one. Now ANY download (right-click, row button, toolbar) packs the whole checked set when 2+ are checked, then clears the selection; with 0/1 checked it downloads the clicked file as-is. - Archive is now a plain tar (no gzip) for speed — size is not a concern. - Archive is named after the first item's stem, e.g. 11.txt -> 11等文件.tar (sanitized, since names come from the server). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
) - 多选打包下载时,远端 tar 还在跑、字节尚未开始传输的阶段,传输记录里 立刻显示一行「文件准备中」(新增传输状态 3),避免大文件时的静默等待。 - 该行复用同一个传输 id,tar 完成开始下载后原地变为「下载中」进度条, 再到「已完成」,无需新增一行。 - During multi-select archive download, a "Preparing..." row now appears in the transfer panel immediately while the remote tar runs and before any bytes flow (new transfer state 3), so a large selection is no longer a silent wait. - The row reuses the same transfer id, so it turns into the live download progress bar in place once tar finishes, then "Done" — no extra row. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…llable download with cleanup (jeff141#100) 慢的根因:下载是「读一块→等服务端→再读下一块」的串行流程,吞吐被往返 延迟卡死(上传早已流水线化,下载没有)。现把下载也改成专用 raw SFTP 通道 + 多请求并发在途(每个带绝对 offset,乱序返回也能正确落盘),延迟 被掩盖,大文件/打包包下载明显变快。 新增「取消下载」: - 每个传输登记一个取消标志;传输记录每行在「下载中/文件准备中」时显示 一个 × 按钮,点击即取消(新增状态 4「已取消」)。 - 取消/失败都会清理本地半成品文件;打包下载还会删除远端 /tmp 临时 tar, 本地和线上都不留垃圾。 - 文件夹下载与「外部打开」用空标志,不受影响。 Root cause of the slowness: downloads read one chunk, waited for the server, then read the next — throughput was capped by round-trip latency (uploads were already pipelined, downloads were not). Downloads now use a dedicated raw SFTP channel and keep many READ requests in flight at once (each tagged with its absolute offset so out-of-order completion is fine), hiding the latency. Large files and archive bundles download much faster. New "cancel download": - Each transfer registers a cancel flag; every transfer row shows an x button while active/preparing, which cancels it (new state 4 Cancelled). - Cancel and error both remove the partial local file; archive downloads also delete the remote /tmp temp tar — no junk left locally or remote. - Folder download and "open externally" pass a no-op flag, unaffected. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ll-text-invisible on macOS 26 (jeff141#108) macOS 26 (Tahoe) 改了 CoreText 行为,Slint 默认的 femtovg 渲染器取字失败, 导致界面所有文本(含内嵌等宽字体)全部消失。macOS 15 不受影响,所以朋友的 M4 没复现。Skia 字体路径更稳,也是 Slint 在 macOS 上的推荐渲染器。 - 仅在 macOS 通过 target 条件依赖引入 renderer-skia 特性,Windows/Linux 完全 不编译 Skia、继续用 femtovg。 - main.rs 在 macOS 启动时(未显式指定时)设置 SLINT_BACKEND=winit-skia。 macOS 26 (Tahoe) changed CoreText behaviour and Slint's default femtovg renderer failed its font lookup, so all UI text (including the embedded mono font) vanished. macOS 15 is unaffected, which is why it didn't repro on the reporter's friend's M4. Skia has a more robust font path and is Slint's recommended renderer on macOS. - Pull in the renderer-skia feature only on macOS via a target-conditional dependency; Windows/Linux never compile Skia and keep femtovg. - main.rs sets SLINT_BACKEND=winit-skia on macOS at startup (unless already set). Note: needs a macOS CI build to confirm Skia compiles — watch the x86_64-apple-darwin cross-compile job in particular. Reporter on macOS 26 must verify the fix. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
SFTP 多选打包下载、可取消传输、下载提速、端口转发命名、界面缩放, 修复 macOS 26 文本消失 (jeff141#108) 与欢迎页会话列表滚动 (jeff141#116)。 SFTP multi-select archive download, cancellable transfers, faster downloads, named port-forward rules, global UI scale; fixes macOS 26 all-text-invisible (jeff141#108) and welcome session-list scrolling (jeff141#116). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Slint 的文本排版会用到 ICU4X,而 icu_provider 在未开启 logging feature 时, 其内部 log 宏直接退化为 std::eprintln!,于是 stderr 被 「ICU4X data error: No segmentation model for language: ja」刷屏(绕过 tracing, RUST_LOG 也压不住),release 版同样如此。 - 打开 icu_provider 的 logging feature,使这些诊断改走真正的 log crate, 经 tracing-log 桥接进我们的 tracing 订阅器。 - init_tracing 在 stderr 与文件层都静音 icu_provider/icu_segmenter/icu_normalizer 目标,彻底消除噪音。 Slint's text layout pulls in ICU4X; with icu_provider's logging feature off, its internal log macro degrades to a raw std::eprintln!, flooding stderr with "ICU4X data error: No segmentation model for language: ja" (bypassing tracing, so RUST_LOG could not suppress it) — in release builds too. - Enable icu_provider's logging feature so those diagnostics go through the real log crate and into our tracing subscriber via the tracing-log bridge. - init_tracing silences the icu_provider/icu_segmenter/icu_normalizer targets on both the stderr and file layers, removing the noise entirely. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…eff141#100) 之前只有下载能取消,上传不行。现在单文件上传也注册取消标志,传输记录里的 取消按钮对上传同样生效;取消后删除远端没传完的半成品文件,并刷新目录列表。 上传失败时同样清理远端残留。文件夹上传用空标志,不可单独取消。 Only downloads were cancellable before. Single-file uploads now register a cancel flag too, so the transfer row's cancel button works for uploads as well; cancelling removes the half-written remote file and refreshes the listing. A failed upload likewise cleans up the remote partial. Folder uploads pass a no-op flag (not individually cancellable). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…r, fix macOS text-invisible (jeff141#129) 0.4.10 为绕过 macOS 26 上 femtovg 取字失败 (jeff141#108),在 macOS 强制改用 Skia 渲染器。该改动未经真机验证就发布,反而弄坏了另一批 Mac (Apple Silicon / macOS 26.5):Skia 无法解析「PingFang SC」界面字体,导致这些机器上文字全部 消失(图标因使用内嵌字体而正常)。 现默认改回 femtovg(对绝大多数机器正常);macOS 仍编译 renderer-skia, femtovg 失效的机器可在启动时用 SLINT_BACKEND=winit-skia 手动启用。 顺带发布 0.4.11:含上传可取消并清理远端 (jeff141#100)、屏蔽 ICU4X 噪音日志、 README 赞助入口。 0.4.10 force-set the Skia renderer on macOS to work around femtovg failing to render text on macOS 26 (jeff141#108). That fix shipped without on-device verification and broke a different set of Macs (Apple Silicon / macOS 26.5): Skia could not resolve the "PingFang SC" UI font, so all text vanished there instead (icons survived because they use an embedded font). The default now stays femtovg (known-good for the majority); renderer-skia is still compiled in on macOS so users for whom femtovg fails can opt in at launch with SLINT_BACKEND=winit-skia. Also cuts release 0.4.11: cancellable uploads with remote cleanup (jeff141#100), silenced ICU4X log noise, README sponsor link. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…K UI font to Heiti SC, fix macOS 26 blank text; release 0.4.12 (jeff141#129) 根因最终定位:部分 macOS 26 机器上 femtovg 无法栅格化新版系统中文字体 (PingFang SC、Hiragino)——fontdb 能找到它们,但每个字形都画成空白;而老字体 Heiti SC / STHeiti / Songti SC 渲染完全正常(已在 M2 / macOS 26 上逐字体肉眼实测)。 既不是渲染器(0.4.11 单独退回 femtovg 没用),也不是字体加载(fontdb 加载了 906 个 face、按名也能查到 PingFang),纯粹是 PingFang/Hiragino 这类字体 femtovg 画不出。 改法: - 启动时用 fontdb 探测,macOS 候选清单改为优先 Heiti SC(干净黑体、所有 macOS 自带),STHeiti / Songti SC 作后备,PingFang/Hiragino 降为末位。 - 一个系统 CJK 字体都匹配不到时,回退内置 "Meatshell Mono",保证窗口永不全白。 - 新增 MEATSHELL_UI_FONT="<字体名>" 环境变量,免重编强制指定任意字体(诊断/逃生)。 - 打一行 WARN 摘要(加载到几个 face + 选中哪个字体)进 error.log,便于诊断。 Root cause finally pinned: on some macOS 26 machines femtovg cannot rasterize the modern system CJK fonts (PingFang SC, Hiragino) — fontdb finds them but every glyph comes out blank — while the older Heiti SC / STHeiti / Songti SC faces render perfectly (verified per-font on an M2 / macOS 26). It was never the renderer (0.4.11's femtovg revert alone didn't help) nor font loading (fontdb loaded 906 faces and resolved PingFang by name). Change: - Probe fontdb at startup; the macOS candidate list now prefers "Heiti SC" (a clean sans-serif present on every macOS), with STHeiti / Songti SC as fallbacks and PingFang/Hiragino demoted to last. - If no system CJK family matches, fall back to the embedded "Meatshell Mono" so the window is never blank. - Add a MEATSHELL_UI_FONT="<family>" env override to force any family without a rebuild (diagnostics / escape hatch). - Log a one-line WARN summary (face count + chosen font) to error.log. Also bumps the release to 0.4.12. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…groups (jeff141#55) 快捷命令新增可选分组,体验对齐欢迎页的会话分组: - 数据:QuickCommand 增加 group 字段(serde default,旧配置兼容);留空归入隐式 「default」分组。 - 命令栏弹窗:按分组渲染,每组带标题,点击收起/展开(运行时状态,不持久化)。 - 管理对话框:新增「分组(可选)」输入框;列表按分组显示分组头。 - 分组会重排显示顺序,删除改用 orig-index 回指原始存储位置,避免删错条目。 - 新增 toggle-quick-group 回调 + on_toggle_quick_group 处理(用运行时 HashSet 记录已收起的分组)。 - 补 zh 翻译:分组(可选)、留空 → 默认分组。 Quick commands gain an optional group, mirroring the welcome page's session groups: - Data: QuickCommand gets a `group` field (serde default → backward compatible); empty means the implicit "default" group. - Command-bar popup: rendered grouped, each group has a clickable header to collapse/expand (runtime-only state, not persisted). - Manage dialog: new "Group (optional)" field; list shows group headers. - Grouping reorders the display, so delete now uses orig-index pointing back to the stored entry to avoid deleting the wrong one. - New toggle-quick-group callback + on_toggle_quick_group handler (collapsed groups tracked in a runtime HashSet). - zh translations added. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…uick commands with full group ops (jeff141#55) 把欢迎页快速连接会话的整套右键管理搬到快捷命令的管理对话框: - 右键命令:编辑(进编辑模式,Add 变 Save)、复制、删除、移动到分组。 - 右键分组标题:重命名分组、删除空分组、新建分组;另加「+ 新建分组」按钮。 - 数据:config 增加 quick_groups(显式分组,支持空分组持久化),并新增 add/remove/rename_quick_group、update_quick_command 方法。 - 模型:空分组渲染为 orig-index = -1 的占位头行,可被重命名/删除(对齐空会话文件夹)。 - 移动到「default」= 清空分组名;分组重排后删除用 orig-index 回指原始条目。 - 新增回调与处理:edit/save/duplicate/move-quick-command、submit/delete-quick-group。 Ports the welcome page's quick-connect right-click management onto the quick- command manage dialog: - Right-click a command: Edit (edit mode — Add becomes Save), Duplicate, Delete, Move to group. - Right-click a group header: Rename group, Delete (empty) group, New group; plus a "+ New group" button. - Data: config gains `quick_groups` (explicit groups so empty ones persist) and add/remove/rename_quick_group + update_quick_command helpers. - Model: an empty group is a placeholder header row (orig-index -1) that can be renamed/deleted, mirroring empty session folders. - Move to "default" clears the group; deletes use orig-index since grouping reorders the display. - New callbacks + handlers: edit/save/duplicate/move-quick-command, submit/delete-quick-group. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…groups collapsed by default (jeff141#55) 上一版把右键菜单只加在管理对话框,但用户是在命令栏弹窗上操作,那里没有右键 菜单(只有左键运行/收起),所以右键没反应。 - 把整套右键菜单搬进命令栏弹窗:右键命令 → 编辑/复制/删除/移动到分组;右键分组 标题 → 重命名/删除空分组/新建分组。TouchArea 同时带 clicked + pointer-event, 与会话列表一致(只有 pointer-event 时在 Flickable 内不抓取右键)。 - 管理对话框的右键 TouchArea 也补上 clicked,保证在 Flickable 内右键生效。 - 分组默认全收起:启动时把所有分组名放进收起集合(init 渲染与运行时集合一致)。 - 新增 TerminalView 回调并在 app.slint 转发到 root:edit/duplicate/delete/move- quick-command、new/rename/delete-quick-group。 - 补 zh 翻译「重命名分组」。 The previous commit only added the right-click menus to the manage dialog, but the user operates in the command-bar popup, which had no right-click menu (only left-click run / collapse) — so right-click did nothing. - Port the full right-click menus into the popup: right-click a command for Edit/Duplicate/Delete/Move-to; right-click a group header for Rename/Delete-empty/New group. Each TouchArea now has both clicked and pointer-event, matching the session list (a pointer-event-only TouchArea doesn't grab right-clicks inside a Flickable). - The manage-dialog right-click TouchAreas got a clicked grab too. - Groups collapsed by default: seed the collapse set with all group names at startup (init render and runtime set agree). - New TerminalView callbacks forwarded to root in app.slint. - zh translation for "Rename group". Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…k log noise - 过滤器新增 fontdb=error:屏蔽 fontdb 对无法解析、但会自动跳过的系统字体发出的 「malformed font」WARN(如 Windows 的 mstmc.ttf);保留 error 级别以便真正的错误仍可见。 - 把 resolve_ui_font_family 里"命中系统字体 / MEATSHELL_UI_FONT 覆盖"两条日志从 warn 降为 debug;只有"找不到任何系统 CJK 字体、回退内置"的失败路径仍保留 warn (继续进 error.log,便于诊断)。 - silence_icu 改名 quiet_noise(现在同时管 ICU4X 与 fontdb)。 - Add fontdb=error to the log filter so fontdb's harmless "malformed font" WARN for fonts it skips (e.g. Windows mstmc.ttf) is suppressed while real errors stay. - Demote the "using system CJK font" / MEATSHELL_UI_FONT override lines in resolve_ui_font_family from warn to debug; only the fallback failure path stays at warn (still lands in error.log for diagnostics). - Rename silence_icu -> quiet_noise (now covers both ICU4X and fontdb). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…r SFTP key, show import result (jeff141#133) 问题1:私钥带口令时,终端能连上但 SFTP 目录树加载失败,报「failed to load key... the key is encrypted」。原因是 SFTP 单独建连时调用 load_secret_key 传了 None,没把口令传进去;而 shell 会话用的是 Some(password)。改为和 shell 一致: 复用会话 password 字段作口令(空=未加密)。 问题2:「导入 ~/.ssh/config」点了像没反应。其实导入有执行,但结果提示 (ssh-import-hint)只显示在欢迎页;用户开着会话时欢迎页被终端盖住,看不到反馈。 改为:点击后不再关闭设置菜单,并把结果(已导入 N / 没有新主机 / 未找到)直接显示 在菜单项下方;打开设置时清空旧提示。 Problem 1: with a passphrase-protected private key the shell connects but the SFTP tree fails with "failed to load key... the key is encrypted". SFTP's dedicated connection called load_secret_key with None instead of the passphrase (the shell passes Some(password)). Reuse the session password field as the passphrase (empty = unencrypted), matching the shell. Problem 2: "Import ~/.ssh/config" looked like a no-op. The import ran, but its result hint only rendered on the welcome page, which is hidden behind an active session. Keep the settings menu open on click and show the result (imported N / no new hosts / not found) inline under the item; clear the stale hint when the menu opens. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ble process window, redesigned settings - 侧栏:在资源面板与主区之间加可拖动分隔条,宽度可在 160–520px 间调节并持久化到配置(重启保留);折叠时分隔条隐藏,拖动期间禁用折叠动画以跟手。 - 窗口:初始尺寸 1200×760 → 1440×900,对齐同类客户端的舒适默认值。 - 进程监视:从内嵌浮层提升为真正的独立 OS 窗口(可拖出父窗口/拖到第二屏),无边框自绘标题栏 + 缩放手柄;两窗口共享同一 VecModel 实时刷新;修复独立窗口主题(Theme 为每窗口 global)与 CJK 字体未同步的问题。 - 设置-界面:右侧改为「分区 + 标签左·控件右」的简约布局(iOS 风开关、[− 值 +] 步进器、固定紧凑字号,不随界面缩放放大);保留内嵌模态浮层,打开时遮罩吞鼠标 + 抢焦点吞键盘,禁止任何输入,卡片仅能在窗口内拖动。 - Sidebar: draggable splitter between the resource panel and main area; width adjustable within 160–520px and persisted to config (survives restart); the splitter hides when collapsed and the collapse animation is disabled while dragging for 1:1 tracking. - Window: initial size 1200×760 → 1440×900, matching the comfortable default of comparable clients. - Process monitor: promoted from an in-app overlay to a real top-level OS window (draggable outside the parent / onto a second monitor) with a frameless custom titlebar and resize grip; both windows share one VecModel for live updates; fixes detached-window theme (Theme is a per-window global) and CJK font not being synced. - Settings → Interface: right pane redesigned into a clean "section + label-left · control-right" layout (iOS-style switches, [− value +] steppers, fixed compact typography that ignores UI scale); kept as an embedded modal overlay that blocks all input while open (veil swallows mouse, focus scope swallows keys) and whose card can only be dragged within the window.
Detect RDP, Sunflower (向日葵), ToDesk, AnyDesk, TeamViewer sessions and set SLINT_BACKEND=software automatically to fix white screen issue when hardware-accelerated OpenGL is unavailable over remote connections.
- Add GPU monitoring via NVML for local machines - Add nvidia-smi polling for remote servers via SSH monitor channel - Support multi-GPU: each GPU shown as separate StatRow in sidebar - Add GpuBackend trait for pluggable GPU vendors (NVIDIA, Hygon, Ascend) - GPU row hidden when no NVIDIA GPU detected or nvidia-smi unavailable
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.
概述
改动内容
GPU 资源监控
nvml-wrapper)采集,远程服务器通过 SSH 监控通道执行nvidia-smi采集GpuBackendtrait,预留海光、昇腾等国产 GPU 扩展接口远程桌面自动检测
SLINT_BACKEND=software),解决远程连接白屏问题SLINT_BACKEND时优先使用用户配置