app

Local-first trade for farms and co-ops
git clone https://radroots.dev/git/app.git
Log | Files | Refs | README | LICENSE

commit d9ac29fe565e664c3b51edd05eef664503579f0d
parent 9ac979c736abd2ef0e5058cd68930774d996a412
Author: triesap <triesap@radroots.dev>
Date:   Mon, 19 Jan 2026 16:37:30 +0000

app: add init stage and state types

- define AppInitStage with string mapping helpers
- add AppInitState and default initializer
- add tests for stage parsing and default state
- re-export init state types from app crate

Diffstat:
Mapp/src/init.rs | 80++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mapp/src/lib.rs | 3+++
2 files changed, 82 insertions(+), 1 deletion(-)

diff --git a/app/src/init.rs b/app/src/init.rs @@ -20,6 +20,62 @@ use leptos::prelude::window; pub const APP_INIT_STORAGE_KEY: &str = "radroots.app.init.ready"; #[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum AppInitStage { + Idle, + Storage, + DownloadSql, + DownloadGeo, + Database, + Geocoder, + Ready, + Error, +} + +impl AppInitStage { + pub const fn as_str(self) -> &'static str { + match self { + AppInitStage::Idle => "idle", + AppInitStage::Storage => "storage", + AppInitStage::DownloadSql => "download_sql", + AppInitStage::DownloadGeo => "download_geo", + AppInitStage::Database => "database", + AppInitStage::Geocoder => "geocoder", + AppInitStage::Ready => "ready", + AppInitStage::Error => "error", + } + } + + pub fn parse(value: &str) -> Option<Self> { + match value { + "idle" => Some(AppInitStage::Idle), + "storage" => Some(AppInitStage::Storage), + "download_sql" => Some(AppInitStage::DownloadSql), + "download_geo" => Some(AppInitStage::DownloadGeo), + "database" => Some(AppInitStage::Database), + "geocoder" => Some(AppInitStage::Geocoder), + "ready" => Some(AppInitStage::Ready), + "error" => Some(AppInitStage::Error), + _ => None, + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct AppInitState { + pub stage: AppInitStage, + pub loaded_bytes: u64, + pub total_bytes: Option<u64>, +} + +pub const fn app_init_state_default() -> AppInitState { + AppInitState { + stage: AppInitStage::Idle, + loaded_bytes: 0, + total_bytes: Some(0), + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum AppInitError { Idb(RadrootsClientIdbStoreError), Datastore(RadrootsClientDatastoreError), @@ -109,7 +165,13 @@ pub async fn app_init_backends() -> AppInitResult<AppBackends> { #[cfg(test)] mod tests { - use super::{app_init_backends, AppInitError, AppInitErrorMessage}; + use super::{ + app_init_backends, + app_init_state_default, + AppInitError, + AppInitErrorMessage, + AppInitStage, + }; use radroots_app_core::datastore::RadrootsClientDatastoreError; use radroots_app_core::idb::RadrootsClientIdbStoreError; use radroots_app_core::keystore::RadrootsClientKeystoreError; @@ -158,4 +220,20 @@ mod tests { super::app_init_mark_completed(); super::app_init_reset(); } + + #[test] + fn app_init_stage_roundtrip() { + let stage = AppInitStage::Ready; + assert_eq!(stage.as_str(), "ready"); + assert_eq!(AppInitStage::parse("ready"), Some(stage)); + assert_eq!(AppInitStage::parse("unknown"), None); + } + + #[test] + fn app_init_state_defaults_match_spec() { + let state = app_init_state_default(); + assert_eq!(state.stage, AppInitStage::Idle); + assert_eq!(state.loaded_bytes, 0); + assert_eq!(state.total_bytes, Some(0)); + } } diff --git a/app/src/lib.rs b/app/src/lib.rs @@ -10,9 +10,12 @@ pub use init::{ app_init_has_completed, app_init_mark_completed, app_init_reset, + app_init_state_default, AppBackends, AppInitError, AppInitErrorMessage, AppInitResult, + AppInitStage, + AppInitState, APP_INIT_STORAGE_KEY, };