hyaenidae/src/admin/pagination.rs

264 lines
8.2 KiB
Rust

use crate::pagination::{Pagination, SearchPagination};
use hyaenidae_profiles::store::{Comment, File, Profile, Report, ReportKind, Server, Submission};
use std::collections::HashMap;
use uuid::Uuid;
pub(super) struct ReportPager<'b> {
pub(super) store: &'b hyaenidae_profiles::store::Store,
pub(super) reports: &'b mut HashMap<Uuid, Report>,
pub(super) profiles: &'b mut HashMap<Uuid, Profile>,
pub(super) submissions: &'b mut HashMap<Uuid, Submission>,
pub(super) comments: &'b mut HashMap<Uuid, Comment>,
pub(super) files: &'b mut HashMap<Uuid, File>,
}
pub(super) struct OpenPager<'b>(pub(super) ReportPager<'b>);
pub(super) struct ClosedPager<'b>(pub(super) ReportPager<'b>);
pub(super) struct ServerPager<'b> {
pub(super) self_id: Uuid,
pub(super) store: &'b hyaenidae_profiles::store::Store,
pub(super) servers: &'b mut HashMap<Uuid, Server>,
}
pub(super) struct FederatedPager<'a>(pub(super) ServerPager<'a>);
pub(super) struct InboundPager<'a>(pub(super) ServerPager<'a>);
pub(super) struct OutboundPager<'a>(pub(super) ServerPager<'a>);
pub(super) struct BlockedPager<'a>(pub(super) ServerPager<'a>);
pub(super) struct KnownPager<'a>(pub(super) ServerPager<'a>);
impl<'b> Pagination for OpenPager<'b> {
fn from_max<'a>(&'a mut self, max: Uuid) -> Box<dyn DoubleEndedIterator<Item = Uuid> + 'a> {
Box::new(
self.0
.store
.reports
.open_reports_older_than(max)
.filter_map(move |report_id| self.0.filter_report(report_id)),
)
}
fn from_min<'a>(&'a mut self, min: Uuid) -> Box<dyn DoubleEndedIterator<Item = Uuid> + 'a> {
Box::new(
self.0
.store
.reports
.open_reports_newer_than(min)
.filter_map(move |report_id| self.0.filter_report(report_id)),
)
}
fn from_start<'a>(&'a mut self) -> Box<dyn DoubleEndedIterator<Item = Uuid> + 'a> {
Box::new(
self.0
.store
.reports
.open_reports()
.filter_map(move |report_id| self.0.filter_report(report_id)),
)
}
}
impl<'b> Pagination for ClosedPager<'b> {
fn from_max<'a>(&'a mut self, max: Uuid) -> Box<dyn DoubleEndedIterator<Item = Uuid> + 'a> {
Box::new(
self.0
.store
.reports
.closed_reports_older_than(max)
.filter_map(move |report_id| self.0.filter_report(report_id)),
)
}
fn from_min<'a>(&'a mut self, min: Uuid) -> Box<dyn DoubleEndedIterator<Item = Uuid> + 'a> {
Box::new(
self.0
.store
.reports
.closed_reports_newer_than(min)
.filter_map(move |report_id| self.0.filter_report(report_id)),
)
}
fn from_start<'a>(&'a mut self) -> Box<dyn DoubleEndedIterator<Item = Uuid> + 'a> {
Box::new(
self.0
.store
.reports
.closed_reports()
.filter_map(move |report_id| self.0.filter_report(report_id)),
)
}
}
impl<'b> ReportPager<'b> {
fn filter_report(&mut self, report_id: Uuid) -> Option<Uuid> {
if !self.reports.contains_key(&report_id) {
let report = self.store.reports.by_id(report_id).ok()??;
if let Some(id) = report.reporter_profile() {
self.cache_profile(id)?;
}
match report.kind() {
ReportKind::Profile => {
self.cache_profile(report.item())?;
}
ReportKind::Submission => {
self.cache_submission(report.item())?;
}
ReportKind::Comment => {
self.cache_comment(report.item())?;
}
ReportKind::Post => {
unimplemented!();
}
}
self.reports.insert(report.id(), report);
Some(report_id)
} else {
None
}
}
fn cache_comment(&mut self, comment_id: Uuid) -> Option<()> {
if !self.comments.contains_key(&comment_id) {
let comment = self.store.comments.by_id(comment_id).ok()??;
self.cache_profile(comment.profile_id())?;
self.comments.insert(comment.id(), comment);
}
Some(())
}
fn cache_submission(&mut self, submission_id: Uuid) -> Option<()> {
if !self.submissions.contains_key(&submission_id) {
let submission = self.store.submissions.by_id(submission_id).ok()??;
self.cache_profile(submission.profile_id())?;
for file_id in submission.files() {
self.cache_file(*file_id)?;
}
self.submissions.insert(submission.id(), submission);
}
Some(())
}
fn cache_profile(&mut self, profile_id: Uuid) -> Option<()> {
if !self.profiles.contains_key(&profile_id) {
let profile = self.store.profiles.by_id(profile_id).ok()??;
for file_id in profile.icon().into_iter().chain(profile.banner()) {
self.cache_file(file_id)?;
}
self.profiles.insert(profile.id(), profile);
}
Some(())
}
fn cache_file(&mut self, file_id: Uuid) -> Option<()> {
if !self.files.contains_key(&file_id) {
let file = self.store.files.by_id(file_id).ok()??;
self.files.insert(file.id(), file);
}
Some(())
}
}
impl<'b> SearchPagination for FederatedPager<'b> {
fn from_term<'a>(&'a mut self, _: &'a str) -> Box<dyn DoubleEndedIterator<Item = Uuid> + 'a> {
Box::new(
self.0
.store
.view
.server_follows
.forward_iter(self.0.self_id)
.chain(
self.0
.store
.view
.server_follows
.backward_iter(self.0.self_id),
)
.filter_map(move |server_id| self.0.filter_server(server_id))
.rev(),
)
}
}
impl<'b> SearchPagination for InboundPager<'b> {
fn from_term<'a>(&'a mut self, _: &'a str) -> Box<dyn DoubleEndedIterator<Item = Uuid> + 'a> {
Box::new(
self.0
.store
.view
.server_follow_requests
.forward_iter(self.0.self_id)
.filter_map(move |server_id| self.0.filter_server(server_id))
.rev(),
)
}
}
impl<'b> SearchPagination for OutboundPager<'b> {
fn from_term<'a>(&'a mut self, _: &'a str) -> Box<dyn DoubleEndedIterator<Item = Uuid> + 'a> {
Box::new(
self.0
.store
.view
.server_follow_requests
.backward_iter(self.0.self_id)
.filter_map(move |server_id| self.0.filter_server(server_id))
.rev(),
)
}
}
impl<'b> SearchPagination for BlockedPager<'b> {
fn from_term<'a>(&'a mut self, _: &'a str) -> Box<dyn DoubleEndedIterator<Item = Uuid> + 'a> {
Box::new(
self.0
.store
.view
.server_blocks
.backward_iter(self.0.self_id)
.filter_map(move |server_id| self.0.filter_server(server_id))
.rev(),
)
}
}
impl<'b> SearchPagination for KnownPager<'b> {
fn from_term<'a>(&'a mut self, _: &'a str) -> Box<dyn DoubleEndedIterator<Item = Uuid> + 'a> {
Box::new(
self.0
.store
.servers
.known()
.filter_map(move |server_id| self.0.filter_server(server_id))
.rev(),
)
}
}
impl<'b> ServerPager<'b> {
fn filter_server(&mut self, server_id: Uuid) -> Option<Uuid> {
if !self.servers.contains_key(&server_id) {
let server = self.store.servers.by_id(server_id).ok()??;
self.servers.insert(server.id(), server);
Some(server_id)
} else {
None
}
}
}