From fd7fa87939a720d1e7f7041b9a62eb55df50ad2a Mon Sep 17 00:00:00 2001 From: Agus Zubiaga Date: Fri, 7 Feb 2025 15:42:27 -0300 Subject: [PATCH] edit predictions: Restore red dot in status buttons when pending ToS (#24408) In one of the recent changes to the edit predictions status bar menu, we lost the red dot that is displayed when the user has Zed as the provider but hasn't accepted terms of service. Note: All the checks were still in place, just the visual indicator was missing. ![CleanShot 2025-02-06 at 20 22 21@2x](https://github.com/user-attachments/assets/da8f25dd-5ed2-4bf9-8453-10b80f00bf63) Release Notes: - N/A --------- Co-authored-by: Danilo Leal --- crates/editor/src/editor.rs | 2 +- .../src/inline_completion_button.rs | 96 +++++++++---------- .../ui/src/components/button/button_icon.rs | 26 ++++- .../ui/src/components/button/icon_button.rs | 22 ++++- 4 files changed, 93 insertions(+), 53 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 24ec46ca61bba155db16921ad01ebc436062d6af..b5ef81bfbabaf1019a31a4aa2e2e41cb37617455 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -5549,7 +5549,7 @@ impl Editor { })) .child( h_flex() - .w_full() + .flex_1() .gap_2() .child(Icon::new(IconName::ZedPredict)) .child(Label::new("Accept Terms of Service")) diff --git a/crates/inline_completion_button/src/inline_completion_button.rs b/crates/inline_completion_button/src/inline_completion_button.rs index a28cfe99c1206acd16c8a262d00ff32f57d6f53d..1864e0c26603885738d73d6040b826a3435e62ef 100644 --- a/crates/inline_completion_button/src/inline_completion_button.rs +++ b/crates/inline_completion_button/src/inline_completion_button.rs @@ -24,8 +24,8 @@ use std::{ }; use supermaven::{AccountStatus, Supermaven}; use ui::{ - prelude::*, Clickable, ContextMenu, ContextMenuEntry, IconButton, IconButtonShape, PopoverMenu, - PopoverMenuHandle, Tooltip, + prelude::*, Clickable, ContextMenu, ContextMenuEntry, IconButton, IconButtonShape, Indicator, + PopoverMenu, PopoverMenuHandle, Tooltip, }; use workspace::{ create_and_open_local_file, item::ItemHandle, notifications::NotificationId, StatusItemView, @@ -240,24 +240,20 @@ impl Render for InlineCompletionButton { let current_user_terms_accepted = self.user_store.read(cx).current_user_has_accepted_terms(); - let icon_button = || { - let base = IconButton::new("zed-predict-pending-button", zeta_icon) - .shape(IconButtonShape::Square); - - match ( - current_user_terms_accepted, - self.popover_menu_handle.is_deployed(), - enabled, - ) { - (Some(false) | None, _, _) => { - let signed_in = current_user_terms_accepted.is_some(); - let tooltip_meta = if signed_in { - "Read Terms of Service" - } else { - "Sign in to use" - }; + if !current_user_terms_accepted.unwrap_or(false) { + let signed_in = current_user_terms_accepted.is_some(); + let tooltip_meta = if signed_in { + "Read Terms of Service" + } else { + "Sign in to use" + }; - base.tooltip(move |window, cx| { + return div().child( + IconButton::new("zed-predict-pending-button", zeta_icon) + .shape(IconButtonShape::Square) + .indicator(Indicator::dot().color(Color::Error)) + .indicator_border_color(Some(cx.theme().colors().status_bar_background)) + .tooltip(move |window, cx| { Tooltip::with_meta( "Edit Predictions", None, @@ -266,34 +262,38 @@ impl Render for InlineCompletionButton { cx, ) }) - .on_click(cx.listener( - move |_, _, window, cx| { - telemetry::event!( - "Pending ToS Clicked", - source = "Edit Prediction Status Button" - ); - window.dispatch_action( - zed_actions::OpenZedPredictOnboarding.boxed_clone(), - cx, - ); - }, - )) + .on_click(cx.listener(move |_, _, window, cx| { + telemetry::event!( + "Pending ToS Clicked", + source = "Edit Prediction Status Button" + ); + window.dispatch_action( + zed_actions::OpenZedPredictOnboarding.boxed_clone(), + cx, + ); + })), + ); + } + + let icon_button = IconButton::new("zed-predict-pending-button", zeta_icon) + .shape(IconButtonShape::Square) + .when(!self.popover_menu_handle.is_deployed(), |element| { + if enabled { + element.tooltip(|window, cx| { + Tooltip::for_action("Edit Prediction", &ToggleMenu, window, cx) + }) + } else { + element.tooltip(|window, cx| { + Tooltip::with_meta( + "Edit Prediction", + Some(&ToggleMenu), + "Disabled For This File", + window, + cx, + ) + }) } - (Some(true), true, _) => base, - (Some(true), false, true) => base.tooltip(|window, cx| { - Tooltip::for_action("Edit Prediction", &ToggleMenu, window, cx) - }), - (Some(true), false, false) => base.tooltip(|window, cx| { - Tooltip::with_meta( - "Edit Prediction", - Some(&ToggleMenu), - "Disabled For This File", - window, - cx, - ) - }), - } - }; + }); let this = cx.entity().clone(); @@ -311,7 +311,7 @@ impl Render for InlineCompletionButton { if is_refreshing { popover_menu = popover_menu.trigger( - icon_button().with_animation( + icon_button.with_animation( "pulsating-label", Animation::new(Duration::from_secs(2)) .repeat() @@ -320,7 +320,7 @@ impl Render for InlineCompletionButton { ), ); } else { - popover_menu = popover_menu.trigger(icon_button()); + popover_menu = popover_menu.trigger(icon_button); } div().child(popover_menu.into_any_element()) diff --git a/crates/ui/src/components/button/button_icon.rs b/crates/ui/src/components/button/button_icon.rs index a2a146ee76f478259ebbbd682706b608d694ef2d..adacd12f27039f5289074f5bb2664afd43113493 100644 --- a/crates/ui/src/components/button/button_icon.rs +++ b/crates/ui/src/components/button/button_icon.rs @@ -1,5 +1,6 @@ #![allow(missing_docs)] -use crate::{prelude::*, Icon, IconName, IconSize}; +use crate::{prelude::*, Icon, IconName, IconSize, IconWithIndicator, Indicator}; +use gpui::Hsla; /// An icon that appears within a button. /// @@ -15,6 +16,8 @@ pub(super) struct ButtonIcon { selected_icon: Option, selected_icon_color: Option, selected_style: Option, + indicator: Option, + indicator_border_color: Option, } impl ButtonIcon { @@ -28,6 +31,8 @@ impl ButtonIcon { selected_icon: None, selected_icon_color: None, selected_style: None, + indicator: None, + indicator_border_color: None, } } @@ -56,6 +61,16 @@ impl ButtonIcon { self.selected_icon_color = color.into(); self } + + pub fn indicator(mut self, indicator: Indicator) -> Self { + self.indicator = Some(indicator); + self + } + + pub fn indicator_border_color(mut self, color: Option) -> Self { + self.indicator_border_color = color; + self + } } impl Disableable for ButtonIcon { @@ -96,6 +111,13 @@ impl RenderOnce for ButtonIcon { self.color }; - Icon::new(icon).size(self.size).color(icon_color) + let icon = Icon::new(icon).size(self.size).color(icon_color); + + match self.indicator { + Some(indicator) => IconWithIndicator::new(icon, Some(indicator)) + .indicator_border_color(self.indicator_border_color) + .into_any_element(), + None => icon.into_any_element(), + } } } diff --git a/crates/ui/src/components/button/icon_button.rs b/crates/ui/src/components/button/icon_button.rs index 840f0fc394842c44780dab5125f890c37ee60539..c28c5ae9ac0dc1ff2f4e678a9b82b23a017b1cff 100644 --- a/crates/ui/src/components/button/icon_button.rs +++ b/crates/ui/src/components/button/icon_button.rs @@ -1,8 +1,8 @@ #![allow(missing_docs)] -use gpui::{AnyView, DefiniteLength}; +use gpui::{AnyView, DefiniteLength, Hsla}; use super::button_like::{ButtonCommon, ButtonLike, ButtonSize, ButtonStyle}; -use crate::{prelude::*, ElevationIndex, SelectableButton}; +use crate::{prelude::*, ElevationIndex, Indicator, SelectableButton}; use crate::{IconName, IconSize}; use super::button_icon::ButtonIcon; @@ -22,6 +22,8 @@ pub struct IconButton { icon_size: IconSize, icon_color: Color, selected_icon: Option, + indicator: Option, + indicator_border_color: Option, alpha: Option, } @@ -34,6 +36,8 @@ impl IconButton { icon_size: IconSize::default(), icon_color: Color::Default, selected_icon: None, + indicator: None, + indicator_border_color: None, alpha: None, }; this.base.base = this.base.base.debug_selector(|| format!("ICON-{:?}", icon)); @@ -64,6 +68,16 @@ impl IconButton { self.selected_icon = icon.into(); self } + + pub fn indicator(mut self, indicator: Indicator) -> Self { + self.indicator = Some(indicator); + self + } + + pub fn indicator_border_color(mut self, color: Option) -> Self { + self.indicator_border_color = color; + self + } } impl Disableable for IconButton { @@ -168,6 +182,10 @@ impl RenderOnce for IconButton { .toggle_state(is_selected) .selected_icon(self.selected_icon) .when_some(selected_style, |this, style| this.selected_style(style)) + .when_some(self.indicator, |this, indicator| { + this.indicator(indicator) + .indicator_border_color(self.indicator_border_color) + }) .size(self.icon_size) .color(Color::Custom(color)), )