feat: separate discs in album page

+ remove tooltip markup
+ refactor css classnames
This commit is contained in:
geoffrey45
2022-10-01 21:35:02 +03:00
committed by Mungai Njoroge
parent 278439eee8
commit 977d9282cb
23 changed files with 187 additions and 193 deletions
-1
View File
@@ -2,7 +2,6 @@
<ContextMenu />
<Modal />
<Notification />
<div id="tooltip"></div>
<section
id="app-grid"
:class="{
+45 -50
View File
@@ -1,14 +1,9 @@
// TEXT
.t-center {
text-align: center;
}
.image {
background-position: center;
background-repeat: no-repeat;
background-size: cover;
transition: transform 0.3s ease-in-out;
}
.ellip {
display: -webkit-box;
-webkit-line-clamp: 1;
@@ -20,6 +15,24 @@
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 {
border-radius: 1rem;
}
@@ -36,8 +49,8 @@
border-radius: 10rem;
}
.flex {
display: flex;
.border {
border: 1px solid $gray3;
}
.bg-primary {
@@ -45,20 +58,7 @@
box-shadow: 0 0 1rem rgba(0, 0, 0, 0.425);
}
.border {
border: 1px solid $gray3;
}
.heading {
font-size: 2rem;
font-weight: bold;
}
a {
text-decoration: none;
color: #fff;
}
// BUTTONS
button {
border: none;
font-size: 0.9rem !important;
@@ -99,6 +99,23 @@ button {
width: 2.5rem;
}
// POSITION
.abs {
position: absolute;
}
// OTHERS
.grid {
display: grid;
}
.flex {
display: flex;
}
.separator {
border-top: 1px $separator solid;
color: transparent;
@@ -106,37 +123,15 @@ button {
opacity: 0.5;
}
// NO THIS, NO THAT (OVERRIDES)
.no-border {
border: none;
}
.noscroll {
.no-scroll {
overflow: hidden;
}
.abs {
position: absolute;
}
.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;
}
.no-select {
user-select: none;
}
+1 -3
View File
@@ -14,6 +14,7 @@ $large: 1.5rem;
$larger: 2rem;
$banner-height: 18rem;
$song-item-height: 4rem;
// apple human design guideline colors
$black: #181a1c;
@@ -49,9 +50,6 @@ $playlist-card-bg: $gray4;
// SVG COLORS
$default: $accent;
$track-btn-svg: $accent;
$side-nav-svg: $red;
$overshoot: cubic-bezier(0.68, -0.55, 0.265, 1.55);
+32
View File
@@ -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>
+7 -7
View File
@@ -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" />
</div>
<div
@@ -59,13 +59,13 @@
import { ref } from "vue";
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 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";
+3 -3
View File
@@ -71,9 +71,9 @@ import { formatSeconds } from "@/utils";
import { Routes } from "@/composables/enums";
import useSettingsStore from "@/stores/settings";
import ArtistName from "@/components/shared/ArtistName.vue";
import HotKeys from "@/components/LeftSidebar/NP/HotKeys.vue";
import Progress from "@/components/LeftSidebar/NP/Progress.vue";
import ArtistName from "@/components/shared/ArtistName.vue";
import HeartSvg from "@/assets/icons/heart.svg";
// import PlusSvg from "@/assets/icons/plus.svg";
@@ -159,7 +159,7 @@ const settings = useSettingsStore();
}
.time {
font-size: 12px;
font-size: $medium;
height: fit-content;
width: 3rem;
@@ -187,7 +187,7 @@ const settings = useSettingsStore();
.artist {
opacity: 0.75;
margin-bottom: -$smaller;
font-size: 12px;
font-size: $medium;
}
}
}
+2 -3
View File
@@ -1,5 +1,5 @@
<template>
<div class="hotkeys rounded-sm noscroll">
<div class="hotkeys rounded-sm no-scroll">
<button @click.prevent="q.playPrev">
<PrevSvg />
</button>
@@ -16,8 +16,7 @@
<script setup lang="ts">
import useQStore from "@/stores/queue";
import NextSvg from "../../../assets/icons/next.svg";
import PrevSvg from "../../../assets/icons/next.svg";
import { default as NextSvg, default as PrevSvg } from "../../../assets/icons/next.svg";
import PauseSvg from "../../../assets/icons/pause.svg";
import PlaySvg from "../../../assets/icons/play.svg";
+2 -2
View File
@@ -1,5 +1,5 @@
<template>
<div v-auto-animate class="l-sidebar noscroll">
<div v-auto-animate class="l-sidebar no-scroll">
<div class="withlogo">
<Logo />
<Navigation />
@@ -11,8 +11,8 @@
<script setup lang="ts">
import Navigation from "@/components/LeftSidebar/Navigation.vue";
import NowPlayingImage from "./NowPlayingImg.vue";
import Logo from "@/components/Logo.vue";
import NowPlayingImage from "./NowPlayingImg.vue";
import useSettingsStore from "@/stores/settings";
+1 -1
View File
@@ -1,6 +1,6 @@
<template>
<div
class="p-header image rounded noscroll"
class="p-header image rounded no-scroll"
ref="playlistheader"
:style="[
{
@@ -1,7 +1,7 @@
<template>
<router-link
:to="{ name: 'PlaylistView', params: { pid: playlist.playlistid } }"
class="p-card rounded noscroll"
class="p-card rounded no-scroll"
>
<img
:src="imguri + playlist.thumb"
+1 -1
View File
@@ -1,7 +1,7 @@
<template>
<div class="r-sidebar">
<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">
<DashBoard />
</div>
@@ -2,7 +2,7 @@
<div id="right-tabs" class="rounded">
<div class="tab-buttons-wrapper">
<Teleport :disabled="!isOnSearchPage" to="#nav-tab-headers">
<div class="tabheaders rounded-sm noscroll">
<div class="tabheaders rounded-sm no-scroll">
<div
class="tab"
v-for="tab in tabs"
@@ -1,5 +1,5 @@
<template>
<div id="tracks-results" class="noscroll">
<div id="tracks-results" class="no-scroll">
<div v-if="search.tracks.value.length">
<TrackComponent
v-for="(track, index) in search.tracks.value"
-17
View File
@@ -159,22 +159,5 @@ function update_playlist(e: Event) {
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>
-39
View File
@@ -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>
+2 -2
View File
@@ -1,8 +1,8 @@
<template>
<div class="nav-queue-title">
<div class="first noscroll">
<div class="first no-scroll">
<router-link :to="(location as RouteLocationRaw)">
<button>Go to source</button>
<button class="btn-active">Go to source</button>
</router-link>
<div class="playing-from">
<div class="border rounded-sm pad-sm">
+11 -21
View File
@@ -12,11 +12,8 @@
<HeartSvg />
</div>
<div class="flex">
<div v-auto-animate @click.pre@dblclick.prevent="emitUpdate" class="thumbnail">
<img
:src="imguri + track.image"
class="album-art image rounded-sm"
/>
<div @click.prevent="emitUpdate" class="thumbnail">
<img :src="imguri + track.image" class="album-art image rounded-sm" />
<div
class="now-playing-track-indicator image"
v-if="isCurrent"
@@ -24,11 +21,7 @@
></div>
</div>
<div v-tooltip class="song-title">
<div
class="title ellip"
@click.pre@dblclick.prevent="emitUpdate"
ref="artisttitle"
>
<div class="title ellip" @click.prevent="emitUpdate" ref="artisttitle">
{{ track.title }}
</div>
<div class="isSmallArtists" style="display: none">
@@ -58,7 +51,7 @@
<div class="song-duration">{{ formatSeconds(track.duration) }}</div>
<div
class="options-icon circular"
:class="{ options_button_clicked }"
:class="{ 'btn-active': options_button_clicked }"
@click.stop="showMenu"
@dblclick.stop="() => {}"
>
@@ -72,7 +65,7 @@ import { ref } from "vue";
import { showTrackContextMenu as showContext } from "@/composables/context";
import { paths } from "@/config";
import { Track } from "@/interfaces";
import { AlbumDisc, Track } from "@/interfaces";
import { formatSeconds } from "@/utils";
import HeartSvg from "@/assets/icons/heart.svg";
@@ -87,7 +80,7 @@ const artisttitle = ref<HTMLElement | null>(null);
const props = defineProps<{
track: Track;
index: number | string;
index: Number | String;
isCurrent: Boolean;
isCurrentPlaying: Boolean;
no_album?: Boolean;
@@ -107,12 +100,14 @@ function showMenu(e: Event) {
</script>
<style lang="scss">
.songlist-item {
display: grid;
grid-template-columns: 1.5rem 2fr 1fr 1.5fr 2.5rem 2.5rem;
align-items: center;
justify-content: flex-start;
height: 3.75rem;
height: $song-item-height;
gap: 1rem;
user-select: none;
padding-left: $small;
@@ -190,16 +185,11 @@ function showMenu(e: Event) {
width: 2rem;
svg {
transition: all 0.2s ease-in;
stroke: $track-btn-svg;
circle {
fill: $track-btn-svg;
}
stroke: $white;
}
&:hover {
background-color: $gray5;
background-color: $darkestblue;
}
}
+7 -4
View File
@@ -1,6 +1,11 @@
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;
title: string;
album?: string;
@@ -18,7 +23,7 @@ export interface Track {
index: number;
hash: string;
copyright?: string;
filetype: string
filetype: string;
}
export interface Folder {
@@ -116,5 +121,3 @@ export interface FuseResult {
item: Track;
refIndex: number;
}
+30 -23
View File
@@ -20,33 +20,40 @@
ref="header"
class="header rounded"
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">
<slot name="header"></slot>
</div>
</div>
<SongItem
style="height: 60px"
v-for="t in tracks"
:key="t.data.trackid"
:track="t.data"
:no_album="on_album_page"
:index="
on_album_page
? t.data.track
: t.data.index !== undefined
? t.data.index + 1
: t.index + 1
"
: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 v-for="t in tracks">
<AlbumDiscBar
v-if="on_album_page && t.data.is_album_disc_number"
:album_disc="t.data"
/>
<SongItem
v-else
style="height: 60px"
:key="t.data.trackid"
:track="t.data"
:no_album="on_album_page"
:index="
on_album_page
? t.data.track
: t.data.index !== undefined
? t.data.index + 1
: t.index + 1
"
: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>
</div>
@@ -61,7 +68,7 @@ import { Track } from "@/interfaces";
import useQStore from "@/stores/queue";
import SongItem from "@/components/shared/SongItem.vue";
import AlbumDiscBar from "@/components/AlbumView/AlbumDiscBar.vue";
// EMITS & PROPS
const emit = defineEmits<{
(e: "playFromPage", index: number): void;
+13 -4
View File
@@ -1,6 +1,7 @@
import { useFuse } from "@/utils";
import { defineStore } from "pinia";
import { ComputedRef } from "vue";
import { AlbumDisc } from "./../../interfaces";
import { FuseTrackOptions } from "@/composables/enums";
@@ -62,7 +63,18 @@ export default defineStore("album", {
},
getters: {
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[] {
const tracks = this.filteredTracks.value.map((result: FuseResult) => {
@@ -76,8 +88,5 @@ export default defineStore("album", {
return tracks;
},
discs(): Discs {
return createDiscs(this.tracks);
},
},
});
+18
View File
@@ -12,10 +12,28 @@
<script setup lang="ts">
import useQStore from "@/stores/queue";
import Layout from "@/layouts/HeaderAndVList.vue";
import { onBeforeMount, onMounted } from "vue";
const queue = useQStore();
function playFromQueue(index: number) {
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>
+7 -7
View File
@@ -14,7 +14,7 @@
{{ page }}
</button>
</div>
<div ref="page" class="page noscroll" v-auto-animate>
<div ref="page" class="page no-scroll" v-auto-animate>
<component :is="component" />
</div>
<button
@@ -28,14 +28,14 @@
</template>
<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 useSearchStore from "@/stores/search";
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
const defaultItemCount = 6;
@@ -169,7 +169,7 @@ onMounted(() => {
}
}
.page.noscroll {
.page.no-scroll {
overflow-x: visible;
}
+2 -2
View File
@@ -1,6 +1,6 @@
<template>
<div class="search-tracks-view">
<div class="noscroll">
<div class="no-scroll">
<Layout :no_header="true" :tracks="search.tracks.value" />
</div>
</div>
@@ -17,7 +17,7 @@ const search = useSearchStore();
.search-tracks-view {
height: 100%;
.noscroll {
.no-scroll {
height: 100%;
}