use std::sync::OnceLock;
use swiftui_native::prelude::*;
use swiftui_native::{state, views};
struct Settings {
name: views::BoundState<String>,
notify: views::BoundState<bool>,
volume: views::BoundState<f64>,
theme: views::BoundState<i64>,
refresh: views::BoundState<f64>,
about: views::BoundState<bool>,
}
fn settings() -> &'static Settings {
static S: OnceLock<Settings> = OnceLock::new();
S.get_or_init(|| Settings {
name: views::BoundState::new("Ada".into()),
notify: views::BoundState::new(true),
volume: views::BoundState::new(0.6),
theme: views::BoundState::new(0),
refresh: views::BoundState::new(5.0),
about: views::BoundState::new(false),
})
}
const THEMES: [&str; 3] = ["System", "Light", "Dark"];
fn body() -> View {
let s = settings();
form![
section![header: text("Account");
hstack![
text("Name"),
spacer(),
textfield_bound("Your name", &s.name).text_field_style(
views::TextFieldStyle::RoundedBorderTextFieldStyle,
),
],
toggle_bound("Notifications", &s.notify),
],
section![header: text("Playback");
vstack_aligned(&[
hstack![
text("Volume"),
spacer(),
text!("{:.0}%", s.volume.get() * 100.0).fg_system(SystemColor::Gray),
],
slider_bound(&s.volume, 0.0, 1.0),
], HorizontalAlignment::Leading),
stepper_bound("Refresh every", &s.refresh, 1.0, 60.0, 1.0),
],
section![header: text("Appearance");
picker_bound!(
"Theme",
&s.theme,
text(THEMES[0]).tag_int(0),
text(THEMES[1]).tag_int(1),
text(THEMES[2]).tag_int(2),
)
.picker_style(PickerStyle::InlinePickerStyle),
],
section![
button("About", show_about)
.a11y_hint("Opens a panel describing this app"),
],
]
.form_style(FormStyle::GroupedFormStyle)
.sheet_bound(&s.about, about_panel())
}
fn about_panel() -> View {
let s = settings();
vstack_spacing(
&[
system_image("gearshape.fill")
.symbol_rendering_mode(Some(views::SymbolRenderingMode::Hierarchical))
.view()
.font_size(48.0)
.fg_system(SystemColor::Blue),
text("Settings").text_style(TextStyle::Title).bold(),
text!("Signed in as {}", s.name.get()).fg_system(SystemColor::Gray),
spacer(),
button("Done", hide_about).button_style(views::ButtonStyle::BorderedProminent),
],
16.0,
)
.padding(24.0)
.presentation_detents(&[views::PresentationDetent::Medium])
.presentation_drag_indicator(Visibility::Visible)
}
fn show_about() {
settings().about.set(true);
state::refresh();
}
fn hide_about() {
settings().about.set(false);
state::refresh();
}
fn content_view() -> swiftui_native::ViewHandle {
state::root_view(|_| body().into_handle())
}
#[cfg(target_os = "macos")]
#[path = "common/simulator.rs"]
mod simulator;
#[cfg(target_os = "macos")]
fn main() {
if std::env::args().any(|a| a == "--sim" || a == "device") {
return simulator::main(&simulator::Bundle {
example: "settings",
bundle_id: "dev.rswift.Settings",
executable: "Settings",
display_name: "Settings",
launch_args: &[],
});
}
if std::env::args().any(|a| a == "--render") {
let out = concat!(env!("CARGO_MANIFEST_DIR"), "/../../target/settings.png");
swiftui_native::render::render(&content_view(), 420, 640).write_png(out);
eprintln!("wrote {out}");
return;
}
show_window(&content_view(), "Settings", 420.0, 640.0);
}
#[cfg(not(target_os = "macos"))]
fn main() {
swiftui_native::app::run(content_view)
}