Skip to content

Commit 6cfafbe

Browse files
committed
feat: add video room page with UI enhancements, state management, and localization support
1 parent 938f55d commit 6cfafbe

4 files changed

Lines changed: 398 additions & 26 deletions

File tree

web/src/i18n/locales/en.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,18 @@
251251
"Video room not found": "Video room not found",
252252
"Room synced": "Room synced",
253253
"Room disconnected": "Room disconnected",
254+
"Share room": "Share room",
255+
"Now watching": "Now watching",
256+
"Everyone follows the same playback": "Everyone follows the same playback",
257+
"Waiting for sync connection": "Waiting for sync connection",
258+
"Playback state is shared in this room": "Playback state is shared in this room",
259+
"Room status": "Room status",
260+
"Playback": "Playback",
261+
"Playing": "Playing",
262+
"Paused": "Paused",
263+
"Current position": "Current position",
264+
"Resync playback": "Resync playback",
265+
"Room link": "Room link",
254266
"Audio": "Audio",
255267
"PDF": "PDF",
256268
"Word": "Word",

web/src/i18n/locales/zh.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,18 @@
270270
"Video room not found": "视频房不存在",
271271
"Room synced": "房间同步中",
272272
"Room disconnected": "房间已断开",
273+
"Share room": "分享房间",
274+
"Now watching": "正在观看",
275+
"Everyone follows the same playback": "所有人同步播放",
276+
"Waiting for sync connection": "等待同步连接",
277+
"Playback state is shared in this room": "房间内会同步播放、暂停和进度",
278+
"Room status": "房间状态",
279+
"Playback": "播放状态",
280+
"Playing": "播放中",
281+
"Paused": "已暂停",
282+
"Current position": "当前进度",
283+
"Resync playback": "重新同步",
284+
"Room link": "房间链接",
273285
"Audio": "音频",
274286
"PDF": "PDF",
275287
"Word": "Word 文档",

