Merge branch 'zed2' of github.com:zed-industries/zed into zed2-workspace

KCaverly created

Change summary

crates/gpui2/src/app.rs                 |   2 
crates/gpui2/src/interactive.rs         |   2 
crates/gpui2/src/view.rs                | 179 ++++++++++++++++----------
crates/gpui2/src/window.rs              |   2 
crates/prettier2/src/prettier2.rs       |   8 
crates/project2/src/project2.rs         | 116 ++++++++++++++--
crates/project2/src/worktree.rs         |  12 
crates/storybook2/src/story_selector.rs |  76 +++++-----
crates/workspace2/src/dock.rs           |   2 
crates/workspace2/src/item.rs           |   4 
crates/workspace2/src/status_bar.rs     |   2 
crates/workspace2/src/toolbar.rs        |   2 
crates/zed2/src/main.rs                 |   5 
13 files changed, 265 insertions(+), 147 deletions(-)

Detailed changes

crates/gpui2/src/app.rs 🔗

@@ -904,7 +904,7 @@ impl MainThread<AppContext> {
             let handle = WindowHandle::new(id);
             let mut window = Window::new(handle.into(), options, cx);
             let root_view = build_root_view(&mut WindowContext::mutable(cx, &mut window));
-            window.root_view.replace(root_view.into_any());
+            window.root_view.replace(root_view.into());
             cx.windows.get_mut(id).unwrap().replace(window);
             handle
         })

crates/gpui2/src/interactive.rs 🔗

@@ -328,7 +328,7 @@ pub trait StatefulInteractive<V: 'static>: StatelessInteractive<V> {
         );
         self.stateful_interaction().drag_listener =
             Some(Box::new(move |view_state, cursor_offset, cx| AnyDrag {
-                view: listener(view_state, cx).into_any(),
+                view: listener(view_state, cx).into(),
                 cursor_offset,
             }));
         self

crates/gpui2/src/view.rs 🔗

@@ -1,14 +1,13 @@
 use crate::{
-    private::Sealed, AnyBox, AnyElement, AnyModel, AppContext, AvailableSpace, BorrowWindow,
-    Bounds, Component, Element, ElementId, Entity, EntityId, Flatten, LayoutId, Model, Pixels,
-    Size, ViewContext, VisualContext, WeakModel, WindowContext,
+    private::Sealed, AnyBox, AnyElement, AnyModel, AnyWeakModel, AppContext, AvailableSpace,
+    BorrowWindow, Bounds, Component, Element, ElementId, Entity, EntityId, Flatten, LayoutId,
+    Model, Pixels, Size, ViewContext, VisualContext, WeakModel, WindowContext,
 };
 use anyhow::{Context, Result};
 use std::{
     any::TypeId,
     hash::{Hash, Hasher},
     marker::PhantomData,
-    sync::Arc,
 };
 
 pub trait Render: 'static + Sized {
@@ -23,12 +22,6 @@ pub struct View<V> {
 
 impl<V> Sealed for View<V> {}
 
-impl<V: Render> View<V> {
-    pub fn into_any(self) -> AnyView {
-        AnyView(Arc::new(self))
-    }
-}
-
 impl<V: 'static> Entity<V> for View<V> {
     type Weak = WeakView<V>;
 
@@ -302,105 +295,149 @@ where
     }
 }
 
-#[derive(Clone)]
-pub struct AnyView(Arc<dyn ViewObject>);
+#[derive(Clone, Debug)]
+pub struct AnyView {
+    model: AnyModel,
+    initialize: fn(&AnyView, &mut WindowContext) -> AnyBox,
+    layout: fn(&AnyView, &mut AnyBox, &mut WindowContext) -> LayoutId,
+    paint: fn(&AnyView, &mut AnyBox, &mut WindowContext),
+}
 
 impl AnyView {
-    pub fn downcast<V: 'static>(self) -> Result<View<V>, AnyView> {
-        self.0
-            .model()
-            .downcast()
-            .map(|model| View { model })
-            .map_err(|_| self)
+    pub fn downgrade(&self) -> AnyWeakView {
+        AnyWeakView {
+            model: self.model.downgrade(),
+            initialize: self.initialize,
+            layout: self.layout,
+            paint: self.paint,
+        }
+    }
+
+    pub fn downcast<T: 'static>(self) -> Result<View<T>, Self> {
+        match self.model.downcast() {
+            Ok(model) => Ok(View { model }),
+            Err(model) => Err(Self {
+                model,
+                initialize: self.initialize,
+                layout: self.layout,
+                paint: self.paint,
+            }),
+        }
     }
 
     pub fn entity_type(&self) -> TypeId {
-        self.0.entity_type()
+        self.model.entity_type
     }
 
     pub(crate) fn draw(&self, available_space: Size<AvailableSpace>, cx: &mut WindowContext) {
-        let mut rendered_element = self.0.initialize(cx);
-        let layout_id = self.0.layout(&mut rendered_element, cx);
+        let mut rendered_element = (self.initialize)(self, cx);
+        let layout_id = (self.layout)(self, &mut rendered_element, cx);
         cx.window
             .layout_engine
             .compute_layout(layout_id, available_space);
-        let bounds = cx.window.layout_engine.layout_bounds(layout_id);
-        self.0.paint(bounds, &mut rendered_element, cx);
-    }
-}
-
-impl<ParentV: 'static> Component<ParentV> for AnyView {
-    fn render(self) -> AnyElement<ParentV> {
-        AnyElement::new(EraseAnyViewState {
-            view: self,
-            parent_view_state_type: PhantomData,
-        })
+        (self.paint)(self, &mut rendered_element, cx);
     }
 }
 
-impl std::fmt::Debug for AnyView {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        self.0.debug(f)
-    }
-}
-
-struct EraseAnyViewState<ParentViewState> {
-    view: AnyView,
-    parent_view_state_type: PhantomData<ParentViewState>,
-}
-
-unsafe impl<ParentV> Send for EraseAnyViewState<ParentV> {}
-
-impl<ParentV: 'static> Component<ParentV> for EraseAnyViewState<ParentV> {
-    fn render(self) -> AnyElement<ParentV> {
+impl<V: 'static> Component<V> for AnyView {
+    fn render(self) -> AnyElement<V> {
         AnyElement::new(self)
     }
 }
 
