const socket = io.connect(window.location.href);
socket.on('connect', () => {
document.getElementById('loading_overlay').classList.remove('active');
});
let toastsWithId = {};
const toast = function (msg, icon = null, dismiss = true, id = null) {
if (toastsWithId[id]) {
let toastObj = toastsWithId[id];
let toastDOM = $(`div.toastify[toast_id=${id}]`);
if (msg) {
toastDOM.find('.toast-message').html(msg);
}
if (icon) {
if (icon == 'loading') icon = `
`;
else icon = `${icon}`;
toastDOM.find('.toast-icon').html(icon);
}
if (dismiss !== null && dismiss) {
setTimeout(function () {
toastObj.hideToast();
delete toastsWithId[id];
}, 3000);
}
} else {
if (icon == null) icon = '';
else if (icon == 'loading') icon = ``;
else icon = `${icon}`;
let toastObj = Toastify({
text: `${icon}${msg}`,
duration: dismiss ? 3000 : 0,
gravity: 'bottom',
position: 'left'
}).showToast();
if (id) {
toastsWithId[id] = toastObj;
$(toastObj.toastElement).attr('toast_id', id);
}
}
};
socket.on('toast', data => {
toast(data.msg, data.icon || null, data.dismiss !== undefined ? data.dismiss : true, data.id || null);
});
/* ===== Locals ===== */
const tabMinWidth = 250;
const tabMaxWidth = 500;
let cachedTabWidth = parseInt(localStorage.getItem('downloadTabWidth')) || 300;
let queueList = {};
let queue = [];
let queueComplete = [];
let tabContainerEl;
let listEl;
let dragHandlerEl;
function init() {
// Find download DOM elements
tabContainerEl = document.getElementById('download_tab_container');
listEl = document.getElementById('download_list');
dragHandlerEl = document.getElementById('download_tab_drag_handler');
// Check if download tab should be open
if ('true' === localStorage.getItem('downloadTabOpen')) {
tabContainerEl.classList.remove('tab_hidden');
setTabWidth(cachedTabWidth);
}
linkListeners();
}
function linkListeners() {
listEl.addEventListener('click', handleListClick);
document.getElementById('toggle_download_tab').addEventListener('click', toggleDownloadTab);
// Queue buttons
document.getElementById('clean_queue').addEventListener('click', () => {
socket.emit('removeFinishedDownloads');
});
document.getElementById('cancel_queue').addEventListener('click', () => {
socket.emit('cancelAllDownloads');
});
dragHandlerEl.addEventListener('mousedown', event => {
event.preventDefault();
document.addEventListener('mousemove', handleDrag);
});
document.addEventListener('mouseup', () => {
document.removeEventListener('mousemove', handleDrag);
});
tabContainerEl.addEventListener('transitionend', () => {
tabContainerEl.style.transition = '';
});
window.addEventListener('beforeunload', () => {
localStorage.setItem('downloadTabWidth', cachedTabWidth);
});
}
function setTabWidth(newWidth) {
if (undefined === newWidth) {
tabContainerEl.style.width = '';
listEl.style.width = '';
} else {
tabContainerEl.style.width = newWidth + 'px';
listEl.style.width = newWidth + 'px';
}
}
function handleDrag(event) {
let newWidth = window.innerWidth - event.pageX + 2;
if (newWidth < tabMinWidth) {
newWidth = tabMinWidth;
} else if (newWidth > tabMaxWidth) {
newWidth = tabMaxWidth;
}
cachedTabWidth = newWidth;
setTabWidth(newWidth);
}
function sendAddToQueue(url, bitrate = null) {
if (url.indexOf(';') !== -1) {
let urls = url.split(';');
urls.forEach(url => {
socket.emit('addToQueue', { url: url, bitrate: bitrate });
});
} else if (url != '') {
socket.emit('addToQueue', { url: url, bitrate: bitrate });
}
}
function addToQueue(queueItem, current = false) {
queueList[queueItem.uuid] = queueItem;
if (queueItem.downloaded + queueItem.failed == queueItem.size) {
queueComplete.push(queueItem.uuid);
} else {
queue.push(queueItem.uuid);
}
$(listEl).append(
`
${queueItem.title} -
${queueItem.artist}
${queueItem.downloaded + queueItem.failed}/${
queueItem.size
}
`
);
if (queueItem.progress > 0 || current) {
$('#bar_' + queueItem.uuid)
.removeClass('indeterminate')
.addClass('determinate');
}
$('#bar_' + queueItem.uuid).css('width', queueItem.progress + '%');
if (queueItem.failed >= 1) {
$('#download_' + queueItem.uuid + ' .download_info_status').append(
`(${queueItem.failed}error_outline)`
);
}
if (queueItem.downloaded + queueItem.failed == queueItem.size) {
let result_icon = $('#download_' + queueItem.uuid).find('.queue_icon');
if (queueItem.failed == 0) {
result_icon.text('done');
} else if (queueItem.failed == queueItem.size) {
result_icon.text('error');
} else {
result_icon.text('warning');
}
}
}
function initQueue(data) {
if (data.queueComplete.length) {
data.queueComplete.forEach(item => {
addToQueue(data.queueList[item]);
});
}
if (data.currentItem) {
addToQueue(data['queueList'][data.currentItem], true);
}
data.queue.forEach(item => {
addToQueue(data.queueList[item]);
});
}
function startDownload(uuid) {
$('#bar_' + uuid)
.removeClass('indeterminate')
.addClass('determinate');
}
socket.on('startDownload', startDownload);
function handleListClick(event) {
if (!event.target.matches('.queue_icon[data-uuid]')) {
return
}
let icon = event.target.innerText;
let uuid = $(event.target).data('uuid');
switch (icon) {
case 'remove':
socket.emit('removeFromQueue', uuid);
break
}
}
// Show/Hide Download Tab
function toggleDownloadTab(ev) {
ev.preventDefault();
setTabWidth();
tabContainerEl.style.transition = 'all 250ms ease-in-out';
// Toggle returns a Boolean based on the action it performed
let isHidden = tabContainerEl.classList.toggle('tab_hidden');
if (!isHidden) {
setTabWidth(cachedTabWidth);
}
localStorage.setItem('downloadTabOpen', !isHidden);
}
socket.on('init_downloadQueue', initQueue);
socket.on('addedToQueue', addToQueue);
function removeFromQueue(uuid) {
let index = queue.indexOf(uuid);
if (index > -1) {
queue.splice(index, 1);
$(`#download_${queueList[uuid].uuid}`).remove();
delete queueList[uuid];
}
}
socket.on('removedFromQueue', removeFromQueue);
function finishDownload(uuid) {
if (queue.indexOf(uuid) > -1) {
toast(`${queueList[uuid].title} finished downloading.`, 'done');
$('#bar_' + uuid).css('width', '100%');
let result_icon = $('#download_' + uuid).find('.queue_icon');
if (queueList[uuid].failed == 0) {
result_icon.text('done');
} else if (queueList[uuid].failed >= queueList[uuid].size) {
result_icon.text('error');
} else {
result_icon.text('warning');
}
let index = queue.indexOf(uuid);
if (index > -1) {
queue.splice(index, 1);
queueComplete.push(uuid);
}
if (queue.length <= 0) {
toast('All downloads completed!', 'done_all');
}
}
}
socket.on('finishDownload', finishDownload);
function removeAllDownloads(currentItem) {
queueComplete = [];
if (currentItem == '') {
queue = [];
queueList = {};
$(listEl).html('');
} else {
queue = [currentItem];
let tempQueueItem = queueList[currentItem];
queueList = {};
queueList[currentItem] = tempQueueItem;
$('.download_object').each(function (index) {
if ($(this).attr('id') != 'download_' + currentItem) $(this).remove();
});
}
}
socket.on('removedAllDownloads', removeAllDownloads);
function removedFinishedDownloads() {
queueComplete.forEach(item => {
$('#download_' + item).remove();
});
queueComplete = [];
}
socket.on('removedFinishedDownloads', removedFinishedDownloads);
function updateQueue(update) {
if (update.uuid && queue.indexOf(update.uuid) > -1) {
if (update.downloaded) {
queueList[update.uuid].downloaded++;
$('#download_' + update.uuid + ' .queue_downloaded').text(
queueList[update.uuid].downloaded + queueList[update.uuid].failed
);
}
if (update.failed) {
queueList[update.uuid].failed++;
$('#download_' + update.uuid + ' .queue_downloaded').text(
queueList[update.uuid].downloaded + queueList[update.uuid].failed
);
if (queueList[update.uuid].failed == 1) {
$('#download_' + update.uuid + ' .download_info_status').append(
`(1 error_outline)`
);
} else {
$('#download_' + update.uuid + ' .queue_failed').text(queueList[update.uuid].failed);
}
}
if (update.progress) {
queueList[update.uuid].progress = update.progress;
$('#bar_' + update.uuid).css('width', update.progress + '%');
}
}
}
socket.on('updateQueue', updateQueue);
var Downloads = {
init,
sendAddToQueue,
addToQueue
};
const QualityModal = {
// Defaults
open: false,
url: ''
};
function init$1() {
QualityModal.element = document.getElementById('modal_quality');
linkListeners$1();
}
function open(link) {
QualityModal.url = link;
QualityModal.element.style.display = 'block';
QualityModal.element.classList.add('animated', 'fadeIn');
}
function linkListeners$1() {
QualityModal.element.addEventListener('click', handleClick);
QualityModal.element.addEventListener('webkitAnimationEnd', handleAnimationEnd);
}
function handleClick(event) {
QualityModal.element.classList.add('animated', 'fadeOut');
if (!event.target.matches('.quality-button')) {
return
}
let bitrate = event.target.dataset.qualityValue;
Downloads.sendAddToQueue(QualityModal.url, bitrate);
}
function handleAnimationEnd() {
QualityModal.element.classList.remove('animated', QualityModal.open ? 'fadeOut' : 'fadeIn');
QualityModal.element.style.display = QualityModal.open ? 'none' : 'block';
QualityModal.open = !QualityModal.open;
}
var QualityModal$1 = {
init: init$1,
open
};
const ArtistTab = new Vue({
data() {
return {
currentTab: '',
sortKey: 'release_date',
sortOrder: 'desc',
title: '',
image: '',
type: '',
link: '',
head: null,
body: null
}
},
methods: {
albumView,
reset() {
this.title = 'Loading...';
this.image = '';
this.type = '';
this.currentTab = '';
this.sortKey = 'release_date';
this.sortOrder = 'desc';
this.link = '';
this.head = [];
this.body = null;
},
addToQueue(e) {
e.stopPropagation();
Downloads.sendAddToQueue(e.currentTarget.dataset.link);
},
openQualityModal(e) {
QualityModal$1.open(e.currentTarget.dataset.link);
},
sortBy(key) {
if (key == this.sortKey) {
this.sortOrder = this.sortOrder == 'asc' ? 'desc' : 'asc';
} else {
this.sortKey = key;
this.sortOrder = 'asc';
}
},
changeTab(tab) {
this.currentTab = tab;
},
checkNewRelease(date) {
let g1 = new Date();
let g2 = new Date(date);
g2.setDate(g2.getDate() + 3);
g1.setHours(0, 0, 0, 0);
return g1.getTime() <= g2.getTime()
},
showArtist(data) {
this.title = data.name;
this.image = data.picture_xl;
this.type = 'Artist';
this.link = `https://www.deezer.com/artist/${data.id}`;
this.currentTab = Object.keys(data.releases)[0];
this.sortKey = 'release_date';
this.sortOrder = 'desc';
this.head = [
{ title: 'Title', sortKey: 'title' },
{ title: 'Release Date', sortKey: 'release_date' },
{ title: '', width: '32px' }
];
if (_.isEmpty(data.releases)) {
this.body = null;
} else {
this.body = data.releases;
}
}
},
computed: {
showTable() {
if (this.body) return _.orderBy(this.body[this.currentTab], this.sortKey, this.sortOrder)
else return []
}
},
mounted() {
socket.on('show_artist', this.showArtist);
}
}).$mount('#artist_tab');
/* ===== Globals ====== */
window.preview_max_volume = 1;
/* ===== Locals ===== */
let preview_track = document.getElementById('preview-track');
let preview_stopped = true;
// init stuff
function init$2() {
preview_track.volume = 1;
/*preview_max_volume = parseFloat(localStorage.getItem("previewVolume"))
if (preview_max_volume === null){
preview_max_volume = 0.8
localStorage.setItem("previewVolume", preview_max_volume)
}*/
// start playing when track loaded
preview_track.addEventListener('canplay', function () {
preview_track.play();
preview_stopped = false;
$(preview_track).animate({ volume: preview_max_volume }, 500);
});
// auto fadeout when at the end of the song
preview_track.addEventListener('timeupdate', function () {
if (preview_track.currentTime > preview_track.duration - 1) {
$(preview_track).animate({ volume: 0 }, 800);
preview_stopped = true;
$('a[playing] > .preview_controls').css({ opacity: 0 });
$('*').removeAttr('playing');
$('.preview_controls').text('play_arrow');
$('.preview_playlist_controls').text('play_arrow');
}
});
}
// on modal closing
function stopStackedTabsPreview() {
if (
$('.preview_playlist_controls').filter(function () {
return $(this).attr('playing')
}).length > 0
) {
$(preview_track).animate({ volume: 0 }, 800);
preview_stopped = true;
$('.preview_playlist_controls').removeAttr('playing');
$('.preview_playlist_controls').text('play_arrow');
}
}
// on hover event
function previewMouseEnter(e) {
$(e.currentTarget).css({ opacity: 1 });
}
function previewMouseLeave(e) {
let obj = e.currentTarget;
if (($(obj).parent().attr('playing') && preview_stopped) || !$(obj).parent().attr('playing')) {
$(obj).css({ opacity: 0 }, 200);
}
}
// on click event
function playPausePreview(e) {
e.preventDefault();
let obj = e.currentTarget;
var icon = obj.tagName == 'I' ? $(obj) : $(obj).children('i');
if ($(obj).attr('playing')) {
if (preview_track.paused) {
preview_track.play();
preview_stopped = false;
icon.text('pause');
$(preview_track).animate({ volume: preview_max_volume }, 500);
} else {
preview_stopped = true;
icon.text('play_arrow');
$(preview_track).animate({ volume: 0 }, 250, 'swing', () => {
preview_track.pause();
});
}
} else {
$('*').removeAttr('playing');
$(obj).attr('playing', true);
$('.preview_controls').text('play_arrow');
$('.preview_playlist_controls').text('play_arrow');
$('.preview_controls').css({ opacity: 0 });
icon.text('pause');
icon.css({ opacity: 1 });
preview_stopped = false;
$(preview_track).animate({ volume: 0 }, 250, 'swing', () => {
preview_track.pause();
$('#preview-track_source').prop('src', $(obj).data('preview'));
preview_track.load();
});
}
}
var TrackPreview = {
init: init$2,
stopStackedTabsPreview,
previewMouseEnter,
previewMouseLeave,
playPausePreview
};
const TracklistTab = new Vue({
data: () => ({
title: '',
metadata: '',
release_date: '',
label: '',
explicit: false,
image: '',
type: '',
link: '',
head: null,
body: []
}),
methods: {
artistView,
albumView,
playPausePreview: TrackPreview.playPausePreview,
reset() {
this.title = 'Loading...';
this.image = '';
this.metadata = '';
this.label = '';
this.release_date = '';
this.explicit = false;
this.type = '';
this.head = [];
this.body = [];
},
addToQueue(e) {
e.stopPropagation();
Downloads.sendAddToQueue(e.currentTarget.dataset.link);
},
openQualityModal(e) {
QualityModal$1.open(e.currentTarget.dataset.link);
},
toggleAll(e) {
this.body.forEach(item => {
if (item.type == 'track') {
item.selected = e.currentTarget.checked;
}
});
},
selectedLinks() {
var selected = [];
if (this.body) {
this.body.forEach(item => {
if (item.type == 'track' && item.selected) selected.push(this.type == "Spotify Playlist" ? item.uri : item.link);
});
}
return selected.join(';')
},
convertDuration(duration) {
//convert from seconds only to mm:ss format
let mm, ss;
mm = Math.floor(duration / 60);
ss = duration - mm * 60;
//add leading zero if ss < 0
if (ss < 10) {
ss = '0' + ss;
}
return mm + ':' + ss
},
showAlbum(data) {
this.type = 'Album';
this.link = `https://www.deezer.com/album/${data.id}`;
this.title = data.title;
this.explicit = data.explicit_lyrics;
this.label = data.label;
this.metadata = `${data.artist.name} • ${data.tracks.length} songs`;
this.release_date = data.release_date.substring(0, 10);
this.image = data.cover_xl;
this.head = [
{ title: 'music_note', width: '24px' },
{ title: '#' },
{ title: 'Song' },
{ title: 'Artist' },
{ title: 'timer', width: '40px' }
];
if (_.isEmpty(data.tracks)) {
console.log('show e lodash ok');
this.body = null;
} else {
this.body = data.tracks;
}
},
showPlaylist(data) {
this.type = 'Playlist';
this.link = `https://www.deezer.com/playlist/${data.id}`;
this.title = data.title;
this.image = data.picture_xl;
this.release_date = data.creation_date.substring(0, 10);
this.metadata = `by ${data.creator.name} • ${data.tracks.length} songs`;
this.head = [
{ title: 'music_note', width: '24px' },
{ title: '#' },
{ title: 'Song' },
{ title: 'Artist' },
{ title: 'Album' },
{ title: 'timer', width: '40px' }
];
if (_.isEmpty(data.tracks)) {
this.body = null;
} else {
this.body = data.tracks;
}
},
showSpotifyPlaylist(data) {
this.type = 'Spotify Playlist';
this.link = data.uri;
this.title = data.name;
this.image = data.images.length ? data.images[0].url : "https://e-cdns-images.dzcdn.net/images/cover/d41d8cd98f00b204e9800998ecf8427e/1000x1000-000000-80-0-0.jpg";
this.release_date = "";
this.metadata = `by ${data.owner.display_name} • ${data.tracks.length} songs`;
this.head = [
{ title: 'music_note', width: '24px' },
{ title: '#' },
{ title: 'Song' },
{ title: 'Artist' },
{ title: 'Album' },
{ title: 'timer', width: '40px' }
];
if (_.isEmpty(data.tracks)) {
this.body = null;
} else {
this.body = data.tracks;
}
}
},
mounted() {
socket.on('show_album', this.showAlbum);
socket.on('show_playlist', this.showPlaylist);
socket.on('show_spotifyplaylist', this.showSpotifyPlaylist);
}
}).$mount('#tracklist_tab');
function isValidURL(text) {
let lowerCaseText = text.toLowerCase();
if (lowerCaseText.startsWith('http')) {
if (lowerCaseText.indexOf('deezer.com') >= 0 || lowerCaseText.indexOf('open.spotify.com') >= 0) {
return true
}
} else if (lowerCaseText.startsWith('spotify:')) {
return true
}
return false
}
function convertDuration(duration) {
// convert from seconds only to mm:ss format
let mm, ss;
mm = Math.floor(duration / 60);
ss = duration - mm * 60;
//add leading zero if ss < 0
if (ss < 10) {
ss = '0' + ss;
}
return mm + ':' + ss
}
function convertDurationSeparated(duration) {
let hh, mm, ss;
mm = Math.floor(duration / 60);
hh = Math.floor(mm / 60);
ss = duration - mm * 60;
mm -= hh * 60;
return [hh, mm, ss]
}
function numberWithDots(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, '.')
}
// On scroll event, returns currentTarget = null
// Probably on other events too
function debounce(func, wait, immediate) {
var timeout;
return function () {
var context = this;
var args = arguments;
var later = function () {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
}
}
const COUNTRIES = {
AF: 'Afghanistan',
AX: '\u00c5land Islands',
AL: 'Albania',
DZ: 'Algeria',
AS: 'American Samoa',
AD: 'Andorra',
AO: 'Angola',
AI: 'Anguilla',
AQ: 'Antarctica',
AG: 'Antigua and Barbuda',
AR: 'Argentina',
AM: 'Armenia',
AW: 'Aruba',
AU: 'Australia',
AT: 'Austria',
AZ: 'Azerbaijan',
BS: 'Bahamas',
BH: 'Bahrain',
BD: 'Bangladesh',
BB: 'Barbados',
BY: 'Belarus',
BE: 'Belgium',
BZ: 'Belize',
BJ: 'Benin',
BM: 'Bermuda',
BT: 'Bhutan',
BO: 'Bolivia, Plurinational State of',
BQ: 'Bonaire, Sint Eustatius and Saba',
BA: 'Bosnia and Herzegovina',
BW: 'Botswana',
BV: 'Bouvet Island',
BR: 'Brazil',
IO: 'British Indian Ocean Territory',
BN: 'Brunei Darussalam',
BG: 'Bulgaria',
BF: 'Burkina Faso',
BI: 'Burundi',
KH: 'Cambodia',
CM: 'Cameroon',
CA: 'Canada',
CV: 'Cape Verde',
KY: 'Cayman Islands',
CF: 'Central African Republic',
TD: 'Chad',
CL: 'Chile',
CN: 'China',
CX: 'Christmas Island',
CC: 'Cocos (Keeling) Islands',
CO: 'Colombia',
KM: 'Comoros',
CG: 'Congo',
CD: 'Congo, the Democratic Republic of the',
CK: 'Cook Islands',
CR: 'Costa Rica',
CI: "C\u00f4te d'Ivoire",
HR: 'Croatia',
CU: 'Cuba',
CW: 'Cura\u00e7ao',
CY: 'Cyprus',
CZ: 'Czech Republic',
DK: 'Denmark',
DJ: 'Djibouti',
DM: 'Dominica',
DO: 'Dominican Republic',
EC: 'Ecuador',
EG: 'Egypt',
SV: 'El Salvador',
GQ: 'Equatorial Guinea',
ER: 'Eritrea',
EE: 'Estonia',
ET: 'Ethiopia',
FK: 'Falkland Islands (Malvinas)',
FO: 'Faroe Islands',
FJ: 'Fiji',
FI: 'Finland',
FR: 'France',
GF: 'French Guiana',
PF: 'French Polynesia',
TF: 'French Southern Territories',
GA: 'Gabon',
GM: 'Gambia',
GE: 'Georgia',
DE: 'Germany',
GH: 'Ghana',
GI: 'Gibraltar',
GR: 'Greece',
GL: 'Greenland',
GD: 'Grenada',
GP: 'Guadeloupe',
GU: 'Guam',
GT: 'Guatemala',
GG: 'Guernsey',
GN: 'Guinea',
GW: 'Guinea-Bissau',
GY: 'Guyana',
HT: 'Haiti',
HM: 'Heard Island and McDonald Islands',
VA: 'Holy See (Vatican City State)',
HN: 'Honduras',
HK: 'Hong Kong',
HU: 'Hungary',
IS: 'Iceland',
IN: 'India',
ID: 'Indonesia',
IR: 'Iran, Islamic Republic of',
IQ: 'Iraq',
IE: 'Ireland',
IM: 'Isle of Man',
IL: 'Israel',
IT: 'Italy',
JM: 'Jamaica',
JP: 'Japan',
JE: 'Jersey',
JO: 'Jordan',
KZ: 'Kazakhstan',
KE: 'Kenya',
KI: 'Kiribati',
KP: "Korea, Democratic People's Republic of",
KR: 'Korea, Republic of',
KW: 'Kuwait',
KG: 'Kyrgyzstan',
LA: "Lao People's Democratic Republic",
LV: 'Latvia',
LB: 'Lebanon',
LS: 'Lesotho',
LR: 'Liberia',
LY: 'Libya',
LI: 'Liechtenstein',
LT: 'Lithuania',
LU: 'Luxembourg',
MO: 'Macao',
MK: 'Macedonia, the Former Yugoslav Republic of',
MG: 'Madagascar',
MW: 'Malawi',
MY: 'Malaysia',
MV: 'Maldives',
ML: 'Mali',
MT: 'Malta',
MH: 'Marshall Islands',
MQ: 'Martinique',
MR: 'Mauritania',
MU: 'Mauritius',
YT: 'Mayotte',
MX: 'Mexico',
FM: 'Micronesia, Federated States of',
MD: 'Moldova, Republic of',
MC: 'Monaco',
MN: 'Mongolia',
ME: 'Montenegro',
MS: 'Montserrat',
MA: 'Morocco',
MZ: 'Mozambique',
MM: 'Myanmar',
NA: 'Namibia',
NR: 'Nauru',
NP: 'Nepal',
NL: 'Netherlands',
NC: 'New Caledonia',
NZ: 'New Zealand',
NI: 'Nicaragua',
NE: 'Niger',
NG: 'Nigeria',
NU: 'Niue',
NF: 'Norfolk Island',
MP: 'Northern Mariana Islands',
NO: 'Norway',
OM: 'Oman',
PK: 'Pakistan',
PW: 'Palau',
PS: 'Palestine, State of',
PA: 'Panama',
PG: 'Papua New Guinea',
PY: 'Paraguay',
PE: 'Peru',
PH: 'Philippines',
PN: 'Pitcairn',
PL: 'Poland',
PT: 'Portugal',
PR: 'Puerto Rico',
QA: 'Qatar',
RE: 'R\u00e9union',
RO: 'Romania',
RU: 'Russian Federation',
RW: 'Rwanda',
BL: 'Saint Barth\u00e9lemy',
SH: 'Saint Helena, Ascension and Tristan da Cunha',
KN: 'Saint Kitts and Nevis',
LC: 'Saint Lucia',
MF: 'Saint Martin (French part)',
PM: 'Saint Pierre and Miquelon',
VC: 'Saint Vincent and the Grenadines',
WS: 'Samoa',
SM: 'San Marino',
ST: 'Sao Tome and Principe',
SA: 'Saudi Arabia',
SN: 'Senegal',
RS: 'Serbia',
SC: 'Seychelles',
SL: 'Sierra Leone',
SG: 'Singapore',
SX: 'Sint Maarten (Dutch part)',
SK: 'Slovakia',
SI: 'Slovenia',
SB: 'Solomon Islands',
SO: 'Somalia',
ZA: 'South Africa',
GS: 'South Georgia and the South Sandwich Islands',
SS: 'South Sudan',
ES: 'Spain',
LK: 'Sri Lanka',
SD: 'Sudan',
SR: 'Suriname',
SJ: 'Svalbard and Jan Mayen',
SZ: 'Swaziland',
SE: 'Sweden',
CH: 'Switzerland',
SY: 'Syrian Arab Republic',
TW: 'Taiwan, Province of China',
TJ: 'Tajikistan',
TZ: 'Tanzania, United Republic of',
TH: 'Thailand',
TL: 'Timor-Leste',
TG: 'Togo',
TK: 'Tokelau',
TO: 'Tonga',
TT: 'Trinidad and Tobago',
TN: 'Tunisia',
TR: 'Turkey',
TM: 'Turkmenistan',
TC: 'Turks and Caicos Islands',
TV: 'Tuvalu',
UG: 'Uganda',
UA: 'Ukraine',
AE: 'United Arab Emirates',
GB: 'United Kingdom',
US: 'United States',
UM: 'United States Minor Outlying Islands',
UY: 'Uruguay',
UZ: 'Uzbekistan',
VU: 'Vanuatu',
VE: 'Venezuela, Bolivarian Republic of',
VN: 'Viet Nam',
VG: 'Virgin Islands, British',
VI: 'Virgin Islands, U.S.',
WF: 'Wallis and Futuna',
EH: 'Western Sahara',
YE: 'Yemen',
ZM: 'Zambia',
ZW: 'Zimbabwe'
};
var Utils = {
isValidURL,
convertDuration,
convertDurationSeparated,
numberWithDots,
debounce,
COUNTRIES
};
const LinkAnalyzerTab = new Vue({
data() {
return {
title: '',
subtitle: '',
image: '',
data: {},
type: '',
link: '',
countries: []
}
},
methods: {
albumView,
convertDuration: Utils.convertDuration,
reset() {
this.title = 'Loading...';
this.subtitle = '';
this.image = '';
this.data = {};
this.type = '';
this.link = '';
this.countries = [];
},
showTrack(data) {
this.title =
data.title +
(data.title_version && data.title.indexOf(data.title_version) == -1 ? ' ' + data.title_version : '');
this.subtitle = `by ${data.artist.name}\nin ${data.album.title}`;
this.image = data.album.cover_xl;
this.type = 'track';
this.link = data.link;
data.available_countries.forEach(cc => {
let temp = [];
let chars = [...cc].map(c => c.charCodeAt() + 127397);
temp.push(String.fromCodePoint(...chars));
temp.push(Utils.COUNTRIES[cc]);
this.countries.push(temp);
});
this.data = data;
},
showAlbum(data) {
console.log(data);
this.title = data.title;
this.subtitle = `by ${data.artist.name}\n${data.nb_tracks} tracks`;
this.image = data.cover_xl;
this.type = 'album';
this.link = data.link;
this.data = data;
}
},
mounted() {
socket.on('analyze_track', this.showTrack);
socket.on('analyze_album', this.showAlbum);
}
}).$mount('#analyzer_tab');
const HomeTab = new Vue({
data() {
return {
tracks: [],
albums: [],
artists: [],
playlists: []
}
},
methods: {
artistView,
albumView,
playlistView,
playPausePreview: TrackPreview.playPausePreview,
previewMouseEnter: TrackPreview.previewMouseEnter,
previewMouseLeave: TrackPreview.previewMouseLeave,
numberWithDots: Utils.numberWithDots,
convertDuration: Utils.convertDuration,
addToQueue(e) {
e.stopPropagation();
Downloads.sendAddToQueue(e.currentTarget.dataset.link);
},
openQualityModal(e) {
QualityModal$1.open(e.currentTarget.dataset.link);
},
initHome(data) {
this.tracks = data.tracks.data;
this.albums = data.albums.data;
this.artists = data.artists.data;
this.playlists = data.playlists.data;
}
},
mounted() {
socket.on('init_home', this.initHome);
}
}).$mount('#home_tab');
const ChartsTab = new Vue({
data() {
return {
country: '',
id: 0,
countries: [],
chart: []
}
},
methods: {
artistView,
albumView,
playPausePreview: TrackPreview.playPausePreview,
previewMouseEnter: TrackPreview.previewMouseEnter,
previewMouseLeave: TrackPreview.previewMouseLeave,
convertDuration: Utils.convertDuration,
addToQueue(e) {
e.stopPropagation();
Downloads.sendAddToQueue(e.currentTarget.dataset.link);
},
openQualityModal(e) {
QualityModal$1.open(e.currentTarget.dataset.link);
},
getTrackList(e){
this.country = e.currentTarget.dataset.title;
localStorage.setItem('chart', this.country);
this.id = e.currentTarget.dataset.id;
socket.emit('getChartTracks', this.id);
},
setTracklist(data){
this.chart = data;
},
changeCountry(){
this.country = '';
this.id = 0;
},
initCharts(data) {
this.countries = data;
this.country = localStorage.getItem('chart') || '';
if (this.country){
let i = 0;
for (i; i < this.countries.length; i++) if (this.countries[i].title == this.country) break
if (i != this.countries.length){
this.id = this.countries[i].id;
socket.emit('getChartTracks', this.id);
}else {
this.country = '';
localStorage.setItem('chart', this.country);
}
}
}
},
mounted() {
socket.on('init_charts', this.initCharts);
socket.on('setChartTracks', this.setTracklist);
}
}).$mount('#charts_tab');
const FavoritesTab = new Vue({
data() {
return {
tracks: [],
albums: [],
artists: [],
playlists: [],
spotifyPlaylists: []
}
},
methods: {
playlistView,
artistView,
albumView,
spotifyPlaylistView,
playPausePreview: TrackPreview.playPausePreview,
previewMouseEnter: TrackPreview.previewMouseEnter,
previewMouseLeave: TrackPreview.previewMouseLeave,
convertDuration: Utils.convertDuration,
addToQueue(e) {
e.stopPropagation();
Downloads.sendAddToQueue(e.currentTarget.dataset.link);
},
openQualityModal(e) {
QualityModal$1.open(e.currentTarget.dataset.link);
},
updated_userSpotifyPlaylists(data){this.spotifyPlaylists = data;},
updated_userPlaylists(data){this.playlists = data;},
updated_userAlbums(data){this.albums = data;},
updated_userArtist(data){this.artists = data;},
updated_userTracks(data){this.tracks = data;},
initFavorites(data) {
this.tracks = data.tracks;
this.albums = data.albums;
this.artists = data.artists;
this.playlists = data.playlists;
document.getElementById('favorites_playlist_tab').click();
}
},
mounted() {
socket.on('init_favorites', this.initFavorites);
socket.on('updated_userSpotifyPlaylists', this.updated_userSpotifyPlaylists);
socket.on('updated_userPlaylists', this.updated_userPlaylists);
socket.on('updated_userAlbums', this.updated_userAlbums);
socket.on('updated_userArtist', this.updated_userArtist);
socket.on('updated_userTracks', this.updated_userTracks);
}
}).$mount('#favorites_tab');
const SettingsTab = new Vue({
data: () => ({
settings: { tags: {} },
lastSettings: {},
spotifyFeatures: {},
lastCredentials: {},
defaultSettings: {},
lastUser: '',
spotifyUser: '',
darkMode: false,
slimDownloads: false
}),
computed: {
changeDarkMode: {
get() {
return this.darkMode
},
set(wantDarkMode) {
this.darkMode = wantDarkMode;
document.documentElement.setAttribute('data-theme', wantDarkMode ? 'dark' : 'default');
localStorage.setItem('darkMode', wantDarkMode);
}
},
changeSlimDownloads: {
get() {
return this.slimDownloads
},
set(wantSlimDownloads) {
this.slimDownloads = wantSlimDownloads;
document.getElementById('download_list').classList.toggle('slim', wantSlimDownloads);
localStorage.setItem('slimDownloads', wantSlimDownloads);
}
}
},
methods: {
copyARLtoClipboard() {
let copyText = this.$refs.loginInput;
copyText.setAttribute('type', 'text');
copyText.select();
copyText.setSelectionRange(0, 99999);
document.execCommand('copy');
copyText.setAttribute('type', 'password');
toast('ARL copied to clipboard', 'assignment');
},
saveSettings() {
this.lastSettings = { ...this.settings };
this.lastCredentials = { ...this.spotifyFeatures };
let changed = false;
if (this.lastUser != this.spotifyUser) {
// force cloning without linking
this.lastUser = (' ' + this.spotifyUser).slice(1);
localStorage.setItem('spotifyUser', this.lastUser);
changed = true;
}
socket.emit('saveSettings', this.lastSettings, this.lastCredentials, changed ? this.lastUser : false);
console.log(this.darkMode);
},
loadSettings(settings, spotifyCredentials, defaults = null) {
if (defaults) {
this.defaultSettings = { ...defaults };
}
this.lastSettings = { ...settings };
this.lastCredentials = { ...spotifyCredentials };
this.settings = settings;
this.spotifyFeatures = spotifyCredentials;
},
login() {
let arl = this.$refs.loginInput.value;
if (arl != '' && arl != localStorage.getItem('arl')) {
socket.emit('login', arl, true);
}
},
logout() {
socket.emit('logout');
},
initSettings(settings, credentials, defaults) {
this.loadSettings(settings, credentials, defaults);
toast('Settings loaded!', 'settings');
},
updateSettings(settings, credentials) {
this.loadSettings(settings, credentials);
toast('Settings updated!', 'settings');
},
resetSettings() {
this.settings = { ...this.defaultSettings };
}
},
mounted() {
socket.on('init_settings', this.initSettings);
socket.on('updateSettings', this.updateSettings);
let spotyUser = localStorage.getItem('spotifyUser');
if ('' !== spotyUser) {
this.lastUser = spotyUser;
this.spotifyUser = spotyUser;
}
this.changeDarkMode = 'true' === localStorage.getItem('darkMode');
this.changeSlimDownloads = 'true' === localStorage.getItem('slimDownloads');
}
}).$mount('#settings_tab');
const MainSearch = new Vue({
data: {
names: {
TOP_RESULT: 'Top Result',
TRACK: 'Tracks',
ARTIST: 'Artists',
ALBUM: 'Albums',
PLAYLIST: 'Playlists'
},
results: {
query: '',
allTab: {
ORDER: [],
TOP_RESULT: [],
ALBUM: {},
ARTIST: {},
TRACK: {},
PLAYLIST: {}
},
trackTab: {
data: [],
next: 0,
total: 0,
loaded: false
},
albumTab: {
data: [],
next: 0,
total: 0,
loaded: false
},
artistTab: {
data: [],
next: 0,
total: 0,
loaded: false
},
playlistTab: {
data: [],
next: 0,
total: 0,
loaded: false
}
}
},
methods: {
artistView,
albumView,
playlistView,
playPausePreview: TrackPreview.playPausePreview,
previewMouseEnter: TrackPreview.previewMouseEnter,
previewMouseLeave: TrackPreview.previewMouseLeave,
handleClickTopResult(event) {
let topResultType = this.results.allTab.TOP_RESULT[0].type;
switch (topResultType) {
case 'artist':
this.artistView(event);
break
case 'album':
this.albumView(event);
break
case 'playlist':
this.playlistView(event);
break
}
},
changeSearchTab(section) {
if (section != 'TOP_RESULT') {
document.getElementById(`search_${section.toLowerCase()}_tab`).click();
}
},
addToQueue: function (e) {
Downloads.sendAddToQueue(e.currentTarget.dataset.link);
},
openQualityModal: function (e) {
QualityModal$1.open(e.currentTarget.dataset.link);
},
numberWithDots: Utils.numberWithDots,
convertDuration: Utils.convertDuration,
search(type) {
socket.emit('search', {
term: this.results.query,
type: type,
start: this.results[type + 'Tab'].next,
nb: 30
});
},
scrolledSearch(type) {
if (this.results[type + 'Tab'].next < this.results[type + 'Tab'].total) {
socket.emit('search', {
term: this.results.query,
type: type,
start: this.results[type + 'Tab'].next,
nb: 30
});
}
},
handleMainSearch(result) {
let resetObj = { data: [], next: 0, total: 0, loaded: false };
this.results.allTab = result;
this.results.query = result.QUERY;
this.results.trackTab = { ...resetObj };
this.results.albumTab = { ...resetObj };
this.results.artistTab = { ...resetObj };
this.results.playlistTab = { ...resetObj };
document.getElementById('search_all_tab').click();
document.getElementById('search_tab_content').style.display = 'block';
document.getElementById('main_search_tablink').click();
},
handleSearch(result) {
let next = 0;
if (result.next) {
next = parseInt(result.next.match(/index=(\d*)/)[1]);
} else {
next = result.total;
}
if (this.results[result.type + 'Tab'].total != result.total) {
this.results[result.type + 'Tab'].total = result.total;
}
if (this.results[result.type + 'Tab'].next != next) {
this.results[result.type + 'Tab'].next = next;
this.results[result.type + 'Tab'].data = this.results[result.type + 'Tab'].data.concat(result.data);
}
this.results[result.type + 'Tab'].loaded = true;
}
},
mounted() {
socket.on('mainSearch', this.handleMainSearch);
socket.on('search', this.handleSearch);
}
}).$mount('#search_tab');
/* ===== Globals ====== */
window.search_selected = '';
window.main_selected = '';
window.windows_stack = [];
/* ===== Locals ===== */
let currentStack = {};
// Exporting this function out of the default export
// because it's used in components that are needed
// in this file too
function artistView(ev) {
let id = ev.currentTarget.dataset.id;
ArtistTab.reset();
socket.emit('getTracklist', { type: 'artist', id: id });
showTab('artist', id);
}
// Exporting this function out of the default export
// because it's used in components that are needed
// in this file too
function albumView(ev) {
let id = ev.currentTarget.dataset.id;
TracklistTab.reset();
socket.emit('getTracklist', { type: 'album', id: id });
showTab('album', id);
}
// Exporting this function out of the default export
// because it's used in components that are needed
// in this file too
function playlistView(ev) {
let id = ev.currentTarget.dataset.id;
TracklistTab.reset();
socket.emit('getTracklist', { type: 'playlist', id: id });
showTab('playlist', id);
}
function spotifyPlaylistView(ev) {
let id = ev.currentTarget.dataset.id;
TracklistTab.reset();
socket.emit('getTracklist', { type: 'spotifyplaylist', id: id });
showTab('spotifyplaylist', id);
}
function analyzeLink(link) {
console.log('Analyzing: ' + link);
LinkAnalyzerTab.reset();
socket.emit('analyzeLink', link);
}
function linkListeners$2() {
document.getElementById('search_tab').addEventListener('click', handleSearchTabClick);
document.getElementById('favorites_tab').addEventListener('click', handleFavoritesTabClick);
document.getElementById('sidebar').addEventListener('click', handleSidebarClick);
const backButtons = Array.from(document.getElementsByClassName('back-button'));
backButtons.forEach(button => {
button.addEventListener('click', backTab);
});
}
/**
* Handles click Event on the sidebar and changes tab
* according to clicked icon.
* Uses event delegation
* @param {Event} event
* @since 0.1.0
*/
function handleSidebarClick(event) {
if (!(event.target.matches('.main_tablinks') || event.target.parentElement.matches('.main_tablinks'))) {
return
}
let sidebarEl = event.target.matches('.main_tablinks') ? event.target : event.target.parentElement;
let targetID = sidebarEl.getAttribute('id');
switch (targetID) {
case 'main_search_tablink':
changeTab(sidebarEl, 'main', 'search_tab');
break
case 'main_home_tablink':
changeTab(sidebarEl, 'main', 'home_tab');
break
case 'main_charts_tablink':
changeTab(sidebarEl, 'main', 'charts_tab');
break
case 'main_favorites_tablink':
changeTab(sidebarEl, 'main', 'favorites_tab');
break
case 'main_analyzer_tablink':
changeTab(sidebarEl, 'main', 'analyzer_tab');
break
case 'main_settings_tablink':
changeTab(sidebarEl, 'main', 'settings_tab');
break
case 'main_about_tablink':
changeTab(sidebarEl, 'main', 'about_tab');
break
}
}
function handleSearchTabClick(event) {
let targetID = event.target.id;
switch (targetID) {
case 'search_all_tab':
changeTab(event.target, 'search', 'main_search');
break
case 'search_track_tab':
changeTab(event.target, 'search', 'track_search');
break
case 'search_album_tab':
changeTab(event.target, 'search', 'album_search');
break
case 'search_artist_tab':
changeTab(event.target, 'search', 'artist_search');
break
case 'search_playlist_tab':
changeTab(event.target, 'search', 'playlist_search');
break
}
}
function handleFavoritesTabClick(event) {
let targetID = event.target.id;
switch (targetID) {
case 'favorites_playlist_tab':
changeTab(event.target, 'favorites', 'playlist_favorites');
break
case 'favorites_album_tab':
changeTab(event.target, 'favorites', 'album_favorites');
break
case 'favorites_artist_tab':
changeTab(event.target, 'favorites', 'artist_favorites');
break
case 'favorites_track_tab':
changeTab(event.target, 'favorites', 'track_favorites');
break
}
}
function changeTab(sidebarEl, section, tabName) {
windows_stack = [];
currentStack = {};
var i, tabcontent, tablinks;
tabcontent = document.getElementsByClassName(section + '_tabcontent');
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = 'none';
}
tablinks = document.getElementsByClassName(section + '_tablinks');
for (i = 0; i < tablinks.length; i++) {
tablinks[i].classList.remove('active');
}
if (tabName == 'settings_tab' && main_selected != 'settings_tab') {
SettingsTab.settings = { ...SettingsTab.lastSettings };
SettingsTab.spotifyCredentials = { ...SettingsTab.lastCredentials };
SettingsTab.spotifyUser = (' ' + SettingsTab.lastUser).slice(1);
}
document.getElementById(tabName).style.display = 'block';
if ('main' === section) {
main_selected = tabName;
} else if ('search' === section) {
search_selected = tabName;
}
// Not choosing .currentTarget beacuse the event
// is delegated
sidebarEl.classList.add('active');
// Check if you need to load more content in the search tab
if (
main_selected == 'search_tab' &&
['track_search', 'album_search', 'artist_search', 'playlist_search'].indexOf(search_selected) != -1 &&
MainSearch.results[search_selected.split('_')[0] + 'Tab'].data.length == 0
) {
MainSearch.search(search_selected.split('_')[0]);
}
}
function showTab(type, id, back = false) {
if (windows_stack.length == 0) {
windows_stack.push({ tab: main_selected });
} else if (!back) {
windows_stack.push(currentStack);
}
window.tab = type == 'artist' ? 'artist_tab' : 'tracklist_tab';
currentStack = { type: type, id: id };
let tabcontent = document.getElementsByClassName('main_tabcontent');
for (let i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = 'none';
}
document.getElementById(tab).style.display = 'block';
TrackPreview.stopStackedTabsPreview();
}
function backTab() {
if (windows_stack.length == 1) {
document.getElementById(`main_${main_selected}link`).click();
} else {
let tabObj = windows_stack.pop();
if (tabObj.type == 'artist') {
ArtistTab.reset();
} else {
TracklistTab.reset();
}
socket.emit('getTracklist', { type: tabObj.type, id: tabObj.id });
showTab(tabObj.type, tabObj.id, true);
}
TrackPreview.stopStackedTabsPreview();
}
var Tabs = {
linkListeners: linkListeners$2,
artistView,
albumView,
playlistView,
analyzeLink
};
function linkListeners$3() {
document.getElementById('content').addEventListener('scroll', Utils.debounce(handleContentScroll, 100));
document.getElementById('searchbar').addEventListener('keyup', handleSearchBarKeyup);
}
// Load more content when the search page is at the end
function handleContentScroll(event) {
let contentElement = event.target;
if (contentElement.scrollTop + contentElement.clientHeight >= contentElement.scrollHeight) {
if (
main_selected === 'search_tab' &&
['track_search', 'album_search', 'artist_search', 'playlist_search'].indexOf(search_selected) != -1
) {
MainSearch.scrolledSearch(search_selected.split('_')[0]);
}
}
}
function handleSearchBarKeyup(e) {
if (e.keyCode == 13) {
let term = this.value;
if (Utils.isValidURL(term)) {
if (e.ctrlKey) {
QualityModal$1.open(term);
} else {
if (window.main_selected == 'analyzer_tab') {
Tabs.analyzeLink(term);
} else {
Downloads.sendAddToQueue(term);
}
}
} else {
if (term != MainSearch.query || main_selected == 'search_tab') {
document.getElementById('search_tab_content').style.display = 'none';
socket.emit('mainSearch', { term: term });
} else {
document.getElementById('search_all_tab').click();
document.getElementById('search_tab_content').style.display = 'block';
document.getElementById('main_search_tablink').click();
}
}
}
}
var Search = {
linkListeners: linkListeners$3
};
/* ===== Socketio listeners ===== */
// Debug messages for socketio
socket.on('message', function (msg) {
console.log(msg);
});
socket.on('logging_in', function () {
toast('Logging in', 'loading', false, 'login-toast');
});
socket.on('logged_in', function (data) {
switch (data.status) {
case 1:
case 3:
toast('Logged in', 'done', true, 'login-toast');
if (data.arl) {
localStorage.setItem('arl', data.arl);
$('#login_input_arl').val(data.arl);
}
$('#open_login_prompt').hide();
if (data.user) {
$('#settings_username').text(data.user.name);
$('#settings_picture').attr(
'src',
`https://e-cdns-images.dzcdn.net/images/user/${data.user.picture}/125x125-000000-80-0-0.jpg`
);
// $('#logged_in_info').show()
document.getElementById('logged_in_info').classList.remove('hide');
}
break
case 2:
toast('Already logged in', 'done', true, 'login-toast');
if (data.user) {
$('#settings_username').text(data.user.name);
$('#settings_picture').attr(
'src',
`https://e-cdns-images.dzcdn.net/images/user/${data.user.picture}/125x125-000000-80-0-0.jpg`
);
// $('#logged_in_info').show()
document.getElementById('logged_in_info').classList.remove('hide');
}
break
case 0:
toast("Couldn't log in", 'close', true, 'login-toast');
localStorage.removeItem('arl');
$('#login_input_arl').val('');
$('#open_login_prompt').show();
document.getElementById('logged_in_info').classList.add('hide');
// $('#logged_in_info').hide()
$('#settings_username').text('Not Logged');
$('#settings_picture').attr('src', `https://e-cdns-images.dzcdn.net/images/user/125x125-000000-80-0-0.jpg`);
break
}
});
socket.on('logged_out', function () {
toast('Logged out', 'done', true, 'login-toast');
localStorage.removeItem('arl');
$('#login_input_arl').val('');
$('#open_login_prompt').show();
document.getElementById('logged_in_info').classList.add('hide');
// $('#logged_in_info').hide()
$('#settings_username').text('Not Logged');
$('#settings_picture').attr('src', `https://e-cdns-images.dzcdn.net/images/user/125x125-000000-80-0-0.jpg`);
});
/* ===== App initialization ===== */
function startApp() {
Downloads.init();
QualityModal$1.init();
Tabs.linkListeners();
Search.linkListeners();
TrackPreview.init();
document.getElementById('logged_in_info').classList.add('hide');
if (localStorage.getItem('arl')) {
let arl = localStorage.getItem('arl');
socket.emit('login', arl);
$('#login_input_arl').val(arl);
}
if ('true' === localStorage.getItem('slimDownloads')) {
document.getElementById('download_list').classList.add('slim');
}
let spotifyUser = localStorage.getItem('spotifyUser');
if (spotifyUser != '') {
socket.emit('update_userSpotifyPlaylists', spotifyUser);
}
// Open default tab
document.getElementById('main_home_tablink').click();
}
document.addEventListener('DOMContentLoaded', startApp);
//# sourceMappingURL=bundle.js.map