web/src/pages/VideoRoomPage.css

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
.video-room-page {
2+
min-height: 100vh;
3+
padding: 24px;
4+
background: #0b0f12;
5+
}
6+
7+
.video-room-page--center {
8+
display: flex;
9+
align-items: center;
10+
justify-content: center;
11+
}
12+
13+
.video-room-page--center .ant-empty-description {
14+
color: rgba(255, 255, 255, 0.72);
15+
}
16+
17+
.video-room-header {
18+
display: flex;
19+
align-items: center;
20+
justify-content: space-between;
21+
gap: 16px;
22+
max-width: 1720px;
23+
margin: 0 auto 16px;
24+
}
25+
26+
.video-room-header__left {
27+
min-width: 0;
28+
}
29+
30+
.video-room-header__right {
31+
display: flex;
32+
flex: none;
33+
align-items: center;
34+
gap: 10px;
35+
}
36+
37+
.video-room-title-block {
38+
min-width: 0;
39+
}
40+
41+
.video-room-title.ant-typography {
42+
max-width: min(980px, 70vw);
43+
margin: 0 0 4px;
44+
overflow: hidden;
45+
color: rgba(255, 255, 255, 0.92);
46+
text-overflow: ellipsis;
47+
white-space: nowrap;
48+
}
49+
50+
.video-room-file-name {
51+
max-width: min(720px, 58vw);
52+
}
53+
54+
.video-room-status-tag.ant-tag {
55+
display: inline-flex;
56+
align-items: center;
57+
height: 32px;
58+
margin: 0;
59+
padding: 0 12px;
60+
border-radius: 8px;
61+
}
62+
63+
.video-room-shell {
64+
display: grid;
65+
grid-template-columns: minmax(0, 1fr) 360px;
66+
gap: 18px;
67+
max-width: 1720px;
68+
margin: 0 auto;
69+
}
70+
71+
.video-room-main {
72+
min-width: 0;
73+
}
74+
75+
.video-room-stage {
76+
overflow: hidden;
77+
border: 1px solid rgba(255, 255, 255, 0.08);
78+
border-radius: 12px;
79+
background: #000;
80+
}
81+
82+
.video-room-player {
83+
width: 100%;
84+
height: min(72vh, 760px);
85+
min-height: 480px;
86+
background: #000;
87+
}
88+
89+
.video-room-note {
90+
display: flex;
91+
align-items: center;
92+
justify-content: center;
93+
gap: 8px;
94+
padding: 14px;
95+
color: rgba(255, 255, 255, 0.45);
96+
font-size: 13px;
97+
}
98+
99+
.video-room-note .anticon {
100+
color: var(--ant-color-primary, #1677ff);
101+
}
102+
103+
.video-room-side {
104+
display: flex;
105+
flex-direction: column;
106+
gap: 14px;
107+
min-width: 0;
108+
}
109+
110+
.video-room-panel.ant-card {
111+
border-color: rgba(255, 255, 255, 0.08);
112+
background: #14191d;
113+
}
114+
115+
.video-room-panel .ant-card-head {
116+
min-height: 48px;
117+
border-bottom-color: rgba(255, 255, 255, 0.08);
118+
}
119+
120+
.video-room-panel .ant-card-head-title {
121+
color: rgba(255, 255, 255, 0.9);
122+
font-weight: 600;
123+
}
124+
125+
.video-room-panel .ant-card-body {
126+
padding: 16px;
127+
}
128+
129+
.video-room-dot {
130+
display: block;
131+
width: 8px;
132+
height: 8px;
133+
border-radius: 999px;
134+
background: var(--ant-color-error, #ff4d4f);
135+
box-shadow: 0 0 0 4px rgba(255, 77, 79, 0.14);
136+
}
137+
138+
.video-room-dot.is-connected {
139+
background: var(--ant-color-success, #52c41a);
140+
box-shadow: 0 0 0 4px rgba(82, 196, 26, 0.14);
141+
}
142+
143+
.video-room-status-list {
144+
display: flex;
145+
flex-direction: column;
146+
gap: 10px;
147+
margin-bottom: 16px;
148+
}
149+
150+
.video-room-status-item {
151+
display: flex;
152+
align-items: center;
153+
gap: 12px;
154+
min-width: 0;
155+
padding: 12px;
156+
border: 1px solid rgba(255, 255, 255, 0.06);
157+
border-radius: 8px;
158+
background: rgba(255, 255, 255, 0.03);
159+
}
160+
161+
.video-room-status-item > .anticon {
162+
flex: none;
163+
color: var(--ant-color-primary, #1677ff);
164+
font-size: 18px;
165+
}
166+
167+
.video-room-status-item div {
168+
min-width: 0;
169+
}
170+
171+
.video-room-status-item span {
172+
display: block;
173+
margin-bottom: 2px;
174+
color: rgba(255, 255, 255, 0.45);
175+
font-size: 12px;
176+
}
177+
178+
.video-room-status-item strong {
179+
display: block;
180+
overflow: hidden;
181+
color: rgba(255, 255, 255, 0.88);
182+
font-size: 14px;
183+
font-weight: 600;
184+
text-overflow: ellipsis;
185+
white-space: nowrap;
186+
}
187+
188+
.video-room-primary-action.ant-btn {
189+
height: 40px;
190+
}
191+
192+
.video-room-panel__text {
193+
margin: 0 0 14px;
194+
color: rgba(255, 255, 255, 0.55);
195+
font-size: 14px;
196+
line-height: 1.6;
197+
}
198+
199+
@media (max-width: 1180px) {
200+
.video-room-shell {
201+
grid-template-columns: 1fr;
202+
}
203+
204+
.video-room-side {
205+
display: grid;
206+
grid-template-columns: repeat(2, minmax(0, 1fr));
207+
}
208+
}
209+
210+
@media (max-width: 760px) {
211+
.video-room-page {
212+
padding: 14px;
213+
}
214+
215+
.video-room-header {
216+
align-items: stretch;
217+
flex-direction: column;
218+
}
219+
220+
.video-room-header__right {
221+
display: grid;
222+
grid-template-columns: 1fr 1fr;
223+
}
224+
225+
.video-room-title.ant-typography,
226+
.video-room-file-name {
227+
max-width: 100%;
228+
}
229+
230+
.video-room-player {
231+
height: 56vh;
232+
min-height: 280px;
233+
}
234+
235+
.video-room-side {
236+
display: flex;
237+
}
238+
}

0 commit comments

Comments
 (0)