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;
|
let overlay = self.modal_overlay;
|
||||||
cx.open_drawer(move |this, cx| {
|
cx.open_drawer_at(placement, move |this, cx| {
|
||||||
this.placement(placement)
|
this.overlay(overlay)
|
||||||
.overlay(overlay)
|
|
||||||
.size(px(400.))
|
.size(px(400.))
|
||||||
.title("Drawer Title")
|
.title("Drawer Title")
|
||||||
.gap_4()
|
.gap_4()
|
||||||
.child(input.clone())
|
.child(input.clone())
|
||||||
.child(date_picker.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(
|
.child(
|
||||||
div()
|
div()
|
||||||
.border_1()
|
.border_1()
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,8 @@ pub fn init(cx: &mut AppContext) {
|
||||||
#[derive(IntoElement)]
|
#[derive(IntoElement)]
|
||||||
pub struct Drawer {
|
pub struct Drawer {
|
||||||
pub(crate) focus_handle: FocusHandle,
|
pub(crate) focus_handle: FocusHandle,
|
||||||
placement: Placement,
|
pub(crate) placement: Placement,
|
||||||
size: DefiniteLength,
|
pub(crate) size: DefiniteLength,
|
||||||
resizable: bool,
|
resizable: bool,
|
||||||
on_close: Rc<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>,
|
on_close: Rc<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>,
|
||||||
title: Option<AnyElement>,
|
title: Option<AnyElement>,
|
||||||
|
|
@ -81,17 +81,6 @@ impl Drawer {
|
||||||
self
|
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`.
|
/// Sets whether the drawer is resizable, default is `true`.
|
||||||
pub fn resizable(mut self, resizable: bool) -> Self {
|
pub fn resizable(mut self, resizable: bool) -> Self {
|
||||||
self.resizable = resizable;
|
self.resizable = resizable;
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,12 @@ use crate::{
|
||||||
modal::Modal,
|
modal::Modal,
|
||||||
notification::{Notification, NotificationList},
|
notification::{Notification, NotificationList},
|
||||||
theme::ActiveTheme,
|
theme::ActiveTheme,
|
||||||
|
Placement,
|
||||||
};
|
};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, AnyView, FocusHandle, InteractiveElement, IntoElement, ParentElement as _, Render, Styled,
|
canvas, div, prelude::FluentBuilder as _, AnyView, DefiniteLength, FocusHandle,
|
||||||
View, ViewContext, VisualContext as _, WindowContext,
|
InteractiveElement, IntoElement, ParentElement as _, Render, Styled, View, ViewContext,
|
||||||
|
VisualContext as _, WindowContext,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
|
|
@ -15,11 +17,16 @@ use std::{
|
||||||
|
|
||||||
/// Extension trait for [`WindowContext`] and [`ViewContext`] to add drawer functionality.
|
/// Extension trait for [`WindowContext`] and [`ViewContext`] to add drawer functionality.
|
||||||
pub trait ContextModal: Sized {
|
pub trait ContextModal: Sized {
|
||||||
/// Opens a Drawer.
|
/// Opens a Drawer at right placement.
|
||||||
fn open_drawer<F>(&mut self, build: F)
|
fn open_drawer<F>(&mut self, build: F)
|
||||||
where
|
where
|
||||||
F: Fn(Drawer, &mut WindowContext) -> Drawer + 'static;
|
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.
|
/// Return true, if there is an active Drawer.
|
||||||
fn has_active_drawer(&self) -> bool;
|
fn has_active_drawer(&self) -> bool;
|
||||||
|
|
||||||
|
|
@ -49,6 +56,13 @@ pub trait ContextModal: Sized {
|
||||||
|
|
||||||
impl ContextModal for WindowContext<'_> {
|
impl ContextModal for WindowContext<'_> {
|
||||||
fn open_drawer<F>(&mut self, build: F)
|
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
|
where
|
||||||
F: Fn(Drawer, &mut WindowContext) -> Drawer + 'static,
|
F: Fn(Drawer, &mut WindowContext) -> Drawer + 'static,
|
||||||
{
|
{
|
||||||
|
|
@ -62,6 +76,7 @@ impl ContextModal for WindowContext<'_> {
|
||||||
|
|
||||||
root.active_drawer = Some(ActiveDrawer {
|
root.active_drawer = Some(ActiveDrawer {
|
||||||
focus_handle,
|
focus_handle,
|
||||||
|
placement,
|
||||||
builder: Rc::new(build),
|
builder: Rc::new(build),
|
||||||
});
|
});
|
||||||
cx.notify();
|
cx.notify();
|
||||||
|
|
@ -156,6 +171,13 @@ impl<V> ContextModal for ViewContext<'_, V> {
|
||||||
self.deref_mut().open_drawer(build)
|
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 {
|
fn has_active_modal(&self) -> bool {
|
||||||
self.deref().has_active_modal()
|
self.deref().has_active_modal()
|
||||||
}
|
}
|
||||||
|
|
@ -208,12 +230,14 @@ pub struct Root {
|
||||||
active_drawer: Option<ActiveDrawer>,
|
active_drawer: Option<ActiveDrawer>,
|
||||||
active_modals: Vec<ActiveModal>,
|
active_modals: Vec<ActiveModal>,
|
||||||
pub notification: View<NotificationList>,
|
pub notification: View<NotificationList>,
|
||||||
|
drawer_size: Option<DefiniteLength>,
|
||||||
view: AnyView,
|
view: AnyView,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct ActiveDrawer {
|
struct ActiveDrawer {
|
||||||
focus_handle: FocusHandle,
|
focus_handle: FocusHandle,
|
||||||
|
placement: Placement,
|
||||||
builder: Rc<dyn Fn(Drawer, &mut WindowContext) -> Drawer + 'static>,
|
builder: Rc<dyn Fn(Drawer, &mut WindowContext) -> Drawer + 'static>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -230,6 +254,7 @@ impl Root {
|
||||||
active_drawer: None,
|
active_drawer: None,
|
||||||
active_modals: Vec::new(),
|
active_modals: Vec::new(),
|
||||||
notification: cx.new_view(NotificationList::new),
|
notification: cx.new_view(NotificationList::new),
|
||||||
|
drawer_size: None,
|
||||||
view,
|
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.
|
// Render Notification layer.
|
||||||
pub fn render_notification_layer(cx: &mut WindowContext) -> Option<impl IntoElement> {
|
pub fn render_notification_layer(cx: &mut WindowContext) -> Option<impl IntoElement> {
|
||||||
let root = cx
|
let root = cx
|
||||||
|
|
@ -271,7 +304,20 @@ impl Root {
|
||||||
.and_then(|w| w.root_view(cx).ok())
|
.and_then(|w| w.root_view(cx).ok())
|
||||||
.expect("The window root view should be of type `ui::Root`.");
|
.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.
|
/// Render the Drawer layer.
|
||||||
|
|
@ -286,8 +332,20 @@ impl Root {
|
||||||
let mut drawer = Drawer::new(cx);
|
let mut drawer = Drawer::new(cx);
|
||||||
drawer = (active_drawer.builder)(drawer, cx);
|
drawer = (active_drawer.builder)(drawer, cx);
|
||||||
drawer.focus_handle = active_drawer.focus_handle.clone();
|
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
|
None
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue