fix: spinner clockwise, lock target on start, context-aware shortcut (#18)
## Что сделано ### Спиннер крутится по часовой стрелке - Зеркально отражён SVG-arrow (стрелка указывает вправо) - Вращение изменено с counterclockwise (-360deg) на clockwise (360deg) ### Fix: «Could not find input field» в question prompt - **Корень проблемы**: `currentTarget` перезаписывался при каждом вызове `toggleDictation`, включая остановку. Если запись начата с микрофона question prompt (target="question"), а остановлена через Ctrl+Space (target всегда "composer"), target перезаписывался → текст вставлялся не туда. - **Фикс**: `currentTarget` устанавливается только при старте записи (state="idle") - Ctrl+Space теперь контекстно-зависимый: если открыт question prompt — target="question", иначе "composer" - Auto-submit для question prompt уже был отключён — без изменений Co-authored-by: opencode-agent <agent@slaid098.dev>
This commit is contained in:
parent
12c3974960
commit
3eec9f311c
3 changed files with 15 additions and 5 deletions
12
src/index.ts
12
src/index.ts
|
|
@ -6,7 +6,13 @@ import {
|
||||||
setConfig,
|
setConfig,
|
||||||
validateApiKey,
|
validateApiKey,
|
||||||
} from "./config.js";
|
} from "./config.js";
|
||||||
import { type InsertTarget, insertText, isOpencodePage, submitPrompt } from "./insert.js";
|
import {
|
||||||
|
type InsertTarget,
|
||||||
|
insertText,
|
||||||
|
isOpencodePage,
|
||||||
|
isQuestionPromptOpen,
|
||||||
|
submitPrompt,
|
||||||
|
} from "./insert.js";
|
||||||
import { setupKeyboardShortcut } from "./keyboard.js";
|
import { setupKeyboardShortcut } from "./keyboard.js";
|
||||||
import { transcribe } from "./transcribe.js";
|
import { transcribe } from "./transcribe.js";
|
||||||
import type { DictationState } from "./types.js";
|
import type { DictationState } from "./types.js";
|
||||||
|
|
@ -35,8 +41,8 @@ function stopTimer(): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function toggleDictation(target: InsertTarget): Promise<void> {
|
async function toggleDictation(target: InsertTarget): Promise<void> {
|
||||||
currentTarget = target;
|
|
||||||
if (currentState === "idle") {
|
if (currentState === "idle") {
|
||||||
|
currentTarget = target;
|
||||||
await startRecording();
|
await startRecording();
|
||||||
} else if (currentState === "recording") {
|
} else if (currentState === "recording") {
|
||||||
await stopAndTranscribe();
|
await stopAndTranscribe();
|
||||||
|
|
@ -182,7 +188,7 @@ function init(): void {
|
||||||
});
|
});
|
||||||
|
|
||||||
setupKeyboardShortcut(() => {
|
setupKeyboardShortcut(() => {
|
||||||
void toggleDictation("composer");
|
void toggleDictation(isQuestionPromptOpen() ? "question" : "composer");
|
||||||
});
|
});
|
||||||
|
|
||||||
registerMenuCommands({
|
registerMenuCommands({
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,10 @@ export function isOpencodePage(): boolean {
|
||||||
return document.querySelector(PROMPT_INPUT_SELECTOR) !== null;
|
return document.querySelector(PROMPT_INPUT_SELECTOR) !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isQuestionPromptOpen(): boolean {
|
||||||
|
return document.querySelector(QUESTION_INPUT_SELECTOR) !== null;
|
||||||
|
}
|
||||||
|
|
||||||
export function insertText(text: string, target: InsertTarget = "composer"): boolean {
|
export function insertText(text: string, target: InsertTarget = "composer"): boolean {
|
||||||
if (target === "question") {
|
if (target === "question") {
|
||||||
return insertIntoTextarea(text);
|
return insertIntoTextarea(text);
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ const QUESTION_INPUT_SELECTOR = '[data-slot="question-custom-input"]';
|
||||||
const ICON_MIC = `<svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor"><path d="M12 14c1.66 0 3-1.34 3-3V5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3z"/><path d="M17 11c0 2.76-2.24 5-5 5s-5-2.24-5-5H5c0 3.53 2.61 6.43 6 6.92V21h2v-3.08c3.39-.49 6-3.39 6-6.92h-2z"/></svg>`;
|
const ICON_MIC = `<svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor"><path d="M12 14c1.66 0 3-1.34 3-3V5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3z"/><path d="M17 11c0 2.76-2.24 5-5 5s-5-2.24-5-5H5c0 3.53 2.61 6.43 6 6.92V21h2v-3.08c3.39-.49 6-3.39 6-6.92h-2z"/></svg>`;
|
||||||
const ICON_STOP = `<svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor"><rect x="6" y="6" width="12" height="12" rx="3"/></svg>`;
|
const ICON_STOP = `<svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor"><rect x="6" y="6" width="12" height="12" rx="3"/></svg>`;
|
||||||
const ICON_CANCEL = `<svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor"><path d="M18.3 5.71L12 12l6.3 6.29-1.42 1.42L10.58 13.4 4.29 19.71 2.87 18.3 9.16 12 2.87 5.71 4.29 4.29 10.58 10.58l6.29-6.29z"/></svg>`;
|
const ICON_CANCEL = `<svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor"><path d="M18.3 5.71L12 12l6.3 6.29-1.42 1.42L10.58 13.4 4.29 19.71 2.87 18.3 9.16 12 2.87 5.71 4.29 4.29 10.58 10.58l6.29-6.29z"/></svg>`;
|
||||||
const ICON_SPINNER = `<svg class="ocvd-spin" viewBox="0 0 24 24" width="18" height="18" fill="currentColor"><path d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8z"/></svg>`;
|
const ICON_SPINNER = `<svg class="ocvd-spin" viewBox="0 0 24 24" width="18" height="18" fill="currentColor"><path d="M12 4V1L16 5l-4 4V6c-3.31 0-6 2.69-6 6 0 1.01.25 1.97.7 2.8L5.24 16.26C4.46 15.03 4 13.57 4 12c0-4.42 3.58-8 8-8z"/></svg>`;
|
||||||
|
|
||||||
function createButtonStyle(): string {
|
function createButtonStyle(): string {
|
||||||
return `
|
return `
|
||||||
|
|
@ -119,7 +119,7 @@ function createButtonStyle(): string {
|
||||||
}
|
}
|
||||||
@keyframes ocvd-spin {
|
@keyframes ocvd-spin {
|
||||||
from { transform: rotate(0deg); }
|
from { transform: rotate(0deg); }
|
||||||
to { transform: rotate(-360deg); }
|
to { transform: rotate(360deg); }
|
||||||
}
|
}
|
||||||
.ocvd-spin {
|
.ocvd-spin {
|
||||||
animation: ocvd-spin 0.8s linear infinite;
|
animation: ocvd-spin 0.8s linear infinite;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue