aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShadowghost <Shadowghost@users.noreply.github.com>2026-10-05 19:19:05 -0400
committerCody Robibero <cody@robibe.ro>2026-10-05 19:19:05 -0400
commita2bd48c1d235b929b20047d124382f83d9830668 (patch)
tree8a78758b8c7fd28ec92604556282818693eeddda
parent9c28aab413756ae7b61e6b9ad8e6d89d14e55a38 (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.cs5
-rw-r--r--MediaBrowser.Providers/Manager/ItemImageProvider.cs5
-rw-r--r--tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs31
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)]