< Summary - Jellyfin

Information
Class: MediaBrowser.Controller.Library.VersionPlaybackSelector
Assembly: MediaBrowser.Controller
File(s): /srv/git/jellyfin/MediaBrowser.Controller/Library/VersionPlaybackSelector.cs
Line coverage
100%
Covered lines: 15
Uncovered lines: 0
Coverable lines: 15
Total lines: 59
Line coverage: 100%
Branch coverage
91%
Covered branches: 11
Total branches: 12
Branch coverage: 91.6%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100 7/6/2026 - 12:16:28 AM Line coverage: 100% (15/15) Branch coverage: 91.6% (11/12) Total lines: 59 7/6/2026 - 12:16:28 AM Line coverage: 100% (15/15) Branch coverage: 91.6% (11/12) Total lines: 59

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
SelectMostRecentlyPlayed(...)91.66%1212100%

File(s)

/srv/git/jellyfin/MediaBrowser.Controller/Library/VersionPlaybackSelector.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using MediaBrowser.Controller.Entities;
 4
 5namespace MediaBrowser.Controller.Library
 6{
 7    /// <summary>
 8    /// Single definition of "which alternate version was most recently played" shared by the resume tile
 9    /// (<see cref="IUserDataManager.GetResumeUserData"/>), the media-source default ordering and Next Up.
 10    /// Each call site declares its own eligibility rule so the intentional differences (resumable-only vs.
 11    /// resumable-or-completed) are visible in one place instead of being re-implemented divergently.
 12    /// The SQL resume query keeps its own translation of the same rule.
 13    /// </summary>
 14    public static class VersionPlaybackSelector
 15    {
 16        /// <summary>
 17        /// Selects the entry whose user data has the greatest <see cref="UserItemData.LastPlayedDate"/>,
 18        /// considering only entries that satisfy <paramref name="isEligible"/>. On an exact tie the first
 19        /// encountered entry wins.
 20        /// </summary>
 21        /// <typeparam name="T">The candidate type (e.g. a version item or a media source).</typeparam>
 22        /// <param name="items">The candidates to choose from.</param>
 23        /// <param name="dataSelector">Resolves the user data for a candidate, or <c>null</c> when it has none.</param>
 24        /// <param name="isEligible">Whether a candidate's user data makes it a valid winner.</param>
 25        /// <returns>The most recently played eligible candidate, or <c>default</c> when none qualify.</returns>
 26        public static T? SelectMostRecentlyPlayed<T>(
 27            IEnumerable<T> items,
 28            Func<T, UserItemData?> dataSelector,
 29            Func<UserItemData, bool> isEligible)
 30        {
 331            ArgumentNullException.ThrowIfNull(items);
 332            ArgumentNullException.ThrowIfNull(dataSelector);
 333            ArgumentNullException.ThrowIfNull(isEligible);
 34
 335            T? winner = default;
 336            var winnerDate = DateTime.MinValue;
 337            var hasWinner = false;
 38
 2439            foreach (var item in items)
 40            {
 941                var data = dataSelector(item);
 942                if (data is null || !isEligible(data))
 43                {
 44                    continue;
 45                }
 46
 347                var date = data.LastPlayedDate ?? DateTime.MinValue;
 348                if (!hasWinner || date > winnerDate)
 49                {
 350                    winner = item;
 351                    winnerDate = date;
 352                    hasWinner = true;
 53                }
 54            }
 55
 356            return winner;
 57        }
 58    }
 59}