Detailed changes
@@ -1,11 +1,10 @@
use auto_update::{AutoUpdateStatus, AutoUpdater, DismissErrorMessage, VersionCheckType};
use editor::Editor;
-use extension_host::ExtensionStore;
+use extension_host::{ExtensionOperation, ExtensionStore};
use futures::StreamExt;
use gpui::{
- Animation, AnimationExt as _, App, Context, CursorStyle, Entity, EventEmitter,
- InteractiveElement as _, ParentElement as _, Render, SharedString, StatefulInteractiveElement,
- Styled, Transformation, Window, actions, percentage,
+ App, Context, CursorStyle, Entity, EventEmitter, InteractiveElement as _, ParentElement as _,
+ Render, SharedString, StatefulInteractiveElement, Styled, Window, actions,
};
use language::{
BinaryStatus, LanguageRegistry, LanguageServerId, LanguageServerName,
@@ -25,7 +24,10 @@ use std::{
sync::Arc,
time::{Duration, Instant},
};
-use ui::{ButtonLike, ContextMenu, PopoverMenu, PopoverMenuHandle, Tooltip, prelude::*};
+use ui::{
+ ButtonLike, CommonAnimationExt, ContextMenu, PopoverMenu, PopoverMenuHandle, Tooltip,
+ prelude::*,
+};
use util::truncate_and_trailoff;
use workspace::{StatusItemView, Workspace, item::ItemHandle};
@@ -405,13 +407,7 @@ impl ActivityIndicator {
icon: Some(
Icon::new(IconName::ArrowCircle)
.size(IconSize::Small)
- .with_animation(
- "arrow-circle",
- Animation::new(Duration::from_secs(2)).repeat(),
- |icon, delta| {
- icon.transform(Transformation::rotate(percentage(delta)))
- },
- )
+ .with_rotate_animation(2)
.into_any_element(),
),
message,
@@ -433,11 +429,7 @@ impl ActivityIndicator {
icon: Some(
Icon::new(IconName::ArrowCircle)
.size(IconSize::Small)
- .with_animation(
- "arrow-circle",
- Animation::new(Duration::from_secs(2)).repeat(),
- |icon, delta| icon.transform(Transformation::rotate(percentage(delta))),
- )
+ .with_rotate_animation(2)
.into_any_element(),
),
message: format!("Debug: {}", session.read(cx).adapter()),
@@ -460,11 +452,7 @@ impl ActivityIndicator {
icon: Some(
Icon::new(IconName::ArrowCircle)
.size(IconSize::Small)
- .with_animation(
- "arrow-circle",
- Animation::new(Duration::from_secs(2)).repeat(),
- |icon, delta| icon.transform(Transformation::rotate(percentage(delta))),
- )
+ .with_rotate_animation(2)
.into_any_element(),
),
message: job_info.message.into(),
@@ -671,8 +659,9 @@ impl ActivityIndicator {
}
// Show any application auto-update info.
- if let Some(updater) = &self.auto_updater {
- return match &updater.read(cx).status() {
+ self.auto_updater
+ .as_ref()
+ .and_then(|updater| match &updater.read(cx).status() {
AutoUpdateStatus::Checking => Some(Content {
icon: Some(
Icon::new(IconName::Download)
@@ -728,28 +717,49 @@ impl ActivityIndicator {
tooltip_message: None,
}),
AutoUpdateStatus::Idle => None,
- };
- }
-
- if let Some(extension_store) =
- ExtensionStore::try_global(cx).map(|extension_store| extension_store.read(cx))
- && let Some(extension_id) = extension_store.outstanding_operations().keys().next()
- {
- return Some(Content {
- icon: Some(
- Icon::new(IconName::Download)
- .size(IconSize::Small)
- .into_any_element(),
- ),
- message: format!("Updating {extension_id} extensionโฆ"),
- on_click: Some(Arc::new(|this, window, cx| {
- this.dismiss_error_message(&DismissErrorMessage, window, cx)
- })),
- tooltip_message: None,
- });
- }
+ })
+ .or_else(|| {
+ if let Some(extension_store) =
+ ExtensionStore::try_global(cx).map(|extension_store| extension_store.read(cx))
+ && let Some((extension_id, operation)) =
+ extension_store.outstanding_operations().iter().next()
+ {
+ let (message, icon, rotate) = match operation {
+ ExtensionOperation::Install => (
+ format!("Installing {extension_id} extensionโฆ"),
+ IconName::LoadCircle,
+ true,
+ ),
+ ExtensionOperation::Upgrade => (
+ format!("Updating {extension_id} extensionโฆ"),
+ IconName::Download,
+ false,
+ ),
+ ExtensionOperation::Remove => (
+ format!("Removing {extension_id} extensionโฆ"),
+ IconName::LoadCircle,
+ true,
+ ),
+ };
- None
+ Some(Content {
+ icon: Some(Icon::new(icon).size(IconSize::Small).map(|this| {
+ if rotate {
+ this.with_rotate_animation(3).into_any_element()
+ } else {
+ this.into_any_element()
+ }
+ })),
+ message,
+ on_click: Some(Arc::new(|this, window, cx| {
+ this.dismiss_error_message(&Default::default(), window, cx)
+ })),
+ tooltip_message: None,
+ })
+ } else {
+ None
+ }
+ })
}
fn version_tooltip_message(version: &VersionCheckType) -> String {
@@ -23,9 +23,9 @@ use gpui::{
Action, Animation, AnimationExt, AnyView, App, BorderStyle, ClickEvent, ClipboardItem,
CursorStyle, EdgesRefinement, ElementId, Empty, Entity, FocusHandle, Focusable, Hsla, Length,
ListOffset, ListState, MouseButton, PlatformDisplay, SharedString, Stateful, StyleRefinement,
- Subscription, Task, TextStyle, TextStyleRefinement, Transformation, UnderlineStyle, WeakEntity,
- Window, WindowHandle, div, ease_in_out, linear_color_stop, linear_gradient, list, percentage,
- point, prelude::*, pulsating_between,
+ Subscription, Task, TextStyle, TextStyleRefinement, UnderlineStyle, WeakEntity, Window,
+ WindowHandle, div, ease_in_out, linear_color_stop, linear_gradient, list, point, prelude::*,
+ pulsating_between,
};
use language::Buffer;
@@ -45,8 +45,8 @@ use terminal_view::terminal_panel::TerminalPanel;
use text::Anchor;
use theme::ThemeSettings;
use ui::{
- Callout, Disclosure, Divider, DividerColor, ElevationIndex, KeyBinding, PopoverMenuHandle,
- Scrollbar, ScrollbarState, SpinnerLabel, Tooltip, prelude::*,
+ Callout, CommonAnimationExt, Disclosure, Divider, DividerColor, ElevationIndex, KeyBinding,
+ PopoverMenuHandle, Scrollbar, ScrollbarState, SpinnerLabel, Tooltip, prelude::*,
};
use util::{ResultExt, size::format_file_size, time::duration_alt_display};
use workspace::{CollaboratorId, Workspace};
@@ -2515,13 +2515,7 @@ impl AcpThreadView {
Icon::new(IconName::ArrowCircle)
.size(IconSize::XSmall)
.color(Color::Info)
- .with_animation(
- "arrow-circle",
- Animation::new(Duration::from_secs(2)).repeat(),
- |icon, delta| {
- icon.transform(Transformation::rotate(percentage(delta)))
- },
- ),
+ .with_rotate_animation(2)
)
})
.child(
@@ -2948,16 +2942,7 @@ impl AcpThreadView {
Icon::new(IconName::ArrowCircle)
.size(IconSize::Small)
.color(Color::Muted)
- .with_animation(
- "arrow-circle",
- Animation::new(Duration::from_secs(2)).repeat(),
- |icon, delta| {
- icon.transform(Transformation::rotate(percentage(
- delta,
- )))
- },
- )
- .into_any_element(),
+ .with_rotate_animation(2)
)
.child(Label::new("Authenticatingโฆ").size(LabelSize::Small)),
)
@@ -3270,13 +3255,7 @@ impl AcpThreadView {
acp::PlanEntryStatus::InProgress => Icon::new(IconName::TodoProgress)
.size(IconSize::Small)
.color(Color::Accent)
- .with_animation(
- "running",
- Animation::new(Duration::from_secs(2)).repeat(),
- |icon, delta| {
- icon.transform(Transformation::rotate(percentage(delta)))
- },
- )
+ .with_rotate_animation(2)
.into_any_element(),
acp::PlanEntryStatus::Completed => Icon::new(IconName::TodoComplete)
.size(IconSize::Small)
@@ -5000,11 +4979,7 @@ fn loading_contents_spinner(size: IconSize) -> AnyElement {
Icon::new(IconName::LoadCircle)
.size(size)
.color(Color::Accent)
- .with_animation(
- "load_context_circle",
- Animation::new(Duration::from_secs(3)).repeat(),
- |icon, delta| icon.transform(Transformation::rotate(percentage(delta))),
- )
+ .with_rotate_animation(3)
.into_any_element()
}
@@ -23,9 +23,8 @@ use gpui::{
AbsoluteLength, Animation, AnimationExt, AnyElement, App, ClickEvent, ClipboardEntry,
ClipboardItem, DefiniteLength, EdgesRefinement, Empty, Entity, EventEmitter, Focusable, Hsla,
ListAlignment, ListOffset, ListState, MouseButton, PlatformDisplay, ScrollHandle, Stateful,
- StyleRefinement, Subscription, Task, TextStyle, TextStyleRefinement, Transformation,
- UnderlineStyle, WeakEntity, WindowHandle, linear_color_stop, linear_gradient, list, percentage,
- pulsating_between,
+ StyleRefinement, Subscription, Task, TextStyle, TextStyleRefinement, UnderlineStyle,
+ WeakEntity, WindowHandle, linear_color_stop, linear_gradient, list, pulsating_between,
};
use language::{Buffer, Language, LanguageRegistry};
use language_model::{
@@ -46,8 +45,8 @@ use std::time::Duration;
use text::ToPoint;
use theme::ThemeSettings;
use ui::{
- Banner, Disclosure, KeyBinding, PopoverMenuHandle, Scrollbar, ScrollbarState, TextSize,
- Tooltip, prelude::*,
+ Banner, CommonAnimationExt, Disclosure, KeyBinding, PopoverMenuHandle, Scrollbar,
+ ScrollbarState, TextSize, Tooltip, prelude::*,
};
use util::ResultExt as _;
use util::markdown::MarkdownCodeBlock;
@@ -2647,15 +2646,7 @@ impl ActiveThread {
Icon::new(IconName::ArrowCircle)
.color(Color::Accent)
.size(IconSize::Small)
- .with_animation(
- "arrow-circle",
- Animation::new(Duration::from_secs(2)).repeat(),
- |icon, delta| {
- icon.transform(Transformation::rotate(
- percentage(delta),
- ))
- },
- )
+ .with_rotate_animation(2)
}),
),
)
@@ -2831,17 +2822,11 @@ impl ActiveThread {
}
ToolUseStatus::Pending
| ToolUseStatus::InputStillStreaming
- | ToolUseStatus::Running => {
- let icon = Icon::new(IconName::ArrowCircle)
- .color(Color::Accent)
- .size(IconSize::Small);
- icon.with_animation(
- "arrow-circle",
- Animation::new(Duration::from_secs(2)).repeat(),
- |icon, delta| icon.transform(Transformation::rotate(percentage(delta))),
- )
- .into_any_element()
- }
+ | ToolUseStatus::Running => Icon::new(IconName::ArrowCircle)
+ .color(Color::Accent)
+ .size(IconSize::Small)
+ .with_rotate_animation(2)
+ .into_any_element(),
ToolUseStatus::Finished(_) => div().w_0().into_any_element(),
ToolUseStatus::Error(_) => {
let icon = Icon::new(IconName::Close)
@@ -2930,15 +2915,7 @@ impl ActiveThread {
Icon::new(IconName::ArrowCircle)
.size(IconSize::Small)
.color(Color::Accent)
- .with_animation(
- "arrow-circle",
- Animation::new(Duration::from_secs(2)).repeat(),
- |icon, delta| {
- icon.transform(Transformation::rotate(percentage(
- delta,
- )))
- },
- ),
+ .with_rotate_animation(2),
)
.child(
Label::new("Runningโฆ")
@@ -3,7 +3,7 @@ mod configure_context_server_modal;
mod manage_profiles_modal;
mod tool_picker;
-use std::{ops::Range, sync::Arc, time::Duration};
+use std::{ops::Range, sync::Arc};
use agent_servers::{AgentServerCommand, AllAgentServersSettings, CustomAgentServerSettings};
use agent_settings::AgentSettings;
@@ -17,9 +17,8 @@ use extension::ExtensionManifest;
use extension_host::ExtensionStore;
use fs::Fs;
use gpui::{
- Action, Animation, AnimationExt as _, AnyView, App, AsyncWindowContext, Corner, Entity,
- EventEmitter, FocusHandle, Focusable, Hsla, ScrollHandle, Subscription, Task, Transformation,
- WeakEntity, percentage,
+ Action, AnyView, App, AsyncWindowContext, Corner, Entity, EventEmitter, FocusHandle, Focusable,
+ Hsla, ScrollHandle, Subscription, Task, WeakEntity,
};
use language::LanguageRegistry;
use language_model::{
@@ -32,8 +31,9 @@ use project::{
};
use settings::{Settings, SettingsStore, update_settings_file};
use ui::{
- Chip, ContextMenu, Disclosure, Divider, DividerColor, ElevationIndex, Indicator, PopoverMenu,
- Scrollbar, ScrollbarState, Switch, SwitchColor, SwitchField, Tooltip, prelude::*,
+ Chip, CommonAnimationExt, ContextMenu, Disclosure, Divider, DividerColor, ElevationIndex,
+ Indicator, PopoverMenu, Scrollbar, ScrollbarState, Switch, SwitchColor, SwitchField, Tooltip,
+ prelude::*,
};
use util::ResultExt as _;
use workspace::{Workspace, create_and_open_local_file};
@@ -670,10 +670,9 @@ impl AgentConfiguration {
Icon::new(IconName::LoadCircle)
.size(IconSize::XSmall)
.color(Color::Accent)
- .with_animation(
- SharedString::from(format!("{}-starting", context_server_id.0,)),
- Animation::new(Duration::from_secs(3)).repeat(),
- |icon, delta| icon.transform(Transformation::rotate(percentage(delta))),
+ .with_keyed_rotate_animation(
+ SharedString::from(format!("{}-starting", context_server_id.0)),
+ 3,
)
.into_any_element(),
"Server is starting.",
@@ -1,16 +1,14 @@
use std::{
path::PathBuf,
sync::{Arc, Mutex},
- time::Duration,
};
use anyhow::{Context as _, Result};
use context_server::{ContextServerCommand, ContextServerId};
use editor::{Editor, EditorElement, EditorStyle};
use gpui::{
- Animation, AnimationExt as _, AsyncWindowContext, DismissEvent, Entity, EventEmitter,
- FocusHandle, Focusable, Task, TextStyle, TextStyleRefinement, Transformation, UnderlineStyle,
- WeakEntity, percentage, prelude::*,
+ AsyncWindowContext, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, Task,
+ TextStyle, TextStyleRefinement, UnderlineStyle, WeakEntity, prelude::*,
};
use language::{Language, LanguageRegistry};
use markdown::{Markdown, MarkdownElement, MarkdownStyle};
@@ -24,7 +22,9 @@ use project::{
};
use settings::{Settings as _, update_settings_file};
use theme::ThemeSettings;
-use ui::{KeyBinding, Modal, ModalFooter, ModalHeader, Section, Tooltip, prelude::*};
+use ui::{
+ CommonAnimationExt, KeyBinding, Modal, ModalFooter, ModalHeader, Section, Tooltip, prelude::*,
+};
use util::ResultExt as _;
use workspace::{ModalView, Workspace};
@@ -638,11 +638,7 @@ impl ConfigureContextServerModal {
Icon::new(IconName::ArrowCircle)
.size(IconSize::XSmall)
.color(Color::Info)
- .with_animation(
- "arrow-circle",
- Animation::new(Duration::from_secs(2)).repeat(),
- |icon, delta| icon.transform(Transformation::rotate(percentage(delta))),
- )
+ .with_rotate_animation(2)
.into_any_element(),
)
.child(
@@ -14,9 +14,8 @@ use editor::{
scroll::Autoscroll,
};
use gpui::{
- Action, Animation, AnimationExt, AnyElement, AnyView, App, AppContext, Empty, Entity,
- EventEmitter, FocusHandle, Focusable, Global, SharedString, Subscription, Task, Transformation,
- WeakEntity, Window, percentage, prelude::*,
+ Action, AnyElement, AnyView, App, AppContext, Empty, Entity, EventEmitter, FocusHandle,
+ Focusable, Global, SharedString, Subscription, Task, WeakEntity, Window, prelude::*,
};
use language::{Buffer, Capability, DiskState, OffsetRangeExt, Point};
@@ -29,9 +28,8 @@ use std::{
collections::hash_map::Entry,
ops::Range,
sync::Arc,
- time::Duration,
};
-use ui::{IconButtonShape, KeyBinding, Tooltip, prelude::*, vertical_divider};
+use ui::{CommonAnimationExt, IconButtonShape, KeyBinding, Tooltip, prelude::*, vertical_divider};
use util::ResultExt;
use workspace::{
Item, ItemHandle, ItemNavHistory, ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView,
@@ -1084,11 +1082,7 @@ impl Render for AgentDiffToolbar {
Icon::new(IconName::LoadCircle)
.size(IconSize::Small)
.color(Color::Accent)
- .with_animation(
- "load_circle",
- Animation::new(Duration::from_secs(3)).repeat(),
- |icon, delta| icon.transform(Transformation::rotate(percentage(delta))),
- ),
+ .with_rotate_animation(3),
)
.into_any();
@@ -25,8 +25,8 @@ use gpui::{
Action, Animation, AnimationExt, AnyElement, AnyView, App, ClipboardEntry, ClipboardItem,
Empty, Entity, EventEmitter, FocusHandle, Focusable, FontWeight, Global, InteractiveElement,
IntoElement, ParentElement, Pixels, Render, RenderImage, SharedString, Size,
- StatefulInteractiveElement, Styled, Subscription, Task, Transformation, WeakEntity, actions,
- div, img, percentage, point, prelude::*, pulsating_between, size,
+ StatefulInteractiveElement, Styled, Subscription, Task, WeakEntity, actions, div, img, point,
+ prelude::*, pulsating_between, size,
};
use language::{
BufferSnapshot, LspAdapterDelegate, ToOffset,
@@ -53,8 +53,8 @@ use std::{
};
use text::SelectionGoal;
use ui::{
- ButtonLike, Disclosure, ElevationIndex, KeyBinding, PopoverMenuHandle, TintColor, Tooltip,
- prelude::*,
+ ButtonLike, CommonAnimationExt, Disclosure, ElevationIndex, KeyBinding, PopoverMenuHandle,
+ TintColor, Tooltip, prelude::*,
};
use util::{ResultExt, maybe};
use workspace::{
@@ -1061,15 +1061,7 @@ impl TextThreadEditor {
Icon::new(IconName::ArrowCircle)
.size(IconSize::XSmall)
.color(Color::Info)
- .with_animation(
- "arrow-circle",
- Animation::new(Duration::from_secs(2)).repeat(),
- |icon, delta| {
- icon.transform(Transformation::rotate(
- percentage(delta),
- ))
- },
- )
+ .with_rotate_animation(2)
.into_any_element(),
);
note = Some(Self::esc_kbd(cx).into_any_element());
@@ -2790,11 +2782,7 @@ fn invoked_slash_command_fold_placeholder(
.child(Label::new(format!("/{}", command.name)))
.map(|parent| match &command.status {
InvokedSlashCommandStatus::Running(_) => {
- parent.child(Icon::new(IconName::ArrowCircle).with_animation(
- "arrow-circle",
- Animation::new(Duration::from_secs(4)).repeat(),
- |icon, delta| icon.transform(Transformation::rotate(percentage(delta))),
- ))
+ parent.child(Icon::new(IconName::ArrowCircle).with_rotate_animation(4))
}
InvokedSlashCommandStatus::Error(message) => parent.child(
Label::new(format!("error: {message}"))
@@ -1,12 +1,9 @@
-use std::{sync::Arc, time::Duration};
+use std::sync::Arc;
use client::{Client, UserStore, zed_urls};
use cloud_llm_client::Plan;
-use gpui::{
- Animation, AnimationExt, AnyElement, App, Entity, IntoElement, RenderOnce, Transformation,
- Window, percentage,
-};
-use ui::{Divider, Vector, VectorName, prelude::*};
+use gpui::{AnyElement, App, Entity, IntoElement, RenderOnce, Window};
+use ui::{CommonAnimationExt, Divider, Vector, VectorName, prelude::*};
use crate::{SignInStatus, YoungAccountBanner, plan_definitions::PlanDefinitions};
@@ -147,11 +144,7 @@ impl RenderOnce for AiUpsellCard {
rems_from_px(72.),
)
.color(Color::Custom(cx.theme().colors().text_accent.alpha(0.3)))
- .with_animation(
- "loading_stamp",
- Animation::new(Duration::from_secs(10)).repeat(),
- |this, delta| this.transform(Transformation::rotate(percentage(delta))),
- ),
+ .with_rotate_animation(10),
);
let pro_trial_stamp = div()
@@ -17,7 +17,7 @@ use editor::{
use futures::StreamExt;
use gpui::{
Animation, AnimationExt, AnyWindowHandle, App, AppContext, AsyncApp, Entity, Task,
- TextStyleRefinement, Transformation, WeakEntity, percentage, pulsating_between, px,
+ TextStyleRefinement, WeakEntity, pulsating_between, px,
};
use indoc::formatdoc;
use language::{
@@ -44,7 +44,7 @@ use std::{
time::Duration,
};
use theme::ThemeSettings;
-use ui::{Disclosure, Tooltip, prelude::*};
+use ui::{CommonAnimationExt, Disclosure, Tooltip, prelude::*};
use util::ResultExt;
use workspace::Workspace;
@@ -939,11 +939,7 @@ impl ToolCard for EditFileToolCard {
Icon::new(IconName::ArrowCircle)
.size(IconSize::XSmall)
.color(Color::Info)
- .with_animation(
- "arrow-circle",
- Animation::new(Duration::from_secs(2)).repeat(),
- |icon, delta| icon.transform(Transformation::rotate(percentage(delta))),
- ),
+ .with_rotate_animation(2),
)
})
.when_some(error_message, |header, error_message| {
@@ -8,8 +8,8 @@ use anyhow::{Context as _, Result, anyhow};
use assistant_tool::{Tool, ToolCard, ToolResult, ToolUseStatus};
use futures::{FutureExt as _, future::Shared};
use gpui::{
- Animation, AnimationExt, AnyWindowHandle, App, AppContext, Empty, Entity, EntityId, Task,
- TextStyleRefinement, Transformation, WeakEntity, Window, percentage,
+ AnyWindowHandle, App, AppContext, Empty, Entity, EntityId, Task, TextStyleRefinement,
+ WeakEntity, Window,
};
use language::LineEnding;
use language_model::{LanguageModel, LanguageModelRequest, LanguageModelToolSchemaFormat};
@@ -28,7 +28,7 @@ use std::{
};
use terminal_view::TerminalView;
use theme::ThemeSettings;
-use ui::{Disclosure, Tooltip, prelude::*};
+use ui::{CommonAnimationExt, Disclosure, Tooltip, prelude::*};
use util::{
ResultExt, get_system_shell, markdown::MarkdownInlineCode, size::format_file_size,
time::duration_alt_display,
@@ -522,11 +522,7 @@ impl ToolCard for TerminalToolCard {
Icon::new(IconName::ArrowCircle)
.size(IconSize::XSmall)
.color(Color::Info)
- .with_animation(
- "arrow-circle",
- Animation::new(Duration::from_secs(2)).repeat(),
- |icon, delta| icon.transform(Transformation::rotate(percentage(delta))),
- ),
+ .with_rotate_animation(2),
)
})
.when(tool_failed || command_failed, |header| {
@@ -1,9 +1,9 @@
-use std::{rc::Rc, time::Duration};
+use std::rc::Rc;
use collections::HashMap;
-use gpui::{Animation, AnimationExt as _, Entity, Transformation, WeakEntity, percentage};
+use gpui::{Entity, WeakEntity};
use project::debugger::session::{ThreadId, ThreadStatus};
-use ui::{ContextMenu, DropdownMenu, DropdownStyle, Indicator, prelude::*};
+use ui::{CommonAnimationExt, ContextMenu, DropdownMenu, DropdownStyle, Indicator, prelude::*};
use util::{maybe, truncate_and_trailoff};
use crate::{
@@ -152,11 +152,7 @@ impl DebugPanel {
Icon::new(IconName::ArrowCircle)
.size(IconSize::Small)
.color(Color::Muted)
- .with_animation(
- "arrow-circle",
- Animation::new(Duration::from_secs(2)).repeat(),
- |icon, delta| icon.transform(Transformation::rotate(percentage(delta))),
- )
+ .with_rotate_animation(2)
.into_any_element()
} else {
match running_state.thread_status(cx).unwrap_or_default() {
@@ -31,11 +31,11 @@ use git::{
UnstageAll,
};
use gpui::{
- Action, Animation, AnimationExt as _, AsyncApp, AsyncWindowContext, Axis, ClickEvent, Corner,
- DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, KeyContext,
- ListHorizontalSizingBehavior, ListSizingBehavior, MouseButton, MouseDownEvent, Point,
- PromptLevel, ScrollStrategy, Subscription, Task, Transformation, UniformListScrollHandle,
- WeakEntity, actions, anchored, deferred, percentage, uniform_list,
+ Action, AsyncApp, AsyncWindowContext, Axis, ClickEvent, Corner, DismissEvent, Entity,
+ EventEmitter, FocusHandle, Focusable, KeyContext, ListHorizontalSizingBehavior,
+ ListSizingBehavior, MouseButton, MouseDownEvent, Point, PromptLevel, ScrollStrategy,
+ Subscription, Task, UniformListScrollHandle, WeakEntity, actions, anchored, deferred,
+ uniform_list,
};
use itertools::Itertools;
use language::{Buffer, File};
@@ -63,8 +63,8 @@ use std::{collections::HashSet, sync::Arc, time::Duration, usize};
use strum::{IntoEnumIterator, VariantNames};
use time::OffsetDateTime;
use ui::{
- Checkbox, ContextMenu, ElevationIndex, IconPosition, Label, LabelSize, PopoverMenu, Scrollbar,
- ScrollbarState, SplitButton, Tooltip, prelude::*,
+ Checkbox, CommonAnimationExt, ContextMenu, ElevationIndex, IconPosition, Label, LabelSize,
+ PopoverMenu, Scrollbar, ScrollbarState, SplitButton, Tooltip, prelude::*,
};
use util::{ResultExt, TryFutureExt, maybe};
use workspace::SERIALIZATION_THROTTLE_TIME;
@@ -3088,13 +3088,7 @@ impl GitPanel {
Icon::new(IconName::ArrowCircle)
.size(IconSize::XSmall)
.color(Color::Info)
- .with_animation(
- "arrow-circle",
- Animation::new(Duration::from_secs(2)).repeat(),
- |icon, delta| {
- icon.transform(Transformation::rotate(percentage(delta)))
- },
- ),
+ .with_rotate_animation(2),
)
.child(
Label::new("Generating Commit...")
@@ -87,7 +87,7 @@ pub trait AnimationExt {
}
}
-impl<E> AnimationExt for E {}
+impl<E: IntoElement + 'static> AnimationExt for E {}
/// A GPUI element that applies an animation to another element
pub struct AnimationElement<E> {
@@ -14,10 +14,7 @@ use copilot::{Copilot, Status};
use futures::future::BoxFuture;
use futures::stream::BoxStream;
use futures::{FutureExt, Stream, StreamExt};
-use gpui::{
- Action, Animation, AnimationExt, AnyView, App, AsyncApp, Entity, Render, Subscription, Task,
- Transformation, percentage, svg,
-};
+use gpui::{Action, AnyView, App, AsyncApp, Entity, Render, Subscription, Task, svg};
use language::language_settings::all_language_settings;
use language_model::{
AuthenticateError, LanguageModel, LanguageModelCompletionError, LanguageModelCompletionEvent,
@@ -28,8 +25,7 @@ use language_model::{
StopReason, TokenUsage,
};
use settings::SettingsStore;
-use std::time::Duration;
-use ui::prelude::*;
+use ui::{CommonAnimationExt, prelude::*};
use util::debug_panic;
use crate::provider::x_ai::count_xai_tokens;
@@ -672,11 +668,7 @@ impl Render for ConfigurationView {
}),
)
} else {
- let loading_icon = Icon::new(IconName::ArrowCircle).with_animation(
- "arrow-circle",
- Animation::new(Duration::from_secs(4)).repeat(),
- |icon, delta| icon.transform(Transformation::rotate(percentage(delta))),
- );
+ let loading_icon = Icon::new(IconName::ArrowCircle).with_rotate_animation(4);
const ERROR_LABEL: &str = "Copilot Chat requires an active GitHub Copilot subscription. Please ensure Copilot is configured and try again, or use a different Assistant provider.";
@@ -1,5 +1,5 @@
use std::collections::BTreeSet;
-use std::{path::PathBuf, sync::Arc, time::Duration};
+use std::{path::PathBuf, sync::Arc};
use anyhow::{Context as _, Result};
use auto_update::AutoUpdater;
@@ -7,9 +7,9 @@ use editor::Editor;
use extension_host::ExtensionStore;
use futures::channel::oneshot;
use gpui::{
- Animation, AnimationExt, AnyWindowHandle, App, AsyncApp, DismissEvent, Entity, EventEmitter,
- Focusable, FontFeatures, ParentElement as _, PromptLevel, Render, SemanticVersion,
- SharedString, Task, TextStyleRefinement, Transformation, WeakEntity, percentage,
+ AnyWindowHandle, App, AsyncApp, DismissEvent, Entity, EventEmitter, Focusable, FontFeatures,
+ ParentElement as _, PromptLevel, Render, SemanticVersion, SharedString, Task,
+ TextStyleRefinement, WeakEntity,
};
use language::CursorShape;
@@ -24,8 +24,8 @@ use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources, SettingsUi};
use theme::ThemeSettings;
use ui::{
- ActiveTheme, Color, Context, Icon, IconName, IconSize, InteractiveElement, IntoElement, Label,
- LabelCommon, Styled, Window, prelude::*,
+ ActiveTheme, Color, CommonAnimationExt, Context, Icon, IconName, IconSize, InteractiveElement,
+ IntoElement, Label, LabelCommon, Styled, Window, prelude::*,
};
use util::serde::default_true;
use workspace::{AppState, ModalView, Workspace};
@@ -268,13 +268,7 @@ impl Render for RemoteConnectionPrompt {
.child(
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)))
- },
- ),
+ .with_rotate_animation(2),
)
.child(
div()
@@ -33,16 +33,13 @@
//! This module is designed to work with Jupyter message protocols,
//! interpreting and displaying various types of Jupyter output.
-use std::time::Duration;
-
use editor::{Editor, MultiBuffer};
-use gpui::{
- Animation, AnimationExt, AnyElement, ClipboardItem, Entity, Render, Transformation, WeakEntity,
- percentage,
-};
+use gpui::{AnyElement, ClipboardItem, Entity, Render, WeakEntity};
use language::Buffer;
use runtimelib::{ExecutionState, JupyterMessageContent, MimeBundle, MimeType};
-use ui::{Context, IntoElement, Styled, Tooltip, Window, div, prelude::*, v_flex};
+use ui::{
+ CommonAnimationExt, Context, IntoElement, Styled, Tooltip, Window, div, prelude::*, v_flex,
+};
mod image;
use image::ImageView;
@@ -481,11 +478,7 @@ impl Render for ExecutionView {
Icon::new(IconName::ArrowCircle)
.size(IconSize::Small)
.color(Color::Muted)
- .with_animation(
- "arrow-circle",
- Animation::new(Duration::from_secs(3)).repeat(),
- |icon, delta| icon.transform(Transformation::rotate(percentage(delta))),
- ),
+ .with_rotate_animation(3),
)
.child(Label::new("Executing...").color(Color::Muted))
.into_any_element(),
@@ -9,6 +9,7 @@ use gpui::{AnimationElement, AnyElement, Hsla, IntoElement, Rems, Transformation
pub use icon_decoration::*;
pub use icons::*;
+use crate::traits::transformable::Transformable;
use crate::{Indicator, prelude::*};
#[derive(IntoElement)]
@@ -180,8 +181,10 @@ impl Icon {
self.size = size;
self
}
+}
- pub fn transform(mut self, transformation: Transformation) -> Self {
+impl Transformable for Icon {
+ fn transform(mut self, transformation: Transformation) -> Self {
self.transformation = transformation;
self
}
@@ -7,6 +7,7 @@ use strum::{EnumIter, EnumString, IntoStaticStr};
use crate::Color;
use crate::prelude::*;
+use crate::traits::transformable::Transformable;
#[derive(
Debug, PartialEq, Eq, Copy, Clone, EnumIter, EnumString, IntoStaticStr, Serialize, Deserialize,
@@ -74,8 +75,10 @@ impl Vector {
self.size = size;
self
}
+}
- pub fn transform(mut self, transformation: Transformation) -> Self {
+impl Transformable for Vector {
+ fn transform(mut self, transformation: Transformation) -> Self {
self.transformation = transformation;
self
}
@@ -1,6 +1,8 @@
+pub mod animation_ext;
pub mod clickable;
pub mod disableable;
pub mod fixed;
pub mod styled_ext;
pub mod toggleable;
+pub mod transformable;
pub mod visible_on_hover;
@@ -0,0 +1,42 @@
+use std::time::Duration;
+
+use gpui::{Animation, AnimationElement, AnimationExt, Transformation, percentage};
+
+use crate::{prelude::*, traits::transformable::Transformable};
+
+/// An extension trait for adding common animations to animatable components.
+pub trait CommonAnimationExt: AnimationExt {
+ /// Render this component as rotating over the given duration.
+ ///
+ /// NOTE: This method uses the location of the caller to generate an ID for this state.
+ /// If this is not sufficient to identify your state (e.g. you're rendering a list item),
+ /// you can provide a custom ElementID using the `use_keyed_rotate_animation` method.
+ #[track_caller]
+ fn with_rotate_animation(self, duration: u64) -> AnimationElement<Self>
+ where
+ Self: Transformable + Sized,
+ {
+ self.with_keyed_rotate_animation(
+ ElementId::CodeLocation(*std::panic::Location::caller()),
+ duration,
+ )
+ }
+
+ /// Render this component as rotating with the given element ID over the given duration.
+ fn with_keyed_rotate_animation(
+ self,
+ id: impl Into<ElementId>,
+ duration: u64,
+ ) -> AnimationElement<Self>
+ where
+ Self: Transformable + Sized,
+ {
+ self.with_animation(
+ id,
+ Animation::new(Duration::from_secs(duration)).repeat(),
+ |component, delta| component.transform(Transformation::rotate(percentage(delta))),
+ )
+ }
+}
+
+impl<T: AnimationExt> CommonAnimationExt for T {}
@@ -0,0 +1,7 @@
+use gpui::Transformation;
+
+/// A trait for components that can be transformed.
+pub trait Transformable {
+ /// Sets the transformation for the element.
+ fn transform(self, transformation: Transformation) -> Self;
+}
@@ -17,3 +17,4 @@ pub mod utils;
pub use components::*;
pub use prelude::*;
pub use styles::*;
+pub use traits::animation_ext::*;
@@ -1,7 +1,5 @@
-use std::time::Duration;
-
use gpui::ElementId;
-use gpui::{Animation, AnimationExt, AnyElement, Entity, Transformation, percentage};
+use gpui::{AnyElement, Entity};
use picker::Picker;
use repl::{
ExecutionState, JupyterSettings, Kernel, KernelSpecification, KernelStatus, Session,
@@ -10,8 +8,8 @@ use repl::{
worktree_id_for_editor,
};
use ui::{
- ButtonLike, ContextMenu, IconWithIndicator, Indicator, IntoElement, PopoverMenu,
- PopoverMenuHandle, Tooltip, prelude::*,
+ ButtonLike, CommonAnimationExt, ContextMenu, IconWithIndicator, Indicator, IntoElement,
+ PopoverMenu, PopoverMenuHandle, Tooltip, prelude::*,
};
use util::ResultExt;
@@ -224,11 +222,7 @@ impl QuickActionBar {
.child(if menu_state.icon_is_animating {
Icon::new(menu_state.icon)
.color(menu_state.icon_color)
- .with_animation(
- "arrow-circle",
- Animation::new(Duration::from_secs(5)).repeat(),
- |icon, delta| icon.transform(Transformation::rotate(percentage(delta))),
- )
+ .with_rotate_animation(5)
.into_any_element()
} else {
IconWithIndicator::new(