Cargo.lock 🔗
@@ -17439,6 +17439,7 @@ dependencies = [
"anyhow",
"auto_update",
"call",
+ "channel",
"chrono",
"client",
"cloud_llm_client",
Marshall Bowers created
This PR adds a setting to prevent projects from being shared in public
channels.
This can be enabled by adding the following to the project settings
(`.zed/settings.json`):
```json
{
"prevent_sharing_in_public_channels": true
}
```
This will then disable the "Share" button when not in a private channel:
<img width="380" height="115" alt="Screenshot 2025-10-28 at 2 28 10 PM"
src="https://github.com/user-attachments/assets/6761ac34-c0d5-4451-a443-adf7a1c42bcd"
/>
Release Notes:
- collaboration: Added a `prevent_sharing_in_public_channels` project
setting for preventing projects from being shared in public channels.
Cargo.lock | 1
crates/settings/src/settings_content/project.rs | 6 ++++
crates/settings/src/vscode_import.rs | 1
crates/title_bar/Cargo.toml | 1
crates/title_bar/src/collab.rs | 28 +++++++++++++++++++
crates/worktree/src/worktree_settings.rs | 3 ++
6 files changed, 40 insertions(+)
@@ -17439,6 +17439,7 @@ dependencies = [
"anyhow",
"auto_update",
"call",
+ "channel",
"chrono",
"client",
"cloud_llm_client",
@@ -64,6 +64,12 @@ pub struct WorktreeSettingsContent {
#[serde(skip_serializing_if = "Maybe::is_unset")]
pub project_name: Maybe<String>,
+ /// Whether to prevent this project from being shared in public channels.
+ ///
+ /// Default: false
+ #[serde(default)]
+ pub prevent_sharing_in_public_channels: bool,
+
/// Completely ignore files matching globs from `file_scan_exclusions`. Overrides
/// `file_scan_inclusions`.
///
@@ -855,6 +855,7 @@ impl VsCodeSettings {
fn worktree_settings_content(&self) -> WorktreeSettingsContent {
WorktreeSettingsContent {
project_name: crate::Maybe::Unset,
+ prevent_sharing_in_public_channels: false,
file_scan_exclusions: self
.read_value("files.watcherExclude")
.and_then(|v| v.as_array())
@@ -30,6 +30,7 @@ test-support = [
anyhow.workspace = true
auto_update.workspace = true
call.workspace = true
+channel.workspace = true
chrono.workspace = true
client.workspace = true
cloud_llm_client.workspace = true
@@ -2,18 +2,22 @@ use std::rc::Rc;
use std::sync::Arc;
use call::{ActiveCall, ParticipantLocation, Room};
+use channel::ChannelStore;
use client::{User, proto::PeerId};
use gpui::{
AnyElement, Hsla, IntoElement, MouseButton, Path, ScreenCaptureSource, Styled, WeakEntity,
canvas, point,
};
use gpui::{App, Task, Window, actions};
+use project::WorktreeSettings;
use rpc::proto::{self};
+use settings::{Settings as _, SettingsLocation};
use theme::ActiveTheme;
use ui::{
Avatar, AvatarAudioStatusIndicator, ContextMenu, ContextMenuItem, Divider, DividerColor,
Facepile, PopoverMenu, SplitButton, SplitButtonStyle, TintColor, Tooltip, prelude::*,
};
+use util::rel_path::RelPath;
use workspace::notifications::DetachAndPromptErr;
use crate::TitleBar;
@@ -347,6 +351,11 @@ impl TitleBar {
let can_share_projects = room.can_share_projects();
let screen_sharing_supported = cx.is_screen_capture_supported();
+ let channel_store = ChannelStore::global(cx);
+ let channel = room
+ .channel_id()
+ .and_then(|channel_id| channel_store.read(cx).channel_for_id(channel_id).cloned());
+
let mut children = Vec::new();
children.push(
@@ -368,6 +377,20 @@ impl TitleBar {
);
if is_local && can_share_projects && !is_connecting_to_project {
+ let is_sharing_disabled = channel.is_some_and(|channel| match channel.visibility {
+ proto::ChannelVisibility::Public => project.visible_worktrees(cx).any(|worktree| {
+ let worktree_id = worktree.read(cx).id();
+
+ let settings_location = Some(SettingsLocation {
+ worktree_id,
+ path: RelPath::empty(),
+ });
+
+ WorktreeSettings::get(settings_location, cx).prevent_sharing_in_public_channels
+ }),
+ proto::ChannelVisibility::Members => false,
+ });
+
children.push(
Button::new(
"toggle_sharing",
@@ -382,6 +405,11 @@ impl TitleBar {
.selected_style(ButtonStyle::Tinted(TintColor::Accent))
.toggle_state(is_shared)
.label_size(LabelSize::Small)
+ .when(is_sharing_disabled, |parent| {
+ parent.disabled(true).tooltip(Tooltip::text(
+ "This project may not be shared in a public channel.",
+ ))
+ })
.on_click(cx.listener(move |this, _, window, cx| {
if is_shared {
this.unshare_project(window, cx);
@@ -11,6 +11,8 @@ use util::{
#[derive(Clone, PartialEq, Eq)]
pub struct WorktreeSettings {
pub project_name: Option<String>,
+ /// Whether to prevent this project from being shared in public channels.
+ pub prevent_sharing_in_public_channels: bool,
pub file_scan_inclusions: PathMatcher,
pub file_scan_exclusions: PathMatcher,
pub private_files: PathMatcher,
@@ -51,6 +53,7 @@ impl Settings for WorktreeSettings {
Self {
project_name: worktree.project_name.into_inner(),
+ prevent_sharing_in_public_channels: worktree.prevent_sharing_in_public_channels,
file_scan_exclusions: path_matchers(file_scan_exclusions, "file_scan_exclusions")
.log_err()
.unwrap_or_default(),