v64: рефакторинг — разбил монолит на css/ js/ build.sh dist/ (781→43 строки index.html)
This commit is contained in:
+102
@@ -0,0 +1,102 @@
|
||||
// ---------- Хранилище (IndexedDB + localStorage) ----------
|
||||
|
||||
function openRecDB() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const req = indexedDB.open('lyngvo_recs', 1);
|
||||
req.onupgradeneeded = () => { req.result.createObjectStore('recs', { keyPath: 'id', autoIncrement: true }); };
|
||||
req.onsuccess = () => resolve(req.result);
|
||||
req.onerror = () => reject(req.error);
|
||||
});
|
||||
}
|
||||
|
||||
async function saveTranscription(id, text) {
|
||||
try {
|
||||
const db = await openRecDB();
|
||||
const tx = db.transaction('recs', 'readwrite');
|
||||
const store = tx.objectStore('recs');
|
||||
const rec = await new Promise(r => { const req = store.get(id); req.onsuccess = () => r(req.result); });
|
||||
if (rec) { rec.transcription = text; store.put(rec); }
|
||||
await new Promise(r => { tx.oncomplete = r; });
|
||||
renderRecHistory();
|
||||
} catch(e) { /* тихо */ }
|
||||
}
|
||||
|
||||
async function saveRecording(blob, word, duration) {
|
||||
try {
|
||||
const db = await openRecDB();
|
||||
const tx = db.transaction('recs', 'readwrite');
|
||||
const store = tx.objectStore('recs');
|
||||
store.add({ word, duration, blob, ts: Date.now() });
|
||||
const all = await new Promise(r => { const req = store.getAll(); req.onsuccess = () => r(req.result); });
|
||||
if (all.length > 10) {
|
||||
const toDelete = all.sort((a,b) => a.ts - b.ts).slice(0, all.length - 10);
|
||||
for (const rec of toDelete) store.delete(rec.id);
|
||||
}
|
||||
await new Promise(r => { tx.oncomplete = r; });
|
||||
renderRecHistory();
|
||||
} catch(e) { /* тихо */ }
|
||||
}
|
||||
|
||||
async function loadRecordings() {
|
||||
try {
|
||||
const db = await openRecDB();
|
||||
const tx = db.transaction('recs', 'readonly');
|
||||
const store = tx.objectStore('recs');
|
||||
const all = await new Promise(r => { const req = store.getAll(); req.onsuccess = () => r(req.result); });
|
||||
return all.sort((a,b) => b.ts - a.ts);
|
||||
} catch(e) { return []; }
|
||||
}
|
||||
|
||||
async function renderRecHistory() {
|
||||
const recs = await loadRecordings();
|
||||
const div = document.getElementById('recHistory');
|
||||
if (!recs.length) { div.innerHTML = ''; return; }
|
||||
div.innerHTML = '<div style="color:#999;margin-bottom:4px">📼 История записей (выберите для стерео):</div>' +
|
||||
recs.map(r => {
|
||||
const d = new Date(r.ts);
|
||||
const time = d.toLocaleTimeString('ru-RU', {hour:'2-digit',minute:'2-digit'});
|
||||
return '<div class="recItem">' +
|
||||
'<span style="cursor:pointer" onclick="document.getElementById(\'inputText\').value=\'' +
|
||||
r.word.replace(/'/g, "\\'") + '\';ttsText=\'' + r.word.replace(/'/g, "\\'") + '\'">' + r.word + '</span>' +
|
||||
'<span style="color:#999">' + time + ' · ' + r.duration.toFixed(1) + 'с</span>' +
|
||||
'<button onclick="playRec(' + r.id + ')">▶</button>' +
|
||||
'<button onclick="stereoRec(' + r.id + ')">🎧</button>' +
|
||||
'<button onclick="compareRec(' + r.id + ')">📊</button>' +
|
||||
(r.transcription ? '<span style="color:#aaa;font-size:0.82em;margin:0 4px">' + syllabifyPhrase(r.transcription) + '</span>' : '') +
|
||||
'<button onclick="deleteRec(' + r.id + ')" style="background:#e44;padding:4px 8px">🗑</button>' +
|
||||
'</div>';
|
||||
}).join('');
|
||||
}
|
||||
|
||||
async function deleteRec(id) {
|
||||
try {
|
||||
const db = await openRecDB();
|
||||
const tx = db.transaction('recs', 'readwrite');
|
||||
tx.objectStore('recs').delete(id);
|
||||
await new Promise(r => { tx.oncomplete = r; });
|
||||
renderRecHistory();
|
||||
} catch(e) { /* тихо */ }
|
||||
}
|
||||
|
||||
// ---------- История фраз (localStorage) ----------
|
||||
const HIST_KEY = 'lyngvo_phrases';
|
||||
function loadHistory() {
|
||||
try { return JSON.parse(localStorage.getItem(HIST_KEY)) || []; }
|
||||
catch { return []; }
|
||||
}
|
||||
function saveToHistory(text) {
|
||||
let hist = loadHistory().filter(t => t !== text);
|
||||
hist.unshift(text);
|
||||
hist = hist.slice(0, 5);
|
||||
localStorage.setItem(HIST_KEY, JSON.stringify(hist));
|
||||
renderHistory();
|
||||
}
|
||||
function renderHistory() {
|
||||
const hist = loadHistory();
|
||||
const div = document.getElementById('history');
|
||||
if (!hist.length) { div.innerHTML = ''; return; }
|
||||
div.innerHTML = hist.map(t =>
|
||||
'<span onclick="var v=\'' + t.replace(/'/g, "\\'") +
|
||||
'\';document.getElementById(\'inputText\').value=v;ttsText=v;renderHistory()">' + t + '</span>'
|
||||
).join('');
|
||||
}
|
||||
Reference in New Issue
Block a user