Render an offline icon in titlebar when connection is lost

Co-Authored-By: Max Brunsfeld <maxbrunsfeld@gmail.com>
This commit is contained in:
Nathan Sobo
2021-09-14 17:47:43 -06:00
co-authored by Max Brunsfeld
parent e212461dfe
commit 99a2dc4880
11 changed files with 102 additions and 40 deletions
+8 -8
View File
@@ -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.)
+4 -4
View File
@@ -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,
+9 -1
View File
@@ -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)]
+4 -4
View File
@@ -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)
+45 -7
View File
@@ -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.)
+13 -4
View File
@@ -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| {
+2 -2
View File
@@ -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 {