diff --git a/crates/client2/src/client2.rs b/crates/client2/src/client2.rs index e3c6ccfaec..1029b1d394 100644 --- a/crates/client2/src/client2.rs +++ b/crates/client2/src/client2.rs @@ -14,8 +14,8 @@ use futures::{ future::BoxFuture, AsyncReadExt, FutureExt, SinkExt, StreamExt, TryFutureExt as _, TryStreamExt, }; use gpui2::{ - serde_json, AnyHandle, AnyWeakHandle, AnyWindowHandle, AppContext, AsyncAppContext, Handle, - SemanticVersion, Task, ViewContext, WeakHandle, + serde_json, AnyHandle, AnyWeakHandle, AppContext, AsyncAppContext, Handle, SemanticVersion, + Task, WeakHandle, }; use lazy_static::lazy_static; use parking_lot::RwLock; @@ -235,7 +235,7 @@ struct ClientState { dyn Send + Sync + Fn( - Subscriber, + AnyHandle, Box, &Arc, AsyncAppContext, @@ -245,18 +245,10 @@ struct ClientState { } enum WeakSubscriber { - Entity { - handle: AnyWeakHandle, - window_handle: Option, - }, + Entity { handle: AnyWeakHandle }, Pending(Vec>), } -struct Subscriber { - handle: AnyHandle, - window_handle: Option, -} - #[derive(Clone, Debug)] pub struct Credentials { pub user_id: u64, @@ -310,7 +302,7 @@ impl Drop for Subscription { } } -pub struct PendingEntitySubscription { +pub struct PendingEntitySubscription { client: Arc, remote_id: u64, _entity_type: PhantomData, @@ -335,7 +327,6 @@ where id, WeakSubscriber::Entity { handle: model.downgrade().into(), - window_handle: None, }, ); drop(state); @@ -349,7 +340,10 @@ where } } -impl Drop for PendingEntitySubscription { +impl Drop for PendingEntitySubscription +where + T: 'static, +{ fn drop(&mut self) { if !self.consumed { let mut state = self.client.state.write(); @@ -494,7 +488,7 @@ impl Client { Status::ConnectionLost => { let this = self.clone(); let reconnect_interval = state.reconnect_interval; - state._reconnect_task = Some(cx.spawn(|cx| async move { + state._reconnect_task = Some(cx.spawn(move |cx| async move { #[cfg(any(test, feature = "test-support"))] let mut rng = StdRng::seed_from_u64(0); #[cfg(not(any(test, feature = "test-support")))] @@ -521,39 +515,21 @@ impl Client { })); } Status::SignedOut | Status::UpgradeRequired => { - cx.update(|cx| self.telemetry.set_authenticated_user_info(None, false, cx)); + cx.update(|cx| self.telemetry.set_authenticated_user_info(None, false, cx)) + .log_err(); state._reconnect_task.take(); } _ => {} } } - pub fn add_view_for_remote_entity( - self: &Arc, - remote_id: u64, - cx: &mut ViewContext, - ) -> Subscription - where - T: 'static + Send + Sync, - { - let id = (TypeId::of::(), remote_id); - self.state.write().entities_by_type_and_remote_id.insert( - id, - WeakSubscriber::Entity { - handle: cx.handle().into(), - window_handle: Some(cx.window_handle()), - }, - ); - Subscription::Entity { - client: Arc::downgrade(self), - id, - } - } - pub fn subscribe_to_entity( self: &Arc, remote_id: u64, - ) -> Result> { + ) -> Result> + where + T: 'static + Send + Sync, + { let id = (TypeId::of::(), remote_id); let mut state = self.state.write(); @@ -594,7 +570,7 @@ impl Client { let prev_handler = state.message_handlers.insert( message_type_id, Arc::new(move |subscriber, envelope, client, cx| { - let subscriber = subscriber.handle.downcast::().unwrap(); + let subscriber = subscriber.downcast::().unwrap(); let envelope = envelope.into_any().downcast::>().unwrap(); handler(subscriber, *envelope, client.clone(), cx).boxed() }), @@ -643,22 +619,15 @@ impl Client { F: 'static + Future> + Send, { self.add_entity_message_handler::(move |subscriber, message, client, cx| { - handler( - subscriber.handle.downcast::().unwrap(), - message, - client, - cx, - ) + handler(subscriber.downcast::().unwrap(), message, client, cx) }) } fn add_entity_message_handler(self: &Arc, handler: H) where M: EntityMessage, - H: 'static - + Send - + Sync - + Fn(Subscriber, TypedEnvelope, Arc, AsyncAppContext) -> F, + E: 'static + Send + Sync, + H: 'static + Send + Sync + Fn(AnyHandle, TypedEnvelope, Arc, AsyncAppContext) -> F, F: 'static + Future> + Send, { let model_type_id = TypeId::of::(); @@ -1079,7 +1048,7 @@ impl Client { write!(&mut url, "&impersonate={}", impersonate_login).unwrap(); } - cx.run_on_main(|cx| cx.open_url(&url))?.await; + cx.run_on_main(move |cx| cx.open_url(&url))?.await; // Receive the HTTP request from the user's browser. Retrieve the user id and encrypted // access token from the query params. @@ -1269,10 +1238,7 @@ impl Client { .get(&payload_type_id) .and_then(|handle| handle.upgrade()) { - subscriber = Some(Subscriber { - handle, - window_handle: None, - }); + subscriber = Some(handle); } else if let Some((extract_entity_id, entity_type_id)) = state.entity_id_extractors.get(&payload_type_id).zip( state @@ -1292,14 +1258,8 @@ impl Client { return; } Some(weak_subscriber @ _) => match weak_subscriber { - WeakSubscriber::Entity { - handle, - window_handle, - } => { - subscriber = handle.upgrade().map(|handle| Subscriber { - handle, - window_handle: window_handle.clone(), - }); + WeakSubscriber::Entity { handle } => { + subscriber = handle.upgrade(); } WeakSubscriber::Pending(_) => {} @@ -1331,7 +1291,7 @@ impl Client { sender_id, type_name ); - cx.spawn_on_main(|_| async move { + cx.spawn_on_main(move |_| async move { match future.await { Ok(()) => { log::debug!( diff --git a/crates/client2/src/telemetry.rs b/crates/client2/src/telemetry.rs index 8804ee60b9..acb129ea33 100644 --- a/crates/client2/src/telemetry.rs +++ b/crates/client2/src/telemetry.rs @@ -159,7 +159,7 @@ impl Telemetry { } let this = self.clone(); - cx.spawn(|mut cx| async move { + cx.spawn(|cx| async move { let mut system = System::new_all(); system.refresh_all(); diff --git a/crates/client2/src/user.rs b/crates/client2/src/user.rs index 2c96a09c3c..43e4846376 100644 --- a/crates/client2/src/user.rs +++ b/crates/client2/src/user.rs @@ -1,7 +1,7 @@ use super::{proto, Client, Status, TypedEnvelope}; use anyhow::{anyhow, Context, Result}; use collections::{hash_map::Entry, HashMap, HashSet}; -use feature_flags::FeatureFlagAppExt; +use feature_flags2::FeatureFlagAppExt; use futures::{channel::mpsc, future, AsyncReadExt, Future, StreamExt}; use gpui2::{AsyncAppContext, EventEmitter, Handle, ImageData, ModelContext, Task}; use postage::{sink::Sink, watch}; @@ -78,7 +78,7 @@ pub struct UserStore { client: Weak, http: Arc, _maintain_contacts: Task<()>, - _maintain_current_user: Task<()>, + _maintain_current_user: Task>, } #[derive(Clone)] @@ -167,28 +167,20 @@ impl UserStore { client.request(proto::GetPrivateUserInfo {}).log_err(); let (user, info) = futures::join!(fetch_user, fetch_metrics_id); - if let Some(info) = info { - cx.update(|cx| { + cx.update(|cx| { + if let Some(info) = info { cx.update_flags(info.staff, info.flags); client.telemetry.set_authenticated_user_info( Some(info.metrics_id.clone()), info.staff, cx, ) - }); - } else { - cx.read(|cx| { - client - .telemetry - .set_authenticated_user_info(None, false, cx) - }); - } + } + })?; current_user_tx.send(user).await.ok(); - this.update(&mut cx, |_, cx| { - cx.notify(); - }); + this.update(&mut cx, |_, cx| cx.notify())?; } } Status::SignedOut => { @@ -196,21 +188,20 @@ impl UserStore { this.update(&mut cx, |this, cx| { cx.notify(); this.clear_contacts() - }) + })? .await; } Status::ConnectionLost => { - if let Some(this) = this.upgrade() { - this.update(&mut cx, |this, cx| { - cx.notify(); - this.clear_contacts() - }) - .await; - } + this.update(&mut cx, |this, cx| { + cx.notify(); + this.clear_contacts() + })? + .await; } _ => {} } } + Ok(()) }), pending_contact_requests: Default::default(), } @@ -233,7 +224,7 @@ impl UserStore { count: message.payload.count, }); cx.notify(); - }); + })?; Ok(()) } @@ -243,7 +234,7 @@ impl UserStore { _: Arc, mut cx: AsyncAppContext, ) -> Result<()> { - this.update(&mut cx, |_, cx| cx.emit(Event::ShowContacts)); + this.update(&mut cx, |_, cx| cx.emit(Event::ShowContacts))?; Ok(()) } @@ -261,7 +252,7 @@ impl UserStore { this.update_contacts_tx .unbounded_send(UpdateContacts::Update(message.payload)) .unwrap(); - }); + })?; Ok(()) } @@ -297,6 +288,9 @@ impl UserStore { // Users are fetched in parallel above and cached in call to get_users // No need to paralellize here let mut updated_contacts = Vec::new(); + let this = this + .upgrade() + .ok_or_else(|| anyhow!("can't upgrade user store handle"))?; for contact in message.contacts { let should_notify = contact.should_notify; updated_contacts.push(( @@ -309,7 +303,9 @@ impl UserStore { for request in message.incoming_requests { incoming_requests.push({ let user = this - .update(&mut cx, |this, cx| this.get_user(request.requester_id, cx)) + .update(&mut cx, |this, cx| { + this.get_user(request.requester_id, cx) + })? .await?; (user, request.should_notify) }); @@ -318,7 +314,7 @@ impl UserStore { let mut outgoing_requests = Vec::new(); for requested_user_id in message.outgoing_requests { outgoing_requests.push( - this.update(&mut cx, |this, cx| this.get_user(requested_user_id, cx)) + this.update(&mut cx, |this, cx| this.get_user(requested_user_id, cx))? .await?, ); } @@ -398,7 +394,7 @@ impl UserStore { } cx.notify(); - }); + })?; Ok(()) }) @@ -494,7 +490,7 @@ impl UserStore { cx: &mut ModelContext, ) -> Task> { let client = self.client.upgrade(); - cx.spawn_weak(|_, _| async move { + cx.spawn(move |_, _| async move { client .ok_or_else(|| anyhow!("can't upgrade client reference"))? .request(proto::RespondToContactRequest { @@ -516,7 +512,7 @@ impl UserStore { *self.pending_contact_requests.entry(user_id).or_insert(0) += 1; cx.notify(); - cx.spawn(|this, mut cx| async move { + cx.spawn(move |this, mut cx| async move { let response = client .ok_or_else(|| anyhow!("can't upgrade client reference"))? .request(request) @@ -531,7 +527,7 @@ impl UserStore { } } cx.notify(); - }); + })?; response?; Ok(()) }) @@ -574,11 +570,11 @@ impl UserStore { }, cx, ) - }) + })? .await?; } - this.read_with(&cx, |this, _| { + this.update(&mut cx, |this, _| { user_ids .iter() .map(|user_id| { @@ -588,7 +584,7 @@ impl UserStore { .ok_or_else(|| anyhow!("user {} not found", user_id)) }) .collect() - }) + })? }) } @@ -614,7 +610,7 @@ impl UserStore { } let load_users = self.get_users(vec![user_id], cx); - cx.spawn(|this, mut cx| async move { + cx.spawn(move |this, mut cx| async move { load_users.await?; this.update(&mut cx, |this, _| { this.users @@ -700,7 +696,7 @@ impl Contact { let user = user_store .update(cx, |user_store, cx| { user_store.get_user(contact.user_id, cx) - }) + })? .await?; Ok(Self { user, diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index b4ef23edc5..cfd800fbe1 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -430,7 +430,6 @@ impl<'a, 'w> WindowContext<'a, 'w> { where G: 'static + Send + Sync, { - let global_type = TypeId::of::(); let mut global = self.app.lease_global::(); let result = f(global.as_mut(), self); self.app.set_global(global); diff --git a/crates/settings2/src/settings_file.rs b/crates/settings2/src/settings_file.rs index 936bcac0ad..56b75cc26d 100644 --- a/crates/settings2/src/settings_file.rs +++ b/crates/settings2/src/settings_file.rs @@ -2,7 +2,7 @@ use crate::{settings_store::SettingsStore, Setting}; use anyhow::Result; use fs::Fs; use futures::{channel::mpsc, StreamExt}; -use gpui2::{AppContext, Context, Executor}; +use gpui2::{AppContext, Executor}; use std::{ io::ErrorKind, path::{Path, PathBuf}, diff --git a/crates/storybook2/src/storybook2.rs b/crates/storybook2/src/storybook2.rs index 353e12f8c1..552e124c06 100644 --- a/crates/storybook2/src/storybook2.rs +++ b/crates/storybook2/src/storybook2.rs @@ -10,14 +10,13 @@ use std::sync::Arc; use clap::Parser; use gpui2::{ - div, px, size, view, AnyView, BorrowAppContext, Bounds, Context, Element, ViewContext, - WindowBounds, WindowOptions, + div, px, size, view, AnyView, Bounds, Context, Element, ViewContext, WindowBounds, + WindowOptions, }; use log::LevelFilter; use simplelog::SimpleLogger; use story_selector::ComponentStory; -use ui::prelude::*; -use ui::{themed, with_settings, FakeSettings}; +use ui::{prelude::*, themed}; use crate::assets::Assets; use crate::story_selector::StorySelector; @@ -67,13 +66,7 @@ fn main() { }, move |cx| { view( - cx.entity(|cx| { - cx.with_global(FakeSettings::default(), |cx| { - cx.with_global(theme.clone(), |cx| { - StoryWrapper::new(selector.story(cx), theme) - }) - }) - }), + cx.entity(|cx| StoryWrapper::new(selector.story(cx), theme)), StoryWrapper::render, ) }, @@ -87,27 +80,20 @@ fn main() { pub struct StoryWrapper { story: AnyView, theme: Theme, - settings: FakeSettings, } impl StoryWrapper { pub(crate) fn new(story: AnyView, theme: Theme) -> Self { - Self { - story, - theme, - settings: FakeSettings::default(), - } + Self { story, theme } } fn render(&mut self, cx: &mut ViewContext) -> impl Element { - with_settings(self.settings.clone(), cx, |cx| { - themed(self.theme.clone(), cx, |cx| { - div() - .flex() - .flex_col() - .size_full() - .child(self.story.clone()) - }) + themed(self.theme.clone(), cx, |cx| { + div() + .flex() + .flex_col() + .size_full() + .child(self.story.clone()) }) } } diff --git a/crates/ui2/src/settings.rs b/crates/ui2/src/settings.rs index c68e39e71c..5c88608c88 100644 --- a/crates/ui2/src/settings.rs +++ b/crates/ui2/src/settings.rs @@ -1,8 +1,6 @@ use std::ops::Deref; -use gpui2::{ - rems, AbsoluteLength, AnyElement, BorrowAppContext, Bounds, LayoutId, Pixels, WindowContext, -}; +use gpui2::{rems, AbsoluteLength, WindowContext}; use crate::prelude::*; @@ -72,78 +70,3 @@ impl Default for FakeSettings { } impl FakeSettings {} - -pub fn with_settings( - settings: FakeSettings, - cx: &mut ViewContext, - build_child: F, -) -> WithSettings -where - E: Element, - F: FnOnce(&mut ViewContext) -> E, -{ - let child = cx.with_global(settings.clone(), |cx| build_child(cx)); - WithSettings { settings, child } -} - -pub struct WithSettings { - pub(crate) settings: FakeSettings, - pub(crate) child: E, -} - -impl IntoAnyElement for WithSettings -where - E: Element, -{ - fn into_any(self) -> AnyElement { - AnyElement::new(self) - } -} - -impl Element for WithSettings { - type ViewState = E::ViewState; - type ElementState = E::ElementState; - - fn id(&self) -> Option { - None - } - - fn initialize( - &mut self, - view_state: &mut Self::ViewState, - element_state: Option, - cx: &mut ViewContext, - ) -> Self::ElementState { - cx.with_global(self.settings.clone(), |cx| { - self.child.initialize(view_state, element_state, cx) - }) - } - - fn layout( - &mut self, - view_state: &mut E::ViewState, - element_state: &mut Self::ElementState, - cx: &mut ViewContext, - ) -> LayoutId - where - Self: Sized, - { - cx.with_global(self.settings.clone(), |cx| { - self.child.layout(view_state, element_state, cx) - }) - } - - fn paint( - &mut self, - bounds: Bounds, - view_state: &mut Self::ViewState, - frame_state: &mut Self::ElementState, - cx: &mut ViewContext, - ) where - Self: Sized, - { - cx.with_global(self.settings.clone(), |cx| { - self.child.paint(bounds, view_state, frame_state, cx); - }); - } -} diff --git a/crates/ui2/src/theme.rs b/crates/ui2/src/theme.rs index 0054bb84be..dec773b08f 100644 --- a/crates/ui2/src/theme.rs +++ b/crates/ui2/src/theme.rs @@ -1,13 +1,12 @@ +use gpui2::{ + AnyElement, Bounds, Element, Hsla, IntoAnyElement, LayoutId, Pixels, Result, ViewContext, + WindowContext, +}; +use serde::{de::Visitor, Deserialize, Deserializer}; use std::collections::HashMap; use std::fmt; use std::sync::Arc; -use gpui2::{ - AnyElement, BorrowAppContext, Bounds, Element, Hsla, IntoAnyElement, LayoutId, Pixels, Result, - ViewContext, WindowContext, -}; -use serde::{de::Visitor, Deserialize, Deserializer}; - #[derive(Deserialize, Clone, Default, Debug)] pub struct Theme { pub name: String, @@ -138,7 +137,9 @@ where E: Element, F: FnOnce(&mut ViewContext) -> E, { - let child = cx.with_global(theme.clone(), |cx| build_child(cx)); + cx.default_global::().0.push(theme.clone()); + let child = build_child(cx); + cx.default_global::().0.pop(); Themed { theme, child } } @@ -156,6 +157,9 @@ where } } +#[derive(Default)] +struct ThemeStack(Vec); + impl Element for Themed { type ViewState = E::ViewState; type ElementState = E::ElementState; @@ -170,9 +174,10 @@ impl Element for Themed { element_state: Option, cx: &mut ViewContext, ) -> Self::ElementState { - cx.with_global(self.theme.clone(), |cx| { - self.child.initialize(view_state, element_state, cx) - }) + cx.default_global::().0.push(self.theme.clone()); + let element_state = self.child.initialize(view_state, element_state, cx); + cx.default_global::().0.pop(); + element_state } fn layout( @@ -184,9 +189,10 @@ impl Element for Themed { where Self: Sized, { - cx.with_global(self.theme.clone(), |cx| { - self.child.layout(view_state, element_state, cx) - }) + cx.default_global::().0.push(self.theme.clone()); + let layout_id = self.child.layout(view_state, element_state, cx); + cx.default_global::().0.pop(); + layout_id } fn paint( @@ -198,9 +204,9 @@ impl Element for Themed { ) where Self: Sized, { - cx.with_global(self.theme.clone(), |cx| { - self.child.paint(bounds, view_state, frame_state, cx); - }); + cx.default_global::().0.push(self.theme.clone()); + self.child.paint(bounds, view_state, frame_state, cx); + cx.default_global::().0.pop(); } } diff --git a/crates/zed2/src/main.rs b/crates/zed2/src/main.rs index bfec1bce29..91aed9e666 100644 --- a/crates/zed2/src/main.rs +++ b/crates/zed2/src/main.rs @@ -38,6 +38,7 @@ use util::{ http::HttpClient, paths, ResultExt, }; +use uuid::Uuid; use zed2::{ensure_only_instance, AppState, Assets, IsOnlyInstance}; // use zed2::{ // assets::Assets, @@ -59,7 +60,7 @@ fn main() { log::info!("========== starting zed =========="); let app = App::production(Arc::new(Assets)); - // let installation_id = app.background().block(installation_id()).ok(); + // let installation_id = app.executor().block(installation_id()).ok(); // let session_id = Uuid::new_v4().to_string(); // init_panic_hook(&app, installation_id.clone(), session_id.clone()); @@ -259,15 +260,10 @@ fn main() { } OpenRequest::CliConnection { connection } => { let app_state = app_state.clone(); - if cx - .spawn(move |cx| { - handle_cli_connection(connection, app_state.clone(), cx) - }) - .map(Task::detach) - .is_err() - { - break; - } + cx.spawn(move |cx| { + handle_cli_connection(connection, app_state.clone(), cx) + }) + .detach(); } OpenRequest::JoinChannel { channel_id: _ } => { // cx @@ -404,9 +400,7 @@ static PANIC_COUNT: AtomicU32 = AtomicU32::new(0); fn init_panic_hook(app: &App, installation_id: Option, session_id: String) { let is_pty = stdout_is_a_pty(); - let app_version = app.app_version().ok(); - let os_name = app.os_name(); - let os_version = app.os_version().ok(); + let app_metadata = app.metadata(); panic::set_hook(Box::new(move |info| { let prior_panic_count = PANIC_COUNT.fetch_add(1, Ordering::SeqCst); @@ -442,8 +436,8 @@ fn init_panic_hook(app: &App, installation_id: Option, session_id: Strin std::process::exit(-1); } - let app_version = client::ZED_APP_VERSION - .or(app_version) + let app_version = client2::ZED_APP_VERSION + .or(app_metadata.app_version) .map_or("dev".to_string(), |v| v.to_string()); let backtrace = Backtrace::new(); @@ -470,8 +464,11 @@ fn init_panic_hook(app: &App, installation_id: Option, session_id: Strin }), app_version: app_version.clone(), release_channel: RELEASE_CHANNEL.display_name().into(), - os_name: os_name.into(), - os_version: os_version.as_ref().map(SemanticVersion::to_string), + os_name: app_metadata.os_name.into(), + os_version: app_metadata + .os_version + .as_ref() + .map(SemanticVersion::to_string), architecture: env::consts::ARCH.into(), panicked_on: SystemTime::now() .duration_since(UNIX_EPOCH) @@ -507,11 +504,11 @@ fn init_panic_hook(app: &App, installation_id: Option, session_id: Strin } fn upload_previous_panics(http: Arc, cx: &mut AppContext) { - let telemetry_settings = *settings2::get::(cx); + let telemetry_settings = *settings2::get::(cx); cx.executor() .spawn(async move { - let panic_report_url = format!("{}/api/panic", &*client::ZED_SERVER_URL); + let panic_report_url = format!("{}/api/panic", &*client2::ZED_SERVER_URL); let mut children = smol::fs::read_dir(&*paths::LOGS_DIR).await?; while let Some(child) = children.next().await { let child = child?; @@ -554,7 +551,7 @@ fn upload_previous_panics(http: Arc, cx: &mut AppContext) { if let Some(panic) = panic { let body = serde_json::to_string(&PanicRequest { panic, - token: client::ZED_SECRET_CLIENT_TOKEN.into(), + token: client2::ZED_SECRET_CLIENT_TOKEN.into(), }) .unwrap();