Compare commits

...

11 Commits

Author SHA1 Message Date
Joseph Lyons
e724d7fae9 v0.84.x stable 2023-05-03 14:38:06 -04:00
Antonio Scandurra
7ad90fd0a7 Merge pull request #2436 from zed-industries/close-window-end-call
Move methods querying window state into `AsyncAppContext`
2023-05-03 10:33:09 +02:00
Antonio Scandurra
4df6b75ba3 Merge pull request #2431 from zed-industries/fix-broken-contact-finder
Fix broken styling in contact finder
2023-05-02 13:55:39 +02:00
Antonio Scandurra
1908d3cf43 zed 0.84.3 2023-05-02 12:02:09 +02:00
Antonio Scandurra
b4531235ef Merge pull request #2430 from zed-industries/fix-toggle-contacts-panic
Fix panic when showing contacts popover via keybinding
2023-05-02 12:02:01 +02:00
Antonio Scandurra
c3212e559f Merge pull request #2429 from zed-industries/fix-debug-elements-panic
Move `debug_elements` to `AsyncAppContext`
2023-05-02 11:19:11 +02:00
Max Brunsfeld
1c7fb0f0cb zed 0.84.2 2023-04-27 10:50:15 -07:00
Max Brunsfeld
df26ef9770 Merge pull request #2418 from zed-industries/vim-inactive-window-crash
Fix vim mode crash when active editor changes in inactive window
2023-04-27 10:49:21 -07:00
Max Brunsfeld
74d5e22cec zed 0.84.1 2023-04-26 16:13:30 -07:00
Max Brunsfeld
80efdb13be Merge pull request #2416 from zed-industries/outline-view-leaving-lines-highlighted
Remove highlighted rows when confirming outline view
2023-04-26 16:13:03 -07:00
Joseph Lyons
3f8415b62e v0.84.x preview 2023-04-26 14:19:40 -04:00
19 changed files with 206 additions and 249 deletions

2
Cargo.lock generated
View File

