stremio-core icon indicating copy to clipboard operation
stremio-core copied to clipboard

Feat: Add auto rotation setting for PWA to local storage

Open FastZet opened this issue 2 months ago • 3 comments

Description

Adds auto_rotate_player boolean setting to control screen rotation behavior in the Stremio PWA.

Changes

  • Added auto_rotate_player field to Settings struct with default value true
  • Implemented schema migration v19 → v20 to add setting to existing user profiles
  • Updated serialization tests in default_tokens_ext.rs and settings.rs
  • All changes maintain backward compatibility

Testing

  • ✅ All 191 unit tests pass
  • ✅ All 15 doc tests pass
  • ✅ Schema migration tested (v19 → v20)
  • ✅ Code compiles successfully

Implementation Notes

This PR implements the backend portion of the rotation control feature. The setting:

  • Defaults to true (maintains current auto-rotate behavior)
  • Is stored in user profile settings
  • Will be consumed by stremio-web to control the Screen Orientation API

Frontend implementation in stremio-web will follow to:

  • Read profile.settings.autoRotatePlayer
  • Call screen.orientation.lock('landscape') when true
  • Call screen.orientation.unlock() when false

Related Issues

Part 1 of Stremio/stremio-web/issues/787

FastZet avatar Oct 16 '25 09:10 FastZet

hi there, thanks for the PR you will need to make some changes for the builds to pass run cargo fmt and then run cargo clippy and commit the lint changes

thank you

PS: you could rename the field to something like: pwa_auto_rotation since this will apply for the whole app not only the player

kKaskak avatar Oct 16 '25 11:10 kKaskak

cargo fmt

Warning: can't set format_code_in_doc_comments = true, unstable features are only available in nightly channel. Warning: can't set format_code_in_doc_comments = true, unstable features are only available in nightly channel. Warning: can't set format_code_in_doc_comments = true, unstable features are only available in nightly channel. Warning: can't set format_code_in_doc_comments = true, unstable features are only available in nightly channel.

cargo clippy

Checking stremio-core v0.1.0 (/workspaces/stremio-core) Finished dev [unoptimized + debuginfo] target(s) in 5.32s

cargo test

Compiling stremio-core v0.1.0 (/workspaces/stremio-core) Finished test [unoptimized + debuginfo] target(s) in 11.16s Running unittests src/lib.rs (target/debug/deps/stremio_core-d61412ff8a264f7d)

