diff --git a/public/css/modules/download-tab.css b/public/css/modules/download-tab.css index d35d2ab..df9d80b 100644 --- a/public/css/modules/download-tab.css +++ b/public/css/modules/download-tab.css @@ -1,16 +1,17 @@ #download_tab_container { - width: 300px; + /* width: 300px; */ height: 100%; background-color: var(--panels-background); color: var(--panels-text); display: block; flex-direction: column; - transition: all 250ms ease-in-out; + /* transition: all 250ms ease-in-out; */ } #toggle_download_tab { width: 25px; height: 25px; + margin-left: 20px; } #toggle_download_tab::before { @@ -134,7 +135,7 @@ } #download_tab_container #download_list { - width: 300px; + /* width: 300px; */ } #download_tab_container #download_tab_label { @@ -143,11 +144,27 @@ transition: all 250ms ease-in-out; } +#download_tab_drag_handler { + width: 15px; + height: 100%; + position: absolute; + background-color: #333; + cursor: ew-resize; +} + /* ===== Hidden tab styles ===== */ #download_tab_container.tab_hidden { width: 32px; } +#download_tab_container.tab_hidden #toggle_download_tab { + margin-left: 4px; +} + +#download_tab_container.tab_hidden #download_tab_drag_handler { + display: none; +} + #download_tab_container.tab_hidden #toggle_download_tab::before { font-family: 'Material Icons'; font-style: normal; diff --git a/public/index.html b/public/index.html index a700eb5..3d3fb4e 100644 --- a/public/index.html +++ b/public/index.html @@ -16,10 +16,10 @@ <body> <aside id="sidebar" role="navigation"> - <span id="main_home_tablink" class="main_tablinks" role="link" aria-label="home"><i - class="material-icons side_icon">home</i><span class="main_tablinks_text">Home</span></span> + <span id="main_home_tablink" class="main_tablinks" role="link" aria-label="home"><i + class="material-icons side_icon">home</i><span class="main_tablinks_text">Home</span></span> <span id="main_search_tablink" class="main_tablinks" role="link" aria-label="search"><i - class="material-icons side_icon">search</i><span class="main_tablinks_text">Search</span></span> + class="material-icons side_icon">search</i><span class="main_tablinks_text">Search</span></span> <span id="main_charts_tablink" class="main_tablinks" role="link" aria-label="charts"><i class="material-icons side_icon">bubble_chart</i><span class="main_tablinks_text">Charts</span></span> <span id="main_favorites_tablink" class="main_tablinks" role="link" aria-label="favorites"><i @@ -160,8 +160,13 @@ <h1>No Tracks found</h1> </tr> <tr v-for="track in results.trackTab.data" class="track_row"> <td style="width: 48px; text-align: center;"> - <a href="#" @click="playPausePreview" v-bind:class="'rounded' + (track.preview ? ' single-cover' : '')" v-bind:data-preview="track.preview"><i @mouseenter="previewMouseEnter" @mouseleave="previewMouseLeave" v-if="track.preview" class="material-icons preview_controls">play_arrow</i><img class="rounded coverart" v-bind:src="track.album.cover_small"> - </td> + <a href="#" @click="playPausePreview" + v-bind:class="'rounded' + (track.preview ? ' single-cover' : '')" + v-bind:data-preview="track.preview"><i @mouseenter="previewMouseEnter" + @mouseleave="previewMouseLeave" v-if="track.preview" + class="material-icons preview_controls">play_arrow</i><img class="rounded coverart" + v-bind:src="track.album.cover_small"> + </td> <td class="breakline">{{track.title + (track.title_version ? ' '+track.title_version : '')}}</td> <td class="breakline clickable" @click="artistView" v-bind:data-id="track.artist.id"> {{track.artist.name}}</td> @@ -257,24 +262,54 @@ <h1>Favorites</h1> </div> <div id="analyzer_tab" class="main_tabcontent"> - <h1>Link Analyzer</h1> - <h1>{{ title }}</h1> + <h1>Link Analyzer</h1> + <h1>{{ title }}</h1> <h2>{{ subtitle }}</h2> - <table> - <tr v-if="data.isrc"><td>ISRC</td><td>{{ data.isrc }}</td></tr> - <tr v-if="data.upc"><td>UPC</td><td>{{ data.upc }}</td></tr> - <tr v-if="data.duration"><td>Duration</td><td>{{ convertDuration(data.duration) }}</td></tr> - <tr v-if="data.disk_number"><td>Disk Number</td><td>{{ data.disk_number }}</td></tr> - <tr v-if="data.track_position"><td>Track Number</td><td>{{ data.track_position }}</td></tr> - <tr v-if="data.release_date"><td>Release Date</td><td>{{ data.release_date }}</td></tr> - <tr v-if="data.bpm"><td>BPM</td><td>{{ data.bpm }}</td></tr> - <tr v-if="data.label"><td>Label</td><td>{{ data.label }}</td></tr> - <tr v-if="data.record_type"><td>Record Type</td><td>{{ data.record_type }}</td></tr> - <tr v-if="data.genres && data.genres.data.length"><td>Genres</td><td>{{ data.genres.data.map(x => x.name).join("; ") }}</td></tr> - </table> - <div v-if="countries.length"> - <p v-for="country in countries">{{ country[0] }} - {{ country[1] }}</p> - </div> + <table> + <tr v-if="data.isrc"> + <td>ISRC</td> + <td>{{ data.isrc }}</td> + </tr> + <tr v-if="data.upc"> + <td>UPC</td> + <td>{{ data.upc }}</td> + </tr> + <tr v-if="data.duration"> + <td>Duration</td> + <td>{{ convertDuration(data.duration) }}</td> + </tr> + <tr v-if="data.disk_number"> + <td>Disk Number</td> + <td>{{ data.disk_number }}</td> + </tr> + <tr v-if="data.track_position"> + <td>Track Number</td> + <td>{{ data.track_position }}</td> + </tr> + <tr v-if="data.release_date"> + <td>Release Date</td> + <td>{{ data.release_date }}</td> + </tr> + <tr v-if="data.bpm"> + <td>BPM</td> + <td>{{ data.bpm }}</td> + </tr> + <tr v-if="data.label"> + <td>Label</td> + <td>{{ data.label }}</td> + </tr> + <tr v-if="data.record_type"> + <td>Record Type</td> + <td>{{ data.record_type }}</td> + </tr> + <tr v-if="data.genres && data.genres.data.length"> + <td>Genres</td> + <td>{{ data.genres.data.map(x => x.name).join("; ") }}</td> + </tr> + </table> + <div v-if="countries.length"> + <p v-for="country in countries">{{ country[0] }} - {{ country[1] }}</p> + </div> </div> <div id="settings_tab" class="main_tabcontent fixed_footer"> @@ -551,10 +586,13 @@ <h2 class="inline-flex"><span v-if="metadata">{{ metadata }}</span><span class=" <tbody> <template v-for="track in body"> <tr v-if="track.type == 'track'"> - <td><i @click=playPausePreview v-bind:class="'material-icons' + (track.preview ? ' preview_playlist_controls' : '')" v-bind:data-preview="track.preview">play_arrow</i></td> + <td><i @click=playPausePreview + v-bind:class="'material-icons' + (track.preview ? ' preview_playlist_controls' : '')" + v-bind:data-preview="track.preview">play_arrow</i></td> <td>{{ track.track_position }}</td> <td class="inline-flex"><i v-if="track.explicit_lyrics" - class="material-icons">explicit</i>{{ track.title + (track.title_version && track.title.indexOf(track.title_version) == -1 ? ' '+track.title_version : '') }} </td> + class="material-icons">explicit</i>{{ track.title + (track.title_version && track.title.indexOf(track.title_version) == -1 ? ' '+track.title_version : '') }} + </td> <td class="clickable" @click="artistView" v-bind:data-id="track.artist.id"> {{ track.artist.name }}</td> <td class="clickable" v-if="type == 'Playlist'" @click="albumView" v-bind:data-id="track.album.id"> @@ -586,8 +624,8 @@ <h2 class="inline-flex"><span v-if="metadata">{{ metadata }}</span><span class=" </div> <div id="download_tab_container" class="tab_hidden"> + <div id="download_tab_drag_handler"></div> <i id="toggle_download_tab" class="material-icons download_bar_icon"></i> - <!-- <div id="queue_buttons" class="right"> --> <div id="queue_buttons"> <i id="clean_queue" class="material-icons download_bar_icon">clear_all</i> <i id="cancel_queue" class="material-icons download_bar_icon">delete_sweep</i> @@ -596,11 +634,11 @@ <h2 class="inline-flex"><span v-if="metadata">{{ metadata }}</span><span class=" </div> </main> - <audio id="preview-track"> - <source id="preview-track_source" src="" type="audio/mpeg"> - </audio> + <audio id="preview-track"> + <source id="preview-track_source" src="" type="audio/mpeg"> + </audio> - <div id="modal_quality" class="smallmodal"> + <div id="modal_quality" class="smallmodal"> <!-- Modal content --> <div class="smallmodal-content"> <button class="quality-button" data-quality-value="9">Download FLAC</button><br> @@ -620,4 +658,4 @@ <h2 class="inline-flex"><span v-if="metadata">{{ metadata }}</span><span class=" <script type="module" src="/public/js/app.js"></script> -</html> +</html> \ No newline at end of file diff --git a/public/js/app.js b/public/js/app.js index 2874d79..bd76e90 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -71,11 +71,11 @@ socket.on('logged_out', function () { /* ===== App initialization ===== */ function startApp() { - Downloads.linkListeners() + Downloads.init() QualityModal.init() Tabs.linkListeners() Search.linkListeners() - initTrackPreview() + initTrackPreview() if (localStorage.getItem('arl')) { let arl = localStorage.getItem('arl') @@ -84,11 +84,6 @@ function startApp() { $('#login_input_arl').val(arl) } - // Check if download tab should be open - if ('true' === localStorage.getItem('downloadTabOpen')) { - document.querySelector('#download_tab_container').classList.remove('tab_hidden') - } - // Open default tab document.getElementById('main_home_tablink').click() } diff --git a/public/js/modules/downloads.js b/public/js/modules/downloads.js index 57644bd..4dc2ff9 100644 --- a/public/js/modules/downloads.js +++ b/public/js/modules/downloads.js @@ -1,14 +1,36 @@ import { socket } from './socket.js' import { toast } from './toasts.js' +import Utils from './utils.js' +/* ===== 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 -const downloadListEl = document.getElementById('download_list') +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() { - downloadListEl.addEventListener('click', handleListClick) + listEl.addEventListener('click', handleListClick) document.getElementById('toggle_download_tab').addEventListener('click', toggleDownloadTab) // Queue buttons @@ -19,6 +41,48 @@ function linkListeners() { 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) { @@ -39,7 +103,7 @@ function addToQueue(queueItem, current = false) { } else { queue.push(queueItem.uuid) } - $(downloadListEl).append( + $(listEl).append( `<div class="download_object" id="download_${queueItem.uuid}" data-deezerid="${queueItem.id}"> <div class="download_info"> <img width="75px" class="rounded coverart" src="${queueItem.cover}" alt="Cover ${queueItem.title}"/> @@ -124,7 +188,16 @@ function handleListClick(event) { function toggleDownloadTab(ev) { ev.preventDefault() - let isHidden = document.querySelector('#download_tab_container').classList.toggle('tab_hidden') + 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) } @@ -141,18 +214,8 @@ function removeFromQueue(uuid) { } } -// Needs: -// 1. socket -// 2. queue -// 3. queueList socket.on('removedFromQueue', removeFromQueue) -// Needs: -// 1. socket -// 2. queue -// 3. queueList -// 4. queueComplete -// 5. toast function finishDownload(uuid) { if (queue.indexOf(uuid) > -1) { toast(`${queueList[uuid].title} finished downloading.`, 'done') @@ -178,18 +241,12 @@ function finishDownload(uuid) { socket.on('finishDownload', finishDownload) -// Needs: -// 1. socket -// 2. queueComplete -// 3. queue -// 4. queueList - function removeAllDownloads(currentItem) { queueComplete = [] if (currentItem == '') { queue = [] queueList = {} - $(downloadListEl).html('') + $(listEl).html('') } else { queue = [currentItem] let tempQueueItem = queueList[currentItem] @@ -203,9 +260,6 @@ function removeAllDownloads(currentItem) { socket.on('removedAllDownloads', removeAllDownloads) -// Needs: -// 1. socket -// 2. queueComplete function removedFinishedDownloads() { queueComplete.forEach(item => { $('#download_' + item).remove() @@ -215,10 +269,6 @@ function removedFinishedDownloads() { socket.on('removedFinishedDownloads', removedFinishedDownloads) -// Needs: -// 1. socket -// 2. queue -// 3. queueList function updateQueue(update) { if (update.uuid && queue.indexOf(update.uuid) > -1) { if (update.downloaded) { @@ -250,7 +300,7 @@ function updateQueue(update) { socket.on('updateQueue', updateQueue) export default { - linkListeners, + init, sendAddToQueue, addToQueue } diff --git a/public/js/modules/link-analyzer-tab.js b/public/js/modules/link-analyzer-tab.js index 2139d31..862f01d 100644 --- a/public/js/modules/link-analyzer-tab.js +++ b/public/js/modules/link-analyzer-tab.js @@ -2,59 +2,59 @@ import { socket } from './socket.js' import { albumView } from './tabs.js' import Utils from './utils.js' -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"} - const LinkAnalyzerTab = new Vue({ data() { return { - title: '', + title: '', subtitle: '', - image: '', + image: '', data: {}, type: '', link: '', - countries: [] + countries: [] } }, methods: { albumView, - convertDuration: Utils.convertDuration, + convertDuration: Utils.convertDuration, reset() { this.title = 'Loading...' this.subtitle = '' - this.image = '' + this.image = '' this.data = {} this.type = '' this.link = '' - this.countries = [] + 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.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(COUNTRIES[cc]) - this.countries.push(temp) - }) - this.data = data + 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) + console.log(data) this.title = data.title - this.subtitle = `by ${data.artist.name}\n${data.nb_tracks} tracks` - this.image = data.cover_xl + 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 + this.data = data } }, mounted() { - socket.on('analyze_track', this.showTrack) + socket.on('analyze_track', this.showTrack) socket.on('analyze_album', this.showAlbum) } }).$mount('#analyzer_tab') diff --git a/public/js/modules/search.js b/public/js/modules/search.js index 3c37334..8024583 100644 --- a/public/js/modules/search.js +++ b/public/js/modules/search.js @@ -32,11 +32,11 @@ export default class Search { if (e.ctrlKey) { QualityModal.open(term) } else { - if (window.main_selected == 'analyzer_tab'){ - analyzeLink(term) - }else{ - Downloads.sendAddToQueue(term) - } + if (window.main_selected == 'analyzer_tab') { + analyzeLink(term) + } else { + Downloads.sendAddToQueue(term) + } } } else { if (term != MainSearch.query || main_selected == 'search_tab') { diff --git a/public/js/modules/tabs.js b/public/js/modules/tabs.js index 39a3cdd..69f6df4 100644 --- a/public/js/modules/tabs.js +++ b/public/js/modules/tabs.js @@ -36,9 +36,9 @@ export function playlistView(ev) { } export function analyzeLink(link) { - console.log("Analyzing: "+link) - LinkAnalyzerTab.reset() - socket.emit('analyzeLink', link) + console.log('Analyzing: ' + link) + LinkAnalyzerTab.reset() + socket.emit('analyzeLink', link) } export class Tabs { @@ -190,7 +190,7 @@ function showTab(type, id, back = false) { tabcontent[i].style.display = 'none' } document.getElementById(tab).style.display = 'block' - stopStackedTabsPreview() + stopStackedTabsPreview() } // Uses: @@ -213,5 +213,5 @@ function backTab() { socket.emit('getTracklist', { type: tabObj.type, id: tabObj.id }) showTab(tabObj.type, tabObj.id, true) } - stopStackedTabsPreview() + stopStackedTabsPreview() } diff --git a/public/js/modules/track-preview.js b/public/js/modules/track-preview.js index 6daa4e7..e662f5f 100644 --- a/public/js/modules/track-preview.js +++ b/public/js/modules/track-preview.js @@ -1,4 +1,3 @@ - /* ===== Globals ====== */ window.preview_max_volume = 1 @@ -7,85 +6,91 @@ let preview_track = document.getElementById('preview-track') let preview_stopped = true // init stuff -export function initTrackPreview(){ - preview_track.volume = 1 - /*preview_max_volume = parseFloat(localStorage.getItem("previewVolume")) +export function initTrackPreview() { + 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) - }) + // 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") - } - }) + // 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 -export 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") - } +export 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 -export function previewMouseEnter(e){ - $(e.currentTarget).css({opacity: 1}) +export function previewMouseEnter(e) { + $(e.currentTarget).css({ opacity: 1 }) } -export function previewMouseLeave(e){ - let obj = e.currentTarget - if (($(obj).parent().attr("playing") && preview_stopped) || !$(obj).parent().attr("playing")){ - $(obj).css({opacity: 0}, 200) - } +export 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 -export function playPausePreview(e){ - e.preventDefault() - console.log("PlayPause") - 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() - }) - } +export function playPausePreview(e) { + e.preventDefault() + console.log('PlayPause') + 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() + }) + } } diff --git a/public/js/modules/utils.js b/public/js/modules/utils.js index c59c4ec..a58bcb4 100644 --- a/public/js/modules/utils.js +++ b/public/js/modules/utils.js @@ -7,7 +7,7 @@ function isValidURL(text) { } function convertDuration(duration) { - //convert from seconds only to mm:ss format + // convert from seconds only to mm:ss format let mm, ss mm = Math.floor(duration / 60) ss = duration - mm * 60 @@ -28,7 +28,7 @@ function convertDurationSeparated(duration) { } function numberWithDots(x) { - return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, '.') + return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, '.') } // On scroll event, returns currentTarget = null @@ -49,10 +49,263 @@ function debounce(func, wait, immediate) { } } +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' +} + export default { isValidURL, convertDuration, convertDurationSeparated, - numberWithDots, - debounce + numberWithDots, + debounce, + COUNTRIES }