Skip to content

Fix tvOS Storage#1876

Merged
JPKribs merged 11 commits into
jellyfin:mainfrom
LePips:fix-tvos-storage
Apr 19, 2026
Merged

Fix tvOS Storage#1876
JPKribs merged 11 commits into
jellyfin:mainfrom
LePips:fix-tvos-storage

Conversation

@LePips

@LePips LePips commented Dec 27, 2025

Copy link
Copy Markdown
Member

This does a bit of work around data storage, performing the following migrations:

  • V3 schema that migrates the servers and users to just arrays in AnyData
    • Performs manual V1 -> V2 -> V3 migrations
  • tvOS now only has defaults storage
  • StoredValues can now have defaults or SQL storage
    • tvOS will just always use defaults
    • I frankly now doubt the necessity of having different storages and may just move back to defaults later

To help with tvOS memory pressure and overall data maintenance, we will need to implement periodic cleanup of redundant stored values and proper deletion/reset of user settings.

@JPKribs

JPKribs commented Apr 18, 2026

Copy link
Copy Markdown
Member

Hey, not to sidetrack you but it might be worth looking at some of the changes here:

#1888

Primarily just the UserDto values for:

  • isHidePlayedInLatest | Home View
  • isDisplayMissingEpisodes | Item View for Seasons
  • enableNextEpisodeAutoPlay | Player UI + Video Player Settings

Just so we're not migrating these over. These are settings saved on the UserDto on server so it might make sense to drop those stored values in favor of using their server values so it's synced between clients and we don't have to manage them locally.

@LePips

LePips commented Apr 18, 2026

Copy link
Copy Markdown
Member Author

Thanks for the consideration, but this work is separate from adding new settings.

@LePips LePips marked this pull request as ready for review April 18, 2026 17:56
@LePips LePips requested a review from JPKribs April 18, 2026 17:56

@JPKribs JPKribs left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One of the items that I am testing is migrating from Main/1.5(1) to this branch. When I do this, I lose my servers with the following errors:

[💥 Critical] Field.Stored#228:subscript(_enclosingInstance:wrapped:storage:) Attempted to access 'StoredUser''s value outside it's designated queue.
CoreData: warning: dynamic accessors failed to find @property implementation for 'ownerID' for entity 'AnyData' while resolving selector 'ownerID' on class '_CoreStore.CoreStoreManagedObject__V3___TtCOO12Swiftfin_iOS13SwiftfinStore2V37AnyData__AnyData'.  Did you remember to declare it @dynamic or @synthesized in the @implementation ?
CoreData: warning: dynamic accessors failed to find @property implementation for 'ownerID' for entity 'AnyData' while resolving selector 'ownerID' on class '_CoreStore.CoreStoreManagedObject__V3___TtCOO12Swiftfin_iOS13SwiftfinStore2V37AnyData__AnyData'.  Did you remember to declare it @dynamic or @synthesized in the @implementation ?
CoreData: warning: dynamic accessors failed to find @property implementation for 'field' for entity 'AnyData' while resolving selector 'field' on class '_CoreStore.CoreStoreManagedObject__V3___TtCOO12Swiftfin_iOS13SwiftfinStore2V37AnyData__AnyData'.  Did you remember to declare it @dynamic or @synthesized in the @implementation ?
CoreData: warning: dynamic accessors failed to find @property implementation for 'field' for entity 'AnyData' while resolving selector 'field' on class '_CoreStore.CoreStoreManagedObject__V3___TtCOO12Swiftfin_iOS13SwiftfinStore2V37AnyData__AnyData'.  Did you remember to declare it @dynamic or @synthesized in the @implementation ?
CoreData: warning: dynamic accessors failed to find @property implementation for 'key' for entity 'AnyData' while resolving selector 'key' on class '_CoreStore.CoreStoreManagedObject__V3___TtCOO12Swiftfin_iOS13SwiftfinStore2V37AnyData__AnyData'.  Did you remember to declare it @dynamic or @synthesized in the @implementation ?
CoreData: warning: dynamic accessors failed to find @property implementation for 'key' for entity 'AnyData' while resolving selector 'key' on class '_CoreStore.CoreStoreManagedObject__V3___TtCOO12Swiftfin_iOS13SwiftfinStore2V37AnyData__AnyData'.  Did you remember to declare it @dynamic or @synthesized in the @implementation ?
Called -[UIContextMenuInteraction updateVisibleMenuWithBlock:] while no context menu is visible. This won't do anything.

This does not exist on a clean install nor on future app usage after the initial wipe. As a note, none of the user settings are lost. Only the server. Once I log back into the server all my settings are back where they were before.

I don't think this is egregious, especially for tvOS, if we document this in the release notes that settings will be lost. If it's possible to migrate that would be ideal though.

/Users/runner/work/Swiftfin/Swiftfin/Shared/Components/Marquee.swift:86:1: error: (redundantEmptyView) Remove redundant else { EmptyView() } branches in SwiftUI result builders.
@JPKribs

JPKribs commented Apr 18, 2026

Copy link
Copy Markdown
Member

Also added the the fix for the linting error. It's unrelated to this PR so idk why SwiftFormat is picking this fight now lol:

aebfbd5

@JPKribs JPKribs left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Settings are now saved at the device level instead of at the user level. So, changing a setting in Jellyfin User A then switching to Jellyfin User B will give me Jellyfin User A's settings. If I change something in Jellyfin User B, the setting will update for Jellyfin User A.

On tvOS, this is the same but switching Apple TV users I have different settings. That tradeoff seems correct.

Again, this doesn't seem like a dealbreaker but this changes all settings to be device settings opposed to Jellyfin User settings. Checking some other apps, this is how most other apps do this as well so this could be ideal.

This would also prevent us from the tvOS issue where StoredValues were N*size for usage since we have a smaller size limit there.

Mostly just FYI / is the above intentional

@JPKribs

JPKribs commented Apr 18, 2026

Copy link
Copy Markdown
Member

Alright sorry about that! I've wrapped up testing and this all looks and works as expected with our 2 caveats:

  1. The Server & User don't migrate from Main to this branch. Settings persist but you need to log back in in my testing.
  2. Settings are saved by the Device-User now. I think the is the appropriate way to do this for tvOS but this means that changing settings for separate Jellyfin users will update it for all users on device.

Other than these two, this looks and works as expected! I think even 2 seems to reflect what a lot of other apps I have do as well so this is likely just 1).

@LePips

LePips commented Apr 19, 2026

Copy link
Copy Markdown
Member Author

Thanks for the thorough testing!

When I do this, I lose my servers

This was due to a mis-casing of keys between swiftfinApp and SwiftfinApp when retrieving the servers and users.

Settings are now saved at the device level instead of at the user level.

This is the same issue as I've noticed earlier, where it's not "per device" but that the settings would reflect the "first signed in user during the current app session". This was caused by having views being made once now with NavigationRoute. Additionally, the defaults keys should have been computed variables as well anyways.

@LePips LePips requested a review from JPKribs April 19, 2026 03:04

@JPKribs JPKribs left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the same issue as #1935 (comment), where it's not "per device" but that the settings would reflect the "first signed in user during the current app session". This was caused by having views being made once now with NavigationRoute. Additionally, the defaults keys should have been computed variables as well anyways.

Ah! This makes sense and your changes now resolve this as well!

Migration is working as expected now as well! Looks great!

@JPKribs JPKribs merged commit 2d9789b into jellyfin:main Apr 19, 2026
4 checks passed
@RespectIsEverything

Copy link
Copy Markdown

Wow. Congrats!!

@JPKribs JPKribs added the release highlight Major feature or fix that should be highlighted in TestFlight's "What to Test" section. label Apr 20, 2026
@LePips LePips deleted the fix-tvos-storage branch April 24, 2026 18:14
@JPKribs JPKribs mentioned this pull request May 24, 2026
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

crash This issue results in a crash release highlight Major feature or fix that should be highlighted in TestFlight's "What to Test" section. tvOS Impacts tvOS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Logged Out Between Sessions [TVOS]

3 participants