Skip to content

Fix observe order#2761

Closed
Luna712 wants to merge 2 commits intorecloudstream:masterfrom
Luna712:fix-observe
Closed

Fix observe order#2761
Luna712 wants to merge 2 commits intorecloudstream:masterfrom
Luna712:fix-observe

Conversation

@Luna712
Copy link
Copy Markdown
Contributor

@Luna712 Luna712 commented May 4, 2026

Fixes #2746
Closes #2750

@fire-light42
Copy link
Copy Markdown
Collaborator

This still relies on unproven semantics. I feel like we need to refactor this part rather than patching it. I will take a closer look on how we can solve this correctly.

@Luna712
Copy link
Copy Markdown
Contributor Author

Luna712 commented May 4, 2026

Fair enough and yeah it does. I just thought a better fix then relying on .value, as simply changing observe order and couldn't reproduce the issue anymore but yeah it is still just a patch fix. I didnt really like either but this one just felt "safer" and more reliable then the other way.

@fire-light42
Copy link
Copy Markdown
Collaborator

Fair enough and yeah it does. I just thought a better fix then relying on .value, as simply changing observe order and couldn't reproduce the issue anymore but yeah it is still just a patch fix. I didnt really like either but this one just felt "safer" and more reliable then the other way.

I will possibly make a pull request tomorrow, but the core idea is to have some immutable state to store all data needed to display the video. This state can then be efficiently modified using a persistent data type, and avoid concurrency issues by having it copy the data structure. We can then have a single source of truth for the entire player that exists within the viewmodel and can be exposed with e.g. ConsistentLiveData for both observe and .value without any issues.

typealias VideoLink = Pair<ExtractorLink?, ExtractorUri?>

/** Immutable state of all current links relevant to displaying the video */
data class VideoState(
    val subtitles: PersistentSet<SubtitleData>,
    val links: PersistentSet<VideoLink>,
    val stamps: PersistentSet<VideoSkipStamp>
) {
    /** This acts as a local cache for sorted links that are not copied over by the copy constructor */
    private val sortedLinks: ConcurrentHashMap<Int, List<VideoLink>> = ConcurrentHashMap()

    fun sortLinks(qualityProfile: Int) : List<VideoLink> {
        return sortedLinks[qualityProfile] ?: links.sortedBy { link ->
            // negative because we want to sort highest quality first
            -getLinkPriority(qualityProfile, link.first)
        }.also { value -> sortedLinks[qualityProfile] = value }
    }

    fun add(item: SubtitleData): VideoState = copy(subtitles = subtitles.add(item))
    fun add(item: VideoLink): VideoState = copy(links = links.add(item))
    fun add(item: VideoSkipStamp): VideoState = copy(stamps = stamps.add(item))
    fun add(items: Collection<SubtitleData>): VideoState = copy(subtitles = subtitles.addAll(items))
    fun add(items: Collection<VideoLink>): VideoState = copy(links = links.addAll(items))
    fun add(items: Collection<VideoSkipStamp>): VideoState = copy(stamps = stamps.addAll(items))
}

@Luna712 Luna712 closed this May 5, 2026
@Luna712 Luna712 deleted the fix-observe branch May 5, 2026 22:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

No Links Found bug in DownloadedPlayerActivity

2 participants