running 191 tests test addon_transport::http_transport::legacy::test::query_meta ... ok test addon_transport::http_transport::legacy::test::query_stream ... ok test addon_transport::http_transport::legacy::test::catalog ... ok test addon_transport::http_transport::legacy::test::stream_imdb ... ok test addon_transport::http_transport::legacy::test::subtitles_only_id ... ok test addon_transport::http_transport::legacy::test::subtitles_with_hash ... ok test deep_links::error_link::tests::error_link ... ok test models::addon_details::test::test_deserialization_of_select ... ok test models::library_with_filters::test::test_watched_and_not_watched_sort_items_ordering_of_library_items ... ok test models::local_search::test::test_imdb_rating_parsing ... ok test models::player::tests::test_underflow_calculate_outro ... ok test models::local_search::test::test_deserialization_of_searchable ... ok test runtime::effects::test::test_effects_defaults ... ok test runtime::env::test::test_migration_from_10_to_11 ... ok test runtime::env::test::test_migration_from_11_to_12 ... ok test runtime::env::test::test_migration_from_12_to_13 ... ok test runtime::env::test::test_migration_from_13_to_14 ... ok test runtime::env::test::test_migration_from_15_to_16 ... ok test runtime::env::test::test_migration_from_14_to_15 ... ok test runtime::env::test::test_migration_from_16_to_17 ... ok test runtime::env::test::test_migration_from_17_to_18 ... ok test runtime::env::test::test_migration_from_18_to_19 ... ok test runtime::env::test::test_migration_from_6_to_7 ... ok test runtime::env::test::test_migration_from_7_to_8 ... ok test runtime::env::test::test_migration_from_8_to_9 ... ok test runtime::env::test::test_migration_from_5_to_6 ... ok test runtime::env::test::test_migration_from_9_to_10 ... ok test types::api::request::tests::test_versioning_of_api_fetch_request_params ... ok test types::addon::response::tests::test_response_deserialization_keys ... ok test runtime::env::test::test_migration_to_latest_version ... ok test types::api::response::test::deserialization_of_api_response_with_path_and_without ... ok test types::api::response::test::deserialize_skip_gaps_response ... ok test types::serde_as_ext::tests::test_bool_as_option ... ok test types::resource::stream::tests::test_stream_url_source_with_proxy_headers_to_streaming_url ... ok test types::serde_ext::empty_string_as_null::test::test_empty_field ... ok test types::serde_ext::empty_string_as_null::test::test_field ... ok test types::torrent::tests::test_info_has_for_zero_sized_chunk ... ok test types::streaming_server::response::test::test_server_settings_response_deserialization ... ok test unit_tests::calendar::load_action::calendar ... ok test unit_tests::catalog_with_filters::load_action::default_catalog ... ok test unit_tests::catalog_with_filters::load_action::search_catalog ... ok test unit_tests::ctx::add_to_library::actionctx_addtolibrary ... ok test unit_tests::ctx::add_to_library::actionctx_addtolibrary_already_added ... ok test unit_tests::ctx::authenticate::actionctx_authenticate_apple ... ok test unit_tests::ctx::authenticate::actionctx_authenticate_facebook ... ok test unit_tests::ctx::authenticate::actionctx_authenticate_login ... ok test unit_tests::ctx::authenticate::actionctx_authenticate_login_with_token ... ok test unit_tests::ctx::authenticate::actionctx_authenticate_register ... ok test unit_tests::ctx::delete_account::actionctx_delete_account ... ok test unit_tests::ctx::install_addon::actionctx_installaddon_already_installed ... ok test unit_tests::ctx::install_addon::actionctx_installaddon_install ... ok test unit_tests::ctx::install_addon::actionctx_installaddon_install_with_user ... ok test unit_tests::ctx::install_addon::actionctx_installaddon_update ... ok test unit_tests::ctx::logout::actionctx_logout ... ok test unit_tests::ctx::notifications::update_notifications::test_dismiss_notification ... ok test unit_tests::ctx::notifications::update_notifications::test_pull_notifications_and_play_in_player ... ok test unit_tests::ctx::notifications::update_notifications::test_pull_notifications_test_cases ... ok test unit_tests::ctx::pull_addons_from_api::actionctx_pulladdonsfromapi ... ok test unit_tests::ctx::pull_addons_from_api::actionctx_pulladdonsfromapi_with_user ... ok test unit_tests::ctx::push_addons_to_api::actionctx_pushaddonstoapi ... ok test unit_tests::ctx::push_addons_to_api::actionctx_pushaddonstoapi_with_user ... ok test unit_tests::ctx::remove_from_library::actionctx_removefromlibrary ... ok test unit_tests::ctx::remove_from_library::actionctx_removefromlibrary_not_added ... ok test unit_tests::ctx::rewind_library_item::actionctx_rewindlibraryitem ... ok test unit_tests::ctx::rewind_library_item::actionctx_rewindlibraryitem_not_added ... ok test unit_tests::ctx::sync_library_with_api::actionctx_synclibrarywithapi_with_user_empty_library ... ok test unit_tests::ctx::uninstall_addon::actionctx_uninstalladdon ... ok test models::streaming_server::tests::test_magnet_hash ... ok test unit_tests::ctx::sync_library_with_api::actionctx_synclibrarywithapi_with_user ... ok test unit_tests::ctx::sync_library_with_api::actionctx_synclibrarywithapi ... ok test unit_tests::ctx::uninstall_addon::actionctx_uninstalladdon_not_installed ... ok test unit_tests::ctx::uninstall_addon::actionctx_uninstalladdon_protected ... ok test unit_tests::ctx::uninstall_addon::actionctx_uninstalladdon_streams_bucket ... ok test unit_tests::ctx::uninstall_addon::actionctx_uninstalladdon_with_user ... ok test unit_tests::ctx::update_events::test_dismissed_events ... ok test unit_tests::ctx::update_events::test_events ... ok test unit_tests::ctx::update_events::test_stored_dismissed_events ... ok test unit_tests::ctx::update_search_history::test_search_history_clear_items ... ok test unit_tests::ctx::update_search_history::test_search_history_update ... ok test unit_tests::ctx::update_settings::actionctx_updatesettings ... ok test unit_tests::ctx::update_settings::actionctx_updatesettings_not_changed ... ok test unit_tests::ctx::update_streaming_server_urls::test_add_server_url ... ok test unit_tests::ctx::update_streaming_server_urls::test_delete_server_url ... ok test unit_tests::ctx::upgrade_addon::actionctx_addon_upgrade ... ok test unit_tests::deep_links::addons_deep_links::addons_deep_links_installed_addons_request_no_type ... ok test unit_tests::deep_links::addons_deep_links::addons_deep_links_installed_addons_request_type ... ok test unit_tests::ctx::upgrade_addon::actionctx_addon_upgrade_fail_due_to_different_url ... ok test unit_tests::deep_links::addons_deep_links::addons_deep_links_request ... ok test unit_tests::deep_links::discover_deep_links::discover_deep_links ... ok test unit_tests::data_export::data_export_with_user ... ok test unit_tests::deep_links::external_player_link::external_player_link_external ... ok test unit_tests::data_export::data_export_without_a_user ... ok test unit_tests::deep_links::external_player_link::external_player_link_http ... ok test unit_tests::deep_links::external_player_link::external_player_link_player_frame ... ok test unit_tests::deep_links::external_player_link::external_player_link_torrent ... ok test unit_tests::deep_links::external_player_link::external_player_link_with_infuse ... ok test unit_tests::deep_links::external_player_link::external_player_link_with_justplayer ... ok test unit_tests::deep_links::external_player_link::external_player_link_with_outplayer ... ok test unit_tests::deep_links::external_player_link::external_player_link_with_mxplayer ... ok test unit_tests::deep_links::library_deep_links::library_deep_links_request_no_type ... ok test unit_tests::deep_links::external_player_link::external_player_link_magnet ... ok test unit_tests::deep_links::library_deep_links::library_deep_links_request_type ... ok test unit_tests::deep_links::library_deep_links::library_deep_links_string ... ok test unit_tests::deep_links::external_player_link::external_player_link_with_vlc_player ... ok test unit_tests::deep_links::external_player_link::external_player_link_youtube ... ok test unit_tests::deep_links::library_item_deep_links::library_item_deep_links_no_video ... ok test unit_tests::deep_links::library_item_deep_links::library_item_deep_links_behavior_hints_default_video_id ... ok test unit_tests::deep_links::library_item_deep_links::library_item_deep_links_state_and_behavior_hints_default_video_id ... ok test unit_tests::deep_links::library_item_deep_links::library_item_deep_links_state_no_time_offset_and_behavior_hints_default_video_id ... ok test unit_tests::deep_links::meta_item_deep_links::meta_item_deep_links ... ok test unit_tests::deep_links::meta_item_deep_links::meta_item_deep_links_behavior_hints ... ok test unit_tests::deep_links::search_history_item_deep_links::search_history_item_deep_links ... ok test unit_tests::deep_links::library_item_deep_links::library_item_deep_links_state_video_id_no_time_offset_infuse_player ... ok test unit_tests::deep_links::library_item_deep_links::library_item_deep_links_state_video_id ... ok test unit_tests::deep_links::stream_deep_links::stream_deep_links_external ... ok test unit_tests::deep_links::stream_deep_links::stream_deep_links_http ... ok test unit_tests::deep_links::meta_item_deep_links::meta_item_deep_links_behavior_hints_yt_id ... ok test unit_tests::deep_links::stream_deep_links::stream_deep_links_http_with_request_headers ... ok test unit_tests::deep_links::stream_deep_links::stream_deep_links_http_with_request_response_headers_and_query_params ... ok test unit_tests::deep_links::stream_deep_links::stream_deep_links_player_frame ... ok test unit_tests::deep_links::stream_deep_links::stream_deep_links_requests ... ok test unit_tests::deep_links::stream_deep_links::stream_deep_links_magnet ... ok test unit_tests::deep_links::stream_deep_links::stream_deep_links_torrent ... ok test unit_tests::deep_links::stream_deep_links::stream_deep_links_torrent_without_file_index ... ok test unit_tests::deep_links::stream_deep_links::stream_deep_links_youtube ... ok test unit_tests::link::create_link_code ... ok test unit_tests::meta_details::override_selected::override_selected_default_video_id ... ok test unit_tests::deep_links::video_deep_links::video_deep_links ... ok test unit_tests::serde::api_error::api_error ... ok test unit_tests::serde::api_result::api_result ... ok test unit_tests::serde::api_request::api_request ... ok test unit_tests::serde::auth_key::auth_key ... ok test unit_tests::serde::auth::auth ... ok test unit_tests::serde::auth_request::auth_request ... ok test unit_tests::serde::auth_response::auth_response ... ok test unit_tests::meta_details::override_selected::override_selected_meta_id ... ok test unit_tests::serde::collection_response::cft_test::collection_response ... ok test unit_tests::serde::datastore_command::datastore_command ... ok test unit_tests::serde::datastore_request::datastore_request ... ok test unit_tests::serde::descriptor_flags::descriptor_flags ... ok test unit_tests::serde::extra_prop::extra_prop ... ok test unit_tests::serde::descriptor_preview::descriptor_preview ... ok test unit_tests::serde::extra_value::extra_value ... ok test unit_tests::serde::descriptor::descriptor ... ok test unit_tests::serde::gdpr_consent::gdpr_consent ... ok test unit_tests::serde::library_bucket::library_bucket ... ok test unit_tests::serde::library_bucket_ref::library_bucket_ref ... ok test unit_tests::serde::library_item_modified::library_item_modified ... ok test unit_tests::serde::link::link ... ok test unit_tests::serde::library_item::library_item ... ok test unit_tests::serde::link_code_response::link_code_response ... ok test unit_tests::serde::link_data_response::link_data_response ... ok test unit_tests::player::next_stream::next_stream ... ok test unit_tests::serde::manifest_behavior_hints::manifest_behavior_hints ... ok test unit_tests::serde::manifest::manifest ... ok test unit_tests::serde::manifest_catalog::manifest_catalog ... ok test unit_tests::serde::manifest_extra::manifest_extra ... ok test unit_tests::serde::manifest_resource::manifest_resource ... ok test unit_tests::serde::manifest_preview::manifest_preview ... ok test unit_tests::serde::meta_item::meta_item_de_urls_none_when_empty ... ok test unit_tests::serde::meta_item_behavior_hints::meta_item_behavior_hints ... ok test unit_tests::serde::library_item_state::library_item_state ... ok test unit_tests::serde::meta_item::meta_item ... ok test unit_tests::serde::meta_item_preview::meta_item_preview_de ... ok test unit_tests::serde::meta_item_preview::meta_item_preview_de_null ... ok test unit_tests::serde::meta_item_preview::meta_item_preview_de_minimal ... ok test unit_tests::serde::meta_item_preview::meta_item_preview_de_ignore_legacy_when_links ... ok test unit_tests::serde::meta_item_preview::meta_item_preview_de_numeric_imdb ... ok test unit_tests::serde::meta_item_preview::meta_item_preview_serialize ... ok test unit_tests::serde::poster_shape::poster_shape ... ok test unit_tests::serde::meta_item_preview::meta_item_preview_de_legacy_links ... ok test unit_tests::serde::r#true::r#true ... ok test unit_tests::serde::resource_path::resource_path ... ok test unit_tests::serde::resource_request::resource_request ... ok test unit_tests::serde::series_info::series_info ... ok test unit_tests::serde::profile::profile ... ok test unit_tests::serde::resource_response::resource_response ... ok test unit_tests::serde::settings::settings_de ... ok test unit_tests::serde::settings::settings ... ok test unit_tests::serde::stream::stream ... ok test unit_tests::serde::stream_source::stream_source_from_json ... ok test unit_tests::serde::subtitles::subtitles ... ok test unit_tests::serde::success_response::success_response ... ok test unit_tests::serde::stream_source::stream_source ... ok test unit_tests::serde::user::user ... ok test unit_tests::serde::video::various_videos_deserialization ... ok test unit_tests::serde::video::videos_minimal ... ok test unit_tests::serde::video::video ... ok test unit_tests::serde::video::videos_released_equal ... ok test unit_tests::serde::video::videos_released_sequal ... ok test unit_tests::streaming_server::remote_endpoint::remote_endpoint ... ok

test result: ok. 191 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.07s

Doc-tests stremio-core

running 15 tests test src/models/common/compare_with_priorities.rs - models::common::compare_with_priorities::compare_with_priorities (line 10) ... ok test src/runtime/effects.rs - runtime::effects::Effects (line 21) ... ok test src/types/addon/manifest.rs - types::addon::manifest::Manifest::resources (line 49) ... ok test src/types/addon/manifest.rs - types::addon::manifest::Manifest::resources (line 65) ... ok test src/types/addon/manifest.rs - types::addon::manifest::ManifestResource (line 192) ... ok test src/runtime/msg/action.rs - runtime::msg::action::ActionCtx::PullUserFromAPI (line 60) ... ok test src/types/addon/response.rs - types::addon::response::ResourceResponse::Metas (line 93) ... ok test src/types/resource/meta_item.rs - types::resource::meta_item::MetaItemPreview (line 107) ... ok test src/types/resource/stream.rs - types::resource::stream::Stream (line 24) ... ok test src/types/addon/response.rs - types::addon::response::ResourceResponseCache (line 26) ... ok test src/types/resource/stream.rs - types::resource::stream::StreamSource (line 316) ... ok test src/types/resource/stream.rs - types::resource::stream::StreamSource (line 372) ... ok test src/types/serde_as_ext.rs - types::serde_as_ext::DefaultOnBool (line 132) ... ok test src/types/torrent.rs - types::torrent::InfoHash (line 9) ... ok test src/types/streaming_server/mod.rs - types::streaming_server::CreatedTorrent (line 28) ... ok

