use crate::prelude::*;
use beet_core::exports::notify::EventKind;
use beet_core::exports::notify::event::CreateKind;
use beet_core::exports::notify::event::ModifyKind;
use beet_core::exports::notify::event::RemoveKind;
use beet_core::prelude::*;
use std::path::Path;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Component, Deref)]
#[require(FileExprHash)]
pub struct SourceFile {
path: AbsPathBuf,
}
impl SourceFile {
pub fn new(path: AbsPathBuf) -> Self { Self { path } }
pub fn path(&self) -> &AbsPathBuf { &self.path }
}
impl AsRef<Path> for SourceFile {
fn as_ref(&self) -> &Path { self.path.as_ref() }
}
#[derive(Component)]
pub struct NonCollectionSourceFiles;
#[derive(Deref, Component)]
#[relationship(relationship_target = WatchedFiles)]
pub struct FileWatchedBy(pub Entity);
#[derive(Deref, Component)]
#[relationship_target(relationship = FileWatchedBy, linked_spawn)]
pub struct WatchedFiles(Vec<Entity>);
pub fn parse_dir_watch_events(
ev: On<DirEvent>,
mut commands: Commands,
root_entity: Populated<Entity, With<NonCollectionSourceFiles>>,
config: When<Res<WorkspaceConfig>>,
mut existing: Query<(Entity, &mut SourceFile)>,
) -> Result {
for ev in ev
.iter()
.filter(|ev| config.passes(&ev.path))
{
tracing::debug!("SourceFile event: {}", ev);
let matches = existing
.iter_mut()
.filter(|(_, file)| ***file == ev.path)
.map(|(en, _)| en)
.collect::<Vec<_>>();
match ev.kind {
EventKind::Create(CreateKind::File) => {
commands.spawn((
ChildOf(root_entity.single()?),
SourceFile::new(ev.path.clone()),
));
}
EventKind::Create(CreateKind::Folder) => {
}
EventKind::Modify(ModifyKind::Name(_)) => {
if matches.is_empty() {
commands.spawn((
ChildOf(root_entity.single()?),
SourceFile::new(ev.path.clone()),
));
} else {
for entity in matches {
commands.entity(entity).despawn();
}
}
}
EventKind::Remove(RemoveKind::File) => {
for entity in matches {
commands.entity(entity).despawn();
}
}
EventKind::Modify(_) => {
for entity in matches {
commands.run_system_cached_with(reset_file, entity);
}
}
other => {
tracing::warn!("Unhandled file event: {:?}", other);
}
}
}
Ok(())
}
fn reset_file(
In(entity): In<Entity>,
mut commands: Commands,
mut files: Query<(Entity, &mut SourceFile, Option<&FileWatchedBy>)>,
) {
if let Ok((entity, mut file, parent)) = files.get_mut(entity) {
trace!("Resetting Source File: {}", file.path);
file.set_added();
commands.entity(entity).despawn_related::<Children>();
if let Some(parent) = parent {
commands.run_system_cached_with(reset_file, **parent);
}
}
}