feat(ads): client banner rotation, fade UX & live toggle (PR2)
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Has been skipped
CI / integration (pull_request) Has been skipped
CI / ui (pull_request) Successful in 50s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 58s
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Has been skipped
CI / integration (pull_request) Has been skipped
CI / ui (pull_request) Successful in 50s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 58s
Consume the server-driven banner block (PR1) in the UI and retire the gate. - banner.ts: createScheduler — a smooth weighted round-robin over campaigns (each appears its weight share per cycle, evenly interleaved) with round-robin over a campaign's messages; the rotator drives fade-in -> hold/scroll -> fade-out -> gap -> fade-in, a lone message stays put, reduce-motion swaps instantly without scroll. - model.ts/codec.ts: Profile.banner (Banner/BannerCampaign/BannerTimings) decoded from the fbs block. - Screen.svelte: drop the compile-time SHOW_AD_BANNER; render AdBanner from app.profile.banner (campaigns + timings + reduceMotion). - AdBanner.svelte: opacity-driven fades + scroll host; the rotator is recreated when the campaigns/timings change (a `banner` notify re-fetch swaps them in place). - app.svelte.ts: on the `notify` `banner` sub-kind, refreshProfile() so the banner shows/hides in place. - tests: scheduler distribution + round-robin, the fade sequence, single-message, reduce-motion, stop(); codec banner decode. UI_DESIGN.md + trackers updated.
This commit is contained in:
+14
-6
@@ -195,16 +195,24 @@ Login uses `Screen`.
|
||||
under-board slot shows the **Scores: N** preview. The screen **title** is the variant's
|
||||
display name (Scrabble / Скрэббл / Erudite / Эрудит), not a constant "Scrabble".
|
||||
|
||||
## Announcement banner (`components/AdBanner.svelte`, `lib/banner.ts`)
|
||||
## Advertising banner (`components/AdBanner.svelte`, `lib/banner.ts`)
|
||||
|
||||
A one-line inset strip under the nav bar, drawn on a dedicated `--ad-bg` token —
|
||||
a subtle accent, a touch darker than the surroundings in the light theme and a touch lighter
|
||||
in the dark theme, mapped to Telegram's `secondary_bg_color` inside the Mini App. Content is
|
||||
minimal markdown (text + links, escaped + linkified). A parameterised **rotator** drives messages: a fitting message
|
||||
holds `holdMs` (default 60 s) then cross-fades to the next; a message wider than the strip
|
||||
pauses (`edgePauseMs`), scrolls to its right edge at `scrollPxPerSec`, pauses, and repeats
|
||||
until the cycle exceeds `holdMs`. Today a **mock** provider rotates a long and a short
|
||||
message; the source becomes a server-driven channel later (see ARCHITECTURE).
|
||||
minimal markdown (text + links, escaped + linkified). It is **server-driven**: the campaigns and
|
||||
display timings ride the `profile.get` response (`app.profile.banner`, present only for an eligible
|
||||
viewer — see ARCHITECTURE §10), so `Screen` renders the strip only when that block is present, and
|
||||
a `notify` `banner` event re-fetches the profile to show or hide it in place.
|
||||
|
||||
A **smooth weighted round-robin** (`createScheduler`) picks the next message: campaigns compete by
|
||||
their weight (each appears its weight share per cycle, evenly interleaved, not at random), and a
|
||||
campaign's own messages advance round-robin. The **rotator** then drives one message: it fades in
|
||||
(`fadeInMs`), holds `holdMs` (a message wider than the strip pauses `edgePauseMs`, scrolls to its
|
||||
right edge at `scrollPxPerSec`, pauses, and repeats while under `holdMs`), then — when more than one
|
||||
message exists — fades out (`fadeOutMs`), waits `gapMs`, and fades the next in. A lone message stays
|
||||
put (a long one keeps scrolling). All timings are operator-set (`/_gm/banner-settings`). Under
|
||||
**reduce-motion** the fades collapse to an instant swap and a long message does not scroll.
|
||||
|
||||
## Result / status iconography (`lib/result.ts`)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user