attach artist page link to ArtistName component

+ separate fetching artist albums with fetching artist info
+ include limit when fetching artist albums
+ refactor interfaces
This commit is contained in:
geoffrey45 2022-12-05 18:27:55 +03:00 committed by Mungai Njoroge
parent e54fea2d4d
commit 580dce1da9
14 changed files with 162 additions and 53 deletions

View File

@ -25,10 +25,10 @@ import { isLight } from "@/composables/colors/album";
const album = useAlbumStore();
onMounted(() => {
onMounted(async () => {
// onMounted, fetch data to be used in the component below this one.
const album = useAlbumStore();
album.fetchArtistAlbums();
await album.fetchArtistAlbums();
});
</script>

View File

@ -40,11 +40,10 @@
<div class="stats ellip">
<div class="border rounded-sm pad-sm">
<ArtistName
:artists="album.albumartists.map((a) => a.name)"
:artists="album.albumartists"
:albumartists="''"
:small="true"
/>
&nbsp; {{ album.date }} {{ album.count }}
/>&nbsp; {{ album.date }} {{ album.count }}
{{ album.count === 1 ? "Track" : "Tracks" }}
{{ formatSeconds(album.duration, true) }}
</div>
@ -57,7 +56,7 @@
v-for="a in album.albumartists"
:to="{
name: Routes.artist,
params: { hash: a.hash },
params: { hash: a.artisthash },
}"
>
<img
@ -130,6 +129,21 @@ useVisibility(albumheaderthing, handleVisibilityState);
background-color: $black;
align-items: flex-end;
// .albumartists {
// outline: solid 1px;
// // display: flex;
// // width: 100%;
// // flex-wrap: nowrap;
// // height: 1rem;
// // overflow: hidden;
// span {
// // white-space: nowrap;
// // overflow: hidden;
// // text-overflow: ellipsis;
// }
// }
.big-img {
height: calc(100%);
width: 16rem;
@ -204,6 +218,7 @@ useVisibility(albumheaderthing, handleVisibilityState);
.artist {
font-size: 1.15rem;
background-color: red;
}
}
@ -215,11 +230,20 @@ useVisibility(albumheaderthing, handleVisibilityState);
margin-bottom: 0.75rem;
font-size: 0.8rem;
.artistname {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}
div {
font-size: 0.8rem;
display: flex;
width: fit-content;
cursor: text;
flex-wrap: wrap;
// width: fit-content;
// cursor: text;
}
}
}

View File

@ -1,30 +1,55 @@
<template>
<div
v-tooltip
style="width: fit-content"
class="ellip"
v-tooltip
class="artistname ellip"
:style="{
width: 'fit-content',
fontSize: small ? '0.85rem' : smaller ? 'small' : '',
}"
@click.stop="() => {}"
>
<div v-if="artists === null || artists.length === 0">
<span>{{ albumartists }}</span>
</div>
<div v-else>
<span v-for="artist in putCommas(artists)" :key="artist">{{
artist
}}</span>
<template v-for="(artist, index) in artists" :key="artist.artisthash">
<RouterLink
class="artist"
:to="{
name: Routes.artist,
params: { hash: artist.artisthash },
}"
>{{ `${artist.name}` }}</RouterLink
>
{{ index === artists.length - 1 ? "" : ",&nbsp;" }}
</template>
</div>
</div>
</template>
<script setup lang="ts">
import { Artist } from "@/interfaces";
import { putCommas } from "@/utils";
import { Routes } from "@/composables/enums";
const props = defineProps<{
artists: string[] | null;
artists: Artist[] | null;
albumartists: string | null;
small?: boolean;
smaller?: boolean;
}>();
</script>
<style lang="scss">
.artistname {
a {
color: inherit;
cursor: pointer !important;
&:hover {
text-decoration: underline;
}
}
}
</style>

View File

