Detailed changes
@@ -1559,6 +1559,7 @@ dependencies = [
"serde_json",
"settings",
"smallvec",
+ "story",
"theme",
"theme_selector",
"time",
@@ -7447,6 +7448,7 @@ dependencies = [
"backtrace-on-stack-overflow",
"chrono",
"clap 4.4.4",
+ "collab_ui",
"dialoguer",
"editor",
"fuzzy",
@@ -9,6 +9,8 @@ path = "src/collab_ui.rs"
doctest = false
[features]
+default = []
+stories = ["dep:story"]
test-support = [
"call/test-support",
"client/test-support",
@@ -44,6 +46,7 @@ project = { path = "../project" }
recent_projects = { path = "../recent_projects" }
rpc = { path = "../rpc" }
settings = { path = "../settings" }
+story = { path = "../story", optional = true }
feature_flags = { path = "../feature_flags"}
theme = { path = "../theme" }
theme_selector = { path = "../theme_selector" }
@@ -1,9 +1,16 @@
+mod collab_notification;
+pub mod incoming_call_notification;
+pub mod project_shared_notification;
+
+#[cfg(feature = "stories")]
+mod stories;
+
use gpui::AppContext;
use std::sync::Arc;
use workspace::AppState;
-pub mod incoming_call_notification;
-pub mod project_shared_notification;
+#[cfg(feature = "stories")]
+pub use stories::*;
pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
incoming_call_notification::init(app_state, cx);
@@ -0,0 +1,52 @@
+use gpui::{img, prelude::*, AnyElement};
+use smallvec::SmallVec;
+use ui::prelude::*;
+
+#[derive(IntoElement)]
+pub struct CollabNotification {
+ avatar_uri: SharedString,
+ accept_button: Button,
+ dismiss_button: Button,
+ children: SmallVec<[AnyElement; 2]>,
+}
+
+impl CollabNotification {
+ pub fn new(
+ avatar_uri: impl Into<SharedString>,
+ accept_button: Button,
+ dismiss_button: Button,
+ ) -> Self {
+ Self {
+ avatar_uri: avatar_uri.into(),
+ accept_button,
+ dismiss_button,
+ children: SmallVec::new(),
+ }
+ }
+}
+
+impl ParentElement for CollabNotification {
+ fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> {
+ &mut self.children
+ }
+}
+
+impl RenderOnce for CollabNotification {
+ fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+ h_stack()
+ .text_ui()
+ .justify_between()
+ .size_full()
+ .overflow_hidden()
+ .elevation_3(cx)
+ .p_2()
+ .gap_2()
+ .child(img(self.avatar_uri).w_12().h_12().rounded_full())
+ .child(v_stack().overflow_hidden().children(self.children))
+ .child(
+ v_stack()
+ .child(self.accept_button)
+ .child(self.dismiss_button),
+ )
+ }
+}
@@ -1,15 +1,12 @@
use crate::notification_window_options;
+use crate::notifications::collab_notification::CollabNotification;
use call::{ActiveCall, IncomingCall};
use futures::StreamExt;
-use gpui::{
- img, px, AppContext, ParentElement, Render, RenderOnce, Styled, ViewContext,
- VisualContext as _, WindowHandle,
-};
+use gpui::{prelude::*, AppContext, WindowHandle};
use settings::Settings;
use std::sync::{Arc, Weak};
use theme::ThemeSettings;
-use ui::prelude::*;
-use ui::{h_stack, v_stack, Button, Label};
+use ui::{prelude::*, Button, Label};
use util::ResultExt;
use workspace::AppState;
@@ -31,8 +28,8 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
if let Some(incoming_call) = incoming_call {
let unique_screens = cx.update(|cx| cx.displays()).unwrap();
let window_size = gpui::Size {
- width: px(380.),
- height: px(64.),
+ width: px(400.),
+ height: px(72.),
};
for screen in unique_screens {
@@ -129,35 +126,22 @@ impl Render for IncomingCallNotification {
cx.set_rem_size(ui_font_size);
- h_stack()
- .font(ui_font)
- .text_ui()
- .justify_between()
- .size_full()
- .overflow_hidden()
- .elevation_3(cx)
- .p_2()
- .gap_2()
- .child(
- img(self.state.call.calling_user.avatar_uri.clone())
- .w_12()
- .h_12()
- .rounded_full(),
+ div().size_full().font(ui_font).child(
+ CollabNotification::new(
+ self.state.call.calling_user.avatar_uri.clone(),
+ Button::new("accept", "Accept").on_click({
+ let state = self.state.clone();
+ move |_, cx| state.respond(true, cx)
+ }),
+ Button::new("decline", "Decline").on_click({
+ let state = self.state.clone();
+ move |_, cx| state.respond(false, cx)
+ }),
)
.child(v_stack().overflow_hidden().child(Label::new(format!(
"{} is sharing a project in Zed",
self.state.call.calling_user.github_login
- ))))
- .child(
- v_stack()
- .child(Button::new("accept", "Accept").render(cx).on_click({
- let state = self.state.clone();
- move |_, cx| state.respond(true, cx)
- }))
- .child(Button::new("decline", "Decline").render(cx).on_click({
- let state = self.state.clone();
- move |_, cx| state.respond(false, cx)
- })),
- )
+ )))),
+ )
}
}
@@ -1,12 +1,13 @@
use crate::notification_window_options;
+use crate::notifications::collab_notification::CollabNotification;
use call::{room, ActiveCall};
use client::User;
use collections::HashMap;
-use gpui::{img, px, AppContext, ParentElement, Render, Size, Styled, ViewContext, VisualContext};
+use gpui::{AppContext, Size};
use settings::Settings;
use std::sync::{Arc, Weak};
use theme::ThemeSettings;
-use ui::{h_stack, prelude::*, v_stack, Button, Label};
+use ui::{prelude::*, Button, Label};
use workspace::AppState;
pub fn init(app_state: &Arc<AppState>, cx: &mut AppContext) {
@@ -130,51 +131,30 @@ impl Render for ProjectSharedNotification {
cx.set_rem_size(ui_font_size);
- h_stack()
- .font(ui_font)
- .text_ui()
- .justify_between()
- .size_full()
- .overflow_hidden()
- .elevation_3(cx)
- .p_2()
- .gap_2()
- .child(
- img(self.owner.avatar_uri.clone())
- .w_12()
- .h_12()
- .rounded_full(),
- )
- .child(
- v_stack()
- .overflow_hidden()
- .child(Label::new(self.owner.github_login.clone()))
- .child(Label::new(format!(
- "is sharing a project in Zed{}",
- if self.worktree_root_names.is_empty() {
- ""
- } else {
- ":"
- }
- )))
- .children(if self.worktree_root_names.is_empty() {
- None
- } else {
- Some(Label::new(self.worktree_root_names.join(", ")))
- }),
- )
- .child(
- v_stack()
- .child(Button::new("open", "Open").on_click(cx.listener(
- move |this, _event, cx| {
- this.join(cx);
- },
- )))
- .child(Button::new("dismiss", "Dismiss").on_click(cx.listener(
- move |this, _event, cx| {
- this.dismiss(cx);
- },
- ))),
+ div().size_full().font(ui_font).child(
+ CollabNotification::new(
+ self.owner.avatar_uri.clone(),
+ Button::new("open", "Open").on_click(cx.listener(move |this, _event, cx| {
+ this.join(cx);
+ })),
+ Button::new("dismiss", "Dismiss").on_click(cx.listener(move |this, _event, cx| {
+ this.dismiss(cx);
+ })),
)
+ .child(Label::new(self.owner.github_login.clone()))
+ .child(Label::new(format!(
+ "is sharing a project in Zed{}",
+ if self.worktree_root_names.is_empty() {
+ ""
+ } else {
+ ":"
+ }
+ )))
+ .children(if self.worktree_root_names.is_empty() {
+ None
+ } else {
+ Some(Label::new(self.worktree_root_names.join(", ")))
+ }),
+ )
}
}
@@ -0,0 +1,3 @@
+mod collab_notification;
+
+pub use collab_notification::*;
@@ -0,0 +1,50 @@
+use gpui::prelude::*;
+use story::{StoryContainer, StoryItem, StorySection};
+use ui::prelude::*;
+
+use crate::notifications::collab_notification::CollabNotification;
+
+pub struct CollabNotificationStory;
+
+impl Render for CollabNotificationStory {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ let window_container = |width, height| div().w(px(width)).h(px(height));
+
+ StoryContainer::new(
+ "CollabNotification Story",
+ "crates/collab_ui/src/notifications/stories/collab_notification.rs",
+ )
+ .child(
+ StorySection::new().child(StoryItem::new(
+ "Incoming Call Notification",
+ window_container(400., 72.).child(
+ CollabNotification::new(
+ "https://avatars.githubusercontent.com/u/1486634?v=4",
+ Button::new("accept", "Accept"),
+ Button::new("decline", "Decline"),
+ )
+ .child(
+ v_stack()
+ .overflow_hidden()
+ .child(Label::new("maxdeviant is sharing a project in Zed")),
+ ),
+ ),
+ )),
+ )
+ .child(
+ StorySection::new().child(StoryItem::new(
+ "Project Shared Notification",
+ window_container(400., 72.).child(
+ CollabNotification::new(
+ "https://avatars.githubusercontent.com/u/1714999?v=4",
+ Button::new("open", "Open"),
+ Button::new("dismiss", "Dismiss"),
+ )
+ .child(Label::new("iamnbutler"))
+ .child(Label::new("is sharing a project in Zed:"))
+ .child(Label::new("zed")),
+ ),
+ )),
+ )
+ }
+}
@@ -14,6 +14,7 @@ anyhow.workspace = true
backtrace-on-stack-overflow = "0.3.0"
chrono = "0.4"
clap = { version = "4.4", features = ["derive", "string"] }
+collab_ui = { path = "../collab_ui", features = ["stories"] }
strum = { version = "0.25.0", features = ["derive"] }
dialoguer = { version = "0.11.0", features = ["fuzzy-select"] }
editor = { path = "../editor" }
@@ -16,6 +16,7 @@ pub enum ComponentStory {
Avatar,
Button,
Checkbox,
+ CollabNotification,
ContextMenu,
Cursor,
Disclosure,
@@ -45,6 +46,9 @@ impl ComponentStory {
Self::Avatar => cx.new_view(|_| ui::AvatarStory).into(),
Self::Button => cx.new_view(|_| ui::ButtonStory).into(),
Self::Checkbox => cx.new_view(|_| ui::CheckboxStory).into(),
+ Self::CollabNotification => cx
+ .new_view(|_| collab_ui::notifications::CollabNotificationStory)
+ .into(),
Self::ContextMenu => cx.new_view(|_| ui::ContextMenuStory).into(),
Self::Cursor => cx.new_view(|_| crate::stories::CursorStory).into(),
Self::Disclosure => cx.new_view(|_| ui::DisclosureStory).into(),