1398 lines
63 KiB
HTML
1398 lines
63 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en" dir="ltr" data-theme="light">
|
|
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title>deemix</title>
|
|
<link rel="stylesheet" type="text/css" href="/public/css/style.css">
|
|
<link rel="shortcut icon" href="/public/favicon.ico">
|
|
<meta name="viewport"
|
|
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=0">
|
|
<script>
|
|
if (localStorage.getItem('selectedTheme')) {
|
|
document.documentElement.setAttribute('data-theme', localStorage.getItem('selectedTheme'))
|
|
}
|
|
</script>
|
|
</head>
|
|
|
|
<body>
|
|
<div id="loading_overlay" class="active">
|
|
<span id="loading_text">Connecting to the server...</span>
|
|
<div class="lds-ring">
|
|
<div></div>
|
|
<div></div>
|
|
<div></div>
|
|
<div></div>
|
|
</div>
|
|
</div>
|
|
|
|
<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_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>
|
|
<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 class="material-icons side_icon">album</i>
|
|
<span class="main_tablinks_text">Favorites</span>
|
|
</span>
|
|
<span id="main_analyzer_tablink" class="main_tablinks" role="link" aria-label="link analyzer">
|
|
<i class="material-icons side_icon">link</i>
|
|
<span class="main_tablinks_text">Link
|
|
Analyzer</span>
|
|
</span>
|
|
<span id="main_settings_tablink" class="main_tablinks" role="link" aria-label="settings">
|
|
<i class="material-icons side_icon">settings</i>
|
|
<span class="main_tablinks_text">Settings</span>
|
|
</span>
|
|
<span id="main_about_tablink" class="main_tablinks" role="link" aria-label="info">
|
|
<i class="material-icons side_icon">info</i>
|
|
<span class="main_tablinks_text">Info</span>
|
|
</span>
|
|
<span id="theme_selector" class="main_tablinks" role="link" aria-label="theme selector">
|
|
<i class="material-icons side_icon side_icon--theme">palette</i>
|
|
<div id="theme_togglers">
|
|
<div class="theme_toggler" data-theme-variant="purple"></div>
|
|
<div class="theme_toggler" data-theme-variant="dark"></div>
|
|
<div class="theme_toggler theme_toggler--active" data-theme-variant="light"></div>
|
|
</div>
|
|
</span>
|
|
</aside>
|
|
<main id="main_content">
|
|
<div id="middle_section">
|
|
<header id="search">
|
|
<input id="searchbar" autocomplete="off" type="text" name="searchbar" value=""
|
|
placeholder="Search or paste a link..." autofocus>
|
|
</header>
|
|
<section id="content">
|
|
<div id="container">
|
|
<div id="search_tab" class="main_tabcontent">
|
|
<div :class="{'hide': results.query != ''}">
|
|
<h2>Start searching!</h2>
|
|
<p>
|
|
You can search a track, a whole album, an artist, a playlist.... everything! You can also paste a
|
|
Deezer link
|
|
</p>
|
|
</div>
|
|
<div :class="{'hide': results.query == ''}">
|
|
<div class="tab">
|
|
<button class="search_tablinks" id="search_all_tab">All</button>
|
|
<button class="search_tablinks" id="search_track_tab">Tracks</button>
|
|
<button class="search_tablinks" id="search_album_tab">Album</button>
|
|
<button class="search_tablinks" id="search_artist_tab">Artist</button>
|
|
<button class="search_tablinks" id="search_playlist_tab">Playlist</button>
|
|
</div>
|
|
<div id="search_tab_content">
|
|
<!-- ### Main Search Tab ### -->
|
|
<div id="main_search" class="search_tabcontent">
|
|
<template v-for="section in results.allTab.ORDER">
|
|
<section
|
|
v-if="(section != 'TOP_RESULT' && results.allTab[section].data.length > 0) || (results.allTab[section].length > 0)"
|
|
class="search_section">
|
|
<h2 @click="changeSearchTab(section)" class="search_header"
|
|
:class="{ top_result_header : section === 'TOP_RESULT'}">
|
|
{{ names[section] }}
|
|
</h2>
|
|
<!-- Top result -->
|
|
<div v-if="section == 'TOP_RESULT'" class="top_result clickable" @click="handleClickTopResult"
|
|
:data-id="results.allTab.TOP_RESULT[0].id">
|
|
<div class="cover_container">
|
|
<img aria-hidden="true" :src="results.allTab.TOP_RESULT[0].picture"
|
|
:class="(results.allTab.TOP_RESULT[0].type == 'artist' ? 'circle' : 'rounded') + ' coverart'" />
|
|
<div role="button" aria-label="download" @contextmenu.prevent="openQualityModal"
|
|
@click.stop="addToQueue" :data-link="results.allTab.TOP_RESULT[0].link"
|
|
class="download_overlay">
|
|
<i class="material-icons">get_app</i>
|
|
</div>
|
|
</div>
|
|
<div class="info_box">
|
|
<p class="primary-text">{{ results.allTab.TOP_RESULT[0].title }}</p>
|
|
<p class="secondary-text">
|
|
{{ results.allTab.TOP_RESULT[0].type == 'artist' ? numberWithDots(results.allTab.TOP_RESULT[0].nb_fan) + ' fans' : 'by '+results.allTab.TOP_RESULT[0].artist+' - '+results.allTab.TOP_RESULT[0].nb_song+' tracks'}}
|
|
</p>
|
|
<span
|
|
class="tag">{{ results.allTab.TOP_RESULT[0].type.charAt(0).toUpperCase() + results.allTab.TOP_RESULT[0].type.substring(1)}}</span>
|
|
</div>
|
|
</div>
|
|
<div v-else-if="section == 'TRACK'">
|
|
<table class="table table--tracks">
|
|
<tbody>
|
|
<tr v-for="track in results.allTab.TRACK.data.slice(0, 6)">
|
|
<td class="table__icon" aria-hidden="true">
|
|
<img class="rounded coverart"
|
|
:src="'https://e-cdns-images.dzcdn.net/images/cover/'+track.ALB_PICTURE+'/32x32-000000-80-0-0.jpg'">
|
|
</td>
|
|
<td class="table__cell table__cell--large breakline">
|
|
<div class="table__cell-content table__cell-content--vertical-center">
|
|
<i v-if="track.EXPLICIT_LYRICS == 1" class="material-icons explicit_icon">
|
|
explicit
|
|
</i>
|
|
{{ track.SNG_TITLE + (track.VERSION ? ' ' + track.VERSION : '') }}
|
|
</div>
|
|
</td>
|
|
<td class="table__cell table__cell--medium table__cell--center breakline">
|
|
<span class="clickable" @click="artistView" :data-id="artist.ART_ID"
|
|
v-for="artist in track.ARTISTS">{{artist.ART_NAME}}
|
|
</span>
|
|
</td>
|
|
<td class="table__cell--medium table__cell--center breakline clickable"
|
|
@click="albumView" :data-id="track.ALB_ID">
|
|
{{track.ALB_TITLE}}
|
|
</td>
|
|
<td class="table__cell table__cell--center">
|
|
{{convertDuration(track.DURATION)}}
|
|
</td>
|
|
<td class="table__cell--download table__cell--center clickable"
|
|
@contextmenu.prevent="openQualityModal" @click.stop="addToQueue"
|
|
:data-link="'https://www.deezer.com/track/'+track.SNG_ID" role="button"
|
|
aria-label="download">
|
|
<i class="material-icons">
|
|
get_app
|
|
</i>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div v-else-if="section == 'ARTIST'" class="release_grid firstrow_only">
|
|
<div v-for="release in results.allTab.ARTIST.data.slice(0, 10)" class="release clickable"
|
|
@click="artistView" :data-id="release.ART_ID">
|
|
<div class="cover_container">
|
|
<img aria-hidden="true" class="circle coverart"
|
|
:src="'https://e-cdns-images.dzcdn.net/images/artist/' + release.ART_PICTURE + '/156x156-000000-80-0-0.jpg'">
|
|
<div role="button" aria-label="download" @contextmenu.prevent="openQualityModal"
|
|
@click.stop="addToQueue" :data-link="'https://deezer.com/artist/'+release.ART_ID"
|
|
class="download_overlay"><i class="material-icons">get_app</i></div>
|
|
</div>
|
|
<p class="primary-text">{{ release.ART_NAME }}</p>
|
|
<p class="secondary-text">{{numberWithDots(release.NB_FAN) + ' fans'}}</p>
|
|
</div>
|
|
</div>
|
|
<div v-else-if="section == 'ALBUM'" class="release_grid firstrow_only">
|
|
<div v-for="release in results.allTab.ALBUM.data.slice(0, 10)" class="release clickable"
|
|
@click="albumView" :data-id="release.ALB_ID">
|
|
<div class="cover_container">
|
|
<img aria-hidden="true" class="rounded coverart"
|
|
:src="'https://e-cdns-images.dzcdn.net/images/cover/' + release.ALB_PICTURE + '/156x156-000000-80-0-0.jpg'">
|
|
<div role="button" aria-label="download" @contextmenu.prevent="openQualityModal"
|
|
@click.stop="addToQueue" :data-link="'https://deezer.com/album/'+release.ALB_ID"
|
|
class="download_overlay"><i class="material-icons">get_app</i></div>
|
|
</div>
|
|
<p class="primary-text inline-flex">
|
|
<i v-if="[1, 4].indexOf(release.EXPLICIT_ALBUM_CONTENT.EXPLICIT_LYRICS_STATUS) != -1"
|
|
class="material-icons explicit_icon">explicit</i>
|
|
{{release.ALB_TITLE}}
|
|
</p>
|
|
<p class="secondary-text">{{release.ART_NAME+' - '+release.NUMBER_TRACK+' tracks'}}</p>
|
|
</div>
|
|
</div>
|
|
<div v-else-if="section == 'PLAYLIST'" class="release_grid firstrow_only">
|
|
<div v-for="release in results.allTab.PLAYLIST.data.slice(0, 10)" class="release clickable"
|
|
@click="playlistView" :data-id="release.PLAYLIST_ID">
|
|
<div class="cover_container">
|
|
<img aria-hidden="true" class="rounded coverart"
|
|
:src="'https://e-cdns-images.dzcdn.net/images/'+ release.PICTURE_TYPE +'/' + release.PLAYLIST_PICTURE + '/156x156-000000-80-0-0.jpg'">
|
|
<div role="button" aria-label="download" @contextmenu.prevent="openQualityModal"
|
|
@click.stop="addToQueue" :data-link="'https://deezer.com/playlist/'+release.PLAYLIST_ID"
|
|
class="download_overlay"><i class="material-icons">get_app</i></div>
|
|
</div>
|
|
<p class="primary-text">{{ release.TITLE }}</p>
|
|
<p class="secondary-text">{{release.NB_SONG+' tracks'}}</p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</template>
|
|
<div
|
|
v-if="results.allTab.ORDER.every(section => section == 'TOP_RESULT' ? results.allTab[section].length == 0 : results.allTab[section].data.length == 0)">
|
|
<h1>No results</h1>
|
|
</div>
|
|
</div>
|
|
<!-- ### Track Search Tab ### -->
|
|
<div id="track_search" class="search_tabcontent">
|
|
<div v-if="!results.trackTab.loaded">
|
|
<h1>Loading</h1>
|
|
</div>
|
|
<div v-else-if="results.trackTab.data.length == 0">
|
|
<h1>No Tracks found</h1>
|
|
</div>
|
|
<table class="table table--tracks" v-if="results.trackTab.data.length > 0">
|
|
<thead>
|
|
<tr>
|
|
<th colspan="2">Title</th>
|
|
<th>Artists</th>
|
|
<th>Album</th>
|
|
<th>
|
|
<i class="material-icons">
|
|
timer
|
|
</i>
|
|
</th>
|
|
<th style="width: 56px;"></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr v-for="track in results.trackTab.data">
|
|
<td class="table__icon table__icon--big">
|
|
<a href="#" @click="playPausePreview"
|
|
:class="'rounded' + (track.preview ? ' single-cover' : '')" :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" :src="track.album.cover_small">
|
|
</a>
|
|
</td>
|
|
<td class="table__cell table__cell--large breakline">
|
|
<i v-if="track.explicit_lyrics" class="material-icons explicit_icon">
|
|
explicit
|
|
</i>
|
|
{{ track.title + (track.title_version && track.title.indexOf(track.title_version) == -1 ? ' '+ track.title_version : '') }}
|
|
</td>
|
|
<td class="table__cell table__cell--medium table__cell--center breakline clickable"
|
|
@click="artistView" :data-id="track.artist.id">
|
|
{{track.artist.name}}
|
|
</td>
|
|
<td class="table__cell table__cell--medium table__cell--center breakline clickable"
|
|
@click="albumView" :data-id="track.album.id">
|
|
{{track.album.title}}
|
|
</td>
|
|
<td class="table__cell table__cell--small table__cell--center">
|
|
{{convertDuration(track.duration)}}
|
|
</td>
|
|
<td class="table__cell--download table__cell--center clickable"
|
|
@contextmenu.prevent="openQualityModal" @click.stop="addToQueue" :data-link="track.link"
|
|
role="button" aria-label="download">
|
|
<i class="material-icons">
|
|
get_app
|
|
</i>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<!-- ### Album Search Tab ### -->
|
|
<div id="album_search" class="search_tabcontent">
|
|
<div v-if="!results.albumTab.loaded">
|
|
<h1>Loading</h1>
|
|
</div>
|
|
<div v-else-if="results.albumTab.data.length == 0">
|
|
<h1>No Albums found</h1>
|
|
</div>
|
|
<div class="release_grid" v-if="results.albumTab.data.length > 0">
|
|
<div v-for="release in results.albumTab.data" class="release clickable" @click="albumView"
|
|
:data-id="release.id">
|
|
<div class="cover_container">
|
|
<img aria-hidden="true" class="rounded coverart" :src="release.cover_medium">
|
|
<div role="button" aria-label="download" @contextmenu.prevent="openQualityModal"
|
|
@click.stop="addToQueue" :data-link="release.link" class="download_overlay"><i
|
|
class="material-icons">get_app</i></div>
|
|
</div>
|
|
<p class="primary-text inline-flex">
|
|
<i v-if="release.explicit_lyrics" class="material-icons explicit_icon">explicit</i>
|
|
{{ release.title }}
|
|
</p>
|
|
<p class="secondary-text">{{ 'by '+release.artist.name+' - '+release.nb_tracks+' tracks' }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- ### Artist Search Tab ### -->
|
|
<div id="artist_search" class="search_tabcontent">
|
|
<div v-if="!results.artistTab.loaded">
|
|
<h1>Loading</h1>
|
|
</div>
|
|
<div v-else-if="results.artistTab.data.length == 0">
|
|
<h1>No Artists found</h1>
|
|
</div>
|
|
<div class="release_grid" v-if="results.artistTab.data.length > 0">
|
|
<div v-for="release in results.artistTab.data" class="release clickable" @click="artistView"
|
|
:data-id="release.id">
|
|
<div class="cover_container">
|
|
<img aria-hidden="true" class="circle coverart" :src="release.picture_medium">
|
|
<div role="button" aria-label="download" @contextmenu.prevent="openQualityModal"
|
|
@click.stop="addToQueue" :data-link="release.link" class="download_overlay"><i
|
|
class="material-icons">get_app</i></div>
|
|
</div>
|
|
<p class="primary-text">{{ release.name }}</p>
|
|
<p class="secondary-text">{{ release.nb_album + ' releases' }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- ### Playlist Search Tab ### -->
|
|
<div id="playlist_search" class="search_tabcontent">
|
|
<div v-if="!results.playlistTab.loaded">
|
|
<h1>Loading</h1>
|
|
</div>
|
|
<div v-else-if="results.playlistTab.data.length == 0">
|
|
<h1>No Playlists found</h1>
|
|
</div>
|
|
<div class="release_grid" v-if="results.playlistTab.data.length > 0">
|
|
<div v-for="release in results.playlistTab.data" class="release clickable" @click="playlistView"
|
|
:data-id="release.id">
|
|
<div class="cover_container">
|
|
<img aria-hidden="true" class="rounded coverart" :src="release.picture_medium">
|
|
<div role="button" aria-label="download" @contextmenu.prevent="openQualityModal"
|
|
@click.stop="addToQueue" :data-link="release.link" class="download_overlay"><i
|
|
class="material-icons">get_app</i></div>
|
|
</div>
|
|
<p class="primary-text">{{ release.title }}</p>
|
|
<p class="secondary-text">{{ 'by '+release.user.name+' - '+release.nb_tracks+' tracks' }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="home_tab" class="main_tabcontent">
|
|
<h2 class="page_heading">Welcome to deemix</h2>
|
|
<section id="home_not_logged_in" class="home_section" ref="notLogged">
|
|
<p id="home_not_logged_text">You need to log into your deezer account before you can start downloading.
|
|
</p>
|
|
<button type="button" name="button" @click="openSettings">Open Settings</button>
|
|
</section>
|
|
<section v-if="playlists.length" class="home_section">
|
|
<h3 class="section_heading">Popular playlists</h3>
|
|
<div class="release_grid">
|
|
<div v-for="release in playlists" class="release clickable" @click="playlistView"
|
|
:data-id="release.id">
|
|
<div class="cover_container">
|
|
<img aria-hidden="true" class="rounded coverart" :src="release.picture_medium">
|
|
<div role="button" aria-label="download" @contextmenu.prevent="openQualityModal"
|
|
@click.stop="addToQueue" :data-link="release.link" class="download_overlay"><i
|
|
class="material-icons">get_app</i></div>
|
|
</div>
|
|
<p class="primary-text">{{ release.title }}</p>
|
|
<p class="secondary-text">{{ 'by '+release.user.name+' - '+release.nb_tracks+' tracks' }}</p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<section v-if="albums.length" class="home_section">
|
|
<h3 class="section_heading">Most streamed albums</h3>
|
|
<div class="release_grid">
|
|
<div v-for="release in albums" class="release clickable" @click="albumView" :data-id="release.id">
|
|
<div class="cover_container">
|
|
<img aria-hidden="true" class="rounded coverart" :src="release.cover_medium">
|
|
<div role="button" aria-label="download" @contextmenu.prevent="openQualityModal"
|
|
@click.stop="addToQueue" :data-link="release.link" class="download_overlay"><i
|
|
class="material-icons">get_app</i></div>
|
|
</div>
|
|
<p class="primary-text">{{ release.title }}</p>
|
|
<p class="secondary-text">{{ 'by '+release.artist.name }}</p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
|
|
<div id="charts_tab" class="main_tabcontent">
|
|
<h2 class="page_heading">Charts</h2>
|
|
<div v-if='country === ""' id="charts_selection">
|
|
<div class="release_grid charts_grid">
|
|
|
|
<!-- Ugly af -->
|
|
<template v-for="release in countries">
|
|
<div role="button" :aria-label="release.title" v-if="release.title === 'Worldwide'"
|
|
class="release clickable" @click="getTrackList" :data-title="release.title" :data-id="release.id"
|
|
:key="release.id">
|
|
<img class="rounded coverart" :src="release.picture_medium">
|
|
</div>
|
|
</template>
|
|
|
|
<template v-for="release in countries">
|
|
<div role="button" :aria-label="release.title" v-if="release.title !== 'Worldwide'"
|
|
class="release clickable" @click="getTrackList" :data-title="release.title" :data-id="release.id"
|
|
:key="release.id">
|
|
<img class="rounded coverart" :src="release.picture_medium">
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
<div v-else id="charts_table">
|
|
<button @click="changeCountry">Change Country</button>
|
|
<button @contextmenu.prevent="openQualityModal" @click.stop="addToQueue"
|
|
:data-link="'https://www.deezer.com/playlist/'+id">Download Chart</button>
|
|
<table class="table table--charts">
|
|
<tbody>
|
|
<tr v-for="track in chart" class="track_row">
|
|
<td class="top-tracks-position" :class="{ first: track.position === 1 }">
|
|
{{ track.position }}
|
|
</td>
|
|
<td class="table__icon table__icon--big">
|
|
<a href="#" @click="playPausePreview" class="rounded"
|
|
:class="{ 'single-cover' : track.preview }" :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" :src="track.album.cover_small">
|
|
</a>
|
|
</td>
|
|
<td class="table__cell--large breakline">
|
|
{{ track.title + (track.title_version && track.title.indexOf(track.title_version) == -1 ? ' '+ track.title_version : '') }}
|
|
</td>
|
|
<td class="table__cell--medium table__cell--center breakline clickable" @click="artistView"
|
|
:data-id="track.artist.id">
|
|
{{track.artist.name}}
|
|
</td>
|
|
<td class="table__cell--medium table__cell--center breakline clickable" @click="albumView"
|
|
:data-id="track.album.id">
|
|
{{track.album.title}}
|
|
</td>
|
|
<td class="table__cell--small table__cell--center">
|
|
{{convertDuration(track.duration)}}
|
|
</td>
|
|
<td class="table__cell--download" @contextmenu.prevent="openQualityModal" @click.stop="addToQueue"
|
|
:data-link="track.link" role="button" aria-label="download">
|
|
<i class="material-icons">get_app</i>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="favorites_tab" class="main_tabcontent">
|
|
<h1>Favorites</h1>
|
|
<div class="tab">
|
|
<button class="favorites_tablinks" id="favorites_playlist_tab">Playlists</button>
|
|
<button class="favorites_tablinks" id="favorites_album_tab">Albums</button>
|
|
<button class="favorites_tablinks" id="favorites_artist_tab">Artists</button>
|
|
<button class="favorites_tablinks" id="favorites_track_tab">Tracks</button>
|
|
</div>
|
|
<div id="playlist_favorites" class="favorites_tabcontent">
|
|
<div v-if="playlists.length == 0">
|
|
<h1>No Playlists found</h1>
|
|
</div>
|
|
<div class="release_grid" v-if="playlists.length > 0 || spotifyPlaylists > 0">
|
|
<div v-for="release in playlists" class="release clickable" @click="playlistView"
|
|
:data-id="release.id">
|
|
<div class="cover_container">
|
|
<img aria-hidden="true" class="rounded coverart" :src="release.picture_medium">
|
|
<div role="button" aria-label="download" @contextmenu.prevent="openQualityModal"
|
|
@click.stop="addToQueue" :data-link="release.link" class="download_overlay"><i
|
|
class="material-icons">get_app</i></div>
|
|
</div>
|
|
<p class="primary-text">{{ release.title }}</p>
|
|
<p class="secondary-text">{{ 'by '+release.creator.name+' - '+release.nb_tracks+' tracks' }}</p>
|
|
</div>
|
|
<div v-for="release in spotifyPlaylists" class="release clickable" @click="spotifyPlaylistView"
|
|
:data-id="release.id">
|
|
<div class="cover_container">
|
|
<img aria-hidden="true" class="rounded coverart" :src="release.picture_medium">
|
|
<div role="button" aria-label="download" @contextmenu.prevent="openQualityModal"
|
|
@click.stop="addToQueue" :data-link="release.link" class="download_overlay"><i
|
|
class="material-icons">get_app</i></div>
|
|
</div>
|
|
<p class="primary-text">{{ release.title }}</p>
|
|
<p class="secondary-text">{{ 'by '+release.creator.name+' - '+release.nb_tracks+' tracks' }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="album_favorites" class="favorites_tabcontent">
|
|
<div v-if="albums.length == 0">
|
|
<h1>No Favorite Albums found</h1>
|
|
</div>
|
|
<div class="release_grid" v-if="albums.length > 0">
|
|
<div v-for="release in albums" class="release clickable" @click="albumView" :data-id="release.id">
|
|
<div class="cover_container">
|
|
<img aria-hidden="true" class="rounded coverart" :src="release.cover_medium">
|
|
<div role="button" aria-label="download" @contextmenu.prevent="openQualityModal"
|
|
@click.stop="addToQueue" :data-link="release.link" class="download_overlay"><i
|
|
class="material-icons">get_app</i></div>
|
|
</div>
|
|
<p class="primary-text">{{ release.title }}</p>
|
|
<p class="secondary-text">{{ 'by '+release.artist.name }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="artist_favorites" class="favorites_tabcontent">
|
|
<div v-if="artists.length == 0">
|
|
<h1>No Favorite Artist found</h1>
|
|
</div>
|
|
<div class="release_grid" v-if="artists.length > 0">
|
|
<div v-for="release in artists" class="release clickable" @click="artistView" :data-id="release.id">
|
|
<div class="cover_container">
|
|
<img aria-hidden="true" class="circle coverart" :src="release.picture_medium">
|
|
<div role="button" aria-label="download" @contextmenu.prevent="openQualityModal"
|
|
@click.stop="addToQueue" :data-link="release.link" class="download_overlay"><i
|
|
class="material-icons">get_app</i></div>
|
|
</div>
|
|
<p class="primary-text">{{ release.name }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="track_favorites" class="favorites_tabcontent">
|
|
<div v-if="tracks.length == 0">
|
|
<h1>No Favorite Tracks found</h1>
|
|
</div>
|
|
<table v-if="tracks.length > 0" class="table">
|
|
<tr v-for="track in tracks" class="track_row">
|
|
<td class="top-tracks-position" :class="{ first: track.position === 1 }">
|
|
{{ track.position }}
|
|
</td>
|
|
<td>
|
|
<a href="#" class="rounded" :class="{ 'single-cover' : !!track.preview }"
|
|
@click="playPausePreview" :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" :src="track.album.cover_small">
|
|
</a>
|
|
</td>
|
|
<td class="table__cell--large breakline">
|
|
{{ track.title + (track.title_version && track.title.indexOf(track.title_version) == -1 ? ' '+ track.title_version : '') }}
|
|
</td>
|
|
<td class="table__cell--medium table__cell--center breakline clickable" @click="artistView"
|
|
:data-id="track.artist.id">
|
|
{{track.artist.name}}
|
|
</td>
|
|
<td class="table__cell--medium table__cell--center breakline clickable" @click="albumView"
|
|
:data-id="track.album.id">
|
|
{{track.album.title}}
|
|
</td>
|
|
<td class="table__cell--small">
|
|
{{convertDuration(track.duration)}}
|
|
</td>
|
|
<td class="table__cell--download clickable" @contextmenu.prevent="openQualityModal"
|
|
@click.stop="addToQueue" :data-link="track.link" role="button" aria-label="download">
|
|
<div class="table__cell-content table__cell-content--vertical-center">
|
|
<i class="material-icons">get_app</i>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="analyzer_tab" class="main_tabcontent image_header">
|
|
<h1>Link Analyzer</h1>
|
|
<div v-if="link == ''">
|
|
<p>You can use this section to find out more information about the link you are trying to
|
|
download<br />This is usefull if you're trying to download some tracks that are not available in your
|
|
country and want to know where they are available</p>
|
|
</div>
|
|
<div v-else-if="link == 'error'">
|
|
<h2>This link is not supported</h2>
|
|
<p>Seems like this link is not yet supported, try analyzing another one.</p>
|
|
</div>
|
|
<div v-else>
|
|
<header class="inline-flex"
|
|
:style="{ 'background-image': 'linear-gradient(to bottom, transparent 0%, var(--main-background) 100%), url(\''+image+'\')' }">
|
|
<div>
|
|
<h1>{{ title }}</h1>
|
|
<h2 v-if="type == 'track'">by <span class="clickable" @click="artistView"
|
|
:data-id="data.artist.id">{{data.artist.name}}</span> • in <span class="clickable"
|
|
@click="albumView" :data-id="data.album.id">{{data.album.title}}</span></h2>
|
|
<h2 v-else-if="type == 'album'">by <span class="clickable" @click="artistView"
|
|
:data-id="data.artist.id">{{data.artist.name}}</span> • {{data.nb_tracks}} tracks</h2>
|
|
</div>
|
|
<div role="button" aria-label="download" @contextmenu.prevent="openQualityModal"
|
|
@click.stop="addToQueue" :data-link="link" class="fab right"><i class="material-icons">get_app</i>
|
|
</div>
|
|
</header>
|
|
<table class="table">
|
|
<tr v-if="data.id">
|
|
<td>ID</td>
|
|
<td>{{ data.id }}</td>
|
|
</tr>
|
|
<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="type == 'album'">
|
|
<button @click="albumView" :data-id="id">Tracklist</button>
|
|
</div>
|
|
<div v-if="countries.length">
|
|
<p v-for="country in countries">{{ country[0] }} - {{ country[1] }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="settings_tab" class="main_tabcontent fixed_footer">
|
|
<h2 class="page_heading">Settings</h2>
|
|
|
|
<div id="logged_in_info" ref="loggedInInfo">
|
|
<img id="settings_picture" src="" alt="Profile Picture" ref="userpicture" class="circle" />
|
|
<p>You are logged in as <strong id="settings_username" ref="username"></strong></p>
|
|
<button id="settings_btn_logout" @click="logout">Logout</button>
|
|
<select v-if="accounts.length" id="family_account" v-model="accountNum" @change="changeAccount">
|
|
<option v-for="(account, i) in accounts" :value="i.toString()">{{ account.BLOG_NAME }}</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="settings-group">
|
|
<h3 class="settings-group__header settings-group__header--with-icon">
|
|
<i class="material-icons">person</i>Login
|
|
</h3>
|
|
<div class="inline-flex">
|
|
<input autocomplete="off" type="password" id="login_input_arl" ref="loginInput" placeholder="ARL" />
|
|
<button id="settings_btn_copyArl" @click="copyARLtoClipboard">
|
|
<i class="material-icons">assignment</i>
|
|
</button>
|
|
</div>
|
|
<a href="https://notabug.org/RemixDevs/DeezloaderRemix/wiki/Login+via+userToken" target="_blank">
|
|
How do I get my own ARL?
|
|
</a>
|
|
<button id="settings_btn_updateArl" @click="login" style="width:100%;">Update ARL</button>
|
|
</div>
|
|
|
|
<div class="settings-group">
|
|
<h3 class="settings-group__header settings-group__header--with-icon">
|
|
<i class="material-icons">web</i>Appearance
|
|
</h3>
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="changeSlimDownloads">
|
|
<span class="checkbox_text">Slim download tab</span>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="settings-group">
|
|
<h3 class="settings-group__header settings-group__header--with-icon">
|
|
<i class="material-icons">folder</i>Download Path
|
|
</h3>
|
|
<input type="text" v-model="settings.downloadLocation">
|
|
</div>
|
|
|
|
<div class="settings-group">
|
|
<h3 class="settings-group__header settings-group__header--with-icon">
|
|
<i class="material-icons">font_download</i>Templates
|
|
</h3>
|
|
|
|
<p>Trackname template</p>
|
|
<input type="text" v-model="settings.tracknameTemplate">
|
|
|
|
<p>Album track template</p>
|
|
<input type="text" v-model="settings.albumTracknameTemplate">
|
|
|
|
<p>Playlist track template</p>
|
|
<input type="text" v-model="settings.playlistTracknameTemplate">
|
|
</div>
|
|
|
|
<div class="settings-group">
|
|
<h3 class="settings-group__header settings-group__header--with-icon">
|
|
<i class="material-icons">create_new_folder</i>Folders
|
|
</h3>
|
|
<div class="settings-container">
|
|
<div class="settings-container__third">
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.createPlaylistFolder">
|
|
<span class="checkbox_text">Create folder for playlist</span>
|
|
</label>
|
|
<div class="input_group" v-if="settings.createPlaylistFolder">
|
|
<p class="input_group_text">Playlist folder template</p>
|
|
<input type="text" v-model="settings.playlistNameTemplate">
|
|
</div>
|
|
</div>
|
|
<div class="settings-container__third">
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.createArtistFolder">
|
|
<span class="checkbox_text">Create folder for artist</span>
|
|
</label>
|
|
|
|
<div class="input_group" v-if="settings.createArtistFolder">
|
|
<p class="input_group_text">Artist folder template</p>
|
|
<input type="text" v-model="settings.artistNameTemplate">
|
|
</div>
|
|
</div>
|
|
<div class="settings-container__third">
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.createAlbumFolder">
|
|
<span class="checkbox_text">Create folder for album</span>
|
|
</label>
|
|
|
|
<div class="input_group" v-if="settings.createAlbumFolder">
|
|
<p class="input_group_text">Album folder template</p>
|
|
<input type="text" v-model="settings.albumNameTemplate">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.createCDFolder">
|
|
<span class="checkbox_text">Create folder for CDs</span>
|
|
</label>
|
|
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.createStructurePlaylist">
|
|
<span class="checkbox_text">Create folder structure for playlists</span>
|
|
</label>
|
|
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.createSingleFolder">
|
|
<span class="checkbox_text">Create folder structure for singles</span>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="settings-group">
|
|
<h3 class="settings-group__header settings-group__header--with-icon">
|
|
<i class="material-icons">title</i>Track titles
|
|
</h3>
|
|
|
|
<div class="settings-container">
|
|
<div class="settings-container__third settings-container__third--only-checkbox">
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.padTracks">
|
|
<span class="checkbox_text">Pad tracks</span>
|
|
</label>
|
|
</div>
|
|
<div class="settings-container__third">
|
|
<div class="input_group">
|
|
<p class="input_group_text">Overwrite padding size</p>
|
|
<input type="number" v-model="settings.paddingSize">
|
|
</div>
|
|
</div>
|
|
<div class="settings-container__third">
|
|
<div class="input_group">
|
|
<p class="input_group_text">Illegal Character replacer</p>
|
|
<input type="text" v-model="settings.illegalCharacterReplacer">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="settings-group">
|
|
<h3 class="settings-group__header settings-group__header--with-icon">
|
|
<i class="material-icons">get_app</i>Downloads
|
|
</h3>
|
|
|
|
<div class="input_group">
|
|
<p class="input_group_text">Concurrent Downloads</p>
|
|
<input type="number" v-model.number="settings.queueConcurrency">
|
|
</div>
|
|
|
|
<div class="input_group">
|
|
<p class="input_group_text">Preferred Bitrate</p>
|
|
<select v-model="settings.maxBitrate">
|
|
<option value="9">FLAC 1411kbps</option>
|
|
<option value="3">MP3 320kbps</option>
|
|
<option value="1">MP3 128kbps</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="input_group">
|
|
<p class="input_group_text">Should I overwrite the files?</p>
|
|
<select v-model="settings.overwriteFile">
|
|
<option value="y">Yes, overwrite the file</option>
|
|
<option value="n">No, don't overwrite the file</option>
|
|
<option value="t">Overwrite only the tags</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="settings-container">
|
|
<div class="settings-container__third settings-container__third--only-checkbox">
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.fallbackBitrate">
|
|
<span class="checkbox_text">Bitrate fallback</span>
|
|
</label>
|
|
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.fallbackSearch">
|
|
<span class="checkbox_text">Search fallback</span>
|
|
</label>
|
|
</div>
|
|
<div class="settings-container__third settings-container__third--only-checkbox">
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.logErrors">
|
|
<span class="checkbox_text">Create log file for errors</span>
|
|
</label>
|
|
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.logSearched">
|
|
<span class="checkbox_text">Create log file for searched tracks</span>
|
|
</label>
|
|
</div>
|
|
<div class="settings-container__third settings-container__third--only-checkbox">
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.createM3U8File">
|
|
<span class="checkbox_text">Create playlist file</span>
|
|
</label>
|
|
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.syncedLyrics">
|
|
<span class="checkbox_text">Create .lyr files (Sync Lyrics)</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.saveDownloadQueue">
|
|
<span class="checkbox_text">Save download queue when closing the app</span>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="settings-group">
|
|
<h3 class="settings-group__header settings-group__header--with-icon">
|
|
<i class="material-icons">album</i>Album covers
|
|
</h3>
|
|
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.saveArtwork">
|
|
<span class="checkbox_text">Save covers</span>
|
|
</label>
|
|
|
|
<div class="input_group" v-if="settings.saveArtwork">
|
|
<p class="input_group_text">Cover name template</p>
|
|
<input type="text" v-model="settings.coverImageTemplate">
|
|
</div>
|
|
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.saveArtworkArtist">
|
|
<span class="checkbox_text">Save artist image</span>
|
|
</label>
|
|
|
|
<div class="input_group" v-if="settings.saveArtworkArtist">
|
|
<p class="input_group_text">Artist image name template</p>
|
|
<input type="text" v-model="settings.artistImageTemplate">
|
|
</div>
|
|
|
|
<div class="input_group">
|
|
<p class="input_group_text">Local artwork size</p>
|
|
<input type="number" min="100" max="1800" step="100" v-model.number="settings.localArtworkSize">
|
|
</div>
|
|
|
|
<div class="input_group">
|
|
<p class="input_group_text">Embedded artwork size</p>
|
|
<input type="number" min="100" max="1800" step="100" v-model.number="settings.embeddedArtworkSize">
|
|
</div>
|
|
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.PNGcovers">
|
|
<span class="checkbox_text">Save images as png</span>
|
|
</label>
|
|
|
|
<div class="input_group">
|
|
<p class="input_group_text">JPEG image quality</p>
|
|
<input type="number" min="1" max="100" v-model.number="settings.jpegImageQuality">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="settings-group">
|
|
<h3 class="settings-group__header settings-group__header--with-icon">
|
|
<i class="material-icons" style="width: 1em; height: 1em;">bookmarks</i>Which tags to save
|
|
</h3>
|
|
|
|
<div class="settings-container">
|
|
<div class="settings-container__half">
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.tags.title">
|
|
<span class="checkbox_text">Title</span>
|
|
</label>
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.tags.artist">
|
|
<span class="checkbox_text">Artists</span>
|
|
</label>
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.tags.album">
|
|
<span class="checkbox_text">Album</span>
|
|
</label>
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.tags.cover">
|
|
<span class="checkbox_text">Cover</span>
|
|
</label>
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.tags.trackNumber">
|
|
<span class="checkbox_text">Track Number</span>
|
|
</label>
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.tags.trackTotal">
|
|
<span class="checkbox_text">Track Total</span>
|
|
</label>
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.tags.discNumber">
|
|
<span class="checkbox_text">Disc Number</span>
|
|
</label>
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.tags.discTotal">
|
|
<span class="checkbox_text">Disc Total</span>
|
|
</label>
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.tags.albumArtist">
|
|
<span class="checkbox_text">Album Artist</span>
|
|
</label>
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.tags.genre">
|
|
<span class="checkbox_text">Genre</span>
|
|
</label>
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.tags.year">
|
|
<span class="checkbox_text">Year</span>
|
|
</label>
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.tags.date">
|
|
<span class="checkbox_text">Date</span>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="settings-container__half">
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.tags.explicit">
|
|
<span class="checkbox_text">Explicit Lyrics</span>
|
|
</label>
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.tags.isrc">
|
|
<span class="checkbox_text">ISRC</span>
|
|
</label>
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.tags.length">
|
|
<span class="checkbox_text">Track Length</span>
|
|
</label>
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.tags.barcode">
|
|
<span class="checkbox_text">Album Barcode (UPC)</span>
|
|
</label>
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.tags.bpm">
|
|
<span class="checkbox_text">BPM</span>
|
|
</label>
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.tags.replayGain">
|
|
<span class="checkbox_text">Replay Gain</span>
|
|
</label>
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.tags.label">
|
|
<span class="checkbox_text">Album Label</span>
|
|
</label>
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.tags.lyrics">
|
|
<span class="checkbox_text">Unsynchronized Lyrics</span>
|
|
</label>
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.tags.copyright">
|
|
<span class="checkbox_text">Copyright</span>
|
|
</label>
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.tags.composer">
|
|
<span class="checkbox_text">Composer</span>
|
|
</label>
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.tags.involvedPeople">
|
|
<span class="checkbox_text">Involved People</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="settings-group">
|
|
<h3 class="settings-group__header settings-group__header--with-icon">
|
|
<i class="material-icons">list</i>Other
|
|
</h3>
|
|
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.tags.savePlaylistAsCompilation">
|
|
<span class="checkbox_text">Save playlists as compilation</span>
|
|
</label>
|
|
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.tags.useNullSeparator">
|
|
<span class="checkbox_text">Use null separator</span>
|
|
</label>
|
|
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.tags.saveID3v1">
|
|
<span class="checkbox_text">Save ID3v1 as well</span>
|
|
</label>
|
|
|
|
<div class="input_group">
|
|
<p class="input_group_text">How would you like to separate your artists?</p>
|
|
<select v-model="settings.tags.multitagSeparator">
|
|
<option value="default">Using standard specification</option>
|
|
<option value="andFeat">Using & and feat.</option>
|
|
<option value=" & ">Using " & "</option>
|
|
<option value=",">Using ","</option>
|
|
<option value=", ">Using ", "</option>
|
|
<option value="/">Using "/"</option>
|
|
<option value=" / ">Using "/ "</option>
|
|
<option value=";">Using ";"</option>
|
|
<option value="; ">Using "; "</option>
|
|
</select>
|
|
</div>
|
|
|
|
<label class="with_checkbox">
|
|
<input type="checkbox" v-model="settings.removeAlbumVersion">
|
|
<span class="checkbox_text">Remove album version from track title</span>
|
|
</label>
|
|
|
|
<div class="input_group">
|
|
<p class="input_group_text">Date format for FLAC files</p>
|
|
<select v-model="settings.dateFormat">
|
|
<option value="Y-M-D">YYYY-MM-DD</option>
|
|
<option value="Y-D-M">YYYY-DD-MM</option>
|
|
<option value="D-M-Y">DD-MM-YYYY</option>
|
|
<option value="M-D-Y">MM-DD-YYYY</option>
|
|
<option value="Y">YYYY</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="input_group">
|
|
<p class="input_group_text">What should I do with featured artists?</p>
|
|
<select v-model="settings.featuredToTitle">
|
|
<option value="0">Nothing</option>
|
|
<option value="1">Remove it from the title</option>
|
|
<option value="2">Move it to the title</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="input_group">
|
|
<p class="input_group_text">Title casing</p>
|
|
<select v-model="settings.titleCasing">
|
|
<option value="nothing">Keep unchanged</option>
|
|
<option value="lower">lowercase</option>
|
|
<option value="upper">UPPERCASE</option>
|
|
<option value="start">Start Of Each Word</option>
|
|
<option value="sentence">Like a sentence</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="input_group">
|
|
<p class="input_group_text">Artist casing</p>
|
|
<select v-model="settings.artistCasing">
|
|
<option value="nothing">Keep unchanged</option>
|
|
<option value="lower">lowercase</option>
|
|
<option value="upper">UPPERCASE</option>
|
|
<option value="start">Start Of Each Word</option>
|
|
<option value="sentence">Like a sentence</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="input_group">
|
|
<p class="input_group_text">Preview Volume</p>
|
|
<input type="range" @change="updateMaxVolume" min="0" max="100" step="1" class="slider"
|
|
v-model.number="previewVolume.preview_max_volume">
|
|
<span>{{previewVolume.preview_max_volume}}%</span>
|
|
</div>
|
|
|
|
<div class="input_group">
|
|
<p class="input_group_text">Command to execute after download</p>
|
|
<p class="secondary-text">Leave blank for no action</p>
|
|
<input type="text" v-model="settings.executeCommand">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="settings-group">
|
|
<h3 class="settings-group__header settings-group__header--with-icon">
|
|
<svg id="spotify-icon" enable-background="new 0 0 24 24" viewBox="0 0 24 24"
|
|
xmlns="http://www.w3.org/2000/svg">
|
|
<path
|
|
d="m12 24c6.624 0 12-5.376 12-12s-5.376-12-12-12-12 5.376-12 12 5.376 12 12 12zm4.872-6.344v.001c-.807 0-3.356-2.828-10.52-1.36-.189.049-.436.126-.576.126-.915 0-1.09-1.369-.106-1.578 3.963-.875 8.013-.798 11.467 1.268.824.526.474 1.543-.265 1.543zm1.303-3.173c-.113-.03-.08.069-.597-.203-3.025-1.79-7.533-2.512-11.545-1.423-.232.063-.358.126-.576.126-1.071 0-1.355-1.611-.188-1.94 4.716-1.325 9.775-.552 13.297 1.543.392.232.547.533.547.953-.005.522-.411.944-.938.944zm-13.627-7.485c4.523-1.324 11.368-.906 15.624 1.578 1.091.629.662 2.22-.498 2.22l-.001-.001c-.252 0-.407-.063-.625-.189-3.443-2.056-9.604-2.549-13.59-1.436-.175.048-.393.125-.625.125-.639 0-1.127-.499-1.127-1.142 0-.657.407-1.029.842-1.155z" />
|
|
</svg>
|
|
Spotify Features
|
|
</h3>
|
|
|
|
<div class="input_group">
|
|
<p class="input_group_text">Spotify clientID</p>
|
|
<input type="text" v-model="spotifyFeatures.clientId">
|
|
</div>
|
|
|
|
<div class="input_group">
|
|
<p class="input_group_text">Spotify Client Secret</p>
|
|
<input type="password" v-model="spotifyFeatures.clientSecret">
|
|
</div>
|
|
|
|
<div class="input_group">
|
|
<p class="input_group_text">Spotify username</p>
|
|
<input type="text" v-model="spotifyUser">
|
|
</div>
|
|
</div>
|
|
|
|
<footer>
|
|
<button @click="resetSettings">Reset to Default</button>
|
|
<button @click="saveSettings">Save</button>
|
|
</footer>
|
|
</div>
|
|
|
|
<div id="about_tab" class="main_tabcontent">
|
|
<h1>About</h1>
|
|
<p>
|
|
This app uses the <a href="https://deemix.app" target="_blank">deemix</a> library, you can use this
|
|
library to make your own UI for deemix.</br>
|
|
Here's the <a href="https://notabug.org/RemixDev/deemix" target="_blank">official repo</a> for the
|
|
library.
|
|
</p>
|
|
<p>
|
|
Stay up to date with the updates by following the <a href="https://t.me/RemixDevNews"
|
|
target="_blank">news channel</a> on Telegram.
|
|
</p>
|
|
<br />
|
|
<h2>Donations</h2>
|
|
<h3>You want to contribute to this project? You can do that <b>in different ways!</b></h3>
|
|
<p>
|
|
If you're fluent in python you could try to make a new UI for the app using the base library, or fix bugs in the library with a pull request on the <a href="https://notabug.org/RemixDev/deemix" target="_blank">repo</a>.<br>
|
|
I accept features as well, but no complex things, as they can be implementend directly in the app and not the library.</p>
|
|
<p>
|
|
If you're fluent in another programming language you could try to port deemix into other programming languages!<br>
|
|
You need help understanding the code? Just hit RemixDev up on Telegram or Reddit.</p>
|
|
<p>If you know JavaScript, HTML or CSS you could contribute to the <a href="https://notabug.org/RemixDev/deemix-webui" target="_blank">webui</a>.</p>
|
|
<p>
|
|
If you find some bugs you can report them in the repo, just make sure your bug isn't something that only affects you and it can be reproducible by other users as well.<br>
|
|
Duplicate bug reports will be closed, so keep an eye out on that.</p>
|
|
<hr>
|
|
<h3>You want to contribute monetarily? You could make a donation!</h3>
|
|
<p>
|
|
If you can donate you can do that with this links.<br>
|
|
You shoud remember that <b>this is a free project</b> and <b>you should support the artists you love</b> before supporting the developers.<br>
|
|
Don't feel obligated to donate, I appreciate you anyway!</p>
|
|
<p>
|
|
<b>PayPal:</b> <a href="https://paypal.me/RemixDev" target="_blank">PayPal.me/RemixDev</a><br>
|
|
<b>Bitcoin:</b> 1sdNymSJrMBWyHM4u2m9uco5nv6uV4Qs1<br>
|
|
<b>Ethereum:</b> 0x1d2aa67e671485CD4062289772B662e0A6Ff976c
|
|
</p>
|
|
<br />
|
|
<h2>License</h2>
|
|
<p>
|
|
<a rel="license" href="https://www.gnu.org/licenses/gpl-3.0.en.html" target="_blank">
|
|
<img alt="GNU General Public License" style="border-width:0"
|
|
src="https://www.gnu.org/graphics/gplv3-127x51.png" />
|
|
</a><br />
|
|
This work is licensed under a <a rel="license" href="https://www.gnu.org/licenses/gpl-3.0.en.html"
|
|
target="_blank">GNU General Public License 3.0</a>.
|
|
</p>
|
|
</div>
|
|
|
|
<div id="artist_tab" class="main_tabcontent fixed_footer image_header">
|
|
<header class="inline-flex"
|
|
:style="{ 'background-image': 'linear-gradient(to bottom, transparent 0%, var(--main-background) 100%), url(\''+image+'\')' }">
|
|
<h1>{{ title }}</h1>
|
|
<div role="button" aria-label="download" @contextmenu.prevent="openQualityModal"
|
|
@click.stop="addToQueue" :data-link="link" class="fab right"><i class="material-icons">get_app</i>
|
|
</div>
|
|
</header>
|
|
|
|
<div class="tab">
|
|
<template v-for="(item, name, index) in body">
|
|
<button :class="'selective' + (name==currentTab ? ' active' : '')" :href="'#artist_' + name"
|
|
@click="changeTab(name)">{{ name }}</button>
|
|
</template>
|
|
</div>
|
|
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th v-for="data in head" @click="data.sortKey ? sortBy(data.sortKey) : null"
|
|
:style="{ 'width': data.width ? data.width : 'auto'}"
|
|
:class="{ 'sort-asc': data.sortKey == sortKey && sortOrder == 'asc', 'sort-desc': data.sortKey == sortKey && sortOrder == 'desc', 'sortable': data.sortKey, 'clickable': data.sortKey }">
|
|
{{data.title}}
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr v-for="release in showTable">
|
|
<td class="inline-flex clickable" @click="albumView" :data-id="release.id">
|
|
<img class="rounded coverart" :src="release.cover_small"
|
|
style="margin-right: 16px; width: 56px; height: 56px;" />
|
|
<i v-if="release.explicit_lyrics" class="material-icons explicit_icon">
|
|
explicit
|
|
</i>
|
|
{{release.title}}
|
|
<i v-if="checkNewRelease(release.release_date)" class="material-icons" style="color:#FF7300;">
|
|
fiber_new
|
|
</i>
|
|
</td>
|
|
<td>{{release.release_date}}</td>
|
|
<td @click.stop="addToQueue" @contextmenu.prevent="openQualityModal" :data-link="release.link"
|
|
class="clickable">
|
|
<i class="material-icons">
|
|
file_download
|
|
</i>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<footer>
|
|
<button class="back-button">Back</button>
|
|
</footer>
|
|
</div>
|
|
|
|
<div id="tracklist_tab" class="main_tabcontent fixed_footer image_header">
|
|
<header
|
|
:style="{ 'background-image': 'linear-gradient(to bottom, transparent 0%, var(--main-background) 100%), url(\''+image+'\')' }">
|
|
<h1 class="inline-flex">{{ title }} <i v-if="explicit"
|
|
class="material-icons explicit_tracklist">explicit</i></h1>
|
|
<h2 class="inline-flex"><span v-if="metadata">{{ metadata }}</span><span class="right"
|
|
v-if="release_date">{{ release_date }}</span></h2>
|
|
</header>
|
|
|
|
<table class="table table--tracklist">
|
|
<thead>
|
|
<tr>
|
|
<th>
|
|
<i class="material-icons">music_note</i>
|
|
</th>
|
|
<th>#</th>
|
|
<th>Song</th>
|
|
<th>Artist</th>
|
|
<th v-if="type == 'Playlist'">Album</th>
|
|
<th>
|
|
<i class="material-icons">timer</i>
|
|
</th>
|
|
<th class="table__icon table__cell--center clickable">
|
|
<input @click="toggleAll" class="selectAll" type="checkbox">
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<template v-if="type !== 'Spotify Playlist'">
|
|
<template v-for="track in body">
|
|
<tr v-if="track.type == 'track'">
|
|
<td class="table__cell--x-small table__cell--center">
|
|
<div class="table__cell-content table__cell-content--vertical-center">
|
|
<i class="material-icons"
|
|
:class="{ 'preview_playlist_controls' : track.preview, disabled: !track.preview }"
|
|
v-on="{ click: track.preview ? playPausePreview : null }" :data-preview="track.preview">
|
|
play_arrow
|
|
</i>
|
|
</div>
|
|
</td>
|
|
<td class="table__cell--small table__cell--center track_position">
|
|
{{ type === 'Album' ? track.track_position : (body.indexOf(track) + 1) }}
|
|
</td>
|
|
<td class="table__cell--large table__cell--with-icon">
|
|
<div class="table__cell-content table__cell-content--vertical-center">
|
|
<i v-if="track.explicit_lyrics" class="material-icons explicit_icon">
|
|
explicit
|
|
</i>
|
|
{{ track.title + (track.title_version && track.title.indexOf(track.title_version) == -1 ? ' '+ track.title_version : '') }}
|
|
</div>
|
|
</td>
|
|
<td class="table__cell--medium table__cell--center clickable" @click="artistView"
|
|
:data-id="track.artist.id">
|
|
{{ track.artist.name }}
|
|
</td>
|
|
<td v-if="type == 'Playlist'" class="table__cell--medium table__cell--center clickable"
|
|
@click="albumView" :data-id="track.album.id">
|
|
{{ track.album.title }}
|
|
</td>
|
|
<td class="table__cell--center"
|
|
:class="{ 'table__cell--small' : type === 'Album', 'table__cell--x-small' : type === 'Playlist' }">
|
|
{{ convertDuration(track.duration) }}
|
|
</td>
|
|
<td class="table__icon table__cell--center">
|
|
<input class="clickable" type="checkbox" v-model="track.selected">
|
|
</td>
|
|
</tr>
|
|
<tr v-else-if="track.type == 'disc_separator'" class="table__row-no-highlight"
|
|
style="opacity: 0.54;">
|
|
<td>
|
|
<div class="table__cell-content table__cell-content--vertical-center" style="opacity: 0.54;">
|
|
<i class="material-icons">album</i>
|
|
</div>
|
|
</td>
|
|
<td class="table__cell--center">
|
|
{{ track.number }}
|
|
</td>
|
|
<td colspan="4"></td>
|
|
</tr>
|
|
</template>
|
|
</template>
|
|
<template v-else>
|
|
<tr v-for="(track, i) in body">
|
|
<td>
|
|
<i v-if="track.preview_url" @click="playPausePreview"
|
|
:class="'material-icons' + (track.preview_url ? ' preview_playlist_controls' : '')"
|
|
:data-preview="track.preview_url">play_arrow</i>
|
|
<i v-else class="material-icons disabled">play_arrow</i>
|
|
</td>
|
|
<td>{{ i+1 }}</td>
|
|
<td class="inline-flex">
|
|
<i v-if="track.explicit" class="material-icons explicit_icon">explicit</i>
|
|
{{ track.name }}
|
|
</td>
|
|
<td>{{ track.artists[0].name }}</td>
|
|
<td>{{ track.album.name }}</td>
|
|
<td>{{ convertDuration(Math.floor(track.duration_ms/1000)) }}</td>
|
|
<td><input class="clickable" type="checkbox" v-model="track.selected"></td>
|
|
</tr>
|
|
</template>
|
|
</tbody>
|
|
</table>
|
|
<span v-if="label"
|
|
style="opacity: 0.40;margin-top: 8px;display: inline-block;font-size: 13px;">{{ label }}</span>
|
|
<footer>
|
|
<button @contextmenu.prevent="openQualityModal" @click.stop="addToQueue" :data-link="link">Download
|
|
{{ type }}</button>
|
|
<button class="with_icon" @contextmenu.prevent="openQualityModal" @click.stop="addToQueue"
|
|
:data-link="selectedLinks()">Download selection<i class="material-icons">file_download</i></button>
|
|
<button class="back-button">Back</button>
|
|
</footer>
|
|
</div>
|
|
|
|
</div>
|
|
</section>
|
|
</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">
|
|
<i id="open_downloads_folder" class="material-icons download_bar_icon hide">folder_open</i>
|
|
<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>
|
|
</div>
|
|
<div id="download_list"></div>
|
|
</div>
|
|
</main>
|
|
|
|
<audio id="preview-track">
|
|
<source id="preview-track_source" src="" type="audio/mpeg">
|
|
</audio>
|
|
|
|
<div id="modal_quality" class="smallmodal">
|
|
<!-- Modal content -->
|
|
<div class="smallmodal-content">
|
|
<button class="quality-button" data-quality-value="9">Download FLAC</button><br>
|
|
<button class="quality-button" data-quality-value="3">Download MP3 320kbps</button><br>
|
|
<button class="quality-button" data-quality-value="1">Download MP3 128kbps</button><br>
|
|
<button class="quality-button" data-quality-value="15">Download 360 Reality Audio [HQ]</button><br>
|
|
<button class="quality-button" data-quality-value="14">Download 360 Reality Audio [MQ]</button><br>
|
|
<button class="quality-button" data-quality-value="13">Download 360 Reality Audio [LQ]</button><br>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
<script type="text/javascript" src="/public/js/vendor/socket.io.js"></script>
|
|
|
|
<script src="/public/js/bundle.js"></script>
|
|
|
|
</html>
|