Remove unnecessary calls to WeakViewHandle::upgrade

This commit is contained in:
Antonio Scandurra 2023-04-26 11:13:46 +02:00
parent 94c2eaad23
commit 2b6830c798
19 changed files with 378 additions and 443 deletions

View file

@ -65,18 +65,14 @@ impl ActivityIndicator {
let mut status_events = languages.language_server_binary_statuses(); let mut status_events = languages.language_server_binary_statuses();
cx.spawn(|this, mut cx| async move { cx.spawn(|this, mut cx| async move {
while let Some((language, event)) = status_events.next().await { while let Some((language, event)) = status_events.next().await {
if let Some(this) = this.upgrade(&cx) { this.update(&mut cx, |this, cx| {
this.update(&mut cx, |this, cx| { this.statuses.retain(|s| s.name != language.name());
this.statuses.retain(|s| s.name != language.name()); this.statuses.push(LspStatus {
this.statuses.push(LspStatus { name: language.name(),
name: language.name(), status: event,
status: event, });
}); cx.notify();
cx.notify(); })?;
})?;
} else {
break;
}
} }
anyhow::Ok(()) anyhow::Ok(())
}) })

View file

@ -104,17 +104,15 @@ pub fn notify_of_any_new_update(
cx.spawn(|mut cx| async move { cx.spawn(|mut cx| async move {
let should_show_notification = should_show_notification.await?; let should_show_notification = should_show_notification.await?;
if should_show_notification { if should_show_notification {
if let Some(workspace) = workspace.upgrade(&cx) { workspace.update(&mut cx, |workspace, cx| {
workspace.update(&mut cx, |workspace, cx| { workspace.show_notification(0, cx, |cx| {
workspace.show_notification(0, cx, |cx| { cx.add_view(|_| UpdateNotification::new(version))
cx.add_view(|_| UpdateNotification::new(version)) });
}); updater
updater .read(cx)
.read(cx) .set_should_show_update_notification(false, cx)
.set_should_show_update_notification(false, cx) .detach_and_log_err(cx);
.detach_and_log_err(cx); })?;
})?;
}
} }
anyhow::Ok(()) anyhow::Ok(())
}) })

View file

@ -2510,9 +2510,6 @@ impl Editor {
None None
}; };
let this = this
.upgrade(&cx)
.ok_or_else(|| anyhow!("editor was dropped"))?;
this.update(&mut cx, |this, cx| { this.update(&mut cx, |this, cx| {
this.completion_tasks.retain(|(task_id, _)| *task_id > id); this.completion_tasks.retain(|(task_id, _)| *task_id > id);
@ -2672,30 +2669,25 @@ impl Editor {
cx.spawn(|this, mut cx| async move { cx.spawn(|this, mut cx| async move {
while let Some(prev_task) = task { while let Some(prev_task) = task {
prev_task.await; prev_task.await;
task = this task = this.update(&mut cx, |this, _| this.code_actions_task.take())?;
.upgrade(&cx)
.ok_or_else(|| anyhow!("editor dropped"))?
.update(&mut cx, |this, _| this.code_actions_task.take())?;
} }
this.upgrade(&cx) this.update(&mut cx, |this, cx| {
.ok_or_else(|| anyhow!("editor dropped"))? if this.focused {
.update(&mut cx, |this, cx| { if let Some((buffer, actions)) = this.available_code_actions.clone() {
if this.focused { this.show_context_menu(
if let Some((buffer, actions)) = this.available_code_actions.clone() { ContextMenu::CodeActions(CodeActionsMenu {
this.show_context_menu( buffer,
ContextMenu::CodeActions(CodeActionsMenu { actions,
buffer, selected_item: Default::default(),
actions, list: Default::default(),
selected_item: Default::default(), deployed_from_indicator,
list: Default::default(), }),
deployed_from_indicator, cx,
}), );
cx,
);
}
} }
})?; }
})?;
Ok::<_, anyhow::Error>(()) Ok::<_, anyhow::Error>(())
}) })
@ -2828,19 +2820,17 @@ impl Editor {
}); });
self.code_actions_task = Some(cx.spawn(|this, mut cx| async move { self.code_actions_task = Some(cx.spawn(|this, mut cx| async move {
let actions = actions.await; let actions = actions.await;
if let Some(this) = this.upgrade(&cx) { this.update(&mut cx, |this, cx| {
this.update(&mut cx, |this, cx| { this.available_code_actions = actions.log_err().and_then(|actions| {
this.available_code_actions = actions.log_err().and_then(|actions| { if actions.is_empty() {
if actions.is_empty() { None
None } else {
} else { Some((start_buffer, actions.into()))
Some((start_buffer, actions.into())) }
} });
}); cx.notify();
cx.notify(); })
}) .log_err();
.log_err();
}
})); }));
None None
} }
@ -2866,8 +2856,7 @@ impl Editor {
}); });
self.document_highlights_task = Some(cx.spawn(|this, mut cx| async move { self.document_highlights_task = Some(cx.spawn(|this, mut cx| async move {
let highlights = highlights.log_err().await; if let Some(highlights) = highlights.await.log_err() {
if let Some((this, highlights)) = this.upgrade(&cx).zip(highlights) {
this.update(&mut cx, |this, cx| { this.update(&mut cx, |this, cx| {
if this.pending_rename.is_some() { if this.pending_rename.is_some() {
return; return;
@ -2976,21 +2965,20 @@ impl Editor {
.flatten() .flatten()
.collect_vec(); .collect_vec();
this.upgrade(&cx)? this.update(&mut cx, |this, cx| {
.update(&mut cx, |this, cx| { if !completions.is_empty() {
if !completions.is_empty() { this.copilot_state.cycled = false;
this.copilot_state.cycled = false; this.copilot_state.pending_cycling_refresh = Task::ready(None);
this.copilot_state.pending_cycling_refresh = Task::ready(None); this.copilot_state.completions.clear();
this.copilot_state.completions.clear(); this.copilot_state.active_completion_index = 0;
this.copilot_state.active_completion_index = 0; this.copilot_state.excerpt_id = Some(cursor.excerpt_id);
this.copilot_state.excerpt_id = Some(cursor.excerpt_id); for completion in completions {
for completion in completions { this.copilot_state.push_completion(completion);
this.copilot_state.push_completion(completion);
}
this.update_visible_copilot_suggestion(cx);
} }
}) this.update_visible_copilot_suggestion(cx);
.log_err()?; }
})
.log_err()?;
Some(()) Some(())
}); });
@ -3021,16 +3009,15 @@ impl Editor {
}) })
.await; .await;
this.upgrade(&cx)? this.update(&mut cx, |this, cx| {
.update(&mut cx, |this, cx| { this.copilot_state.cycled = true;
this.copilot_state.cycled = true; for completion in completions.log_err().into_iter().flatten() {
for completion in completions.log_err().into_iter().flatten() { this.copilot_state.push_completion(completion);
this.copilot_state.push_completion(completion); }
} this.copilot_state.cycle_completions(direction);
this.copilot_state.cycle_completions(direction); this.update_visible_copilot_suggestion(cx);
this.update_visible_copilot_suggestion(cx); })
}) .log_err()?;
.log_err()?;
Some(()) Some(())
}); });

View file

@ -201,15 +201,13 @@ fn show_hover(
}) })
}); });
if let Some(this) = this.upgrade(&cx) { this.update(&mut cx, |this, _| {
this.update(&mut cx, |this, _| { this.hover_state.diagnostic_popover =
this.hover_state.diagnostic_popover = local_diagnostic.map(|local_diagnostic| DiagnosticPopover {
local_diagnostic.map(|local_diagnostic| DiagnosticPopover { local_diagnostic,
local_diagnostic, primary_diagnostic,
primary_diagnostic, });
}); })?;
})?;
}
// Construct new hover popover from hover request // Construct new hover popover from hover request
let hover_popover = hover_request.await.ok().flatten().and_then(|hover_result| { let hover_popover = hover_request.await.ok().flatten().and_then(|hover_result| {
@ -239,23 +237,22 @@ fn show_hover(
}) })
}); });
if let Some(this) = this.upgrade(&cx) { this.update(&mut cx, |this, cx| {
this.update(&mut cx, |this, cx| { if let Some(hover_popover) = hover_popover.as_ref() {
if let Some(hover_popover) = hover_popover.as_ref() { // Highlight the selected symbol using a background highlight
// Highlight the selected symbol using a background highlight this.highlight_background::<HoverState>(
this.highlight_background::<HoverState>( vec![hover_popover.symbol_range.clone()],
vec![hover_popover.symbol_range.clone()], |theme| theme.editor.hover_popover.highlight,
|theme| theme.editor.hover_popover.highlight, cx,
cx, );
); } else {
} else { this.clear_background_highlights::<HoverState>(cx);
this.clear_background_highlights::<HoverState>(cx); }
}
this.hover_state.info_popover = hover_popover;
cx.notify();
})?;
this.hover_state.info_popover = hover_popover;
cx.notify();
})?;
}
Ok::<_, anyhow::Error>(()) Ok::<_, anyhow::Error>(())
} }
.log_err() .log_err()

