Spaces:
Running
Running
copilot-swe-agent[bot] ArnavSingh76533 commited on
Commit ·
8b825da
1
Parent(s): 7f6fc57
Address code review feedback: fix CSS duplication, improve URL validation and detection
Browse filesCo-authored-by: ArnavSingh76533 <160649079+ArnavSingh76533@users.noreply.github.com>
- components/player/Controls.tsx +20 -2
- pages/api/socketio.ts +7 -4
- pages/global.css +0 -1
components/player/Controls.tsx
CHANGED
|
@@ -116,8 +116,11 @@ const Controls: FC<Props> = ({
|
|
| 116 |
const left = window.screen.width - width - 20
|
| 117 |
const top = window.screen.height - height - 100
|
| 118 |
|
|
|
|
|
|
|
|
|
|
| 119 |
const pipWindow = window.open(
|
| 120 |
-
`/embed/${
|
| 121 |
'PiP Player',
|
| 122 |
`width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=no,status=no,toolbar=no,menubar=no,location=no`
|
| 123 |
)
|
|
@@ -334,7 +337,19 @@ const Controls: FC<Props> = ({
|
|
| 334 |
}
|
| 335 |
} else {
|
| 336 |
// Try to enter PiP
|
| 337 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 338 |
|
| 339 |
if (isYouTube) {
|
| 340 |
// For YouTube, use ReactPlayer's pip prop
|
|
@@ -344,6 +359,9 @@ const Controls: FC<Props> = ({
|
|
| 344 |
}
|
| 345 |
} else {
|
| 346 |
// For file sources, try native PiP API
|
|
|
|
|
|
|
|
|
|
| 347 |
const videoElement = document.querySelector('video')
|
| 348 |
|
| 349 |
if (videoElement && 'requestPictureInPicture' in videoElement && document.pictureInPictureEnabled) {
|
|
|
|
| 116 |
const left = window.screen.width - width - 20
|
| 117 |
const top = window.screen.height - height - 100
|
| 118 |
|
| 119 |
+
// Encode roomId to prevent any potential injection issues
|
| 120 |
+
const encodedRoomId = encodeURIComponent(roomId)
|
| 121 |
+
|
| 122 |
const pipWindow = window.open(
|
| 123 |
+
`/embed/${encodedRoomId}`,
|
| 124 |
'PiP Player',
|
| 125 |
`width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=no,status=no,toolbar=no,menubar=no,location=no`
|
| 126 |
)
|
|
|
|
| 337 |
}
|
| 338 |
} else {
|
| 339 |
// Try to enter PiP
|
| 340 |
+
// More robust YouTube URL detection
|
| 341 |
+
let isYouTube = false
|
| 342 |
+
try {
|
| 343 |
+
const url = new URL(currentSrc.src)
|
| 344 |
+
const hostname = url.hostname.toLowerCase()
|
| 345 |
+
isYouTube = hostname.includes('youtube.com') ||
|
| 346 |
+
hostname.includes('youtu.be') ||
|
| 347 |
+
hostname.includes('m.youtube.com') ||
|
| 348 |
+
hostname.includes('gaming.youtube.com')
|
| 349 |
+
} catch (e) {
|
| 350 |
+
// Invalid URL, treat as non-YouTube
|
| 351 |
+
isYouTube = false
|
| 352 |
+
}
|
| 353 |
|
| 354 |
if (isYouTube) {
|
| 355 |
// For YouTube, use ReactPlayer's pip prop
|
|
|
|
| 359 |
}
|
| 360 |
} else {
|
| 361 |
// For file sources, try native PiP API
|
| 362 |
+
// Note: We query for the first video element on the page.
|
| 363 |
+
// This works for the current app structure where there's only one video player.
|
| 364 |
+
// If multiple video elements exist, this might select the wrong one.
|
| 365 |
const videoElement = document.querySelector('video')
|
| 366 |
|
| 367 |
if (videoElement && 'requestPictureInPicture' in videoElement && document.pictureInPictureEnabled) {
|
pages/api/socketio.ts
CHANGED
|
@@ -205,15 +205,18 @@ const ioHandler = (_: NextApiRequest, res: NextApiResponse) => {
|
|
| 205 |
room.targetState.playlist.items.length
|
| 206 |
) {
|
| 207 |
// Auto-advance to next item: play next video and remove finished one
|
|
|
|
|
|
|
|
|
|
|
|
|
| 208 |
room.targetState.playing =
|
| 209 |
-
room.targetState.playlist.items[
|
| 210 |
-
room.targetState.playlist.currentIndex + 1
|
| 211 |
-
]
|
| 212 |
|
| 213 |
// Remove the finished item from playlist (shift remaining items left)
|
| 214 |
-
room.targetState.playlist.items.splice(
|
| 215 |
|
| 216 |
// Reset currentIndex to 0 since items have shifted
|
|
|
|
| 217 |
room.targetState.playlist.currentIndex = 0
|
| 218 |
room.targetState.progress = 0
|
| 219 |
room.targetState.paused = false
|
|
|
|
| 205 |
room.targetState.playlist.items.length
|
| 206 |
) {
|
| 207 |
// Auto-advance to next item: play next video and remove finished one
|
| 208 |
+
// This condition ensures there IS a next item before we splice
|
| 209 |
+
const currentIdx = room.targetState.playlist.currentIndex
|
| 210 |
+
|
| 211 |
+
// Get the next item before removing current
|
| 212 |
room.targetState.playing =
|
| 213 |
+
room.targetState.playlist.items[currentIdx + 1]
|
|
|
|
|
|
|
| 214 |
|
| 215 |
// Remove the finished item from playlist (shift remaining items left)
|
| 216 |
+
room.targetState.playlist.items.splice(currentIdx, 1)
|
| 217 |
|
| 218 |
// Reset currentIndex to 0 since items have shifted
|
| 219 |
+
// (the next item is now at position 0)
|
| 220 |
room.targetState.playlist.currentIndex = 0
|
| 221 |
room.targetState.progress = 0
|
| 222 |
room.targetState.paused = false
|
pages/global.css
CHANGED
|
@@ -96,7 +96,6 @@ html {
|
|
| 96 |
/* Non-fullscreen video styles */
|
| 97 |
.video-normal {
|
| 98 |
height: calc((9 / 16) * 100vw);
|
| 99 |
-
max-height: calc(100vh - 210px);
|
| 100 |
max-height: calc(100dvh - 210px);
|
| 101 |
}
|
| 102 |
|
|
|
|
| 96 |
/* Non-fullscreen video styles */
|
| 97 |
.video-normal {
|
| 98 |
height: calc((9 / 16) * 100vw);
|
|
|
|
| 99 |
max-height: calc(100dvh - 210px);
|
| 100 |
}
|
| 101 |
|