drawer: Render notification at the side of drawer when drawer (top, right) it opened. (#512)
This change to make sure notification will display when WebView render on the drawer. 
This commit is contained in:
parent
d051ac6a8c
commit
ea0954b425
3 changed files with 74 additions and 21 deletions
|
|
@ -292,14 +292,20 @@ impl ModalStory {
|
|||
};
|
||||
|
||||
let overlay = self.modal_overlay;
|
||||
cx.open_drawer(move |this, cx| {
|
||||
this.placement(placement)
|
||||
.overlay(overlay)
|
||||
cx.open_drawer_at(placement, move |this, cx| {
|
||||
this.overlay(overlay)
|
||||
.size(px(400.))
|
||||
.title("Drawer Title")
|
||||
.gap_4()
|
||||
.child(input.clone())
|
||||
.child(date_picker.clone())
|
||||
.child(
|
||||
Button::new("send-notification")
|
||||
.child("Test Notification")
|
||||
.on_click(|_, cx| {
|
||||
cx.push_notification("Hello this is message from Drawer.")
|
||||
}),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.border_1()
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ pub fn init(cx: &mut AppContext) {
|
|||
#[derive(IntoElement)]
|
||||
pub struct Drawer {
|
||||
pub(crate) focus_handle: FocusHandle,
|
||||
placement: Placement,
|
||||
size: DefiniteLength,
|
||||
pub(crate) placement: Placement,
|
||||
pub(crate) size: DefiniteLength,
|
||||
resizable: bool,
|
||||
on_close: Rc<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>,
|
||||
title: Option<AnyElement>,
|
||||
|
|
@ -81,17 +81,6 @@ impl Drawer {
|
|||
self
|
||||
}
|
||||
|
||||
/// Sets the placement of the drawer, default is `Placement::Right`.
|
||||
pub fn placement(mut self, placement: Placement) -> Self {
|
||||
self.placement = placement;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the placement of the drawer, default is `Placement::Right`.
|
||||
pub fn set_placement(&mut self, placement: Placement) {
|
||||
self.placement = placement;
|
||||
}
|
||||
|
||||
/// Sets whether the drawer is resizable, default is `true`.
|
||||
pub fn resizable(mut self, resizable: bool) -> Self {
|
||||
self.resizable = resizable;
|
||||
|
|
|
|||
|
|
@ -3,10 +3,12 @@ use crate::{
|
|||
modal::Modal,
|
||||
notification::{Notification, NotificationList},
|
||||
theme::ActiveTheme,
|
||||
Placement,
|
||||
};
|
||||
use gpui::{
|
||||
div, AnyView, FocusHandle, InteractiveElement, IntoElement, ParentElement as _, Render, Styled,
|
||||
View, ViewContext, VisualContext as _, WindowContext,
|
||||
canvas, div, prelude::FluentBuilder as _, AnyView, DefiniteLength, FocusHandle,
|
||||
InteractiveElement, IntoElement, ParentElement as _, Render, Styled, View, ViewContext,
|
||||
VisualContext as _, WindowContext,
|
||||
};
|
||||
use std::{
|
||||
ops::{Deref, DerefMut},
|
||||
|
|
@ -15,11 +17,16 @@ use std::{
|
|||
|
||||
/// Extension trait for [`WindowContext`] and [`ViewContext`] to add drawer functionality.
|
||||
pub trait ContextModal: Sized {
|
||||
/// Opens a Drawer.
|
||||
/// Opens a Drawer at right placement.
|
||||
fn open_drawer<F>(&mut self, build: F)
|
||||
where
|
||||
F: Fn(Drawer, &mut WindowContext) -> Drawer + 'static;
|
||||
|
||||
/// Opens a Drawer at the given placement.
|
||||
fn open_drawer_at<F>(&mut self, placement: Placement, build: F)
|
||||
where
|
||||
F: Fn(Drawer, &mut WindowContext) -> Drawer + 'static;
|
||||
|
||||
/// Return true, if there is an active Drawer.
|
||||
fn has_active_drawer(&self) -> bool;
|
||||
|
||||
|
|
@ -49,6 +56,13 @@ pub trait ContextModal: Sized {
|
|||
|
||||
impl ContextModal for WindowContext<'_> {
|
||||
fn open_drawer<F>(&mut self, build: F)
|
||||
where
|
||||
F: Fn(Drawer, &mut WindowContext) -> Drawer + 'static,
|
||||
{
|
||||
self.open_drawer_at(Placement::Right, build)
|
||||
}
|
||||
|
||||
fn open_drawer_at<F>(&mut self, placement: Placement, build: F)
|
||||
where
|
||||
F: Fn(Drawer, &mut WindowContext) -> Drawer + 'static,
|
||||
{
|
||||
|
|
@ -62,6 +76,7 @@ impl ContextModal for WindowContext<'_> {
|
|||
|
||||
root.active_drawer = Some(ActiveDrawer {
|
||||
focus_handle,
|
||||
placement,
|
||||
builder: Rc::new(build),
|
||||
});
|
||||
cx.notify();
|
||||
|
|
@ -156,6 +171,13 @@ impl<V> ContextModal for ViewContext<'_, V> {
|
|||
self.deref_mut().open_drawer(build)
|
||||
}
|
||||
|
||||
fn open_drawer_at<F>(&mut self, placement: Placement, build: F)
|
||||
where
|
||||
F: Fn(Drawer, &mut WindowContext) -> Drawer + 'static,
|
||||
{
|
||||
self.deref_mut().open_drawer_at(placement, build)
|
||||
}
|
||||
|
||||
fn has_active_modal(&self) -> bool {
|
||||
self.deref().has_active_modal()
|
||||
}
|
||||
|
|
@ -208,12 +230,14 @@ pub struct Root {
|
|||
active_drawer: Option<ActiveDrawer>,
|
||||
active_modals: Vec<ActiveModal>,
|
||||
pub notification: View<NotificationList>,
|
||||
drawer_size: Option<DefiniteLength>,
|
||||
view: AnyView,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct ActiveDrawer {
|
||||
focus_handle: FocusHandle,
|
||||
placement: Placement,
|
||||
builder: Rc<dyn Fn(Drawer, &mut WindowContext) -> Drawer + 'static>,
|
||||
}
|
||||
|
||||
|
|
@ -230,6 +254,7 @@ impl Root {
|
|||
active_drawer: None,
|
||||
active_modals: Vec::new(),
|
||||
notification: cx.new_view(NotificationList::new),
|
||||
drawer_size: None,
|
||||
view,
|
||||
}
|
||||
}
|
||||
|
|
@ -263,6 +288,14 @@ impl Root {
|
|||
}
|
||||
}
|
||||
|
||||
fn active_drawer_placement(&self, cx: &WindowContext) -> Option<Placement> {
|
||||
if let Some(drawer) = Root::read(cx).active_drawer.as_ref() {
|
||||
Some(drawer.placement)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
// Render Notification layer.
|
||||
pub fn render_notification_layer(cx: &mut WindowContext) -> Option<impl IntoElement> {
|
||||
let root = cx
|
||||
|
|
@ -271,7 +304,20 @@ impl Root {
|
|||
.and_then(|w| w.root_view(cx).ok())
|
||||
.expect("The window root view should be of type `ui::Root`.");
|
||||
|
||||
Some(div().child(root.read(cx).notification.clone()))
|
||||
let active_drawer_placement = root.read(cx).active_drawer_placement(cx);
|
||||
|
||||
let (mt, mr) = match active_drawer_placement {
|
||||
Some(Placement::Right) => (None, root.read(cx).drawer_size),
|
||||
Some(Placement::Top) => (root.read(cx).drawer_size, None),
|
||||
_ => (None, None),
|
||||
};
|
||||
|
||||
Some(
|
||||
div()
|
||||
.when_some(mt, |this, offset| this.mt(offset))
|
||||
.when_some(mr, |this, offset| this.mr(offset))
|
||||
.child(root.read(cx).notification.clone()),
|
||||
)
|
||||
}
|
||||
|
||||
/// Render the Drawer layer.
|
||||
|
|
@ -286,8 +332,20 @@ impl Root {
|
|||
let mut drawer = Drawer::new(cx);
|
||||
drawer = (active_drawer.builder)(drawer, cx);
|
||||
drawer.focus_handle = active_drawer.focus_handle.clone();
|
||||
drawer.placement = active_drawer.placement;
|
||||
|
||||
return Some(div().child(drawer));
|
||||
let drawer_size = drawer.size;
|
||||
|
||||
return Some(
|
||||
div().relative().child(drawer).child(
|
||||
canvas(
|
||||
move |_, cx| root.update(cx, |r, _| r.drawer_size = Some(drawer_size)),
|
||||
|_, _, _| {},
|
||||
)
|
||||
.absolute()
|
||||
.size_full(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
None
|
||||
|
|
|
|||
Loading…
Reference in a new issue