Detailed changes
@@ -13,7 +13,7 @@ use crate::{
Element, ElementBox, Event, EventContext, LayoutContext, PaintContext, SizeConstraint,
};
-#[derive(Clone, Debug, Default, Deserialize)]
+#[derive(Clone, Copy, Debug, Default, Deserialize)]
pub struct ContainerStyle {
#[serde(default)]
pub margin: Margin,
@@ -42,8 +42,8 @@ impl Container {
}
}
- pub fn with_style(mut self, style: &ContainerStyle) -> Self {
- self.style = style.clone();
+ pub fn with_style(mut self, style: ContainerStyle) -> Self {
+ self.style = style;
self
}
@@ -242,7 +242,7 @@ impl ToJson for ContainerStyle {
}
}
-#[derive(Clone, Debug, Default)]
+#[derive(Clone, Copy, Debug, Default)]
pub struct Margin {
pub top: f32,
pub left: f32,
@@ -269,7 +269,7 @@ impl ToJson for Margin {
}
}
-#[derive(Clone, Debug, Default)]
+#[derive(Clone, Copy, Debug, Default)]
pub struct Padding {
pub top: f32,
pub left: f32,
@@ -367,7 +367,7 @@ impl ToJson for Padding {
}
}
-#[derive(Clone, Debug, Default, Deserialize)]
+#[derive(Clone, Copy, Debug, Default, Deserialize)]
pub struct Shadow {
#[serde(default, deserialize_with = "deserialize_vec2f")]
offset: Vector2F,
@@ -111,7 +111,7 @@ impl View for Select {
mouse_state.hovered,
cx,
))
- .with_style(&style.header)
+ .with_style(style.header)
.boxed()
})
.on_click(move |cx| cx.dispatch_action(ToggleSelect))
@@ -158,7 +158,7 @@ impl View for Select {
.with_max_height(200.)
.boxed(),
)
- .with_style(&style.menu)
+ .with_style(style.menu)
.boxed(),
)
.boxed(),
@@ -0,0 +1,3 @@
+<svg width="14" height="12" viewBox="0 0 14 12" fill="none" xmlns="http://www.w3.org/2000/svg">
@@ -9,9 +9,13 @@ pane_divider = { width = 1, color = "$border.0" }
border = { width = 1, bottom = true, color = "$border.0" }
title = "$text.0"
avatar_width = 20
-icon_signed_out = "$text.2.color"
+icon_color = "$text.2.color"
avatar = { corner_radius = 10, border = { width = 1, color = "#00000088" } }
+[workspace.titlebar.offline_icon]
+padding = { right = 4 }
+width = 16
+
[workspace.tab]
text = "$text.2"
padding = { left = 10, right = 10 }
@@ -29,7 +33,7 @@ background = "$surface.1"
text = "$text.0"
[workspace.sidebar]
-width = 38
+width = 32
border = { right = true, width = 1, color = "$border.0" }
[workspace.sidebar.resize_handle]
@@ -209,7 +209,7 @@ impl ChatPanel {
Flex::column()
.with_child(
Container::new(ChildView::new(self.channel_select.id()).boxed())
- .with_style(&theme.chat_panel.channel_select.container)
+ .with_style(theme.chat_panel.channel_select.container)
.boxed(),
)
.with_child(self.render_active_channel_messages())
@@ -243,7 +243,7 @@ impl ChatPanel {
)
.boxed(),
)
- .with_style(&theme.sender.container)
+ .with_style(theme.sender.container)
.boxed(),
)
.with_child(
@@ -254,7 +254,7 @@ impl ChatPanel {
)
.boxed(),
)
- .with_style(&theme.timestamp.container)
+ .with_style(theme.timestamp.container)
.boxed(),
)
.boxed(),
@@ -262,14 +262,14 @@ impl ChatPanel {
.with_child(Text::new(message.body.clone(), theme.body.clone()).boxed())
.boxed(),
)
- .with_style(&theme.container)
+ .with_style(theme.container)
.boxed()
}
fn render_input_box(&self) -> ElementBox {
let theme = &self.settings.borrow().theme;
Container::new(ChildView::new(self.input_editor.id()).boxed())
- .with_style(&theme.chat_panel.input_editor.container)
+ .with_style(theme.chat_panel.input_editor.container)
.boxed()
}
@@ -293,13 +293,13 @@ impl ChatPanel {
Flex::row()
.with_child(
Container::new(Label::new("#".to_string(), theme.hash.text.clone()).boxed())
- .with_style(&theme.hash.container)
+ .with_style(theme.hash.container)
.boxed(),
)
.with_child(Label::new(channel.name.clone(), theme.name.clone()).boxed())
.boxed(),
)
- .with_style(&theme.container)
+ .with_style(theme.container)
.boxed()
}
@@ -387,7 +387,7 @@ impl View for ChatPanel {
};
ConstrainedBox::new(
Container::new(element)
- .with_style(&theme.chat_panel.container)
+ .with_style(theme.chat_panel.container)
.boxed(),
)
.with_min_width(150.)
@@ -88,13 +88,13 @@ impl View for FileFinder {
Flex::new(Axis::Vertical)
.with_child(
Container::new(ChildView::new(self.query_editor.id()).boxed())
- .with_style(&settings.theme.selector.input_editor.container)
+ .with_style(settings.theme.selector.input_editor.container)
.boxed(),
)
.with_child(Flexible::new(1.0, self.render_matches()).boxed())
.boxed(),
)
- .with_style(&settings.theme.selector.container)
+ .with_style(settings.theme.selector.container)
.boxed(),
)
.with_max_width(500.0)
@@ -127,7 +127,7 @@ impl FileFinder {
)
.boxed(),
)
- .with_style(&settings.theme.selector.empty.container)
+ .with_style(settings.theme.selector.empty.container)
.named("empty matches");
}
@@ -200,7 +200,7 @@ impl FileFinder {
)
.boxed(),
)
- .with_style(&style.container);
+ .with_style(style.container);
let action = Select(Entry {
worktree_id: path_match.tree_id,
@@ -48,10 +48,18 @@ pub struct Titlebar {
pub container: ContainerStyle,
pub title: TextStyle,
pub avatar_width: f32,
- pub icon_signed_out: Color,
+ pub offline_icon: OfflineIcon,
+ pub icon_color: Color,
pub avatar: ImageStyle,
}
+#[derive(Clone, Deserialize)]
+pub struct OfflineIcon {
+ #[serde(flatten)]
+ pub container: ContainerStyle,
+ pub width: f32,
+}
+
#[derive(Clone, Deserialize)]
pub struct Tab {
#[serde(flatten)]
@@ -214,7 +214,7 @@ impl ThemeSelector {
)
.boxed(),
)
- .with_style(&settings.theme.selector.empty.container)
+ .with_style(settings.theme.selector.empty.container)
.named("empty matches");
}
@@ -259,9 +259,9 @@ impl ThemeSelector {
.boxed(),
)
.with_style(if index == self.selected_index {
- &theme.selector.active_item.container
+ theme.selector.active_item.container
} else {
- &theme.selector.item.container
+ theme.selector.item.container
});
container.boxed()
@@ -288,7 +288,7 @@ impl View for ThemeSelector {
.with_child(Flexible::new(1.0, self.render_matches(cx)).boxed())
.boxed(),
)
- .with_style(&settings.theme.selector.container)
+ .with_style(settings.theme.selector.container)
.boxed(),
)
.with_max_width(600.0)
@@ -31,7 +31,6 @@ pub use pane::*;
pub use pane_group::*;
use postage::{prelude::Stream, watch};
use sidebar::{Side, Sidebar, ToggleSidebarItem};
-use smol::prelude::*;
use std::{
collections::{hash_map::Entry, HashMap, HashSet},
future::Future,
@@ -391,9 +390,14 @@ impl Workspace {
right_sidebar.add_item("icons/user-16.svg", cx.add_view(|_| ProjectBrowser).into());
let mut current_user = app_state.user_store.current_user().clone();
+ let mut connection_status = app_state.rpc.status().clone();
let _observe_current_user = cx.spawn_weak(|this, mut cx| async move {
current_user.recv().await;
- while current_user.recv().await.is_some() {
+ connection_status.recv().await;
+ let mut stream =
+ Stream::map(current_user, drop).merge(Stream::map(connection_status, drop));
+
+ while stream.recv().await.is_some() {
cx.update(|cx| {
if let Some(this) = this.upgrade(&cx) {
this.update(cx, |_, cx| cx.notify());
@@ -642,7 +646,7 @@ impl Workspace {
if let Some(load_result) = watch.borrow().as_ref() {
break load_result.clone();
}
- watch.next().await;
+ watch.recv().await;
};
this.update(&mut cx, |this, cx| {
@@ -954,7 +958,34 @@ impl Workspace {
&self.active_pane
}
- fn render_current_user(&self, cx: &mut RenderContext<Self>) -> ElementBox {
+ fn render_connection_status(&self) -> Option<ElementBox> {
+ let theme = &self.settings.borrow().theme;
+ match dbg!(&*self.rpc.status().borrow()) {
+ rpc::Status::ConnectionError
+ | rpc::Status::ConnectionLost
+ | rpc::Status::Reauthenticating
+ | rpc::Status::Reconnecting { .. }
+ | rpc::Status::ReconnectionError { .. } => Some(
+ Container::new(
+ Align::new(
+ ConstrainedBox::new(
+ Svg::new("icons/offline-14.svg")
+ .with_color(theme.workspace.titlebar.icon_color)
+ .boxed(),
+ )
+ .with_width(theme.workspace.titlebar.offline_icon.width)
+ .boxed(),
+ )
+ .boxed(),
+ )
+ .with_style(theme.workspace.titlebar.offline_icon.container)
+ .boxed(),
+ ),
+ _ => None,
+ }
+ }
+
+ fn render_avatar(&self, cx: &mut RenderContext<Self>) -> ElementBox {
let theme = &self.settings.borrow().theme;
let avatar = if let Some(avatar) = self
.user_store
@@ -969,7 +1000,7 @@ impl Workspace {
} else {
MouseEventHandler::new::<Authenticate, _, _, _>(0, cx, |_, _| {
Svg::new("icons/signed-out-12.svg")
- .with_color(theme.workspace.titlebar.icon_signed_out)
+ .with_color(theme.workspace.titlebar.icon_color)
.boxed()
})
.on_click(|cx| cx.dispatch_action(Authenticate))
@@ -1019,11 +1050,18 @@ impl View for Workspace {
.boxed(),
)
.with_child(
- Align::new(self.render_current_user(cx)).right().boxed(),
+ Align::new(
+ Flex::row()
+ .with_children(self.render_connection_status())
+ .with_child(self.render_avatar(cx))
+ .boxed(),
+ )
+ .right()
+ .boxed(),
)
.boxed(),
)
- .with_style(&theme.workspace.titlebar.container)
+ .with_style(theme.workspace.titlebar.container)
.boxed(),
)
.with_height(32.)
@@ -1,6 +1,14 @@
use super::{ItemViewHandle, SplitDirection};
use crate::settings::Settings;
-use gpui::{Border, Entity, MutableAppContext, Quad, RenderContext, View, ViewContext, ViewHandle, action, color::Color, elements::*, geometry::{rect::RectF, vector::vec2f}, keymap::Binding, platform::CursorStyle};
+use gpui::{
+ action,
+ color::Color,
+ elements::*,
+ geometry::{rect::RectF, vector::vec2f},
+ keymap::Binding,
+ platform::CursorStyle,
+ Border, Entity, MutableAppContext, Quad, RenderContext, View, ViewContext, ViewHandle,
+};
use postage::watch;
use std::{cmp, path::Path, sync::Arc};
@@ -256,7 +264,7 @@ impl Pane {
)
.boxed(),
)
- .with_style(&ContainerStyle {
+ .with_style(ContainerStyle {
margin: Margin {
left: style.spacing,
right: style.spacing,
@@ -283,7 +291,8 @@ impl Pane {
icon.with_color(style.icon_close).boxed()
}
},
- ).with_cursor_style(CursorStyle::PointingHand)
+ )
+ .with_cursor_style(CursorStyle::PointingHand)
.on_click(move |cx| {
cx.dispatch_action(CloseItem(item_id))
})
@@ -298,7 +307,7 @@ impl Pane {
)
.boxed(),
)
- .with_style(&style.container)
+ .with_style(style.container)
.boxed(),
)
.on_mouse_down(move |cx| {
@@ -113,7 +113,7 @@ impl Sidebar {
}))
.boxed(),
)
- .with_style(&theme.container)
+ .with_style(theme.container)
.boxed(),
)
.with_width(theme.width)
@@ -165,7 +165,7 @@ impl Sidebar {
let side = self.side;
MouseEventHandler::new::<Self, _, _, _>(self.side.id(), &mut cx, |_, _| {
Container::new(Empty::new().boxed())
- .with_style(&self.theme(settings).resize_handle)
+ .with_style(self.theme(settings).resize_handle)
.boxed()
})
.with_padding(Padding {