diff --git a/crates/collections/src/collections.rs b/crates/collections/src/collections.rs index eb4e4d8462..bffa5c877a 100644 --- a/crates/collections/src/collections.rs +++ b/crates/collections/src/collections.rs @@ -23,11 +23,13 @@ pub type HashMap = std::collections::HashMap; #[cfg(not(feature = "test-support"))] pub type HashSet = std::collections::HashSet; +use std::any::TypeId; pub use std::collections::*; // NEW TYPES #[derive(Default)] pub struct CommandPaletteFilter { - pub filtered_namespaces: HashSet<&'static str>, + pub hidden_namespaces: HashSet<&'static str>, + pub hidden_action_types: HashSet, } diff --git a/crates/command_palette/src/command_palette.rs b/crates/command_palette/src/command_palette.rs index ce762876a4..356300052e 100644 --- a/crates/command_palette/src/command_palette.rs +++ b/crates/command_palette/src/command_palette.rs @@ -109,7 +109,7 @@ impl PickerDelegate for CommandPaletteDelegate { let filtered = cx.read(|cx| { if cx.has_global::() { let filter = cx.global::(); - filter.filtered_namespaces.contains(action.namespace()) + filter.hidden_namespaces.contains(action.namespace()) } else { false } @@ -430,7 +430,7 @@ mod tests { // Add namespace filter, and redeploy the palette cx.update(|cx| { cx.update_default_global::(|filter, _| { - filter.filtered_namespaces.insert("editor"); + filter.hidden_namespaces.insert("editor"); }) }); diff --git a/crates/command_palette2/src/command_palette.rs b/crates/command_palette2/src/command_palette.rs index 04688b0549..f94b5e77ca 100644 --- a/crates/command_palette2/src/command_palette.rs +++ b/crates/command_palette2/src/command_palette.rs @@ -49,7 +49,10 @@ impl CommandPalette { .filter_map(|action| { let name = gpui::remove_the_2(action.name()); let namespace = name.split("::").next().unwrap_or("malformed action name"); - if filter.is_some_and(|f| f.filtered_namespaces.contains(namespace)) { + if filter.is_some_and(|f| { + f.hidden_namespaces.contains(namespace) + || f.hidden_action_types.contains(&action.type_id()) + }) { return None; } @@ -429,7 +432,7 @@ mod tests { cx.update(|cx| { cx.set_global(CommandPaletteFilter::default()); cx.update_global::(|filter, _| { - filter.filtered_namespaces.insert("editor"); + filter.hidden_namespaces.insert("editor"); }) }); diff --git a/crates/copilot/src/copilot.rs b/crates/copilot/src/copilot.rs index 92d430e3fb..0c6f7e3907 100644 --- a/crates/copilot/src/copilot.rs +++ b/crates/copilot/src/copilot.rs @@ -58,16 +58,16 @@ pub fn init( cx.update_default_global::(move |filter, _cx| { match status { Status::Disabled => { - filter.filtered_namespaces.insert(COPILOT_NAMESPACE); - filter.filtered_namespaces.insert(COPILOT_AUTH_NAMESPACE); + filter.hidden_namespaces.insert(COPILOT_NAMESPACE); + filter.hidden_namespaces.insert(COPILOT_AUTH_NAMESPACE); } Status::Authorized => { - filter.filtered_namespaces.remove(COPILOT_NAMESPACE); - filter.filtered_namespaces.remove(COPILOT_AUTH_NAMESPACE); + filter.hidden_namespaces.remove(COPILOT_NAMESPACE); + filter.hidden_namespaces.remove(COPILOT_AUTH_NAMESPACE); } _ => { - filter.filtered_namespaces.insert(COPILOT_NAMESPACE); - filter.filtered_namespaces.remove(COPILOT_AUTH_NAMESPACE); + filter.hidden_namespaces.insert(COPILOT_NAMESPACE); + filter.hidden_namespaces.remove(COPILOT_AUTH_NAMESPACE); } } }); diff --git a/crates/copilot2/src/copilot2.rs b/crates/copilot2/src/copilot2.rs index b245472864..d23d25119b 100644 --- a/crates/copilot2/src/copilot2.rs +++ b/crates/copilot2/src/copilot2.rs @@ -22,6 +22,7 @@ use request::StatusNotification; use settings::SettingsStore; use smol::{fs, io::BufReader, stream::StreamExt}; use std::{ + any::TypeId, ffi::OsString, mem, ops::Range, @@ -32,13 +33,14 @@ use util::{ fs::remove_matching, github::latest_github_release, http::HttpClient, paths, ResultExt, }; -// todo!() -// const COPILOT_AUTH_NAMESPACE: &'static str = "copilot_auth"; -actions!(SignIn, SignOut); - -// todo!() -// const COPILOT_NAMESPACE: &'static str = "copilot"; -actions!(Suggest, NextSuggestion, PreviousSuggestion, Reinstall); +actions!( + Suggest, + NextSuggestion, + PreviousSuggestion, + Reinstall, + SignIn, + SignOut +); pub fn init( new_server_id: LanguageServerId, @@ -51,52 +53,63 @@ pub fn init( move |cx| Copilot::start(new_server_id, http, node_runtime, cx) }); cx.set_global(copilot.clone()); + cx.observe(&copilot, |handle, cx| { + let copilot_action_types = [ + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + TypeId::of::(), + ]; + let copilot_auth_action_types = [TypeId::of::(), TypeId::of::()]; - // TODO - // cx.observe(&copilot, |handle, cx| { - // let status = handle.read(cx).status(); - // cx.update_default_global::(move |filter, _cx| { - // match status { - // Status::Disabled => { - // filter.filtered_namespaces.insert(COPILOT_NAMESPACE); - // filter.filtered_namespaces.insert(COPILOT_AUTH_NAMESPACE); - // } - // Status::Authorized => { - // filter.filtered_namespaces.remove(COPILOT_NAMESPACE); - // filter.filtered_namespaces.remove(COPILOT_AUTH_NAMESPACE); - // } - // _ => { - // filter.filtered_namespaces.insert(COPILOT_NAMESPACE); - // filter.filtered_namespaces.remove(COPILOT_AUTH_NAMESPACE); - // } - // } - // }); - // }) - // .detach(); + let status = handle.read(cx).status(); + let filter = cx.default_global::(); - // sign_in::init(cx); - // cx.add_global_action(|_: &SignIn, cx| { - // if let Some(copilot) = Copilot::global(cx) { - // copilot - // .update(cx, |copilot, cx| copilot.sign_in(cx)) - // .detach_and_log_err(cx); - // } - // }); - // cx.add_global_action(|_: &SignOut, cx| { - // if let Some(copilot) = Copilot::global(cx) { - // copilot - // .update(cx, |copilot, cx| copilot.sign_out(cx)) - // .detach_and_log_err(cx); - // } - // }); + match status { + Status::Disabled => { + filter.hidden_action_types.extend(copilot_action_types); + filter.hidden_action_types.extend(copilot_auth_action_types); + } + Status::Authorized => { + for type_id in copilot_action_types + .iter() + .chain(&copilot_auth_action_types) + { + filter.hidden_action_types.remove(type_id); + } + } + _ => { + filter.hidden_action_types.extend(copilot_action_types); + for type_id in &copilot_auth_action_types { + filter.hidden_action_types.remove(type_id); + } + } + } + }) + .detach(); - // cx.add_global_action(|_: &Reinstall, cx| { - // if let Some(copilot) = Copilot::global(cx) { - // copilot - // .update(cx, |copilot, cx| copilot.reinstall(cx)) - // .detach(); - // } - // }); + sign_in::init(cx); + cx.on_action(|_: &SignIn, cx| { + if let Some(copilot) = Copilot::global(cx) { + copilot + .update(cx, |copilot, cx| copilot.sign_in(cx)) + .detach_and_log_err(cx); + } + }); + cx.on_action(|_: &SignOut, cx| { + if let Some(copilot) = Copilot::global(cx) { + copilot + .update(cx, |copilot, cx| copilot.sign_out(cx)) + .detach_and_log_err(cx); + } + }); + cx.on_action(|_: &Reinstall, cx| { + if let Some(copilot) = Copilot::global(cx) { + copilot + .update(cx, |copilot, cx| copilot.reinstall(cx)) + .detach(); + } + }); } enum CopilotServer { diff --git a/crates/copilot2/src/sign_in.rs b/crates/copilot2/src/sign_in.rs index 57f248aa52..7973d935af 100644 --- a/crates/copilot2/src/sign_in.rs +++ b/crates/copilot2/src/sign_in.rs @@ -9,314 +9,319 @@ // }; // use theme::ui::modal; -// #[derive(PartialEq, Eq, Debug, Clone)] -// struct CopyUserCode; +const COPILOT_SIGN_UP_URL: &'static str = "https://github.com/features/copilot"; -// #[derive(PartialEq, Eq, Debug, Clone)] -// struct OpenGithub; +use crate::{Copilot, Status}; +use gpui::{ + px, size, AppContext, Bounds, Div, GlobalPixels, Point, Render, ViewContext, VisualContext, + WindowBounds, WindowHandle, WindowKind, WindowOptions, +}; -// const COPILOT_SIGN_UP_URL: &'static str = "https://github.com/features/copilot"; +pub fn init(cx: &mut AppContext) { + if let Some(copilot) = Copilot::global(cx) { + let mut verification_window: Option> = None; + cx.observe(&copilot, move |copilot, cx| { + let status = copilot.read(cx).status(); -// pub fn init(cx: &mut AppContext) { -// if let Some(copilot) = Copilot::global(cx) { -// let mut verification_window: Option> = None; -// cx.observe(&copilot, move |copilot, cx| { -// let status = copilot.read(cx).status(); + match &status { + crate::Status::SigningIn { prompt } => { + if let Some(window) = verification_window.as_mut() { + let updated = window + .update(cx, |verification, cx| { + verification.set_status(status.clone(), cx); + cx.activate_window(); + }) + .is_ok(); + if !updated { + verification_window = Some(create_copilot_auth_window(cx, &status)); + } + } else if let Some(_prompt) = prompt { + verification_window = Some(create_copilot_auth_window(cx, &status)); + } + } + Status::Authorized | Status::Unauthorized => { + if let Some(window) = verification_window.as_ref() { + window + .update(cx, |verification, cx| { + verification.set_status(status, cx); + cx.activate(true); + cx.activate_window(); + }) + .ok(); + } + } + _ => { + if let Some(code_verification) = verification_window.take() { + code_verification.update(cx, |_, cx| cx.remove_window()); + } + } + } + }) + .detach(); + } +} -// match &status { -// crate::Status::SigningIn { prompt } => { -// if let Some(window) = verification_window.as_mut() { -// let updated = window -// .root(cx) -// .map(|root| { -// root.update(cx, |verification, cx| { -// verification.set_status(status.clone(), cx); -// cx.activate_window(); -// }) -// }) -// .is_some(); -// if !updated { -// verification_window = Some(create_copilot_auth_window(cx, &status)); -// } -// } else if let Some(_prompt) = prompt { -// verification_window = Some(create_copilot_auth_window(cx, &status)); -// } -// } -// Status::Authorized | Status::Unauthorized => { -// if let Some(window) = verification_window.as_ref() { -// if let Some(verification) = window.root(cx) { -// verification.update(cx, |verification, cx| { -// verification.set_status(status, cx); -// cx.platform().activate(true); -// cx.activate_window(); -// }); -// } -// } -// } -// _ => { -// if let Some(code_verification) = verification_window.take() { -// code_verification.update(cx, |cx| cx.remove_window()); -// } -// } -// } -// }) -// .detach(); -// } -// } +fn create_copilot_auth_window( + cx: &mut AppContext, + status: &Status, +) -> WindowHandle { + let window_size = size(GlobalPixels::from(280.), GlobalPixels::from(280.)); + let window_options = WindowOptions { + bounds: WindowBounds::Fixed(Bounds::new(Point::default(), window_size)), + titlebar: None, + center: true, + focus: true, + show: true, + kind: WindowKind::Normal, + is_movable: true, + display_id: None, + }; + cx.open_window(window_options, |cx| { + cx.build_view(|_| CopilotCodeVerification::new(status.clone())) + }) +} -// fn create_copilot_auth_window( -// cx: &mut AppContext, -// status: &Status, -// ) -> WindowHandle { -// let window_size = theme::current(cx).copilot.modal.dimensions(); -// let window_options = WindowOptions { -// bounds: WindowBounds::Fixed(RectF::new(Default::default(), window_size)), -// titlebar: None, -// center: true, -// focus: true, -// show: true, -// kind: WindowKind::Normal, -// is_movable: true, -// screen: None, -// }; -// cx.add_window(window_options, |_cx| { -// CopilotCodeVerification::new(status.clone()) -// }) -// } +pub struct CopilotCodeVerification { + status: Status, + connect_clicked: bool, +} -// pub struct CopilotCodeVerification { -// status: Status, -// connect_clicked: bool, -// } +impl CopilotCodeVerification { + pub fn new(status: Status) -> Self { + Self { + status, + connect_clicked: false, + } + } -// impl CopilotCodeVerification { -// pub fn new(status: Status) -> Self { -// Self { -// status, -// connect_clicked: false, -// } -// } + pub fn set_status(&mut self, status: Status, cx: &mut ViewContext) { + self.status = status; + cx.notify(); + } -// pub fn set_status(&mut self, status: Status, cx: &mut ViewContext) { -// self.status = status; -// cx.notify(); -// } + // fn render_device_code( + // data: &PromptUserDeviceFlow, + // style: &theme::Copilot, + // cx: &mut ViewContext, + // ) -> impl IntoAnyElement { + // let copied = cx + // .read_from_clipboard() + // .map(|item| item.text() == &data.user_code) + // .unwrap_or(false); -// fn render_device_code( -// data: &PromptUserDeviceFlow, -// style: &theme::Copilot, -// cx: &mut ViewContext, -// ) -> impl IntoAnyElement { -// let copied = cx -// .read_from_clipboard() -// .map(|item| item.text() == &data.user_code) -// .unwrap_or(false); + // let device_code_style = &style.auth.prompting.device_code; -// let device_code_style = &style.auth.prompting.device_code; + // MouseEventHandler::new::(0, cx, |state, _cx| { + // Flex::row() + // .with_child( + // Label::new(data.user_code.clone(), device_code_style.text.clone()) + // .aligned() + // .contained() + // .with_style(device_code_style.left_container) + // .constrained() + // .with_width(device_code_style.left), + // ) + // .with_child( + // Label::new( + // if copied { "Copied!" } else { "Copy" }, + // device_code_style.cta.style_for(state).text.clone(), + // ) + // .aligned() + // .contained() + // .with_style(*device_code_style.right_container.style_for(state)) + // .constrained() + // .with_width(device_code_style.right), + // ) + // .contained() + // .with_style(device_code_style.cta.style_for(state).container) + // }) + // .on_click(gpui::platform::MouseButton::Left, { + // let user_code = data.user_code.clone(); + // move |_, _, cx| { + // cx.platform() + // .write_to_clipboard(ClipboardItem::new(user_code.clone())); + // cx.notify(); + // } + // }) + // .with_cursor_style(gpui::platform::CursorStyle::PointingHand) + // } -// MouseEventHandler::new::(0, cx, |state, _cx| { -// Flex::row() -// .with_child( -// Label::new(data.user_code.clone(), device_code_style.text.clone()) -// .aligned() -// .contained() -// .with_style(device_code_style.left_container) -// .constrained() -// .with_width(device_code_style.left), -// ) -// .with_child( -// Label::new( -// if copied { "Copied!" } else { "Copy" }, -// device_code_style.cta.style_for(state).text.clone(), -// ) -// .aligned() -// .contained() -// .with_style(*device_code_style.right_container.style_for(state)) -// .constrained() -// .with_width(device_code_style.right), -// ) -// .contained() -// .with_style(device_code_style.cta.style_for(state).container) -// }) -// .on_click(gpui::platform::MouseButton::Left, { -// let user_code = data.user_code.clone(); -// move |_, _, cx| { -// cx.platform() -// .write_to_clipboard(ClipboardItem::new(user_code.clone())); -// cx.notify(); -// } -// }) -// .with_cursor_style(gpui::platform::CursorStyle::PointingHand) -// } + // fn render_prompting_modal( + // connect_clicked: bool, + // data: &PromptUserDeviceFlow, + // style: &theme::Copilot, + // cx: &mut ViewContext, + // ) -> AnyElement { + // enum ConnectButton {} -// fn render_prompting_modal( -// connect_clicked: bool, -// data: &PromptUserDeviceFlow, -// style: &theme::Copilot, -// cx: &mut ViewContext, -// ) -> AnyElement { -// enum ConnectButton {} + // Flex::column() + // .with_child( + // Flex::column() + // .with_children([ + // Label::new( + // "Enable Copilot by connecting", + // style.auth.prompting.subheading.text.clone(), + // ) + // .aligned(), + // Label::new( + // "your existing license.", + // style.auth.prompting.subheading.text.clone(), + // ) + // .aligned(), + // ]) + // .align_children_center() + // .contained() + // .with_style(style.auth.prompting.subheading.container), + // ) + // .with_child(Self::render_device_code(data, &style, cx)) + // .with_child( + // Flex::column() + // .with_children([ + // Label::new( + // "Paste this code into GitHub after", + // style.auth.prompting.hint.text.clone(), + // ) + // .aligned(), + // Label::new( + // "clicking the button below.", + // style.auth.prompting.hint.text.clone(), + // ) + // .aligned(), + // ]) + // .align_children_center() + // .contained() + // .with_style(style.auth.prompting.hint.container.clone()), + // ) + // .with_child(theme::ui::cta_button::( + // if connect_clicked { + // "Waiting for connection..." + // } else { + // "Connect to GitHub" + // }, + // style.auth.content_width, + // &style.auth.cta_button, + // cx, + // { + // let verification_uri = data.verification_uri.clone(); + // move |_, verification, cx| { + // cx.platform().open_url(&verification_uri); + // verification.connect_clicked = true; + // } + // }, + // )) + // .align_children_center() + // .into_any() + // } -// Flex::column() -// .with_child( -// Flex::column() -// .with_children([ -// Label::new( -// "Enable Copilot by connecting", -// style.auth.prompting.subheading.text.clone(), -// ) -// .aligned(), -// Label::new( -// "your existing license.", -// style.auth.prompting.subheading.text.clone(), -// ) -// .aligned(), -// ]) -// .align_children_center() -// .contained() -// .with_style(style.auth.prompting.subheading.container), -// ) -// .with_child(Self::render_device_code(data, &style, cx)) -// .with_child( -// Flex::column() -// .with_children([ -// Label::new( -// "Paste this code into GitHub after", -// style.auth.prompting.hint.text.clone(), -// ) -// .aligned(), -// Label::new( -// "clicking the button below.", -// style.auth.prompting.hint.text.clone(), -// ) -// .aligned(), -// ]) -// .align_children_center() -// .contained() -// .with_style(style.auth.prompting.hint.container.clone()), -// ) -// .with_child(theme::ui::cta_button::( -// if connect_clicked { -// "Waiting for connection..." -// } else { -// "Connect to GitHub" -// }, -// style.auth.content_width, -// &style.auth.cta_button, -// cx, -// { -// let verification_uri = data.verification_uri.clone(); -// move |_, verification, cx| { -// cx.platform().open_url(&verification_uri); -// verification.connect_clicked = true; -// } -// }, -// )) -// .align_children_center() -// .into_any() -// } + // fn render_enabled_modal( + // style: &theme::Copilot, + // cx: &mut ViewContext, + // ) -> AnyElement { + // enum DoneButton {} -// fn render_enabled_modal( -// style: &theme::Copilot, -// cx: &mut ViewContext, -// ) -> AnyElement { -// enum DoneButton {} + // let enabled_style = &style.auth.authorized; + // Flex::column() + // .with_child( + // Label::new("Copilot Enabled!", enabled_style.subheading.text.clone()) + // .contained() + // .with_style(enabled_style.subheading.container) + // .aligned(), + // ) + // .with_child( + // Flex::column() + // .with_children([ + // Label::new( + // "You can update your settings or", + // enabled_style.hint.text.clone(), + // ) + // .aligned(), + // Label::new( + // "sign out from the Copilot menu in", + // enabled_style.hint.text.clone(), + // ) + // .aligned(), + // Label::new("the status bar.", enabled_style.hint.text.clone()).aligned(), + // ]) + // .align_children_center() + // .contained() + // .with_style(enabled_style.hint.container), + // ) + // .with_child(theme::ui::cta_button::( + // "Done", + // style.auth.content_width, + // &style.auth.cta_button, + // cx, + // |_, _, cx| cx.remove_window(), + // )) + // .align_children_center() + // .into_any() + // } -// let enabled_style = &style.auth.authorized; -// Flex::column() -// .with_child( -// Label::new("Copilot Enabled!", enabled_style.subheading.text.clone()) -// .contained() -// .with_style(enabled_style.subheading.container) -// .aligned(), -// ) -// .with_child( -// Flex::column() -// .with_children([ -// Label::new( -// "You can update your settings or", -// enabled_style.hint.text.clone(), -// ) -// .aligned(), -// Label::new( -// "sign out from the Copilot menu in", -// enabled_style.hint.text.clone(), -// ) -// .aligned(), -// Label::new("the status bar.", enabled_style.hint.text.clone()).aligned(), -// ]) -// .align_children_center() -// .contained() -// .with_style(enabled_style.hint.container), -// ) -// .with_child(theme::ui::cta_button::( -// "Done", -// style.auth.content_width, -// &style.auth.cta_button, -// cx, -// |_, _, cx| cx.remove_window(), -// )) -// .align_children_center() -// .into_any() -// } + // fn render_unauthorized_modal( + // style: &theme::Copilot, + // cx: &mut ViewContext, + // ) -> AnyElement { + // let unauthorized_style = &style.auth.not_authorized; -// fn render_unauthorized_modal( -// style: &theme::Copilot, -// cx: &mut ViewContext, -// ) -> AnyElement { -// let unauthorized_style = &style.auth.not_authorized; + // Flex::column() + // .with_child( + // Flex::column() + // .with_children([ + // Label::new( + // "Enable Copilot by connecting", + // unauthorized_style.subheading.text.clone(), + // ) + // .aligned(), + // Label::new( + // "your existing license.", + // unauthorized_style.subheading.text.clone(), + // ) + // .aligned(), + // ]) + // .align_children_center() + // .contained() + // .with_style(unauthorized_style.subheading.container), + // ) + // .with_child( + // Flex::column() + // .with_children([ + // Label::new( + // "You must have an active copilot", + // unauthorized_style.warning.text.clone(), + // ) + // .aligned(), + // Label::new( + // "license to use it in Zed.", + // unauthorized_style.warning.text.clone(), + // ) + // .aligned(), + // ]) + // .align_children_center() + // .contained() + // .with_style(unauthorized_style.warning.container), + // ) + // .with_child(theme::ui::cta_button::( + // "Subscribe on GitHub", + // style.auth.content_width, + // &style.auth.cta_button, + // cx, + // |_, _, cx| { + // cx.remove_window(); + // cx.platform().open_url(COPILOT_SIGN_UP_URL) + // }, + // )) + // .align_children_center() + // .into_any() + // } +} -// Flex::column() -// .with_child( -// Flex::column() -// .with_children([ -// Label::new( -// "Enable Copilot by connecting", -// unauthorized_style.subheading.text.clone(), -// ) -// .aligned(), -// Label::new( -// "your existing license.", -// unauthorized_style.subheading.text.clone(), -// ) -// .aligned(), -// ]) -// .align_children_center() -// .contained() -// .with_style(unauthorized_style.subheading.container), -// ) -// .with_child( -// Flex::column() -// .with_children([ -// Label::new( -// "You must have an active copilot", -// unauthorized_style.warning.text.clone(), -// ) -// .aligned(), -// Label::new( -// "license to use it in Zed.", -// unauthorized_style.warning.text.clone(), -// ) -// .aligned(), -// ]) -// .align_children_center() -// .contained() -// .with_style(unauthorized_style.warning.container), -// ) -// .with_child(theme::ui::cta_button::( -// "Subscribe on GitHub", -// style.auth.content_width, -// &style.auth.cta_button, -// cx, -// |_, _, cx| { -// cx.remove_window(); -// cx.platform().open_url(COPILOT_SIGN_UP_URL) -// }, -// )) -// .align_children_center() -// .into_any() -// } -// } +impl Render for CopilotCodeVerification { + type Element = Div; + + fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + todo!() + } +} // impl Entity for CopilotCodeVerification { // type Event = (); diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 40594a7187..5ca35844d8 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -1486,10 +1486,18 @@ impl<'a> WindowContext<'a> { pub fn available_actions(&self) -> Vec> { if let Some(focus_id) = self.window.focus { - self.window + let mut actions = self + .window .current_frame .dispatch_tree - .available_actions(focus_id) + .available_actions(focus_id); + actions.extend( + self.app + .global_action_listeners + .keys() + .filter_map(|type_id| self.app.actions.build_action_type(type_id).ok()), + ); + actions } else { Vec::new() } diff --git a/crates/vim/src/vim.rs b/crates/vim/src/vim.rs index 8eee654331..7bfec95317 100644 --- a/crates/vim/src/vim.rs +++ b/crates/vim/src/vim.rs @@ -101,7 +101,7 @@ pub fn init(cx: &mut AppContext) { // will be initialized as disabled by default, so we filter its commands // out when starting up. cx.update_default_global::(|filter, _| { - filter.filtered_namespaces.insert("vim"); + filter.hidden_namespaces.insert("vim"); }); cx.update_global(|vim: &mut Vim, cx: &mut AppContext| { vim.set_enabled(settings::get::(cx).0, cx) @@ -477,9 +477,9 @@ impl Vim { cx.update_default_global::(|filter, _| { if self.enabled { - filter.filtered_namespaces.remove("vim"); + filter.hidden_namespaces.remove("vim"); } else { - filter.filtered_namespaces.insert("vim"); + filter.hidden_namespaces.insert("vim"); } });