Skip to content

Commit

Permalink
Merge pull request #504 from Stremio/feat/update-last-watched-on-mark…
Browse files Browse the repository at this point in the history
…-actions

Feat: update last watched on mark actions
  • Loading branch information
elpiel authored Aug 21, 2023
2 parents dbd30e1 + 9b03e18 commit c50b0a2
Show file tree
Hide file tree
Showing 12 changed files with 40 additions and 55 deletions.
17 changes: 15 additions & 2 deletions src/models/meta_details.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,21 +88,34 @@ impl<E: Env + 'static> UpdateWithCtx<E> for MetaDetails {
true => library_item.state.times_watched + 1,
false => 0,
};
// update the last_watched for the LibraryItem
library_item.state.last_watched = Some(E::now());

Effects::msg(Msg::Internal(Internal::UpdateLibraryItem(library_item)))
.unchanged()
}
_ => Effects::none().unchanged(),
}
}
Msg::Action(Action::MetaDetails(ActionMetaDetails::MarkVideoAsWatched(
video_id,
video,
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);
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(),
};
}
Effects::msg(Msg::Internal(Internal::UpdateLibraryItem(library_item)))
.unchanged()
}
Expand Down
12 changes: 3 additions & 9 deletions src/models/player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -745,7 +745,8 @@ fn library_item_update<E: Env + 'static>(
} => Some(meta_item),
_ => None,
});
let mut library_item = match (library_item, meta_item) {

match (library_item, meta_item) {
(Some(library_item), Some(meta_item)) => {
Some(LibraryItem::from((&meta_item.preview, library_item)))
}
Expand All @@ -754,14 +755,7 @@ fn library_item_update<E: Env + 'static>(
}
(Some(library_item), None) => Some(library_item.to_owned()),
_ => None,
};
if let (Some(library_item), Some(meta_item)) = (&mut library_item, meta_item) {
library_item.state.last_video_released = meta_item
.videos_iter()
.rev()
.find_map(|last_video| last_video.released.to_owned());
};
library_item
}
}
_ => None,
};
Expand Down
10 changes: 8 additions & 2 deletions src/runtime/msg/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use crate::{
api::AuthRequest,
library::LibraryItemId,
profile::Settings as ProfileSettings,
resource::{MetaItemId, MetaItemPreview},
resource::{MetaItemId, MetaItemPreview, Video},
},
};

