From 2f73d92602dcc0f6d3fc0f89cbf173d6426cd41a Mon Sep 17 00:00:00 2001 From: provokateurin Date: Thu, 27 Mar 2025 08:22:53 +0100 Subject: [PATCH 1/4] fix(files_versions): Cache previews Signed-off-by: provokateurin --- .../lib/Controller/PreviewController.php | 4 +++- .../tests/Controller/PreviewControllerTest.php | 15 +++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/apps/files_versions/lib/Controller/PreviewController.php b/apps/files_versions/lib/Controller/PreviewController.php index 8416503c6432b..c0ae55921510e 100644 --- a/apps/files_versions/lib/Controller/PreviewController.php +++ b/apps/files_versions/lib/Controller/PreviewController.php @@ -79,7 +79,9 @@ public function getPreview( $file = $userFolder->get($file); $versionFile = $this->versionManager->getVersionFile($user, $file, $version); $preview = $this->previewManager->getPreview($versionFile, $x, $y, true, IPreview::MODE_FILL, $versionFile->getMimetype()); - return new FileDisplayResponse($preview, Http::STATUS_OK, ['Content-Type' => $preview->getMimeType()]); + $response = new FileDisplayResponse($preview, Http::STATUS_OK, ['Content-Type' => $preview->getMimeType()]); + $response->cacheFor(3600 * 24, false, true); + return $response; } catch (NotFoundException $e) { return new DataResponse([], Http::STATUS_NOT_FOUND); } catch (\InvalidArgumentException $e) { diff --git a/apps/files_versions/tests/Controller/PreviewControllerTest.php b/apps/files_versions/tests/Controller/PreviewControllerTest.php index 1673a212f891b..6b46c65cd0c80 100644 --- a/apps/files_versions/tests/Controller/PreviewControllerTest.php +++ b/apps/files_versions/tests/Controller/PreviewControllerTest.php @@ -3,13 +3,13 @@ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ + namespace OCA\Files_Versions\Tests\Controller; use OCA\Files_Versions\Controller\PreviewController; use OCA\Files_Versions\Versions\IVersionManager; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; -use OCP\AppFramework\Http\FileDisplayResponse; use OCP\Files\File; use OCP\Files\Folder; use OCP\Files\IMimeTypeDetector; @@ -20,6 +20,8 @@ use OCP\IRequest; use OCP\IUser; use OCP\IUserSession; +use OCP\Preview\IMimeIconProvider; +use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class PreviewControllerTest extends TestCase { @@ -45,6 +47,8 @@ class PreviewControllerTest extends TestCase { /** @var IVersionManager|\PHPUnit\Framework\MockObject\MockObject */ private $versionManager; + private IMimeIconProvider&MockObject $mimeIconProvider; + protected function setUp(): void { parent::setUp(); @@ -60,6 +64,7 @@ protected function setUp(): void { ->method('getUser') ->willReturn($user); $this->versionManager = $this->createMock(IVersionManager::class); + $this->mimeIconProvider = $this->createMock(IMimeIconProvider::class); $this->controller = new PreviewController( 'files_versions', @@ -67,7 +72,8 @@ protected function setUp(): void { $this->rootFolder, $this->userSession, $this->versionManager, - $this->previewManager + $this->previewManager, + $this->mimeIconProvider, ); } @@ -131,9 +137,10 @@ public function testValidPreview() { ->willReturn('previewMime'); $res = $this->controller->getPreview('file', 10, 10, '42'); - $expected = new FileDisplayResponse($preview, Http::STATUS_OK, ['Content-Type' => 'previewMime']); - $this->assertEquals($expected, $res); + $this->assertEquals('previewMime', $res->getHeaders()['Content-Type']); + $this->assertEquals(Http::STATUS_OK, $res->getStatus()); + $this->assertEquals($preview, $this->invokePrivate($res, 'file')); } public function testVersionNotFound() { From 4e7fc5bfbf59f2ceba0ecccc855bb03cb4946560 Mon Sep 17 00:00:00 2001 From: provokateurin Date: Thu, 27 Mar 2025 08:33:13 +0100 Subject: [PATCH 2/4] feat(files_versions): Implement preview mime icon fallback Signed-off-by: provokateurin --- .../lib/Controller/PreviewController.php | 21 ++++++++++++++--- apps/files_versions/openapi.json | 23 +++++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/apps/files_versions/lib/Controller/PreviewController.php b/apps/files_versions/lib/Controller/PreviewController.php index c0ae55921510e..0733c42af623d 100644 --- a/apps/files_versions/lib/Controller/PreviewController.php +++ b/apps/files_versions/lib/Controller/PreviewController.php @@ -12,11 +12,13 @@ use OCP\AppFramework\Http\Attribute\NoCSRFRequired; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\Http\FileDisplayResponse; +use OCP\AppFramework\Http\RedirectResponse; use OCP\Files\IRootFolder; use OCP\Files\NotFoundException; use OCP\IPreview; use OCP\IRequest; use OCP\IUserSession; +use OCP\Preview\IMimeIconProvider; class PreviewController extends Controller { @@ -38,7 +40,8 @@ public function __construct( IRootFolder $rootFolder, IUserSession $userSession, IVersionManager $versionManager, - IPreview $previewManager + IPreview $previewManager, + private IMimeIconProvider $mimeIconProvider, ) { parent::__construct($appName, $request); @@ -55,9 +58,11 @@ public function __construct( * @param int $x Width of the preview * @param int $y Height of the preview * @param string $version Version of the file to get the preview for - * @return FileDisplayResponse|DataResponse, array{}> + * @param bool $mimeFallback Whether to fallback to the mime icon if no preview is available + * @return FileDisplayResponse|DataResponse, array{}>|RedirectResponse * * 200: Preview returned + * 303: Redirect to the mime icon url if mimeFallback is true * 400: Getting preview is not possible * 404: Preview not found */ @@ -67,12 +72,14 @@ public function getPreview( string $file = '', int $x = 44, int $y = 44, - string $version = '' + string $version = '', + bool $mimeFallback = false, ) { if ($file === '' || $version === '' || $x === 0 || $y === 0) { return new DataResponse([], Http::STATUS_BAD_REQUEST); } + $versionFile = null; try { $user = $this->userSession->getUser(); $userFolder = $this->rootFolder->getUserFolder($user->getUID()); @@ -83,6 +90,14 @@ public function getPreview( $response->cacheFor(3600 * 24, false, true); return $response; } catch (NotFoundException $e) { + // If we have no preview enabled, we can redirect to the mime icon if any + if ($mimeFallback && $versionFile !== null) { + $url = $this->mimeIconProvider->getMimeIconUrl($versionFile->getMimeType()); + if ($url !== null) { + return new RedirectResponse($url); + } + } + return new DataResponse([], Http::STATUS_NOT_FOUND); } catch (\InvalidArgumentException $e) { return new DataResponse([], Http::STATUS_BAD_REQUEST); diff --git a/apps/files_versions/openapi.json b/apps/files_versions/openapi.json index 9c6a7e5f47345..aea18edf3ec16 100644 --- a/apps/files_versions/openapi.json +++ b/apps/files_versions/openapi.json @@ -103,6 +103,19 @@ "type": "string", "default": "" } + }, + { + "name": "mimeFallback", + "in": "query", + "description": "Whether to fallback to the mime icon if no preview is available", + "schema": { + "type": "integer", + "default": 0, + "enum": [ + 0, + 1 + ] + } } ], "responses": { @@ -132,6 +145,16 @@ "schema": {} } } + }, + "303": { + "description": "Redirect to the mime icon url if mimeFallback is true", + "headers": { + "Location": { + "schema": { + "type": "string" + } + } + } } } } From e05838e259d0b63b148a71a961c84219033728d5 Mon Sep 17 00:00:00 2001 From: provokateurin Date: Thu, 27 Mar 2025 08:39:53 +0100 Subject: [PATCH 3/4] fix(files_versions): Rely on server mime fallback icons Signed-off-by: provokateurin --- apps/files_versions/src/components/Version.vue | 2 +- apps/files_versions/src/utils/versions.ts | 6 ++---- apps/files_versions/src/views/VersionTab.vue | 5 ++--- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/apps/files_versions/src/components/Version.vue b/apps/files_versions/src/components/Version.vue index 91bcee4a7fa57..c4406e4df0a70 100644 --- a/apps/files_versions/src/components/Version.vue +++ b/apps/files_versions/src/components/Version.vue @@ -10,7 +10,7 @@