No flicker when rendering thumbnails
Some checks failed
DokuWiki Default Tasks / all (push) Has been cancelled

This commit is contained in:
2026-01-06 10:48:05 +01:00
parent 23403bcc4f
commit 41580fa010
2 changed files with 53 additions and 5 deletions

View File

@@ -56,6 +56,7 @@ class Output
$thumbW = 150; $thumbW = 150;
$thumbH = 150; $thumbH = 150;
$thumbQ = 80;
$placeholderUrl = DOKU_BASE . 'lib/images/blank.gif'; $placeholderUrl = DOKU_BASE . 'lib/images/blank.gif';
$syntax = plugin_load('syntax', 'luxtools'); $syntax = plugin_load('syntax', 'luxtools');
@@ -81,12 +82,21 @@ class Output
$safePlaceholderUrl = hsc($placeholderUrl); $safePlaceholderUrl = hsc($placeholderUrl);
$label = hsc($item['name']); $label = hsc($item['name']);
$renderer->doc .= '<a href="' . $safeUrl . '" class="media" title="' . $label . '">'; $initialSrc = $safePlaceholderUrl;
$dataThumb = ' data-thumb-src="' . $safeThumbUrl . '"';
$thumbCachePath = $this->thumbCachePathForItem($item, $thumbW, $thumbH, $thumbQ);
if (is_string($thumbCachePath) && $thumbCachePath !== '' && @is_file($thumbCachePath)) {
// Thumb already exists: start with it immediately (no JS swap needed)
$initialSrc = $safeThumbUrl;
$dataThumb = '';
}
$renderer->doc .= '<a href="' . $safeUrl . '" class="media" title="' . $label . '" aria-label="' . $label . '">';
$renderer->doc .= '<img' $renderer->doc .= '<img'
. ' class="luxtools-thumb"' . ' class="luxtools-thumb"'
. ' src="' . $safePlaceholderUrl . '"' . ' src="' . $initialSrc . '"'
. ' data-thumb-src="' . $safeThumbUrl . '"' . $dataThumb
. ' alt="' . $label . '"' . ' alt=""'
. ' width="' . $thumbW . '"' . ' width="' . $thumbW . '"'
. ' height="' . $thumbH . '"' . ' height="' . $thumbH . '"'
. ' loading="lazy"' . ' loading="lazy"'
@@ -122,6 +132,44 @@ class Output
return $url . $glue . http_build_query($params, '', '&', PHP_QUERY_RFC3986) . $fragment; return $url . $glue . http_build_query($params, '', '&', PHP_QUERY_RFC3986) . $fragment;
} }
/**
* Compute the expected thumbnail cache path for an item.
*
* Mirrors the hashing scheme in file.php so we can detect whether a thumb
* already exists and can be used immediately.
*
* @param array $item
* @param int $w
* @param int $h
* @param int $q
* @return string|null
*/
protected function thumbCachePathForItem(array $item, int $w, int $h, int $q): ?string
{
if (!isset($item['path']) || !is_string($item['path']) || $item['path'] === '') return null;
if (!isset($item['mtime'])) return null;
$path = $item['path'];
$mtime = (int)$item['mtime'];
// Decide output format the same way file.php does.
try {
[, $mime,] = mimetype($path, false);
} catch (\Throwable $e) {
return null;
}
if (!is_string($mime) || !str_starts_with($mime, 'image/')) return null;
$dstFormat = ($mime === 'image/png' || $mime === 'image/gif') ? 'png' : 'jpg';
global $conf;
if (!isset($conf['cachedir']) || !is_string($conf['cachedir']) || trim($conf['cachedir']) === '') return null;
$hash = sha1($path . '|' . $mtime . '|w=' . $w . '|h=' . $h . '|q=' . $q . '|f=' . $dstFormat);
$sub = substr($hash, 0, 2);
$cacheDir = rtrim($conf['cachedir'], '/');
return $cacheDir . '/luxtools/thumbs/' . $sub . '/' . $hash . '.' . $dstFormat;
}
/** /**
* Renders the files as a table, including details if configured that way. * Renders the files as a table, including details if configured that way.
* *

View File

@@ -239,7 +239,7 @@ class plugin_luxtools_test extends DokuWikiTest
$this->structureCheck($doc, $structure); $this->structureCheck($doc, $structure);
$this->assertStringContainsString('exampleimage.png', $xhtml); $this->assertStringContainsString('exampleimage.png', $xhtml);
$this->assertStringContainsString('data-thumb-src=', $xhtml); $this->assertStringContainsString('thumb=1', $xhtml);
$this->assertStringContainsString('width="150"', $xhtml); $this->assertStringContainsString('width="150"', $xhtml);
$this->assertStringContainsString('height="150"', $xhtml); $this->assertStringContainsString('height="150"', $xhtml);
} }