fret_ui_kit/recipes/
resolve.rs1use fret_runtime::PlatformCapabilities;
2use fret_ui::{Theme, UiHost};
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum DegradationReason {
6 UnsupportedCapability,
7 BudgetExceeded,
8 ReducedMotion,
9 ReducedTransparency,
10 InvalidInput,
11}
12
13#[derive(Debug, Clone, Copy)]
14pub struct ResolveCtx<'a> {
15 pub theme: &'a Theme,
16 pub caps: &'a PlatformCapabilities,
17 pub prefers_reduced_motion: Option<bool>,
18 pub prefers_reduced_transparency: Option<bool>,
19}
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub struct RecipeDegradedEvent {
23 pub label: &'static str,
24 pub reason: DegradationReason,
25}
26
27#[derive(Debug, Default, Clone)]
28pub struct RecipeDiagnostics {
29 pub degraded: Vec<RecipeDegradedEvent>,
30}
31
32pub fn report_recipe_degraded<H: UiHost>(app: &mut H, event: RecipeDegradedEvent) {
33 app.with_global_mut_untracked(RecipeDiagnostics::default, |diag, _app| {
34 diag.degraded.push(event);
35 });
36}
37
38#[derive(Debug, Clone)]
39pub struct ResolvedWithFallback<T> {
40 pub value: T,
41 pub degraded: bool,
42 pub reason: Option<DegradationReason>,
43 pub label: Option<&'static str>,
44}
45
46impl<T> ResolvedWithFallback<T> {
47 pub fn ok(value: T) -> Self {
48 Self {
49 value,
50 degraded: false,
51 reason: None,
52 label: None,
53 }
54 }
55
56 pub fn degraded(value: T, label: &'static str, reason: DegradationReason) -> Self {
57 Self {
58 value,
59 degraded: true,
60 reason: Some(reason),
61 label: Some(label),
62 }
63 }
64
65 pub fn report_if_degraded<H: UiHost>(&self, app: &mut H) {
66 if !self.degraded {
67 return;
68 }
69 let (Some(label), Some(reason)) = (self.label, self.reason) else {
70 return;
71 };
72 report_recipe_degraded(app, RecipeDegradedEvent { label, reason });
73 }
74}