View file

@ -202,67 +202,65 @@ pub fn show_link_definition(
) )
}); });
if let Some(this) = this.upgrade(&cx) { this.update(&mut cx, |this, cx| {
this.update(&mut cx, |this, cx| { // Clear any existing highlights
// Clear any existing highlights this.clear_text_highlights::<LinkGoToDefinitionState>(cx);
this.clear_text_highlights::<LinkGoToDefinitionState>(cx); this.link_go_to_definition_state.kind = Some(definition_kind);
this.link_go_to_definition_state.kind = Some(definition_kind); this.link_go_to_definition_state.symbol_range = result
this.link_go_to_definition_state.symbol_range = result .as_ref()
.as_ref() .and_then(|(symbol_range, _)| symbol_range.clone());
.and_then(|(symbol_range, _)| symbol_range.clone());
if let Some((symbol_range, definitions)) = result { if let Some((symbol_range, definitions)) = result {
this.link_go_to_definition_state.definitions = definitions.clone(); this.link_go_to_definition_state.definitions = definitions.clone();
let buffer_snapshot = buffer.read(cx).snapshot(); let buffer_snapshot = buffer.read(cx).snapshot();
// Only show highlight if there exists a definition to jump to that doesn't contain // Only show highlight if there exists a definition to jump to that doesn't contain
// the current location. // the current location.
let any_definition_does_not_contain_current_location = let any_definition_does_not_contain_current_location =
definitions.iter().any(|definition| { definitions.iter().any(|definition| {
let target = &definition.target; let target = &definition.target;
if target.buffer == buffer { if target.buffer == buffer {
let range = &target.range; let range = &target.range;
// Expand range by one character as lsp definition ranges include positions adjacent // Expand range by one character as lsp definition ranges include positions adjacent
// but not contained by the symbol range // but not contained by the symbol range
let start = buffer_snapshot.clip_offset( let start = buffer_snapshot.clip_offset(
range.start.to_offset(&buffer_snapshot).saturating_sub(1), range.start.to_offset(&buffer_snapshot).saturating_sub(1),
Bias::Left, Bias::Left,
); );
let end = buffer_snapshot.clip_offset( let end = buffer_snapshot.clip_offset(
range.end.to_offset(&buffer_snapshot) + 1, range.end.to_offset(&buffer_snapshot) + 1,
Bias::Right, Bias::Right,
); );
let offset = buffer_position.to_offset(&buffer_snapshot); let offset = buffer_position.to_offset(&buffer_snapshot);
!(start <= offset && end >= offset) !(start <= offset && end >= offset)
} else { } else {
true true
} }
}); });
if any_definition_does_not_contain_current_location { if any_definition_does_not_contain_current_location {
// If no symbol range returned from language server, use the surrounding word. // If no symbol range returned from language server, use the surrounding word.
let highlight_range = symbol_range.unwrap_or_else(|| { let highlight_range = symbol_range.unwrap_or_else(|| {
let snapshot = &snapshot.buffer_snapshot; let snapshot = &snapshot.buffer_snapshot;
let (offset_range, _) = snapshot.surrounding_word(trigger_point); let (offset_range, _) = snapshot.surrounding_word(trigger_point);
snapshot.anchor_before(offset_range.start) snapshot.anchor_before(offset_range.start)
..snapshot.anchor_after(offset_range.end) ..snapshot.anchor_after(offset_range.end)
}); });
// Highlight symbol using theme link definition highlight style // Highlight symbol using theme link definition highlight style
let style = cx.global::<Settings>().theme.editor.link_definition; let style = cx.global::<Settings>().theme.editor.link_definition;
this.highlight_text::<LinkGoToDefinitionState>( this.highlight_text::<LinkGoToDefinitionState>(
vec![highlight_range], vec![highlight_range],
style, style,
cx, cx,
); );
} else { } else {
hide_link_definition(this, cx); hide_link_definition(this, cx);
}
} }
})?; }
} })?;
Ok::<_, anyhow::Error>(()) Ok::<_, anyhow::Error>(())
} }

