Skip to content

Commit

Permalink
feat: add mark season as watched for videos
Browse files Browse the repository at this point in the history
  • Loading branch information
tymmesyde committed Jan 22, 2025
1 parent 43e3384 commit bfaff6b
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 0 deletions.
39 changes: 39 additions & 0 deletions src/models/meta_details.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::{borrow::Cow, marker::PhantomData};

use itertools::Itertools;
use serde::{Deserialize, Serialize};

use stremio_watched_bitfield::WatchedBitField;
Expand Down Expand Up @@ -131,6 +132,44 @@ impl<E: Env + 'static> UpdateWithCtx<E> for MetaDetails {
}
_ => Effects::none().unchanged(),
},
Msg::Action(Action::MetaDetails(ActionMetaDetails::MarkSeasonAsWatched(
season,
is_watched,
))) => match (&self.library_item, &self.watched) {
(Some(library_item), Some(watched)) => {
// Find videos of given season from the first ready meta item loadable
let videos = self
.meta_items
.iter()
.find(|meta_item| matches!(&meta_item.content, Some(Loadable::Ready(_))))
.and_then(|meta_item| meta_item.content.as_ref())
.and_then(|meta_item| meta_item.ready())
.map(|meta_item| {
meta_item
.videos
.iter()
.filter(|video| {
video
.series_info
.as_ref()
.is_some_and(|series_info| series_info.season == *season)
})
.collect_vec()
});

match videos {
Some(videos) => {
let mut library_item = library_item.to_owned();
library_item.mark_videos_as_watched::<E>(watched, videos, *is_watched);

Effects::msg(Msg::Internal(Internal::UpdateLibraryItem(library_item)))
.unchanged()
}
None => Effects::none().unchanged(),
}
}
_ => Effects::none().unchanged(),
},
Msg::Internal(Internal::ResourceRequestResult(request, result))
if request.path.resource == META_RESOURCE_NAME =>
{
Expand Down
41 changes: 41 additions & 0 deletions src/models/player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,47 @@ impl<E: Env + 'static> UpdateWithCtx<E> for Player {
_ => Effects::none().unchanged(),
}
}
Msg::Action(Action::Player(ActionPlayer::MarkSeasonAsWatched(season, is_watched))) => {
match (&self.library_item, &self.watched) {
(Some(library_item), Some(watched)) => {
// Find videos of given season from the first ready meta item loadable
let videos = self
.meta_item
.as_ref()
.and_then(|meta_item| meta_item.content.as_ref())
.and_then(|meta_item| meta_item.ready())
.map(|meta_item| {
meta_item
.videos
.iter()
.filter(|video| {
video.series_info.as_ref().is_some_and(|series_info| {
series_info.season == *season
})
})
.collect_vec()
});

match videos {
Some(videos) => {
let mut library_item = library_item.to_owned();
library_item.mark_videos_as_watched::<E>(
watched,
videos,
*is_watched,
);

Effects::msg(Msg::Internal(Internal::UpdateLibraryItem(
library_item,
)))
.unchanged()
}
None => Effects::none().unchanged(),
}
}
_ => Effects::none().unchanged(),
}
}
Msg::Internal(Internal::LibraryChanged(_)) => {
let library_item_effects = library_item_update::<E>(
&mut self.library_item,
Expand Down
4 changes: 4 additions & 0 deletions src/runtime/msg/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ pub enum ActionMetaDetails {
///
/// [`LibraryItem`]: crate::types::library::LibraryItem
MarkVideoAsWatched(Video, bool),
/// Mark all videos from given season as watched
MarkSeasonAsWatched(u32, bool),
}

#[derive(Clone, Deserialize, Debug)]
Expand Down Expand Up @@ -199,6 +201,8 @@ pub enum ActionPlayer {
///
/// [`LibraryItem`]: crate::types::library::LibraryItem
MarkVideoAsWatched(Video, bool),
/// Mark all videos from given season as watched
MarkSeasonAsWatched(u32, bool),
}

#[derive(Clone, Deserialize, Debug)]
Expand Down
28 changes: 28 additions & 0 deletions src/types/library/library_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,34 @@ impl LibraryItem {
};
}
}

pub fn mark_videos_as_watched<E: Env>(
&mut self,
watched: &WatchedBitField,
videos: Vec<&Video>,
is_watched: bool,
) {
let mut watched = watched.to_owned();

for video in &videos {
watched.set_video(&video.id, is_watched);
}

self.state.watched = Some(watched.into());

if is_watched {
self.state.last_watched = match (
&self.state.last_watched,
videos.last().and_then(|last_video| last_video.released),
) {
(Some(last_watched), Some(released)) if last_watched < &released => {
Some(released.to_owned())
}
(None, released) => released.to_owned(),
(last_watched, _) => last_watched.to_owned(),
};
}
}
}

impl<E: Env + 'static> From<(&MetaItemPreview, PhantomData<E>)> for LibraryItem {
Expand Down

0 comments on commit bfaff6b

Please sign in to comment.