assistant panel: Animate assistant label if message is pending (#16152)

This adds a pulsating effect to the assistant header in case the message
is pending.

The pulsating effect is capped between 0.2 and 1.0 and I tried (with the
help of Claude) to give it a "breathing" effect, since I found the
normal bounce a bit too much.

Also opted for setting the `alpha` on the `LabelLike` things, vs.
overwriting the color, since I think that's cleaner instead of exposing
the color and mutating that.


https://github.com/user-attachments/assets/4a94a1c5-8dc7-4c40-b30f-d92d112db7b5


Release Notes:

- N/A
This commit is contained in:
Thorsten Ball 2024-08-13 11:41:44 +02:00 committed by GitHub
parent b36d1386a9
commit af36d4934c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 98 additions and 10 deletions

View file

@ -34,9 +34,9 @@ use editor::{
use editor::{display_map::CreaseId, FoldPlaceholder};
use fs::Fs;
use gpui::{
canvas, div, percentage, point, Action, Animation, AnimationExt, AnyElement, AnyView,
AppContext, AsyncWindowContext, ClipboardItem, Context as _, DismissEvent, Empty, Entity,
EntityId, EventEmitter, FocusHandle, FocusableView, FontWeight, InteractiveElement,
canvas, div, percentage, point, pulsating_between, Action, Animation, AnimationExt, AnyElement,
AnyView, AppContext, AsyncWindowContext, ClipboardItem, Context as _, DismissEvent, Empty,
Entity, EntityId, EventEmitter, FocusHandle, FocusableView, FontWeight, InteractiveElement,
IntoElement, Model, ParentElement, Pixels, ReadGlobal, Render, SharedString,
StatefulInteractiveElement, Styled, Subscription, Task, Transformation, UpdateGlobal, View,
ViewContext, VisualContext, WeakView, WindowContext,
@ -2953,13 +2953,38 @@ impl ContextEditor {
let context = self.context.clone();
move |cx| {
let message_id = message.id;
let show_spinner = message.role == Role::Assistant
&& message.status == MessageStatus::Pending;
let label = match message.role {
Role::User => {
Label::new("You").color(Color::Default).into_any_element()
}
Role::Assistant => {
let label = Label::new("Assistant").color(Color::Info);
if show_spinner {
label
.with_animation(
"pulsating-label",
Animation::new(Duration::from_secs(2))
.repeat()
.with_easing(pulsating_between(0.2, 1.0)),
|label, delta| label.alpha(delta),
)
.into_any_element()
} else {
label.into_any_element()
}
}
Role::System => Label::new("System")
.color(Color::Warning)
.into_any_element(),
};
let sender = ButtonLike::new("role")
.style(ButtonStyle::Filled)
.child(match message.role {
Role::User => Label::new("You").color(Color::Default),
Role::Assistant => Label::new("Assistant").color(Color::Info),
Role::System => Label::new("System").color(Color::Warning),
})
.child(label)
.tooltip(|cx| {
Tooltip::with_meta(
"Toggle message role",