Skip to content

Commit

Permalink
feat: implement dismissed events bucket
Browse files Browse the repository at this point in the history
  • Loading branch information
tymmesyde committed Dec 13, 2023
1 parent 39fb65e commit 720ece5
Show file tree
Hide file tree
Showing 29 changed files with 410 additions and 118 deletions.
3 changes: 2 additions & 1 deletion src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub const LIBRARY_RECENT_STORAGE_KEY: &str = "library_recent";
pub const STREAMS_STORAGE_KEY: &str = "streams";
pub const SEARCH_HISTORY_STORAGE_KEY: &str = "search_history";
pub const NOTIFICATIONS_STORAGE_KEY: &str = "notifications";
pub const DISMISSED_EVENTS_STORAGE_KEY: &str = "dismissed_events";
pub const LIBRARY_COLLECTION_NAME: &str = "libraryItem";
pub const SEARCH_EXTRA_NAME: &str = "search";
/// `https://{ADDON_UR}/meta/...` resource
Expand All @@ -32,7 +33,7 @@ pub const NOTIFICATION_ITEMS_COUNT: usize = 100;
pub const WATCHED_THRESHOLD_COEF: f64 = 0.7;
pub const CREDITS_THRESHOLD_COEF: f64 = 0.9;
/// The latest migration scheme version
pub const SCHEMA_VERSION: u32 = 11;
pub const SCHEMA_VERSION: u32 = 12;
pub const IMDB_LINK_CATEGORY: &str = "imdb";
pub const GENRES_LINK_CATEGORY: &str = "Genres";
pub const CINEMETA_TOP_CATALOG_ID: &str = "top";
Expand Down
15 changes: 13 additions & 2 deletions src/models/ctx/ctx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::types::api::{
fetch_api, APIRequest, APIResult, AuthRequest, AuthResponse, CollectionResponse,
DatastoreCommand, DatastoreRequest, LibraryItemsResponse, SuccessResponse,
};
use crate::types::events::Events;
use crate::types::events::{DismissedEventsBucket, Events};
use crate::types::library::LibraryBucket;
use crate::types::notifications::NotificationsBucket;
use crate::types::profile::{Auth, AuthKey, Profile};
Expand Down Expand Up @@ -48,6 +48,8 @@ pub struct Ctx {
#[serde(skip)]
pub search_history: SearchHistoryBucket,
#[serde(skip)]
pub dismissed_events: DismissedEventsBucket,
#[serde(skip)]
#[cfg_attr(test, derivative(Default(value = "CtxStatus::Ready")))]
pub status: CtxStatus,
#[serde(skip)]
Expand All @@ -65,12 +67,14 @@ impl Ctx {
streams: StreamsBucket,
notifications: NotificationsBucket,
search_history: SearchHistoryBucket,
dismissed_events: DismissedEventsBucket,
) -> Self {
Self {
profile,
library,
streams,
search_history,
dismissed_events,
notifications,
trakt_addon: None,
notification_catalogs: vec![],
Expand Down Expand Up @@ -103,6 +107,8 @@ impl<E: Env + 'static> Update<E> for Ctx {
let streams_effects = update_streams::<E>(&mut self.streams, &self.status, msg);
let search_history_effects =
update_search_history::<E>(&mut self.search_history, &self.status, msg);
let events_effects =
update_events::<E>(&mut self.events, &mut self.dismissed_events, msg);
let trakt_addon_effects = update_trakt_addon::<E>(
&mut self.trakt_addon,
&self.profile,
Expand All @@ -125,6 +131,7 @@ impl<E: Env + 'static> Update<E> for Ctx {
.join(library_effects)
.join(streams_effects)
.join(search_history_effects)
.join(events_effects)
.join(trakt_addon_effects)
.join(notifications_effects)
}
Expand All @@ -150,6 +157,8 @@ impl<E: Env + 'static> Update<E> for Ctx {
let streams_effects = update_streams::<E>(&mut self.streams, &self.status, msg);
let search_history_effects =
update_search_history::<E>(&mut self.search_history, &self.status, msg);
let events_effects =
update_events::<E>(&mut self.events, &mut self.dismissed_events, msg);
let ctx_effects = match &self.status {
CtxStatus::Loading(loading_auth_request)
if loading_auth_request == auth_request =>
Expand Down Expand Up @@ -177,6 +186,7 @@ impl<E: Env + 'static> Update<E> for Ctx {
.join(trakt_addon_effects)
.join(notifications_effects)
.join(search_history_effects)
.join(events_effects)
.join(ctx_effects)
}
_ => {
Expand All @@ -201,7 +211,8 @@ impl<E: Env + 'static> Update<E> for Ctx {
);
let search_history_effects =
update_search_history::<E>(&mut self.search_history, &self.status, msg);
let events_effects = update_events::<E>(&mut self.events, msg);
let events_effects =
update_events::<E>(&mut self.events, &mut self.dismissed_events, msg);
profile_effects
.join(library_effects)
.join(streams_effects)
Expand Down
101 changes: 93 additions & 8 deletions src/models/ctx/update_events.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
use chrono::DateTime;
use enclose::enclose;
use futures::{future, FutureExt, TryFutureExt};

use crate::constants::DISMISSED_EVENTS_STORAGE_KEY;
use crate::models::common::{eq_update, Loadable};
use crate::models::ctx::CtxError;
use crate::runtime::msg::{Action, ActionCtx, Internal, Msg};
use crate::runtime::msg::{Action, ActionCtx, Event, Internal, Msg};
use crate::runtime::{Effect, EffectFuture, Effects, Env, EnvFutureExt};
use crate::types::api::{
fetch_api, APIRequest, APIResult, GetModalResponse, GetNotificationResponse,
};
use crate::types::events::Events;
use crate::types::events::{DismissedEventsBucket, Events};

pub fn update_events<E: Env + 'static>(events: &mut Events, msg: &Msg) -> Effects {
pub fn update_events<E: Env + 'static>(
events: &mut Events,
dismissed_events: &mut DismissedEventsBucket,
msg: &Msg,
) -> Effects {
match msg {
Msg::Action(Action::Ctx(ActionCtx::Logout)) | Msg::Internal(Internal::Logout) => {
let next_dismissed_events = DismissedEventsBucket::default();
*dismissed_events = next_dismissed_events;
Effects::msg(Msg::Internal(Internal::DismissedEventsChanged))
}
Msg::Action(Action::Ctx(ActionCtx::GetEvents)) => {
let modal_effects = eq_update(&mut events.modal, Loadable::Loading);
let notification_effects = eq_update(&mut events.notification, Loadable::Loading);
Expand All @@ -21,17 +32,72 @@ pub fn update_events<E: Env + 'static>(events: &mut Events, msg: &Msg) -> Effect
.join(notification_effects)
.join(requests_effects)
}
Msg::Action(Action::Ctx(ActionCtx::DismissEvent(id))) => {
dismissed_events
.items
.insert(id.to_owned(), DateTime::from(E::now()));

let message_effects = Effects::one(Effect::Msg(Box::new(Msg::Internal(
Internal::DismissedEventsChanged,
))));

let events_modal_effects = match events.modal.as_ref() {
Loadable::Ready(result) => match result {
Some(GetModalResponse { id, .. })
if dismissed_events.items.contains_key(id) =>
{
eq_update(&mut events.modal, Loadable::Ready(None))
}
_ => Effects::none().unchanged(),
},
_ => Effects::none().unchanged(),
};

let events_notification_effects = match events.notification.as_ref() {
Loadable::Ready(result) => match result {
Some(GetNotificationResponse { id, .. })
if dismissed_events.items.contains_key(id) =>
{
eq_update(&mut events.notification, Loadable::Ready(None))
}
_ => Effects::none().unchanged(),
},
_ => Effects::none().unchanged(),
};

message_effects
.join(events_modal_effects)
.join(events_notification_effects)
}
Msg::Internal(Internal::GetModalResult(_, result)) => match result {
Ok(response) => eq_update(&mut events.modal, Loadable::Ready(response.to_owned())),
Ok(response) => match response {
Some(GetModalResponse { id, .. }) if !dismissed_events.items.contains_key(id) => {
eq_update(&mut events.modal, Loadable::Ready(response.to_owned()))
}
_ => eq_update(&mut events.modal, Loadable::Ready(response.to_owned())),
},
Err(error) => eq_update(&mut events.modal, Loadable::Err(error.to_owned())),
},
Msg::Internal(Internal::GetNotificationResult(_, result)) => match result {
Ok(response) => eq_update(
&mut events.notification,
Loadable::Ready(response.to_owned()),
),
Ok(response) => match response {
Some(GetNotificationResponse { id, .. })
if !dismissed_events.items.contains_key(id) =>
{
eq_update(
&mut events.notification,
Loadable::Ready(response.to_owned()),
)
}
_ => eq_update(
&mut events.notification,
Loadable::Ready(response.to_owned()),
),
},
Err(error) => eq_update(&mut events.notification, Loadable::Err(error.to_owned())),
},
Msg::Internal(Internal::DismissedEventsChanged) => {
Effects::one(push_dismissed_events_to_storage::<E>(dismissed_events)).unchanged()
}
_ => Effects::none().unchanged(),
}
}
Expand Down Expand Up @@ -71,3 +137,22 @@ fn get_notification<E: Env + 'static>() -> Effect {
)
.into()
}

fn push_dismissed_events_to_storage<E: Env + 'static>(
dismissed_events: &DismissedEventsBucket,
) -> Effect {
EffectFuture::Sequential(
E::set_storage(DISMISSED_EVENTS_STORAGE_KEY, Some(&dismissed_events))
.map(
enclose!((dismissed_events.uid => uid) move |result| match result {
Ok(_) => Msg::Event(Event::DismissedEventsPushedToStorage { uid }),
Err(error) => Msg::Event(Event::Error {
error: CtxError::from(error),
source: Box::new(Event::DismissedEventsPushedToStorage { uid }),
})
}),
)
.boxed_env(),
)
.into()
}
39 changes: 33 additions & 6 deletions src/runtime/env.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::addon_transport::{AddonHTTPTransport, AddonTransport, UnsupportedTransport};
use crate::constants::{
LIBRARY_RECENT_STORAGE_KEY, LIBRARY_STORAGE_KEY, PROFILE_STORAGE_KEY, SCHEMA_VERSION,
SCHEMA_VERSION_STORAGE_KEY, SEARCH_HISTORY_STORAGE_KEY, STREAMS_STORAGE_KEY,
DISMISSED_EVENTS_STORAGE_KEY, LIBRARY_RECENT_STORAGE_KEY, LIBRARY_STORAGE_KEY,
PROFILE_STORAGE_KEY, SCHEMA_VERSION, SCHEMA_VERSION_STORAGE_KEY, SEARCH_HISTORY_STORAGE_KEY,
STREAMS_STORAGE_KEY,
};
use crate::models::ctx::Ctx;
use crate::models::streaming_server::StreamingServer;
Expand Down Expand Up @@ -244,6 +245,12 @@ pub trait Env {
.await?;
schema_version = 11;
}
if schema_version == 11 {
migrate_storage_schema_to_v12::<Self>()
.map_err(|error| EnvError::StorageSchemaVersionUpgrade(Box::new(error)))
.await?;
schema_version = 12;
}
if schema_version != SCHEMA_VERSION {
panic!(
"Storage schema version must be upgraded from {} to {}",
Expand Down Expand Up @@ -529,6 +536,12 @@ fn migrate_storage_schema_to_v11<E: Env>() -> TryEnvFuture<()> {
.boxed_env()
}

fn migrate_storage_schema_to_v12<E: Env>() -> TryEnvFuture<()> {
E::set_storage::<()>(DISMISSED_EVENTS_STORAGE_KEY, None)
.and_then(|_| E::set_storage(SCHEMA_VERSION_STORAGE_KEY, Some(&12)))
.boxed_env()
}

#[cfg(test)]
mod test {
use serde_json::{json, Value};
Expand All @@ -540,8 +553,9 @@ mod test {
runtime::{
env::{
migrate_storage_schema_to_v10, migrate_storage_schema_to_v11,
migrate_storage_schema_to_v6, migrate_storage_schema_to_v7,
migrate_storage_schema_to_v8, migrate_storage_schema_to_v9,
migrate_storage_schema_to_v12, migrate_storage_schema_to_v6,
migrate_storage_schema_to_v7, migrate_storage_schema_to_v8,
migrate_storage_schema_to_v9,
},
Env,
},
Expand Down Expand Up @@ -581,7 +595,7 @@ mod test {
);
}

fn assert_storage_shema_version(schema_v: u32) {
fn assert_storage_schema_version(schema_v: u32) {
let storage = STORAGE.read().expect("Should lock");

assert_eq!(
Expand Down Expand Up @@ -926,7 +940,7 @@ mod test {
.expect("Should migrate");

{
assert_storage_shema_version(10);
assert_storage_schema_version(10);
}
}

Expand Down Expand Up @@ -970,4 +984,17 @@ mod test {
);
}
}

#[tokio::test]
async fn test_migration_from_11_to_12() {
let _test_env_guard = TestEnv::reset().expect("Should lock TestEnv");

migrate_storage_schema_to_v12::<TestEnv>()
.await
.expect("Should migrate");

{
assert_storage_schema_version(12);
}
}
}
2 changes: 2 additions & 0 deletions src/runtime/msg/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ pub enum ActionCtx {
PullNotifications,
/// Make request to api to get events modal and notification
GetEvents,
/// Dismiss an event
DismissEvent(String),
}

#[derive(Clone, Deserialize, Debug)]
Expand Down
3 changes: 3 additions & 0 deletions src/runtime/msg/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ pub enum Event {
NotificationsPushedToStorage {
ids: Vec<String>,
},
DismissedEventsPushedToStorage {
uid: UID,
},
UserPulledFromAPI {
uid: UID,
},
Expand Down
2 changes: 2 additions & 0 deletions src/runtime/msg/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,6 @@ pub enum Internal {
APIRequest,
Result<Option<GetNotificationResponse>, CtxError>,
),
/// When dismissed events changed
DismissedEventsChanged,
}
21 changes: 21 additions & 0 deletions src/types/events/dimissed_events_bucket.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use std::collections::HashMap;

use chrono::{DateTime, Local};
use serde::{Deserialize, Serialize};

use crate::types::profile::UID;

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct DismissedEventsBucket {
pub uid: UID,
pub items: HashMap<String, DateTime<Local>>,
}

impl DismissedEventsBucket {
pub fn new(uid: UID) -> Self {
Self {
uid,
items: HashMap::new(),
}
}
}
3 changes: 3 additions & 0 deletions src/types/events/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
mod dimissed_events_bucket;
pub use dimissed_events_bucket::*;

mod events;
pub use events::*;
3 changes: 3 additions & 0 deletions src/unit_tests/catalog_with_filters/load_action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::models::ctx::Ctx;
use crate::runtime::msg::{Action, ActionLoad};
use crate::runtime::{EnvFutureExt, Runtime, RuntimeAction, RuntimeEvent, TryEnvFuture};
use crate::types::addon::{ExtraValue, ResourcePath, ResourceRequest, ResourceResponse};
use crate::types::events::DismissedEventsBucket;
use crate::types::library::LibraryBucket;
use crate::types::notifications::NotificationsBucket;
use crate::types::profile::Profile;
Expand Down Expand Up @@ -51,6 +52,7 @@ fn default_catalog() {
StreamsBucket::default(),
NotificationsBucket::new::<TestEnv>(None, vec![]),
SearchHistoryBucket::default(),
DismissedEventsBucket::default(),
);
let (discover, effects) = CatalogWithFilters::<MetaItemPreview>::new(&ctx.profile);
let (runtime, rx) = Runtime::<TestEnv, _>::new(
Expand Down Expand Up @@ -151,6 +153,7 @@ fn search_catalog() {
StreamsBucket::default(),
NotificationsBucket::new::<TestEnv>(None, vec![]),
SearchHistoryBucket::default(),
DismissedEventsBucket::default(),
);
let (discover, effects) = CatalogWithFilters::<MetaItemPreview>::new(&ctx.profile);
let (runtime, rx) = Runtime::<TestEnv, _>::new(
Expand Down
Loading

0 comments on commit 720ece5

Please sign in to comment.