Async Button surface, LocalizableError, and alert(error:) - #135
Merged
Conversation
…26-08-20, incl. review amendments)
…, tap-to-cancel AsyncButtonActivity (idle/running/cancelling) + AsyncButtonEngine hold the tap semantics once: clear-on-launch error routing into a required error: binding, optional caller-owned activity for deterministic re-entry refusal, cancel-face-enabled toggle mode with cooperative cancellation and a refractory window on the face flip. Four hand-written ViewBuilder primitives; the 12 Localizable-titled forms are generated by the overload sweep's Stage 6b (cross-checked against Button's action-taking Localizable surface; --emit-async-only re-renders just that file from the checked-in SDK stamp).
…or:)
Errors compose like ViewModels: @LocalizedString/@LocalizedSubs message,
plumbing from the @LocalizableError macro, exposed as localizedMessage —
localized during the encode, so wire errors arrive resolved.
@LocalizableError(options: [.clientHosted]) marks client-created errors
(ClientHostedLocalizableError); localized(mvvmEnv:locale:) resolves them at
presentation via the same round-trip ClientHostedViewModelFactory runs for
a ViewModel, nil meaning present the debug description. The
alert(error:title:message:dismissButtonLabel:) modifier is pure Localizable
twin composition: one screen-level error binding in, localized alert out,
%{error} substitution filled with a typed Localizable.
…(plugin 2.27.0) Adds the Async Actions and Error Presentation DocC article, catalog entries + reach-for index lines, and the CHANGELOG entry. Skills now teach the shipped API — Button(error:action:) twins, activity/cancelTitle, alert(error:), LocalizableError composition — replacing the consumer helper shapes (Button(errorBinding:asyncAction:), .alert(errorBinding:), .task(errorBinding:), .onAsyncSubmit) that had leaked in as framework API.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the async action surface designed and ratified in
planning/stream/feat-async-button-surface.md:Buttonforms — everyLocalizable-titled Button form (and the ViewBuilder forms) gains an async twin: the action is@Sendable () async throws, a thrown error lands in a requirederror:binding (cleared on each launch — the binding holds the outcome of the most recent invocation). An optional caller-ownedAsyncButtonActivityadds deterministic re-entry refusal plus running-state fordisabled(_:)/progress. Providing the cancel face (cancelTitle:/cancelSystemImage:/cancelImage:or a phase-aware label) makes the button two-faced — tap to start, tap again to cancel — with acancellingphase while the work unwinds cooperatively and a refractory window against taps aimed at a face that just flipped. All tap semantics live once, inAsyncButtonEngine; the 12 titled forms are generated by the overload sweep's new Stage 6b, cross-checked against Button's action-taking Localizable surface on every full sweep (--emit-async-onlyre-renders just that file from the checked-in SDK stamp).LocalizableError+@LocalizableError— errors compose like ViewModels:@LocalizedString/@LocalizedSubsmessage, plumbing from the macro, exposed aslocalizedMessage. Localization is the localizing encode —ErrorMiddlewareresolves the message on the way out, so wire errors arrive resolved.options: [.clientHosted]marks client-created errors (ClientHostedLocalizableError);localized(mvvmEnv:locale:)resolves them at presentation via the same round-tripClientHostedViewModelFactoryruns for a ViewModel. One localization domain per error type.alert(error:title:message:dismissButtonLabel:)— one screen-level presentation point for the shared error binding, implemented as pure Localizable twin composition; the%{error}substitution point is filled with a typedLocalizable.[Unreleased]; generator skills now teach this shipped API (replacing stale helper shapes that had crept in).Testing
LocalizableErrorflows (en/es), alert substitution ladder, and macro expansion.swift testgreen; api-catalog audit clean (0 gaps, 0 stale); swiftformat fixed-point and swiftlint clean on all changed files.--checkleg (first run ofverifyAsyncTwinBase+ byte-compare ofButton+AsyncAction.swifton 26.5 SDKs), Linux legs, and per-platform xcodebuild legs.