mod use2 { #![allow(missing_docs)] use dioxus_core::{ScopeState, TaskId}; use std::{ any::Any, cell::{Cell, RefCell}, future::Future, rc::Rc, }; /// A future that resolves to a value. /// /// This runs the future only once - though the future may be regenerated /// through the [`UseFuture::restart`] method. /// /// This is commonly used for components that cannot be rendered until some /// asynchronous operation has completed. /// /// /// /// /// pub fn use_future<'a>( // pub fn use_future<'a, T: 'static, F: Future + 'static>( cx: &'a ScopeState, ) -> &'a UseFuture<()> { // let state = cx.use_hook(move |_| UseFuture { // update: cx.schedule_update(), // needs_regen: Cell::new(true), // slot: Rc::new(Cell::new(None)), // value: None, // task: None, // pending: true, // dep_cont: Cell::new(0), // deps: RefCell::new(Vec::new()), // first_time: true, // }); // if let Some(value) = state.slot.take() { // state.value = Some(value); // state.task = None; // } // if state.needs_regen.get() { // // We don't need regen anymore // state.needs_regen.set(false); // state.pending = false; // // Create the new future // let fut = new_fut(); // // Clone in our cells // let slot = state.slot.clone(); // let updater = state.update.clone(); // state.task = Some(cx.push_future(async move { // let res = fut.await; // slot.set(Some(res)); // updater(); // })); // } // state.first_time = false; // state // new_fut: impl FnOnce() -> F, todo!() } pub enum FutureState<'a, T> { Pending, Complete(&'a T), Regenerating(&'a T), // the old value } pub struct UseFuture { update: Rc, needs_regen: Cell, value: Option, slot: Rc>>, task: Option, pending: bool, deps: RefCell>>, dep_cont: Cell, first_time: bool, } impl UseFuture { pub fn restart(&self) { self.needs_regen.set(true); (self.update)(); } // clears the value in the future slot without starting the future over pub fn clear(&self) -> Option { (self.update)(); self.slot.replace(None) } // Manually set the value in the future slot without starting the future over pub fn set(&self, new_value: T) { self.slot.set(Some(new_value)); self.needs_regen.set(true); (self.update)(); } pub fn value(&self) -> Option<&T> { self.value.as_ref() } pub fn state(&self) -> FutureState { // self.value.as_ref() FutureState::Pending } pub fn build(&self, new_fut: impl FnOnce() -> F) {} } #[test] fn test_use_future_deps() { use dioxus_core::prelude::*; struct MyProps { val: String, name: i32, } fn app(cx: Scope) -> Element { let MyProps { val, name } = cx.props; // let val = use_c(&cx) // .use_dep(val) // .restart_if(|| false) // .use_dep(name) // .build(|(val, name)| async move {}); // async fn fetch_thing(name: String, num: i32) -> String { // format!("{} {}", name, num) // } // let val = use_future(&cx, || fetch_thing(val.clone(), *name)) // .with_dep(val) // .with_dep(name) // .restart_if(|| false); None } } // pub struct CoroutineBuilder<'a, const PARAM: usize> { // deps: Vec>, // cx: &'a ScopeState, // } // macro_rules! dep_impl { // ($id1:literal to $id2:literal) => { // impl<'a> CoroutineBuilder<'a, $id1> { // pub fn use_dep( // mut self, // dep: &F, // ) -> CoroutineBuilder<'a, $id2> { // self.deps.push(Box::new(dep.clone())); // unsafe { std::mem::transmute(self) } // } // } // }; // } // dep_impl!(0 to 1); // dep_impl!(1 to 2); // dep_impl!(2 to 3); // dep_impl!(3 to 4); // dep_impl!(4 to 5); // dep_impl!(5 to 6); // dep_impl!(6 to 7); // dep_impl!(7 to 8); // dep_impl!(8 to 9); }