app

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

commit f3be8c83fdb19a29b1077ff8f3d561343940faae
parent c733950a4e9bf4ab0abe4b10b449ca1d07a74b49
Author: triesap <tyson@radroots.org>
Date:   Wed, 15 Jul 2026 23:05:30 +0000

build: make Studio validation warning-clean

- box large runtime, signer, and state payloads exposed by clippy
- tighten desktop runtime and UI helper warning hygiene
- keep source guards green under runtime shader validation
- validate with Studio fmt, check, clippy, and source guard tests

Diffstat:
Mcrates/desktop/src/pack_day_host_handoff.rs | 4++--
Mcrates/desktop/src/pack_day_print.rs | 6+++---
Mcrates/desktop/src/runtime.rs | 41++++++++++++++++++++---------------------
Mcrates/desktop/src/window.rs | 187+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Mcrates/runtime/src/pack_day_export.rs | 2+-
Mcrates/runtime/src/sdk.rs | 87+++++++++++++++++++++++++++++++++++++++----------------------------------------
Mcrates/signer/src/protocol.rs | 28++++++++++++++++------------
Mcrates/state/src/lib.rs | 213+++++++++++++++++++++++++++++++++++++++----------------------------------------
Mcrates/ui/src/primitives.rs | 20+++++++++++---------
9 files changed, 296 insertions(+), 292 deletions(-)

