Skip to content

feat(widget): add opt-in overlay queue ticker (WW-42) - #390

Merged
nathanialhenniges merged 2 commits into
mainfrom
claude/ticket-triage-selection-cf96e3
Aug 5, 2026
Merged

feat(widget): add opt-in overlay queue ticker (WW-42)#390
nathanialhenniges merged 2 commits into
mainfrom
claude/ticket-triage-selection-cf96e3

Conversation

@nathanialhenniges

@nathanialhenniges nathanialhenniges commented Aug 4, 2026

Copy link
Copy Markdown
Member

Summary

  • Opt-in ?queueTicker=1 overlay panel showing the next 3 song requests (title + requester), off by default so no existing streamer's OBS Browser Source changes on upgrade
  • New queue_upcoming WebSocket broadcast (WebSocketServerService), capped at 3 items, replayed on connect
  • SongRequestQueue.upcoming(limit:): prefix read of the already fair-share-ordered queue
  • Widget panel is independent of the now-playing card/layout, themed via existing ThemePreset tokens (no new design-system keys needed)

Jira

  • WW-42: implemented. Its stated "Depends on: WW-37" was stale — WW-37 has zero code in the repo — confirmed unblocked, commented on the ticket, built directly.
  • WW-51: Jira hygiene only, no repo changes. Commented on WW-45 flagging its stale "blocked by WW-36" link (needs manual removal in the Jira UI, no API verb available for it) and on WW-51 itself with the close-ritual/automation-rule writeup.

Test plan

  • SongRequestQueueTests — 4 new tests (empty/cap/default-limit/fair-share-order)
  • WebSocketServerIntegrationTests — 2 new tests (snapshot replay on connect, default-empty-array)
  • Full targeted suite: 53/53 passing
  • bunx tsc --noEmit clean on apps/widget
  • bun run --filter widget build — regenerated widget.html committed, diff is clean (only the changed inline CSS/JS lines + new HTML block)
  • Manual: verified in Browser pane — ticker hidden by default, ?queueTicker=1 renders rows + empty state correctly across themes ("Default", "Glass"), no console errors
  • Not yet verified against a live native app instance (Music.app + real Twitch queue) — no tooling available in this session to drive the actual macOS app end-to-end

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added an optional queue ticker overlay for the now-playing widget.
    • Enable it with ?queueTicker=1 to display up to three upcoming song requests, including titles and requesters.
    • The ticker follows the selected widget theme and updates as the queue changes.
    • Empty queues display an appropriate empty state.
  • Documentation

    • Added setup and usage guidance for the queue ticker and its URL parameter.

Shows the next 3 song requests (title + requester) on the OBS overlay
so viewers see their spot in line. New `queue_upcoming` WebSocket
broadcast, capped at 3 items and replayed on connect so a Browser
Source reload never sits on a stale ticker.

- SongRequestQueue.upcoming(limit:): plain prefix read, queue is
  already fair-share ordered at insert time
- WebSocketServerService: queue_upcoming payload/broadcast/send-to-one,
  joins the existing songRequestQueueChanged trigger in
  broadcastStreamDeckState()
- widget.ts/html/css: independent `?queueTicker=1` panel, off by
  default so no existing streamer's OBS scene changes on upgrade,
  themed via existing ThemePreset tokens (no new design-system keys)
- Tests: 4 new SongRequestQueueTests, 2 new WebSocketServerIntegrationTests
- Docs: widget.mdx, README, features.mdx, CHANGELOG.md + changelog.mdx

The ticket's stated "Depends on: WW-37" was stale (WW-37 has zero
code in the repo); confirmed unblocked and built directly.

Also files Jira comments on WW-45/WW-42/WW-51 flagging a stale
"blocked by WW-36" link and the WW-37 dependency claim above (no
repo changes for that half, WW-51 is Jira hygiene only).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@nathanialhenniges, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 52 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ad6a0e27-3102-4b71-b561-a2a4a85ffd50

📥 Commits

Reviewing files that changed from the base of the PR and between 784512a and 7aed63a.

📒 Files selected for processing (4)
  • apps/docs/content/docs/widget.mdx
  • apps/native/WolfWave/Resources/widget.html
  • apps/widget/src/widget.css
  • apps/widget/src/widget.ts

Walkthrough

The change adds an opt-in queue ticker overlay. The native service publishes up to three upcoming requests through WebSocket snapshots. The widget renders titles and requesters with theme-aware styling, empty-state handling, escaping, and reduced-motion support.

Changes

Queue ticker overlay

Layer / File(s) Summary
Queue selection and limits
apps/native/WolfWave/Core/AppConstants.swift, apps/native/WolfWave/Services/SongRequest/SongRequestQueue.swift, apps/native/WolfWaveTests/SongRequestQueueTests.swift
The queue exposes an order-preserving upcoming(limit:) method with a default maximum of three items. Tests cover limits, empty queues, and ordering.
Queue snapshot delivery
apps/native/WolfWave/Services/WebSocket/WebSocketServerService.swift, apps/native/WolfWave/Core/AppDelegate+StreamDeck.swift, apps/native/WolfWaveTests/WebSocketServerIntegrationTests.swift
The application publishes queue_upcoming snapshots, caches the latest state, and replays it to new WebSocket connections. Integration tests cover populated and empty snapshots.
Widget ticker rendering
apps/widget/src/widget.ts, apps/widget/src/widget.html, apps/widget/src/widget.css, apps/native/WolfWave/Resources/widget.html
The widget enables the ticker with queueTicker=1, renders up to three requests or an empty state, escapes displayed values, follows widget configuration, and updates with queue messages.
Queue ticker documentation
CHANGELOG.md, README.md, apps/docs/content/docs/changelog.mdx, apps/docs/content/docs/features.mdx, apps/docs/content/docs/widget.mdx
The documentation describes the URL parameter, WebSocket message, display behavior, empty state, and theme handling.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant SongRequestQueue
  participant AppDelegate
  participant WebSocketServerService
  participant Widget
  SongRequestQueue->>AppDelegate: Return upcoming requests
  AppDelegate->>WebSocketServerService: Broadcast queue snapshot
  WebSocketServerService->>Widget: Send queue_upcoming
  Widget->>Widget: Render themed ticker
Loading

Possibly related PRs

Poem

A rabbit sees three songs in line,
With titles bright and names that shine.
The ticker hops when queues grow,
In themes that match the widget’s glow.
Empty queues rest, neat and light.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 54.55% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely identifies the opt-in overlay queue ticker, which is the pull request's primary change.
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.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/ticket-triage-selection-cf96e3

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

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 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 `@apps/docs/content/docs/widget.mdx`:
- Around line 140-145: Update the widget URL guidance in the documented
queueTicker examples to distinguish URLs without query parameters, which require
?queueTicker=1, from URLs that already contain parameters such as ?token=...,
which require &queueTicker=1. Ensure neither form produces an invalid URL or
duplicate query separator.

In `@apps/widget/src/widget.css`:
- Around line 154-157: Update the `#queue-ticker.hidden` rule to set display:
block so its opacity transition remains active while hidden, preserving the
existing opacity and pointer-events behavior. Then regenerate the committed
widget artifact with the project’s widget build command and include the updated
widget.html.

In `@apps/widget/src/widget.ts`:
- Around line 98-100: Update the queueTickerEnabled initialization in widget.ts
to enable the ticker only when the queueTicker parameter’s value is exactly the
documented "1"; keep it disabled for missing, empty, zero, false, and other
values.
🪄 Autofix

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 Plus

Run ID: c6784120-f516-4c93-8f0b-b6a037f86da4

📥 Commits

Reviewing files that changed from the base of the PR and between 207ec45 and 784512a.

📒 Files selected for processing (15)
  • CHANGELOG.md
  • README.md
  • apps/docs/content/docs/changelog.mdx
  • apps/docs/content/docs/features.mdx
  • apps/docs/content/docs/widget.mdx
  • apps/native/WolfWave/Core/AppConstants.swift
  • apps/native/WolfWave/Core/AppDelegate+StreamDeck.swift
  • apps/native/WolfWave/Resources/widget.html
  • apps/native/WolfWave/Services/SongRequest/SongRequestQueue.swift
  • apps/native/WolfWave/Services/WebSocket/WebSocketServerService.swift
  • apps/native/WolfWaveTests/SongRequestQueueTests.swift
  • apps/native/WolfWaveTests/WebSocketServerIntegrationTests.swift
  • apps/widget/src/widget.css
  • apps/widget/src/widget.html
  • apps/widget/src/widget.ts

Comment thread apps/docs/content/docs/widget.mdx Outdated
Comment thread apps/widget/src/widget.css
Comment thread apps/widget/src/widget.ts Outdated
- widget.ts: require exact ?queueTicker=1, not just key presence
  (=0/=false/bare param would have wrongly enabled it)
- widget.css: #queue-ticker.hidden now sets display:block, overriding
  Tailwind's .hidden{display:none} so the 400ms opacity fade can
  actually animate instead of snapping invisible
- widget.mdx: correct the query-separator guidance (?queueTicker=1 on
  a bare URL, &queueTicker=1 only when a param like ?token= already
  exists) - the loopback widget URL has no query string by default,
  so the old &-only wording was wrong for the common case

Rebuilt and committed widget.html. bunx tsc --noEmit clean.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@nathanialhenniges
nathanialhenniges merged commit 0ee2fcc into main Aug 5, 2026
8 checks passed
@nathanialhenniges
nathanialhenniges deleted the claude/ticket-triage-selection-cf96e3 branch August 5, 2026 01:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant