use std::time::Duration;
use gpui::prelude::*;
use gpui::{div, px, Animation, AnimationExt, App, IntoElement, SharedString, Window};
use crate::devtools::Probed;
use crate::markdown::Markdown;
use crate::theme::{theme, Size};
const BLINK_MS: u64 = 900;
#[derive(IntoElement)]
pub struct AIStreamingText {
text: SharedString,
size: Size,
caret: bool,
}
impl AIStreamingText {
pub fn new(text: impl Into<SharedString>) -> Self {
AIStreamingText {
text: text.into(),
size: Size::Sm,
caret: true,
}
}
pub fn size(mut self, size: Size) -> Self {
self.size = size;
self
}
pub fn caret(mut self, caret: bool) -> Self {
self.caret = caret;
self
}
}
impl RenderOnce for AIStreamingText {
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let t = theme(cx);
let font = t.font_size(self.size);
let caret_color = t.text().hsla();
let caret = div()
.w(px(font * 0.5))
.h(px(font * 1.1))
.bg(caret_color)
.with_animation(
"guise-ai-caret",
Animation::new(Duration::from_millis(BLINK_MS)).repeat(),
|caret, delta| caret.opacity(if delta < 0.5 { 1.0 } else { 0.0 }),
);
div()
.flex()
.flex_col()
.w_full()
.child(Markdown::new(self.text).size(self.size))
.when(self.caret, |column| {
column.child(div().flex().items_center().h(px(font * 1.3)).child(caret))
})
.probe("AIStreamingText")
}
}