Expand description
Native presentations: platform-owned modal UI (an alert, and on iOS/iPadOS a sheet) requested imperatively from Rust and resolved to exactly one terminal outcome.
§Why not a platform-view slot
A control is a platform_view slot the differ owns: it disposes a slot
that goes missing from the ingest stream and knows nothing about modal
stacking. A modal belongs to the host instead — the resumed Android
Activity, the topmost iOS view controller, the macOS key window — so a
presentation is a request (show_alert, show_sheet) answered by
a Presentation future, never a node in the tree.
§The contract
- One in flight, process-wide — across every kind. A second request
while one is live resolves
PresentError::Busyimmediately — no queueing, no replacing. The slot is shared by every presentation kind: an alert and a sheet can never both be live, so ashow_sheetwhile an alert is up (or the reverse) is refusedBusytoo. - Exactly one terminal outcome. Each accepted request is stamped with
a fresh, never-zero generation, and resolves through a one-shot
channel whose sending half is consumed by its first use: an action, a
cancellation, a programmatic
dismiss, or the host going away (AlertOutcome::HostLost,SheetOutcome::HostLost). A platform callback arriving for any other generation finds no live entry and is dropped. A sheet’s detent changes are not outcomes: they stream throughSheetSpec::on_detentwhile the sheet stays live. - The slot frees itself. It is released when the outcome is sent
(before the caller is woken, so the caller’s continuation may present
again), when an arm drops its sender without sending (resolving
PresentError::Platform), or when the caller drops thePresentation. Dropping the future frees only this module’s bookkeeping: the platform UI stays up until the user answers it, and that answer is discarded. - Awaitable anywhere.
Presentationis a plainFuturewith no executor dependency: resolution is driven by the platform’s main thread, so it can be polled fromfrust::spawn_localor any other executor. Nothing ever blocks waiting for a modal result.
§Platform arms
AlertHost is the alert seam, selected by cfg per OS:
- iOS/iPadOS —
apple_alert: aUIAlertController(alert or action sheet, an iPad action sheet anchored as a popover) built overapple_host’s shared helpers. - macOS —
appkit_alert: anNSAlertpresented as a window sheet (beginSheetModalForWindow:completionHandler:) on the key/main window, also built overapple_host’s shared helpers. macOS has no action-sheet idiom, soAlertStyle::ActionSheetpresents the same sheet asAlertStyle::AlertandAlertSpec::anchoris ignored. - Android —
android_alert: anandroid.app.AlertDialog, overandroid_host’s shared JNI plumbing (thedev.frust.nativewidgets.FrustNativePresenterKotlin object that tracks the resumedActivity, its onenativeOnOutcomecallback and the live-presentation guard). - Every other target —
unsupported:PresentError::Unsupported.
SheetHost is the sheet seam: iOS/iPadOS — apple_sheet, a
plugin-owned UIViewController subclass presented as a page sheet under
UISheetPresentationController (detents, grabber, adaptive dismissal);
every other target — this module’s own UnsupportedSheet
(PresentError::Unsupported; a macOS NSPopover or Android
BottomSheetDialog arm is follow-up work).
apple_host holds what every Apple arm shares: host discovery, the
main-queue hop and the live-presentation guard.
Structs§
- Alert
Action - One alert button.
- Alert
Spec - What an alert asks: a title, a message, up to
MAX_ALERT_ACTIONSactions, and how it is presented. - Anchor
Rect - A rectangle in logical points of the presenting window’s coordinate space, origin top-left — where an action sheet’s popover points from.
- Presentation
- The future a presentation request answers with — see the module doc’s The contract.
- Presentation
Handle - Names one accepted presentation, for
dismiss. Stale once that presentation has resolved: dismissing it then does nothing. - Sheet
Action - One sheet action row — a system button.
- Sheet
Content - A sheet’s content — the constrained schema a native sheet renders with
platform views only (decision D4): a title, a message, an optional image
and up to
MAX_SHEET_ACTIONSaction rows, laid out top to bottom in that order. Arbitrary frust content is deliberately not accepted: frust has a single render root, and aplatform_viewslot never mounts inside a presented controller. - Sheet
Handle - Names one accepted sheet: take it down or move it between detents. Stale once that sheet has resolved — both calls then do nothing.
- Sheet
Spec - What a sheet asks: its
SheetContent, the detents it rests at and how its sheet chrome behaves.
Enums§
- Action
Role - An action’s semantic role, mapped onto each platform’s own button styles.
- Alert
Outcome - How an alert ended — exactly one per accepted
show_alert. - Alert
Style - How an alert is presented.
- Detent
- A height a sheet rests at.
- Dismiss
Reason - Why a sheet went away without an action.
- Present
Error - Why a presentation could not be shown or did not complete.
- Sheet
Outcome - How a sheet ended — exactly one per accepted
show_sheet.
Constants§
- MAX_
ALERT_ ACTIONS - The most actions one alert takes — the common ceiling of the three
platforms (Android’s
AlertDialoghas exactly three button slots). - MAX_
SHEET_ ACTIONS - The most actions one sheet takes — the same ceiling as an alert’s
(
MAX_ALERT_ACTIONS): a sheet’s action rows are a short choice, not a menu.
Functions§
- dismiss
- Take the presentation
handlenames down; it resolvesAlertOutcome::Dismissed— or, for a sheet,SheetOutcome::Dismissed(DismissReason::Programmatic)— exactly once. A stale handle — its presentation already resolved, or superseded — is ignored. - show_
alert - Present a native alert — see the module doc’s The contract.
- show_
sheet - Present a native sheet — see the module doc’s The contract.