v64: рефакторинг — разбил монолит на css/ js/ build.sh dist/ (781→43 строки index.html)

This commit is contained in:
“Naeel”
2026-05-22 18:39:13 +04:00
parent bd042be61c
commit 9c13c21898
11 changed files with 1516 additions and 747 deletions
+102
View File
@@ -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('');
}