Skip to content

docs(readme): enhance README with getting started guide and visual assets#4

Merged
Scofieldfree merged 7 commits intomainfrom
improve/hud-component-readme
Jan 24, 2026
Merged

docs(readme): enhance README with getting started guide and visual assets#4
Scofieldfree merged 7 commits intomainfrom
improve/hud-component-readme

Conversation

@Scofieldfree
Copy link
Contributor

Summary

  • Enhanced README with logo, screenshots, and badges (Shields.io)
  • Added comprehensive "Getting Started" guide with installation and usage instructions
  • Refactored HUD component by extracting Waveform as a separate component
  • Implemented session cancellation functionality during audio processing

Changes

Documentation:

  • Added project logo and app screenshot to README
  • Integrated badges for build status, license, and version
  • Added "Getting Started" section with step-by-step guide

Components:

  • Extracted Waveform.tsx from HUD.tsx for better separation of concerns
  • Optimized HUD layout and reduced component complexity

Features:

  • Added session cancellation checks in audio processing pipeline
  • Implemented IPC handlers for cancel session functionality

Files Changed

  • README.md, README_EN.md - Documentation enhancements
  • src/components/HUD.tsx - Refactored, extracted Waveform
  • src/components/Waveform.tsx - New component
  • electron/main/main.ts - Session cancellation logic
  • electron/preload/preload.ts - IPC exposure
  • electron/shared/types.ts - Type updates
  • imgs/logo.png, imgs/screenshot.png - New assets

Test plan

  • Verify README displays correctly with logo and screenshots
  • Test getting started instructions
  • Verify HUD component renders without issues after refactoring
  • Test session cancellation during audio recording

🤖 Generated with Claude Code

scofield added 6 commits January 24, 2026 19:32
- Extract waveform visualization to standalone Waveform.tsx component
- Remove unused CheckCheck icon import
- Simplify recording state UI with extracted waveform component
- Add close button on right side of HUD
- Improve layout spacing and alignment
- Add handleCancelSession function in main process
- Add CANCEL_SESSION IPC channel
- Expose cancelSession API in preload
- Simplify HUD cancel handler to use new API
- Check session status after audio conversion
- Check session status after ASR transcription
- Check session status before text injection
- Clean up temp files when session is cancelled
- Add logo and screenshot images
- Add GitHub badges (contributors, forks, stars, issues)
- Add table of contents with anchor links
- Add tech stack section with framework badges
- Add star history chart
- Improve overall structure and readability
- Add environment prerequisites section
- Add installation steps with commands
- Fix screenshot alignment with centered wrapper
@Scofieldfree
Copy link
Contributor Author

Code review

Found 2 issues:

  1. CSS class typo: bg-linear-to-br should be bg-gradient-to-br (Tailwind CSS uses bg-gradient-to-{direction} for gradients)

