diff --git a/crates/inline_completion/src/inline_completion.rs b/crates/inline_completion/src/inline_completion.rs index cea21472ca..80077cc169 100644 --- a/crates/inline_completion/src/inline_completion.rs +++ b/crates/inline_completion/src/inline_completion.rs @@ -25,18 +25,30 @@ pub enum DataCollectionState { /// The provider doesn't support data collection. Unsupported, /// Data collection is enabled. - Enabled, + Enabled { is_project_open_source: bool }, /// Data collection is disabled or unanswered. - Disabled, + Disabled { is_project_open_source: bool }, } impl DataCollectionState { pub fn is_supported(&self) -> bool { - !matches!(self, DataCollectionState::Unsupported) + !matches!(self, DataCollectionState::Unsupported { .. }) } pub fn is_enabled(&self) -> bool { - matches!(self, DataCollectionState::Enabled) + matches!(self, DataCollectionState::Enabled { .. }) + } + + pub fn is_project_open_source(&self) -> bool { + match self { + Self::Enabled { + is_project_open_source, + } + | Self::Disabled { + is_project_open_source, + } => *is_project_open_source, + _ => false, + } } } diff --git a/crates/inline_completion_button/src/inline_completion_button.rs b/crates/inline_completion_button/src/inline_completion_button.rs index 244fa8324b..c8b2bc333a 100644 --- a/crates/inline_completion_button/src/inline_completion_button.rs +++ b/crates/inline_completion_button/src/inline_completion_button.rs @@ -456,17 +456,56 @@ impl InlineCompletionButton { if data_collection.is_supported() { let provider = provider.clone(); let enabled = data_collection.is_enabled(); + let is_open_source = data_collection.is_project_open_source(); + let is_collecting = data_collection.is_enabled(); menu = menu.item( - // TODO: We want to add something later that communicates whether - // the current project is open-source. ContextMenuEntry::new("Share Training Data") .toggleable(IconPosition::Start, data_collection.is_enabled()) - .documentation_aside(|_| { - Label::new(indoc!{" - Help us improve our open model by sharing data from open source repositories. \ - Zed must detect a license file in your repo for this setting to take effect.\ - "}).into_any_element() + .icon_color(if is_open_source && is_collecting { + Color::Success + } else { + Color::Accent + }) + .documentation_aside(move |cx| { + let (msg, label_color, icon_name, icon_color) = match (is_open_source, is_collecting) { + (true, true) => ( + "Project identified as open-source, and you're sharing data.", + Color::Default, + IconName::Check, + Color::Success, + ), + (true, false) => ( + "Project identified as open-source, but you're not sharing data.", + Color::Muted, + IconName::XCircle, + Color::Muted, + ), + (false, _) => ( + "Project not identified as open-source. No data captured.", + Color::Muted, + IconName::XCircle, + Color::Muted, + ), + }; + v_flex() + .gap_2() + .child( + Label::new(indoc!{ + "Help us improve our open model by sharing data from open source repositories. \ + Zed must detect a license file in your repo for this setting to take effect." + }) + ) + .child( + h_flex() + .pt_2() + .gap_1p5() + .border_t_1() + .border_color(cx.theme().colors().border_variant) + .child(Icon::new(icon_name).size(IconSize::XSmall).color(icon_color)) + .child(div().child(Label::new(msg).size(LabelSize::Small).color(label_color))) + ) + .into_any_element() }) .handler(move |_, cx| { provider.toggle_data_collection(cx); @@ -483,7 +522,7 @@ impl InlineCompletionButton { ); } }) - ) + ); } } diff --git a/crates/ui/src/components/context_menu.rs b/crates/ui/src/components/context_menu.rs index 2ebaa55105..2349754293 100644 --- a/crates/ui/src/components/context_menu.rs +++ b/crates/ui/src/components/context_menu.rs @@ -524,7 +524,7 @@ impl Render for ContextMenu { .occlude() .elevation_2(cx) .p_2() - .max_w_80() + .max_w_96() .child(aside(cx)), ) }) @@ -600,6 +600,8 @@ impl Render for ContextMenu { let menu = cx.entity().downgrade(); let icon_color = if *disabled { Color::Muted + } else if toggle.is_some() { + icon_color.unwrap_or(Color::Accent) } else { icon_color.unwrap_or(Color::Default) }; @@ -674,7 +676,7 @@ impl Render for ContextMenu { let contents = div().flex_none().child( Icon::new(IconName::Check) - .color(Color::Accent) + .color(icon_color) .size(*icon_size) ) .when(!toggled, |contents| diff --git a/crates/zeta/src/zeta.rs b/crates/zeta/src/zeta.rs index 14cd32b300..9365f1945d 100644 --- a/crates/zeta/src/zeta.rs +++ b/crates/zeta/src/zeta.rs @@ -1024,7 +1024,7 @@ impl LicenseDetectionWatcher { } /// Answers false until we find out it's open source - pub fn is_open_source(&self) -> bool { + pub fn is_project_open_source(&self) -> bool { *self.is_open_source_rx.borrow() } } @@ -1227,7 +1227,6 @@ impl ProviderDataCollection { let zeta = zeta.read(cx); let choice = zeta.data_collection_choice.clone(); - // Unwrap safety: there should be a watcher for each worktree let license_detection_watcher = zeta .license_detection_watchers .get(&file.worktree_id(cx)) @@ -1249,20 +1248,20 @@ impl ProviderDataCollection { } } - pub fn user_data_collection_choice(&self, cx: &App) -> bool { - self.choice - .as_ref() - .map_or(false, |choice| choice.read(cx).is_enabled()) + pub fn can_collect_data(&self, cx: &App) -> bool { + self.is_data_collection_enabled(cx) && self.is_project_open_source() } - pub fn can_collect_data(&self, cx: &App) -> bool { + pub fn is_data_collection_enabled(&self, cx: &App) -> bool { self.choice .as_ref() .is_some_and(|choice| choice.read(cx).is_enabled()) - && self - .license_detection_watcher - .as_ref() - .is_some_and(|watcher| watcher.is_open_source()) + } + + fn is_project_open_source(&self) -> bool { + self.license_detection_watcher + .as_ref() + .is_some_and(|watcher| watcher.is_project_open_source()) } pub fn toggle(&mut self, cx: &mut App) { @@ -1326,13 +1325,16 @@ impl inline_completion::EditPredictionProvider for ZetaInlineCompletionProvider } fn data_collection_state(&self, cx: &App) -> DataCollectionState { - if self - .provider_data_collection - .user_data_collection_choice(cx) - { - DataCollectionState::Enabled + let is_project_open_source = self.provider_data_collection.is_project_open_source(); + + if self.provider_data_collection.is_data_collection_enabled(cx) { + DataCollectionState::Enabled { + is_project_open_source, + } } else { - DataCollectionState::Disabled + DataCollectionState::Disabled { + is_project_open_source, + } } }