Avoid moving contacts popover during call start & add button style state
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
parent
dd02bc7748
commit
1ed47663ef
2 changed files with 114 additions and 70 deletions
|
@ -31,6 +31,12 @@ actions!(
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq)]
|
||||||
|
enum ContactsPopoverSide {
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
}
|
||||||
|
|
||||||
pub fn init(cx: &mut MutableAppContext) {
|
pub fn init(cx: &mut MutableAppContext) {
|
||||||
cx.add_action(CollabTitlebarItem::toggle_collaborator_list_popover);
|
cx.add_action(CollabTitlebarItem::toggle_collaborator_list_popover);
|
||||||
cx.add_action(CollabTitlebarItem::toggle_contacts_popover);
|
cx.add_action(CollabTitlebarItem::toggle_contacts_popover);
|
||||||
|
@ -42,6 +48,7 @@ pub struct CollabTitlebarItem {
|
||||||
workspace: WeakViewHandle<Workspace>,
|
workspace: WeakViewHandle<Workspace>,
|
||||||
user_store: ModelHandle<UserStore>,
|
user_store: ModelHandle<UserStore>,
|
||||||
contacts_popover: Option<ViewHandle<ContactsPopover>>,
|
contacts_popover: Option<ViewHandle<ContactsPopover>>,
|
||||||
|
contacts_popover_side: ContactsPopoverSide,
|
||||||
collaborator_list_popover: Option<ViewHandle<CollaboratorListPopover>>,
|
collaborator_list_popover: Option<ViewHandle<CollaboratorListPopover>>,
|
||||||
_subscriptions: Vec<Subscription>,
|
_subscriptions: Vec<Subscription>,
|
||||||
}
|
}
|
||||||
|
@ -98,8 +105,7 @@ impl View for CollabTitlebarItem {
|
||||||
right_container
|
right_container
|
||||||
.add_child(self.render_in_call_share_unshare_button(&workspace, &theme, cx));
|
.add_child(self.render_in_call_share_unshare_button(&workspace, &theme, cx));
|
||||||
} else {
|
} else {
|
||||||
right_container
|
right_container.add_child(self.render_outside_call_share_button(&theme, cx));
|
||||||
.add_child(self.render_outside_call_share_button(&workspace, &theme, cx));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
right_container.add_children(self.render_connection_status(&workspace, cx));
|
right_container.add_children(self.render_connection_status(&workspace, cx));
|
||||||
|
@ -166,6 +172,7 @@ impl CollabTitlebarItem {
|
||||||
workspace: workspace.downgrade(),
|
workspace: workspace.downgrade(),
|
||||||
user_store: user_store.clone(),
|
user_store: user_store.clone(),
|
||||||
contacts_popover: None,
|
contacts_popover: None,
|
||||||
|
contacts_popover_side: ContactsPopoverSide::Right,
|
||||||
collaborator_list_popover: None,
|
collaborator_list_popover: None,
|
||||||
_subscriptions: subscriptions,
|
_subscriptions: subscriptions,
|
||||||
}
|
}
|
||||||
|
@ -306,27 +313,31 @@ impl CollabTitlebarItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toggle_contacts_popover(&mut self, _: &ToggleContactsMenu, cx: &mut ViewContext<Self>) {
|
pub fn toggle_contacts_popover(&mut self, _: &ToggleContactsMenu, cx: &mut ViewContext<Self>) {
|
||||||
match self.contacts_popover.take() {
|
if self.contacts_popover.take().is_none() {
|
||||||
Some(_) => {}
|
if let Some(workspace) = self.workspace.upgrade(cx) {
|
||||||
None => {
|
let project = workspace.read(cx).project().clone();
|
||||||
if let Some(workspace) = self.workspace.upgrade(cx) {
|
let user_store = workspace.read(cx).user_store().clone();
|
||||||
let project = workspace.read(cx).project().clone();
|
let view = cx.add_view(|cx| ContactsPopover::new(project, user_store, cx));
|
||||||
let user_store = workspace.read(cx).user_store().clone();
|
cx.subscribe(&view, |this, _, event, cx| {
|
||||||
let view = cx.add_view(|cx| ContactsPopover::new(project, user_store, cx));
|
match event {
|
||||||
cx.subscribe(&view, |this, _, event, cx| {
|
contacts_popover::Event::Dismissed => {
|
||||||
match event {
|
this.contacts_popover = None;
|
||||||
contacts_popover::Event::Dismissed => {
|
|
||||||
this.contacts_popover = None;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cx.notify();
|
cx.notify();
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
self.contacts_popover = Some(view);
|
|
||||||
}
|
self.contacts_popover_side = match ActiveCall::global(cx).read(cx).room() {
|
||||||
|
Some(_) => ContactsPopoverSide::Left,
|
||||||
|
None => ContactsPopoverSide::Right,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.contacts_popover = Some(view);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,9 +372,11 @@ impl CollabTitlebarItem {
|
||||||
Stack::new()
|
Stack::new()
|
||||||
.with_child(
|
.with_child(
|
||||||
MouseEventHandler::<ToggleContactsMenu>::new(0, cx, |state, _| {
|
MouseEventHandler::<ToggleContactsMenu>::new(0, cx, |state, _| {
|
||||||
let style = titlebar
|
let style = titlebar.toggle_contacts_button.style_for(
|
||||||
.toggle_contacts_button
|
state,
|
||||||
.style_for(state, self.contacts_popover.is_some());
|
self.contacts_popover.is_some()
|
||||||
|
&& self.contacts_popover_side == ContactsPopoverSide::Left,
|
||||||
|
);
|
||||||
Svg::new("icons/plus_8.svg")
|
Svg::new("icons/plus_8.svg")
|
||||||
.with_color(style.color)
|
.with_color(style.color)
|
||||||
.constrained()
|
.constrained()
|
||||||
|
@ -384,20 +397,7 @@ impl CollabTitlebarItem {
|
||||||
.boxed(),
|
.boxed(),
|
||||||
)
|
)
|
||||||
.with_children(badge)
|
.with_children(badge)
|
||||||
.with_children(self.contacts_popover.as_ref().map(|popover| {
|
.with_children(self.contacts_popover_host(ContactsPopoverSide::Left, titlebar, cx))
|
||||||
Overlay::new(
|
|
||||||
ChildView::new(popover, cx)
|
|
||||||
.contained()
|
|
||||||
.with_margin_top(titlebar.height)
|
|
||||||
.with_margin_left(titlebar.toggle_contacts_button.default.button_width)
|
|
||||||
.with_margin_right(-titlebar.toggle_contacts_button.default.button_width)
|
|
||||||
.boxed(),
|
|
||||||
)
|
|
||||||
.with_fit_mode(OverlayFitMode::SwitchAnchor)
|
|
||||||
.with_anchor_corner(AnchorCorner::BottomLeft)
|
|
||||||
.with_z_index(999)
|
|
||||||
.boxed()
|
|
||||||
}))
|
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -468,33 +468,47 @@ impl CollabTitlebarItem {
|
||||||
let titlebar = &theme.workspace.titlebar;
|
let titlebar = &theme.workspace.titlebar;
|
||||||
|
|
||||||
enum ShareUnshare {}
|
enum ShareUnshare {}
|
||||||
MouseEventHandler::<ShareUnshare>::new(0, cx, |state, _| {
|
Stack::new()
|
||||||
//TODO: Ensure this button has consistant width for both text variations
|
.with_child(
|
||||||
let style = titlebar.share_button.style_for(state, false);
|
MouseEventHandler::<ShareUnshare>::new(0, cx, |state, _| {
|
||||||
Label::new(label, style.text.clone())
|
//TODO: Ensure this button has consistant width for both text variations
|
||||||
.contained()
|
let style = titlebar.share_button.style_for(
|
||||||
.with_style(style.container)
|
state,
|
||||||
.boxed()
|
self.contacts_popover.is_some()
|
||||||
})
|
&& self.contacts_popover_side == ContactsPopoverSide::Right,
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
);
|
||||||
.on_click(MouseButton::Left, move |_, cx| {
|
Label::new(label, style.text.clone())
|
||||||
if is_shared {
|
.contained()
|
||||||
cx.dispatch_action(UnshareProject);
|
.with_style(style.container)
|
||||||
} else {
|
.boxed()
|
||||||
cx.dispatch_action(ShareProject);
|
})
|
||||||
}
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
})
|
.on_click(MouseButton::Left, move |_, cx| {
|
||||||
.with_tooltip::<ShareUnshare, _>(0, tooltip.to_owned(), None, theme.tooltip.clone(), cx)
|
if is_shared {
|
||||||
.aligned()
|
cx.dispatch_action(UnshareProject);
|
||||||
.contained()
|
} else {
|
||||||
.with_margin_left(theme.workspace.titlebar.avatar_margin)
|
cx.dispatch_action(ShareProject);
|
||||||
.with_margin_right(theme.workspace.titlebar.avatar_margin)
|
}
|
||||||
.boxed()
|
})
|
||||||
|
.with_tooltip::<ShareUnshare, _>(
|
||||||
|
0,
|
||||||
|
tooltip.to_owned(),
|
||||||
|
None,
|
||||||
|
theme.tooltip.clone(),
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
.boxed(),
|
||||||
|
)
|
||||||
|
.with_children(self.contacts_popover_host(ContactsPopoverSide::Right, titlebar, cx))
|
||||||
|
.aligned()
|
||||||
|
.contained()
|
||||||
|
.with_margin_left(theme.workspace.titlebar.avatar_margin)
|
||||||
|
.with_margin_right(theme.workspace.titlebar.avatar_margin)
|
||||||
|
.boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_outside_call_share_button(
|
fn render_outside_call_share_button(
|
||||||
&self,
|
&self,
|
||||||
workspace: &ViewHandle<Workspace>,
|
|
||||||
theme: &Theme,
|
theme: &Theme,
|
||||||
cx: &mut RenderContext<Self>,
|
cx: &mut RenderContext<Self>,
|
||||||
) -> ElementBox {
|
) -> ElementBox {
|
||||||
|
@ -506,7 +520,11 @@ impl CollabTitlebarItem {
|
||||||
.with_child(
|
.with_child(
|
||||||
MouseEventHandler::<OutsideCallShare>::new(0, cx, |state, _| {
|
MouseEventHandler::<OutsideCallShare>::new(0, cx, |state, _| {
|
||||||
//TODO: Ensure this button has consistant width for both text variations
|
//TODO: Ensure this button has consistant width for both text variations
|
||||||
let style = titlebar.share_button.style_for(state, false);
|
let style = titlebar.share_button.style_for(
|
||||||
|
state,
|
||||||
|
self.contacts_popover.is_some()
|
||||||
|
&& self.contacts_popover_side == ContactsPopoverSide::Right,
|
||||||
|
);
|
||||||
Label::new("Share".to_owned(), style.text.clone())
|
Label::new("Share".to_owned(), style.text.clone())
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(style.container)
|
.with_style(style.container)
|
||||||
|
@ -525,25 +543,37 @@ impl CollabTitlebarItem {
|
||||||
)
|
)
|
||||||
.boxed(),
|
.boxed(),
|
||||||
)
|
)
|
||||||
.with_children(self.contacts_popover.as_ref().map(|popover| {
|
.with_children(self.contacts_popover_host(ContactsPopoverSide::Right, titlebar, cx))
|
||||||
|
.aligned()
|
||||||
|
.contained()
|
||||||
|
.with_margin_left(theme.workspace.titlebar.avatar_margin)
|
||||||
|
.with_margin_right(theme.workspace.titlebar.avatar_margin)
|
||||||
|
.boxed()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn contacts_popover_host<'a>(
|
||||||
|
&'a self,
|
||||||
|
side: ContactsPopoverSide,
|
||||||
|
theme: &'a theme::Titlebar,
|
||||||
|
cx: &'a RenderContext<Self>,
|
||||||
|
) -> impl Iterator<Item = ElementBox> + 'a {
|
||||||
|
self.contacts_popover
|
||||||
|
.iter()
|
||||||
|
.filter(move |_| self.contacts_popover_side == side)
|
||||||
|
.map(|popover| {
|
||||||
Overlay::new(
|
Overlay::new(
|
||||||
ChildView::new(popover, cx)
|
ChildView::new(popover, cx)
|
||||||
.contained()
|
.contained()
|
||||||
.with_margin_top(titlebar.height)
|
.with_margin_top(theme.height)
|
||||||
.with_margin_left(titlebar.toggle_contacts_button.default.button_width)
|
.with_margin_left(theme.toggle_contacts_button.default.button_width)
|
||||||
.with_margin_right(-titlebar.toggle_contacts_button.default.button_width)
|
.with_margin_right(-theme.toggle_contacts_button.default.button_width)
|
||||||
.boxed(),
|
.boxed(),
|
||||||
)
|
)
|
||||||
.with_fit_mode(OverlayFitMode::SwitchAnchor)
|
.with_fit_mode(OverlayFitMode::SwitchAnchor)
|
||||||
.with_anchor_corner(AnchorCorner::BottomLeft)
|
.with_anchor_corner(AnchorCorner::BottomLeft)
|
||||||
.with_z_index(999)
|
.with_z_index(999)
|
||||||
.boxed()
|
.boxed()
|
||||||
}))
|
})
|
||||||
.aligned()
|
|
||||||
.contained()
|
|
||||||
.with_margin_left(theme.workspace.titlebar.avatar_margin)
|
|
||||||
.with_margin_right(theme.workspace.titlebar.avatar_margin)
|
|
||||||
.boxed()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_collaborators(
|
fn render_collaborators(
|
||||||
|
|
|
@ -29,6 +29,16 @@ export default function workspace(colorScheme: ColorScheme) {
|
||||||
background: background(layer, "variant", "hovered"),
|
background: background(layer, "variant", "hovered"),
|
||||||
border: border(layer, "variant", "hovered"),
|
border: border(layer, "variant", "hovered"),
|
||||||
},
|
},
|
||||||
|
clicked: {
|
||||||
|
...text(layer, "sans", "variant", "pressed", { size: "xs" }),
|
||||||
|
background: background(layer, "variant", "pressed"),
|
||||||
|
border: border(layer, "variant", "pressed"),
|
||||||
|
},
|
||||||
|
active: {
|
||||||
|
...text(layer, "sans", "variant", "active", { size: "xs" }),
|
||||||
|
background: background(layer, "variant", "active"),
|
||||||
|
border: border(layer, "variant", "active"),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
const avatarWidth = 18;
|
const avatarWidth = 18;
|
||||||
|
|
||||||
|
@ -178,6 +188,10 @@ export default function workspace(colorScheme: ColorScheme) {
|
||||||
background: background(layer, "variant", "active"),
|
background: background(layer, "variant", "active"),
|
||||||
color: foreground(layer, "variant", "active"),
|
color: foreground(layer, "variant", "active"),
|
||||||
},
|
},
|
||||||
|
clicked: {
|
||||||
|
background: background(layer, "variant", "pressed"),
|
||||||
|
color: foreground(layer, "variant", "pressed"),
|
||||||
|
},
|
||||||
hover: {
|
hover: {
|
||||||
background: background(layer, "variant", "hovered"),
|
background: background(layer, "variant", "hovered"),
|
||||||
color: foreground(layer, "variant", "hovered"),
|
color: foreground(layer, "variant", "hovered"),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue