use super::*;
#[derive(Debug, Clone, Default)]
pub struct QueryMsgFilter {
sender: Staff,
recipients: HashSet<Staff>,
topical_assets: Option<HashSet<ProductionAsset>>,
date_range: Option<DateRange>,
}
impl QueryMsgFilter {
pub fn today(start_day_offset: i64, id_source: Option<&str>) -> Self {
Self {
date_range: Some(DateRange::today_local(start_day_offset, id_source)),
..Default::default()
}
}
pub fn with_assets(mut self, assets: Option<HashSet<ProductionAsset>>) -> Self {
self.topical_assets = assets;
self
}
pub fn sender(mut self, sender: Staff) -> Self {
self.sender = sender;
self
}
pub fn include_recipient(mut self, user: Staff) -> Self {
self.recipients.insert(user);
self
}
pub fn date_range(mut self, date_range: &DateRange) -> Self {
self.date_range = Some(date_range.clone());
self
}
pub fn date_range_owned(mut self, range: DateRange) -> Self {
self.date_range = Some(range);
self
}
pub fn sender_name(&self) -> &String {
self.sender.name_unwrap()
}
pub fn recipients_name(&self) -> Vec<&str> {
self.recipients
.iter()
.map(|r| r.name_unwrap().as_str())
.collect()
}
pub fn is_topical_assets_none(&self) -> bool {
self.topical_assets.is_none()
}
pub fn assets_ids_unwrap(&self) -> Vec<&ObjectId> {
self.topical_assets
.as_ref()
.unwrap()
.iter()
.filter_map(|a| a.bson_id_as_ref())
.collect()
}
pub fn into_assets_ids_unwrap(self) -> Vec<ObjectId> {
self.topical_assets
.unwrap()
.into_iter()
.filter_map(|a| a.bson_id_owned())
.collect()
}
pub fn date_range_as_ref_unwrap(&self) -> &DateRange {
self.date_range.as_ref().unwrap()
}
#[cfg(feature = "gui")]
pub fn date_range_ui_unwrap(&mut self, ui: &mut egui::Ui) {
self.date_range.as_mut().unwrap().ui(ui);
}
pub fn date_range_end_today_mut_if_unmodified_unwrap(&mut self) {
self.date_range
.as_mut()
.unwrap()
.end_today_mut_if_unmodified();
}
pub fn date_range_mut_unwrap(&mut self, range: DateRange) {
*self.date_range.as_mut().unwrap() = range;
}
pub fn start_datetime_unwrap(&self) -> DateTime<Utc> {
self.date_range.as_ref().unwrap().start_datetime()
}
pub fn end_datetime_unwrap(&self) -> DateTime<Utc> {
self.date_range.as_ref().unwrap().end_datetime()
}
}
#[derive(Debug, Clone)]
pub enum QmsBox {
Mixed(Messages),
Handwritten(Messages),
System(Messages),
Sent(Messages),
}
impl QmsBox {
pub fn uninitialized() -> Result<Self, DatabaseError> {
Err(anyhow!("Idling").into())
}
pub fn empty_mixed() -> Self {
Self::Mixed(Messages::empty())
}
pub fn empty_handwritten() -> Self {
Self::Handwritten(Messages::empty())
}
pub fn empty_system() -> Self {
Self::System(Messages::empty())
}
pub fn empty_sent() -> Self {
Self::Sent(Messages::empty())
}
pub fn with_inner(self, inner: Messages) -> Self {
match self {
Self::Mixed(_) => Self::Mixed(inner),
Self::Handwritten(_) => Self::Handwritten(inner),
Self::System(_) => Self::System(inner),
Self::Sent(_) => Self::Sent(inner),
}
}
fn drain_messages(&mut self) -> Vec<QueryMsg> {
match self {
Self::Mixed(inner)
| Self::Handwritten(inner)
| Self::System(inner)
| Self::Sent(inner) => inner.drain().into_iter().collect(),
}
}
pub fn println_each(&self) {
match self {
Self::Mixed(inner) => {
inner.println_each();
}
Self::Handwritten(inner) => {
inner.println_each();
}
Self::System(inner) => {
inner.println_each();
}
Self::Sent(inner) => {
inner.println_each();
}
}
}
}
#[cfg(feature = "gui")]
impl QmsBox {
fn label(&self) -> &'static str {
match &self {
Self::Mixed(_) => "Mixed",
Self::Handwritten(_) => "Chat",
Self::System(_) => "System",
Self::Sent(_) => "Sent",
}
}
fn len_hint(&self) -> RichText {
match &self {
Self::Mixed(inner)
| Self::Handwritten(inner)
| Self::System(inner)
| Self::Sent(inner) => RichText::new(&inner.len_hint).color(Color32::LIGHT_GRAY),
}
}
fn unread_count(&self) -> Option<RichText> {
match &self {
Self::Mixed(inner)
| Self::Handwritten(inner)
| Self::System(inner)
| Self::Sent(inner) => {
if let Some(unread) = &inner.unread_count {
Some(
RichText::new(unread)
.background_color(Color32::RED)
.color(Color32::WHITE),
)
} else {
None
}
}
}
}
fn batch_actions_ui(&mut self, ui: &mut egui::Ui, tx: &Sender<MsgAction>) {
ui.with_layout(Layout::right_to_left(Align::Min), |ui| {
if ui
.button("― All")
.on_hover_text("Mark all as unread")
.clicked()
{
tx.send(MsgAction::BatchUpdateReadState(
self.drain_messages(),
ReadState::Unread,
))
.ok();
};
if ui
.button("👁 All")
.on_hover_text("Mark all as read")
.clicked()
{
tx.send(MsgAction::BatchUpdateReadState(
self.drain_messages(),
ReadState::Read,
))
.ok();
};
});
}
fn title_ui(&mut self, ui: &mut egui::Ui, tx: &Sender<MsgAction>) {
ui.horizontal(|ui| {
ui.heading(self.label());
if let Self::Sent(_) = self {
return;
};
if let Some(unread) = self.unread_count() {
ui.heading(unread);
};
ui.label(self.len_hint());
self.batch_actions_ui(ui, tx);
});
}
pub fn ui(&mut self, ui: &mut egui::Ui, tx: &Sender<MsgAction>, order: &CreatedAtOrdering) {
ui.vertical(|ui| {
self.title_ui(ui, tx);
ui.separator();
egui::ScrollArea::vertical()
.id_source(self.label())
.show(ui, |ui| {
match self {
Self::Mixed(inner) => {
inner.mixed_msg_ui(ui, tx, order);
}
Self::Handwritten(inner) => {
inner.handwritten_msg_ui(ui, tx, order);
}
Self::System(inner) => {
inner.system_msg_ui(ui, tx, order);
}
Self::Sent(inner) => {
inner.sent_msg_ui(ui, tx, order);
}
};
});
});
}
}
#[derive(Debug, Clone)]
pub struct Messages {
messages: Vec<QueryMsg>,
len_hint: String,
unread_count: Option<String>,
}
impl Messages {
pub fn empty() -> Self {
Self {
messages: vec![],
len_hint: String::new(),
unread_count: None,
}
}
fn drain(&mut self) -> std::vec::Drain<'_, QueryMsg> {
self.unread_count.take();
self.len_hint = "Being drained...".to_owned();
self.messages.drain(..)
}
fn println_each(&self) {
for msg in self.messages.iter() {
println!("\n{:?}", msg);
}
}
}
#[cfg(feature = "gui")]
impl Messages {
fn mixed_msg_ui(
&mut self,
ui: &mut egui::Ui,
tx: &Sender<MsgAction>,
order: &CreatedAtOrdering,
) {
match order {
CreatedAtOrdering::NewestFirst => {
self.messages.iter_mut().for_each(|m| {
m.mixed_msg_ui(ui, tx);
});
}
CreatedAtOrdering::OldestFirst => {
self.messages.iter_mut().rev().for_each(|m| {
m.mixed_msg_ui(ui, tx);
});
}
}
}
fn handwritten_msg_ui(
&mut self,
ui: &mut egui::Ui,
tx: &Sender<MsgAction>,
order: &CreatedAtOrdering,
) {
match order {
CreatedAtOrdering::NewestFirst => {
self.messages.iter_mut().for_each(|m| {
m.handwritten_msg_ui(ui, tx);
});
}
CreatedAtOrdering::OldestFirst => {
self.messages.iter_mut().rev().for_each(|m| {
m.handwritten_msg_ui(ui, tx);
});
}
}
}
fn system_msg_ui(
&mut self,
ui: &mut egui::Ui,
tx: &Sender<MsgAction>,
order: &CreatedAtOrdering,
) {
match order {
CreatedAtOrdering::NewestFirst => {
self.messages.iter_mut().for_each(|m| {
m.system_msg_ui(ui, tx);
});
}
CreatedAtOrdering::OldestFirst => {
self.messages.iter_mut().rev().for_each(|m| {
m.system_msg_ui(ui, tx);
});
}
}
}
fn sent_msg_ui(
&mut self,
ui: &mut egui::Ui,
tx: &Sender<MsgAction>,
order: &CreatedAtOrdering,
) {
match order {
CreatedAtOrdering::NewestFirst => {
self.messages.iter_mut().for_each(|m| {
m.sent_msg_ui(ui, tx);
});
}
CreatedAtOrdering::OldestFirst => {
self.messages.iter_mut().rev().for_each(|m| {
m.sent_msg_ui(ui, tx);
});
}
}
}
}
impl From<Vec<QueryMsg>> for Messages {
fn from(messages: Vec<QueryMsg>) -> Self {
let len = messages.len();
let unread = messages.iter().filter(|m| !m.ext.seen_by_self).count();
let len_hint = if let Ordering::Greater = unread.cmp(&0) {
format!("/{}", len)
} else {
format!("({})", len)
};
let unread_count = if let Ordering::Greater = unread.cmp(&0) {
Some(format!("{}", unread))
} else {
None
};
Self {
messages,
len_hint,
unread_count,
}
}
}