-impl<T, E> Render for T
-where
-    T: 'static + FnMut(&mut WindowContext) -> E,
-    E: 'static + Send + Element<T>,
-{
-    type Element = E;
-
-    fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
-        (self)(cx)
+impl<V: Render> From<View<V>> for AnyView {
+    fn from(value: View<V>) -> Self {
+        AnyView {
+            model: value.model.into_any(),
+            initialize: |view, cx| {
+                cx.with_element_id(view.model.entity_id, |_, cx| {
+                    let view = view.clone().downcast::<V>().unwrap();
+                    Box::new(AnyElement::new(
+                        view.update(cx, |view, cx| Render::render(view, cx)),
+                    ))
+                })
+            },
+            layout: |view, element, cx| {
+                cx.with_element_id(view.model.entity_id, |_, cx| {
+                    let view = view.clone().downcast::<V>().unwrap();
+                    let element = element.downcast_mut::<AnyElement<V>>().unwrap();
+                    view.update(cx, |view, cx| element.layout(view, cx))
+                })
+            },
+            paint: |view, element, cx| {
+                cx.with_element_id(view.model.entity_id, |_, cx| {
+                    let view = view.clone().downcast::<V>().unwrap();
+                    let element = element.downcast_mut::<AnyElement<V>>().unwrap();
+                    view.update(cx, |view, cx| element.paint(view, cx))
+                })
+            },
+        }
     }
 }
 
-impl<ParentV: 'static> Element<ParentV> for EraseAnyViewState<ParentV> {
+impl<ParentViewState: 'static> Element<ParentViewState> for AnyView {
     type ElementState = AnyBox;
 
     fn id(&self) -> Option<ElementId> {
-        Some(self.view.0.entity_id().into())
+        Some(self.model.entity_id.into())
     }
 
     fn initialize(
         &mut self,
-        _: &mut ParentV,
-        _: Option<Self::ElementState>,
-        cx: &mut ViewContext<ParentV>,
+        _view_state: &mut ParentViewState,
+        _element_state: Option<Self::ElementState>,
+        cx: &mut ViewContext<ParentViewState>,
     ) -> Self::ElementState {
-        self.view.0.initialize(cx)
+        (self.initialize)(self, cx)
     }
 
     fn layout(
         &mut self,
-        _: &mut ParentV,
-        element: &mut Self::ElementState,
-        cx: &mut ViewContext<ParentV>,
+        _view_state: &mut ParentViewState,
+        rendered_element: &mut Self::ElementState,
+        cx: &mut ViewContext<ParentViewState>,
     ) -> LayoutId {
-        self.view.0.layout(element, cx)
+        (self.layout)(self, rendered_element, cx)
     }
 
     fn paint(
         &mut self,
-        bounds: Bounds<Pixels>,
-        _: &mut ParentV,
-        element: &mut Self::ElementState,
-        cx: &mut ViewContext<ParentV>,
+        _bounds: Bounds<Pixels>,
+        _view_state: &mut ParentViewState,
+        rendered_element: &mut Self::ElementState,
+        cx: &mut ViewContext<ParentViewState>,
     ) {
-        self.view.0.paint(bounds, element, cx)
+        (self.paint)(self, rendered_element, cx)
+    }
+}
+
+pub struct AnyWeakView {
+    model: AnyWeakModel,
+    initialize: fn(&AnyView, &mut WindowContext) -> AnyBox,
+    layout: fn(&AnyView, &mut AnyBox, &mut WindowContext) -> LayoutId,
+    paint: fn(&AnyView, &mut AnyBox, &mut WindowContext),
+}
+
+impl AnyWeakView {
+    pub fn upgrade(&self) -> Option<AnyView> {
+        let model = self.model.upgrade()?;
+        Some(AnyView {
+            model,
+            initialize: self.initialize,
+            layout: self.layout,
+            paint: self.paint,
+        })
+    }
+}
+
+impl<T, E> Render for T
+where
+    T: 'static + FnMut(&mut WindowContext) -> E,
+    E: 'static + Send + Element<T>,
+{
+    type Element = E;
+
+    fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
+        (self)(cx)
     }
 }

crates/gpui2/src/window.rs 🔗

