Merge branch 'master' of lemonyzer/deemix into master

This commit is contained in:
RemixDev 2020-05-13 18:09:19 +00:00 committed by Gogs
commit 37a09c5f6b
4 changed files with 577 additions and 0 deletions

View File

@ -43,6 +43,10 @@
<i class="material-icons side_icon">album</i>
<span class="main_tablinks_text">Favorites</span>
</span>
<span id="main_spotify_tablink" class="main_tablinks" role="link" aria-label="spotify">
<i class="material-icons side_icon">extension</i>
<span class="main_tablinks_text">Spotify</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
@ -484,6 +488,67 @@ <h1>No Favorite Tracks found</h1>
</div>
</div>
<div id="spotify_tab" class="main_tabcontent">
<h1>Spotify</h1>
<div class="tab">
<button class="spotify_tablinks" id="spotify_playlist_tab">Playlists</button>
<button class="spotify_tablinks" id="spotify_result_tab">Result</button>
</div>
<div id="playlist_spotify" class="spotify_tabcontent">
<div v-if="spotifyNativePlaylists.length == 0">
<h1>No (native) Playlists found</h1>
</div>
<div v-else>
<h1>native Spotify Playlists</h1>
<table>
<tr>
<th>compare</th>
<th>title</th>
<th>tracks</th>
<th>id</th>
</tr>
<tr v-for="cPlaylist in spotifyNativePlaylists" :key="cPlaylist.uri">
<td><input class="playlistCheckbox" type="checkbox" v-model="cPlaylist.selected"></td>
<td>{{cPlaylist.name}}</td>
<td>{{cPlaylist.tracks.total}}</td>
<td class="clickable" @click="spotifyPlaylistView" :data-id="cPlaylist.id">{{cPlaylist.id}}</td>
</tr>
</table>
</div>
<div v-if="spotifyPlaylists.length == 0">
<h1>No Playlists found</h1>
</div>
<div v-else>
<table>
<tr>
<th>compare</th>
<th>title</th>
<th>creator</th>
<th>tracks</th>
<th>id</th>
</tr>
<tr v-for="release in spotifyPlaylists">
<td><input class="playlistCheckbox" type="checkbox" v-model="release.selected"></td>
<td>{{release.title}}</td>
<td>{{release.creator.name}}</td>
<td>{{release.nb_tracks}}</td>
<td class="clickable" @click="spotifyPlaylistView" :data-id="release.id">{{release.id}}</td>
</tr>
</table>
</div>
</div>
<footer>
<button class="with_icon" @contextmenu.prevent="openQualityModal" @click.stop="comparePlaylists"
:data-link="selectedLinksNative()">compare (native) selection<i class="material-icons">compare</i></button>
<!-- <button class="with_icon" @contextmenu.prevent="openQualityModal" @click.stop="comparePlaylists"
:data-link="selectedLinks()">compare selection<i class="material-icons">compare</i></button> -->
<button class="with_icon" @contextmenu.prevent="openQualityModal" @click.stop="mergePlaylists"
:data-link="selectedLinksNative()">merge (native) selection<i class="material-icons">call_merge</i></button>
<!-- <button class="with_icon" @contextmenu.prevent="openQualityModal" @click.stop="addToBucket"
:data-link="selectedLinks()">add selection to bucket<i class="material-icons">archive</i></button> -->
</footer>
</div>
<div id="analyzer_tab" class="main_tabcontent image_header">
<h1>Link Analyzer</h1>
<div v-if="link == ''">
@ -1105,6 +1170,125 @@ <h2 class="inline-flex"><span v-if="metadata">{{ metadata }}</span><span class="
</footer>
</div>
<div id="spotifytracklist_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</i></h1>
<h2 class="inline-flex"><span v-if="metadata">{{ metadata }}</span><span class="right"
v-if="release_date">{{ release_date }}</span></h2>
</header>
<div v-if="includedPlaylists.length == 0">
<h1>No included Playlist found</h1>
</div>
<div v-else>
<div>
<h1>Options</h1>
<span><input class="playlistCheckbox" type="checkbox" v-model="showTracksInSinglePlaylistOnly">showTracksInSinglePlaylistOnly</span>
<span><input class="playlistCheckbox" type="checkbox" v-model="hideTrackIfNoPlaylistSelected">hideTrackIfNoPlaylistSelected</span>
<span><input class="playlistCheckbox" type="checkbox" v-model="showTracksInMultiplePlaylistOnly">showTracksInMultiplePlaylistOnly</span>
</div>
<table>
<thead>
<tr>
<th>include</th>
<th>name</th>
<th>owner</th>
<th>tracks</th>
<th>id</th>
<th>uri</th>
</tr>
</thead>
<tbody>
<tr v-for="playlist in includedPlaylists">
<td><input class="playlistCheckbox" type="checkbox" v-model="playlist.selected"></td>
<td><span>{{playlist.name}}</span></td>
<td>
<span v-for="owner in playlist.owner">
{{owner.display_name}}<br />
</span>
</td>
<td><span>{{playlist.numTracks}}</span></td>
<td class="clickable" @click="spotifyPlaylistView" :data-id="playlist.id">{{playlist.id}}</td>
<td class="clickable" @click="spotifyPlaylistView" :data-id="playlist.uri">{{playlist.uri}}</td>
</tr>
</tbody>
</table>
</div>
<table>
<thead>
<tr>
<th style="width: 32px">DL<input @click="toggleAll" class="selectAll" type="checkbox"></th>
<th v-for="data in head" v-html="data.title" :style="{ 'width': data.width ? data.width : 'auto'}">
</th>
</tr>
</thead>
<tbody>
<template v-if="type!='Spotify Playlist'">
<template v-for="track in body">
<tr v-if="track.type == 'track'">
<td><i @click=playPausePreview
:class="'material-icons' + (track.preview ? ' preview_playlist_controls' : '')"
: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>
<td class="clickable" @click="artistView" :data-id="track.artist.id">
{{ track.artist.name }}</td>
<td class="clickable" v-if="type == 'Playlist'" @click="albumView" :data-id="track.album.id">
{{ track.album.title }}</td>
<td>{{ convertDuration(track.duration) }}</td>
<td><input class="trackCheckbox" type="checkbox" v-model="track.selected"></td>
</tr>
<tr v-else-if="track.type == 'disc_separator'">
<td colspan="6" style="opacity: 0.54;"><i class="material-icons">album</i>{{ track.number }}</td>
</tr>
</template>
</template>
<template v-else>
<tr v-for="(track, i) in body">
<template v-if="(!hideTrackIfNoPlaylistSelected || trackInVisiblePlaylist(track)) &&
(!showTracksInSinglePlaylistOnly || (!trackInMoreThanOnePlaylist(track) && showTracksInSinglePlaylistOnly)) &&
(!showTracksInMultiplePlaylistOnly || (trackInMoreThanOnePlaylist(track) && showTracksInMultiplePlaylistOnly))">
<!-- <template v-for="pl in track.inPlaylists">
<template v-if="includedPlaylists.includes(pl)">
<template v-if="includedPlaylists[includedPlaylists.indexOf(pl)].selected"> -->
<td><input class="trackCheckbox" type="checkbox" v-model="track.selected"></td>
<td><i @click=playPausePreview
:class="'material-icons' + (track.preview_url ? ' preview_playlist_controls' : '')"
:data-preview="track.preview_url">play_arrow</i></td>
<td>{{ i+1 }}</td>
<td class="inline-flex"><i v-if="track.explicit" class="material-icons">explicit</i>{{ track.name }}
</td>
<td v-for="artist in track.artists">
{{ artist.name }}<br />
</td>
<td>{{ track.album.name }}</td>
<td>{{ convertDuration(Math.floor(track.duration_ms/1000)) }}</td>
<td v-for="playlistId in track.inPlaylists">
<input class="trackCheckbox" type="checkbox" v-model="getPlaylistObj(playlistId).selected">{{ getPlaylistObj(playlistId).name }}<br />
</td>
<!-- </template>
</template>
</template> -->
</template>
</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>

