import '../css/filetypes.scss' import '../css/files.scss' import { emit } from '@nextcloud/event-bus' import { imagePath, generateOcsUrl, generateUrl, generateFilePath } from '@nextcloud/router' import { showError } from '@nextcloud/dialogs' import { getDocumentUrlFromTemplate, getDocumentUrlForPublicFile, getDocumentUrlForFile } from './helpers/url' import PostMessageService from './services/postMessage.tsx' import Config from './services/config.tsx' import Types from './helpers/types' import FilesAppIntegration from './view/FilesAppIntegration' import { splitPath } from './helpers' import NewFileMenu from './view/NewFileMenu' const FRAME_DOCUMENT = 'FRAME_DOCUMENT' const PostMessages = new PostMessageService({ FRAME_DOCUMENT: () => document.getElementById('richdocumentsframe').contentWindow, }) const isBrandedVersion = OC.getCapabilities().richdocuments.collabora.productVersion.split('.')[0] >= 21 // Workaround for Safari to resize the iframe to the proper height // as 100vh is not the proper viewport height there const handleResize = () => { const frame = document.getElementById('richdocumentsframe') if (frame) { const headerOffset = (!isBrandedVersion && window.innerWidth > 768) ? 50 : 0 frame.style.maxHeight = (document.documentElement.clientHeight - headerOffset) + 'px' } } window.addEventListener('resize', handleResize) if (window && window.visualViewport) { visualViewport.addEventListener('resize', handleResize) } const isDownloadHidden = document.getElementById('hideDownload') && document.getElementById('hideDownload').value === 'true' const isPublic = document.getElementById('isPublic') && document.getElementById('isPublic').value === '1' const odfViewer = { open: false, receivedLoading: false, isProxyStarting: false, isCollaboraConfigured: ( (OC.getCapabilities().richdocuments.config.wopi_url.indexOf('proxy.php') !== -1) || (typeof OC.getCapabilities().richdocuments.collabora === 'object' && OC.getCapabilities().richdocuments.collabora.length !== 0)), supportedMimes: OC.getCapabilities().richdocuments.mimetypes.concat(OC.getCapabilities().richdocuments.mimetypesNoDefaultOpen), excludeMimeFromDefaultOpen: OC.getCapabilities().richdocuments.mimetypesNoDefaultOpen, hideDownloadMimes: ['image/jpeg', 'image/svg+xml', 'image/cgm', 'image/vnd.dxf', 'image/x-emf', 'image/x-wmf', 'image/x-wpg', 'image/x-freehand', 'image/bmp', 'image/png', 'image/gif', 'image/tiff', 'image/jpg', 'image/jpeg', 'text/plain', 'application/pdf'], registerFileActions() { const EDIT_ACTION_NAME = 'Edit with ' + OC.getCapabilities().richdocuments.productName for (const mime of odfViewer.supportedMimes) { OCA.Files.fileActions.register( mime, EDIT_ACTION_NAME, OC.PERMISSION_READ, imagePath('core', 'actions/rename'), (fileName, context) => { // Workaround since the new template frontend doesn't pass // the full context yet nor the filelist contains the element // at the point when the action is triggered. // This will be fixed by https://github.com/nextcloud/server/pull/25797 // but this should be kept for backward compatibility for now if (!context?.$file) { if (context?.fileList) { context.fileList.setViewerMode(true) } const filePath = (context.dir === '/' ? '/' : context.dir + '/') + fileName OCA.Files.App.fileList.filesClient.getFileInfo(filePath).then((status, fileInfo) => { const fileModel = context.fileList.findFile(fileName) const shareOwnerId = fileModel?.shareOwnerId || fileInfo?.shareOwnerId context.fileId = fileInfo.id return this.onEdit(fileName, { ...context, shareOwnerId, }) }) return } const fileModel = context.fileList.findFile(fileName) const shareOwnerId = fileModel?.shareOwnerId return this.onEdit(fileName, { ...context, shareOwnerId, }) }, t('richdocuments', 'Edit with {productName}', { productName: OC.getCapabilities().richdocuments.productName }, undefined, { escape: false }) ) if (odfViewer.excludeMimeFromDefaultOpen.indexOf(mime) === -1 || isDownloadHidden) { OCA.Files.fileActions.setDefault(mime, EDIT_ACTION_NAME) } } }, onEdit(fileName, context) { let fileDir let fileId let templateId if (!odfViewer.isCollaboraConfigured) { $.get(generateOcsUrl('cloud') + '/capabilities?format=json').then( e => { if ((OC.getCapabilities().richdocuments.config.wopi_url.indexOf('proxy.php') !== -1) || (typeof e.ocs.data.capabilities.richdocuments.collabora === 'object' && e.ocs.data.capabilities.richdocuments.collabora.length !== 0)) { odfViewer.isCollaboraConfigured = true odfViewer.onEdit(fileName, context) } else { const setupUrl = generateUrl('/settings/admin/richdocuments') const installHint = OC.isUserAdmin() ? `Collabora Online is not setup yet.
Click here to configure your own server or connect to a demo server.
` : t('richdocuments', 'Collabora Online is not setup yet. Please contact your administrator.') showError(installHint, { isHTML: true, timeout: 0, }) } } ) return } if (odfViewer.open === true) { return } odfViewer.open = true if (context) { if (context?.$file?.attr('data-mounttype') === 'external-session') { showError(t('richdocuments', 'Opening the file is not supported, since the credentials for the external storage are not available without a session'), { timeout: 0, }) odfViewer.open = false return } fileDir = context.dir fileId = context.fileId || context.$file?.attr('data-id') templateId = context.templateId } FilesAppIntegration.startLoading() odfViewer.receivedLoading = false let documentUrl = getDocumentUrlForFile(fileDir, fileId) if (isPublic) { documentUrl = getDocumentUrlForPublicFile(fileName, fileId) } if (typeof (templateId) !== 'undefined') { documentUrl = getDocumentUrlFromTemplate(templateId, fileName, fileDir) } $('head').append($('')) const $iframe = $('