Expand Down Expand Up @@ -82,8 +82,14 @@ pub enum ActionLibraryByType {
#[derive(Clone, Deserialize, Debug)]
#[serde(tag = "action", content = "args")]
pub enum ActionMetaDetails {
/// Marks the [`LibraryItem`] as watched.
///
/// Applicable when you have single-video (e.g. a movie) and multi-video (e.g. a movie series) item.
MarkAsWatched(bool),
MarkVideoAsWatched(String, bool),
/// Marks the given [`Video`] of the [`LibraryItem`] as watched.
///
/// Applicable only when you have a multi-video (e.g. movie series) item.
MarkVideoAsWatched(Video, bool),
}

#[derive(Clone, Deserialize, Debug)]
Expand Down
10 changes: 6 additions & 4 deletions src/types/library/library_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,12 @@ impl From<(&MetaItemPreview, &LibraryItem)> for LibraryItem {
#[derive(Default, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct LibraryItemState {
/// Indicates the last time this [`LibraryItem`] was watched and:
/// - When we're playing the LibraryItem we're constantly updating the field
/// - Marking the whole [`LibraryItem`] as watched will update the field
/// to the latest released video if `last_watched < released date`.
/// - Marking a video from the [`LibraryItem`] will update the field
/// to the video released date if `last_watched < released date`.
#[serde(default)]
#[serde_as(deserialize_as = "DefaultOnNull<NoneAsEmptyString>")]
pub last_watched: Option<DateTime<Utc>>,
Expand Down Expand Up @@ -142,10 +148,6 @@ pub struct LibraryItemState {
#[serde(default)]
#[serde_as(deserialize_as = "DefaultOnNull<NoneAsEmptyString>")]
pub watched: Option<WatchedField>,
/// Release date of last observed video
#[serde(default)]
#[serde_as(deserialize_as = "DefaultOnNull<NoneAsEmptyString>")]
pub last_video_released: Option<DateTime<Utc>>,
/// Weather or not to receive notification for the given [`LibraryItem`].
///
/// Default: receive notifications
Expand Down
2 changes: 1 addition & 1 deletion src/unit_tests/ctx/add_to_library.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fn actionctx_addtolibrary() {
url, method, body, ..
} if url == "https://api.strem.io/api/datastorePut"
&& method == "POST"
&& body == "{\"authKey\":\"auth_key\",\"collection\":\"libraryItem\",\"changes\":[{\"_id\":\"id\",\"name\":\"name\",\"type\":\"type\",\"poster\":null,\"posterShape\":\"poster\",\"removed\":false,\"temp\":false,\"_ctime\":\"2020-01-01T00:00:00Z\",\"_mtime\":\"2020-01-01T00:00:00Z\",\"state\":{\"lastWatched\":\"2020-01-01T00:00:00Z\",\"timeWatched\":0,\"timeOffset\":0,\"overallTimeWatched\":0,\"timesWatched\":0,\"flaggedWatched\":0,\"duration\":0,\"video_id\":null,\"watched\":null,\"lastVideoReleased\":null,\"noNotif\":false},\"behaviorHints\":{\"defaultVideoId\":null,\"featuredVideoId\":null,\"hasScheduledVideos\":false}}]}" =>
&& body == "{\"authKey\":\"auth_key\",\"collection\":\"libraryItem\",\"changes\":[{\"_id\":\"id\",\"name\":\"name\",\"type\":\"type\",\"poster\":null,\"posterShape\":\"poster\",\"removed\":false,\"temp\":false,\"_ctime\":\"2020-01-01T00:00:00Z\",\"_mtime\":\"2020-01-01T00:00:00Z\",\"state\":{\"lastWatched\":\"2020-01-01T00:00:00Z\",\"timeWatched\":0,\"timeOffset\":0,\"overallTimeWatched\":0,\"timesWatched\":0,\"flaggedWatched\":0,\"duration\":0,\"video_id\":null,\"watched\":null,\"noNotif\":false},\"behaviorHints\":{\"defaultVideoId\":null,\"featuredVideoId\":null,\"hasScheduledVideos\":false}}]}" =>
{
future::ok(Box::new(APIResult::Ok {
result: SuccessResponse { success: True {} },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@
"timeOffset": 100,
"duration": 101,
"video_id": "tt1:1:5",
"lastVideoReleased": "2020-01-01T00:00:00.000Z",
"noNotif": false
}
}
Expand Down
11 changes: 1 addition & 10 deletions src/unit_tests/ctx/notifications/update_notifications.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,9 +230,6 @@ fn test_pull_notifications_and_play_in_player() {
time_offset: 100,
duration: 101,
video_id: Some("tt1:1:5".to_string()),
last_video_released: Some(
Utc.with_ymd_and_hms(2020, 1, 1, 0, 0, 0).unwrap(),
),
no_notif: false,
},
behavior_hints: Default::default(),
Expand Down Expand Up @@ -448,9 +445,6 @@ fn test_dismiss_notification() {
duration: 55 * 60 * 60 * 1000,
video_id: Some("tt1:1".into()),
watched: None,
last_video_released: Some(
Utc.with_ymd_and_hms(2023, 7, 10, 0, 0, 0).unwrap(),
),
no_notif: false,
},
behavior_hints: Default::default(),
Expand All @@ -477,9 +471,6 @@ fn test_dismiss_notification() {
duration: 55 * 60 * 60 * 1000,
video_id: Some("tt1:1".into()),
watched: None,
last_video_released: Some(
Utc.with_ymd_and_hms(2023, 8, 14, 0, 0, 0).unwrap(),
),
no_notif: false,
},
behavior_hints: Default::default(),
Expand Down Expand Up @@ -510,7 +501,7 @@ fn test_dismiss_notification() {
let runtime = Arc::new(RwLock::new(runtime));
// update now to later date than both last_watched
let expected_last_watched = Utc.with_ymd_and_hms(2023, 8, 14, 0, 0, 0).unwrap();
*NOW.write().unwrap() = expected_last_watched.clone();
*NOW.write().unwrap() = expected_last_watched;

TestEnv::run_with_runtime(
rx,
Expand Down
2 changes: 1 addition & 1 deletion src/unit_tests/ctx/remove_from_library.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ fn actionctx_removefromlibrary() {
url, method, body, ..
} if url == "https://api.strem.io/api/datastorePut"
&& method == "POST"
&& body == "{\"authKey\":\"auth_key\",\"collection\":\"libraryItem\",\"changes\":[{\"_id\":\"id\",\"name\":\"name\",\"type\":\"type\",\"poster\":null,\"posterShape\":\"poster\",\"removed\":true,\"temp\":false,\"_ctime\":\"2020-01-01T00:00:00Z\",\"_mtime\":\"2020-01-02T00:00:00Z\",\"state\":{\"lastWatched\":null,\"timeWatched\":0,\"timeOffset\":0,\"overallTimeWatched\":0,\"timesWatched\":0,\"flaggedWatched\":0,\"duration\":0,\"video_id\":null,\"watched\":null,\"lastVideoReleased\":null,\"noNotif\":false},\"behaviorHints\":{\"defaultVideoId\":null,\"featuredVideoId\":null,\"hasScheduledVideos\":false}}]}" =>
&& body == "{\"authKey\":\"auth_key\",\"collection\":\"libraryItem\",\"changes\":[{\"_id\":\"id\",\"name\":\"name\",\"type\":\"type\",\"poster\":null,\"posterShape\":\"poster\",\"removed\":true,\"temp\":false,\"_ctime\":\"2020-01-01T00:00:00Z\",\"_mtime\":\"2020-01-02T00:00:00Z\",\"state\":{\"lastWatched\":null,\"timeWatched\":0,\"timeOffset\":0,\"overallTimeWatched\":0,\"timesWatched\":0,\"flaggedWatched\":0,\"duration\":0,\"video_id\":null,\"watched\":null,\"noNotif\":false},\"behaviorHints\":{\"defaultVideoId\":null,\"featuredVideoId\":null,\"hasScheduledVideos\":false}}]}" =>
{
future::ok(Box::new(APIResult::Ok {
result: SuccessResponse { success: True {} },
Expand Down
2 changes: 1 addition & 1 deletion src/unit_tests/ctx/rewind_library_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ fn actionctx_rewindlibraryitem() {
url, method, body, ..
} if url == "https://api.strem.io/api/datastorePut"
&& method == "POST"
&& body == "{\"authKey\":\"auth_key\",\"collection\":\"libraryItem\",\"changes\":[{\"_id\":\"id\",\"name\":\"name\",\"type\":\"type\",\"poster\":null,\"posterShape\":\"poster\",\"removed\":false,\"temp\":false,\"_ctime\":\"2020-01-01T00:00:00Z\",\"_mtime\":\"2020-01-02T00:00:00Z\",\"state\":{\"lastWatched\":null,\"timeWatched\":0,\"timeOffset\":0,\"overallTimeWatched\":0,\"timesWatched\":0,\"flaggedWatched\":0,\"duration\":0,\"video_id\":null,\"watched\":null,\"lastVideoReleased\":null,\"noNotif\":false},\"behaviorHints\":{\"defaultVideoId\":null,\"featuredVideoId\":null,\"hasScheduledVideos\":false}}]}" =>
&& body == "{\"authKey\":\"auth_key\",\"collection\":\"libraryItem\",\"changes\":[{\"_id\":\"id\",\"name\":\"name\",\"type\":\"type\",\"poster\":null,\"posterShape\":\"poster\",\"removed\":false,\"temp\":false,\"_ctime\":\"2020-01-01T00:00:00Z\",\"_mtime\":\"2020-01-02T00:00:00Z\",\"state\":{\"lastWatched\":null,\"timeWatched\":0,\"timeOffset\":0,\"overallTimeWatched\":0,\"timesWatched\":0,\"flaggedWatched\":0,\"duration\":0,\"video_id\":null,\"watched\":null,\"noNotif\":false},\"behaviorHints\":{\"defaultVideoId\":null,\"featuredVideoId\":null,\"hasScheduledVideos\":false}}]}" =>
{
future::ok(Box::new(APIResult::Ok {
result: SuccessResponse { success: True {} },
Expand Down
6 changes: 0 additions & 6 deletions src/unit_tests/deep_links/library_item_deep_links.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ fn library_item_deep_links() {
duration: 0,
video_id: None,
watched: None,
last_video_released: None,
no_notif: true,
},
behavior_hints: Default::default(),
Expand Down Expand Up @@ -67,7 +66,6 @@ fn library_item_deep_links_state_video_id_no_time_offset() {
duration: 0,
video_id: Some("video_id".to_string()),
watched: None,
last_video_released: None,
no_notif: true,
},
behavior_hints: Default::default(),
Expand Down Expand Up @@ -105,7 +103,6 @@ fn library_item_deep_links_state_video_id() {
duration: 0,
video_id: Some("video_id".to_string()),
watched: None,
last_video_released: None,
no_notif: true,
},
behavior_hints: Default::default(),
Expand Down Expand Up @@ -145,7 +142,6 @@ fn library_item_deep_links_behavior_hints_default_video_id() {
duration: 0,
video_id: None,
watched: None,
last_video_released: None,
no_notif: true,
},
behavior_hints: MetaItemBehaviorHints {
Expand Down Expand Up @@ -187,7 +183,6 @@ fn library_item_deep_links_state_and_behavior_hints_default_video_id() {
duration: 0,
video_id: Some("video_id".to_string()),
watched: None,
last_video_released: None,
no_notif: true,
},
behavior_hints: MetaItemBehaviorHints {
Expand Down Expand Up @@ -229,7 +224,6 @@ fn library_item_deep_links_state_no_time_offset_and_behavior_hints_default_video
duration: 0,
video_id: Some("video_id".to_string()),
watched: None,
last_video_released: None,
no_notif: true,
},
behavior_hints: MetaItemBehaviorHints {
Expand Down
4 changes: 1 addition & 3 deletions src/unit_tests/serde/default_tokens_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ impl DefaultTokens for LibraryItemState {
vec![
Token::Struct {
name: "LibraryItemState",
len: 11,
len: 10,
},
Token::Str("lastWatched"),
Token::None,
Expand All @@ -44,8 +44,6 @@ impl DefaultTokens for LibraryItemState {
Token::None,
Token::Str("watched"),
Token::None,
Token::Str("lastVideoReleased"),
Token::None,
Token::Str("noNotif"),
Token::Bool(false),
Token::StructEnd,
Expand Down
18 changes: 3 additions & 15 deletions src/unit_tests/serde/library_item_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ fn library_item_state() {
duration: 1,
video_id: Some("tt2934286:1:5".to_owned()),
watched: Some("tt2934286:1:5:5:eJyTZwAAAEAAIA==".parse().unwrap()),
last_video_released: Some(Utc.with_ymd_and_hms(2020, 1, 1, 0, 0, 0).unwrap()),
no_notif: true,
},
LibraryItemState {
Expand All @@ -29,15 +28,14 @@ fn library_item_state() {
duration: 0,
video_id: None,
watched: None,
last_video_released: None,
no_notif: false,
},
],
&[
Token::Seq { len: Some(2) },
Token::Struct {
name: "LibraryItemState",
len: 11,
len: 10,
},
Token::Str("lastWatched"),
Token::Some,
Expand All @@ -60,15 +58,12 @@ fn library_item_state() {
Token::Str("watched"),
Token::Some,
Token::Str("tt2934286:1:5:5:eJyTZwAAAEAAIA=="),
Token::Str("lastVideoReleased"),
Token::Some,
Token::Str("2020-01-01T00:00:00Z"),
Token::Str("noNotif"),
Token::Bool(true),
Token::StructEnd,
Token::Struct {
name: "LibraryItemState",
len: 11,
len: 10,
},
Token::Str("lastWatched"),
Token::None,
Expand All @@ -88,8 +83,6 @@ fn library_item_state() {
Token::None,
Token::Str("watched"),
Token::None,
Token::Str("lastVideoReleased"),
Token::None,
Token::Str("noNotif"),
Token::Bool(false),
Token::StructEnd,
Expand All @@ -108,7 +101,6 @@ fn library_item_state() {
duration: 0,
video_id: None,
watched: None,
last_video_released: None,
no_notif: false,
},
LibraryItemState {
Expand All @@ -121,7 +113,6 @@ fn library_item_state() {
duration: 0,
video_id: None,
watched: None,
last_video_released: None,
no_notif: false,
},
],
Expand All @@ -148,7 +139,7 @@ fn library_item_state() {
Token::StructEnd,
Token::Struct {
name: "LibraryItemState",
len: 11,
len: 10,
},
Token::Str("lastWatched"),
Token::Some,
Expand All @@ -171,9 +162,6 @@ fn library_item_state() {
Token::Str("watched"),
Token::Some,
Token::Str(""),
Token::Str("lastVideoReleased"),
Token::Some,
Token::Str(""),
Token::Str("noNotif"),
Token::Bool(false),
Token::StructEnd,
Expand Down

0 comments on commit c50b0a2

Please sign in to comment.