use std::future::Future;
use std::pin::Pin;
use bytes::Bytes;
use crate::stream::{with_active, PendingSuspense, StreamError};
pub const REPLACE_SCRIPT: &str = r#"window.$ISLANDS_REPLACE=(s,t)=>{const o=document.getElementById(s),p=document.getElementById(t);if(o&&p){o.replaceChildren(p.content);p.remove();window.__islands_remount?.();}};"#;
pub struct Suspense<F> {
fallback: Bytes,
future: F,
}
impl<F> Suspense<F>
where
F: Future<Output = Result<String, StreamError>> + Send + 'static,
{
pub fn new(fallback: impl Into<Bytes>, future: F) -> Self {
Self {
fallback: fallback.into(),
future,
}
}
pub fn render(self) -> String {
let Self { fallback, future } = self;
let slot_id = with_active(|context| {
let slot_id = context.next_slot_id();
context.register(PendingSuspense {
slot_id,
fallback_html: fallback.clone(),
future: Box::pin(future) as Pin<Box<dyn Future<Output = _> + Send>>,
});
slot_id
});
format!(
"<div data-suspense-slot id=\"S:{slot_id}\">{}</div>",
std::str::from_utf8(&fallback).unwrap_or("")
)
}
}