cloudflare_dns/ui/state.rs
1/// Application state management.
2///
3/// This module contains the core state types used throughout the application,
4/// including the shared AppState and iocraft Props definitions.
5use iocraft::prelude::*;
6use std::sync::{Arc, Mutex};
7
8use crate::api::{CloudflareClient, DnsCache, DnsRecord};
9
10/// Shared application state wrapped in Arc for thread-safe access.
11///
12/// This state is shared across multiple async tasks and UI components.
13pub struct AppState {
14 /// Cloudflare API client
15 pub client: Arc<CloudflareClient>,
16 /// Zone name (resolved from zone ID on startup)
17 pub zone_name: Mutex<String>,
18 /// Current DNS records
19 pub records: Mutex<Vec<DnsRecord>>,
20 /// Unique IPs extracted from A/AAAA records (for IP selector)
21 pub existing_ips: Mutex<Vec<String>>,
22 /// Cache for DNS records to reduce redundant API calls
23 pub dns_cache: Mutex<DnsCache>,
24}
25
26impl AppState {
27 /// Create a new AppState instance.
28 pub fn new(api_token: String, zone_id: String) -> Self {
29 Self {
30 client: Arc::new(CloudflareClient::new(api_token, zone_id.clone())),
31 zone_name: Mutex::new(zone_id),
32 records: Mutex::new(Vec::new()),
33 existing_ips: Mutex::new(Vec::new()),
34 dns_cache: Mutex::new(DnsCache::with_default_ttl()),
35 }
36 }
37}
38
39/// Props passed to the root App component.
40#[derive(Props, Clone)]
41pub struct AppProps {
42 /// Shared application state
43 pub state: Arc<AppState>,
44}
45
46impl Default for AppProps {
47 fn default() -> Self {
48 Self {
49 state: Arc::new(AppState::new(String::new(), String::new())),
50 }
51 }
52}
53
54/// Props for the FormField component.
55#[derive(Default, Props)]
56pub struct FormFieldProps {
57 /// Field label
58 pub label: String,
59 /// Field value (state binding)
60 pub value: Option<State<String>>,
61 /// Whether this field has focus
62 pub has_focus: bool,
63 /// Optional suffix text (e.g., domain suffix)
64 pub suffix: String,
65 /// Whether this field should be editable as text input (false for cycled fields like Type/Proxied)
66 pub is_editable: bool,
67}
68
69/// Props for the StatusBar component.
70#[derive(Default, Props)]
71pub struct StatusBarProps {
72 /// Status message text
73 pub message: String,
74}
75
76/// Represents the current view mode of the application.
77#[derive(Clone, Copy, PartialEq, Default)]
78pub enum AppView {
79 /// Main record list view
80 #[default]
81 List,
82 /// Create new record form
83 Create,
84 /// Edit existing record form
85 Edit,
86 /// Delete confirmation dialog
87 Delete,
88 /// IP address selector
89 IpSelect,
90}