View File

@ -0,0 +1,87 @@
import Vue from 'vue/dist/vue.esm'
import { socket } from '../socket.js'
import { playlistView, artistView, albumView, spotifyPlaylistView } from '../tabs.js'
import Downloads from '../downloads.js'
import QualityModal from '../quality-modal.js'
import TrackPreview from '../track-preview.js'
import Utils from '../utils.js'
const SpotifyTab = new Vue({
data() {
return {
tracks: [],
albums: [],
artists: [],
playlists: [],
spotifyPlaylists: [],
spotifyNativePlaylists: [],
spotifyTracks: []
}
},
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.open(e.currentTarget.dataset.link)
},
updated_userSpotifyPlaylists(data){this.spotifyPlaylists = data},
updated_userSpotifyNativePlaylists(data){this.spotifyNativePlaylists = data},
initSpotify(data) {
console.log(data)
this.tracks = []
this.albums = []
this.artists = []
this.playlists = []
this.updated_userSpotifyNativePlaylists(data)
this.spotifyTracks = []
document.getElementById('spotify_playlist_tab').click()
},
selectedLinks() {
var selected = []
if (this.spotifyPlaylists) {
this.spotifyPlaylists.forEach(item => {
if (item.selected)
selected.push(item.id)
})
}
return selected.join(';')
},
selectedLinksNative() {
var selected = []
if (this.spotifyNativePlaylists) {
this.spotifyNativePlaylists.forEach(item => {
if (item.selected)
selected.push(item.id)
})
}
return selected.join(';')
},
comparePlaylists(e) {
e.stopPropagation()
//console.log(e) // e == MouseEvent
console.log(e.currentTarget.dataset.link)
socket.emit('getTracklistFromSpotifyPlaylists', { playlists: e.currentTarget.dataset.link })
},
mergePlaylists(e) {
e.stopPropagation()
//console.log(e) // e == MouseEvent
console.log(e.currentTarget.dataset.link)
socket.emit('mergeSpotifyPlaylists', { playlists: e.currentTarget.dataset.link })
}
},
mounted() {
socket.on('init_spotify', this.initSpotify)
}
}).$mount('#spotify_tab')
export default SpotifyTab

