SHA256
UI: упростить профиль и обновить UX чатов/шапок
This commit is contained in:
@@ -19,35 +19,39 @@ function showSttMissingConfigDialog(navigate) {
|
||||
if (goSettings) navigate('tools-settings-view');
|
||||
}
|
||||
|
||||
export async function openSpeechInputModal({ navigate, onTextReady }) {
|
||||
export async function openSpeechInputModal({ navigate, onTextReady, onSendText, onSendQueued }) {
|
||||
if (!isSpeechToTextConfigured(state.entrySettings)) {
|
||||
showSttMissingConfigDialog(navigate);
|
||||
return;
|
||||
}
|
||||
|
||||
const root = document.getElementById('modal-root');
|
||||
root.innerHTML = `
|
||||
<div class="modal" id="speech-input-modal">
|
||||
const host = document.createElement('div');
|
||||
host.innerHTML = `
|
||||
<div class="modal" id="speech-input-modal-layer">
|
||||
<div class="modal-card stack">
|
||||
<h3 class="modal-title">Голосовой ввод</h3>
|
||||
<p class="meta-muted" id="speech-input-status">Идёт запись...</p>
|
||||
<div class="voice-level-wrap"><div class="voice-level-fill" id="speech-level-fill"></div></div>
|
||||
<p class="meta-muted" id="speech-input-time">00:00</p>
|
||||
<p class="inline-error" id="speech-input-error"></p>
|
||||
<div class="form-actions-grid">
|
||||
<div class="speech-actions-top">
|
||||
<button class="secondary-btn" type="button" id="speech-cancel">Отмена</button>
|
||||
<button class="primary-btn" type="button" id="speech-ok">OK</button>
|
||||
</div>
|
||||
<button class="primary-btn speech-send-now-btn" type="button" id="speech-send-now">Распознать и сразу отправить сообщение</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
root.append(host);
|
||||
|
||||
const statusEl = root.querySelector('#speech-input-status');
|
||||
const timeEl = root.querySelector('#speech-input-time');
|
||||
const levelEl = root.querySelector('#speech-level-fill');
|
||||
const errorEl = root.querySelector('#speech-input-error');
|
||||
const cancelBtn = root.querySelector('#speech-cancel');
|
||||
const okBtn = root.querySelector('#speech-ok');
|
||||
const statusEl = host.querySelector('#speech-input-status');
|
||||
const timeEl = host.querySelector('#speech-input-time');
|
||||
const levelEl = host.querySelector('#speech-level-fill');
|
||||
const errorEl = host.querySelector('#speech-input-error');
|
||||
const cancelBtn = host.querySelector('#speech-cancel');
|
||||
const sendNowBtn = host.querySelector('#speech-send-now');
|
||||
const okBtn = host.querySelector('#speech-ok');
|
||||
const recorder = createMicrophoneRecorder();
|
||||
let closed = false;
|
||||
let busy = false;
|
||||
@@ -55,14 +59,16 @@ export async function openSpeechInputModal({ navigate, onTextReady }) {
|
||||
const close = () => {
|
||||
if (closed) return;
|
||||
closed = true;
|
||||
root.innerHTML = '';
|
||||
host.remove();
|
||||
};
|
||||
|
||||
const setBusy = (flag) => {
|
||||
busy = !!flag;
|
||||
cancelBtn.disabled = busy;
|
||||
sendNowBtn.disabled = busy;
|
||||
okBtn.disabled = busy;
|
||||
okBtn.textContent = busy ? 'Распознаю...' : 'OK';
|
||||
sendNowBtn.textContent = busy ? 'Распознаю...' : 'Распознать и сразу отправить сообщение';
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -84,10 +90,16 @@ export async function openSpeechInputModal({ navigate, onTextReady }) {
|
||||
okBtn.addEventListener('click', async () => {
|
||||
if (busy) return;
|
||||
setBusy(true);
|
||||
errorEl.textContent = '';
|
||||
statusEl.textContent = 'Распознаю речь...';
|
||||
try {
|
||||
const audioBlob = await recorder.stop();
|
||||
host.innerHTML = `
|
||||
<div class="modal" id="speech-input-modal-layer">
|
||||
<div class="modal-card stack">
|
||||
<h3 class="modal-title">Голосовой ввод</h3>
|
||||
<p class="meta-muted">Идёт распознавание текста...</p>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
const text = await transcribeAudioBySettings(audioBlob, state.entrySettings);
|
||||
if (typeof onTextReady === 'function') onTextReady(text);
|
||||
close();
|
||||
@@ -97,4 +109,24 @@ export async function openSpeechInputModal({ navigate, onTextReady }) {
|
||||
errorEl.textContent = `Ошибка распознавания: ${error?.message || 'unknown'}`;
|
||||
}
|
||||
});
|
||||
|
||||
sendNowBtn.addEventListener('click', async () => {
|
||||
if (busy) return;
|
||||
setBusy(true);
|
||||
try {
|
||||
const audioBlob = await recorder.stop();
|
||||
close();
|
||||
if (typeof onSendQueued === 'function') onSendQueued();
|
||||
const text = await transcribeAudioBySettings(audioBlob, state.entrySettings);
|
||||
if (typeof onSendText === 'function') {
|
||||
await onSendText(text);
|
||||
} else if (typeof onTextReady === 'function') {
|
||||
onTextReady(text);
|
||||
}
|
||||
} catch (error) {
|
||||
setBusy(false);
|
||||
close();
|
||||
window.alert(`Ошибка распознавания: ${error?.message || 'unknown'}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user