mirror of
https://github.com/Dvorinka/swingmusic-extended.git
synced 2026-06-03 20:13:02 +00:00
add functionality to play button on artist page
This commit is contained in:
committed by
Mungai Njoroge
parent
bb95011dff
commit
90dd1a1fe8
@@ -1,20 +1,21 @@
|
||||
<template>
|
||||
<div class="albums-from-artist">
|
||||
<div class="artist-albums">
|
||||
<h3>
|
||||
<span>{{ title }} </span>
|
||||
<span class="see-more">SEE ALL</span>
|
||||
</h3>
|
||||
<div class="cards">
|
||||
<AlbumCard v-for="a in albums" :album="a" />
|
||||
<AlbumCard v-for="a in albums.slice(0, maxAbumCards)" :album="a" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import AlbumCard from "../shared/AlbumCard.vue";
|
||||
|
||||
import { Album } from "@/interfaces";
|
||||
|
||||
import { maxAbumCards } from "@/stores/content-width";
|
||||
|
||||
defineProps<{
|
||||
title: string;
|
||||
albums: Album[];
|
||||
@@ -22,7 +23,7 @@ defineProps<{
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.albums-from-artist {
|
||||
.artist-albums {
|
||||
overflow: hidden;
|
||||
|
||||
h3 {
|
||||
@@ -40,7 +41,7 @@ defineProps<{
|
||||
.cards {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
|
||||
gap: 2rem 0;
|
||||
gap: 5rem 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
{{ formatSeconds(artist.info.duration, true) }}
|
||||
</div>
|
||||
</section>
|
||||
<PlayBtnRect />
|
||||
<PlayBtnRect :source="playSources.artist" :store="useArtistPageStore" />
|
||||
</div>
|
||||
<div class="artist-img no-select">
|
||||
<img :src="paths.images.artist.large + artist.info.image" />
|
||||
@@ -28,7 +28,7 @@
|
||||
<div
|
||||
class="gradient"
|
||||
:style="{
|
||||
backgroundImage: `linear-gradient(to left, transparent 10%,
|
||||
backgroundImage: `linear-gradient(to left, transparent 40%,
|
||||
${artist.info.colors[0]} 50%,
|
||||
${artist.info.colors[0]} 100%)`,
|
||||
}"
|
||||
@@ -42,6 +42,7 @@ import PlayBtnRect from "../shared/PlayBtnRect.vue";
|
||||
import formatSeconds from "@/utils/useFormatSeconds";
|
||||
import { isLight } from "@/composables/colors/album";
|
||||
import { paths } from "@/config";
|
||||
import { playSources } from "@/composables/enums";
|
||||
|
||||
const artist = useArtistPageStore();
|
||||
</script>
|
||||
@@ -55,9 +56,11 @@ const artist = useArtistPageStore();
|
||||
|
||||
.artist-img {
|
||||
height: 18rem;
|
||||
|
||||
img {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
aspect-ratio: 1;
|
||||
object-fit: cover;
|
||||
object-position: 0% 20%;
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@ const artist = useArtistPageStore();
|
||||
|
||||
<style lang="scss">
|
||||
.artist-top-tracks {
|
||||
margin-bottom: 1rem;
|
||||
margin-top: 2rem;
|
||||
|
||||
.section-title {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import AlbumSvg from "@/assets/icons/album.svg";
|
||||
import FolderSvg from "@/assets/icons/folder.svg";
|
||||
import PlaylistSvg from "@/assets/icons/playlist.svg";
|
||||
import SearchSvg from "@/assets/icons/search.svg";
|
||||
import ArtistSvg from "@/assets/icons/artist.svg";
|
||||
|
||||
import { RouteLocationRaw } from "vue-router";
|
||||
|
||||
@@ -82,6 +83,18 @@ function getSource() {
|
||||
},
|
||||
};
|
||||
|
||||
case FromOptions.artist:
|
||||
return {
|
||||
name: source.artistname,
|
||||
icon: ArtistSvg,
|
||||
location: {
|
||||
name: Routes.artist,
|
||||
params: {
|
||||
hash: source.artisthash,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
default:
|
||||
return { name: "👻 No source", location: {} };
|
||||
}
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
<template>
|
||||
<button
|
||||
class="playbtnrect"
|
||||
@click="usePlayFrom(source, useQStore, store)"
|
||||
>
|
||||
<button class="playbtnrect" @click="usePlayFrom(source, useQStore, store)">
|
||||
<playBtnSvg />
|
||||
<div class="text">Play</div>
|
||||
</button>
|
||||
@@ -14,20 +11,18 @@ import usePlayFrom from "@/composables/usePlayFrom";
|
||||
import useFStore from "@/stores/pages/folder";
|
||||
import useAStore from "@/stores/pages/album";
|
||||
import usePStore from "@/stores/pages/playlist";
|
||||
import useArtistPageStore from "@/stores/pages/artist";
|
||||
import useQStore from "@/stores/queue";
|
||||
import playBtnSvg from "@/assets/icons/play.svg";
|
||||
|
||||
defineProps<{
|
||||
source: playSources;
|
||||
background?: {
|
||||
color: string;
|
||||
isDark?: boolean;
|
||||
};
|
||||
store:
|
||||
| typeof useQStore
|
||||
| typeof useFStore
|
||||
| typeof useAStore
|
||||
| typeof usePStore;
|
||||
| typeof usePStore
|
||||
| typeof useArtistPageStore;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ export enum playSources {
|
||||
album,
|
||||
search,
|
||||
folder,
|
||||
artist,
|
||||
}
|
||||
|
||||
export enum NotifType {
|
||||
@@ -16,6 +17,7 @@ export enum FromOptions {
|
||||
folder = "folder",
|
||||
album = "album",
|
||||
search = "search",
|
||||
artist = "artist",
|
||||
}
|
||||
|
||||
export enum ContextSrc {
|
||||
|
||||
@@ -21,6 +21,12 @@ const getArtistData = async (hash: string) => {
|
||||
};
|
||||
|
||||
const getArtistAlbums = async (hash: string, limit = 6) => {
|
||||
interface ArtistAlbums {
|
||||
albums: Album[];
|
||||
eps: Album[];
|
||||
singles: Album[];
|
||||
}
|
||||
|
||||
const { data, error } = await useAxios({
|
||||
get: true,
|
||||
url: paths.api.artist + `/${hash}/albums?limit=${limit}`,
|
||||
@@ -30,7 +36,20 @@ const getArtistAlbums = async (hash: string, limit = 6) => {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
return data.albums as Album[];
|
||||
return data as ArtistAlbums;
|
||||
};
|
||||
|
||||
export { getArtistData, getArtistAlbums };
|
||||
const getArtistTracks = async (hash: string, offset: number = 0, limit = 6) => {
|
||||
const { data, error } = await useAxios({
|
||||
get: true,
|
||||
url: paths.api.artist + `/${hash}/tracks?offset=${offset}&limit=${limit}`,
|
||||
});
|
||||
|
||||
if (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
return data.tracks as Track[];
|
||||
};
|
||||
|
||||
export { getArtistData, getArtistAlbums, getArtistTracks };
|
||||
|
||||
@@ -2,16 +2,24 @@ import { playSources } from "@/composables/enums";
|
||||
import useAStore from "@/stores/pages/album";
|
||||
import useFStore from "@/stores/pages/folder";
|
||||
import usePStore from "@/stores/pages/playlist";
|
||||
import useArtistPageStore from "@/stores/pages/artist";
|
||||
import { getArtistTracks } from "./fetch/artists";
|
||||
import useQStore from "@/stores/queue";
|
||||
|
||||
const queue = useQStore;
|
||||
const folder = useFStore;
|
||||
const album = useAStore;
|
||||
const playlist = usePStore;
|
||||
const artist = useArtistPageStore;
|
||||
|
||||
type store = typeof queue | typeof folder | typeof album | typeof playlist;
|
||||
type store =
|
||||
| typeof queue
|
||||
| typeof folder
|
||||
| typeof album
|
||||
| typeof playlist
|
||||
| typeof artist;
|
||||
|
||||
export default function play(
|
||||
export default async function play(
|
||||
source: playSources,
|
||||
aqueue: typeof queue,
|
||||
store: store
|
||||
@@ -20,13 +28,13 @@ export default function play(
|
||||
|
||||
switch (source) {
|
||||
// check which route the play request come from
|
||||
case playSources.folder:
|
||||
store = store as typeof folder;
|
||||
const f = store();
|
||||
// case playSources.folder:
|
||||
// store = store as typeof folder;
|
||||
// const f = store();
|
||||
|
||||
useQueue.playFromFolder(f.path, f.allTracks);
|
||||
useQueue.play();
|
||||
break;
|
||||
// useQueue.playFromFolder(f.path, f.tracks);
|
||||
// useQueue.play();
|
||||
// break;
|
||||
case playSources.album:
|
||||
store = store as typeof album;
|
||||
const a_store = store();
|
||||
@@ -47,5 +55,14 @@ export default function play(
|
||||
useQueue.playFromPlaylist(p.info.name, p.info.id, p.tracks);
|
||||
useQueue.play();
|
||||
break;
|
||||
|
||||
case playSources.artist:
|
||||
store = store as typeof artist;
|
||||
const ar = store();
|
||||
|
||||
const tracks = await getArtistTracks(ar.info.artisthash);
|
||||
|
||||
useQueue.playFromArtist(ar.info.artisthash, ar.info.name, tracks);
|
||||
useQueue.play();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,6 +110,12 @@ export interface fromSearch {
|
||||
query: string;
|
||||
}
|
||||
|
||||
export interface fromArtist {
|
||||
type: FromOptions.artist;
|
||||
artisthash: string;
|
||||
artistname: string;
|
||||
}
|
||||
|
||||
export interface subPath {
|
||||
name: string;
|
||||
path: string;
|
||||
|
||||
@@ -7,8 +7,10 @@ import { maxAbumCards } from "@/stores/content-width";
|
||||
export default defineStore("artistPage", {
|
||||
state: () => ({
|
||||
info: <Artist>{},
|
||||
albums: <Album[]>[],
|
||||
tracks: <Track[]>[],
|
||||
albums: <Album[]>[],
|
||||
eps: <Album[]>[],
|
||||
singles: <Album[]>[],
|
||||
}),
|
||||
actions: {
|
||||
async getData(hash: string) {
|
||||
@@ -18,17 +20,28 @@ export default defineStore("artistPage", {
|
||||
this.tracks = tracks;
|
||||
},
|
||||
async getArtistAlbums() {
|
||||
const albums = await getArtistAlbums(
|
||||
const { albums, eps, singles } = await getArtistAlbums(
|
||||
this.info.artisthash,
|
||||
maxAbumCards.value
|
||||
);
|
||||
|
||||
if (albums.length > 0) {
|
||||
this.albums = albums;
|
||||
}
|
||||
this.albums = albums;
|
||||
this.eps = eps;
|
||||
this.singles = singles;
|
||||
|
||||
// if (albums.length > 0) {
|
||||
// }
|
||||
|
||||
// if (eps.length > 0) {
|
||||
// }
|
||||
|
||||
// if (singles.length > 0) {
|
||||
// }
|
||||
},
|
||||
resetAlbums() {
|
||||
this.albums = [];
|
||||
this.eps = [];
|
||||
this.singles = [];
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
+12
-2
@@ -8,6 +8,7 @@ import updateMediaNotif from "../composables/mediaNotification";
|
||||
|
||||
import {
|
||||
fromAlbum,
|
||||
fromArtist,
|
||||
fromFolder,
|
||||
fromPlaylist,
|
||||
fromSearch,
|
||||
@@ -23,7 +24,7 @@ function shuffle(tracks: Track[]) {
|
||||
return shuffled;
|
||||
}
|
||||
|
||||
type From = fromFolder | fromAlbum | fromPlaylist | fromSearch;
|
||||
type From = fromFolder | fromAlbum | fromPlaylist | fromSearch | fromArtist;
|
||||
|
||||
let audio = new Audio();
|
||||
audio.autoplay = false;
|
||||
@@ -150,7 +151,7 @@ export default defineStore("Queue", {
|
||||
this.from = <fromFolder>{
|
||||
type: FromOptions.folder,
|
||||
path: fpath,
|
||||
name: fpath?.split("/").splice(-1).join(""),
|
||||
name: "Folder",
|
||||
};
|
||||
this.setNewQueue(tracks);
|
||||
},
|
||||
@@ -180,6 +181,15 @@ export default defineStore("Queue", {
|
||||
|
||||
this.setNewQueue(tracks);
|
||||
},
|
||||
playFromArtist(artisthash: string, artistname: string, tracks: Track[]) {
|
||||
this.from = <fromArtist>{
|
||||
type: FromOptions.artist,
|
||||
artisthash: artisthash,
|
||||
artistname: artistname,
|
||||
};
|
||||
|
||||
this.setNewQueue(tracks);
|
||||
},
|
||||
addTrackToQueue(track: Track) {
|
||||
this.tracklist.push(track);
|
||||
},
|
||||
|
||||
@@ -39,6 +39,7 @@ import ArtistAlbums from "@/components/AlbumView/ArtistAlbums.vue";
|
||||
import ArtistAlbumsFetcher from "@/components/ArtistView/ArtistAlbumsFetcher.vue";
|
||||
import { computed } from "vue";
|
||||
import { onBeforeRouteLeave, onBeforeRouteUpdate } from "vue-router";
|
||||
import { Album } from "@/interfaces";
|
||||
|
||||
const store = useArtistPageStore();
|
||||
|
||||
@@ -63,6 +64,17 @@ const artist_albums_fetcher: ScrollerItem = {
|
||||
component: ArtistAlbumsFetcher,
|
||||
};
|
||||
|
||||
function createAbumComponent(title: string, albums: Album[]) {
|
||||
return {
|
||||
id: title,
|
||||
component: ArtistAlbums,
|
||||
props: {
|
||||
title,
|
||||
albums,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const scrollerItems = computed(() => {
|
||||
let components = [header];
|
||||
|
||||
@@ -73,13 +85,18 @@ const scrollerItems = computed(() => {
|
||||
components = [...components, artist_albums_fetcher];
|
||||
|
||||
if (store.albums.length > 0) {
|
||||
const artistAlbums: ScrollerItem = {
|
||||
id: "artist-albums",
|
||||
component: ArtistAlbums,
|
||||
props: { title: "Albums", albums: store.albums },
|
||||
};
|
||||
const albums = createAbumComponent("Albums", store.albums);
|
||||
components.push(albums);
|
||||
}
|
||||
|
||||
components.push(artistAlbums);
|
||||
if (store.eps.length > 0) {
|
||||
const eps = createAbumComponent("EPs", store.eps);
|
||||
components.push(eps);
|
||||
}
|
||||
|
||||
if (store.singles.length > 0) {
|
||||
const singles = createAbumComponent("Singles", store.singles);
|
||||
components.push(singles);
|
||||
}
|
||||
|
||||
return components;
|
||||
@@ -97,8 +114,14 @@ onBeforeRouteLeave(async () => {
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.section-title {
|
||||
margin: 1rem;
|
||||
padding-left: 1rem;
|
||||
.artist-page {
|
||||
.artist-albums {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
margin: 1rem;
|
||||
padding-left: 1rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user