@@ -1231,7 +1231,7 @@ impl ChatSpace {
|
|||||||
this.child(
|
this.child(
|
||||||
h_flex()
|
h_flex()
|
||||||
.id("downloading")
|
.id("downloading")
|
||||||
.px_4()
|
.px_2()
|
||||||
.h_6()
|
.h_6()
|
||||||
.gap_1()
|
.gap_1()
|
||||||
.text_xs()
|
.text_xs()
|
||||||
@@ -1434,7 +1434,7 @@ impl Render for ChatSpace {
|
|||||||
|
|
||||||
// Only render titlebar child elements if user is logged in
|
// Only render titlebar child elements if user is logged in
|
||||||
if registry.identity.is_some() {
|
if registry.identity.is_some() {
|
||||||
let profile = Registry::read_global(cx).identity(cx);
|
let profile = registry.identity(cx);
|
||||||
|
|
||||||
let left_side = self
|
let left_side = self
|
||||||
.render_titlebar_left_side(window, cx)
|
.render_titlebar_left_side(window, cx)
|
||||||
@@ -1457,9 +1457,7 @@ impl Render for ChatSpace {
|
|||||||
.relative()
|
.relative()
|
||||||
.size_full()
|
.size_full()
|
||||||
.child(
|
.child(
|
||||||
div()
|
v_flex()
|
||||||
.flex()
|
|
||||||
.flex_col()
|
|
||||||
.size_full()
|
.size_full()
|
||||||
// Title Bar
|
// Title Bar
|
||||||
.child(self.title_bar.clone())
|
.child(self.title_bar.clone())
|
||||||
|
|||||||
@@ -79,6 +79,9 @@ fn main() {
|
|||||||
|
|
||||||
// Open a window with default options
|
// Open a window with default options
|
||||||
cx.open_window(opts, |window, cx| {
|
cx.open_window(opts, |window, cx| {
|
||||||
|
// Bring the app to the foreground
|
||||||
|
cx.activate(true);
|
||||||
|
|
||||||
// Automatically sync theme with system appearance
|
// Automatically sync theme with system appearance
|
||||||
window
|
window
|
||||||
.observe_window_appearance(|window, cx| {
|
.observe_window_appearance(|window, cx| {
|
||||||
@@ -88,7 +91,6 @@ fn main() {
|
|||||||
|
|
||||||
// Root Entity
|
// Root Entity
|
||||||
cx.new(|cx| {
|
cx.new(|cx| {
|
||||||
cx.activate(true);
|
|
||||||
// Initialize the tokio runtime
|
// Initialize the tokio runtime
|
||||||
gpui_tokio::init(cx);
|
gpui_tokio::init(cx);
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use gpui::prelude::FluentBuilder;
|
|||||||
use gpui::{
|
use gpui::{
|
||||||
div, img, list, px, red, relative, rems, svg, white, Action, AnyElement, App, AppContext,
|
div, img, list, px, red, relative, rems, svg, white, Action, AnyElement, App, AppContext,
|
||||||
ClipboardItem, Context, Element, Entity, EventEmitter, Flatten, FocusHandle, Focusable,
|
ClipboardItem, Context, Element, Entity, EventEmitter, Flatten, FocusHandle, Focusable,
|
||||||
InteractiveElement, IntoElement, ListAlignment, ListState, MouseButton, ObjectFit,
|
InteractiveElement, IntoElement, ListAlignment, ListOffset, ListState, MouseButton, ObjectFit,
|
||||||
ParentElement, PathPromptOptions, Render, RetainAllImageCache, SharedString,
|
ParentElement, PathPromptOptions, Render, RetainAllImageCache, SharedString,
|
||||||
StatefulInteractiveElement, Styled, StyledImage, Subscription, Task, Window,
|
StatefulInteractiveElement, Styled, StyledImage, Subscription, Task, Window,
|
||||||
};
|
};
|
||||||
@@ -139,7 +139,7 @@ impl Chat {
|
|||||||
match signal {
|
match signal {
|
||||||
RoomSignal::NewMessage((gift_wrap_id, event)) => {
|
RoomSignal::NewMessage((gift_wrap_id, event)) => {
|
||||||
if !this.is_sent_by_coop(gift_wrap_id) {
|
if !this.is_sent_by_coop(gift_wrap_id) {
|
||||||
this.insert_message(event, cx);
|
this.insert_message(event, false, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RoomSignal::Refresh => {
|
RoomSignal::Refresh => {
|
||||||
@@ -258,11 +258,7 @@ impl Chat {
|
|||||||
|
|
||||||
cx.defer_in(window, |this, window, cx| {
|
cx.defer_in(window, |this, window, cx| {
|
||||||
// Optimistically update message list
|
// Optimistically update message list
|
||||||
this.insert_message(temp_message, cx);
|
this.insert_message(temp_message, true, cx);
|
||||||
|
|
||||||
// Scroll to reveal the new message
|
|
||||||
this.list_state
|
|
||||||
.scroll_to_reveal_item(this.messages.len() + 1);
|
|
||||||
|
|
||||||
// Remove all replies
|
// Remove all replies
|
||||||
this.remove_all_replies(cx);
|
this.remove_all_replies(cx);
|
||||||
@@ -341,7 +337,7 @@ impl Chat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Convert and insert a nostr event into the chat panel
|
/// Convert and insert a nostr event into the chat panel
|
||||||
fn insert_message<E>(&mut self, event: E, _cx: &mut Context<Self>)
|
fn insert_message<E>(&mut self, event: E, scroll: bool, cx: &mut Context<Self>)
|
||||||
where
|
where
|
||||||
E: Into<RenderedMessage>,
|
E: Into<RenderedMessage>,
|
||||||
{
|
{
|
||||||
@@ -350,13 +346,21 @@ impl Chat {
|
|||||||
// Extend the messages list with the new events
|
// Extend the messages list with the new events
|
||||||
if self.messages.insert(Message::user(event)) {
|
if self.messages.insert(Message::user(event)) {
|
||||||
self.list_state.splice(old_len..old_len, 1);
|
self.list_state.splice(old_len..old_len, 1);
|
||||||
|
|
||||||
|
if scroll {
|
||||||
|
self.list_state.scroll_to(ListOffset {
|
||||||
|
item_ix: self.list_state.item_count(),
|
||||||
|
offset_in_item: px(0.0),
|
||||||
|
});
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert and insert a vector of nostr events into the chat panel
|
/// Convert and insert a vector of nostr events into the chat panel
|
||||||
fn insert_messages(&mut self, events: Vec<Event>, cx: &mut Context<Self>) {
|
fn insert_messages(&mut self, events: Vec<Event>, cx: &mut Context<Self>) {
|
||||||
for event in events.into_iter() {
|
for event in events.into_iter() {
|
||||||
self.insert_message(event, cx);
|
self.insert_message(event, false, cx);
|
||||||
}
|
}
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -656,6 +656,7 @@ impl Render for Sidebar {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
.small()
|
.small()
|
||||||
|
.cta()
|
||||||
.bold()
|
.bold()
|
||||||
.secondary()
|
.secondary()
|
||||||
.rounded(ButtonRounded::Full)
|
.rounded(ButtonRounded::Full)
|
||||||
@@ -676,6 +677,7 @@ impl Render for Sidebar {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
.small()
|
.small()
|
||||||
|
.cta()
|
||||||
.bold()
|
.bold()
|
||||||
.secondary()
|
.secondary()
|
||||||
.rounded(ButtonRounded::Full)
|
.rounded(ButtonRounded::Full)
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use gpui::prelude::FluentBuilder as _;
|
use gpui::prelude::FluentBuilder as _;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, relative, AnyElement, App, ClickEvent, Div, ElementId, Hsla, InteractiveElement,
|
div, relative, AnyElement, App, ClickEvent, Div, ElementId, Hsla, InteractiveElement,
|
||||||
IntoElement, MouseButton, ParentElement, RenderOnce, SharedString,
|
IntoElement, MouseButton, ParentElement, RenderOnce, SharedString, Stateful,
|
||||||
StatefulInteractiveElement as _, Styled, Window,
|
StatefulInteractiveElement as _, StyleRefinement, Styled, Window,
|
||||||
};
|
};
|
||||||
use theme::ActiveTheme;
|
use theme::ActiveTheme;
|
||||||
|
|
||||||
@@ -121,8 +121,8 @@ type OnClick = Option<Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>
|
|||||||
/// A Button element.
|
/// A Button element.
|
||||||
#[derive(IntoElement)]
|
#[derive(IntoElement)]
|
||||||
pub struct Button {
|
pub struct Button {
|
||||||
pub base: Div,
|
base: Stateful<Div>,
|
||||||
id: ElementId,
|
style: StyleRefinement,
|
||||||
|
|
||||||
icon: Option<Icon>,
|
icon: Option<Icon>,
|
||||||
label: Option<SharedString>,
|
label: Option<SharedString>,
|
||||||
@@ -156,8 +156,8 @@ impl From<Button> for AnyElement {
|
|||||||
impl Button {
|
impl Button {
|
||||||
pub fn new(id: impl Into<ElementId>) -> Self {
|
pub fn new(id: impl Into<ElementId>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
base: div().flex_shrink_0(),
|
base: div().id(id.into()).flex_shrink_0(),
|
||||||
id: id.into(),
|
style: StyleRefinement::default(),
|
||||||
icon: None,
|
icon: None,
|
||||||
label: None,
|
label: None,
|
||||||
disabled: false,
|
disabled: false,
|
||||||
@@ -255,14 +255,14 @@ impl Disableable for Button {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Selectable for Button {
|
impl Selectable for Button {
|
||||||
fn element_id(&self) -> &ElementId {
|
|
||||||
&self.id
|
|
||||||
}
|
|
||||||
|
|
||||||
fn selected(mut self, selected: bool) -> Self {
|
fn selected(mut self, selected: bool) -> Self {
|
||||||
self.selected = selected;
|
self.selected = selected;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_selected(&self) -> bool {
|
||||||
|
self.selected
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sizable for Button {
|
impl Sizable for Button {
|
||||||
@@ -280,8 +280,8 @@ impl ButtonVariants for Button {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Styled for Button {
|
impl Styled for Button {
|
||||||
fn style(&mut self) -> &mut gpui::StyleRefinement {
|
fn style(&mut self) -> &mut StyleRefinement {
|
||||||
self.base.style()
|
&mut self.style
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,11 +308,11 @@ impl RenderOnce for Button {
|
|||||||
};
|
};
|
||||||
|
|
||||||
self.base
|
self.base
|
||||||
.id(self.id)
|
.flex_shrink_0()
|
||||||
.flex()
|
.flex()
|
||||||
.items_center()
|
.items_center()
|
||||||
.justify_center()
|
.justify_center()
|
||||||
.cursor_pointer()
|
.cursor_default()
|
||||||
.overflow_hidden()
|
.overflow_hidden()
|
||||||
.map(|this| match self.rounded {
|
.map(|this| match self.rounded {
|
||||||
ButtonRounded::Normal => this.rounded(cx.theme().radius),
|
ButtonRounded::Normal => this.rounded(cx.theme().radius),
|
||||||
@@ -359,6 +359,8 @@ impl RenderOnce for Button {
|
|||||||
Size::XSmall => {
|
Size::XSmall => {
|
||||||
if self.icon.is_some() {
|
if self.icon.is_some() {
|
||||||
this.h_6().pl_2().pr_2p5()
|
this.h_6().pl_2().pr_2p5()
|
||||||
|
} else if self.cta {
|
||||||
|
this.h_6().px_4()
|
||||||
} else {
|
} else {
|
||||||
this.h_6().px_2()
|
this.h_6().px_2()
|
||||||
}
|
}
|
||||||
@@ -366,6 +368,8 @@ impl RenderOnce for Button {
|
|||||||
Size::Small => {
|
Size::Small => {
|
||||||
if self.icon.is_some() {
|
if self.icon.is_some() {
|
||||||
this.h_7().pl_2().pr_2p5()
|
this.h_7().pl_2().pr_2p5()
|
||||||
|
} else if self.cta {
|
||||||
|
this.h_7().px_4()
|
||||||
} else {
|
} else {
|
||||||
this.h_7().px_2()
|
this.h_7().px_2()
|
||||||
}
|
}
|
||||||
@@ -388,10 +392,6 @@ impl RenderOnce for Button {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.text_color(normal_style.fg)
|
.text_color(normal_style.fg)
|
||||||
.when(self.selected, |this| {
|
|
||||||
let selected_style = style.selected(window, cx);
|
|
||||||
this.bg(selected_style.bg).text_color(selected_style.fg)
|
|
||||||
})
|
|
||||||
.when(!self.disabled && !self.selected, |this| {
|
.when(!self.disabled && !self.selected, |this| {
|
||||||
this.bg(normal_style.bg)
|
this.bg(normal_style.bg)
|
||||||
.hover(|this| {
|
.hover(|this| {
|
||||||
@@ -403,6 +403,10 @@ impl RenderOnce for Button {
|
|||||||
this.bg(active_style.bg).text_color(active_style.fg)
|
this.bg(active_style.bg).text_color(active_style.fg)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
.when(self.selected, |this| {
|
||||||
|
let selected_style = style.selected(window, cx);
|
||||||
|
this.bg(selected_style.bg).text_color(selected_style.fg)
|
||||||
|
})
|
||||||
.when(self.disabled, |this| {
|
.when(self.disabled, |this| {
|
||||||
let disabled_style = style.disabled(window, cx);
|
let disabled_style = style.disabled(window, cx);
|
||||||
this.cursor_not_allowed()
|
this.cursor_not_allowed()
|
||||||
@@ -410,6 +414,7 @@ impl RenderOnce for Button {
|
|||||||
.text_color(disabled_style.fg)
|
.text_color(disabled_style.fg)
|
||||||
.shadow_none()
|
.shadow_none()
|
||||||
})
|
})
|
||||||
|
.refine_style(&self.style)
|
||||||
.child({
|
.child({
|
||||||
h_flex()
|
h_flex()
|
||||||
.id("label")
|
.id("label")
|
||||||
|
|||||||
@@ -54,13 +54,13 @@ impl Disableable for Checkbox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Selectable for Checkbox {
|
impl Selectable for Checkbox {
|
||||||
fn element_id(&self) -> &ElementId {
|
|
||||||
&self.id
|
|
||||||
}
|
|
||||||
|
|
||||||
fn selected(self, selected: bool) -> Self {
|
fn selected(self, selected: bool) -> Self {
|
||||||
self.checked(selected)
|
self.checked(selected)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_selected(&self) -> bool {
|
||||||
|
self.checked
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderOnce for Checkbox {
|
impl RenderOnce for Checkbox {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ impl Indicator {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
size: Size::Small,
|
size: Size::Small,
|
||||||
speed: Duration::from_secs_f64(0.8),
|
speed: Duration::from_secs(1),
|
||||||
icon: Icon::new(IconName::Loader),
|
icon: Icon::new(IconName::Loader),
|
||||||
color: None,
|
color: None,
|
||||||
}
|
}
|
||||||
@@ -52,17 +52,15 @@ impl Sizable for Indicator {
|
|||||||
|
|
||||||
impl RenderOnce for Indicator {
|
impl RenderOnce for Indicator {
|
||||||
fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
|
fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
|
||||||
div()
|
div().child(
|
||||||
.child(
|
self.icon
|
||||||
self.icon
|
.with_size(self.size)
|
||||||
.with_size(self.size)
|
.when_some(self.color, |this, color| this.text_color(color))
|
||||||
.when_some(self.color, |this, color| this.text_color(color))
|
.with_animation(
|
||||||
.with_animation(
|
"circle",
|
||||||
"circle",
|
Animation::new(self.speed).repeat().with_easing(ease_in_out),
|
||||||
Animation::new(self.speed).repeat().with_easing(ease_in_out),
|
|this, delta| this.transform(Transformation::rotate(percentage(delta))),
|
||||||
|this, delta| this.transform(Transformation::rotate(percentage(delta))),
|
),
|
||||||
),
|
)
|
||||||
)
|
|
||||||
.into_element()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ type Suffix = Option<Box<dyn Fn(&mut Window, &mut App) -> AnyElement + 'static>>
|
|||||||
|
|
||||||
#[derive(IntoElement)]
|
#[derive(IntoElement)]
|
||||||
pub struct ListItem {
|
pub struct ListItem {
|
||||||
id: ElementId,
|
|
||||||
base: Stateful<Div>,
|
base: Stateful<Div>,
|
||||||
disabled: bool,
|
disabled: bool,
|
||||||
selected: bool,
|
selected: bool,
|
||||||
@@ -30,8 +29,8 @@ pub struct ListItem {
|
|||||||
impl ListItem {
|
impl ListItem {
|
||||||
pub fn new(id: impl Into<ElementId>) -> Self {
|
pub fn new(id: impl Into<ElementId>) -> Self {
|
||||||
let id: ElementId = id.into();
|
let id: ElementId = id.into();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
id: id.clone(),
|
|
||||||
base: h_flex().id(id).gap_x_1().py_1().px_2().text_base(),
|
base: h_flex().id(id).gap_x_1().py_1().px_2().text_base(),
|
||||||
disabled: false,
|
disabled: false,
|
||||||
selected: false,
|
selected: false,
|
||||||
@@ -104,14 +103,14 @@ impl Disableable for ListItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Selectable for ListItem {
|
impl Selectable for ListItem {
|
||||||
fn element_id(&self) -> &ElementId {
|
|
||||||
&self.id
|
|
||||||
}
|
|
||||||
|
|
||||||
fn selected(mut self, selected: bool) -> Self {
|
fn selected(mut self, selected: bool) -> Self {
|
||||||
self.selected = selected;
|
self.selected = selected;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_selected(&self) -> bool {
|
||||||
|
self.selected
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Styled for ListItem {
|
impl Styled for ListItem {
|
||||||
|
|||||||
@@ -299,7 +299,7 @@ impl Render for Notification {
|
|||||||
.border_1()
|
.border_1()
|
||||||
.border_color(cx.theme().border)
|
.border_color(cx.theme().border)
|
||||||
.bg(cx.theme().surface_background)
|
.bg(cx.theme().surface_background)
|
||||||
.rounded(cx.theme().radius)
|
.rounded(cx.theme().radius * 1.6)
|
||||||
.shadow_md()
|
.shadow_md()
|
||||||
.p_2()
|
.p_2()
|
||||||
.gap_3()
|
.gap_3()
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ pub fn init(cx: &mut App) {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait PopupMenuExt: Styled + Selectable + IntoElement + 'static {
|
pub trait PopupMenuExt: Styled + Selectable + InteractiveElement + IntoElement + 'static {
|
||||||
/// Create a popup menu with the given items, anchored to the TopLeft corner
|
/// Create a popup menu with the given items, anchored to the TopLeft corner
|
||||||
fn popup_menu(
|
fn popup_menu(
|
||||||
self,
|
self,
|
||||||
@@ -60,9 +60,9 @@ pub trait PopupMenuExt: Styled + Selectable + IntoElement + 'static {
|
|||||||
f: impl Fn(PopupMenu, &mut Window, &mut Context<PopupMenu>) -> PopupMenu + 'static,
|
f: impl Fn(PopupMenu, &mut Window, &mut Context<PopupMenu>) -> PopupMenu + 'static,
|
||||||
) -> Popover<PopupMenu> {
|
) -> Popover<PopupMenu> {
|
||||||
let style = self.style().clone();
|
let style = self.style().clone();
|
||||||
let element_id = self.element_id();
|
let id = self.interactivity().element_id.clone();
|
||||||
|
|
||||||
Popover::new(SharedString::from(format!("popup-menu:{element_id:?}")))
|
Popover::new(SharedString::from(format!("popup-menu:{id:?}")))
|
||||||
.no_style()
|
.no_style()
|
||||||
.trigger(self)
|
.trigger(self)
|
||||||
.trigger_style(style)
|
.trigger_style(style)
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
use std::fmt::{self, Display, Formatter};
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
use gpui::{
|
use gpui::{div, px, App, Axis, Div, Element, Pixels, Refineable, StyleRefinement, Styled};
|
||||||
div, px, App, Axis, Div, Element, ElementId, Pixels, Refineable, StyleRefinement, Styled,
|
|
||||||
};
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use theme::ActiveTheme;
|
use theme::ActiveTheme;
|
||||||
|
|
||||||
@@ -105,9 +103,16 @@ impl From<Pixels> for Size {
|
|||||||
|
|
||||||
/// A trait for defining element that can be selected.
|
/// A trait for defining element that can be selected.
|
||||||
pub trait Selectable: Sized {
|
pub trait Selectable: Sized {
|
||||||
fn element_id(&self) -> &ElementId;
|
|
||||||
/// Set the selected state of the element.
|
/// Set the selected state of the element.
|
||||||
fn selected(self, selected: bool) -> Self;
|
fn selected(self, selected: bool) -> Self;
|
||||||
|
|
||||||
|
/// Returns true if the element is selected.
|
||||||
|
fn is_selected(&self) -> bool;
|
||||||
|
|
||||||
|
/// Set is the element mouse right clicked, default do nothing.
|
||||||
|
fn secondary_selected(self, _: bool) -> Self {
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A trait for defining element that can be disabled.
|
/// A trait for defining element that can be disabled.
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ pub mod tab_bar;
|
|||||||
|
|
||||||
#[derive(IntoElement)]
|
#[derive(IntoElement)]
|
||||||
pub struct Tab {
|
pub struct Tab {
|
||||||
id: ElementId,
|
|
||||||
base: Stateful<Div>,
|
base: Stateful<Div>,
|
||||||
label: AnyElement,
|
label: AnyElement,
|
||||||
prefix: Option<AnyElement>,
|
prefix: Option<AnyElement>,
|
||||||
@@ -25,7 +24,6 @@ impl Tab {
|
|||||||
let id: ElementId = id.into();
|
let id: ElementId = id.into();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
id: id.clone(),
|
|
||||||
base: div().id(id),
|
base: div().id(id),
|
||||||
label: label.into_any_element(),
|
label: label.into_any_element(),
|
||||||
disabled: false,
|
disabled: false,
|
||||||
@@ -55,14 +53,14 @@ impl Tab {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Selectable for Tab {
|
impl Selectable for Tab {
|
||||||
fn element_id(&self) -> &ElementId {
|
|
||||||
&self.id
|
|
||||||
}
|
|
||||||
|
|
||||||
fn selected(mut self, selected: bool) -> Self {
|
fn selected(mut self, selected: bool) -> Self {
|
||||||
self.selected = selected;
|
self.selected = selected;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_selected(&self) -> bool {
|
||||||
|
self.selected
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InteractiveElement for Tab {
|
impl InteractiveElement for Tab {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use gpui::{
|
use gpui::{
|
||||||
div, relative, App, AppContext, Context, Entity, IntoElement, ParentElement, Render,
|
deferred, div, relative, App, AppContext, Context, Entity, IntoElement, ParentElement, Render,
|
||||||
SharedString, Styled, Window,
|
SharedString, Styled, Window,
|
||||||
};
|
};
|
||||||
use theme::ActiveTheme;
|
use theme::ActiveTheme;
|
||||||
@@ -16,7 +16,7 @@ impl Tooltip {
|
|||||||
|
|
||||||
impl Render for Tooltip {
|
impl Render for Tooltip {
|
||||||
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||||
div().child(
|
div().child(deferred(
|
||||||
div()
|
div()
|
||||||
.font_family(".SystemUIFont")
|
.font_family(".SystemUIFont")
|
||||||
.m_3()
|
.m_3()
|
||||||
@@ -30,6 +30,6 @@ impl Render for Tooltip {
|
|||||||
.text_color(cx.theme().text_muted)
|
.text_color(cx.theme().text_muted)
|
||||||
.line_height(relative(1.25))
|
.line_height(relative(1.25))
|
||||||
.child(self.text.clone()),
|
.child(self.text.clone()),
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -380,6 +380,6 @@ sidebar:
|
|||||||
|
|
||||||
loading:
|
loading:
|
||||||
label:
|
label:
|
||||||
en: "Downloading messages"
|
en: "Getting messages. This may take a while..."
|
||||||
tooltip:
|
tooltip:
|
||||||
en: "This may take a while. Please be patient."
|
en: "The progress runs in the background. It doesn't affect your experience."
|
||||||
|
|||||||
Reference in New Issue
Block a user