Skip to content

Commit

Permalink
Merge pull request #750 from Stremio/feat/player-mark-video-as-watched
Browse files Browse the repository at this point in the history
feat: add player MarkVideoAsWatched action
  • Loading branch information
elpiel authored Dec 11, 2024
2 parents 196b655 + eb422c5 commit ef64789
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 49 deletions.
15 changes: 2 additions & 13 deletions src/models/meta_details.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,20 +123,9 @@ impl<E: Env + 'static> UpdateWithCtx<E> 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::<E>(watched, video, *is_watched);

Effects::msg(Msg::Internal(Internal::UpdateLibraryItem(library_item)))
.unchanged()
}
Expand Down
53 changes: 27 additions & 26 deletions src/models/player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,31 @@ impl<E: Env + 'static> UpdateWithCtx<E> 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::<E>(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::<E>(
&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)
}
Expand Down Expand Up @@ -1052,10 +1077,7 @@ fn library_item_update<E: Env + 'static>(
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)),
Expand All @@ -1077,28 +1099,7 @@ fn library_item_update<E: Env + 'static>(
}
_ => 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(
Expand Down
6 changes: 6 additions & 0 deletions src/runtime/msg/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
22 changes: 22 additions & 0 deletions src/types/library/library_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,28 @@ impl LibraryItem {
self.state.times_watched = 0;
}
}

pub fn mark_video_as_watched<E: Env>(
&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<E: Env + 'static> From<(&MetaItemPreview, PhantomData<E>)> for LibraryItem {
Expand Down
14 changes: 4 additions & 10 deletions stremio-core-web/src/model/serialize_player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,16 +146,10 @@ pub fn serialize_player<E: stremio_core::runtime::Env + 'static>(
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
Expand Down

0 comments on commit ef64789

Please sign in to comment.