new: option to love tracks on last.fm

This commit is contained in:
Julien Maille 2025-12-29 23:14:57 +01:00
parent 14691da826
commit 0185f161a0
6 changed files with 59 additions and 6 deletions

View file

@ -339,6 +339,17 @@
<span class="slider"></span> <span class="slider"></span>
</label> </label>
</div> </div>
<div class="setting-item" id="lastfm-love-setting" style="display: none;">
<div class="info">
<span class="label">Love on Like</span>
<span class="description">Automatically 'love' tracks on Last.fm when you like them</span>
</div>
<label class="toggle-switch">
<input type="checkbox" id="lastfm-love-toggle">
<span class="slider"></span>
</label>
</div>
</div> </div>
<div class="settings-group"> <div class="settings-group">

View file

@ -196,7 +196,7 @@ document.addEventListener('DOMContentLoaded', async () => {
initializeSettings(scrobbler, player, api, ui); initializeSettings(scrobbler, player, api, ui);
initializePlayerEvents(player, audioPlayer, scrobbler, ui); initializePlayerEvents(player, audioPlayer, scrobbler, ui);
initializeTrackInteractions(player, api, document.querySelector('.main-content'), document.getElementById('context-menu'), lyricsManager, ui); initializeTrackInteractions(player, api, document.querySelector('.main-content'), document.getElementById('context-menu'), lyricsManager, ui, scrobbler);
initializeUIInteractions(player, api); initializeUIInteractions(player, api);
initializeKeyboardShortcuts(player, audioPlayer, lyricsPanel); initializeKeyboardShortcuts(player, audioPlayer, lyricsPanel);

View file

@ -316,7 +316,7 @@ function initializeSmoothSliders(audioPlayer, player) {
}); });
} }
export async function handleTrackAction(action, item, player, api, lyricsManager, type = 'track', ui = null) { export async function handleTrackAction(action, item, player, api, lyricsManager, type = 'track', ui = null, scrobbler = null) {
if (!item) return; if (!item) return;
if (action === 'add-to-queue') { if (action === 'add-to-queue') {
@ -357,6 +357,10 @@ export async function handleTrackAction(action, item, player, api, lyricsManager
const added = await db.toggleFavorite(type, item); const added = await db.toggleFavorite(type, item);
syncManager.syncLibraryItem(type, item, added); syncManager.syncLibraryItem(type, item, added);
if (added && type === 'track' && scrobbler && lastFMStorage.isEnabled() && lastFMStorage.shouldLoveOnLike()) {
scrobbler.loveTrack(item);
}
// Update all instances of this item's like button on the page // Update all instances of this item's like button on the page
const id = type === 'playlist' ? item.uuid : item.id; const id = type === 'playlist' ? item.uuid : item.id;
const selector = type === 'track' const selector = type === 'track'
@ -429,7 +433,7 @@ export async function handleTrackAction(action, item, player, api, lyricsManager
} }
} }
export function initializeTrackInteractions(player, api, mainContent, contextMenu, lyricsManager, ui) { export function initializeTrackInteractions(player, api, mainContent, contextMenu, lyricsManager, ui, scrobbler) {
let contextTrack = null; let contextTrack = null;
mainContent.addEventListener('click', async e => { mainContent.addEventListener('click', async e => {
@ -462,7 +466,7 @@ export function initializeTrackInteractions(player, api, mainContent, contextMen
} }
if (item) { if (item) {
await handleTrackAction(action, item, player, api, lyricsManager, type, ui); await handleTrackAction(action, item, player, api, lyricsManager, type, ui, scrobbler);
} }
return; return;
} }
@ -539,7 +543,7 @@ export function initializeTrackInteractions(player, api, mainContent, contextMen
e.stopPropagation(); e.stopPropagation();
const action = e.target.dataset.action; const action = e.target.dataset.action;
if (action && contextTrack) { if (action && contextTrack) {
await handleTrackAction(action, contextTrack, player, api, lyricsManager, 'track', ui); await handleTrackAction(action, contextTrack, player, api, lyricsManager, 'track', ui, scrobbler);
} }
contextMenu.style.display = 'none'; contextMenu.style.display = 'none';
}); });
@ -575,7 +579,7 @@ export function initializeTrackInteractions(player, api, mainContent, contextMen
nowPlayingLikeBtn.addEventListener('click', async (e) => { nowPlayingLikeBtn.addEventListener('click', async (e) => {
e.stopPropagation(); e.stopPropagation();
if (player.currentTrack) { if (player.currentTrack) {
await handleTrackAction('toggle-like', player.currentTrack, player, api, lyricsManager, 'track', ui); await handleTrackAction('toggle-like', player.currentTrack, player, api, lyricsManager, 'track', ui, scrobbler);
} }
}); });
} }

View file

@ -232,6 +232,22 @@ export class LastFMScrobbler {
} }
} }
async loveTrack(track) {
if (!this.isAuthenticated()) return;
try {
const params = {
artist: track.artist?.name || 'Unknown Artist',
track: track.title
};
await this.makeRequest('track.love', params, true);
console.log('Loved track on Last.fm:', track.title);
} catch (error) {
console.error('Failed to love track on Last.fm:', error);
}
}
onTrackChange(track) { onTrackChange(track) {
if (!this.isAuthenticated()) return; if (!this.isAuthenticated()) return;
this.updateNowPlaying(track); this.updateNowPlaying(track);

View file

@ -14,6 +14,8 @@ export function initializeSettings(scrobbler, player, api, ui) {
const lastfmStatus = document.getElementById('lastfm-status'); const lastfmStatus = document.getElementById('lastfm-status');
const lastfmToggle = document.getElementById('lastfm-toggle'); const lastfmToggle = document.getElementById('lastfm-toggle');
const lastfmToggleSetting = document.getElementById('lastfm-toggle-setting'); const lastfmToggleSetting = document.getElementById('lastfm-toggle-setting');
const lastfmLoveToggle = document.getElementById('lastfm-love-toggle');
const lastfmLoveSetting = document.getElementById('lastfm-love-setting');
function updateLastFMUI() { function updateLastFMUI() {
if (scrobbler.isAuthenticated()) { if (scrobbler.isAuthenticated()) {
@ -21,12 +23,15 @@ export function initializeSettings(scrobbler, player, api, ui) {
lastfmConnectBtn.textContent = 'Disconnect'; lastfmConnectBtn.textContent = 'Disconnect';
lastfmConnectBtn.classList.add('danger'); lastfmConnectBtn.classList.add('danger');
lastfmToggleSetting.style.display = 'flex'; lastfmToggleSetting.style.display = 'flex';
lastfmLoveSetting.style.display = 'flex';
lastfmToggle.checked = lastFMStorage.isEnabled(); lastfmToggle.checked = lastFMStorage.isEnabled();
lastfmLoveToggle.checked = lastFMStorage.shouldLoveOnLike();
} else { } else {
lastfmStatus.textContent = 'Connect your Last.fm account to scrobble tracks'; lastfmStatus.textContent = 'Connect your Last.fm account to scrobble tracks';
lastfmConnectBtn.textContent = 'Connect Last.fm'; lastfmConnectBtn.textContent = 'Connect Last.fm';
lastfmConnectBtn.classList.remove('danger'); lastfmConnectBtn.classList.remove('danger');
lastfmToggleSetting.style.display = 'none'; lastfmToggleSetting.style.display = 'none';
lastfmLoveSetting.style.display = 'none';
} }
} }
@ -104,6 +109,10 @@ export function initializeSettings(scrobbler, player, api, ui) {
lastFMStorage.setEnabled(e.target.checked); lastFMStorage.setEnabled(e.target.checked);
}); });
lastfmLoveToggle?.addEventListener('change', (e) => {
lastFMStorage.setLoveOnLike(e.target.checked);
});
// Theme picker // Theme picker
const themePicker = document.getElementById('theme-picker'); const themePicker = document.getElementById('theme-picker');
const currentTheme = themeManager.getTheme(); const currentTheme = themeManager.getTheme();

View file

@ -293,6 +293,7 @@ export const themeManager = {
export const lastFMStorage = { export const lastFMStorage = {
STORAGE_KEY: 'lastfm-enabled', STORAGE_KEY: 'lastfm-enabled',
LOVE_ON_LIKE_KEY: 'lastfm-love-on-like',
isEnabled() { isEnabled() {
try { try {
@ -304,6 +305,18 @@ export const lastFMStorage = {
setEnabled(enabled) { setEnabled(enabled) {
localStorage.setItem(this.STORAGE_KEY, enabled ? 'true' : 'false'); localStorage.setItem(this.STORAGE_KEY, enabled ? 'true' : 'false');
},
shouldLoveOnLike() {
try {
return localStorage.getItem(this.LOVE_ON_LIKE_KEY) === 'true';
} catch (e) {
return false;
}
},
setLoveOnLike(enabled) {
localStorage.setItem(this.LOVE_ON_LIKE_KEY, enabled ? 'true' : 'false');
} }
}; };