diff --git a/index.html b/index.html
index 785778d..3646bcb 100644
--- a/index.html
+++ b/index.html
@@ -27,6 +27,8 @@
- Like
- Add to Playlist
+ - Go to Artist
+ - Go to Album
- Track Mix
- Play Next
- Add to Queue
@@ -776,7 +778,7 @@
id="album-section-more-albums"
style="display: none; margin-top: 3rem"
>
- More from Artist
+ from Artist
diff --git a/js/app.js b/js/app.js
index e7ca6cb..04fc4bf 100644
--- a/js/app.js
+++ b/js/app.js
@@ -1006,6 +1006,42 @@ document.addEventListener('DOMContentLoaded', async () => {
ui.renderRecentPage();
}
});
+
+ const contextMenu = document.getElementById('context-menu');
+ if (contextMenu) {
+ const observer = new MutationObserver((mutations) => {
+ mutations.forEach((mutation) => {
+ if (mutation.type === 'attributes' && mutation.attributeName === 'style') {
+ if (contextMenu.style.display === 'block') {
+ const track = contextMenu._contextTrack;
+ const albumItem = contextMenu.querySelector('[data-action="go-to-album"]');
+ const artistItem = contextMenu.querySelector('[data-action="go-to-artist"]');
+
+ if (track) {
+ if (albumItem) {
+ let label = 'Album';
+ const albumType = track.album?.type?.toUpperCase();
+ const trackCount = track.album?.numberOfTracks;
+
+ if (albumType === 'SINGLE' || trackCount === 1) label = 'Single';
+ else if (albumType === 'EP') label = 'EP';
+ else if (trackCount && trackCount <= 6) label = 'EP';
+
+ albumItem.textContent = `Go to ${label}`;
+ albumItem.style.display = track.album ? 'block' : 'none';
+ }
+ if (artistItem) {
+ const hasArtist = track.artist || (track.artists && track.artists.length > 0);
+ artistItem.style.display = hasArtist ? 'block' : 'none';
+ }
+ }
+ }
+ }
+ });
+ });
+
+ observer.observe(contextMenu, { attributes: true });
+ }
});
function showUpdateNotification(updateCallback) {
diff --git a/js/events.js b/js/events.js
index 6efa818..277ffc9 100644
--- a/js/events.js
+++ b/js/events.js
@@ -102,7 +102,6 @@ export function initializePlayerEvents(player, audioPlayer, scrobbler, ui) {
audioPlayer.addEventListener('error', (e) => {
console.error('Audio playback error:', e);
- document.querySelector('.now-playing-bar .artist').textContent = 'Playback error. Try another track.';
playPauseBtn.innerHTML = SVG_PLAY;
});
@@ -723,6 +722,15 @@ export async function handleTrackAction(
list.addEventListener('click', handleOptionClick);
modal.classList.add('active');
+ } else if (action === 'go-to-artist') {
+ const artistId = item.artist?.id || item.artists?.[0]?.id;
+ if (artistId) {
+ window.location.hash = `#artist/${artistId}`;
+ }
+ } else if (action === 'go-to-album') {
+ if (item.album?.id) {
+ window.location.hash = `#album/${item.album.id}`;
+ }
}
}
@@ -863,6 +871,7 @@ export function initializeTrackInteractions(player, api, mainContent, contextMen
if (contextTrack) {
if (contextTrack.isLocal) return;
+ contextMenu._contextTrack = contextTrack;
await updateContextMenuLikeState(contextMenu, contextTrack);
positionMenu(contextMenu, e.pageX, e.pageY);
}
@@ -875,7 +884,10 @@ export function initializeTrackInteractions(player, api, mainContent, contextMen
contextMenu.addEventListener('click', async (e) => {
e.stopPropagation();
- const action = e.target.dataset.action;
+ const target = e.target.closest('[data-action]');
+ if (!target) return;
+
+ const action = target.dataset.action;
const track = contextMenu._contextTrack || contextTrack;
if (action && track) {
await handleTrackAction(action, track, player, api, lyricsManager, 'track', ui, scrobbler);
diff --git a/js/player.js b/js/player.js
index ba8415b..72ad1e8 100644
--- a/js/player.js
+++ b/js/player.js
@@ -332,8 +332,6 @@ export class Player {
this.preloadNextTracks();
} catch (error) {
console.error(`Could not play track: ${trackTitle}`, error);
- document.querySelector('.now-playing-bar .title').textContent = `Error: ${trackTitle}`;
- document.querySelector('.now-playing-bar .artist').textContent = error.message || 'Could not load track';
}
}
diff --git a/js/storage.js b/js/storage.js
index 44e8325..f620707 100644
--- a/js/storage.js
+++ b/js/storage.js
@@ -53,7 +53,7 @@ export const apiSettings = {
} catch (error) {
console.error('Failed to load instances from GitHub:', error);
this.defaultInstances = {
- api: ['https://tidal-api.binimum.org', 'https://monochrome-api.samidy.com'],
+ api: ['https://triton.squid.wtf', 'https://tidal-api.binimum.org', 'https://vogel.qqdl.site'],
streaming: [
'https://triton.squid.wtf',
'https://wolf.qqdl.site',
@@ -63,6 +63,8 @@ export const apiSettings = {
'https://hund.qqdl.site',
'https://tidal.kinoplus.online',
'https://tidal-api.binimum.org',
+ 'https://hifi-one.spotisaver.net',
+ 'https://hifi-two.spotisaver.net',
],
};
this.instancesLoaded = true;