Merge pull request #39119 from nextcloud/artonge/backport/stable27/38905

[stable27] Reduce load of files versions preview loading
This commit is contained in:
Louis 2023-07-05 08:53:27 +02:00 committed by GitHub
commit d119cb132a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 51 additions and 12 deletions

View file

@ -28,6 +28,7 @@ export default class Tab {
_icon
_iconSvgSanitized
_mount
_setIsActive
_update
_destroy
_enabled
@ -42,12 +43,13 @@ export default class Tab {
* @param {?string} options.icon the icon css class
* @param {?string} options.iconSvg the icon in svg format
* @param {Function} options.mount function to mount the tab
* @param {Function} [options.setIsActive] function to forward the active state of the tab
* @param {Function} options.update function to update the tab
* @param {Function} options.destroy function to destroy the tab
* @param {Function} [options.enabled] define conditions whether this tab is active. Must returns a boolean
* @param {Function} [options.scrollBottomReached] executed when the tab is scrolled to the bottom
*/
constructor({ id, name, icon, iconSvg, mount, update, destroy, enabled, scrollBottomReached } = {}) {
constructor({ id, name, icon, iconSvg, mount, setIsActive, update, destroy, enabled, scrollBottomReached } = {}) {
if (enabled === undefined) {
enabled = () => true
}
@ -68,6 +70,9 @@ export default class Tab {
if (typeof mount !== 'function') {
throw new Error('The mount argument should be a function')
}
if (setIsActive !== undefined && typeof setIsActive !== 'function') {
throw new Error('The setIsActive argument should be a function')
}
if (typeof update !== 'function') {
throw new Error('The update argument should be a function')
}
@ -85,6 +90,7 @@ export default class Tab {
this._name = name
this._icon = icon
this._mount = mount
this._setIsActive = setIsActive
this._update = update
this._destroy = destroy
this._enabled = enabled
@ -119,6 +125,10 @@ export default class Tab {
return this._mount
}
get setIsActive() {
return this._setIsActive || (() => undefined)
}
get update() {
return this._update
}

View file

@ -366,6 +366,7 @@ export default {
*/
setActiveTab(id) {
OCA.Files.Sidebar.setActiveTab(id)
this.tabs.forEach(tab => tab.setIsActive(id === tab.id))
},
/**
@ -453,6 +454,7 @@ export default {
if (this.$refs.tabs) {
this.$refs.tabs.updateTabs()
}
this.setActiveTab(this.Sidebar.activeTab || this.tabs[0].id)
})
} catch (error) {
this.error = t('files', 'Error while loading the file data')

View file

@ -27,6 +27,8 @@ declare(strict_types=1);
namespace OCA\Files_Versions\Sabre;
use OC\AppFramework\Http\Request;
use OCA\DAV\Connector\Sabre\FilesPlugin;
use OCP\IPreview;
use OCP\IRequest;
use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\INode;
@ -39,12 +41,12 @@ use Sabre\HTTP\ResponseInterface;
class Plugin extends ServerPlugin {
private Server $server;
private IRequest $request;
public const VERSION_LABEL = '{http://nextcloud.org/ns}version-label';
public function __construct(
IRequest $request
private IRequest $request,
private IPreview $previewManager,
) {
$this->request = $request;
}
@ -91,6 +93,7 @@ class Plugin extends ServerPlugin {
public function propFind(PropFind $propFind, INode $node): void {
if ($node instanceof VersionFile) {
$propFind->handle(self::VERSION_LABEL, fn() => $node->getLabel());
$propFind->handle(FilesPlugin::HAS_PREVIEW_PROPERTYNAME, fn () => $this->previewManager->isMimeSupported($node->getContentType()));
}
}

View file

@ -31,6 +31,7 @@ use OCA\Files_Versions\Versions\INameableVersion;
use OCA\Files_Versions\Versions\INameableVersionBackend;
use OCA\Files_Versions\Versions\IVersion;
use OCA\Files_Versions\Versions\IVersionManager;
use OCP\Files\FileInfo;
use OCP\Files\NotFoundException;
use Sabre\DAV\Exception\Forbidden;
use Sabre\DAV\Exception\NotFound;

View file

@ -23,11 +23,15 @@
:force-display-actions="true"
data-files-versions-version>
<template #icon>
<img v-if="!previewError"
<div v-if="!(loadPreview || previewLoaded)" class="version__image" />
<img v-else-if="isCurrent || version.hasPreview"
:src="previewURL"
alt=""
decoding="async"
fetchpriority="low"
loading="lazy"
class="version__image"
@error="previewError = true">
@load="previewLoaded = true">
<div v-else
class="version__image">
<ImageOffOutline :size="20" />
@ -176,13 +180,17 @@ export default {
type: Boolean,
default: false,
},
loadPreview: {
type: Boolean,
default: false,
},
},
data() {
return {
previewLoaded: false,
showVersionLabelForm: false,
formVersionLabelValue: this.version.label,
capabilities: loadState('core', 'capabilities', { files: { version_labeling: false, version_deletion: false } }),
previewError: false,
}
},
computed: {

View file

@ -59,6 +59,9 @@ window.addEventListener('DOMContentLoaded', function() {
update(fileInfo) {
TabInstance.update(fileInfo)
},
setIsActive(isActive) {
TabInstance.setIsActive(isActive)
},
destroy() {
TabInstance.$destroy()
TabInstance = null

View file

@ -30,5 +30,6 @@ export default `<?xml version="1.0"?>
<d:getcontenttype />
<d:getlastmodified />
<nc:version-label />
<nc:has-preview />
</d:prop>
</d:propfind>`

View file

@ -36,6 +36,7 @@ import moment from '@nextcloud/moment'
* @property {string} size - Human readable size
* @property {string} type - 'file'
* @property {number} mtime - Version creation date as a timestamp
* @property {boolean} hasPreview - Whether the version has a preview
* @property {string} preview - Preview URL of the version
* @property {string} url - Download URL of the version
* @property {string|null} fileVersion - The version id, null for the current version
@ -98,6 +99,7 @@ function formatVersion(version, fileInfo) {
size: version.size,
type: version.type,
mtime: moment(version.lastmod).unix() * 1000,
hasPreview: version.props['has-preview'] === 1,
preview: generateUrl('/apps/files_versions/preview?file={file}&version={fileVersion}', {
file: joinPaths(fileInfo.path, fileInfo.name),
fileVersion: version.basename,

View file

@ -19,6 +19,7 @@
<ul data-files-versions-versions-list>
<Version v-for="version in orderedVersions"
:key="version.mtime"
:load-preview="isActive"
:version="version"
:file-info="fileInfo"
:is-current="version.mtime === fileInfo.mtime"
@ -42,6 +43,7 @@ export default {
data() {
return {
fileInfo: null,
isActive: false,
/** @type {import('../utils/versions.js').Version[]} */
versions: [],
loading: false,
@ -89,6 +91,13 @@ export default {
this.fetchVersions()
},
/**
* @param {boolean} isActive whether the tab is active
*/
async setIsActive(isActive) {
this.isActive = isActive
},
/**
* Get the existing versions infos
*/

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long