Implement fuzzy page search using fuse.js (#86)

This commit is contained in:
Mungai Njoroge
2022-09-10 10:46:45 -04:00
committed by GitHub
parent befdf383b6
commit 5770a66d67
67 changed files with 568 additions and 558 deletions
+22 -9
View File
@@ -3,12 +3,17 @@
class="a-header rounded"
ref="albumheaderthing"
:style="{
backgroundImage: `linear-gradient(
backgroundImage: album.colors
? `linear-gradient(
37deg, ${album.colors[0]}, ${album.colors[3]}
)`,
)`
: '',
}"
>
<div class="info" :class="{ nocontrast: isLight(album.colors[0]) }">
<div
class="info"
:class="{ nocontrast: album.colors ? isLight(album.colors[0]) : false }"
>
<div class="art">
<img
:src="imguri.artist + album.artistimg"
@@ -31,8 +36,11 @@
</div>
<div class="bottom">
<div class="stats">
{{ album.artist }} {{ album.date }} {{ album.count }} Tracks
{{ formatSeconds(album.duration, true) }}
<div class="border rounded-sm pad-sm">
{{ album.artist }} {{ album.date }} {{ album.count }}
{{ album.count === 1 ? "Track" : "Tracks" }}
{{ formatSeconds(album.duration, true) }}
</div>
</div>
<PlayBtnRect
:source="playSources.album"
@@ -62,9 +70,8 @@ import { getButtonColor, isLight } from "../../composables/colors/album";
import PlayBtnRect from "../shared/PlayBtnRect.vue";
const props = defineProps<{
defineProps<{
album: AlbumInfo;
bio: string | null;
}>();
const emit = defineEmits<{
@@ -136,12 +143,14 @@ useVisibility(albumheaderthing, handleVisibilityState);
.top {
.h {
font-size: 14px;
opacity: 0.5;
}
.title {
font-size: 2.5rem;
font-weight: 600;
width: fit-content;
cursor: text;
}
.artist {
@@ -157,15 +166,19 @@ useVisibility(albumheaderthing, handleVisibilityState);
margin-top: $smaller;
.stats {
border-radius: $small;
font-weight: bold;
font-size: 0.8rem;
margin-bottom: 0.75rem;
cursor: text;
div {
width: fit-content;
}
}
}
}
// grid-template-columns: 1fr !important;
@include for-desktop-down {
.art > img {
height: 6rem;
+3 -3
View File
@@ -135,7 +135,7 @@ export default {
padding: $small 0.95rem $small 0.95rem;
margin: $smaller;
transition: all 0.2s ease-in-out;
cursor: pointer;
cursor: default;
float: left;
.play {
@@ -146,7 +146,7 @@ export default {
width: 3rem;
background: url(../../assets/icons/play.svg) no-repeat center;
background-size: 60%;
cursor: pointer;
cursor: default;
opacity: 0;
transition: all 0.5s ease-in-out;
}
@@ -208,7 +208,7 @@ export default {
input::-webkit-search-cancel-button {
position: relative;
right: 20px;
cursor: pointer;
cursor: default;
width: 50px;
height: 50px;
}
+1 -1
View File
@@ -74,7 +74,7 @@ export default {
align-items: center;
grid-template-columns: 7.5rem 1fr;
padding: $small;
cursor: pointer;
cursor: default;
transition: all 0.2s ease-in-out;
&:hover {
@@ -68,7 +68,7 @@ export default {
padding: $small 0.95rem $small 0.95rem;
margin: $smaller;
transition: all 0.2s ease-in-out;
cursor: pointer;
cursor: default;
float: left;
&:hover {
@@ -116,7 +116,7 @@ export default {
input::-webkit-search-cancel-button {
position: relative;
right: 20px;
cursor: pointer;
cursor: default;
width: 50px;
height: 50px;
}
@@ -70,7 +70,7 @@ export default {
align-items: center;
grid-template-columns: 7.5rem 1fr;
padding: $small;
cursor: pointer;
cursor: default;
transition: all 0.2s ease-in-out;
&:hover {
@@ -32,7 +32,6 @@ defineProps<{
width: 100%;
display: flex;
align-items: center;
cursor: default;
padding: 0.4rem 1rem;
position: relative;
+17 -12
View File
@@ -16,11 +16,17 @@
</div>
<div class="songlist">
<SongItem
v-for="(track, index) in getTrackList()"
v-for="(track, index) in tracks"
:key="track.trackid"
:track="track"
:index="track.index"
@updateQueue="updateQueue(index)"
:index="
on_album_page
? track.tracknumber
: track.index !== undefined
? track.index + 1
: index + 1
"
@playThis="updateQueue(track.index !== undefined ? track.index : index)"
:isPlaying="queue.playing"
:isCurrent="queue.currentid == track.trackid"
/>
@@ -37,7 +43,7 @@
</template>
<script setup lang="ts">
import { ref } from "vue";
import { onUpdated, ref } from "vue";
import { useElementSize } from "@vueuse/core";
import { computed } from "@vue/reactivity";
@@ -59,6 +65,10 @@ const props = defineProps<{
copyright?: string | null;
}>();
// onUpdated(() => {
// console.log(props.tracks[1].index);
// });
const emit = defineEmits<{
(e: "playFromPage", index: number): void;
}>();
@@ -79,11 +89,11 @@ function updateQueue(index: number) {
}
/**
* Used to show track numbers as indexes in the album page.
* Used to show handle track indexes.
*/
function getTrackList() {
if (props.on_album_page) {
let tracks = props.tracks.map((track) => {
const tracks = props.tracks.map((track) => {
track.index = track.tracknumber;
return track;
});
@@ -91,12 +101,7 @@ function getTrackList() {
return tracks;
}
const tracks = props.tracks.map((track, index) => {
track.index = index + 1;
return track;
});
return tracks;
return props.tracks;
}
</script>
@@ -34,7 +34,6 @@ const q = useQStore();
height: 2.5rem;
width: 100%;
background-size: 1.5rem !important;
cursor: pointer;
&:hover {
background-color: $darkestblue;
+12 -18
View File
@@ -25,34 +25,26 @@
</router-link>
<div class="bottom">
<div class="title ellip">{{ props.track?.title }}</div>
<div
class="artists ellip"
v-if="track?.artists && track?.artists[0] !== ''"
>
<span v-for="artist in putCommas(track.artists)" :key="artist">{{
artist
}}</span>
</div>
<div class="artists" v-else-if="track?.artists">
<span>{{ track.albumartist }}</span>
</div>
<div class="artists" v-else>
<span>Meh</span>
</div>
<div class="title ellip t-center">{{ props.track?.title }}</div>
<ArtistName
:artists="track?.artists || ['Artist']"
:albumartist="track?.albumartist"
class="artists"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { putCommas } from "@/utils";
import { paths } from "../../../config";
import { Track } from "../../../interfaces";
const imguri = paths.images.thumb;
import ArtistName from "@/components/shared/ArtistName.vue";
const props = defineProps<{
track: Track | null;
}>();
const imguri = paths.images.thumb;
</script>
<style lang="scss">
@@ -91,12 +83,14 @@ const props = defineProps<{
.title {
font-weight: 900;
margin: 0 auto;
}
.artists {
font-size: 0.85rem;
opacity: 0.75;
margin: 0 auto;
&:hover {
text-decoration: underline 1px !important;
}
+1 -1
View File
@@ -1,5 +1,5 @@
<template>
<div class="l-sidebar">
<div class="l-sidebar noscroll">
<div class="withlogo">
<Logo />
<Navigation />
@@ -19,9 +19,9 @@
</div>
</template>
<script setup lang="ts">
import { ref } from "@vue/reactivity";
import ArtistCard from "@/components/shared/ArtistCard.vue";
import { Artist } from "@/interfaces";
import { ref } from "@vue/reactivity";
import ArrowSvg from "../../assets/icons/right-arrow.svg";
defineProps<{
@@ -82,7 +82,6 @@ const scrollRight = () => {
.icon {
border-radius: $small;
cursor: pointer;
transition: all 0.5s ease;
background-color: rgb(51, 51, 51);
padding: $smaller;
+5 -20
View File
@@ -37,20 +37,17 @@
import { ref } from "vue";
import useNavStore from "@/stores/nav";
import useModalStore from "../../stores/modal";
import pContext from "../../contexts/playlist";
import usePStore from "@/stores/pages/playlist";
import useContextStore from "../../stores/context";
import useModalStore from "../../stores/modal";
import { playSources } from "@/composables/enums";
import { formatSeconds, useVisibility } from "@/utils";
import { paths } from "../../config";
import { Playlist } from "../../interfaces";
import { useVisibility, formatSeconds } from "@/utils";
import { ContextSrc, playSources } from "@/composables/enums";
import PlayBtnRect from "../shared/PlayBtnRect.vue";
const imguri = paths.images.playlist;
const context = useContextStore();
const modal = useModalStore();
const nav = useNavStore();
const playlistheader = ref<HTMLElement | null>(null);
@@ -64,10 +61,6 @@ const props = defineProps<{
function editPlaylist() {
modal.showEditPlaylistModal(props.info);
}
function showDropdown(e: any) {
context.showContextMenu(e, pContext(), ContextSrc.PHeader);
}
</script>
<style lang="scss">
@@ -155,16 +148,7 @@ function showDropdown(e: any) {
font-size: 2.5rem;
font-weight: 900;
text-transform: capitalize;
}
.desc {
overflow: hidden;
text-overflow: ellipsis;
white-space: initial;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
max-width: 50%;
cursor: text;
}
.duration {
@@ -173,6 +157,7 @@ function showDropdown(e: any) {
padding: $smaller;
padding-left: 0;
font-weight: 900;
cursor: text;
}
.btns {
@@ -1,28 +0,0 @@
<template>
<div
class="p-card new-playlist-card rounded"
@click="Modal.showNewPlaylistModal()"
>
<PlusSvg />
</div>
</template>
<script setup lang="ts">
import PlusSvg from "../../assets/icons/plus.svg";
import useModalStore from "../../stores/modal";
const Modal = useModalStore();
</script>
<style lang="scss">
.new-playlist-card {
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
svg {
transform: scale(3);
}
}
</style>
@@ -60,7 +60,6 @@ const songs = [
&:hover {
background-color: #3a39393d;
cursor: pointer;
}
}
}
+2 -1
View File
@@ -10,10 +10,11 @@
v-for="(t, index) in queue.tracklist"
:key="index"
:track="t"
:index="index + 1"
:index="index"
:isPlaying="queue.playing"
:isHighlighted="false"
:isCurrent="index === queue.currentindex"
:isQueueTrack="true"
@PlayThis="playFromQueue(index)"
/>
</div>
@@ -1,150 +0,0 @@
<template>
<div id="playing-from" class="bg-primary rounded" @click="goTo">
<div class="h">
<div class="icon image" :class="from.icon"></div>
Playing from
</div>
<div class="name">
<div id="to">
{{ from.text }}
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { FromOptions } from "@/composables/enums";
import {
fromAlbum, fromFolder, fromPlaylist,
fromSearch
} from "@/interfaces";
import { computed } from "@vue/reactivity";
import { useRouter } from "vue-router";
const props = defineProps<{
from: fromFolder | fromAlbum | fromPlaylist | fromSearch;
}>();
interface from {
icon: string;
text: string;
}
const from = computed((): from => {
switch (props.from.type) {
case undefined:
return {
icon: "album",
text: "Welcome to Alice",
};
case FromOptions.folder:
return {
icon: "folder",
text: props.from.name,
};
case FromOptions.album:
return {
icon: "album",
text: `${props.from.name} - ${props.from.albumartist}`,
};
case FromOptions.playlist:
return {
icon: "playlist",
text: props.from.name,
};
case FromOptions.search:
return {
icon: "search",
text: `Search results for: "${props.from.query}"`,
};
}
});
const router = useRouter();
function goToAlbum(from: fromAlbum) {
router.push({
name: "AlbumView",
params: {
hash: from.hash,
},
});
}
function goToFolder(from: fromFolder) {
router.push({
name: "FolderView",
params: {
path: from.path,
},
});
}
function goToPlaylist(from: fromPlaylist) {
router.push({
name: "PlaylistView",
params: {
pid: from.playlistid,
},
});
}
function goTo() {
switch (props.from.type) {
case FromOptions.folder:
goToFolder(props.from);
break;
case FromOptions.album:
goToAlbum(props.from);
break;
case FromOptions.playlist:
goToPlaylist(props.from);
break;
}
}
</script>
<style lang="scss">
#playing-from {
background-size: 120%;
padding: 0.75rem;
cursor: pointer;
position: relative;
transition: all 0.2s ease;
background-color: $black;
&:hover {
background-position: -4rem;
}
.name {
font-weight: bolder;
}
.h {
font-size: 0.9rem;
margin-bottom: $small;
display: flex;
align-items: center;
gap: $small;
color: rgba(255, 255, 255, 0.849);
.icon {
height: 1.25rem;
width: 1.25rem;
}
.folder {
background-image: url("../../../assets/icons/folder.fill.svg") !important;
}
.album {
background-image: url("../../../assets/icons/album.svg") !important;
}
.playlist {
background-image: url("../../../assets/icons/playlist.svg") !important;
}
}
}
</style>
@@ -50,7 +50,6 @@ function showMenu(e: Event) {
gap: 1rem;
padding: 1rem;
width: 100%;
cursor: pointer;
&:hover {
background-color: $gray4;
@@ -8,7 +8,8 @@
:isHighlighted="false"
:isPlaying="queue.playing"
:track="track"
@PlayThis="updateQueue(index)"
@playThis="updateQueue(index)"
:index="index + 1"
/>
</div>
<div v-else class="t-center"><h5>🤷</h5></div>
@@ -17,12 +18,13 @@
</template>
<script setup lang="ts">
import { computed } from "vue";
import LoadMore from "./LoadMore.vue";
import TrackItem from "@/components/shared/TrackItem.vue";
import SongItem from "@/components/shared/SongItem.vue";
import useQStore from "../../../stores/queue";
import useSearchStore from "../../../stores/search";
import { computed } from "vue";
import useQStore from "@/stores/queue";
import useSearchStore from "@/stores/search";
const queue = useQStore();
const search = useSearchStore();
@@ -5,8 +5,6 @@
</template>
<script setup lang="ts">
import { ref } from "vue";
defineProps<{
state: boolean;
}>();
@@ -14,16 +12,16 @@ defineProps<{
<style lang="scss">
.switch {
height: 2rem;
height: 1.5rem;
background-color: $gray;
width: 3.75rem;
width: 2.5rem;
padding: $smaller;
position: relative;
transition: all 0.25s ease;
.circle {
transition: all 0.25s ease;
height: 1.5rem;
height: 1rem;
aspect-ratio: 1;
background-color: $gray1;
position: absolute;
@@ -37,7 +35,7 @@ defineProps<{
.circle {
background-color: $white;
left: calc((100% - ($smaller + 1.5rem)));
left: calc((100% - ($smaller + 1rem)));
}
}
</style>
+1 -1
View File
@@ -20,7 +20,7 @@ defineProps<{
<style lang="scss">
.settingscontent {
width: 100%;
max-width: 40rem;
// max-width: 40rem;
margin: 0 auto;
}
</style>
+5 -4
View File
@@ -1,16 +1,16 @@
<template>
<div class="settingsgroup">
<div>
<h4 v-if="group.title">{{ group.title }}</h4>
<div v-if="group.name || group.desc">
<h4 v-if="group.name">{{ group.name }}</h4>
<div class="desc" v-if="group.desc">{{ group.desc }}</div>
</div>
<div class="setting rounded bg-primary pad-lg">
<div class="setting rounded border pad-lg">
<div
v-for="(setting, index) in group.settings"
:key="index"
:class="{ inactive: setting.inactive && setting.inactive() }"
>
<div class="title">
<div class="title ellip" @click="setting.action()">
{{ setting.title }}
</div>
<div class="options">
@@ -69,6 +69,7 @@ defineProps<{
.title {
margin: auto 0;
user-select: none;
}
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
<template>
<div class="settingsnav">
<div class="buttongroup rounded bg-primary">
<div class="buttongroup rounded-sm bg-primary">
<button v-for="(group, index) in settingGroups" :key="index">
{{ group.title }}
</button>
-1
View File
@@ -108,7 +108,6 @@
button {
padding: 0 $medium;
cursor: pointer;
}
}
}
-1
View File
@@ -80,7 +80,6 @@ function hideModal() {
transform: rotate(45deg);
&:hover {
cursor: pointer;
transform: rotate(135deg);
}
}
+2 -3
View File
@@ -37,10 +37,10 @@
</template>
<script setup lang="ts">
import usePStore from "@/stores/pages/playlist";
import { onMounted } from "vue";
import { updatePlaylist } from "@/composables/fetch/playlists";
import { Playlist } from "@/interfaces";
import usePStore from "@/stores/pages/playlist";
import { onMounted } from "vue";
const pStore = usePStore();
@@ -132,7 +132,6 @@ function update_playlist(e: Event) {
place-items: center;
color: $gray1;
margin: $small 0;
cursor: pointer;
#update-pl-img-preview {
width: 4.5rem;
+17 -15
View File
@@ -2,15 +2,19 @@
<div class="topnav">
<div class="left">
<NavButtons />
<div
class="info"
:style="{
overflow: $route.name === Routes.search ? 'visible' : 'hidden',
overflowY: hideOverflow() ? 'visible' : 'hidden',
}"
class="info"
>
<APTitle v-if="showAPTitle" />
<SimpleTitle v-if="$route.name == Routes.settings" :text="'Settings'" />
<Folder v-if="$route.name == Routes.folder" :subPaths="subPaths" />
<APTitle
v-if="$route.name == Routes.album || $route.name == Routes.playlist"
:header_shown="nav.h_visible"
/>
<SettingsTitle v-if="$route.name == Routes.settings" :text="'Settings'" />
<FolderTitle v-if="$route.name == Routes.folder" :subPaths="subPaths" />
<SearchTitle v-if="$route.name == Routes.search" />
<PlaylistsTitle v-if="$route.name == Routes.playlists" />
<QueueTitle v-if="$route.name == Routes.queue" />
@@ -26,7 +30,6 @@
<script setup lang="ts">
import { ref, watch } from "vue";
import { useRoute } from "vue-router";
import { computed } from "@vue/reactivity";
import { subPath } from "@/interfaces";
import useNavStore from "@/stores/nav";
@@ -34,26 +37,26 @@ import { createSubPaths } from "@/utils";
import { Routes } from "@/composables/enums";
import NavButtons from "./NavButtons.vue";
// import Loader from "../shared/Loader.vue";
import Folder from "./Titles/Folder.vue";
import FolderTitle from "./Titles/Folder.vue";
import SimpleTitle from "./Titles/SimpleTitle.vue";
import APTitle from "./Titles/APTitle.vue";
import SearchTitle from "./Titles/SearchTitle.vue";
import PlaylistsTitle from "./Titles/PlaylistsTitle.vue";
import QueueTitle from "./Titles/QueueTitle.vue";
import SettingsTitle from "./Titles/SettingsTitle.vue";
const route = useRoute();
const nav = useNavStore();
const subPaths = ref<subPath[]>([]);
const showAPTitle = computed(() => {
return (
(route.name == Routes.album || route.name == Routes.playlist) &&
!nav.h_visible
);
});
function hideOverflow() {
const { name } = route;
const { album, playlist, search, folder } = Routes;
return (album + playlist + search + folder).includes(name as string);
}
watch(
() => route.name,
@@ -88,7 +91,6 @@ watch(
display: grid;
grid-template-columns: 1fr min-content;
width: 100%;
// gap: $small;
.left {
display: grid;
+34 -8
View File
@@ -1,19 +1,33 @@
<template>
<div class="title albumnavtitle">
<PlayBtn :source="things.source" :store="things.store" />
<div class="ellip">
{{ things.text }}
<div
class="title grid albumnavtitle"
:class="{
hide_play: header_shown,
}"
>
<div class="first grid">
<PlayBtn :source="things.source" :store="things.store" />
<div class="ellip">
{{ things.text }}
</div>
</div>
<Input :page="($route.name as string)" />
</div>
</template>
<script setup lang="ts">
import { useRoute } from "vue-router";
import { computed } from "@vue/reactivity";
import PlayBtn from "@/components/shared/PlayBtn.vue";
import { playSources, Routes } from "@/composables/enums";
import useAlbumStore from "@/stores/pages/album";
import usePStore from "@/stores/pages/playlist";
import { computed } from "@vue/reactivity";
import { useRoute } from "vue-router";
import Input from "@/components/shared/Input.vue";
defineProps<{
header_shown: boolean;
}>();
const things = computed(() => {
const route = useRoute();
@@ -46,10 +60,22 @@ const things = computed(() => {
<style lang="scss">
.albumnavtitle {
display: flex;
grid-template-columns: max-content 1fr;
align-items: center;
justify-content: space-between;
gap: $small;
outline: solid 1px $gray3;
height: 100%;
.first {
grid-template-columns: max-content 1fr;
gap: $small;
align-items: center;
}
}
.albumnavtitle.hide_play {
.first {
visibility: hidden;
}
}
</style>
+33 -39
View File
@@ -1,37 +1,43 @@
<template>
<div id="folder-nav-title">
<div class="folder">
<div class="fname">
<div
class="icon image"
@click="
$router.push({ name: Routes.folder, params: { path: '$home' } })
"
></div>
<div class="paths">
<div class="fname-wrapper">
<div class="fname">
<div
class="path"
v-for="path in subPaths.slice(1)"
:key="path.path"
:class="{ inthisfolder: path.active }"
>
<router-link
class="text"
:to="{ name: Routes.folder, params: { path: path.path } }"
>{{ path.name }}</router-link
class="icon image"
@click="
$router.push({ name: Routes.folder, params: { path: '$home' } })
"
></div>
<div class="paths">
<div
class="path"
v-for="path in subPaths.slice(1)"
:key="path.path"
:class="{ inthisfolder: path.active }"
>
<router-link
class="text"
:to="{ name: Routes.folder, params: { path: path.path } }"
>{{ path.name }}</router-link
>
</div>
</div>
</div>
</div>
<div>
<Input :page="Routes.folder" />
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { focusElem } from "@/utils";
import { subPath } from "@/interfaces";
import { onUpdated } from "vue";
import Input from "@/components/shared/Input.vue";
import { Routes } from "@/composables/enums";
import { subPath } from "@/interfaces";
import { focusElem } from "@/utils";
import { onUpdated } from "vue";
defineProps<{
subPaths: subPath[];
@@ -44,24 +50,16 @@ onUpdated(() => {
<style lang="scss">
#folder-nav-title {
overflow: hidden;
width: 100%;
.folder {
display: flex;
display: grid;
grid-template-columns: 1fr max-content;
gap: $small;
.playbtnrect {
height: 2.25rem;
}
.drop-btn {
width: 2.25rem;
.drop-icon {
height: 2.25rem;
width: 2.25rem;
}
.fname-wrapper {
width: 100%;
overflow: auto;
}
.fname {
@@ -70,8 +68,9 @@ onUpdated(() => {
height: 2.25rem;
display: flex;
align-items: center;
overflow: auto;
padding-right: $smaller;
width: fit-content;
max-width: 100%;
.icon {
height: 2rem;
@@ -79,7 +78,6 @@ onUpdated(() => {
background-image: url("../../../assets/icons/folder.fill.svg");
background-size: 1.5rem;
margin-left: $smaller;
cursor: pointer;
}
.paths {
@@ -97,10 +95,6 @@ onUpdated(() => {
white-space: nowrap;
margin: auto 0;
a {
cursor: default;
}
.text {
padding: $smaller;
border-radius: $smaller;
+2 -5
View File
@@ -20,10 +20,10 @@ import QueueActions from "@/components/RightSideBar/Queue/QueueActions.vue";
import { FromOptions, Routes } from "@/composables/enums";
import useQueueStore from "@/stores/queue";
import FolderSvg from "@/assets/icons/folder.svg";
import SearchSvg from "@/assets/icons/search.svg";
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 { RouteLocationRaw } from "vue-router";
@@ -120,9 +120,6 @@ const { name, icon: SourceIcon, location } = getSource();
}
}
button {
cursor: pointer;
}
}
.queue-actions {
@@ -23,6 +23,7 @@ import SearchInput from "@/components/RightSideBar/SearchInput.vue";
#ginner {
max-width: 30rem;
margin: 0 auto;
border-radius: $small;
}
.buttons {
@@ -0,0 +1,18 @@
<template>
<div class="settings-nav">
<SimpleTitle :text="'Settings'" />
<Nav />
</div>
</template>
<script setup lang="ts">
import SimpleTitle from "./SimpleTitle.vue";
import Nav from "@/components/SettingsView/Nav.vue";
</script>
<style lang="scss">
.settings-nav {
display: grid;
grid-template-columns: 1fr max-content;
}
</style>
-1
View File
@@ -32,7 +32,6 @@ defineProps<{
border-radius: 0.75rem;
display: grid;
justify-content: center;
cursor: pointer;
.artist-image {
width: 100%;
+5 -5
View File
@@ -1,13 +1,13 @@
<template>
<div v-tooltip="returnArtists()" style="width: auto;">
<div class="ellip" v-if="artists[0] !== '' && artists.length > 1">
<div v-tooltip="returnArtists()" style="width: auto">
<div class="ellip" v-if="artists[0] === '' && artists.length === 1">
<span>{{ albumartist }}</span>
</div>
<div class="ellip" v-else>
<span v-for="artist in putCommas(artists)" :key="artist">{{
artist
}}</span>
</div>
<div class="ellip" v-else>
<span>{{ albumartist }}</span>
</div>
</div>
</template>
+59
View File
@@ -0,0 +1,59 @@
<template>
<input
type="search"
class="header-input rounded-sm pad-sm"
placeholder="search here"
v-model.trim="source"
id="page-search"
/>
</template>
<script setup lang="ts">
import usePStore from "@/stores/pages/playlist";
import useFolderStore from "@/stores/pages/folder";
import useAlbumStore from "@/stores/pages/album";
import { storeToRefs } from "pinia";
import { Routes } from "@/composables/enums";
const { query: playlistQuery } = storeToRefs(usePStore());
const { query: folderQuery } = storeToRefs(useFolderStore());
const { query: albumQuery } = storeToRefs(useAlbumStore());
const props = defineProps<{
page: Routes | string;
}>();
function getRef() {
switch (props.page) {
case Routes.playlist:
return playlistQuery;
case Routes.folder:
return folderQuery;
case Routes.album:
return albumQuery;
default:
return null;
}
}
const source = getRef();
</script>
<style lang="scss">
.header-input {
background-color: $gray3;
outline: none;
border: none;
color: inherit;
font-size: 1rem;
z-index: 200;
&:focus {
outline: solid;
}
}
</style>
+8 -14
View File
@@ -5,7 +5,9 @@
@dblclick="emitUpdate(track)"
@contextmenu.prevent="showMenu"
>
<div class="index t-center ellip">{{ index }}</div>
<div class="index t-center ellip">
{{ index }}
</div>
<div class="flex">
<div @click="emitUpdate(track)" class="thumbnail">
<img
@@ -54,6 +56,7 @@
class="options-icon circular"
:class="{ options_button_clicked }"
@click.stop="showMenu"
@dblclick.stop="() => {}"
>
<OptionSvg />
</div>
@@ -79,17 +82,17 @@ const artisttitle = ref<HTMLElement | null>(null);
const props = defineProps<{
track: Track;
index?: number;
index: number;
isPlaying: Boolean;
isCurrent: Boolean;
}>();
const emit = defineEmits<{
(e: "updateQueue"): void;
(e: "playThis"): void;
}>();
function emitUpdate(track: Track) {
emit("updateQueue");
emit("playThis");
}
function showMenu(e: Event) {
@@ -118,7 +121,7 @@ function showMenu(e: Event) {
.song-album {
max-width: max-content;
cursor: pointer;
cursor: pointer !important;
&:hover {
text-decoration: underline;
@@ -128,10 +131,6 @@ function showMenu(e: Event) {
.song-artists {
width: fit-content;
max-width: 100%;
.artist {
cursor: pointer;
}
}
.index {
@@ -158,7 +157,6 @@ function showMenu(e: Event) {
svg {
transition: all 0.2s ease-in;
// transform: rotate(90deg);
stroke: $track-btn-svg;
circle {
@@ -196,10 +194,6 @@ function showMenu(e: Event) {
left: $small;
top: $small;
}
.title {
cursor: pointer;
}
}
td {
+10 -17
View File
@@ -24,14 +24,7 @@
</div>
<hr />
<div class="artist">
<div class="ellip" v-if="track.artists[0] !== ''">
<span v-for="artist in putCommas(track.artists)" :key="artist">{{
artist
}}</span>
</div>
<div class="ellip" v-else>
<span>{{ track.albumartist }}</span>
</div>
<ArtistName :artists="track.artists" :albumartist="track.albumartist" />
</div>
</div>
<div
@@ -47,12 +40,12 @@
<script setup lang="ts">
import { ref } from "vue";
import { paths } from "@/config";
import { putCommas } from "@/utils";
import { Track } from "@/interfaces";
import DelSvg from "@/assets/icons/delete.svg";
import { showTrackContextMenu as showContext } from "@/composables/context";
import DelSvg from "@/assets/icons/plus.svg";
import { paths } from "@/config";
import { Track } from "@/interfaces";
import useQueueStore from "@/stores/queue";
import ArtistName from "./ArtistName.vue";
const props = defineProps<{
track: Track;
@@ -70,11 +63,11 @@ function showMenu(e: Event) {
}
const emit = defineEmits<{
(e: "PlayThis"): void;
(e: "playThis"): void;
}>();
const playThis = (track: Track) => {
emit("PlayThis");
emit("playThis");
};
</script>
@@ -103,7 +96,7 @@ const playThis = (track: Track) => {
.remove-track {
opacity: 0;
transition: all 0.25s ease;
transform: translateX(1rem) rotate(45deg);
transform: scale(0.75) translateY(1rem);
&:hover {
opacity: 1 !important;
@@ -113,10 +106,9 @@ const playThis = (track: Track) => {
&:hover {
.remove-track {
opacity: 0.5;
transform: translateX(0) rotate(45deg);
transform: scale(1) translateY(0);
}
cursor: pointer;
background: linear-gradient(37deg, $gray4, $gray3, $gray3);
}
@@ -146,6 +138,7 @@ const playThis = (track: Track) => {
.artist {
font-size: small;
opacity: 0.67;
width: fit-content;
}
}
</style>