feat(Home): implement grid layout switcher

This commit is contained in:
Hakadao
2024-03-10 19:34:35 -03:00
parent 2b25373161
commit fede8758ff
9 changed files with 201 additions and 40 deletions

View File

@@ -1,12 +1,25 @@
<script setup lang="ts">
import type { Ref } from 'vue'
import type { GridLayout } from '~/logic'
import type { DataItem as MomentItem, MomentResult } from '~/models/moment/moment'
const props = defineProps<{
gridLayout: GridLayout
}>()
const emit = defineEmits<{
(e: 'beforeLoading'): void
(e: 'afterLoading'): void
}>()
const gridValue = computed((): string => {
if (props.gridLayout === 'adaptive')
return '~ 2xl:cols-5 xl:cols-4 lg:cols-3 md:cols-2 gap-5'
if (props.gridLayout === 'twoColumns')
return '~ cols-1 xl:cols-2 gap-4'
return '~ cols-1 gap-4'
})
const videoList = reactive<MomentItem[]>([])
const isLoading = ref<boolean>(false)
const needToLoginFirst = ref<boolean>(false)
@@ -111,6 +124,11 @@ function jumpToLoginPage() {
<template>
<div>
<!-- By directly using predefined unocss grid properties, it is possible to dynamically set the grid attribute -->
<div hidden grid="~ 2xl:cols-5 xl:cols-4 lg:cols-3 md:cols-2 gap-5" />
<div hidden grid="~ cols-1 xl:cols-2 gap-4" />
<div hidden grid="~ cols-1 gap-4" />
<Empty v-if="needToLoginFirst" mt-6 :description="$t('common.please_log_in_first')">
<Button type="primary" @click="jumpToLoginPage()">
{{ $t('common.login') }}
@@ -120,7 +138,7 @@ function jumpToLoginPage() {
v-else
ref="containerRef"
m="b-0 t-0" relative w-full h-full
grid="~ 2xl:cols-5 xl:cols-4 lg:cols-3 md:cols-2 gap-5"
:grid="gridValue"
>
<VideoCard
v-for="video in videoList"
@@ -137,11 +155,15 @@ function jumpToLoginPage() {
:capsule-text="video.modules.module_author.pub_time"
:bvid="video.modules.module_dynamic.major.archive?.bvid"
show-preview
:horizontal="gridLayout !== 'adaptive'"
/>
<!-- skeleton -->
<template v-if="isLoading">
<VideoCardSkeleton v-for="item in 30" :key="item" />
<VideoCardSkeleton
v-for="item in 30" :key="item"
:horizontal="gridLayout !== 'adaptive'"
/>
</template>
</div>

View File

@@ -2,15 +2,28 @@
import type { Ref } from 'vue'
import type { AppForYouResult, Item as AppVideoItem } from '~/models/video/appForYou'
import type { Item as VideoItem, forYouResult } from '~/models/video/forYou'
import type { GridLayout } from '~/logic'
import { accessKey, settings } from '~/logic'
import { LanguageType } from '~/enums/appEnums'
import { TVAppKey } from '~/utils/authProvider'
const props = defineProps<{
gridLayout: GridLayout
}>()
const emit = defineEmits<{
(e: 'beforeLoading'): void
(e: 'afterLoading'): void
}>()
const gridValue = computed((): string => {
if (props.gridLayout === 'adaptive')
return '~ 2xl:cols-5 xl:cols-4 lg:cols-3 md:cols-2 gap-5'
if (props.gridLayout === 'twoColumns')
return '~ cols-1 xl:cols-2 gap-4'
return '~ cols-1 gap-4'
})
const videoList = reactive<VideoItem[]>([])
const appVideoList = reactive<AppVideoItem[]>([])
const isLoading = ref<boolean>(true)
@@ -174,16 +187,22 @@ function jumpToLoginPage() {
<template>
<div>
<!-- By directly using predefined unocss grid properties, it is possible to dynamically set the grid attribute -->
<div hidden grid="~ 2xl:cols-5 xl:cols-4 lg:cols-3 md:cols-2 gap-5" />
<div hidden grid="~ cols-1 xl:cols-2 gap-4" />
<div hidden grid="~ cols-1 gap-4" />
<Empty v-if="needToLoginFirst" mt-6 :description="$t('common.please_log_in_first')">
<Button type="primary" @click="jumpToLoginPage()">
{{ $t('common.login') }}
</Button>
</Empty>
<div
v-else
ref="containerRef"
m="b-0 t-0" relative w-full h-full
grid="~ 2xl:cols-5 xl:cols-4 lg:cols-3 md:cols-2 gap-5"
:grid="gridValue"
>
<template v-if="settings.recommendationMode === 'web'">
<VideoCard
@@ -203,6 +222,7 @@ function jumpToLoginPage() {
:cid="video.cid"
:uri="video.uri"
show-preview
:horizontal="gridLayout !== 'adaptive'"
/>
</template>
<template v-else>
@@ -223,12 +243,16 @@ function jumpToLoginPage() {
:cid="video?.player_args?.cid"
:uri="video.uri"
show-preview
:horizontal="gridLayout !== 'adaptive'"
/>
</template>
<!-- skeleton -->
<template v-if="isLoading">
<VideoCardSkeleton v-for="item in 30" :key="item" />
<VideoCardSkeleton
v-for="item in 30" :key="item"
:horizontal="gridLayout !== 'adaptive'"
/>
</template>
</div>

View File

@@ -3,9 +3,14 @@ import { useI18n } from 'vue-i18n'
import type { RankingType } from '../types'
import type { RankingResult, List as RankingVideoItem } from '~/models/video/ranking'
import type { List as RankingPgcItem, RankingPgcResult } from '~/models/video/rankingPgc'
import type { GridLayout } from '~/logic'
import { settings } from '~/logic'
import emitter from '~/utils/mitt'
const props = defineProps<{
gridLayout: GridLayout
}>()
const emit = defineEmits<{
(e: 'beforeLoading'): void
(e: 'afterLoading'): void
@@ -14,6 +19,20 @@ const emit = defineEmits<{
const { t } = useI18n()
const { handleBackToTop, handlePageRefresh } = useBewlyApp()
const gridValue = computed((): string => {
if (props.gridLayout === 'adaptive') {
// eslint-disable-next-line ts/no-use-before-define
if (!activatedRankingType.value.seasonType)
return '~ 2xl:cols-4 xl:cols-3 lg:cols-2 md:cols-1 gap-5'
else
return '~ 2xl:cols-5 xl:cols-4 lg:cols-3 md:cols-2 gap-5'
}
if (props.gridLayout === 'twoColumns')
return '~ cols-1 xl:cols-2 gap-4'
return '~ cols-1 gap-4'
})
const rankingTypes = computed((): RankingType[] => {
return [
{ id: 1, name: t('ranking.all'), rid: 0 },
@@ -140,10 +159,10 @@ function getRankingPgc() {
<ul flex="~ col gap-2">
<li v-for="rankingType in rankingTypes" :key="rankingType.id">
<a
:class="{ active: activatedRankingType.id === rankingType.id }"
px-4 lh-30px h-30px hover:bg="$bew-fill-2" w-inherit
block rounded="$bew-radius" cursor-pointer transition="all 300 ease-out"
hover:scale-105 un-text="$bew-text-2 hover:$bew-text-1"
:class="{ active: activatedRankingType.id === rankingType.id }"
hover:scale-105 un-text="$bew-text-1"
@click="activatedRankingType = rankingType"
>{{ rankingType.name }}</a>
</li>
@@ -151,7 +170,13 @@ function getRankingPgc() {
</OverlayScrollbarsComponent>
</aside>
<main w-full>
<!-- By directly using predefined unocss grid properties, it is possible to dynamically set the grid attribute -->
<div hidden grid="~ 2xl:cols-5 xl:cols-4 lg:cols-3 md:cols-2 gap-5" />
<div hidden grid="~ 2xl:cols-4 xl:cols-3 lg:cols-2 md:cols-1 gap-5" />
<div hidden grid="~ cols-1 xl:cols-2 gap-4" />
<div hidden grid="~ cols-1 gap-4" />
<main w-full :grid="gridValue">
<template v-if="!('seasonType' in activatedRankingType)">
<VideoCard
v-for="(video, index) in videoList"
@@ -171,38 +196,41 @@ function getRankingPgc() {
:rank="index + 1"
:cid="video.cid"
show-preview
horizontal
:horizontal="gridLayout !== 'adaptive'"
w-full
/>
</template>
<template v-else>
<div grid="~ cols-2 gap-4">
<LongCoverCard
v-for="pgc in PgcList"
:key="pgc.url"
:url="pgc.url"
:cover="pgc.cover"
:title="pgc.title"
:desc="pgc.new_ep.index_show"
:view="pgc.stat.view"
:follow="pgc.stat.follow"
:rank="pgc.rank"
:capsule-text="pgc.rating.replace('', '')"
horizontal
mb-8
/>
</div>
<LongCoverCard
v-for="pgc in PgcList"
:key="pgc.url"
:url="pgc.url"
:cover="pgc.cover"
:title="pgc.title"
:desc="pgc.new_ep.index_show"
:view="pgc.stat.view"
:follow="pgc.stat.follow"
:rank="pgc.rank"
:capsule-text="pgc.rating.replace('', '')"
:horizontal="gridLayout !== 'adaptive'"
mb-8
/>
</template>
<!-- skeleton -->
<template v-if="isLoading">
<template v-if="!('seasonType' in activatedRankingType)">
<VideoCardSkeleton v-for="item in 30" :key="item" horizontal />
<VideoCardSkeleton
v-for="item in 30" :key="item"
:horizontal="gridLayout !== 'adaptive'"
/>
</template>
<template v-else>
<div grid="~ cols-2 gap-4">
<LongCoverCardSkeleton v-for="item in 30" :key="item" horizontal />
</div>
<LongCoverCardSkeleton
v-for="item in 30" :key="item"
:horizontal="gridLayout !== 'adaptive'"
/>
</template>
</template>
</main>
@@ -211,7 +239,7 @@ function getRankingPgc() {
<style lang="scss" scoped>
.active {
--at-apply: scale-110 bg-$bew-theme-color dark:bg-white text-white dark:text-black shadow-$bew-shadow-2;
--at-apply: scale-110 bg-$bew-theme-color-auto text-$bew-text-auto shadow-$bew-shadow-2;
}
.hide {

View File

@@ -1,12 +1,25 @@
<script setup lang="ts">
import type { Ref } from 'vue'
import type { GridLayout } from '~/logic'
import type { DataItem as MomentItem, MomentResult } from '~/models/moment/moment'
const props = defineProps<{
gridLayout: GridLayout
}>()
const emit = defineEmits<{
(e: 'beforeLoading'): void
(e: 'afterLoading'): void
}>()
const gridValue = computed((): string => {
if (props.gridLayout === 'adaptive')
return '~ 2xl:cols-5 xl:cols-4 lg:cols-3 md:cols-2 gap-5'
if (props.gridLayout === 'twoColumns')
return '~ cols-1 xl:cols-2 gap-4'
return '~ cols-1 gap-4'
})
const momentList = reactive<MomentItem[]>([])
const isLoading = ref<boolean>(false)
const needToLoginFirst = ref<boolean>(false)
@@ -116,6 +129,11 @@ function jumpToLoginPage() {
<template>
<div>
<!-- By directly using predefined unocss grid properties, it is possible to dynamically set the grid attribute -->
<div hidden grid="~ 2xl:cols-5 xl:cols-4 lg:cols-3 md:cols-2 gap-5" />
<div hidden grid="~ cols-1 xl:cols-2 gap-4" />
<div hidden grid="~ cols-1 gap-4" />
<Empty v-if="needToLoginFirst" mt-6 :description="$t('common.please_log_in_first')">
<Button type="primary" @click="jumpToLoginPage()">
{{ $t('common.login') }}
@@ -125,7 +143,7 @@ function jumpToLoginPage() {
v-else
ref="containerRef"
m="b-0 t-0" relative w-full h-full
grid="~ 2xl:cols-5 xl:cols-4 lg:cols-3 md:cols-2 gap-5"
:grid="gridValue"
>
<VideoCard
v-for="moment in momentList"
@@ -142,11 +160,15 @@ function jumpToLoginPage() {
:danmaku-str="moment.modules.module_dynamic.major.pgc?.stat.danmaku"
:capsule-text="moment.modules.module_author.pub_time"
:epid="moment.modules.module_dynamic.major.pgc?.epid"
:horizontal="gridLayout !== 'adaptive'"
/>
<!-- skeleton -->
<template v-if="isLoading">
<VideoCardSkeleton v-for="item in 30" :key="item" />
<VideoCardSkeleton
v-for="item in 30" :key="item"
:horizontal="gridLayout !== 'adaptive'"
/>
</template>
</div>

View File

@@ -1,12 +1,25 @@
<script setup lang="ts">
import type { Ref } from 'vue'
import type { GridLayout } from '~/logic'
import type { TrendingResult, List as VideoItem } from '~/models/video/trending'
const props = defineProps<{
gridLayout: GridLayout
}>()
const emit = defineEmits<{
(e: 'beforeLoading'): void
(e: 'afterLoading'): void
}>()
const gridValue = computed((): string => {
if (props.gridLayout === 'adaptive')
return '~ 2xl:cols-5 xl:cols-4 lg:cols-3 md:cols-2 gap-5'
if (props.gridLayout === 'twoColumns')
return '~ cols-1 xl:cols-2 gap-4'
return '~ cols-1 gap-4'
})
const videoList = reactive<VideoItem[]>([])
const isLoading = ref<boolean>(false)
const containerRef = ref<HTMLElement>() as Ref<HTMLElement>
@@ -72,10 +85,15 @@ async function getTrendingVideos() {
<template>
<div>
<!-- By directly using predefined unocss grid properties, it is possible to dynamically set the grid attribute -->
<div hidden grid="~ 2xl:cols-5 xl:cols-4 lg:cols-3 md:cols-2 gap-5" />
<div hidden grid="~ cols-1 xl:cols-2 gap-4" />
<div hidden grid="~ cols-1 gap-4" />
<div
ref="containerRef"
m="b-0 t-0" relative w-full h-full
grid="~ cols-1 xl:cols-2 gap-4"
:grid="gridValue"
>
<VideoCard
v-for="video in videoList"
@@ -95,13 +113,15 @@ async function getTrendingVideos() {
:tag="video.rcmd_reason.content"
:cid="video.cid"
show-preview
horizontal
w-full
:horizontal="gridLayout !== 'adaptive'"
/>
<!-- skeleton -->
<template v-if="isLoading">
<VideoCardSkeleton v-for="item in 30" :key="item" horizontal />
<VideoCardSkeleton
v-for="item in 30" :key="item"
:horizontal="gridLayout !== 'adaptive'"
/>
</template>
</div>