///|
struct ComponentEffect {
key : String
cleanup : (() -> Unit)?
cleanup_with_reason : ((ComponentEffectCancelReason) -> Unit)?
mut reused : Bool
}
///|
pub(all) enum ComponentEffectCancelReason {
EffectKeyChanged
EffectUnmounted
EffectRuntimeDestroyed
} derive(Eq, Debug, ToJson)
///|
fn ComponentEffect::new(
key~ : String,
cleanup? : (() -> Unit)? = None,
cleanup_with_reason? : ((ComponentEffectCancelReason) -> Unit)? = None,
) -> ComponentEffect {
{ key, cleanup, cleanup_with_reason, reused: false }
}
///|
fn ComponentEffect::cancel_with_reason(
self : ComponentEffect,
reason : ComponentEffectCancelReason,
) -> Unit {
match self.cleanup_with_reason {
Some(cleanup) => cleanup(reason)
None => ()
}
match self.cleanup {
Some(cleanup) => cleanup()
None => ()
}
}
///|
pub fn ComponentEffect::finish_reuse(
old_effects : Array[ComponentEffect],
reason? : ComponentEffectCancelReason = ComponentEffectCancelReason::EffectKeyChanged,
cancel_reused? : Bool = false,
) -> Unit {
for effect in old_effects {
if cancel_reused || !effect.reused {
effect.cancel_with_reason(reason)
}
effect.reused = false
}
}
///|
pub fn ComponentContext::run_effect(
self : ComponentContext,
key~ : String,
effect : () -> (() -> Unit)?,
) -> Unit {
match self.take_old_effect(key) {
Some(existing) => {
existing.reused = true
self.effects.push(existing)
}
None => self.effects.push(ComponentEffect::new(key~, cleanup=effect()))
}
}
///|
pub fn ComponentContext::run_effect_with_reason(
self : ComponentContext,
key~ : String,
effect : () -> ((ComponentEffectCancelReason) -> Unit)?,
) -> Unit {
match self.take_old_effect(key) {
Some(existing) => {
existing.reused = true
self.effects.push(existing)
}
None =>
self.effects.push(
ComponentEffect::new(key~, cleanup_with_reason=effect()),
)
}
}
///|
pub fn cancel_component_effects(
effects : Array[ComponentEffect],
reason? : ComponentEffectCancelReason = ComponentEffectCancelReason::EffectUnmounted,
) -> Unit {
ComponentEffect::finish_reuse(effects, reason~, cancel_reused=true)
}