use super::*;
fn roots(store: &AttachmentChunkStore, text: &str) -> anyhow::Result<Vec<Hash>> {
let mut staged: HashSet<Hash> = store
.staged_references()?
.into_iter()
.map(|(root, _, _)| root)
.collect();
if staged.is_empty() {
return Ok(Vec::new());
}
Ok(extract_message_attachments(text)
.1
.into_iter()
.filter_map(|attachment| nhash_decode(&attachment.nhash).ok().map(|data| data.hash))
.filter(|root| staged.remove(root))
.collect())
}
impl AppCore {
pub(in crate::core) fn bind_attachment_message(
&mut self,
chat: &str,
message: &str,
text: &str,
) -> anyhow::Result<bool> {
let Some(service) = &self.attachment_service else {
return Ok(false);
};
service
.store
.bind_message(&roots(&service.store, text)?, chat, message)
}
pub(in crate::core) fn resolve_attachment_staging(
&self,
store: &AttachmentChunkStore,
selected: Option<&[Hash]>,
) -> anyhow::Result<()> {
for (root, chat, message) in store.staged_references()? {
if selected.is_some_and(|selected| !selected.contains(&root)) {
continue;
}
let durable = match (chat, message) {
(Some(chat), Some(message)) => {
self.app_store.message_exists(&chat, Some(&message), None)?
}
_ => false,
};
store.resolve_staged(&root, durable)?;
}
Ok(())
}
pub(in crate::core) fn finish_attachment_message(&mut self, text: &str) {
if let Some(service) = &self.attachment_service {
let result = roots(&service.store, text)
.and_then(|roots| self.resolve_attachment_staging(&service.store, Some(&roots)));
if let Err(error) = result {
self.push_debug_log("attachment.message.commit.error", error.to_string());
}
}
}
}
#[cfg(test)]
#[path = "message_commit_tests.rs"]
mod tests;