Allow prompts to have detail, and use for good
Make channel panel errors louder
This commit is contained in:
parent
df420c3767
commit
01424a62ea
17 changed files with 162 additions and 65 deletions
|
@ -2959,6 +2959,7 @@ impl InlineAssistant {
|
|||
cx.prompt(
|
||||
PromptLevel::Info,
|
||||
prompt_text.as_str(),
|
||||
None,
|
||||
&["Continue", "Cancel"],
|
||||
)
|
||||
})?;
|
||||
|
|
|
@ -130,7 +130,8 @@ pub fn check(_: &Check, cx: &mut WindowContext) {
|
|||
} else {
|
||||
drop(cx.prompt(
|
||||
gpui::PromptLevel::Info,
|
||||
"Auto-updates disabled for non-bundled app.",
|
||||
"Could not check for updates",
|
||||
Some("Auto-updates disabled for non-bundled app."),
|
||||
&["Ok"],
|
||||
));
|
||||
}
|
||||
|
|
|
@ -22,7 +22,10 @@ use gpui::{
|
|||
};
|
||||
use menu::{Cancel, Confirm, SecondaryConfirm, SelectNext, SelectPrev};
|
||||
use project::{Fs, Project};
|
||||
use rpc::proto::{self, PeerId};
|
||||
use rpc::{
|
||||
proto::{self, PeerId},
|
||||
ErrorCode, ErrorExt,
|
||||
};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use settings::Settings;
|
||||
use smallvec::SmallVec;
|
||||
|
@ -35,7 +38,7 @@ use ui::{
|
|||
use util::{maybe, ResultExt, TryFutureExt};
|
||||
use workspace::{
|
||||
dock::{DockPosition, Panel, PanelEvent},
|
||||
notifications::{NotifyResultExt, NotifyTaskExt},
|
||||
notifications::{DetachAndPromptErr, NotifyResultExt, NotifyTaskExt},
|
||||
Workspace,
|
||||
};
|
||||
|
||||
|
@ -879,7 +882,7 @@ impl CollabPanel {
|
|||
.update(cx, |workspace, cx| {
|
||||
let app_state = workspace.app_state().clone();
|
||||
workspace::join_remote_project(project_id, host_user_id, app_state, cx)
|
||||
.detach_and_log_err(cx);
|
||||
.detach_and_prompt_err("Failed to join project", cx, |_, _| None);
|
||||
})
|
||||
.ok();
|
||||
}))
|
||||
|
@ -1017,7 +1020,12 @@ impl CollabPanel {
|
|||
)
|
||||
})
|
||||
})
|
||||
.detach_and_notify_err(cx)
|
||||
.detach_and_prompt_err("Failed to grant write access", cx, |e, _| {
|
||||
match e.error_code() {
|
||||
ErrorCode::NeedsCla => Some("This user has not yet signed the CLA at https://zed.dev/cla.".into()),
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
}),
|
||||
)
|
||||
} else if role == proto::ChannelRole::Member {
|
||||
|
@ -1038,7 +1046,7 @@ impl CollabPanel {
|
|||
)
|
||||
})
|
||||
})
|
||||
.detach_and_notify_err(cx)
|
||||
.detach_and_prompt_err("Failed to revoke write access", cx, |_, _| None)
|
||||
}),
|
||||
)
|
||||
} else {
|
||||
|
@ -1258,7 +1266,11 @@ impl CollabPanel {
|
|||
app_state,
|
||||
cx,
|
||||
)
|
||||
.detach_and_log_err(cx);
|
||||
.detach_and_prompt_err(
|
||||
"Failed to join project",
|
||||
cx,
|
||||
|_, _| None,
|
||||
);
|
||||
}
|
||||
}
|
||||
ListEntry::ParticipantScreen { peer_id, .. } => {
|
||||
|
@ -1432,7 +1444,7 @@ impl CollabPanel {
|
|||
fn leave_call(cx: &mut WindowContext) {
|
||||
ActiveCall::global(cx)
|
||||
.update(cx, |call, cx| call.hang_up(cx))
|
||||
.detach_and_log_err(cx);
|
||||
.detach_and_prompt_err("Failed to hang up", cx, |_, _| None);
|
||||
}
|
||||
|
||||
fn toggle_contact_finder(&mut self, cx: &mut ViewContext<Self>) {
|
||||
|
@ -1534,11 +1546,11 @@ impl CollabPanel {
|
|||
cx: &mut ViewContext<CollabPanel>,
|
||||
) {
|
||||
if let Some(clipboard) = self.channel_clipboard.take() {
|
||||
self.channel_store.update(cx, |channel_store, cx| {
|
||||
channel_store
|
||||
.move_channel(clipboard.channel_id, Some(to_channel_id), cx)
|
||||
.detach_and_log_err(cx)
|
||||
})
|
||||
self.channel_store
|
||||
.update(cx, |channel_store, cx| {
|
||||
channel_store.move_channel(clipboard.channel_id, Some(to_channel_id), cx)
|
||||
})
|
||||
.detach_and_prompt_err("Failed to move channel", cx, |_, _| None)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1610,7 +1622,12 @@ impl CollabPanel {
|
|||
"Are you sure you want to remove the channel \"{}\"?",
|
||||
channel.name
|
||||
);
|
||||
let answer = cx.prompt(PromptLevel::Warning, &prompt_message, &["Remove", "Cancel"]);
|
||||
let answer = cx.prompt(
|
||||
PromptLevel::Warning,
|
||||
&prompt_message,
|
||||
None,
|
||||
&["Remove", "Cancel"],
|
||||
);
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
if answer.await? == 0 {
|
||||
channel_store
|
||||
|
@ -1631,7 +1648,12 @@ impl CollabPanel {
|
|||
"Are you sure you want to remove \"{}\" from your contacts?",
|
||||
github_login
|
||||
);
|
||||
let answer = cx.prompt(PromptLevel::Warning, &prompt_message, &["Remove", "Cancel"]);
|
||||
let answer = cx.prompt(
|
||||
PromptLevel::Warning,
|
||||
&prompt_message,
|
||||
None,
|
||||
&["Remove", "Cancel"],
|
||||
);
|
||||
cx.spawn(|_, mut cx| async move {
|
||||
if answer.await? == 0 {
|
||||
user_store
|
||||
|
@ -1641,7 +1663,7 @@ impl CollabPanel {
|
|||
}
|
||||
anyhow::Ok(())
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
.detach_and_prompt_err("Failed to remove contact", cx, |_, _| None);
|
||||
}
|
||||
|
||||
fn respond_to_contact_request(
|
||||
|
@ -1654,7 +1676,7 @@ impl CollabPanel {
|
|||
.update(cx, |store, cx| {
|
||||
store.respond_to_contact_request(user_id, accept, cx)
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
.detach_and_prompt_err("Failed to respond to contact request", cx, |_, _| None);
|
||||
}
|
||||
|
||||
fn respond_to_channel_invite(
|
||||
|
@ -1675,7 +1697,7 @@ impl CollabPanel {
|
|||
.update(cx, |call, cx| {
|
||||
call.invite(recipient_user_id, Some(self.project.clone()), cx)
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
.detach_and_prompt_err("Call failed", cx, |_, _| None);
|
||||
}
|
||||
|
||||
fn join_channel(&self, channel_id: u64, cx: &mut ViewContext<Self>) {
|
||||
|
@ -1691,7 +1713,7 @@ impl CollabPanel {
|
|||
Some(handle),
|
||||
cx,
|
||||
)
|
||||
.detach_and_log_err(cx)
|
||||
.detach_and_prompt_err("Failed to join channel", cx, |_, _| None)
|
||||
}
|
||||
|
||||
fn join_channel_chat(&mut self, channel_id: ChannelId, cx: &mut ViewContext<Self>) {
|
||||
|
@ -1704,7 +1726,7 @@ impl CollabPanel {
|
|||
panel.update(cx, |panel, cx| {
|
||||
panel
|
||||
.select_channel(channel_id, None, cx)
|
||||
.detach_and_log_err(cx);
|
||||
.detach_and_notify_err(cx);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -1981,7 +2003,7 @@ impl CollabPanel {
|
|||
.update(cx, |channel_store, cx| {
|
||||
channel_store.move_channel(dragged_channel.id, None, cx)
|
||||
})
|
||||
.detach_and_log_err(cx)
|
||||
.detach_and_prompt_err("Failed to move channel", cx, |_, _| None)
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
@ -2257,7 +2279,7 @@ impl CollabPanel {
|
|||
.update(cx, |channel_store, cx| {
|
||||
channel_store.move_channel(dragged_channel.id, Some(channel_id), cx)
|
||||
})
|
||||
.detach_and_log_err(cx)
|
||||
.detach_and_prompt_err("Failed to move channel", cx, |_, _| None)
|
||||
}))
|
||||
.child(
|
||||
ListItem::new(channel_id as usize)
|
||||
|
|
|
@ -14,7 +14,7 @@ use rpc::proto::channel_member;
|
|||
use std::sync::Arc;
|
||||
use ui::{prelude::*, Avatar, Checkbox, ContextMenu, ListItem, ListItemSpacing};
|
||||
use util::TryFutureExt;
|
||||
use workspace::{notifications::NotifyTaskExt, ModalView};
|
||||
use workspace::{notifications::DetachAndPromptErr, ModalView};
|
||||
|
||||
actions!(
|
||||
channel_modal,
|
||||
|
@ -498,7 +498,7 @@ impl ChannelModalDelegate {
|
|||
cx.notify();
|
||||
})
|
||||
})
|
||||
.detach_and_notify_err(cx);
|
||||
.detach_and_prompt_err("Failed to update role", cx, |_, _| None);
|
||||
Some(())
|
||||
}
|
||||
|
||||
|
@ -530,7 +530,7 @@ impl ChannelModalDelegate {
|
|||
cx.notify();
|
||||
})
|
||||
})
|
||||
.detach_and_notify_err(cx);
|
||||
.detach_and_prompt_err("Failed to remove member", cx, |_, _| None);
|
||||
Some(())
|
||||
}
|
||||
|
||||
|
@ -556,7 +556,7 @@ impl ChannelModalDelegate {
|
|||
cx.notify();
|
||||
})
|
||||
})
|
||||
.detach_and_notify_err(cx);
|
||||
.detach_and_prompt_err("Failed to invite member", cx, |_, _| None);
|
||||
}
|
||||
|
||||
fn show_context_menu(&mut self, ix: usize, cx: &mut ViewContext<Picker<Self>>) {
|
||||
|
|
|
@ -31,7 +31,8 @@ pub fn init(cx: &mut AppContext) {
|
|||
|
||||
let prompt = cx.prompt(
|
||||
PromptLevel::Info,
|
||||
&format!("Copied into clipboard:\n\n{specs}"),
|
||||
"Copied into clipboard",
|
||||
Some(&specs),
|
||||
&["OK"],
|
||||
);
|
||||
cx.spawn(|_, _cx| async move {
|
||||
|
|
|
@ -97,7 +97,7 @@ impl ModalView for FeedbackModal {
|
|||
return true;
|
||||
}
|
||||
|
||||
let answer = cx.prompt(PromptLevel::Info, "Discard feedback?", &["Yes", "No"]);
|
||||
let answer = cx.prompt(PromptLevel::Info, "Discard feedback?", None, &["Yes", "No"]);
|
||||
|
||||
cx.spawn(move |this, mut cx| async move {
|
||||
if answer.await.ok() == Some(0) {
|
||||
|
@ -222,6 +222,7 @@ impl FeedbackModal {
|
|||
let answer = cx.prompt(
|
||||
PromptLevel::Info,
|
||||
"Ready to submit your feedback?",
|
||||
None,
|
||||
&["Yes, Submit!", "No"],
|
||||
);
|
||||
let client = cx.global::<Arc<Client>>().clone();
|
||||
|
@ -255,6 +256,7 @@ impl FeedbackModal {
|
|||
let prompt = cx.prompt(
|
||||
PromptLevel::Critical,
|
||||
FEEDBACK_SUBMISSION_ERROR_TEXT,
|
||||
None,
|
||||
&["OK"],
|
||||
);
|
||||
cx.spawn(|_, _cx| async move {
|
||||
|
|
|
@ -150,7 +150,13 @@ pub(crate) trait PlatformWindow {
|
|||
fn as_any_mut(&mut self) -> &mut dyn Any;
|
||||
fn set_input_handler(&mut self, input_handler: PlatformInputHandler);
|
||||
fn take_input_handler(&mut self) -> Option<PlatformInputHandler>;
|
||||
fn prompt(&self, level: PromptLevel, msg: &str, answers: &[&str]) -> oneshot::Receiver<usize>;
|
||||
fn prompt(
|
||||
&self,
|
||||
level: PromptLevel,
|
||||
msg: &str,
|
||||
detail: Option<&str>,
|
||||
answers: &[&str],
|
||||
) -> oneshot::Receiver<usize>;
|
||||
fn activate(&self);
|
||||
fn set_title(&mut self, title: &str);
|
||||
fn set_edited(&mut self, edited: bool);
|
||||
|
|
|
@ -772,7 +772,13 @@ impl PlatformWindow for MacWindow {
|
|||
self.0.as_ref().lock().input_handler.take()
|
||||
}
|
||||
|
||||
fn prompt(&self, level: PromptLevel, msg: &str, answers: &[&str]) -> oneshot::Receiver<usize> {
|
||||
fn prompt(
|
||||
&self,
|
||||
level: PromptLevel,
|
||||
msg: &str,
|
||||
detail: Option<&str>,
|
||||
answers: &[&str],
|
||||
) -> oneshot::Receiver<usize> {
|
||||
// macOs applies overrides to modal window buttons after they are added.
|
||||
// Two most important for this logic are:
|
||||
// * Buttons with "Cancel" title will be displayed as the last buttons in the modal
|
||||
|
@ -808,6 +814,9 @@ impl PlatformWindow for MacWindow {
|
|||
};
|
||||
let _: () = msg_send![alert, setAlertStyle: alert_style];
|
||||
let _: () = msg_send![alert, setMessageText: ns_string(msg)];
|
||||
if let Some(detail) = detail {
|
||||
let _: () = msg_send![alert, setInformativeText: ns_string(detail)];
|
||||
}
|
||||
|
||||
for (ix, answer) in answers
|
||||
.iter()
|
||||
|
|
|
@ -185,6 +185,7 @@ impl PlatformWindow for TestWindow {
|
|||
&self,
|
||||
_level: crate::PromptLevel,
|
||||
_msg: &str,
|
||||
_detail: Option<&str>,
|
||||
_answers: &[&str],
|
||||
) -> futures::channel::oneshot::Receiver<usize> {
|
||||
self.0
|
||||
|
|
|
@ -1478,9 +1478,12 @@ impl<'a> WindowContext<'a> {
|
|||
&self,
|
||||
level: PromptLevel,
|
||||
message: &str,
|
||||
detail: Option<&str>,
|
||||
answers: &[&str],
|
||||
) -> oneshot::Receiver<usize> {
|
||||
self.window.platform_window.prompt(level, message, answers)
|
||||
self.window
|
||||
.platform_window
|
||||
.prompt(level, message, detail, answers)
|
||||
}
|
||||
|
||||
/// Returns all available actions for the focused element.
|
||||
|
|
|
@ -778,6 +778,7 @@ impl ProjectPanel {
|
|||
let answer = cx.prompt(
|
||||
PromptLevel::Info,
|
||||
&format!("Delete {file_name:?}?"),
|
||||
None,
|
||||
&["Delete", "Cancel"],
|
||||
);
|
||||
|
||||
|
|
|
@ -209,6 +209,7 @@ enum ErrorCode {
|
|||
UpgradeRequired = 4;
|
||||
Forbidden = 5;
|
||||
WrongReleaseChannel = 6;
|
||||
NeedsCla = 7;
|
||||
}
|
||||
|
||||
message Test {
|
||||
|
|
|
@ -746,6 +746,7 @@ impl ProjectSearchView {
|
|||
cx.prompt(
|
||||
PromptLevel::Info,
|
||||
prompt_text.as_str(),
|
||||
None,
|
||||
&["Continue", "Cancel"],
|
||||
)
|
||||
})?;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use crate::{Toast, Workspace};
|
||||
use collections::HashMap;
|
||||
use gpui::{
|
||||
AnyView, AppContext, AsyncWindowContext, DismissEvent, Entity, EntityId, EventEmitter, Render,
|
||||
Task, View, ViewContext, VisualContext, WindowContext,
|
||||
AnyView, AppContext, AsyncWindowContext, DismissEvent, Entity, EntityId, EventEmitter,
|
||||
PromptLevel, Render, Task, View, ViewContext, VisualContext, WindowContext,
|
||||
};
|
||||
use std::{any::TypeId, ops::DerefMut};
|
||||
|
||||
|
@ -299,7 +299,7 @@ pub trait NotifyTaskExt {
|
|||
|
||||
impl<R, E> NotifyTaskExt for Task<Result<R, E>>
|
||||
where
|
||||
E: std::fmt::Debug + 'static,
|
||||
E: std::fmt::Debug + Sized + 'static,
|
||||
R: 'static,
|
||||
{
|
||||
fn detach_and_notify_err(self, cx: &mut WindowContext) {
|
||||
|
@ -307,3 +307,39 @@ where
|
|||
.detach();
|
||||
}
|
||||
}
|
||||
|
||||
pub trait DetachAndPromptErr {
|
||||
fn detach_and_prompt_err(
|
||||
self,
|
||||
msg: &str,
|
||||
cx: &mut WindowContext,
|
||||
f: impl FnOnce(&anyhow::Error, &mut WindowContext) -> Option<String> + 'static,
|
||||
);
|
||||
}
|
||||
|
||||
impl<R> DetachAndPromptErr for Task<anyhow::Result<R>>
|
||||
where
|
||||
R: 'static,
|
||||
{
|
||||
fn detach_and_prompt_err(
|
||||
self,
|
||||
msg: &str,
|
||||
cx: &mut WindowContext,
|
||||
f: impl FnOnce(&anyhow::Error, &mut WindowContext) -> Option<String> + 'static,
|
||||
) {
|
||||
let msg = msg.to_owned();
|
||||
cx.spawn(|mut cx| async move {
|
||||
if let Err(err) = self.await {
|
||||
log::error!("{err:?}");
|
||||
if let Ok(prompt) = cx.update(|cx| {
|
||||
let detail = f(&err, cx)
|
||||
.unwrap_or_else(|| format!("{err:?}. Please try again.", err = err));
|
||||
cx.prompt(PromptLevel::Critical, &msg, Some(&detail), &["Ok"])
|
||||
}) {
|
||||
prompt.await.ok();
|
||||
}
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -870,7 +870,7 @@ impl Pane {
|
|||
items: &mut dyn Iterator<Item = &Box<dyn ItemHandle>>,
|
||||
all_dirty_items: usize,
|
||||
cx: &AppContext,
|
||||
) -> String {
|
||||
) -> (String, String) {
|
||||
/// Quantity of item paths displayed in prompt prior to cutoff..
|
||||
const FILE_NAMES_CUTOFF_POINT: usize = 10;
|
||||
let mut file_names: Vec<_> = items
|
||||
|
@ -894,10 +894,12 @@ impl Pane {
|
|||
file_names.push(format!(".. {} files not shown", not_shown_files).into());
|
||||
}
|
||||
}
|
||||
let file_names = file_names.join("\n");
|
||||
format!(
|
||||
"Do you want to save changes to the following {} files?\n{file_names}",
|
||||
all_dirty_items
|
||||
(
|
||||
format!(
|
||||
"Do you want to save changes to the following {} files?",
|
||||
all_dirty_items
|
||||
),
|
||||
file_names.join("\n"),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -929,11 +931,12 @@ impl Pane {
|
|||
cx.spawn(|pane, mut cx| async move {
|
||||
if save_intent == SaveIntent::Close && dirty_items.len() > 1 {
|
||||
let answer = pane.update(&mut cx, |_, cx| {
|
||||
let prompt =
|
||||
let (prompt, detail) =
|
||||
Self::file_names_for_prompt(&mut dirty_items.iter(), dirty_items.len(), cx);
|
||||
cx.prompt(
|
||||
PromptLevel::Warning,
|
||||
&prompt,
|
||||
Some(&detail),
|
||||
&["Save all", "Discard all", "Cancel"],
|
||||
)
|
||||
})?;
|
||||
|
@ -1131,6 +1134,7 @@ impl Pane {
|
|||
cx.prompt(
|
||||
PromptLevel::Warning,
|
||||
CONFLICT_MESSAGE,
|
||||
None,
|
||||
&["Overwrite", "Discard", "Cancel"],
|
||||
)
|
||||
})?;
|
||||
|
@ -1154,6 +1158,7 @@ impl Pane {
|
|||
cx.prompt(
|
||||
PromptLevel::Warning,
|
||||
&prompt,
|
||||
None,
|
||||
&["Save", "Don't Save", "Cancel"],
|
||||
)
|
||||
})?;
|
||||
|
|
|
@ -30,8 +30,8 @@ use gpui::{
|
|||
DragMoveEvent, Element, ElementContext, Entity, EntityId, EventEmitter, FocusHandle,
|
||||
FocusableView, GlobalPixels, InteractiveElement, IntoElement, KeyContext, LayoutId,
|
||||
ManagedView, Model, ModelContext, ParentElement, PathPromptOptions, Pixels, Point, PromptLevel,
|
||||
Render, Size, Styled, Subscription, Task, View, ViewContext, VisualContext, WeakView,
|
||||
WindowBounds, WindowContext, WindowHandle, WindowOptions,
|
||||
Render, SharedString, Size, Styled, Subscription, Task, View, ViewContext, VisualContext,
|
||||
WeakView, WindowBounds, WindowContext, WindowHandle, WindowOptions,
|
||||
};
|
||||
use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, ProjectItem};
|
||||
use itertools::Itertools;
|
||||
|
@ -1159,6 +1159,7 @@ impl Workspace {
|
|||
cx.prompt(
|
||||
PromptLevel::Warning,
|
||||
"Do you want to leave the current call?",
|
||||
None,
|
||||
&["Close window and hang up", "Cancel"],
|
||||
)
|
||||
})?;
|
||||
|
@ -1214,7 +1215,7 @@ impl Workspace {
|
|||
// Override save mode and display "Save all files" prompt
|
||||
if save_intent == SaveIntent::Close && dirty_items.len() > 1 {
|
||||
let answer = workspace.update(&mut cx, |_, cx| {
|
||||
let prompt = Pane::file_names_for_prompt(
|
||||
let (prompt, detail) = Pane::file_names_for_prompt(
|
||||
&mut dirty_items.iter().map(|(_, handle)| handle),
|
||||
dirty_items.len(),
|
||||
cx,
|
||||
|
@ -1222,6 +1223,7 @@ impl Workspace {
|
|||
cx.prompt(
|
||||
PromptLevel::Warning,
|
||||
&prompt,
|
||||
Some(&detail),
|
||||
&["Save all", "Discard all", "Cancel"],
|
||||
)
|
||||
})?;
|
||||
|
@ -3887,13 +3889,16 @@ async fn join_channel_internal(
|
|||
|
||||
if should_prompt {
|
||||
if let Some(workspace) = requesting_window {
|
||||
let answer = workspace.update(cx, |_, cx| {
|
||||
cx.prompt(
|
||||
PromptLevel::Warning,
|
||||
"Leaving this call will unshare your current project.\nDo you want to switch channels?",
|
||||
&["Yes, Join Channel", "Cancel"],
|
||||
)
|
||||
})?.await;
|
||||
let answer = workspace
|
||||
.update(cx, |_, cx| {
|
||||
cx.prompt(
|
||||
PromptLevel::Warning,
|
||||
"Do you want to switch channels?",
|
||||
Some("Leaving this call will unshare your current project."),
|
||||
&["Yes, Join Channel", "Cancel"],
|
||||
)
|
||||
})?
|
||||
.await;
|
||||
|
||||
if answer == Ok(1) {
|
||||
return Ok(false);
|
||||
|
@ -3995,23 +4000,27 @@ pub fn join_channel(
|
|||
if let Some(active_window) = active_window {
|
||||
active_window
|
||||
.update(&mut cx, |_, cx| {
|
||||
let message:SharedString = match err.error_code() {
|
||||
let detail: SharedString = match err.error_code() {
|
||||
ErrorCode::SignedOut => {
|
||||
"Failed to join channel\n\nPlease sign in to continue.".into()
|
||||
"Please sign in to continue.".into()
|
||||
},
|
||||
ErrorCode::UpgradeRequired => {
|
||||
"Failed to join channel\n\nPlease update to the latest version of Zed to continue.".into()
|
||||
"Your are running an unsupported version of Zed. Please update to continue.".into()
|
||||
},
|
||||
ErrorCode::NoSuchChannel => {
|
||||
"Failed to find channel\n\nPlease check the link and try again.".into()
|
||||
"No matching channel was found. Please check the link and try again.".into()
|
||||
},
|
||||
ErrorCode::Disconnected => "Failed to join channel\n\nPlease check your internet connection and try again.".into(),
|
||||
ErrorCode::WrongReleaseChannel => format!("Failed to join channel\n\nOther people in the channel are using the {} release of Zed, please switch to that release instead.", err.error_tag("required").unwrap_or("other")).into(),
|
||||
_ => format!("Failed to join channel\n\n{}\n\nPlease try again.", err).into(),
|
||||
ErrorCode::Forbidden => {
|
||||
"This channel is private, and you do not have access. Please ask someone to add you and try again.".into()
|
||||
},
|
||||
ErrorCode::Disconnected => "Please check your internet connection and try again.".into(),
|
||||
ErrorCode::WrongReleaseChannel => format!("Others in the channel are using the {} release of Zed. Please switch to join this call.", err.error_tag("required").unwrap_or("other")).into(),
|
||||
_ => format!("{}\n\nPlease try again.", err).into(),
|
||||
};
|
||||
cx.prompt(
|
||||
PromptLevel::Critical,
|
||||
&message,
|
||||
"Failed to join channel",
|
||||
Some(&detail),
|
||||
&["Ok"],
|
||||
)
|
||||
})?
|
||||
|
@ -4238,6 +4247,7 @@ pub fn restart(_: &Restart, cx: &mut AppContext) {
|
|||
cx.prompt(
|
||||
PromptLevel::Info,
|
||||
"Are you sure you want to restart?",
|
||||
None,
|
||||
&["Restart", "Cancel"],
|
||||
)
|
||||
})
|
||||
|
|
|
@ -370,16 +370,12 @@ fn initialize_pane(workspace: &mut Workspace, pane: &View<Pane>, cx: &mut ViewCo
|
|||
}
|
||||
|
||||
fn about(_: &mut Workspace, _: &About, cx: &mut gpui::ViewContext<Workspace>) {
|
||||
use std::fmt::Write as _;
|
||||
|
||||
let app_name = cx.global::<ReleaseChannel>().display_name();
|
||||
let version = env!("CARGO_PKG_VERSION");
|
||||
let mut message = format!("{app_name} {version}");
|
||||
if let Some(sha) = cx.try_global::<AppCommitSha>() {
|
||||
write!(&mut message, "\n\n{}", sha.0).unwrap();
|
||||
}
|
||||
let message = format!("{app_name} {version}");
|
||||
let detail = cx.try_global::<AppCommitSha>().map(|sha| sha.0.as_ref());
|
||||
|
||||
let prompt = cx.prompt(PromptLevel::Info, &message, &["OK"]);
|
||||
let prompt = cx.prompt(PromptLevel::Info, &message, detail, &["OK"]);
|
||||
cx.foreground_executor()
|
||||
.spawn(async {
|
||||
prompt.await.ok();
|
||||
|
@ -410,6 +406,7 @@ fn quit(_: &Quit, cx: &mut AppContext) {
|
|||
cx.prompt(
|
||||
PromptLevel::Info,
|
||||
"Are you sure you want to quit?",
|
||||
None,
|
||||
&["Quit", "Cancel"],
|
||||
)
|
||||
})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue