mirror of
https://github.com/Dvorinka/swingmusic-extended.git
synced 2026-06-05 04:53:01 +00:00
feat: separate discs in album page
+ remove tooltip markup + refactor css classnames
This commit is contained in:
committed by
Mungai Njoroge
parent
278439eee8
commit
977d9282cb
@@ -2,7 +2,6 @@
|
|||||||
<ContextMenu />
|
<ContextMenu />
|
||||||
<Modal />
|
<Modal />
|
||||||
<Notification />
|
<Notification />
|
||||||
<div id="tooltip"></div>
|
|
||||||
<section
|
<section
|
||||||
id="app-grid"
|
id="app-grid"
|
||||||
:class="{
|
:class="{
|
||||||
|
|||||||
@@ -1,14 +1,9 @@
|
|||||||
|
// TEXT
|
||||||
|
|
||||||
.t-center {
|
.t-center {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.image {
|
|
||||||
background-position: center;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: cover;
|
|
||||||
transition: transform 0.3s ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ellip {
|
.ellip {
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
-webkit-line-clamp: 1;
|
-webkit-line-clamp: 1;
|
||||||
@@ -20,6 +15,24 @@
|
|||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.heading {
|
||||||
|
font-size: 2rem;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image {
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: cover;
|
||||||
|
transition: transform 0.3s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// BORDERS
|
||||||
.rounded {
|
.rounded {
|
||||||
border-radius: 1rem;
|
border-radius: 1rem;
|
||||||
}
|
}
|
||||||
@@ -36,8 +49,8 @@
|
|||||||
border-radius: 10rem;
|
border-radius: 10rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.flex {
|
.border {
|
||||||
display: flex;
|
border: 1px solid $gray3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg-primary {
|
.bg-primary {
|
||||||
@@ -45,20 +58,7 @@
|
|||||||
box-shadow: 0 0 1rem rgba(0, 0, 0, 0.425);
|
box-shadow: 0 0 1rem rgba(0, 0, 0, 0.425);
|
||||||
}
|
}
|
||||||
|
|
||||||
.border {
|
// BUTTONS
|
||||||
border: 1px solid $gray3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.heading {
|
|
||||||
font-size: 2rem;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
text-decoration: none;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
button {
|
||||||
border: none;
|
border: none;
|
||||||
font-size: 0.9rem !important;
|
font-size: 0.9rem !important;
|
||||||
@@ -99,6 +99,23 @@ button {
|
|||||||
width: 2.5rem;
|
width: 2.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// POSITION
|
||||||
|
|
||||||
|
.abs {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
// OTHERS
|
||||||
|
.grid {
|
||||||
|
display: grid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
.separator {
|
.separator {
|
||||||
border-top: 1px $separator solid;
|
border-top: 1px $separator solid;
|
||||||
color: transparent;
|
color: transparent;
|
||||||
@@ -106,37 +123,15 @@ button {
|
|||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NO THIS, NO THAT (OVERRIDES)
|
||||||
.no-border {
|
.no-border {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.noscroll {
|
.no-scroll {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.abs {
|
.no-select {
|
||||||
position: absolute;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid {
|
|
||||||
display: grid;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-dark {
|
|
||||||
background-color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tooltip {
|
|
||||||
background-color: $darkestblue;
|
|
||||||
border-radius: $smaller;
|
|
||||||
padding: $smaller;
|
|
||||||
font-size: 0.85rem;
|
|
||||||
visibility: hidden;
|
|
||||||
position: absolute;
|
|
||||||
z-index: 300;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tooltip[data-popper-reference-hidden] {
|
|
||||||
visibility: hidden !important;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
@@ -14,6 +14,7 @@ $large: 1.5rem;
|
|||||||
$larger: 2rem;
|
$larger: 2rem;
|
||||||
|
|
||||||
$banner-height: 18rem;
|
$banner-height: 18rem;
|
||||||
|
$song-item-height: 4rem;
|
||||||
|
|
||||||
// apple human design guideline colors
|
// apple human design guideline colors
|
||||||
$black: #181a1c;
|
$black: #181a1c;
|
||||||
@@ -49,9 +50,6 @@ $playlist-card-bg: $gray4;
|
|||||||
|
|
||||||
// SVG COLORS
|
// SVG COLORS
|
||||||
$default: $accent;
|
$default: $accent;
|
||||||
$track-btn-svg: $accent;
|
|
||||||
$side-nav-svg: $red;
|
$side-nav-svg: $red;
|
||||||
|
|
||||||
|
|
||||||
$overshoot: cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
$overshoot: cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="album_disc_header no-select"
|
||||||
|
v-if="album_disc.is_album_disc_number"
|
||||||
|
>
|
||||||
|
<div class="disc_number">Disc {{ album_disc.album_page_disc_number }}</div>
|
||||||
|
<div></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { AlbumDisc } from "@/interfaces";
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
album_disc: AlbumDisc;
|
||||||
|
}>();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.album_disc_header {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr max-content;
|
||||||
|
align-items: center;
|
||||||
|
padding-left: 1rem;
|
||||||
|
height: $song-item-height;
|
||||||
|
|
||||||
|
.disc_number {
|
||||||
|
font-size: $medium;
|
||||||
|
opacity: 0.75;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
: '',
|
: '',
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<div class="big-img noscroll" :class="{ imgSmall: widthIsSmall }">
|
<div class="big-img no-scroll" :class="{ imgSmall: widthIsSmall }">
|
||||||
<img :src="imguri.thumb.large + album.image" class="rounded" />
|
<img :src="imguri.thumb.large + album.image" class="rounded" />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
@@ -59,13 +59,13 @@
|
|||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
|
|
||||||
import { paths } from "@/config";
|
import { paths } from "@/config";
|
||||||
import useNavStore from "@/stores/nav";
|
|
||||||
import { AlbumInfo } from "../../interfaces";
|
|
||||||
import useAlbumStore from "@/stores/pages/album";
|
|
||||||
import { playSources } from "../../composables/enums";
|
|
||||||
import { useVisibility, formatSeconds } from "@/utils";
|
|
||||||
import { getButtonColor, isLight } from "../../composables/colors/album";
|
|
||||||
import { isSmall as widthIsSmall } from "@/stores/content-width";
|
import { isSmall as widthIsSmall } from "@/stores/content-width";
|
||||||
|
import useNavStore from "@/stores/nav";
|
||||||
|
import useAlbumStore from "@/stores/pages/album";
|
||||||
|
import { formatSeconds, useVisibility } from "@/utils";
|
||||||
|
import { getButtonColor, isLight } from "../../composables/colors/album";
|
||||||
|
import { playSources } from "../../composables/enums";
|
||||||
|
import { AlbumInfo } from "../../interfaces";
|
||||||
|
|
||||||
import PlayBtnRect from "../shared/PlayBtnRect.vue";
|
import PlayBtnRect from "../shared/PlayBtnRect.vue";
|
||||||
|
|
||||||
|
|||||||
@@ -71,9 +71,9 @@ import { formatSeconds } from "@/utils";
|
|||||||
import { Routes } from "@/composables/enums";
|
import { Routes } from "@/composables/enums";
|
||||||
import useSettingsStore from "@/stores/settings";
|
import useSettingsStore from "@/stores/settings";
|
||||||
|
|
||||||
import ArtistName from "@/components/shared/ArtistName.vue";
|
|
||||||
import HotKeys from "@/components/LeftSidebar/NP/HotKeys.vue";
|
import HotKeys from "@/components/LeftSidebar/NP/HotKeys.vue";
|
||||||
import Progress from "@/components/LeftSidebar/NP/Progress.vue";
|
import Progress from "@/components/LeftSidebar/NP/Progress.vue";
|
||||||
|
import ArtistName from "@/components/shared/ArtistName.vue";
|
||||||
|
|
||||||
import HeartSvg from "@/assets/icons/heart.svg";
|
import HeartSvg from "@/assets/icons/heart.svg";
|
||||||
// import PlusSvg from "@/assets/icons/plus.svg";
|
// import PlusSvg from "@/assets/icons/plus.svg";
|
||||||
@@ -159,7 +159,7 @@ const settings = useSettingsStore();
|
|||||||
}
|
}
|
||||||
|
|
||||||
.time {
|
.time {
|
||||||
font-size: 12px;
|
font-size: $medium;
|
||||||
height: fit-content;
|
height: fit-content;
|
||||||
width: 3rem;
|
width: 3rem;
|
||||||
|
|
||||||
@@ -187,7 +187,7 @@ const settings = useSettingsStore();
|
|||||||
.artist {
|
.artist {
|
||||||
opacity: 0.75;
|
opacity: 0.75;
|
||||||
margin-bottom: -$smaller;
|
margin-bottom: -$smaller;
|
||||||
font-size: 12px;
|
font-size: $medium;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="hotkeys rounded-sm noscroll">
|
<div class="hotkeys rounded-sm no-scroll">
|
||||||
<button @click.prevent="q.playPrev">
|
<button @click.prevent="q.playPrev">
|
||||||
<PrevSvg />
|
<PrevSvg />
|
||||||
</button>
|
</button>
|
||||||
@@ -16,8 +16,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import useQStore from "@/stores/queue";
|
import useQStore from "@/stores/queue";
|
||||||
|
|
||||||
import NextSvg from "../../../assets/icons/next.svg";
|
import { default as NextSvg, default as PrevSvg } from "../../../assets/icons/next.svg";
|
||||||
import PrevSvg from "../../../assets/icons/next.svg";
|
|
||||||
import PauseSvg from "../../../assets/icons/pause.svg";
|
import PauseSvg from "../../../assets/icons/pause.svg";
|
||||||
import PlaySvg from "../../../assets/icons/play.svg";
|
import PlaySvg from "../../../assets/icons/play.svg";
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-auto-animate class="l-sidebar noscroll">
|
<div v-auto-animate class="l-sidebar no-scroll">
|
||||||
<div class="withlogo">
|
<div class="withlogo">
|
||||||
<Logo />
|
<Logo />
|
||||||
<Navigation />
|
<Navigation />
|
||||||
@@ -11,8 +11,8 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import Navigation from "@/components/LeftSidebar/Navigation.vue";
|
import Navigation from "@/components/LeftSidebar/Navigation.vue";
|
||||||
import NowPlayingImage from "./NowPlayingImg.vue";
|
|
||||||
import Logo from "@/components/Logo.vue";
|
import Logo from "@/components/Logo.vue";
|
||||||
|
import NowPlayingImage from "./NowPlayingImg.vue";
|
||||||
|
|
||||||
import useSettingsStore from "@/stores/settings";
|
import useSettingsStore from "@/stores/settings";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="p-header image rounded noscroll"
|
class="p-header image rounded no-scroll"
|
||||||
ref="playlistheader"
|
ref="playlistheader"
|
||||||
:style="[
|
:style="[
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<router-link
|
<router-link
|
||||||
:to="{ name: 'PlaylistView', params: { pid: playlist.playlistid } }"
|
:to="{ name: 'PlaylistView', params: { pid: playlist.playlistid } }"
|
||||||
class="p-card rounded noscroll"
|
class="p-card rounded no-scroll"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
:src="imguri + playlist.thumb"
|
:src="imguri + playlist.thumb"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="r-sidebar">
|
<div class="r-sidebar">
|
||||||
<SearchInput />
|
<SearchInput />
|
||||||
<div v-auto-animate class="r-content noscroll" >
|
<div v-auto-animate class="r-content no-scroll" >
|
||||||
<div class="r-dash" v-if="tabs.current === tabs.tabs.home">
|
<div class="r-dash" v-if="tabs.current === tabs.tabs.home">
|
||||||
<DashBoard />
|
<DashBoard />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<div id="right-tabs" class="rounded">
|
<div id="right-tabs" class="rounded">
|
||||||
<div class="tab-buttons-wrapper">
|
<div class="tab-buttons-wrapper">
|
||||||
<Teleport :disabled="!isOnSearchPage" to="#nav-tab-headers">
|
<Teleport :disabled="!isOnSearchPage" to="#nav-tab-headers">
|
||||||
<div class="tabheaders rounded-sm noscroll">
|
<div class="tabheaders rounded-sm no-scroll">
|
||||||
<div
|
<div
|
||||||
class="tab"
|
class="tab"
|
||||||
v-for="tab in tabs"
|
v-for="tab in tabs"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="tracks-results" class="noscroll">
|
<div id="tracks-results" class="no-scroll">
|
||||||
<div v-if="search.tracks.value.length">
|
<div v-if="search.tracks.value.length">
|
||||||
<TrackComponent
|
<TrackComponent
|
||||||
v-for="(track, index) in search.tracks.value"
|
v-for="(track, index) in search.tracks.value"
|
||||||
|
|||||||
@@ -159,22 +159,5 @@ function update_playlist(e: Event) {
|
|||||||
background-color: $gray4;
|
background-color: $gray4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
textarea {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 28rem;
|
|
||||||
max-height: 5rem;
|
|
||||||
color: $white;
|
|
||||||
background-color: $gray2;
|
|
||||||
border: none;
|
|
||||||
font-family: inherit;
|
|
||||||
padding: $small;
|
|
||||||
outline: none;
|
|
||||||
margin: $small 0;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
outline: solid 2px $gray1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="nav-search">
|
|
||||||
<form>
|
|
||||||
<input
|
|
||||||
type="search"
|
|
||||||
name=""
|
|
||||||
id=""
|
|
||||||
placeholder="Search here"
|
|
||||||
class="rounded"
|
|
||||||
/>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
#nav-search {
|
|
||||||
// border: solid 1px $gray2;
|
|
||||||
|
|
||||||
form {
|
|
||||||
display: flex;
|
|
||||||
gap: $small;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
|
|
||||||
input[type="search"] {
|
|
||||||
background-color: $gray5;
|
|
||||||
border: none;
|
|
||||||
padding: $small;
|
|
||||||
width: 100%;
|
|
||||||
color: $white;
|
|
||||||
font-size: 1rem;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
outline: solid $accent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="nav-queue-title">
|
<div class="nav-queue-title">
|
||||||
<div class="first noscroll">
|
<div class="first no-scroll">
|
||||||
<router-link :to="(location as RouteLocationRaw)">
|
<router-link :to="(location as RouteLocationRaw)">
|
||||||
<button>Go to source</button>
|
<button class="btn-active">Go to source</button>
|
||||||
</router-link>
|
</router-link>
|
||||||
<div class="playing-from">
|
<div class="playing-from">
|
||||||
<div class="border rounded-sm pad-sm">
|
<div class="border rounded-sm pad-sm">
|
||||||
|
|||||||
@@ -12,11 +12,8 @@
|
|||||||
<HeartSvg />
|
<HeartSvg />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<div v-auto-animate @click.pre@dblclick.prevent="emitUpdate" class="thumbnail">
|
<div @click.prevent="emitUpdate" class="thumbnail">
|
||||||
<img
|
<img :src="imguri + track.image" class="album-art image rounded-sm" />
|
||||||
:src="imguri + track.image"
|
|
||||||
class="album-art image rounded-sm"
|
|
||||||
/>
|
|
||||||
<div
|
<div
|
||||||
class="now-playing-track-indicator image"
|
class="now-playing-track-indicator image"
|
||||||
v-if="isCurrent"
|
v-if="isCurrent"
|
||||||
@@ -24,11 +21,7 @@
|
|||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
<div v-tooltip class="song-title">
|
<div v-tooltip class="song-title">
|
||||||
<div
|
<div class="title ellip" @click.prevent="emitUpdate" ref="artisttitle">
|
||||||
class="title ellip"
|
|
||||||
@click.pre@dblclick.prevent="emitUpdate"
|
|
||||||
ref="artisttitle"
|
|
||||||
>
|
|
||||||
{{ track.title }}
|
{{ track.title }}
|
||||||
</div>
|
</div>
|
||||||
<div class="isSmallArtists" style="display: none">
|
<div class="isSmallArtists" style="display: none">
|
||||||
@@ -58,7 +51,7 @@
|
|||||||
<div class="song-duration">{{ formatSeconds(track.duration) }}</div>
|
<div class="song-duration">{{ formatSeconds(track.duration) }}</div>
|
||||||
<div
|
<div
|
||||||
class="options-icon circular"
|
class="options-icon circular"
|
||||||
:class="{ options_button_clicked }"
|
:class="{ 'btn-active': options_button_clicked }"
|
||||||
@click.stop="showMenu"
|
@click.stop="showMenu"
|
||||||
@dblclick.stop="() => {}"
|
@dblclick.stop="() => {}"
|
||||||
>
|
>
|
||||||
@@ -72,7 +65,7 @@ import { ref } from "vue";
|
|||||||
|
|
||||||
import { showTrackContextMenu as showContext } from "@/composables/context";
|
import { showTrackContextMenu as showContext } from "@/composables/context";
|
||||||
import { paths } from "@/config";
|
import { paths } from "@/config";
|
||||||
import { Track } from "@/interfaces";
|
import { AlbumDisc, Track } from "@/interfaces";
|
||||||
import { formatSeconds } from "@/utils";
|
import { formatSeconds } from "@/utils";
|
||||||
|
|
||||||
import HeartSvg from "@/assets/icons/heart.svg";
|
import HeartSvg from "@/assets/icons/heart.svg";
|
||||||
@@ -87,7 +80,7 @@ const artisttitle = ref<HTMLElement | null>(null);
|
|||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
track: Track;
|
track: Track;
|
||||||
index: number | string;
|
index: Number | String;
|
||||||
isCurrent: Boolean;
|
isCurrent: Boolean;
|
||||||
isCurrentPlaying: Boolean;
|
isCurrentPlaying: Boolean;
|
||||||
no_album?: Boolean;
|
no_album?: Boolean;
|
||||||
@@ -107,12 +100,14 @@ function showMenu(e: Event) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|
||||||
|
|
||||||
.songlist-item {
|
.songlist-item {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1.5rem 2fr 1fr 1.5fr 2.5rem 2.5rem;
|
grid-template-columns: 1.5rem 2fr 1fr 1.5fr 2.5rem 2.5rem;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
height: 3.75rem;
|
height: $song-item-height;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
padding-left: $small;
|
padding-left: $small;
|
||||||
@@ -190,16 +185,11 @@ function showMenu(e: Event) {
|
|||||||
width: 2rem;
|
width: 2rem;
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
transition: all 0.2s ease-in;
|
stroke: $white;
|
||||||
stroke: $track-btn-svg;
|
|
||||||
|
|
||||||
circle {
|
|
||||||
fill: $track-btn-svg;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: $gray5;
|
background-color: $darkestblue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-4
@@ -1,6 +1,11 @@
|
|||||||
import { FromOptions, NotifType } from "./composables/enums";
|
import { FromOptions, NotifType } from "./composables/enums";
|
||||||
|
|
||||||
export interface Track {
|
export interface AlbumDisc {
|
||||||
|
is_album_disc_number?: boolean;
|
||||||
|
album_page_disc_number?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Track extends AlbumDisc {
|
||||||
trackid: string;
|
trackid: string;
|
||||||
title: string;
|
title: string;
|
||||||
album?: string;
|
album?: string;
|
||||||
@@ -18,7 +23,7 @@ export interface Track {
|
|||||||
index: number;
|
index: number;
|
||||||
hash: string;
|
hash: string;
|
||||||
copyright?: string;
|
copyright?: string;
|
||||||
filetype: string
|
filetype: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Folder {
|
export interface Folder {
|
||||||
@@ -116,5 +121,3 @@ export interface FuseResult {
|
|||||||
item: Track;
|
item: Track;
|
||||||
refIndex: number;
|
refIndex: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -20,33 +20,40 @@
|
|||||||
ref="header"
|
ref="header"
|
||||||
class="header rounded"
|
class="header rounded"
|
||||||
v-if="!no_header"
|
v-if="!no_header"
|
||||||
:style="{ height: headerHeight + 24 + 'px' }"
|
:style="{ height: headerHeight + (on_album_page ? 0 : 24) + 'px' }"
|
||||||
>
|
>
|
||||||
<div ref="header_content" class="header-content">
|
<div ref="header_content" class="header-content">
|
||||||
<slot name="header"></slot>
|
<slot name="header"></slot>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<SongItem
|
<div v-for="t in tracks">
|
||||||
style="height: 60px"
|
<AlbumDiscBar
|
||||||
v-for="t in tracks"
|
v-if="on_album_page && t.data.is_album_disc_number"
|
||||||
:key="t.data.trackid"
|
:album_disc="t.data"
|
||||||
:track="t.data"
|
/>
|
||||||
:no_album="on_album_page"
|
|
||||||
:index="
|
<SongItem
|
||||||
on_album_page
|
v-else
|
||||||
? t.data.track
|
style="height: 60px"
|
||||||
: t.data.index !== undefined
|
:key="t.data.trackid"
|
||||||
? t.data.index + 1
|
:track="t.data"
|
||||||
: t.index + 1
|
:no_album="on_album_page"
|
||||||
"
|
:index="
|
||||||
:isCurrent="queue.currentid === t.data.trackid"
|
on_album_page
|
||||||
:isCurrentPlaying="
|
? t.data.track
|
||||||
queue.currentid === t.data.trackid && queue.playing
|
: t.data.index !== undefined
|
||||||
"
|
? t.data.index + 1
|
||||||
@playThis="
|
: t.index + 1
|
||||||
updateQueue(t.data.index !== undefined ? t.data.index : t.index)
|
"
|
||||||
"
|
:isCurrent="queue.currentid === t.data.trackid"
|
||||||
/>
|
:isCurrentPlaying="
|
||||||
|
queue.currentid === t.data.trackid && queue.playing
|
||||||
|
"
|
||||||
|
@playThis="
|
||||||
|
updateQueue(t.data.index !== undefined ? t.data.index : t.index)
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div class="page-bottom-padding" style="height: 64px"></div>
|
<div class="page-bottom-padding" style="height: 64px"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -61,7 +68,7 @@ import { Track } from "@/interfaces";
|
|||||||
import useQStore from "@/stores/queue";
|
import useQStore from "@/stores/queue";
|
||||||
|
|
||||||
import SongItem from "@/components/shared/SongItem.vue";
|
import SongItem from "@/components/shared/SongItem.vue";
|
||||||
|
import AlbumDiscBar from "@/components/AlbumView/AlbumDiscBar.vue";
|
||||||
// EMITS & PROPS
|
// EMITS & PROPS
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: "playFromPage", index: number): void;
|
(e: "playFromPage", index: number): void;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useFuse } from "@/utils";
|
import { useFuse } from "@/utils";
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { ComputedRef } from "vue";
|
import { ComputedRef } from "vue";
|
||||||
|
import { AlbumDisc } from "./../../interfaces";
|
||||||
|
|
||||||
import { FuseTrackOptions } from "@/composables/enums";
|
import { FuseTrackOptions } from "@/composables/enums";
|
||||||
|
|
||||||
@@ -62,7 +63,18 @@ export default defineStore("album", {
|
|||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
filteredTracks(): ComputedRef<FuseResult[]> {
|
filteredTracks(): ComputedRef<FuseResult[]> {
|
||||||
return useFuse(this.query, this.allTracks, FuseTrackOptions);
|
const discs = createDiscs(this.allTracks);
|
||||||
|
let tracks: (Track[] | AlbumDisc[]) = [];
|
||||||
|
|
||||||
|
Object.keys(discs).forEach((disc) => {
|
||||||
|
const discHeader = {
|
||||||
|
is_album_disc_number: true,
|
||||||
|
album_page_disc_number: parseInt(disc),
|
||||||
|
} as AlbumDisc;
|
||||||
|
tracks = [...tracks, discHeader, ...discs[disc]];
|
||||||
|
});
|
||||||
|
|
||||||
|
return useFuse(this.query, tracks, FuseTrackOptions);
|
||||||
},
|
},
|
||||||
tracks(): Track[] {
|
tracks(): Track[] {
|
||||||
const tracks = this.filteredTracks.value.map((result: FuseResult) => {
|
const tracks = this.filteredTracks.value.map((result: FuseResult) => {
|
||||||
@@ -76,8 +88,5 @@ export default defineStore("album", {
|
|||||||
|
|
||||||
return tracks;
|
return tracks;
|
||||||
},
|
},
|
||||||
discs(): Discs {
|
|
||||||
return createDiscs(this.tracks);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,10 +12,28 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import useQStore from "@/stores/queue";
|
import useQStore from "@/stores/queue";
|
||||||
import Layout from "@/layouts/HeaderAndVList.vue";
|
import Layout from "@/layouts/HeaderAndVList.vue";
|
||||||
|
import { onBeforeMount, onMounted } from "vue";
|
||||||
|
|
||||||
const queue = useQStore();
|
const queue = useQStore();
|
||||||
|
|
||||||
function playFromQueue(index: number) {
|
function playFromQueue(index: number) {
|
||||||
queue.play(index);
|
queue.play(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function scrollToCurrent() {
|
||||||
|
const scrollable = document.getElementById("v-page-scrollable");
|
||||||
|
const itemHeight = 64;
|
||||||
|
const top = queue.currentindex * itemHeight - 290;
|
||||||
|
|
||||||
|
scrollable?.scrollTo({
|
||||||
|
top,
|
||||||
|
behavior: "smooth",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
scrollToCurrent();
|
||||||
|
}, 1000);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
{{ page }}
|
{{ page }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div ref="page" class="page noscroll" v-auto-animate>
|
<div ref="page" class="page no-scroll" v-auto-animate>
|
||||||
<component :is="component" />
|
<component :is="component" />
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
@@ -28,14 +28,14 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useRoute } from "vue-router";
|
|
||||||
import { computed, onMounted, ref } from "vue";
|
|
||||||
import TracksPage from "./tracks.vue";
|
|
||||||
import AlbumPage from "./albums.vue";
|
|
||||||
import ArtistPage from "./artists.vue";
|
|
||||||
import { Routes } from "@/composables/enums";
|
import { Routes } from "@/composables/enums";
|
||||||
import useSearchStore from "@/stores/search";
|
import useSearchStore from "@/stores/search";
|
||||||
import { focusElemByClass } from "@/utils";
|
import { focusElemByClass } from "@/utils";
|
||||||
|
import { computed, onMounted, ref } from "vue";
|
||||||
|
import { useRoute } from "vue-router";
|
||||||
|
import AlbumPage from "./albums.vue";
|
||||||
|
import ArtistPage from "./artists.vue";
|
||||||
|
import TracksPage from "./tracks.vue";
|
||||||
|
|
||||||
// width of album and artist cards
|
// width of album and artist cards
|
||||||
const defaultItemCount = 6;
|
const defaultItemCount = 6;
|
||||||
@@ -169,7 +169,7 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.page.noscroll {
|
.page.no-scroll {
|
||||||
overflow-x: visible;
|
overflow-x: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="search-tracks-view">
|
<div class="search-tracks-view">
|
||||||
<div class="noscroll">
|
<div class="no-scroll">
|
||||||
<Layout :no_header="true" :tracks="search.tracks.value" />
|
<Layout :no_header="true" :tracks="search.tracks.value" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -17,7 +17,7 @@ const search = useSearchStore();
|
|||||||
.search-tracks-view {
|
.search-tracks-view {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
.noscroll {
|
.no-scroll {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user