use editor::Editor; use futures::channel::oneshot; use gpui::{AppContext, DismissEvent, Entity, EventEmitter, Focusable, Styled}; use ui::{ ActiveTheme, App, Context, DynamicSpacing, Headline, HeadlineSize, Icon, IconName, IconSize, InteractiveElement, IntoElement, ParentElement, Render, SharedString, StyledExt, StyledTypography, Window, div, h_flex, v_flex, }; use workspace::ModalView; pub(crate) struct AskPassModal { operation: SharedString, prompt: SharedString, editor: Entity, tx: Option>, } impl EventEmitter for AskPassModal {} impl ModalView for AskPassModal {} impl Focusable for AskPassModal { fn focus_handle(&self, cx: &App) -> gpui::FocusHandle { self.editor.focus_handle(cx) } } impl AskPassModal { pub fn new( operation: SharedString, prompt: SharedString, tx: oneshot::Sender, window: &mut Window, cx: &mut Context, ) -> Self { let editor = cx.new(|cx| { let mut editor = Editor::single_line(window, cx); if prompt.contains("yes/no") { editor.set_masked(false, cx); } else { editor.set_masked(true, cx); } editor }); Self { operation, prompt, editor, tx: Some(tx), } } fn cancel(&mut self, _: &menu::Cancel, _window: &mut Window, cx: &mut Context) { cx.emit(DismissEvent); } fn confirm(&mut self, _: &menu::Confirm, _window: &mut Window, cx: &mut Context) { if let Some(tx) = self.tx.take() { tx.send(self.editor.read(cx).text(cx)).ok(); } cx.emit(DismissEvent); } } impl Render for AskPassModal { fn render(&mut self, _: &mut Window, cx: &mut Context) -> impl IntoElement { v_flex() .key_context("PasswordPrompt") .on_action(cx.listener(Self::cancel)) .on_action(cx.listener(Self::confirm)) .elevation_2(cx) .size_full() .font_buffer(cx) .child( h_flex() .px(DynamicSpacing::Base12.rems(cx)) .pt(DynamicSpacing::Base08.rems(cx)) .pb(DynamicSpacing::Base04.rems(cx)) .rounded_t_sm() .w_full() .gap_1p5() .child(Icon::new(IconName::GitBranch).size(IconSize::XSmall)) .child(h_flex().gap_1().overflow_x_hidden().child( div().max_w_96().overflow_x_hidden().text_ellipsis().child( Headline::new(self.operation.clone()).size(HeadlineSize::XSmall), ), )), ) .child( div() .text_buffer(cx) .py_2() .px_3() .bg(cx.theme().colors().editor_background) .border_t_1() .border_color(cx.theme().colors().border_variant) .size_full() .overflow_hidden() .child(self.prompt.clone()) .child(self.editor.clone()), ) } }