View File

@ -0,0 +1,263 @@
import _ from 'lodash'
import Vue from 'vue/dist/vue.esm'
import { socket } from '../socket.js'
import { albumView, artistView, spotifyTracklistResultView, spotifyPlaylistView } from '../tabs.js'
import Downloads from '../downloads.js'
import QualityModal from '../quality-modal.js'
import TrackPreview from '../track-preview.js'
const SpotifyTracklistTab = new Vue({
data: () => ({
title: '',
metadata: '',
release_date: '',
label: '',
explicit: false,
image: '',
type: '',
link: '',
head: null,
body: [],
includedPlaylists: [],
showTracksInSinglePlaylistOnly: false,
hideTrackIfNoPlaylistSelected: false,
showTracksInMultiplePlaylistOnly: false
}),
methods: {
artistView,
albumView,
spotifyPlaylistView,
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 = []
this.includedPlaylists = []
this.showTracksInSinglePlaylistOnly = false
this.hideTrackIfNoPlaylistSelected = false
this.showTracksInMultiplePlaylistOnly = false
},
addToQueue(e) {
e.stopPropagation()
Downloads.sendAddToQueue(e.currentTarget.dataset.link)
},
openQualityModal(e) {
QualityModal.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: '<i class="material-icons">music_note</i>', width: '24px' },
{ title: '#' },
{ title: 'Song' },
{ title: 'Artist' },
{ title: '<i class="material-icons">timer</i>', 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: '<i class="material-icons">music_note</i>', width: '24px' },
{ title: '#' },
{ title: 'Song' },
{ title: 'Artist' },
{ title: 'Album' },
{ title: '<i class="material-icons">timer</i>', width: '40px' }
]
if (_.isEmpty(data.tracks)) {
this.body = null
} else {
this.body = data.tracks
}
},
showSpotifyPlaylist(data) {
console.log(data)
this.type = 'Spotify Playlist'
this.link = data.uri
this.title = `from ${data.name}`
//this.title = `from ${data.name.split(";").forEach(function(e){return " • " + e})}`
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: '<i class="material-icons">music_note</i>', width: '24px' },
{ title: '#' },
{ title: 'Song' },
{ title: 'Artist' },
{ title: 'Album' },
{ title: 'Length <i class="material-icons">timer</i>', width: '40px' },
{ title: 'Playlist <i class="material-icons">playlist_play</i>', width: '40px' }
]
if (_.isEmpty(data.tracks)) {
this.body = null
} else {
this.body = data.tracks
}
if (_.isEmpty(data.includedPlaylists)) {
this.includedPlaylists = null
} else {
// select all
data.includedPlaylists.forEach(function(pl) {
pl.selected = true
})
this.includedPlaylists = data.includedPlaylists
}
document.getElementById('spotify_result_tab').click()
// // let map = new Map(data)
// // console.log(map)
// let tracks = []
// for (obj in data) {
// tracks.push(obj)
// //tracks.push(obj.track.name)
// }
// console.log(tracks)
// if (_.isEmpty(data.tracks)){
// this.body = null
// } else {
// this.body = data.tracks
// }
// if (_.isEmpty(data.tracks)) {
// this.body = null
// } else {
// this.body = data.tracks
// }
},
getPlaylistObj(playlistId) {
for (k = 0; k < this.includedPlaylists.length; k++) {
includedPlId = this.includedPlaylists[k].id
if (includedPlId == playlistId) {
return this.includedPlaylists[k]
}
}
return null
},
trackInMoreThanOnePlaylist(track) {
if(track.inPlaylists.length>1)
return true
else
return false
},
trackInVisiblePlaylist(track) {
//console.log(this.includedPlaylists[0].id)
//console.log(track.inPlaylists[0])
for (i = 0; i < track.inPlaylists.length; i++) {
plId = track.inPlaylists[i]
for (k = 0; k < this.includedPlaylists.length; k++) {
includedPlId = this.includedPlaylists[k].id
if (includedPlId == plId) {
if (this.includedPlaylists[k].selected)
return true
}
}
}
return false
// warum auch immer, aber diese for-Schleife funktioniert nicht!
// die properties werden nicht richtig abgerufen!
// for (plId in track.inPlaylists) {
// for (includedPlaylist in this.includedPlaylists) {
// //console.log(includedPlaylist[includedPlaylist] + " = includedPlaylist.id")
// //console.log(plId[plId] + " = plId")
// if (includedPlaylist.id == plId) {
// if (includedPlaylist.selected) {
// return true
// }
// }
// }
// }
// return false
},
getTracklistFromSpotifyPlaylists_done(data) {
console.log(data)
//deserialized = JSON.parse(data) // error
//console.log(deserialized)
// for (obj in data) {
// obj.id
// obj.name
// obj.duration_ms
// obj.playlists
// for (a in obj.artists) {
// a.name
// }
// }
// bodyData =
this.spotifyTracks = data
this.showSpotifyPlaylist(data)
}
},
mounted() {
// socket.on('show_album', this.showAlbum)
// socket.on('show_playlist', this.showPlaylist)
// socket.on('show_spotifyplaylist', this.showSpotifyPlaylist)
socket.on('getTracklistFromSpotifyPlaylists_done', this.getTracklistFromSpotifyPlaylists_done)
}
}).$mount('#spotifytracklist_tab')
export default SpotifyTracklistTab

