From af38b0a7d2c770a81a3b71032e8ff3d283757273 Mon Sep 17 00:00:00 2001 From: "Misha M.-Kupriyanov" Date: Tue, 27 Aug 2024 12:48:43 +0200 Subject: [PATCH 01/20] IONOS: feat: add always_show_viewer app config value enable via: ./occ config:app:set --value yes --type string viewer always_show_viewer Signed-off-by: Misha M.-Kupriyanov (cherry picked from commit 781cfbf583df56ff2b5fed6cd28629022ecf2336) --- lib/Listener/LoadViewerScript.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/Listener/LoadViewerScript.php b/lib/Listener/LoadViewerScript.php index 552a22b78..e3f585b1c 100644 --- a/lib/Listener/LoadViewerScript.php +++ b/lib/Listener/LoadViewerScript.php @@ -11,6 +11,7 @@ use OCA\Files\Event\LoadAdditionalScriptsEvent; use OCA\Viewer\AppInfo\Application; use OCA\Viewer\Event\LoadViewer; +use OCP\AppFramework\Services\IAppConfig; use OCP\AppFramework\Services\IInitialState; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; @@ -24,13 +25,16 @@ class LoadViewerScript implements IEventListener { private IInitialState $initialStateService; private IPreview $previewManager; + private IAppConfig $appConfig; public function __construct( IInitialState $initialStateService, IPreview $previewManager, + IAppConfig $appConfig, ) { $this->initialStateService = $initialStateService; $this->previewManager = $previewManager; + $this->appConfig = $appConfig; } public function handle(Event $event): void { @@ -39,9 +43,13 @@ public function handle(Event $event): void { } Util::addStyle(Application::APP_ID, 'viewer-init'); + + $alwaysShowViewer = $this->appConfig->getAppValue('always_show_viewer', 'no') === 'yes'; + Util::addStyle(Application::APP_ID, 'viewer-main'); Util::addInitScript(Application::APP_ID, 'viewer-init'); Util::addScript(Application::APP_ID, 'viewer-main', 'files'); $this->initialStateService->provideInitialState('enabled_preview_providers', array_keys($this->previewManager->getProviders())); + $this->initialStateService->provideInitialState('always_show_viewer', $alwaysShowViewer); } } From f345c1225dd9949de801044064106276ee4a17fc Mon Sep 17 00:00:00 2001 From: "Misha M.-Kupriyanov" Date: Tue, 27 Aug 2024 17:05:56 +0200 Subject: [PATCH 02/20] IONOS: feat: add config module to expose alwaysShowViewer Signed-off-by: Misha M.-Kupriyanov (cherry picked from commit 939299c6c1965a5eb349bd3f852c160b3052bafe) --- src/models/config.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/models/config.ts diff --git a/src/models/config.ts b/src/models/config.ts new file mode 100644 index 000000000..cbe1653fd --- /dev/null +++ b/src/models/config.ts @@ -0,0 +1,12 @@ +/** + * SPDX-FileLicenseText: 2024 STRATO AG + * SPDX-License-Identifier: AGPL-3.0-or-later + * SPDX-FileContributor: Mikhailo Matiyenko-Kupriyanov + */ +import { loadState } from '@nextcloud/initial-state' + +const alwaysShowViewer = loadState('viewer', 'always_show_viewer', false) + +export default { + alwaysShowViewer, +} From b852c66b2b69fea8a79cde3a6d7a8c4380b87d75 Mon Sep 17 00:00:00 2001 From: "Misha M.-Kupriyanov" Date: Tue, 27 Aug 2024 17:16:53 +0200 Subject: [PATCH 03/20] IONOS: feat: add default component stub in order later to use it as default viewer Signed-off-by: Misha M.-Kupriyanov (cherry picked from commit de2ba4d0eec821687964cd10dd4dd78571d91f2f) --- src/components/Default.vue | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/components/Default.vue diff --git a/src/components/Default.vue b/src/components/Default.vue new file mode 100644 index 000000000..e9a47575b --- /dev/null +++ b/src/components/Default.vue @@ -0,0 +1,22 @@ + + + + + + From df78a5151095f2da9a66e951d5a7882521c77834 Mon Sep 17 00:00:00 2001 From: "Misha M.-Kupriyanov" Date: Wed, 28 Aug 2024 12:50:49 +0200 Subject: [PATCH 04/20] IONOS: feat: add default viewer in order later to display it for all not known mime types Signed-off-by: Misha M.-Kupriyanov (cherry picked from commit 4cfcad5c945415689c9e56570b205c3c35614b64) --- src/models/default.ts | 16 ++++++++++++++++ src/services/Viewer.js | 2 ++ 2 files changed, 18 insertions(+) create mode 100644 src/models/default.ts diff --git a/src/models/default.ts b/src/models/default.ts new file mode 100644 index 000000000..9de86a667 --- /dev/null +++ b/src/models/default.ts @@ -0,0 +1,16 @@ +/** + * SPDX-FileCopyrightText: 2024 STRATO AG + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import Default from '../components/Default.vue' + +export default { + id: 'default', + group: 'other', + mimes: [ + '*/*', + ], + mimesAliases: {}, + component: Default, +} diff --git a/src/services/Viewer.js b/src/services/Viewer.js index 3b1076be0..2c671f8f5 100644 --- a/src/services/Viewer.js +++ b/src/services/Viewer.js @@ -6,6 +6,7 @@ import Images from '../models/images.js' import Videos from '../models/videos.js' import Audios from '../models/audios.js' +import Default from '../models/default.ts' import logger from './logger.js' /** @@ -62,6 +63,7 @@ export default class Viewer { this.registerHandler(Images) this.registerHandler(Videos) this.registerHandler(Audios) + this.registerHandler(Default) logger.debug('OCA.Viewer initialized') } From e8813a774eec61681ed23b72c13095097bb53a24 Mon Sep 17 00:00:00 2001 From: "Misha M.-Kupriyanov" Date: Wed, 28 Aug 2024 12:54:29 +0200 Subject: [PATCH 05/20] IONOS: feat: enable default viewer Signed-off-by: Misha M.-Kupriyanov (cherry picked from commit c997a3d620d21a6068e29ece81f5715ef0925842) --- src/views/Viewer.vue | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/views/Viewer.vue b/src/views/Viewer.vue index 7c2245422..a729c2e4b 100644 --- a/src/views/Viewer.vue +++ b/src/views/Viewer.vue @@ -192,6 +192,7 @@ import { canDownload } from '../utils/canDownload.ts' import { extractFilePaths, extractFilePathFromSource } from '../utils/fileUtils.ts' import { toggleEditor } from '../files_actions/viewerAction.ts' import cancelableRequest from '../utils/CancelableRequest.js' +import configModule from '../models/config.ts' import Error from '../components/Error.vue' import fetchNode from '../services/FetchFile.ts' import File from '../models/file.js' @@ -728,6 +729,11 @@ export default defineComponent({ handler = this.registeredHandlers[mime] ?? this.registeredHandlers[alias] } + // fallback to default viewer if enabled + if (!handler && configModule.alwaysShowViewer) { + handler = this.registeredHandlers['*/*'] + } + // if we don't have a handler for this mime, abort if (!handler) { logger.error('The following file could not be displayed', { fileInfo }) From e40d056c178264abf9dd5bf6dc3c55593c93cffa Mon Sep 17 00:00:00 2001 From: "Misha M.-Kupriyanov" Date: Tue, 3 Sep 2024 14:28:53 +0200 Subject: [PATCH 06/20] IONOS: feat: extract default mime type to config in order to reuse it later Signed-off-by: Misha M.-Kupriyanov (cherry picked from commit 41daec7f878927c95acc5ec5ec6ae259ae8fb643) --- src/models/config.ts | 1 + src/models/default.ts | 3 ++- src/views/Viewer.vue | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/models/config.ts b/src/models/config.ts index cbe1653fd..ca6096b6b 100644 --- a/src/models/config.ts +++ b/src/models/config.ts @@ -9,4 +9,5 @@ const alwaysShowViewer = loadState('viewer', 'always_show_viewer', fals export default { alwaysShowViewer, + defaultMimeType: 'all', } diff --git a/src/models/default.ts b/src/models/default.ts index 9de86a667..94ef98f3a 100644 --- a/src/models/default.ts +++ b/src/models/default.ts @@ -4,12 +4,13 @@ */ import Default from '../components/Default.vue' +import config from './config.ts' export default { id: 'default', group: 'other', mimes: [ - '*/*', + config.defaultMimeType, ], mimesAliases: {}, component: Default, diff --git a/src/views/Viewer.vue b/src/views/Viewer.vue index a729c2e4b..6395fb7df 100644 --- a/src/views/Viewer.vue +++ b/src/views/Viewer.vue @@ -731,7 +731,7 @@ export default defineComponent({ // fallback to default viewer if enabled if (!handler && configModule.alwaysShowViewer) { - handler = this.registeredHandlers['*/*'] + handler = this.registeredHandlers[configModule.defaultMimeType] } // if we don't have a handler for this mime, abort From 001cb5d9ed4479efe9b63f63bfa1c4c609e68cf8 Mon Sep 17 00:00:00 2001 From: Franziska Bath Date: Mon, 2 Sep 2024 13:37:47 +0200 Subject: [PATCH 07/20] IONOS: feat: properly implement default component Signed-off-by: Franziska Bath (cherry picked from commit 1eeec05ff796a6a60316649606d20871e19d988e) --- src/components/Default.vue | 48 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/src/components/Default.vue b/src/components/Default.vue index e9a47575b..3bb98846e 100644 --- a/src/components/Default.vue +++ b/src/components/Default.vue @@ -5,18 +5,62 @@ --> From bd8be93b35d67b526504ac33330cb7146f27844c Mon Sep 17 00:00:00 2001 From: "Misha M.-Kupriyanov" Date: Tue, 3 Sep 2024 13:26:55 +0200 Subject: [PATCH 08/20] IONOS: feat(Viewer): extract modal title as own method in order to be able to influence it later Signed-off-by: Misha M.-Kupriyanov (cherry picked from commit a2072f4766d299a039b14f6ca2dc876910e18251) --- src/views/Viewer.vue | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/views/Viewer.vue b/src/views/Viewer.vue index 6395fb7df..50cc9f5be 100644 --- a/src/views/Viewer.vue +++ b/src/views/Viewer.vue @@ -44,7 +44,7 @@ :inline-actions="canEdit ? 1 : 0" :spread-navigation="true" :style="{ width: isSidebarShown ? `${sidebarPosition}px` : null }" - :name="currentFile.basename" + :name="modalTitle" class="viewer" size="full" @close="close" @@ -391,6 +391,10 @@ export default defineComponent({ } }, + modalTitle() { + return this.currentFile.basename + }, + showComparison() { return !this.isMobile }, From c2cc17b2691b06f7ec1f330902e0d0f4cd096d5c Mon Sep 17 00:00:00 2001 From: Franziska Bath Date: Mon, 2 Sep 2024 13:40:22 +0200 Subject: [PATCH 09/20] IONOS: feat(Viewer): hide file name in modal header when mime image shown Signed-off-by: Franziska Bath (cherry picked from commit e7ac87eb9923b450b0525845fe3d939d9d4a8448) --- src/views/Viewer.vue | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/views/Viewer.vue b/src/views/Viewer.vue index 50cc9f5be..1b7332c60 100644 --- a/src/views/Viewer.vue +++ b/src/views/Viewer.vue @@ -392,7 +392,11 @@ export default defineComponent({ }, modalTitle() { - return this.currentFile.basename + if (!configModule.alwaysShowViewer) { + return this.currentFile.basename + } + + return this.currentFile?.modal?.name === 'Default' ? '' : this.currentFile.basename }, showComparison() { From de6d5f0e91b48fa0cce4e4d1717c052d053eb8cc Mon Sep 17 00:00:00 2001 From: Thomas Lehmann Date: Wed, 11 Sep 2024 17:50:37 +0200 Subject: [PATCH 10/20] IONOS:fix(Viewer): remove directories from fileList Don't include directories as they can not be displayed. Note: including directories could also cause a follow-up error with certain directory structures which happen to include a directory named like a number (i.e. 123) because of sloppy, too broad type casting in fileUtils.ts's genFileInfo() accidentally converting such a folder name to a Number, which then can not be used in string comparisons. Signed-off-by: Thomas Lehmann (cherry picked from commit 453442026c1d50f5552294158b17fcc95dc8138d) --- src/views/Viewer.vue | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/views/Viewer.vue b/src/views/Viewer.vue index 1b7332c60..4feaf2056 100644 --- a/src/views/Viewer.vue +++ b/src/views/Viewer.vue @@ -783,8 +783,14 @@ export default defineComponent({ const fileList = await folderRequest(dirPath) - // filter out the unwanted mimes - const filteredFiles = fileList.filter(file => file.mime && mimes.indexOf(file.mime) !== -1) + let filteredFiles + if (configModule.alwaysShowViewer) { + // don't include directories, otherwise accept all mimes + filteredFiles = fileList.filter(({ type }) => type !== 'directory') + } else { + // filter out the unwanted mimes + filteredFiles = fileList.filter(file => file.mime && mimes.indexOf(file.mime) !== -1) + } // sort like the files list // TODO: implement global sorting API From db33c2d11882f724478613c967895c152e435c05 Mon Sep 17 00:00:00 2001 From: Thomas Lehmann Date: Thu, 12 Sep 2024 17:19:55 +0200 Subject: [PATCH 11/20] IONOS:fix(Default): define proper text color == The error The text below the mimetype icon has Nextcloud's default text styling, which is dark text on light background, yet here it's dark background. == The fix The default component now defines a text color. Signed-off-by: Thomas Lehmann (cherry picked from commit 7834768b91c8cef04aafc38af32656b9144f30c5) --- src/components/Default.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/Default.vue b/src/components/Default.vue index 3bb98846e..b78c0fd27 100644 --- a/src/components/Default.vue +++ b/src/components/Default.vue @@ -57,6 +57,7 @@ img { } .title { + color: var(--color-primary-element-text); font-weight: bold; font-size: 1.4em; overflow: hidden; From 0250e0411d8e7b6dccdd8ebbdbc7bd9ad97d0da2 Mon Sep 17 00:00:00 2001 From: Thomas Lehmann Date: Thu, 12 Sep 2024 15:41:35 +0200 Subject: [PATCH 12/20] IONOS: fix(Images): hide loading spinner on failed image load == The cause Previously the code attempted to load a preview of an image. If loading this preview image failed it was attempted to load the original image. Load errors of images were only handled _once_. This meant that a load error for the original image was never handled, thus the viewer was still in loading state and showed a browser-dependant "broken image" replacement icon. == The fix Now further image load errors are handled too. In case the original fails too, the loading state is ended and a placeholder text is shown. The default preview component, which was introduced to show something for any mimetype if configured, is now also used as a fallback. Signed-off-by: Thomas Lehmann (cherry picked from commit 04a174029f4fce7acf0b7c97172e988dcf81c40a) --- src/components/Images.vue | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/components/Images.vue b/src/components/Images.vue index dd07e1441..ecd7534ec 100644 --- a/src/components/Images.vue +++ b/src/components/Images.vue @@ -12,7 +12,8 @@ @close="onClose" />