import { getDetailedUserInfo, userState } from '../api/user'
import type { HookConfig } from '../config'
import bookshelf from '../assets/bookshelf.svg?raw'
function formatReadingTime(readBookTime: bigint): string {
let minutes = readBookTime / 60_000n
const hours = minutes / 60n
minutes = minutes % 60n
return `${hours} 时 ${minutes} 分`
}
function createMenuItem(text: string, icon?: string, onclick?: () => void): HTMLDivElement {
//
const item = document.createElement('div')
item.role = 'menuitem'
item.classList.add('fqa-menu-item', 'arco-menu-item', 'serial-menu-item', 'slogin-user-avatar__menu-item-wrapper')
const inner1 = document.createElement('div')
inner1.classList.add('slogin-user-avatar__menu-item')
if (icon) {
const iconDiv = document.createElement('div')
iconDiv.classList.add('slogin-user-avatar__menu-item__icon')
iconDiv.innerHTML = icon
inner1.appendChild(iconDiv)
}
const inner2 = document.createElement('div')
inner2.classList.add('slogin-user-avatar__menu-item__content')
inner2.textContent = text
inner1.appendChild(inner2)
item.appendChild(inner1)
if (onclick) {
item.addEventListener('click', onclick)
}
return item
}
async function mainHook(_previous?: string): Promise {
const userInfo = await getDetailedUserInfo()
if (!userInfo) {
return
}
const injected = new WeakSet()
const inject = (menuInner: HTMLElement) => {
if (injected.has(menuInner)) {
return
}
injected.add(menuInner)
console.log('user action dialog created', menuInner)
const firstDiv = createMenuItem(`阅读 ${userInfo.read_book_num} 本书`)
menuInner.insertAdjacentElement('afterbegin', firstDiv)
const secondDiv = createMenuItem(formatReadingTime(userInfo.read_book_time ?? 0n))
firstDiv.insertAdjacentElement('afterend', secondDiv)
const thirdDiv = createMenuItem('我的书架', bookshelf, () => {
window.open('https://fanqienovel.com/bookshelf', '_blank')
})
secondDiv.insertAdjacentElement('afterend', thirdDiv)
}
const scan = (root: HTMLElement) => {
if (root.classList.contains('arco-menu-inner')) {
inject(root)
}
root.querySelectorAll('.arco-menu-inner').forEach(inject)
}
// watch create of div.arco-menu-inner
const observer = new MutationObserver((mutationsList) => {
mutationsList.forEach((mutation) => {
if (mutation.type === 'childList') {
mutation.addedNodes.forEach((node) => {
if (node instanceof HTMLElement) {
scan(node)
}
})
}
})
})
observer.observe(document.body, { childList: true, subtree: true })
// 请求 userInfo 期间菜单可能已经创建
scan(document.body)
}
function filter(path: string, _query: URLSearchParams, _hash: string): boolean {
return userState.isLogin && !path.startsWith('/writer') && !path.startsWith('/welfare')
}
const _exports: HookConfig[] = [
{
id: 'userHook',
event: 'load',
filter,
handler: mainHook
}
]
export default _exports