fix layout shift caused by scrollbar

+ append search query to url (to support reload)
+ fix right sidebar search tabs bug
+ redesign the load more button on the search page
This commit is contained in:
geoffrey45 2023-01-03 19:43:52 +03:00 committed by Mungai Njoroge
parent 68f990aada
commit c1fb05e2a0
11 changed files with 67 additions and 59 deletions

View File

@ -32,9 +32,7 @@ $g-border: solid 1px $gray5;
.vue-recycle-scroller {
padding-left: 1.25rem;
// padding-right: 1rem;
// margin-right: 1rem;
scrollbar-gutter: stable;
}
.r-sidebar {
@ -62,8 +60,9 @@ $g-border: solid 1px $gray5;
.content-page {
margin-left: 1.25rem;
// margin-right: -$medium;
padding-right: 1.25rem;
margin-right: -$medium;
padding-right: $medium;
scrollbar-gutter: stable;
}
// ====== MODIFIERS =======

View File

@ -3,7 +3,11 @@
<router-link
v-for="menu in menus"
:key="menu.name"
:to="{ name: menu.route_name, params: menu?.params }"
:to="{
name: menu.route_name,
params: menu?.params,
query: menu.query && menu.query(),
}"
>
<div
v-if="menu.separator"
@ -34,6 +38,7 @@ import QueueSvg from "../../assets/icons/queue.svg";
import SearchSvg from "../../assets/icons/search.svg";
import SettingsSvg from "../../assets/icons/settings.svg";
import HeartSvg from "../../assets/icons/heart.svg";
import useSearchStore from "@/stores/search";
const menus = [
{
@ -65,6 +70,7 @@ const menus = [
name: "search",
route_name: Routes.search,
params: { page: "tracks" },
query: () => ({ q: useSearchStore().query }),
icon: SearchSvg,
},
{

View File

@ -40,6 +40,8 @@ function switchTab(tab: string) {
overflow: hidden;
height: 100%;
width: 100%;
display: grid;
grid-template-rows: max-content 1fr;
.heading {
padding: $medium;

View File

@ -1,11 +1,13 @@
<template>
<div class="nav-search-input">
<SearchInput :on_nav="true" />
<TabsWrapper
<Tabs
:tabs="tabs"
:currentTab="($route.params.page as string)"
@switchTab="(tab: string) => {
$router.push({ name: Routes.search, params: { page: tab } });
$router.replace({ name: Routes.search, params: { page: tab }, query: {
q: search.query,
} });
search.switchTab(tab);
}"
/>
@ -13,7 +15,7 @@
</template>
<script setup lang="ts">
import TabsWrapper from "@/components/RightSideBar/Search/TabsWrapper.vue";
import Tabs from "@/components/RightSideBar/Search/TabsWrapper.vue";
import SearchInput from "@/components/RightSideBar/SearchInput.vue";
import { Routes } from "@/router/routes";

View File

@ -49,12 +49,11 @@ async function loadMoreTracks(index: number) {
return response.data;
}
async function loadMoreAlbums(index: number, count: number) {
async function loadMoreAlbums(index: number) {
const response = await axios.get(loadMoreUrl, {
params: {
type: "albums",
index: index,
count: count,
},
});

View File

@ -4,6 +4,7 @@ import { defineStore } from "pinia";
import { watch } from "vue";
import { useRoute } from "vue-router";
import { Routes } from "@/router/routes";
import router from "@/router";
import {
loadMoreAlbums,
@ -128,11 +129,11 @@ export default defineStore("search", () => {
.then(() => scrollOnLoad());
}
function loadAlbums(count = 6) {
loadCounter.albums += count;
function loadAlbums() {
loadCounter.albums += RESULT_COUNT;
startLoading();
loadMoreAlbums(loadCounter.albums, count)
loadMoreAlbums(loadCounter.albums)
.then((res) => {
albums.value = [...albums.value, ...res.albums];
albums.more = res.more;
@ -165,6 +166,15 @@ export default defineStore("search", () => {
watch(
() => debouncedQuery.value,
(newQuery) => {
if (route.name === Routes.search) {
router.replace({
name: Routes.search,
params: {
page: route.params.page,
},
query: { q: newQuery },
});
}
// reset all counters
for (const key in loadCounter) {
// @ts-ignore

View File

@ -60,8 +60,9 @@ async function handlePlay(index: number) {
<style lang="scss">
.favorites-page {
height: 100%;
overflow: scroll;
overflow: auto;
padding-bottom: 4rem;
padding-right: 1rem;
h3 {
margin-top: 0;

View File

@ -1,8 +1,8 @@
<template>
<div class="search-albums-view grid-page" v-auto-animate>
<div class="search-albums-view grid-page">
<AlbumCard
v-for="album in search.albums.value"
:key="album.albumhash"
:key="Math.random()"
:album="album"
/>
</div>

View File

@ -1,5 +1,5 @@
<template>
<div v-auto-animate class="search-artists-view grid-page">
<div class="grid-page">
<ArtistCard
v-for="artist in search.artists.value"
:key="artist.image"

View File

@ -1,12 +1,13 @@
<template>
<div class="search-view content-page" style="padding-right: 0;">
<div class="search-view content-page" style="padding-right: 0">
<div ref="page" class="page no-scroll" v-auto-animate>
<component :is="component" />
</div>
<button
v-if="$route.params.page !== 'tracks'"
class="load-more"
:class="{ 'btn-disabled': !canLoadMore }"
@click="loadMore"
@click="canLoadMore && loadMore()"
>
Load more
</button>
@ -14,20 +15,15 @@
</template>
<script setup lang="ts">
import { Routes } from "@/router/routes";
import { useRoute } from "vue-router";
import { computed, onMounted, ref } from "vue";
import { focusElemByClass } from "@/utils";
import useSearchStore from "@/stores/search";
import AlbumPage from "./albums.vue";
import ArtistPage from "./artists.vue";
import TracksPage from "./tracks.vue";
// width of album and artist cards
const defaultItemCount = 6;
const gridItemWidth = 160;
const page = ref<HTMLElement>();
const search = useSearchStore();
@ -57,44 +53,24 @@ const component = computed(() => {
function loadTracks() {
search.loadTracks();
focusElemByClass("track-11", 100);
}
function getGridRowItemCount() {
if (page.value?.offsetWidth === undefined) return defaultItemCount;
const page_width = page.value?.offsetWidth - 16;
return Math.floor(page_width / gridItemWidth);
}
function scrollToGridPageBottom() {
const elem = document.getElementsByClassName("grid-page")[0] as HTMLElement;
setTimeout(() => {
elem.scrollTo(0, elem.scrollHeight);
elem.scroll({
top: elem.scrollHeight,
behavior: "smooth",
});
}, 250);
// const elemWidth = elem.offsetWidth;
// console.log(Math.floor(elemWidth / 160));
// elem.scroll({
// top: elem.scrollHeight,
// behavior: "smooth",
// });
}
function loadAlbums() {
search.loadAlbums();
scrollToGridPageBottom();
setTimeout(() => {
// search.loadAlbums();
const itemCount = getGridRowItemCount();
search.loadAlbums(itemCount);
scrollToGridPageBottom();
}, 250);
}
function loadArtists() {
// const itemCount = getGridRowItemCount();
search.loadArtists();
scrollToGridPageBottom();
@ -132,17 +108,16 @@ const canLoadMore = computed(() => {
onMounted(() => {
search.switchTab(route.params.page as string);
search.query = route.query.q as string;
});
</script>
<style lang="scss">
.search-view {
height: calc(100% - 1rem);
height: calc(100%);
display: grid;
gap: 1rem;
grid-template-rows: 1fr max-content;
margin-right: -0.75rem;
position: relative;
.page.no-scroll {
overflow-x: visible;
@ -151,17 +126,31 @@ onMounted(() => {
.grid-page {
max-height: 100%;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
gap: 1.75rem 0;
padding-bottom: 4rem;
overflow: auto;
padding-right: $medium;
scrollbar-gutter: stable;
}
button.load-more {
width: 10rem;
margin: 0 auto;
position: absolute;
bottom: 0;
height: 3rem;
left: -1.25rem;
width: calc(100% + 1.25rem);
border-radius: 0;
background: $darkestblue;
// margin: 0 auto;
// margin-bottom: 1rem;
}
.btn-disabled {
pointer-events: all;
background: $gray !important;
opacity: 1;
}
}
</style>

View File

@ -1,9 +1,9 @@
<template>
<div class="settingspage content-page">
<div class="settingspage content-page" style="height: 100%; overflow: auto">
<Content :current="0" />
</div>
</template>
<script setup lang="ts">
import Content from "../components/SettingsView/Content.vue";
</script>z
</script>