mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-28 21:32:39 +00:00
Allow making projects private
This commit is contained in:
parent
8f676e76b3
commit
3ea061a11e
7 changed files with 131 additions and 82 deletions
|
@ -532,7 +532,7 @@ async fn test_private_projects(
|
||||||
.read_with(cx_b, |store, _| { store.contacts()[0].projects.is_empty() }));
|
.read_with(cx_b, |store, _| { store.contacts()[0].projects.is_empty() }));
|
||||||
|
|
||||||
// The project is registered when it is made public.
|
// The project is registered when it is made public.
|
||||||
project_a.update(cx_a, |project, _| project.set_public(true));
|
project_a.update(cx_a, |project, cx| project.set_public(true, cx));
|
||||||
deterministic.run_until_parked();
|
deterministic.run_until_parked();
|
||||||
assert!(project_a.read_with(cx_a, |project, _| project.remote_id().is_some()));
|
assert!(project_a.read_with(cx_a, |project, _| project.remote_id().is_some()));
|
||||||
assert!(!client_b
|
assert!(!client_b
|
||||||
|
|
|
@ -207,7 +207,7 @@ impl ContactsPanel {
|
||||||
ContactEntry::Contact(contact) => {
|
ContactEntry::Contact(contact) => {
|
||||||
Self::render_contact(&contact.user, theme, is_selected)
|
Self::render_contact(&contact.user, theme, is_selected)
|
||||||
}
|
}
|
||||||
ContactEntry::ContactProject(contact, project_ix, _) => {
|
ContactEntry::ContactProject(contact, project_ix, open_project) => {
|
||||||
let is_last_project_for_contact =
|
let is_last_project_for_contact =
|
||||||
this.entries.get(ix + 1).map_or(true, |next| {
|
this.entries.get(ix + 1).map_or(true, |next| {
|
||||||
if let ContactEntry::ContactProject(next_contact, _, _) = next {
|
if let ContactEntry::ContactProject(next_contact, _, _) = next {
|
||||||
|
@ -216,10 +216,11 @@ impl ContactsPanel {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Self::render_contact_project(
|
Self::render_project(
|
||||||
contact.clone(),
|
contact.clone(),
|
||||||
current_user_id,
|
current_user_id,
|
||||||
*project_ix,
|
*project_ix,
|
||||||
|
open_project.clone(),
|
||||||
theme,
|
theme,
|
||||||
is_last_project_for_contact,
|
is_last_project_for_contact,
|
||||||
is_selected,
|
is_selected,
|
||||||
|
@ -328,10 +329,11 @@ impl ContactsPanel {
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_contact_project(
|
fn render_project(
|
||||||
contact: Arc<Contact>,
|
contact: Arc<Contact>,
|
||||||
current_user_id: Option<u64>,
|
current_user_id: Option<u64>,
|
||||||
project_index: usize,
|
project_index: usize,
|
||||||
|
open_project: Option<WeakModelHandle<Project>>,
|
||||||
theme: &theme::ContactsPanel,
|
theme: &theme::ContactsPanel,
|
||||||
is_last_project: bool,
|
is_last_project: bool,
|
||||||
is_selected: bool,
|
is_selected: bool,
|
||||||
|
@ -340,6 +342,7 @@ impl ContactsPanel {
|
||||||
let project = &contact.projects[project_index];
|
let project = &contact.projects[project_index];
|
||||||
let project_id = project.id;
|
let project_id = project.id;
|
||||||
let is_host = Some(contact.user.id) == current_user_id;
|
let is_host = Some(contact.user.id) == current_user_id;
|
||||||
|
let open_project = open_project.and_then(|p| p.upgrade(cx.deref_mut()));
|
||||||
|
|
||||||
let font_cache = cx.font_cache();
|
let font_cache = cx.font_cache();
|
||||||
let host_avatar_height = theme
|
let host_avatar_height = theme
|
||||||
|
@ -354,48 +357,78 @@ impl ContactsPanel {
|
||||||
let baseline_offset =
|
let baseline_offset =
|
||||||
row.name.text.baseline_offset(font_cache) + (theme.row_height - line_height) / 2.;
|
row.name.text.baseline_offset(font_cache) + (theme.row_height - line_height) / 2.;
|
||||||
|
|
||||||
MouseEventHandler::new::<JoinProject, _, _>(project_id as usize, cx, |mouse_state, _| {
|
MouseEventHandler::new::<JoinProject, _, _>(project_id as usize, cx, |mouse_state, cx| {
|
||||||
let tree_branch = *tree_branch.style_for(mouse_state, is_selected);
|
let tree_branch = *tree_branch.style_for(mouse_state, is_selected);
|
||||||
let row = theme.project_row.style_for(mouse_state, is_selected);
|
let row = theme.project_row.style_for(mouse_state, is_selected);
|
||||||
|
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_child(
|
.with_child(
|
||||||
Canvas::new(move |bounds, _, cx| {
|
Stack::new()
|
||||||
let start_x =
|
.with_child(
|
||||||
bounds.min_x() + (bounds.width() / 2.) - (tree_branch.width / 2.);
|
Canvas::new(move |bounds, _, cx| {
|
||||||
let end_x = bounds.max_x();
|
let start_x = bounds.min_x() + (bounds.width() / 2.)
|
||||||
let start_y = bounds.min_y();
|
- (tree_branch.width / 2.);
|
||||||
let end_y = bounds.min_y() + baseline_offset - (cap_height / 2.);
|
let end_x = bounds.max_x();
|
||||||
|
let start_y = bounds.min_y();
|
||||||
|
let end_y = bounds.min_y() + baseline_offset - (cap_height / 2.);
|
||||||
|
|
||||||
cx.scene.push_quad(gpui::Quad {
|
cx.scene.push_quad(gpui::Quad {
|
||||||
bounds: RectF::from_points(
|
bounds: RectF::from_points(
|
||||||
vec2f(start_x, start_y),
|
vec2f(start_x, start_y),
|
||||||
vec2f(
|
vec2f(
|
||||||
start_x + tree_branch.width,
|
start_x + tree_branch.width,
|
||||||
if is_last_project {
|
if is_last_project {
|
||||||
end_y
|
end_y
|
||||||
} else {
|
} else {
|
||||||
bounds.max_y()
|
bounds.max_y()
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
background: Some(tree_branch.color),
|
||||||
|
border: gpui::Border::default(),
|
||||||
|
corner_radius: 0.,
|
||||||
|
});
|
||||||
|
cx.scene.push_quad(gpui::Quad {
|
||||||
|
bounds: RectF::from_points(
|
||||||
|
vec2f(start_x, end_y),
|
||||||
|
vec2f(end_x, end_y + tree_branch.width),
|
||||||
|
),
|
||||||
|
background: Some(tree_branch.color),
|
||||||
|
border: gpui::Border::default(),
|
||||||
|
corner_radius: 0.,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.boxed(),
|
||||||
|
)
|
||||||
|
.with_children(if mouse_state.hovered && open_project.is_some() {
|
||||||
|
Some(
|
||||||
|
MouseEventHandler::new::<ToggleProjectPublic, _, _>(
|
||||||
|
project_id as usize,
|
||||||
|
cx,
|
||||||
|
|state, _| {
|
||||||
|
let mut icon_style =
|
||||||
|
*theme.private_button.style_for(state, false);
|
||||||
|
icon_style.container.background_color =
|
||||||
|
row.container.background_color;
|
||||||
|
render_icon_button(&icon_style, "icons/lock-8.svg")
|
||||||
|
.aligned()
|
||||||
|
.boxed()
|
||||||
},
|
},
|
||||||
),
|
)
|
||||||
),
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
background: Some(tree_branch.color),
|
.on_click(move |_, _, cx| {
|
||||||
border: gpui::Border::default(),
|
cx.dispatch_action(ToggleProjectPublic {
|
||||||
corner_radius: 0.,
|
project: open_project.clone(),
|
||||||
});
|
})
|
||||||
cx.scene.push_quad(gpui::Quad {
|
})
|
||||||
bounds: RectF::from_points(
|
.boxed(),
|
||||||
vec2f(start_x, end_y),
|
)
|
||||||
vec2f(end_x, end_y + tree_branch.width),
|
} else {
|
||||||
),
|
None
|
||||||
background: Some(tree_branch.color),
|
})
|
||||||
border: gpui::Border::default(),
|
.constrained()
|
||||||
corner_radius: 0.,
|
.with_width(host_avatar_height)
|
||||||
});
|
.boxed(),
|
||||||
})
|
|
||||||
.constrained()
|
|
||||||
.with_width(host_avatar_height)
|
|
||||||
.boxed(),
|
|
||||||
)
|
)
|
||||||
.with_child(
|
.with_child(
|
||||||
Label::new(
|
Label::new(
|
||||||
|
@ -467,9 +500,9 @@ impl ContactsPanel {
|
||||||
MouseEventHandler::new::<LocalProject, _, _>(project_id, cx, |state, cx| {
|
MouseEventHandler::new::<LocalProject, _, _>(project_id, cx, |state, cx| {
|
||||||
let row = theme.project_row.style_for(state, is_selected);
|
let row = theme.project_row.style_for(state, is_selected);
|
||||||
let mut worktree_root_names = String::new();
|
let mut worktree_root_names = String::new();
|
||||||
let project = project.read(cx);
|
let project_ = project.read(cx);
|
||||||
let is_public = project.is_public();
|
let is_public = project_.is_public();
|
||||||
for tree in project.visible_worktrees(cx) {
|
for tree in project_.visible_worktrees(cx) {
|
||||||
if !worktree_root_names.is_empty() {
|
if !worktree_root_names.is_empty() {
|
||||||
worktree_root_names.push_str(", ");
|
worktree_root_names.push_str(", ");
|
||||||
}
|
}
|
||||||
|
@ -498,7 +531,9 @@ impl ContactsPanel {
|
||||||
CursorStyle::PointingHand
|
CursorStyle::PointingHand
|
||||||
})
|
})
|
||||||
.on_click(move |_, _, cx| {
|
.on_click(move |_, _, cx| {
|
||||||
cx.dispatch_action(ToggleProjectPublic { project: None })
|
cx.dispatch_action(ToggleProjectPublic {
|
||||||
|
project: Some(project.clone()),
|
||||||
|
})
|
||||||
})
|
})
|
||||||
.boxed(),
|
.boxed(),
|
||||||
)
|
)
|
||||||
|
|
|
@ -8,7 +8,7 @@ use anyhow::{anyhow, Context, Result};
|
||||||
use client::{proto, Client, PeerId, TypedEnvelope, User, UserStore};
|
use client::{proto, Client, PeerId, TypedEnvelope, User, UserStore};
|
||||||
use clock::ReplicaId;
|
use clock::ReplicaId;
|
||||||
use collections::{hash_map, BTreeMap, HashMap, HashSet};
|
use collections::{hash_map, BTreeMap, HashMap, HashSet};
|
||||||
use futures::{future::Shared, select_biased, Future, FutureExt, StreamExt, TryFutureExt};
|
use futures::{future::Shared, Future, FutureExt, StreamExt, TryFutureExt};
|
||||||
use fuzzy::{PathMatch, PathMatchCandidate, PathMatchCandidateSet};
|
use fuzzy::{PathMatch, PathMatchCandidate, PathMatchCandidateSet};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
AnyModelHandle, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle,
|
AnyModelHandle, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle,
|
||||||
|
@ -25,6 +25,7 @@ use language::{
|
||||||
use lsp::{DiagnosticSeverity, DiagnosticTag, DocumentHighlightKind, LanguageServer};
|
use lsp::{DiagnosticSeverity, DiagnosticTag, DocumentHighlightKind, LanguageServer};
|
||||||
use lsp_command::*;
|
use lsp_command::*;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
use postage::stream::Stream;
|
||||||
use postage::watch;
|
use postage::watch;
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use search::SearchQuery;
|
use search::SearchQuery;
|
||||||
|
@ -325,14 +326,12 @@ impl Project {
|
||||||
let (public_tx, public_rx) = watch::channel_with(public);
|
let (public_tx, public_rx) = watch::channel_with(public);
|
||||||
let (remote_id_tx, remote_id_rx) = watch::channel();
|
let (remote_id_tx, remote_id_rx) = watch::channel();
|
||||||
let _maintain_remote_id_task = cx.spawn_weak({
|
let _maintain_remote_id_task = cx.spawn_weak({
|
||||||
let mut status_rx = client.clone().status();
|
let status_rx = client.clone().status();
|
||||||
let mut public_rx = public_rx.clone();
|
let public_rx = public_rx.clone();
|
||||||
move |this, mut cx| async move {
|
move |this, mut cx| async move {
|
||||||
loop {
|
let mut stream = Stream::map(status_rx.clone(), drop)
|
||||||
select_biased! {
|
.merge(Stream::map(public_rx.clone(), drop));
|
||||||
value = status_rx.next().fuse() => { value?; }
|
while stream.recv().await.is_some() {
|
||||||
value = public_rx.next().fuse() => { value?; }
|
|
||||||
};
|
|
||||||
let this = this.upgrade(&cx)?;
|
let this = this.upgrade(&cx)?;
|
||||||
if status_rx.borrow().is_connected() && *public_rx.borrow() {
|
if status_rx.borrow().is_connected() && *public_rx.borrow() {
|
||||||
this.update(&mut cx, |this, cx| this.register(cx))
|
this.update(&mut cx, |this, cx| this.register(cx))
|
||||||
|
@ -342,11 +341,12 @@ impl Project {
|
||||||
this.update(&mut cx, |this, cx| this.unregister(cx));
|
this.update(&mut cx, |this, cx| this.unregister(cx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
None
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let handle = cx.weak_handle();
|
let handle = cx.weak_handle();
|
||||||
project_store.update(cx, |store, cx| store.add(handle, cx));
|
project_store.update(cx, |store, cx| store.add_project(handle, cx));
|
||||||
|
|
||||||
let (opened_buffer_tx, opened_buffer_rx) = watch::channel();
|
let (opened_buffer_tx, opened_buffer_rx) = watch::channel();
|
||||||
Self {
|
Self {
|
||||||
|
@ -434,7 +434,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: &mut ModelContext<Self>| {
|
let this = cx.add_model(|cx: &mut ModelContext<Self>| {
|
||||||
let handle = cx.weak_handle();
|
let handle = cx.weak_handle();
|
||||||
project_store.update(cx, |store, cx| store.add(handle, cx));
|
project_store.update(cx, |store, cx| store.add_project(handle, cx));
|
||||||
|
|
||||||
let mut this = Self {
|
let mut this = Self {
|
||||||
worktrees: Vec::new(),
|
worktrees: Vec::new(),
|
||||||
|
@ -624,9 +624,10 @@ impl Project {
|
||||||
&self.fs
|
&self.fs
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_public(&mut self, is_public: bool) {
|
pub fn set_public(&mut self, is_public: bool, cx: &mut ModelContext<Self>) {
|
||||||
if let ProjectClientState::Local { public_tx, .. } = &mut self.client_state {
|
if let ProjectClientState::Local { public_tx, .. } = &mut self.client_state {
|
||||||
*public_tx.borrow_mut() = is_public;
|
*public_tx.borrow_mut() = is_public;
|
||||||
|
self.metadata_changed(cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -648,10 +649,19 @@ impl Project {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let ProjectClientState::Local { remote_id_tx, .. } = &mut self.client_state {
|
if let ProjectClientState::Local { remote_id_tx, .. } = &mut self.client_state {
|
||||||
*remote_id_tx.borrow_mut() = None;
|
let mut remote_id = remote_id_tx.borrow_mut();
|
||||||
|
if let Some(remote_id) = *remote_id {
|
||||||
|
self.client
|
||||||
|
.send(proto::UnregisterProject {
|
||||||
|
project_id: remote_id,
|
||||||
|
})
|
||||||
|
.log_err();
|
||||||
|
}
|
||||||
|
*remote_id = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.subscriptions.clear();
|
self.subscriptions.clear();
|
||||||
|
self.metadata_changed(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
|
fn register(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
|
||||||
|
@ -671,6 +681,7 @@ impl Project {
|
||||||
*remote_id_tx.borrow_mut() = Some(remote_id);
|
*remote_id_tx.borrow_mut() = Some(remote_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.metadata_changed(cx);
|
||||||
cx.emit(Event::RemoteIdChanged(Some(remote_id)));
|
cx.emit(Event::RemoteIdChanged(Some(remote_id)));
|
||||||
|
|
||||||
this.subscriptions
|
this.subscriptions
|
||||||
|
@ -745,6 +756,10 @@ impl Project {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn metadata_changed(&mut self, cx: &mut ModelContext<Self>) {
|
||||||
|
self.project_store.update(cx, |_, cx| cx.notify());
|
||||||
|
}
|
||||||
|
|
||||||
pub fn collaborators(&self) -> &HashMap<PeerId, Collaborator> {
|
pub fn collaborators(&self) -> &HashMap<PeerId, Collaborator> {
|
||||||
&self.collaborators
|
&self.collaborators
|
||||||
}
|
}
|
||||||
|
@ -3743,6 +3758,7 @@ impl Project {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
self.metadata_changed(cx);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3772,6 +3788,7 @@ impl Project {
|
||||||
self.worktrees
|
self.worktrees
|
||||||
.push(WorktreeHandle::Weak(worktree.downgrade()));
|
.push(WorktreeHandle::Weak(worktree.downgrade()));
|
||||||
}
|
}
|
||||||
|
self.metadata_changed(cx);
|
||||||
cx.emit(Event::WorktreeAdded);
|
cx.emit(Event::WorktreeAdded);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
@ -5204,7 +5221,7 @@ impl ProjectStore {
|
||||||
.filter_map(|project| project.upgrade(cx))
|
.filter_map(|project| project.upgrade(cx))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add(&mut self, project: WeakModelHandle<Project>, cx: &mut ModelContext<Self>) {
|
fn add_project(&mut self, project: WeakModelHandle<Project>, cx: &mut ModelContext<Self>) {
|
||||||
if let Err(ix) = self
|
if let Err(ix) = self
|
||||||
.projects
|
.projects
|
||||||
.binary_search_by_key(&project.id(), WeakModelHandle::id)
|
.binary_search_by_key(&project.id(), WeakModelHandle::id)
|
||||||
|
@ -5214,7 +5231,7 @@ impl ProjectStore {
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prune(&mut self, cx: &mut ModelContext<Self>) {
|
fn prune_projects(&mut self, cx: &mut ModelContext<Self>) {
|
||||||
let mut did_change = false;
|
let mut did_change = false;
|
||||||
self.projects.retain(|project| {
|
self.projects.retain(|project| {
|
||||||
if project.is_upgradable(cx) {
|
if project.is_upgradable(cx) {
|
||||||
|
@ -5316,7 +5333,7 @@ impl Entity for Project {
|
||||||
type Event = Event;
|
type Event = Event;
|
||||||
|
|
||||||
fn release(&mut self, cx: &mut gpui::MutableAppContext) {
|
fn release(&mut self, cx: &mut gpui::MutableAppContext) {
|
||||||
self.project_store.update(cx, ProjectStore::prune);
|
self.project_store.update(cx, ProjectStore::prune_projects);
|
||||||
|
|
||||||
match &self.client_state {
|
match &self.client_state {
|
||||||
ProjectClientState::Local { remote_id_rx, .. } => {
|
ProjectClientState::Local { remote_id_rx, .. } => {
|
||||||
|
|
|
@ -151,14 +151,7 @@ impl Entity for Worktree {
|
||||||
|
|
||||||
fn release(&mut self, _: &mut MutableAppContext) {
|
fn release(&mut self, _: &mut MutableAppContext) {
|
||||||
if let Some(worktree) = self.as_local_mut() {
|
if let Some(worktree) = self.as_local_mut() {
|
||||||
if let Registration::Done { project_id } = worktree.registration {
|
worktree.unregister();
|
||||||
let client = worktree.client.clone();
|
|
||||||
let unregister_message = proto::UnregisterWorktree {
|
|
||||||
project_id,
|
|
||||||
worktree_id: worktree.id().to_proto(),
|
|
||||||
};
|
|
||||||
client.send(unregister_message).log_err();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1063,6 +1056,15 @@ impl LocalWorktree {
|
||||||
|
|
||||||
pub fn unregister(&mut self) {
|
pub fn unregister(&mut self) {
|
||||||
self.unshare();
|
self.unshare();
|
||||||
|
if let Registration::Done { project_id } = self.registration {
|
||||||
|
self.client
|
||||||
|
.clone()
|
||||||
|
.send(proto::UnregisterWorktree {
|
||||||
|
project_id,
|
||||||
|
worktree_id: self.id().to_proto(),
|
||||||
|
})
|
||||||
|
.log_err();
|
||||||
|
}
|
||||||
self.registration = Registration::None;
|
self.registration = Registration::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -319,7 +319,7 @@ pub struct Icon {
|
||||||
pub path: String,
|
pub path: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default)]
|
#[derive(Deserialize, Clone, Copy, Default)]
|
||||||
pub struct IconButton {
|
pub struct IconButton {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
|
|
|
@ -22,7 +22,7 @@ use gpui::{
|
||||||
platform::{CursorStyle, WindowOptions},
|
platform::{CursorStyle, WindowOptions},
|
||||||
AnyModelHandle, AnyViewHandle, AppContext, AsyncAppContext, Border, Entity, ImageData,
|
AnyModelHandle, AnyViewHandle, AppContext, AsyncAppContext, Border, Entity, ImageData,
|
||||||
ModelContext, ModelHandle, MutableAppContext, PathPromptOptions, PromptLevel, RenderContext,
|
ModelContext, ModelHandle, MutableAppContext, PathPromptOptions, PromptLevel, RenderContext,
|
||||||
Task, View, ViewContext, ViewHandle, WeakModelHandle, WeakViewHandle,
|
Task, View, ViewContext, ViewHandle, WeakViewHandle,
|
||||||
};
|
};
|
||||||
use language::LanguageRegistry;
|
use language::LanguageRegistry;
|
||||||
use log::error;
|
use log::error;
|
||||||
|
@ -102,7 +102,7 @@ pub struct OpenPaths {
|
||||||
#[derive(Clone, Deserialize)]
|
#[derive(Clone, Deserialize)]
|
||||||
pub struct ToggleProjectPublic {
|
pub struct ToggleProjectPublic {
|
||||||
#[serde(skip_deserializing)]
|
#[serde(skip_deserializing)]
|
||||||
pub project: Option<WeakModelHandle<Project>>,
|
pub project: Option<ModelHandle<Project>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -1050,19 +1050,13 @@ impl Workspace {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toggle_project_public(&mut self, action: &ToggleProjectPublic, cx: &mut ViewContext<Self>) {
|
fn toggle_project_public(&mut self, action: &ToggleProjectPublic, cx: &mut ViewContext<Self>) {
|
||||||
let project = if let Some(project) = action.project {
|
let project = action
|
||||||
if let Some(project) = project.upgrade(cx) {
|
.project
|
||||||
project
|
.clone()
|
||||||
} else {
|
.unwrap_or_else(|| self.project.clone());
|
||||||
return;
|
project.update(cx, |project, cx| {
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.project.clone()
|
|
||||||
};
|
|
||||||
|
|
||||||
project.update(cx, |project, _| {
|
|
||||||
let is_public = project.is_public();
|
let is_public = project.is_public();
|
||||||
project.set_public(!is_public);
|
project.set_public(!is_public, cx);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,8 @@ export default function contactsPanel(theme: Theme) {
|
||||||
privateButton: {
|
privateButton: {
|
||||||
iconWidth: 8,
|
iconWidth: 8,
|
||||||
color: iconColor(theme, "primary"),
|
color: iconColor(theme, "primary"),
|
||||||
buttonWidth: 8,
|
cornerRadius: 5,
|
||||||
|
buttonWidth: 12,
|
||||||
},
|
},
|
||||||
rowHeight: 28,
|
rowHeight: 28,
|
||||||
sectionIconSize: 8,
|
sectionIconSize: 8,
|
||||||
|
|
Loading…
Reference in a new issue