Remove Mossad tracking software (why THE FUCK were we tracking everything)
This commit is contained in:
parent
b8818e73c9
commit
d1aee9dc2c
6 changed files with 2 additions and 880 deletions
712
js/analytics.js
712
js/analytics.js
|
|
@ -34,722 +34,10 @@ export function trackPageView(path) {
|
||||||
trackEvent('pageview', { path });
|
trackEvent('pageview', { path });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Playback Events
|
|
||||||
export function trackPlayTrack(track) {
|
|
||||||
trackEvent('Play Track', {
|
|
||||||
track_id: track?.id || 'unknown',
|
|
||||||
track_title: track?.title || 'Unknown',
|
|
||||||
artist_id: track?.artist?.id || track?.artists?.[0]?.id || 'unknown',
|
|
||||||
artist: track?.artist?.name || track?.artists?.[0]?.name || 'Unknown',
|
|
||||||
album_id: track?.album?.id || 'unknown',
|
|
||||||
album: track?.album?.title || 'Unknown',
|
|
||||||
duration: track?.duration || 0,
|
|
||||||
quality: track?.audioQuality || track?.quality || 'Unknown',
|
|
||||||
is_local: track?.isLocal || false,
|
|
||||||
is_explicit: track?.explicit || false,
|
|
||||||
track_number: track?.trackNumber || 0,
|
|
||||||
year: track?.album?.releaseYear || track?.album?.releaseDate || 'unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackPauseTrack(track) {
|
|
||||||
trackEvent('Pause Track', {
|
|
||||||
track_id: track?.id || 'unknown',
|
|
||||||
track_title: track?.title || 'Unknown',
|
|
||||||
artist_id: track?.artist?.id || track?.artists?.[0]?.id || 'unknown',
|
|
||||||
artist: track?.artist?.name || track?.artists?.[0]?.name || 'Unknown',
|
|
||||||
album_id: track?.album?.id || 'unknown',
|
|
||||||
album: track?.album?.title || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackSkipTrack(track, direction) {
|
|
||||||
trackEvent('Skip Track', {
|
|
||||||
track_id: track?.id || 'unknown',
|
|
||||||
track_title: track?.title || 'Unknown',
|
|
||||||
artist_id: track?.artist?.id || track?.artists?.[0]?.id || 'unknown',
|
|
||||||
artist: track?.artist?.name || track?.artists?.[0]?.name || 'Unknown',
|
|
||||||
album_id: track?.album?.id || 'unknown',
|
|
||||||
album: track?.album?.title || 'Unknown',
|
|
||||||
direction: direction,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackToggleShuffle(enabled) {
|
|
||||||
trackEvent('Toggle Shuffle', { enabled });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackToggleRepeat(mode) {
|
|
||||||
trackEvent('Toggle Repeat', { mode });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackTrackComplete(track, completionPercent) {
|
|
||||||
trackEvent('Track Complete', {
|
|
||||||
track_id: track?.id || 'unknown',
|
|
||||||
track_title: track?.title || 'Unknown',
|
|
||||||
artist_id: track?.artist?.id || track?.artists?.[0]?.id || 'unknown',
|
|
||||||
artist: track?.artist?.name || track?.artists?.[0]?.name || 'Unknown',
|
|
||||||
album_id: track?.album?.id || 'unknown',
|
|
||||||
album: track?.album?.title || 'Unknown',
|
|
||||||
duration: track?.duration || 0,
|
|
||||||
completion_percent: completionPercent || 100,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackSetVolume(level) {
|
|
||||||
// Only track volume changes at coarse intervals to avoid spam
|
|
||||||
const roundedLevel = Math.round(level * 10) / 10;
|
|
||||||
trackEvent('Set Volume', { level: roundedLevel });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackToggleMute(muted) {
|
|
||||||
trackEvent('Toggle Mute', { muted });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Track listening progress milestones (10%, 50%, 90%, 100%)
|
|
||||||
export function trackListeningProgress(track, percent) {
|
|
||||||
trackEvent('Listening Progress', {
|
|
||||||
track_id: track?.id || 'unknown',
|
|
||||||
track_title: track?.title || 'Unknown',
|
|
||||||
artist_id: track?.artist?.id || track?.artists?.[0]?.id || 'unknown',
|
|
||||||
percent: percent,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search Events
|
|
||||||
export function trackSearch(query, resultsCount) {
|
|
||||||
trackEvent('Search', {
|
|
||||||
query_length: query?.length || 0,
|
|
||||||
has_results: resultsCount > 0,
|
|
||||||
results_count: resultsCount,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackSearchTabChange(tab) {
|
|
||||||
trackEvent('Search Tab Change', { tab });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Navigation Events
|
|
||||||
export function trackNavigate(path, pageType) {
|
|
||||||
trackEvent('Navigate', {
|
|
||||||
path,
|
|
||||||
page_type: pageType,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackSidebarNavigation(item) {
|
|
||||||
trackEvent('Sidebar Navigation', { item });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Library Events
|
|
||||||
export function trackLikeTrack(track) {
|
|
||||||
trackEvent('Like Track', {
|
|
||||||
track_id: track?.id || 'unknown',
|
|
||||||
track_title: track?.title || 'Unknown',
|
|
||||||
artist_id: track?.artist?.id || track?.artists?.[0]?.id || 'unknown',
|
|
||||||
artist: track?.artist?.name || track?.artists?.[0]?.name || 'Unknown',
|
|
||||||
album_id: track?.album?.id || 'unknown',
|
|
||||||
album: track?.album?.title || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackUnlikeTrack(track) {
|
|
||||||
trackEvent('Unlike Track', {
|
|
||||||
track_id: track?.id || 'unknown',
|
|
||||||
track_title: track?.title || 'Unknown',
|
|
||||||
artist_id: track?.artist?.id || track?.artists?.[0]?.id || 'unknown',
|
|
||||||
artist: track?.artist?.name || track?.artists?.[0]?.name || 'Unknown',
|
|
||||||
album_id: track?.album?.id || 'unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackLikeAlbum(album) {
|
|
||||||
trackEvent('Like Album', {
|
|
||||||
album_title: album?.title || 'Unknown',
|
|
||||||
artist: album?.artist?.name || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackUnlikeAlbum(album) {
|
|
||||||
trackEvent('Unlike Album', {
|
|
||||||
album_title: album?.title || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackLikeArtist(artist) {
|
|
||||||
trackEvent('Like Artist', {
|
|
||||||
artist_name: artist?.name || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackUnlikeArtist(artist) {
|
|
||||||
trackEvent('Unlike Artist', {
|
|
||||||
artist_name: artist?.name || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackLikePlaylist(playlist) {
|
|
||||||
trackEvent('Like Playlist', {
|
|
||||||
playlist_name: playlist?.title || playlist?.name || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackUnlikePlaylist(playlist) {
|
|
||||||
trackEvent('Unlike Playlist', {
|
|
||||||
playlist_name: playlist?.title || playlist?.name || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Playlist Management Events
|
|
||||||
export function trackCreatePlaylist(playlist, source) {
|
|
||||||
trackEvent('Create Playlist', {
|
|
||||||
playlist_name: playlist?.name || 'Unknown',
|
|
||||||
track_count: playlist?.tracks?.length || 0,
|
|
||||||
is_public: playlist?.isPublic || false,
|
|
||||||
source: source || 'manual',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackEditPlaylist(playlist) {
|
|
||||||
trackEvent('Edit Playlist', {
|
|
||||||
playlist_name: playlist?.name || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackDeletePlaylist(playlistName) {
|
|
||||||
trackEvent('Delete Playlist', { playlist_name: playlistName });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackAddToPlaylist(track, playlist) {
|
|
||||||
trackEvent('Add to Playlist', {
|
|
||||||
track_title: track?.title || 'Unknown',
|
|
||||||
playlist_name: playlist?.name || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackRemoveFromPlaylist(track, playlist) {
|
|
||||||
trackEvent('Remove from Playlist', {
|
|
||||||
track_title: track?.title || 'Unknown',
|
|
||||||
playlist_name: playlist?.name || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackCreateFolder(folder) {
|
|
||||||
trackEvent('Create Folder', {
|
|
||||||
folder_name: folder?.name || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackDeleteFolder(folderName) {
|
|
||||||
trackEvent('Delete Folder', { folder_name: folderName });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Playback Actions
|
|
||||||
export function trackPlayAlbum(album, shuffle) {
|
|
||||||
trackEvent('Play Album', {
|
|
||||||
album_id: album?.id || 'unknown',
|
|
||||||
album_title: album?.title || 'Unknown',
|
|
||||||
artist_id: album?.artist?.id || 'unknown',
|
|
||||||
artist: album?.artist?.name || 'Unknown',
|
|
||||||
shuffle: shuffle || false,
|
|
||||||
track_count: album?.numberOfTracks || album?.tracks?.length || 0,
|
|
||||||
year: album?.releaseYear || album?.releaseDate || 'unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackPlayPlaylist(playlist, shuffle) {
|
|
||||||
trackEvent('Play Playlist', {
|
|
||||||
playlist_id: playlist?.id || 'unknown',
|
|
||||||
playlist_name: playlist?.title || playlist?.name || 'Unknown',
|
|
||||||
shuffle: shuffle || false,
|
|
||||||
track_count: playlist?.tracks?.length || 0,
|
|
||||||
is_public: playlist?.isPublic || false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackPlayArtistRadio(artist) {
|
|
||||||
trackEvent('Play Artist Radio', {
|
|
||||||
artist_id: artist?.id || 'unknown',
|
|
||||||
artist_name: artist?.name || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackShuffleLikedTracks(count) {
|
|
||||||
trackEvent('Shuffle Liked Tracks', { track_count: count });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Download Events
|
|
||||||
export function trackDownloadTrack(track, quality) {
|
|
||||||
trackEvent('Download Track', {
|
|
||||||
track_id: track?.id || 'unknown',
|
|
||||||
track_title: track?.title || 'Unknown',
|
|
||||||
artist_id: track?.artist?.id || track?.artists?.[0]?.id || 'unknown',
|
|
||||||
artist: track?.artist?.name || track?.artists?.[0]?.name || 'Unknown',
|
|
||||||
album_id: track?.album?.id || 'unknown',
|
|
||||||
quality: quality || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackDownloadAlbum(album, quality) {
|
|
||||||
trackEvent('Download Album', {
|
|
||||||
album_id: album?.id || 'unknown',
|
|
||||||
album_title: album?.title || 'Unknown',
|
|
||||||
artist_id: album?.artist?.id || 'unknown',
|
|
||||||
artist: album?.artist?.name || 'Unknown',
|
|
||||||
track_count: album?.numberOfTracks || album?.tracks?.length || 0,
|
|
||||||
quality: quality || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackDownloadPlaylist(playlist, quality) {
|
|
||||||
trackEvent('Download Playlist', {
|
|
||||||
playlist_id: playlist?.id || 'unknown',
|
|
||||||
playlist_name: playlist?.title || playlist?.name || 'Unknown',
|
|
||||||
track_count: playlist?.tracks?.length || 0,
|
|
||||||
quality: quality || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackDownloadLikedTracks(count, quality) {
|
|
||||||
trackEvent('Download Liked Tracks', {
|
|
||||||
track_count: count,
|
|
||||||
quality: quality || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackDownloadDiscography(artist, selection) {
|
|
||||||
trackEvent('Download Discography', {
|
|
||||||
artist_id: artist?.id || 'unknown',
|
|
||||||
artist_name: artist?.name || 'Unknown',
|
|
||||||
include_albums: selection?.includeAlbums || false,
|
|
||||||
include_eps: selection?.includeEPs || false,
|
|
||||||
include_singles: selection?.includeSingles || false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Queue Management
|
|
||||||
export function trackAddToQueue(track, position) {
|
|
||||||
trackEvent('Add to Queue', {
|
|
||||||
track_id: track?.id || 'unknown',
|
|
||||||
track_title: track?.title || 'Unknown',
|
|
||||||
artist_id: track?.artist?.id || track?.artists?.[0]?.id || 'unknown',
|
|
||||||
artist: track?.artist?.name || track?.artists?.[0]?.name || 'Unknown',
|
|
||||||
album_id: track?.album?.id || 'unknown',
|
|
||||||
position: position || 'end',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackPlayNext(track) {
|
|
||||||
trackEvent('Play Next', {
|
|
||||||
track_id: track?.id || 'unknown',
|
|
||||||
track_title: track?.title || 'Unknown',
|
|
||||||
artist_id: track?.artist?.id || track?.artists?.[0]?.id || 'unknown',
|
|
||||||
artist: track?.artist?.name || track?.artists?.[0]?.name || 'Unknown',
|
|
||||||
album_id: track?.album?.id || 'unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackClearQueue() {
|
|
||||||
trackEvent('Clear Queue');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackShuffleQueue() {
|
|
||||||
trackEvent('Shuffle Queue');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Context Menu Actions
|
|
||||||
export function trackContextMenuAction(action, itemType, item) {
|
|
||||||
trackEvent('Context Menu Action', {
|
|
||||||
action,
|
|
||||||
item_type: itemType,
|
|
||||||
item_name: item?.title || item?.name || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackBlockTrack(track) {
|
|
||||||
trackEvent('Block Track', {
|
|
||||||
track_id: track?.id || 'unknown',
|
|
||||||
track_title: track?.title || 'Unknown',
|
|
||||||
artist_id: track?.artist?.id || track?.artists?.[0]?.id || 'unknown',
|
|
||||||
artist: track?.artist?.name || track?.artists?.[0]?.name || 'Unknown',
|
|
||||||
album_id: track?.album?.id || 'unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackUnblockTrack(track) {
|
|
||||||
trackEvent('Unblock Track', {
|
|
||||||
track_id: track?.id || 'unknown',
|
|
||||||
track_title: track?.title || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackBlockAlbum(album) {
|
|
||||||
trackEvent('Block Album', {
|
|
||||||
album_id: album?.id || 'unknown',
|
|
||||||
album_title: album?.title || 'Unknown',
|
|
||||||
artist_id: album?.artist?.id || 'unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackUnblockAlbum(album) {
|
|
||||||
trackEvent('Unblock Album', {
|
|
||||||
album_id: album?.id || 'unknown',
|
|
||||||
album_title: album?.title || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackBlockArtist(artist) {
|
|
||||||
trackEvent('Block Artist', {
|
|
||||||
artist_id: artist?.id || 'unknown',
|
|
||||||
artist_name: artist?.name || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackUnblockArtist(artist) {
|
|
||||||
trackEvent('Unblock Artist', {
|
|
||||||
artist_id: artist?.id || 'unknown',
|
|
||||||
artist_name: artist?.name || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackCopyLink(type, id) {
|
|
||||||
trackEvent('Copy Link', { type, id });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackOpenInNewTab(type, id) {
|
|
||||||
trackEvent('Open in New Tab', { type, id });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lyrics Events
|
|
||||||
export function trackOpenLyrics(track) {
|
|
||||||
trackEvent('Open Lyrics', {
|
|
||||||
track_title: track?.title || 'Unknown',
|
|
||||||
artist: track?.artist?.name || track?.artists?.[0]?.name || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackCloseLyrics(track) {
|
|
||||||
trackEvent('Close Lyrics', {
|
|
||||||
track_title: track?.title || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fullscreen/Cover View Events
|
|
||||||
export function trackOpenFullscreenCover(track) {
|
|
||||||
trackEvent('Open Fullscreen Cover', {
|
|
||||||
track_title: track?.title || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackCloseFullscreenCover() {
|
|
||||||
trackEvent('Close Fullscreen Cover');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackToggleVisualizer(enabled) {
|
|
||||||
trackEvent('Toggle Visualizer', { enabled });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackToggleLyricsFullscreen(enabled) {
|
|
||||||
trackEvent('Toggle Lyrics Fullscreen', { enabled });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Settings Events
|
|
||||||
export function trackChangeSetting(setting, value) {
|
|
||||||
trackEvent('Change Setting', {
|
|
||||||
setting,
|
|
||||||
value: typeof value === 'object' ? JSON.stringify(value) : String(value),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackChangeTheme(theme) {
|
|
||||||
trackEvent('Change Theme', { theme });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackChangeQuality(type, quality) {
|
|
||||||
trackEvent('Change Quality', { type, quality });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackChangeVolume(volume) {
|
|
||||||
trackEvent('Change Volume', { volume: Math.round(volume * 100) });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackToggleScrobbler(service, enabled) {
|
|
||||||
trackEvent('Toggle Scrobbler', { service, enabled });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackConnectScrobbler(service) {
|
|
||||||
trackEvent('Connect Scrobbler', { service });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackDisconnectScrobbler(service) {
|
|
||||||
trackEvent('Disconnect Scrobbler', { service });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Local Files Events
|
|
||||||
export function trackSelectLocalFolder(fileCount) {
|
|
||||||
trackEvent('Select Local Folder', { file_count: fileCount });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackPlayLocalFile(track) {
|
|
||||||
trackEvent('Play Local File', {
|
|
||||||
track_title: track?.title || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackChangeLocalFolder() {
|
|
||||||
trackEvent('Change Local Folder');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Import/Export Events
|
|
||||||
export function trackImportCSV(playlistName, trackCount, missingCount) {
|
|
||||||
trackEvent('Import CSV', {
|
|
||||||
playlist_name: playlistName,
|
|
||||||
track_count: trackCount,
|
|
||||||
missing_count: missingCount,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackImportJSPF(playlistName, trackCount, missingCount, source) {
|
|
||||||
trackEvent('Import JSPF', {
|
|
||||||
playlist_name: playlistName,
|
|
||||||
track_count: trackCount,
|
|
||||||
missing_count: missingCount,
|
|
||||||
source: source || 'unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackImportXSPF(playlistName, trackCount, missingCount) {
|
|
||||||
trackEvent('Import XSPF', {
|
|
||||||
playlist_name: playlistName,
|
|
||||||
track_count: trackCount,
|
|
||||||
missing_count: missingCount,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackImportXML(playlistName, trackCount, missingCount) {
|
|
||||||
trackEvent('Import XML', {
|
|
||||||
playlist_name: playlistName,
|
|
||||||
track_count: trackCount,
|
|
||||||
missing_count: missingCount,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackImportM3U(playlistName, trackCount, missingCount) {
|
|
||||||
trackEvent('Import M3U', {
|
|
||||||
playlist_name: playlistName,
|
|
||||||
track_count: trackCount,
|
|
||||||
missing_count: missingCount,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sleep Timer Events
|
|
||||||
export function trackSetSleepTimer(minutes) {
|
|
||||||
trackEvent('Set Sleep Timer', { minutes });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackCancelSleepTimer() {
|
|
||||||
trackEvent('Cancel Sleep Timer');
|
|
||||||
}
|
|
||||||
|
|
||||||
// History Events
|
|
||||||
export function trackClearHistory() {
|
|
||||||
trackEvent('Clear History');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackClearRecent() {
|
|
||||||
trackEvent('Clear Recent');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Casting Events
|
|
||||||
export function trackStartCasting(deviceType) {
|
|
||||||
trackEvent('Start Casting', { device_type: deviceType });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackStopCasting() {
|
|
||||||
trackEvent('Stop Casting');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keyboard Shortcuts
|
|
||||||
export function trackKeyboardShortcut(key) {
|
|
||||||
trackEvent('Keyboard Shortcut', { key });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pinning Events
|
|
||||||
export function trackPinItem(type, item) {
|
|
||||||
trackEvent('Pin Item', {
|
|
||||||
type,
|
|
||||||
item_name: item?.title || item?.name || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackUnpinItem(type, item) {
|
|
||||||
trackEvent('Unpin Item', {
|
|
||||||
type,
|
|
||||||
item_name: item?.title || item?.name || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Side Panel Events
|
|
||||||
export function trackOpenSidePanel(panelType) {
|
|
||||||
trackEvent('Open Side Panel', { panel_type: panelType });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackCloseSidePanel() {
|
|
||||||
trackEvent('Close Side Panel');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Queue Panel Events
|
|
||||||
export function trackOpenQueue() {
|
|
||||||
trackEvent('Open Queue');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackCloseQueue() {
|
|
||||||
trackEvent('Close Queue');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mix Events
|
|
||||||
export function trackStartMix(sourceType, source) {
|
|
||||||
trackEvent('Start Mix', {
|
|
||||||
source_type: sourceType,
|
|
||||||
source_name: source?.title || source?.name || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackPlayMix(mixId) {
|
|
||||||
trackEvent('Play Mix', { mix_id: mixId });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search History Events
|
|
||||||
export function trackClearSearchHistory() {
|
|
||||||
trackEvent('Clear Search History');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackClickSearchHistory(query) {
|
|
||||||
trackEvent('Click Search History', { query_length: query?.length || 0 });
|
|
||||||
}
|
|
||||||
|
|
||||||
// PWA/Update Events
|
|
||||||
export function trackPwaInstall() {
|
|
||||||
trackEvent('PWA Install');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackPwaUpdate() {
|
|
||||||
trackEvent('PWA Update');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackDismissUpdate() {
|
|
||||||
trackEvent('Dismiss Update');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort Events
|
|
||||||
export function trackChangeSort(sortType) {
|
|
||||||
trackEvent('Change Sort', { sort_type: sortType });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Modal Events
|
|
||||||
export function trackOpenModal(modalName) {
|
|
||||||
trackEvent('Open Modal', { modal_name: modalName });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackCloseModal(modalName) {
|
|
||||||
trackEvent('Close Modal', { modal_name: modalName });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sharing Events
|
|
||||||
export function trackSharePlaylist(playlist, isPublic) {
|
|
||||||
trackEvent('Share Playlist', {
|
|
||||||
playlist_name: playlist?.name || 'Unknown',
|
|
||||||
is_public: isPublic,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Audio Effects Events
|
|
||||||
export function trackChangePlaybackSpeed(speed) {
|
|
||||||
trackEvent('Change Playback Speed', { speed });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackToggleReplayGain(mode) {
|
|
||||||
trackEvent('Toggle ReplayGain', { mode });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackChangeEqualizer(preset) {
|
|
||||||
trackEvent('Change Equalizer', { preset });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Waveform Events
|
|
||||||
export function trackToggleWaveform(enabled) {
|
|
||||||
trackEvent('Toggle Waveform', { enabled });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error Events
|
|
||||||
export function trackPlaybackError(errorType, track) {
|
|
||||||
trackEvent('Playback Error', {
|
|
||||||
error_type: errorType,
|
|
||||||
track_title: track?.title || 'Unknown',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackSearchError(query) {
|
|
||||||
trackEvent('Search Error', { query_length: query?.length || 0 });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackApiError(endpoint) {
|
|
||||||
trackEvent('API Error', { endpoint });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Feature Discovery Events
|
|
||||||
export function trackViewFeature(feature) {
|
|
||||||
trackEvent('View Feature', { feature });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackUseFeature(feature) {
|
|
||||||
trackEvent('Use Feature', { feature });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Session Events
|
|
||||||
export function trackSessionStart() {
|
|
||||||
trackEvent('Session Start', {
|
|
||||||
user_agent: navigator.userAgent,
|
|
||||||
screen_width: window.screen.width,
|
|
||||||
screen_height: window.screen.height,
|
|
||||||
language: navigator.language,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackSessionEnd(duration) {
|
|
||||||
trackEvent('Session End', { duration });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize analytics on page load
|
// Initialize analytics on page load
|
||||||
export function initAnalytics() {
|
export function initAnalytics() {
|
||||||
if (!isAnalyticsEnabled()) return;
|
if (!isAnalyticsEnabled()) return;
|
||||||
|
|
||||||
// Track initial page view
|
// Track initial page view
|
||||||
trackPageView(window.location.pathname);
|
trackPageView(window.location.pathname);
|
||||||
|
|
||||||
// Track session start
|
|
||||||
trackSessionStart();
|
|
||||||
|
|
||||||
// Track navigation changes
|
|
||||||
let lastPath = window.location.pathname;
|
|
||||||
setInterval(() => {
|
|
||||||
const currentPath = window.location.pathname;
|
|
||||||
if (currentPath !== lastPath) {
|
|
||||||
trackPageView(currentPath);
|
|
||||||
lastPath = currentPath;
|
|
||||||
}
|
|
||||||
}, 500);
|
|
||||||
|
|
||||||
// Track online/offline status
|
|
||||||
window.addEventListener('online', () => trackEvent('Go Online'));
|
|
||||||
window.addEventListener('offline', () => trackEvent('Go Offline'));
|
|
||||||
|
|
||||||
// Track visibility changes (app focus/blur)
|
|
||||||
document.addEventListener('visibilitychange', () => {
|
|
||||||
if (document.visibilityState === 'hidden') {
|
|
||||||
trackEvent('App Background');
|
|
||||||
} else {
|
|
||||||
trackEvent('App Foreground');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
78
js/app.js
78
js/app.js
|
|
@ -35,28 +35,7 @@ import { openEditProfile } from './profile.js';
|
||||||
import { ThemeStore } from './themeStore.js';
|
import { ThemeStore } from './themeStore.js';
|
||||||
import './commandPalette.js';
|
import './commandPalette.js';
|
||||||
import { initTracker } from './tracker.js';
|
import { initTracker } from './tracker.js';
|
||||||
import {
|
import { initAnalytics } from './analytics.js';
|
||||||
initAnalytics,
|
|
||||||
trackSidebarNavigation,
|
|
||||||
trackCreatePlaylist,
|
|
||||||
trackCreateFolder,
|
|
||||||
trackImportJSPF,
|
|
||||||
trackImportCSV,
|
|
||||||
trackImportXSPF,
|
|
||||||
trackImportXML,
|
|
||||||
trackImportM3U,
|
|
||||||
trackSelectLocalFolder,
|
|
||||||
trackChangeLocalFolder,
|
|
||||||
trackOpenModal,
|
|
||||||
trackCloseModal,
|
|
||||||
trackKeyboardShortcut,
|
|
||||||
trackPwaUpdate,
|
|
||||||
trackDismissUpdate,
|
|
||||||
trackOpenFullscreenCover,
|
|
||||||
trackCloseFullscreenCover,
|
|
||||||
trackOpenLyrics,
|
|
||||||
trackCloseLyrics,
|
|
||||||
} from './analytics.js';
|
|
||||||
import {
|
import {
|
||||||
parseCSV,
|
parseCSV,
|
||||||
parseJSPF,
|
parseJSPF,
|
||||||
|
|
@ -253,52 +232,40 @@ function initializeCasting(audioPlayer, castBtn) {
|
||||||
function initializeKeyboardShortcuts(player, _audioPlayer) {
|
function initializeKeyboardShortcuts(player, _audioPlayer) {
|
||||||
const keyActionMap = {
|
const keyActionMap = {
|
||||||
playPause: () => {
|
playPause: () => {
|
||||||
trackKeyboardShortcut('Space');
|
|
||||||
player.handlePlayPause();
|
player.handlePlayPause();
|
||||||
},
|
},
|
||||||
seekForward: () => {
|
seekForward: () => {
|
||||||
trackKeyboardShortcut('Right');
|
|
||||||
player.seekForward(10);
|
player.seekForward(10);
|
||||||
},
|
},
|
||||||
seekBackward: () => {
|
seekBackward: () => {
|
||||||
trackKeyboardShortcut('Left');
|
|
||||||
player.seekBackward(10);
|
player.seekBackward(10);
|
||||||
},
|
},
|
||||||
nextTrack: () => {
|
nextTrack: () => {
|
||||||
trackKeyboardShortcut('Shift+Right');
|
|
||||||
player.playNext();
|
player.playNext();
|
||||||
},
|
},
|
||||||
previousTrack: () => {
|
previousTrack: () => {
|
||||||
trackKeyboardShortcut('Shift+Left');
|
|
||||||
player.playPrev();
|
player.playPrev();
|
||||||
},
|
},
|
||||||
volumeUp: () => {
|
volumeUp: () => {
|
||||||
trackKeyboardShortcut('Up');
|
|
||||||
player.setVolume(player.userVolume + 0.1);
|
player.setVolume(player.userVolume + 0.1);
|
||||||
},
|
},
|
||||||
volumeDown: () => {
|
volumeDown: () => {
|
||||||
trackKeyboardShortcut('Down');
|
|
||||||
player.setVolume(player.userVolume - 0.1);
|
player.setVolume(player.userVolume - 0.1);
|
||||||
},
|
},
|
||||||
mute: () => {
|
mute: () => {
|
||||||
trackKeyboardShortcut('M');
|
|
||||||
const el = player.activeElement;
|
const el = player.activeElement;
|
||||||
el.muted = !el.muted;
|
el.muted = !el.muted;
|
||||||
},
|
},
|
||||||
shuffle: () => {
|
shuffle: () => {
|
||||||
trackKeyboardShortcut('S');
|
|
||||||
document.getElementById('shuffle-btn')?.click();
|
document.getElementById('shuffle-btn')?.click();
|
||||||
},
|
},
|
||||||
repeat: () => {
|
repeat: () => {
|
||||||
trackKeyboardShortcut('R');
|
|
||||||
document.getElementById('repeat-btn')?.click();
|
document.getElementById('repeat-btn')?.click();
|
||||||
},
|
},
|
||||||
queue: () => {
|
queue: () => {
|
||||||
trackKeyboardShortcut('Q');
|
|
||||||
document.getElementById('queue-btn')?.click();
|
document.getElementById('queue-btn')?.click();
|
||||||
},
|
},
|
||||||
lyrics: () => {
|
lyrics: () => {
|
||||||
trackKeyboardShortcut('L');
|
|
||||||
const overlay = document.getElementById('fullscreen-cover-overlay');
|
const overlay = document.getElementById('fullscreen-cover-overlay');
|
||||||
const isFullscreenOpen = overlay && getComputedStyle(overlay).display !== 'none';
|
const isFullscreenOpen = overlay && getComputedStyle(overlay).display !== 'none';
|
||||||
|
|
||||||
|
|
@ -309,29 +276,24 @@ function initializeKeyboardShortcuts(player, _audioPlayer) {
|
||||||
document.getElementById('toggle-lyrics-btn')?.click();
|
document.getElementById('toggle-lyrics-btn')?.click();
|
||||||
},
|
},
|
||||||
search: () => {
|
search: () => {
|
||||||
trackKeyboardShortcut('/');
|
|
||||||
document.getElementById('search-input')?.focus();
|
document.getElementById('search-input')?.focus();
|
||||||
},
|
},
|
||||||
escape: () => {
|
escape: () => {
|
||||||
trackKeyboardShortcut('Escape');
|
|
||||||
document.getElementById('search-input')?.blur();
|
document.getElementById('search-input')?.blur();
|
||||||
sidePanelManager.close();
|
sidePanelManager.close();
|
||||||
clearLyricsPanelSync(player.activeElement, sidePanelManager.panel);
|
clearLyricsPanelSync(player.activeElement, sidePanelManager.panel);
|
||||||
},
|
},
|
||||||
visualizerNext: () => {
|
visualizerNext: () => {
|
||||||
trackKeyboardShortcut('VisualizerNext');
|
|
||||||
if (UIRenderer.instance.visualizer?.presets?.['butterchurn']) {
|
if (UIRenderer.instance.visualizer?.presets?.['butterchurn']) {
|
||||||
UIRenderer.instance.visualizer.presets['butterchurn'].nextPreset();
|
UIRenderer.instance.visualizer.presets['butterchurn'].nextPreset();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
visualizerPrev: () => {
|
visualizerPrev: () => {
|
||||||
trackKeyboardShortcut('VisualizerPrev');
|
|
||||||
if (UIRenderer.instance.visualizer?.presets?.['butterchurn']) {
|
if (UIRenderer.instance.visualizer?.presets?.['butterchurn']) {
|
||||||
UIRenderer.instance.visualizer.presets['butterchurn'].prevPreset();
|
UIRenderer.instance.visualizer.presets['butterchurn'].prevPreset();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
visualizerCycle: () => {
|
visualizerCycle: () => {
|
||||||
trackKeyboardShortcut('VisualizerCycle');
|
|
||||||
if (UIRenderer.instance.visualizer?.presets?.['butterchurn']) {
|
if (UIRenderer.instance.visualizer?.presets?.['butterchurn']) {
|
||||||
UIRenderer.instance.visualizer.presets['butterchurn'].toggleCycle();
|
UIRenderer.instance.visualizer.presets['butterchurn'].toggleCycle();
|
||||||
}
|
}
|
||||||
|
|
@ -694,7 +656,6 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
const href = link.getAttribute('href');
|
const href = link.getAttribute('href');
|
||||||
if (href && !href.startsWith('http')) {
|
if (href && !href.startsWith('http')) {
|
||||||
const item = link.querySelector('span')?.textContent || href;
|
const item = link.querySelector('span')?.textContent || href;
|
||||||
trackSidebarNavigation(item);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -729,18 +690,10 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
|
|
||||||
if (mode === 'lyrics') {
|
if (mode === 'lyrics') {
|
||||||
const isActive = sidePanelManager.isActive('lyrics');
|
const isActive = sidePanelManager.isActive('lyrics');
|
||||||
|
|
||||||
if (isActive) {
|
|
||||||
trackCloseLyrics(Player.instance.currentTrack);
|
|
||||||
} else {
|
|
||||||
trackOpenLyrics(Player.instance.currentTrack);
|
|
||||||
}
|
|
||||||
} else if (mode === 'cover') {
|
} else if (mode === 'cover') {
|
||||||
const overlay = document.getElementById('fullscreen-cover-overlay');
|
const overlay = document.getElementById('fullscreen-cover-overlay');
|
||||||
if (overlay && overlay.style.display === 'flex') {
|
if (overlay && overlay.style.display === 'flex') {
|
||||||
trackCloseFullscreenCover();
|
|
||||||
} else {
|
} else {
|
||||||
trackOpenFullscreenCover(Player.instance.currentTrack);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -781,7 +734,6 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('close-fullscreen-cover-btn')?.addEventListener('click', async () => {
|
document.getElementById('close-fullscreen-cover-btn')?.addEventListener('click', async () => {
|
||||||
trackCloseFullscreenCover();
|
|
||||||
await closeFullscreenOverlay();
|
await closeFullscreenOverlay();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -1332,7 +1284,6 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.target.closest('#create-playlist-btn') || e.target.closest('#library-create-playlist-card')) {
|
if (e.target.closest('#create-playlist-btn') || e.target.closest('#library-create-playlist-card')) {
|
||||||
trackOpenModal('Create Playlist');
|
|
||||||
const modal = document.getElementById('playlist-modal');
|
const modal = document.getElementById('playlist-modal');
|
||||||
document.getElementById('playlist-modal-title').textContent = 'Create Playlist';
|
document.getElementById('playlist-modal-title').textContent = 'Create Playlist';
|
||||||
document.getElementById('playlist-name-input').value = '';
|
document.getElementById('playlist-name-input').value = '';
|
||||||
|
|
@ -1386,7 +1337,6 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.target.closest('#create-folder-btn') || e.target.closest('#library-create-folder-card')) {
|
if (e.target.closest('#create-folder-btn') || e.target.closest('#library-create-folder-card')) {
|
||||||
trackOpenModal('Create Folder');
|
|
||||||
const modal = document.getElementById('folder-modal');
|
const modal = document.getElementById('folder-modal');
|
||||||
document.getElementById('folder-name-input').value = '';
|
document.getElementById('folder-name-input').value = '';
|
||||||
document.getElementById('folder-cover-input').value = '';
|
document.getElementById('folder-cover-input').value = '';
|
||||||
|
|
@ -1400,11 +1350,9 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
|
|
||||||
if (name) {
|
if (name) {
|
||||||
const folder = await db.createFolder(name, cover);
|
const folder = await db.createFolder(name, cover);
|
||||||
trackCreateFolder(folder);
|
|
||||||
await syncManager.syncUserFolder(folder, 'create');
|
await syncManager.syncUserFolder(folder, 'create');
|
||||||
UIRenderer.instance.renderLibraryPage();
|
UIRenderer.instance.renderLibraryPage();
|
||||||
document.getElementById('folder-modal').classList.remove('active');
|
document.getElementById('folder-modal').classList.remove('active');
|
||||||
trackCloseModal('Create Folder');
|
|
||||||
} else {
|
} else {
|
||||||
showNotification('Please enter a folder name.');
|
showNotification('Please enter a folder name.');
|
||||||
}
|
}
|
||||||
|
|
@ -1593,7 +1541,6 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Imported ${tracks.length} tracks from YouTube`);
|
console.log(`Imported ${tracks.length} tracks from YouTube`);
|
||||||
trackImportCSV(name || 'Untitled', tracks.length, missingTracks.length);
|
|
||||||
|
|
||||||
if (missingTracks.length > 0) {
|
if (missingTracks.length > 0) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|
@ -1673,12 +1620,6 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
jspfPlaylist?.creator ||
|
jspfPlaylist?.creator ||
|
||||||
jspfPlaylist?.extension?.['https://musicbrainz.org/doc/jspf#playlist']?.creator ||
|
jspfPlaylist?.extension?.['https://musicbrainz.org/doc/jspf#playlist']?.creator ||
|
||||||
'unknown';
|
'unknown';
|
||||||
trackImportJSPF(
|
|
||||||
name || jspfPlaylist?.title || 'Untitled',
|
|
||||||
tracks.length,
|
|
||||||
missingTracks.length,
|
|
||||||
jspfCreator
|
|
||||||
);
|
|
||||||
|
|
||||||
if (missingTracks.length > 0) {
|
if (missingTracks.length > 0) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|
@ -1792,8 +1733,6 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
}
|
}
|
||||||
console.log(`Imported ${tracks.length} tracks from CSV`);
|
console.log(`Imported ${tracks.length} tracks from CSV`);
|
||||||
|
|
||||||
trackImportCSV(name || 'Untitled', tracks.length, missingTracks.length);
|
|
||||||
|
|
||||||
if (missingTracks.length > 0) {
|
if (missingTracks.length > 0) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
showMissingTracksNotification(missingTracks, name || 'Untitled');
|
showMissingTracksNotification(missingTracks, name || 'Untitled');
|
||||||
|
|
@ -1851,8 +1790,6 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
}
|
}
|
||||||
console.log(`Imported ${tracks.length} tracks from XSPF`);
|
console.log(`Imported ${tracks.length} tracks from XSPF`);
|
||||||
|
|
||||||
trackImportXSPF(name || 'Untitled', tracks.length, missingTracks.length);
|
|
||||||
|
|
||||||
if (missingTracks.length > 0) {
|
if (missingTracks.length > 0) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
showMissingTracksNotification(missingTracks, name || 'Untitled');
|
showMissingTracksNotification(missingTracks, name || 'Untitled');
|
||||||
|
|
@ -1910,8 +1847,6 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
}
|
}
|
||||||
console.log(`Imported ${tracks.length} tracks from XML`);
|
console.log(`Imported ${tracks.length} tracks from XML`);
|
||||||
|
|
||||||
trackImportXML(name || 'Untitled', tracks.length, missingTracks.length);
|
|
||||||
|
|
||||||
if (missingTracks.length > 0) {
|
if (missingTracks.length > 0) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
showMissingTracksNotification(missingTracks, name || 'Untitled');
|
showMissingTracksNotification(missingTracks, name || 'Untitled');
|
||||||
|
|
@ -1969,8 +1904,6 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
}
|
}
|
||||||
console.log(`Imported ${tracks.length} tracks from M3U`);
|
console.log(`Imported ${tracks.length} tracks from M3U`);
|
||||||
|
|
||||||
trackImportM3U(name || 'Untitled', tracks.length, missingTracks.length);
|
|
||||||
|
|
||||||
if (missingTracks.length > 0) {
|
if (missingTracks.length > 0) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
showMissingTracksNotification(missingTracks, name || 'Untitled');
|
showMissingTracksNotification(missingTracks, name || 'Untitled');
|
||||||
|
|
@ -2002,10 +1935,8 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
// Update DB again with isPublic flag
|
// Update DB again with isPublic flag
|
||||||
await db.performTransaction('user_playlists', 'readwrite', (store) => store.put(playlist));
|
await db.performTransaction('user_playlists', 'readwrite', (store) => store.put(playlist));
|
||||||
await syncManager.syncUserPlaylist(playlist, 'create');
|
await syncManager.syncUserPlaylist(playlist, 'create');
|
||||||
trackCreatePlaylist(playlist, importSource);
|
|
||||||
UIRenderer.instance.renderLibraryPage();
|
UIRenderer.instance.renderLibraryPage();
|
||||||
modal.classList.remove('active');
|
modal.classList.remove('active');
|
||||||
trackCloseModal('Create Playlist');
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -2507,9 +2438,6 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
await db.saveSetting('local_folder_handle', handle);
|
await db.saveSetting('local_folder_handle', handle);
|
||||||
if (isChange) {
|
|
||||||
trackChangeLocalFolder();
|
|
||||||
}
|
|
||||||
|
|
||||||
const btn = document.getElementById('select-local-folder-btn');
|
const btn = document.getElementById('select-local-folder-btn');
|
||||||
const btnText = document.getElementById('select-local-folder-text');
|
const btnText = document.getElementById('select-local-folder-text');
|
||||||
|
|
@ -2520,7 +2448,6 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const tracks = scanLocalMediaFolder(true);
|
const tracks = scanLocalMediaFolder(true);
|
||||||
trackSelectLocalFolder(tracks?.length ?? 0);
|
|
||||||
UIRenderer.instance.renderLibraryPage();
|
UIRenderer.instance.renderLibraryPage();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.name !== 'AbortError') {
|
if (err.name !== 'AbortError') {
|
||||||
|
|
@ -2707,12 +2634,10 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
onNeedRefresh() {
|
onNeedRefresh() {
|
||||||
if (pwaUpdateSettings.isAutoUpdateEnabled()) {
|
if (pwaUpdateSettings.isAutoUpdateEnabled()) {
|
||||||
// Auto-update: immediately activate the new service worker
|
// Auto-update: immediately activate the new service worker
|
||||||
trackPwaUpdate();
|
|
||||||
updateSW(true);
|
updateSW(true);
|
||||||
} else {
|
} else {
|
||||||
// Show notification with Update button and dismiss option
|
// Show notification with Update button and dismiss option
|
||||||
showUpdateNotification(() => {
|
showUpdateNotification(() => {
|
||||||
trackPwaUpdate();
|
|
||||||
updateSW(true);
|
updateSW(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -2955,7 +2880,6 @@ function showUpdateNotification(updateCallback) {
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('dismiss-update-btn').addEventListener('click', () => {
|
document.getElementById('dismiss-update-btn').addEventListener('click', () => {
|
||||||
trackDismissUpdate();
|
|
||||||
notification.remove();
|
notification.remove();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
74
js/events.js
74
js/events.js
|
|
@ -23,37 +23,6 @@ import { syncManager } from './accounts/pocketbase.js';
|
||||||
import { waveformGenerator } from './waveform.js';
|
import { waveformGenerator } from './waveform.js';
|
||||||
import { audioContextManager } from './audio-context.js';
|
import { audioContextManager } from './audio-context.js';
|
||||||
import { hapticLongPress, hapticMedium, hapticLight } from './haptics.js';
|
import { hapticLongPress, hapticMedium, hapticLight } from './haptics.js';
|
||||||
import {
|
|
||||||
trackPlayTrack,
|
|
||||||
trackPauseTrack,
|
|
||||||
trackSkipTrack,
|
|
||||||
trackToggleShuffle,
|
|
||||||
trackToggleRepeat,
|
|
||||||
trackAddToQueue,
|
|
||||||
trackPlayNext,
|
|
||||||
trackLikeTrack,
|
|
||||||
trackUnlikeTrack,
|
|
||||||
trackLikeAlbum,
|
|
||||||
trackUnlikeAlbum,
|
|
||||||
trackLikeArtist,
|
|
||||||
trackUnlikeArtist,
|
|
||||||
trackLikePlaylist,
|
|
||||||
trackUnlikePlaylist,
|
|
||||||
trackDownloadTrack,
|
|
||||||
trackContextMenuAction,
|
|
||||||
trackBlockTrack,
|
|
||||||
trackUnblockTrack,
|
|
||||||
trackBlockAlbum,
|
|
||||||
trackUnblockAlbum,
|
|
||||||
trackBlockArtist,
|
|
||||||
trackUnblockArtist,
|
|
||||||
trackCopyLink,
|
|
||||||
trackOpenInNewTab,
|
|
||||||
trackSetSleepTimer,
|
|
||||||
trackCancelSleepTimer,
|
|
||||||
trackStartMix,
|
|
||||||
trackEvent,
|
|
||||||
} from './analytics.js';
|
|
||||||
import { SVG_BIN, SVG_MUTE, SVG_PAUSE, SVG_PLAY, SVG_VOLUME, SVG_CHECKBOX, SVG_CHECKBOX_CHECKED } from './icons.js';
|
import { SVG_BIN, SVG_MUTE, SVG_PAUSE, SVG_PLAY, SVG_VOLUME, SVG_CHECKBOX, SVG_CHECKBOX_CHECKED } from './icons.js';
|
||||||
import { partyManager } from './listening-party.js';
|
import { partyManager } from './listening-party.js';
|
||||||
import { MusicAPI } from './music-api.js';
|
import { MusicAPI } from './music-api.js';
|
||||||
|
|
@ -435,9 +404,6 @@ export function initializePlayerEvents(player, audioPlayer, scrobbler, ui) {
|
||||||
await audioContextManager.resume();
|
await audioContextManager.resume();
|
||||||
|
|
||||||
if (player.currentTrack) {
|
if (player.currentTrack) {
|
||||||
// Track play event
|
|
||||||
trackPlayTrack(player.currentTrack);
|
|
||||||
|
|
||||||
// Scrobble
|
// Scrobble
|
||||||
if (scrobbler.isAuthenticated()) {
|
if (scrobbler.isAuthenticated()) {
|
||||||
scrobbler.updateNowPlaying(player.currentTrack);
|
scrobbler.updateNowPlaying(player.currentTrack);
|
||||||
|
|
@ -460,9 +426,6 @@ export function initializePlayerEvents(player, audioPlayer, scrobbler, ui) {
|
||||||
|
|
||||||
element.addEventListener('pause', () => {
|
element.addEventListener('pause', () => {
|
||||||
if (player.activeElement !== element) return;
|
if (player.activeElement !== element) return;
|
||||||
if (player.currentTrack) {
|
|
||||||
trackPauseTrack(player.currentTrack);
|
|
||||||
}
|
|
||||||
playPauseBtn.innerHTML = SVG_PLAY(20);
|
playPauseBtn.innerHTML = SVG_PLAY(20);
|
||||||
player.updateMediaSessionPlaybackState();
|
player.updateMediaSessionPlaybackState();
|
||||||
player.updateMediaSessionPositionState();
|
player.updateMediaSessionPositionState();
|
||||||
|
|
@ -566,19 +529,16 @@ export function initializePlayerEvents(player, audioPlayer, scrobbler, ui) {
|
||||||
});
|
});
|
||||||
nextBtn.addEventListener('click', async () => {
|
nextBtn.addEventListener('click', async () => {
|
||||||
await hapticMedium();
|
await hapticMedium();
|
||||||
trackSkipTrack(player.currentTrack, 'next');
|
|
||||||
player.playNext();
|
player.playNext();
|
||||||
});
|
});
|
||||||
prevBtn.addEventListener('click', async () => {
|
prevBtn.addEventListener('click', async () => {
|
||||||
await hapticMedium();
|
await hapticMedium();
|
||||||
trackSkipTrack(player.currentTrack, 'previous');
|
|
||||||
player.playPrev();
|
player.playPrev();
|
||||||
});
|
});
|
||||||
|
|
||||||
shuffleBtn.addEventListener('click', async () => {
|
shuffleBtn.addEventListener('click', async () => {
|
||||||
await hapticLight();
|
await hapticLight();
|
||||||
player.toggleShuffle();
|
player.toggleShuffle();
|
||||||
trackToggleShuffle(player.shuffleActive);
|
|
||||||
shuffleBtn.classList.toggle('active', player.shuffleActive);
|
shuffleBtn.classList.toggle('active', player.shuffleActive);
|
||||||
if (window.renderQueueFunction) await window.renderQueueFunction();
|
if (window.renderQueueFunction) await window.renderQueueFunction();
|
||||||
});
|
});
|
||||||
|
|
@ -586,7 +546,6 @@ export function initializePlayerEvents(player, audioPlayer, scrobbler, ui) {
|
||||||
repeatBtn.addEventListener('click', async () => {
|
repeatBtn.addEventListener('click', async () => {
|
||||||
await hapticLight();
|
await hapticLight();
|
||||||
const mode = await player.toggleRepeat();
|
const mode = await player.toggleRepeat();
|
||||||
trackToggleRepeat(mode === REPEAT_MODE.OFF ? 'off' : mode === REPEAT_MODE.ALL ? 'all' : 'one');
|
|
||||||
repeatBtn.classList.toggle('active', mode !== REPEAT_MODE.OFF);
|
repeatBtn.classList.toggle('active', mode !== REPEAT_MODE.OFF);
|
||||||
repeatBtn.classList.toggle('repeat-one', mode === REPEAT_MODE.ONE);
|
repeatBtn.classList.toggle('repeat-one', mode === REPEAT_MODE.ONE);
|
||||||
repeatBtn.title =
|
repeatBtn.title =
|
||||||
|
|
@ -604,7 +563,6 @@ export function initializePlayerEvents(player, audioPlayer, scrobbler, ui) {
|
||||||
sleepTimerBtnDesktop.addEventListener('click', () => {
|
sleepTimerBtnDesktop.addEventListener('click', () => {
|
||||||
if (player.isSleepTimerActive()) {
|
if (player.isSleepTimerActive()) {
|
||||||
player.clearSleepTimer();
|
player.clearSleepTimer();
|
||||||
trackCancelSleepTimer();
|
|
||||||
showNotification('Sleep timer cancelled');
|
showNotification('Sleep timer cancelled');
|
||||||
} else {
|
} else {
|
||||||
showSleepTimerModal(player);
|
showSleepTimerModal(player);
|
||||||
|
|
@ -617,7 +575,6 @@ export function initializePlayerEvents(player, audioPlayer, scrobbler, ui) {
|
||||||
sleepTimerBtnMobile.addEventListener('click', () => {
|
sleepTimerBtnMobile.addEventListener('click', () => {
|
||||||
if (player.isSleepTimerActive()) {
|
if (player.isSleepTimerActive()) {
|
||||||
player.clearSleepTimer();
|
player.clearSleepTimer();
|
||||||
trackCancelSleepTimer();
|
|
||||||
showNotification('Sleep timer cancelled');
|
showNotification('Sleep timer cancelled');
|
||||||
} else {
|
} else {
|
||||||
showSleepTimerModal(player);
|
showSleepTimerModal(player);
|
||||||
|
|
@ -1349,12 +1306,10 @@ export async function handleTrackAction(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action === 'add-to-queue') {
|
if (action === 'add-to-queue') {
|
||||||
trackAddToQueue(item, 'end');
|
|
||||||
player.addToQueue(item);
|
player.addToQueue(item);
|
||||||
if (window.renderQueueFunction) await window.renderQueueFunction();
|
if (window.renderQueueFunction) await window.renderQueueFunction();
|
||||||
showNotification(`Added to queue: ${item.title}`);
|
showNotification(`Added to queue: ${item.title}`);
|
||||||
} else if (action === 'play-next') {
|
} else if (action === 'play-next') {
|
||||||
trackPlayNext(item);
|
|
||||||
player.addNextToQueue(item);
|
player.addNextToQueue(item);
|
||||||
if (window.renderQueueFunction) await window.renderQueueFunction();
|
if (window.renderQueueFunction) await window.renderQueueFunction();
|
||||||
showNotification(`Playing next: ${item.title}`);
|
showNotification(`Playing next: ${item.title}`);
|
||||||
|
|
@ -1363,34 +1318,17 @@ export async function handleTrackAction(
|
||||||
player.playAtIndex(0);
|
player.playAtIndex(0);
|
||||||
showNotification(`Playing track: ${item.title}`);
|
showNotification(`Playing track: ${item.title}`);
|
||||||
} else if (action === 'start-mix') {
|
} else if (action === 'start-mix') {
|
||||||
trackStartMix(type, item);
|
|
||||||
if (item.mixes?.TRACK_MIX) {
|
if (item.mixes?.TRACK_MIX) {
|
||||||
navigate(`/mix/${item.mixes.TRACK_MIX}`);
|
navigate(`/mix/${item.mixes.TRACK_MIX}`);
|
||||||
} else {
|
} else {
|
||||||
showNotification('No mix available for this track');
|
showNotification('No mix available for this track');
|
||||||
}
|
}
|
||||||
} else if (action === 'download') {
|
} else if (action === 'download') {
|
||||||
trackDownloadTrack(item, downloadQualitySettings.getQuality());
|
|
||||||
await downloadTrackWithMetadata(item, downloadQualitySettings.getQuality(), api, lyricsManager);
|
await downloadTrackWithMetadata(item, downloadQualitySettings.getQuality(), api, lyricsManager);
|
||||||
} else if (action === 'toggle-like') {
|
} else if (action === 'toggle-like') {
|
||||||
const added = await db.toggleFavorite(type, item);
|
const added = await db.toggleFavorite(type, item);
|
||||||
await syncManager.syncLibraryItem(type, item, added);
|
await syncManager.syncLibraryItem(type, item, added);
|
||||||
|
|
||||||
// Track like/unlike
|
|
||||||
if (added) {
|
|
||||||
if (type === 'track') trackLikeTrack(item);
|
|
||||||
else if (type === 'video') trackEvent('Like Video', { title: item.title });
|
|
||||||
else if (type === 'album') trackLikeAlbum(item);
|
|
||||||
else if (type === 'artist') trackLikeArtist(item);
|
|
||||||
else if (type === 'playlist' || type === 'user-playlist') trackLikePlaylist(item);
|
|
||||||
} else {
|
|
||||||
if (type === 'track') trackUnlikeTrack(item);
|
|
||||||
else if (type === 'video') trackEvent('Unlike Video', { title: item.title });
|
|
||||||
else if (type === 'album') trackUnlikeAlbum(item);
|
|
||||||
else if (type === 'artist') trackUnlikeArtist(item);
|
|
||||||
else if (type === 'playlist' || type === 'user-playlist') trackUnlikePlaylist(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (added && type === 'track' && scrobbler) {
|
if (added && type === 'track' && scrobbler) {
|
||||||
if (lastFMStorage.isEnabled() && lastFMStorage.shouldLoveOnLike()) {
|
if (lastFMStorage.isEnabled() && lastFMStorage.shouldLoveOnLike()) {
|
||||||
scrobbler.loveTrack(item);
|
scrobbler.loveTrack(item);
|
||||||
|
|
@ -1675,7 +1613,6 @@ export async function handleTrackAction(
|
||||||
const typeForUrl = type === 'user-playlist' ? 'userplaylist' : type;
|
const typeForUrl = type === 'user-playlist' ? 'userplaylist' : type;
|
||||||
const url = getShareUrl(storedHref ? storedHref : `/${typeForUrl}/${item.id || item.uuid}`);
|
const url = getShareUrl(storedHref ? storedHref : `/${typeForUrl}/${item.id || item.uuid}`);
|
||||||
|
|
||||||
trackCopyLink(type, item.id || item.uuid);
|
|
||||||
await navigator.clipboard
|
await navigator.clipboard
|
||||||
.writeText(url)
|
.writeText(url)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|
@ -1690,7 +1627,6 @@ export async function handleTrackAction(
|
||||||
? `${window.location.origin}${storedHref}`
|
? `${window.location.origin}${storedHref}`
|
||||||
: `${window.location.origin}/${type}/${item.id || item.uuid}`;
|
: `${window.location.origin}/${type}/${item.id || item.uuid}`;
|
||||||
|
|
||||||
trackOpenInNewTab(type, item.id || item.uuid);
|
|
||||||
window.open(url, '_blank');
|
window.open(url, '_blank');
|
||||||
} else if (action === 'open-in-harmony') {
|
} else if (action === 'open-in-harmony') {
|
||||||
const albumId = item.id;
|
const albumId = item.id;
|
||||||
|
|
@ -1868,11 +1804,9 @@ export async function handleTrackAction(
|
||||||
const { contentBlockingSettings } = await import('./storage.js');
|
const { contentBlockingSettings } = await import('./storage.js');
|
||||||
if (contentBlockingSettings.isTrackBlocked(item.id)) {
|
if (contentBlockingSettings.isTrackBlocked(item.id)) {
|
||||||
contentBlockingSettings.unblockTrack(item.id);
|
contentBlockingSettings.unblockTrack(item.id);
|
||||||
trackUnblockTrack(item);
|
|
||||||
showNotification(`Unblocked track: ${item.title}`);
|
showNotification(`Unblocked track: ${item.title}`);
|
||||||
} else {
|
} else {
|
||||||
contentBlockingSettings.blockTrack(item);
|
contentBlockingSettings.blockTrack(item);
|
||||||
trackBlockTrack(item);
|
|
||||||
showNotification(`Blocked track: ${item.title}`);
|
showNotification(`Blocked track: ${item.title}`);
|
||||||
}
|
}
|
||||||
} else if (action === 'block-album') {
|
} else if (action === 'block-album') {
|
||||||
|
|
@ -1891,11 +1825,9 @@ export async function handleTrackAction(
|
||||||
|
|
||||||
if (contentBlockingSettings.isAlbumBlocked(albumId)) {
|
if (contentBlockingSettings.isAlbumBlocked(albumId)) {
|
||||||
contentBlockingSettings.unblockAlbum(albumId);
|
contentBlockingSettings.unblockAlbum(albumId);
|
||||||
trackUnblockAlbum(albumObj);
|
|
||||||
showNotification(`Unblocked album: ${albumTitle || 'Unknown Album'}`);
|
showNotification(`Unblocked album: ${albumTitle || 'Unknown Album'}`);
|
||||||
} else {
|
} else {
|
||||||
contentBlockingSettings.blockAlbum(albumObj);
|
contentBlockingSettings.blockAlbum(albumObj);
|
||||||
trackBlockAlbum(albumObj);
|
|
||||||
showNotification(`Blocked album: ${albumTitle || 'Unknown Album'}`);
|
showNotification(`Blocked album: ${albumTitle || 'Unknown Album'}`);
|
||||||
}
|
}
|
||||||
} else if (action === 'block-artist') {
|
} else if (action === 'block-artist') {
|
||||||
|
|
@ -1912,11 +1844,9 @@ export async function handleTrackAction(
|
||||||
|
|
||||||
if (contentBlockingSettings.isArtistBlocked(artistId)) {
|
if (contentBlockingSettings.isArtistBlocked(artistId)) {
|
||||||
contentBlockingSettings.unblockArtist(artistId);
|
contentBlockingSettings.unblockArtist(artistId);
|
||||||
trackUnblockArtist(artistObj);
|
|
||||||
showNotification(`Unblocked artist: ${artistName || 'Unknown Artist'}`);
|
showNotification(`Unblocked artist: ${artistName || 'Unknown Artist'}`);
|
||||||
} else {
|
} else {
|
||||||
contentBlockingSettings.blockArtist(artistObj);
|
contentBlockingSettings.blockArtist(artistObj);
|
||||||
trackBlockArtist(artistObj);
|
|
||||||
showNotification(`Blocked artist: ${artistName || 'Unknown Artist'}`);
|
showNotification(`Blocked artist: ${artistName || 'Unknown Artist'}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2494,7 +2424,6 @@ export function initializeTrackInteractions(player, api, mainContent, contextMen
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case 'play-next':
|
case 'play-next':
|
||||||
selectedTracks.forEach((t) => {
|
selectedTracks.forEach((t) => {
|
||||||
trackPlayNext(t);
|
|
||||||
player.addNextToQueue(t);
|
player.addNextToQueue(t);
|
||||||
});
|
});
|
||||||
if (window.renderQueueFunction) await window.renderQueueFunction();
|
if (window.renderQueueFunction) await window.renderQueueFunction();
|
||||||
|
|
@ -2536,8 +2465,6 @@ export function initializeTrackInteractions(player, api, mainContent, contextMen
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Track context menu action
|
|
||||||
trackContextMenuAction(action, type, track);
|
|
||||||
await handleTrackAction(action, track, player, api, lyricsManager, type, ui, scrobbler, target.dataset);
|
await handleTrackAction(action, track, player, api, lyricsManager, type, ui, scrobbler, target.dataset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2700,7 +2627,6 @@ function showSleepTimerModal(player) {
|
||||||
|
|
||||||
if (minutes) {
|
if (minutes) {
|
||||||
player.setSleepTimer(minutes);
|
player.setSleepTimer(minutes);
|
||||||
trackSetSleepTimer(minutes);
|
|
||||||
showNotification(`Sleep timer set for ${minutes} minute${minutes === 1 ? '' : 's'}`);
|
showNotification(`Sleep timer set for ${minutes} minute${minutes === 1 ? '' : 's'}`);
|
||||||
closeModal();
|
closeModal();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
import { trackCloseSidePanel, trackCloseQueue, trackCloseLyrics } from './analytics.js';
|
|
||||||
|
|
||||||
export class SidePanelManager {
|
export class SidePanelManager {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.panel = document.getElementById('side-panel');
|
this.panel = document.getElementById('side-panel');
|
||||||
|
|
@ -103,15 +101,9 @@ export class SidePanelManager {
|
||||||
close() {
|
close() {
|
||||||
// Track side panel close
|
// Track side panel close
|
||||||
if (this.currentView) {
|
if (this.currentView) {
|
||||||
trackCloseSidePanel();
|
if (this.currentView === 'lyrics') {
|
||||||
if (this.currentView === 'queue') {
|
|
||||||
trackCloseQueue();
|
|
||||||
} else if (this.currentView === 'lyrics') {
|
|
||||||
// Get current track from audio player context
|
// Get current track from audio player context
|
||||||
const audioPlayer = document.getElementById('audio-player');
|
const audioPlayer = document.getElementById('audio-player');
|
||||||
if (audioPlayer && audioPlayer._currentTrack) {
|
|
||||||
trackCloseLyrics(audioPlayer._currentTrack);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ import { downloadQualitySettings, contentBlockingSettings } from './storage.js';
|
||||||
import { db } from './db.js';
|
import { db } from './db.js';
|
||||||
import { syncManager } from './accounts/pocketbase.js';
|
import { syncManager } from './accounts/pocketbase.js';
|
||||||
import { showNotification, downloadTracks } from './downloads.js';
|
import { showNotification, downloadTracks } from './downloads.js';
|
||||||
import { trackSearchTabChange, trackOpenQueue } from './analytics.js';
|
|
||||||
import {
|
import {
|
||||||
SVG_CLOSE,
|
SVG_CLOSE,
|
||||||
SVG_BIN,
|
SVG_BIN,
|
||||||
|
|
@ -474,7 +473,6 @@ export function initializeUIInteractions(player, api, ui) {
|
||||||
};
|
};
|
||||||
|
|
||||||
const openQueuePanel = () => {
|
const openQueuePanel = () => {
|
||||||
trackOpenQueue();
|
|
||||||
sidePanelManager.open('queue', 'Queue', renderQueueControls, renderQueueContent);
|
sidePanelManager.open('queue', 'Queue', renderQueueControls, renderQueueContent);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|
@ -536,9 +534,6 @@ export function initializeUIInteractions(player, api, ui) {
|
||||||
const page = tab.closest('.page');
|
const page = tab.closest('.page');
|
||||||
if (!page) return;
|
if (!page) return;
|
||||||
|
|
||||||
// Track tab change
|
|
||||||
trackSearchTabChange(tab.dataset.tab);
|
|
||||||
|
|
||||||
page.querySelectorAll('.search-tab').forEach((t) => t.classList.remove('active'));
|
page.querySelectorAll('.search-tab').forEach((t) => t.classList.remove('active'));
|
||||||
page.querySelectorAll('.search-tab-content').forEach((c) => c.classList.remove('active'));
|
page.querySelectorAll('.search-tab-content').forEach((c) => c.classList.remove('active'));
|
||||||
|
|
||||||
|
|
|
||||||
3
js/ui.js
3
js/ui.js
|
|
@ -49,7 +49,6 @@ import {
|
||||||
createProjectCardHTML,
|
createProjectCardHTML,
|
||||||
createTrackFromSong,
|
createTrackFromSong,
|
||||||
} from './tracker.js';
|
} from './tracker.js';
|
||||||
import { trackSearch, trackChangeSort } from './analytics.js';
|
|
||||||
|
|
||||||
fontSettings.applyFont().catch(console.error);
|
fontSettings.applyFont().catch(console.error);
|
||||||
fontSettings.applyFontSize();
|
fontSettings.applyFontSize();
|
||||||
|
|
@ -3608,7 +3607,6 @@ export class UIRenderer {
|
||||||
|
|
||||||
// Track search with results
|
// Track search with results
|
||||||
const totalResults = finalTracks.length + finalArtists.length + finalAlbums.length + finalPlaylists.length;
|
const totalResults = finalTracks.length + finalArtists.length + finalAlbums.length + finalPlaylists.length;
|
||||||
trackSearch(query, totalResults);
|
|
||||||
|
|
||||||
if (finalTracks.length) {
|
if (finalTracks.length) {
|
||||||
await this.renderListWithTracks(tracksContainer, finalTracks, true, false, false, true);
|
await this.renderListWithTracks(tracksContainer, finalTracks, true, false, false, true);
|
||||||
|
|
@ -5674,7 +5672,6 @@ export class UIRenderer {
|
||||||
const handleSort = async (ev) => {
|
const handleSort = async (ev) => {
|
||||||
const li = ev.target.closest('li');
|
const li = ev.target.closest('li');
|
||||||
if (li && li.dataset.sort) {
|
if (li && li.dataset.sort) {
|
||||||
trackChangeSort(li.dataset.sort);
|
|
||||||
await onSort(li.dataset.sort);
|
await onSort(li.dataset.sort);
|
||||||
closeMenu();
|
closeMenu();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue