Skip to content

Review cleanup: inbox backfill cap, chat swipe, weekly rotation play state - #14602

Merged
dylanjeffers merged 2 commits into
mainfrom
fix/review-cleanup-sep
Sep 24, 2026
Merged

dylanjeffers merged 2 commits into
mainfrom
fix/review-cleanup-sep

Conversation

@dylanjeffers

Copy link
Copy Markdown
Contributor

Logic fixes

  • Inbox Priority/General backfill (web + mobile) is capped at 5 pages per tab visit. Before, opening a near-empty General tab paged through the user's whole chat history (about 100 serial requests for a 3,000-chat inbox).
  • Mobile chat row swipe now needs 30pt of horizontal travel to activate (default was 10pt), so vertical scrolls that drift sideways stay with the list.
  • OTA banner polling: an in-flight poll can no longer reschedule itself after stop/restart. Before, this left duplicate loops after foregrounding, or a loop running after unmount.
  • Weekly Rotation (web + mobile): a shared mix no longer shows "Your Weekly Rotation" to signed-out viewers while the handle loads or when it isn't found.
  • Weekly Rotation (web + mobile): the playback source now includes the mix owner. Before, a shared mix containing the track currently playing from your own mix showed "Pause" and controlled your queue. No other code keys on the WEEKLY_ROTATION_TRACKS source string.

Comment cleanup: shortened comments in the weekly rotation, chat category, OTA banner, and share files; fixed stale api references in weeklyRotationPeriod; the weekly rotation notification body now matches the push copy ("Updates every Wednesday.").

Tests

  • tsc passes for common, web, and mobile
  • eslint passes on all touched files
  • vitest passes: common src/store/pages/chat (21), web weeklyRotationPeriod, InboxTabs, ChatList a11y, PlaylistEditModeContext, InlineAlbumPriceAndAudience (21)
  • No mobile jest tests cover the touched files, and the change wasn't run on a simulator.

🤖 Generated with Claude Code

dylanjeffers and others added 2 commits September 23, 2026 16:47
…play state

- Cap the Priority/General tab backfill at 5 pages per tab visit (web and
  mobile) so a near-empty tab doesn't page through the whole chat history.
- Raise the chat row swipe activation offsets to 30pt so diagonal vertical
  scrolls stay with the list.
- OTA banner: stop an in-flight poll from rescheduling after stop/restart.
- Weekly Rotation: don't treat a shared mix as your own while its handle
  is loading or not found, and key playback state per mix owner so your
  own mix and a shared one don't share the header play button.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Shorten comments to plain statements, fix stale api references in the
weekly rotation period helper, and align the weekly rotation notification
body with the push copy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Sep 23, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 8945e2b

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@dylanjeffers
dylanjeffers merged commit 1eca87f into main Sep 24, 2026
18 checks passed
@dylanjeffers
dylanjeffers deleted the fix/review-cleanup-sep branch September 24, 2026 19:01
dylanjeffers added a commit that referenced this pull request Sep 24, 2026
… usage analytics (#14605)

Stacked on #14602 (`fix/review-cleanup-sep`). Merge that first; this
PR's base will then retarget to `main`.

Instruments Weekly Rotation so reach, click-through, plays, shares,
notification opens and retention can be measured in Amplitude. No
existing events are renamed.

## Events and properties

**Common**
- `PlaybackSource`, `FavoriteSource` and `RepostSource` each gain
`WEEKLY_ROTATION = 'weekly rotation'`.
- `Playback: Play` gains `weeklyRotationOwnerId`. It is set on passive
(auto-advance and previous) plays whose queue entry came from a mix, and
is parsed from the `WEEKLY_ROTATION_TRACKS:<ownerId>` queue source in
the shared playback saga, so it works on both web and mobile.
- `Weekly Rotation: Banner View`, `Banner Click`, `Page View` and `Play
All` gain `period` (e.g. `2026-38`), `isOwnMix` and `ownerUserId`.
Banner events are always `isOwnMix: true`, with the viewer as owner.
- `Weekly Rotation: Page View` gains `status` (`success` | `empty` |
`error`) and `isSignedIn`. It now fires once the fetch settles, so empty
mixes and errors are counted. Signed-out visitors on
`/explore/weekly-rotation/:handle` are counted too.
- `Modal Opened` now fires with `name: 'Share'` whenever the share modal
or drawer opens (from the shared share-modal saga, any content type). It
carries `source` (the ShareSource), `kind` (e.g. `weeklyRotation`) and
the entity id (`userId` for a mix).
- `Share` gains an optional `channel` (`copyLink` | `shareSheet`).
- `Chat Entry Point` gains `kind` (what was shared) when `source:
'share'`.
- `Notifications: Open Push Notification` gains `type` and `id` from the
push payload. This applies to every push type.
- The period helper moved to `@audius/common/utils`
(`getWeeklyRotationPeriod`, `formatWeeklyRotationPeriod`), along with
`getWeeklyRotationQueueSource` and
`getWeeklyRotationOwnerIdFromQueueSource`. The web SSR still imports it
by path, and the file has no dependencies.

**Web**
- The mix page's lineup plays and header play/pause use `source: 'weekly
rotation'`. Before this they used `'playlist page'` or `'track tile'`.
- Row favorite and repost buttons use `'weekly rotation'`.
`TrackTableLineup` takes `favoriteSource` and `repostSource`, and
History keeps its default.
- The share modal copy link records `Share` with `channel: 'copyLink'`.
DM share records `Chat Entry Point` with `kind`.
- Banner fix: the CTA button's click also bubbled to the card, so
`Banner Click` was recorded (and navigation ran) twice. Only the card
handles the click now.

**Mobile**
- Mix screen tile taps now record `Playback: Play` and `Playback: Pause`
with `source: 'weekly rotation'`. The header play button also records
them. Before this, mobile lineup taps recorded no Playback events:
`TrackLineup` accepted `playbackSource` but ignored it. It now records
Playback events only when that prop is passed, and only this screen
passes it, so other screens are unchanged.
- Tile favorite and repost on the mix screen use `'weekly rotation'`.
`TrackLineup` and `TrackTile` take `favoriteSource` and `repostSource`,
defaulting to `TILE`.
- In the share drawer, weeklyRotation copy link records `Share`
(`channel: 'copyLink'`), the share sheet records `Share` (`channel:
'shareSheet'`), and X records `Share to Twitter`. DM share records `Chat
Entry Point` with `kind`.
- A Weekly Rotation notification tile tap records `Notifications:
Clicked Tile` with `kind: 'WeeklyRotation'`, matching web.

**Not covered**
- The overflow-menu save, repost and add-to-playlist actions still
report `overflow` on both platforms. Adding a source there means
threading it through the table, `OverflowMenuButton` and `TrackMenu` on
web, and through the overflow drawer state on mobile. `Playlist Add` has
no source property at all. Row and tile buttons are covered.

## How to measure (Amplitude)

| Metric | Event and filter |
| --- | --- |
| Reach (impressions) | `Weekly Rotation: Banner View`, uniques, grouped
by `surface` and `source` |
| Banner CTR | Funnel `Weekly Rotation: Banner View` → `Weekly Rotation:
Banner Click`, same `surface` |
| Page views, own vs shared | `Weekly Rotation: Page View` grouped by
`isOwnMix`; filter `status = success` for non-empty views |
| Shared-link landings | `Weekly Rotation: Page View` where `isOwnMix =
false`, grouped by `isSignedIn` (signed-out = new-visitor landings) |
| Empty or broken mixes | `Weekly Rotation: Page View` grouped by
`status` |
| Plays per user from the mix | `Playback: Play` where `source = weekly
rotation` OR `weeklyRotationOwnerId` is set; formula `TOTALS / UNIQUES`.
Split own vs shared by comparing `weeklyRotationOwnerId` to the user, or
use `Play All`'s `isOwnMix` |
| Play-all rate | Funnel `Page View` → `Weekly Rotation: Play All` |
| Saves and reposts from the mix | `Favorite` or `Repost` where `source
= weekly rotation` |
| Share opens | `Modal Opened` where `name = Share` and `kind =
weeklyRotation` |
| Share rate by channel | Share opens (above) as the denominator.
Channels: `Share` where `kind = weeklyRotation`, grouped by `channel`
(web copy link, mobile copy link or share sheet); `Share to Twitter`
where `kind = weeklyRotation`; `Chat Entry Point` where `source = share`
and `kind = weeklyRotation` |
| Push open rate | Opens: `Notifications: Open Push Notification` where
`type = WeeklyRotation` (`id` includes the
`weekly_rotation:<period>:<user>` group). Sends come from the `weekly
rotation push processed` log line added in AudiusProject/pedalboard#98
(sum `mobileSent` per `groupId` period) |
| Notification tile CTR | `Notifications: Clicked Tile` where `kind =
WeeklyRotation` |
| Week-over-week retention | Retention on `Weekly Rotation: Page View`
(or `Play All`) with weekly buckets, or group by `period` to line up
with the Wednesday rollover |

## Testing
- `tsc` passes for common, web and mobile. `eslint` passes on the
touched files.
- `vitest`: new tests for the common period and queue-source helpers and
for the share-modal saga's `Modal Opened`. The web OG URL test and
tracks-table tests pass.
- Checked locally on the web dev server by loading
`/explore/weekly-rotation/dylan` signed out and reading Amplitude's
unsent-event queue:
- `Weekly Rotation: Page View` was recorded with `{isOwnMix: false,
isSignedIn: false, ownerUserId: "18269", period: "2026-39", status:
"success", trackCount: 30}`.
- Play recorded `Weekly Rotation: Play All` and `Playback: Play` with
`source: "weekly rotation"`. Pressing Next recorded `Playback: Play`
with `source: "passive", weeklyRotationOwnerId: "18269"`.
- Opening the share modal recorded `Modal Opened` with `{name: "Share",
kind: "weeklyRotation", source: "page", userId: 18269}`. Copy link
recorded `Share` with `channel: "copyLink"`.
- Mobile jest does not run in this worktree: the react-native module
mapping fails, which also happens on the base branch. No touched mobile
file has tests.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.

1 participant