View File

@ -1,9 +1,11 @@
import ArtistTab from './components/artist-tab.js'
import TracklistTab from './components/tracklist-tab.js'
import SpotifyTracklistTab from './components/spotify-tracklist-tab.js'
import LinkAnalyzerTab from './components/link-analyzer-tab.js'
import HomeTab from './components/home-tab.js'
import ChartsTab from './components/charts-tab.js'
import FavoritesTab from './components/favorites-tab.js'
import SpotifyTab from './components/spotify-tab.js'
import { socket } from './socket.js'
import SettingsTab from './components/settings-tab.js'
import MainSearch from './components/main-search.js'
@ -54,6 +56,13 @@ export function spotifyPlaylistView(ev) {
showTab('spotifyplaylist', id)
}
export function spotifyTracklistResultView(ev) {
let id = ev.currentTarget.dataset.id
SpotifyTracklistTab.reset()
//socket.emit('getTracklist', { type: 'spotifyplaylist', id: id })
showTab('spotifytracklistresult', id)
}
function analyzeLink(link) {
console.log('Analyzing: ' + link)
LinkAnalyzerTab.reset()
@ -63,6 +72,7 @@ function analyzeLink(link) {
function linkListeners() {
document.getElementById('search_tab').addEventListener('click', handleSearchTabClick)
document.getElementById('favorites_tab').addEventListener('click', handleFavoritesTabClick)
document.getElementById('spotify_tab').addEventListener('click', handleSpotifyTabClick)
document.getElementById('sidebar').addEventListener('click', handleSidebarClick)
const backButtons = Array.from(document.getElementsByClassName('back-button'))
@ -100,6 +110,9 @@ function handleSidebarClick(event) {
case 'main_favorites_tablink':
changeTab(sidebarEl, 'main', 'favorites_tab')
break
case 'main_spotify_tablink':
changeTab(sidebarEl, 'main', 'spotify_tab')
break
case 'main_analyzer_tablink':
changeTab(sidebarEl, 'main', 'analyzer_tab')
break
@ -140,6 +153,32 @@ function handleSearchTabClick(event) {
}
}
function handleSpotifyTabClick(event) {
let targetID = event.target.id
let id = event.currentTarget.dataset.id
switch (targetID) {
case 'spotify_playlist_tab':
changeTab(event.target, 'spotify', 'playlist_spotify')
break
case 'spotify_result_tab':
showTab('spotifytracklistresult', id)
//changeTab(event.target, 'spotify', 'album_favorites') // TODO
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
default:
break
}
}
function handleFavoritesTabClick(event) {
let targetID = event.target.id
@ -211,6 +250,10 @@ function showTab(type, id, back = false) {
window.tab = type == 'artist' ? 'artist_tab' : 'tracklist_tab'
if (type == 'spotifytracklistresult') {
window.tab = 'spotifytracklist_tab'
}
currentStack = { type: type, id: id }
let tabcontent = document.getElementsByClassName('main_tabcontent')