Skip to content

Commit

Permalink
chore: refactor scroll bar and basic layout
Browse files Browse the repository at this point in the history
  • Loading branch information
Discreater committed Nov 7, 2023
1 parent 713697b commit 91317d2
Show file tree
Hide file tree
Showing 11 changed files with 114 additions and 121 deletions.
2 changes: 1 addition & 1 deletion src-tauri/server/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{net::SocketAddr, path::PathBuf, sync::Arc, time::Duration};

use abi::{musync_service_server::MusyncServiceServer, UpdatePlayerEvent};
use abi::musync_service_server::MusyncServiceServer;
use axum::{routing::get, Extension, Router};

use axum_server::Handle;
Expand Down
10 changes: 8 additions & 2 deletions src/components/QScrollbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,23 @@
import Scrollbar from 'smooth-scrollbar';
import { onMounted, onUnmounted, ref } from 'vue';
const scrollbar = ref<Scrollbar | null>(null);
const container = ref<HTMLDivElement | null>(null);
onMounted(() => {
if (container.value) {
Scrollbar.init(container.value, {
scrollbar.value = Scrollbar.init(container.value, {
alwaysShowTracks: true,
});
}
});
onUnmounted(() => {
if (container.value)
Scrollbar.destroy(container.value!);
scrollbar.value?.destroy();
});
defineExpose({
scrollbar,
});
</script>

Expand Down
28 changes: 25 additions & 3 deletions src/layouts/Basic.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,35 @@
<script setup lang="ts">
import { type VNodeRef, ref } from 'vue';
import { getPlatform } from '~/platforms';
import H1 from '~/components/typo/H1.vue';
import QScrollbar from '~/components/QScrollbar.vue';
defineProps<{ customPadding?: boolean }>();
defineProps<{ header: string; showModel?: boolean }>();
const scrollbar = ref<VNodeRef | null>(null);
const pt = getPlatform() !== 'web' ? 'pt-12' : 'pt-4';
defineExpose({
scrollbar,
});
</script>

<template>
<main
:class="`relative h-full w-full grow ${getPlatform() !== 'web' ? 'pt-12' : 'pt-4'} pb-1 ${customPadding ? 'px-1' : 'px-3 sm:px-16'} overflow-auto flex flex-col`"
class="relative h-full w-full grow pb-1 overflow-auto flex flex-col px-1"
:class="pt"
>
<slot />
<div class="flex justify-between px-16">
<H1>{{ header }}</H1>
<slot name="header-extra" />
</div>
<div class="px-16">
<slot name="actions" />
</div>
<QScrollbar ref="scrollbar" class="flex-1 grow relative px-16">
<slot />
</QScrollbar>
<div v-if="showModel" class="absolute inset-0 bg-[#4b4b4b80] flex justify-center items-center" :class="pt">
<slot name="model" />
</div>
</main>
</template>
4 changes: 1 addition & 3 deletions src/pages/main/Account.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import { useI18n } from 'vue-i18n';
import { computed, ref } from 'vue';
import LongButton from '~/components/LongButton.vue';
import H1 from '~/components/typo/H1.vue';
import H2 from '~/components/typo/H2.vue';
import Basic from '~/layouts/Basic.vue';
import IconConnected from '~icons/fluent/plug-connected-24-regular';
Expand All @@ -19,8 +18,7 @@ const online = computed(() => accountStore.online);
</script>

<template>
<Basic>
<H1>{{ t('menu.account') }}</H1>
<Basic :header="t('menu.account')">
<H2>{{ t('account.qsync') }}</H2>
<LongButton :icon="online ? IconConnected : IconDisconnected" :text="online ? accountStore.username : t('account.not-login')">
<template #extra>
Expand Down
4 changes: 1 addition & 3 deletions src/pages/main/Home.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { useI18n } from 'vue-i18n';
import { breakpointsTailwind, useBreakpoints } from '@vueuse/core';
import Basic from '~/layouts/Basic.vue';
import { toggleDark } from '~/utils';
import H1 from '~/components/typo/H1.vue';
import { useMusyncStore } from '~/store';
import QSelect from '~/components/QSelect.vue';
Expand All @@ -20,8 +19,7 @@ const current = breakPoints.current();
</script>

<template>
<Basic>
<H1>{{ t('menu.home') }}</H1>
<Basic :header="t('menu.home')">
<button @click="toggleDark()">
toggle dark
</button>
Expand Down
114 changes: 50 additions & 64 deletions src/pages/main/MusicLib.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
<script setup lang="ts">
import Scrollbar from 'smooth-scrollbar';
import type Scrollbar from 'smooth-scrollbar';
import { useI18n } from 'vue-i18n';
import { onMounted, onUnmounted, ref } from 'vue';
import { ref } from 'vue';
import { useRouter } from 'vue-router';
import IconArrowShuffle from '~icons/fluent/arrow-shuffle-24-regular';
import H1 from '~/components/typo/H1.vue';
import Basic from '~/layouts/Basic.vue';
import { useMusyncStore } from '~/store';
import QButton from '~/components/QButton.vue';
Expand All @@ -22,21 +21,13 @@ import QTable from '~/components/QTable.vue';
const { t } = useI18n();
const store = useMusyncStore();
const playerStore = usePlayerStore();
const container = ref<HTMLDivElement | null>(null);
const scrollbar = ref<Scrollbar | null>(null);
onMounted(() => {
if (container.value) {
scrollbar.value = Scrollbar.init(container.value, {
alwaysShowTracks: true,
});
}
});
const layout = ref<InstanceType<typeof Basic>>();
function getScrollBar(): Scrollbar | undefined {
return layout.value?.scrollbar?.scrollbar;
}
const views = ref(store.musicFolders.flatMap(folder => folder.tracks));
onUnmounted(() => {
if (container.value)
scrollbar.value?.destroy();
});
function shufflePlay() {
store.play(shuffle([...views.value]));
Expand All @@ -47,22 +38,20 @@ function playByIdx(idx: number) {
}
function locateToPlaying() {
if (container.value) {
const playing = container.value.querySelector<HTMLElement>('.playing');
const scrollbar = getScrollBar();
if (scrollbar) {
const playing = document.querySelector<HTMLElement>('.playing');
if (playing) {
scrollbar.value?.scrollIntoView(playing, {
scrollbar.scrollIntoView(playing, {
onlyScrollIfNeeded: true,
});
}
}
}
function locateToTop() {
if (container.value) {
const playing = container.value.querySelector<HTMLElement>('.playing');
if (playing)
scrollbar.value?.scrollTo(0, 0, 600);
}
const scrollbar = getScrollBar();
scrollbar?.scrollTo(0, 0, 600);
}
function rowClassName(row: Track) {
Expand Down Expand Up @@ -101,46 +90,43 @@ function handleTitleClick(track: Track) {
</script>

<template>
<Basic :custom-padding="true">
<H1 class="px-16">
{{ t('music-lib.music') }}
</H1>
<div class="px-16 mb-4 flex gap-2">
<QButton :icon="IconArrowShuffle" :text="t('btn.shuffle')" @click="shufflePlay()" />
<QButton :icon="IconLocation" class="text-passion" :title="t('btn.location')" @click="locateToPlaying" />
<QButton :icon="IconTop" class="text-passion" @click="locateToTop" />
</div>
<div ref="container" class="flex-1 overflow-auto grow relative container px-16">
<QTable :columns="columns" :data="views" :row-class-name="rowClassName">
<template #bodyCell="{ column, row, rowIdx }">
<template v-if="column.key === 'actions'">
<div class="flex">
<QHoverButton :icon="IconPlay" class="text-passion" @click="playByIdx(rowIdx)" />
</div>
</template>
<template v-else-if="column.key === 'title'">
<QHoverButton :text="row.title" class="hover:text-passion text-left" @click="handleTitleClick(row)" />
</template>
<template v-else-if="column.key === 'artist'">
<div>
{{ row.artist }}
</div>
</template>
<template v-else-if="column.key === 'album'">
{{ row.album }}
</template>
<template v-else-if="column.key === 'year'">
{{ row.year }}
</template>
<template v-else-if="column.key === 'genre'">
{{ row.genre }}
</template>
<template v-else-if="column.key === 'duration'">
{{ row.duration != null ? formatTime(Math.floor(row.duration / 1000)) : '' }}
</template>
<Basic ref="layout" :header="t('music-lib.music')">
<template #actions>
<div class="mb-4 flex gap-2">
<QButton :icon="IconArrowShuffle" :text="t('btn.shuffle')" @click="shufflePlay()" />
<QButton :icon="IconLocation" class="text-passion" :title="t('btn.location')" @click="locateToPlaying" />
<QButton :icon="IconTop" class="text-passion" @click="locateToTop" />
</div>
</template>
<QTable :columns="columns" :data="views" :row-class-name="rowClassName">
<template #bodyCell="{ column, row, rowIdx }">
<template v-if="column.key === 'actions'">
<div class="flex">
<QHoverButton :icon="IconPlay" class="text-passion" @click="playByIdx(rowIdx)" />
</div>
</template>
<template v-else-if="column.key === 'title'">
<QHoverButton :text="row.title" class="hover:text-passion text-left" @click="handleTitleClick(row)" />
</template>
<template v-else-if="column.key === 'artist'">
<div>
{{ row.artist }}
</div>
</template>
<template v-else-if="column.key === 'album'">
{{ row.album }}
</template>
<template v-else-if="column.key === 'year'">
{{ row.year }}
</template>
<template v-else-if="column.key === 'genre'">
{{ row.genre }}
</template>
<template v-else-if="column.key === 'duration'">
{{ row.duration != null ? formatTime(Math.floor(row.duration / 1000)) : '' }}
</template>
</QTable>
</div>
</template>
</QTable>
</Basic>
</template>

Expand Down
45 changes: 19 additions & 26 deletions src/pages/main/PlayQueue.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
<script setup lang="ts">
import { useI18n } from 'vue-i18n';
import QScrollbar from '~/components/QScrollbar.vue';
import type { Column } from '~/components/QTable.vue';
import H1 from '~/components/typo/H1.vue';
import Basic from '~/layouts/Basic.vue';
import { useMusyncStore } from '~/store';
import QTable from '~/components/QTable.vue';
Expand Down Expand Up @@ -45,30 +43,25 @@ const columns: Column[] = [
</script>

<template>
<Basic :custom-padding="true">
<H1 class="px-16">
{{ t('menu.play-queue') }}
</H1>
<QScrollbar class="flex-1 grow relative px-16">
<QTable :columns="columns" :data="views">
<template #bodyCell="{ column, row, rowIdx }">
<template v-if="column.key === 'actions'">
<QHoverButton :icon="IconPlay" class="text-passion" @click="playByIdx(rowIdx)" />
</template>
<template v-else-if="column.key === 'title'">
{{ row.title }}
</template>
<template v-else-if="column.key === 'artist'">
{{ row.artist }}
</template>
<template v-else-if="column.key === 'album'">
{{ row.album }}
</template>
<template v-else-if="column.key === 'duration'">
{{ row.duration != null ? formatTime(TrackExt.durationInSecs(row.duration)) : '' }}
</template>
<Basic :header="t('menu.play-queue')">
<QTable :columns="columns" :data="views">
<template #bodyCell="{ column, row, rowIdx }">
<template v-if="column.key === 'actions'">
<QHoverButton :icon="IconPlay" class="text-passion" @click="playByIdx(rowIdx)" />
</template>
</QTable>
</QScrollbar>
<template v-else-if="column.key === 'title'">
{{ row.title }}
</template>
<template v-else-if="column.key === 'artist'">
{{ row.artist }}
</template>
<template v-else-if="column.key === 'album'">
{{ row.album }}
</template>
<template v-else-if="column.key === 'duration'">
{{ row.duration != null ? formatTime(TrackExt.durationInSecs(row.duration)) : '' }}
</template>
</template>
</QTable>
</Basic>
</template>
6 changes: 2 additions & 4 deletions src/pages/main/SearchResult.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ import { ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router';
import { ApiClient } from '~/api/client';
import H1 from '~/components/typo/H1.vue';
import H2 from '~/components/typo/H2.vue';
import Basic from '~/layouts/Basic.vue';
import type { Track } from '~/generated/protos/musync';
import type { NcmSearchResult } from '~/model_ext/ncm';
const props = defineProps<{
defineProps<{
query: string
}>();
const loading = ref(true);
Expand All @@ -32,8 +31,7 @@ const { t } = useI18n();
</script>

<template>
<Basic>
<H1>{{ t('search-result.title') }} : "{{ props.query }}"</H1>
<Basic :header="`${t('search-result.title')} : ${query}`">
<div v-if="loading">
Loading
</div>
Expand Down
4 changes: 1 addition & 3 deletions src/pages/main/Settings.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<script setup lang="ts">
import { useI18n } from 'vue-i18n';
import Basic from '~/layouts/Basic.vue';
import H1 from '~/components/typo/H1.vue';
import H2 from '~/components/typo/H2.vue';
import LongButton from '~/components/LongButton.vue';
import QButton from '~/components/QButton.vue';
Expand Down Expand Up @@ -30,8 +29,7 @@ async function rebuildIndex() {
</script>

<template>
<Basic>
<H1>{{ t('menu.settings') }}</H1>
<Basic :header="t('menu.settings')">
<H2>{{ t("settings.user") }}</H2>
<LongButton :icon="IconFolder" :droppable="true" :text="t('settings.music-lib-position')">
<template #extra>
Expand Down
Loading

0 comments on commit 91317d2

Please sign in to comment.