mirror of
https://github.com/nextcloud/server.git
synced 2026-06-11 01:30:50 -04:00
Merge pull request #51748 from nextcloud/backport/51744/stable31
[stable31] fix(files_versions): Rely on server mime fallback icons
This commit is contained in:
commit
1fd0651d08
8 changed files with 61 additions and 17 deletions
|
|
@ -13,11 +13,13 @@ use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
|
|||
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 @@ class PreviewController extends Controller {
|
|||
private IUserSession $userSession,
|
||||
private IVersionManager $versionManager,
|
||||
private IPreview $previewManager,
|
||||
private IMimeIconProvider $mimeIconProvider,
|
||||
) {
|
||||
parent::__construct($appName, $request);
|
||||
}
|
||||
|
|
@ -40,9 +43,11 @@ class PreviewController extends Controller {
|
|||
* @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<Http::STATUS_OK, array{Content-Type: string}>|DataResponse<Http::STATUS_BAD_REQUEST|Http::STATUS_NOT_FOUND, list<empty>, array{}>
|
||||
* @param bool $mimeFallback Whether to fallback to the mime icon if no preview is available
|
||||
* @return FileDisplayResponse<Http::STATUS_OK, array{Content-Type: string}>|DataResponse<Http::STATUS_BAD_REQUEST|Http::STATUS_NOT_FOUND, list<empty>, array{}>|RedirectResponse<Http::STATUS_SEE_OTHER, array{}>
|
||||
*
|
||||
* 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,19 +58,31 @@ class PreviewController extends Controller {
|
|||
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());
|
||||
$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) {
|
||||
// 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);
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
<!-- Icon -->
|
||||
<template #icon>
|
||||
<div v-if="!(loadPreview || previewLoaded)" class="version__image" />
|
||||
<img v-else-if="(isCurrent || version.hasPreview) && !previewErrored"
|
||||
<img v-else-if="version.previewUrl && !previewErrored"
|
||||
:src="version.previewUrl"
|
||||
alt=""
|
||||
decoding="async"
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ export interface Version {
|
|||
type: string, // 'file'
|
||||
mtime: number, // Version creation date as a timestamp
|
||||
permissions: string, // Only readable: 'R'
|
||||
hasPreview: boolean, // Whether the version has a preview
|
||||
previewUrl: string, // Preview URL of the version
|
||||
url: string, // Download URL of the version
|
||||
source: string, // The WebDAV endpoint of the ressource
|
||||
|
|
@ -78,12 +77,12 @@ function formatVersion(version: any, fileInfo: any): Version {
|
|||
let previewUrl = ''
|
||||
|
||||
if (mtime === fileInfo.mtime) { // Version is the current one
|
||||
previewUrl = generateUrl('/core/preview?fileId={fileId}&c={fileEtag}&x=250&y=250&forceIcon=0&a=0', {
|
||||
previewUrl = generateUrl('/core/preview?fileId={fileId}&c={fileEtag}&x=250&y=250&forceIcon=0&a=0&forceIcon=1&mimeFallback=1', {
|
||||
fileId: fileInfo.id,
|
||||
fileEtag: fileInfo.etag,
|
||||
})
|
||||
} else {
|
||||
previewUrl = generateUrl('/apps/files_versions/preview?file={file}&version={fileVersion}', {
|
||||
previewUrl = generateUrl('/apps/files_versions/preview?file={file}&version={fileVersion}&mimeFallback=1', {
|
||||
file: joinPaths(fileInfo.path, fileInfo.name),
|
||||
fileVersion: version.basename,
|
||||
})
|
||||
|
|
@ -102,7 +101,6 @@ function formatVersion(version: any, fileInfo: any): Version {
|
|||
type: version.type,
|
||||
mtime,
|
||||
permissions: 'R',
|
||||
hasPreview: version.props['has-preview'] === 1,
|
||||
previewUrl,
|
||||
url: joinPaths('/remote.php/dav', version.filename),
|
||||
source: generateRemoteUrl('dav') + encodePath(version.filename),
|
||||
|
|
|
|||
|
|
@ -273,13 +273,12 @@ export default {
|
|||
return
|
||||
}
|
||||
|
||||
// Versions previews are too small for our use case, so we override hasPreview and previewUrl
|
||||
// Versions previews are too small for our use case, so we override previewUrl
|
||||
// which makes the viewer render the original file.
|
||||
// We also point to the original filename if the version is the current one.
|
||||
const versions = this.versions.map(version => ({
|
||||
...version,
|
||||
filename: version.mtime === this.fileInfo.mtime ? path.join('files', getCurrentUser()?.uid ?? '', this.fileInfo.path, this.fileInfo.name) : version.filename,
|
||||
hasPreview: false,
|
||||
previewUrl: undefined,
|
||||
}))
|
||||
|
||||
|
|
@ -290,7 +289,7 @@ export default {
|
|||
},
|
||||
|
||||
compareVersion({ version }) {
|
||||
const versions = this.versions.map(version => ({ ...version, hasPreview: false, previewUrl: undefined }))
|
||||
const versions = this.versions.map(version => ({ ...version, previewUrl: undefined }))
|
||||
|
||||
OCA.Viewer.compare(this.viewerFileInfo, versions.find(v => v.source === version.source))
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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\IPreview;
|
|||
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 @@ class PreviewControllerTest extends TestCase {
|
|||
->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 @@ class PreviewControllerTest extends TestCase {
|
|||
$this->rootFolder,
|
||||
$this->userSession,
|
||||
$this->versionManager,
|
||||
$this->previewManager
|
||||
$this->previewManager,
|
||||
$this->mimeIconProvider,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -131,9 +137,10 @@ class PreviewControllerTest extends TestCase {
|
|||
->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 {
|
||||
|
|
|
|||
4
dist/files_versions-files_versions.js
vendored
4
dist/files_versions-files_versions.js
vendored
File diff suppressed because one or more lines are too long
2
dist/files_versions-files_versions.js.map
vendored
2
dist/files_versions-files_versions.js.map
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue