mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-26 10:40:54 +00:00
Render overlay after remote project becomes read-only
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
parent
dc5a09b3f7
commit
b21d91db22
7 changed files with 73 additions and 17 deletions
|
@ -127,6 +127,12 @@ pub enum Status {
|
||||||
ReconnectionError { next_reconnection: Instant },
|
ReconnectionError { next_reconnection: Instant },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Status {
|
||||||
|
pub fn is_connected(&self) -> bool {
|
||||||
|
matches!(self, Self::Connected { .. })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct ClientState {
|
struct ClientState {
|
||||||
credentials: Option<Credentials>,
|
credentials: Option<Credentials>,
|
||||||
status: (watch::Sender<Status>, watch::Receiver<Status>),
|
status: (watch::Sender<Status>, watch::Receiver<Status>),
|
||||||
|
|
|
@ -92,6 +92,7 @@ enum ProjectClientState {
|
||||||
sharing_has_stopped: bool,
|
sharing_has_stopped: bool,
|
||||||
remote_id: u64,
|
remote_id: u64,
|
||||||
replica_id: ReplicaId,
|
replica_id: ReplicaId,
|
||||||
|
_detect_unshare_task: Task<Option<()>>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,7 +245,7 @@ impl Project {
|
||||||
let mut status = rpc.status();
|
let mut status = rpc.status();
|
||||||
while let Some(status) = status.next().await {
|
while let Some(status) = status.next().await {
|
||||||
if let Some(this) = this.upgrade(&cx) {
|
if let Some(this) = this.upgrade(&cx) {
|
||||||
let remote_id = if let client::Status::Connected { .. } = status {
|
let remote_id = if status.is_connected() {
|
||||||
let response = rpc.request(proto::RegisterProject {}).await?;
|
let response = rpc.request(proto::RegisterProject {}).await?;
|
||||||
Some(response.project_id)
|
Some(response.project_id)
|
||||||
} else {
|
} else {
|
||||||
|
@ -333,7 +334,7 @@ impl Project {
|
||||||
}
|
}
|
||||||
|
|
||||||
let (opened_buffer_tx, opened_buffer_rx) = watch::channel();
|
let (opened_buffer_tx, opened_buffer_rx) = watch::channel();
|
||||||
let this = cx.add_model(|cx| {
|
let this = cx.add_model(|cx: &mut ModelContext<Self>| {
|
||||||
let mut this = Self {
|
let mut this = Self {
|
||||||
worktrees: Vec::new(),
|
worktrees: Vec::new(),
|
||||||
loading_buffers: Default::default(),
|
loading_buffers: Default::default(),
|
||||||
|
@ -346,11 +347,26 @@ impl Project {
|
||||||
user_store: user_store.clone(),
|
user_store: user_store.clone(),
|
||||||
fs,
|
fs,
|
||||||
subscriptions: vec![client.add_model_for_remote_entity(remote_id, cx)],
|
subscriptions: vec![client.add_model_for_remote_entity(remote_id, cx)],
|
||||||
client,
|
client: client.clone(),
|
||||||
client_state: ProjectClientState::Remote {
|
client_state: ProjectClientState::Remote {
|
||||||
sharing_has_stopped: false,
|
sharing_has_stopped: false,
|
||||||
remote_id,
|
remote_id,
|
||||||
replica_id,
|
replica_id,
|
||||||
|
_detect_unshare_task: cx.spawn_weak(move |this, mut cx| {
|
||||||
|
async move {
|
||||||
|
let mut status = client.status();
|
||||||
|
let is_connected =
|
||||||
|
status.next().await.map_or(false, |s| s.is_connected());
|
||||||
|
// Even if we're initially connected, any future change of the status means we momentarily disconnected.
|
||||||
|
if !is_connected || status.next().await.is_some() {
|
||||||
|
if let Some(this) = this.upgrade(&cx) {
|
||||||
|
this.update(&mut cx, |this, cx| this.project_unshared(cx))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
.log_err()
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
language_servers_with_diagnostics_running: 0,
|
language_servers_with_diagnostics_running: 0,
|
||||||
language_servers: Default::default(),
|
language_servers: Default::default(),
|
||||||
|
@ -666,6 +682,18 @@ impl Project {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn project_unshared(&mut self, cx: &mut ModelContext<Self>) {
|
||||||
|
if let ProjectClientState::Remote {
|
||||||
|
sharing_has_stopped,
|
||||||
|
..
|
||||||
|
} = &mut self.client_state
|
||||||
|
{
|
||||||
|
*sharing_has_stopped = true;
|
||||||
|
self.collaborators.clear();
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_read_only(&self) -> bool {
|
pub fn is_read_only(&self) -> bool {
|
||||||
match &self.client_state {
|
match &self.client_state {
|
||||||
ProjectClientState::Local { .. } => false,
|
ProjectClientState::Local { .. } => false,
|
||||||
|
@ -2628,20 +2656,7 @@ impl Project {
|
||||||
_: Arc<Client>,
|
_: Arc<Client>,
|
||||||
mut cx: AsyncAppContext,
|
mut cx: AsyncAppContext,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
this.update(&mut cx, |this, cx| {
|
this.update(&mut cx, |this, cx| this.project_unshared(cx));
|
||||||
if let ProjectClientState::Remote {
|
|
||||||
sharing_has_stopped,
|
|
||||||
..
|
|
||||||
} = &mut this.client_state
|
|
||||||
{
|
|
||||||
*sharing_has_stopped = true;
|
|
||||||
this.collaborators.clear();
|
|
||||||
cx.notify();
|
|
||||||
} else {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ pub struct Workspace {
|
||||||
pub right_sidebar: Sidebar,
|
pub right_sidebar: Sidebar,
|
||||||
pub status_bar: StatusBar,
|
pub status_bar: StatusBar,
|
||||||
pub toolbar: Toolbar,
|
pub toolbar: Toolbar,
|
||||||
|
pub disconnected_overlay: ContainedText,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Clone, Deserialize, Default)]
|
||||||
|
|
|
@ -1297,6 +1297,24 @@ impl Workspace {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn render_disconnected_overlay(&self, cx: &AppContext) -> Option<ElementBox> {
|
||||||
|
if self.project.read(cx).is_read_only() {
|
||||||
|
let theme = &self.settings.borrow().theme;
|
||||||
|
Some(
|
||||||
|
Label::new(
|
||||||
|
"Your connection to the remote project has been lost.".to_string(),
|
||||||
|
theme.workspace.disconnected_overlay.text.clone(),
|
||||||
|
)
|
||||||
|
.aligned()
|
||||||
|
.contained()
|
||||||
|
.with_style(theme.workspace.disconnected_overlay.container)
|
||||||
|
.boxed(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Entity for Workspace {
|
impl Entity for Workspace {
|
||||||
|
@ -1339,6 +1357,7 @@ impl View for Workspace {
|
||||||
content.boxed()
|
content.boxed()
|
||||||
})
|
})
|
||||||
.with_children(self.modal.as_ref().map(|m| ChildView::new(m).boxed()))
|
.with_children(self.modal.as_ref().map(|m| ChildView::new(m).boxed()))
|
||||||
|
.with_children(self.render_disconnected_overlay(cx))
|
||||||
.flexible(1.0, true)
|
.flexible(1.0, true)
|
||||||
.boxed(),
|
.boxed(),
|
||||||
)
|
)
|
||||||
|
|
|
@ -60,3 +60,8 @@ emphasis = "#4ec9b0"
|
||||||
link_uri = { color = "#6a9955", underline = true }
|
link_uri = { color = "#6a9955", underline = true }
|
||||||
link_text = { color = "#cb8f77", italic = true }
|
link_text = { color = "#cb8f77", italic = true }
|
||||||
list_marker = "#4e94ce"
|
list_marker = "#4e94ce"
|
||||||
|
|
||||||
|
[workspace.disconnected_overlay]
|
||||||
|
extends = "$text.base"
|
||||||
|
color = "#ffffff"
|
||||||
|
background = "#000000aa"
|
||||||
|
|
|
@ -60,3 +60,8 @@ emphasis = "#4ec9b0"
|
||||||
link_uri = { color = "#6a9955", underline = true }
|
link_uri = { color = "#6a9955", underline = true }
|
||||||
link_text = { color = "#cb8f77", italic = true }
|
link_text = { color = "#cb8f77", italic = true }
|
||||||
list_marker = "#4e94ce"
|
list_marker = "#4e94ce"
|
||||||
|
|
||||||
|
[workspace.disconnected_overlay]
|
||||||
|
extends = "$text.base"
|
||||||
|
color = "#ffffff"
|
||||||
|
background = "#000000aa"
|
||||||
|
|
|
@ -60,3 +60,8 @@ emphasis = "#267f29"
|
||||||
link_uri = { color = "#6a9955", underline = true }
|
link_uri = { color = "#6a9955", underline = true }
|
||||||
link_text = { color = "#a82121", italic = true }
|
link_text = { color = "#a82121", italic = true }
|
||||||
list_marker = "#4e94ce"
|
list_marker = "#4e94ce"
|
||||||
|
|
||||||
|
[workspace.disconnected_overlay]
|
||||||
|
extends = "$text.base"
|
||||||
|
color = "#ffffff"
|
||||||
|
background = "#000000cc"
|
||||||
|
|
Loading…
Reference in a new issue