-
Notifications
You must be signed in to change notification settings - Fork 16
Open
Description
Instead of polling the subgraph on webapp using js, we should do it with a function exported from gui.
gui.awaitDeployment(txhash) could be used to automatically use the correct values to return indexing state.
Here is a simple example using web-sys
use wasm_bindgen::prelude::*;
use web_sys::Window;
use std::rc::Rc;
use std::cell::RefCell;
// A trait for callbacks that can be executed on interval
pub trait IntervalCallback: 'static {
fn call(&mut self);
}
// Implementation for FnMut closures
impl<F: FnMut() + 'static> IntervalCallback for F {
fn call(&mut self) {
self();
}
}
#[wasm_bindgen]
pub struct IntervalHandle {
interval_id: i32,
window: Window,
}
#[wasm_bindgen]
impl IntervalHandle {
#[wasm_bindgen(constructor)]
pub fn new(interval_id: i32, window: Window) -> Self {
Self { interval_id, window }
}
#[wasm_bindgen]
pub fn clear(&self) {
let _ = self.window.clear_interval_with_handle(self.interval_id);
}
}
// A struct to hold our callback state
struct CallbackState<T: IntervalCallback> {
callback: T,
}
// Generic set_interval function with Rust callbacks
pub fn set_interval<T: IntervalCallback>(mut callback: T, delay: i32) -> Result<IntervalHandle, JsValue> {
let window = web_sys::window().expect("no global window exists");
// Wrap the callback in a new struct to manage its state
let callback_state = Rc::new(RefCell::new(CallbackState {
callback
}));
// Clone for closure
let callback_state_clone = callback_state.clone();
// Create JS closure wrapper
let closure = Closure::wrap(Box::new(move || {
// Call the Rust callback
callback_state_clone.borrow_mut().callback.call();
}) as Box<dyn FnMut()>);
// Set the interval using the window.setInterval method
let interval_id = window.set_interval_with_callback_and_timeout_and_arguments_0(
closure.as_ref().unchecked_ref(),
delay,
)?;
// Forget the closure to keep it alive
// NOTE: This will cause a memory leak if clear() is never called
closure.forget();
Ok(IntervalHandle::new(interval_id, window))
}
// Example of a counter implementation
pub struct Counter {
count: i32,
max: i32,
handle: Option<IntervalHandle>,
}
impl Counter {
pub fn new(max: i32) -> Self {
Self {
count: 0,
max,
handle: None,
}
}
pub fn set_handle(&mut self, handle: IntervalHandle) {
self.handle = Some(handle);
}
}
impl IntervalCallback for Counter {
fn call(&mut self) {
self.count += 1;
web_sys::console::log_1(&format!("Counter: {}/{}", self.count, self.max).into());
if self.count >= self.max {
if let Some(handle) = &self.handle {
handle.clear();
web_sys::console::log_1(&"Counter interval cleared!".into());
}
}
}
}
// Example function to demonstrate using a custom struct
#[wasm_bindgen]
pub fn start_counter(delay: i32, max_ticks: i32) -> Result<IntervalHandle, JsValue> {
// Create a counter struct
let counter = Counter::new(max_ticks);
// Set up interval with the counter as callback
let handle = set_interval(counter, delay)?;
Ok(handle)
}
// Example with a simple closure
#[wasm_bindgen]
pub fn simple_interval(delay: i32) -> Result<IntervalHandle, JsValue> {
// Create a counter in a closure
let counter = Rc::new(RefCell::new(0));
let counter_clone = counter.clone();
let closure = move || {
let mut count = counter_clone.borrow_mut();
*count += 1;
web_sys::console::log_1(&format!("Tick: {}", *count).into());
};
set_interval(closure, delay)
}
// Self-clearing interval example
#[wasm_bindgen]
pub fn self_clearing_interval(delay: i32, max_ticks: i32) -> Result<IntervalHandle, JsValue> {
// Create a counter and handle reference
let counter = Rc::new(RefCell::new(0));
let handle_ref = Rc::new(RefCell::new(None));
// Clone for closure
let counter_clone = counter.clone();
let handle_ref_clone = handle_ref.clone();
let closure = move || {
let mut count = counter_clone.borrow_mut();
*count += 1;
web_sys::console::log_1(&format!("Tick: {}/{}", *count, max_ticks).into());
if *count >= max_ticks {
if let Some(handle) = &*handle_ref_clone.borrow() {
handle.clear();
web_sys::console::log_1(&"Interval cleared!".into());
}
}
};
// Set interval with our closure
let handle = set_interval(closure, delay)?;
// Store handle for later use in the closure
*handle_ref.borrow_mut() = Some(IntervalHandle::new(handle.interval_id, handle.window));
Ok(handle)
}Reactions are currently unavailable