From 1d88e8571f26507e7a8da640932ec52b01b76c39 Mon Sep 17 00:00:00 2001 From: TheBeastLT Date: Tue, 26 Sep 2023 18:23:08 +0300 Subject: [PATCH] resolve suggested stream in meta details model --- src/models/meta_details.rs | 104 +++++++++++++++++++++++++++++++++++-- 1 file changed, 100 insertions(+), 4 deletions(-) diff --git a/src/models/meta_details.rs b/src/models/meta_details.rs index 52469242c..70006ea24 100644 --- a/src/models/meta_details.rs +++ b/src/models/meta_details.rs @@ -11,6 +11,7 @@ use crate::types::api::{DatastoreCommand, DatastoreRequest}; use crate::types::library::{LibraryBucket, LibraryItem}; use crate::types::profile::Profile; use crate::types::resource::{MetaItem, Stream}; +use crate::types::streams::{StreamsBucket, StreamsItemKey}; use serde::{Deserialize, Serialize}; use std::borrow::Cow; use std::marker::PhantomData; @@ -30,6 +31,7 @@ pub struct MetaDetails { pub meta_items: Vec>, pub meta_streams: Vec>>, pub streams: Vec>>, + pub suggested_stream: Option, pub library_item: Option, #[serde(skip_serializing)] pub watched: Option, @@ -48,6 +50,14 @@ impl UpdateWithCtx for MetaDetails { meta_streams_update(&mut self.meta_streams, &self.selected, &self.meta_items); let streams_effects = streams_update::(&mut self.streams, &self.selected, &ctx.profile); + let suggested_stream_effects = suggested_stream_update( + &mut self.suggested_stream, + &self.selected, + &self.meta_items, + &self.meta_streams, + &self.streams, + &ctx.streams, + ); let library_item_effects = library_item_update::( &mut self.library_item, &self.selected, @@ -63,6 +73,7 @@ impl UpdateWithCtx for MetaDetails { .join(meta_items_effects) .join(meta_streams_effects) .join(streams_effects) + .join(suggested_stream_effects) .join(library_item_effects) .join(watched_effects) } @@ -72,11 +83,13 @@ impl UpdateWithCtx for MetaDetails { let meta_streams_effects = eq_update(&mut self.meta_streams, vec![]); let streams_effects = eq_update(&mut self.streams, vec![]); let library_item_effects = eq_update(&mut self.library_item, None); + let suggested_stream_effects = eq_update(&mut self.suggested_stream, None); let watched_effects = eq_update(&mut self.watched, None); selected_effects .join(meta_items_effects) .join(meta_streams_effects) .join(streams_effects) + .join(suggested_stream_effects) .join(library_item_effects) .join(watched_effects) } @@ -137,6 +150,14 @@ impl UpdateWithCtx for MetaDetails { }; let meta_streams_effects = meta_streams_update(&mut self.meta_streams, &self.selected, &self.meta_items); + let suggested_stream_effects = suggested_stream_update( + &mut self.suggested_stream, + &self.selected, + &self.meta_items, + &self.meta_streams, + &self.streams, + &ctx.streams, + ); let library_item_effects = library_item_update::( &mut self.library_item, &self.selected, @@ -149,6 +170,7 @@ impl UpdateWithCtx for MetaDetails { .join(meta_items_effects) .join(meta_streams_effects) .join(streams_effects) + .join(suggested_stream_effects) .join(library_item_effects) .join(watched_effects) } @@ -178,6 +200,14 @@ impl UpdateWithCtx for MetaDetails { meta_streams_update(&mut self.meta_streams, &self.selected, &self.meta_items); let streams_effects = streams_update::(&mut self.streams, &self.selected, &ctx.profile); + let suggested_stream_effects = suggested_stream_update( + &mut self.suggested_stream, + &self.selected, + &self.meta_items, + &self.meta_streams, + &self.streams, + &ctx.streams, + ); let library_item_effects = library_item_update::( &mut self.library_item, &self.selected, @@ -189,6 +219,7 @@ impl UpdateWithCtx for MetaDetails { meta_items_effects .join(meta_streams_effects) .join(streams_effects) + .join(suggested_stream_effects) .join(library_item_effects) .join(watched_effects) } @@ -219,10 +250,7 @@ fn selected_override_update( meta_items: &[ResourceLoadable], ) -> Effects { let meta_path = match &selected { - Some(Selected { - meta_path, - stream_path: None, - }) => meta_path, + Some(Selected { meta_path, .. }) => meta_path, _ => return Effects::default(), }; let meta_item = match meta_items @@ -355,6 +383,74 @@ fn streams_update( } } +fn suggested_stream_update( + suggested_stream: &mut Option, + selected: &Option, + meta_items: &[ResourceLoadable], + meta_streams: &[ResourceLoadable>], + streams: &[ResourceLoadable>], + stream_bucket: &StreamsBucket, +) -> Effects { + let next_suggested_stream = match selected { + Some(Selected { + meta_path, + stream_path: Some(stream_path), + }) => { + meta_items + .iter() + .find_map(|meta_item| match &meta_item.content { + Some(Loadable::Ready(meta_item)) => Some(&meta_item.videos), + _ => None, + }) + .and_then(|videos| { + // Check saved stream only for last 30 videos starting from the current video + videos + .iter() + .position(|video| video.id == stream_path.id) + .and_then(|max_index| { + videos[max_index.saturating_sub(30)..=max_index] + .iter() + .rev() + .find_map(|video| { + stream_bucket.items.get(&StreamsItemKey { + meta_id: meta_path.id.to_string(), + video_id: video.id.to_owned(), + }) + }) + }) + }) + .and_then(|stream_item| { + [meta_streams, streams] + .concat() + .iter() + .find(|resource| resource.request.base == stream_item.stream_transport_url) + .and_then(|resource| match &resource.content { + Some(Loadable::Ready(streams)) => Some(streams), + _ => None, + }) + .and_then(|streams| { + streams + .iter() + .find(|stream| *stream == &stream_item.stream) + .or_else(|| { + streams.iter().find(|stream| { + stream.behavior_hints.binge_group.as_deref() + == stream_item + .stream + .behavior_hints + .binge_group + .as_deref() + }) + }) + .cloned() + }) + }) + } + _ => None, + }; + eq_update(suggested_stream, next_suggested_stream) +} + fn library_item_update( library_item: &mut Option, selected: &Option,