diff --git a/src/constants.rs b/src/constants.rs index e97b69ad28..d8d134936f 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -42,7 +42,7 @@ pub const NEW_USER_DAYS: chrono::Duration = chrono::Duration::days(30); 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 = 18; +pub const SCHEMA_VERSION: u32 = 19; pub const IMDB_LINK_CATEGORY: &str = "imdb"; pub const GENRES_LINK_CATEGORY: &str = "Genres"; pub const CINEMETA_TOP_CATALOG_ID: &str = "top"; diff --git a/src/runtime/env.rs b/src/runtime/env.rs index 6c6ab119f2..84578d3a53 100644 --- a/src/runtime/env.rs +++ b/src/runtime/env.rs @@ -289,6 +289,12 @@ pub trait Env { .await?; schema_version = 18; } + if schema_version == 18 { + migrate_storage_schema_to_v19::() + .map_err(|error| EnvError::StorageSchemaVersionUpgrade(Box::new(error))) + .await?; + schema_version = 19; + } if schema_version != SCHEMA_VERSION { panic!( "Storage schema version must be upgraded from {} to {}", @@ -688,6 +694,27 @@ fn migrate_storage_schema_to_v18() -> TryEnvFuture<()> { .boxed_env() } +fn migrate_storage_schema_to_v19() -> TryEnvFuture<()> { + E::get_storage::(PROFILE_STORAGE_KEY) + .and_then(|mut profile| { + match profile + .as_mut() + .and_then(|profile| profile.as_object_mut()) + .and_then(|profile| profile.get_mut("settings")) + .and_then(|settings| settings.as_object_mut()) + { + Some(settings) => { + settings.insert("volume".to_owned(), serde_json::Value::from(100)); + settings.insert("playbackSpeed".to_owned(), serde_json::Value::from(1000)); + E::set_storage(PROFILE_STORAGE_KEY, Some(&profile)) + } + _ => E::set_storage::<()>(PROFILE_STORAGE_KEY, None), + } + }) + .and_then(|_| E::set_storage(SCHEMA_VERSION_STORAGE_KEY, Some(&19))) + .boxed_env() +} + #[cfg(test)] mod test { use serde_json::{json, Value}; @@ -702,9 +729,9 @@ mod test { migrate_storage_schema_to_v12, migrate_storage_schema_to_v13, migrate_storage_schema_to_v14, migrate_storage_schema_to_v15, migrate_storage_schema_to_v16, migrate_storage_schema_to_v17, - migrate_storage_schema_to_v18, migrate_storage_schema_to_v6, - migrate_storage_schema_to_v7, migrate_storage_schema_to_v8, - migrate_storage_schema_to_v9, + migrate_storage_schema_to_v18, migrate_storage_schema_to_v19, + migrate_storage_schema_to_v6, migrate_storage_schema_to_v7, + migrate_storage_schema_to_v8, migrate_storage_schema_to_v9, }, Env, }, @@ -1355,4 +1382,46 @@ mod test { ); } } + + #[tokio::test] + async fn test_migration_from_18_to_19() { + { + let _test_env_guard = TestEnv::reset().expect("Should lock TestEnv"); + let profile_before = json!({ + "settings": {} + }); + + let migrated_profile = json!({ + "settings": { + "playbackSpeed": 1000, + "volume": 100, + } + }); + + // setup storage for migration + set_profile_and_schema_version(&profile_before, 18); + + // migrate storage + migrate_storage_schema_to_v19::() + .await + .expect("Should migrate"); + + let storage = STORAGE.read().expect("Should lock"); + + assert_eq!( + &19.to_string(), + storage + .get(SCHEMA_VERSION_STORAGE_KEY) + .expect("Should have the schema set"), + "Scheme version should now be updated" + ); + assert_eq!( + &migrated_profile.to_string(), + storage + .get(PROFILE_STORAGE_KEY) + .expect("Should have the profile set"), + "Profile should match" + ); + } + } } diff --git a/src/types/profile/settings.rs b/src/types/profile/settings.rs index 4aa887a625..2760ac37f3 100644 --- a/src/types/profile/settings.rs +++ b/src/types/profile/settings.rs @@ -43,6 +43,8 @@ pub struct Settings { pub streaming_server_warning_dismissed: Option>, pub server_in_foreground: bool, pub send_crash_reports: bool, + pub volume: u8, + pub playback_speed: i16 } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] @@ -86,6 +88,8 @@ impl Default for Settings { streaming_server_warning_dismissed: None, server_in_foreground: false, send_crash_reports: true, + volume: 100, + playback_speed: 1000 } } } diff --git a/src/types/streams/streams_item.rs b/src/types/streams/streams_item.rs index 79c69870e9..de188ea843 100644 --- a/src/types/streams/streams_item.rs +++ b/src/types/streams/streams_item.rs @@ -46,6 +46,8 @@ pub struct StreamItemState { #[serde(default, skip_serializing_if = "Option::is_none")] pub playback_speed: Option, #[serde(default, skip_serializing_if = "Option::is_none")] + pub volume: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] pub player_type: Option, } @@ -91,7 +93,7 @@ impl StreamsItem { /// a stream for next binge video as audio/subtitle sync might be different, /// but we want to retain track ids as next binge group might have /// the same embedded tracks with same ids; - /// Otherwise retain only playback speed and player type as these should not change + /// Otherwise retain only playback speed, volume and player type as these should not change /// regardless of the video, since you usually want to maintain these throughout /// the whole series; #[inline] @@ -111,6 +113,7 @@ impl StreamsItem { } StreamItemState { playback_speed: state.playback_speed, + volume: state.volume, player_type: state.player_type, ..Default::default() } diff --git a/src/unit_tests/serde/settings.rs b/src/unit_tests/serde/settings.rs index a9d5791ddc..3fcc5911a6 100644 --- a/src/unit_tests/serde/settings.rs +++ b/src/unit_tests/serde/settings.rs @@ -40,6 +40,8 @@ fn settings() { ), server_in_foreground: false, send_crash_reports: true, + playback_speed: 1000, + volume: 100 }, &[ Token::Struct {