@@ -8539,7 +8539,7 @@ checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
[[package]]
name = "zed"
version = "0.84.0"
version = "0.84.3"
dependencies = [
"activity_indicator",
"anyhow",

View File

@@ -4,7 +4,7 @@ use crate::{
ToggleScreenSharing,
};
use call::{ActiveCall, ParticipantLocation, Room};
use client::{proto::PeerId, ContactEventKind, SignIn, SignOut, User, UserStore};
use client::{proto::PeerId, Client, ContactEventKind, SignIn, SignOut, User, UserStore};
use clock::ReplicaId;
use contacts_popover::ContactsPopover;
use context_menu::{ContextMenu, ContextMenuItem};
@@ -19,6 +19,7 @@ use gpui::{
AppContext, Entity, ImageData, ModelHandle, SceneBuilder, Subscription, View, ViewContext,
ViewHandle, WeakViewHandle,
};
use project::Project;
use settings::Settings;
use std::{ops::Range, sync::Arc};
use theme::{AvatarStyle, Theme};
@@ -51,8 +52,10 @@ pub fn init(cx: &mut AppContext) {
}
pub struct CollabTitlebarItem {
workspace: WeakViewHandle<Workspace>,
project: ModelHandle<Project>,
user_store: ModelHandle<UserStore>,
client: Arc<Client>,
workspace: WeakViewHandle<Workspace>,
contacts_popover: Option<ViewHandle<ContactsPopover>>,
user_menu: ViewHandle<ContextMenu>,
collaborator_list_popover: Option<ViewHandle<CollaboratorListPopover>>,
@@ -75,7 +78,7 @@ impl View for CollabTitlebarItem {
return Empty::new().into_any();
};
let project = workspace.read(cx).project().read(cx);
let project = self.project.read(cx);
let mut project_title = String::new();
for (i, name) in project.worktree_root_names(cx).enumerate() {
if i > 0 {
@@ -100,8 +103,8 @@ impl View for CollabTitlebarItem {
.left(),
);
let user = workspace.read(cx).user_store().read(cx).current_user();
let peer_id = workspace.read(cx).client().peer_id();
let user = self.user_store.read(cx).current_user();
let peer_id = self.client.peer_id();
if let Some(((user, peer_id), room)) = user
.zip(peer_id)
.zip(ActiveCall::global(cx).read(cx).room().cloned())
@@ -135,20 +138,23 @@ impl View for CollabTitlebarItem {
impl CollabTitlebarItem {
pub fn new(
workspace: &ViewHandle<Workspace>,
user_store: &ModelHandle<UserStore>,
workspace: &Workspace,
workspace_handle: &ViewHandle<Workspace>,
cx: &mut ViewContext<Self>,
) -> Self {
let project = workspace.project().clone();
let user_store = workspace.user_store().clone();
let client = workspace.client().clone();
let active_call = ActiveCall::global(cx);
let mut subscriptions = Vec::new();
subscriptions.push(cx.observe(workspace, |_, _, cx| cx.notify()));
subscriptions.push(cx.observe(workspace_handle, |_, _, cx| cx.notify()));
subscriptions.push(cx.observe(&active_call, |this, _, cx| this.active_call_changed(cx)));
subscriptions.push(cx.observe_window_activation(|this, active, cx| {
this.window_activation_changed(active, cx)
}));
subscriptions.push(cx.observe(user_store, |_, _, cx| cx.notify()));
subscriptions.push(cx.observe(&user_store, |_, _, cx| cx.notify()));
subscriptions.push(
cx.subscribe(user_store, move |this, user_store, event, cx| {
cx.subscribe(&user_store, move |this, user_store, event, cx| {
if let Some(workspace) = this.workspace.upgrade(cx) {
workspace.update(cx, |workspace, cx| {
if let client::Event::Contact { user, kind } = event {
@@ -171,8 +177,10 @@ impl CollabTitlebarItem {
);
Self {
workspace: workspace.downgrade(),
user_store: user_store.clone(),
workspace: workspace.weak_handle(),
project,
user_store,
client,
contacts_popover: None,
user_menu: cx.add_view(|cx| {
let mut menu = ContextMenu::new(cx);
@@ -185,16 +193,14 @@ impl CollabTitlebarItem {
}
fn window_activation_changed(&mut self, active: bool, cx: &mut ViewContext<Self>) {
if let Some(workspace) = self.workspace.upgrade(cx) {
let project = if active {
Some(workspace.read(cx).project().clone())
} else {
None
};
ActiveCall::global(cx)
.update(cx, |call, cx| call.set_location(project.as_ref(), cx))
.detach_and_log_err(cx);
}
let project = if active {
Some(self.project.clone())
} else {
None
};
ActiveCall::global(cx)
.update(cx, |call, cx| call.set_location(project.as_ref(), cx))
.detach_and_log_err(cx);
}
fn active_call_changed(&mut self, cx: &mut ViewContext<Self>) {
@@ -205,23 +211,19 @@ impl CollabTitlebarItem {
}
fn share_project(&mut self, _: &ShareProject, cx: &mut ViewContext<Self>) {
if let Some(workspace) = self.workspace.upgrade(cx) {
let active_call = ActiveCall::global(cx);
let project = workspace.read(cx).project().clone();
active_call
.update(cx, |call, cx| call.share_project(project, cx))
.detach_and_log_err(cx);
}
let active_call = ActiveCall::global(cx);
let project = self.project.clone();
active_call
.update(cx, |call, cx| call.share_project(project, cx))
.detach_and_log_err(cx);
}
fn unshare_project(&mut self, _: &UnshareProject, cx: &mut ViewContext<Self>) {
if let Some(workspace) = self.workspace.upgrade(cx) {
let active_call = ActiveCall::global(cx);
let project = workspace.read(cx).project().clone();
active_call
.update(cx, |call, cx| call.unshare_project(project, cx))
.log_err();
}
let active_call = ActiveCall::global(cx);
let project = self.project.clone();
active_call
.update(cx, |call, cx| call.unshare_project(project, cx))
.log_err();
}
pub fn toggle_collaborator_list_popover(
@@ -256,22 +258,20 @@ impl CollabTitlebarItem {
pub fn toggle_contacts_popover(&mut self, _: &ToggleContactsMenu, cx: &mut ViewContext<Self>) {
if self.contacts_popover.take().is_none() {
if let Some(workspace) = self.workspace.upgrade(cx) {
let project = workspace.read(cx).project().clone();
let user_store = workspace.read(cx).user_store().clone();
let view = cx.add_view(|cx| ContactsPopover::new(project, user_store, cx));
cx.subscribe(&view, |this, _, event, cx| {
match event {
contacts_popover::Event::Dismissed => {
this.contacts_popover = None;
}
let view = cx.add_view(|cx| {
ContactsPopover::new(self.project.clone(), self.user_store.clone(), cx)
});
cx.subscribe(&view, |this, _, event, cx| {
match event {
contacts_popover::Event::Dismissed => {
this.contacts_popover = None;
}
}
cx.notify();
})
.detach();
self.contacts_popover = Some(view);
}
cx.notify();
})
.detach();
self.contacts_popover = Some(view);
}
cx.notify();

View File

@@ -52,13 +52,16 @@ fn join_project(action: &JoinProject, app_state: Arc<AppState>, cx: &mut AppCont
let project_id = action.project_id;
let follow_user_id = action.follow_user_id;
cx.spawn(|mut cx| async move {
let existing_workspace = cx.update(|cx| {
cx.window_ids()
.filter_map(|window_id| cx.root_view(window_id)?.clone().downcast::<Workspace>())
.find(|workspace| {
let existing_workspace = cx
.window_ids()
.into_iter()
.filter_map(|window_id| cx.root_view(window_id)?.clone().downcast::<Workspace>())
.find(|workspace| {
cx.read_window(workspace.window_id(), |cx| {
workspace.read(cx).project().read(cx).remote_id() == Some(project_id)
})
});
.unwrap_or(false)
});
let workspace = if let Some(existing_workspace) = existing_workspace {
existing_workspace.downgrade()

View File

@@ -23,6 +23,7 @@ pub fn build_contact_finder(
},
cx,
)
.with_theme(|theme| theme.contact_finder.picker.clone())
}
pub struct ContactFinderDelegate {

View File

@@ -62,14 +62,14 @@ pub fn init(cx: &mut AppContext) {
room::Event::RemoteProjectUnshared { project_id } => {
if let Some(window_ids) = notification_windows.remove(&project_id) {
for window_id in window_ids {
cx.remove_window(window_id);
cx.update_window(window_id, |cx| cx.remove_window());
}
}
}
room::Event::Left => {
for (_, window_ids) in notification_windows.drain() {
for window_id in window_ids {
cx.remove_window(window_id);
cx.update_window(window_id, |cx| cx.remove_window());
}
}
}

View File

@@ -20,10 +20,10 @@ pub fn init(cx: &mut AppContext) {
status_indicator = Some(cx.add_status_bar_item(|_| SharingStatusIndicator));
}
} else if let Some((window_id, _)) = status_indicator.take() {
cx.remove_status_bar_item(window_id);
cx.update_window(window_id, |cx| cx.remove_window());
}
} else if let Some((window_id, _)) = status_indicator.take() {
cx.remove_status_bar_item(window_id);
cx.update_window(window_id, |cx| cx.remove_window());
}
})
.detach();

View File

@@ -33,14 +33,13 @@ pub fn init(cx: &mut AppContext) {
crate::Status::SigningIn { prompt } => {
if let Some(code_verification_handle) = code_verification.as_mut() {
let window_id = code_verification_handle.window_id();
if cx.has_window(window_id) {
cx.update_window(window_id, |cx| {
code_verification_handle.update(cx, |code_verification, cx| {
code_verification.set_status(status, cx)
});
cx.activate_window();
let updated = cx.update_window(window_id, |cx| {
code_verification_handle.update(cx, |code_verification, cx| {
code_verification.set_status(status.clone(), cx)
});
} else {
cx.activate_window();
});
if updated.is_none() {
code_verification = Some(create_copilot_auth_window(cx, &status));
}
} else if let Some(_prompt) = prompt {
@@ -62,7 +61,7 @@ pub fn init(cx: &mut AppContext) {
}
_ => {
if let Some(code_verification) = code_verification.take() {
cx.remove_window(code_verification.window_id());
cx.update_window(code_verification.window_id(), |cx| cx.remove_window());
}
}
}

View File

@@ -43,6 +43,7 @@ use window_input_handler::WindowInputHandler;
use crate::{
elements::{AnyElement, AnyRootElement, RootElement},
executor::{self, Task},
json,
keymap_matcher::{self, Binding, KeymapContext, KeymapMatcher, Keystroke, MatchResult},
platform::{
self, FontSystem, KeyDownEvent, KeyUpEvent, ModifiersChangedEvent, MouseButton,
@@ -301,6 +302,14 @@ impl AsyncAppContext {
self.0.borrow_mut().update(callback)
}
pub fn read_window<T, F: FnOnce(&WindowContext) -> T>(
&self,
window_id: usize,
callback: F,
) -> Option<T> {
self.0.borrow_mut().read_window(window_id, callback)
}
pub fn update_window<T, F: FnOnce(&mut WindowContext) -> T>(
&mut self,
window_id: usize,
@@ -309,6 +318,30 @@ impl AsyncAppContext {
self.0.borrow_mut().update_window(window_id, callback)
}
pub fn debug_elements(&self, window_id: usize) -> Option<json::Value> {
self.0.borrow().read_window(window_id, |cx| {
let root_view = cx.window.root_view();
let root_element = cx.window.rendered_views.get(&root_view.id())?;
root_element.debug(cx).log_err()
})?
}
pub fn has_window(&self, window_id: usize) -> bool {
self.read(|cx| cx.windows.contains_key(&window_id))
}
pub fn window_is_active(&self, window_id: usize) -> bool {
self.read(|cx| cx.windows.get(&window_id).map_or(false, |w| w.is_active))
}
pub fn root_view(&self, window_id: usize) -> Option<AnyViewHandle> {
self.read(|cx| cx.windows.get(&window_id).map(|w| w.root_view().clone()))
}
pub fn window_ids(&self) -> Vec<usize> {
self.read(|cx| cx.windows.keys().copied().collect())
}
pub fn add_model<T, F>(&mut self, build_model: F) -> ModelHandle<T>
where
T: Entity,
@@ -330,7 +363,7 @@ impl AsyncAppContext {
}
pub fn remove_window(&mut self, window_id: usize) {
self.update(|cx| cx.remove_window(window_id))
self.update_window(window_id, |cx| cx.remove_window());
}
pub fn activate_window(&mut self, window_id: usize) {
@@ -529,7 +562,7 @@ impl AppContext {
App(self.weak_self.as_ref().unwrap().upgrade().unwrap())
}
pub fn quit(&mut self) {
fn quit(&mut self) {
let mut futures = Vec::new();
self.update(|cx| {
@@ -546,7 +579,8 @@ impl AppContext {
}
});
self.remove_all_windows();
self.windows.clear();
self.flush_effects();
let futures = futures::future::join_all(futures);
if self
@@ -558,11 +592,6 @@ impl AppContext {
}
}
pub fn remove_all_windows(&mut self) {
self.windows.clear();
self.flush_effects();
}
pub fn foreground(&self) -> &Rc<executor::Foreground> {
&self.foreground
}
@@ -679,24 +708,6 @@ impl AppContext {
}
}
pub fn has_window(&self, window_id: usize) -> bool {
self.window_ids()
.find(|window| window == &window_id)
.is_some()
}
pub fn window_is_active(&self, window_id: usize) -> bool {
self.windows.get(&window_id).map_or(false, |w| w.is_active)
}
pub fn root_view(&self, window_id: usize) -> Option<&AnyViewHandle> {
self.windows.get(&window_id).map(|w| w.root_view())
}
pub fn window_ids(&self) -> impl Iterator<Item = usize> + '_ {
self.windows.keys().copied()
}
pub fn view_ui_name(&self, window_id: usize, view_id: usize) -> Option<&'static str> {
Some(self.views.get(&(window_id, view_id))?.ui_name())
}
@@ -1266,15 +1277,6 @@ impl AppContext {
})
}
pub fn remove_status_bar_item(&mut self, id: usize) {
self.remove_window(id);
}
pub fn remove_window(&mut self, window_id: usize) {
self.windows.remove(&window_id);
self.flush_effects();
}
pub fn build_window<V, F>(
&mut self,
window_id: usize,
@@ -1333,7 +1335,7 @@ impl AppContext {
{
let mut app = self.upgrade();
platform_window.on_close(Box::new(move || {
app.update(|cx| cx.remove_window(window_id));
app.update(|cx| cx.update_window(window_id, |cx| cx.remove_window()));
}));
}
@@ -4708,7 +4710,7 @@ mod tests {
assert!(model_release_observed.get());
drop(view);
cx.remove_window(window_id);
cx.update_window(window_id, |cx| cx.remove_window());
assert!(view_released.get());
assert!(view_release_observed.get());
}

View File

@@ -180,7 +180,11 @@ impl TestAppContext {
}
pub fn window_ids(&self) -> Vec<usize> {
self.cx.borrow().window_ids().collect()
self.cx.borrow().windows.keys().copied().collect()
}
pub fn remove_all_windows(&mut self) {
self.update(|cx| cx.windows.clear());
}
pub fn read<T, F: FnOnce(&AppContext) -> T>(&self, callback: F) -> T {

View File

@@ -1,7 +1,7 @@
use crate::{
elements::AnyRootElement,
geometry::rect::RectF,
json::{self, ToJson},
json::ToJson,
keymap_matcher::{Binding, Keystroke, MatchResult},
platform::{
self, Appearance, CursorStyle, Event, KeyDownEvent, KeyUpEvent, ModifiersChangedEvent,
@@ -975,17 +975,6 @@ impl<'a> WindowContext<'a> {
.flatten()
}
pub fn debug_elements(&self) -> Option<json::Value> {
let view = self.window.root_view();
Some(json!({
"root_view": view.debug_json(self),
"root_element": self.window.rendered_views.get(&view.id())
.and_then(|root_element| {
root_element.debug(self).log_err()
})
}))
}
pub fn set_window_title(&mut self, title: &str) {
self.window.platform_window.set_title(title);
}
@@ -1454,13 +1443,7 @@ impl<V: View> Element<V> for ChildView {
) -> serde_json::Value {
json!({
"type": "ChildView",
"view_id": self.view_id,
"bounds": bounds.to_json(),
"view": if let Some(view) = cx.views.get(&(cx.window_id, self.view_id)) {
view.debug_json(cx)
} else {
json!(null)
},
"child": if let Some(element) = cx.window.rendered_views.get(&self.view_id) {
element.debug(&cx.window_context).log_err().unwrap_or_else(|| json!(null))
} else {

View File

@@ -45,7 +45,6 @@ use std::{
mem,
ops::{Deref, DerefMut, Range},
};
use util::ResultExt;
pub trait Element<V: View>: 'static {
type LayoutState;
@@ -709,7 +708,12 @@ impl<V: View> AnyRootElement for RootElement<V> {
.ok_or_else(|| anyhow!("debug called on a root element for a dropped view"))?;
let view = view.read(cx);
let view_context = ViewContext::immutable(cx, self.view.id());
Ok(self.element.debug(view, &view_context))
Ok(serde_json::json!({
"view_id": self.view.id(),
"view_name": V::ui_name(),
"view": view.debug_json(cx),
"element": self.element.debug(view, &view_context)
}))
}
fn name(&self) -> Option<&str> {
@@ -717,63 +721,6 @@ impl<V: View> AnyRootElement for RootElement<V> {
}
}
impl<V: View, R: View> Element<V> for RootElement<R> {
type LayoutState = ();
type PaintState = ();
fn layout(
&mut self,
constraint: SizeConstraint,
_view: &mut V,
cx: &mut ViewContext<V>,
) -> (Vector2F, ()) {
let size = AnyRootElement::layout(self, constraint, cx)
.log_err()
.unwrap_or_else(|| Vector2F::zero());
(size, ())
}
fn paint(
&mut self,
scene: &mut SceneBuilder,
bounds: RectF,
visible_bounds: RectF,
_layout: &mut Self::LayoutState,
_view: &mut V,
cx: &mut ViewContext<V>,
) {
AnyRootElement::paint(self, scene, bounds.origin(), visible_bounds, cx).log_err();
}
fn rect_for_text_range(
&self,
range_utf16: Range<usize>,
_bounds: RectF,
_visible_bounds: RectF,
_layout: &Self::LayoutState,
_paint: &Self::PaintState,
_view: &V,
cx: &ViewContext<V>,
) -> Option<RectF> {
AnyRootElement::rect_for_text_range(self, range_utf16, cx)
.log_err()
.flatten()
}
fn debug(
&self,
_bounds: RectF,
_layout: &Self::LayoutState,
_paint: &Self::PaintState,
_view: &V,
cx: &ViewContext<V>,
) -> serde_json::Value {
AnyRootElement::debug(self, cx)
.log_err()
.unwrap_or_default()
}
}
pub trait ParentElement<'a, V: View>: Extend<AnyElement<V>> + Sized {
fn add_children<E: Element<V>>(&mut self, children: impl IntoIterator<Item = E>) {
self.extend(children.into_iter().map(|child| child.into_any()));

View File

@@ -100,7 +100,7 @@ pub fn run_test(
test_fn(cx, foreground_platform.clone(), deterministic.clone(), seed);
});
cx.update(|cx| cx.remove_all_windows());
cx.remove_all_windows();
deterministic.run_until_parked();
cx.update(|cx| cx.clear_globals());

View File

@@ -137,7 +137,7 @@ pub fn test(args: TokenStream, function: TokenStream) -> TokenStream {
);
));
cx_teardowns.extend(quote!(
#cx_varname.update(|cx| cx.remove_all_windows());
#cx_varname.remove_all_windows();
deterministic.run_until_parked();
#cx_varname.update(|cx| cx.clear_globals());
));
@@ -212,7 +212,7 @@ pub fn test(args: TokenStream, function: TokenStream) -> TokenStream {
);
));
cx_teardowns.extend(quote!(
#cx_varname.update(|cx| cx.remove_all_windows());
#cx_varname.remove_all_windows();
deterministic.run_until_parked();
#cx_varname.update(|cx| cx.clear_globals());
));

View File

@@ -187,6 +187,7 @@ impl PickerDelegate for OutlineViewDelegate {
active_editor.change_selections(Some(Autoscroll::center()), cx, |s| {
s.select_ranges([position..position])
});
active_editor.highlight_rows(None);
}
});
cx.emit(PickerEvent::Dismiss);

View File

@@ -9,11 +9,18 @@ pub fn init(cx: &mut AppContext) {
}
fn focused(EditorFocused(editor): &EditorFocused, cx: &mut AppContext) {
if let Some(previously_active_editor) = Vim::read(cx).active_editor.clone() {
cx.update_window(previously_active_editor.window_id(), |cx| {
Vim::update(cx, |vim, cx| {
vim.update_active_editor(cx, |previously_active_editor, cx| {
Vim::unhook_vim_settings(previously_active_editor, cx);
});
});
});
}
cx.update_window(editor.window_id(), |cx| {
Vim::update(cx, |vim, cx| {
vim.update_active_editor(cx, |previously_active_editor, cx| {
Vim::unhook_vim_settings(previously_active_editor, cx);
});
vim.set_active_editor(editor.clone(), cx);
});
});

View File

@@ -1044,7 +1044,7 @@ impl Workspace {
&self.project
}
pub fn client(&self) -> &Client {
pub fn client(&self) -> &Arc<Client> {
&self.client
}
@@ -1110,12 +1110,18 @@ impl Workspace {
}
pub fn close_global(_: &CloseWindow, cx: &mut AppContext) {
let id = cx.window_ids().find(|&id| cx.window_is_active(id));
if let Some(id) = id {
//This can only get called when the window's project connection has been lost
//so we don't need to prompt the user for anything and instead just close the window
cx.remove_window(id);
}
cx.spawn(|mut cx| async move {
let id = cx
.window_ids()
.into_iter()
.find(|&id| cx.window_is_active(id));
if let Some(id) = id {
//This can only get called when the window's project connection has been lost
//so we don't need to prompt the user for anything and instead just close the window
cx.remove_window(id);
}
})
.detach();
}
pub fn close(
@@ -1140,19 +1146,14 @@ impl Workspace {
) -> Task<Result<bool>> {
let active_call = self.active_call().cloned();
let window_id = cx.window_id();
let workspace_count = cx
.window_ids()
.collect::<Vec<_>>()
.into_iter()
.filter_map(|window_id| {
cx.app_context()
.root_view(window_id)?
.clone()
.downcast::<Workspace>()
})
.count();
cx.spawn(|this, mut cx| async move {
let workspace_count = cx
.window_ids()
.into_iter()
.filter_map(|window_id| cx.root_view(window_id)?.clone().downcast::<Workspace>())
.count();
if let Some(active_call) = active_call {
if !quitting
&& workspace_count == 1
@@ -2979,10 +2980,10 @@ impl std::fmt::Debug for OpenPaths {
pub struct WorkspaceCreated(WeakViewHandle<Workspace>);
pub fn activate_workspace_for_project(
cx: &mut AppContext,
cx: &mut AsyncAppContext,
predicate: impl Fn(&mut Project, &mut ModelContext<Project>) -> bool,
) -> Option<WeakViewHandle<Workspace>> {
for window_id in cx.window_ids().collect::<Vec<_>>() {
for window_id in cx.window_ids() {
let handle = cx
.update_window(window_id, |cx| {
if let Some(workspace_handle) = cx.root_view().clone().downcast::<Workspace>() {
@@ -3021,13 +3022,14 @@ pub fn open_paths(
> {
log::info!("open paths {:?}", abs_paths);
// Open paths in existing workspace if possible
let existing =
activate_workspace_for_project(cx, |project, cx| project.contains_paths(abs_paths, cx));
let app_state = app_state.clone();
let abs_paths = abs_paths.to_vec();
cx.spawn(|mut cx| async move {
// Open paths in existing workspace if possible
let existing = activate_workspace_for_project(&mut cx, |project, cx| {
project.contains_paths(&abs_paths, cx)
});
if let Some(existing) = existing {
Ok((
existing.clone(),

View File

@@ -3,7 +3,7 @@ authors = ["Nathan Sobo <nathansobo@gmail.com>"]
description = "The fast, collaborative code editor."
edition = "2021"
name = "zed"
version = "0.84.0"
version = "0.84.3"
publish = false
[lib]

View File

@@ -1 +1 @@
dev
stable

View File

@@ -11,6 +11,7 @@ use collections::VecDeque;
pub use editor;
use editor::{Editor, MultiBuffer};
use anyhow::anyhow;
use feedback::{
feedback_info_text::FeedbackInfoText, submit_feedback_button::SubmitFeedbackButton,
};
@@ -223,9 +224,14 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut gpui::AppContext) {
move |_: &mut Workspace, _: &DebugElements, cx: &mut ViewContext<Workspace>| {
let app_state = app_state.clone();
let markdown = app_state.languages.language_for_name("JSON");
let content = to_string_pretty(&cx.debug_elements()).unwrap();
let window_id = cx.window_id();
cx.spawn(|workspace, mut cx| async move {
let markdown = markdown.await.log_err();
let content = to_string_pretty(
&cx.debug_elements(window_id)
.ok_or_else(|| anyhow!("could not debug elements for {window_id}"))?,
)
.unwrap();
workspace
.update(&mut cx, |workspace, cx| {
workspace.with_local_workspace(&app_state, cx, move |workspace, cx| {
@@ -303,7 +309,7 @@ pub fn initialize_workspace(
cx.emit(workspace::Event::PaneAdded(workspace.dock_pane().clone()));
let collab_titlebar_item =
cx.add_view(|cx| CollabTitlebarItem::new(&workspace_handle, &app_state.user_store, cx));
cx.add_view(|cx| CollabTitlebarItem::new(workspace, &workspace_handle, cx));
workspace.set_titlebar_item(collab_titlebar_item.into_any(), cx);
let project_panel = ProjectPanel::new(workspace.project().clone(), cx);
@@ -372,24 +378,25 @@ pub fn build_window_options(
}
fn restart(_: &Restart, cx: &mut gpui::AppContext) {
let mut workspaces = cx
.window_ids()
.filter_map(|window_id| {
Some(
cx.root_view(window_id)?
.clone()
.downcast::<Workspace>()?
.downgrade(),
)
})
.collect::<Vec<_>>();
// If multiple windows have unsaved changes, and need a save prompt,
// prompt in the active window before switching to a different window.
workspaces.sort_by_key(|workspace| !cx.window_is_active(workspace.window_id()));
let should_confirm = cx.global::<Settings>().confirm_quit;
cx.spawn(|mut cx| async move {
let mut workspaces = cx
.window_ids()
.into_iter()
.filter_map(|window_id| {
Some(
cx.root_view(window_id)?
.clone()
.downcast::<Workspace>()?
.downgrade(),
)
})
.collect::<Vec<_>>();
// If multiple windows have unsaved changes, and need a save prompt,
// prompt in the active window before switching to a different window.
workspaces.sort_by_key(|workspace| !cx.window_is_active(workspace.window_id()));
if let (true, Some(workspace)) = (should_confirm, workspaces.first()) {
let answer = cx.prompt(
workspace.window_id(),
@@ -424,24 +431,25 @@ fn restart(_: &Restart, cx: &mut gpui::AppContext) {
}
fn quit(_: &Quit, cx: &mut gpui::AppContext) {
let mut workspaces = cx
.window_ids()
.filter_map(|window_id| {
Some(
cx.root_view(window_id)?
.clone()
.downcast::<Workspace>()?
.downgrade(),
)
})
.collect::<Vec<_>>();
// If multiple windows have unsaved changes, and need a save prompt,
// prompt in the active window before switching to a different window.
workspaces.sort_by_key(|workspace| !cx.window_is_active(workspace.window_id()));
let should_confirm = cx.global::<Settings>().confirm_quit;
cx.spawn(|mut cx| async move {
let mut workspaces = cx
.window_ids()
.into_iter()
.filter_map(|window_id| {
Some(
cx.root_view(window_id)?
.clone()
.downcast::<Workspace>()?
.downgrade(),
)
})
.collect::<Vec<_>>();
// If multiple windows have unsaved changes, and need a save prompt,
// prompt in the active window before switching to a different window.
workspaces.sort_by_key(|workspace| !cx.window_is_active(workspace.window_id()));
if let (true, Some(workspace)) = (should_confirm, workspaces.first()) {
let answer = cx.prompt(
workspace.window_id(),