refactor: share search history

This commit is contained in:
starknt
2024-01-08 10:41:18 +08:00
parent e99e9fa95b
commit 08146c4497
3 changed files with 106 additions and 26 deletions

View File

@@ -24,7 +24,7 @@ const suggestionItemRef = ref<HTMLElement[]>([])
watch(isFocus, async (focus) => {
// 延后加载搜索历史
if (focus)
searchHistory.value = getSearchHistory()
searchHistory.value = await getSearchHistory()
})
function handleInput() {
@@ -46,21 +46,19 @@ function handleInput() {
}
}
function navigateToSearchResultPage(keyword: string) {
async function navigateToSearchResultPage(keyword: string) {
if (keyword) {
window.open(`//search.bilibili.com/all?keyword=${keyword}`, '_blank')
const searchItem = {
value: keyword,
timestamp: Number(new Date()),
}
addSearchHistory(searchItem)
searchHistory.value = getSearchHistory()
searchHistory.value = await addSearchHistory(searchItem)
}
}
function handleDelete(value: string) {
removeSearchHistory(value)
searchHistory.value = getSearchHistory()
async function handleDelete(value: string) {
searchHistory.value = await removeSearchHistory(value)
}
function handleKeyUp() {
@@ -129,8 +127,8 @@ function handleKeyDown() {
})
}
function handleClearSearchHistory() {
clearAllSearchHistory()
async function handleClearSearchHistory() {
await clearAllSearchHistory()
searchHistory.value = []
}
</script>

View File

@@ -1,4 +1,5 @@
const SEARCH_HISTORY_KEY = 'bew_search_history'
import { LazyValue } from '~/utils/lazyLoad'
const SEARCH_HISTORY_LIMIT = 20
export interface HistoryItem {
@@ -28,17 +29,77 @@ function historySort(historyItems: HistoryItem[]) {
return historyItems
}
export function getSearchHistory(): HistoryItem[] {
const history = localStorage.getItem(SEARCH_HISTORY_KEY)
if (!history) {
localStorage.setItem(SEARCH_HISTORY_KEY, JSON.stringify([]))
return []
}
return historySort(JSON.parse(history))
export interface BilibiliStorageEvent {
type: 'COLS_RES'
id?: string
key: string
value: string
}
export function addSearchHistory(historyItem: HistoryItem) {
let history = getSearchHistory()
class BilibiliStorageProvider {
static BILIBILI_HISTORY_KEY = 'search_history:search_history'
private readonly iframe = new LazyValue<HTMLIFrameElement>(() => Array.from(document.getElementsByTagName('iframe')).find(i => i.src.includes('https://s1.hdslb.com/bfs/seed/jinkela/short/cols/iframe.html'))!)
private async operate(type: 'COLS_GET'): Promise<BilibiliStorageEvent>
private async operate(type: 'COLS_SET', value: string): Promise<void>
private async operate(type: 'COLS_CLR'): Promise<void>
private async operate(type: 'COLS_GET' | 'COLS_CLR' | 'COLS_SET', value?: string) {
const iframe = this.iframe.value
switch (type) {
case 'COLS_GET':
return new Promise<BilibiliStorageEvent>((resolve) => {
iframe.contentWindow!.postMessage({ type: 'COLS_GET', key: BilibiliStorageProvider.BILIBILI_HISTORY_KEY }, iframe!.src)
window.addEventListener('message', (e: MessageEvent<BilibiliStorageEvent>) => {
if (e.origin === 'https://s1.hdslb.com' && e.data && e.data?.type === 'COLS_RES' && e.data?.key === BilibiliStorageProvider.BILIBILI_HISTORY_KEY)
resolve(e.data)
}, { once: true })
})
case 'COLS_CLR':
return iframe.contentWindow!.postMessage({ type: 'COLS_CLR', key: 'search_history' }, iframe.src)
case 'COLS_SET':
return iframe.contentWindow!.postMessage({ type: 'COLS_SET', key: BilibiliStorageProvider.BILIBILI_HISTORY_KEY, value }, iframe.src)
}
}
getSearchHistory() {
return this.operate('COLS_GET')
}
clearSearchHistory() {
return this.operate('COLS_CLR')
}
addSearchHistory(value: string) {
return this.operate('COLS_SET', value)
}
removeSearchHistory(value: string) {
return this.operate('COLS_SET', value)
}
}
const provider = new BilibiliStorageProvider()
export async function getSearchHistory(): Promise<HistoryItem[]> {
const e = await provider.getSearchHistory()
if (!e)
return []
try {
const history = JSON.parse(e.value)
return historySort(history)
}
catch (error) {
console.error(error)
return []
}
}
export async function addSearchHistory(historyItem: HistoryItem) {
let history = await getSearchHistory()
let hasSameValue = false
history.forEach((item) => {
@@ -54,18 +115,21 @@ export function addSearchHistory(historyItem: HistoryItem) {
history = history.filter((item, index) => {
if (index < SEARCH_HISTORY_LIMIT)
return item
else return false
else
return false
})
localStorage.setItem(SEARCH_HISTORY_KEY, JSON.stringify(history))
provider.addSearchHistory(JSON.stringify(history))
return history
}
export function removeSearchHistory(value: string) {
let history = getSearchHistory()
export async function removeSearchHistory(value: string) {
let history = await getSearchHistory()
history = history.filter(item => item.value !== value)
localStorage.setItem(SEARCH_HISTORY_KEY, JSON.stringify(history))
provider.removeSearchHistory(JSON.stringify(history))
return history
}
export function clearAllSearchHistory() {
localStorage.setItem(SEARCH_HISTORY_KEY, JSON.stringify([]))
export async function clearAllSearchHistory() {
return provider.clearSearchHistory()
}

View File

@@ -74,3 +74,21 @@ declare function cancelIdleCallback(handle: number): void;
}
}
})()
// TODO: handle error
export class LazyValue<T> {
private _value: T | undefined
private _didRun = false
constructor(
private executor: () => T,
) {}
get value(): T {
if (!this._didRun) {
this._value = this.executor()
this._didRun = true
}
return this._value!
}
}