diff --git a/crates/desktop/src/pack_day_host_handoff.rs b/crates/desktop/src/pack_day_host_handoff.rs @@ -346,7 +346,7 @@ mod tests { } } - fn sample_bundle(bundle_directory: &PathBuf) -> PackDayExportBundle { + fn sample_bundle(bundle_directory: &std::path::Path) -> PackDayExportBundle { PackDayExportBundle { fulfillment_window_id: radroots_studio_app_view::FulfillmentWindowId::generate(), export_instance_id: radroots_studio_app_view::PackDayExportInstanceId::generate(), @@ -369,7 +369,7 @@ mod tests { } } - fn write_artifact(bundle_directory: &PathBuf, file_name: &str) -> PathBuf { + fn write_artifact(bundle_directory: &std::path::Path, file_name: &str) -> PathBuf { let path = bundle_directory.join(file_name); fs::write(&path, file_name).expect("artifact should write"); path diff --git a/crates/desktop/src/pack_day_print.rs b/crates/desktop/src/pack_day_print.rs @@ -934,7 +934,7 @@ mod tests { } } - fn sample_bundle(bundle_directory: &PathBuf) -> PackDayExportBundle { + fn sample_bundle(bundle_directory: &std::path::Path) -> PackDayExportBundle { PackDayExportBundle { fulfillment_window_id: radroots_studio_app_view::FulfillmentWindowId::generate(), export_instance_id: PackDayExportInstanceId::generate(), @@ -961,13 +961,13 @@ mod tests { PackDayBatchPrintRequest::for_bundle(bundle) } - fn write_artifact(bundle_directory: &PathBuf, file_name: &str) -> PathBuf { + fn write_artifact(bundle_directory: &std::path::Path, file_name: &str) -> PathBuf { let path = bundle_directory.join(file_name); fs::write(&path, file_name).expect("artifact should write"); path } - fn write_all_artifacts(bundle_directory: &PathBuf) { + fn write_all_artifacts(bundle_directory: &std::path::Path) { write_artifact(bundle_directory, "pack_sheet.txt"); write_artifact(bundle_directory, "pickup_roster.txt"); write_artifact(bundle_directory, "customer_labels.txt"); diff --git a/crates/desktop/src/runtime.rs b/crates/desktop/src/runtime.rs @@ -501,9 +501,7 @@ impl DesktopAppRuntime { .sdk_runtime .lock() .unwrap_or_else(|poisoned| poisoned.into_inner()); - let Some(runtime) = sdk_runtime.as_ref() else { - return None; - }; + let runtime = sdk_runtime.as_ref()?; DesktopRuntimeDiagnostics::from_snapshot(runtime.snapshot()) } @@ -1274,10 +1272,10 @@ pub struct DesktopRuntimeSupervisorIssueSummary { impl DesktopRuntimeSupervisorIssueSummary { fn from_issue(issue: &DesktopRuntimeIssue) -> Self { Self { - code: issue.code.clone(), - class: issue.class.clone(), + code: issue.code.to_string(), + class: issue.class.to_string(), retryable: issue.retryable, - recovery_actions: issue.recovery_actions.clone(), + recovery_actions: issue.recovery_actions.to_vec(), } } @@ -6405,7 +6403,7 @@ async fn fetch_app_events_from_single_relay_async( .map_err(|source| AppSyncTransportError::failed(source.to_string()))?; let last_event_created_at_unix_seconds = events .iter() - .map(|event| relay_event_created_at_unix_seconds_for_fetch(event)) + .map(relay_event_created_at_unix_seconds_for_fetch) .collect::<Result<Vec<_>, _>>()? .into_iter() .max(); @@ -6864,17 +6862,17 @@ fn sdk_idempotency_key(source_record_id: &str) -> String { fn sdk_runtime_unavailable_error() -> DesktopRuntimeSupervisorError { DesktopRuntimeSupervisorError::Unavailable(DesktopRuntimeIssue { - code: "sdk_runtime_not_available".to_owned(), - class: "runtime".to_owned(), + code: "sdk_runtime_not_available".into(), + class: "runtime".into(), retryable: true, - message: "app SDK runtime is not available".to_owned(), - recovery_actions: vec!["retry_startup".to_owned()], - detail_json: json!({ + message: "app SDK runtime is not available".into(), + recovery_actions: vec!["retry_startup".to_owned()].into_boxed_slice(), + detail_json: Box::new(json!({ "code": "sdk_runtime_not_available", "class": "runtime", "retryable": true, "recovery_actions": ["retry_startup"], - }), + })), }) } @@ -6888,7 +6886,7 @@ fn desktop_runtime_supervisor_error_detail_json( error: &DesktopRuntimeSupervisorError, ) -> serde_json::Value { match error { - DesktopRuntimeSupervisorError::Unavailable(issue) => issue.detail_json.clone(), + DesktopRuntimeSupervisorError::Unavailable(issue) => (*issue.detail_json).clone(), DesktopRuntimeSupervisorError::EffectQueueCapacityZero => json!({ "code": "desktop_runtime_effect_queue_capacity_zero", "class": "runtime", @@ -7682,9 +7680,7 @@ fn shared_optional_line_value( ) -> Option<String> { let mut resolved = None::<String>; for line in lines { - let Some(next) = value(line).map(str::trim).filter(|next| !next.is_empty()) else { - return None; - }; + let next = value(line).map(str::trim).filter(|next| !next.is_empty())?; if let Some(existing) = resolved.as_deref() { if existing != next { return None; @@ -8020,6 +8016,7 @@ fn sanitize_pack_day_query( Ok((default_query, default_projection)) } +#[allow(clippy::too_many_arguments)] fn load_selected_account_reminder_context_with_options( sqlite_store: &AppSqliteStore, account_id: &str, @@ -8304,6 +8301,7 @@ fn build_sync_reminder_projection( None } +#[allow(clippy::too_many_arguments)] fn build_reminder_projection( farm_id: FarmId, identity_key: String, @@ -16387,10 +16385,10 @@ mod tests { .expect("print success should apply") ); - if let PackDayPrintKind::PrintCustomerLabels = kind { - if let Some(parent) = prepared.1.target_path.parent() { - let _ = fs::remove_dir_all(parent); - } + if let PackDayPrintKind::PrintCustomerLabels = kind + && let Some(parent) = prepared.1.target_path.parent() + { + let _ = fs::remove_dir_all(parent); } } @@ -19604,6 +19602,7 @@ mod tests { ) } + #[allow(clippy::too_many_arguments)] fn append_signed_order_cancellation_record_with_prev( paths: &AppDesktopRuntimePaths, trade_order_id: &str, diff --git a/crates/desktop/src/window.rs b/crates/desktop/src/window.rs @@ -898,12 +898,12 @@ enum StartupSignerConnectState { Idle, Connecting, PendingApproval { - pending_session: RadrootsAppRemoteSignerPendingSession, + pending_session: Box<RadrootsAppRemoteSignerPendingSession>, auth_challenge_url: Option<String>, }, Approved { - pending_session: RadrootsAppRemoteSignerPendingSession, - approved_session: RadrootsAppRemoteSignerApprovedSession, + pending_session: Box<RadrootsAppRemoteSignerPendingSession>, + approved_session: Box<RadrootsAppRemoteSignerApprovedSession>, auth_challenge_url: Option<String>, }, } @@ -967,19 +967,19 @@ enum HomeAutoFocusTarget { #[derive(Clone, Copy, Debug, Eq, PartialEq)] enum BuyerWorkspaceNotice { - MarketplaceRefreshFailed, - DetailOpenFailed, - OrderPlaceFailed, - OrderCoordinationFailed, + MarketplaceRefresh, + DetailOpen, + OrderPlace, + OrderCoordination, } impl BuyerWorkspaceNotice { fn text_key(self) -> AppTextKey { match self { - Self::MarketplaceRefreshFailed => AppTextKey::PersonalMarketplaceRefreshFailedNotice, - Self::DetailOpenFailed => AppTextKey::PersonalDetailOpenFailedNotice, - Self::OrderPlaceFailed => AppTextKey::PersonalOrderPlaceFailedNotice, - Self::OrderCoordinationFailed => AppTextKey::PersonalOrderCoordinationFailedNotice, + Self::MarketplaceRefresh => AppTextKey::PersonalMarketplaceRefreshFailedNotice, + Self::DetailOpen => AppTextKey::PersonalDetailOpenFailedNotice, + Self::OrderPlace => AppTextKey::PersonalOrderPlaceFailedNotice, + Self::OrderCoordination => AppTextKey::PersonalOrderCoordinationFailedNotice, } } @@ -1381,7 +1381,7 @@ impl HomeView { } self.startup_view.clear_notice(); self.startup_signer_connect_state = StartupSignerConnectState::PendingApproval { - pending_session: pending_session.clone(), + pending_session: Box::new(pending_session.clone()), auth_challenge_url: None, }; cx.notify(); @@ -1412,7 +1412,7 @@ impl HomeView { Ok(RadrootsAppRemoteSignerPendingPollOutcome::PendingApproval) => { self.startup_view.clear_notice(); self.startup_signer_connect_state = StartupSignerConnectState::PendingApproval { - pending_session, + pending_session: Box::new(pending_session), auth_challenge_url, }; cx.notify(); @@ -1425,7 +1425,7 @@ impl HomeView { self.startup_view.clear_notice(); } self.startup_signer_connect_state = StartupSignerConnectState::PendingApproval { - pending_session, + pending_session: Box::new(pending_session), auth_challenge_url, }; cx.notify(); @@ -1435,12 +1435,12 @@ impl HomeView { .runtime .activate_startup_approved_remote_signer_session( &pending_session, - &approved_session, + approved_session.as_ref(), ) { Ok(_) => { self.startup_view.clear_notice(); self.startup_signer_connect_state = StartupSignerConnectState::Approved { - pending_session, + pending_session: Box::new(pending_session), approved_session, auth_challenge_url, }; @@ -1451,7 +1451,7 @@ impl HomeView { self.startup_view.set_notice(error.to_string()); self.startup_signer_connect_state = StartupSignerConnectState::PendingApproval { - pending_session, + pending_session: Box::new(pending_session), auth_challenge_url, }; cx.notify(); @@ -1525,7 +1525,7 @@ impl HomeView { let task_token = self.next_startup_signer_task_token(); self.startup_view.clear_notice(); self.startup_signer_connect_state = StartupSignerConnectState::PendingApproval { - pending_session: pending_session.clone(), + pending_session: Box::new(pending_session.clone()), auth_challenge_url: None, }; cx.notify(); @@ -1874,7 +1874,7 @@ impl HomeView { error = %runtime_error, "failed to select buyer section" ); - self.set_buyer_workspace_notice(BuyerWorkspaceNotice::MarketplaceRefreshFailed) + self.set_buyer_workspace_notice(BuyerWorkspaceNotice::MarketplaceRefresh) } } } @@ -2050,7 +2050,7 @@ impl HomeView { error = %runtime_error, "failed to update buyer search query" ); - self.set_buyer_workspace_notice(BuyerWorkspaceNotice::MarketplaceRefreshFailed) + self.set_buyer_workspace_notice(BuyerWorkspaceNotice::MarketplaceRefresh) } } } @@ -2152,7 +2152,7 @@ impl HomeView { method = method.storage_key(), "failed to update buyer fulfillment filter" ); - self.set_buyer_workspace_notice(BuyerWorkspaceNotice::MarketplaceRefreshFailed) + self.set_buyer_workspace_notice(BuyerWorkspaceNotice::MarketplaceRefresh) } } } @@ -2190,7 +2190,7 @@ impl HomeView { error = %runtime_error, "failed to open buyer product detail" ); - self.set_buyer_workspace_notice(BuyerWorkspaceNotice::DetailOpenFailed) + self.set_buyer_workspace_notice(BuyerWorkspaceNotice::DetailOpen) } } } @@ -2332,7 +2332,7 @@ impl HomeView { Ok(false) => false, Err(runtime_error) => { let notice = buyer_order_place_failure_notice(&runtime_error); - if notice == BuyerWorkspaceNotice::OrderCoordinationFailed { + if notice == BuyerWorkspaceNotice::OrderCoordination { self.buyer_order_review_form = None; } error!( @@ -2367,7 +2367,7 @@ impl HomeView { error = %runtime_error, "failed to retry buyer order coordination" ); - let notice = BuyerWorkspaceNotice::OrderCoordinationFailed; + let notice = BuyerWorkspaceNotice::OrderCoordination; let notice_changed = self.set_buyer_workspace_notice(notice); buyer_order_coordination_notice_forces_redraw(notice) || notice_changed } @@ -3299,7 +3299,7 @@ impl HomeView { sections.push( home_setup_card( projection, - matches!(farm_state, FarmerHomeFarmState::IncompleteFarm).then_some( + matches!(farm_state, FarmerHomeFarmState::Incomplete).then_some( action_button_primary( "home-farm-setup-continue", app_shared_text(AppTextKey::HomeFarmSetupContinueAction), @@ -3435,7 +3435,7 @@ impl HomeView { .into_any_element(), ); } else if runtime.startup_issue.is_none() - && farm_state == FarmerHomeFarmState::NoFarm + && farm_state == FarmerHomeFarmState::None && setup_onboarding.is_none() { sections.push( @@ -3446,7 +3446,7 @@ impl HomeView { .into_any_element(), ); } else if runtime.startup_issue.is_none() - && farm_state == FarmerHomeFarmState::ConfiguredFarm + && farm_state == FarmerHomeFarmState::Configured && !projection.needs_setup() && projection.next_fulfillment_window.is_none() && !projection.has_attention_items() @@ -5757,6 +5757,7 @@ impl StartupHomeView { self.startup_notice = None; } + #[allow(clippy::too_many_arguments)] fn render( &self, runtime: &DesktopAppRuntimeSummary, @@ -6345,10 +6346,9 @@ impl SettingsFarmPanelState { .pickup_locations .iter() .any(|pickup_location| pickup_location.is_default) + && let Some(first_pickup_location) = self.pickup_locations.first_mut() { - if let Some(first_pickup_location) = self.pickup_locations.first_mut() { - first_pickup_location.is_default = true; - } + first_pickup_location.is_default = true; } self.sync_pickup_location_removability(); self.save_failed = false; @@ -6525,30 +6525,30 @@ impl SettingsFarmPanelState { ); } - if let Some(pickup_location_id) = fulfillment_window.selected_pickup_location_id { - if !missing_required_fields { - if ends_at <= starts_at { - push_unique_text_key( - &mut row_validation_keys, - AppTextKey::SettingsReadinessFieldFulfillmentWindowEndsBeforeStart, - ); - } - if order_cutoff_at >= starts_at { - push_unique_text_key( - &mut row_validation_keys, - AppTextKey::SettingsReadinessFieldFulfillmentWindowCutoffAfterStart, - ); - } - fulfillment_windows.push(FulfillmentWindowRecord { - fulfillment_window_id: fulfillment_window.fulfillment_window_id, - farm_id: self.farm_id, - pickup_location_id, - label, - starts_at, - ends_at, - order_cutoff_at, - }); + if let Some(pickup_location_id) = fulfillment_window.selected_pickup_location_id + && !missing_required_fields + { + if ends_at <= starts_at { + push_unique_text_key( + &mut row_validation_keys, + AppTextKey::SettingsReadinessFieldFulfillmentWindowEndsBeforeStart, + ); + } + if order_cutoff_at >= starts_at { + push_unique_text_key( + &mut row_validation_keys, + AppTextKey::SettingsReadinessFieldFulfillmentWindowCutoffAfterStart, + ); } + fulfillment_windows.push(FulfillmentWindowRecord { + fulfillment_window_id: fulfillment_window.fulfillment_window_id, + farm_id: self.farm_id, + pickup_location_id, + label, + starts_at, + ends_at, + order_cutoff_at, + }); } fulfillment_window_validation_keys.push(row_validation_keys); @@ -8835,7 +8835,7 @@ fn today_auto_focus_target( return Some(HomeAutoFocusTarget::FarmerSetupStart); } } else if projection.needs_setup() - && farmer_home_farm_state(runtime) == FarmerHomeFarmState::IncompleteFarm + && farmer_home_farm_state(runtime) == FarmerHomeFarmState::Incomplete { return Some(HomeAutoFocusTarget::FarmerSetupContinue); } @@ -9223,6 +9223,7 @@ fn buyer_workspace_title_block(title_key: AppTextKey, body_key: AppTextKey) -> i ) } +#[allow(clippy::too_many_arguments)] fn account_tab_frame( tabs: impl IntoIterator<Item = AppUnderlineTabSpec>, selected_index: usize, @@ -11183,6 +11184,7 @@ fn buyer_listing_price_text(price: &ProductPricePresentation) -> String { format!("${dollars}.{cents:02} / {}", price.unit_label) } +#[allow(clippy::too_many_arguments)] fn buyer_product_detail_card( detail: &BuyerProductDetailProjection, replace_confirmation: Option<&BuyerCartReplaceConfirmationProjection>, @@ -12080,6 +12082,7 @@ fn startup_home_surface(runtime: &DesktopAppRuntimeSummary) -> StartupHomeSurfac } } +#[allow(clippy::too_many_arguments)] fn startup_home_shell( runtime: &DesktopAppRuntimeSummary, startup_notice: Option<&str>, @@ -12611,6 +12614,7 @@ async fn run_startup_signer_pending_poll( } } +#[allow(clippy::too_many_arguments)] fn home_sidebar( runtime: &DesktopAppRuntimeSummary, on_select_today: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static, @@ -12970,6 +12974,7 @@ fn products_title_row( .child(add_product_action) } +#[allow(clippy::too_many_arguments)] fn products_controls_card( runtime: &DesktopAppRuntimeSummary, products_search: Option<&ProductsSearchState>, @@ -13405,6 +13410,7 @@ struct PackDayBatchPrintStatusPresentation { title_key: AppTextKey, } +#[allow(clippy::too_many_arguments)] fn pack_day_export_card( runtime: &DesktopAppRuntimeSummary, on_export: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static, @@ -13488,7 +13494,7 @@ fn pack_day_export_card( app_cluster(APP_UI_THEME.foundation.spacing.small_px) .items_center() .children(host_handoff_actions.into_iter().map(move |action| { - let button = match action.kind { + match action.kind { PackDayHostHandoffKind::RevealBundle if action.enabled => { action_button( "pack-day-reveal-bundle", @@ -13585,8 +13591,7 @@ fn pack_day_export_card( ) .into_any_element() } - }; - button + } })), ) .when_some(host_handoff_status, |this, status| { @@ -16093,14 +16098,14 @@ fn home_empty_state_card(title_key: AppTextKey, body_key: AppTextKey) -> impl In fn buyer_order_place_failure_notice(error: &AppSqliteError) -> BuyerWorkspaceNotice { match error { AppSqliteError::RuntimeStoreSql { .. } | AppSqliteError::RuntimeStore { .. } => { - BuyerWorkspaceNotice::OrderCoordinationFailed + BuyerWorkspaceNotice::OrderCoordination } - _ => BuyerWorkspaceNotice::OrderPlaceFailed, + _ => BuyerWorkspaceNotice::OrderPlace, } } fn buyer_order_coordination_notice_forces_redraw(notice: BuyerWorkspaceNotice) -> bool { - notice == BuyerWorkspaceNotice::OrderCoordinationFailed + notice == BuyerWorkspaceNotice::OrderCoordination } fn buyer_workspace_notice_card(notice: String) -> impl IntoElement { @@ -16133,9 +16138,9 @@ fn farm_setup_save_state_key(state: FarmSetupSaveState) -> AppTextKey { #[derive(Clone, Copy, Debug, Eq, PartialEq)] enum FarmerHomeFarmState { - NoFarm, - IncompleteFarm, - ConfiguredFarm, + None, + Incomplete, + Configured, } fn home_saved_farm(runtime: &DesktopAppRuntimeSummary) -> Option<&FarmSummary> { @@ -16148,15 +16153,15 @@ fn home_saved_farm(runtime: &DesktopAppRuntimeSummary) -> Option<&FarmSummary> { fn farmer_home_farm_state(runtime: &DesktopAppRuntimeSummary) -> FarmerHomeFarmState { match runtime.farm_readiness_projection.status { - FarmWorkspaceStatus::NoFarm => FarmerHomeFarmState::NoFarm, + FarmWorkspaceStatus::NoFarm => FarmerHomeFarmState::None, FarmWorkspaceStatus::SetupRequired => { if home_saved_farm(runtime).is_some() { - FarmerHomeFarmState::IncompleteFarm + FarmerHomeFarmState::Incomplete } else { - FarmerHomeFarmState::NoFarm + FarmerHomeFarmState::None } } - FarmWorkspaceStatus::Ready => FarmerHomeFarmState::ConfiguredFarm, + FarmWorkspaceStatus::Ready => FarmerHomeFarmState::Configured, } } @@ -16192,19 +16197,19 @@ fn home_status_presentation(runtime: &DesktopAppRuntimeSummary) -> HomeStatusPre } match farmer_home_farm_state(runtime) { - FarmerHomeFarmState::NoFarm => { + FarmerHomeFarmState::None => { return HomeStatusPresentation { indicator_color: APP_UI_THEME.components.app_status_indicator.offline, label_key: AppTextKey::HomeTodayStatusNoFarm, }; } - FarmerHomeFarmState::IncompleteFarm => { + FarmerHomeFarmState::Incomplete => { return HomeStatusPresentation { indicator_color: APP_UI_THEME.components.app_status_indicator.offline, label_key: AppTextKey::HomeTodayStatusSetup, }; } - FarmerHomeFarmState::ConfiguredFarm => {} + FarmerHomeFarmState::Configured => {} } if runtime.today_projection.has_attention_items() { @@ -16348,7 +16353,7 @@ mod tests { } } - fn write_artifact(bundle_directory: &PathBuf, file_name: &str) -> PathBuf { + fn write_artifact(bundle_directory: &std::path::Path, file_name: &str) -> PathBuf { let path = bundle_directory.join(file_name); fs::write(&path, file_name).unwrap(); path @@ -16393,18 +16398,18 @@ mod tests { fn buyer_workspace_notice_tracks_visible_buyer_runtime_errors() { let (mut view, _, home_dir) = test_home_view("buyer_notice"); - assert!(view.set_buyer_workspace_notice(BuyerWorkspaceNotice::MarketplaceRefreshFailed)); + assert!(view.set_buyer_workspace_notice(BuyerWorkspaceNotice::MarketplaceRefresh)); assert_eq!( view.buyer_workspace_notice.as_deref(), Some(app_text(AppTextKey::PersonalMarketplaceRefreshFailedNotice).as_str()) ); - assert!(!view.set_buyer_workspace_notice(BuyerWorkspaceNotice::MarketplaceRefreshFailed)); - assert!(view.set_buyer_workspace_notice(BuyerWorkspaceNotice::OrderPlaceFailed)); + assert!(!view.set_buyer_workspace_notice(BuyerWorkspaceNotice::MarketplaceRefresh)); + assert!(view.set_buyer_workspace_notice(BuyerWorkspaceNotice::OrderPlace)); assert_eq!( view.buyer_workspace_notice.as_deref(), Some(app_text(AppTextKey::PersonalOrderPlaceFailedNotice).as_str()) ); - assert!(view.set_buyer_workspace_notice(BuyerWorkspaceNotice::OrderCoordinationFailed)); + assert!(view.set_buyer_workspace_notice(BuyerWorkspaceNotice::OrderCoordination)); assert_eq!( view.buyer_workspace_notice.as_deref(), Some(app_text(AppTextKey::PersonalOrderCoordinationFailedNotice).as_str()) @@ -16431,10 +16436,10 @@ mod tests { #[test] fn buyer_order_coordination_failure_forces_redraw_when_notice_is_unchanged() { assert!(buyer_order_coordination_notice_forces_redraw( - BuyerWorkspaceNotice::OrderCoordinationFailed + BuyerWorkspaceNotice::OrderCoordination )); assert!(!buyer_order_coordination_notice_forces_redraw( - BuyerWorkspaceNotice::OrderPlaceFailed + BuyerWorkspaceNotice::OrderPlace )); } @@ -16578,7 +16583,7 @@ mod tests { let _ = fs::remove_dir_all(home_dir); } - fn sample_pack_day_bundle(bundle_directory: &PathBuf) -> PackDayExportBundle { + fn sample_pack_day_bundle(bundle_directory: &std::path::Path) -> PackDayExportBundle { PackDayExportBundle { fulfillment_window_id: FulfillmentWindowId::generate(), export_instance_id: radroots_studio_app_view::PackDayExportInstanceId::generate(), @@ -17288,7 +17293,7 @@ mod tests { TodayAgendaProjection::default(), FarmSetupProjection::default(), )), - FarmerHomeFarmState::NoFarm + FarmerHomeFarmState::None ); assert_eq!( farmer_home_farm_state(&summary( @@ -17306,7 +17311,7 @@ mod tests { Some(incomplete_farm), ), )), - FarmerHomeFarmState::IncompleteFarm + FarmerHomeFarmState::Incomplete ); assert_eq!( farmer_home_farm_state(&summary( @@ -17324,7 +17329,7 @@ mod tests { Some(configured_farm), ), )), - FarmerHomeFarmState::ConfiguredFarm + FarmerHomeFarmState::Configured ); } @@ -18183,14 +18188,14 @@ mod tests { ); assert_eq!( startup_signer_status_spec(&StartupSignerConnectState::PendingApproval { - pending_session: pending_session.clone(), + pending_session: Box::new(pending_session.clone()), auth_challenge_url: None, }), Some((AppTextKey::HomeSetupSignerPendingTitle, None)) ); assert_eq!( startup_signer_status_spec(&StartupSignerConnectState::PendingApproval { - pending_session: pending_session.clone(), + pending_session: Box::new(pending_session.clone()), auth_challenge_url: Some("https://auth.example/challenge".to_owned()), }), Some(( @@ -18200,15 +18205,15 @@ mod tests { ); assert_eq!( startup_signer_status_spec(&StartupSignerConnectState::Approved { - pending_session, - approved_session: RadrootsAppRemoteSignerApprovedSession { + pending_session: Box::new(pending_session), + approved_session: Box::new(RadrootsAppRemoteSignerApprovedSession { user_identity: fixture_identity( "2222222222222222222222222222222222222222222222222222222222222222", ) .to_public(), relays: vec!["wss://relay.radroots.example".to_owned()], approved_permissions: Default::default(), - }, + }), auth_challenge_url: None, }), Some((AppTextKey::HomeSetupSignerApprovedTitle, None)) @@ -18227,21 +18232,21 @@ mod tests { )); assert!(!startup_signer_source_input_is_editable( &StartupSignerConnectState::PendingApproval { - pending_session: pending_session.clone(), + pending_session: Box::new(pending_session.clone()), auth_challenge_url: None, } )); assert!(!startup_signer_source_input_is_editable( &StartupSignerConnectState::Approved { - pending_session, - approved_session: RadrootsAppRemoteSignerApprovedSession { + pending_session: Box::new(pending_session), + approved_session: Box::new(RadrootsAppRemoteSignerApprovedSession { user_identity: fixture_identity( "2222222222222222222222222222222222222222222222222222222222222222", ) .to_public(), relays: vec!["wss://relay.radroots.example".to_owned()], approved_permissions: Default::default(), - }, + }), auth_challenge_url: None, } )); @@ -18253,7 +18258,7 @@ mod tests { let preview = startup_signer_preview_summary_for_connect_state( "bunker://466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f27?relay=wss%3A%2F%2Frelay.radroots.example", &StartupSignerConnectState::PendingApproval { - pending_session: pending_session.clone(), + pending_session: Box::new(pending_session.clone()), auth_challenge_url: None, }, ) diff --git a/crates/runtime/src/pack_day_export.rs b/crates/runtime/src/pack_day_export.rs @@ -213,7 +213,7 @@ fn render_customer_labels(source: &PackDayOutputSource) -> String { if blocks.is_empty() { blocks.push( - vec![ + [ source.fulfillment_window.farm_display_name.clone(), "No customer labels".to_owned(), format!( diff --git a/crates/runtime/src/sdk.rs b/crates/runtime/src/sdk.rs @@ -101,12 +101,12 @@ pub struct DesktopRuntimeStoragePaths { #[derive(Clone, Debug, PartialEq)] pub struct DesktopRuntimeIssue { - pub code: String, - pub class: String, + pub code: Box<str>, + pub class: Box<str>, pub retryable: bool, - pub message: String, - pub recovery_actions: Vec<String>, - pub detail_json: Value, + pub message: Box<str>, + pub recovery_actions: Box<[String]>, + pub detail_json: Box<Value>, } #[derive(Clone, Debug, PartialEq)] @@ -438,27 +438,27 @@ enum DesktopRuntimeEffect { RefreshDiagnostics(DesktopRuntimeEffectReceipt), RestorePreflight( DesktopRuntimeEffectReceipt, - DesktopRuntimeRestorePreflightRequest, + Box<DesktopRuntimeRestorePreflightRequest>, ), EnqueueFarmPublish( DesktopRuntimeEffectReceipt, - DesktopRuntimeFarmPublishRequest, + Box<DesktopRuntimeFarmPublishRequest>, ), EnqueueListingPublish( DesktopRuntimeEffectReceipt, - DesktopRuntimeListingPublishRequest, + Box<DesktopRuntimeListingPublishRequest>, ), TradePropose( DesktopRuntimeEffectReceipt, - DesktopRuntimeTradeProposeRequest, + Box<DesktopRuntimeTradeProposeRequest>, ), TradeDecision( DesktopRuntimeEffectReceipt, - DesktopRuntimeTradeDecisionRequest, + Box<DesktopRuntimeTradeDecisionRequest>, ), TradeCancellation( DesktopRuntimeEffectReceipt, - DesktopRuntimeTradeCancellationRequest, + Box<DesktopRuntimeTradeCancellationRequest>, ), BeginProjectionRebuild(DesktopRuntimeEffectReceipt), CompleteProjectionRebuild(DesktopRuntimeEffectReceipt), @@ -595,7 +595,7 @@ impl DesktopRuntimeSupervisor { DesktopRuntimeEffectKind::RestorePreflight, None, None, - |receipt| DesktopRuntimeEffect::RestorePreflight(receipt, request), + |receipt| DesktopRuntimeEffect::RestorePreflight(receipt, Box::new(request)), ) } @@ -608,7 +608,7 @@ impl DesktopRuntimeSupervisor { DesktopRuntimeEffectKind::FarmPublish, Some(FARM_PUBLISH_OPERATION_KIND.to_owned()), actor_pubkey, - |receipt| DesktopRuntimeEffect::EnqueueFarmPublish(receipt, request), + |receipt| DesktopRuntimeEffect::EnqueueFarmPublish(receipt, Box::new(request)), ) } @@ -621,7 +621,7 @@ impl DesktopRuntimeSupervisor { DesktopRuntimeEffectKind::ListingPublish, Some(LISTING_PUBLISH_OPERATION_KIND.to_owned()), actor_pubkey, - |receipt| DesktopRuntimeEffect::EnqueueListingPublish(receipt, request), + |receipt| DesktopRuntimeEffect::EnqueueListingPublish(receipt, Box::new(request)), ) } @@ -634,7 +634,7 @@ impl DesktopRuntimeSupervisor { DesktopRuntimeEffectKind::TradePropose, Some(TRADE_SUBMIT_OPERATION_KIND.to_owned()), actor_pubkey, - |receipt| DesktopRuntimeEffect::TradePropose(receipt, request), + |receipt| DesktopRuntimeEffect::TradePropose(receipt, Box::new(request)), ) } @@ -647,7 +647,7 @@ impl DesktopRuntimeSupervisor { DesktopRuntimeEffectKind::TradeDecision, Some(TRADE_DECISION_OPERATION_KIND.to_owned()), actor_pubkey, - |receipt| DesktopRuntimeEffect::TradeDecision(receipt, request), + |receipt| DesktopRuntimeEffect::TradeDecision(receipt, Box::new(request)), ) } @@ -660,7 +660,7 @@ impl DesktopRuntimeSupervisor { DesktopRuntimeEffectKind::TradeCancellation, Some(TRADE_CANCELLATION_OPERATION_KIND.to_owned()), actor_pubkey, - |receipt| DesktopRuntimeEffect::TradeCancellation(receipt, request), + |receipt| DesktopRuntimeEffect::TradeCancellation(receipt, Box::new(request)), ) } @@ -774,52 +774,53 @@ impl From<&RadrootsSdkStoragePaths> for DesktopRuntimeStoragePaths { impl DesktopRuntimeIssue { fn from_sdk_error(error: &RadrootsSdkError) -> Self { Self { - code: error.code().to_owned(), - class: sdk_error_class_label(error), + code: error.code().into(), + class: sdk_error_class_label(error).into_boxed_str(), retryable: error.retryable(), - message: error.to_string(), + message: error.to_string().into_boxed_str(), recovery_actions: error .recovery_actions() .into_iter() .filter_map(|action| serde_json::to_value(action).ok()) .filter_map(|value| value.as_str().map(str::to_owned)) - .collect(), - detail_json: error.detail_json(), + .collect::<Vec<_>>() + .into_boxed_slice(), + detail_json: Box::new(error.detail_json()), } } fn runtime_error(code: &'static str, message: String) -> Self { Self { - code: code.to_owned(), - class: "runtime".to_owned(), + code: code.into(), + class: "runtime".into(), retryable: true, - message: message.clone(), - recovery_actions: vec!["retry_startup".to_owned()], - detail_json: json!({ + message: message.clone().into_boxed_str(), + recovery_actions: vec!["retry_startup".to_owned()].into_boxed_slice(), + detail_json: Box::new(json!({ "code": code, "class": "runtime", "retryable": true, "message": message, "recovery_actions": ["retry_startup"], "detail": {} - }), + })), } } fn lifecycle_blocked(state: DesktopRuntimeLifecycleState) -> Self { Self { - code: "sdk_lifecycle_busy".to_owned(), - class: "runtime".to_owned(), + code: "sdk_lifecycle_busy".into(), + class: "runtime".into(), retryable: true, - message: format!("app sdk runtime is {:?}", state), - recovery_actions: vec!["wait_for_sdk_lifecycle".to_owned()], - detail_json: json!({ + message: format!("app sdk runtime is {:?}", state).into_boxed_str(), + recovery_actions: vec!["wait_for_sdk_lifecycle".to_owned()].into_boxed_slice(), + detail_json: Box::new(json!({ "code": "sdk_lifecycle_busy", "class": "runtime", "retryable": true, "state": format!("{state:?}"), "recovery_actions": ["wait_for_sdk_lifecycle"] - }), + })), } } } @@ -1161,7 +1162,7 @@ fn run_desktop_runtime_worker( } DesktopRuntimeEffect::RestorePreflight(receipt, request) => { let result = match sdk.as_ref() { - Some(_) => run_restore_preflight(&runtime, &shared, &config, request), + Some(_) => run_restore_preflight(&runtime, &shared, &config, *request), None => Err(runtime_unavailable_issue(&shared)), }; finish_restore_preflight_result(&shared, receipt, result); @@ -1171,7 +1172,7 @@ fn run_desktop_runtime_worker( Err(issue) } else { match sdk.as_ref() { - Some(sdk) => enqueue_farm_publish_with_sdk(&runtime, sdk, request), + Some(sdk) => enqueue_farm_publish_with_sdk(&runtime, sdk, *request), None => Err(runtime_unavailable_issue(&shared)), } }; @@ -1182,7 +1183,7 @@ fn run_desktop_runtime_worker( Err(issue) } else { match sdk.as_ref() { - Some(sdk) => enqueue_listing_publish_with_sdk(&runtime, sdk, request), + Some(sdk) => enqueue_listing_publish_with_sdk(&runtime, sdk, *request), None => Err(runtime_unavailable_issue(&shared)), } }; @@ -1193,7 +1194,7 @@ fn run_desktop_runtime_worker( Err(issue) } else { match sdk.as_ref() { - Some(_) => trade_propose_with_sdk(&runtime, &config, request), + Some(_) => trade_propose_with_sdk(&runtime, &config, *request), None => Err(runtime_unavailable_issue(&shared)), } }; @@ -1204,7 +1205,7 @@ fn run_desktop_runtime_worker( Err(issue) } else { match sdk.as_ref() { - Some(_) => trade_decision_with_sdk(&runtime, &config, request), + Some(_) => trade_decision_with_sdk(&runtime, &config, *request), None => Err(runtime_unavailable_issue(&shared)), } }; @@ -1215,7 +1216,7 @@ fn run_desktop_runtime_worker( Err(issue) } else { match sdk.as_ref() { - Some(_) => trade_cancel_with_sdk(&runtime, &config, request), + Some(_) => trade_cancel_with_sdk(&runtime, &config, *request), None => Err(runtime_unavailable_issue(&shared)), } }; @@ -2062,8 +2063,7 @@ fn mark_projections_stale( DesktopRuntimeStartupMilestone::ProjectionsReady, false, ); - let projection_lifecycle = status.projection_lifecycle.clone(); - projection_lifecycle + status.projection_lifecycle.clone() } fn begin_projection_rebuild( @@ -2084,8 +2084,7 @@ fn begin_projection_rebuild( DesktopRuntimeStartupMilestone::ProjectionsReady, false, ); - let projection_lifecycle = status.projection_lifecycle.clone(); - projection_lifecycle + status.projection_lifecycle.clone() } fn complete_projection_rebuild( diff --git a/crates/signer/src/protocol.rs b/crates/signer/src/protocol.rs @@ -55,7 +55,7 @@ pub enum RadrootsAppRemoteSignerProgressUpdate { #[derive(Debug, Clone)] pub enum RadrootsAppRemoteSignerPendingPollOutcome { PendingApproval, - Approved(RadrootsAppRemoteSignerApprovedSession), + Approved(Box<RadrootsAppRemoteSignerApprovedSession>), TransportFailure { message: String }, Rejected { message: String }, FatalError { message: String }, @@ -554,16 +554,16 @@ fn classify_pending_poll_response( ) -> RadrootsAppRemoteSignerPendingPollOutcome { match response.into_pending_connection_poll_outcome() { RadrootsNostrConnectPendingConnectionPollOutcome::Approved(public_key) => { - RadrootsAppRemoteSignerPendingPollOutcome::Approved( + RadrootsAppRemoteSignerPendingPollOutcome::Approved(Box::new( RadrootsAppRemoteSignerApprovedSession { user_identity: RadrootsIdentityPublic::new(public_key), relays: Vec::new(), approved_permissions: RadrootsNostrConnectPermissions::default(), }, - ) + )) } RadrootsNostrConnectPendingConnectionPollOutcome::ApprovedCapability(capability) => { - RadrootsAppRemoteSignerPendingPollOutcome::Approved( + RadrootsAppRemoteSignerPendingPollOutcome::Approved(Box::new( RadrootsAppRemoteSignerApprovedSession { user_identity: RadrootsIdentityPublic::new(capability.user_public_key), relays: capability @@ -573,7 +573,7 @@ fn classify_pending_poll_response( .collect(), approved_permissions: capability.permissions, }, - ) + )) } RadrootsNostrConnectPendingConnectionPollOutcome::PendingApproval => { RadrootsAppRemoteSignerPendingPollOutcome::PendingApproval @@ -733,13 +733,17 @@ mod tests { }, )); - assert!(matches!( - outcome, - RadrootsAppRemoteSignerPendingPollOutcome::Approved( - RadrootsAppRemoteSignerApprovedSession { user_identity, approved_permissions, .. } - ) if user_identity.public_key_hex == fixture_public_key().to_hex() - && approved_permissions.to_string() == "sign_event:kind:1,switch_relays" - )); + let RadrootsAppRemoteSignerPendingPollOutcome::Approved(approved_session) = outcome else { + panic!("expected approved outcome"); + }; + assert_eq!( + approved_session.user_identity.public_key_hex, + fixture_public_key().to_hex() + ); + assert_eq!( + approved_session.approved_permissions.to_string(), + "sign_event:kind:1,switch_relays" + ); } #[test] diff --git a/crates/state/src/lib.rs b/crates/state/src/lib.rs @@ -144,23 +144,13 @@ pub struct PersonalWorkspaceProjection { pub orders: BuyerOrdersScreenProjection, } -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] pub struct ProductsScreenQueryState { pub search_query: String, pub filter: ProductsFilter, pub sort: ProductsSort, } -impl Default for ProductsScreenQueryState { - fn default() -> Self { - Self { - search_query: String::new(), - filter: ProductsFilter::default(), - sort: ProductsSort::default(), - } - } -} - impl ProductsScreenQueryState { pub fn new( search_query: impl Into<String>, @@ -242,16 +232,11 @@ impl ProductEditorSession { } } -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Default, Eq, PartialEq)] pub enum ProductEditorState { + #[default] Closed, - Open(ProductEditorSession), -} - -impl Default for ProductEditorState { - fn default() -> Self { - Self::Closed - } + Open(Box<ProductEditorSession>), } impl ProductEditorState { @@ -260,7 +245,10 @@ impl ProductEditorState { farm_readiness: &FarmWorkspaceReadinessProjection, farm_rules: &FarmRulesProjection, ) { - *self = Self::Open(ProductEditorSession::new_draft(farm_readiness, farm_rules)); + *self = Self::Open(Box::new(ProductEditorSession::new_draft( + farm_readiness, + farm_rules, + ))); } fn open_existing( @@ -270,12 +258,12 @@ impl ProductEditorState { farm_readiness: &FarmWorkspaceReadinessProjection, farm_rules: &FarmRulesProjection, ) { - *self = Self::Open(ProductEditorSession::existing( + *self = Self::Open(Box::new(ProductEditorSession::existing( product_id, draft, farm_readiness, farm_rules, - )); + ))); } fn replace_draft( @@ -1032,68 +1020,68 @@ pub enum AppStateCommand { ShowStartupSignerEntry, SetStartupSignerSourceInput(String), ResetLoggedOutStartup, - ReplaceIdentityProjection(AppIdentityProjection), - ReplaceSyncProjection(AppSyncProjection), - ReplacePersonalProjection(PersonalWorkspaceProjection), - ReplaceFarmSetupProjection(FarmSetupProjection), - ReplaceFarmRulesProjection(FarmRulesProjection), + ReplaceIdentityProjection(Box<AppIdentityProjection>), + ReplaceSyncProjection(Box<AppSyncProjection>), + ReplacePersonalProjection(Box<PersonalWorkspaceProjection>), + ReplaceFarmSetupProjection(Box<FarmSetupProjection>), + ReplaceFarmRulesProjection(Box<FarmRulesProjection>), SelectFarmSetupFlowStage(FarmSetupFlowStage), SetSettingsPreference { preference: SettingsPreference, enabled: bool, }, - ReplaceTodayAgenda(TodayAgendaProjection), + ReplaceTodayAgenda(Box<TodayAgendaProjection>), SetProductsSearchQuery(String), SelectProductsFilter(ProductsFilter), SelectProductsSort(ProductsSort), - ReplaceProductsList(ProductsListProjection), + ReplaceProductsList(Box<ProductsListProjection>), SelectOrdersFilter(OrdersFilter), SelectOrdersFulfillmentWindow(Option<FulfillmentWindowId>), - ReplaceOrdersList(OrdersListProjection), - ReplaceOrdersReminders(ReminderFeedProjection), - ReplaceReminderLog(ReminderLogProjection), - ReplaceOrderDetail(Option<OrderDetailProjection>), + ReplaceOrdersList(Box<OrdersListProjection>), + ReplaceOrdersReminders(Box<ReminderFeedProjection>), + ReplaceReminderLog(Box<ReminderLogProjection>), + ReplaceOrderDetail(Box<Option<OrderDetailProjection>>), SetPackDayFulfillmentWindow(Option<FulfillmentWindowId>), - ReplacePackDayProjection(PackDayProjection), - BeginPackDayExport(PackDayExportRequest), + ReplacePackDayProjection(Box<PackDayProjection>), + BeginPackDayExport(Box<PackDayExportRequest>), SucceedPackDayExport { - request: PackDayExportRequest, - bundle: PackDayExportBundle, + request: Box<PackDayExportRequest>, + bundle: Box<PackDayExportBundle>, }, FailPackDayExport { - request: PackDayExportRequest, + request: Box<PackDayExportRequest>, message: String, }, ResetPackDayExport, - BeginPackDayPrint(PackDayPrintRequest), - SucceedPackDayPrint(PackDayPrintRequest), - FailPackDayPrint(PackDayPrintRequest), + BeginPackDayPrint(Box<PackDayPrintRequest>), + SucceedPackDayPrint(Box<PackDayPrintRequest>), + FailPackDayPrint(Box<PackDayPrintRequest>), FailPackDayPrintWithKind { - request: PackDayPrintRequest, + request: Box<PackDayPrintRequest>, failure: PackDayPrintFailureKind, }, ResetPackDayPrint, - BeginPackDayBatchPrint(PackDayBatchPrintRequest), - SucceedPackDayBatchPrint(PackDayBatchPrintRequest), + BeginPackDayBatchPrint(Box<PackDayBatchPrintRequest>), + SucceedPackDayBatchPrint(Box<PackDayBatchPrintRequest>), FailPackDayBatchPrint { - request: PackDayBatchPrintRequest, + request: Box<PackDayBatchPrintRequest>, failed_artifact: Option<PackDayBatchPrintArtifact>, failure: PackDayBatchPrintFailureKind, }, ResetPackDayBatchPrint, - BeginPackDayHostHandoff(PackDayHostHandoffRequest), - SucceedPackDayHostHandoff(PackDayHostHandoffRequest), + BeginPackDayHostHandoff(Box<PackDayHostHandoffRequest>), + SucceedPackDayHostHandoff(Box<PackDayHostHandoffRequest>), FailPackDayHostHandoff { - request: PackDayHostHandoffRequest, + request: Box<PackDayHostHandoffRequest>, message: String, }, ResetPackDayHostHandoff, OpenNewProductEditor, OpenExistingProductEditor { product_id: ProductId, - draft: ProductEditorDraft, + draft: Box<ProductEditorDraft>, }, - ReplaceProductEditorDraft(ProductEditorDraft), + ReplaceProductEditorDraft(Box<ProductEditorDraft>), CloseProductEditor, } @@ -1127,23 +1115,23 @@ impl AppStateCommand { } pub fn replace_identity_projection(projection: AppIdentityProjection) -> Self { - Self::ReplaceIdentityProjection(projection) + Self::ReplaceIdentityProjection(Box::new(projection)) } pub fn replace_sync_projection(projection: AppSyncProjection) -> Self { - Self::ReplaceSyncProjection(projection) + Self::ReplaceSyncProjection(Box::new(projection)) } pub fn replace_personal_projection(projection: PersonalWorkspaceProjection) -> Self { - Self::ReplacePersonalProjection(projection) + Self::ReplacePersonalProjection(Box::new(projection)) } pub fn replace_farm_setup_projection(projection: FarmSetupProjection) -> Self { - Self::ReplaceFarmSetupProjection(projection) + Self::ReplaceFarmSetupProjection(Box::new(projection)) } pub fn replace_farm_rules_projection(projection: FarmRulesProjection) -> Self { - Self::ReplaceFarmRulesProjection(projection) + Self::ReplaceFarmRulesProjection(Box::new(projection)) } pub const fn select_farm_setup_flow_stage(stage: FarmSetupFlowStage) -> Self { @@ -1151,7 +1139,7 @@ impl AppStateCommand { } pub fn replace_today_agenda(projection: TodayAgendaProjection) -> Self { - Self::ReplaceTodayAgenda(projection) + Self::ReplaceTodayAgenda(Box::new(projection)) } pub fn set_products_search_query(search_query: impl Into<String>) -> Self { @@ -1167,7 +1155,7 @@ impl AppStateCommand { } pub fn replace_products_list(projection: ProductsListProjection) -> Self { - Self::ReplaceProductsList(projection) + Self::ReplaceProductsList(Box::new(projection)) } pub const fn select_orders_filter(filter: OrdersFilter) -> Self { @@ -1181,19 +1169,19 @@ impl AppStateCommand { } pub fn replace_orders_list(projection: OrdersListProjection) -> Self { - Self::ReplaceOrdersList(projection) + Self::ReplaceOrdersList(Box::new(projection)) } pub fn replace_orders_reminders(projection: ReminderFeedProjection) -> Self { - Self::ReplaceOrdersReminders(projection) + Self::ReplaceOrdersReminders(Box::new(projection)) } pub fn replace_reminder_log(projection: ReminderLogProjection) -> Self { - Self::ReplaceReminderLog(projection) + Self::ReplaceReminderLog(Box::new(projection)) } pub fn replace_order_detail(projection: Option<OrderDetailProjection>) -> Self { - Self::ReplaceOrderDetail(projection) + Self::ReplaceOrderDetail(Box::new(projection)) } pub fn set_pack_day_fulfillment_window( @@ -1203,23 +1191,26 @@ impl AppStateCommand { } pub fn replace_pack_day_projection(projection: PackDayProjection) -> Self { - Self::ReplacePackDayProjection(projection) + Self::ReplacePackDayProjection(Box::new(projection)) } pub fn begin_pack_day_export(request: PackDayExportRequest) -> Self { - Self::BeginPackDayExport(request) + Self::BeginPackDayExport(Box::new(request)) } pub fn succeed_pack_day_export( request: PackDayExportRequest, bundle: PackDayExportBundle, ) -> Self { - Self::SucceedPackDayExport { request, bundle } + Self::SucceedPackDayExport { + request: Box::new(request), + bundle: Box::new(bundle), + } } pub fn fail_pack_day_export(request: PackDayExportRequest, message: impl Into<String>) -> Self { Self::FailPackDayExport { - request, + request: Box::new(request), message: message.into(), } } @@ -1229,22 +1220,25 @@ impl AppStateCommand { } pub fn begin_pack_day_print(request: PackDayPrintRequest) -> Self { - Self::BeginPackDayPrint(request) + Self::BeginPackDayPrint(Box::new(request)) } pub fn succeed_pack_day_print(request: PackDayPrintRequest) -> Self { - Self::SucceedPackDayPrint(request) + Self::SucceedPackDayPrint(Box::new(request)) } pub fn fail_pack_day_print(request: PackDayPrintRequest) -> Self { - Self::FailPackDayPrint(request) + Self::FailPackDayPrint(Box::new(request)) } pub fn fail_pack_day_print_with_kind( request: PackDayPrintRequest, failure: PackDayPrintFailureKind, ) -> Self { - Self::FailPackDayPrintWithKind { request, failure } + Self::FailPackDayPrintWithKind { + request: Box::new(request), + failure, + } } pub const fn reset_pack_day_print() -> Self { @@ -1252,11 +1246,11 @@ impl AppStateCommand { } pub fn begin_pack_day_batch_print(request: PackDayBatchPrintRequest) -> Self { - Self::BeginPackDayBatchPrint(request) + Self::BeginPackDayBatchPrint(Box::new(request)) } pub fn succeed_pack_day_batch_print(request: PackDayBatchPrintRequest) -> Self { - Self::SucceedPackDayBatchPrint(request) + Self::SucceedPackDayBatchPrint(Box::new(request)) } pub fn fail_pack_day_batch_print( @@ -1265,7 +1259,7 @@ impl AppStateCommand { failure: PackDayBatchPrintFailureKind, ) -> Self { Self::FailPackDayBatchPrint { - request, + request: Box::new(request), failed_artifact, failure, } @@ -1276,11 +1270,11 @@ impl AppStateCommand { } pub fn begin_pack_day_host_handoff(request: PackDayHostHandoffRequest) -> Self { - Self::BeginPackDayHostHandoff(request) + Self::BeginPackDayHostHandoff(Box::new(request)) } pub fn succeed_pack_day_host_handoff(request: PackDayHostHandoffRequest) -> Self { - Self::SucceedPackDayHostHandoff(request) + Self::SucceedPackDayHostHandoff(Box::new(request)) } pub fn fail_pack_day_host_handoff( @@ -1288,7 +1282,7 @@ impl AppStateCommand { message: impl Into<String>, ) -> Self { Self::FailPackDayHostHandoff { - request, + request: Box::new(request), message: message.into(), } } @@ -1302,11 +1296,14 @@ impl AppStateCommand { } pub fn open_existing_product_editor(product_id: ProductId, draft: ProductEditorDraft) -> Self { - Self::OpenExistingProductEditor { product_id, draft } + Self::OpenExistingProductEditor { + product_id, + draft: Box::new(draft), + } } pub fn replace_product_editor_draft(draft: ProductEditorDraft) -> Self { - Self::ReplaceProductEditorDraft(draft) + Self::ReplaceProductEditorDraft(Box::new(draft)) } pub const fn close_product_editor() -> Self { @@ -1473,13 +1470,13 @@ impl AppStateRepository for FileBackedAppStateRepository { #[derive(Clone, Debug, Eq, PartialEq)] pub enum AppStatePersistenceRepository { - InMemory(InMemoryAppStateRepository), + InMemory(Box<InMemoryAppStateRepository>), FileBacked(FileBackedAppStateRepository), } impl AppStatePersistenceRepository { pub fn in_memory() -> Self { - Self::InMemory(InMemoryAppStateRepository::default()) + Self::InMemory(Box::default()) } pub fn file_backed(path: impl Into<PathBuf>) -> Self { @@ -1713,19 +1710,19 @@ fn apply_command(projection: &mut AppProjection, command: AppStateCommand) -> Ap projection.logged_out_startup = LoggedOutStartupProjection::default(); } AppStateCommand::ReplaceIdentityProjection(identity_projection) => { - projection.identity = identity_projection; + projection.identity = *identity_projection; } AppStateCommand::ReplaceSyncProjection(sync_projection) => { - projection.sync = sync_projection; + projection.sync = *sync_projection; } AppStateCommand::ReplacePersonalProjection(personal_projection) => { - projection.personal = personal_projection; + projection.personal = *personal_projection; } AppStateCommand::ReplaceFarmSetupProjection(farm_setup_projection) => { - projection.farm_setup = farm_setup_projection; + projection.farm_setup = *farm_setup_projection; } AppStateCommand::ReplaceFarmRulesProjection(farm_rules_projection) => { - projection.farm_rules = farm_rules_projection; + projection.farm_rules = *farm_rules_projection; } AppStateCommand::SelectFarmSetupFlowStage(flow_stage) => { projection.farm_setup_flow_stage = flow_stage; @@ -1741,7 +1738,7 @@ fn apply_command(projection: &mut AppProjection, command: AppStateCommand) -> Ap .set_preference(preference, enabled); } AppStateCommand::ReplaceTodayAgenda(today_projection) => { - projection.today = today_projection; + projection.today = *today_projection; } AppStateCommand::SetProductsSearchQuery(search_query) => { projection.products.query.set_search_query(search_query); @@ -1753,7 +1750,7 @@ fn apply_command(projection: &mut AppProjection, command: AppStateCommand) -> Ap projection.products.query.select_sort(sort); } AppStateCommand::ReplaceProductsList(products_projection) => { - projection.products.list = products_projection; + projection.products.list = *products_projection; } AppStateCommand::SelectOrdersFilter(filter) => { projection.orders.select_filter(filter); @@ -1764,16 +1761,16 @@ fn apply_command(projection: &mut AppProjection, command: AppStateCommand) -> Ap .select_fulfillment_window(fulfillment_window_id); } AppStateCommand::ReplaceOrdersList(orders_projection) => { - projection.orders.list = orders_projection; + projection.orders.list = *orders_projection; } AppStateCommand::ReplaceOrdersReminders(reminders_projection) => { - projection.orders.reminders = reminders_projection; + projection.orders.reminders = *reminders_projection; } AppStateCommand::ReplaceReminderLog(reminder_log_projection) => { - projection.reminder_log = reminder_log_projection; + projection.reminder_log = *reminder_log_projection; } AppStateCommand::ReplaceOrderDetail(order_detail_projection) => { - projection.orders.replace_detail(order_detail_projection); + projection.orders.replace_detail(*order_detail_projection); } AppStateCommand::SetPackDayFulfillmentWindow(fulfillment_window_id) => { projection @@ -1781,22 +1778,22 @@ fn apply_command(projection: &mut AppProjection, command: AppStateCommand) -> Ap .select_fulfillment_window(fulfillment_window_id); } AppStateCommand::ReplacePackDayProjection(pack_day_projection) => { - projection.pack_day.replace_projection(pack_day_projection); + projection.pack_day.replace_projection(*pack_day_projection); } AppStateCommand::BeginPackDayExport(request) => { projection .pack_day - .replace_export(PackDayExportProjection::running(request)); + .replace_export(PackDayExportProjection::running(*request)); } AppStateCommand::SucceedPackDayExport { request, bundle } => { projection .pack_day - .replace_export(PackDayExportProjection::succeeded(request, bundle)); + .replace_export(PackDayExportProjection::succeeded(*request, *bundle)); } AppStateCommand::FailPackDayExport { request, message } => { projection .pack_day - .replace_export(PackDayExportProjection::failed(request, message)); + .replace_export(PackDayExportProjection::failed(*request, message)); } AppStateCommand::ResetPackDayExport => { projection @@ -1806,22 +1803,22 @@ fn apply_command(projection: &mut AppProjection, command: AppStateCommand) -> Ap AppStateCommand::BeginPackDayPrint(request) => { projection .pack_day - .replace_print(PackDayPrintProjection::running(request)); + .replace_print(PackDayPrintProjection::running(*request)); } AppStateCommand::SucceedPackDayPrint(request) => { projection .pack_day - .replace_print(PackDayPrintProjection::succeeded(request)); + .replace_print(PackDayPrintProjection::succeeded(*request)); } AppStateCommand::FailPackDayPrint(request) => { projection .pack_day - .replace_print(PackDayPrintProjection::failed(request)); + .replace_print(PackDayPrintProjection::failed(*request)); } AppStateCommand::FailPackDayPrintWithKind { request, failure } => { projection .pack_day - .replace_print(PackDayPrintProjection::failed_with_kind(request, failure)); + .replace_print(PackDayPrintProjection::failed_with_kind(*request, failure)); } AppStateCommand::ResetPackDayPrint => { projection @@ -1831,12 +1828,12 @@ fn apply_command(projection: &mut AppProjection, command: AppStateCommand) -> Ap AppStateCommand::BeginPackDayBatchPrint(request) => { projection .pack_day - .replace_batch_print(PackDayBatchPrintProjection::running(request)); + .replace_batch_print(PackDayBatchPrintProjection::running(*request)); } AppStateCommand::SucceedPackDayBatchPrint(request) => { projection .pack_day - .replace_batch_print(PackDayBatchPrintProjection::succeeded(request)); + .replace_batch_print(PackDayBatchPrintProjection::succeeded(*request)); } AppStateCommand::FailPackDayBatchPrint { request, @@ -1846,7 +1843,7 @@ fn apply_command(projection: &mut AppProjection, command: AppStateCommand) -> Ap projection .pack_day .replace_batch_print(PackDayBatchPrintProjection::failed( - request, + *request, failed_artifact, failure, )); @@ -1859,17 +1856,17 @@ fn apply_command(projection: &mut AppProjection, command: AppStateCommand) -> Ap AppStateCommand::BeginPackDayHostHandoff(request) => { projection .pack_day - .replace_host_handoff(PackDayHostHandoffProjection::running(request)); + .replace_host_handoff(PackDayHostHandoffProjection::running(*request)); } AppStateCommand::SucceedPackDayHostHandoff(request) => { projection .pack_day - .replace_host_handoff(PackDayHostHandoffProjection::succeeded(request)); + .replace_host_handoff(PackDayHostHandoffProjection::succeeded(*request)); } AppStateCommand::FailPackDayHostHandoff { request, message } => { projection .pack_day - .replace_host_handoff(PackDayHostHandoffProjection::failed(request, message)); + .replace_host_handoff(PackDayHostHandoffProjection::failed(*request, message)); } AppStateCommand::ResetPackDayHostHandoff => { projection @@ -1885,14 +1882,14 @@ fn apply_command(projection: &mut AppProjection, command: AppStateCommand) -> Ap AppStateCommand::OpenExistingProductEditor { product_id, draft } => { projection.products.editor.open_existing( product_id, - draft, + *draft, &projection.farm_readiness, &projection.farm_rules, ); } AppStateCommand::ReplaceProductEditorDraft(draft) => { projection.products.editor.replace_draft( - draft, + *draft, &projection.farm_readiness, &projection.farm_rules, ); @@ -1922,9 +1919,7 @@ fn apply_command(projection: &mut AppProjection, command: AppStateCommand) -> Ap AppStateMutation::PersonalChanged } else if projection.products != before.products { AppStateMutation::ProductsChanged - } else if projection.orders != before.orders { - AppStateMutation::OrdersChanged - } else if projection.reminder_log != before.reminder_log { + } else if projection.orders != before.orders || projection.reminder_log != before.reminder_log { AppStateMutation::OrdersChanged } else if projection.pack_day != before.pack_day { AppStateMutation::PackDayChanged diff --git a/crates/ui/src/primitives.rs b/crates/ui/src/primitives.rs @@ -14,6 +14,8 @@ use std::rc::Rc; use crate::APP_UI_THEME; +type AppPillTabClickHandler = dyn Fn(&usize, &mut Window, &mut App); + #[derive(Clone, Copy, Debug, Eq, PartialEq)] enum AppButtonVariant { Secondary, @@ -378,7 +380,7 @@ pub fn app_pill_tabs( on_click: impl Fn(&usize, &mut Window, &mut App) + 'static, cx: &App, ) -> impl IntoElement { - let on_click: Rc<dyn Fn(&usize, &mut Window, &mut App)> = Rc::new(on_click); + let on_click: Rc<AppPillTabClickHandler> = Rc::new(on_click); let tabs = tabs.into_iter().collect::<Vec<_>>(); let height_px = APP_UI_THEME.components.app_button.sizing.height_px; let radius_px = height_px / 2.0; @@ -415,7 +417,7 @@ pub fn app_pill_tabs( .active(rgb(primary.active_background).into()) } else { ButtonCustomVariant::new(cx) - .color(transparent_black().into()) + .color(transparent_black()) .foreground(rgb(inactive_foreground).into()) .border(transparent_black()) .hover(rgb(inactive_hover_background).into()) @@ -673,11 +675,11 @@ pub fn app_checkbox_field( Button::new((checkbox_id, 0usize)) .custom( ButtonCustomVariant::new(cx) - .color(transparent_black().into()) + .color(transparent_black()) .foreground(rgb(APP_UI_THEME.foundation.text.primary).into()) .border(transparent_black()) - .hover(transparent_black().into()) - .active(transparent_black().into()), + .hover(transparent_black()) + .active(transparent_black()), ) .rounded(ButtonRounded::Size(px(0.0))) .w_full() @@ -1153,11 +1155,11 @@ pub fn app_button_text( Button::new(id) .custom( ButtonCustomVariant::new(cx) - .color(transparent_black().into()) + .color(transparent_black()) .foreground(rgb(APP_UI_THEME.foundation.text.secondary).into()) .border(transparent_black()) - .hover(transparent_black().into()) - .active(transparent_black().into()), + .hover(transparent_black()) + .active(transparent_black()), ) .rounded(ButtonRounded::Size(px(0.0))) .on_click(on_click) @@ -1212,7 +1214,7 @@ pub fn app_button_list_row( .color(if is_selected { selected_background.into() } else { - transparent_black().into() + transparent_black() }) .foreground(rgb(APP_UI_THEME.foundation.text.primary).into()) .border(transparent_black())