Skip to content

feat(featured-stream): mobile flick-to-dismiss - #4673

Merged
evanpelle merged 1 commit into
openfrontio:mainfrom
Zixer1:feat/featured-stream-mobile-dismiss
Jul 23, 2026
Merged

feat(featured-stream): mobile flick-to-dismiss#4673
evanpelle merged 1 commit into
openfrontio:mainfrom
Zixer1:feat/featured-stream-mobile-dismiss

Conversation

@Zixer1

@Zixer1 Zixer1 commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

What

On touch devices, dragging the featured-stream panel off the edge of the screen dismisses it for the current page visit. Desktop is unchanged: the same drag still snaps to the nearest corner.

Why

On small screens the panel can get in the way. This gives mobile users a quick "flick it away" gesture to hide it, without a persistent opt-out they might set once and forget.

Behavior

  • Touch only, gated on matchMedia("(pointer: coarse)"). Mouse users keep corner-snap.
  • On drag release, if the panel's center has left the viewport (more than half off-screen), it is dismissed.
  • Not persisted (in-memory), so a refresh or the next visit brings the panel back.
  • Dismiss tears down the Twitch player and stops the offline re-probe, so nothing keeps streaming behind a hidden panel, and leaving a game does not resurrect it.

Tests

Added unit coverage for the pure isOffFrame helper. Existing FeaturedStream tests pass.

Follow-up to #4335 (merged).

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 149a2f03-f644-4212-9c27-5333b086a8c1

📥 Commits

Reviewing files that changed from the base of the PR and between 13ee1f0 and eae5573.

📒 Files selected for processing (2)
  • src/client/FeaturedStream.ts
  • tests/client/components/FeaturedStream.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/client/components/FeaturedStream.test.ts
  • src/client/FeaturedStream.ts

Walkthrough

FeaturedStream now supports touch flick-to-dismiss behavior. Dismissal lasts for the current page visit, removes the panel, tears down Twitch playback, and prevents later remounting or re-probing. The viewport helper and boundary behavior are tested.

Changes

Featured stream dismissal

Layer / File(s) Summary
Dismissed lifecycle
src/client/FeaturedStream.ts
Adds page-visit dismissal state, prevents player mounting and lobby re-probing, tears down the Twitch player, resets canceled drags, and renders no output after dismissal.
Flick detection and trigger
src/client/FeaturedStream.ts, tests/client/components/FeaturedStream.test.ts
Adds coarse-pointer off-frame detection for drag dismissal and tests viewport boundary behavior.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant FeaturedStream
  participant TwitchPlayer
  User->>FeaturedStream: Drag panel beyond viewport edge
  FeaturedStream->>FeaturedStream: Check isOffFrame
  FeaturedStream->>FeaturedStream: Dismiss panel
  FeaturedStream->>TwitchPlayer: Tear down player
  FeaturedStream-->>User: Render no panel
Loading

Possibly related PRs

Suggested labels: Feature

Poem