test result: ok. 15 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 6.96s

cargo fmt -- --check

Warning: can't set format_code_in_doc_comments = true, unstable features are only available in nightly channel. Warning: can't set format_code_in_doc_comments = true, unstable features are only available in nightly channel. Warning: can't set format_code_in_doc_comments = true, unstable features are only available in nightly channel. Warning: can't set format_code_in_doc_comments = true, unstable features are only available in nightly channel.

cargo check --all

Compiling stremio-derive v0.1.0 (/workspaces/stremio-core/stremio-derive) Checking stremio-watched-bitfield v0.1.0 (/workspaces/stremio-core/stremio-watched-bitfield) Checking stremio-core v0.1.0 (/workspaces/stremio-core) Checking stremio-core-web v0.49.4 (/workspaces/stremio-core/stremio-core-web) Finished dev [unoptimized + debuginfo] target(s) in 7.10s

cargo clippy --all --no-deps

Compiling stremio-derive v0.1.0 (/workspaces/stremio-core/stremio-derive) Checking stremio-watched-bitfield v0.1.0 (/workspaces/stremio-core/stremio-watched-bitfield) Checking stremio-core v0.1.0 (/workspaces/stremio-core) Checking stremio-core-web v0.49.4 (/workspaces/stremio-core/stremio-core-web) Finished dev [unoptimized + debuginfo] target(s) in 7.08s

FastZet avatar Oct 17 '25 07:10 FastZet

hi there, thanks for the PR you will need to make some changes for the builds to pass run cargo fmt and then run cargo clippy and commit the lint changes

thank you

PS: you could rename the field to something like: pwa_auto_rotation since this will apply for the whole app not only the player

Thanks for your guidance. I had Rust v1.90 installed in the system during the previous PR. After downgrading to v1.77 all checks seemingly passed this time. I have added the output for your perusal.

I have also changed field name as you suggested.

FastZet avatar Oct 17 '25 07:10 FastZet