-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathjimaku.tsx
152 lines (132 loc) · 5.67 KB
/
jimaku.tsx
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import '~style.css';
import {
Checkbox,
IconButton,
List,
ListItem,
Menu,
MenuHandler,
MenuItem,
MenuList,
Navbar,
Typography
} from '@material-tailwind/react';
import { Fragment, memo, useEffect, useRef, useState } from 'react';
import BJFThemeProvider from '~components/BJFThemeProvider';
import VirtualScroller from 'virtual-scroller/react';
import { useForwarder } from '~hooks/forwarder';
export type Jimaku = {
text: string
date: string
hash: string
}
const urlParams = new URLSearchParams(window.location.search)
const roomId = urlParams.get('roomId')
const roomTitle = urlParams.get('title')
const roomOwner = urlParams.get('owner')
function JimakuPage(): JSX.Element {
const [title, setTitle] = useState('加载中')
const [openNav, setOpenNav] = useState(false);
const [keepBottom, setKeepBottom] = useState(true);
const bottomRef = useRef(keepBottom)
useEffect(() => {
bottomRef.current = keepBottom
}, [keepBottom])
const [messages, setMessages] = useState<Jimaku[]>([])
const forwarder = useForwarder('jimaku', 'pages')
useEffect(() => {
if (bottomRef.current) {
window.scrollTo(0, document.body.scrollHeight)
}
}, [messages])
useEffect(() => {
if (roomId) {
setTitle(roomTitle ?? `B站直播间 ${roomId} 的同传弹幕视窗`)
forwarder.addHandler((message) => {
if (message.room !== roomId) return
setMessages(messages => [...messages, message])
})
} else {
alert('未知房间Id, 此同传弹幕视窗不会运行。')
}
}, []);
return (
<Fragment>
<Navbar className="sticky top-0 z-10 shadow-md w-full max-w-full px-6 py-3 bg-gray-800 dark:bg-gray-800 rounded-none ring-0 border-0">
<div className="flex items-center justify-between">
<div className='flex flex-col justify-normal py-1'>
<Typography variant="h5" className='text-gray-100'>
{title}
</Typography>
<Typography variant='h5' className='text-gray-100 text-md'>
{`${roomOwner} 的直播间`}
</Typography>
</div>
<Menu
open={openNav}
handler={setOpenNav}
dismiss={{
itemPress: false,
isRequired: {} // I dunno why but adding this eliminated the error from material-tailwind
}}
>
<MenuHandler>
<IconButton
variant="text"
className="ml-auto h-6 w-6 text-inherit hover:bg-transparent focus:bg-transparent active:bg-transparent transition-all duration-100 ease-in-out"
ripple={false}
onClick={() => setOpenNav(!openNav)}
>
{openNav ? (
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor" className="w-6 h-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
) : (
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor" className="w-6 h-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
</svg>
)}
</IconButton>
</MenuHandler>
<MenuList dismissible={false} className="p-0">
<MenuItem className="p-0 overflow-hidden">
<label className="flex w-full cursor-pointer items-center px-3 py-2">
<Checkbox
ripple={false}
crossOrigin={'annymous'}
label="自動置底"
checked={keepBottom}
onChange={e => setKeepBottom(e.target.checked)}
/>
</label>
</MenuItem>
</MenuList>
</Menu>
</div>
</Navbar>
<div id="popup-jimaku-list-container" className="container w-full max-w-full">
<List id='popup-jimaku-list' className="overflow-y-auto">
<VirtualScroller
items={messages}
itemComponent={memo(MessageItem)}
/>
</List>
</div>
</Fragment>
)
}
function MessageItem({ item: jimaku }: { item: Jimaku }): JSX.Element {
return (
<ListItem key={jimaku.hash} className="dark:text-white dark:hover:text-white dark:focus:text-white dark:hover:bg-gray-700 dark:focus:bg-gray-700" ripple={false}>
【{jimaku.date}】{jimaku.text}
</ListItem>
)
}
function JimakuApp(): JSX.Element {
return (
<BJFThemeProvider>
<JimakuPage />
</BJFThemeProvider>
)
}
export default JimakuApp