mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-06-09 01:08:45 +01:00
Fix version names
This commit is contained in:
@@ -87,9 +87,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
Model.Entities.ExtraType.Short
|
||||
};
|
||||
|
||||
// Separators the naming layer treats as version delimiters (Emby.Naming VideoFlagDelimiters),
|
||||
// used when stripping the shared prefix from an alternate version's media source name.
|
||||
private static readonly char[] VersionSeparators = [' ', '-', '_', '.'];
|
||||
private static readonly char[] VersionDelimiters = ['-', '_', '.'];
|
||||
|
||||
private string _sortName;
|
||||
|
||||
@@ -1235,13 +1233,13 @@ namespace MediaBrowser.Controller.Entities
|
||||
// Prefer the suffix that differs from the other versions: strip the prefix shared by
|
||||
// all sibling files. This works regardless of folder layout, so it also labels episode
|
||||
// versions that share a season folder (e.g. "Greyscale" instead of the full
|
||||
// "Show - S01E02 - Title - Greyscale"). The prefix is already retreated to a separator
|
||||
// "Show - S01E02 - Title - Greyscale"). The prefix is already retreated to a delimiter
|
||||
// boundary (see GetCommonVersionPrefix).
|
||||
if (!string.IsNullOrEmpty(commonPrefix)
|
||||
&& displayName.Length > commonPrefix.Length
|
||||
&& displayName.StartsWith(commonPrefix, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var name = displayName.AsSpan(commonPrefix.Length).TrimStart(VersionSeparators);
|
||||
var name = displayName.AsSpan(commonPrefix.Length).TrimStart([' ', .. VersionDelimiters]);
|
||||
if (!name.IsWhiteSpace())
|
||||
{
|
||||
terms.Add(name.ToString());
|
||||
@@ -1255,7 +1253,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
var containingFolderName = System.IO.Path.GetFileName(ContainingFolderPath);
|
||||
if (displayName.Length > containingFolderName.Length && displayName.StartsWith(containingFolderName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var name = displayName.AsSpan(containingFolderName.Length).TrimStart(VersionSeparators);
|
||||
var name = displayName.AsSpan(containingFolderName.Length).TrimStart([' ', .. VersionDelimiters]);
|
||||
if (!name.IsWhiteSpace())
|
||||
{
|
||||
terms.Add(name.ToString());
|
||||
@@ -1341,11 +1339,14 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
/// <summary>
|
||||
/// Computes the case-insensitive longest common prefix of the supplied version file names,
|
||||
/// retreated to the last separator boundary. Retreating keeps the differing suffix intact:
|
||||
/// retreated to the last delimiter boundary. Retreating keeps the differing suffix intact:
|
||||
/// it avoids slicing through a word every version shares (e.g. "Grey" in "Greyscale" and
|
||||
/// "Greyish") while still trimming the common part when every version is suffixed (e.g.
|
||||
/// "- Greyscale" / "- Colorized"). The separators mirror the version delimiters recognised by
|
||||
/// the naming layer (Emby.Naming VideoFlagDelimiters).
|
||||
/// "- Greyscale" / "- Colorized"). It prefers a structural delimiter ('-', '_', '.') so a
|
||||
/// token shared by the descriptors but separated only by spaces (e.g. a common "2160p ") is
|
||||
/// kept in the label, falling back to a space only when no structural delimiter is shared. The
|
||||
/// separators mirror the version delimiters recognised by the naming layer (Emby.Naming
|
||||
/// VideoFlagDelimiters).
|
||||
/// </summary>
|
||||
/// <param name="fileNames">The version file names without extension; must contain at least one entry.</param>
|
||||
/// <returns>The shared prefix retreated to a separator boundary, or an empty string when none is shared.</returns>
|
||||
@@ -1379,12 +1380,22 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
if (!prefixIsWholeName)
|
||||
{
|
||||
// Retreat to the last structural delimiter ('-', '_', '.').
|
||||
var cut = prefix.Length;
|
||||
while (cut > 0 && Array.IndexOf(VersionSeparators, prefix[cut - 1]) < 0)
|
||||
while (cut > 0 && Array.IndexOf(VersionDelimiters, prefix[cut - 1]) < 0)
|
||||
{
|
||||
cut--;
|
||||
}
|
||||
|
||||
if (cut == 0)
|
||||
{
|
||||
cut = prefix.Length;
|
||||
while (cut > 0 && prefix[cut - 1] != ' ')
|
||||
{
|
||||
cut--;
|
||||
}
|
||||
}
|
||||
|
||||
prefix = prefix[..cut];
|
||||
}
|
||||
|
||||
|
||||
@@ -408,6 +408,19 @@ namespace MediaBrowser.Controller.Entities
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets this video together with all of its alternate versions (local and linked and, when this
|
||||
/// is itself an alternate, the primary and the primary's other versions), deduplicated.
|
||||
/// </summary>
|
||||
/// <returns>This video and every alternate version of it.</returns>
|
||||
public IReadOnlyList<Video> GetAllVersions()
|
||||
{
|
||||
return GetAllItemsForMediaSources()
|
||||
.Select(i => i.Item)
|
||||
.OfType<Video>()
|
||||
.ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the alternate version of this video that matches the supplied item id.
|
||||
/// </summary>
|
||||
@@ -415,10 +428,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
/// <returns>The matching version, or <c>null</c> when the id is not a version of this video.</returns>
|
||||
public Video GetAlternateVersion(Guid itemId)
|
||||
{
|
||||
return GetAllItemsForMediaSources()
|
||||
.Select(i => i.Item)
|
||||
.OfType<Video>()
|
||||
.FirstOrDefault(i => i.Id.Equals(itemId));
|
||||
return GetAllVersions().FirstOrDefault(i => i.Id.Equals(itemId));
|
||||
}
|
||||
|
||||
public override string CreatePresentationUniqueKey()
|
||||
|
||||
@@ -82,6 +82,13 @@ public class BaseItemTests
|
||||
[InlineData("Movie (2020).UHD", "Movie (2020).1080p", "UHD", "1080p")]
|
||||
// Resolution variants that share leading digits must retreat to the separator, not yield "p"/"i".
|
||||
[InlineData("Movie - 1080p", "Movie - 1080i", "1080p", "1080i")]
|
||||
// A token shared by the descriptors but separated only by spaces (the resolution) must stay in the
|
||||
// label: retreat to the '-' delimiter, not the interior space, so the resolution is kept.
|
||||
[InlineData(
|
||||
"movie (2020) - 2160p Extended",
|
||||
"movie (2020) - 2160p Original",
|
||||
"2160p Extended",
|
||||
"2160p Original")]
|
||||
// Bracketed version labels: the opening bracket is kept in the label.
|
||||
[InlineData(
|
||||
"Blade Runner (1982) [Final Cut] [1080p HEVC AAC]",
|
||||
|
||||
Reference in New Issue
Block a user