className={`
w-8 h-8 rounded-full flex items-center justify-center shrink-0 shadow-lg relative overflow-hidden transition-all duration-500
${status === 'recording' ? 'bg-linear-to-br from-red-500 to-orange-600 text-white shadow-red-500/20' : ''}
${status === 'processing' ? 'bg-neutral-800 border border-neutral-700' : ''}
${status === 'success' ? 'bg-emerald-500 text-white shadow-emerald-500/20' : ''}

  1. CLAUDE.md Documentation Guidelines violation: New files and functionality added without updating README.md files

CLAUDE.md states: "ALWAYS update the README.md after creating/modifying files: New file? Add entry with concise description of its role"

This PR adds:

  • New src/components/Waveform.tsx (https://github.com/BuildWithAIs/voicekey/blob/b28e990bd106e0df5ae297bdc81d279d526f7324/src/components/Waveform.tsx) - but src/components/README.md was not updated
  • New cancelSession functionality in electron/main/main.ts (
    async function handleCancelSession() {
    // 1. 立即隐藏窗口
    hideOverlay()
    // 2. 标记当前会话为已取消
    if (currentSession) {
    currentSession = null // 或保留引用但标记失效
    }
    // 3. 通知后台窗口停止录音 (如果正在录音)
    if (backgroundWindow) {
    backgroundWindow.webContents.send(IPC_CHANNELS.SESSION_STOP)
    }
    // 4. (关键) 在 handleAudioData 中添加检查
    // 如果收到音频数据时 currentSession 为 null 或 status 为 aborted,则直接丢弃,不执行 ASR 和 注入。
    }
    ) - but electron/main/README.md was not updated
  • New cancelSession API in electron/preload/preload.ts (
    // 取消会话
    cancelSession: () => Promise<void>
    }
    // 暴露安全的API到渲染进程
    contextBridge.exposeInMainWorld('electronAPI', {
    // 系统信息
    platform: process.platform,
    // 配置相关
    getConfig: () => ipcRenderer.invoke(IPC_CHANNELS.CONFIG_GET),
    setConfig: (config: Partial<AppConfig>) => ipcRenderer.invoke(IPC_CHANNELS.CONFIG_SET, config),
    testConnection: (config?: ASRConfig) => ipcRenderer.invoke(IPC_CHANNELS.CONFIG_TEST, config),
    // 录音会话相关
    startSession: () => ipcRenderer.invoke(IPC_CHANNELS.SESSION_START),
    stopSession: () => ipcRenderer.invoke(IPC_CHANNELS.SESSION_STOP),
    getSessionStatus: () => ipcRenderer.invoke(IPC_CHANNELS.SESSION_STATUS),
    // 历史记录相关
    getHistory: () => ipcRenderer.invoke(IPC_CHANNELS.HISTORY_GET),
    clearHistory: () => ipcRenderer.invoke(IPC_CHANNELS.HISTORY_CLEAR),
    deleteHistoryItem: (id: string) => ipcRenderer.invoke(IPC_CHANNELS.HISTORY_DELETE, id),
    // 快捷键相关
    registerHotkey: (accelerator: string) =>
    ipcRenderer.invoke(IPC_CHANNELS.HOTKEY_REGISTER, accelerator),
    unregisterHotkey: (accelerator: string) =>
    ipcRenderer.invoke(IPC_CHANNELS.HOTKEY_UNREGISTER, accelerator),
    // 事件监听
    onSessionStatus: (callback: (status: string) => void) => {
    const listener = (_event: IpcRendererEvent, status: string) => callback(status)
    ipcRenderer.on(IPC_CHANNELS.SESSION_STATUS, listener)
    return () => ipcRenderer.removeListener(IPC_CHANNELS.SESSION_STATUS, listener)
    },
    onTranscription: (callback: (text: string) => void) => {
    const listener = (_event: IpcRendererEvent, text: string) => callback(text)
    ipcRenderer.on('transcription:result', listener)
    return () => ipcRenderer.removeListener('transcription:result', listener)
    },
    onError: (callback: (error: string) => void) => {
    const listener = (_event: IpcRendererEvent, error: string) => callback(error)
    ipcRenderer.on('error', listener)
    return () => ipcRenderer.removeListener('error', listener)
    },
    // [NEW] Audio Recording (Main -> Renderer)
    onStartRecording: (callback: () => void) => {
    const listener = () => {
    console.log('[Preload] Received SESSION_START')
    callback()
    }
    ipcRenderer.on(IPC_CHANNELS.SESSION_START, listener)
    return () => ipcRenderer.removeListener(IPC_CHANNELS.SESSION_START, listener)
    },
    onStopRecording: (callback: () => void) => {
    const listener = () => {
    console.log('[Preload] Received SESSION_STOP')
    callback()
    }
    ipcRenderer.on(IPC_CHANNELS.SESSION_STOP, listener)
    return () => ipcRenderer.removeListener(IPC_CHANNELS.SESSION_STOP, listener)
    },
    sendAudioData: (buffer: ArrayBuffer) => {
    ipcRenderer.send('audio:data', buffer)
    },
    sendError: (error: string) => {
    ipcRenderer.send('error', error)
    },
    sendAudioLevel: (level: number) => {
    ipcRenderer.send(IPC_CHANNELS.OVERLAY_AUDIO_LEVEL, level)
    },
    onOverlayUpdate: (callback: (state: OverlayState) => void) => {
    const listener = (_event: any, state: OverlayState) => callback(state)
    ipcRenderer.on(IPC_CHANNELS.OVERLAY_UPDATE, listener)
    return () => ipcRenderer.removeListener(IPC_CHANNELS.OVERLAY_UPDATE, listener)
    },
    onAudioLevel: (callback: (level: number) => void) => {
    const listener = (_event: any, level: number) => callback(level)
    ipcRenderer.on(IPC_CHANNELS.OVERLAY_AUDIO_LEVEL, listener)
    return () => ipcRenderer.removeListener(IPC_CHANNELS.OVERLAY_AUDIO_LEVEL, listener)
    },
    setIgnoreMouseEvents: (ignore: boolean, options?: { forward?: boolean }) => {
    ipcRenderer.send('set-ignore-mouse-events', ignore, options)
    },
    // 更新相关
    checkForUpdates: () => ipcRenderer.invoke(IPC_CHANNELS.CHECK_FOR_UPDATES),
    getUpdateStatus: () => ipcRenderer.invoke(IPC_CHANNELS.GET_UPDATE_STATUS),
    ) - but electron/preload/README.md was not updated
  • New CANCEL_SESSION channel in electron/shared/types.ts (
    // 取消回话
    CANCEL_SESSION: 'session:cancel',
    ) - but electron/shared/README.md was not updated

voicekey/CLAUDE.md

Lines 32 to 41 in b28e990

│ │ ├── ui/ # shadcn/ui component library
│ │ │ ├── README.md
│ │ │ ├── button.tsx # Multi-variant button
│ │ │ ├── input.tsx # Text input
│ │ │ ├── card.tsx # Card container
│ │ │ ├── dialog.tsx # Modal dialog
│ │ │ ├── select.tsx # Dropdown select
│ │ │ └── ... # 13+ more components
│ │ ├── README.md
│ │ ├── AudioRecorder.tsx # Headless audio capture (Web Audio API)

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

@Scofieldfree Scofieldfree merged commit 9a8770f into main Jan 24, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant