mirror of
https://github.com/Dvorinka/swingmusic-extended.git
synced 2026-06-04 20:43:04 +00:00
fix albumView using watch function
- other minor changes to almost all files
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="b-bar border card-dark">
|
||||
<div class="grid">
|
||||
<SongCard />
|
||||
<SongCard/>
|
||||
<div class="controlsx border rounded">
|
||||
<div class="controls controls-bottom">
|
||||
<HotKeys />
|
||||
@@ -9,7 +9,7 @@
|
||||
<div class="progress progress-bottom">
|
||||
<span class="durationx">0:45</span>
|
||||
<Progress />
|
||||
<span class="durationx">3:55</span>
|
||||
<span class="durationx">{{ state.current.value.length }}</span>
|
||||
</div>
|
||||
<div class="r-group">
|
||||
<div class="heart image"></div>
|
||||
@@ -18,24 +18,15 @@
|
||||
</div>
|
||||
<div class="controls controls-bottom"></div>
|
||||
</div>
|
||||
<div class="volume-group">
|
||||
|
||||
</div>
|
||||
<div class="volume-group"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import "../../assets/css/BottomBar/BottomBar.scss";
|
||||
import playAudio from "../../composables/playAudio";
|
||||
import SongCard from "./SongCard.vue";
|
||||
import Progress from "../shared/Progress.vue";
|
||||
import HotKeys from "../shared/HotKeys.vue";
|
||||
|
||||
const isPlaying = ref(playAudio.playing);
|
||||
|
||||
const { playNext } = playAudio;
|
||||
const { playPrev } = playAudio;
|
||||
const { playPause } = playAudio;
|
||||
import state from "../../composables/state";
|
||||
</script>
|
||||
|
||||
@@ -26,8 +26,9 @@
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import perks from "../../composables/perks";
|
||||
import state from "../../composables/state";
|
||||
|
||||
const track = ref(perks.current);
|
||||
const track = ref(state.current);
|
||||
|
||||
const putCommas = perks.putCommas;
|
||||
</script>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<tbody>
|
||||
<SongItem
|
||||
v-for="(song, index) in props.songs"
|
||||
:key="song"
|
||||
:key="song.id"
|
||||
:song="song"
|
||||
:index="index + 1"
|
||||
@updateQueue="updateQueue"
|
||||
@@ -25,8 +25,7 @@
|
||||
</div>
|
||||
<div v-else-if="props.songs.length === 0 && search_query">
|
||||
<div class="no-results">
|
||||
<div class="icon"></div>
|
||||
<div class="text">No tracks 🎸</div>
|
||||
<div class="text">Nothing down here 😑</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else ref="songtitle"></div>
|
||||
@@ -47,8 +46,8 @@ import state from "@/composables/state.js";
|
||||
const props = defineProps({
|
||||
songs: {
|
||||
type: Array,
|
||||
required: true
|
||||
}
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
let route;
|
||||
@@ -85,7 +84,15 @@ function loadAlbum(title, album_artist) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
padding: 1rem;
|
||||
|
||||
// .icon {
|
||||
// height: 10rem;
|
||||
// width: 15rem;
|
||||
// border: solid;
|
||||
// background-image: url("../../assets/images/sokka.webp");
|
||||
// }
|
||||
}
|
||||
|
||||
.table {
|
||||
@@ -138,7 +145,7 @@ table {
|
||||
display: none;
|
||||
}
|
||||
|
||||
width: 5rem;
|
||||
width: 6rem;
|
||||
}
|
||||
|
||||
th.album-header {
|
||||
@@ -152,4 +159,4 @@ table {
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -110,6 +110,7 @@ export default {
|
||||
align-items: flex-end;
|
||||
flex-wrap: nowrap;
|
||||
overflow-x: scroll;
|
||||
gap: $small;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
<template>
|
||||
<div class="r-sidebar">
|
||||
<div class="grid">
|
||||
<div class="r-content border rounded">
|
||||
<div class="r-dash" v-if="current_tab == tabs.home">
|
||||
<DashBoard/>
|
||||
<div class="r-content rounded">
|
||||
<div class="r-dash" v-show="current_tab == tabs.home">
|
||||
<DashBoard />
|
||||
</div>
|
||||
<div class="r-search" v-if="current_tab == tabs.search">
|
||||
<Search
|
||||
v-model:search="search"
|
||||
@expandSearch="expandSearch"
|
||||
@collapseSearch="collapseSearch"
|
||||
/>
|
||||
<div class="r-search" v-show="current_tab == tabs.search">
|
||||
<Search />
|
||||
</div>
|
||||
|
||||
<div class="r-queue" v-if="current_tab == tabs.queue">
|
||||
<UpNext v-model:up_next="up_next" @expandQueue="expandQueue" />
|
||||
<div class="r-queue" v-show="current_tab == tabs.queue">
|
||||
<UpNext />
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-keys card-dark border">
|
||||
@@ -33,28 +29,13 @@ import Main from "./Home/Main.vue";
|
||||
|
||||
const DashBoard = Main;
|
||||
|
||||
let up_next = ref(true);
|
||||
let search = ref(false);
|
||||
|
||||
const expandQueue = () => {
|
||||
up_next.value = !up_next.value;
|
||||
};
|
||||
|
||||
const expandSearch = () => {
|
||||
search.value = true;
|
||||
};
|
||||
|
||||
const collapseSearch = () => {
|
||||
search.value = false;
|
||||
};
|
||||
|
||||
const tabs = {
|
||||
home: "home",
|
||||
search: "search",
|
||||
queue: "queue",
|
||||
};
|
||||
|
||||
const current_tab = ref(tabs.search);
|
||||
const current_tab = ref(tabs.queue);
|
||||
|
||||
function changeTab(tab) {
|
||||
current_tab.value = tab;
|
||||
@@ -63,18 +44,30 @@ function changeTab(tab) {
|
||||
|
||||
<style lang="scss">
|
||||
.r-sidebar {
|
||||
width: 34em;
|
||||
width: 34.5em;
|
||||
margin: $small 0 $small 0;
|
||||
|
||||
@include phone-only {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// @include tablet-landscape {
|
||||
// width: 3rem;
|
||||
// }
|
||||
|
||||
.grid {
|
||||
height: 100%;
|
||||
display: grid;
|
||||
grid-template-areas: "content tabs";
|
||||
display: flex;
|
||||
position: relative;
|
||||
|
||||
.r-content {
|
||||
grid-area: content;
|
||||
width: 100%;
|
||||
width: 31rem;
|
||||
overflow: hidden;
|
||||
margin: $small $small $small 0;
|
||||
|
||||
// @include tablet-landscape {
|
||||
// display: none;
|
||||
// }
|
||||
|
||||
.r-search {
|
||||
height: 100%;
|
||||
@@ -90,10 +83,12 @@ function changeTab(tab) {
|
||||
}
|
||||
|
||||
.tab-keys {
|
||||
right: 0;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
grid-area: tabs;
|
||||
width: 3rem;
|
||||
padding: $small;
|
||||
margin-left: $small;
|
||||
border-radius: $small 0 0 $small;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,10 @@
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="scrollable-r border">
|
||||
<TrackItem v-for="song in queue" :key="song" :track="song" />
|
||||
<div class="scrl border rounded">
|
||||
<div class="scrollable-r">
|
||||
<TrackItem v-for="song in queue" :key="song.id" :track="song" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -76,8 +78,6 @@ export default {
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
|
||||
|
||||
|
||||
.heading {
|
||||
position: relative;
|
||||
margin: 0.5rem 0 1rem 0;
|
||||
@@ -127,13 +127,19 @@ export default {
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-template-rows: min-content 1fr;
|
||||
padding-bottom: $small;
|
||||
|
||||
.scrl {
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.scrollable-r {
|
||||
margin-bottom: $small;
|
||||
height: 100%;
|
||||
padding: $small;
|
||||
overflow: auto;
|
||||
background-color: $card-dark;
|
||||
border-radius: 0.5rem;
|
||||
scrollbar-color: grey transparent;
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background-color: transparent;
|
||||
|
||||
+20
-68
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="right-search" ref="searchComponent">
|
||||
<div class="right-search border">
|
||||
<div>
|
||||
<div class="input">
|
||||
<Loader />
|
||||
@@ -8,29 +8,17 @@
|
||||
<input
|
||||
type="text"
|
||||
id="search"
|
||||
@focus="activateMagicFlag"
|
||||
@blur="removeMagicFlag"
|
||||
@keyup.backspace="removeLastFilter"
|
||||
placeholder="find your music"
|
||||
v-model="query"
|
||||
/>
|
||||
<div class="search-icon image"></div>
|
||||
<!-- -->
|
||||
</div>
|
||||
<div
|
||||
class="suggestions v00"
|
||||
:class="{
|
||||
v00: !filters.length && !query,
|
||||
v11: filters.length || query,
|
||||
}"
|
||||
>
|
||||
<div class="item">Kenny Rogers</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="separator no-border"></div>
|
||||
<Options :magic_flag="magic_flag" @addFilter="addFilter" />
|
||||
<Options @addFilter="addFilter" />
|
||||
</div>
|
||||
<div class="scrollable" :class="{ v0: !is_hidden, v1: is_hidden }">
|
||||
<div class="scrollable">
|
||||
<TracksGrid
|
||||
:tracks="tracks.tracks"
|
||||
:more="tracks.more"
|
||||
@@ -52,22 +40,24 @@
|
||||
v-if="
|
||||
!artists.artists.length &&
|
||||
!tracks.tracks.length &&
|
||||
!albums.albums.length
|
||||
!albums.albums.length && query.length != 0
|
||||
"
|
||||
>
|
||||
<div class="no-res-icon image"></div>
|
||||
<div class="no-res-text">
|
||||
No results for <span class="highlight rounded">{{ query }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="query.length == 0" class="no-res">
|
||||
<div class="no-res-text">Find your music 🔍😀</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { reactive, ref, toRefs } from "@vue/reactivity";
|
||||
import { reactive, ref } from "@vue/reactivity";
|
||||
|
||||
import { onMounted, watch } from "@vue/runtime-core";
|
||||
import { watch } from "@vue/runtime-core";
|
||||
import state from "@/composables/state.js";
|
||||
import searchMusic from "@/composables/searchMusic.js";
|
||||
import useDebouncedRef from "@/composables/useDebouncedRef";
|
||||
@@ -80,8 +70,6 @@ import Filters from "@/components/Search/Filters.vue";
|
||||
import "@/assets/css/Search/Search.scss";
|
||||
|
||||
export default {
|
||||
emits: ["expandSearch", "collapseSearch"],
|
||||
props: ["search"],
|
||||
components: {
|
||||
AlbumGrid,
|
||||
ArtistGrid,
|
||||
@@ -91,9 +79,8 @@ export default {
|
||||
Filters,
|
||||
},
|
||||
|
||||
setup(props, { emit }) {
|
||||
setup() {
|
||||
const loading = ref(state.loading);
|
||||
const searchComponent = ref(null);
|
||||
const filters = ref([]);
|
||||
|
||||
const tracks = reactive({
|
||||
@@ -111,9 +98,7 @@ export default {
|
||||
more: false,
|
||||
});
|
||||
|
||||
const query = useDebouncedRef("", 400);
|
||||
const magic_flag = ref(state.magic_flag);
|
||||
const is_hidden = toRefs(props).search;
|
||||
const query = useDebouncedRef("", 600);
|
||||
|
||||
function addFilter(filter) {
|
||||
if (!filters.value.includes(filter)) {
|
||||
@@ -137,24 +122,15 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
function activateMagicFlag() {
|
||||
setTimeout(() => {
|
||||
state.magic_flag.value = true;
|
||||
}, 300);
|
||||
}
|
||||
|
||||
function removeMagicFlag() {
|
||||
setTimeout(() => {
|
||||
if (
|
||||
(!filters.value.length && query.value == null) ||
|
||||
query.value == ""
|
||||
) {
|
||||
state.magic_flag.value = false;
|
||||
}
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
watch(query, (new_query) => {
|
||||
if (query.value == "" || query.value == " " || query.value.length < 2) {
|
||||
albums.albums = [];
|
||||
artists.artists = [];
|
||||
tracks.tracks = [];
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
searchMusic(new_query).then((res) => {
|
||||
albums.albums = res.albums.albums;
|
||||
albums.more = res.albums.more;
|
||||
@@ -165,43 +141,19 @@ export default {
|
||||
tracks.tracks = res.tracks.tracks;
|
||||
tracks.more = res.tracks.more;
|
||||
});
|
||||
|
||||
state.search_query.value = new_query;
|
||||
if (new_query !== "" && new_query.length > 2) {
|
||||
counter = 0;
|
||||
emit("expandSearch");
|
||||
} else {
|
||||
emit("collapseSearch");
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
const dom = document.getElementsByClassName("right-search")[0];
|
||||
|
||||
document.addEventListener("click", (e) => {
|
||||
var isClickedInside = dom.contains(e.target);
|
||||
if (!isClickedInside) {
|
||||
emit("collapseSearch");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
addFilter,
|
||||
activateMagicFlag,
|
||||
removeMagicFlag,
|
||||
removeFilter,
|
||||
removeLastFilter,
|
||||
tracks,
|
||||
albums,
|
||||
artists,
|
||||
query,
|
||||
is_hidden,
|
||||
magic_flag,
|
||||
filters,
|
||||
searchComponent,
|
||||
loading,
|
||||
searchMusic,
|
||||
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
@@ -34,17 +34,15 @@ export default {
|
||||
.right-search .albums-results {
|
||||
border-radius: 0.5rem;
|
||||
background: #0f131b44;
|
||||
|
||||
margin-top: $small;
|
||||
padding: $small 0;
|
||||
padding-bottom: $small;
|
||||
padding-top: $small;
|
||||
overflow-x: hidden;
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
|
||||
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding: 0 0 0 $small;
|
||||
padding: $small $small 0 $small;
|
||||
gap: $small;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,9 +42,10 @@ export default {
|
||||
margin-bottom: $small;
|
||||
|
||||
.grid {
|
||||
padding: 0 0 0 $small;
|
||||
padding: $small $small 0 $small;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: $small;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -32,8 +32,8 @@ export default {
|
||||
margin-left: 2rem;
|
||||
height: 2rem;
|
||||
|
||||
|
||||
.item {
|
||||
transition: all 0.2s ease-in-out;
|
||||
&:hover {
|
||||
width: 4rem;
|
||||
|
||||
@@ -48,4 +48,4 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
<template>
|
||||
<div class="options border rounded">
|
||||
<div class="item info">Filter by:</div>
|
||||
<div class="item info header">Filter by:</div>
|
||||
<div
|
||||
class="item"
|
||||
v-for="option in options"
|
||||
:key="option"
|
||||
@click="addFilter(option.icon)"
|
||||
>
|
||||
{{ option.title }}
|
||||
<div>
|
||||
<span class="icon">{{ option.icon }}</span>
|
||||
<span class="title"> {{ option.title }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -18,23 +21,23 @@ export default {
|
||||
setup(props, { emit }) {
|
||||
const options = [
|
||||
{
|
||||
title: "🎵 Track",
|
||||
title: "Track",
|
||||
icon: "🎵",
|
||||
},
|
||||
{
|
||||
title: "💿 Album",
|
||||
title: "Album",
|
||||
icon: "💿",
|
||||
},
|
||||
{
|
||||
title: "🙄 Artist",
|
||||
title: "Artist",
|
||||
icon: "🙄",
|
||||
},
|
||||
{
|
||||
title: "😍 Playlist",
|
||||
title: "Playlist",
|
||||
icon: "😍",
|
||||
},
|
||||
{
|
||||
title: "📁 Folder",
|
||||
title: "Folder",
|
||||
icon: "📁",
|
||||
},
|
||||
];
|
||||
@@ -58,6 +61,38 @@ export default {
|
||||
|
||||
.item {
|
||||
margin: $small;
|
||||
width: 2.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
transition: all 0.2s ease-in-out;
|
||||
position: relative;
|
||||
|
||||
.title {
|
||||
position: absolute;
|
||||
left: 1.5rem;
|
||||
top: 0.5rem;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.icon {
|
||||
position: absolute;
|
||||
top: 0.5rem;
|
||||
left: .75rem;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
width: 5.5rem;
|
||||
|
||||
.title {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
width: 5.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<tbody>
|
||||
<TrackItem
|
||||
v-for="track in props.tracks"
|
||||
:key="track"
|
||||
:key="track.id"
|
||||
:track="track"
|
||||
/>
|
||||
</tbody>
|
||||
|
||||
@@ -32,6 +32,7 @@ export default {
|
||||
border-radius: $small;
|
||||
text-align: left !important;
|
||||
width: 9rem;
|
||||
// border: solid 1px red !important;
|
||||
|
||||
.album-art {
|
||||
height: 7rem;
|
||||
|
||||
@@ -21,7 +21,6 @@ export default {
|
||||
flex: 0 0 auto;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
margin: 0 $small 0 0;
|
||||
|
||||
width: 9em;
|
||||
height: 11em;
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
</div>
|
||||
<div>
|
||||
<span class="ellip">{{ song.title }}</span>
|
||||
<div class="separator no-border"></div>
|
||||
<div class="artist ellip">
|
||||
<span v-for="artist in putCommas(song.artists)" :key="artist">
|
||||
{{ artist }}
|
||||
|
||||
@@ -60,6 +60,9 @@ const playThis = (song) => {
|
||||
align-items: center;
|
||||
padding: 0.5rem;
|
||||
border-radius: 0.5rem;
|
||||
position: relative;
|
||||
height: 4rem;
|
||||
padding-left: 4rem;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
@@ -72,6 +75,8 @@ const playThis = (song) => {
|
||||
}
|
||||
|
||||
.album-art {
|
||||
position: absolute;
|
||||
left: $small;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -83,7 +88,6 @@ const playThis = (song) => {
|
||||
background-image: url(../../assets/images/null.webp);
|
||||
}
|
||||
.artist {
|
||||
width: 20rem;
|
||||
font-size: small;
|
||||
color: rgba(255, 255, 255, 0.637);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user