From eb422c5a5f849e76797b057113504ee90556c5b9 Mon Sep 17 00:00:00 2001 From: Tim Date: Sat, 7 Dec 2024 14:41:18 +0100 Subject: [PATCH] feat: add player MarkVideoAsWatched action --- src/models/meta_details.rs | 15 +----- src/models/player.rs | 53 ++++++++++--------- src/runtime/msg/action.rs | 6 +++ src/types/library/library_item.rs | 22 ++++++++ .../src/model/serialize_player.rs | 14 ++--- 5 files changed, 61 insertions(+), 49 deletions(-) diff --git a/src/models/meta_details.rs b/src/models/meta_details.rs index 47a995999..76b68e341 100644 --- a/src/models/meta_details.rs +++ b/src/models/meta_details.rs @@ -123,20 +123,9 @@ impl UpdateWithCtx for MetaDetails { is_watched, ))) => match (&self.library_item, &self.watched) { (Some(library_item), Some(watched)) => { - let mut watched = watched.to_owned(); - watched.set_video(&video.id, *is_watched); let mut library_item = library_item.to_owned(); - library_item.state.watched = Some(watched.into()); - if *is_watched { - library_item.state.last_watched = - match (&library_item.state.last_watched, &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(), - }; - } + library_item.mark_video_as_watched::(watched, video, *is_watched); + Effects::msg(Msg::Internal(Internal::UpdateLibraryItem(library_item))) .unchanged() } diff --git a/src/models/player.rs b/src/models/player.rs index e5576e923..4c87a7851 100644 --- a/src/models/player.rs +++ b/src/models/player.rs @@ -658,6 +658,31 @@ impl UpdateWithCtx for Player { })) .unchanged() } + Msg::Action(Action::Player(ActionPlayer::MarkVideoAsWatched(video, is_watched))) => { + match (&self.library_item, &self.watched) { + (Some(library_item), Some(watched)) => { + let mut library_item = library_item.to_owned(); + library_item.mark_video_as_watched::(watched, video, *is_watched); + + Effects::msg(Msg::Internal(Internal::UpdateLibraryItem(library_item))) + .unchanged() + } + _ => Effects::none().unchanged(), + } + } + Msg::Internal(Internal::LibraryChanged(_)) => { + let library_item_effects = library_item_update::( + &mut self.library_item, + &self.selected, + &self.meta_item, + &ctx.library, + ); + + let watched_effects = + watched_update(&mut self.watched, &self.meta_item, &self.library_item); + + library_item_effects.join(watched_effects) + } Msg::Internal(Internal::StreamsChanged(_)) => { stream_state_update(&mut self.stream_state, &self.selected, &ctx.streams) } @@ -1052,10 +1077,7 @@ fn library_item_update( meta_request: Some(meta_request), .. }) => { - let library_item = library_item - .as_ref() - .filter(|library_item| library_item.id == meta_request.path.id) - .or_else(|| library.items.get(&meta_request.path.id)); + let library_item = library.items.get(&meta_request.path.id); let meta_item = meta_item.as_ref().and_then(|meta_item| match meta_item { ResourceLoadable { content: Some(Loadable::Ready(meta_item)), @@ -1077,28 +1099,7 @@ fn library_item_update( } _ => None, }; - if *library_item != next_library_item { - let update_library_item_effects = match &library_item { - Some(library_item) => Effects::msg(Msg::Internal(Internal::UpdateLibraryItem( - library_item.to_owned(), - ))) - .unchanged(), - _ => Effects::none().unchanged(), - }; - let update_next_library_item_effects = match &next_library_item { - Some(next_library_item) => Effects::msg(Msg::Internal(Internal::UpdateLibraryItem( - next_library_item.to_owned(), - ))) - .unchanged(), - _ => Effects::none().unchanged(), - }; - *library_item = next_library_item; - Effects::none() - .join(update_library_item_effects) - .join(update_next_library_item_effects) - } else { - Effects::none().unchanged() - } + eq_update(library_item, next_library_item) } fn watched_update( diff --git a/src/runtime/msg/action.rs b/src/runtime/msg/action.rs index 70cecee2d..15b6c5692 100644 --- a/src/runtime/msg/action.rs +++ b/src/runtime/msg/action.rs @@ -191,6 +191,12 @@ pub enum ActionPlayer { /// - We've watched a movie to the last second /// - We've watched a movie series to the last second Ended, + /// Marks the given [`Video`] of the [`LibraryItem`] as watched. + /// + /// Applicable only when you have a multi-video (e.g. movie series) item. + /// + /// [`LibraryItem`]: crate::types::library::LibraryItem + MarkVideoAsWatched(Video, bool), } #[derive(Clone, Deserialize, Debug)] diff --git a/src/types/library/library_item.rs b/src/types/library/library_item.rs index d771ebed2..3d1143bc6 100644 --- a/src/types/library/library_item.rs +++ b/src/types/library/library_item.rs @@ -106,6 +106,28 @@ impl LibraryItem { self.state.times_watched = 0; } } + + pub fn mark_video_as_watched( + &mut self, + watched: &WatchedBitField, + video: &Video, + is_watched: bool, + ) { + let mut watched = watched.to_owned(); + 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, &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 From<(&MetaItemPreview, PhantomData)> for LibraryItem { diff --git a/stremio-core-web/src/model/serialize_player.rs b/stremio-core-web/src/model/serialize_player.rs index f712a4717..67e930963 100644 --- a/stremio-core-web/src/model/serialize_player.rs +++ b/stremio-core-web/src/model/serialize_player.rs @@ -146,16 +146,10 @@ pub fn serialize_player( video, upcoming: meta_item.preview.behavior_hints.has_scheduled_videos && video.released > Some(E::now()), - watched: ctx - .library - .items - .get(&meta_item.preview.id) - .map(|library_item| { - library_item - .state - .watched_bitfield(&meta_item.videos) - .get_video(&video.id) - }) + watched: player + .watched + .as_ref() + .map(|watched| watched.get_video(&video.id)) .unwrap_or_default(), // only the currently playing video can have the progress // as we keep that information in the LibraryItem