extension: Add ExtensionEvents
for listening to extension-related events (#26562)
This PR adds a new `ExtensionEvents` event bus that can be used to listen for extension-related events throughout the app. Today you need to have a handle to the `ExtensionStore` (which entails depending on `extension_host`) in order to listen for extension events. With this change subscribers only need to depend on `extension`, which has a leaner dependency graph. Release Notes: - N/A
This commit is contained in:
parent
ffcd023f83
commit
acf9b22466
7 changed files with 57 additions and 8 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -4639,6 +4639,7 @@ dependencies = [
|
||||||
"collections",
|
"collections",
|
||||||
"db",
|
"db",
|
||||||
"editor",
|
"editor",
|
||||||
|
"extension",
|
||||||
"extension_host",
|
"extension_host",
|
||||||
"feature_flags",
|
"feature_flags",
|
||||||
"fs",
|
"fs",
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
pub mod extension_builder;
|
pub mod extension_builder;
|
||||||
|
mod extension_events;
|
||||||
mod extension_host_proxy;
|
mod extension_host_proxy;
|
||||||
mod extension_manifest;
|
mod extension_manifest;
|
||||||
mod types;
|
mod types;
|
||||||
|
@ -14,12 +15,14 @@ use gpui::{App, Task};
|
||||||
use language::LanguageName;
|
use language::LanguageName;
|
||||||
use semantic_version::SemanticVersion;
|
use semantic_version::SemanticVersion;
|
||||||
|
|
||||||
|
pub use crate::extension_events::*;
|
||||||
pub use crate::extension_host_proxy::*;
|
pub use crate::extension_host_proxy::*;
|
||||||
pub use crate::extension_manifest::*;
|
pub use crate::extension_manifest::*;
|
||||||
pub use crate::types::*;
|
pub use crate::types::*;
|
||||||
|
|
||||||
/// Initializes the `extension` crate.
|
/// Initializes the `extension` crate.
|
||||||
pub fn init(cx: &mut App) {
|
pub fn init(cx: &mut App) {
|
||||||
|
extension_events::init(cx);
|
||||||
ExtensionHostProxy::default_global(cx);
|
ExtensionHostProxy::default_global(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
35
crates/extension/src/extension_events.rs
Normal file
35
crates/extension/src/extension_events.rs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
use gpui::{App, AppContext as _, Context, Entity, EventEmitter, Global, ReadGlobal as _};
|
||||||
|
|
||||||
|
pub fn init(cx: &mut App) {
|
||||||
|
let extension_events = cx.new(ExtensionEvents::new);
|
||||||
|
cx.set_global(GlobalExtensionEvents(extension_events));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GlobalExtensionEvents(Entity<ExtensionEvents>);
|
||||||
|
|
||||||
|
impl Global for GlobalExtensionEvents {}
|
||||||
|
|
||||||
|
/// An event bus for broadcasting extension-related events throughout the app.
|
||||||
|
pub struct ExtensionEvents;
|
||||||
|
|
||||||
|
impl ExtensionEvents {
|
||||||
|
/// Returns the global [`ExtensionEvents`].
|
||||||
|
pub fn global(cx: &App) -> Entity<Self> {
|
||||||
|
GlobalExtensionEvents::global(cx).0.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(_cx: &mut Context<Self>) -> Self {
|
||||||
|
Self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn emit(&mut self, event: Event, cx: &mut Context<Self>) {
|
||||||
|
cx.emit(event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub enum Event {
|
||||||
|
ExtensionsUpdated,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EventEmitter<Event> for ExtensionEvents {}
|
|
@ -14,7 +14,7 @@ use collections::{btree_map, BTreeMap, BTreeSet, HashMap, HashSet};
|
||||||
use extension::extension_builder::{CompileExtensionOptions, ExtensionBuilder};
|
use extension::extension_builder::{CompileExtensionOptions, ExtensionBuilder};
|
||||||
pub use extension::ExtensionManifest;
|
pub use extension::ExtensionManifest;
|
||||||
use extension::{
|
use extension::{
|
||||||
ExtensionContextServerProxy, ExtensionGrammarProxy, ExtensionHostProxy,
|
ExtensionContextServerProxy, ExtensionEvents, ExtensionGrammarProxy, ExtensionHostProxy,
|
||||||
ExtensionIndexedDocsProviderProxy, ExtensionLanguageProxy, ExtensionLanguageServerProxy,
|
ExtensionIndexedDocsProviderProxy, ExtensionLanguageProxy, ExtensionLanguageServerProxy,
|
||||||
ExtensionSlashCommandProxy, ExtensionSnippetProxy, ExtensionThemeProxy,
|
ExtensionSlashCommandProxy, ExtensionSnippetProxy, ExtensionThemeProxy,
|
||||||
};
|
};
|
||||||
|
@ -127,7 +127,6 @@ pub enum ExtensionOperation {
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
ExtensionsUpdated,
|
|
||||||
StartedReloading,
|
StartedReloading,
|
||||||
ExtensionInstalled(Arc<str>),
|
ExtensionInstalled(Arc<str>),
|
||||||
ExtensionFailedToLoad(Arc<str>),
|
ExtensionFailedToLoad(Arc<str>),
|
||||||
|
@ -1214,7 +1213,9 @@ impl ExtensionStore {
|
||||||
|
|
||||||
self.extension_index = new_index;
|
self.extension_index = new_index;
|
||||||
cx.notify();
|
cx.notify();
|
||||||
cx.emit(Event::ExtensionsUpdated);
|
ExtensionEvents::global(cx).update(cx, |this, cx| {
|
||||||
|
this.emit(extension::Event::ExtensionsUpdated, cx)
|
||||||
|
});
|
||||||
|
|
||||||
cx.spawn(|this, mut cx| async move {
|
cx.spawn(|this, mut cx| async move {
|
||||||
cx.background_spawn({
|
cx.background_spawn({
|
||||||
|
|
|
@ -780,6 +780,7 @@ fn init_test(cx: &mut TestAppContext) {
|
||||||
let store = SettingsStore::test(cx);
|
let store = SettingsStore::test(cx);
|
||||||
cx.set_global(store);
|
cx.set_global(store);
|
||||||
release_channel::init(SemanticVersion::default(), cx);
|
release_channel::init(SemanticVersion::default(), cx);
|
||||||
|
extension::init(cx);
|
||||||
theme::init(theme::LoadThemes::JustBase, cx);
|
theme::init(theme::LoadThemes::JustBase, cx);
|
||||||
Project::init_settings(cx);
|
Project::init_settings(cx);
|
||||||
ExtensionSettings::register(cx);
|
ExtensionSettings::register(cx);
|
||||||
|
|
|
@ -17,6 +17,7 @@ client.workspace = true
|
||||||
collections.workspace = true
|
collections.workspace = true
|
||||||
db.workspace = true
|
db.workspace = true
|
||||||
editor.workspace = true
|
editor.workspace = true
|
||||||
|
extension.workspace = true
|
||||||
extension_host.workspace = true
|
extension_host.workspace = true
|
||||||
feature_flags.workspace = true
|
feature_flags.workspace = true
|
||||||
fs.workspace = true
|
fs.workspace = true
|
||||||
|
|
|
@ -9,6 +9,7 @@ use std::{ops::Range, sync::Arc};
|
||||||
use client::{ExtensionMetadata, ExtensionProvides};
|
use client::{ExtensionMetadata, ExtensionProvides};
|
||||||
use collections::{BTreeMap, BTreeSet};
|
use collections::{BTreeMap, BTreeSet};
|
||||||
use editor::{Editor, EditorElement, EditorStyle};
|
use editor::{Editor, EditorElement, EditorStyle};
|
||||||
|
use extension::ExtensionEvents;
|
||||||
use extension_host::{ExtensionManifest, ExtensionOperation, ExtensionStore};
|
use extension_host::{ExtensionManifest, ExtensionOperation, ExtensionStore};
|
||||||
use feature_flags::FeatureFlagAppExt as _;
|
use feature_flags::FeatureFlagAppExt as _;
|
||||||
use fuzzy::{match_strings, StringMatchCandidate};
|
use fuzzy::{match_strings, StringMatchCandidate};
|
||||||
|
@ -212,7 +213,7 @@ pub struct ExtensionsPage {
|
||||||
query_editor: Entity<Editor>,
|
query_editor: Entity<Editor>,
|
||||||
query_contains_error: bool,
|
query_contains_error: bool,
|
||||||
provides_filter: Option<ExtensionProvides>,
|
provides_filter: Option<ExtensionProvides>,
|
||||||
_subscriptions: [gpui::Subscription; 2],
|
_subscriptions: Vec<gpui::Subscription>,
|
||||||
extension_fetch_task: Option<Task<()>>,
|
extension_fetch_task: Option<Task<()>>,
|
||||||
upsells: BTreeSet<Feature>,
|
upsells: BTreeSet<Feature>,
|
||||||
}
|
}
|
||||||
|
@ -226,15 +227,12 @@ impl ExtensionsPage {
|
||||||
cx.new(|cx| {
|
cx.new(|cx| {
|
||||||
let store = ExtensionStore::global(cx);
|
let store = ExtensionStore::global(cx);
|
||||||
let workspace_handle = workspace.weak_handle();
|
let workspace_handle = workspace.weak_handle();
|
||||||
let subscriptions = [
|
let subscriptions = vec![
|
||||||
cx.observe(&store, |_: &mut Self, _, cx| cx.notify()),
|
cx.observe(&store, |_: &mut Self, _, cx| cx.notify()),
|
||||||
cx.subscribe_in(
|
cx.subscribe_in(
|
||||||
&store,
|
&store,
|
||||||
window,
|
window,
|
||||||
move |this, _, event, window, cx| match event {
|
move |this, _, event, window, cx| match event {
|
||||||
extension_host::Event::ExtensionsUpdated => {
|
|
||||||
this.fetch_extensions_debounced(cx)
|
|
||||||
}
|
|
||||||
extension_host::Event::ExtensionInstalled(extension_id) => this
|
extension_host::Event::ExtensionInstalled(extension_id) => this
|
||||||
.on_extension_installed(
|
.on_extension_installed(
|
||||||
workspace_handle.clone(),
|
workspace_handle.clone(),
|
||||||
|
@ -245,6 +243,15 @@ impl ExtensionsPage {
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
cx.subscribe_in(
|
||||||
|
&ExtensionEvents::global(cx),
|
||||||
|
window,
|
||||||
|
move |this, _, event, _window, cx| match event {
|
||||||
|
extension::Event::ExtensionsUpdated => {
|
||||||
|
this.fetch_extensions_debounced(cx);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
let query_editor = cx.new(|cx| {
|
let query_editor = cx.new(|cx| {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue