editor's picks and open in new tab
This commit is contained in:
parent
2522e0e5be
commit
8bb3b285b1
7 changed files with 121 additions and 2 deletions
26
index.html
26
index.html
|
|
@ -45,6 +45,7 @@
|
|||
<li data-action="go-to-artist" data-type-filter="track,album">Go to artist</li>
|
||||
<li data-action="go-to-album" data-type-filter="track">Go to album</li>
|
||||
<li data-action="copy-link">Copy link</li>
|
||||
<li data-action="open-in-new-tab">Open in new tab</li>
|
||||
<li data-action="track-info" data-type-filter="track">Track info</li>
|
||||
<li data-action="open-original-url" data-type-filter="track">Open original URL</li>
|
||||
<li data-action="download">Download</li>
|
||||
|
|
@ -1164,6 +1165,19 @@
|
|||
</div>
|
||||
<div class="card-grid" id="home-recommended-albums"></div>
|
||||
</section>
|
||||
<section class="content-section" id="home-editors-picks-section">
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 1rem;
|
||||
"
|
||||
>
|
||||
<h2 class="section-title" style="margin-bottom: 0">Editor's Picks</h2>
|
||||
</div>
|
||||
<div class="card-grid" id="home-editors-picks"></div>
|
||||
</section>
|
||||
<section class="content-section">
|
||||
<div
|
||||
style="
|
||||
|
|
@ -2267,6 +2281,18 @@
|
|||
<span class="slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div class="info">
|
||||
<span class="label">Show Editor's Picks</span>
|
||||
<span class="description"
|
||||
>Display curated album selections on the home page</span
|
||||
>
|
||||
</div>
|
||||
<label class="toggle-switch">
|
||||
<input type="checkbox" id="show-editors-picks-toggle" checked />
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings-group">
|
||||
|
|
|
|||
|
|
@ -1067,6 +1067,15 @@ export async function handleTrackAction(
|
|||
navigator.clipboard.writeText(url).then(() => {
|
||||
showNotification('Link copied to clipboard!');
|
||||
});
|
||||
} else if (action === 'open-in-new-tab') {
|
||||
// Use stored href from card if available, otherwise construct URL
|
||||
const contextMenu = document.getElementById('context-menu');
|
||||
const storedHref = contextMenu?._contextHref;
|
||||
const url = storedHref
|
||||
? `${window.location.origin}${storedHref}`
|
||||
: `${window.location.origin}/track/${item.id || item.uuid}`;
|
||||
|
||||
window.open(url, '_blank');
|
||||
} else if (action === 'track-info') {
|
||||
// Show detailed track info modal
|
||||
const isTracker = item.isTracker;
|
||||
|
|
|
|||
|
|
@ -919,6 +919,14 @@ export function initializeSettings(scrobbler, player, api, ui) {
|
|||
});
|
||||
}
|
||||
|
||||
const showEditorsPicksToggle = document.getElementById('show-editors-picks-toggle');
|
||||
if (showEditorsPicksToggle) {
|
||||
showEditorsPicksToggle.checked = homePageSettings.shouldShowEditorsPicks();
|
||||
showEditorsPicksToggle.addEventListener('change', (e) => {
|
||||
homePageSettings.setShowEditorsPicks(e.target.checked);
|
||||
});
|
||||
}
|
||||
|
||||
// Sidebar Section Toggles
|
||||
const sidebarShowHomeToggle = document.getElementById('sidebar-show-home-toggle');
|
||||
if (sidebarShowHomeToggle) {
|
||||
|
|
|
|||
|
|
@ -969,6 +969,21 @@ export const homePageSettings = {
|
|||
setShowJumpBackIn(enabled) {
|
||||
localStorage.setItem(this.SHOW_JUMP_BACK_IN_KEY, enabled ? 'true' : 'false');
|
||||
},
|
||||
|
||||
SHOW_EDITORS_PICKS_KEY: 'home-show-editors-picks',
|
||||
|
||||
shouldShowEditorsPicks() {
|
||||
try {
|
||||
const val = localStorage.getItem(this.SHOW_EDITORS_PICKS_KEY);
|
||||
return val === null ? true : val === 'true';
|
||||
} catch {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
setShowEditorsPicks(enabled) {
|
||||
localStorage.setItem(this.SHOW_EDITORS_PICKS_KEY, enabled ? 'true' : 'false');
|
||||
},
|
||||
};
|
||||
|
||||
export const sidebarSectionSettings = {
|
||||
|
|
|
|||
58
js/ui.js
58
js/ui.js
|
|
@ -1414,6 +1414,7 @@ export class UIRenderer {
|
|||
|
||||
this.renderHomeSongs();
|
||||
this.renderHomeAlbums();
|
||||
this.renderHomeEditorsPicks();
|
||||
this.renderHomeArtists();
|
||||
this.renderHomeRecent();
|
||||
}
|
||||
|
|
@ -1518,6 +1519,63 @@ export class UIRenderer {
|
|||
}
|
||||
}
|
||||
|
||||
async renderHomeEditorsPicks(forceRefresh = false) {
|
||||
const picksContainer = document.getElementById('home-editors-picks');
|
||||
const section = document.getElementById('home-editors-picks-section');
|
||||
|
||||
if (!homePageSettings.shouldShowEditorsPicks()) {
|
||||
if (section) section.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
if (section) section.style.display = '';
|
||||
|
||||
if (picksContainer) {
|
||||
if (forceRefresh) picksContainer.innerHTML = this.createSkeletonCards(6);
|
||||
else if (picksContainer.children.length > 0 && !picksContainer.querySelector('.skeleton')) return;
|
||||
|
||||
try {
|
||||
const response = await fetch('/editors-picks.json');
|
||||
if (!response.ok) throw new Error("Failed to load editor's picks");
|
||||
|
||||
const data = await response.json();
|
||||
const albumIds = data.albums || [];
|
||||
|
||||
if (albumIds.length === 0) {
|
||||
picksContainer.innerHTML = createPlaceholder("No editor's picks available.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch album details
|
||||
const albums = [];
|
||||
for (const albumId of albumIds.slice(0, 12)) {
|
||||
try {
|
||||
const result = await this.api.getAlbum(albumId);
|
||||
if (result && result.album) albums.push(result.album);
|
||||
} catch (e) {
|
||||
console.warn(`Failed to load album ${albumId}:`, e);
|
||||
}
|
||||
}
|
||||
|
||||
if (albums.length > 0) {
|
||||
picksContainer.innerHTML = albums.map((a) => this.createAlbumCardHTML(a)).join('');
|
||||
albums.forEach((a) => {
|
||||
const el = picksContainer.querySelector(`[data-album-id="${a.id}"]`);
|
||||
if (el) {
|
||||
trackDataStore.set(el, a);
|
||||
this.updateLikeState(el, 'album', a.id);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
picksContainer.innerHTML = createPlaceholder("No editor's picks available.");
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Failed to load editor's picks:", e);
|
||||
picksContainer.innerHTML = createPlaceholder("Failed to load editor's picks.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async renderHomeArtists(forceRefresh = false) {
|
||||
const artistsContainer = document.getElementById('home-recommended-artists');
|
||||
const section = artistsContainer?.closest('.content-section');
|
||||
|
|
|
|||
5
public/editors-picks.json
Normal file
5
public/editors-picks.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"name": "Editor's Picks",
|
||||
"description": "Curated selection of standout albums handpicked by the monochrome team",
|
||||
"albums": ["4527433", "90502209"]
|
||||
}
|
||||
2
todo.md
2
todo.md
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
Sorted by ease of implementation (easiest to hardest):
|
||||
|
||||
- [ ] Editor's Picks: Create a JSON file of curated album IDs with metadata for the home screen. Include an option to disable in settings to avoid extra API calls.
|
||||
|
||||
- [ ] Update notifications: Add ability to show the update popup in settings, with an option to automatically update (enabled by default)
|
||||
- [ ] Volume curve option: Add setting to switch between exponential and linear volume scaling
|
||||
- [ ] Custom fonts: Allow users to change fonts in settings or add custom fonts from Google Fonts or direct links
|
||||
|
|
|
|||
Loading…
Reference in a new issue