use bevy::prelude::*;
use bevy_async_task::TaskRunner;
use nostr_sdk::prelude::Event;
use std::task::Poll;
use crate::{
NostrClient,
components::{DatabaseFetchEvent, FetchingEvent, NostrEvent, NostrEventId},
};
#[derive(EntityEvent)]
pub struct DbFetchEvent {
entity: Entity,
}
pub fn fetch_events_from_db(
mut commands: Commands,
to_fetch: Query<
(Entity, &NostrEventId),
Or<(Added<DatabaseFetchEvent>, With<FetchingEvent>)>,
>,
) {
for (entity, _) in &to_fetch {
commands.trigger(DbFetchEvent { entity });
}
}
pub fn on_db_fetch(
db_event: On<DbFetchEvent>,
mut commands: Commands,
mut task_runner: TaskRunner<'_, (Entity, Option<Event>)>,
nostr_client: Res<NostrClient>,
nostr_events: Query<(Entity, &NostrEventId)>,
) {
let Ok((entity, event_id)) = nostr_events.get(db_event.entity) else {
warn!("on_db_fetch: Cannot find event!");
return;
};
commands.entity(entity).insert(FetchingEvent);
if task_runner.is_idle() {
let client = nostr_client.client.clone();
let id = event_id.0.clone();
let entity_c = entity.clone();
task_runner.start(async move {
match client.database().event_by_id(&id).await {
Ok(result) => (entity_c, result),
Err(err) => {
warn!("Error fetching event with id {id:?}: {err}");
(entity_c, None)
}
}
});
}
if let Poll::Ready((ev_entity, result)) = task_runner.poll() {
match result {
Some(event) => {
commands
.entity(ev_entity)
.insert(NostrEvent(event))
.remove::<FetchingEvent>();
}
None => {
commands.entity(ev_entity).remove::<FetchingEvent>();
}
}
}
}