diff options
| author | Shadowghost <Shadowghost@users.noreply.github.com> | 2026-10-05 19:19:05 -0400 |
|---|---|---|
| committer | Cody Robibero <cody@robibe.ro> | 2026-10-05 19:19:05 -0400 |
| commit | a2bd48c1d235b929b20047d124382f83d9830668 (patch) | |
| tree | 8a78758b8c7fd28ec92604556282818693eeddda | |
| parent | 9c28aab413756ae7b61e6b9ad8e6d89d14e55a38 (diff) | |
Backport pull request #18278 from jellyfin/release-12.z
Compare local image dates with a one second tolerance
Original-merge: 2a59779ae98d96be782078ddf414040d931831ea
Merged-by: crobibero <cody@robibe.ro>
Backported-by: Cody Robibero <cody@robibe.ro>
| -rw-r--r-- | MediaBrowser.Controller/Entities/BaseItem.cs | 5 | ||||
| -rw-r--r-- | MediaBrowser.Providers/Manager/ItemImageProvider.cs | 5 | ||||
| -rw-r--r-- | tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs | 31 |
3 files changed, 37 insertions, 4 deletions
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 70e7da8932..022f8f0fbf 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -2560,8 +2560,9 @@ namespace MediaBrowser.Controller.Entities { var newDateModified = FileSystem.GetLastWriteTimeUtc(newImage); - // If date changed then we need to reset saved image dimensions - if (existing.DateModified != newDateModified && (existing.Width > 0 || existing.Height > 0)) + // If date changed then we need to reset saved image dimensions. Stores such as PostgreSQL keep + // only microseconds, so an exact comparison would treat every unchanged image as modified. + if (Math.Abs((existing.DateModified - newDateModified).TotalSeconds) > 1 && (existing.Width > 0 || existing.Height > 0)) { existing.Width = 0; existing.Height = 0; diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index ce5468c5c4..3317e33e1c 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -463,8 +463,9 @@ namespace MediaBrowser.Providers.Manager { var newDateModified = _fileSystem.GetLastWriteTimeUtc(image.FileInfo); - // If date changed then we need to reset saved image dimensions - if (currentImage.DateModified != newDateModified && (currentImage.Width > 0 || currentImage.Height > 0)) + // If date changed then we need to reset saved image dimensions. Stores such as PostgreSQL keep + // only microseconds, so an exact comparison would treat every unchanged image as modified. + if (Math.Abs((currentImage.DateModified - newDateModified).TotalSeconds) > 1 && (currentImage.Width > 0 || currentImage.Height > 0)) { currentImage.Width = 0; currentImage.Height = 0; diff --git a/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs b/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs index 459973acba..e234e07fb0 100644 --- a/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs +++ b/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs @@ -177,6 +177,37 @@ namespace Jellyfin.Providers.Tests.Manager } [Theory] + [InlineData(ImageType.Primary, 1)] + [InlineData(ImageType.Backdrop, 2)] + public void MergeImages_StoredTimeTruncatedToMicroseconds_NoChange(ImageType imageType, int imageCount) + { + // Regression test for https://github.com/jellyfin/jellyfin/issues/18274 + var fileTime = new DateTime(2021, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddTicks(1234567); + var storedTime = fileTime.AddTicks(-(fileTime.Ticks % 10)); + + var fileSystem = new Mock<IFileSystem>(); + fileSystem.Setup(fs => fs.GetLastWriteTimeUtc(It.IsAny<FileSystemMetadata>())) + .Returns(fileTime); + BaseItem.FileSystem = fileSystem.Object; + + var item = GetItemWithImages(imageType, imageCount, true); + foreach (var image in item.GetImages(imageType)) + { + image.DateModified = storedTime; + image.Height = 1; + image.Width = 1; + } + + var images = GetImages(imageType, imageCount, true); + + var itemImageProvider = GetItemImageProvider(null, fileSystem); + var changed = itemImageProvider.MergeImages(item, images, new ImageRefreshOptions(Mock.Of<IDirectoryService>())); + + Assert.False(changed); + Assert.All(item.GetImages(imageType), image => Assert.Equal(1, image.Width)); + } + + [Theory] [InlineData(ImageType.Primary, 0)] [InlineData(ImageType.Primary, 1)] [InlineData(ImageType.Backdrop, 2)] |
