Vectrum
Sign In
81 lines · 3.3 KB · Rust
//! The Integrations page: what T3 Code's has that this app supports, the
//! agents' access to the shared browser, plus the editor "Open in" uses.

use gpui_kit::component::menu::{DropdownMenu as _, PopupMenuItem};
use gpui_kit::prelude::FluentBuilder as _;
use gpui_kit::*;

use super::SettingsView;
use super::widgets::{Section, SettingRow, reset, switch};
use crate::browser;
use crate::settings;
use crate::ui::icons::Lucide;
use crate::ui::metal::{self, MetalButton};

impl SettingsView {
    pub(super) fn render_integrations(&mut self, cx: &mut Context<Self>) -> Vec<AnyElement> {
        let p = metal::palette(cx);
        let view = cx.weak_entity();
        let on = settings::get(|settings| settings.agent_browser);
        let installed = browser::find_binary().is_some();

        let browser = Section::new("Browser")
            .id("browser-access")
            .row(
                SettingRow::new("Agent browser access")
                    .id("agent-browser-access")
                    .description("Allow agents to use the shared browser. Applies when the agent session next starts.")
                    .when(!installed, |row| {
                        row.status("agent-browser isn't installed: npm install -g agent-browser && agent-browser install")
                    })
                    .dimmed(!installed)
                    .reset(reset(&view, |s| s.agent_browser, |s, on| s.agent_browser = on))
                    .control(switch("agent-browser", on, &view, p, |settings, on| settings.agent_browser = on)),
            )
            .render(cx);

        let editor = Section::new("Editor")
            .row(
                SettingRow::new("Open in")
                    .id("open-in")
                    .description("The editor the project panel opens projects in.")
                    .control(self.editor_control(cx)),
            )
            .render(cx);
        vec![browser, editor]
    }

    fn editor_control(&self, cx: &mut Context<Self>) -> AnyElement {
        let Some(workspace) = self.workspace.upgrade() else {
            return div().into_any_element();
        };
        let (names, current) = {
            let workspace = workspace.read(cx);
            (workspace.editor_names(), workspace.editor())
        };
        let Some(label) = names.get(current).copied() else {
            let p = metal::palette(cx);
            return div().text_size(px(13.)).text_color(p.ink3).child("No editor found").into_any_element();
        };
        let weak = self.workspace.clone();
        let view = cx.weak_entity();
        MetalButton::new("default-editor")
            .compact()
            .icon(Lucide::Code)
            .label(label)
            .caret()
            .dropdown_menu_with_anchor(Anchor::TopRight, move |mut menu, _, _| {
                menu = menu.min_w(px(200.));
                for (ix, name) in names.iter().enumerate() {
                    let weak = weak.clone();
                    let view = view.clone();
                    menu = menu.item(PopupMenuItem::new(*name).checked(ix == current).on_click(move |_, _, cx| {
                        let _ = weak.update(cx, |workspace, cx| workspace.set_editor(ix, cx));
                        let _ = view.update(cx, |_, cx| cx.notify());
                    }));
                }
                menu
            })
            .into_any_element()
    }
}