/** * app_utils.js — Общие утилиты (форматирование, стрелки, модалки). * Вынесены из app.js для облегчения анализа и отладки. * Загружается ДО app.js. */ /** * Форматирует размер файла в человекочитаемый вид. * Используется в renderTable() для колонки "Размер". */ function formatSize(bytes) { if (!bytes || bytes === 0) return '—'; if (bytes < 1024) return bytes + ' B'; if (bytes < 1048576) return (bytes / 1024).toFixed(1) + ' KB'; return (bytes / 1048576).toFixed(1) + ' MB'; } /** * Форматирует timestamp в российскую дату + время. * Используется в renderTable() для колонки "Изменён". */ function formatDate(ts) { if (!ts) return '—'; var d = new Date(ts); return d.toLocaleDateString('ru-RU') + ' ' + d.toLocaleTimeString('ru-RU', {hour:'2-digit',minute:'2-digit'}); } /** * Удаляет файл из очереди по индексу. * Вызывается по кнопке ✕ в таблице файлов. */ function removeFile(i) { fileQueue.splice(i, 1); if (fileQueue.length === 0) contractId = null; renderTable(); // Синхронизировать БД с таблицей if (typeof syncDB === 'function') syncDB(); // Разблокировать кнопку классификации при изменении состава файлов if (typeof showClassifyBtn === 'function') showClassifyBtn(); } window.removeFile = removeFile; /** * Переместить файл на одну позицию ВВЕРХ (сохранено для возможного возврата ручной сортировки). * В текущей версии (v1.0.164+) не используется — порядок определяет авто-классификация. */ function moveUp(i) { if (i <= 0) return; var tmp = fileQueue[i]; fileQueue[i] = fileQueue[i-1]; fileQueue[i-1] = tmp; renderTable(); } /** * Переместить файл на одну позицию ВНИЗ (сохранено для возможного возврата ручной сортировки). * В текущей версии (v1.0.164+) не используется — порядок определяет авто-классификация. */ function moveDown(i) { if (i >= fileQueue.length - 1) return; var tmp = fileQueue[i]; fileQueue[i] = fileQueue[i+1]; fileQueue[i+1] = tmp; renderTable(); } window.moveUp = moveUp; window.moveDown = moveDown; /** * Открыть модальное окно "О сервисе". */ function openAbout() { document.getElementById('aboutModalOverlay').classList.add('open'); } /** * Закрыть модальное окно "О сервисе" (по клику на оверлей или кнопку). */ function closeAbout(e) { if (e && e.target !== document.getElementById('aboutModalOverlay')) return; document.getElementById('aboutModalOverlay').classList.remove('open'); } window.openAbout = openAbout; window.closeAbout = closeAbout; /** * Экранировать HTML (для безопасного рендеринга пользовательских данных). * Используется в истории промптов. */ function escHtml(s) { var d = document.createElement('div'); d.textContent = s; return d.innerHTML; } /** * Форматировать дату для истории промптов (YYYY-MM-DD HH:MM). */ function fmtDate(d) { if (!d) return ''; return d.replace('T', ' ').substring(0, 16); }