leptos-use/src/use_timestamp.rs

189 lines
5 KiB
Rust
Raw Normal View History

use crate::core::now;
2023-09-17 15:44:55 +01:00
use crate::utils::Pausable;
use crate::{
use_interval_fn_with_options, use_raf_fn_with_options, UseIntervalFnOptions, UseRafFnOptions,
};
use default_struct_builder::DefaultBuilder;
use leptos::*;
use std::rc::Rc;
/// Reactive current timestamp.
///
/// ## Demo
///
/// [Link to Demo](https://github.com/Synphonyte/leptos-use/tree/main/examples/use_timestamp)
///
/// ## Usage
///
/// ```
/// # use leptos::*;
/// # use leptos_use::use_timestamp;
/// #
/// # #[component]
/// # fn Demo() -> impl IntoView {
/// let timestamp = use_timestamp();
/// #
/// # view! { }
/// # }
/// ```
///
/// With controls:
///
/// ```
/// # use leptos::*;
/// # use leptos_use::{use_timestamp_with_controls, UseTimestampReturn};
/// #
/// # #[component]
/// # fn Demo() -> impl IntoView {
/// let UseTimestampReturn {
/// timestamp,
/// is_active,
/// pause,
/// resume,
/// } = use_timestamp_with_controls();
/// #
/// # view! { }
/// # }
/// ```
///
/// ## Server-Side Rendering
///
/// On the server this function will return a signal with the milliseconds since the Unix epoch.
/// But the signal will never update (as there's no `request_animation_frame` on the server).
2023-09-17 15:44:55 +01:00
pub fn use_timestamp() -> Signal<f64> {
use_timestamp_with_controls().timestamp
}
/// Version of [`use_timestamp`] that takes a `UseTimestampOptions`. See [`use_timestamp`] for how to use.
pub fn use_timestamp_with_options(options: UseTimestampOptions) -> Signal<f64> {
use_timestamp_with_controls_and_options(options).timestamp
}
/// Version of [`use_timestamp`] that returns controls. See [`use_timestamp`] for how to use.
pub fn use_timestamp_with_controls() -> UseTimestampReturn {
use_timestamp_with_controls_and_options(UseTimestampOptions::default())
}
/// Version of [`use_timestamp`] that takes a `UseTimestampOptions` and returns controls. See [`use_timestamp`] for how to use.
pub fn use_timestamp_with_controls_and_options(options: UseTimestampOptions) -> UseTimestampReturn {
let UseTimestampOptions {
offset,
immediate,
interval,
callback,
} = options;
let (ts, set_ts) = create_signal(now() + offset);
2023-09-17 15:44:55 +01:00
let update = move || {
set_ts.set(now() + offset);
2023-09-17 15:44:55 +01:00
};
let cb = {
let callback = Rc::clone(&callback);
move || {
update();
callback(ts.get_untracked());
2023-09-17 15:44:55 +01:00
}
};
match interval {
TimestampInterval::RequestAnimationFrame => {
let Pausable {
pause,
resume,
is_active,
} = use_raf_fn_with_options(
move |_| cb(),
UseRafFnOptions::default().immediate(immediate),
);
UseTimestampReturn {
timestamp: ts.into(),
is_active,
pause: Rc::new(pause),
resume: Rc::new(resume),
}
}
TimestampInterval::Interval(interval) => {
let Pausable {
pause,
resume,
is_active,
} = use_interval_fn_with_options(
cb,
interval,
UseIntervalFnOptions::default().immediate(immediate),
);
UseTimestampReturn {
timestamp: ts.into(),
is_active,
pause: Rc::new(pause),
resume: Rc::new(resume),
}
}
}
}
/// Options for [`use_timestamp_with_controls_and_options`].
#[derive(DefaultBuilder)]
pub struct UseTimestampOptions {
/// Offset value in milliseconds that is added to the returned timestamp. Defaults to `0.0`.
offset: f64,
/// Whether to update the timestamp immediately. Defaults to `true`.
immediate: bool,
/// Update interval in milliseconds or `RequestAnimationFrame`. Defaults to `RequestAnimationFrame`.
#[builder(into)]
interval: TimestampInterval,
/// Callback to be called whenever the timestamp is updated.
callback: Rc<dyn Fn(f64)>,
}
/// Interval type for [`UseTimestampOptions`].
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum TimestampInterval {
/// use [`use_raf_fn`] for updating the timestamp
RequestAnimationFrame,
/// use [`use_interval_fn`] for updating the timestamp
Interval(u64),
}
impl From<u64> for TimestampInterval {
fn from(value: u64) -> Self {
Self::Interval(value)
}
}
impl Default for UseTimestampOptions {
fn default() -> Self {
Self {
offset: 0.0,
immediate: true,
interval: TimestampInterval::RequestAnimationFrame,
callback: Rc::new(|_| {}),
}
}
}
/// Return type of [`use_timestamp_with_controls`].
pub struct UseTimestampReturn {
/// The current timestamp
pub timestamp: Signal<f64>,
/// A Signal that indicates whether the timestamp updating is active. `false` when paused.
pub is_active: Signal<bool>,
/// Temporarily pause the timestamp from updating
pub pause: Rc<dyn Fn()>,
/// Resume the timestamp updating
pub resume: Rc<dyn Fn()>,
}