diff --git a/CLAUDE.md b/CLAUDE.md index a7c66dc9..47782816 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -35,7 +35,7 @@ When user says "COM": 1. Increment version in BOTH `package.json` AND `CLAUDE.md` (verify they match with `grep version package.json && grep Version CLAUDE.md`) 2. Run: `git add -A && git commit -m "chore: bump version to X.XXXX" && git push && npm run build && systemctl --user restart claudeman-web` -**Version**: 0.1636 (must match `package.json`) +**Version**: 0.1637 (must match `package.json`) ## Project Overview diff --git a/package.json b/package.json index 10fa8657..35fda81f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "claudeman", - "version": "0.1636", + "version": "0.1637", "description": "The missing control plane for Claude Code - run 20 autonomous agents with real-time monitoring and session persistence", "type": "module", "main": "dist/index.js", diff --git a/src/web/public/app.js b/src/web/public/app.js index 7575caae..33acf09a 100644 --- a/src/web/public/app.js +++ b/src/web/public/app.js @@ -659,8 +659,13 @@ const VoiceInput = { this._showPreview('Listening...'); try { this.recognition.start(); - } catch (_e) { - // Already started — ignore + } catch (e) { + // InvalidStateError = already started — ignore. Other errors = genuine failure. + if (e.name !== 'InvalidStateError') { + this.stop(); + app.showToast('Voice input failed to start: ' + e.message, 'error'); + return; + } } this._resetSilenceTimeout(); // Haptic feedback on mobile @@ -749,7 +754,7 @@ const VoiceInput = { _insertText(text) { if (!app.activeSessionId || !text.trim()) return; // Send text to session input (user presses Enter to submit) - app.sendInput(text.trim()); + app.sendInput(text.trim()).catch(() => {}); }, _resetSilenceTimeout() { diff --git a/src/web/public/mobile.css b/src/web/public/mobile.css index 1ac26b36..a94e21c9 100644 --- a/src/web/public/mobile.css +++ b/src/web/public/mobile.css @@ -320,8 +320,8 @@ html.mobile-init .file-browser-panel { display: inline-flex; align-items: center; justify-content: center; - width: 32px; - height: 32px; + width: 40px; + height: 40px; background: #1a2a3f; border: 1px solid rgba(59, 130, 246, 0.3); border-radius: 6px; diff --git a/src/web/public/styles.css b/src/web/public/styles.css index 175cd8e3..86ce0300 100644 --- a/src/web/public/styles.css +++ b/src/web/public/styles.css @@ -2006,8 +2006,15 @@ body { } @keyframes voice-pulse { - 0%, 100% { transform: scale(1); opacity: 1; } - 50% { transform: scale(1.1); opacity: 0.75; } + 0%, 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.4); } + 50% { box-shadow: 0 0 0 4px rgba(239, 68, 68, 0); } +} + +@media (prefers-reduced-motion: reduce) { + .btn-toolbar.btn-voice.recording, + .btn-voice-mobile.recording { + animation: none; + } } /* Voice preview overlay — shows interim transcription */ @@ -2025,9 +2032,8 @@ body { border: 1px solid rgba(255, 255, 255, 0.1); font-size: 0.85rem; max-width: 80%; - white-space: nowrap; + max-height: 3.6em; overflow: hidden; - text-overflow: ellipsis; z-index: 100; pointer-events: none; backdrop-filter: blur(8px);