build: v1.5.2; fix: spotify favorites playlist not showing in Favorites page until the refresh button is clicked (closes #21); refactor: favorites logic
This commit is contained in:
parent
835b0e9f8d
commit
d752efa30f
File diff suppressed because one or more lines are too long
@ -3,13 +3,13 @@
|
||||
<h1 class="mb-8 text-5xl">
|
||||
{{ $t('favorites.title') }}
|
||||
<div
|
||||
@click="reloadTabs"
|
||||
class="inline-block clickable reload-button"
|
||||
@click="refreshFavorites"
|
||||
class="inline-block clickable"
|
||||
ref="reloadButton"
|
||||
role="button"
|
||||
aria-label="reload"
|
||||
>
|
||||
<i class="material-icons">sync</i>
|
||||
<i class="material-icons" :class="{ spin: isRefreshingFavorites }">sync</i>
|
||||
</div>
|
||||
</h1>
|
||||
|
||||
@ -20,10 +20,10 @@
|
||||
</BaseTabs>
|
||||
|
||||
<button class="btn btn-primary" v-if="!activeTabEmpty" style="margin-bottom: 2rem" @click="downloadAllOfType">
|
||||
{{ $t('globals.download', { thing: $tc(`globals.listTabs.${activeTab}N`, getTabLenght()) }) }}
|
||||
{{ $t('globals.download', { thing: $tc(`globals.listTabs.${activeTab}N`, getTabLength()) }) }}
|
||||
</button>
|
||||
|
||||
<div class="favorites_tabcontent" :class="{ 'favorites_tabcontent--active': activeTab === 'playlist' }">
|
||||
<div v-show="activeTab === 'playlist'">
|
||||
<div v-if="playlists.length == 0">
|
||||
<h1>{{ $t('favorites.noPlaylists') }}</h1>
|
||||
</div>
|
||||
@ -62,7 +62,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="favorites_tabcontent" :class="{ 'favorites_tabcontent--active': activeTab === 'album' }">
|
||||
<div v-show="activeTab === 'album'">
|
||||
<div v-if="albums.length == 0">
|
||||
<h1>{{ $t('favorites.noAlbums') }}</h1>
|
||||
</div>
|
||||
@ -81,7 +81,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="favorites_tabcontent" :class="{ 'favorites_tabcontent--active': activeTab === 'artist' }">
|
||||
<div v-show="activeTab === 'artist'">
|
||||
<div v-if="artists.length == 0">
|
||||
<h1>{{ $t('favorites.noArtists') }}</h1>
|
||||
</div>
|
||||
@ -99,7 +99,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="favorites_tabcontent" :class="{ 'favorites_tabcontent--active': activeTab === 'track' }">
|
||||
<div v-show="activeTab === 'track'">
|
||||
<div v-if="tracks.length == 0">
|
||||
<h1>{{ $t('favorites.noTracks') }}</h1>
|
||||
</div>
|
||||
@ -163,86 +163,70 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.favorites_tabcontent {
|
||||
display: none;
|
||||
|
||||
&--active {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.reload-button {
|
||||
&.spin {
|
||||
i {
|
||||
animation: spin 500ms infinite ease-out reverse;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import { socket } from '@/utils/socket'
|
||||
import { sendAddToQueue, aggregateDownloadLinks } from '@/utils/downloads'
|
||||
import { convertDuration } from '@/utils/utils'
|
||||
import { toast } from '@/utils/toasts'
|
||||
import { getFavoritesData } from '@/data/favorites'
|
||||
import { defineComponent, onMounted, reactive, toRefs, watchEffect, ref, computed, watch } from '@vue/composition-api'
|
||||
|
||||
import PreviewControls from '@components/globals/PreviewControls.vue'
|
||||
import CoverContainer from '@components/globals/CoverContainer.vue'
|
||||
import { playPausePreview } from '@components/globals/TheTrackPreview.vue'
|
||||
import { BaseTabs, BaseTab } from '@components/globals/BaseTabs'
|
||||
|
||||
export default {
|
||||
import { sendAddToQueue, aggregateDownloadLinks } from '@/utils/downloads'
|
||||
import { convertDuration } from '@/utils/utils'
|
||||
import { toast } from '@/utils/toasts'
|
||||
import { useFavorites } from '@/use/favorites'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
PreviewControls,
|
||||
CoverContainer,
|
||||
BaseTabs,
|
||||
BaseTab
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tracks: [],
|
||||
albums: [],
|
||||
artists: [],
|
||||
playlists: [],
|
||||
spotifyPlaylists: [],
|
||||
setup(props, ctx) {
|
||||
const state = reactive({
|
||||
activeTab: 'playlist',
|
||||
tabs: ['playlist', 'album', 'artist', 'track']
|
||||
})
|
||||
const {
|
||||
favoriteArtists,
|
||||
favoriteAlbums,
|
||||
favoriteSpotifyPlaylists,
|
||||
favoritePlaylists,
|
||||
favoriteTracks,
|
||||
isRefreshingFavorites,
|
||||
refreshFavorites
|
||||
} = useFavorites()
|
||||
const reloadButton = computed(() => ctx.refs.reloadButton)
|
||||
|
||||
watch(isRefreshingFavorites, (newVal, oldVal) => {
|
||||
// If oldVal is true and newOne is false, it means that a refreshing has just terminated
|
||||
// because isRefreshingFavorites represents the status of the refresh functionality
|
||||
const isRefreshingTerminated = oldVal && !newVal
|
||||
|
||||
if (!isRefreshingTerminated) return
|
||||
|
||||
toast(ctx.root.$t('toasts.refreshFavs'), 'done', true)
|
||||
})
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
tracks: favoriteTracks,
|
||||
albums: favoriteAlbums,
|
||||
artists: favoriteArtists,
|
||||
playlists: favoritePlaylists,
|
||||
spotifyPlaylists: favoriteSpotifyPlaylists,
|
||||
refreshFavorites,
|
||||
isRefreshingFavorites
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
activeTabEmpty() {
|
||||
let toCheck = this.getActiveRelease()
|
||||
|
||||
return toCheck.length === 0
|
||||
return toCheck?.length === 0
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
const favoritesData = await getFavoritesData()
|
||||
|
||||
// TODO Change with isLoggedIn vuex getter
|
||||
if (Object.entries(favoritesData).length === 0) return
|
||||
|
||||
this.setFavorites(favoritesData)
|
||||
},
|
||||
mounted() {
|
||||
socket.on('updated_userFavorites', this.updated_userFavorites)
|
||||
socket.on('updated_userSpotifyPlaylists', this.updated_userSpotifyPlaylists)
|
||||
socket.on('updated_userPlaylists', this.updated_userPlaylists)
|
||||
socket.on('updated_userAlbums', this.updated_userAlbums)
|
||||
socket.on('updated_userArtist', this.updated_userArtist)
|
||||
socket.on('updated_userTracks', this.updated_userTracks)
|
||||
|
||||
this.$on('hook:destroyed', () => {
|
||||
socket.off('updated_userFavorites')
|
||||
socket.off('updated_userSpotifyPlaylists')
|
||||
socket.off('updated_userPlaylists')
|
||||
socket.off('updated_userAlbums')
|
||||
socket.off('updated_userArtist')
|
||||
socket.off('updated_userTracks')
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
playPausePreview,
|
||||
convertDuration,
|
||||
@ -264,54 +248,9 @@ export default {
|
||||
addToQueue(e) {
|
||||
sendAddToQueue(e.currentTarget.dataset.link)
|
||||
},
|
||||
updated_userSpotifyPlaylists(data) {
|
||||
this.spotifyPlaylists = data
|
||||
},
|
||||
updated_userPlaylists(data) {
|
||||
this.playlists = data
|
||||
},
|
||||
updated_userAlbums(data) {
|
||||
this.albums = data
|
||||
},
|
||||
updated_userArtist(data) {
|
||||
this.artists = data
|
||||
},
|
||||
updated_userTracks(data) {
|
||||
this.tracks = data
|
||||
},
|
||||
reloadTabs() {
|
||||
this.$refs.reloadButton.classList.add('spin')
|
||||
|
||||
socket.emit('update_userFavorites')
|
||||
|
||||
if (localStorage.getItem('spotifyUser')) {
|
||||
socket.emit('update_userSpotifyPlaylists', localStorage.getItem('spotifyUser'))
|
||||
}
|
||||
},
|
||||
updated_userFavorites(data) {
|
||||
this.setFavorites(data)
|
||||
|
||||
// Removing animation class only when the animation has completed an iteration
|
||||
// Prevents animation ugly stutter
|
||||
this.$refs.reloadButton.addEventListener(
|
||||
'animationiteration',
|
||||
() => {
|
||||
this.$refs.reloadButton.classList.remove('spin')
|
||||
toast(this.$t('toasts.refreshFavs'), 'done', true)
|
||||
},
|
||||
{ once: true }
|
||||
)
|
||||
},
|
||||
setFavorites(data) {
|
||||
const { tracks, albums, artists, playlists } = data
|
||||
|
||||
this.tracks = tracks
|
||||
this.albums = albums
|
||||
this.artists = artists
|
||||
this.playlists = playlists
|
||||
},
|
||||
getActiveRelease(tab = this.activeTab) {
|
||||
let toDownload
|
||||
// console.log({ tab, play: this.playlists })
|
||||
|
||||
switch (tab) {
|
||||
case 'playlist':
|
||||
@ -333,11 +272,11 @@ export default {
|
||||
|
||||
return toDownload
|
||||
},
|
||||
getTabLenght(tab = this.activeTab) {
|
||||
let total = this[`${tab}s`].length
|
||||
getTabLength(tab = this.activeTab) {
|
||||
let total = this[`${tab}s`]?.length
|
||||
// TODO: Add Spotify playlists to downlaod queue as well
|
||||
//if (tab === "playlist") total += this.spotifyPlaylists.length
|
||||
return total
|
||||
return total || 0
|
||||
},
|
||||
getLovedTracksPlaylist() {
|
||||
let lovedTracks = this.playlists.filter(playlist => {
|
||||
@ -351,5 +290,5 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
@ -1,22 +0,0 @@
|
||||
import { socket } from '@/utils/socket'
|
||||
|
||||
let favoritesData = {}
|
||||
let cached = false
|
||||
|
||||
export function getFavoritesData() {
|
||||
if (cached) {
|
||||
return favoritesData
|
||||
} else {
|
||||
socket.emit('get_favorites_data')
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
socket.on('init_favorites', data => {
|
||||
favoritesData = data
|
||||
cached = true
|
||||
|
||||
socket.off('init_favorites')
|
||||
resolve(data)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
@ -6,10 +6,17 @@ const getDefaultState = () => ({
|
||||
name: '',
|
||||
picture: ''
|
||||
},
|
||||
spotifyUser: {
|
||||
id: localStorage.getItem('spotifyUser'),
|
||||
name: null,
|
||||
picture: null
|
||||
},
|
||||
clientMode: false
|
||||
})
|
||||
|
||||
const state = getDefaultState()
|
||||
const state = () => {
|
||||
return getDefaultState()
|
||||
}
|
||||
|
||||
const actions = {
|
||||
login({ commit, dispatch }, payload) {
|
||||
@ -51,8 +58,11 @@ const actions = {
|
||||
const getters = {
|
||||
getARL: state => state.arl,
|
||||
getUser: state => state.user,
|
||||
getSpotifyUser: state => state.spotifyUser,
|
||||
getClientMode: state => state.clientMode,
|
||||
isLoggedIn: state => !!state.arl
|
||||
|
||||
isLoggedIn: state => !!state.arl,
|
||||
isLoggedWithSpotify: state => !!state.spotifyUser.id
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
|
@ -22,6 +22,10 @@
|
||||
width: 156px;
|
||||
}
|
||||
|
||||
.spin {
|
||||
animation: spin 500ms infinite ease-out reverse;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
|
79
src/use/favorites.js
Normal file
79
src/use/favorites.js
Normal file
@ -0,0 +1,79 @@
|
||||
import { ref } from '@vue/composition-api'
|
||||
|
||||
import store from '@/store'
|
||||
import { socket } from '@/utils/socket'
|
||||
|
||||
const favoriteArtists = ref([])
|
||||
const favoriteAlbums = ref([])
|
||||
const favoriteSpotifyPlaylists = ref([])
|
||||
const favoritePlaylists = ref([])
|
||||
const favoriteTracks = ref([])
|
||||
|
||||
const isRefreshingFavorites = ref(false)
|
||||
|
||||
if (store.getters.isLoggedIn) {
|
||||
refreshFavorites({ isInitial: true })
|
||||
}
|
||||
|
||||
function refreshFavorites({ isInitial = false }) {
|
||||
if (!isInitial) {
|
||||
isRefreshingFavorites.value = true
|
||||
}
|
||||
|
||||
socket.emit('get_favorites_data')
|
||||
|
||||
if (store.getters.isLoggedWithSpotify) {
|
||||
socket.emit('update_userSpotifyPlaylists', store.getters.getSpotifyUser.id)
|
||||
}
|
||||
}
|
||||
|
||||
export function useFavorites() {
|
||||
return {
|
||||
favoriteArtists,
|
||||
favoriteAlbums,
|
||||
favoriteSpotifyPlaylists,
|
||||
favoritePlaylists,
|
||||
favoriteTracks,
|
||||
isRefreshingFavorites,
|
||||
refreshFavorites
|
||||
}
|
||||
}
|
||||
|
||||
function setAllFavorites(data) {
|
||||
const { tracks, albums, artists, playlists } = data
|
||||
|
||||
favoriteArtists.value = artists
|
||||
favoriteAlbums.value = albums
|
||||
favoritePlaylists.value = playlists
|
||||
favoriteTracks.value = tracks
|
||||
}
|
||||
|
||||
socket.on('updated_userFavorites', data => {
|
||||
setAllFavorites(data)
|
||||
// Commented out because the corresponding emit function is never called at the moment
|
||||
// therefore isRefreshingFavorites is never set to true
|
||||
// isRefreshingFavorites.value = false
|
||||
})
|
||||
socket.on('init_favorites', data => {
|
||||
setAllFavorites(data)
|
||||
isRefreshingFavorites.value = false
|
||||
})
|
||||
|
||||
socket.on('updated_userSpotifyPlaylists', data => {
|
||||
favoriteSpotifyPlaylists.value = data
|
||||
})
|
||||
socket.on('updated_userSpotifyPlaylists', data => {
|
||||
favoriteSpotifyPlaylists.value = data
|
||||
})
|
||||
socket.on('updated_userPlaylists', data => {
|
||||
favoritePlaylists.value = data
|
||||
})
|
||||
socket.on('updated_userAlbums', data => {
|
||||
favoriteAlbums.value = data
|
||||
})
|
||||
socket.on('updated_userArtist', data => {
|
||||
favoriteArtists.value = data
|
||||
})
|
||||
socket.on('updated_userTracks', data => {
|
||||
favoriteTracks.value = data
|
||||
})
|
@ -19,7 +19,3 @@ export function aggregateDownloadLinks(releases) {
|
||||
|
||||
return links.join(';')
|
||||
}
|
||||
|
||||
// export default {
|
||||
// sendAddToQueue
|
||||
// }
|
||||
|
Loading…
Reference in New Issue
Block a user