The screens
Every screen in the SDK, and the code that shows it.
Every screen takes the hub you created. Put each one inside a NavigationStack in your app: the stack gives the screen its title bar, its search field and a place to push a request's detail.
| Screen | What a user does with it |
|---|---|
DifferentRequestsView(hub:) | The list of requests, with search, filters, voting and New request. |
RequestDetailView(hub:requestID:) | One request, its thread, its vote and its follow. Open it straight from a push notification. |
RoadmapView(hub:isShowingRequests:) | Planned, in progress and shipped, one section each. Empty, it offers See requests if you pass a binding. |
ChangelogView(hub:isShowingRequests:) | What shipped, newest first. Empty, it offers See requests if you pass a binding. |
InboxView(hub:) | Status changes, replies and merges on what they follow. |
SubmitRequestView(hub:) | The composer on its own. Call hub.beginSubmission() before you present it. |
VoteControl(voteCount:voted:isWriting:toggle:) | The vote button for your own rows. isWriting turns the button off while a vote is saving. |
StatusBadge(state:) | The colored status pill, for your own rows. |
What every screen already handles
Each screen already shows its own loading, error, empty and full states. If the server returns an error for a vote, a follow, a comment or a notification marked read, the screen shows it next to the control that was tapped. Nothing fails quietly, and you do not write any of it.
Hide what this app does not include
The Roadmap and What's New screens are Pro. On a Free app those screens still open, and say the app doesn't have one. Better still, leave their tabs out: build your tabs from what the app config says.
let config = try await requests.client.config().config
if config.roadmapEnabled {
Tab("Roadmap", systemImage: "map") { RoadmapView(hub: requests, isShowingRequests: nil) }
}Sign in to see which of these your app has.