Skip to repository content117 lines · 3.6 KB · rust
tenant.openagents/omega
No repository description is available.
OpenAgents Git authority 2026-07-28T05:42:03.311Z Public web read
NIP-34 coordinate
30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omegaMaintainersHidden in public view
References2 branches · 1 tag
Read-only clone
git clone https://openagents.com/git/tenant.openagents/omega.gitBrowse files
open_url_modal.rs
1use editor::Editor;
2use gpui::{AppContext as _, DismissEvent, Entity, EventEmitter, Focusable, ReadGlobal, Styled};
3use ui::{
4 ActiveTheme, App, Color, Context, FluentBuilder, InteractiveElement, IntoElement, Label,
5 LabelCommon, LabelSize, ParentElement, Render, SharedString, StyledExt, Window, div, h_flex,
6 v_flex,
7};
8use workspace::ModalView;
9
10use super::{OpenListener, RawOpenRequest};
11
12pub struct OpenUrlModal {
13 editor: Entity<Editor>,
14 last_error: Option<SharedString>,
15}
16
17impl EventEmitter<DismissEvent> for OpenUrlModal {}
18impl ModalView for OpenUrlModal {}
19
20impl Focusable for OpenUrlModal {
21 fn focus_handle(&self, cx: &App) -> gpui::FocusHandle {
22 self.editor.focus_handle(cx)
23 }
24}
25
26impl OpenUrlModal {
27 pub fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
28 let editor = cx.new(|cx| {
29 let mut editor = Editor::single_line(window, cx);
30 editor.set_placeholder_text("zed://...", window, cx);
31 editor
32 });
33
34 Self {
35 editor,
36 last_error: None,
37 }
38 }
39
40 fn cancel(&mut self, _: &menu::Cancel, _window: &mut Window, cx: &mut Context<Self>) {
41 cx.emit(DismissEvent);
42 }
43
44 fn confirm(&mut self, _: &menu::Confirm, window: &mut Window, cx: &mut Context<Self>) {
45 let url = self.editor.update(cx, |editor, cx| {
46 let text = editor.text(cx).trim().to_string();
47 editor.clear(window, cx);
48 text
49 });
50
51 if url.is_empty() {
52 cx.emit(DismissEvent);
53 return;
54 }
55
56 // Handle zed:// URLs internally.
57 if url.starts_with("zed://") || url.starts_with("zed-cli://") {
58 OpenListener::global(cx).open(RawOpenRequest {
59 urls: vec![url],
60 ..Default::default()
61 });
62 cx.emit(DismissEvent);
63 return;
64 }
65
66 match url::Url::parse(&url) {
67 Ok(parsed_url) => {
68 cx.open_url(parsed_url.as_str());
69 cx.emit(DismissEvent);
70 }
71 Err(e) => {
72 self.last_error = Some(format!("Invalid URL: {}", e).into());
73 cx.notify();
74 }
75 }
76 }
77}
78
79impl Render for OpenUrlModal {
80 fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
81 let theme = cx.theme();
82
83 v_flex()
84 .key_context("OpenUrlModal")
85 .on_action(cx.listener(Self::cancel))
86 .on_action(cx.listener(Self::confirm))
87 .elevation_3(cx)
88 .w_96()
89 .overflow_hidden()
90 .child(
91 div()
92 .p_2()
93 .border_b_1()
94 .border_color(theme.colors().border_variant)
95 .child(self.editor.clone()),
96 )
97 .child(
98 h_flex()
99 .bg(theme.colors().editor_background)
100 .rounded_b_sm()
101 .w_full()
102 .p_2()
103 .gap_1()
104 .when_some(self.last_error.clone(), |this, error| {
105 this.child(Label::new(error).size(LabelSize::Small).color(Color::Error))
106 })
107 .when(self.last_error.is_none(), |this| {
108 this.child(
109 Label::new("Paste a URL to open.")
110 .color(Color::Muted)
111 .size(LabelSize::Small),
112 )
113 }),
114 )
115 }
116}
117