View file

@ -247,14 +247,12 @@ impl ScrollManager {
if cx.default_global::<ScrollbarAutoHide>().0 { if cx.default_global::<ScrollbarAutoHide>().0 {
self.hide_scrollbar_task = Some(cx.spawn(|editor, mut cx| async move { self.hide_scrollbar_task = Some(cx.spawn(|editor, mut cx| async move {
cx.background().timer(SCROLLBAR_SHOW_INTERVAL).await; cx.background().timer(SCROLLBAR_SHOW_INTERVAL).await;
if let Some(editor) = editor.upgrade(&cx) { editor
editor .update(&mut cx, |editor, cx| {
.update(&mut cx, |editor, cx| { editor.scroll_manager.show_scrollbars = false;
editor.scroll_manager.show_scrollbars = false; cx.notify();
cx.notify(); })
}) .log_err();
.log_err();
}
})); }));
} else { } else {
self.hide_scrollbar_task = None; self.hide_scrollbar_task = None;

View file

@ -104,9 +104,7 @@ impl<V: View> Tooltip<V> {
|view, mut cx| async move { |view, mut cx| async move {
cx.background().timer(DEBOUNCE_TIMEOUT).await; cx.background().timer(DEBOUNCE_TIMEOUT).await;
state.visible.set(true); state.visible.set(true);
if let Some(view) = view.upgrade(&cx) { view.update(&mut cx, |_, cx| cx.notify()).log_err();
view.update(&mut cx, |_, cx| cx.notify()).log_err();
}
} }
})); }));
} }

View file

@ -162,17 +162,15 @@ impl PickerDelegate for LanguageSelectorDelegate {
.await .await
}; };
if let Some(this) = this.upgrade(&cx) { this.update(&mut cx, |this, cx| {
this.update(&mut cx, |this, cx| { let delegate = this.delegate_mut();
let delegate = this.delegate_mut(); delegate.matches = matches;
delegate.matches = matches; delegate.selected_index = delegate
delegate.selected_index = delegate .selected_index
.selected_index .min(delegate.matches.len().saturating_sub(1));
.min(delegate.matches.len().saturating_sub(1)); cx.notify();
cx.notify(); })
}) .log_err();
.log_err();
}
}) })
} }

View file

@ -240,8 +240,7 @@ impl<D: PickerDelegate> Picker<D> {
self.matches_updated(cx); self.matches_updated(cx);
self.pending_update_matches = cx.spawn(|this, mut cx| async move { self.pending_update_matches = cx.spawn(|this, mut cx| async move {
update.await; update.await;
this.upgrade(&cx)? this.update(&mut cx, |this, cx| this.matches_updated(cx))
.update(&mut cx, |this, cx| this.matches_updated(cx))
.log_err() .log_err()
}); });
} }

View file

@ -1,4 +1,3 @@
use anyhow::anyhow;
use editor::{ use editor::{
combine_syntax_and_fuzzy_match_highlights, scroll::autoscroll::Autoscroll, combine_syntax_and_fuzzy_match_highlights, scroll::autoscroll::Autoscroll,
styled_runs_for_code_label, Bias, Editor, styled_runs_for_code_label, Bias, Editor,
@ -119,9 +118,6 @@ impl PickerDelegate for ProjectSymbolsDelegate {
let workspace = self.workspace.clone(); let workspace = self.workspace.clone();
cx.spawn(|_, mut cx| async move { cx.spawn(|_, mut cx| async move {
let buffer = buffer.await?; let buffer = buffer.await?;
let workspace = workspace
.upgrade(&cx)
.ok_or_else(|| anyhow!("workspace was dropped"))?;
workspace.update(&mut cx, |workspace, cx| { workspace.update(&mut cx, |workspace, cx| {
let position = buffer let position = buffer
.read(cx) .read(cx)
@ -163,34 +159,31 @@ impl PickerDelegate for ProjectSymbolsDelegate {
.update(cx, |project, cx| project.symbols(&query, cx)); .update(cx, |project, cx| project.symbols(&query, cx));
cx.spawn(|this, mut cx| async move { cx.spawn(|this, mut cx| async move {
let symbols = symbols.await.log_err(); let symbols = symbols.await.log_err();
if let Some(this) = this.upgrade(&cx) { if let Some(symbols) = symbols {
if let Some(symbols) = symbols { this.update(&mut cx, |this, cx| {
this.update(&mut cx, |this, cx| { let delegate = this.delegate_mut();
let delegate = this.delegate_mut(); let project = delegate.project.read(cx);
let project = delegate.project.read(cx); let (visible_match_candidates, external_match_candidates) = symbols
let (visible_match_candidates, external_match_candidates) = symbols .iter()
.iter() .enumerate()
.enumerate() .map(|(id, symbol)| {
.map(|(id, symbol)| { StringMatchCandidate::new(
StringMatchCandidate::new( id,
id, symbol.label.text[symbol.label.filter_range.clone()].to_string(),
symbol.label.text[symbol.label.filter_range.clone()] )
.to_string(), })
) .partition(|candidate| {
}) project
.partition(|candidate| { .entry_for_path(&symbols[candidate.id].path, cx)
project .map_or(false, |e| !e.is_ignored)
.entry_for_path(&symbols[candidate.id].path, cx) });
.map_or(false, |e| !e.is_ignored)
});
delegate.visible_match_candidates = visible_match_candidates; delegate.visible_match_candidates = visible_match_candidates;
delegate.external_match_candidates = external_match_candidates; delegate.external_match_candidates = external_match_candidates;
delegate.symbols = symbols; delegate.symbols = symbols;
delegate.filter(&query, cx); delegate.filter(&query, cx);
}) })
.log_err(); .log_err();
}
} }
}) })
} }

View file

@ -196,16 +196,15 @@ impl ToolbarItemView for BufferSearchBar {
if let Some(searchable_item_handle) = if let Some(searchable_item_handle) =
item.and_then(|item| item.to_searchable_item_handle(cx)) item.and_then(|item| item.to_searchable_item_handle(cx))
{ {
let handle = cx.weak_handle(); let this = cx.weak_handle();
self.active_searchable_item_subscription = self.active_searchable_item_subscription =
Some(searchable_item_handle.subscribe_to_search_events( Some(searchable_item_handle.subscribe_to_search_events(
cx, cx,
Box::new(move |search_event, cx| { Box::new(move |search_event, cx| {
if let Some(this) = handle.upgrade(cx) { this.update(cx, |this, cx| {
this.update(cx, |this, cx| { this.on_active_searchable_item_event(search_event, cx)
this.on_active_searchable_item_event(search_event, cx) })
}); .log_err();
}
}), }),
)); ));
@ -584,34 +583,31 @@ impl BufferSearchBar {
let active_searchable_item = active_searchable_item.downgrade(); let active_searchable_item = active_searchable_item.downgrade();
self.pending_search = Some(cx.spawn(|this, mut cx| async move { self.pending_search = Some(cx.spawn(|this, mut cx| async move {
let matches = matches.await; let matches = matches.await;
if let Some(this) = this.upgrade(&cx) { this.update(&mut cx, |this, cx| {
this.update(&mut cx, |this, cx| { if let Some(active_searchable_item) =
if let Some(active_searchable_item) = WeakSearchableItemHandle::upgrade( WeakSearchableItemHandle::upgrade(active_searchable_item.as_ref(), cx)
active_searchable_item.as_ref(), {
cx, this.seachable_items_with_matches
) { .insert(active_searchable_item.downgrade(), matches);
this.seachable_items_with_matches
.insert(active_searchable_item.downgrade(), matches);
this.update_match_index(cx); this.update_match_index(cx);
if !this.dismissed { if !this.dismissed {
let matches = this let matches = this
.seachable_items_with_matches .seachable_items_with_matches
.get(&active_searchable_item.downgrade()) .get(&active_searchable_item.downgrade())
.unwrap(); .unwrap();
active_searchable_item.update_matches(matches, cx); active_searchable_item.update_matches(matches, cx);
if select_closest_match { if select_closest_match {
if let Some(match_ix) = this.active_match_index { if let Some(match_ix) = this.active_match_index {
active_searchable_item active_searchable_item
.activate_match(match_ix, matches, cx); .activate_match(match_ix, matches, cx);
}
} }
} }
cx.notify();
} }
}) cx.notify();
.log_err(); }
} })
.log_err();
})); }));
} }
} }

View file

@ -277,10 +277,8 @@ impl TerminalView {
let epoch = self.next_blink_epoch(); let epoch = self.next_blink_epoch();
cx.spawn(|this, mut cx| async move { cx.spawn(|this, mut cx| async move {
Timer::after(CURSOR_BLINK_INTERVAL).await; Timer::after(CURSOR_BLINK_INTERVAL).await;
if let Some(this) = this.upgrade(&cx) { this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx))
this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx)) .log_err();
.log_err();
}
}) })
.detach(); .detach();
} }
@ -293,10 +291,8 @@ impl TerminalView {
let epoch = self.next_blink_epoch(); let epoch = self.next_blink_epoch();
cx.spawn(|this, mut cx| async move { cx.spawn(|this, mut cx| async move {
Timer::after(CURSOR_BLINK_INTERVAL).await; Timer::after(CURSOR_BLINK_INTERVAL).await;
if let Some(this) = this.upgrade(&cx) { this.update(&mut cx, |this, cx| this.resume_cursor_blinking(epoch, cx))
this.update(&mut cx, |this, cx| this.resume_cursor_blinking(epoch, cx)) .log_err();
.log_err();
}
}) })
.detach(); .detach();
} }

View file

@ -187,17 +187,15 @@ impl PickerDelegate for ThemeSelectorDelegate {
.await .await
}; };
if let Some(this) = this.upgrade(&cx) { this.update(&mut cx, |this, cx| {
this.update(&mut cx, |this, cx| { let delegate = this.delegate_mut();
let delegate = this.delegate_mut(); delegate.matches = matches;
delegate.matches = matches; delegate.selected_index = delegate
delegate.selected_index = delegate .selected_index
.selected_index .min(delegate.matches.len().saturating_sub(1));
.min(delegate.matches.len().saturating_sub(1)); delegate.show_selected_theme(cx);
delegate.show_selected_theme(cx); })
}) .log_err();
.log_err();
}
}) })
} }

