From 89779808e061494252b5d4259d84061e63a69651 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 2c2793b687893..909aac6ba7186 100644 --- a/apps/files_versions/lib/Controller/PreviewController.php +++ b/apps/files_versions/lib/Controller/PreviewController.php @@ -64,7 +64,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 9899836bb8882..0e36703d5aa30 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(): void { ->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(): void { From 936166939cb83acc940de9e1bef495013c2dc162 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 | 17 +++++++++++++- apps/files_versions/openapi.json | 23 +++++++++++++++++++ openapi.json | 23 +++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/apps/files_versions/lib/Controller/PreviewController.php b/apps/files_versions/lib/Controller/PreviewController.php index 909aac6ba7186..be62c5eb957d6 100644 --- a/apps/files_versions/lib/Controller/PreviewController.php +++ b/apps/files_versions/lib/Controller/PreviewController.php @@ -13,11 +13,13 @@ use OCP\AppFramework\Http\Attribute\OpenAPI; 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; #[OpenAPI(scope: OpenAPI::SCOPE_DEFAULT)] class PreviewController extends Controller { @@ -29,6 +31,7 @@ public function __construct( private IUserSession $userSession, private IVersionManager $versionManager, private IPreview $previewManager, + private IMimeIconProvider $mimeIconProvider, ) { parent::__construct($appName, $request); } @@ -40,9 +43,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 */ @@ -53,11 +58,13 @@ public function getPreview( int $x = 44, int $y = 44, 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()); @@ -68,6 +75,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" + } + } + } } } } diff --git a/openapi.json b/openapi.json index ff87fc71c7a81..fffdec3ad35c7 100644 --- a/openapi.json +++ b/openapi.json @@ -22048,6 +22048,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": { @@ -22077,6 +22090,16 @@ "schema": [] } } + }, + "303": { + "description": "Redirect to the mime icon url if mimeFallback is true", + "headers": { + "Location": { + "schema": { + "type": "string" + } + } + } } } } From 07c1aea2f53691d33dd0c727bd42a9cf4ccc02e0 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 7235566f48e0d..8ea16e215c63a 100644 --- a/apps/files_versions/src/components/Version.vue +++ b/apps/files_versions/src/components/Version.vue @@ -11,7 +11,7 @@