Make joining on boot work
This commit is contained in:
parent
4128e2ffcb
commit
63a230f92e
5 changed files with 118 additions and 65 deletions
|
@ -22,7 +22,7 @@ use drag_and_drop::DragAndDrop;
|
|||
use futures::{
|
||||
channel::{mpsc, oneshot},
|
||||
future::try_join_all,
|
||||
select_biased, FutureExt, StreamExt,
|
||||
FutureExt, StreamExt,
|
||||
};
|
||||
use gpui::{
|
||||
actions,
|
||||
|
@ -36,9 +36,9 @@ use gpui::{
|
|||
CursorStyle, ModifiersChangedEvent, MouseButton, PathPromptOptions, Platform, PromptLevel,
|
||||
WindowBounds, WindowOptions,
|
||||
},
|
||||
AnyModelHandle, AnyViewHandle, AnyWeakViewHandle, AppContext, AsyncAppContext, Entity,
|
||||
ModelContext, ModelHandle, SizeConstraint, Subscription, Task, View, ViewContext, ViewHandle,
|
||||
WeakViewHandle, WindowContext, WindowHandle,
|
||||
AnyModelHandle, AnyViewHandle, AnyWeakViewHandle, AnyWindowHandle, AppContext, AsyncAppContext,
|
||||
Entity, ModelContext, ModelHandle, SizeConstraint, Subscription, Task, View, ViewContext,
|
||||
ViewHandle, WeakViewHandle, WindowContext, WindowHandle,
|
||||
};
|
||||
use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ProjectItem};
|
||||
use itertools::Itertools;
|
||||
|
@ -4156,7 +4156,7 @@ pub async fn last_opened_workspace_paths() -> Option<WorkspaceLocation> {
|
|||
|
||||
async fn join_channel_internal(
|
||||
channel_id: u64,
|
||||
app_state: Arc<AppState>,
|
||||
app_state: &Arc<AppState>,
|
||||
requesting_window: Option<WindowHandle<Workspace>>,
|
||||
active_call: &ModelHandle<ActiveCall>,
|
||||
cx: &mut AsyncAppContext,
|
||||
|
@ -4196,33 +4196,24 @@ async fn join_channel_internal(
|
|||
|
||||
let client = cx.read(|cx| active_call.read(cx).client());
|
||||
|
||||
let mut timer = cx.background().timer(Duration::from_secs(5)).fuse();
|
||||
let mut client_status = client.status();
|
||||
|
||||
// this loop will terminate within client::CONNECTION_TIMEOUT seconds.
|
||||
'outer: loop {
|
||||
select_biased! {
|
||||
_ = timer => {
|
||||
return Err(anyhow!("connecting timed out"))
|
||||
},
|
||||
status = client_status.recv().fuse() => {
|
||||
let Some(status) = status else {
|
||||
return Err(anyhow!("unexpected error reading connection status"))
|
||||
};
|
||||
let Some(status) = client_status.recv().await else {
|
||||
return Err(anyhow!("error connecting"));
|
||||
};
|
||||
|
||||
match status {
|
||||
Status::Connecting | Status::Authenticating | Status::Reconnecting | Status::Reauthenticating => continue,
|
||||
Status::Connected { .. } => break 'outer,
|
||||
Status::SignedOut => {
|
||||
if client.has_keychain_credentials(&cx) {
|
||||
client.authenticate_and_connect(true, &cx).await?;
|
||||
timer = cx.background().timer(Duration::from_secs(5)).fuse();
|
||||
} else {
|
||||
return Err(anyhow!("not signed in"))
|
||||
}
|
||||
},
|
||||
Status::UpgradeRequired => return Err(anyhow!("zed is out of date")),
|
||||
| Status::ConnectionError | Status::ConnectionLost | Status::ReconnectionError { .. } => return Err(anyhow!("zed is offline"))
|
||||
}
|
||||
match status {
|
||||
Status::Connecting
|
||||
| Status::Authenticating
|
||||
| Status::Reconnecting
|
||||
| Status::Reauthenticating => continue,
|
||||
Status::Connected { .. } => break 'outer,
|
||||
Status::SignedOut => return Err(anyhow!("not signed in")),
|
||||
Status::UpgradeRequired => return Err(anyhow!("zed is out of date")),
|
||||
Status::ConnectionError | Status::ConnectionLost | Status::ReconnectionError { .. } => {
|
||||
return Err(anyhow!("zed is offline"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4233,6 +4224,8 @@ async fn join_channel_internal(
|
|||
})
|
||||
.await?;
|
||||
|
||||
room.update(cx, |room, cx| room.next_room_update()).await;
|
||||
|
||||
let task = room.update(cx, |room, cx| {
|
||||
if let Some((project, host)) = room.most_active_project() {
|
||||
return Some(join_remote_project(project, host, app_state.clone(), cx));
|
||||
|
@ -4255,10 +4248,10 @@ pub fn join_channel(
|
|||
cx: &mut AppContext,
|
||||
) -> Task<Result<()>> {
|
||||
let active_call = ActiveCall::global(cx);
|
||||
cx.spawn(|mut cx| {
|
||||
cx.spawn(|mut cx| async move {
|
||||
let result = join_channel_internal(
|
||||
channel_id,
|
||||
app_state,
|
||||
&app_state,
|
||||
requesting_window,
|
||||
&active_call,
|
||||
&mut cx,
|
||||
|
@ -4266,7 +4259,7 @@ pub fn join_channel(
|
|||
.await;
|
||||
|
||||
// join channel succeeded, and opened a window
|
||||
if Some(true) = result {
|
||||
if matches!(result, Ok(true)) {
|
||||
return anyhow::Ok(());
|
||||
}
|
||||
|
||||
|
@ -4275,28 +4268,53 @@ pub fn join_channel(
|
|||
}
|
||||
|
||||
// find an existing workspace to focus and show call controls
|
||||
for window in cx.windows() {
|
||||
let found = window.update(&mut cx, |cx| {
|
||||
let is_workspace = cx.root_view().clone().downcast::<Workspace>().is_some();
|
||||
if is_workspace {
|
||||
cx.activate_window();
|
||||
}
|
||||
is_workspace
|
||||
});
|
||||
let mut active_window = activate_any_workspace_window(&mut cx);
|
||||
if active_window.is_none() {
|
||||
// no open workspaces, make one to show the error in (blergh)
|
||||
cx.update(|cx| Workspace::new_local(vec![], app_state.clone(), requesting_window, cx))
|
||||
.await;
|
||||
}
|
||||
|
||||
if found.unwrap_or(false) {
|
||||
return anyhow::Ok(());
|
||||
active_window = activate_any_workspace_window(&mut cx);
|
||||
if active_window.is_none() {
|
||||
return result.map(|_| ()); // unreachable!() assuming new_local always opens a window
|
||||
}
|
||||
|
||||
if let Err(err) = result {
|
||||
let prompt = active_window.unwrap().prompt(
|
||||
PromptLevel::Critical,
|
||||
&format!("Failed to join channel: {}", err),
|
||||
&["Ok"],
|
||||
&mut cx,
|
||||
);
|
||||
if let Some(mut prompt) = prompt {
|
||||
prompt.next().await;
|
||||
} else {
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
|
||||
// no open workspaces
|
||||
cx.update(|cx| Workspace::new_local(vec![], app_state.clone(), requesting_window, cx))
|
||||
.await;
|
||||
|
||||
return connected.map(|_| ());
|
||||
// return ok, we showed the error to the user.
|
||||
return anyhow::Ok(());
|
||||
})
|
||||
}
|
||||
|
||||
pub fn activate_any_workspace_window(cx: &mut AsyncAppContext) -> Option<AnyWindowHandle> {
|
||||
for window in cx.windows() {
|
||||
let found = window.update(cx, |cx| {
|
||||
let is_workspace = cx.root_view().clone().downcast::<Workspace>().is_some();
|
||||
if is_workspace {
|
||||
cx.activate_window();
|
||||
}
|
||||
is_workspace
|
||||
});
|
||||
if found == Some(true) {
|
||||
return Some(window);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn open_paths(
|
||||
abs_paths: &[PathBuf],
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue