Skip to content

fix(linux): fcitx5 auxDown 持久化 + 热键模式保存修复 + 隐藏剪贴板/胶囊设置#554

Merged
H-Chris233 merged 2 commits into
Open-Less:betafrom
aeoform:fix/linux-fcitx5-auxdown-persist-and-hotkey-mode-save
May 29, 2026
Merged

fix(linux): fcitx5 auxDown 持久化 + 热键模式保存修复 + 隐藏剪贴板/胶囊设置#554
H-Chris233 merged 2 commits into
Open-Less:betafrom
aeoform:fix/linux-fcitx5-auxdown-persist-and-hotkey-mode-save

Conversation

@aeoform
Copy link
Copy Markdown
Contributor

@aeoform aeoform commented May 29, 2026

User description

变更

fcitx5 插件

  • openless.cpp:新增 PostInputMethod 事件钩子,fcitx5 按键处理后自动恢复 auxDown 文字,解决状态提示被键盘事件覆盖的问题

后端

  • coordinator.rs:终态(✅已插入/❌出错/—已取消)3 秒后自动清除 auxDown;修复 RETRY_GEN 代数比较(fetch_add 返回旧值,改为 latest_gen > gen+1);移除无效的 300ms 重试

前端

  • HotkeySettingsContext.tsx:修复 queueSetSettings 永久跳过 setSettings() 的 bug(latestPrefsRef 在 microtask 执行前已被同步更新为新对象,导致 next === current
  • RecordingInputSection.tsx:Linux 隐藏剪贴板/粘贴/胶囊设置组,流式输入开关移入录音卡片内
  • ShortcutsSection.tsx:Linux 隐藏"胶囊确认插入"快捷键提示

已知问题(Linux)

问题 现状
fcitx5 输入法状态弹窗在浏览器内不显示 待解决
fcitx5 插件在浏览器中 alt+a 热键导致字母 a 被输入 待解决
主程序网络异常时可能触发奇怪行为 待解决

Linux / Wayland 使用说明

在 Wayland 下使用 fcitx5 时,需要在系统设置中开启 允许 X11 应用(兼容性 → X11 应用监测快捷键),否则 fcitx5 插件在部分应用中可能无法捕获热键。

🤖 Generated with Claude Code


PR Type

Bug fix, Enhancement


Description

  • Fix Linux fcitx5 auxDown persistence

  • Restore saved hotkey settings reliably

  • Hide Linux-only settings clutter

  • Auto-clear terminal capsule states


Diagram Walkthrough

flowchart LR
  A["Linux settings UI"] -- "hide / move options" --> B["Cleaner recording & shortcuts panels"]
  C["Hotkey settings queue"] -- "persist resolved prefs" --> D["Settings saved reliably"]
  E["fcitx5 plugin PostInputMethod"] -- "restore auxDown" --> F["auxDown survives key handling"]
  G["Capsule coordinator"] -- "gen guard / auto-clear" --> H["Terminal states clear after 3s"]
Loading

File Walkthrough

Relevant files
Bug fix
coordinator.rs
Fix capsule state timing and retries                                         

openless-all/app/src-tauri/src/coordinator.rs

  • Removes the old 300ms retry path for set_aux_down.
  • Fixes generation comparison for retry/cancel guards.
  • Auto-clears terminal capsule states after 3 seconds.
  • Keeps async DBus updates guarded against stale state.
+10/-25 
HotkeySettingsContext.tsx
Fix queued settings persistence                                                   

openless-all/app/src/state/HotkeySettingsContext.tsx

  • Changes queueSetSettings to persist a resolved preference object.
  • Stops relying on latestPrefsRef inside the queued microtask.
  • Fixes the bug where setSettings() could be skipped permanently.
  • Updates locale sync to enqueue the merged preferences directly.
+4/-11   
openless.cpp
Restore auxDown after key handling                                             

openless-all/scripts/linux-fcitx5-plugin/openless.cpp

  • Adds a PostInputMethod key event watcher.
  • Restores lastAuxText_ after fcitx5 processes key events.
  • Prevents auxDown from being cleared by enter/backspace handling.
  • Improves Linux IME status persistence in the plugin.
+15/-0   
Enhancement
RecordingInputSection.tsx
Rework Linux recording settings layout                                     

openless-all/app/src/pages/settings/RecordingInputSection.tsx

  • Detects Linux with detectOS() and branches UI rendering.
  • Hides capsule and insert-group settings on Linux.
  • Moves streaming insert toggle into the recording card on Linux.
  • Keeps the original grouped layout for macOS and Windows.
+15/-2   
ShortcutsSection.tsx
Hide Linux-only shortcut hint                                                       

openless-all/app/src/pages/settings/ShortcutsSection.tsx

  • Detects Linux platform in the shortcuts settings page.
  • Removes the capsule confirm shortcut hint on Linux.
  • Leaves the confirm shortcut visible on other platforms.
+3/-1     

aeoform and others added 2 commits May 29, 2026 20:53
…oard/capsule settings

- coordinator.rs: terminal state (Done/Error/Cancelled) auto-clears after 3s;
  fix RETRY_GEN comparison (fetch_add returns old value, use latest_gen > gen+1);
  remove broken 300ms retry
- HotkeySettingsContext.tsx: fix queueSetSettings never calling setSettings()
  (latestPrefsRef was already updated to the new object before microtask ran)
- openless.cpp: add PostInputMethod event hook to restore auxDown after
  fcitx5 processes key events
- RecordingInputSection.tsx: hide clipboard/paste/capsule settings on Linux;
  streaming insert shown as standalone card instead of inside clipboard group
- ShortcutsSection.tsx: hide "capsule confirm" shortcut hint on Linux

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
On Linux, hide the clipboard/paste/capsule settings group and move
the streaming insert toggle directly into the recording input card.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Stale Write

This helper now persists the provided snapshot directly instead of resolving against the latest prefs when the queued task runs. If another settings change is queued before this write executes, the older snapshot can be written afterward and overwrite the newer update. The previous callback-based version avoided that by merging at flush time.

const queueSetSettings = useCallback(
    (resolved: UserPreferences) => {
        const task = persistQueueRef.current
            .catch(() => undefined)
            .then(async () => {
                await setSettings(resolved)
            })
State Desync

The auto-clear path clears LAST_AUX unconditionally after calling set_aux_down(""). If that DBus call fails or fcitx5 is temporarily unavailable, the UI can still show the old aux text but future emissions will be skipped because the code now believes the state is already cleared.

log::info!("[capsule] auto-clear terminal state: {text}");
let _ = crate::linux_fcitx::set_aux_down("");
*LAST_AUX.lock().unwrap() = None;

@aeoform
Copy link
Copy Markdown
Contributor Author

aeoform commented May 29, 2026

Re: the two flagged areas from the AI review:

  1. State Desync — the *LAST_AUX.lock().unwrap() = None after set_aux_down("") is a cosmetic corner case: if DBus fails and fcitx5 is unreachable, the aux text may linger visually until the next dictation session starts, which calls set_aux_down("🎤 收音中...") and overwrites it. The window is a single session boundary with zero user-visible side effects. Not worth adding retry complexity for this PR.

  2. Stale Write — this isn't actually a problem. persistQueueRef is a FIFO promise chain. updatePrefs(A) then updatePrefs(B) means B always waits for A's write to settle, so the latest value always lands last. The chain preserves ordering by construction.

@aeoform
Copy link
Copy Markdown
Contributor Author

aeoform commented May 29, 2026

State Desync似乎存在一个类似的问题,下周我看一下能不能修改,但触发概率确实很低,不会产生重大影响。先这样吧。

@H-Chris233
Copy link
Copy Markdown
Collaborator

State Desync似乎存在一个类似的问题,下周我看一下能不能修改,但触发概率确实很低,不会产生重大影响。先这样吧。

行,先这样吧,但别忘了。

@H-Chris233 H-Chris233 merged commit e0711c1 into Open-Less:beta May 29, 2026
4 checks passed
@aeoform
Copy link
Copy Markdown
Contributor Author

aeoform commented May 29, 2026

刚才测试了一下,在谷歌里面无法输入的情况,是输入法本身出的问题,不是插件问题。输入法完全无法使用,所以不需要修改任何相关代码了。

@aeoform
Copy link
Copy Markdown
Contributor Author

aeoform commented May 29, 2026

State Desync这个问题有一定可能性发生,需要通过重启输入法来临时解决。具体来说,就是在切换窗口的时候,旧的弹窗可能没有被正确关闭,而新的弹窗已经被打开了,新的还可能会被关闭,但旧的不会了。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants