refactor: improve components load method, and improve provide app

This commit is contained in:
starknt
2024-01-11 16:38:11 +08:00
parent e9ebeabc48
commit 91418521f3
20 changed files with 240 additions and 121 deletions

View File

@@ -1,28 +1,32 @@
<script setup lang="ts">
import { useToggle } from '@vueuse/core'
import { useThrottleFn, useToggle } from '@vueuse/core'
import { useI18n } from 'vue-i18n'
import browser from 'webextension-polyfill'
import type { Ref } from 'vue'
import Home from './Home/Home.vue'
import Search from './Search/Search.vue'
import Anime from './Anime/Anime.vue'
import History from './History/History.vue'
import WatchLater from './WatchLater/WatchLater.vue'
import Favorites from './Favorites/Favorites.vue'
import { accessKey, settings } from '~/logic'
import { AppPage, LanguageType } from '~/enums/appEnums'
import { getUserID, hexToRGBA, isHomePage, smoothScrollToTop } from '~/utils/main'
import emitter from '~/utils/mitt'
import type { BewlyAppProvider } from '~/composables/useAppProvider'
const activatedPage = ref<AppPage>(settings.value.dockItemVisibilityList.find(e => e.visible === true)?.page ?? AppPage.Home)
const { locale } = useI18n()
const [showSettings, toggleSettings] = useToggle(false)
const pages = { Home, Search, Anime, History, WatchLater, Favorites }
const pages = {
[AppPage.Home]: defineAsyncComponent(() => import('./Home/Home.vue')),
[AppPage.Search]: defineAsyncComponent(() => import('./Search/Search.vue')),
[AppPage.Anime]: defineAsyncComponent(() => import('./Anime/Anime.vue')),
[AppPage.History]: defineAsyncComponent(() => import('./History/History.vue')),
[AppPage.WatchLater]: defineAsyncComponent(() => import('./WatchLater/WatchLater.vue')),
[AppPage.Favorites]: defineAsyncComponent(() => import('./Favorites/Favorites.vue')),
}
const mainAppRef = ref<HTMLElement>() as Ref<HTMLElement>
const scrollbarRef = ref()
const showTopBarMask = ref<boolean>(false)
const dynamicComponentKey = ref<string>(`dynamicComponent${Number(new Date())}`)
const handlePageRefresh = ref<() => void>()
const handleReachBottom = ref<() => void>()
const handleThrottledPageRefresh = useThrottleFn(() => handlePageRefresh.value?.(), 500)
const handleThrottledReachBottom = useThrottleFn(() => handleReachBottom.value?.(), 500)
const topBarRef = ref()
const isVideoPage = computed(() => {
@@ -123,7 +127,7 @@ function changeActivatePage(pageName: AppPage) {
if (activatedPage.value === pageName) {
if (activatedPage.value !== AppPage.Search) {
if (scrollTop === 0)
handleRefresh()
handleThrottledPageRefresh()
else
handleBackToTop()
}
@@ -198,12 +202,6 @@ function setAppThemeColor() {
document.documentElement.style.setProperty(`--bew-theme-color-${i + 1}0`, hexToRGBA(settings.value.themeColor, i * 0.1 + 0.1))
}
function handleRefresh() {
emitter.emit('pageRefresh')
if (activatedPage.value === AppPage.Anime)
dynamicComponentKey.value = `dynamicComponent${Number(new Date())}`
}
function handleBackToTop(targetScrollTop = 0 as number) {
const osInstance = scrollbarRef.value?.osInstance()
@@ -229,17 +227,20 @@ function handleOsScroll() {
showTopBarMask.value = true
if (clientHeight + scrollTop >= scrollHeight - 20)
emitter.emit('reachBottom')
handleThrottledReachBottom()
if (isHomePage())
topBarRef.value?.handleScroll()
}
provide('handleBackToTop', handleBackToTop)
provide('handleRefresh', handleRefresh)
provide('activatedPage', activatedPage)
provide('scrollbarRef', scrollbarRef)
provide('mainAppRef', mainAppRef)
provide<BewlyAppProvider>('BEWLY_APP', {
activatedPage,
mainAppRef,
scrollbarRef,
handleBackToTop,
handlePageRefresh,
handleReachBottom,
})
</script>
<template>
@@ -312,12 +313,14 @@ provide('mainAppRef', mainAppRef)
<!-- control button group -->
<BackToTopAndRefreshButtons
v-if="activatedPage !== AppPage.Search" :show-refresh-button="!showTopBarMask"
@refresh="handleRefresh"
@refresh="handleThrottledPageRefresh"
@back-to-top="handleBackToTop"
/>
<Transition name="page-fade">
<Component :is="pages[activatedPage]" :key="dynamicComponentKey" />
<KeepAlive>
<Component :is="pages[activatedPage]" :key="activatedPage" />
</KeepAlive>
</Transition>
</div>
</main>

View File

@@ -1,5 +1,6 @@
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import type { Ref } from 'vue'
import { getCSRF, getUserID, openLinkToNewTab, removeHttpFromUrl } from '~/utils/main'
import type { FavoriteCategory, FavoriteResource } from '~/components/TopBar/types'
import emitter from '~/utils/mitt'
@@ -19,7 +20,7 @@ const activatedCategoryCover = ref<string>('')
const shouldMoveCtrlBarUp = ref<boolean>(false)
const currentPageNum = ref<number>(1)
const keyword = ref<string>('')
const handlePageRefresh = inject('handlePageRefresh') as Ref<() => void | Promise<void>>
const isLoading = ref<boolean>(true)
const isFullPageLoading = ref<boolean>(false)
const noMoreContent = ref<boolean>()
@@ -37,11 +38,6 @@ onMounted(async () => {
getFavoriteResources(selectedCategory.value!.id, ++currentPageNum.value, keyword.value)
})
emitter.off('pageRefresh')
emitter.on('pageRefresh', async () => {
favoriteResources.length = 0
handleSearch()
})
emitter.off('topBarVisibleChange')
emitter.on('topBarVisibleChange', (val) => {
shouldMoveCtrlBarUp.value = false
@@ -61,10 +57,16 @@ onMounted(async () => {
onUnmounted(() => {
emitter.off('reachBottom')
emitter.off('pageRefresh')
emitter.off('topBarVisibleChange')
})
onActivated(() => {
handlePageRefresh.value = () => {
favoriteResources.length = 0
handleSearch()
}
})
async function getFavoriteCategories() {
await browser.runtime
.sendMessage({

View File

@@ -3,6 +3,7 @@ import { useDateFormat } from '@vueuse/core'
import { useI18n } from 'vue-i18n'
// import type { HistoryItem } from './types'
import type { Ref } from 'vue'
import { getCSRF, openLinkToNewTab, removeHttpFromUrl } from '~/utils/main'
import { calcCurrentTime } from '~/utils/dataFormatter'
import emitter from '~/utils/mitt'
@@ -18,6 +19,7 @@ const historyList = reactive<Array<HistoryItem>>([])
const currentPageNum = ref<number>(1)
const keyword = ref<string>()
const historyStatus = ref<boolean>()
const handlePageRefresh = inject('handlePageRefresh') as Ref<() => void | Promise<void>>
const HistoryBusiness = computed(() => {
return Business
@@ -56,17 +58,17 @@ onMounted(() => {
else getHistoryList()
}
})
emitter.off('pageRefresh')
emitter.on('pageRefresh', async () => {
historyList.length = 0
getHistoryList()
})
})
onUnmounted(() => {
emitter.off('reachBottom')
emitter.off('pageRefresh')
})
onActivated(() => {
handlePageRefresh.value = () => {
historyList.length = 0
getHistoryList()
}
})
/**

View File

@@ -1,10 +1,6 @@
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import ForYou from './components/ForYou.vue'
import Following from './components/Following.vue'
import Trending from './components/Trending.vue'
import Ranking from './components/Ranking.vue'
import SubscribedSeries from './components/SubscribedSeries.vue'
import type { HomeTab } from './types'
import { HomeSubPage } from './types'
import emitter from '~/utils/mitt'
@@ -12,11 +8,16 @@ import { settings } from '~/logic'
const { t } = useI18n()
const handleBackToTop = inject('handleBackToTop') as (targetScrollTop: number) => void
const { handleBackToTop } = useBewlyApp()
const recommendContentKey = ref<string>(`recommendContent${Number(new Date())}`)
const activatedPage = ref<HomeSubPage>(HomeSubPage.ForYou)
const pages = { ForYou, Following, SubscribedSeries, Trending, Ranking }
const pages = {
[HomeSubPage.ForYou]: defineAsyncComponent(() => import('./components/ForYou.vue')),
[HomeSubPage.Following]: defineAsyncComponent(() => import('./components/Following.vue')),
[HomeSubPage.SubscribedSeries]: defineAsyncComponent(() => import('./components/SubscribedSeries.vue')),
[HomeSubPage.Trending]: defineAsyncComponent(() => import('./components/Trending.vue')),
[HomeSubPage.Ranking]: defineAsyncComponent(() => import('./components/Ranking.vue')),
}
const showSearchPageMode = ref<boolean>(false)
const shouldMoveTabsUp = ref<boolean>(false)
@@ -51,10 +52,6 @@ watch(() => activatedPage.value, () => {
onMounted(() => {
showSearchPageMode.value = true
emitter.off('pageRefresh')
emitter.on('pageRefresh', async () => {
recommendContentKey.value = `recommendContent${Number(new Date())}`
})
emitter.off('topBarVisibleChange')
emitter.on('topBarVisibleChange', (val) => {
shouldMoveTabsUp.value = false
@@ -73,7 +70,6 @@ onMounted(() => {
})
onUnmounted(() => {
emitter.off('pageRefresh')
emitter.off('topBarVisibleChange')
})
</script>
@@ -158,7 +154,9 @@ onUnmounted(() => {
</header>
<Transition name="page-fade">
<Component :is="pages[activatedPage]" :key="recommendContentKey" />
<KeepAlive>
<Component :is="pages[activatedPage]" :key="activatedPage" />
</KeepAlive>
</Transition>
<!-- <RecommendContent :key="recommendContentKey" /> -->
</main>

View File

@@ -1,7 +1,6 @@
<script setup lang="ts">
import type { Ref } from 'vue'
import type { DataItem as MomentItem, MomentResult } from '~/models/moment/moment'
import emitter from '~/utils/mitt'
const videoList = reactive<MomentItem[]>([])
const isLoading = ref<boolean>(false)
@@ -10,28 +9,49 @@ const containerRef = ref<HTMLElement>() as Ref<HTMLElement>
const offset = ref<string>('')
const updateBaseline = ref<string>('')
const noMoreContent = ref<boolean>(false)
const noMoreContentWarning = ref<boolean>(false)
const { handleReachBottom, handlePageRefresh } = useBewlyApp()
function initPageAction() {
handleReachBottom.value = async () => {
if (isLoading.value)
return
if (noMoreContent.value) {
noMoreContentWarning.value = true
return
}
for (let i = 0; i < 3; i++)
await getFollowedUsersVideos()
}
handlePageRefresh.value = async () => {
videoList.length = 0
offset.value = ''
noMoreContent.value = false
noMoreContentWarning.value = false
for (let i = 0; i < 3; i++)
await getFollowedUsersVideos()
}
}
onMounted(async () => {
for (let i = 0; i < 3; i++)
await getFollowedUsersVideos()
emitter.off('reachBottom')
emitter.on('reachBottom', async () => {
if (!isLoading.value) {
for (let i = 0; i < 3; i++)
await getFollowedUsersVideos()
}
})
initPageAction()
})
onUnmounted(() => {
emitter.off('reachBottom')
onActivated(() => {
initPageAction()
})
async function getFollowedUsersVideos() {
if (noMoreContent.value)
return
if (offset.value === '0') {
noMoreContent.value = true
return
}
isLoading.value = true
try {
const response: MomentResult = await browser.runtime.sendMessage({
@@ -116,6 +136,9 @@ function jumpToLoginPage() {
</template>
</div>
<!-- no more content -->
<Empty v-if="noMoreContentWarning" class="pb-4" :description="$t('common.no_more_content')" />
<Transition name="fade">
<Loading v-if="isLoading" />
</Transition>

View File

@@ -2,7 +2,6 @@
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 emitter from '~/utils/mitt'
import { accessKey, settings } from '~/logic'
import { LanguageType } from '~/enums/appEnums'
import { TVAppKey } from '~/utils/authProvider'
@@ -14,6 +13,33 @@ const needToLoginFirst = ref<boolean>(false)
const containerRef = ref<HTMLElement>() as Ref<HTMLElement>
const refreshIdx = ref<number>(1)
const noMoreContent = ref<boolean>(false)
const { handleReachBottom, handlePageRefresh } = useBewlyApp()
function initPageAction() {
handleReachBottom.value = async () => {
if (!isLoading.value) {
if (settings.value.recommendationMode === 'web') {
getRecommendVideos()
}
else {
for (let i = 0; i < 3; i++)
await getAppRecommendVideos()
}
}
}
handlePageRefresh.value = async () => {
videoList.length = 0
appVideoList.length = 0
if (settings.value.recommendationMode === 'web') {
await getRecommendVideos()
}
else {
for (let i = 0; i < 3; i++)
await getAppRecommendVideos()
}
}
}
watch(() => settings.value.recommendationMode, (newValue) => {
videoList.length = 0
@@ -41,22 +67,11 @@ onMounted(async () => {
}
}, 200)
emitter.off('reachBottom')
emitter.on('reachBottom', async () => {
if (!isLoading.value) {
if (settings.value.recommendationMode === 'web') {
getRecommendVideos()
}
else {
for (let i = 0; i < 3; i++)
await getAppRecommendVideos()
}
}
})
initPageAction()
})
onUnmounted(() => {
emitter.off('reachBottom')
onActivated(() => {
initPageAction()
})
async function getRecommendVideos() {

View File

@@ -7,8 +7,7 @@ import { settings } from '~/logic'
import emitter from '~/utils/mitt'
const { t } = useI18n()
const handleBackToTop = inject('handleBackToTop') as (targetScrollTop: number) => void
const { handleBackToTop, handlePageRefresh } = useBewlyApp()
const rankingTypes = computed((): RankingType[] => {
return [
@@ -46,6 +45,16 @@ const videoList = reactive<RankingVideoItem[]>([])
const PgcList = reactive<RankingPgcItem[]>([])
const shouldMoveAsideUp = ref<boolean>(false)
function initPageAction() {
handlePageRefresh.value = async () => {
videoList.length = 0
PgcList.length = 0
if (isLoading.value)
return
getRankingVideos()
}
}
watch(() => activatedRankingType.value.id, () => {
handleBackToTop(settings.value.useSearchPageModeOnHomePage ? 510 : 0)
@@ -72,6 +81,11 @@ onMounted(() => {
})
getRankingVideos()
initPageAction()
})
onActivated(() => {
initPageAction()
})
onBeforeUnmount(() => {

View File

@@ -1,7 +1,6 @@
<script setup lang="ts">
import type { Ref } from 'vue'
import type { DataItem as MomentItem, MomentResult } from '~/models/moment/moment'
import emitter from '~/utils/mitt'
const momentList = reactive<MomentItem[]>([])
const isLoading = ref<boolean>(false)
@@ -10,28 +9,52 @@ const containerRef = ref<HTMLElement>() as Ref<HTMLElement>
const offset = ref<string>('')
const updateBaseline = ref<string>('')
const noMoreContent = ref<boolean>(false)
const noMoreContentWarning = ref<boolean>(false)
const { handleReachBottom, handlePageRefresh } = useBewlyApp()
function initPageAction() {
handleReachBottom.value = async () => {
if (isLoading.value)
return
if (noMoreContent.value) {
noMoreContentWarning.value = true
return
}
for (let i = 0; i < 3; i++)
await getFollowedUsersVideos()
}
handlePageRefresh.value = async () => {
offset.value = ''
momentList.length = 0
noMoreContent.value = false
noMoreContentWarning.value = false
if (isLoading.value)
return
for (let i = 0; i < 3; i++)
await getFollowedUsersVideos()
}
}
onMounted(async () => {
for (let i = 0; i < 3; i++)
await getFollowedUsersVideos()
emitter.off('reachBottom')
emitter.on('reachBottom', async () => {
if (!isLoading.value) {
for (let i = 0; i < 3; i++)
await getFollowedUsersVideos()
}
})
initPageAction()
})
onUnmounted(() => {
emitter.off('reachBottom')
onActivated(() => {
initPageAction()
})
async function getFollowedUsersVideos() {
if (noMoreContent.value)
return
if (offset.value === '0') {
noMoreContent.value = true
return
}
isLoading.value = true
try {
const response: MomentResult = await browser.runtime.sendMessage({
@@ -115,6 +138,9 @@ function jumpToLoginPage() {
</template>
</div>
<!-- no more content -->
<Empty v-if="noMoreContentWarning" class="pb-4" :description="$t('common.no_more_content')" />
<Transition name="fade">
<Loading v-if="isLoading" />
</Transition>

View File

@@ -1,25 +1,34 @@
<script setup lang="ts">
import type { Ref } from 'vue'
import type { TrendingResult, List as VideoItem } from '~/models/video/trending'
import emitter from '~/utils/mitt'
const videoList = reactive<VideoItem[]>([])
const isLoading = ref<boolean>(false)
const containerRef = ref<HTMLElement>() as Ref<HTMLElement>
const pn = ref<number>(1)
const { handleReachBottom, handlePageRefresh } = useBewlyApp()
function initPageAction() {
handleReachBottom.value = async () => {
if (!isLoading.value)
await getTrendingVideos()
}
handlePageRefresh.value = async () => {
videoList.length = 0
pn.value = 1
await getTrendingVideos()
}
}
onMounted(async () => {
await getTrendingVideos()
emitter.off('reachBottom')
emitter.on('reachBottom', async () => {
if (!isLoading.value)
await getTrendingVideos()
})
initPageAction()
})
onUnmounted(() => {
emitter.off('reachBottom')
onActivated(() => {
initPageAction()
})
async function getTrendingVideos() {

View File

@@ -3,7 +3,6 @@ import { useDateFormat } from '@vueuse/core'
import { useI18n } from 'vue-i18n'
import { getCSRF, openLinkToNewTab, removeHttpFromUrl } from '~/utils/main'
import { calcCurrentTime } from '~/utils/dataFormatter'
import emitter from '~/utils/mitt'
import type { List as VideoItem, WatchLaterResult } from '~/models/video/watchLater'
const { t } = useI18n()
@@ -11,19 +10,17 @@ const { t } = useI18n()
const isLoading = ref<boolean>()
const noMoreContent = ref<boolean>()
const watchLaterList = reactive<VideoItem[]>([])
const { handlePageRefresh } = useBewlyApp()
onMounted(() => {
getAllWatchLaterList()
emitter.off('pageRefresh')
emitter.on('pageRefresh', async () => {
watchLaterList.length = 0
getAllWatchLaterList()
})
})
onUnmounted(() => {
emitter.off('pageRefresh')
onActivated(() => {
handlePageRefresh.value = () => {
watchLaterList.length = 0
getAllWatchLaterList()
}
})
/**