openvibers/openvibe.live Commits
Channel: on a phone held upright a live channel's chat sits under the stream info and fills the screen (a third of the screen was empty while chat waited behind a button) (#163)
Changes
@@@ -1485,3 +1485,24 @@/* Tabs that run past the edge fade out there, so it reads as "scroll for more" (class set by app-channel.js). */.ch-tabs.is-clipped { -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 36px), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 36px), transparent); }++++/* A live channel on a phone held upright: the chat sits under the stream info and fills the screen below the video,++ the way phone streaming apps do. The stream area was sized to the whole screen while the chat waited behind a++ button, which left about a third of the screen empty (seen 2026-10-16). */++@media (max-width: 768px) and (orientation: portrait) {++ #page-channel #ch-live-area .stream-main { flex: none; overflow: visible; }++ #page-channel #ch-live-area .stream-layout > .chat-sidebar {++ position: relative; inset: auto; transform: none; transition: none; z-index: auto;++ flex: 1 1 auto; width: 100%; height: auto; min-height: 220px; max-height: none;++ border-radius: 0; box-shadow: none; border-top: 1px solid var(--border);++ }++ #page-channel #ch-live-area .stream-layout > .chat-sidebar .mobile-chat-close,++ #page-channel #ch-live-area .stream-layout > .chat-sidebar > .chat-grip { display: none; }++ /* Docked, the chat's messages get the room: a slim header, the tools beside nothing else. */++ #page-channel #ch-live-area .stream-layout > .chat-sidebar .chat-header { padding: 6px 12px; min-height: 0; }++ #page-channel #ch-live-area .stream-layout > .chat-sidebar .chat-input-area { padding-top: 6px; padding-bottom: calc(6px + env(safe-area-inset-bottom, 0px)); }++ /* The chat is on screen, so its button goes; the DM bubble steps aside as it does for the open chat sheet++ (it covered the chat's emoji button). */++ body:has(#page-channel.active #ch-live-area .stream-layout > .chat-sidebar) .mobile-chat-toggle,++ body:has(#page-channel.active #ch-live-area .stream-layout > .chat-sidebar) #messenger-toggle { display: none !important; }++}nnew file mode 100644@@@ -0,0 +1,27 @@++/**++ * A live channel on a phone held upright shows its chat under the stream info, filling the screen below the video++ * (public/css/features/channel.css). Before, the stream area was sized to the whole screen while the chat waited++ * behind a floating button, which left about a third of the screen empty (seen 2026-10-16 at phone width). Docked,++ * the chat's button and the DM bubble (which covered the chat's emoji button) step aside.++ *++ * A real browser pass at phone width is in the PR (local Live, a live test stream, a signed-out phone viewer).++ *++ * node test/channel-phone-chat.test.js++ */++'use strict';++const assert = require('assert');++const fs = require('fs');++const path = require('path');++++const css = fs.readFileSync(path.join(__dirname, '..', 'public', 'css', 'features', 'channel.css'), 'utf8');++const at = css.lastIndexOf('@media (max-width: 768px) and (orientation: portrait) {\n #page-channel #ch-live-area .stream-main');++assert.ok(at > 0, 'the portrait-phone block for a live channel exists');++let depth = 0, end = css.indexOf('{', at);++for (; end < css.length; end++) { if (css[end] === '{') depth++; else if (css[end] === '}' && --depth === 0) break; }++const block = css.slice(at, end + 1);++++assert.match(block, /#ch-live-area \.stream-main \{ flex: none; overflow: visible; \}/, 'the stream area keeps its own height');++assert.match(block, /\.stream-layout > \.chat-sidebar \{[^}]*position: relative;[^}]*transform: none;[^}]*flex: 1 1 auto;[^}]*min-height: 220px;/, 'the chat docks below and fills the rest');++assert.match(block, /\.chat-sidebar > \.chat-grip \{ display: none; \}|> \.chat-grip \{ display: none; \}/, 'no bottom-sheet grip on the docked chat');++assert.match(block, /\.mobile-chat-toggle,\s*body:has\([^)]*\) #messenger-toggle \{ display: none !important; \}/, 'its button and the DM bubble step aside');++console.log('channel phone chat: all checks passed');
@@ -1485,3 +1485,24 @@
@@ -1485,3 +1485,24 @@
/* Tabs that run past the edge fade out there, so it reads as "scroll for more" (class set by app-channel.js). */
/* Tabs that run past the edge fade out there, so it reads as "scroll for more" (class set by app-channel.js). */
.ch-tabs.is-clipped { -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 36px), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 36px), transparent); }
.ch-tabs.is-clipped { -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 36px), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 36px), transparent); }
+
+/* A live channel on a phone held upright: the chat sits under the stream info and fills the screen below the video,
+ the way phone streaming apps do. The stream area was sized to the whole screen while the chat waited behind a
+ button, which left about a third of the screen empty (seen 2026-10-16). */
+@media (max-width: 768px) and (orientation: portrait) {
+ #page-channel #ch-live-area .stream-main { flex: none; overflow: visible; }
+ #page-channel #ch-live-area .stream-layout > .chat-sidebar {
+ position: relative; inset: auto; transform: none; transition: none; z-index: auto;
+ flex: 1 1 auto; width: 100%; height: auto; min-height: 220px; max-height: none;
+ border-radius: 0; box-shadow: none; border-top: 1px solid var(--border);
+ }
+ #page-channel #ch-live-area .stream-layout > .chat-sidebar .mobile-chat-close,
+ #page-channel #ch-live-area .stream-layout > .chat-sidebar > .chat-grip { display: none; }
+ /* Docked, the chat's messages get the room: a slim header, the tools beside nothing else. */
+ #page-channel #ch-live-area .stream-layout > .chat-sidebar .chat-header { padding: 6px 12px; min-height: 0; }
+ #page-channel #ch-live-area .stream-layout > .chat-sidebar .chat-input-area { padding-top: 6px; padding-bottom: calc(6px + env(safe-area-inset-bottom, 0px)); }
+ /* The chat is on screen, so its button goes; the DM bubble steps aside as it does for the open chat sheet
+ (it covered the chat's emoji button). */
+ body:has(#page-channel.active #ch-live-area .stream-layout > .chat-sidebar) .mobile-chat-toggle,
+ body:has(#page-channel.active #ch-live-area .stream-layout > .chat-sidebar) #messenger-toggle { display: none !important; }
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
+/**
+ * A live channel on a phone held upright shows its chat under the stream info, filling the screen below the video
+ * (public/css/features/channel.css). Before, the stream area was sized to the whole screen while the chat waited
+ * behind a floating button, which left about a third of the screen empty (seen 2026-10-16 at phone width). Docked,
+ * the chat's button and the DM bubble (which covered the chat's emoji button) step aside.
+ *
+ * A real browser pass at phone width is in the PR (local Live, a live test stream, a signed-out phone viewer).
+ *
+ * node test/channel-phone-chat.test.js
+ */
+'use strict';
+const assert = require('assert');
+const fs = require('fs');
+const path = require('path');
+
+const css = fs.readFileSync(path.join(__dirname, '..', 'public', 'css', 'features', 'channel.css'), 'utf8');
+const at = css.lastIndexOf('@media (max-width: 768px) and (orientation: portrait) {\n #page-channel #ch-live-area .stream-main');
+assert.ok(at > 0, 'the portrait-phone block for a live channel exists');
+let depth = 0, end = css.indexOf('{', at);
+for (; end < css.length; end++) { if (css[end] === '{') depth++; else if (css[end] === '}' && --depth === 0) break; }
+const block = css.slice(at, end + 1);
+
+assert.match(block, /#ch-live-area \.stream-main \{ flex: none; overflow: visible; \}/, 'the stream area keeps its own height');
+assert.match(block, /\.stream-layout > \.chat-sidebar \{[^}]*position: relative;[^}]*transform: none;[^}]*flex: 1 1 auto;[^}]*min-height: 220px;/, 'the chat docks below and fills the rest');
+assert.match(block, /\.chat-sidebar > \.chat-grip \{ display: none; \}|> \.chat-grip \{ display: none; \}/, 'no bottom-sheet grip on the docked chat');
+assert.match(block, /\.mobile-chat-toggle,\s*body:has\([^)]*\) #messenger-toggle \{ display: none !important; \}/, 'its button and the DM bubble step aside');
+console.log('channel phone chat: all checks passed');