A stream drifts toward the screen’s edge,
One little flick fulfills the pledge.
Twitch signs off, the panel flies,
Quiet space beneath clear skies. 🌤️

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the new mobile flick-to-dismiss behavior in FeaturedStream.
Description check ✅ Passed The description matches the changes and explains the touch-only dismissal, non-persistent behavior, and tests.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/client/FeaturedStream.ts`:
- Around line 335-342: Update the pointer event wiring so pointer cancellation
no longer invokes onDragUp(). Add a dedicated cancel handler that only clears
the active drag state, without running dismiss or stream-opening logic, while
preserving onDragUp() for normal pointer releases.
- Around line 356-367: Update dismiss() to invalidate callbacks from the current
player before or during teardown, either by incrementing mountGen or ensuring
callbacks reject when dismissed. Preserve the existing timer cleanup and
teardownPlayer behavior so delayed fresh() callbacks cannot return true or
recreate recheckTimer after dismissal.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 02edf5a2-9c5d-4a57-ba7d-7d0e83de0118

📥 Commits

Reviewing files that changed from the base of the PR and between ebd22af and 69fcf08.

📒 Files selected for processing (2)
  • src/client/FeaturedStream.ts
  • tests/client/components/FeaturedStream.test.ts

Comment thread src/client/FeaturedStream.ts
Comment thread src/client/FeaturedStream.ts
@github-project-automation github-project-automation Bot moved this from Triage to Development in OpenFront Release Management Jul 22, 2026
@Zixer1
Zixer1 force-pushed the feat/featured-stream-mobile-dismiss branch from 69fcf08 to 13ee1f0 Compare July 22, 2026 20:58
@Zixer1 Zixer1 added this to the v33 milestone Jul 22, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 22, 2026
evanpelle
evanpelle previously approved these changes Jul 23, 2026
@github-project-automation github-project-automation Bot moved this from Development to Final Review in OpenFront Release Management Jul 23, 2026
On touch devices, dragging the featured-stream panel off the edge of the
screen hides it for the current page visit. Not persisted, so it returns
on the next load or refresh. Desktop is unchanged (the same drag still
snaps to the nearest corner).

Dismiss tears down the Twitch player and stops re-probing, so nothing keeps
streaming behind a hidden panel, and leaving a game won't resurrect it.
@Zixer1
Zixer1 dismissed stale reviews from evanpelle and coderabbitai[bot] via eae5573 July 23, 2026 19:56
@Zixer1
Zixer1 force-pushed the feat/featured-stream-mobile-dismiss branch from 13ee1f0 to eae5573 Compare July 23, 2026 19:56
@evanpelle
evanpelle merged commit 741ab0f into openfrontio:main Jul 23, 2026
9 checks passed
@github-project-automation github-project-automation Bot moved this from Final Review to Complete in OpenFront Release Management Jul 23, 2026
evanpelle pushed a commit that referenced this pull request Jul 23, 2026
On touch devices, dragging the featured-stream panel off the edge of the
screen dismisses it for the current page visit. Desktop is unchanged:
the same drag still snaps to the nearest corner, exactly as today.

On small screens the panel can get in the way. This gives mobile users a
quick, familiar "flick it away" gesture to hide it, without a persistent
opt-out they might set once and forget.

- **Touch only**, gated on `matchMedia("(pointer: coarse)")`. Mouse
users keep corner-snap.
- **Trigger:** on drag release, if the panel's center has left the
viewport (more than half of it is off-screen), it is dismissed.
- **Not persisted.** Dismiss is in-memory only, so a refresh or the next
visit brings the panel back. It's a "not now", not a permanent hide.
- Dismiss tears down the Twitch player and stops the offline re-probe,
so nothing keeps streaming behind a hidden panel, and leaving a game
does not resurrect it.

Added unit coverage for the new pure `isOffFrame(cx, cy, vw, vh)` helper
(inside the viewport vs past each edge). Existing FeaturedStream tests
still pass.

Follow-up to #4335 (now merged).
@Zixer1 Zixer1 changed the title feat(featured-stream): mobile flick-to-dismiss feat(featured-stream): mobile dismiss, off-web exclusion, ad-free close button Jul 23, 2026
@Zixer1 Zixer1 changed the title feat(featured-stream): mobile dismiss, off-web exclusion, ad-free close button feat(featured-stream): mobile flick-to-dismiss Jul 23, 2026
evanpelle pushed a commit that referenced this pull request Jul 24, 2026
… lobby wait (#4698)

Three related changes to the homepage featured-stream panel.

## 1. Exclude the embed off the open web (ToS)
Never mount the Twitch embed on **CrazyGames** or the **desktop (Steam)
shell**, and never load the Twitch SDK there. Matches how the app
already suppresses its own promos off-web via `window.adsEnabled`:

- **CrazyGames:** [only SDK-served ads are
allowed](https://docs.crazygames.com/requirements/ads/) and no external
cross-promotion; a Twitch embed serves Twitch's own ads and is
third-party content.
- **Steam:** Steam [does not support advertising models in
games](https://partner.steamgames.com/doc/marketing/advertising); a live
Twitch player carries Twitch ad breaks, and the desktop shell can't
satisfy Twitch's `parent`-domain requirement.

## 2. Close button for ad-free users
Ad-free users (any shop purchase makes a user `adfree` for life, which
zeroes `window.adsEnabled`) get an `×` in the minimized bar. The close
is remembered **for the current day** (the day is stored in
`localStorage`), so the panel stays gone across reloads that day and
resets for the next day's stream. Ad-supported users keep minimize only;
their mobile flick stays session-only. The minimized state is scoped to
the day the same way.

## 3. Keep the panel through the lobby wait
The panel used to hide the moment you joined a lobby (`join-lobby`). Now
it stays up through the **queue/lobby wait** and hides only once the
game actually starts. `Main.ts` dispatches a new `game-starting` event
at `prestart` (the real start moment); the panel hides on that instead
of on `join-lobby`, and reappears on `leave-lobby`.

> Heads-up for maintainers: (1) and (2) couple this OFM widget to OF's
own ad/entitlement signals (`crazyGamesSDK.isOnCrazyGames()`,
`isDesktopShell()`, `window.adsEnabled`); (3) adds a small shared
`game-starting` document event in `Main.ts`. Flagging in case you'd
rather gate/signal differently.

## Tests
Verified locally: prettier, eslint, tsc, tests all green. Reuses the
existing `common.close` i18n key (no locale-file changes).

Follow-up to #4335 / #4673. Sizing (Twitch's 400×300 minimum) landed in
#4696.
evanpelle pushed a commit that referenced this pull request Jul 25, 2026
… lobby wait (#4698)

Three related changes to the homepage featured-stream panel.

## 1. Exclude the embed off the open web (ToS)
Never mount the Twitch embed on **CrazyGames** or the **desktop (Steam)
shell**, and never load the Twitch SDK there. Matches how the app
already suppresses its own promos off-web via `window.adsEnabled`:

- **CrazyGames:** [only SDK-served ads are
allowed](https://docs.crazygames.com/requirements/ads/) and no external
cross-promotion; a Twitch embed serves Twitch's own ads and is
third-party content.
- **Steam:** Steam [does not support advertising models in
games](https://partner.steamgames.com/doc/marketing/advertising); a live
Twitch player carries Twitch ad breaks, and the desktop shell can't
satisfy Twitch's `parent`-domain requirement.

## 2. Close button for ad-free users
Ad-free users (any shop purchase makes a user `adfree` for life, which
zeroes `window.adsEnabled`) get an `×` in the minimized bar. The close
is remembered **for the current day** (the day is stored in
`localStorage`), so the panel stays gone across reloads that day and
resets for the next day's stream. Ad-supported users keep minimize only;
their mobile flick stays session-only. The minimized state is scoped to
the day the same way.

## 3. Keep the panel through the lobby wait
The panel used to hide the moment you joined a lobby (`join-lobby`). Now
it stays up through the **queue/lobby wait** and hides only once the
game actually starts. `Main.ts` dispatches a new `game-starting` event
at `prestart` (the real start moment); the panel hides on that instead
of on `join-lobby`, and reappears on `leave-lobby`.

> Heads-up for maintainers: (1) and (2) couple this OFM widget to OF's
own ad/entitlement signals (`crazyGamesSDK.isOnCrazyGames()`,
`isDesktopShell()`, `window.adsEnabled`); (3) adds a small shared
`game-starting` document event in `Main.ts`. Flagging in case you'd
rather gate/signal differently.

## Tests
Verified locally: prettier, eslint, tsc, tests all green. Reuses the
existing `common.close` i18n key (no locale-file changes).

Follow-up to #4335 / #4673. Sizing (Twitch's 400×300 minimum) landed in
#4696.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Complete

Development

Successfully merging this pull request may close these issues.

2 participants