use std::collections::VecDeque;
use std::future::Future;
use anyhow::Result;
use crate::assets::Assets;
use crate::message::{ErrorMessage, Page};
use crate::model::SeriesId;
use crate::service::{NewSeries, Service};
const ERRORS: usize = 5;
pub(crate) struct State {
pub(crate) service: Service,
pub(crate) assets: Assets,
history: Vec<(Page, f32)>,
history_index: usize,
history_changed: bool,
errors: VecDeque<ErrorMessage>,
saving: bool,
}
impl State {
#[inline]
pub fn new(service: Service, assets: Assets) -> Self {
Self {
service,
assets,
history: vec![(Page::Dashboard, 0.0)],
history_index: 0,
history_changed: false,
errors: VecDeque::new(),
saving: false,
}
}
pub(crate) fn page(&self) -> Option<&Page> {
Some(&self.history.get(self.history_index)?.0)
}
pub(crate) fn push_history(&mut self, page: Page) {
self.assets.clear();
while self.history_index + 1 < self.history.len() {
self.history.pop();
}
self.history.push((page, 0.0));
self.history_index += 1;
self.history_changed = true;
}
pub(crate) fn history_scroll(&mut self, scroll: f32) {
if let Some((_, s)) = self.history.get_mut(self.history_index) {
*s = scroll;
}
}
pub(crate) fn history(&mut self, relative: isize) {
if relative > 0 {
self.history_index = self.history_index.saturating_add(relative as usize);
} else if relative < 0 {
self.history_index = self.history_index.saturating_sub(-relative as usize);
}
self.history_index = self.history_index.min(self.history.len().saturating_sub(1));
self.history_changed = true;
}
pub(crate) fn history_change(&mut self) -> Option<(Page, f32)> {
if !self.history_changed {
return None;
}
self.history_changed = false;
Some(*self.history.get(self.history_index)?)
}
pub(crate) fn handle_error(&mut self, error: ErrorMessage) {
log::error!("error: {error}");
self.saving = false;
self.errors.push_back(error);
if self.errors.len() > ERRORS {
self.errors.pop_front();
}
}
pub(crate) fn remove_series(&mut self, series_id: &SeriesId) {
if matches!(self.page(), Some(Page::Series(id) | Page::Season(id, _)) if *id == *series_id)
{
self.push_history(Page::Dashboard);
}
self.service.remove_series(series_id);
}
pub(crate) fn refresh_series(
&mut self,
series_id: &SeriesId,
) -> Option<impl Future<Output = Result<NewSeries>>> {
let remote_id = self.service.series(series_id)?.remote_id?;
Some(self.service.download_series(&remote_id, false))
}
#[inline]
pub(crate) fn errors(&self) -> impl Iterator<Item = &ErrorMessage> {
self.errors.iter()
}
#[inline]
pub(crate) fn is_saving(&self) -> bool {
self.saving
}
#[inline]
pub(crate) fn set_saving(&mut self, saving: bool) {
self.saving = saving;
}
#[inline]
pub(crate) fn warning_text(&self) -> iced::theme::Text {
crate::style::warning_text(self.service.theme())
}
#[inline]
pub(crate) fn missing_poster(&self) -> iced_native::image::Handle {
self.assets.missing_poster(self.service.theme())
}
}