From 1635ca792522e08b0d7bfef75a74fb63a3def81e Mon Sep 17 00:00:00 2001 From: Hakadao Date: Sat, 24 Dec 2022 01:28:26 +0800 Subject: [PATCH] chore: --- src/background/apis/favorites.ts | 14 + src/background/apis/index.ts | 2 + src/components/Topbar/Topbar.vue | 65 +-- src/components/Topbar/TopbarFavoritesPop.vue | 422 +++++++++++++++++++ 4 files changed, 474 insertions(+), 29 deletions(-) create mode 100644 src/background/apis/favorites.ts create mode 100644 src/components/Topbar/TopbarFavoritesPop.vue diff --git a/src/background/apis/favorites.ts b/src/background/apis/favorites.ts new file mode 100644 index 00000000..a98a274a --- /dev/null +++ b/src/background/apis/favorites.ts @@ -0,0 +1,14 @@ +import browser from 'webextension-polyfill' +import { API_URL } from '.' + +export const setupFavoritesAPIs = () => { + browser.runtime.onMessage.addListener((message) => { + if (message.contentScriptQuery === 'getHistoryList') { + const url = `${API_URL}/x/v3/fav/folder/created/list-all?up_mid=${message.mid}&jsonp=jsonp` + return fetch(url) + .then(response => response.json()) + .then(data => (data)) + .catch(error => console.error(error)) + } + }) +} diff --git a/src/background/apis/index.ts b/src/background/apis/index.ts index 115307b1..50f8ab7f 100644 --- a/src/background/apis/index.ts +++ b/src/background/apis/index.ts @@ -5,6 +5,7 @@ import { setupSearchAPIs } from './search' import { setupNotificationsAPIs } from './notifications' import { setupMomentsAPIs } from './moments' import { setupHistoryAPIs } from './history' +import { setupFavoritesAPIs } from './favorites' export const APP_URL = 'https://app.bilibili.com' export const API_URL = 'https://api.bilibili.com' @@ -17,4 +18,5 @@ export const setupAllAPIs = () => { setupNotificationsAPIs() setupMomentsAPIs() setupHistoryAPIs() + setupFavoritesAPIs() } diff --git a/src/components/Topbar/Topbar.vue b/src/components/Topbar/Topbar.vue index 4af52db7..d601b664 100644 --- a/src/components/Topbar/Topbar.vue +++ b/src/components/Topbar/Topbar.vue @@ -2,20 +2,19 @@ import type { Ref, UnwrapNestedRefs } from 'vue' import { Transition, onMounted, watch } from 'vue' import type { UnReadDm, UnReadMessage, UserInfo } from '../topbar/types' -import MomentsDropdown from './TopbarMomentsPop.vue' -import HistoryDropdown from './TopbarHistoryPop.vue' import { updateInterval } from './notify' import { getUserID } from '~/utils' const mid = getUserID() || '' const userInfo = reactive({}) as UnwrapNestedRefs -const showLogoDropDown = ref(false) -const showUserPanel = ref(false) +const showChannelsPop = ref(false) +const showUserPanelPop = ref(false) const showTopbarMask = ref(false) -const showNotificationsDropDown = ref(false) -const showMomentsDropDown = ref(false) -const showUploadDropDown = ref(false) -const showHistoryDropDown = ref(false) +const showNotificationsPop = ref(false) +const showMomentsPop = ref(false) +const showFavoritesPop = ref(false) +const showUploadPop = ref(false) +const showHistoryPop = ref(false) const isLogin = ref(!!getUserID()) const unReadMessage = reactive({}) as UnwrapNestedRefs const unReadDm = reactive({} as UnwrapNestedRefs) @@ -27,14 +26,14 @@ const avatarImg = ref() as Ref const avatarShadow = ref() as Ref watch( - () => showNotificationsDropDown, + () => showNotificationsPop, (newValue, oldValue) => { getUnreadMessageCount() }, ) watch( - () => showMomentsDropDown, + () => showMomentsPop, (newValue, oldValue) => { getNewMomentsCount() }, @@ -64,22 +63,22 @@ function initUserPanel() { function showLogoMenuDropdown() { logo.value.classList.add('hover') - showLogoDropDown.value = true + showChannelsPop.value = true } function closeLogoMenuDropdown() { logo.value.classList.remove('hover') - showLogoDropDown.value = false + showChannelsPop.value = false } function openUserPanel() { - showUserPanel.value = true + showUserPanelPop.value = true avatarImg.value.classList.add('hover') avatarShadow.value.classList.add('hover') } function closeUserPanel() { - showUserPanel.value = false + showUserPanelPop.value = false avatarImg.value.classList.remove('hover') avatarShadow.value.classList.remove('hover') } @@ -190,7 +189,7 @@ function getNewMomentsCount() {
{{ unReadMessageCount > 999 ? '999+' : unReadMessageCount }} @@ -282,7 +281,7 @@ function getNewMomentsCount() { @@ -292,8 +291,8 @@ function getNewMomentsCount() {
{{ newMomentsCount > 999 ? '999+' : newMomentsCount }} @@ -307,12 +306,16 @@ function getNewMomentsCount() { - +
-
+import { useI18n } from 'vue-i18n' +import type { Ref } from 'vue' +import { onMounted, reactive, ref, watch } from 'vue' +import { useDateFormat } from '@vueuse/core' +import type { HistoryItem } from './types' +import { HistoryType } from './types' +import { calcCurrentTime } from '~/utils' +const { t } = useI18n() + +const historys = reactive>([]) +const historyTabs = reactive([ + { + id: 0, + name: t('topbar.moments_dropdown.tabs.videos'), + isSelected: true, + }, + { + id: 1, + name: t('topbar.moments_dropdown.tabs.live'), + isSelected: false, + }, + { + id: 2, + name: t('topbar.moments_dropdown.tabs.articles'), + isSelected: false, + }, +]) +/** + * Active tab (0: archive, 1: live, 2: article) + */ +const activatedTab = ref(0) +const isLoading = ref(false) +// when noMoreContent is true, the user can't scroll down to load more content +const noMoreContent = ref(false) +const livePage = ref(1) +const historysWrap = ref() as Ref + +watch(activatedTab, (newVal: number, oldVal: number) => { + if (newVal === oldVal) + return + + historys.length = 0 + if (historysWrap.value) + scrollToTop(historysWrap.value, 300) + + if (newVal === 0) { + getHistoryList(HistoryType.Archive) + } + else if (newVal === 1) { + livePage.value = 1 + getHistoryList(HistoryType.Live) + } + else if (newVal === 2) { + getHistoryList(HistoryType.Article) + } +}) + +onMounted(() => { + // getHistoryList(HistoryType.Archive) + + // if (historysWrap.value) { + // historysWrap.value.addEventListener('scroll', () => { + // // When you scroll to the bottom, they will automatically + // // add the next page of data to the history list + // if ( + // historysWrap.value.clientHeight + historysWrap.value.scrollTop + // >= historysWrap.value.scrollHeight - 20 + // && historys.length > 0 + // && !isLoading.value + // ) { + // if (activatedTab.value === 0 && !noMoreContent.value) { + // getHistoryList( + // HistoryType.Archive, + // historys[historys.length - 1].view_at, + // ) + // } + // else if (activatedTab.value === 1 && !noMoreContent.value) { + // getHistoryList( + // HistoryType.Live, + // historys[historys.length - 1].view_at, + // ) + // } + // else if (activatedTab.value === 2 && !noMoreContent.value) { + // getHistoryList( + // HistoryType.Article, + // historys[historys.length - 1].view_at, + // ) + // } + // } + // }) + // } +}) + +function onClickTab(tabId: number) { + // Prevent changing tab when loading, cuz it will cause a bug + if (isLoading.value) + return + + activatedTab.value = tabId + historyTabs.forEach((tab) => { + tab.isSelected = tab.id === tabId + }) +} + +/** + * Return the URL of the history item + * @param item history item + * @return {string} url + */ +function getHistoryUrl(item: HistoryItem) { + // Video + if (activatedTab.value === 0) + return item.history.bvid + // Live + else if (activatedTab.value === 1) + return `//live.bilibili.com/${item.history.oid}` + // Article + else if (activatedTab.value === 2) + return `/read/cv${item.history.oid}` + + return '' +} + +/** + * Get history list + * @param {HistoryType} type + * @param {number} viewAt Last viewed timestamp + */ +function getHistoryList(type: HistoryType, viewAt = 0 as number) { + isLoading.value = true + browser.runtime + .sendMessage({ + contentScriptQuery: 'getHistoryList', + type, + viewAt, + }) + .then((res) => { + if (res.code === 0) { + if (historys.length !== 0 && res.data.list.length < 20) { + isLoading.value = false + noMoreContent.value = true + return + } + + res.data.list.forEach((item: HistoryItem) => { + historys.push(item) + }) + + noMoreContent.value = false + } + isLoading.value = false + }) +} + +/** + * smooth scroll to the top of the html element + */ +function scrollToTop(element: HTMLElement, duration: number) { + // cancel if already on top + if (element.scrollTop === 0) + return + + const cosParameter = element.scrollTop / 2 + let scrollCount = 0 + let oldTimestamp = 0 + + function step(newTimestamp: number) { + if (oldTimestamp !== 0) { + // if duration is 0 scrollCount will be Infinity + scrollCount += (Math.PI * (newTimestamp - oldTimestamp)) / duration + if (scrollCount >= Math.PI) + return (element.scrollTop = 0) + element.scrollTop = cosParameter + cosParameter * Math.cos(scrollCount) + } + oldTimestamp = newTimestamp + window.requestAnimationFrame(step) + } + window.requestAnimationFrame(step) +} + + + + +