mirror of
https://github.com/the1812/Bilibili-Evolved.git
synced 2025-11-04 21:22:45 +08:00
142 lines
4.5 KiB
TypeScript
142 lines
4.5 KiB
TypeScript
import { defineComponentMetadata } from '@/components/define'
|
|
import { CommentArea } from '@/components/utils/comment-apis'
|
|
import { getJson } from '@/core/ajax'
|
|
import { fullyLoaded } from '@/core/life-cycle'
|
|
import { childList } from '@/core/observer'
|
|
import { select } from '@/core/spin-query'
|
|
import { videoUrls } from '@/core/utils/urls'
|
|
|
|
enum CommentSortOrder {
|
|
Default = 1,
|
|
ByTime,
|
|
ByLikes,
|
|
}
|
|
const getComments = (oid: number | string, mode: CommentSortOrder, page = 1) => {
|
|
if (mode === CommentSortOrder.ByTime) {
|
|
return getJson(`https://api.bilibili.com/x/v2/reply/main?oid=${oid}&type=1&mode=${mode}`)
|
|
}
|
|
return getJson(
|
|
`https://api.bilibili.com/x/v2/reply/main?oid=${oid}&type=1&mode=${mode}&next=${page}`,
|
|
)
|
|
}
|
|
const getOid = async (commentContainer: HTMLElement) => {
|
|
if (document.URL.match(/\/\/www\.bilibili\.com\/(video|bangumi)/)) {
|
|
return select(() => unsafeWindow.aid)
|
|
}
|
|
console.error('commentContainer = ', commentContainer)
|
|
throw new Error('No oid extract method for current context.')
|
|
}
|
|
const restore = async (commentContainer: HTMLElement) => {
|
|
const oid = await getOid(commentContainer)
|
|
if (!oid) {
|
|
return
|
|
}
|
|
const mode =
|
|
dq(commentContainer, '.hot-sort.on') !== null
|
|
? CommentSortOrder.ByLikes
|
|
: CommentSortOrder.ByTime
|
|
let page = 1
|
|
const pagesElement = dq(commentContainer, '.paging-box .current')
|
|
if (pagesElement !== null) {
|
|
page = parseInt(pagesElement.textContent)
|
|
}
|
|
const json = await getComments(oid, mode, page)
|
|
if (json.code !== 0) {
|
|
console.error('Comment API failed: ', json.message)
|
|
return
|
|
}
|
|
const getFloorInfo = (item: any) => {
|
|
const result = [
|
|
{
|
|
id: item.rpid_str as string,
|
|
floor: item.floor as number,
|
|
},
|
|
]
|
|
if (item.replies !== null) {
|
|
result.push(
|
|
...item.replies.map((it: any) => ({
|
|
id: it.rpid_str as string,
|
|
floor: it.floor as number,
|
|
})),
|
|
)
|
|
}
|
|
return result
|
|
}
|
|
const replies = lodash.flatMap(lodash.get(json, 'data.replies', []), getFloorInfo)
|
|
const top = lodash.get(json, 'data.top.upper')
|
|
if (top) {
|
|
replies.push(...getFloorInfo(top))
|
|
}
|
|
// console.log(replies)
|
|
const commentItems = dqa(commentContainer, '.reply-wrap[data-id]')
|
|
const commentInfos = commentItems.map(
|
|
item => dq(item, '.reply-wrap > .con > .info, .reply-wrap > .info') as HTMLElement,
|
|
)
|
|
commentItems.forEach((item, index) => {
|
|
const id = item.getAttribute('data-id') as string
|
|
const reply = replies.find(r => r.id === id)
|
|
if (reply !== undefined) {
|
|
const info = commentInfos[index]
|
|
if (info.getAttribute('data-restore-floor') === null) {
|
|
info.insertAdjacentHTML(
|
|
'afterbegin',
|
|
/* html */ `<span class="floor">#${reply.floor}</span>`,
|
|
)
|
|
info.setAttribute('data-restore-floor', reply.floor.toString())
|
|
}
|
|
}
|
|
})
|
|
}
|
|
const prepareRestore = (commentContainer: HTMLElement) => {
|
|
const commentLoading = 'comment-loading'
|
|
const isCommentLoading = Array.prototype.some.call(commentContainer.children, (it: HTMLElement) =>
|
|
it.classList.contains(commentLoading),
|
|
)
|
|
if (isCommentLoading) {
|
|
const [observer] = childList(commentContainer, records => {
|
|
const isCommentLoaded = records.some(r =>
|
|
Array.prototype.some.call(
|
|
r.removedNodes,
|
|
(node: Node) =>
|
|
node.nodeType === Node.ELEMENT_NODE &&
|
|
(node as HTMLElement).classList.contains(commentLoading),
|
|
),
|
|
)
|
|
if (isCommentLoaded) {
|
|
observer.disconnect()
|
|
prepareRestore(commentContainer)
|
|
}
|
|
})
|
|
} else if (commentContainer.getAttribute('data-restore-floor') === null) {
|
|
commentContainer.setAttribute('data-restore-floor', 'true')
|
|
const list = dq(commentContainer, '.comment-list') as HTMLElement
|
|
childList(
|
|
list,
|
|
lodash.debounce(records => {
|
|
console.log(records)
|
|
restore(commentContainer)
|
|
}, 100),
|
|
)
|
|
}
|
|
}
|
|
export const component = defineComponentMetadata({
|
|
name: 'restoreFloors',
|
|
displayName: '评论楼层显示',
|
|
urlInclude: [
|
|
...videoUrls,
|
|
// '//www.bilibili.com/bangumi',
|
|
// '//t.bilibili.com/',
|
|
],
|
|
description: {
|
|
'zh-CN': '恢复按热度排序时评论楼层, 按时间排序只能恢复第一页, 仅对普通视频页有效.',
|
|
},
|
|
tags: [componentsTags.utils],
|
|
entry: () => {
|
|
fullyLoaded(async () => {
|
|
const { forEachCommentArea } = await import('@/components/utils/comment-apis')
|
|
const callback = (area: CommentArea) => prepareRestore(area.element)
|
|
forEachCommentArea(callback)
|
|
})
|
|
},
|
|
})
|