$(document).ready(function () { const player = new Player(userId); const largeImage = document.getElementById("largeImage"); const img = document.getElementById("image"); const canvas = document.createElement('canvas'); const $positionInfo = $('.position-info'); var startPos = null; var selectedTrack = null; var selectedPlaylistId = null; var selectedPlaylistTrack = null; var typingTimer; var doneTypingInterval = 2000; largeImage.crossOrigin = "Anonymous"; largeImage.onload = function () { try { const context = canvas.getContext('2d', { willReadFrequently: true }); const width = canvas.width = largeImage.width; const height = canvas.height = Math.round(largeImage.height * 0.7); const startY = Math.round((largeImage.height - height) / 2); context.drawImage(largeImage, 0, startY, width, height, 0, 0, width, height); getMainColorsFromImage(4) .then(colors => { let bg = $(".thumbnail-background"); bg.css({ "background": `linear-gradient(-132deg, ${colors[0]}, ${colors[1]}, ${colors[2]}, ${colors[3]})`, "width": "70%", "padding-bottom": `${largeImage.naturalHeight / largeImage.naturalWidth * 70}%`, }); bg.fadeIn(200); $("#largeImage").fadeIn(200); }) .catch(error => { return }); } catch (e) { } } img.onload = function () { try { $("#image").fadeIn(200); } catch (e) { } } function getMainColorsFromImage(numColors) { return new Promise((resolve, reject) => { const imageData = canvas.getContext('2d', { willReadFrequently: true }).getImageData(0, 0, canvas.width, canvas.height).data; const colorCount = {}; const threshold = 20; // adjust this value to change the threshold for black/white similarity const colorGap = 30; // adjust this value to change the minimum color difference between each main color for (let i = 0; i < imageData.length; i += 4) { const r = imageData[i]; const g = imageData[i + 1]; const b = imageData[i + 2]; const color = `rgb(${r}, ${g}, ${b})`; if (!colorCount[color]) { // Check if the color is too close to black or white const isBlackOrWhite = r < threshold || r > 255 - threshold || g < threshold || g > 255 - threshold || b < threshold || b > 255 - threshold; if (isBlackOrWhite) continue; // Check if the color is too similar to previous colors const prevColors = Object.keys(colorCount); const isTooSimilar = prevColors.some(prevColor => { const [pr, pg, pb] = prevColor.match(/\d+/g).map(Number); const diff = Math.sqrt(Math.pow(r - pr, 2) + Math.pow(g - pg, 2) + Math.pow(b - pb, 2)); return diff < colorGap; }); if (isTooSimilar) continue; colorCount[color] = 0; } colorCount[color]++; } const colors = Object.keys(colorCount).sort((color1, color2) => colorCount[color2] - colorCount[color1]).slice(0, numColors); resolve(colors); }); } $("#seek-bar").on('mousemove', function (e) { let position = e.pageX - $(this).offset().left; let duration = $(this).width(); let percentage = (position / duration) * 100; let time = player.msToReadableTime(percentage * player.currentTrack?.length / 100); $positionInfo.text(time).css({ left: e.pageX - $positionInfo.outerWidth() / 2, }); }); $('body').click(function (event) { let $target = $(event.target); if (!$target.closest(".search-container").length && !$target.is("#search-input") && $('#search-result-list').css("display") != 'none') { $("#search-result-list").fadeOut(200); } else if (!$target.closest(".users-bar").is('.users-bar') && !$target.closest("#users-btn").is('#users-btn') && $(".users-bar").hasClass("active")) { $(".users-bar").removeClass("active"); $("#users-btn").css({ "color": "" }); } else if ($target.closest(".action").is(".action") && $target.closest(".playlists-tracks").is(".playlists-tracks")) { selectedPlaylistTrack = $target.closest(".track").data("value"); const $contextMenu = $("#context-menu"); const menuHeight = $contextMenu.outerHeight(); const windowHeight = $(window).height(); const topPosition = event.pageY + 30; if (topPosition + menuHeight > windowHeight) { // If the menu would go out of the page, position it above the btn instead $contextMenu.css({ "left": `${event.pageX - 130}px`, "top": `${event.pageY - menuHeight - 30}px` }).fadeIn(200); } else { $contextMenu.css({ "left": `${event.pageX - 130}px`, "top": `${topPosition}px` }).fadeIn(200); } } else if ($target.closest(".playlists-tracks").is(".playlists-tracks") && $target.closest(".track").is(".track")) { const track_id = $target.closest(".track").data("value"); player.send({ "op": "addTracks", "tracks": [track_id] }) } else if ($target.closest(".playlist").is(".playlist")) { selectedPlaylistId = $target.closest(".playlist").data("value"); if ($target.closest(".action").is(".action")) { const $contextMenu = $("#playlist-context-menu") const menuHeight = $contextMenu.outerHeight(); const windowHeight = $(window).height(); const topPosition = event.pageY + 30; if (topPosition + menuHeight > windowHeight) { // If the menu would go out of the page, position it above the btn instead $contextMenu.css({ "left": `${event.pageX - 130}px`, "top": `${event.pageY - menuHeight - 30}px` }).fadeIn(200); } else { $contextMenu.css({ "left": `${event.pageX - 130}px`, "top": `${topPosition}px` }).fadeIn(200); } } else if ($target.closest(".play").is(".play")) { if (selectedPlaylistId in player.playlists) { if ("tracks" in player.playlists[selectedPlaylistId]) { if (player.playlists[selectedPlaylistId]['tracks'].length != 0) { player.send({ "op": "addTracks", "tracks": player.playlists[selectedPlaylistId]["tracks"] }); } } } } else { const $pTracks = $("#playlists-tracks"); if (selectedPlaylistId in player.playlists) { $pTracks.empty(); for (const track_id of player.playlists[selectedPlaylistId]["tracks"]) { const track = decode(track_id); let $trackDiv = $(`
${track.title}
${track.author}
${player.msToReadableTime(track.length)}