Add collapsible YouTube panel
This commit is contained in:
@@ -11,6 +11,7 @@ const youtubeInput = document.querySelector("#youtube-input");
|
||||
const youtubeShell = document.querySelector("#youtube-shell");
|
||||
const watchPanel = document.querySelector(".watch-panel");
|
||||
const watchResizeHandle = document.querySelector("#watch-resize-handle");
|
||||
const watchCollapseButton = document.querySelector("#watch-collapse-button");
|
||||
const playlistList = document.querySelector("#playlist-list");
|
||||
const clearPlaylistButton = document.querySelector("#clear-playlist-button");
|
||||
const cameraSelect = document.querySelector("#camera-select");
|
||||
@@ -24,6 +25,7 @@ const nameStorageKey = "kkkmeet.displayName";
|
||||
const cameraStorageKey = "kkkmeet.cameraDeviceId";
|
||||
const micStorageKey = "kkkmeet.micDeviceId";
|
||||
const watchHeightStorageKey = "kkkmeet.watchPanelHeight";
|
||||
const watchCollapsedStorageKey = "kkkmeet.watchPanelCollapsed";
|
||||
const rtcConfig = {
|
||||
iceServers: [{ urls: "stun:stun.l.google.com:19302" }]
|
||||
};
|
||||
@@ -49,6 +51,28 @@ function applyStoredWatchHeight() {
|
||||
if (savedHeight > 0) {
|
||||
stage.style.setProperty("--watch-panel-height", `${savedHeight}px`);
|
||||
}
|
||||
setWatchCollapsed(localStorage.getItem(watchCollapsedStorageKey) === "true");
|
||||
}
|
||||
|
||||
function setWatchCollapsed(collapsed) {
|
||||
stage.classList.toggle("is-watch-collapsed", collapsed);
|
||||
watchCollapseButton.textContent = collapsed ? "↓" : "↑";
|
||||
watchCollapseButton.setAttribute(
|
||||
"aria-label",
|
||||
collapsed ? "Expand YouTube panel" : "Collapse YouTube panel"
|
||||
);
|
||||
watchCollapseButton.title = collapsed ? "Expand YouTube panel" : "Collapse YouTube panel";
|
||||
localStorage.setItem(watchCollapsedStorageKey, String(collapsed));
|
||||
}
|
||||
|
||||
function toggleWatchCollapsed() {
|
||||
if (!stage.classList.contains("is-watch-collapsed")) {
|
||||
const height = Math.round(watchPanel.getBoundingClientRect().height);
|
||||
if (height > 0) {
|
||||
localStorage.setItem(watchHeightStorageKey, String(height));
|
||||
}
|
||||
}
|
||||
setWatchCollapsed(!stage.classList.contains("is-watch-collapsed"));
|
||||
}
|
||||
|
||||
function setStatus(message) {
|
||||
@@ -752,6 +776,10 @@ navigator.mediaDevices?.addEventListener?.("devicechange", () => {
|
||||
applyStoredWatchHeight();
|
||||
|
||||
watchResizeHandle.addEventListener("pointerdown", (event) => {
|
||||
if (event.target.closest("#watch-collapse-button") || stage.classList.contains("is-watch-collapsed")) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
watchResizeHandle.setPointerCapture(event.pointerId);
|
||||
stage.classList.add("is-resizing-watch");
|
||||
@@ -779,3 +807,14 @@ watchResizeHandle.addEventListener("pointerdown", (event) => {
|
||||
watchResizeHandle.addEventListener("pointerup", stop);
|
||||
watchResizeHandle.addEventListener("pointercancel", stop);
|
||||
});
|
||||
|
||||
watchCollapseButton.addEventListener("click", (event) => {
|
||||
event.stopPropagation();
|
||||
toggleWatchCollapsed();
|
||||
});
|
||||
|
||||
watchCollapseButton.addEventListener("keydown", (event) => {
|
||||
if (event.key !== "Enter" && event.key !== " ") return;
|
||||
event.preventDefault();
|
||||
toggleWatchCollapsed();
|
||||
});
|
||||
|
||||
+22
-11
@@ -22,16 +22,6 @@
|
||||
<section class="stage" aria-label="Video call">
|
||||
<section class="watch-panel" aria-label="Watch together">
|
||||
<div class="watch-main">
|
||||
<form id="youtube-form" class="youtube-form">
|
||||
<input
|
||||
id="youtube-input"
|
||||
type="url"
|
||||
inputmode="url"
|
||||
placeholder="YouTube URL"
|
||||
autocomplete="off"
|
||||
/>
|
||||
<button type="submit">Add</button>
|
||||
</form>
|
||||
<div class="youtube-shell" id="youtube-shell">
|
||||
<div id="youtube-player"></div>
|
||||
</div>
|
||||
@@ -42,6 +32,16 @@
|
||||
<button id="clear-playlist-button" type="button">Clear list</button>
|
||||
</div>
|
||||
<ul id="playlist-list" class="playlist-list"></ul>
|
||||
<form id="youtube-form" class="youtube-form">
|
||||
<input
|
||||
id="youtube-input"
|
||||
type="url"
|
||||
inputmode="url"
|
||||
placeholder="YouTube URL"
|
||||
autocomplete="off"
|
||||
/>
|
||||
<button type="submit">Add</button>
|
||||
</form>
|
||||
</aside>
|
||||
</section>
|
||||
<button
|
||||
@@ -50,7 +50,18 @@
|
||||
type="button"
|
||||
aria-label="Resize YouTube panel"
|
||||
title="Resize YouTube panel"
|
||||
></button>
|
||||
>
|
||||
<span
|
||||
id="watch-collapse-button"
|
||||
class="watch-collapse-button"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
aria-label="Collapse YouTube panel"
|
||||
title="Collapse YouTube panel"
|
||||
>
|
||||
↑
|
||||
</span>
|
||||
</button>
|
||||
<div class="remote-grid" id="remote-grid">
|
||||
<div class="empty-stage" id="empty-stage">Waiting for others to join</div>
|
||||
</div>
|
||||
|
||||
+46
-8
@@ -110,6 +110,10 @@ button[aria-pressed="false"] {
|
||||
padding: 18px 18px 12px;
|
||||
}
|
||||
|
||||
.stage.is-watch-collapsed {
|
||||
grid-template-rows: 0 20px minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.watch-panel {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(320px, 1fr) minmax(240px, 360px);
|
||||
@@ -120,17 +124,21 @@ button[aria-pressed="false"] {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.stage.is-watch-collapsed .watch-panel {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.watch-main {
|
||||
display: grid;
|
||||
grid-template-rows: auto minmax(0, 1fr);
|
||||
gap: 10px;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.youtube-form {
|
||||
display: flex;
|
||||
align-items: end;
|
||||
align-items: stretch;
|
||||
gap: 10px;
|
||||
padding: 10px;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.youtube-form input {
|
||||
@@ -171,6 +179,10 @@ button[aria-pressed="false"] {
|
||||
cursor: row-resize;
|
||||
}
|
||||
|
||||
.stage.is-watch-collapsed .watch-resize-handle {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.watch-resize-handle::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
@@ -183,6 +195,32 @@ button[aria-pressed="false"] {
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.watch-collapse-button {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
z-index: 1;
|
||||
display: inline-grid;
|
||||
place-items: center;
|
||||
width: 34px;
|
||||
height: 20px;
|
||||
border-radius: 999px;
|
||||
background: #1f8f5f;
|
||||
color: #ffffff;
|
||||
font-size: 14px;
|
||||
font-weight: 800;
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.watch-collapse-button:hover,
|
||||
.watch-collapse-button:focus-visible {
|
||||
filter: brightness(1.12);
|
||||
outline: 2px solid rgba(255, 255, 255, 0.42);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.watch-resize-handle:hover::before,
|
||||
.watch-resize-handle:focus-visible::before,
|
||||
.stage.is-resizing-watch .watch-resize-handle::before {
|
||||
@@ -195,7 +233,7 @@ button[aria-pressed="false"] {
|
||||
|
||||
.playlist-panel {
|
||||
display: grid;
|
||||
grid-template-rows: auto minmax(0, 1fr);
|
||||
grid-template-rows: auto minmax(0, 1fr) auto;
|
||||
min-height: 0;
|
||||
border-radius: 8px;
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
@@ -490,16 +528,16 @@ button[aria-pressed="false"] {
|
||||
grid-template-rows: var(--watch-panel-height, 430px) 14px minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.stage.is-watch-collapsed {
|
||||
grid-template-rows: 0 20px minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.watch-panel {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: minmax(220px, 1fr) minmax(160px, auto);
|
||||
min-height: 430px;
|
||||
}
|
||||
|
||||
.youtube-form {
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.remote-grid {
|
||||
grid-template-columns: 1fr;
|
||||
grid-auto-rows: minmax(190px, 1fr);
|
||||
|
||||
Reference in New Issue
Block a user