forked from sifue/nyobi-commentviewer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcomment-viewer.js
101 lines (81 loc) · 3.05 KB
/
comment-viewer.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import { Comment, CommentCollector } from './modules/comment-collector.js'
import { html, html_unsafe } from './modules/helpers/html.js'
import { isNearBottom, scrollToBottom } from './modules/helpers/scroll.js'
const videoPlayer = document.querySelector('[aria-label="動画プレイヤー"]')
const videoPlayerContainer = videoPlayer.parentElement.parentElement
const videoElement = document.querySelector('video')
const asideElement = document.querySelector('aside')
const commentPanel = html`<div id="comment-panel"></div>`
const commentList = html`<ul id="comment-list" class="comment-list"></ul>`
const commentToolbar = html`
<div class="comment-toolbar">
<label for="position-select">表示位置</label>
</div>
`
const positionSelect = html`
<select id="position-select">
<option value="top-right">右上</option>
<option value="bottom-left" selected>左下</option>
</select>
`
commentToolbar.append(positionSelect)
commentPanel.append(commentList, commentToolbar)
// デフォルトでは動画プレイヤーの下に配置する
videoPlayerContainer.append(commentPanel)
// 表示位置の切り替え
positionSelect.addEventListener('change', (event) => {
const position = event.target.value
switch (position) {
case 'top-right':
asideElement.prepend(commentPanel)
break
case 'bottom-left':
videoPlayerContainer.append(commentPanel)
break
}
scrollToBottom(commentList)
commentPanel.scrollIntoView({ behavior: 'smooth', block: 'center' })
})
// ---------- コメントを取得して表示する ----------
const commentCollector = new CommentCollector({
shouldCollectComments: true,
shouldCollectOfficialComments: true,
})
commentCollector.addEventListener('collect', ({ detail: comment }) => {
displayComment(comment)
})
videoElement.addEventListener('seeked', () => {
while (commentList.firstChild) {
commentList.removeChild(commentList.firstChild)
}
commentCollector.collection = commentCollector.collection.filter((comment) => {
return comment.time < videoElement.currentTime - 3
})
commentCollector.collection.forEach((comment) => {
displayComment(comment)
})
})
function displayComment(comment) {
// 既にリストの最後にスクロールしている場合のみ自動でスクロールする
const shouldAutoScroll = isNearBottom(commentList, 50)
const commentListItem = comment.type === Comment.OFFICIAL_COMMENT
? html`<li class="comment official"></li>`
: html`<li class="comment"></li>`
const commentTime = html`
<a
class="time"
title="${comment.formattedTime} にジャンプする"
>
${comment.formattedTime}
</a>
`
commentTime.addEventListener('click', () => {
videoElement.currentTime = comment.time
})
const commentText = comment.type === Comment.OFFICIAL_COMMENT
? html_unsafe`<span class="text">${comment.text}</span>`
: html`<span class="text">${comment.text}</span>`
commentListItem.append(commentTime, commentText)
commentList.append(commentListItem)
if (shouldAutoScroll) scrollToBottom(commentList)
}