openvibers/openvibe.live Commits
openvibe-shared v4.95.0; on a phone, Recent Pastes is a rail that loads as you swipe (#553)
Changes
@@@ -177,5 +177,5 @@ Minimum `.env`: `BASE_URL`, `JWT_SECRET`, `OV_NETWORK_URL`, `OV_NETWORK_INTERNAL<!-- versions:start -->- openvibe-contracts: v0.222.0- openvibe-sdk: v0.81.0--- openvibe-shared: v4.94.0++- openvibe-shared: v4.95.0<!-- versions:end -->@@@ -7,7 +7,7 @@"domain": "openvibe.live (www, ingest, whip)","contracts": "openvibe-contracts v0.222.0","sdk": "openvibe-sdk v0.81.0",-- "shared": "openvibe-shared v4.94.0",++ "shared": "openvibe-shared v4.95.0","capabilities": ["live.chat_context.read","live.chat_effects.write",@@@ -25,7 +25,7 @@"onnxruntime-node": "^1.20.0","openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.222.0","openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.81.0",-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.94.0",++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.95.0","pg": "^8.23.1","sanitize-html": "^2.17.7","sdp-transform": "^3.0.0",@@@ -2884,9 +2884,9 @@}},"node_modules/openvibe-shared": {-- "version": "4.94.0",-- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.94.0",-- "integrity": "sha512-iMsgL7a5vxouygXsWxQACJrnRubhpe6tnMAKjiJZ0m6Fn+hFcJjQzrI/fERZB3ToC+xK4zO6b6hsm4zK6x4MYg==",++ "version": "4.95.0",++ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.95.0",++ "integrity": "sha512-jY0ZKFQMvx3NiyKxHkZ950nq7P8CtlzlP4OOnTkJf0nyVVG93qT4JE0udr8bF8Kwm7FrzkLgfaLB1qDrjH22eg==","license": "MIT","dependencies": {"jsonwebtoken": "^9.0.0",@@@ -44,7 +44,7 @@"onnxruntime-node": "^1.20.0","openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.222.0","openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.81.0",-- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.94.0",++ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.95.0","pg": "^8.23.1","sanitize-html": "^2.17.7","sdp-transform": "^3.0.0",@@@ -1332,22 +1332,23 @@ body.egg-rainbow { animation: eggRainbow 2.6s linear; }.home-tabbox [data-panel="network"] .network-hub-header h3 { display: none; }/* Catch up on a phone: each rail is one row of cards that scrolls sideways, so all five fit in a few screens-- and nothing is behind a tab. */-- #home-catchup .stream-grid {++ and nothing is behind a tab. Recent Pastes rides the same rail (2026-11-02): it was two cards a row with a++ "Load 2 more · 309 left" button under them. */++ #home-catchup .stream-grid, #home-catchup .home-pastes-list {display: grid; grid-auto-flow: column; grid-template-columns: none; grid-auto-columns: minmax(232px, 74%); align-items: start;gap: 12px; margin-inline: -16px; padding: 2px 16px 10px; scroll-padding-inline: 16px;overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory; scrollbar-width: none;}-- #home-catchup .stream-grid::-webkit-scrollbar { display: none; }++ #home-catchup .stream-grid::-webkit-scrollbar, #home-catchup .home-pastes-list::-webkit-scrollbar { display: none; }/* ov-density.js reads a sideways rail's implicit columns as "too many" and clamps the grid to repeat(N, minmax(0, 1fr))with !important, which squeezed the first cards to a few pixels (production's Recently Online showed an 81 pxsliver, 2026-11-01). A rail has no columns to choose: its own track sizing wins. */-- #home-catchup .stream-grid[data-ovd-cols] { grid-template-columns: none !important; }-- #home-catchup .stream-grid > * { scroll-snap-align: start; min-width: 0; }-- #home-catchup .stream-grid > .empty-state { grid-column: auto; min-width: calc(100vw - 32px); }++ #home-catchup .stream-grid[data-ovd-cols], #home-catchup .home-pastes-list[data-ovd-cols] { grid-template-columns: none !important; }++ #home-catchup .stream-grid > *, #home-catchup .home-pastes-list > * { scroll-snap-align: start; min-width: 0; }++ #home-catchup .stream-grid > .empty-state, #home-catchup .home-pastes-list > .empty-state { grid-column: auto; min-width: calc(100vw - 32px); }/* The end of a sideways rail (2026-11-01): placeholder cards where the next ones load by themselves as the readerswipes toward them (app-home.js homeRailTail), then one "View all" card once every card is in. */-- #home-catchup .stream-grid > .home-rail-tail { display: flex; }++ #home-catchup .stream-grid > .home-rail-tail, #home-catchup .home-pastes-list > .home-rail-tail { display: flex; }.home-rail-skel {flex-direction: column; gap: 10px; padding-bottom: 14px; overflow: hidden;border-radius: 14px; border: 1px solid var(--border); background: var(--bg-card);@@@ -111,12 +111,25 @@const sweep = () => {document.querySelectorAll('.hfx-reveal:not(.is-in)').forEach(el => {const r = el.getBoundingClientRect();-- if (r.height && r.top < window.innerHeight && r.bottom > 0) el.classList.add('is-in');++ if (r.height && r.top < window.innerHeight) el.classList.add('is-in'); // on screen, or already passed});revealPasses++;revealSafety = revealPasses < 5 ? setTimeout(sweep, 2000) : 0;};revealSafety = setTimeout(sweep, 1200);++ // A fling can carry a section past the screen between two frames, so the observer never reports it, and the++ // sweeps above stop after ten seconds. When scrolling stops, anything above the bottom of the screen that is++ // still waiting is shown: one query per pause, never during the scroll.++ let settle = 0;++ window.addEventListener('scroll', () => {++ clearTimeout(settle);++ settle = setTimeout(() => {++ document.querySelectorAll('.hfx-reveal:not(.is-in)').forEach(el => {++ const r = el.getBoundingClientRect();++ if (r.height && r.top < window.innerHeight) el.classList.add('is-in');++ });++ }, 140);++ }, { passive: true });}const REVEAL_SEL = '#page-home .section-header, #page-home .stream-card, #page-home .home-cta-banner, #page-home .home-star-section, #page-home .rs-hero-mount, #page-home .pulse-grid > *, #page-home .moments-row > *, #page-home .home-digest';@@@ -125,7 +138,9 @@let lateIo = null;function attachReveal(roots) {if (!('IntersectionObserver' in window)) return;-- if (!io) io = new IntersectionObserver((entries) => { for (const en of entries) if (en.isIntersecting) { en.target.classList.add('is-in'); io.unobserve(en.target); } }, { rootMargin: '0px 0px -8% 0px', threshold: 0.08 });++ // Seen, or scrolled past before the observer caught it (a fast swipe): either way it shows. A section passed++ // over stayed at opacity 0 until the reader came back to it, a blank band on the way down (2026-11-02).++ if (!io) io = new IntersectionObserver((entries) => { for (const en of entries) if (en.isIntersecting || en.boundingClientRect.bottom < 0) { en.target.classList.add('is-in'); io.unobserve(en.target); } }, { rootMargin: '0px 0px -8% 0px', threshold: 0.08 });if (!lateIo) lateIo = new IntersectionObserver((entries) => {for (const en of entries) {const el = en.target; lateIo.unobserve(el);@@@ -22,8 +22,8 @@ const BUDGETS = {htmlRawKB: 128, // 119.3 with the icons drawn on the server (2026-11-01, plan L54 K4: the OpenVibe glyphs in the HTML, 20.8 KB brotli); measured 94.9 beforehtmlBrotliKB: 30,jsFiles: 26, // measured 23 (incl. route scripts for "/")-- jsRawKB: 1263, // 1262.1 (2026-11-02: openvibe-shared 4.94.0, the Audio chip, the go-live card's labels); 1259.8 (2026-11-02: content labels on cards and the player, L1); 1257.5 (2026-11-01: the Catch up rails load by themselves as you swipe, no Load more on a phone); 1254.2 (2026-11-01: openvibe-shared 4.87.0), about 1255 with #534 (feed and card avatars at their size); 1253.8 (2026-11-01: avatars ask Media for their drawn width, ovImgW); 1252.3 (2026-11-01: Following in the topics row, the picked topic remembered); 1250.2 (2026-11-01: topics live now, readable chat names on light themes); 1247.7 openvibe-shared 4.70.0 (2026-11-01: the app bar, busy(), skeletons, view transitions); 1244.3 with openvibe-shared 4.66.0: the mark with depth and motion, ov-fx loaded on request (2026-10-31); 1243.5 with openvibe-shared 4.64.0: the look travels between sites, the Look panel in the menu (2026-10-31); 1242.7 with openvibe-shared 4.59.0: the Pair mark beside the name, set in the brand face, and the ring on page moves (2026-10-31); 1238.8 with the home's featured stream once and the intro closed on phones (2026-10-31); 1237.4 with the home's two more tab blocks on phones (2026-10-30); 1233.9 with the home's Catch up tabs on phones (2026-10-30); 1230.8 with openvibe-shared 4.53.0: the footer's columns fold on phones (2026-10-30); 1227.8 with openvibe-shared 4.52.0: the Dock's loader and its Chats tab (2026-10-30); 1223.5 with openvibe-shared 4.48.0 (the site switcher on the mark, the menu's Start tab and quick tools; Kit's touch hit areas and the phone navbar fix, 4.44-4.47.3); 1215.4 with openvibe-shared 4.43.0 (room.css carries the kit tokens, 4.39.1; the kit's 4.39.0 rules); measured 1203.9 (2026-10-28: openvibe-shared 4.30.0, the bell center: tabs with counts, the Unread filter, thumbnails, swipe, the phone sheet; 4.31.0's ✦ adds about 3 KB); 1187.2 (2026-10-28: openvibe-shared 4.27.0, Notifications 2.0: opaque themed toasts held while a menu is open, grouping, priority, System cards and the rich bell panel); 1158.8 (2026-10-28: openvibe-shared 4.25.0, the menu's orb, messages, the phone sheet and auto-hide in the navbar; the messenger opens from the bar)-- jsBrotliKB: 295.5, // 295.1 (2026-11-02: openvibe-shared 4.94.0, the Audio chip, the go-live card's labels); 294.6 (2026-11-02: content labels on cards and the player, L1); 294.1 (2026-11-01: the Catch up rails load by themselves as you swipe); 292.6 openvibe-shared 4.70.0 (2026-11-01: the app bar, busy(), skeletons, view transitions); 291.1 with openvibe-shared 4.57.1 (the Dock's async token and scope-aware controls, 4.57.0; the tool frame's facts, 4.56.0) (2026-10-31); 290.6 with the home's two more tab blocks on phones (2026-10-30); 289.8 with the home's Catch up tabs on phones (2026-10-30); 288.2 with openvibe-shared 4.52.0: the Dock's loader and its Chats tab (2026-10-30); 287.4 with openvibe-shared 4.48.0 (the site switcher on the mark, the menu's Start tab and quick tools; Kit's touch hit areas and the phone navbar fix, 4.44-4.47.3); measured 283.2 (2026-10-28: openvibe-shared 4.30.0, the bell center as above); 279.6 (2026-10-28: openvibe-shared 4.27.0, Notifications 2.0 as above); 273.1 (2026-10-28: openvibe-shared 4.25.0 as above); 270.5 (2026-10-28: openvibe-shared 4.22.0, the navbar's search magnifier with / and Ctrl+K and the More menu; search.js and loading.js load only when used); 269.6 (2026-10-28: openvibe-shared 4.19.0, the account menu's gear and people-group icons inline; 268 on 2026-10-27: openvibe-shared 4.16.0, the folded balance chip, Across OpenVibe with site marks and the icon preload in the navbar); 265.3 (2026-10-27: openvibe-shared 4.15.0, the compact footer opens into the whole one, and the pulse line); 263.3 on 10-23 (openvibe-shared 4.9.0, status text twins in every theme); 262.5 on 10-17 (openvibe-shared 4.4.0, every site in the launcher)++ jsRawKB: 1267, // 1266.3 (2026-11-02: openvibe-shared 4.95.0, keyboard-reachable scrollers; the phone Pastes rail); 1262.1 (2026-11-02: openvibe-shared 4.94.0, the Audio chip, the go-live card's labels); 1259.8 (2026-11-02: content labels on cards and the player, L1); 1257.5 (2026-11-01: the Catch up rails load by themselves as you swipe, no Load more on a phone); 1254.2 (2026-11-01: openvibe-shared 4.87.0), about 1255 with #534 (feed and card avatars at their size); 1253.8 (2026-11-01: avatars ask Media for their drawn width, ovImgW); 1252.3 (2026-11-01: Following in the topics row, the picked topic remembered); 1250.2 (2026-11-01: topics live now, readable chat names on light themes); 1247.7 openvibe-shared 4.70.0 (2026-11-01: the app bar, busy(), skeletons, view transitions); 1244.3 with openvibe-shared 4.66.0: the mark with depth and motion, ov-fx loaded on request (2026-10-31); 1243.5 with openvibe-shared 4.64.0: the look travels between sites, the Look panel in the menu (2026-10-31); 1242.7 with openvibe-shared 4.59.0: the Pair mark beside the name, set in the brand face, and the ring on page moves (2026-10-31); 1238.8 with the home's featured stream once and the intro closed on phones (2026-10-31); 1237.4 with the home's two more tab blocks on phones (2026-10-30); 1233.9 with the home's Catch up tabs on phones (2026-10-30); 1230.8 with openvibe-shared 4.53.0: the footer's columns fold on phones (2026-10-30); 1227.8 with openvibe-shared 4.52.0: the Dock's loader and its Chats tab (2026-10-30); 1223.5 with openvibe-shared 4.48.0 (the site switcher on the mark, the menu's Start tab and quick tools; Kit's touch hit areas and the phone navbar fix, 4.44-4.47.3); 1215.4 with openvibe-shared 4.43.0 (room.css carries the kit tokens, 4.39.1; the kit's 4.39.0 rules); measured 1203.9 (2026-10-28: openvibe-shared 4.30.0, the bell center: tabs with counts, the Unread filter, thumbnails, swipe, the phone sheet; 4.31.0's ✦ adds about 3 KB); 1187.2 (2026-10-28: openvibe-shared 4.27.0, Notifications 2.0: opaque themed toasts held while a menu is open, grouping, priority, System cards and the rich bell panel); 1158.8 (2026-10-28: openvibe-shared 4.25.0, the menu's orb, messages, the phone sheet and auto-hide in the navbar; the messenger opens from the bar)++ jsBrotliKB: 296.5, // 296.2 (2026-11-02: openvibe-shared 4.95.0, keyboard-reachable scrollers; the phone Pastes rail); 295.1 (2026-11-02: openvibe-shared 4.94.0, the Audio chip, the go-live card's labels); 294.6 (2026-11-02: content labels on cards and the player, L1); 294.1 (2026-11-01: the Catch up rails load by themselves as you swipe); 292.6 openvibe-shared 4.70.0 (2026-11-01: the app bar, busy(), skeletons, view transitions); 291.1 with openvibe-shared 4.57.1 (the Dock's async token and scope-aware controls, 4.57.0; the tool frame's facts, 4.56.0) (2026-10-31); 290.6 with the home's two more tab blocks on phones (2026-10-30); 289.8 with the home's Catch up tabs on phones (2026-10-30); 288.2 with openvibe-shared 4.52.0: the Dock's loader and its Chats tab (2026-10-30); 287.4 with openvibe-shared 4.48.0 (the site switcher on the mark, the menu's Start tab and quick tools; Kit's touch hit areas and the phone navbar fix, 4.44-4.47.3); measured 283.2 (2026-10-28: openvibe-shared 4.30.0, the bell center as above); 279.6 (2026-10-28: openvibe-shared 4.27.0, Notifications 2.0 as above); 273.1 (2026-10-28: openvibe-shared 4.25.0 as above); 270.5 (2026-10-28: openvibe-shared 4.22.0, the navbar's search magnifier with / and Ctrl+K and the More menu; search.js and loading.js load only when used); 269.6 (2026-10-28: openvibe-shared 4.19.0, the account menu's gear and people-group icons inline; 268 on 2026-10-27: openvibe-shared 4.16.0, the folded balance chip, Across OpenVibe with site marks and the icon preload in the navbar); 265.3 (2026-10-27: openvibe-shared 4.15.0, the compact footer opens into the whole one, and the pulse line); 263.3 on 10-23 (openvibe-shared 4.9.0, status text twins in every theme); 262.5 on 10-17 (openvibe-shared 4.4.0, every site in the launcher)cssRawKB: 270, // measured ~243 since the first-paint subset (style.core.css) replaced style.css (~717 before)cssBrotliKB: 55, // measured ~47.5 (was ~130)};@@@ -49,8 +49,8 @@ check('no tabs and nothing that hides a rail on a phone', () => {check('on a phone each rail is one row that scrolls sideways', () => {const phone = css.slice(css.indexOf('/* Catch up on a phone'));-- assert.match(phone, /#home-catchup \.stream-grid \{[^}]*grid-auto-flow: column;[^}]*overflow-x: auto;[^}]*scroll-snap-type: x mandatory;/);-- assert.match(phone, /#home-catchup \.stream-grid > \* \{ scroll-snap-align: start; min-width: 0; \}/);++ assert.match(phone, /#home-catchup \.stream-grid, #home-catchup \.home-pastes-list \{[^}]*grid-auto-flow: column;[^}]*overflow-x: auto;[^}]*scroll-snap-type: x mandatory;/, 'every rail, Recent Pastes too');++ assert.match(phone, /#home-catchup \.stream-grid > \*, #home-catchup \.home-pastes-list > \* \{ scroll-snap-align: start; min-width: 0; \}/);});check('the changelog preview keeps its full height on a phone', () => {@@@ -104,8 +104,14 @@ function page(overflowX) {// The styles: the tail shows only in a sideways rail, the placeholders keep still for reduced motion, and the density// control's column clamp never squeezes a rail's cards.assert.match(css, /\.home-rail-tail \{ display: none; \}/);-- assert.match(css, /#home-catchup \.stream-grid > \.home-rail-tail \{ display: flex; \}/);++ assert.match(css, /#home-catchup \.stream-grid > \.home-rail-tail, #home-catchup \.home-pastes-list > \.home-rail-tail \{ display: flex; \}/);assert.match(css, /@media \(prefers-reduced-motion: reduce\) \{ \.home-rail-skel \{ animation: none; \} \}/);-- assert.match(css, /#home-catchup \.stream-grid\[data-ovd-cols\] \{ grid-template-columns: none !important; \}/);++ assert.match(css, /#home-catchup \.stream-grid\[data-ovd-cols\], #home-catchup \.home-pastes-list\[data-ovd-cols\] \{ grid-template-columns: none !important; \}/);++ // Recent Pastes rides the same rail on a phone (it was two cards a row with "Load 2 more", 2026-11-02).++ assert.match(css, /#home-catchup \.stream-grid, #home-catchup \.home-pastes-list \{\n\s+display: grid; grid-auto-flow: column;/);++ // A section passed over in a fling is shown: the observer counts "scrolled past", and a pause in scrolling sweeps.++ const fx = fs.readFileSync(path.join(__dirname, '..', 'public', 'js', 'home-fx.js'), 'utf8');++ assert.ok(fx.includes('en.isIntersecting || en.boundingClientRect.bottom < 0'), 'scrolled past counts as seen');++ assert.ok(/window\.addEventListener\('scroll', \(\) => \{\s+clearTimeout\(settle\);/.test(fx), 'a pause in scrolling shows what is still waiting');console.log('home rail autoload: all checks passed');})().catch((e) => { console.error(e); process.exit(1); });
@@ -177,5 +177,5 @@ Minimum `.env`: `BASE_URL`, `JWT_SECRET`, `OV_NETWORK_URL`, `OV_NETWORK_INTERNAL
@@ -177,5 +177,5 @@ Minimum `.env`: `BASE_URL`, `JWT_SECRET`, `OV_NETWORK_URL`, `OV_NETWORK_INTERNAL
<!-- versions:start -->
<!-- versions:start -->
- openvibe-contracts: v0.222.0
- openvibe-contracts: v0.222.0
- openvibe-sdk: v0.81.0
- openvibe-sdk: v0.81.0
-- openvibe-shared: v4.94.0
+- openvibe-shared: v4.95.0
<!-- versions:end -->
<!-- versions:end -->
@@ -7,7 +7,7 @@
@@ -7,7 +7,7 @@
"domain": "openvibe.live (www, ingest, whip)",
"domain": "openvibe.live (www, ingest, whip)",
"contracts": "openvibe-contracts v0.222.0",
"contracts": "openvibe-contracts v0.222.0",
"sdk": "openvibe-sdk v0.81.0",
"sdk": "openvibe-sdk v0.81.0",
- "shared": "openvibe-shared v4.94.0",
+ "shared": "openvibe-shared v4.95.0",
"capabilities": [
"capabilities": [
"live.chat_context.read",
"live.chat_context.read",
"live.chat_effects.write",
"live.chat_effects.write",
@@ -25,7 +25,7 @@
@@ -25,7 +25,7 @@
"onnxruntime-node": "^1.20.0",
"onnxruntime-node": "^1.20.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.222.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.222.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.81.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.81.0",
- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.94.0",
+ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.95.0",
"pg": "^8.23.1",
"pg": "^8.23.1",
"sanitize-html": "^2.17.7",
"sanitize-html": "^2.17.7",
"sdp-transform": "^3.0.0",
"sdp-transform": "^3.0.0",
@@ -2884,9 +2884,9 @@
@@ -2884,9 +2884,9 @@
}
}
},
},
"node_modules/openvibe-shared": {
"node_modules/openvibe-shared": {
- "version": "4.94.0",
- "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.94.0",
- "integrity": "sha512-iMsgL7a5vxouygXsWxQACJrnRubhpe6tnMAKjiJZ0m6Fn+hFcJjQzrI/fERZB3ToC+xK4zO6b6hsm4zK6x4MYg==",
+ "version": "4.95.0",
+ "resolved": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.95.0",
+ "integrity": "sha512-jY0ZKFQMvx3NiyKxHkZ950nq7P8CtlzlP4OOnTkJf0nyVVG93qT4JE0udr8bF8Kwm7FrzkLgfaLB1qDrjH22eg==",
"license": "MIT",
"license": "MIT",
"dependencies": {
"dependencies": {
"jsonwebtoken": "^9.0.0",
"jsonwebtoken": "^9.0.0",
@@ -44,7 +44,7 @@
@@ -44,7 +44,7 @@
"onnxruntime-node": "^1.20.0",
"onnxruntime-node": "^1.20.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.222.0",
"openvibe-contracts": "https://codeload.github.com/OpenVibers/OpenVibe.Contracts/tar.gz/refs/tags/v0.222.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.81.0",
"openvibe-sdk": "https://codeload.github.com/OpenVibers/OpenVibe.SDK/tar.gz/refs/tags/v0.81.0",
- "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.94.0",
+ "openvibe-shared": "https://codeload.github.com/OpenVibers/OpenVibe.Shared/tar.gz/refs/tags/v4.95.0",
"pg": "^8.23.1",
"pg": "^8.23.1",
"sanitize-html": "^2.17.7",
"sanitize-html": "^2.17.7",
"sdp-transform": "^3.0.0",
"sdp-transform": "^3.0.0",
@@ -1332,22 +1332,23 @@ body.egg-rainbow { animation: eggRainbow 2.6s linear; }
@@ -1332,22 +1332,23 @@ body.egg-rainbow { animation: eggRainbow 2.6s linear; }
.home-tabbox [data-panel="network"] .network-hub-header h3 { display: none; }
.home-tabbox [data-panel="network"] .network-hub-header h3 { display: none; }
/* Catch up on a phone: each rail is one row of cards that scrolls sideways, so all five fit in a few screens
/* Catch up on a phone: each rail is one row of cards that scrolls sideways, so all five fit in a few screens
- and nothing is behind a tab. */
- #home-catchup .stream-grid {
+ and nothing is behind a tab. Recent Pastes rides the same rail (2026-11-02): it was two cards a row with a
+ "Load 2 more · 309 left" button under them. */
+ #home-catchup .stream-grid, #home-catchup .home-pastes-list {
display: grid; grid-auto-flow: column; grid-template-columns: none; grid-auto-columns: minmax(232px, 74%); align-items: start;
display: grid; grid-auto-flow: column; grid-template-columns: none; grid-auto-columns: minmax(232px, 74%); align-items: start;
gap: 12px; margin-inline: -16px; padding: 2px 16px 10px; scroll-padding-inline: 16px;
gap: 12px; margin-inline: -16px; padding: 2px 16px 10px; scroll-padding-inline: 16px;
overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory; scrollbar-width: none;
overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory; scrollbar-width: none;
}
}
- #home-catchup .stream-grid::-webkit-scrollbar { display: none; }
+ #home-catchup .stream-grid::-webkit-scrollbar, #home-catchup .home-pastes-list::-webkit-scrollbar { display: none; }
/* ov-density.js reads a sideways rail's implicit columns as "too many" and clamps the grid to repeat(N, minmax(0, 1fr))
/* ov-density.js reads a sideways rail's implicit columns as "too many" and clamps the grid to repeat(N, minmax(0, 1fr))
with !important, which squeezed the first cards to a few pixels (production's Recently Online showed an 81 px
with !important, which squeezed the first cards to a few pixels (production's Recently Online showed an 81 px
sliver, 2026-11-01). A rail has no columns to choose: its own track sizing wins. */
sliver, 2026-11-01). A rail has no columns to choose: its own track sizing wins. */
- #home-catchup .stream-grid[data-ovd-cols] { grid-template-columns: none !important; }
- #home-catchup .stream-grid > * { scroll-snap-align: start; min-width: 0; }
- #home-catchup .stream-grid > .empty-state { grid-column: auto; min-width: calc(100vw - 32px); }
+ #home-catchup .stream-grid[data-ovd-cols], #home-catchup .home-pastes-list[data-ovd-cols] { grid-template-columns: none !important; }
+ #home-catchup .stream-grid > *, #home-catchup .home-pastes-list > * { scroll-snap-align: start; min-width: 0; }
+ #home-catchup .stream-grid > .empty-state, #home-catchup .home-pastes-list > .empty-state { grid-column: auto; min-width: calc(100vw - 32px); }
/* The end of a sideways rail (2026-11-01): placeholder cards where the next ones load by themselves as the reader
/* The end of a sideways rail (2026-11-01): placeholder cards where the next ones load by themselves as the reader
swipes toward them (app-home.js homeRailTail), then one "View all" card once every card is in. */
swipes toward them (app-home.js homeRailTail), then one "View all" card once every card is in. */
- #home-catchup .stream-grid > .home-rail-tail { display: flex; }
+ #home-catchup .stream-grid > .home-rail-tail, #home-catchup .home-pastes-list > .home-rail-tail { display: flex; }
.home-rail-skel {
.home-rail-skel {
flex-direction: column; gap: 10px; padding-bottom: 14px; overflow: hidden;
flex-direction: column; gap: 10px; padding-bottom: 14px; overflow: hidden;
border-radius: 14px; border: 1px solid var(--border); background: var(--bg-card);
border-radius: 14px; border: 1px solid var(--border); background: var(--bg-card);
@@ -111,12 +111,25 @@
@@ -111,12 +111,25 @@
const sweep = () => {
const sweep = () => {
document.querySelectorAll('.hfx-reveal:not(.is-in)').forEach(el => {
document.querySelectorAll('.hfx-reveal:not(.is-in)').forEach(el => {
const r = el.getBoundingClientRect();
const r = el.getBoundingClientRect();
- if (r.height && r.top < window.innerHeight && r.bottom > 0) el.classList.add('is-in');
+ if (r.height && r.top < window.innerHeight) el.classList.add('is-in'); // on screen, or already passed
});
});
revealPasses++;
revealPasses++;
revealSafety = revealPasses < 5 ? setTimeout(sweep, 2000) : 0;
revealSafety = revealPasses < 5 ? setTimeout(sweep, 2000) : 0;
};
};
revealSafety = setTimeout(sweep, 1200);
revealSafety = setTimeout(sweep, 1200);
+ // A fling can carry a section past the screen between two frames, so the observer never reports it, and the
+ // sweeps above stop after ten seconds. When scrolling stops, anything above the bottom of the screen that is
+ // still waiting is shown: one query per pause, never during the scroll.
+ let settle = 0;
+ window.addEventListener('scroll', () => {
+ clearTimeout(settle);
+ settle = setTimeout(() => {
+ document.querySelectorAll('.hfx-reveal:not(.is-in)').forEach(el => {
+ const r = el.getBoundingClientRect();
+ if (r.height && r.top < window.innerHeight) el.classList.add('is-in');
+ });
+ }, 140);
+ }, { passive: true });
}
}
const REVEAL_SEL = '#page-home .section-header, #page-home .stream-card, #page-home .home-cta-banner, #page-home .home-star-section, #page-home .rs-hero-mount, #page-home .pulse-grid > *, #page-home .moments-row > *, #page-home .home-digest';
const REVEAL_SEL = '#page-home .section-header, #page-home .stream-card, #page-home .home-cta-banner, #page-home .home-star-section, #page-home .rs-hero-mount, #page-home .pulse-grid > *, #page-home .moments-row > *, #page-home .home-digest';
@@ -125,7 +138,9 @@
@@ -125,7 +138,9 @@
let lateIo = null;
let lateIo = null;
function attachReveal(roots) {
function attachReveal(roots) {
if (!('IntersectionObserver' in window)) return;
if (!('IntersectionObserver' in window)) return;
- if (!io) io = new IntersectionObserver((entries) => { for (const en of entries) if (en.isIntersecting) { en.target.classList.add('is-in'); io.unobserve(en.target); } }, { rootMargin: '0px 0px -8% 0px', threshold: 0.08 });
+ // Seen, or scrolled past before the observer caught it (a fast swipe): either way it shows. A section passed
+ // over stayed at opacity 0 until the reader came back to it, a blank band on the way down (2026-11-02).
+ if (!io) io = new IntersectionObserver((entries) => { for (const en of entries) if (en.isIntersecting || en.boundingClientRect.bottom < 0) { en.target.classList.add('is-in'); io.unobserve(en.target); } }, { rootMargin: '0px 0px -8% 0px', threshold: 0.08 });
if (!lateIo) lateIo = new IntersectionObserver((entries) => {
if (!lateIo) lateIo = new IntersectionObserver((entries) => {
for (const en of entries) {
for (const en of entries) {
const el = en.target; lateIo.unobserve(el);
const el = en.target; lateIo.unobserve(el);
@@ -22,8 +22,8 @@ const BUDGETS = {
@@ -22,8 +22,8 @@ const BUDGETS = {
htmlRawKB: 128, // 119.3 with the icons drawn on the server (2026-11-01, plan L54 K4: the OpenVibe glyphs in the HTML, 20.8 KB brotli); measured 94.9 before
htmlRawKB: 128, // 119.3 with the icons drawn on the server (2026-11-01, plan L54 K4: the OpenVibe glyphs in the HTML, 20.8 KB brotli); measured 94.9 before
htmlBrotliKB: 30,
htmlBrotliKB: 30,
jsFiles: 26, // measured 23 (incl. route scripts for "/")
jsFiles: 26, // measured 23 (incl. route scripts for "/")
- jsRawKB: 1263, // 1262.1 (2026-11-02: openvibe-shared 4.94.0, the Audio chip, the go-live card's labels); 1259.8 (2026-11-02: content labels on cards and the player, L1); 1257.5 (2026-11-01: the Catch up rails load by themselves as you swipe, no Load more on a phone); 1254.2 (2026-11-01: openvibe-shared 4.87.0), about 1255 with #534 (feed and card avatars at their size); 1253.8 (2026-11-01: avatars ask Media for their drawn width, ovImgW); 1252.3 (2026-11-01: Following in the topics row, the picked topic remembered); 1250.2 (2026-11-01: topics live now, readable chat names on light themes); 1247.7 openvibe-shared 4.70.0 (2026-11-01: the app bar, busy(), skeletons, view transitions); 1244.3 with openvibe-shared 4.66.0: the mark with depth and motion, ov-fx loaded on request (2026-10-31); 1243.5 with openvibe-shared 4.64.0: the look travels between sites, the Look panel in the menu (2026-10-31); 1242.7 with openvibe-shared 4.59.0: the Pair mark beside the name, set in the brand face, and the ring on page moves (2026-10-31); 1238.8 with the home's featured stream once and the intro closed on phones (2026-10-31); 1237.4 with the home's two more tab blocks on phones (2026-10-30); 1233.9 with the home's Catch up tabs on phones (2026-10-30); 1230.8 with openvibe-shared 4.53.0: the footer's columns fold on phones (2026-10-30); 1227.8 with openvibe-shared 4.52.0: the Dock's loader and its Chats tab (2026-10-30); 1223.5 with openvibe-shared 4.48.0 (the site switcher on the mark, the menu's Start tab and quick tools; Kit's touch hit areas and the phone navbar fix, 4.44-4.47.3); 1215.4 with openvibe-shared 4.43.0 (room.css carries the kit tokens, 4.39.1; the kit's 4.39.0 rules); measured 1203.9 (2026-10-28: openvibe-shared 4.30.0, the bell center: tabs with counts, the Unread filter, thumbnails, swipe, the phone sheet; 4.31.0's ✦ adds about 3 KB); 1187.2 (2026-10-28: openvibe-shared 4.27.0, Notifications 2.0: opaque themed toasts held while a menu is open, grouping, priority, System cards and the rich bell panel); 1158.8 (2026-10-28: openvibe-shared 4.25.0, the menu's orb, messages, the phone sheet and auto-hide in the navbar; the messenger opens from the bar)
- jsBrotliKB: 295.5, // 295.1 (2026-11-02: openvibe-shared 4.94.0, the Audio chip, the go-live card's labels); 294.6 (2026-11-02: content labels on cards and the player, L1); 294.1 (2026-11-01: the Catch up rails load by themselves as you swipe); 292.6 openvibe-shared 4.70.0 (2026-11-01: the app bar, busy(), skeletons, view transitions); 291.1 with openvibe-shared 4.57.1 (the Dock's async token and scope-aware controls, 4.57.0; the tool frame's facts, 4.56.0) (2026-10-31); 290.6 with the home's two more tab blocks on phones (2026-10-30); 289.8 with the home's Catch up tabs on phones (2026-10-30); 288.2 with openvibe-shared 4.52.0: the Dock's loader and its Chats tab (2026-10-30); 287.4 with openvibe-shared 4.48.0 (the site switcher on the mark, the menu's Start tab and quick tools; Kit's touch hit areas and the phone navbar fix, 4.44-4.47.3); measured 283.2 (2026-10-28: openvibe-shared 4.30.0, the bell center as above); 279.6 (2026-10-28: openvibe-shared 4.27.0, Notifications 2.0 as above); 273.1 (2026-10-28: openvibe-shared 4.25.0 as above); 270.5 (2026-10-28: openvibe-shared 4.22.0, the navbar's search magnifier with / and Ctrl+K and the More menu; search.js and loading.js load only when used); 269.6 (2026-10-28: openvibe-shared 4.19.0, the account menu's gear and people-group icons inline; 268 on 2026-10-27: openvibe-shared 4.16.0, the folded balance chip, Across OpenVibe with site marks and the icon preload in the navbar); 265.3 (2026-10-27: openvibe-shared 4.15.0, the compact footer opens into the whole one, and the pulse line); 263.3 on 10-23 (openvibe-shared 4.9.0, status text twins in every theme); 262.5 on 10-17 (openvibe-shared 4.4.0, every site in the launcher)
+ jsRawKB: 1267, // 1266.3 (2026-11-02: openvibe-shared 4.95.0, keyboard-reachable scrollers; the phone Pastes rail); 1262.1 (2026-11-02: openvibe-shared 4.94.0, the Audio chip, the go-live card's labels); 1259.8 (2026-11-02: content labels on cards and the player, L1); 1257.5 (2026-11-01: the Catch up rails load by themselves as you swipe, no Load more on a phone); 1254.2 (2026-11-01: openvibe-shared 4.87.0), about 1255 with #534 (feed and card avatars at their size); 1253.8 (2026-11-01: avatars ask Media for their drawn width, ovImgW); 1252.3 (2026-11-01: Following in the topics row, the picked topic remembered); 1250.2 (2026-11-01: topics live now, readable chat names on light themes); 1247.7 openvibe-shared 4.70.0 (2026-11-01: the app bar, busy(), skeletons, view transitions); 1244.3 with openvibe-shared 4.66.0: the mark with depth and motion, ov-fx loaded on request (2026-10-31); 1243.5 with openvibe-shared 4.64.0: the look travels between sites, the Look panel in the menu (2026-10-31); 1242.7 with openvibe-shared 4.59.0: the Pair mark beside the name, set in the brand face, and the ring on page moves (2026-10-31); 1238.8 with the home's featured stream once and the intro closed on phones (2026-10-31); 1237.4 with the home's two more tab blocks on phones (2026-10-30); 1233.9 with the home's Catch up tabs on phones (2026-10-30); 1230.8 with openvibe-shared 4.53.0: the footer's columns fold on phones (2026-10-30); 1227.8 with openvibe-shared 4.52.0: the Dock's loader and its Chats tab (2026-10-30); 1223.5 with openvibe-shared 4.48.0 (the site switcher on the mark, the menu's Start tab and quick tools; Kit's touch hit areas and the phone navbar fix, 4.44-4.47.3); 1215.4 with openvibe-shared 4.43.0 (room.css carries the kit tokens, 4.39.1; the kit's 4.39.0 rules); measured 1203.9 (2026-10-28: openvibe-shared 4.30.0, the bell center: tabs with counts, the Unread filter, thumbnails, swipe, the phone sheet; 4.31.0's ✦ adds about 3 KB); 1187.2 (2026-10-28: openvibe-shared 4.27.0, Notifications 2.0: opaque themed toasts held while a menu is open, grouping, priority, System cards and the rich bell panel); 1158.8 (2026-10-28: openvibe-shared 4.25.0, the menu's orb, messages, the phone sheet and auto-hide in the navbar; the messenger opens from the bar)
+ jsBrotliKB: 296.5, // 296.2 (2026-11-02: openvibe-shared 4.95.0, keyboard-reachable scrollers; the phone Pastes rail); 295.1 (2026-11-02: openvibe-shared 4.94.0, the Audio chip, the go-live card's labels); 294.6 (2026-11-02: content labels on cards and the player, L1); 294.1 (2026-11-01: the Catch up rails load by themselves as you swipe); 292.6 openvibe-shared 4.70.0 (2026-11-01: the app bar, busy(), skeletons, view transitions); 291.1 with openvibe-shared 4.57.1 (the Dock's async token and scope-aware controls, 4.57.0; the tool frame's facts, 4.56.0) (2026-10-31); 290.6 with the home's two more tab blocks on phones (2026-10-30); 289.8 with the home's Catch up tabs on phones (2026-10-30); 288.2 with openvibe-shared 4.52.0: the Dock's loader and its Chats tab (2026-10-30); 287.4 with openvibe-shared 4.48.0 (the site switcher on the mark, the menu's Start tab and quick tools; Kit's touch hit areas and the phone navbar fix, 4.44-4.47.3); measured 283.2 (2026-10-28: openvibe-shared 4.30.0, the bell center as above); 279.6 (2026-10-28: openvibe-shared 4.27.0, Notifications 2.0 as above); 273.1 (2026-10-28: openvibe-shared 4.25.0 as above); 270.5 (2026-10-28: openvibe-shared 4.22.0, the navbar's search magnifier with / and Ctrl+K and the More menu; search.js and loading.js load only when used); 269.6 (2026-10-28: openvibe-shared 4.19.0, the account menu's gear and people-group icons inline; 268 on 2026-10-27: openvibe-shared 4.16.0, the folded balance chip, Across OpenVibe with site marks and the icon preload in the navbar); 265.3 (2026-10-27: openvibe-shared 4.15.0, the compact footer opens into the whole one, and the pulse line); 263.3 on 10-23 (openvibe-shared 4.9.0, status text twins in every theme); 262.5 on 10-17 (openvibe-shared 4.4.0, every site in the launcher)
cssRawKB: 270, // measured ~243 since the first-paint subset (style.core.css) replaced style.css (~717 before)
cssRawKB: 270, // measured ~243 since the first-paint subset (style.core.css) replaced style.css (~717 before)
cssBrotliKB: 55, // measured ~47.5 (was ~130)
cssBrotliKB: 55, // measured ~47.5 (was ~130)
};
};
@@ -49,8 +49,8 @@ check('no tabs and nothing that hides a rail on a phone', () => {
@@ -49,8 +49,8 @@ check('no tabs and nothing that hides a rail on a phone', () => {
check('on a phone each rail is one row that scrolls sideways', () => {
check('on a phone each rail is one row that scrolls sideways', () => {
const phone = css.slice(css.indexOf('/* Catch up on a phone'));
const phone = css.slice(css.indexOf('/* Catch up on a phone'));
- assert.match(phone, /#home-catchup \.stream-grid \{[^}]*grid-auto-flow: column;[^}]*overflow-x: auto;[^}]*scroll-snap-type: x mandatory;/);
- assert.match(phone, /#home-catchup \.stream-grid > \* \{ scroll-snap-align: start; min-width: 0; \}/);
+ assert.match(phone, /#home-catchup \.stream-grid, #home-catchup \.home-pastes-list \{[^}]*grid-auto-flow: column;[^}]*overflow-x: auto;[^}]*scroll-snap-type: x mandatory;/, 'every rail, Recent Pastes too');
+ assert.match(phone, /#home-catchup \.stream-grid > \*, #home-catchup \.home-pastes-list > \* \{ scroll-snap-align: start; min-width: 0; \}/);
});
});
check('the changelog preview keeps its full height on a phone', () => {
check('the changelog preview keeps its full height on a phone', () => {
@@ -104,8 +104,14 @@ function page(overflowX) {
@@ -104,8 +104,14 @@ function page(overflowX) {
// The styles: the tail shows only in a sideways rail, the placeholders keep still for reduced motion, and the density
// The styles: the tail shows only in a sideways rail, the placeholders keep still for reduced motion, and the density
// control's column clamp never squeezes a rail's cards.
// control's column clamp never squeezes a rail's cards.
assert.match(css, /\.home-rail-tail \{ display: none; \}/);
assert.match(css, /\.home-rail-tail \{ display: none; \}/);
- assert.match(css, /#home-catchup \.stream-grid > \.home-rail-tail \{ display: flex; \}/);
+ assert.match(css, /#home-catchup \.stream-grid > \.home-rail-tail, #home-catchup \.home-pastes-list > \.home-rail-tail \{ display: flex; \}/);
assert.match(css, /@media \(prefers-reduced-motion: reduce\) \{ \.home-rail-skel \{ animation: none; \} \}/);
assert.match(css, /@media \(prefers-reduced-motion: reduce\) \{ \.home-rail-skel \{ animation: none; \} \}/);
- assert.match(css, /#home-catchup \.stream-grid\[data-ovd-cols\] \{ grid-template-columns: none !important; \}/);
+ assert.match(css, /#home-catchup \.stream-grid\[data-ovd-cols\], #home-catchup \.home-pastes-list\[data-ovd-cols\] \{ grid-template-columns: none !important; \}/);
+ // Recent Pastes rides the same rail on a phone (it was two cards a row with "Load 2 more", 2026-11-02).
+ assert.match(css, /#home-catchup \.stream-grid, #home-catchup \.home-pastes-list \{\n\s+display: grid; grid-auto-flow: column;/);
+ // A section passed over in a fling is shown: the observer counts "scrolled past", and a pause in scrolling sweeps.
+ const fx = fs.readFileSync(path.join(__dirname, '..', 'public', 'js', 'home-fx.js'), 'utf8');
+ assert.ok(fx.includes('en.isIntersecting || en.boundingClientRect.bottom < 0'), 'scrolled past counts as seen');
+ assert.ok(/window\.addEventListener\('scroll', \(\) => \{\s+clearTimeout\(settle\);/.test(fx), 'a pause in scrolling shows what is still waiting');
console.log('home rail autoload: all checks passed');
console.log('home rail autoload: all checks passed');
})().catch((e) => { console.error(e); process.exit(1); });
})().catch((e) => { console.error(e); process.exit(1); });