Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions openless-all/app/src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -354,18 +354,21 @@ export const en: typeof zhCN = {
startupAtBootError: 'Failed to toggle launch at login: {{message}}',
wayland: {
calloutTitle: 'Wayland desktop detected',
calloutBody: 'Wayland forbids apps from listening for global shortcuts. Please bind the following command to a custom shortcut in your system settings:',
calloutBody: 'Wayland forbids apps from listening for global shortcuts. Please create a custom shortcut for each command below in your system settings (QA and cancel commands are optional):',
copyButton: 'Copy',
copyButtonCopied: 'Copied',
commandToggleDictationLabel: 'Start / stop dictation',
commandToggleQaLabel: 'Open / close QA panel',
commandCancelDictationLabel: 'Cancel current dictation',
helpToggle: 'Setup steps for each desktop environment',
gnomeTitle: 'GNOME',
gnomeSteps: 'Settings → Keyboard → View and Customize Shortcuts → Custom Shortcuts → Add Shortcut. Paste the command above and record the key combination you want.',
gnomeSteps: 'Settings → Keyboard → View and Customize Shortcuts → Custom Shortcuts → Add Shortcut. Repeat 1–3 times, pasting each command above and recording the key combination you want.',
kdeTitle: 'KDE Plasma',
kdeSteps: 'System Settings → Keyboard → Shortcuts → Add New → Command/URL. Record any trigger keys you like, paste the command above, then Apply.',
kdeSteps: 'System Settings → Keyboard → Shortcuts → Add New → Command/URL. Repeat for each command above, recording different trigger keys, then Apply.',
hyprlandTitle: 'Hyprland',
hyprlandSteps: 'Edit ~/.config/hypr/hyprland.conf, add bind = SUPER, Y, exec, openless --toggle-dictation, then run hyprctl reload.',
hyprlandSteps: 'Edit ~/.config/hypr/hyprland.conf, add any 1–3 of the lines below, then run hyprctl reload:\nbind = SUPER, Y, exec, openless --toggle-dictation\nbind = SUPER, U, exec, openless --toggle-qa\nbind = SUPER, I, exec, openless --cancel-dictation',
swayTitle: 'sway',
swaySteps: 'Edit ~/.config/sway/config, add bindsym $mod+y exec openless --toggle-dictation, then run swaymsg reload.',
swaySteps: 'Edit ~/.config/sway/config, add any 1–3 of the lines below, then run swaymsg reload:\nbindsym $mod+y exec openless --toggle-dictation\nbindsym $mod+u exec openless --toggle-qa\nbindsym $mod+i exec openless --cancel-dictation',
},
},
providers: {
Expand Down
13 changes: 8 additions & 5 deletions openless-all/app/src/i18n/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -356,18 +356,21 @@ export const ja: typeof zhCN = {
startupAtBootError: '自動起動の切り替えに失敗:{{message}}',
wayland: {
calloutTitle: 'Wayland デスクトップを検出',
calloutBody: 'Wayland はセキュリティ上、アプリのグローバルショートカット監視を許可していません。システム設定でカスタムショートカットを作成し、以下のコマンドにバインドしてください:',
calloutBody: 'Wayland はセキュリティ上、アプリのグローバルショートカット監視を許可していません。システム設定で以下の各コマンド用にカスタムショートカットを作成してください(QA と録音キャンセルは任意):',
copyButton: 'コピー',
copyButtonCopied: 'コピー済み',
commandToggleDictationLabel: '録音の開始 / 停止',
commandToggleQaLabel: 'QA パネルの表示 / 非表示',
commandCancelDictationLabel: '現在の録音をキャンセル',
helpToggle: '各デスクトップ環境の設定手順',
gnomeTitle: 'GNOME',
gnomeSteps: '設定 → キーボード → ショートカットの表示とカスタマイズ → カスタムショートカット → 追加。コマンド欄に上記コマンドを貼り付け、希望のキー組み合わせを入力。',
gnomeSteps: '設定 → キーボード → ショートカットの表示とカスタマイズ → カスタムショートカット → 追加。1〜3 回繰り返し、コマンド欄に上記の各コマンドを貼り付け、希望のキー組み合わせを入力。',
kdeTitle: 'KDE Plasma',
kdeSteps: 'システム設定 → キーボード → ショートカット → 新規追加 → コマンド/URL。任意のトリガーキーを記録し、アクションに上記コマンドを貼り付けて保存。',
kdeSteps: 'システム設定 → キーボード → ショートカット → 新規追加 → コマンド/URL。上記の各コマンドに対してトリガーキーを別々に記録し、保存。',
hyprlandTitle: 'Hyprland',
hyprlandSteps: '~/.config/hypr/hyprland.conf に bind = SUPER, Y, exec, openless --toggle-dictation を追加し、hyprctl reload を実行。',
hyprlandSteps: '~/.config/hypr/hyprland.conf に以下から 1〜3 行を追加し、hyprctl reload を実行:\nbind = SUPER, Y, exec, openless --toggle-dictation\nbind = SUPER, U, exec, openless --toggle-qa\nbind = SUPER, I, exec, openless --cancel-dictation',
swayTitle: 'sway',
swaySteps: '~/.config/sway/config に bindsym $mod+y exec openless --toggle-dictation を追加し、swaymsg reload を実行。',
swaySteps: '~/.config/sway/config に以下から 1〜3 行を追加し、swaymsg reload を実行:\nbindsym $mod+y exec openless --toggle-dictation\nbindsym $mod+u exec openless --toggle-qa\nbindsym $mod+i exec openless --cancel-dictation',
},
},
providers: {
Expand Down
13 changes: 8 additions & 5 deletions openless-all/app/src/i18n/ko.ts
Original file line number Diff line number Diff line change
Expand Up @@ -356,18 +356,21 @@ export const ko: typeof zhCN = {
startupAtBootError: '자동 시작 전환 실패: {{message}}',
wayland: {
calloutTitle: 'Wayland 데스크톱 환경 감지됨',
calloutBody: 'Wayland는 보안상 앱의 전역 단축키 감지를 허용하지 않습니다. 시스템 설정에서 사용자 지정 단축키를 만들고 다음 명령에 바인딩하세요:',
calloutBody: 'Wayland는 보안상 앱의 전역 단축키 감지를 허용하지 않습니다. 시스템 설정에서 아래 각 명령에 대해 사용자 지정 단축키를 만드세요 (QA와 취소 명령은 선택 사항):',
copyButton: '복사',
copyButtonCopied: '복사됨',
commandToggleDictationLabel: '녹음 시작 / 중지',
commandToggleQaLabel: 'QA 패널 열기 / 닫기',
commandCancelDictationLabel: '현재 녹음 취소',
helpToggle: '각 데스크톱 환경별 설정 단계',
gnomeTitle: 'GNOME',
gnomeSteps: '설정 → 키보드 → 단축키 보기 및 사용자 지정 → 사용자 지정 단축키 → 추가. 명령 칸에 위 명령을 붙여넣고 원하는 키 조합을 기록.',
gnomeSteps: '설정 → 키보드 → 단축키 보기 및 사용자 지정 → 사용자 지정 단축키 → 추가. 1-3회 반복하여 명령 칸에 위 명령을 붙여넣고 원하는 키 조합을 기록.',
kdeTitle: 'KDE Plasma',
kdeSteps: '시스템 설정 → 키보드 → 단축키 → 새로 추가 → 명령/URL. 트리거 키를 기록하고 작업란에 위 명령을 붙여넣은 후 저장.',
kdeSteps: '시스템 설정 → 키보드 → 단축키 → 새로 추가 → 명령/URL. 위 각 명령에 대해 다른 트리거 키를 기록하고 저장.',
hyprlandTitle: 'Hyprland',
hyprlandSteps: '~/.config/hypr/hyprland.conf 파일에 bind = SUPER, Y, exec, openless --toggle-dictation 을 추가하고 hyprctl reload 실행.',
hyprlandSteps: '~/.config/hypr/hyprland.conf 파일에 아래 1-3 줄을 추가하고 hyprctl reload 실행:\nbind = SUPER, Y, exec, openless --toggle-dictation\nbind = SUPER, U, exec, openless --toggle-qa\nbind = SUPER, I, exec, openless --cancel-dictation',
swayTitle: 'sway',
swaySteps: '~/.config/sway/config 파일에 bindsym $mod+y exec openless --toggle-dictation 을 추가하고 swaymsg reload 실행.',
swaySteps: '~/.config/sway/config 파일에 아래 1-3 줄을 추가하고 swaymsg reload 실행:\nbindsym $mod+y exec openless --toggle-dictation\nbindsym $mod+u exec openless --toggle-qa\nbindsym $mod+i exec openless --cancel-dictation',
},
},
providers: {
Expand Down
13 changes: 8 additions & 5 deletions openless-all/app/src/i18n/zh-CN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -352,18 +352,21 @@ export const zhCN = {
startupAtBootError: '开机自启切换失败:{{message}}',
wayland: {
calloutTitle: '检测到 Wayland 桌面环境',
calloutBody: 'Wayland 出于安全考虑不允许应用监听全局快捷键。请在系统设置中创建一个自定义快捷键,绑定下面这条命令:',
calloutBody: 'Wayland 出于安全考虑不允许应用监听全局快捷键。请在系统设置中为下面的命令分别创建自定义快捷键(QA 与取消录音命令可选):',
copyButton: '复制',
copyButtonCopied: '已复制',
commandToggleDictationLabel: '开始 / 停止录音',
commandToggleQaLabel: '打开 / 关闭 QA 面板',
commandCancelDictationLabel: '取消当前录音',
helpToggle: '查看各桌面环境配置步骤',
gnomeTitle: 'GNOME',
gnomeSteps: '设置 → 键盘 → 查看和自定义快捷键 → 自定义快捷键 → 添加快捷键,命令处填入上方命令,再录入想用的按键组合。',
gnomeSteps: '设置 → 键盘 → 查看和自定义快捷键 → 自定义快捷键 → 添加快捷键。重复添加 1-3 组,命令处分别填入上方命令,再录入想用的按键组合。',
kdeTitle: 'KDE Plasma',
kdeSteps: '系统设置 → 键盘 → 快捷键 → 添加新的 → 命令/URL,触发按键随意录入,动作处粘贴上方命令并保存。',
kdeSteps: '系统设置 → 键盘 → 快捷键 → 添加新的 → 命令/URL,动作处分别粘贴上方命令并录入不同触发键,保存即可。',
hyprlandTitle: 'Hyprland',
hyprlandSteps: '编辑 ~/.config/hypr/hyprland.conf,加入 bind = SUPER, Y, exec, openless --toggle-dictation,然后执行 hyprctl reload。',
hyprlandSteps: '编辑 ~/.config/hypr/hyprland.conf,加入下面任意 1-3 行后执行 hyprctl reload:\nbind = SUPER, Y, exec, openless --toggle-dictation\nbind = SUPER, U, exec, openless --toggle-qa\nbind = SUPER, I, exec, openless --cancel-dictation',
swayTitle: 'sway',
swaySteps: '编辑 ~/.config/sway/config,加入 bindsym $mod+y exec openless --toggle-dictation,然后执行 swaymsg reload。',
swaySteps: '编辑 ~/.config/sway/config,加入下面任意 1-3 行后执行 swaymsg reload:\nbindsym $mod+y exec openless --toggle-dictation\nbindsym $mod+u exec openless --toggle-qa\nbindsym $mod+i exec openless --cancel-dictation',
},
},
providers: {
Expand Down
13 changes: 8 additions & 5 deletions openless-all/app/src/i18n/zh-TW.ts
Original file line number Diff line number Diff line change
Expand Up @@ -354,18 +354,21 @@ export const zhTW: typeof zhCN = {
startupAtBootError: '開機自啓切換失敗:{{message}}',
wayland: {
calloutTitle: '偵測到 Wayland 桌面環境',
calloutBody: 'Wayland 出於安全考慮不允許應用監聽全域快速鍵。請在系統設定中建立一個自訂快速鍵,繫結下面這條命令:',
calloutBody: 'Wayland 出於安全考慮不允許應用監聽全域快速鍵。請在系統設定中為下面的命令分別建立自訂快速鍵(QA 與取消錄音命令可選):',
copyButton: '複製',
copyButtonCopied: '已複製',
commandToggleDictationLabel: '開始 / 停止錄音',
commandToggleQaLabel: '開啟 / 關閉 QA 面板',
commandCancelDictationLabel: '取消目前錄音',
helpToggle: '查看各桌面環境設定步驟',
gnomeTitle: 'GNOME',
gnomeSteps: '設定 → 鍵盤 → 檢視並自訂快速鍵 → 自訂快速鍵 → 新增快速鍵,命令處填入上方命令,再錄入想用的按鍵組合。',
gnomeSteps: '設定 → 鍵盤 → 檢視並自訂快速鍵 → 自訂快速鍵 → 新增快速鍵。重複新增 1-3 組,命令處分別填入上方命令,再錄入想用的按鍵組合。',
kdeTitle: 'KDE Plasma',
kdeSteps: '系統設定 → 鍵盤 → 快速鍵 → 新增 → 命令/URL,觸發按鍵隨意錄入,動作處貼上上方命令並儲存。',
kdeSteps: '系統設定 → 鍵盤 → 快速鍵 → 新增 → 命令/URL,動作處分別貼上上方命令並錄入不同觸發鍵,儲存即可。',
hyprlandTitle: 'Hyprland',
hyprlandSteps: '編輯 ~/.config/hypr/hyprland.conf,加入 bind = SUPER, Y, exec, openless --toggle-dictation,然後執行 hyprctl reload。',
hyprlandSteps: '編輯 ~/.config/hypr/hyprland.conf,加入下面任意 1-3 行後執行 hyprctl reload:\nbind = SUPER, Y, exec, openless --toggle-dictation\nbind = SUPER, U, exec, openless --toggle-qa\nbind = SUPER, I, exec, openless --cancel-dictation',
swayTitle: 'sway',
swaySteps: '編輯 ~/.config/sway/config,加入 bindsym $mod+y exec openless --toggle-dictation,然後執行 swaymsg reload。',
swaySteps: '編輯 ~/.config/sway/config,加入下面任意 1-3 行後執行 swaymsg reload:\nbindsym $mod+y exec openless --toggle-dictation\nbindsym $mod+u exec openless --toggle-qa\nbindsym $mod+i exec openless --cancel-dictation',
},
},
providers: {
Expand Down
141 changes: 92 additions & 49 deletions openless-all/app/src/pages/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -556,20 +556,31 @@ function RecordingSection() {
function WaylandHotkeyCallout() {
const { t } = useTranslation();
const [helpOpen, setHelpOpen] = useState(false);
const [copied, setCopied] = useState(false);
const command = 'openless --toggle-dictation';
// 三条命令各自独立的"已复制"反馈。用 string 而非 boolean 数组,
// 避免 stale state(重复点击不同按钮时旧 timer 把别人擦掉)。
const [copiedCommand, setCopiedCommand] = useState<string | null>(null);

const onCopy = useCallback(async () => {
const onCopy = useCallback(async (command: string) => {
try {
await navigator.clipboard.writeText(command);
setCopied(true);
// 1.5s 后还原按钮文案。用户可重复点击;状态机简单到不必上 useRef cleanup。
setTimeout(() => setCopied(false), 1500);
setCopiedCommand(command);
// 1.5s 后还原按钮文案;同时校验仍是这条命令,避免被后点的覆盖。
setTimeout(() => {
setCopiedCommand(prev => (prev === command ? null : prev));
}, 1500);
} catch (err) {
console.warn('[wayland-callout] clipboard write failed', err);
}
}, []);

// 三条 CLI 命令 + 用途短标签。aeoform 在 #420 反馈 1.3.1-19 没提
// --toggle-qa / --cancel-dictation,本次补全。
const commandRows: Array<readonly [string, string]> = [
['openless --toggle-dictation', t('settings.recording.wayland.commandToggleDictationLabel')],
['openless --toggle-qa', t('settings.recording.wayland.commandToggleQaLabel')],
['openless --cancel-dictation', t('settings.recording.wayland.commandCancelDictationLabel')],
];

const helpEntries: Array<readonly [string, string]> = [
[t('settings.recording.wayland.gnomeTitle'), t('settings.recording.wayland.gnomeSteps')],
[t('settings.recording.wayland.kdeTitle'), t('settings.recording.wayland.kdeSteps')],
Expand All @@ -594,48 +605,73 @@ function WaylandHotkeyCallout() {
<div style={{ fontSize: 11.5, color: 'var(--ol-ink-3)', lineHeight: 1.55, marginBottom: 8 }}>
{t('settings.recording.wayland.calloutBody')}
</div>
<div
style={{
display: 'flex',
alignItems: 'center',
gap: 8,
padding: '8px 10px',
borderRadius: 8,
background: 'rgba(255,255,255,0.7)',
border: '0.5px solid rgba(0,0,0,0.08)',
marginBottom: 8,
}}
>
<code
style={{
flex: 1,
fontSize: 12,
fontFamily: 'ui-monospace, SF Mono, Menlo, Consolas, monospace',
color: 'var(--ol-ink)',
userSelect: 'all',
}}
>
{command}
</code>
<button
type="button"
onClick={onCopy}
style={{
padding: '4px 10px',
fontSize: 11,
fontWeight: 500,
border: '0.5px solid rgba(0,0,0,0.12)',
borderRadius: 6,
background: '#fff',
color: 'var(--ol-ink-2)',
cursor: 'pointer',
fontFamily: 'inherit',
}}
>
{copied
? t('settings.recording.wayland.copyButtonCopied')
: t('settings.recording.wayland.copyButton')}
</button>
<div style={{ display: 'flex', flexDirection: 'column', gap: 6, marginBottom: 8 }}>
{commandRows.map(([command, label]) => (
<div
key={command}
style={{ display: 'flex', alignItems: 'center', gap: 10 }}
>
<div
style={{
display: 'flex',
alignItems: 'center',
gap: 8,
padding: '8px 10px',
borderRadius: 8,
background: 'rgba(255,255,255,0.7)',
border: '0.5px solid rgba(0,0,0,0.08)',
flex: 1,
minWidth: 0,
}}
>
<code
style={{
flex: 1,
minWidth: 0,
fontSize: 12,
fontFamily: 'ui-monospace, SF Mono, Menlo, Consolas, monospace',
color: 'var(--ol-ink)',
userSelect: 'all',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
}}
>
{command}
</code>
<button
type="button"
onClick={() => onCopy(command)}
style={{
padding: '4px 10px',
fontSize: 11,
fontWeight: 500,
border: '0.5px solid rgba(0,0,0,0.12)',
borderRadius: 6,
background: '#fff',
color: 'var(--ol-ink-2)',
cursor: 'pointer',
fontFamily: 'inherit',
flexShrink: 0,
}}
>
{copiedCommand === command
? t('settings.recording.wayland.copyButtonCopied')
: t('settings.recording.wayland.copyButton')}
</button>
</div>
<span
style={{
fontSize: 11,
color: 'var(--ol-ink-3)',
whiteSpace: 'nowrap',
flexShrink: 0,
}}
>
{label}
</span>
</div>
))}
</div>
<button
type="button"
Expand All @@ -661,7 +697,14 @@ function WaylandHotkeyCallout() {
<div style={{ fontSize: 11.5, fontWeight: 600, color: 'var(--ol-ink-2)', marginBottom: 2 }}>
{title}
</div>
<div style={{ fontSize: 11, color: 'var(--ol-ink-3)', lineHeight: 1.55 }}>
<div
style={{
fontSize: 11,
color: 'var(--ol-ink-3)',
lineHeight: 1.55,
whiteSpace: 'pre-line',
}}
>
{body}
</div>
</div>
Expand Down
Loading