View file

@ -105,16 +105,14 @@ impl PickerDelegate for BaseKeymapSelectorDelegate {
.await .await
}; };
if let Some(this) = this.upgrade(&cx) { this.update(&mut cx, |this, _| {
this.update(&mut cx, |this, _| { let delegate = this.delegate_mut();
let delegate = this.delegate_mut(); delegate.matches = matches;
delegate.matches = matches; delegate.selected_index = delegate
delegate.selected_index = delegate .selected_index
.selected_index .min(delegate.matches.len().saturating_sub(1));
.min(delegate.matches.len().saturating_sub(1)); })
}) .log_err();
.log_err();
}
}) })
} }

View file

@ -3,7 +3,7 @@ use crate::{
FollowableItemBuilders, ItemNavHistory, Pane, ToolbarItemLocation, ViewId, Workspace, FollowableItemBuilders, ItemNavHistory, Pane, ToolbarItemLocation, ViewId, Workspace,
WorkspaceId, WorkspaceId,
}; };
use anyhow::{anyhow, Result}; use anyhow::Result;
use client::{proto, Client}; use client::{proto, Client};
use gpui::{ use gpui::{
fonts::HighlightStyle, AnyElement, AnyViewHandle, AppContext, ModelHandle, Task, View, fonts::HighlightStyle, AnyElement, AnyViewHandle, AppContext, ModelHandle, Task, View,
@ -481,8 +481,6 @@ impl<T: Item> ItemHandle for ViewHandle<T> {
} else { } else {
cx.spawn(|workspace, mut cx| async move { cx.spawn(|workspace, mut cx| async move {
workspace workspace
.upgrade(&cx)
.ok_or_else(|| anyhow!("workspace was dropped"))?
.update(&mut cx, |workspace, cx| { .update(&mut cx, |workspace, cx| {
item.git_diff_recalc( item.git_diff_recalc(
workspace.project().clone(), workspace.project().clone(),

View file

@ -2005,9 +2005,11 @@ impl NavHistory {
} }
fn did_update(&self, cx: &mut WindowContext) { fn did_update(&self, cx: &mut WindowContext) {
if let Some(pane) = self.pane.upgrade(cx) { let pane = self.pane.clone();
cx.defer(move |cx| pane.update(cx, |pane, cx| pane.history_updated(cx))); cx.defer(move |cx| {
} pane.update(cx, |pane, cx| pane.history_updated(cx))
.log_err();
});
} }
} }

View file

@ -6,7 +6,9 @@ use std::{
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use async_recursion::async_recursion; use async_recursion::async_recursion;
use gpui::{platform::WindowBounds, AsyncAppContext, Axis, ModelHandle, Task, ViewHandle}; use gpui::{
platform::WindowBounds, AsyncAppContext, Axis, ModelHandle, Task, ViewHandle, WeakViewHandle,
};
use db::sqlez::{ use db::sqlez::{
bindable::{Bind, Column, StaticColumnCount}, bindable::{Bind, Column, StaticColumnCount},
@ -97,7 +99,7 @@ impl SerializedPaneGroup {
&self, &self,
project: &ModelHandle<Project>, project: &ModelHandle<Project>,
workspace_id: WorkspaceId, workspace_id: WorkspaceId,
workspace: &ViewHandle<Workspace>, workspace: &WeakViewHandle<Workspace>,
cx: &mut AsyncAppContext, cx: &mut AsyncAppContext,
) -> Option<(Member, Option<ViewHandle<Pane>>)> { ) -> Option<(Member, Option<ViewHandle<Pane>>)> {
match self { match self {
@ -172,7 +174,7 @@ impl SerializedPane {
project: &ModelHandle<Project>, project: &ModelHandle<Project>,
pane_handle: &ViewHandle<Pane>, pane_handle: &ViewHandle<Pane>,
workspace_id: WorkspaceId, workspace_id: WorkspaceId,
workspace: &ViewHandle<Workspace>, workspace: &WeakViewHandle<Workspace>,
cx: &mut AsyncAppContext, cx: &mut AsyncAppContext,
) -> Result<()> { ) -> Result<()> {
let mut active_item_index = None; let mut active_item_index = None;
@ -181,13 +183,7 @@ impl SerializedPane {
let item_handle = pane_handle let item_handle = pane_handle
.update(cx, |_, cx| { .update(cx, |_, cx| {
if let Some(deserializer) = cx.global::<ItemDeserializers>().get(&item.kind) { if let Some(deserializer) = cx.global::<ItemDeserializers>().get(&item.kind) {
deserializer( deserializer(project, workspace.clone(), workspace_id, item.item_id, cx)
project,
workspace.downgrade(),
workspace_id,
item.item_id,
cx,
)
} else { } else {
Task::ready(Err(anyhow::anyhow!( Task::ready(Err(anyhow::anyhow!(
"Deserializer does not exist for item kind: {}", "Deserializer does not exist for item kind: {}",

View file

@ -599,13 +599,11 @@ impl DelayedDebouncedEditAction {
_ = timer => {} _ = timer => {}
} }
if let Some(workspace) = workspace.upgrade(&cx) { if let Some(result) = workspace
if let Some(result) = workspace .update(&mut cx, |workspace, cx| (f)(workspace, cx))
.update(&mut cx, |workspace, cx| (f)(workspace, cx)) .log_err()
.log_err() {
{ result.await.log_err();
result.await.log_err();
}
} }
})); }));
} }
@ -740,9 +738,7 @@ impl Workspace {
Stream::map(current_user, drop).merge(Stream::map(connection_status, drop)); Stream::map(current_user, drop).merge(Stream::map(connection_status, drop));
while stream.recv().await.is_some() { while stream.recv().await.is_some() {
if let Some(this) = this.upgrade(&cx) { this.update(&mut cx, |_, cx| cx.notify())?;
this.update(&mut cx, |_, cx| cx.notify())?;
}
} }
anyhow::Ok(()) anyhow::Ok(())
}); });
@ -754,8 +750,7 @@ impl Workspace {
mpsc::unbounded::<(PeerId, proto::UpdateFollowers)>(); mpsc::unbounded::<(PeerId, proto::UpdateFollowers)>();
let _apply_leader_updates = cx.spawn(|this, mut cx| async move { let _apply_leader_updates = cx.spawn(|this, mut cx| async move {
while let Some((leader_id, update)) = leader_updates_rx.next().await { while let Some((leader_id, update)) = leader_updates_rx.next().await {
let Some(this) = this.upgrade(&cx) else { break }; Self::process_leader_update(&this, leader_id, update, &mut cx)
Self::process_leader_update(this, leader_id, update, &mut cx)
.await .await
.log_err(); .log_err();
} }
@ -1977,30 +1972,28 @@ impl Workspace {
Some(cx.spawn(|this, mut cx| async move { Some(cx.spawn(|this, mut cx| async move {
let response = request.await?; let response = request.await?;
if let Some(this) = this.upgrade(&cx) { this.update(&mut cx, |this, _| {
this.update(&mut cx, |this, _| { let state = this
let state = this .follower_states_by_leader
.follower_states_by_leader .get_mut(&leader_id)
.get_mut(&leader_id) .and_then(|states_by_pane| states_by_pane.get_mut(&pane))
.and_then(|states_by_pane| states_by_pane.get_mut(&pane)) .ok_or_else(|| anyhow!("following interrupted"))?;
.ok_or_else(|| anyhow!("following interrupted"))?; state.active_view_id = if let Some(active_view_id) = response.active_view_id {
state.active_view_id = if let Some(active_view_id) = response.active_view_id { Some(ViewId::from_proto(active_view_id)?)
Some(ViewId::from_proto(active_view_id)?) } else {
} else { None
None };
}; Ok::<_, anyhow::Error>(())
Ok::<_, anyhow::Error>(()) })??;
})??; Self::add_views_from_leader(
Self::add_views_from_leader( this.clone(),
this.clone(), leader_id,
leader_id, vec![pane],
vec![pane], response.views,
response.views, &mut cx,
&mut cx, )
) .await?;
.await?; this.update(&mut cx, |this, cx| this.leader_updated(leader_id, cx))?;
this.update(&mut cx, |this, cx| this.leader_updated(leader_id, cx))?;
}
Ok(()) Ok(())
})) }))
} }
@ -2303,7 +2296,7 @@ impl Workspace {
} }
async fn process_leader_update( async fn process_leader_update(
this: ViewHandle<Self>, this: &WeakViewHandle<Self>,
leader_id: PeerId, leader_id: PeerId,
update: proto::UpdateFollowers, update: proto::UpdateFollowers,
cx: &mut AsyncAppContext, cx: &mut AsyncAppContext,
@ -2363,7 +2356,7 @@ impl Workspace {
} }
async fn add_views_from_leader( async fn add_views_from_leader(
this: ViewHandle<Self>, this: WeakViewHandle<Self>,
leader_id: PeerId, leader_id: PeerId,
panes: Vec<ViewHandle<Pane>>, panes: Vec<ViewHandle<Pane>>,
views: Vec<proto::View>, views: Vec<proto::View>,
@ -2691,82 +2684,80 @@ impl Workspace {
cx: &mut AppContext, cx: &mut AppContext,
) { ) {
cx.spawn(|mut cx| async move { cx.spawn(|mut cx| async move {
if let Some(workspace) = workspace.upgrade(&cx) { let (project, dock_pane_handle, old_center_pane) =
let (project, dock_pane_handle, old_center_pane) = workspace.read_with(&cx, |workspace, _| {
workspace.read_with(&cx, |workspace, _| { (
( workspace.project().clone(),
workspace.project().clone(), workspace.dock_pane().clone(),
workspace.dock_pane().clone(), workspace.last_active_center_pane.clone(),
workspace.last_active_center_pane.clone(),
)
})?;
serialized_workspace
.dock_pane
.deserialize_to(
&project,
&dock_pane_handle,
serialized_workspace.id,
&workspace,
&mut cx,
) )
.await?;
// Traverse the splits tree and add to things
let center_group = serialized_workspace
.center_group
.deserialize(&project, serialized_workspace.id, &workspace, &mut cx)
.await;
// Remove old panes from workspace panes list
workspace.update(&mut cx, |workspace, cx| {
if let Some((center_group, active_pane)) = center_group {
workspace.remove_panes(workspace.center.root.clone(), cx);
// Swap workspace center group
workspace.center = PaneGroup::with_root(center_group);
// Change the focus to the workspace first so that we retrigger focus in on the pane.
cx.focus_self();
if let Some(active_pane) = active_pane {
cx.focus(&active_pane);
} else {
cx.focus(workspace.panes.last().unwrap());
}
} else {
let old_center_handle = old_center_pane.and_then(|weak| weak.upgrade(cx));
if let Some(old_center_handle) = old_center_handle {
cx.focus(&old_center_handle)
} else {
cx.focus_self()
}
}
if workspace.left_sidebar().read(cx).is_open()
!= serialized_workspace.left_sidebar_open
{
workspace.toggle_sidebar(SidebarSide::Left, cx);
}
// Note that without after_window, the focus_self() and
// the focus the dock generates start generating alternating
// focus due to the deferred execution each triggering each other
cx.after_window_update(move |workspace, cx| {
Dock::set_dock_position(
workspace,
serialized_workspace.dock_position,
true,
cx,
);
});
cx.notify();
})?; })?;
// Serialize ourself to make sure our timestamps and any pane / item changes are replicated serialized_workspace
workspace.read_with(&cx, |workspace, cx| workspace.serialize_workspace(cx))? .dock_pane
} .deserialize_to(
&project,
&dock_pane_handle,
serialized_workspace.id,
&workspace,
&mut cx,
)
.await?;
// Traverse the splits tree and add to things
let center_group = serialized_workspace
.center_group
.deserialize(&project, serialized_workspace.id, &workspace, &mut cx)
.await;
// Remove old panes from workspace panes list
workspace.update(&mut cx, |workspace, cx| {
if let Some((center_group, active_pane)) = center_group {
workspace.remove_panes(workspace.center.root.clone(), cx);
// Swap workspace center group
workspace.center = PaneGroup::with_root(center_group);
// Change the focus to the workspace first so that we retrigger focus in on the pane.
cx.focus_self();
if let Some(active_pane) = active_pane {
cx.focus(&active_pane);
} else {
cx.focus(workspace.panes.last().unwrap());
}
} else {
let old_center_handle = old_center_pane.and_then(|weak| weak.upgrade(cx));
if let Some(old_center_handle) = old_center_handle {
cx.focus(&old_center_handle)
} else {
cx.focus_self()
}
}
if workspace.left_sidebar().read(cx).is_open()
!= serialized_workspace.left_sidebar_open
{
workspace.toggle_sidebar(SidebarSide::Left, cx);
}
// Note that without after_window, the focus_self() and
// the focus the dock generates start generating alternating
// focus due to the deferred execution each triggering each other
cx.after_window_update(move |workspace, cx| {
Dock::set_dock_position(
workspace,
serialized_workspace.dock_position,
true,
cx,
);
});
cx.notify();
})?;
// Serialize ourself to make sure our timestamps and any pane / item changes are replicated
workspace.read_with(&cx, |workspace, cx| workspace.serialize_workspace(cx))?;
anyhow::Ok(()) anyhow::Ok(())
}) })
.detach_and_log_err(cx); .detach_and_log_err(cx);

View file

@ -509,43 +509,43 @@ fn open_log_file(
app_state.fs.load(&paths::LOG) app_state.fs.load(&paths::LOG)
); );
if let Some(workspace) = workspace.upgrade(&cx) { let mut lines = VecDeque::with_capacity(MAX_LINES);
let mut lines = VecDeque::with_capacity(MAX_LINES); for line in old_log
for line in old_log .iter()
.iter() .flat_map(|log| log.lines())
.flat_map(|log| log.lines()) .chain(new_log.iter().flat_map(|log| log.lines()))
.chain(new_log.iter().flat_map(|log| log.lines())) {
{ if lines.len() == MAX_LINES {
if lines.len() == MAX_LINES { lines.pop_front();
lines.pop_front();
}
lines.push_back(line);
} }
let log = lines lines.push_back(line);
.into_iter()
.flat_map(|line| [line, "\n"])
.collect::<String>();
workspace
.update(&mut cx, |workspace, cx| {
let project = workspace.project().clone();
let buffer = project
.update(cx, |project, cx| project.create_buffer("", None, cx))
.expect("creating buffers on a local workspace always succeeds");
buffer.update(cx, |buffer, cx| buffer.edit([(0..0, log)], None, cx));
let buffer = cx.add_model(|cx| {
MultiBuffer::singleton(buffer, cx).with_title("Log".into())
});
workspace.add_item(
Box::new(cx.add_view(|cx| {
Editor::for_multibuffer(buffer, Some(project), cx)
})),
cx,
);
})
.log_err();
} }
let log = lines
.into_iter()
.flat_map(|line| [line, "\n"])
.collect::<String>();
workspace
.update(&mut cx, |workspace, cx| {
let project = workspace.project().clone();
let buffer = project
.update(cx, |project, cx| project.create_buffer("", None, cx))
.expect("creating buffers on a local workspace always succeeds");
buffer.update(cx, |buffer, cx| buffer.edit([(0..0, log)], None, cx));
let buffer = cx.add_model(|cx| {
MultiBuffer::singleton(buffer, cx).with_title("Log".into())
});
workspace.add_item(
Box::new(
cx.add_view(|cx| {
Editor::for_multibuffer(buffer, Some(project), cx)
}),
),
cx,
);
})
.log_err();
}) })
.detach(); .detach();
}) })
@ -559,8 +559,6 @@ fn open_telemetry_log_file(
) { ) {
workspace.with_local_workspace(&app_state.clone(), cx, move |_, cx| { workspace.with_local_workspace(&app_state.clone(), cx, move |_, cx| {
cx.spawn(|workspace, mut cx| async move { cx.spawn(|workspace, mut cx| async move {
let workspace = workspace.upgrade(&cx)?;
async fn fetch_log_string(app_state: &Arc<AppState>) -> Option<String> { async fn fetch_log_string(app_state: &Arc<AppState>) -> Option<String> {
let path = app_state.client.telemetry_log_file_path()?; let path = app_state.client.telemetry_log_file_path()?;
app_state.fs.load(&path).await.log_err() app_state.fs.load(&path).await.log_err()