💥 Cambia renderizar por preparar componentes

This commit is contained in:
Manuel Cillero 2023-06-24 01:02:27 +02:00
parent a33de4c92b
commit a39fee9297
14 changed files with 142 additions and 41 deletions

View file

@ -1 +1,3 @@
mod before_render_component; mod before_prepare_component;
mod after_prepare_component;

View file

@ -1,19 +1,19 @@
#[macro_export] #[macro_export]
macro_rules! action_before_render_component { macro_rules! action_after_prepare_component {
( $ACTION_HANDLE:ident for $Component:ty ) => { ( $ACTION_HANDLE:ident for $Component:ty ) => {
$crate::paste! { $crate::paste! {
$crate::use_handle!($ACTION_HANDLE); $crate::use_handle!($ACTION_HANDLE);
type Action = fn(&$Component, &mut RenderContext); type Action = fn(&$Component, &mut RenderContext);
pub struct [<BeforeRender $Component>] { pub struct [<AfterPrepare $Component>] {
action: Option<Action>, action: Option<Action>,
weight: isize, weight: isize,
} }
impl ActionTrait for [<BeforeRender $Component>] { impl ActionTrait for [<AfterPrepare $Component>] {
fn new() -> Self { fn new() -> Self {
[<BeforeRender $Component>] { [<AfterPrepare $Component>] {
action: None, action: None,
weight: 0, weight: 0,
} }
@ -32,7 +32,7 @@ macro_rules! action_before_render_component {
} }
} }
impl [<BeforeRender $Component>] { impl [<AfterPrepare $Component>] {
#[allow(dead_code)] #[allow(dead_code)]
pub fn with_action(mut self, action: Action) -> Self { pub fn with_action(mut self, action: Action) -> Self {
self.action = Some(action); self.action = Some(action);
@ -53,12 +53,12 @@ macro_rules! action_before_render_component {
} }
#[inline(always)] #[inline(always)]
pub fn run_actions_before_render_component( pub fn run_actions_after_prepare_component(
component: &mut $Component, component: &mut $Component,
rcx: &mut RenderContext rcx: &mut RenderContext
) { ) {
run_actions($ACTION_HANDLE, |action| run_actions($ACTION_HANDLE, |action|
action_ref::<[<BeforeRender $Component>]>(&**action) action_ref::<[<AfterPrepare $Component>]>(&**action)
.run(component, rcx) .run(component, rcx)
); );
} }

View file

@ -0,0 +1,67 @@
#[macro_export]
macro_rules! action_before_prepare_component {
( $ACTION_HANDLE:ident for $Component:ty ) => {
$crate::paste! {
$crate::use_handle!($ACTION_HANDLE);
type Action = fn(&$Component, &mut RenderContext);
pub struct [<BeforePrepare $Component>] {
action: Option<Action>,
weight: isize,
}
impl ActionTrait for [<BeforePrepare $Component>] {
fn new() -> Self {
[<BeforePrepare $Component>] {
action: None,
weight: 0,
}
}
fn handle(&self) -> Handle {
$ACTION_HANDLE
}
fn weight(&self) -> isize {
self.weight
}
fn as_ref_any(&self) -> &dyn AnyAction {
self
}
}
impl [<BeforePrepare $Component>] {
#[allow(dead_code)]
pub fn with_action(mut self, action: Action) -> Self {
self.action = Some(action);
self
}
#[allow(dead_code)]
pub fn with_weight(mut self, weight: isize) -> Self {
self.weight = weight;
self
}
pub fn run(&self, component: &mut $Component, rcx: &mut RenderContext) {
if let Some(action) = self.action {
action(component, rcx)
}
}
}
#[inline(always)]
pub fn run_actions_before_prepare_component(
component: &mut $Component,
rcx: &mut RenderContext
) {
run_actions($ACTION_HANDLE, |action|
action_ref::<[<BeforePrepare $Component>]>(&**action)
.run(component, rcx)
);
}
}
};
}

View file

@ -2,7 +2,7 @@ use crate::prelude::*;
use_handle!(COMPONENT_BLOCK); use_handle!(COMPONENT_BLOCK);
action_before_render_component!(ACTION_BEFORE_RENDER_BLOCK for Block); action_before_prepare_component!(ACTION_BEFORE_PREPARE_BLOCK for Block);
#[rustfmt::skip] #[rustfmt::skip]
#[derive(Default)] #[derive(Default)]
@ -37,11 +37,11 @@ impl ComponentTrait for Block {
(self.renderable.check)(rcx) (self.renderable.check)(rcx)
} }
fn before_render(&mut self, rcx: &mut RenderContext) { fn before_prepare(&mut self, rcx: &mut RenderContext) {
run_actions_before_render_component(self, rcx); run_actions_before_prepare_component(self, rcx);
} }
fn default_render(&self, rcx: &mut RenderContext) -> Markup { fn prepare_component(&self, rcx: &mut RenderContext) -> Markup {
let id = rcx.required_id::<Block>(self.id()); let id = rcx.required_id::<Block>(self.id());
html! { html! {
div id=(id) class=[self.classes().get()] { div id=(id) class=[self.classes().get()] {
@ -49,7 +49,7 @@ impl ComponentTrait for Block {
h2 class="block-title" { (title) } h2 class="block-title" { (title) }
} }
div class="block-body" { div class="block-body" {
(self.components().render(rcx)) (self.components().prepare(rcx))
} }
} }
} }

View file

@ -14,7 +14,7 @@ impl ComponentTrait for Html {
COMPONENT_HTML COMPONENT_HTML
} }
fn default_render(&self, _: &mut RenderContext) -> Markup { fn prepare_component(&self, _: &mut RenderContext) -> Markup {
html! { (self.html()) } html! { (self.html()) }
} }

View file

@ -28,7 +28,7 @@ impl ComponentTrait for L10n {
COMPONENT_L10N COMPONENT_L10N
} }
fn default_render(&self, rcx: &mut RenderContext) -> Markup { fn prepare_component(&self, rcx: &mut RenderContext) -> Markup {
match self.op() { match self.op() {
L10nOp::None => html! {}, L10nOp::None => html! {},
L10nOp::Text(text) => html! { (text) }, L10nOp::Text(text) => html! { (text) },

View file

@ -116,12 +116,12 @@ impl ComponentsBundle {
// ComponentsBundle RENDER. // ComponentsBundle RENDER.
pub fn render(&self, rcx: &mut RenderContext) -> Markup { pub fn prepare(&self, rcx: &mut RenderContext) -> Markup {
let mut components = self.0.clone(); let mut components = self.0.clone();
components.sort_by_key(|c| c.read().unwrap().weight()); components.sort_by_key(|c| c.read().unwrap().weight());
html! { html! {
@for c in components.iter() { @for c in components.iter() {
(" ")(c.write().unwrap().render(rcx))(" ") (" ")(c.write().unwrap().prepare(rcx))(" ")
} }
} }
} }

View file

@ -5,7 +5,7 @@ use crate::{util, Handle};
pub use std::any::Any as AnyComponent; pub use std::any::Any as AnyComponent;
pub trait BaseComponent { pub trait BaseComponent {
fn render(&mut self, rcx: &mut RenderContext) -> Markup; fn prepare(&mut self, rcx: &mut RenderContext) -> Markup;
} }
pub trait ComponentTrait: AnyComponent + BaseComponent + Send + Sync { pub trait ComponentTrait: AnyComponent + BaseComponent + Send + Sync {
@ -37,32 +37,44 @@ pub trait ComponentTrait: AnyComponent + BaseComponent + Send + Sync {
} }
#[allow(unused_variables)] #[allow(unused_variables)]
fn before_render(&mut self, rcx: &mut RenderContext) {} fn before_prepare(&mut self, rcx: &mut RenderContext) {}
#[allow(unused_variables)] #[allow(unused_variables)]
fn default_render(&self, rcx: &mut RenderContext) -> Markup { fn prepare_component(&self, rcx: &mut RenderContext) -> Markup {
html! {} html! {}
} }
#[allow(unused_variables)]
fn after_prepare(&mut self, rcx: &mut RenderContext) {}
fn as_ref_any(&self) -> &dyn AnyComponent; fn as_ref_any(&self) -> &dyn AnyComponent;
fn as_mut_any(&mut self) -> &mut dyn AnyComponent; fn as_mut_any(&mut self) -> &mut dyn AnyComponent;
} }
impl<C: ComponentTrait> BaseComponent for C { impl<C: ComponentTrait> BaseComponent for C {
fn render(&mut self, rcx: &mut RenderContext) -> Markup { fn prepare(&mut self, rcx: &mut RenderContext) -> Markup {
// Acciones del componente antes de renderizar. if self.is_renderable(rcx) {
self.before_render(rcx); // Acciones antes de preparar el componente.
self.before_prepare(rcx);
// Acciones del tema antes de renderizar el componente. // Acciones del tema antes de preparar el componente.
rcx.theme().before_render_component(self, rcx); rcx.theme().before_prepare_component(self, rcx);
match self.is_renderable(rcx) { let markup = match rcx.theme().render_component(self, rcx) {
true => match rcx.theme().render_component(self, rcx) {
Some(html) => html, Some(html) => html,
None => self.default_render(rcx), None => self.prepare_component(rcx),
}, };
false => html! {},
// Acciones después de preparar el componente.
self.after_prepare(rcx);
// Acciones del tema después de preparar el componente.
rcx.theme().after_prepare_component(self, rcx);
markup
} else {
html! {}
} }
} }
} }

View file

@ -21,16 +21,16 @@ impl<T: ComponentTrait + Default> OneComponent<T> {
// OneComponent RENDER. // OneComponent RENDER.
pub fn render(&self, rcx: &mut RenderContext) -> Markup { pub fn prepare(&self, rcx: &mut RenderContext) -> Markup {
if let Some(component) = &self.0 { if let Some(component) = &self.0 {
return component.write().unwrap().render(rcx); return component.write().unwrap().prepare(rcx);
} }
html! {} html! {}
} }
pub fn optional_render(&self, rcx: &mut RenderContext) -> Option<Markup> { pub fn prepare_optional(&self, rcx: &mut RenderContext) -> Option<Markup> {
if let Some(component) = &self.0 { if let Some(component) = &self.0 {
let render = component.write().unwrap().render(rcx).into_string(); let render = component.write().unwrap().prepare(rcx).into_string();
if !render.trim().is_empty() { if !render.trim().is_empty() {
return Some(html! { (render) }); return Some(html! { (render) });
} }

View file

@ -80,7 +80,27 @@ pub trait ThemeTrait: ModuleTrait + Send + Sync {
#[rustfmt::skip] #[rustfmt::skip]
#[allow(unused_variables)] #[allow(unused_variables)]
fn before_render_component( fn before_prepare_component(
&self,
component: &mut dyn ComponentTrait,
rcx: &mut RenderContext,
) {
/*
Cómo usarlo:
match component.handle() {
BLOCK_COMPONENT => {
let block = component_mut::<Block>(component);
block.alter_title("New title");
},
_ => {},
}
*/
}
#[rustfmt::skip]
#[allow(unused_variables)]
fn after_prepare_component(
&self, &self,
component: &mut dyn ComponentTrait, component: &mut dyn ComponentTrait,
rcx: &mut RenderContext, rcx: &mut RenderContext,

View file

@ -30,7 +30,7 @@ pub use crate::{db, db::*, migration_item, pub_migration};
pub use crate::core::{action::*, component::*, module::*, theme::*}; pub use crate::core::{action::*, component::*, module::*, theme::*};
pub use crate::{action, action_before_render_component}; pub use crate::{action, action_after_prepare_component, action_before_prepare_component};
pub use crate::base::component::*; pub use crate::base::component::*;

View file

@ -15,7 +15,7 @@ impl ComponentTrait for Error403 {
ERROR_403 ERROR_403
} }
fn default_render(&self, _rcx: &mut RenderContext) -> Markup { fn prepare_component(&self, _rcx: &mut RenderContext) -> Markup {
html! { html! {
div { div {
h1 { ("FORBIDDEN ACCESS") } h1 { ("FORBIDDEN ACCESS") }

View file

@ -15,7 +15,7 @@ impl ComponentTrait for Error404 {
ERROR_404 ERROR_404
} }
fn default_render(&self, _rcx: &mut RenderContext) -> Markup { fn prepare_component(&self, _rcx: &mut RenderContext) -> Markup {
html! { html! {
div { div {
h1 { ("RESOURCE NOT FOUND") } h1 { ("RESOURCE NOT FOUND") }

View file

@ -121,11 +121,11 @@ impl Page {
} }
pub fn title(&mut self) -> String { pub fn title(&mut self) -> String {
self.title.render(&mut self.context).into_string() self.title.prepare(&mut self.context).into_string()
} }
pub fn description(&mut self) -> String { pub fn description(&mut self) -> String {
self.description.render(&mut self.context).into_string() self.description.prepare(&mut self.context).into_string()
} }
pub fn metadata(&self) -> &Vec<(&str, &str)> { pub fn metadata(&self) -> &Vec<(&str, &str)> {
@ -196,7 +196,7 @@ impl Page {
let render = self let render = self
.regions .regions
.get_extended_bundle(self.context.theme().single_name(), region) .get_extended_bundle(self.context.theme().single_name(), region)
.render(self.context()); .prepare(self.context());
if render.is_empty() { if render.is_empty() {
None None
} else { } else {