Skip to content

[mobileWallLayout] Add play-on-visibility and ordered loading#704

Merged
DogmaDragon merged 2 commits intostashapp:mainfrom
speckofthecosmos:mobilewalllayout-scrollfeed
Apr 22, 2026
Merged

[mobileWallLayout] Add play-on-visibility and ordered loading#704
DogmaDragon merged 2 commits intostashapp:mainfrom
speckofthecosmos:mobilewalllayout-scrollfeed

Conversation

@speckofthecosmos
Copy link
Copy Markdown
Contributor

Summary

Two mobile-first behaviors on top of the existing layout fix, and a
display-name rebrand to scrollFeed to reflect the broader feature set.

  • Play-on-visibility. An IntersectionObserver plays each <video> at
    10% visibility and pauses it when it leaves the viewport. Concurrent
    playback caps at 2–3, which keeps iOS Safari comfortably under its
    ~20-simultaneous-<video> decoder ceiling. On a 20-card wall page
    (Stash's minimum per-page size), the unchanged plugin leaves every
    preview autoplay firing at once — this PR fixes that.
  • DOM-ordered load queue. On page mount, Stash fires parallel fetches
    for every <video src>. Over cellular that splits the uplink 20 ways
    and no video is playable for many seconds. The queue cancels those
    fetches via removeAttribute('src') + video.load() and re-issues them
    top-down, 2 at a time. Advances on canplay or a 500ms fallback — the
    top clip is playable fast on cellular, and the whole page is in-flight
    within ~5 seconds so moving into a weaker-signal area doesn't leave the
    bottom of the page with zero bytes.
  • Rebrand. Display name in the YAML is now scrollFeed with an
    updated description. The plugin ID stays mobileWallLayout so existing
    installs upgrade cleanly.

Internals

  • File wrapped in an IIFE to keep top-level identifiers out of global
    scope (Stash loads all UI plugins into the same document).
  • URL matching uses window.location.pathname (exact match on /images
    and /scenes/markers) rather than href.includes.
  • Stale-timer safety: beginLoading captures the current _loading Set
    in its closure so any setTimeout advance that fires after
    deactivateVideoBehavior nulls plugin state detects the mismatch and
    no-ops.
  • All non-iteration references use WeakMap/WeakSet so video GC isn't
    blocked when React unmounts elements.

Tuning knobs

Constants at the top of the load-queue section:

Constant Default Effect
threshold (IntersectionObserver) 0.1 Lower = more continuous scroll; higher = stricter per-clip focus.
_MAX_CONCURRENT_LOADS 2 Higher = full-page finishes sooner; lower = top clips get more bandwidth.
_LOAD_ADVANCE_MS 500 Short = tail starts fetching sooner; long = top clips get more solo time.

Test plan

  • iPhone 16 Pro Max against a home-NAS Stash instance over remote
    cellular: 20-card marker wall plays 2–3 concurrent, top video canplay
    in ~1s, whole page in-flight by ~5s, scroll to video renamerOnUpdate: segment config options into different file #18 shows bytes
    already accumulating.
  • Airplane-mode mid-scroll: already-loaded clips continue playing;
    entering a not-yet-loaded clip shows a queued state and resumes once
    back online.
  • Navigate away from /scenes/markers and back: observers tear down
    and re-attach cleanly, no leaked style tag or decoder stampede.
  • validator/validate.js passes locally; YAML schema-valid.

Internal plugin ID is unchanged (mobileWallLayout), so users with the
current published plugin will transparently upgrade.

Adds two mobile-first behaviors to the existing layout plugin and
rebrands the display name to "scrollFeed":

- IntersectionObserver gates <video> play/pause on 10% visibility.
  Caps concurrent playbacks to ~3, well under iOS Safari's
  ~20-simultaneous-<video> ceiling that the unchanged Stash wall
  hits on a 20-card page.

- A DOM-ordered load queue cancels the parallel-fetch storm Stash
  kicks off when all wall cards mount at once. Top clips get
  uncontested bandwidth first, and a 500ms timeout advance ensures
  the full page is in-flight within ~5s so degrading reception
  doesn't strand the bottom of the page with zero bytes.

The plugin's internal id stays mobileWallLayout so existing
installs upgrade cleanly. The whole file is wrapped in an IIFE
to avoid top-level name collisions with other plugins loaded
into the same document.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment thread plugins/mobileWallLayout/mobileWallLayout.yml
Comment thread plugins/mobileWallLayout/README.md
@DogmaDragon DogmaDragon added the type:plugin Plugins label Apr 21, 2026
The scrollFeed rebrand inadvertently repointed the YAML url: field to a
GitHub tree URL and dropped the discourse link from the top of the README.
Every other plugin in this repo uses the discourse thread as its url: value
(it's what the Stash plugins panel surfaces as the plugin's support
link), so restoring the original discourse URL here keeps the convention
and keeps existing users linked to the plugin's discussion thread.
@speckofthecosmos
Copy link
Copy Markdown
Contributor Author

Apologies — the scrollFeed rebrand silently dropped the discourse URL from two places: the url: field in mobileWallLayout.yml was repointed to a GitHub tree URL, and the discourse link was removed from the top of the README. That breaks the convention every other plugin in this repo follows (the url: field is what the Stash Plugins panel surfaces as the support link), and it was my oversight.

To be upfront: this PR was drafted with AI assistance (Claude Opus 4.7 — noted in the first commit's Co-Authored-By trailer). The rebrand/rewrite step is where the discourse URL was silently dropped, and I did not catch it on my review.

Just pushed b6ad2e3 restoring both:

  • mobileWallLayout.ymlurl: https://discourse.stashapp.cc/t/mobile-wall-layout/6160
  • README → Discussion: link at the top

Adding a pre-PR check to my own routine so the url: field gets verified against the discourse convention before any future CommunityScripts plugin PR I open.

@DogmaDragon DogmaDragon merged commit afc8208 into stashapp:main Apr 22, 2026
1 check passed
@discourse-stashapp
Copy link
Copy Markdown

This pull request has been mentioned on Stash Forum. There might be relevant details there:

https://discourse.stashapp.cc/t/mobile-wall-layout/6160/3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants