Skip to content

Conversation

@FastZet
Copy link

@FastZet FastZet commented Oct 16, 2025

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

…ting

Increment schema version from 19 to 20 and add migration function to support the new auto_rotate_player setting in the Settings struct.

The migration automatically adds autoRotatePlayer: true to existing users' stored settings, ensuring backward compatibility when they upgrade. New users will receive this value from the Settings::default() implementation.

Changes:
- Update SCHEMA_VERSION constant from 19 to 20 in constants.rs
- Add migrate_storage_schema_to_v20 function to env.rs
- Insert v20 migration check in the migration chain
- Update serialization tests in default_tokens_ext.rs

This migration preserves all existing user settings while adding the new field required for PWA rotation control functionality.

Relates to stremio-web#787
Fix two compilation errors introduced in the previous commit:
- Add missing generic parameter to migrate_storage_schema_to_v20
  function signature (TryEnvFuture -> TryEnvFuture<()>)
- Add auto_rotate_player field to Settings test struct in
  unit_tests/serde/settings.rs

These changes ensure the codebase compiles successfully and all
tests pass after the v20 schema migration implementation.

Relates to stremio-web#787
Fix a compilation error introduced in the previous commit:
- Add autoRotatePlayer tokens to settings serialization tests

This change ensure the codebase compiles successfully and all
tests pass after the v20 schema migration implementation.

Relates to stremio-web#787
@kKaskak
Copy link
Member

kKaskak commented Oct 16, 2025

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

@FastZet FastZet marked this pull request as draft October 17, 2025 04:32
@FastZet
Copy link
Author

FastZet commented Oct 17, 2025

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 FastZet marked this pull request as ready for review October 17, 2025 07:06
@FastZet
Copy link
Author

FastZet commented Oct 17, 2025

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.

@kKaskak kKaskak self-requested a review October 17, 2025 10:55
@kKaskak kKaskak changed the title feat: Add auto_rotate_player setting for PWA rotation control (#787) Feat: Add Rotation setting for PWA to local storage Oct 17, 2025
@kKaskak kKaskak changed the title Feat: Add Rotation setting for PWA to local storage Feat: Add auto rotation setting for PWA to local storage Oct 17, 2025
@kKaskak kKaskak requested a review from elpiel October 17, 2025 10:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants