Skip to main content

fret_runtime/window_command_gating/
snapshot.rs

1/// Window-scoped snapshot that aggregates data-only command gating inputs.
2use std::collections::HashMap;
3use std::sync::Arc;
4
5use crate::{CommandId, CommandMeta, CommandScope, InputContext, WhenExpr};
6
7///
8/// This is a consumption-focused seam intended for runner/platform and UI-kit layers:
9/// menus, command palette, shortcut help, etc.
10#[derive(Debug, Default, Clone)]
11pub struct WindowCommandGatingSnapshot {
12    input_ctx: InputContext,
13    key_contexts: Vec<Arc<str>>,
14    enabled_overrides: HashMap<CommandId, bool>,
15    action_availability: Option<Arc<HashMap<CommandId, bool>>>,
16}
17
18impl WindowCommandGatingSnapshot {
19    pub fn new(input_ctx: InputContext, enabled_overrides: HashMap<CommandId, bool>) -> Self {
20        Self {
21            input_ctx,
22            key_contexts: Vec::new(),
23            enabled_overrides,
24            action_availability: None,
25        }
26    }
27
28    pub fn input_ctx(&self) -> &InputContext {
29        &self.input_ctx
30    }
31
32    pub fn key_contexts(&self) -> &[Arc<str>] {
33        self.key_contexts.as_slice()
34    }
35
36    pub fn with_input_ctx(mut self, input_ctx: InputContext) -> Self {
37        self.input_ctx = input_ctx;
38        self
39    }
40
41    pub fn with_key_contexts(mut self, key_contexts: Vec<Arc<str>>) -> Self {
42        self.key_contexts = key_contexts;
43        self
44    }
45
46    pub fn enabled_overrides(&self) -> &HashMap<CommandId, bool> {
47        &self.enabled_overrides
48    }
49
50    pub fn action_availability(&self) -> Option<&HashMap<CommandId, bool>> {
51        self.action_availability.as_deref()
52    }
53
54    /// GPUI naming parity: query the latest published dispatch-path availability, if present.
55    ///
56    /// This is only meaningful for `CommandScope::Widget` commands; other scopes are not modeled
57    /// as dispatch-path availability entries today.
58    pub fn is_action_available(&self, command: &CommandId) -> Option<bool> {
59        self.action_availability
60            .as_ref()
61            .and_then(|map| map.get(command).copied())
62    }
63
64    pub fn with_action_availability(
65        mut self,
66        action_availability: Option<Arc<HashMap<CommandId, bool>>>,
67    ) -> Self {
68        self.action_availability = action_availability;
69        self
70    }
71
72    pub fn is_enabled_for_meta(
73        &self,
74        command: &CommandId,
75        scope: CommandScope,
76        when: Option<&WhenExpr>,
77    ) -> bool {
78        if scope == CommandScope::Widget
79            && let Some(map) = self.action_availability.as_ref()
80            && let Some(is_available) = map.get(command).copied()
81            && !is_available
82        {
83            return false;
84        }
85        if when.is_some_and(|w| !w.eval_with_key_contexts(&self.input_ctx, &self.key_contexts)) {
86            return false;
87        }
88        self.enabled_overrides.get(command).copied().unwrap_or(true)
89    }
90
91    pub fn is_enabled_for_command(&self, command: &CommandId, meta: &CommandMeta) -> bool {
92        self.is_enabled_for_meta(command, meta.scope, meta.when.as_ref())
93    }
94}