mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-24 17:28:40 +00:00
TEMP
This commit is contained in:
parent
31062d424f
commit
b58c42cd53
5 changed files with 197 additions and 129 deletions
|
@ -3,4 +3,4 @@ xtask = "run --package xtask --"
|
|||
|
||||
[build]
|
||||
# v0 mangling scheme provides more detailed backtraces around closures
|
||||
rustflags = ["-C", "symbol-mangling-version=v0"]
|
||||
rustflags = ["-C", "symbol-mangling-version=v0", "-C", "link-arg=-fuse-ld=/opt/homebrew/Cellar/llvm/16.0.6/bin/ld64.lld"]
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use std::env;
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use url::Url;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref RELEASE_CHANNEL_NAME: String = if cfg!(debug_assertions) {
|
||||
|
@ -16,22 +15,6 @@ lazy_static! {
|
|||
"stable" => ReleaseChannel::Stable,
|
||||
_ => panic!("invalid release channel {}", *RELEASE_CHANNEL_NAME),
|
||||
};
|
||||
|
||||
pub static ref URL_SCHEME_PREFIX: String = match RELEASE_CHANNEL_NAME.as_str() {
|
||||
"dev" => "zed-dev:/",
|
||||
"preview" => "zed-preview:/",
|
||||
"stable" => "zed:/",
|
||||
// NOTE: this must be kept in sync with osx_url_schemes in Cargo.toml and with https://zed.dev.
|
||||
_ => unreachable!(),
|
||||
}.to_string();
|
||||
pub static ref LINK_PREFIX: Url = Url::parse(match RELEASE_CHANNEL_NAME.as_str() {
|
||||
"dev" => "http://localhost:3000/dev/",
|
||||
"preview" => "https://zed.dev/preview/",
|
||||
"stable" => "https://zed.dev/",
|
||||
// NOTE: this must be kept in sync with https://zed.dev.
|
||||
_ => unreachable!(),
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Default)]
|
||||
|
@ -58,4 +41,36 @@ impl ReleaseChannel {
|
|||
ReleaseChannel::Stable => "stable",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn url_scheme(&self) -> &'static str {
|
||||
match self {
|
||||
ReleaseChannel::Dev => "zed-dev:/",
|
||||
ReleaseChannel::Preview => "zed-preview:/",
|
||||
ReleaseChannel::Stable => "zed:/",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn link_prefix(&self) -> &'static str {
|
||||
match self {
|
||||
ReleaseChannel::Dev => "https://zed.dev/dev/",
|
||||
ReleaseChannel::Preview => "https://zed.dev/preview/",
|
||||
ReleaseChannel::Stable => "https://zed.dev/",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_zed_link(link: &str) -> Option<&str> {
|
||||
for release in [
|
||||
ReleaseChannel::Dev,
|
||||
ReleaseChannel::Preview,
|
||||
ReleaseChannel::Stable,
|
||||
] {
|
||||
if let Some(stripped) = link.strip_prefix(release.link_prefix()) {
|
||||
return Some(stripped);
|
||||
}
|
||||
if let Some(stripped) = link.strip_prefix(release.url_scheme()) {
|
||||
return Some(stripped);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
|
|
@ -15,14 +15,14 @@ use call::ActiveCall;
|
|||
use channel::ChannelStore;
|
||||
use client::{
|
||||
proto::{self, PeerId},
|
||||
Client, TypedEnvelope, UserStore,
|
||||
Client, Status, TypedEnvelope, UserStore,
|
||||
};
|
||||
use collections::{hash_map, HashMap, HashSet};
|
||||
use drag_and_drop::DragAndDrop;
|
||||
use futures::{
|
||||
channel::{mpsc, oneshot},
|
||||
future::try_join_all,
|
||||
FutureExt, StreamExt,
|
||||
select_biased, FutureExt, StreamExt,
|
||||
};
|
||||
use gpui::{
|
||||
actions,
|
||||
|
@ -4154,6 +4154,100 @@ pub async fn last_opened_workspace_paths() -> Option<WorkspaceLocation> {
|
|||
DB.last_workspace().await.log_err().flatten()
|
||||
}
|
||||
|
||||
async fn join_channel_internal(
|
||||
channel_id: u64,
|
||||
app_state: Arc<AppState>,
|
||||
requesting_window: Option<WindowHandle<Workspace>>,
|
||||
active_call: &ModelHandle<ActiveCall>,
|
||||
cx: &mut AsyncAppContext,
|
||||
) -> Result<bool> {
|
||||
let should_prompt = active_call.read_with(cx, |active_call, cx| {
|
||||
let Some(room) = active_call.room().map(|room| room.read(cx)) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
room.is_sharing_project()
|
||||
&& room.remote_participants().len() > 0
|
||||
&& room.channel_id() != Some(channel_id)
|
||||
});
|
||||
|
||||
if should_prompt {
|
||||
if let Some(workspace) = requesting_window {
|
||||
if let Some(window) = workspace.update(cx, |cx| cx.window()) {
|
||||
let answer = window.prompt(
|
||||
PromptLevel::Warning,
|
||||
"Leaving this call will unshare your current project.\nDo you want to switch channels?",
|
||||
&["Yes, Join Channel", "Cancel"],
|
||||
cx,
|
||||
);
|
||||
|
||||
if let Some(mut answer) = answer {
|
||||
if answer.next().await == Some(1) {
|
||||
return Ok(false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Ok(false); // unreachable!() hopefully
|
||||
}
|
||||
} else {
|
||||
return Ok(false); // unreachable!() hopefully
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
'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"))
|
||||
};
|
||||
|
||||
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"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let room = active_call
|
||||
.update(cx, |active_call, cx| {
|
||||
active_call.join_channel(channel_id, cx)
|
||||
})
|
||||
.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));
|
||||
}
|
||||
|
||||
None
|
||||
});
|
||||
if let Some(task) = task {
|
||||
task.await?;
|
||||
return anyhow::Ok(true);
|
||||
}
|
||||
|
||||
anyhow::Ok(false)
|
||||
}
|
||||
|
||||
pub fn join_channel(
|
||||
channel_id: u64,
|
||||
app_state: Arc<AppState>,
|
||||
|
@ -4161,50 +4255,18 @@ pub fn join_channel(
|
|||
cx: &mut AppContext,
|
||||
) -> Task<Result<()>> {
|
||||
let active_call = ActiveCall::global(cx);
|
||||
cx.spawn(|mut cx| async move {
|
||||
let should_prompt = active_call.read_with(&mut cx, |active_call, cx| {
|
||||
let Some(room) = active_call.room().map( |room| room.read(cx) ) else {
|
||||
return false
|
||||
};
|
||||
cx.spawn(|mut cx| {
|
||||
let result = join_channel_internal(
|
||||
channel_id,
|
||||
app_state,
|
||||
requesting_window,
|
||||
&active_call,
|
||||
&mut cx,
|
||||
)
|
||||
.await;
|
||||
|
||||
room.is_sharing_project() && room.remote_participants().len() > 0 &&
|
||||
room.channel_id() != Some(channel_id)
|
||||
});
|
||||
|
||||
if should_prompt {
|
||||
if let Some(workspace) = requesting_window {
|
||||
if let Some(window) = workspace.update(&mut cx, |cx| {
|
||||
cx.window()
|
||||
}) {
|
||||
let answer = window.prompt(
|
||||
PromptLevel::Warning,
|
||||
"Leaving this call will unshare your current project.\nDo you want to switch channels?",
|
||||
&["Yes, Join Channel", "Cancel"],
|
||||
&mut cx,
|
||||
);
|
||||
|
||||
if let Some(mut answer) = answer {
|
||||
if answer.next().await == Some(1) {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let room = active_call.update(&mut cx, |active_call, cx| {
|
||||
active_call.join_channel(channel_id, cx)
|
||||
}).await?;
|
||||
|
||||
let task = room.update(&mut cx, |room, cx| {
|
||||
if let Some((project, host)) = room.most_active_project() {
|
||||
return Some(join_remote_project(project, host, app_state.clone(), cx))
|
||||
}
|
||||
|
||||
None
|
||||
});
|
||||
if let Some(task) = task {
|
||||
task.await?;
|
||||
// join channel succeeded, and opened a window
|
||||
if Some(true) = result {
|
||||
return anyhow::Ok(());
|
||||
}
|
||||
|
||||
|
@ -4223,16 +4285,15 @@ pub fn join_channel(
|
|||
});
|
||||
|
||||
if found.unwrap_or(false) {
|
||||
return anyhow::Ok(())
|
||||
return anyhow::Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
// no open workspaces
|
||||
cx.update(|cx| {
|
||||
Workspace::new_local(vec![], app_state.clone(), requesting_window, cx)
|
||||
}).await;
|
||||
cx.update(|cx| Workspace::new_local(vec![], app_state.clone(), requesting_window, cx))
|
||||
.await;
|
||||
|
||||
return anyhow::Ok(());
|
||||
return connected.map(|_| ());
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ use std::{
|
|||
};
|
||||
use sum_tree::Bias;
|
||||
use util::{
|
||||
channel::ReleaseChannel,
|
||||
channel::{parse_zed_link, ReleaseChannel},
|
||||
http::{self, HttpClient},
|
||||
paths::PathLikeWithPosition,
|
||||
};
|
||||
|
@ -206,12 +206,9 @@ fn main() {
|
|||
|
||||
if stdout_is_a_pty() {
|
||||
cx.platform().activate(true);
|
||||
let paths = collect_path_args();
|
||||
if paths.is_empty() {
|
||||
cx.spawn(|cx| async move { restore_or_create_workspace(&app_state, cx).await })
|
||||
.detach()
|
||||
} else {
|
||||
workspace::open_paths(&paths, &app_state, None, cx).detach_and_log_err(cx);
|
||||
let urls = collect_url_args();
|
||||
if !urls.is_empty() {
|
||||
listener.open_urls(urls)
|
||||
}
|
||||
} else {
|
||||
upload_previous_panics(http.clone(), cx);
|
||||
|
@ -223,53 +220,51 @@ fn main() {
|
|||
{
|
||||
listener.open_urls(collect_url_args())
|
||||
}
|
||||
}
|
||||
|
||||
match open_rx.try_next() {
|
||||
Ok(Some(OpenRequest::Paths { paths })) => {
|
||||
cx.update(|cx| workspace::open_paths(&paths, &app_state, None, cx))
|
||||
.detach();
|
||||
}
|
||||
Ok(Some(OpenRequest::CliConnection { connection })) => {
|
||||
cx.spawn(|cx| handle_cli_connection(connection, app_state.clone(), cx))
|
||||
.detach();
|
||||
}
|
||||
Ok(Some(OpenRequest::JoinChannel { channel_id })) => cx
|
||||
.update(|cx| workspace::join_channel(channel_id, app_state.clone(), None, cx))
|
||||
.detach(),
|
||||
Ok(None) | Err(_) => cx
|
||||
.spawn({
|
||||
let app_state = app_state.clone();
|
||||
|cx| async move { restore_or_create_workspace(&app_state, cx).await }
|
||||
})
|
||||
.detach(),
|
||||
match open_rx.try_next() {
|
||||
Ok(Some(OpenRequest::Paths { paths })) => {
|
||||
cx.update(|cx| workspace::open_paths(&paths, &app_state, None, cx))
|
||||
.detach();
|
||||
}
|
||||
Ok(Some(OpenRequest::CliConnection { connection })) => {
|
||||
cx.spawn(|cx| handle_cli_connection(connection, app_state.clone(), cx))
|
||||
.detach();
|
||||
}
|
||||
Ok(Some(OpenRequest::JoinChannel { channel_id })) => cx
|
||||
.update(|cx| workspace::join_channel(channel_id, app_state.clone(), None, cx))
|
||||
.detach_and_log_err(cx),
|
||||
Ok(None) | Err(_) => cx
|
||||
.spawn({
|
||||
let app_state = app_state.clone();
|
||||
|cx| async move { restore_or_create_workspace(&app_state, cx).await }
|
||||
})
|
||||
.detach(),
|
||||
}
|
||||
|
||||
cx.spawn(|mut cx| {
|
||||
let app_state = app_state.clone();
|
||||
async move {
|
||||
while let Some(request) = open_rx.next().await {
|
||||
match request {
|
||||
OpenRequest::Paths { paths } => {
|
||||
cx.update(|cx| workspace::open_paths(&paths, &app_state, None, cx))
|
||||
.detach();
|
||||
}
|
||||
OpenRequest::CliConnection { connection } => {
|
||||
cx.spawn(|cx| {
|
||||
handle_cli_connection(connection, app_state.clone(), cx)
|
||||
})
|
||||
cx.spawn(|mut cx| {
|
||||
let app_state = app_state.clone();
|
||||
async move {
|
||||
while let Some(request) = open_rx.next().await {
|
||||
match request {
|
||||
OpenRequest::Paths { paths } => {
|
||||
cx.update(|cx| workspace::open_paths(&paths, &app_state, None, cx))
|
||||
.detach();
|
||||
}
|
||||
OpenRequest::JoinChannel { channel_id } => cx
|
||||
.update(|cx| {
|
||||
workspace::join_channel(channel_id, app_state.clone(), None, cx)
|
||||
})
|
||||
.detach(),
|
||||
}
|
||||
OpenRequest::CliConnection { connection } => {
|
||||
cx.spawn(|cx| handle_cli_connection(connection, app_state.clone(), cx))
|
||||
.detach();
|
||||
}
|
||||
OpenRequest::JoinChannel { channel_id } => cx
|
||||
.update(|cx| {
|
||||
workspace::join_channel(channel_id, app_state.clone(), None, cx)
|
||||
})
|
||||
.detach(),
|
||||
}
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
||||
cx.spawn(|cx| async move {
|
||||
if stdout_is_a_pty() {
|
||||
|
@ -608,23 +603,23 @@ fn stdout_is_a_pty() -> bool {
|
|||
std::env::var(FORCE_CLI_MODE_ENV_VAR_NAME).ok().is_none() && std::io::stdout().is_terminal()
|
||||
}
|
||||
|
||||
fn collect_path_args() -> Vec<PathBuf> {
|
||||
fn collect_url_args() -> Vec<String> {
|
||||
env::args()
|
||||
.skip(1)
|
||||
.filter_map(|arg| match std::fs::canonicalize(arg) {
|
||||
Ok(path) => Some(path),
|
||||
.filter_map(|arg| match std::fs::canonicalize(Path::new(&arg)) {
|
||||
Ok(path) => Some(format!("file://{}", path.to_string_lossy())),
|
||||
Err(error) => {
|
||||
log::error!("error parsing path argument: {}", error);
|
||||
None
|
||||
if let Some(_) = parse_zed_link(&arg) {
|
||||
Some(arg)
|
||||
} else {
|
||||
log::error!("error parsing path argument: {}", error);
|
||||
None
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn collect_url_args() -> Vec<String> {
|
||||
env::args().skip(1).collect()
|
||||
}
|
||||
|
||||
fn load_embedded_fonts(app: &App) {
|
||||
let font_paths = Assets.list("fonts");
|
||||
let embedded_fonts = Mutex::new(Vec::new());
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::ffi::OsStr;
|
|||
use std::os::unix::prelude::OsStrExt;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::{path::PathBuf, sync::atomic::AtomicBool};
|
||||
use util::channel::URL_SCHEME_PREFIX;
|
||||
use util::channel::parse_zed_link;
|
||||
use util::ResultExt;
|
||||
|
||||
use crate::connect_to_cli;
|
||||
|
@ -47,10 +47,7 @@ impl OpenListener {
|
|||
urls.first().and_then(|url| url.strip_prefix("zed-cli://"))
|
||||
{
|
||||
self.handle_cli_connection(server_name)
|
||||
} else if let Some(request_path) = urls
|
||||
.first()
|
||||
.and_then(|url| url.strip_prefix(URL_SCHEME_PREFIX.as_str()))
|
||||
{
|
||||
} else if let Some(request_path) = urls.first().and_then(|url| parse_zed_link(url)) {
|
||||
self.handle_zed_url_scheme(request_path)
|
||||
} else {
|
||||
self.handle_file_urls(urls)
|
||||
|
|
Loading…
Reference in a new issue