@@ -1003,7 +1003,7 @@ impl<'a, 'w> WindowContext<'a, 'w> {
                     self.window.mouse_position = position;
                     if self.active_drag.is_none() {
                         self.active_drag = Some(AnyDrag {
-                            view: self.build_view(|_| files).into_any(),
+                            view: self.build_view(|_| files).into(),
                             cursor_offset: position,
                         });
                     }

crates/prettier2/src/prettier2.rs 🔗

@@ -44,6 +44,9 @@ pub const PRETTIER_SERVER_JS: &str = include_str!("./prettier_server.js");
 const PRETTIER_PACKAGE_NAME: &str = "prettier";
 const TAILWIND_PRETTIER_PLUGIN_PACKAGE_NAME: &str = "prettier-plugin-tailwindcss";
 
+#[cfg(any(test, feature = "test-support"))]
+pub const FORMAT_SUFFIX: &str = "\nformatted by test prettier";
+
 impl Prettier {
     pub const CONFIG_FILE_NAMES: &'static [&'static str] = &[
         ".prettierrc",
@@ -60,9 +63,6 @@ impl Prettier {
         ".editorconfig",
     ];
 
-    #[cfg(any(test, feature = "test-support"))]
-    pub const FORMAT_SUFFIX: &str = "\nformatted by test prettier";
-
     pub async fn locate(
         starting_path: Option<LocateStart>,
         fs: Arc<dyn Fs>,
@@ -328,7 +328,7 @@ impl Prettier {
             #[cfg(any(test, feature = "test-support"))]
             Self::Test(_) => Ok(buffer
                 .update(cx, |buffer, cx| {
-                    let formatted_text = buffer.text() + Self::FORMAT_SUFFIX;
+                    let formatted_text = buffer.text() + FORMAT_SUFFIX;
                     buffer.diff(formatted_text, cx)
                 })?
                 .await),

crates/project2/src/project2.rs 🔗

@@ -54,7 +54,7 @@ use lsp_command::*;
 use node_runtime::NodeRuntime;
 use parking_lot::Mutex;
 use postage::watch;
-use prettier2::{LocateStart, Prettier, PRETTIER_SERVER_FILE, PRETTIER_SERVER_JS};
+use prettier2::{LocateStart, Prettier};
 use project_settings::{LspSettings, ProjectSettings};
 use rand::prelude::*;
 use search::SearchQuery;
@@ -80,16 +80,15 @@ use std::{
     time::{Duration, Instant},
 };
 use terminals::Terminals;
-use text::{Anchor, LineEnding, Rope};
+use text::Anchor;
 use util::{
-    debug_panic, defer,
-    http::HttpClient,
-    merge_json_value_into,
-    paths::{DEFAULT_PRETTIER_DIR, LOCAL_SETTINGS_RELATIVE_PATH},
-    post_inc, ResultExt, TryFutureExt as _,
+    debug_panic, defer, http::HttpClient, merge_json_value_into,
+    paths::LOCAL_SETTINGS_RELATIVE_PATH, post_inc, ResultExt, TryFutureExt as _,
 };
 
 pub use fs2::*;
+#[cfg(any(test, feature = "test-support"))]
+pub use prettier2::FORMAT_SUFFIX as TEST_PRETTIER_FORMAT_SUFFIX;
 pub use worktree::*;
 
 const MAX_SERVER_REINSTALL_ATTEMPT_COUNT: u64 = 4;
@@ -163,12 +162,20 @@ pub struct Project {
     copilot_log_subscription: Option<lsp2::Subscription>,
     current_lsp_settings: HashMap<Arc<str>, LspSettings>,
     node: Option<Arc<dyn NodeRuntime>>,
+    #[cfg(not(any(test, feature = "test-support")))]
+    default_prettier: Option<DefaultPrettier>,
     prettier_instances: HashMap<
         (Option<WorktreeId>, PathBuf),
         Shared<Task<Result<Arc<Prettier>, Arc<anyhow::Error>>>>,
     >,
 }
 
+#[cfg(not(any(test, feature = "test-support")))]
+struct DefaultPrettier {
+    installation_process: Option<Shared<Task<()>>>,
+    installed_plugins: HashSet<&'static str>,
+}
+
 struct DelayedDebounced {
     task: Option<Task<()>>,
     cancel_channel: Option<oneshot::Sender<()>>,
@@ -679,6 +686,8 @@ impl Project {
                 copilot_log_subscription: None,
                 current_lsp_settings: ProjectSettings::get_global(cx).lsp.clone(),
                 node: Some(node),
+                #[cfg(not(any(test, feature = "test-support")))]
+                default_prettier: None,
                 prettier_instances: HashMap::default(),
             }
         })
@@ -780,6 +789,8 @@ impl Project {
                 copilot_log_subscription: None,
                 current_lsp_settings: ProjectSettings::get_global(cx).lsp.clone(),
                 node: None,
+                #[cfg(not(any(test, feature = "test-support")))]
+                default_prettier: None,
                 prettier_instances: HashMap::default(),
             };
             for worktree in worktrees {
@@ -8553,8 +8564,20 @@ impl Project {
         }
     }
 
+    #[cfg(any(test, feature = "test-support"))]
     fn install_default_formatters(
-        &self,
+        &mut self,
+        _: Option<WorktreeId>,
+        _: &Language,
+        _: &LanguageSettings,
+        _: &mut ModelContext<Self>,
+    ) -> Task<anyhow::Result<()>> {
+        Task::ready(Ok(()))
+    }
+
+    #[cfg(not(any(test, feature = "test-support")))]
+    fn install_default_formatters(
+        &mut self,
         worktree: Option<WorktreeId>,
         new_language: &Language,
         language_settings: &LanguageSettings,
@@ -8583,22 +8606,76 @@ impl Project {
             return Task::ready(Ok(()));
         };
 
-        let default_prettier_dir = DEFAULT_PRETTIER_DIR.as_path();
+        let mut plugins_to_install = prettier_plugins;
+        let (mut install_success_tx, mut install_success_rx) =
+            futures::channel::mpsc::channel::<HashSet<&'static str>>(1);
+        let new_installation_process = cx
+            .spawn(|this, mut cx| async move {
+                if let Some(installed_plugins) = install_success_rx.next().await {
+                    this.update(&mut cx, |this, _| {
+                        let default_prettier =
+                            this.default_prettier
+                                .get_or_insert_with(|| DefaultPrettier {
+                                    installation_process: None,
+                                    installed_plugins: HashSet::default(),
+                                });
+                        if !installed_plugins.is_empty() {
+                            log::info!("Installed new prettier plugins: {installed_plugins:?}");
+                            default_prettier.installed_plugins.extend(installed_plugins);
+                        }
+                    })
+                    .ok();
+                }
+            })
+            .shared();
+        let previous_installation_process =
+            if let Some(default_prettier) = &mut self.default_prettier {
+                plugins_to_install
+                    .retain(|plugin| !default_prettier.installed_plugins.contains(plugin));
+                if plugins_to_install.is_empty() {
+                    return Task::ready(Ok(()));
+                }
+                std::mem::replace(
+                    &mut default_prettier.installation_process,
+                    Some(new_installation_process.clone()),
+                )
+            } else {
+                None
+            };
+
+        let default_prettier_dir = util::paths::DEFAULT_PRETTIER_DIR.as_path();
         let already_running_prettier = self
             .prettier_instances
             .get(&(worktree, default_prettier_dir.to_path_buf()))
             .cloned();
-
         let fs = Arc::clone(&self.fs);
-        cx.executor()
-            .spawn(async move {
-                let prettier_wrapper_path = default_prettier_dir.join(PRETTIER_SERVER_FILE);
+        cx.spawn_on_main(move |this, mut cx| async move {
+            if let Some(previous_installation_process) = previous_installation_process {
+                previous_installation_process.await;
+            }
+            let mut everything_was_installed = false;
+            this.update(&mut cx, |this, _| {
+                match &mut this.default_prettier {
+                    Some(default_prettier) => {
+                        plugins_to_install
+                            .retain(|plugin| !default_prettier.installed_plugins.contains(plugin));
+                        everything_was_installed = plugins_to_install.is_empty();
+                    },
+                    None => this.default_prettier = Some(DefaultPrettier { installation_process: Some(new_installation_process), installed_plugins: HashSet::default() }),
+                }
+            })?;
+            if everything_was_installed {
+                return Ok(());
+            }
+
+            cx.spawn(move |_| async move {
+                let prettier_wrapper_path = default_prettier_dir.join(prettier2::PRETTIER_SERVER_FILE);
                 // method creates parent directory if it doesn't exist
-                fs.save(&prettier_wrapper_path, &Rope::from(PRETTIER_SERVER_JS), LineEnding::Unix).await
-                .with_context(|| format!("writing {PRETTIER_SERVER_FILE} file at {prettier_wrapper_path:?}"))?;
+                fs.save(&prettier_wrapper_path, &text::Rope::from(prettier2::PRETTIER_SERVER_JS), text::LineEnding::Unix).await
+                .with_context(|| format!("writing {} file at {prettier_wrapper_path:?}", prettier2::PRETTIER_SERVER_FILE))?;
 
                 let packages_to_versions = future::try_join_all(
-                    prettier_plugins
+                    plugins_to_install
                         .iter()
                         .chain(Some(&"prettier"))
                         .map(|package_name| async {
@@ -8619,15 +8696,18 @@ impl Project {
                     (package.as_str(), version.as_str())
                 }).collect::<Vec<_>>();
                 node.npm_install_packages(default_prettier_dir, &borrowed_packages).await.context("fetching formatter packages")?;
+                let installed_packages = !plugins_to_install.is_empty();
+                install_success_tx.try_send(plugins_to_install).ok();
 
-                if !prettier_plugins.is_empty() {
+                if !installed_packages {
                     if let Some(prettier) = already_running_prettier {
                         prettier.await.map_err(|e| anyhow::anyhow!("Default prettier startup await failure: {e:#}"))?.clear_cache().await.context("clearing default prettier cache after plugins install")?;
                     }
                 }
 
                 anyhow::Ok(())
-            })
+            }).await
+        })
     }
 }
 

crates/project2/src/worktree.rs 🔗

@@ -2659,12 +2659,12 @@ impl language2::File for File {
 
 impl language2::LocalFile for File {
     fn abs_path(&self, cx: &AppContext) -> PathBuf {
-        self.worktree
-            .read(cx)
-            .as_local()
-            .unwrap()
-            .abs_path
-            .join(&self.path)
+        let worktree_path = &self.worktree.read(cx).as_local().unwrap().abs_path;
+        if self.path.as_ref() == Path::new("") {
+            worktree_path.to_path_buf()
+        } else {
+            worktree_path.join(&self.path)
+        }
     }
 
     fn load(&self, cx: &AppContext) -> Task<Result<String>> {

crates/storybook2/src/story_selector.rs 🔗

@@ -28,17 +28,17 @@ pub enum ElementStory {
 impl ElementStory {
     pub fn story(&self, cx: &mut WindowContext) -> AnyView {
         match self {
-            Self::Colors => cx.build_view(|_| ColorsStory).into_any(),
-            Self::Avatar => cx.build_view(|_| AvatarStory).into_any(),
-            Self::Button => cx.build_view(|_| ButtonStory).into_any(),
-            Self::Details => cx.build_view(|_| DetailsStory).into_any(),
-            Self::Focus => FocusStory::view(cx).into_any(),
-            Self::Icon => cx.build_view(|_| IconStory).into_any(),
-            Self::Input => cx.build_view(|_| InputStory).into_any(),
-            Self::Label => cx.build_view(|_| LabelStory).into_any(),
-            Self::Scroll => ScrollStory::view(cx).into_any(),
-            Self::Text => TextStory::view(cx).into_any(),
-            Self::ZIndex => cx.build_view(|_| ZIndexStory).into_any(),
+            Self::Colors => cx.build_view(|_| ColorsStory).into(),
+            Self::Avatar => cx.build_view(|_| AvatarStory).into(),
+            Self::Button => cx.build_view(|_| ButtonStory).into(),
+            Self::Details => cx.build_view(|_| DetailsStory).into(),
+            Self::Focus => FocusStory::view(cx).into(),
+            Self::Icon => cx.build_view(|_| IconStory).into(),
+            Self::Input => cx.build_view(|_| InputStory).into(),
+            Self::Label => cx.build_view(|_| LabelStory).into(),
+            Self::Scroll => ScrollStory::view(cx).into(),
+            Self::Text => TextStory::view(cx).into(),
+            Self::ZIndex => cx.build_view(|_| ZIndexStory).into(),
         }
     }
 }
@@ -77,32 +77,32 @@ pub enum ComponentStory {
 impl ComponentStory {
     pub fn story(&self, cx: &mut WindowContext) -> AnyView {
         match self {
-            Self::AssistantPanel => cx.build_view(|_| ui::AssistantPanelStory).into_any(),
-            Self::Buffer => cx.build_view(|_| ui::BufferStory).into_any(),
-            Self::Breadcrumb => cx.build_view(|_| ui::BreadcrumbStory).into_any(),
-            Self::ChatPanel => cx.build_view(|_| ui::ChatPanelStory).into_any(),
-            Self::CollabPanel => cx.build_view(|_| ui::CollabPanelStory).into_any(),
-            Self::CommandPalette => cx.build_view(|_| ui::CommandPaletteStory).into_any(),
-            Self::ContextMenu => cx.build_view(|_| ui::ContextMenuStory).into_any(),
-            Self::Facepile => cx.build_view(|_| ui::FacepileStory).into_any(),
-            Self::Keybinding => cx.build_view(|_| ui::KeybindingStory).into_any(),
-            Self::LanguageSelector => cx.build_view(|_| ui::LanguageSelectorStory).into_any(),
-            Self::MultiBuffer => cx.build_view(|_| ui::MultiBufferStory).into_any(),
-            Self::NotificationsPanel => cx.build_view(|cx| ui::NotificationsPanelStory).into_any(),
-            Self::Palette => cx.build_view(|cx| ui::PaletteStory).into_any(),
-            Self::Panel => cx.build_view(|cx| ui::PanelStory).into_any(),
-            Self::ProjectPanel => cx.build_view(|_| ui::ProjectPanelStory).into_any(),
-            Self::RecentProjects => cx.build_view(|_| ui::RecentProjectsStory).into_any(),
-            Self::Tab => cx.build_view(|_| ui::TabStory).into_any(),
-            Self::TabBar => cx.build_view(|_| ui::TabBarStory).into_any(),
-            Self::Terminal => cx.build_view(|_| ui::TerminalStory).into_any(),
-            Self::ThemeSelector => cx.build_view(|_| ui::ThemeSelectorStory).into_any(),
-            Self::Toast => cx.build_view(|_| ui::ToastStory).into_any(),
-            Self::Toolbar => cx.build_view(|_| ui::ToolbarStory).into_any(),
-            Self::TrafficLights => cx.build_view(|_| ui::TrafficLightsStory).into_any(),
-            Self::Copilot => cx.build_view(|_| ui::CopilotModalStory).into_any(),
-            Self::TitleBar => ui::TitleBarStory::view(cx).into_any(),
-            Self::Workspace => ui::WorkspaceStory::view(cx).into_any(),
+            Self::AssistantPanel => cx.build_view(|_| ui::AssistantPanelStory).into(),
+            Self::Buffer => cx.build_view(|_| ui::BufferStory).into(),
+            Self::Breadcrumb => cx.build_view(|_| ui::BreadcrumbStory).into(),
+            Self::ChatPanel => cx.build_view(|_| ui::ChatPanelStory).into(),
+            Self::CollabPanel => cx.build_view(|_| ui::CollabPanelStory).into(),
+            Self::CommandPalette => cx.build_view(|_| ui::CommandPaletteStory).into(),
+            Self::ContextMenu => cx.build_view(|_| ui::ContextMenuStory).into(),
+            Self::Facepile => cx.build_view(|_| ui::FacepileStory).into(),
+            Self::Keybinding => cx.build_view(|_| ui::KeybindingStory).into(),
+            Self::LanguageSelector => cx.build_view(|_| ui::LanguageSelectorStory).into(),
+            Self::MultiBuffer => cx.build_view(|_| ui::MultiBufferStory).into(),
+            Self::NotificationsPanel => cx.build_view(|cx| ui::NotificationsPanelStory).into(),
+            Self::Palette => cx.build_view(|cx| ui::PaletteStory).into(),
+            Self::Panel => cx.build_view(|cx| ui::PanelStory).into(),
+            Self::ProjectPanel => cx.build_view(|_| ui::ProjectPanelStory).into(),
+            Self::RecentProjects => cx.build_view(|_| ui::RecentProjectsStory).into(),
+            Self::Tab => cx.build_view(|_| ui::TabStory).into(),
+            Self::TabBar => cx.build_view(|_| ui::TabBarStory).into(),
+            Self::Terminal => cx.build_view(|_| ui::TerminalStory).into(),
+            Self::ThemeSelector => cx.build_view(|_| ui::ThemeSelectorStory).into(),
+            Self::Toast => cx.build_view(|_| ui::ToastStory).into(),
+            Self::Toolbar => cx.build_view(|_| ui::ToolbarStory).into(),
+            Self::TrafficLights => cx.build_view(|_| ui::TrafficLightsStory).into(),
+            Self::Copilot => cx.build_view(|_| ui::CopilotModalStory).into(),
+            Self::TitleBar => ui::TitleBarStory::view(cx).into(),
+            Self::Workspace => ui::WorkspaceStory::view(cx).into(),
         }
     }
 }
@@ -149,7 +149,7 @@ impl StorySelector {
         match self {
             Self::Element(element_story) => element_story.story(cx),
             Self::Component(component_story) => component_story.story(cx),
-            Self::KitchenSink => KitchenSinkStory::view(cx).into_any(),
+            Self::KitchenSink => KitchenSinkStory::view(cx).into(),
         }
     }
 }

crates/workspace2/src/item.rs 🔗

@@ -164,7 +164,7 @@ pub trait Item: Render + EventEmitter + Send {
         _: &'a AppContext,
     ) -> Option<AnyView> {
         if TypeId::of::<Self>() == type_id {
-            Some(self_handle.clone().into_any())
+            Some(self_handle.clone().into())
         } else {
             None
         }
@@ -524,7 +524,7 @@ impl<T: Item> ItemHandle for View<T> {
     }
 
     fn to_any(&self) -> AnyView {
-        self.clone().into_any()
+        self.clone().into()
     }
 
     fn is_dirty(&self, cx: &AppContext) -> bool {

crates/workspace2/src/status_bar.rs 🔗

@@ -160,7 +160,7 @@ impl StatusBar {
 
 impl<T: StatusItemView> StatusItemViewHandle for View<T> {
     fn to_any(&self) -> AnyView {
-        self.clone().into_any()
+        self.clone().into()
     }
 
     fn set_active_pane_item(

crates/workspace2/src/toolbar.rs 🔗

@@ -263,7 +263,7 @@ impl<T: ToolbarItemView> ToolbarItemViewHandle for View<T> {
     }
 
     fn to_any(&self) -> AnyView {
-        self.clone().into_any()
+        self.clone().into()
     }
 
     fn set_active_pane_item(

crates/zed2/src/main.rs 🔗

@@ -45,8 +45,9 @@ use util::{
     paths, ResultExt,
 };
 use uuid::Uuid;
+use workspace2::AppState;
 use zed2::languages;
-use zed2::{ensure_only_instance, AppState, Assets, IsOnlyInstance};
+use zed2::{ensure_only_instance, Assets, IsOnlyInstance};
 
 mod open_listener;
 
@@ -165,7 +166,7 @@ fn main() {
         // client.telemetry().start(installation_id, session_id, cx);
 
         // todo!("app_state")
-        let app_state = Arc::new(AppState { client, user_store });
+        let app_state: Arc<AppState> = todo!();
         // let app_state = Arc::new(AppState {
         //     languages,
         //     client: client.clone(),