use std::{any::TypeId, sync::Arc}; use gpui::{ div, hsla, px, red, AnyView, AppContext, Component, DispatchPhase, Div, ParentElement, Render, StatelessInteractive, Styled, View, ViewContext, }; use ui::v_stack; use crate::Workspace; pub struct ModalRegistry { registered_modals: Vec<(TypeId, Box) -> Div>)>, } pub trait Modal {} #[derive(Clone)] pub struct ModalLayer { open_modal: Option, } pub fn init_modal_registry(cx: &mut AppContext) { cx.set_global(ModalRegistry { registered_modals: Vec::new(), }); } struct ToggleModal { name: String, } impl ModalRegistry { pub fn register_modal(&mut self, action: A, build_view: B) where V: Render, B: Fn(&Workspace, &mut ViewContext) -> Option> + 'static, { let build_view = Arc::new(build_view); self.registered_modals.push(( TypeId::of::(), Box::new(move |mut div| { let build_view = build_view.clone(); div.on_action( move |workspace: &mut Workspace, event: &A, phase: DispatchPhase, cx: &mut ViewContext| { if phase == DispatchPhase::Capture { return; } let Some(new_modal) = (build_view)(workspace, cx) else { return; }; workspace.modal_layer.update(cx, |modal_layer, _| { modal_layer.open_modal = Some(new_modal.into()); }); cx.notify(); }, ) }), )); } } impl ModalLayer { pub fn new() -> Self { Self { open_modal: None } } // Workspace // - ModalLayer parent // - - container // - - - modal // - - - content of the modal // - - content of the workspace // app // workspace // container some layer that contains all modals and is 100% wide and high // modal (this has a shadow, some witdht) // whatever pub fn render(&self, workspace: &Workspace, cx: &ViewContext) -> Div { let mut parent = div().relative().bg(red()).size_full(); for (_, action) in cx.global::().registered_modals.iter() { parent = (action)(parent); } parent.when_some(self.open_modal.as_ref(), |parent, open_modal| { let container1 = div() .absolute() .flex() .flex_col() .items_center() .size_full() .top_0() .left_0() .z_index(400); // transparent layer let container2 = v_stack() .bg(hsla(0.5, 0.5, 0.5, 0.5)) .h(px(0.0)) .relative() .top_20(); parent.child(container1.child(container2.child(open_modal.clone()))) }) } } // impl Render for ModalLayer { // type Element = Div; // fn render(&mut self, cx: &mut ViewContext) -> Self::Element { // let mut div = div(); // for (type_id, build_view) in cx.global::().registered_modals { // div = div.useful_on_action( // type_id, // Box::new(|this, _: dyn Any, phase, cx: &mut ViewContext| { // if phase == DispatchPhase::Capture { // return; // } // self.workspace.update(cx, |workspace, cx| { // self.open_modal = Some(build_view(workspace, cx)); // }); // cx.notify(); // }), // ) // } // div // } // }