Removed LazyLoadable.

This commit is contained in:
Filipe Rodrigues 2024-03-05 18:59:48 +00:00
parent 598fb44f8b
commit f8339133a3
Signed by: zenithsiz
SSH Key Fingerprint: SHA256:Mb5ppb3Sh7IarBO/sBTXLHbYEOz37hJAlslLQPPAPaU
2 changed files with 1 additions and 189 deletions

View File

@ -1,184 +0,0 @@
//! Lazy loadable.
// Imports
use {
crate::Loadable,
dynatos_reactive::{Effect, Signal, SignalGet, SignalSet, SignalUpdate, SignalWith},
std::{future::Future, rc::Rc},
};
/// Load status
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)]
enum LoadStatus {
/// Not loading
Unloaded,
/// Load if empty
LoadIfEmpty,
/// Always load
LoadAlways,
/// Loading
Loading,
}
impl LoadStatus {
/// Sets this load status, to at least `load_status`.
///
/// If the current value is higher than `load_status`, this value won't
/// be lowered.
pub fn set_at_least(&mut self, other: Self) {
*self = Ord::max(*self, other);
}
}
/// A lazy loadable.
#[derive(Debug)]
pub struct LazyLoadable<T, E> {
/// Inner
inner: Signal<Loadable<T, E>>,
/// Load status
load_status: Signal<LoadStatus>,
/// Effect
effect: Effect<dyn Fn()>,
}
impl<T, E> LazyLoadable<T, E> {
/// Creates a new, empty, loadable.
pub fn new<F, Fut>(load: F) -> Self
where
T: 'static,
E: 'static,
F: Fn() -> Fut + 'static,
Fut: Future<Output = Result<T, E>> + 'static,
{
let inner = Signal::new(Loadable::Empty);
let load_status = Signal::new(LoadStatus::Unloaded);
let load = Rc::new(load);
let effect = Effect::new({
let inner = inner.clone();
let load_status = load_status.clone();
move || {
// If we're loading, or shouldn't load, quit.
let should_load = match load_status.get() {
LoadStatus::Unloaded => false,
LoadStatus::LoadIfEmpty => inner.with(|inner| inner.is_empty()),
LoadStatus::LoadAlways => true,
LoadStatus::Loading => false,
};
if !should_load {
return;
}
// Else spawn a future to load the value
// Note: We need to ensure that we only update `inner` inside while `load_status`
// is `Loading`. Otherwise, we could get a race and lose the loaded value to
// another load.
// Note: Although we could get the future outside of `spawn_local`, if we do, it's
// dependencies would leak into this effect, which we don't want. This way, the
// user also receives a warning if they try to use any dependencies within `load`.
load_status.set(LoadStatus::Loading);
let inner = inner.clone();
let load_status = load_status.clone();
let load = Rc::clone(&load);
wasm_bindgen_futures::spawn_local(async move {
let res = load().await;
inner.set(Loadable::from_res(res));
load_status.set(LoadStatus::Unloaded);
});
}
});
Self {
inner,
load_status,
effect,
}
}
/// Starts loading.
///
/// If loading or loaded, does nothing
pub fn load(&self) {
self.load_status
.update(|load_status| load_status.set_at_least(LoadStatus::LoadIfEmpty));
}
/// Reloads the inner value.
///
/// If loading, does nothing.
pub fn reload(&self) {
self.load_status
.update(|load_status| load_status.set_at_least(LoadStatus::LoadAlways));
}
/// Reactively accesses the value, without loading it.
pub fn with_unloaded<R>(&self, f: impl FnOnce(Loadable<&T, E>) -> R) -> R
where
T: 'static,
E: Clone + 'static,
{
self.inner.with(|value| f(value.as_ref()))
}
/// Updates the value mutably, without loading it.
///
/// Will notify any subscribers of the value.
pub fn update_unloaded<R>(&self, f: impl FnOnce(Loadable<&mut T, E>) -> R) -> R
where
T: 'static,
E: Clone + 'static,
{
let mut output = None;
self.inner.update(|inner| output = Some(f(inner.as_mut())));
output.expect("Value was not updated")
}
}
impl<T, E> Clone for LazyLoadable<T, E> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
load_status: self.load_status.clone(),
effect: self.effect.clone(),
}
}
}
// TODO: Use a `Loadable<&T, E>` when `SignalWith` allows?
impl<T, E> SignalWith for LazyLoadable<T, E>
where
T: 'static,
E: Clone + 'static,
{
type Value<'a> = Loadable<&'a T, E>;
fn with<F, O>(&self, f: F) -> O
where
F: for<'a> FnOnce(Self::Value<'a>) -> O,
{
self.load();
self.inner.with(|loadable| f(loadable.as_ref()))
}
}
impl<T, E> SignalUpdate for LazyLoadable<T, E>
where
T: 'static,
E: Clone + 'static,
{
type Value<'a> = Loadable<&'a mut T, E>;
fn update<F, O>(&self, f: F) -> O
where
F: for<'a> FnOnce(Self::Value<'a>) -> O,
{
self.load();
self.inner.update(|loadable| f(loadable.as_mut()))
}
}

View File

@ -4,11 +4,7 @@
#![feature(try_trait_v2, lint_reasons, never_type, extend_one)]
// Modules
mod lazy_loadable;
pub mod loadable;
// Exports
pub use self::{
lazy_loadable::LazyLoadable,
loadable::{IntoLoaded, IteratorLoadableExt, Loadable},
};
pub use self::loadable::{IntoLoaded, IteratorLoadableExt, Loadable};