@@ -54,8 +54,8 @@ use theme_settings::AgentFontSize;
use ui::{
Callout, CircularProgress, CommonAnimationExt, ContextMenu, ContextMenuEntry, CopyButton,
DecoratedIcon, DiffStat, Disclosure, Divider, DividerColor, IconDecoration, IconDecorationKind,
- KeyBinding, PopoverMenu, PopoverMenuHandle, SpinnerLabel, TintColor, Tooltip, WithScrollbar,
- prelude::*, right_click_menu,
+ KeyBinding, PopoverMenu, PopoverMenuHandle, TintColor, Tooltip, WithScrollbar, prelude::*,
+ right_click_menu,
};
use util::{ResultExt, size::format_file_size, time::duration_alt_display};
use util::{debug_panic, defer};
@@ -14,7 +14,7 @@ use gpui::{Corner, List};
use heapless::Vec as ArrayVec;
use language_model::{LanguageModelEffortLevel, Speed};
use settings::update_settings_file;
-use ui::{ButtonLike, SplitButton, SplitButtonStyle, Tab};
+use ui::{ButtonLike, SpinnerLabel, SpinnerVariant, SplitButton, SplitButtonStyle, Tab};
use workspace::SERIALIZATION_THROTTLE_TIME;
use super::*;
@@ -164,6 +164,46 @@ impl ThreadFeedbackState {
}
}
+struct GeneratingSpinner {
+ variant: SpinnerVariant,
+}
+
+impl GeneratingSpinner {
+ fn new(variant: SpinnerVariant) -> Self {
+ Self { variant }
+ }
+}
+
+impl Render for GeneratingSpinner {
+ fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
+ SpinnerLabel::with_variant(self.variant).size(LabelSize::Small)
+ }
+}
+
+#[derive(IntoElement)]
+struct GeneratingSpinnerElement {
+ variant: SpinnerVariant,
+}
+
+impl GeneratingSpinnerElement {
+ fn new(variant: SpinnerVariant) -> Self {
+ Self { variant }
+ }
+}
+
+impl RenderOnce for GeneratingSpinnerElement {
+ fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
+ let id = match self.variant {
+ SpinnerVariant::Dots => "generating-spinner-view",
+ SpinnerVariant::Sand => "confirmation-spinner-view",
+ _ => "spinner-view",
+ };
+ window.with_id(id, |window| {
+ window.use_state(cx, |_, _| GeneratingSpinner::new(self.variant))
+ })
+ }
+}
+
pub enum AcpThreadViewEvent {
FirstSendRequested { content: Vec<acp::ContentBlock> },
MessageSentOrQueued,
@@ -4275,10 +4315,10 @@ impl Render for TokenUsageTooltip {
}
impl ThreadView {
- pub(crate) fn render_entries(&mut self, cx: &mut Context<Self>) -> List {
+ fn render_entries(&mut self, cx: &mut Context<Self>) -> List {
list(
self.list_state.clone(),
- cx.processor(|this, index: usize, window, cx| {
+ cx.processor(move |this, index: usize, window, cx| {
let entries = this.thread.read(cx).entries();
if let Some(entry) = entries.get(index) {
this.render_entry(index, entries.len(), entry, window, cx)
@@ -5193,7 +5233,8 @@ impl ThreadView {
this.child(
h_flex()
.w_2()
- .child(SpinnerLabel::sand().size(LabelSize::Small)),
+ .justify_center()
+ .child(GeneratingSpinnerElement::new(SpinnerVariant::Sand)),
)
.child(
div().min_w(rems(8.)).child(
@@ -5205,7 +5246,12 @@ impl ThreadView {
} else if is_blocked_on_terminal_command {
this
} else {
- this.child(SpinnerLabel::new().size(LabelSize::Small))
+ this.child(
+ h_flex()
+ .w_2()
+ .justify_center()
+ .child(GeneratingSpinnerElement::new(SpinnerVariant::Dots)),
+ )
}
})
.when_some(elapsed_label, |this, elapsed| {