portico/Sources/Example/ExampleApp.swift

194 lines
6.7 KiB
Swift

import Portico
import Adw
private struct ExamplePark: Hashable { let name: String }
@main
struct ExampleApp: App {
var applicationId: String? { "dev.bscubed.PorticoExample" }
@State private var count = 0
@State private var name = "Portico"
@State private var darkMode = false
@State private var convenienceBannerVisible = false
@State private var selectedTheme = "Light"
@State private var volume = 75.0
@State private var currentPage: UInt32 = 0
@WidgetRef private var pager: Adw.Carousel?
@State private var parkPath: [ExamplePark] = []
@State private var uptime = 0
var body: some Scene {
ApplicationWindow { _ in
NavigationView(path: $parkPath) {
VStack {
HeaderBar()
Carousel {
introPage
counterPage
settingsPage
AsyncDemoPage()
EnvironmentDemoPage()
BreakpointDemoPage()
navigationDemoPage
PresentationDemoPage()
conveniencePage
}
.onPageChanged { page in currentPage = page }
.ref(_pager)
CarouselIndicatorDots()
.carousel($pager)
.halign(.center)
Label("Uptime: \(uptime)s, Page \(currentPage + 1) of 9")
.dimmed()
.halign(.center)
.margin(8)
.task(every: .seconds(1)) { uptime += 1 }
}
.navigationTitle("Portico Demo")
.navigationDestination(for: ExamplePark.self) { park in
VStack {
HeaderBar()
Label("Welcome to \(park.name)")
.title1()
.halign(.center)
.margin(24)
Label("This page was pushed programmatically via the path binding.")
.dimmed()
.halign(.center)
}
.hexpand(true)
.vexpand(true)
.navigationTitle(park.name)
}
}
}
.defaultSize(width: 1080, height: 720)
}
var introPage: some View {
Clamp {
StatusPage {
VStack(spacing: 6) {
Label("Declarative GTK apps in Swift")
.title3()
.marginTop(16)
Label("A familiar SwiftUI-like API, zero GObject boilerplate")
.marginBottom(16)
}
.card()
}
.title("Welcome to Portico")
.description("Swipe to explore")
.iconName("face-smile-symbolic")
}
.hexpand(true)
.vexpand(true)
}
var counterPage: some View {
Clamp {
StatusPage {
HStack(spacing: 12) {
Button("-") { count -= 1 }
.circular()
Label("Count: \(count)")
.title1()
Button("+") { count += 1 }
.circular()
}
.halign(.center)
}
.title("Reactive Counter")
.description("@State + Binding drive targeted widget updates")
.iconName("applications-engineering-symbolic")
}
.hexpand(true)
.vexpand(true)
}
var settingsPage: some View {
Clamp {
StatusPage {
VStack(spacing: 12) {
Label("Name: \(name), Dark mode: \(darkMode), Volume: \(volume)")
.title2()
ListBox {
EntryRow()
.title("Your Name")
.text($name)
SwitchRow()
.title("Dark Mode")
.active($darkMode)
SpinRow(min: 0, max: 100, step: 5)
.title("Volume")
.value($volume)
}
.boxedList()
}
}
.title("Quick Settings")
.description("Live GObject property bindings")
.iconName("application-x-firmware-symbolic")
}
.hexpand(true)
.vexpand(true)
}
var conveniencePage: some View {
Clamp {
VStack(spacing: 12) {
Banner("Connection unavailable", revealed: $convenienceBannerVisible, buttonLabel: "Retry")
PreferencesGroup("Convenience APIs", description: selectedTheme) {
ActionRow("Mode", subtitle: "Select an option")
SwitchRow("Show banner", active: $convenienceBannerVisible)
ComboRow("Theme", items: ["Light", "Dark"]) { selectedTheme = $0 }
ExpanderRow("Advanced", subtitle: "More controls") {
ActionRow("First")
ActionRow("Second")
}
ButtonRow("Reset", startIconName: "view-refresh") {
convenienceBannerVisible = false
selectedTheme = "Light"
}
}
}
}
.hexpand(true)
.vexpand(true)
}
var navigationDemoPage: some View {
Clamp {
StatusPage {
ListBox {
ButtonRow()
.title("See Yosemite")
.onActivated {
parkPath.append(ExamplePark(name: "Yosemite"))
}
ButtonRow()
.title("See Yellowstone")
.onActivated {
parkPath.append(ExamplePark(name: "Yellowstone"))
}
ButtonRow()
.title("See Zion")
.onActivated {
parkPath.append(ExamplePark(name: "Zion"))
}
}
.boxedList()
}
.title("Navigation")
.description("Navigating is easy and reactive in Portico! Just bind an array to a NavigationView and it updates when changes are made in either direction!")
}
.valign(.center)
.hexpand(true)
.vexpand(true)
}
}