Files
navidrome-music-sync/app/templates/index.html
T

210 lines
9.3 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Navidrome Music Sync</title>
<link rel="stylesheet" href="static/style.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
</head>
<body>
<div class="app-container">
<header class="header">
<div class="logo-group">
<span class="logo-icon">🎵</span>
<div>
<h1>Navidrome Music Sync</h1>
<p class="subtitle">Поиск, импорт и синхронизация музыки в Navidrome</p>
</div>
</div>
<div class="status-badges">
<span class="badge badge-success" id="yandexStatus">Яндекс Музыка: Активна</span>
<span class="badge badge-info" id="tracksCount">Загружено: 0</span>
{% if user %}
<span class="badge badge-user">👤 {{ user }}</span>
<a href="/logout" class="btn-logout" title="Выйти из системы">Выйти 🚪</a>
{% endif %}
</div>
</header>
<main class="main-content">
<!-- Search & Input Card -->
<section class="card input-card">
<h2>🔍 Поиск и импорт музыки</h2>
<p class="card-desc">Введите название трека/артиста (например: <b>Booker - Время колокольчиков</b>) или вставьте прямую ссылку (Яндекс, Spotify, Apple, YouTube):</p>
<form id="downloadForm" class="download-form">
<div class="input-wrapper">
<input type="text" id="urlInput" placeholder="Название трека или https://..." required autocomplete="off">
<button type="submit" id="submitBtn" class="btn btn-primary">Найти / Загрузить</button>
</div>
</form>
<div class="quick-actions">
<span>Быстрые действия:</span>
<button id="syncLikesBtn" class="btn btn-secondary">
❤️ Синхронизировать «Мне нравится» (Яндекс)
</button>
</div>
</section>
<!-- Search Results Card (Hidden by default) -->
<section class="card search-card" id="searchCard" style="display: none;">
<div class="search-header">
<h2>🎯 Результаты поиска: <span id="searchQueryLabel"></span></h2>
<button id="closeSearchBtn" class="btn-close" title="Закрыть поиск">&times;</button>
</div>
<div id="searchLoading" class="search-loading" style="display: none;">
<div class="spinner"></div> Ищем на Яндекс Музыке, SoundCloud, YouTube и Apple Music...
</div>
<!-- Search Tracks -->
<div class="search-section" id="searchTracksSection">
<h3>🎵 Найденные треки</h3>
<div class="search-tracks-list" id="searchTracksList"></div>
</div>
<!-- Search Albums -->
<div class="search-section" id="searchAlbumsSection" style="margin-top: 1.5rem;">
<h3>💿 Альбомы</h3>
<div class="search-albums-grid" id="searchAlbumsList"></div>
</div>
</section>
<!-- Smart Wave Card -->
<section class="card wave-card">
<div class="wave-header">
<div class="wave-header-title">
<h2>🌊 Моя Волна <span class="badge badge-wave">Smart Wave V2</span> <span class="badge badge-llm">🤖 Qwen 2.5</span></h2>
<p class="wave-subtitle">
Персональный контекстный поток рекомендаций. Нейросетевой реранкинг по времени суток и настроению с авто-ротацией в Navidrome.
</p>
</div>
<div class="wave-controls">
<button id="waveGenerateBtn" class="btn btn-primary">⚡ Обновить Волну</button>
<button id="waveRotateBtn" class="btn btn-outline" title="Перенести лайкнутые треки в постоянную библиотеку и очистить старые">🔄 Ротация</button>
</div>
</div>
<!-- Mood & Context Selector Row -->
<div class="wave-mood-row">
<div class="wave-mood-group">
<label for="waveMoodSelect" class="wave-mood-label">Режим настроения:</label>
<select id="waveMoodSelect" class="wave-mood-select">
<option value="auto" selected>🕒 Авто (по времени суток)</option>
<option value="energy">⚡ Энергия & Спорт</option>
<option value="chill">☕ Спокойствие & Чилл</option>
<option value="dark">🌙 Ночной андеграунд</option>
</select>
</div>
<div class="wave-context-badge-wrap">
<span id="waveContextLabel" class="badge badge-context">Определение контекста...</span>
</div>
</div>
<div class="wave-stats-row">
<div class="wave-stat">
<span class="wave-stat-label">Буфер ротации:</span>
<strong id="waveCountLabel">0 / 25 треков</strong>
</div>
<div class="wave-stat">
<span class="wave-stat-label">Объём на диске:</span>
<strong id="waveSizeLabel">0 МБ</strong>
</div>
<div class="wave-stat">
<span class="wave-stat-label">Срок хранения:</span>
<strong>7 дней</strong>
</div>
<div class="wave-stat">
<span class="wave-stat-label">Умный плейлист:</span>
<strong><a href="https://music.qpid.pro" target="_blank">Моя Волна.nsp ↗</a></strong>
</div>
</div>
<div id="waveAnchorsContainer" class="wave-anchors" style="margin-top: 0.8rem; display: none;">
<span style="font-size: 0.8rem; color: var(--text-secondary);">Якорные исполнители вкуса:</span>
<div id="waveAnchorsList" class="wave-anchors-tags"></div>
</div>
<!-- Wave Tracks List -->
<div class="wave-tracks-container" style="margin-top: 1rem;">
<div class="wave-tracks-header">
<h3>🎵 Треки сейчас в потоке Волны</h3>
<span id="waveLoadingText" style="display: none; color: var(--accent-color); font-size: 0.82rem;">
<span class="spinner-sm"></span> Идёт поиск и загрузка рекомендаций...
</span>
</div>
<div id="waveTracksList" class="wave-tracks-list">
<p class="empty-state">Волна пуста. Нажмите «Обновить Волну» для генерации первого потока.</p>
</div>
</div>
</section>
<!-- Active Tasks -->
<section class="card tasks-card">
<h2>⚡ Очередь задач</h2>
<div id="tasksList" class="tasks-list">
<p class="empty-state">Нет активных загрузок</p>
</div>
</section>
<!-- History -->
<section class="card history-card">
<h2>📜 Недавно загруженные треки</h2>
<div class="table-container">
<table class="tracks-table">
<thead>
<tr>
<th>Сервис</th>
<th>Исполнитель</th>
<th>Трек</th>
<th>Альбом</th>
<th>Дата</th>
</tr>
</thead>
<tbody id="historyBody">
<tr>
<td colspan="5" class="empty-state">Пока нет загрузок</td>
</tr>
</tbody>
</table>
</div>
</section>
</main>
<footer class="footer">
<p>Navidrome Music Sync • Интегрировано с <a href="https://music.qpid.pro" target="_blank">music.qpid.pro</a></p>
</footer>
</div>
<!-- Floating Audio Preview Player -->
<div id="audioPlayerBar" class="audio-player-bar" style="display: none;">
<div class="player-track-info">
<img id="playerCover" class="player-cover" src="" alt="Cover" />
<div class="player-meta">
<div class="player-title-row">
<span id="playerTitle" class="player-title"></span>
<span id="playerExplicitBadge" class="badge"></span>
</div>
<span id="playerArtist" class="player-artist"></span>
</div>
</div>
<div class="player-controls-container">
<audio id="globalAudioPlayer" controls preload="metadata"></audio>
</div>
<div class="player-actions">
<button id="playerImportBtn" class="btn-sm btn-import">📥 В Navidrome</button>
<button id="playerDownloadBtn" class="btn-sm btn-direct-dl">💾 Скачать</button>
<button id="playerCloseBtn" class="btn-player-close" title="Закрыть плеер">&times;</button>
</div>
</div>
<script src="static/app.js"></script>
</body>
</html>