The Shorts feed used to emit one <video id="sv-{idx}"> per short. With
60 shorts, that was 60 HTMLMediaElement allocations even though only
one plays at a time — bandwidth was bounded by preload="none" but the
DOM shape was still N:1.
Replace with the YT-parity architecture:
- One #svGlobal <video> rendered once at the end of the feed. The
IntersectionObserver docks it into the active .short-player-wrap on
entry and sets its src from the slot's data-src. Browsers preserve
the active media context across node moves so playback doesn't
restart just because we re-parented the node.
- Per-slot .short-poster shim keeps the slot filled with the video's
thumbnail while the shared player is docked elsewhere; the slot
never goes blank between swaps.
- Two #svPre1 / #svPre2 preloaders park at the end of the DOM and get
their src set to the NEXT one and two shorts on each dock. preload=
"metadata" grabs the moov atom + first keyframe only — enough that
the switch to playback is instant, cheap enough that we can run two.
- The <video>'s single timeupdate listener now updates the
.short-progress-fill of whichever slot it's currently docked in,
found via video.parentElement.id.replace('wrap-', '').
- toggleMute now mutes the shared video directly instead of looking
up the no-longer-existent sv-{idx} by id.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Previous commit added the HTML + CSS for the comments pane but the JS
handlers only landed in the first (markup) Edit. This drops the two
window.short*Comments functions into the IIFE so the onclick handlers
in the markup actually resolve.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
The comments icon on each Short used to open the full /videos/{id}
page, kicking the viewer out of the vertical feed. Now it opens a
shared side drawer on desktop (right edge, 420px wide, starts below
the header) or a bottom sheet on mobile (70vh, slides up from the
bottom nav), without leaving the feed.
Content is the same resources/views/components/video-comments
section rendered on the watch page — fetched as XHR and the whole
#ytcSection node is lifted into the pane. All the existing comment
features (replies, likes, translate, heart/pin, permalinks) work
identically because we're reusing the exact same DOM.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
A11y:
- Skip-to-content link lands first in the body and jumps to #main
past the header + sidebar for keyboard users.
- aria-label on the icon buttons that previously carried only an
icon: hamburger menu (+ aria-controls="sidebar"), mobile search
toggle, account menu (also drops the duplicate alt on the avatar
since the button name already speaks the user's name).
Admin:
- Dashboard stat card renamed "Live Videos" → "Ready" (matches the
DB status column; nothing on this card is actually live).
Settings:
- Duplicate "Prefer not to say" option on the Gender select — the
empty placeholder shared the same label as the real option.
Placeholder is now "Select…"; the real "Prefer not to say" option
stays unchanged.
- Birthday picker caps the Year dropdown at (this year − 13) and
the server-side register validation requires the same, so a
client bypass can't let a <13 user through.
Titles:
- Admin layout uses "{Page} | TAKEONE" to match the frontend format
(was "{Page} — TAKEONE"). User pages that said "| TAKEONE" literal
now interpolate config('app.name'). Shorts and Welcome moved from
" - " to " | " separator.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
- New route /shorts/{video} opens the feed scrolled to that short.
Controller aborts 404 when the id doesn't resolve to a short or
isn't viewable by the current viewer, so bad links land on the
branded 404 (added in the next commit) rather than loading an
empty feed.
- The IntersectionObserver that detects the active short now
history.replaceState()s the URL to /shorts/{id} so copy-paste of
the address bar works, without pushing a navigation entry — the
back button still exits the feed in one step.
- Mute state is persisted in localStorage (shortsMuted = '0' | '1')
so unmuting once sticks across sessions. Default remains muted
to satisfy autoplay policies on first load.
- Mouse-wheel navigation moves one short per gesture with a 450 ms
debounce. Trackpad flicks no longer skip five shorts at once.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
- Installed p7h/nas-file-manager package via private VCS repo
- Published config/nas-file-manager.php with super_admin middleware restriction
- Added NAS env vars to .env.example
- Created admin/nas-storage page with connection info panel and file browser widget
- Added NAS Storage link to admin sidebar (super_admin only)
- Added SuperAdminController@nasStorage method and admin.nas-storage route
- Includes all accumulated branch changes: profile wall, 2FA, audit logs,
settings panel, country/phone/timezone components, posts, slideshow,
playlist shares, video downloads/shares, comment likes, notifications,
social links, and more
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>