mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-07 20:39:04 +03:00
Remove ViewContext::dispatch_any_action
This commit is contained in:
parent
029538fe21
commit
d815fc88ae
@ -5,7 +5,7 @@ use gpui::{
|
||||
actions, anyhow,
|
||||
elements::*,
|
||||
platform::{CursorStyle, MouseButton},
|
||||
Action, AppContext, Entity, ModelHandle, View, ViewContext, ViewHandle,
|
||||
AppContext, Entity, ModelHandle, View, ViewContext, ViewHandle,
|
||||
};
|
||||
use language::{LanguageRegistry, LanguageServerBinaryStatus};
|
||||
use project::{LanguageServerProgress, Project};
|
||||
@ -45,7 +45,7 @@ struct PendingWork<'a> {
|
||||
struct Content {
|
||||
icon: Option<&'static str>,
|
||||
message: String,
|
||||
action: Option<Box<dyn Action>>,
|
||||
on_click: Option<Arc<dyn Fn(&mut ActivityIndicator, &mut ViewContext<ActivityIndicator>)>>,
|
||||
}
|
||||
|
||||
pub fn init(cx: &mut AppContext) {
|
||||
@ -199,7 +199,7 @@ impl ActivityIndicator {
|
||||
return Content {
|
||||
icon: None,
|
||||
message,
|
||||
action: None,
|
||||
on_click: None,
|
||||
};
|
||||
}
|
||||
|
||||
@ -230,7 +230,7 @@ impl ActivityIndicator {
|
||||
downloading.join(", "),
|
||||
if downloading.len() > 1 { "s" } else { "" }
|
||||
),
|
||||
action: None,
|
||||
on_click: None,
|
||||
};
|
||||
} else if !checking_for_update.is_empty() {
|
||||
return Content {
|
||||
@ -244,7 +244,7 @@ impl ActivityIndicator {
|
||||
""
|
||||
}
|
||||
),
|
||||
action: None,
|
||||
on_click: None,
|
||||
};
|
||||
} else if !failed.is_empty() {
|
||||
return Content {
|
||||
@ -254,7 +254,9 @@ impl ActivityIndicator {
|
||||
failed.join(", "),
|
||||
if failed.len() > 1 { "s" } else { "" }
|
||||
),
|
||||
action: Some(Box::new(ShowErrorMessage)),
|
||||
on_click: Some(Arc::new(|this, cx| {
|
||||
this.show_error_message(&Default::default(), cx)
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
@ -264,27 +266,31 @@ impl ActivityIndicator {
|
||||
AutoUpdateStatus::Checking => Content {
|
||||
icon: Some(DOWNLOAD_ICON),
|
||||
message: "Checking for Zed updates…".to_string(),
|
||||
action: None,
|
||||
on_click: None,
|
||||
},
|
||||
AutoUpdateStatus::Downloading => Content {
|
||||
icon: Some(DOWNLOAD_ICON),
|
||||
message: "Downloading Zed update…".to_string(),
|
||||
action: None,
|
||||
on_click: None,
|
||||
},
|
||||
AutoUpdateStatus::Installing => Content {
|
||||
icon: Some(DOWNLOAD_ICON),
|
||||
message: "Installing Zed update…".to_string(),
|
||||
action: None,
|
||||
on_click: None,
|
||||
},
|
||||
AutoUpdateStatus::Updated => Content {
|
||||
icon: None,
|
||||
message: "Click to restart and update Zed".to_string(),
|
||||
action: Some(Box::new(workspace::Restart)),
|
||||
on_click: Some(Arc::new(|_, cx| {
|
||||
workspace::restart(&Default::default(), cx)
|
||||
})),
|
||||
},
|
||||
AutoUpdateStatus::Errored => Content {
|
||||
icon: Some(WARNING_ICON),
|
||||
message: "Auto update failed".to_string(),
|
||||
action: Some(Box::new(DismissErrorMessage)),
|
||||
on_click: Some(Arc::new(|this, cx| {
|
||||
this.dismiss_error_message(&Default::default(), cx)
|
||||
})),
|
||||
},
|
||||
AutoUpdateStatus::Idle => Default::default(),
|
||||
};
|
||||
@ -294,7 +300,7 @@ impl ActivityIndicator {
|
||||
return Content {
|
||||
icon: None,
|
||||
message: most_recent_active_task.to_string(),
|
||||
action: None,
|
||||
on_click: None,
|
||||
};
|
||||
}
|
||||
|
||||
@ -315,7 +321,7 @@ impl View for ActivityIndicator {
|
||||
let Content {
|
||||
icon,
|
||||
message,
|
||||
action,
|
||||
on_click,
|
||||
} = self.content_to_render(cx);
|
||||
|
||||
let mut element = MouseEventHandler::<Self, _>::new(0, cx, |state, cx| {
|
||||
@ -325,7 +331,7 @@ impl View for ActivityIndicator {
|
||||
.workspace
|
||||
.status_bar
|
||||
.lsp_status;
|
||||
let style = if state.hovered() && action.is_some() {
|
||||
let style = if state.hovered() && on_click.is_some() {
|
||||
theme.hover.as_ref().unwrap_or(&theme.default)
|
||||
} else {
|
||||
&theme.default
|
||||
@ -353,12 +359,10 @@ impl View for ActivityIndicator {
|
||||
.aligned()
|
||||
});
|
||||
|
||||
if let Some(action) = action {
|
||||
if let Some(on_click) = on_click.clone() {
|
||||
element = element
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.on_click(MouseButton::Left, move |_, _, cx| {
|
||||
cx.dispatch_any_action(action.boxed_clone())
|
||||
});
|
||||
.on_click(MouseButton::Left, move |_, this, cx| on_click(this, cx));
|
||||
}
|
||||
|
||||
element.into_any()
|
||||
|
@ -560,7 +560,7 @@ impl Copilot {
|
||||
}
|
||||
}
|
||||
|
||||
fn reinstall(&mut self, cx: &mut ModelContext<Self>) -> Task<()> {
|
||||
pub fn reinstall(&mut self, cx: &mut ModelContext<Self>) -> Task<()> {
|
||||
let start_task = cx
|
||||
.spawn({
|
||||
let http = self.http.clone();
|
||||
|
@ -1,5 +1,5 @@
|
||||
use context_menu::{ContextMenu, ContextMenuItem};
|
||||
use copilot::{Copilot, Reinstall, SignOut, Status};
|
||||
use copilot::{Copilot, SignOut, Status};
|
||||
use editor::Editor;
|
||||
use gpui::{
|
||||
elements::*,
|
||||
@ -103,11 +103,21 @@ impl View for CopilotButton {
|
||||
{
|
||||
workspace.update(cx, |workspace, cx| {
|
||||
workspace.show_toast(
|
||||
Toast::new_action(
|
||||
Toast::new(
|
||||
COPILOT_ERROR_TOAST_ID,
|
||||
format!("Copilot can't be started: {}", e),
|
||||
)
|
||||
.on_click(
|
||||
"Reinstall Copilot",
|
||||
Reinstall,
|
||||
|cx| {
|
||||
if let Some(copilot) = Copilot::global(cx) {
|
||||
copilot
|
||||
.update(cx, |copilot, cx| {
|
||||
copilot.reinstall(cx)
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
},
|
||||
),
|
||||
cx,
|
||||
);
|
||||
|
@ -3199,11 +3199,13 @@ impl Editor {
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.with_padding(Padding::uniform(3.))
|
||||
.on_click(MouseButton::Left, {
|
||||
move |_, _, cx| {
|
||||
cx.dispatch_any_action(match fold_status {
|
||||
FoldStatus::Folded => Box::new(UnfoldAt { buffer_row }),
|
||||
FoldStatus::Foldable => Box::new(FoldAt { buffer_row }),
|
||||
});
|
||||
move |_, editor, cx| match fold_status {
|
||||
FoldStatus::Folded => {
|
||||
editor.unfold_at(&UnfoldAt { buffer_row }, cx);
|
||||
}
|
||||
FoldStatus::Foldable => {
|
||||
editor.fold_at(&FoldAt { buffer_row }, cx);
|
||||
}
|
||||
}
|
||||
})
|
||||
.into_any()
|
||||
|
@ -1745,7 +1745,7 @@ impl AppContext {
|
||||
self.pending_effects.push_back(Effect::RefreshWindows);
|
||||
}
|
||||
|
||||
pub fn dispatch_action_at(&mut self, window_id: usize, view_id: usize, action: impl Action) {
|
||||
fn dispatch_action_at(&mut self, window_id: usize, view_id: usize, action: impl Action) {
|
||||
self.dispatch_any_action_at(window_id, view_id, Box::new(action));
|
||||
}
|
||||
|
||||
@ -3196,13 +3196,6 @@ impl<'a, 'b, V: View> ViewContext<'a, 'b, V> {
|
||||
.dispatch_action_at(window_id, view_id, action)
|
||||
}
|
||||
|
||||
pub fn dispatch_any_action(&mut self, action: Box<dyn Action>) {
|
||||
let window_id = self.window_id;
|
||||
let view_id = self.view_id;
|
||||
self.window_context
|
||||
.dispatch_any_action_at(window_id, view_id, action)
|
||||
}
|
||||
|
||||
pub fn defer(&mut self, callback: impl 'static + FnOnce(&mut V, &mut ViewContext<V>)) {
|
||||
let handle = self.handle();
|
||||
self.window_context
|
||||
|
@ -61,7 +61,7 @@ fn toggle(app_state: Weak<AppState>, cx: &mut ViewContext<Workspace>) -> Option<
|
||||
});
|
||||
} else {
|
||||
workspace.show_notification(0, cx, |cx| {
|
||||
cx.add_view(|_| MessageNotification::new_message("No recent projects to open."))
|
||||
cx.add_view(|_| MessageNotification::new("No recent projects to open."))
|
||||
})
|
||||
}
|
||||
})?;
|
||||
|
@ -338,8 +338,8 @@ impl BufferSearchBar {
|
||||
.contained()
|
||||
.with_style(style.container)
|
||||
})
|
||||
.on_click(MouseButton::Left, move |_, _, cx| {
|
||||
cx.dispatch_any_action(option.to_toggle_action())
|
||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
||||
this.toggle_search_option(option, cx);
|
||||
})
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.with_tooltip::<Self>(
|
||||
@ -386,8 +386,10 @@ impl BufferSearchBar {
|
||||
.with_style(style.container)
|
||||
})
|
||||
.on_click(MouseButton::Left, {
|
||||
let action = action.boxed_clone();
|
||||
move |_, _, cx| cx.dispatch_any_action(action.boxed_clone())
|
||||
move |_, this, cx| match direction {
|
||||
Direction::Prev => this.select_prev_match(&Default::default(), cx),
|
||||
Direction::Next => this.select_next_match(&Default::default(), cx),
|
||||
}
|
||||
})
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.with_tooltip::<NavButton>(
|
||||
@ -405,7 +407,6 @@ impl BufferSearchBar {
|
||||
theme: &theme::Search,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> AnyElement<Self> {
|
||||
let action = Box::new(Dismiss);
|
||||
let tooltip = "Dismiss Buffer Search";
|
||||
let tooltip_style = cx.global::<Settings>().theme.tooltip.clone();
|
||||
|
||||
@ -422,12 +423,17 @@ impl BufferSearchBar {
|
||||
.contained()
|
||||
.with_style(style.container)
|
||||
})
|
||||
.on_click(MouseButton::Left, {
|
||||
let action = action.boxed_clone();
|
||||
move |_, _, cx| cx.dispatch_any_action(action.boxed_clone())
|
||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
||||
this.dismiss(&Default::default(), cx)
|
||||
})
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.with_tooltip::<CloseButton>(0, tooltip.to_string(), Some(action), tooltip_style, cx)
|
||||
.with_tooltip::<CloseButton>(
|
||||
0,
|
||||
tooltip.to_string(),
|
||||
Some(Box::new(Dismiss)),
|
||||
tooltip_style,
|
||||
cx,
|
||||
)
|
||||
.into_any()
|
||||
}
|
||||
|
||||
|
@ -788,9 +788,10 @@ impl ProjectSearchBar {
|
||||
.contained()
|
||||
.with_style(style.container)
|
||||
})
|
||||
.on_click(MouseButton::Left, {
|
||||
let action = action.boxed_clone();
|
||||
move |_, _, cx| cx.dispatch_any_action(action.boxed_clone())
|
||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
||||
if let Some(search) = this.active_project_search.as_ref() {
|
||||
search.update(cx, |search, cx| search.select_match(direction, cx));
|
||||
}
|
||||
})
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.with_tooltip::<NavButton>(
|
||||
@ -822,8 +823,8 @@ impl ProjectSearchBar {
|
||||
.contained()
|
||||
.with_style(style.container)
|
||||
})
|
||||
.on_click(MouseButton::Left, move |_, _, cx| {
|
||||
cx.dispatch_any_action(option.to_toggle_action())
|
||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
||||
this.toggle_search_option(option, cx);
|
||||
})
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.with_tooltip::<Self>(
|
||||
|
@ -114,17 +114,14 @@ impl Workspace {
|
||||
pub fn show_toast(&mut self, toast: Toast, cx: &mut ViewContext<Self>) {
|
||||
self.dismiss_notification::<simple_message_notification::MessageNotification>(toast.id, cx);
|
||||
self.show_notification(toast.id, cx, |cx| {
|
||||
cx.add_view(|_cx| match &toast.click {
|
||||
Some((click_msg, action)) => {
|
||||
simple_message_notification::MessageNotification::new_boxed_action(
|
||||
toast.msg.clone(),
|
||||
action.boxed_clone(),
|
||||
click_msg.clone(),
|
||||
)
|
||||
}
|
||||
None => {
|
||||
simple_message_notification::MessageNotification::new_message(toast.msg.clone())
|
||||
cx.add_view(|_cx| match toast.on_click.as_ref() {
|
||||
Some((click_msg, on_click)) => {
|
||||
let on_click = on_click.clone();
|
||||
simple_message_notification::MessageNotification::new(toast.msg.clone())
|
||||
.with_click_message(click_msg.clone())
|
||||
.on_click(move |cx| on_click(cx))
|
||||
}
|
||||
None => simple_message_notification::MessageNotification::new(toast.msg.clone()),
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -152,19 +149,17 @@ impl Workspace {
|
||||
}
|
||||
|
||||
pub mod simple_message_notification {
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
||||
use gpui::{
|
||||
actions,
|
||||
elements::{Flex, MouseEventHandler, Padding, ParentElement, Svg, Text},
|
||||
impl_actions,
|
||||
platform::{CursorStyle, MouseButton},
|
||||
Action, AppContext, Element, Entity, View, ViewContext,
|
||||
AppContext, Element, Entity, View, ViewContext,
|
||||
};
|
||||
use menu::Cancel;
|
||||
use serde::Deserialize;
|
||||
use settings::Settings;
|
||||
use std::{borrow::Cow, sync::Arc};
|
||||
|
||||
use crate::Workspace;
|
||||
|
||||
@ -194,7 +189,7 @@ pub mod simple_message_notification {
|
||||
|
||||
pub struct MessageNotification {
|
||||
message: Cow<'static, str>,
|
||||
click_action: Option<Box<dyn Action>>,
|
||||
on_click: Option<Arc<dyn Fn(&mut ViewContext<Self>)>>,
|
||||
click_message: Option<Cow<'static, str>>,
|
||||
}
|
||||
|
||||
@ -207,36 +202,31 @@ pub mod simple_message_notification {
|
||||
}
|
||||
|
||||
impl MessageNotification {
|
||||
pub fn new_message<S: Into<Cow<'static, str>>>(message: S) -> MessageNotification {
|
||||
pub fn new<S>(message: S) -> MessageNotification
|
||||
where
|
||||
S: Into<Cow<'static, str>>,
|
||||
{
|
||||
Self {
|
||||
message: message.into(),
|
||||
click_action: None,
|
||||
on_click: None,
|
||||
click_message: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_boxed_action<S1: Into<Cow<'static, str>>, S2: Into<Cow<'static, str>>>(
|
||||
message: S1,
|
||||
click_action: Box<dyn Action>,
|
||||
click_message: S2,
|
||||
) -> Self {
|
||||
Self {
|
||||
message: message.into(),
|
||||
click_action: Some(click_action),
|
||||
click_message: Some(click_message.into()),
|
||||
}
|
||||
pub fn with_click_message<S>(mut self, message: S) -> Self
|
||||
where
|
||||
S: Into<Cow<'static, str>>,
|
||||
{
|
||||
self.click_message = Some(message.into());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn new<S1: Into<Cow<'static, str>>, A: Action, S2: Into<Cow<'static, str>>>(
|
||||
message: S1,
|
||||
click_action: A,
|
||||
click_message: S2,
|
||||
) -> Self {
|
||||
Self {
|
||||
message: message.into(),
|
||||
click_action: Some(Box::new(click_action) as Box<dyn Action>),
|
||||
click_message: Some(click_message.into()),
|
||||
}
|
||||
pub fn on_click<F>(mut self, on_click: F) -> Self
|
||||
where
|
||||
F: 'static + Fn(&mut ViewContext<Self>),
|
||||
{
|
||||
self.on_click = Some(Arc::new(on_click));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn dismiss(&mut self, _: &CancelMessageNotification, cx: &mut ViewContext<Self>) {
|
||||
@ -255,14 +245,10 @@ pub mod simple_message_notification {
|
||||
|
||||
enum MessageNotificationTag {}
|
||||
|
||||
let click_action = self
|
||||
.click_action
|
||||
.as_ref()
|
||||
.map(|action| action.boxed_clone());
|
||||
let click_message = self.click_message.as_ref().map(|message| message.clone());
|
||||
let click_message = self.click_message.clone();
|
||||
let message = self.message.clone();
|
||||
|
||||
let has_click_action = click_action.is_some();
|
||||
let on_click = self.on_click.clone();
|
||||
let has_click_action = on_click.is_some();
|
||||
|
||||
MouseEventHandler::<MessageNotificationTag, _>::new(0, cx, |state, cx| {
|
||||
Flex::column()
|
||||
@ -326,10 +312,10 @@ pub mod simple_message_notification {
|
||||
// Since we're not using a proper overlay, we have to capture these extra events
|
||||
.on_down(MouseButton::Left, |_, _, _| {})
|
||||
.on_up(MouseButton::Left, |_, _, _| {})
|
||||
.on_click(MouseButton::Left, move |_, _, cx| {
|
||||
if let Some(click_action) = click_action.as_ref() {
|
||||
cx.dispatch_any_action(click_action.boxed_clone());
|
||||
cx.dispatch_action(CancelMessageNotification)
|
||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
||||
if let Some(on_click) = on_click.as_ref() {
|
||||
on_click(cx);
|
||||
this.dismiss(&Default::default(), cx);
|
||||
}
|
||||
})
|
||||
.with_cursor_style(if has_click_action {
|
||||
@ -372,7 +358,7 @@ where
|
||||
Err(err) => {
|
||||
workspace.show_notification(0, cx, |cx| {
|
||||
cx.add_view(|_cx| {
|
||||
simple_message_notification::MessageNotification::new_message(format!(
|
||||
simple_message_notification::MessageNotification::new(format!(
|
||||
"Error: {:?}",
|
||||
err,
|
||||
))
|
||||
|
@ -43,8 +43,9 @@ use gpui::{
|
||||
CursorStyle, MouseButton, PathPromptOptions, Platform, PromptLevel, WindowBounds,
|
||||
WindowOptions,
|
||||
},
|
||||
Action, AnyModelHandle, AnyViewHandle, AppContext, AsyncAppContext, Entity, ModelContext,
|
||||
ModelHandle, SizeConstraint, Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle,
|
||||
AnyModelHandle, AnyViewHandle, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle,
|
||||
SizeConstraint, Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle,
|
||||
WindowContext,
|
||||
};
|
||||
use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ProjectItem};
|
||||
use language::LanguageRegistry;
|
||||
@ -59,7 +60,7 @@ use std::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
notifications::simple_message_notification::{MessageNotification, OsOpen},
|
||||
notifications::simple_message_notification::MessageNotification,
|
||||
persistence::model::{SerializedPane, SerializedPaneGroup, SerializedWorkspace},
|
||||
};
|
||||
use lazy_static::lazy_static;
|
||||
@ -137,7 +138,7 @@ pub struct ActivatePane(pub usize);
|
||||
pub struct Toast {
|
||||
id: usize,
|
||||
msg: Cow<'static, str>,
|
||||
click: Option<(Cow<'static, str>, Box<dyn Action>)>,
|
||||
on_click: Option<(Cow<'static, str>, Arc<dyn Fn(&mut WindowContext)>)>,
|
||||
}
|
||||
|
||||
impl Toast {
|
||||
@ -145,21 +146,17 @@ impl Toast {
|
||||
Toast {
|
||||
id,
|
||||
msg: msg.into(),
|
||||
click: None,
|
||||
on_click: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_action<I1: Into<Cow<'static, str>>, I2: Into<Cow<'static, str>>>(
|
||||
id: usize,
|
||||
msg: I1,
|
||||
click_msg: I2,
|
||||
action: impl Action,
|
||||
) -> Self {
|
||||
Toast {
|
||||
id,
|
||||
msg: msg.into(),
|
||||
click: Some((click_msg.into(), Box::new(action))),
|
||||
}
|
||||
pub fn on_click<F, M>(mut self, message: M, on_click: F) -> Self
|
||||
where
|
||||
M: Into<Cow<'static, str>>,
|
||||
F: Fn(&mut WindowContext) + 'static,
|
||||
{
|
||||
self.on_click = Some((message.into(), Arc::new(on_click)));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@ -167,7 +164,7 @@ impl PartialEq for Toast {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.id == other.id
|
||||
&& self.msg == other.msg
|
||||
&& self.click.is_some() == other.click.is_some()
|
||||
&& self.on_click.is_some() == other.on_click.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
@ -176,10 +173,7 @@ impl Clone for Toast {
|
||||
Toast {
|
||||
id: self.id,
|
||||
msg: self.msg.to_owned(),
|
||||
click: self
|
||||
.click
|
||||
.as_ref()
|
||||
.map(|(msg, click)| (msg.to_owned(), click.boxed_clone())),
|
||||
on_click: self.on_click.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -260,6 +254,7 @@ pub fn init(app_state: Arc<AppState>, cx: &mut AppContext) {
|
||||
cx.add_async_action(Workspace::follow_next_collaborator);
|
||||
cx.add_async_action(Workspace::close);
|
||||
cx.add_global_action(Workspace::close_global);
|
||||
cx.add_global_action(restart);
|
||||
cx.add_async_action(Workspace::save_all);
|
||||
cx.add_action(Workspace::add_folder_to_project);
|
||||
cx.add_action(
|
||||
@ -303,9 +298,7 @@ pub fn init(app_state: Arc<AppState>, cx: &mut AppContext) {
|
||||
} else {
|
||||
workspace.show_notification(1, cx, |cx| {
|
||||
cx.add_view(|_| {
|
||||
MessageNotification::new_message(
|
||||
"Successfully installed the `zed` binary",
|
||||
)
|
||||
MessageNotification::new("Successfully installed the `zed` binary")
|
||||
})
|
||||
});
|
||||
}
|
||||
@ -2668,36 +2661,37 @@ impl Workspace {
|
||||
}
|
||||
|
||||
fn notify_if_database_failed(workspace: &WeakViewHandle<Workspace>, cx: &mut AsyncAppContext) {
|
||||
workspace.update(cx, |workspace, cx| {
|
||||
if (*db::ALL_FILE_DB_FAILED).load(std::sync::atomic::Ordering::Acquire) {
|
||||
workspace.show_notification_once(0, cx, |cx| {
|
||||
cx.add_view(|_| {
|
||||
MessageNotification::new(
|
||||
"Failed to load any database file.",
|
||||
OsOpen::new("https://github.com/zed-industries/community/issues/new?assignees=&labels=defect%2Ctriage&template=2_bug_report.yml".to_string()),
|
||||
"Click to let us know about this error"
|
||||
)
|
||||
})
|
||||
});
|
||||
} else {
|
||||
let backup_path = (*db::BACKUP_DB_PATH).read();
|
||||
if let Some(backup_path) = &*backup_path {
|
||||
const REPORT_ISSUE_URL: &str ="https://github.com/zed-industries/community/issues/new?assignees=&labels=defect%2Ctriage&template=2_bug_report.yml";
|
||||
|
||||
workspace
|
||||
.update(cx, |workspace, cx| {
|
||||
if (*db::ALL_FILE_DB_FAILED).load(std::sync::atomic::Ordering::Acquire) {
|
||||
workspace.show_notification_once(0, cx, |cx| {
|
||||
cx.add_view(|_| {
|
||||
let backup_path = backup_path.to_string_lossy();
|
||||
MessageNotification::new(
|
||||
format!(
|
||||
"Database file was corrupted. Old database backed up to {}",
|
||||
backup_path
|
||||
),
|
||||
OsOpen::new(backup_path.to_string()),
|
||||
"Click to show old database in finder",
|
||||
)
|
||||
MessageNotification::new("Failed to load any database file.")
|
||||
.with_click_message("Click to let us know about this error")
|
||||
.on_click(|cx| cx.platform().open_url(REPORT_ISSUE_URL))
|
||||
})
|
||||
});
|
||||
} else {
|
||||
let backup_path = (*db::BACKUP_DB_PATH).read();
|
||||
if let Some(backup_path) = backup_path.clone() {
|
||||
workspace.show_notification_once(0, cx, move |cx| {
|
||||
cx.add_view(move |_| {
|
||||
MessageNotification::new(format!(
|
||||
"Database file was corrupted. Old database backed up to {}",
|
||||
backup_path.display()
|
||||
))
|
||||
.with_click_message("Click to show old database in finder")
|
||||
.on_click(move |cx| {
|
||||
cx.platform().open_url(&backup_path.to_string_lossy())
|
||||
})
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}).log_err();
|
||||
})
|
||||
.log_err();
|
||||
}
|
||||
|
||||
impl Entity for Workspace {
|
||||
@ -3062,6 +3056,58 @@ pub fn join_remote_project(
|
||||
})
|
||||
}
|
||||
|
||||
pub fn restart(_: &Restart, cx: &mut 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 {
|
||||
if let (true, Some(workspace)) = (should_confirm, workspaces.first()) {
|
||||
let answer = cx.prompt(
|
||||
workspace.window_id(),
|
||||
PromptLevel::Info,
|
||||
"Are you sure you want to restart?",
|
||||
&["Restart", "Cancel"],
|
||||
);
|
||||
|
||||
if let Some(mut answer) = answer {
|
||||
let answer = answer.next().await;
|
||||
if answer != Some(0) {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the user cancels any save prompt, then keep the app open.
|
||||
for workspace in workspaces {
|
||||
if !workspace
|
||||
.update(&mut cx, |workspace, cx| {
|
||||
workspace.prepare_to_close(true, cx)
|
||||
})?
|
||||
.await?
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
cx.platform().restart();
|
||||
anyhow::Ok(())
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
}
|
||||
|
||||
fn parse_pixel_position_env_var(value: &str) -> Option<Vector2F> {
|
||||
let mut parts = value.split(',');
|
||||
let width: usize = parts.next()?.parse().ok()?;
|
||||
|
@ -35,7 +35,7 @@ use terminal_view::terminal_button::TerminalButton;
|
||||
use util::{channel::ReleaseChannel, paths, ResultExt};
|
||||
use uuid::Uuid;
|
||||
pub use workspace;
|
||||
use workspace::{sidebar::SidebarSide, AppState, Restart, Workspace};
|
||||
use workspace::{sidebar::SidebarSide, AppState, Workspace};
|
||||
|
||||
#[derive(Deserialize, Clone, PartialEq)]
|
||||
pub struct OpenBrowser {
|
||||
@ -113,7 +113,6 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut gpui::AppContext) {
|
||||
},
|
||||
);
|
||||
cx.add_global_action(quit);
|
||||
cx.add_global_action(restart);
|
||||
cx.add_global_action(move |action: &OpenBrowser, cx| cx.platform().open_url(&action.url));
|
||||
cx.add_global_action(move |_: &IncreaseBufferFontSize, cx| {
|
||||
cx.update_global::<Settings, _, _>(|settings, cx| {
|
||||
@ -370,58 +369,6 @@ 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 {
|
||||
if let (true, Some(workspace)) = (should_confirm, workspaces.first()) {
|
||||
let answer = cx.prompt(
|
||||
workspace.window_id(),
|
||||
PromptLevel::Info,
|
||||
"Are you sure you want to restart?",
|
||||
&["Restart", "Cancel"],
|
||||
);
|
||||
|
||||
if let Some(mut answer) = answer {
|
||||
let answer = answer.next().await;
|
||||
if answer != Some(0) {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the user cancels any save prompt, then keep the app open.
|
||||
for workspace in workspaces {
|
||||
if !workspace
|
||||
.update(&mut cx, |workspace, cx| {
|
||||
workspace.prepare_to_close(true, cx)
|
||||
})?
|
||||
.await?
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
cx.platform().restart();
|
||||
anyhow::Ok(())
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
}
|
||||
|
||||
fn quit(_: &Quit, cx: &mut gpui::AppContext) {
|
||||
let mut workspaces = cx
|
||||
.window_ids()
|
||||
|
Loading…
Reference in New Issue
Block a user