use std::collections::HashSet;
use history_step::IssueHistoryStep;
use log::warn;
use super::{
Issue,
data::{comment::Comment, label::Label, status::Status},
};
use crate::replica::entity::{
id::combined_id::CombinedId,
identity::IdentityStub,
snapshot::{
Snapshot,
timeline::{Timeline, history_step::HistoryStep},
},
};
pub mod history_step;
pub mod timeline;
impl Snapshot<Issue> {
#[must_use]
#[allow(clippy::missing_panics_doc)]
pub fn body(&self) -> &str {
&self
.timeline()
.body_history()
.last()
.expect("This is mandated by the crate op")
.message
}
#[must_use]
#[allow(clippy::missing_panics_doc)]
pub fn comments(&self) -> Vec<Comment> {
let mut output = Vec::with_capacity(self.timeline().comments().count());
for comment in self.timeline().comments() {
let first = comment.history.first();
let last = comment.history.last();
output.push(Comment {
combined_id: CombinedId {
primary_id: self.id().as_id(),
secondary_id: comment.id.as_id(),
},
author: first.author,
message: last.message.clone(),
files: last.files.clone(),
timestamp: first.at,
});
}
output
}
#[must_use]
pub fn labels(&self) -> HashSet<&Label> {
let mut labels = HashSet::new();
for label in self.timeline().labels_history() {
for removed in &label.removed {
if !labels.remove(removed) {
warn!("Label {removed} was removed, but was never added.");
}
}
for added in &label.added {
if !labels.insert(added) {
warn!("Label {added} was added, but was already in the set of labels.");
}
}
}
labels
}
#[must_use]
pub fn status(&self) -> Status {
if let Some(last) = self.timeline().status_history().last() {
last.status
} else {
Status::Open
}
}
#[must_use]
#[allow(clippy::missing_panics_doc)]
pub fn title(&self) -> &str {
let last = self
.timeline()
.title_history()
.last()
.expect("This is mandated by the create op");
&last.title
}
#[must_use]
#[allow(clippy::missing_panics_doc)]
pub fn author(&self) -> IdentityStub {
self.timeline()
.body_history()
.next()
.expect("A body item must exist")
.author
}
pub fn participants(&self) -> impl Iterator<Item = IdentityStub> + use<'_> {
self.timeline()
.history()
.iter()
.filter(|item| matches!(item, IssueHistoryStep::Body(_)))
.map(HistoryStep::author)
}
}