diff --git a/index.html b/index.html
index 0d50570..030e327 100644
--- a/index.html
+++ b/index.html
@@ -339,6 +339,17 @@
+
+
+
+ Love on Like
+ Automatically 'love' tracks on Last.fm when you like them
+
+
+
diff --git a/js/app.js b/js/app.js
index d1b8f59..17452af 100644
--- a/js/app.js
+++ b/js/app.js
@@ -196,7 +196,7 @@ document.addEventListener('DOMContentLoaded', async () => {
initializeSettings(scrobbler, player, api, 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);
initializeKeyboardShortcuts(player, audioPlayer, lyricsPanel);
diff --git a/js/events.js b/js/events.js
index afe457e..3a698d8 100644
--- a/js/events.js
+++ b/js/events.js
@@ -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 (action === 'add-to-queue') {
@@ -357,6 +357,10 @@ export async function handleTrackAction(action, item, player, api, lyricsManager
const added = await db.toggleFavorite(type, item);
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
const id = type === 'playlist' ? item.uuid : item.id;
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;
mainContent.addEventListener('click', async e => {
@@ -462,7 +466,7 @@ export function initializeTrackInteractions(player, api, mainContent, contextMen
}
if (item) {
- await handleTrackAction(action, item, player, api, lyricsManager, type, ui);
+ await handleTrackAction(action, item, player, api, lyricsManager, type, ui, scrobbler);
}
return;
}
@@ -539,7 +543,7 @@ export function initializeTrackInteractions(player, api, mainContent, contextMen
e.stopPropagation();
const action = e.target.dataset.action;
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';
});
@@ -575,7 +579,7 @@ export function initializeTrackInteractions(player, api, mainContent, contextMen
nowPlayingLikeBtn.addEventListener('click', async (e) => {
e.stopPropagation();
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);
}
});
}
diff --git a/js/lastfm.js b/js/lastfm.js
index 1e1e10b..02e299a 100644
--- a/js/lastfm.js
+++ b/js/lastfm.js
@@ -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) {
if (!this.isAuthenticated()) return;
this.updateNowPlaying(track);
diff --git a/js/settings.js b/js/settings.js
index 9074a97..656a184 100644
--- a/js/settings.js
+++ b/js/settings.js
@@ -14,6 +14,8 @@ export function initializeSettings(scrobbler, player, api, ui) {
const lastfmStatus = document.getElementById('lastfm-status');
const lastfmToggle = document.getElementById('lastfm-toggle');
const lastfmToggleSetting = document.getElementById('lastfm-toggle-setting');
+ const lastfmLoveToggle = document.getElementById('lastfm-love-toggle');
+ const lastfmLoveSetting = document.getElementById('lastfm-love-setting');
function updateLastFMUI() {
if (scrobbler.isAuthenticated()) {
@@ -21,12 +23,15 @@ export function initializeSettings(scrobbler, player, api, ui) {
lastfmConnectBtn.textContent = 'Disconnect';
lastfmConnectBtn.classList.add('danger');
lastfmToggleSetting.style.display = 'flex';
+ lastfmLoveSetting.style.display = 'flex';
lastfmToggle.checked = lastFMStorage.isEnabled();
+ lastfmLoveToggle.checked = lastFMStorage.shouldLoveOnLike();
} else {
lastfmStatus.textContent = 'Connect your Last.fm account to scrobble tracks';
lastfmConnectBtn.textContent = 'Connect Last.fm';
lastfmConnectBtn.classList.remove('danger');
lastfmToggleSetting.style.display = 'none';
+ lastfmLoveSetting.style.display = 'none';
}
}
@@ -104,6 +109,10 @@ export function initializeSettings(scrobbler, player, api, ui) {
lastFMStorage.setEnabled(e.target.checked);
});
+ lastfmLoveToggle?.addEventListener('change', (e) => {
+ lastFMStorage.setLoveOnLike(e.target.checked);
+ });
+
// Theme picker
const themePicker = document.getElementById('theme-picker');
const currentTheme = themeManager.getTheme();
diff --git a/js/storage.js b/js/storage.js
index 975feda..c90ca93 100644
--- a/js/storage.js
+++ b/js/storage.js
@@ -293,6 +293,7 @@ export const themeManager = {
export const lastFMStorage = {
STORAGE_KEY: 'lastfm-enabled',
+ LOVE_ON_LIKE_KEY: 'lastfm-love-on-like',
isEnabled() {
try {
@@ -304,6 +305,18 @@ export const lastFMStorage = {
setEnabled(enabled) {
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');
}
};