paritytech / paritytech/host-rust-core
RFC — Game pill, alarm and auto-start
@eugypalu is already working on this.
Since Sep 14, 2026.
- Dominant language
- Swift
- Stars
- 10
- Forks
- 3
- Avg merge
- 1d 10h
- Merged PRs (30d)
- 148
Description
Summary
A product declares a pill with a window, a deadline and a destination. The host draws it with a countdown on every surface, opens the destination on tap and, if asked, at the deadline. Scheduled notifications gain a Critical urgency that rings the device alarm.
Motivation
The Jollity game starts at a fixed instant. Polkadot Mobile brings a registered player there natively with a countdown pill, an alarm and a game that opens itself. A product has none of it: it draws only in its own surface, a notification cannot ring as an alarm, and nothing opens a product at an instant.
Approach
sequenceDiagram
participant J as Jollity worker
participant H as Host
participant U as User
J->>H: declare_pill(key, show_from, deadline, destination, title, open_at_deadline)
J->>H: send_push_notification(Critical, scheduled_at = game start, deeplink)
Note over H: show_from: pill + countdown on every surface, hidden while Jollity is foreground
U->>H: tap
H->>U: open destination
Note over H: deadline: pill withdrawn
alt open_at_deadline set, app in foreground, nothing blocking
H->>U: auto-open destination, current tab kept
else app in background, or flag not set
H->>U: alarm rings
U->>H: act on alarm
H->>U: open deeplink
end
J->>H: withdraw_pill(key), cancel_push_notification(id)
Where the work lands:
| Part | truapi | Host app | Jollity |
|---|---|---|---|
| Pill #558 | Pill service: declare_pill keyed, withdraw_pill idempotent; destination parsed as navigate_to does; show_from before deadline |
Persist the declaration; draw pill and countdown at the bottom of every surface except the declaring product's; no dismissal; open on tap; withdraw at deadline | Declare after registration, redeclare with the same key on a schedule change, withdraw when the game ends |
| Alarm #560 | Urgency Normal or Critical in a new payload version, old version means Normal; response carries the delivered urgency; HostDevicePermissionRequest::Alarms |
Map Alarms to AlarmKit, refuse the grant without an alarm framework; ring Critical at scheduled_at; acting on it opens deeplink |
Request Alarms, send Critical at game time, store the id, cancel and resend on change |
| Auto-start #559 | Nothing beyond the optional open_at_deadline flag |
At the deadline, in the foreground and with nothing blocking, open destination and keep the current tab |
Declare with open_at_deadline |
Pill. A declaration with a key already in use replaces it. The pill carries no permission. A host that draws no pills answers Unsupported, and the alarm is the fallback.
Alarm. A Critical notification is delivered in one of three ways:
- The product holds
Alarms: the host rings the device alarm atscheduled_at, and acting on it opensdeeplink. - The product does not hold
Alarms: the host delivers it asNormal, and the response says so. - The host has no alarm framework: it refuses the
Alarmsgrant, so everyCriticalfrom that product is delivered asNormal.
Auto-start. open_at_deadline is an optional flag on the declaration. Without it the pill is only withdrawn at the deadline. With it the host also opens destination, with no prompt, when the app is in the foreground and nothing blocks; what counts as blocking is host policy, and on iOS only an active call does.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.