Files

90 lines
6.1 KiB
JavaScript

const PageRecord = {
_el: null,
init() { this._el = document.getElementById('page-record'); },
async render() {
this._el.innerHTML = this._template();
this._bindEvents();
this._loadRecordings();
},
async _loadRecordings() {
try {
const res = await fetch('/api/recordings');
const list = await res.json();
const el = document.getElementById('rec-file-list');
if (!el) return;
if (!list.length) { el.innerHTML = '<p style="color:var(--text-tertiary);font-size:13px;padding:20px">' + Lang.t('noRecordings') + '</p>'; return; }
el.innerHTML = list.map(f => {
const size = f.size > 1048576 ? (f.size/1048576).toFixed(1)+'MB' : (f.size/1024).toFixed(1)+'KB';
return '<div class="glass-card" style="padding:10px 14px;margin-bottom:6px;display:flex;align-items:center;justify-content:space-between;gap:8px;flex-wrap:wrap"><span style="font-size:12px;flex:1;min-width:150px">' + f.name + '</span><span style="font-size:11px;color:var(--text-tertiary)">' + size + '</span><button class="btn btn-sm btn-primary btn-play-rec" data-file="' + f.name + '">' + Lang.t('play') + '</button><a class="btn btn-sm btn-secondary" href="/api/recording/' + f.name + '/export" download>' + Lang.t('export') + '</a><button class="btn btn-sm btn-danger btn-del-rec" data-file="' + f.name + '">' + Lang.t('delete') + '</button></div>';
}).join('');
} catch (e) { console.error(e); }
},
_bindEvents() {
document.getElementById('btn-rec-start')?.addEventListener('click', async () => {
await fetch('/api/record/start', { method: 'POST' });
this._updateRecUI(true);
});
document.getElementById('btn-rec-stop')?.addEventListener('click', async () => {
await fetch('/api/record/stop', { method: 'POST' });
this._updateRecUI(false);
this._loadRecordings();
});
document.getElementById('rec-auto-mode')?.addEventListener('change', async (e) => {
await fetch('/api/record/auto', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ enabled: e.target.checked }) });
});
document.getElementById('btn-import-rec')?.addEventListener('click', () => {
const input = document.createElement('input'); input.type = 'file'; input.accept = '.tsr';
input.onchange = async (e) => {
const file = e.target.files[0]; if (!file) return;
const fd = new FormData(); fd.append('file', file);
await fetch('/api/recording/import', { method: 'POST', body: fd });
Toast.show(Lang.t('importSuccess'), 'success'); this._loadRecordings();
}; input.click();
});
document.getElementById('rec-file-list')?.addEventListener('click', async (e) => {
const playBtn = e.target.closest('.btn-play-rec');
const delBtn = e.target.closest('.btn-del-rec');
if (playBtn) this._playRecording(playBtn.dataset.file);
if (delBtn && confirm(Lang.t('confirmDelete'))) {
await fetch('/api/recording/' + delBtn.dataset.file + '/delete', { method: 'DELETE' });
this._loadRecordings();
}
});
document.getElementById('btn-playback-stop')?.addEventListener('click', async () => {
await fetch('/api/playback/stop', { method: 'POST' });
document.getElementById('playback-bar').style.display = 'none';
});
},
_updateRecUI(recording) {
document.getElementById('btn-rec-start').style.display = recording ? 'none' : '';
document.getElementById('btn-rec-stop').style.display = recording ? '' : 'none';
document.getElementById('rec-status').textContent = recording ? Lang.t('recording') : Lang.t('ready');
},
async _playRecording(filename) {
document.getElementById('playback-file').textContent = filename;
document.getElementById('playback-bar').style.display = 'flex';
await fetch('/api/playback/start', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ filename }) });
Toast.show(Lang.t('playbackStartedHint'), 'info');
},
_template() {
return '<div class="animated"><h2 style="font-size:24px;font-weight:700;margin-bottom:8px">' + Lang.t('recordPage') + '</h2><p style="color:var(--text-secondary);margin-bottom:20px">' + Lang.t('recordDesc') + '</p>' +
'<div class="glass-card" style="padding:20px;margin-bottom:20px"><h3 style="font-size:16px;margin-bottom:12px">' + Lang.t('recordControl') + '</h3><div style="display:flex;align-items:center;gap:12px;flex-wrap:wrap"><button id="btn-rec-start" class="btn btn-primary">' + Lang.t('startRecord') + '</button><button id="btn-rec-stop" class="btn btn-danger" style="display:none">' + Lang.t('stopRecord') + '</button><span id="rec-status" style="font-size:13px;color:var(--text-secondary)">' + Lang.t('ready') + '</span><span style="flex:1"></span><label class="switch-label"><input type="checkbox" id="rec-auto-mode"><span class="switch-track"></span> ' + Lang.t('autoDetect') + '</label></div></div>' +
'<div id="playback-bar" class="glass-card" style="padding:12px 20px;margin-bottom:20px;display:none;align-items:center;gap:12px;background:var(--accent-container)"><span style="font-size:13px">' + Lang.t('playbackActive') + '<strong id="playback-file">-</strong></span><span style="flex:1"></span><span style="font-size:12px;color:var(--text-tertiary)">' + Lang.t('playbackHint') + '</span><button id="btn-playback-stop" class="btn btn-sm btn-danger">' + Lang.t('stopPlayback') + '</button></div>' +
'<div class="glass-card" style="padding:20px"><h3 style="font-size:16px;margin-bottom:12px">' + Lang.t('recordFiles') + '</h3><div style="display:flex;gap:8px;margin-bottom:12px"><button id="btn-import-rec" class="btn btn-sm btn-secondary">' + Lang.t('importTsr') + '</button></div><div id="rec-file-list"></div></div>' +
'</div>';
}
};
window.PageRecord = PageRecord;