mirror of
https://github.com/Dvorinka/swingmusic-extended.git
synced 2026-06-04 12:33:03 +00:00
rename setting to "use alt now playing ..."
+ fix right now playing component gap + show emoji if there's no search result + abstract now playing component settings into one setting + break context menu's context item into a component
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
<template>
|
||||
<div class="context-item">
|
||||
<div class="icon image" :class="option.icon"></div>
|
||||
<div class="label ellip">{{ option.label }}</div>
|
||||
<div class="more image" v-if="option.children"></div>
|
||||
<div class="children rounded shadow-sm" v-if="option.children">
|
||||
<div
|
||||
class="context-item"
|
||||
v-for="child in option.children"
|
||||
:key="child.label"
|
||||
:class="[{ critical: child.critical }, child.type]"
|
||||
@click="child.action()"
|
||||
>
|
||||
<div class="label ellip">
|
||||
{{ child.label }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Option } from "@/interfaces";
|
||||
|
||||
defineProps<{
|
||||
option: Option;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.context-item {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: default;
|
||||
padding: 0.4rem 1rem;
|
||||
position: relative;
|
||||
|
||||
.more {
|
||||
height: 1.5rem;
|
||||
width: 1.5rem;
|
||||
position: absolute;
|
||||
right: $small;
|
||||
background-image: url("../assets/icons/expand.svg");
|
||||
}
|
||||
|
||||
.children {
|
||||
position: absolute;
|
||||
right: -13rem;
|
||||
width: 13rem;
|
||||
top: -0.5rem;
|
||||
max-height: 23.5rem;
|
||||
|
||||
background-color: $context;
|
||||
transform: scale(0);
|
||||
transform-origin: top left;
|
||||
padding: $small 0;
|
||||
|
||||
.context-item {
|
||||
padding: $small 1rem;
|
||||
}
|
||||
|
||||
.separator {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: #234ece;
|
||||
|
||||
.children {
|
||||
transform: scale(1);
|
||||
transition: transform 0.1s ease-in-out;
|
||||
transition-delay: 0.3s;
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
height: 1.25rem;
|
||||
width: 1.25rem;
|
||||
margin-right: $small;
|
||||
}
|
||||
|
||||
.label {
|
||||
width: 9rem;
|
||||
}
|
||||
|
||||
.folder {
|
||||
background-image: url("../../assets/icons/folder.svg");
|
||||
}
|
||||
|
||||
.artist {
|
||||
background-image: url("../../assets/icons/artist.svg");
|
||||
}
|
||||
|
||||
.album {
|
||||
background-image: url("../../assets/icons/album.svg");
|
||||
}
|
||||
|
||||
.delete {
|
||||
background-image: url("../../assets/icons/delete.svg");
|
||||
}
|
||||
|
||||
.plus {
|
||||
background-image: url("../../assets/icons/plus.svg");
|
||||
}
|
||||
|
||||
.add_to_queue {
|
||||
background-image: url("../../assets/icons/add_to_queue.svg");
|
||||
}
|
||||
|
||||
.heart {
|
||||
background-image: url("../../assets/icons/heart.svg");
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -5,15 +5,15 @@
|
||||
<Navigation />
|
||||
</div>
|
||||
|
||||
<nowPlaying v-if="settings.use_side_np" />
|
||||
<nowPlaying v-if="!settings.use_alt_np" />
|
||||
<!-- <Playlists /> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Logo from "@/components/Logo.vue";
|
||||
import Navigation from "@/components/LeftSidebar/Navigation.vue";
|
||||
import nowPlaying from "@/components/LeftSidebar/nowPlaying.vue";
|
||||
import Logo from "@/components/Logo.vue";
|
||||
// import Playlists from "./components/LeftSidebar/Playlists.vue";
|
||||
|
||||
import useSettingsStore from "@/stores/settings";
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<template>
|
||||
<div class="r-sidebar">
|
||||
<div
|
||||
class="r-sidebar"
|
||||
:style="{
|
||||
marginBottom: !settings.use_alt_np ? '-1rem' : '',
|
||||
}"
|
||||
>
|
||||
<div class="grid">
|
||||
<div class="r-content">
|
||||
<div class="r-dash" v-show="tabs.current === tabs.tabs.home">
|
||||
@@ -21,8 +26,10 @@ import Search from "./Search/Main.vue";
|
||||
import Queue from "./Queue.vue";
|
||||
import DashBoard from "./Home/Main.vue";
|
||||
import useTabStore from "../../stores/tabs";
|
||||
import useSettingsStore from "@/stores/settings";
|
||||
|
||||
const tabs = useTabStore();
|
||||
const settings = useSettingsStore();
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="b-bar bg-primary pad-medium rounded" v-if="settings.use_right_np">
|
||||
<div class="b-bar bg-primary pad-medium rounded" v-if="settings.use_alt_np">
|
||||
<div class="info">
|
||||
<img
|
||||
:src="paths.images.thumb + queue.currenttrack?.image"
|
||||
|
||||
@@ -11,9 +11,7 @@
|
||||
</button>
|
||||
</div>
|
||||
<div class="right">
|
||||
<button class="more-action action">
|
||||
<MoreSvg />
|
||||
</button>
|
||||
<Option />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -23,7 +21,7 @@ import useQueueStore from "../../../stores/queue";
|
||||
|
||||
import ClearSvg from "@/assets/icons/delete.svg";
|
||||
import ShuffleSvg from "@/assets/icons/shuffle.svg";
|
||||
import MoreSvg from "@/assets/icons/more.svg";
|
||||
import Option from "@/components/shared/Option.vue";
|
||||
|
||||
const queue = useQueueStore();
|
||||
</script>
|
||||
@@ -50,8 +48,9 @@ const queue = useQueueStore();
|
||||
}
|
||||
}
|
||||
|
||||
.more-action {
|
||||
.btn-more {
|
||||
padding-right: $smaller;
|
||||
|
||||
svg {
|
||||
transform: scale(1.25);
|
||||
}
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
<template>
|
||||
<div class="artists-results">
|
||||
<div class="search-results-grid">
|
||||
<AlbumCard
|
||||
v-for="album in search.albums.value"
|
||||
:key="`${album.artist}-${album.title}`"
|
||||
:album="album"
|
||||
/>
|
||||
</div>
|
||||
<LoadMore v-if="search.albums.more" @loadMore="loadMore()" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import AlbumCard from "../../shared/AlbumCard.vue";
|
||||
import LoadMore from "./LoadMore.vue";
|
||||
import useSearchStore from "../../../stores/search";
|
||||
|
||||
const search = useSearchStore();
|
||||
|
||||
function loadMore() {
|
||||
search.updateLoadCounter("albums");
|
||||
search.loadAlbums(search.loadCounter.albums);
|
||||
}
|
||||
</script>
|
||||
@@ -1,9 +1,15 @@
|
||||
<template>
|
||||
<div class="artists-results">
|
||||
<div class="search-results-grid" v-if="album_grid == true">
|
||||
<div
|
||||
class="search-results-grid"
|
||||
v-if="album_grid == true && search.albums.value.length"
|
||||
>
|
||||
<AlbumCard v-for="a in search.albums.value" :key="a.albumid" :album="a" />
|
||||
</div>
|
||||
<div class="search-results-grid" v-else>
|
||||
<div
|
||||
class="search-results-grid"
|
||||
v-else-if="!album_grid && search.artists.value.length"
|
||||
>
|
||||
<ArtistCard
|
||||
v-for="artist in search.artists.value"
|
||||
:key="artist.image"
|
||||
@@ -11,6 +17,7 @@
|
||||
:alt="true"
|
||||
/>
|
||||
</div>
|
||||
<div v-else class="t-center"><h5>🤷</h5></div>
|
||||
<LoadMore
|
||||
v-if="album_grid && search.albums.more"
|
||||
:loader="search.loadAlbums"
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div id="tracks-results" v-if="search.tracks.value">
|
||||
<TransitionGroup name="list">
|
||||
<div id="tracks-results">
|
||||
<TransitionGroup name="list" v-if="search.tracks.value.length">
|
||||
<TrackItem
|
||||
v-for="(track, index) in search.tracks.value"
|
||||
:key="track.trackid"
|
||||
:key="track?.trackid"
|
||||
:track="track"
|
||||
:isPlaying="queue.playing"
|
||||
:isCurrent="queue.currentid == track.trackid"
|
||||
@@ -11,6 +11,7 @@
|
||||
@PlayThis="updateQueue(index)"
|
||||
/>
|
||||
</TransitionGroup>
|
||||
<div v-else class="t-center"><h5>🤷</h5></div>
|
||||
<LoadMore v-if="search.tracks.more" :loader="search.loadTracks" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
<template>
|
||||
<div id="gsearch-input" class="rounded">
|
||||
<div
|
||||
id="ginner"
|
||||
tabindex="0"
|
||||
class="bg-primary rounded"
|
||||
>
|
||||
<div id="ginner" tabindex="0" class="bg-primary rounded">
|
||||
<input
|
||||
id="globalsearch"
|
||||
v-model="search.query"
|
||||
placeholder="Search your library"
|
||||
type="search"
|
||||
@blur.prevent="removeFocusedClass"
|
||||
@focus.prevent="addFocusedClass"
|
||||
/>
|
||||
<SearchSvg />
|
||||
</div>
|
||||
@@ -21,6 +19,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from "vue";
|
||||
import QueueSvg from "../../assets/icons/queue.svg";
|
||||
import SearchSvg from "../../assets/icons/search.svg";
|
||||
import useSearchStore from "../../stores/search";
|
||||
@@ -28,6 +27,20 @@ import useTabStore from "../../stores/tabs";
|
||||
|
||||
const search = useSearchStore();
|
||||
const tabs = useTabStore();
|
||||
const focused = ref(false);
|
||||
let classList: DOMTokenList | undefined;
|
||||
|
||||
onMounted(() => {
|
||||
classList = document.getElementById("ginner")?.classList;
|
||||
});
|
||||
|
||||
function addFocusedClass() {
|
||||
classList?.add("search-focused");
|
||||
}
|
||||
|
||||
function removeFocusedClass() {
|
||||
classList?.remove("search-focused");
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@@ -17,35 +17,20 @@
|
||||
top: context.y + 'px',
|
||||
}"
|
||||
>
|
||||
<div
|
||||
<ContextItem
|
||||
class="context-item"
|
||||
v-for="option in context.options"
|
||||
:key="option.label"
|
||||
:class="[{ critical: option.critical }, option.type]"
|
||||
@click="() => option.action && option.action()"
|
||||
>
|
||||
<div class="icon image" :class="option.icon"></div>
|
||||
<div class="label ellip">{{ option.label }}</div>
|
||||
<div class="more image" v-if="option.children"></div>
|
||||
<div class="children rounded shadow-sm" v-if="option.children">
|
||||
<div
|
||||
class="context-item"
|
||||
v-for="child in option.children"
|
||||
:key="child.label"
|
||||
:class="[{ critical: child.critical }, child.type]"
|
||||
@click="child.action && child.action()"
|
||||
>
|
||||
<div class="label ellip">
|
||||
{{ child.label }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
:option="option"
|
||||
@click="option.action()"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import useContextStore from "../stores/context";
|
||||
import ContextItem from "./Contextmenu/ContextItem.vue";
|
||||
|
||||
const context = useContextStore();
|
||||
</script>
|
||||
@@ -64,91 +49,6 @@ const context = useContextStore();
|
||||
transform-origin: top left;
|
||||
font-size: 0.875rem;
|
||||
|
||||
.context-item {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: default;
|
||||
padding: $small 1rem;
|
||||
position: relative;
|
||||
|
||||
.more {
|
||||
height: 1.5rem;
|
||||
width: 1.5rem;
|
||||
position: absolute;
|
||||
right: $small;
|
||||
background-image: url("../assets/icons/expand.svg");
|
||||
}
|
||||
|
||||
.children {
|
||||
position: absolute;
|
||||
right: -13rem;
|
||||
width: 13rem;
|
||||
top: -0.5rem;
|
||||
max-height: 23.5rem;
|
||||
|
||||
padding: $small 0 !important;
|
||||
background-color: $context;
|
||||
transform: scale(0);
|
||||
transform-origin: top left;
|
||||
|
||||
.context-item {
|
||||
padding: $small 1rem;
|
||||
}
|
||||
|
||||
.separator {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
height: 1.25rem;
|
||||
width: 1.25rem;
|
||||
margin-right: $small;
|
||||
}
|
||||
|
||||
.label {
|
||||
width: 9rem;
|
||||
}
|
||||
|
||||
.folder {
|
||||
background-image: url("../assets/icons/folder.svg");
|
||||
}
|
||||
|
||||
.artist {
|
||||
background-image: url("../assets/icons/artist.svg");
|
||||
}
|
||||
|
||||
.album {
|
||||
background-image: url("../assets/icons/album.svg");
|
||||
}
|
||||
|
||||
.delete {
|
||||
background-image: url("../assets/icons/delete.svg");
|
||||
}
|
||||
|
||||
.plus {
|
||||
background-image: url("../assets/icons/plus.svg");
|
||||
}
|
||||
|
||||
.add_to_queue {
|
||||
background-image: url("../assets/icons/add_to_queue.svg");
|
||||
}
|
||||
|
||||
.heart {
|
||||
background-image: url("../assets/icons/heart.svg");
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: #234ece;
|
||||
|
||||
.children {
|
||||
transform: scale(1);
|
||||
transition: transform 0.1s ease-in-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.separator {
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<button id="option-drop" @click.stop.prevent="showDropdown">
|
||||
<button id="option-drop" @click.stop.prevent="showDropdown" class="btn-more">
|
||||
<MoreSvg />
|
||||
</button>
|
||||
</template>
|
||||
@@ -8,7 +8,7 @@ import { onMounted } from "vue";
|
||||
import MoreSvg from "../../assets/icons/more.svg";
|
||||
let elem: DOMRect;
|
||||
|
||||
defineProps<{
|
||||
const props = defineProps<{
|
||||
src?: string;
|
||||
}>();
|
||||
|
||||
@@ -22,19 +22,11 @@ onMounted(() => {
|
||||
});
|
||||
|
||||
function showDropdown(e: Event) {
|
||||
if (!props.src) return;
|
||||
|
||||
emit("showDropdown", {
|
||||
clientX: elem.left + 35,
|
||||
clientY: elem.top,
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
#option-drop {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
svg {
|
||||
transform: scale(1.25);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user