196 lines
8.2 KiB
HTML
196 lines
8.2 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Blastoise! A very special music server</title>
|
||
<link rel="stylesheet" href="/styles.css?v=20">
|
||
</head>
|
||
<body>
|
||
<div id="app">
|
||
<div id="site-header">
|
||
<h1>Blastoise <span id="sync-indicator"></span></h1>
|
||
<a href="https://git.peterino.com/peterino/blastoise/issues/new" target="_blank" id="btn-report-bug">Suggestions/Bugs</a>
|
||
</div>
|
||
|
||
<div id="login-panel">
|
||
<h2>Sign in to continue</h2>
|
||
<div class="tabs">
|
||
<button id="tab-login" class="active">Login</button>
|
||
<button id="tab-signup">Sign Up</button>
|
||
</div>
|
||
<div id="login-fields" class="form-group">
|
||
<input type="text" id="login-username" placeholder="Username">
|
||
<input type="password" id="login-password" placeholder="Password">
|
||
<button class="submit-btn" id="btn-login">Login</button>
|
||
<div id="auth-error"></div>
|
||
</div>
|
||
<div id="signup-fields" class="form-group hidden">
|
||
<input type="text" id="signup-username" placeholder="Username (min 3 chars)">
|
||
<input type="password" id="signup-password" placeholder="Password (min 6 chars)">
|
||
<button class="submit-btn" id="btn-signup">Sign Up</button>
|
||
<div id="signup-error"></div>
|
||
</div>
|
||
<div id="guest-section" class="hidden">
|
||
<div class="divider"><span>or</span></div>
|
||
<button class="guest-btn" id="btn-guest">Continue as Guest</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="player-content">
|
||
<div id="header-row">
|
||
<div id="auth-section">
|
||
<div class="user-info">
|
||
<span class="username" id="current-username"></span>
|
||
<span class="admin-badge" id="admin-badge" style="display:none;">Admin</span>
|
||
<button id="btn-kick-others" title="Disconnect all other devices">Disconnect all my devices</button>
|
||
<button id="btn-logout">logout</button>
|
||
</div>
|
||
</div>
|
||
<div id="stream-select"></div>
|
||
</div>
|
||
|
||
<!-- Mobile tab bar -->
|
||
<div id="mobile-tabs">
|
||
<button class="mobile-tab active" data-panel="channels-panel">Channels</button>
|
||
<button class="mobile-tab" data-panel="library-panel">Library</button>
|
||
<button class="mobile-tab" data-panel="queue-panel">Queue</button>
|
||
</div>
|
||
|
||
<div id="main-content">
|
||
<div id="channels-panel">
|
||
<div class="panel-header">
|
||
<h3>Channels</h3>
|
||
<button id="btn-new-channel" title="New channel">+</button>
|
||
</div>
|
||
<div id="channels-list"></div>
|
||
</div>
|
||
<div id="library-panel">
|
||
<div class="panel-tabs">
|
||
<button class="panel-tab active" data-tab="library">Library</button>
|
||
<button class="panel-tab" data-tab="playlists">Playlists</button>
|
||
<button class="panel-tab" data-tab="tasks">Tasks</button>
|
||
</div>
|
||
<div class="panel-views">
|
||
<div id="library-view" class="panel-view active">
|
||
<div class="panel-header">
|
||
<input type="text" id="library-search" placeholder="Search..." class="search-input">
|
||
<input type="file" id="file-input" multiple accept=".mp3,.ogg,.flac,.wav,.m4a,.aac,.opus,.wma,.mp4" style="display:none">
|
||
</div>
|
||
<div id="scan-progress" class="scan-progress hidden"></div>
|
||
<div id="library"></div>
|
||
<div id="add-panel" class="add-panel hidden">
|
||
<button id="btn-add-close" class="add-panel-close">Close</button>
|
||
<div class="add-panel-content">
|
||
<button id="btn-upload-files" class="add-option">Upload files...</button>
|
||
<button id="btn-fetch-url" class="add-option">Fetch from website...</button>
|
||
</div>
|
||
</div>
|
||
<div id="fetch-dialog" class="fetch-dialog hidden">
|
||
<div class="fetch-dialog-header">
|
||
<span>Fetch from URL</span>
|
||
<button id="btn-fetch-close" class="fetch-dialog-close">×</button>
|
||
</div>
|
||
<div class="fetch-dialog-content">
|
||
<input type="text" id="fetch-url-input" class="fetch-url-input" placeholder="https://youtube.com/watch?v=...">
|
||
<button id="btn-fetch-submit" class="fetch-submit-btn">Fetch</button>
|
||
</div>
|
||
</div>
|
||
<button id="btn-add" class="add-btn">Add to library...</button>
|
||
<div id="upload-dropzone" class="upload-dropzone hidden">
|
||
<div class="dropzone-content">Drop audio files here</div>
|
||
</div>
|
||
</div>
|
||
<div id="playlists-view" class="panel-view">
|
||
<div class="playlists-container">
|
||
<div id="playlists-list-panel">
|
||
<div class="playlists-section">
|
||
<h4>My Playlists</h4>
|
||
<div id="my-playlists"></div>
|
||
</div>
|
||
<div class="playlists-section">
|
||
<h4>Shared</h4>
|
||
<div id="shared-playlists"></div>
|
||
</div>
|
||
<button id="btn-new-playlist" class="new-playlist-btn">+ New Playlist</button>
|
||
</div>
|
||
<div id="playlist-contents-panel">
|
||
<div id="playlist-contents-header">
|
||
<span id="selected-playlist-name">Select a playlist</span>
|
||
<div id="playlist-actions" class="hidden">
|
||
<button id="btn-playlist-add-queue" title="Add all to queue">Add to Queue</button>
|
||
<button id="btn-playlist-play-next" title="Play next">Play Next</button>
|
||
</div>
|
||
</div>
|
||
<div id="playlist-tracks"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="tasks-view" class="panel-view">
|
||
<div id="tasks-list"></div>
|
||
<div id="tasks-empty" class="tasks-empty">No active tasks</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="queue-panel">
|
||
<h3 id="queue-title">Queue</h3>
|
||
<div id="now-playing-bar" class="now-playing-bar hidden" title="Click to scroll to current track"></div>
|
||
<div id="queue"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="player-bar">
|
||
<div id="now-playing">
|
||
<div id="channel-name"></div>
|
||
<div id="track-name" class="empty">
|
||
<span class="marquee-inner"><span id="track-title">Loading...</span></span>
|
||
</div>
|
||
</div>
|
||
<div id="player-controls">
|
||
<div id="progress-row">
|
||
<span id="btn-sync" title="Toggle sync">sync</span>
|
||
<span id="btn-prev" title="Previous track">⏮</span>
|
||
<span id="status-icon">▶</span>
|
||
<span id="btn-next" title="Next track">⏭</span>
|
||
<span id="btn-mode" class="mode-repeat-all" title="Playback mode">repeat</span>
|
||
<div id="progress-container"><div id="progress-bar"></div><div id="seek-tooltip"></div></div>
|
||
<div id="time"><span id="time-current">0:00</span>/<span id="time-total">0:00</span></div>
|
||
</div>
|
||
<div id="buffer-bar"></div>
|
||
<div id="download-speed"></div>
|
||
</div>
|
||
<div id="volume-controls">
|
||
<span id="btn-stream-only" title="Toggle stream-only mode (no caching)">stream</span>
|
||
<span id="btn-mute" title="Toggle mute">🔊</span>
|
||
<input type="range" id="volume" min="0" max="1" step="0.01" value="1">
|
||
</div>
|
||
</div>
|
||
<div id="status"></div>
|
||
</div>
|
||
<div id="toast-container"></div>
|
||
<button id="btn-history" title="Show notification history">recent notifications</button>
|
||
<div id="toast-history" class="hidden">
|
||
<div class="history-header">
|
||
<span>Notification History</span>
|
||
<button id="btn-close-history">×</button>
|
||
</div>
|
||
<div id="toast-history-list"></div>
|
||
</div>
|
||
</div>
|
||
<script src="/trackStorage.js"></script>
|
||
<script src="/core.js"></script>
|
||
<script src="/utils.js"></script>
|
||
<script src="/trackComponent.js"></script>
|
||
<script src="/trackContainer.js"></script>
|
||
<script src="/audioCache.js"></script>
|
||
<script src="/channelSync.js"></script>
|
||
<script src="/ui.js"></script>
|
||
<script src="/queue.js"></script>
|
||
<script src="/playlists.js"></script>
|
||
<script src="/controls.js"></script>
|
||
<script src="/auth.js"></script>
|
||
<script src="/upload.js"></script>
|
||
<script src="/init.js"></script>
|
||
</body>
|
||
</html>
|