⚡️ (core): Registro de acciones inmutable

This commit is contained in:
Manuel Cillero 2026-09-26 00:56:30 +02:00
parent 5b2ddeb6cc
commit 58d1fef4f1
15 changed files with 624 additions and 244 deletions

View file

@ -5,19 +5,14 @@ use super::FnActionWithComponent;
/// Ejecuta [`FnActionWithComponent`] después de renderizar un componente.
pub struct AfterRender<C: Component> {
f: FnActionWithComponent<C>,
referer_type_id: Option<UniqueId>,
referer_id: Option<String>,
referer: ActionReferer,
weight: Weight,
}
// Filtro para despachar `FnActionWithComponent` después de renderizar un componente `C`.
impl<C: Component> ActionDispatcher for AfterRender<C> {
fn referer_type_id(&self) -> Option<UniqueId> {
self.referer_type_id
}
fn referer_id(&self) -> Option<String> {
self.referer_id.clone()
fn referer(&self) -> Option<&ActionReferer> {
Some(&self.referer)
}
fn weight(&self) -> Weight {
@ -30,8 +25,7 @@ impl<C: Component> AfterRender<C> {
pub fn new(f: FnActionWithComponent<C>) -> Self {
AfterRender {
f,
referer_type_id: Some(UniqueId::of::<C>()),
referer_id: None,
referer: ActionReferer::of::<C>(),
weight: 0,
}
}
@ -39,7 +33,7 @@ impl<C: Component> AfterRender<C> {
/// Afina el registro para ejecutar la acción [`FnActionWithComponent`] sólo para el componente
/// `C` con identificador `id`.
pub fn filter_by_referer_id(mut self, id: impl AsRef<str>) -> Self {
self.referer_id = util::normalize_token(id);
self.referer = self.referer.with_id(id);
self
}
@ -52,18 +46,6 @@ impl<C: Component> AfterRender<C> {
/// Despacha las acciones.
#[inline]
pub(crate) fn dispatch(component: &mut C, cx: &mut Context) {
// Primero despacha las acciones para el tipo de componente.
dispatch_actions(
&ActionKey::new(UniqueId::of::<Self>(), Some(UniqueId::of::<C>()), None),
|action: &Self| (action.f)(component, cx),
);
// Y luego despacha las acciones para el tipo de componente con un identificador dado.
if let Some(id) = component.id() {
dispatch_actions(
&ActionKey::new(UniqueId::of::<Self>(), Some(UniqueId::of::<C>()), Some(id)),
|action: &Self| (action.f)(component, cx),
);
}
dispatch_referer(component, |c| c.id(), |action: &Self, c| (action.f)(c, cx));
}
}

View file

@ -5,19 +5,14 @@ use super::FnActionWithComponent;
/// Ejecuta [`FnActionWithComponent`] antes de renderizar el componente.
pub struct BeforeRender<C: Component> {
f: FnActionWithComponent<C>,
referer_type_id: Option<UniqueId>,
referer_id: Option<String>,
referer: ActionReferer,
weight: Weight,
}
// Filtro para despachar `FnActionWithComponent` antes de renderizar un componente `C`.
impl<C: Component> ActionDispatcher for BeforeRender<C> {
fn referer_type_id(&self) -> Option<UniqueId> {
self.referer_type_id
}
fn referer_id(&self) -> Option<String> {
self.referer_id.clone()
fn referer(&self) -> Option<&ActionReferer> {
Some(&self.referer)
}
fn weight(&self) -> Weight {
@ -30,8 +25,7 @@ impl<C: Component> BeforeRender<C> {
pub fn new(f: FnActionWithComponent<C>) -> Self {
BeforeRender {
f,
referer_type_id: Some(UniqueId::of::<C>()),
referer_id: None,
referer: ActionReferer::of::<C>(),
weight: 0,
}
}
@ -39,7 +33,7 @@ impl<C: Component> BeforeRender<C> {
/// Afina el registro para ejecutar la acción [`FnActionWithComponent`] sólo para el componente
/// `C` con identificador `id`.
pub fn filter_by_referer_id(mut self, id: impl AsRef<str>) -> Self {
self.referer_id = util::normalize_token(id);
self.referer = self.referer.with_id(id);
self
}
@ -52,18 +46,6 @@ impl<C: Component> BeforeRender<C> {
/// Despacha las acciones.
#[inline]
pub(crate) fn dispatch(component: &mut C, cx: &mut Context) {
// Primero despacha las acciones para el tipo de componente.
dispatch_actions(
&ActionKey::new(UniqueId::of::<Self>(), Some(UniqueId::of::<C>()), None),
|action: &Self| (action.f)(component, cx),
);
// Y luego despacha las aciones para el tipo de componente con un identificador dado.
if let Some(id) = component.id() {
dispatch_actions(
&ActionKey::new(UniqueId::of::<Self>(), Some(UniqueId::of::<C>()), Some(id)),
|action: &Self| (action.f)(component, cx),
);
}
dispatch_referer(component, |c| c.id(), |action: &Self, c| (action.f)(c, cx));
}
}

View file

@ -5,19 +5,14 @@ use super::FnActionTransformMarkup;
/// Ejecuta [`FnActionTransformMarkup`] para alterar el renderizado de componentes.
pub struct TransformMarkup<C: Component> {
f: FnActionTransformMarkup<C>,
referer_type_id: Option<UniqueId>,
referer_id: Option<String>,
referer: ActionReferer,
weight: Weight,
}
// Filtro para despachar `FnActionTransformMarkup` sobre el renderizado de un componente `C`.
impl<C: Component> ActionDispatcher for TransformMarkup<C> {
fn referer_type_id(&self) -> Option<UniqueId> {
self.referer_type_id
}
fn referer_id(&self) -> Option<String> {
self.referer_id.clone()
fn referer(&self) -> Option<&ActionReferer> {
Some(&self.referer)
}
fn weight(&self) -> Weight {
@ -30,8 +25,7 @@ impl<C: Component> TransformMarkup<C> {
pub fn new(f: FnActionTransformMarkup<C>) -> Self {
TransformMarkup {
f,
referer_type_id: Some(UniqueId::of::<C>()),
referer_id: None,
referer: ActionReferer::of::<C>(),
weight: 0,
}
}
@ -39,7 +33,7 @@ impl<C: Component> TransformMarkup<C> {
/// Afina el registro para ejecutar la acción [`FnActionTransformMarkup`] sólo para el
/// componente `C` con identificador `id`.
pub fn filter_by_referer_id(mut self, id: impl AsRef<str>) -> Self {
self.referer_id = util::normalize_token(id);
self.referer = self.referer.with_id(id);
self
}
@ -51,29 +45,16 @@ impl<C: Component> TransformMarkup<C> {
/// Despacha las acciones encadenando el [`Markup`] entre cada una.
#[inline]
pub(crate) fn dispatch(component: &C, cx: &Context, markup: Markup) -> Markup {
pub(crate) fn dispatch(component: &mut C, cx: &Context, markup: Markup) -> Markup {
let mut output = markup;
// Primero despacha las acciones para el tipo de componente.
dispatch_actions(
&ActionKey::new(UniqueId::of::<Self>(), Some(UniqueId::of::<C>()), None),
|action: &Self| {
dispatch_referer(
component,
|c| c.id(),
|action: &Self, c| {
let taken = std::mem::replace(&mut output, html! {});
output = (action.f)(component, cx, taken);
output = (action.f)(c, cx, taken);
},
);
// Y luego despacha las acciones para el tipo de componente con un identificador dado.
if let Some(id) = component.id() {
dispatch_actions(
&ActionKey::new(UniqueId::of::<Self>(), Some(UniqueId::of::<C>()), Some(id)),
|action: &Self| {
let taken = std::mem::replace(&mut output, html! {});
output = (action.f)(component, cx, taken);
},
);
}
output
}
}

View file

@ -37,9 +37,6 @@ impl AfterRenderBody {
/// Despacha las acciones.
#[inline]
pub(crate) fn dispatch(page: &mut Page) {
dispatch_actions(
&ActionKey::new(UniqueId::of::<Self>(), None, None),
|action: &Self| (action.f)(page),
);
dispatch_actions(|action: &Self| (action.f)(page));
}
}

View file

@ -37,9 +37,6 @@ impl BeforeRenderBody {
/// Despacha las acciones.
#[inline]
pub(crate) fn dispatch(page: &mut Page) {
dispatch_actions(
&ActionKey::new(UniqueId::of::<Self>(), None, None),
|action: &Self| (action.f)(page),
);
dispatch_actions(|action: &Self| (action.f)(page));
}
}