Add a setting to prevent sharing projects in public channels (#41395)

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.
This commit is contained in:
Marshall Bowers
2025-10-28 14:48:07 -04:00
committed by GitHub
parent 1f5101d9fd
commit e604ef3af9
6 changed files with 40 additions and 0 deletions

1
Cargo.lock generated
View File

@@ -17439,6 +17439,7 @@ dependencies = [
"anyhow",
"auto_update",
"call",
"channel",
"chrono",
"client",
"cloud_llm_client",

View File

@@ -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`.
///

View File

@@ -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())

View File

@@ -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

View File

@@ -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);

View File

@@ -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(),