fix: next_frame leaks (#147)

* fix: next_frame leaks

* ci: added workflow path
This commit is contained in:
luoxiaozero 2024-03-20 11:01:48 +08:00 committed by GitHub
parent 2be216043e
commit 535594f963
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 74 additions and 18 deletions

View file

@ -2,13 +2,16 @@ name: CI
on: on:
workflow_dispatch: workflow_dispatch:
pull_request: pull_request:
paths: ["demo/**", "demo_markdown/**", "thaw/**"] paths:
[
"demo/**",
"demo_markdown/**",
"thaw/**",
"thaw_components/**",
"thaw_utils/**",
]
branches: branches:
- main - main
push:
paths: ["demo/**", "demo_markdown/**", "thaw/**"]
branches:
- thaw/v0.2
jobs: jobs:
stable: stable:

View file

@ -2,7 +2,14 @@ name: Deploy demo
on: on:
workflow_dispatch: workflow_dispatch:
push: push:
paths: ["demo/**", "demo_markdown/**", "thaw/**"] paths:
[
"demo/**",
"demo_markdown/**",
"thaw/**",
"thaw_components/**",
"thaw_utils/**",
]
branches: branches:
- main - main

View file

@ -1,6 +1,6 @@
use leptos::{html::ElementDescriptor, *}; use leptos::{html::ElementDescriptor, *};
use std::{ops::Deref, time::Duration}; use std::{ops::Deref, time::Duration};
use thaw_utils::{add_event_listener, EventListenerHandle}; use thaw_utils::{add_event_listener, use_next_frame, EventListenerHandle};
/// # CSS Transition /// # CSS Transition
/// ///
@ -26,6 +26,7 @@ where
let any_el = node_el.clone().into_any(); let any_el = node_el.clone().into_any();
let el = any_el.deref().clone(); let el = any_el.deref().clone();
let class_list = el.class_list(); let class_list = el.class_list();
let next_frame = use_next_frame();
let end_handle = StoredValue::new(None::<EventListenerHandle>); let end_handle = StoredValue::new(None::<EventListenerHandle>);
let end_count = StoredValue::new(None::<usize>); let end_count = StoredValue::new(None::<usize>);
let finish = StoredValue::new(None::<Callback<()>>); let finish = StoredValue::new(None::<Callback<()>>);
@ -53,7 +54,7 @@ where
set_timeout( set_timeout(
move || { move || {
finish.update_value(|v| { finish.try_update_value(|v| {
v.take().map(|f| f.call(())); v.take().map(|f| f.call(()));
}); });
}, },
@ -107,7 +108,7 @@ where
display.set(None); display.set(None);
let class_list = class_list.clone(); let class_list = class_list.clone();
next_frame(move || { next_frame.run(move || {
let _ = class_list.remove_1(&enter_from); let _ = class_list.remove_1(&enter_from);
let _ = class_list.add_1(&enter_to); let _ = class_list.add_1(&enter_to);
@ -136,7 +137,7 @@ where
let _ = class_list.add_2(&leave_from, &leave_active); let _ = class_list.add_2(&leave_from, &leave_active);
let class_list = class_list.clone(); let class_list = class_list.clone();
next_frame(move || { next_frame.run(move || {
let _ = class_list.remove_1(&leave_from); let _ = class_list.remove_1(&leave_from);
let _ = class_list.add_1(&leave_to); let _ = class_list.add_1(&leave_to);
@ -170,17 +171,19 @@ where
show show
}); });
on_cleanup(move || {
end_handle.update_value(|handle| {
if let Some(handle) = handle.take() {
handle.remove();
}
});
})
}); });
children(display.read_only()) children(display.read_only())
} }
fn next_frame(cb: impl FnOnce() + 'static) {
request_animation_frame(move || {
request_animation_frame(cb);
});
}
#[derive(PartialEq)] #[derive(PartialEq)]
enum AnimationTypes { enum AnimationTypes {
Transition, Transition,

View file

@ -1,5 +1,7 @@
mod use_click_position; mod use_click_position;
mod use_lock_html_scroll; mod use_lock_html_scroll;
mod use_next_frame;
pub use use_click_position::use_click_position; pub use use_click_position::use_click_position;
pub use use_lock_html_scroll::use_lock_html_scroll; pub use use_lock_html_scroll::use_lock_html_scroll;
pub use use_next_frame::{use_next_frame, NextFrame};

View file

@ -0,0 +1,41 @@
use leptos::{
leptos_dom::helpers::AnimationFrameRequestHandle, on_cleanup,
request_animation_frame_with_handle, StoredValue,
};
pub fn use_next_frame() -> NextFrame {
let next_frame = NextFrame::default();
on_cleanup(move || {
next_frame.cancel();
});
next_frame
}
#[derive(Default, Clone)]
pub struct NextFrame(StoredValue<Option<AnimationFrameRequestHandle>>);
impl Copy for NextFrame {}
impl NextFrame {
pub fn run(&self, cb: impl FnOnce() + 'static) {
self.cancel();
let next_frame_hadnle = self.0.clone();
let handle = request_animation_frame_with_handle(move || {
let handle = request_animation_frame_with_handle(cb).unwrap();
next_frame_hadnle.set_value(Some(handle));
})
.unwrap();
self.0.set_value(Some(handle));
}
pub fn cancel(&self) {
self.0.update_value(|value| {
if let Some(value) = value.take() {
value.cancel();
}
});
}
}

View file

@ -7,13 +7,13 @@ mod signals;
mod time; mod time;
pub use event_listener::{add_event_listener, EventListenerHandle}; pub use event_listener::{add_event_listener, EventListenerHandle};
pub use hooks::{use_click_position, use_lock_html_scroll}; pub use hooks::{use_click_position, use_lock_html_scroll, use_next_frame, NextFrame};
pub use mount_style::mount_style; pub use mount_style::mount_style;
pub use optional_prop::OptionalProp; pub use optional_prop::OptionalProp;
pub use signals::{ pub use signals::{
create_component_ref, ComponentRef, Model, OptionalMaybeSignal, SignalWatch, StoredMaybeSignal, create_component_ref, ComponentRef, Model, OptionalMaybeSignal, SignalWatch, StoredMaybeSignal,
}; };
pub use time::*; pub use time::now_date;
pub fn with_hydration_off<T>(f: impl FnOnce() -> T) -> T { pub fn with_hydration_off<T>(f: impl FnOnce() -> T) -> T {
#[cfg(feature = "hydrate")] #[cfg(feature = "hydrate")]