Merge branch 'main' of github.com:SamidyFR/monochrome
This commit is contained in:
commit
cd30df8d6a
8 changed files with 86 additions and 58 deletions
17
index.html
17
index.html
|
|
@ -250,13 +250,10 @@
|
|||
|
||||
<div id="page-library" class="page">
|
||||
<section class="content-section">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem;">
|
||||
<h2 class="section-title" style="margin-bottom: 0;">My Playlists</h2>
|
||||
<div style="display: flex; gap: 0.5rem;">
|
||||
|
||||
<button id="create-playlist-btn" class="btn-secondary">Create Playlist</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="library-header">
|
||||
<h2>My Playlists</h2>
|
||||
<button id="create-playlist-btn" class="btn-primary">Create Playlist</button>
|
||||
</div>
|
||||
<div class="card-grid" id="my-playlists-container"></div>
|
||||
</section>
|
||||
|
||||
|
|
@ -814,7 +811,7 @@
|
|||
<div class="player-actions-row">
|
||||
<button id="now-playing-like-btn" class="like-btn" data-action="toggle-like" title="Save to Favorites" style="display: none;">
|
||||
</button>
|
||||
<button id="now-playing-add-playlist-btn" title="Add to Playlist" class="desktop-only">
|
||||
<button id="now-playing-add-playlist-btn" title="Add to Playlist" class="desktop-only" style="display: none;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/>
|
||||
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/>
|
||||
|
|
@ -825,7 +822,7 @@
|
|||
<path d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"/>
|
||||
</svg>
|
||||
</button>
|
||||
<button id="toggle-lyrics-btn" title="Lyrics">
|
||||
<button id="toggle-lyrics-btn" title="Lyrics" style="display: none;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-mic"><path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" y1="19" x2="12" y2="22"/><line x1="8" y1="22" x2="16" y2="22"/></svg>
|
||||
</button>
|
||||
<button id="download-current-btn" title="Download current track" class="desktop-only">
|
||||
|
|
@ -836,7 +833,7 @@
|
|||
</svg>
|
||||
</button>
|
||||
|
||||
<button id="mobile-add-playlist-btn" class="mobile-only">
|
||||
<button id="mobile-add-playlist-btn" class="mobile-only" style="display: none !important;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/>
|
||||
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/>
|
||||
|
|
|
|||
12
js/app.js
12
js/app.js
|
|
@ -301,10 +301,18 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
|
||||
try {
|
||||
let playlist, tracks;
|
||||
const userPlaylist = await db.getPlaylist(playlistId);
|
||||
let userPlaylist = await db.getPlaylist(playlistId);
|
||||
|
||||
if (!userPlaylist) {
|
||||
try {
|
||||
userPlaylist = await syncManager.getPublicPlaylist(playlistId);
|
||||
} catch (e) {
|
||||
// Not a public playlist
|
||||
}
|
||||
}
|
||||
|
||||
if (userPlaylist) {
|
||||
playlist = { ...userPlaylist, title: userPlaylist.name };
|
||||
playlist = { ...userPlaylist, title: userPlaylist.name || userPlaylist.title };
|
||||
tracks = userPlaylist.tracks || [];
|
||||
} else {
|
||||
const data = await api.getPlaylist(playlistId);
|
||||
|
|
|
|||
11
js/events.js
11
js/events.js
|
|
@ -399,8 +399,15 @@ export async function handleTrackAction(action, item, player, api, lyricsManager
|
|||
const data = await api.getPlaylist(item.uuid);
|
||||
tracks = data.tracks;
|
||||
} else if (type === 'user-playlist') {
|
||||
const playlist = await db.getPlaylist(item.id);
|
||||
tracks = playlist ? playlist.tracks : [];
|
||||
let playlist = await db.getPlaylist(item.id);
|
||||
if (!playlist) {
|
||||
try {
|
||||
playlist = await syncManager.getPublicPlaylist(item.id);
|
||||
} catch (e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
tracks = playlist ? playlist.tracks : (item.tracks || []);
|
||||
}
|
||||
|
||||
if (tracks.length > 0) {
|
||||
|
|
|
|||
55
js/player.js
55
js/player.js
|
|
@ -574,35 +574,44 @@ export class Player {
|
|||
|
||||
updateSleepTimerUI() {
|
||||
const timerBtn = document.getElementById('sleep-timer-btn');
|
||||
if (!timerBtn) return;
|
||||
|
||||
if (this.isSleepTimerActive()) {
|
||||
const remaining = this.getSleepTimerRemaining();
|
||||
if (remaining > 0) {
|
||||
const minutes = Math.floor(remaining / 60);
|
||||
const seconds = remaining % 60;
|
||||
timerBtn.innerHTML = `<span style="font-size: 12px; font-weight: bold;">${minutes}:${seconds.toString().padStart(2, '0')}</span>`;
|
||||
timerBtn.title = `Sleep Timer: ${minutes}:${seconds.toString().padStart(2, '0')} remaining`;
|
||||
timerBtn.classList.add('active');
|
||||
const timerBtnDesktop = document.getElementById('sleep-timer-btn-desktop');
|
||||
|
||||
const updateBtn = (btn) => {
|
||||
if (!btn) return;
|
||||
if (this.isSleepTimerActive()) {
|
||||
const remaining = this.getSleepTimerRemaining();
|
||||
if (remaining > 0) {
|
||||
const minutes = Math.floor(remaining / 60);
|
||||
const seconds = remaining % 60;
|
||||
btn.innerHTML = `<span style="font-size: 12px; font-weight: bold;">${minutes}:${seconds.toString().padStart(2, '0')}</span>`;
|
||||
btn.title = `Sleep Timer: ${minutes}:${seconds.toString().padStart(2, '0')} remaining`;
|
||||
btn.classList.add('active');
|
||||
btn.style.color = 'var(--primary)';
|
||||
} else {
|
||||
btn.innerHTML = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="10"/>
|
||||
<polyline points="12,6 12,12 16,14"/>
|
||||
</svg>
|
||||
`;
|
||||
btn.title = 'Sleep Timer';
|
||||
btn.classList.remove('active');
|
||||
btn.style.color = '';
|
||||
}
|
||||
} else {
|
||||
timerBtn.innerHTML = `
|
||||
btn.innerHTML = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="10"/>
|
||||
<polyline points="12,6 12,12 16,14"/>
|
||||
</svg>
|
||||
`;
|
||||
timerBtn.title = 'Sleep Timer';
|
||||
timerBtn.classList.remove('active');
|
||||
btn.title = 'Sleep Timer';
|
||||
btn.classList.remove('active');
|
||||
btn.style.color = '';
|
||||
}
|
||||
} else {
|
||||
timerBtn.innerHTML = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="10"/>
|
||||
<polyline points="12,6 12,12 16,14"/>
|
||||
</svg>
|
||||
`;
|
||||
timerBtn.title = 'Sleep Timer';
|
||||
timerBtn.classList.remove('active');
|
||||
}
|
||||
};
|
||||
|
||||
updateBtn(timerBtn);
|
||||
updateBtn(timerBtnDesktop);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,10 @@ export const apiSettings = {
|
|||
} catch (error) {
|
||||
console.error('Failed to load instances from GitHub:', error);
|
||||
this.defaultInstances = {
|
||||
api: ["https://monochrome-api.samidy.com"],
|
||||
api: [
|
||||
"https://tidal-api.binimum.org",
|
||||
"https://monochrome-api.samidy.com"
|
||||
],
|
||||
streaming: [
|
||||
"https://triton.squid.wtf",
|
||||
"https://wolf.qqdl.site",
|
||||
|
|
@ -63,7 +66,7 @@ export const apiSettings = {
|
|||
"https://hund.qqdl.site",
|
||||
"https://tidal.kinoplus.online",
|
||||
"https://tidal-api.binimum.org"
|
||||
]
|
||||
]
|
||||
};
|
||||
this.instancesLoaded = true;
|
||||
return this.defaultInstances;
|
||||
|
|
|
|||
19
js/ui.js
19
js/ui.js
|
|
@ -81,14 +81,23 @@ export class UIRenderer {
|
|||
this.updateGlobalTheme();
|
||||
|
||||
const likeBtn = document.getElementById('now-playing-like-btn');
|
||||
if (likeBtn) {
|
||||
if (track) {
|
||||
const addPlaylistBtn = document.getElementById('now-playing-add-playlist-btn');
|
||||
const mobileAddPlaylistBtn = document.getElementById('mobile-add-playlist-btn');
|
||||
const lyricsBtn = document.getElementById('toggle-lyrics-btn');
|
||||
|
||||
if (track) {
|
||||
if (likeBtn) {
|
||||
likeBtn.style.display = 'flex';
|
||||
// Use the centralized update logic if possible, or manual here
|
||||
this.updateLikeState(likeBtn.parentElement, 'track', track.id);
|
||||
} else {
|
||||
likeBtn.style.display = 'none';
|
||||
}
|
||||
if (addPlaylistBtn) addPlaylistBtn.style.removeProperty('display');
|
||||
if (mobileAddPlaylistBtn) mobileAddPlaylistBtn.style.removeProperty('display');
|
||||
if (lyricsBtn) lyricsBtn.style.removeProperty('display');
|
||||
} else {
|
||||
if (likeBtn) likeBtn.style.display = 'none';
|
||||
if (addPlaylistBtn) addPlaylistBtn.style.setProperty('display', 'none', 'important');
|
||||
if (mobileAddPlaylistBtn) mobileAddPlaylistBtn.style.setProperty('display', 'none', 'important');
|
||||
if (lyricsBtn) lyricsBtn.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"api": [
|
||||
"https://tidal-api.binimum.org",
|
||||
"https://monochrome-api.samidy.com"
|
||||
],
|
||||
"streaming": [
|
||||
|
|
|
|||
22
styles.css
22
styles.css
|
|
@ -1575,7 +1575,6 @@ input:checked + .slider::before {
|
|||
position: relative;
|
||||
font-size: 0.8rem;
|
||||
font-weight: bold;
|
||||
color: var(--foreground);
|
||||
transition: all var(--transition);
|
||||
}
|
||||
|
||||
|
|
@ -2687,8 +2686,7 @@ input:checked + .slider::before {
|
|||
}
|
||||
|
||||
.player-controls .buttons {
|
||||
gap: var(--spacing-sm);
|
||||
margin-bottom: var(--spacing-xs);
|
||||
gap: var(--spacing-md);
|
||||
}
|
||||
|
||||
.player-controls .buttons button {
|
||||
|
|
@ -2715,17 +2713,6 @@ input:checked + .slider::before {
|
|||
display: flex;
|
||||
}
|
||||
|
||||
.volume-controls button {
|
||||
padding: 0.375rem;
|
||||
min-width: 32px;
|
||||
min-height: 32px;
|
||||
}
|
||||
|
||||
.volume-controls button svg {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
#download-notifications {
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
|
|
@ -3850,3 +3837,10 @@ img:not([src]), img[src=''] {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
.library-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: var(--spacing-md);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue