SSH Remoting: Fix yes/no/fingerprint prompt (#19526)
Some checks are pending
CI / Check Postgres and Protobuf migrations, mergability (push) Waiting to run
CI / Check formatting and spelling (push) Waiting to run
CI / (macOS) Run Clippy and tests (push) Waiting to run
CI / (Linux) Run Clippy and tests (push) Waiting to run
CI / (Linux) Build Remote Server (push) Waiting to run
CI / (Windows) Run Clippy and tests (push) Waiting to run
CI / Create a macOS bundle (push) Blocked by required conditions
CI / Create a Linux bundle (push) Blocked by required conditions
CI / Create arm64 Linux bundle (push) Blocked by required conditions
Deploy Docs / Deploy Docs (push) Waiting to run
Docs / Check formatting (push) Waiting to run

Release Notes:

- SSH Remoting: fix SSH fingerprint prompt

Co-authored-by: Mikayla <mikayla@zed.dev>
This commit is contained in:
Conrad Irwin 2024-10-21 15:28:22 -06:00 committed by GitHub
parent 1a4b253ee5
commit 9bae93cd39
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 111 additions and 58 deletions

2
Cargo.lock generated
View file

@ -8986,6 +8986,7 @@ dependencies = [
"itertools 0.13.0",
"language",
"log",
"markdown",
"menu",
"ordered-float 2.10.1",
"paths",
@ -9001,6 +9002,7 @@ dependencies = [
"smol",
"task",
"terminal_view",
"theme",
"ui",
"util",
"workspace",

View file

@ -76,9 +76,9 @@ use gpui::{
ClipboardItem, Context, DispatchPhase, ElementId, EventEmitter, FocusHandle, FocusOutEvent,
FocusableView, FontId, FontWeight, HighlightStyle, Hsla, InteractiveText, KeyContext,
ListSizingBehavior, Model, MouseButton, PaintQuad, ParentElement, Pixels, Render, SharedString,
Size, StrikethroughStyle, Styled, StyledText, Subscription, Task, TextStyle, UTF16Selection,
UnderlineStyle, UniformListScrollHandle, View, ViewContext, ViewInputHandler, VisualContext,
WeakFocusHandle, WeakView, WindowContext,
Size, StrikethroughStyle, Styled, StyledText, Subscription, Task, TextStyle,
TextStyleRefinement, UTF16Selection, UnderlineStyle, UniformListScrollHandle, View,
ViewContext, ViewInputHandler, VisualContext, WeakFocusHandle, WeakView, WindowContext,
};
use highlight_matching_bracket::refresh_matching_bracket_highlights;
use hover_popover::{hide_hover, HoverState};
@ -546,6 +546,7 @@ pub struct Editor {
ime_transaction: Option<TransactionId>,
active_diagnostics: Option<ActiveDiagnosticGroup>,
soft_wrap_mode_override: Option<language_settings::SoftWrap>,
project: Option<Model<Project>>,
semantics_provider: Option<Rc<dyn SemanticsProvider>>,
completion_provider: Option<Box<dyn CompletionProvider>>,
@ -615,6 +616,7 @@ pub struct Editor {
pixel_position_of_newest_cursor: Option<gpui::Point<Pixels>>,
gutter_dimensions: GutterDimensions,
style: Option<EditorStyle>,
text_style_refinement: Option<TextStyleRefinement>,
next_editor_action_id: EditorActionId,
editor_actions: Rc<RefCell<BTreeMap<EditorActionId, Box<dyn Fn(&mut ViewContext<Self>)>>>>,
use_autoclose: bool,
@ -2062,6 +2064,7 @@ impl Editor {
next_scroll_position: NextScrollCursorCenterTopBottom::default(),
addons: HashMap::default(),
_scroll_cursor_center_top_bottom_task: Task::ready(()),
text_style_refinement: None,
};
this.tasks_update_task = Some(this.refresh_runnables(cx));
this._subscriptions.extend(project_subscriptions);
@ -11180,7 +11183,12 @@ impl Editor {
cx.notify();
}
pub fn set_style(&mut self, style: EditorStyle, cx: &mut ViewContext<Self>) {
pub fn set_text_style_refinement(&mut self, style: TextStyleRefinement) {
self.text_style_refinement = Some(style);
}
/// called by the Element so we know what style we were most recently rendered with.
pub(crate) fn set_style(&mut self, style: EditorStyle, cx: &mut ViewContext<Self>) {
let rem_size = cx.rem_size();
self.display_map.update(cx, |map, cx| {
map.set_font(
@ -13676,7 +13684,7 @@ impl Render for Editor {
fn render<'a>(&mut self, cx: &mut ViewContext<'a, Self>) -> impl IntoElement {
let settings = ThemeSettings::get_global(cx);
let text_style = match self.mode {
let mut text_style = match self.mode {
EditorMode::SingleLine { .. } | EditorMode::AutoHeight { .. } => TextStyle {
color: cx.theme().colors().editor_foreground,
font_family: settings.ui_font.family.clone(),
@ -13698,6 +13706,9 @@ impl Render for Editor {
..Default::default()
},
};
if let Some(text_style_refinement) = &self.text_style_refinement {
text_style.refine(text_style_refinement)
}
let background = match self.mode {
EditorMode::SingleLine { .. } => cx.theme().system().transparent,

View file

@ -119,6 +119,10 @@ impl Markdown {
this
}
pub fn source(&self) -> &str {
&self.source
}
pub fn append(&mut self, text: &str, cx: &ViewContext<Self>) {
self.source.push_str(text);
self.parse(cx);
@ -137,10 +141,6 @@ impl Markdown {
self.parse(cx);
}
pub fn source(&self) -> &str {
&self.source
}
pub fn parsed_markdown(&self) -> &ParsedMarkdown {
&self.parsed_markdown
}

View file

@ -24,6 +24,8 @@ fuzzy.workspace = true
gpui.workspace = true
itertools.workspace = true
log.workspace = true
language.workspace = true
markdown.workspace = true
menu.workspace = true
ordered-float.workspace = true
picker.workspace = true
@ -37,6 +39,7 @@ settings.workspace = true
smol.workspace = true
task.workspace = true
terminal_view.workspace = true
theme.workspace = true
ui.workspace = true
util.workspace = true
workspace.workspace = true

View file

@ -7,15 +7,18 @@ use futures::channel::oneshot;
use gpui::{
percentage, px, Animation, AnimationExt, AnyWindowHandle, AsyncAppContext, DismissEvent,
EventEmitter, FocusableView, ParentElement as _, Render, SemanticVersion, SharedString, Task,
Transformation, View,
TextStyleRefinement, Transformation, View,
};
use gpui::{AppContext, Model};
use language::CursorShape;
use markdown::{Markdown, MarkdownStyle};
use release_channel::{AppVersion, ReleaseChannel};
use remote::{SshConnectionOptions, SshPlatform, SshRemoteClient};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
use theme::ThemeSettings;
use ui::{
div, h_flex, prelude::*, v_flex, ActiveTheme, Color, Icon, IconName, IconSize,
InteractiveElement, IntoElement, Label, LabelCommon, Styled, ViewContext, VisualContext,
@ -102,7 +105,7 @@ pub struct SshPrompt {
connection_string: SharedString,
status_message: Option<SharedString>,
error_message: Option<SharedString>,
prompt: Option<(SharedString, oneshot::Sender<Result<String>>)>,
prompt: Option<(View<Markdown>, oneshot::Sender<Result<String>>)>,
editor: View<Editor>,
}
@ -132,14 +135,34 @@ impl SshPrompt {
tx: oneshot::Sender<Result<String>>,
cx: &mut ViewContext<Self>,
) {
let theme = ThemeSettings::get_global(cx);
let mut text_style = cx.text_style();
let refinement = TextStyleRefinement {
font_family: Some(theme.buffer_font.family.clone()),
font_size: Some(theme.buffer_font_size.into()),
color: Some(cx.theme().colors().editor_foreground),
background_color: Some(gpui::transparent_black()),
..Default::default()
};
text_style.refine(&refinement);
self.editor.update(cx, |editor, cx| {
if prompt.contains("yes/no") {
editor.set_masked(false, cx);
} else {
editor.set_masked(true, cx);
}
editor.set_text_style_refinement(refinement);
editor.set_cursor_shape(CursorShape::Block, cx);
});
self.prompt = Some((prompt.into(), tx));
let markdown_style = MarkdownStyle {
base_text_style: text_style,
selection_background_color: cx.theme().players().local().selection,
..Default::default()
};
let markdown = cx.new_view(|cx| Markdown::new_text(prompt, markdown_style, None, cx, None));
self.prompt = Some((markdown, tx));
self.status_message.take();
cx.focus_view(&self.editor);
cx.notify();
@ -157,6 +180,7 @@ impl SshPrompt {
pub fn confirm(&mut self, cx: &mut ViewContext<Self>) {
if let Some((_, tx)) = self.prompt.take() {
self.status_message = Some("Connecting".into());
self.editor.update(cx, |editor, cx| {
tx.send(Ok(editor.text(cx))).ok();
editor.clear(cx);
@ -172,60 +196,73 @@ impl Render for SshPrompt {
v_flex()
.key_context("PasswordPrompt")
.size_full()
.child(
h_flex()
.p_2()
.flex()
.child(if self.error_message.is_some() {
Icon::new(IconName::XCircle)
.size(IconSize::Medium)
.color(Color::Error)
.into_any_element()
} else {
Icon::new(IconName::ArrowCircle)
.size(IconSize::Medium)
.with_animation(
"arrow-circle",
Animation::new(Duration::from_secs(2)).repeat(),
|icon, delta| {
icon.transform(Transformation::rotate(percentage(delta)))
},
)
.into_any_element()
})
.child(
div()
.ml_1()
.text_ellipsis()
.overflow_x_hidden()
.when_some(self.error_message.as_ref(), |el, error| {
el.child(Label::new(format!("{}", error)).size(LabelSize::Small))
})
.when(
self.error_message.is_none() && self.status_message.is_some(),
|el| {
el.child(
Label::new(format!(
"{}…",
self.status_message.clone().unwrap()
))
.size(LabelSize::Small),
.when(
self.error_message.is_some() || self.status_message.is_some(),
|el| {
el.child(
h_flex()
.p_2()
.flex()
.child(if self.error_message.is_some() {
Icon::new(IconName::XCircle)
.size(IconSize::Medium)
.color(Color::Error)
.into_any_element()
} else {
Icon::new(IconName::ArrowCircle)
.size(IconSize::Medium)
.with_animation(
"arrow-circle",
Animation::new(Duration::from_secs(2)).repeat(),
|icon, delta| {
icon.transform(Transformation::rotate(percentage(
delta,
)))
},
)
},
.into_any_element()
})
.child(
div()
.ml_1()
.text_ellipsis()
.overflow_x_hidden()
.when_some(self.error_message.as_ref(), |el, error| {
el.child(
Label::new(format!("{}", error)).size(LabelSize::Small),
)
})
.when(
self.error_message.is_none()
&& self.status_message.is_some(),
|el| {
el.child(
Label::new(format!(
"{}…",
self.status_message.clone().unwrap()
))
.size(LabelSize::Small),
)
},
),
),
),
)
},
)
.child(div().when_some(self.prompt.as_ref(), |el, prompt| {
.when_some(self.prompt.as_ref(), |el, prompt| {
el.child(
h_flex()
div()
.size_full()
.overflow_hidden()
.p_4()
.border_t_1()
.border_color(theme.colors().border_variant)
.font_buffer(cx)
.child(Label::new(prompt.0.clone()))
.text_buffer(cx)
.child(prompt.0.clone())
.child(self.editor.clone()),
)
}))
})
}
}

View file

@ -1202,7 +1202,7 @@ impl SshRemoteConnection {
use smol::{fs::unix::PermissionsExt as _, net::unix::UnixListener};
use util::ResultExt as _;
delegate.set_status(Some("connecting"), cx);
delegate.set_status(Some("Connecting"), cx);
let url = connection_options.ssh_url();
let temp_dir = tempfile::Builder::new()

View file

@ -79,7 +79,7 @@ pub trait StyledTypography: Styled + Sized {
///
/// This should only be used for text that is displayed in a buffer,
/// or other places that text needs to match the user's buffer font size.
fn text_buffer(self, cx: &mut WindowContext) -> Self {
fn text_buffer(self, cx: &WindowContext) -> Self {
let settings = ThemeSettings::get_global(cx);
self.text_size(settings.buffer_font_size(cx))
}