diff options
author | Julius Härtl <jus@bitgrid.net> | 2021-11-29 20:29:25 +0300 |
---|---|---|
committer | Julius Härtl <jus@bitgrid.net> | 2021-11-29 20:33:50 +0300 |
commit | c9cb1bd98224a53bd7db73c62ae4c81c6ea51f00 (patch) | |
tree | 45584b148522bd78a0fc1bd683376e2ab02b27cc | |
parent | 6551749b8627b2da1eca3bd07947175f4cffadfb (diff) |
Improve loading state handling
Signed-off-by: Julius Härtl <jus@bitgrid.net>
-rw-r--r-- | css/viewer.scss | 4 | ||||
-rw-r--r-- | lib/AppInfo/Application.php | 28 | ||||
-rw-r--r-- | src/services/collabora.js | 18 | ||||
-rw-r--r-- | src/view/Office.vue | 100 |
4 files changed, 93 insertions, 57 deletions
diff --git a/css/viewer.scss b/css/viewer.scss index 1393881b..efc70649 100644 --- a/css/viewer.scss +++ b/css/viewer.scss @@ -37,10 +37,10 @@ #richdocumentsframe { background-color: #fff; width:100%; - height: calc(100vh - 50px); + height: calc(100vh - 50px + 3px); display:block; position:absolute; - top:0; + top: -3px; z-index:110; &.full { height: 100%; diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 721e8031..0d6562e1 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -27,6 +27,7 @@ namespace OCA\Richdocuments\AppInfo; use OC\EventDispatcher\SymfonyAdapter; use OC\Files\Type\Detection; use OC\Security\CSP\ContentSecurityPolicy; +use OCA\Files_Sharing\Listener\LoadAdditionalListener; use OCA\Richdocuments\AppConfig; use OCA\Richdocuments\Capabilities; use OCA\Richdocuments\Middleware\WOPIMiddleware; @@ -38,6 +39,7 @@ use OCA\Richdocuments\Preview\OpenDocument; use OCA\Richdocuments\Preview\Pdf; use OCA\Richdocuments\Service\CapabilitiesService; use OCA\Richdocuments\Service\FederationService; +use OCA\Richdocuments\Service\InitialStateService; use OCA\Richdocuments\Template\CollaboraTemplateProvider; use OCA\Richdocuments\WOPI\DiscoveryManager; use OCA\Viewer\Event\LoadViewer; @@ -78,12 +80,6 @@ class Application extends App implements IBootstrap { } } - /** @var IEventDispatcher $eventDispatcher */ - $eventDispatcher = $this->getContainer()->getServer()->query(IEventDispatcher::class); - $eventDispatcher->addListener(LoadViewer::class, function () { - \OCP\Util::addScript('richdocuments', 'richdocuments-viewer'); - }); - $context->injectFn(function(ITemplateManager $templateManager, IL10N $l10n, IConfig $config, CapabilitiesService $capabilitiesService) { if (empty($capabilitiesService->getCapabilities())) { return; @@ -142,17 +138,15 @@ class Application extends App implements IBootstrap { }); }); - $context->injectFn(function (SymfonyAdapter $eventDispatcher) { - $eventDispatcher->addListener('OCA\Files::loadAdditionalScripts', - function() { - \OCP\Util::addScript('richdocuments', 'richdocuments-files'); - } - ); - $eventDispatcher->addListener('OCA\Files_Sharing::loadAdditionalScripts', - function() { - \OCP\Util::addScript('richdocuments', 'richdocuments-files'); - } - ); + $context->injectFn(function (SymfonyAdapter $symfonyAdapter, IEventDispatcher $eventDispatcher, InitialStateService $initialStateService) { + $eventDispatcher->addListener(LoadViewer::class, function () use ($initialStateService) { + $initialStateService->provideCapabilities(); + \OCP\Util::addScript('richdocuments', 'richdocuments-viewer'); + }); + $eventDispatcher->addListener('OCA\Files_Sharing::loadAdditionalScripts', function () use ($initialStateService) { + $initialStateService->provideCapabilities(); + \OCP\Util::addScript('richdocuments', 'richdocuments-files'); + }); if (class_exists('\OC\Files\Type\TemplateManager')) { $manager = \OC_Helper::getFileTemplateManager(); diff --git a/src/services/collabora.js b/src/services/collabora.js index 8be1612c..435bc936 100644 --- a/src/services/collabora.js +++ b/src/services/collabora.js @@ -19,9 +19,13 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ - -import { getCapabilities } from '@nextcloud/capabilities' import axios from '@nextcloud/axios' +import { getCapabilities } from '@nextcloud/capabilities' + +export const LOADING_ERROR = { + COLLABORA_UNCONFIGURED: 1, + PROXY_FAILED: 2, +} export const isCollaboraConfigured = () => { const collaboraCapabilities = getCapabilities()?.richdocuments?.collabora @@ -33,14 +37,16 @@ export const isBuiltinCodeServerUsed = () => { return richdocumentsCapabilities?.config?.wopi_url?.indexOf('proxy.php') !== -1 } -let proxyStatusCheckRetry = 0 -export const checkProxyStatus = async(_resolve, _reject) => { - +export const checkCollaboraConfiguration = async() => { const wopiUrl = getCapabilities()?.richdocuments?.config?.wopi_url if (!wopiUrl) { - throw Error(t('richdocuments', 'Collabora is not configured')) + throw Error(LOADING_ERROR.COLLABORA_UNCONFIGURED) } +} +let proxyStatusCheckRetry = 0 +export const checkProxyStatus = async(_resolve, _reject) => { + const wopiUrl = getCapabilities()?.richdocuments?.config?.wopi_url if (wopiUrl.indexOf('proxy.php') === -1) { return true } diff --git a/src/view/Office.vue b/src/view/Office.vue index 78b567af..7513faba 100644 --- a/src/view/Office.vue +++ b/src/view/Office.vue @@ -25,12 +25,20 @@ <div id="richdocuments-wrapper"> <div v-if="showLoadingIndicator" id="cool-loading-overlay" :class="{ debug: debug }"> <EmptyContent v-if="!error" icon="icon-loading"> - Loading document + {{ t('richdocuments', 'Loading {filename}…', { filename: basename }) }} + <template #desc> + <button @click="close"> + {{ t('richdocuments', 'Cancel') }} + </button> + </template> </EmptyContent> <EmptyContent v-else icon="icon-error"> {{ t('richdocuments', 'Document loading failed') }} <template #desc> - {{ errorMessage }} + {{ errorMessage }}<br><br> + <button @click="close"> + {{ t('richdocuments', 'Close') }} + </button> </template> </EmptyContent> </div> @@ -61,13 +69,13 @@ import Avatar from '@nextcloud/vue/dist/Components/Avatar' import Actions from '@nextcloud/vue/dist/Components/Actions' import ActionButton from '@nextcloud/vue/dist/Components/ActionButton' import EmptyContent from '@nextcloud/vue/dist/Components/EmptyContent' +import { loadState } from '@nextcloud/initial-state' import { basename, dirname } from 'path' import { getDocumentUrlForFile, getDocumentUrlForPublicFile } from '../helpers/url' import PostMessageService from '../services/postMessage.tsx' import FilesAppIntegration from './FilesAppIntegration' -import { checkProxyStatus } from '../services/collabora' - +import { LOADING_ERROR, checkCollaboraConfiguration, checkProxyStatus } from '../services/collabora' const FRAME_DOCUMENT = 'FRAME_DOCUMENT' const PostMessages = new PostMessageService({ FRAME_DOCUMENT: () => document.getElementById('collaboraframe').contentWindow, @@ -77,14 +85,9 @@ const LOADING_STATE = { LOADING: 0, FRAME_READY: 1, DOCUMENT_READY: 2, - FAILED: -1, } -const LOADING_ERROR = { - PROXY_FAILED: 1, -} - export default { name: 'Office', components: { @@ -112,11 +115,15 @@ export default { return { src: null, loading: LOADING_STATE.LOADING, + loadingTimeout: null, error: null, views: [], } }, computed: { + basename() { + return basename(this.filename) + }, useNativeHeader() { return true }, @@ -137,11 +144,13 @@ export default { return this.loading !== LOADING_STATE.DOCUMENT_READY }, errorMessage() { - switch (this.error) { + switch (parseInt(this.error)) { + case LOADING_ERROR.COLLABORA_UNCONFIGURED: + return t('richdocuments', '{productName} is not configured', { productName: loadState('richdocuments', 'productName', 'Nextcloud Office') }) case LOADING_ERROR.PROXY_FAILED: return t('richdocuments', 'Starting the built-in CODE server failed') default: - return t('richdocuments', 'Unknown error') + return this.error } }, debug() { @@ -150,9 +159,10 @@ export default { }, async mounted() { try { + await checkCollaboraConfiguration() await checkProxyStatus() } catch (e) { - this.error = LOADING_ERROR.PROXY_FAILED + this.error = e.message this.loading = LOADING_STATE.FAILED return } @@ -168,7 +178,37 @@ export default { PostMessages.sendWOPIPostMessage(FRAME_DOCUMENT, msgId, values) }, }) - PostMessages.registerPostMessageHandler(({ parsed }) => { + PostMessages.registerPostMessageHandler(this.postMessageHandler) + this.load() + }, + beforeDestroy() { + PostMessages.unregisterPostMessageHandler(this.postMessageHandler) + }, + methods: { + async load() { + const isPublic = document.getElementById('isPublic') && document.getElementById('isPublic').value === '1' + this.src = getDocumentUrlForFile(this.filename, this.fileid) + '&path=' + encodeURIComponent(this.filename) + if (isPublic) { + this.src = getDocumentUrlForPublicFile(this.filename, this.fileid) + } + this.loading = LOADING_STATE.LOADING + this.loadingTimeout = setTimeout(() => { + console.error('FAILED') + this.loading = LOADING_STATE.FAILED + this.error = t('richdocuments', 'Failed to load {productName} - please try again later', { productName: loadState('richdocuments', 'productName', 'Nextcloud Office') }) + }, (OC.getCapabilities().richdocuments.config.timeout * 1000 || 15000)) + }, + documentReady() { + this.loading = LOADING_STATE.DOCUMENT_READY + clearTimeout(this.loadingTimeout) + }, + async share() { + FilesAppIntegration.share() + }, + close() { + this.$parent.close() + }, + postMessageHandler({ parsed }) { console.debug('[viewer] Received post message', parsed) const { msgId, args, deprecated } = parsed if (deprecated) { return } @@ -182,16 +222,24 @@ export default { FilesAppIntegration.initAfterReady() } if (args.Status === 'Document_Loaded') { - this.loading = LOADING_STATE.DOCUMENT_READY + this.documentReady() } else if (args.Status === 'Failed') { this.loading = LOADING_STATE.FAILED this.$emit('update:loaded', true) } break + case 'Action_Load_Resp': + if (args.success) { + this.documentReady() + } else { + this.error = args.errorMsg + this.loading = LOADING_STATE.FAILED + } + break case 'loading': break case 'close': - this.$parent.close() + this.close() break case 'Get_Views_Resp': case 'Views_List': @@ -218,25 +266,9 @@ export default { } break case 'UI_Share': - FilesAppIntegration.share() + this.share() break } - }) - this.load() - }, - methods: { - async load() { - const isPublic = document.getElementById('isPublic') && document.getElementById('isPublic').value === '1' - this.src = getDocumentUrlForFile(this.filename, this.fileid) + '&path=' + encodeURIComponent(this.filename) - if (isPublic) { - this.src = getDocumentUrlForPublicFile(this.filename, this.fileid) - } - this.loading = LOADING_STATE.LOADING - }, - async share() { - if (OCA.Files.Sidebar) { - OCA.Files.Sidebar.open(this.filename) - } }, }, } @@ -254,6 +286,10 @@ export default { &.debug { opacity: .5; } + + .empty-content p { + text-align: center; + } } .header { |