@ -131,6 +131,7 @@ function showMenu(e: MouseEvent) {
.song-album {
max-width: max-content;
cursor: pointer !important;
&:hover {

View File

@ -5,22 +5,32 @@ import { Artist, Track, Album } from "@/interfaces";
const getArtistData = async (hash: string) => {
interface ArtistData {
artist: Artist;
albums: Album[];
tracks: Track[];
}
const { data, error } = await useAxios({
get: true,
url: paths.api.artist + `/${hash}?limit=6`,
url: paths.api.artist + `/${hash}`,
});
if (error) {
console.error(error);
}
console.log(data);
return data as ArtistData;
};
export { getArtistData };
const getArtistAlbums = async (hash: string, limit = 6) => {
const { data, error } = await useAxios({
get: true,
url: paths.api.artist + `/${hash}/albums?limit=${limit}`,
});
if (error) {
console.error(error);
}
return data.albums as Album[];
};
export { getArtistData, getArtistAlbums };

View File

@ -6,11 +6,16 @@ export default () => {
if ("mediaSession" in navigator) {
const queue = useQueueStore();
const { currenttrack: track } = queue;
const url = paths.images.thumb.large
if (track === undefined) {
return;
}
const url = paths.images.thumb.large;
navigator.mediaSession.metadata = new window.MediaMetadata({
title: track.title,
artist: track.artist.join(", "),
artist: track.artist.map((a) => a.name).join(", "),
artwork: [
{
src: url + track.image,

View File

@ -20,7 +20,6 @@ const imageRoutes = {
large: "/t/",
small: "/t/s/",
},
// artist: "/a/",
artist: {
large: "/a/",
small: "/a/s/",

View File

@ -9,7 +9,7 @@ export interface Track extends AlbumDisc {
id: string;
title: string;
album?: string;
artist: string[];
artist: Artist[];
albumartist: string;
albumhash?: string;
folder?: string;
@ -37,11 +37,7 @@ export interface Folder {
export interface Album {
albumid: string;
title: string;
albumartists: {
name: string;
hash: string;
image: string;
}[];
albumartists: Artist[];
count: number;
duration: number;
date: string;

View File

@ -21,5 +21,17 @@ const isMedium = computed(() => {
const albumHeaderSmall = computed(() => {
return content_width.value <= brk.album_header_small;
});
const album_card_with = 10 * 16;
export { content_width, window_width, isSmall, isMedium, albumHeaderSmall };
const maxAbumCards = computed(() => {
return Math.floor(content_width.value / album_card_with);
});
export {
content_width,
window_width,
isSmall,
isMedium,
albumHeaderSmall,
maxAbumCards,
};

View File

@ -4,11 +4,11 @@ import { ComputedRef } from "vue";
import { AlbumDisc } from "./../../interfaces";
import { FuseTrackOptions } from "@/composables/enums";
import { content_width } from "@/stores/content-width";
import { maxAbumCards } from "@/stores/content-width";
import {
getAlbumsFromArtist,
getAlbumTracks
getAlbumsFromArtist,
getAlbumTracks,
} from "../../composables/fetch/album";
import { Album, Artist, FuseResult, Track } from "../../interfaces";
import { useNotifStore } from "../notification";
@ -27,11 +27,11 @@ function sortByTrackNumber(tracks: Track[]) {
});
}
function albumHasNoDiscs(album: Album) {
if (album.is_single) return true;
// function albumHasNoDiscs(album: Album) {
// if (album.is_single) return true;
return false;
}
// return false;
// }
/**
*
@ -68,13 +68,12 @@ export default defineStore("album", {
},
async fetchArtistAlbums() {
const albumartists = this.info.albumartists;
const cardWidth = 10 * 16;
const visible_cards = Math.floor(content_width.value / cardWidth);
const albumartisthashes = albumartists.map((artist) => artist.hash);
const albumartisthashes = albumartists.map((artist) => artist.artisthash);
this.albumArtists = await getAlbumsFromArtist(
albumartisthashes.join(),
visible_cards,
maxAbumCards.value,
this.info.albumhash
);
},

View File

@ -1,7 +1,8 @@
import { defineStore } from "pinia";
import { Artist, Album, Track } from "@/interfaces";
import { getArtistData } from "@/composables/fetch/artists";
import { getArtistData, getArtistAlbums } from "@/composables/fetch/artists";
import { maxAbumCards } from "@/stores/content-width";
export default defineStore("artistPage", {
state: () => ({
@ -11,11 +12,23 @@ export default defineStore("artistPage", {
}),
actions: {
async getData(hash: string) {
const { artist, albums, tracks } = await getArtistData(hash);
const { artist, tracks } = await getArtistData(hash);
this.info = artist;
this.tracks = tracks;
this.albums = albums;
},
async getArtistAlbums() {
const albums = await getArtistAlbums(
this.info.artisthash,
maxAbumCards.value
);
if (albums.length > 0) {
this.albums = albums;
}
},
resetAlbums() {
this.albums = [];
},
},
});

View File

@ -86,7 +86,7 @@ function getSongItems() {
function getArtistAlbumComponents(): ScrollerItem[] {
return album.albumArtists.map((artist) => {
const artist_name = album.info.albumartists.find(
(a) => a.hash === artist.artisthash
(a) => a.artisthash === artist.artisthash
)?.name;
return {
id: Math.random().toString(),
@ -121,7 +121,7 @@ function playFromAlbum(index: number) {
queue.play(index);
}
onBeforeRouteUpdate(async (to: RouteLocationNormalized) => {
onBeforeRouteUpdate(async (to) => {
await album.fetchTracksAndArtists(to.params.hash.toString()).then(() => {
album.resetQuery();
album.resetAlbumArtists();

View File

@ -0,0 +1,18 @@
<template><div style="height: 1px;"></div></template>
<script setup lang="ts">
import { onMounted } from "vue";
import useArtistPageStore from "@/stores/pages/artist";
import { onBeforeRouteUpdate } from "vue-router";
const store = useArtistPageStore();
onMounted(async () => {
await store.getArtistAlbums();
});
onBeforeRouteUpdate(async (to) => {
store.resetAlbums();
await store.getArtistAlbums();
});
</script>

View File

@ -34,14 +34,13 @@ import { isMedium, isSmall } from "@/stores/content-width";
import Header from "@/components/ArtistView/Header.vue";
import TopTracks from "@/components/ArtistView/TopTracks.vue";
// import Albums from "@/components/ArtistView/Albums.vue";
import useArtistPageStore from "@/stores/pages/artist";
import ArtistAlbums from "@/components/AlbumView/ArtistAlbums.vue";
import ArtistAlbumsFetcher from "./ArtistAlbumsFetcher.vue";
import { computed } from "vue";
import { onBeforeRouteUpdate } from "vue-router";
const artistStore = useArtistPageStore();
const store = useArtistPageStore();
interface ScrollerItem {
id: string | number;
@ -59,18 +58,25 @@ const top_tracks: ScrollerItem = {
component: TopTracks,
};
const artist_albums_fetcher: ScrollerItem = {
id: "artist-albums-fetcher",
component: ArtistAlbumsFetcher,
};
const scrollerItems = computed(() => {
let components = [header];
if (artistStore.tracks.length > 0) {
if (store.tracks.length > 0) {
components.push(top_tracks);
}
if (artistStore.albums.length > 0) {
components = [...components, artist_albums_fetcher];
if (store.albums.length > 0) {
const artistAlbums: ScrollerItem = {
id: "artist-albums",
component: ArtistAlbums,
props: { title: "Albums", albums: artistStore.albums },
props: { title: "Albums", albums: store.albums },
};
components.push(artistAlbums);
@ -79,8 +85,9 @@ const scrollerItems = computed(() => {
return components;
});
onBeforeRouteUpdate((to, from, next) => {
artistStore.getData(to.params.hash as string);
onBeforeRouteUpdate(async (to) => {
await store.getData(to.params.hash as string);
});
</script>