zed ai: Show ToS form in Configuration View (#16736)

Thorsten Ball created

Related #16618

Release Notes:

- N/A

Change summary

crates/language_model/src/provider/cloud.rs | 121 ++++++++++++++--------
1 file changed, 78 insertions(+), 43 deletions(-)

Detailed changes

crates/language_model/src/provider/cloud.rs 🔗

@@ -31,7 +31,7 @@ use std::{
     sync::{Arc, LazyLock},
 };
 use strum::IntoEnumIterator;
-use ui::prelude::*;
+use ui::{prelude::*, TintColor};
 
 use crate::{LanguageModelAvailability, LanguageModelProvider};
 
@@ -793,6 +793,46 @@ impl ConfigurationView {
         });
         cx.notify();
     }
+
+    fn render_accept_terms(&mut self, cx: &mut ViewContext<Self>) -> Option<AnyElement> {
+        if self.state.read(cx).has_accepted_terms_of_service(cx) {
+            return None;
+        }
+
+        let accept_terms_disabled = self.state.read(cx).accept_terms.is_some();
+
+        let terms_button = Button::new("terms_of_service", "Terms of Service")
+            .style(ButtonStyle::Subtle)
+            .icon(IconName::ExternalLink)
+            .icon_color(Color::Muted)
+            .on_click(move |_, cx| cx.open_url("https://zed.dev/terms-of-service"));
+
+        let text =
+            "In order to use Zed AI, please read and accept our terms and conditions to continue:";
+
+        let form = v_flex()
+            .gap_2()
+            .child(Label::new("Terms and Conditions"))
+            .child(Label::new(text))
+            .child(h_flex().justify_center().child(terms_button))
+            .child(
+                h_flex().justify_center().child(
+                    Button::new("accept_terms", "I've read and accept the terms of service")
+                        .style(ButtonStyle::Tinted(TintColor::Accent))
+                        .disabled(accept_terms_disabled)
+                        .on_click({
+                            let state = self.state.downgrade();
+                            move |_, cx| {
+                                state
+                                    .update(cx, |state, cx| state.accept_terms_of_service(cx))
+                                    .ok();
+                            }
+                        }),
+                ),
+            );
+
+        Some(form.into_any())
+    }
 }
 
 impl Render for ConfigurationView {
@@ -802,55 +842,50 @@ impl Render for ConfigurationView {
 
         let is_connected = !self.state.read(cx).is_signed_out();
         let plan = self.state.read(cx).user_store.read(cx).current_plan();
-        let must_accept_terms = !self.state.read(cx).has_accepted_terms_of_service(cx);
+        let has_accepted_terms = self.state.read(cx).has_accepted_terms_of_service(cx);
 
         let is_pro = plan == Some(proto::Plan::ZedPro);
+        let subscription_text = Label::new(if is_pro {
+            "You have full access to Zed's hosted models from Anthropic, OpenAI, Google with faster speeds and higher limits through Zed Pro."
+        } else {
+            "You have basic access to models from Anthropic through the Zed AI Free plan."
+        });
+        let manage_subscription_button = if is_pro {
+            Some(
+                h_flex().child(
+                    Button::new("manage_settings", "Manage Subscription")
+                        .style(ButtonStyle::Tinted(TintColor::Accent))
+                        .on_click(cx.listener(|_, _, cx| cx.open_url(ACCOUNT_SETTINGS_URL))),
+                ),
+            )
+        } else if cx.has_flag::<ZedPro>() {
+            Some(
+                h_flex()
+                    .gap_2()
+                    .child(
+                        Button::new("learn_more", "Learn more")
+                            .style(ButtonStyle::Subtle)
+                            .on_click(cx.listener(|_, _, cx| cx.open_url(ZED_AI_URL))),
+                    )
+                    .child(
+                        Button::new("upgrade", "Upgrade")
+                            .style(ButtonStyle::Subtle)
+                            .color(Color::Accent)
+                            .on_click(cx.listener(|_, _, cx| cx.open_url(ACCOUNT_SETTINGS_URL))),
+                    ),
+            )
+        } else {
+            None
+        };
 
         if is_connected {
             v_flex()
                 .gap_3()
                 .max_w_4_5()
-                .when(must_accept_terms, |this| {
-                    this.child(Label::new(
-                        "You must accept the terms of service to use this provider.",
-                    ))
-                })
-                .child(Label::new(
-                    if is_pro {
-                        "You have full access to Zed's hosted models from Anthropic, OpenAI, Google with faster speeds and higher limits through Zed Pro."
-                    } else {
-                        "You have basic access to models from Anthropic through the Zed AI Free plan."
-                    }))
-                .children(if is_pro {
-                    Some(
-                        h_flex().child(
-                            Button::new("manage_settings", "Manage Subscription")
-                                .style(ButtonStyle::Filled)
-                                .on_click(
-                                    cx.listener(|_, _, cx| cx.open_url(ACCOUNT_SETTINGS_URL)),
-                                ),
-                        ),
-                    )
-                } else if cx.has_flag::<ZedPro>() {
-                    Some(
-                        h_flex()
-                            .gap_2()
-                            .child(
-                                Button::new("learn_more", "Learn more")
-                                    .style(ButtonStyle::Subtle)
-                                    .on_click(cx.listener(|_, _, cx| cx.open_url(ZED_AI_URL))),
-                            )
-                            .child(
-                                Button::new("upgrade", "Upgrade")
-                                    .style(ButtonStyle::Subtle)
-                                    .color(Color::Accent)
-                                    .on_click(
-                                        cx.listener(|_, _, cx| cx.open_url(ACCOUNT_SETTINGS_URL)),
-                                    ),
-                            ),
-                    )
-                } else {
-                    None
+                .children(self.render_accept_terms(cx))
+                .when(has_accepted_terms, |this| {
+                    this.child(subscription_text)
+                        .children(manage_subscription_button)
                 })
         } else {
             v_flex()