diff options
author | skjnldsv <skjnldsv@protonmail.com> | 2025-01-23 13:08:36 +0100 |
---|---|---|
committer | skjnldsv <skjnldsv@protonmail.com> | 2025-01-23 13:08:36 +0100 |
commit | 9fc3b2f29ebe8001777838fecda1750fda971acb (patch) | |
tree | 94d5d589618610e41597b60085b8689a58aaf286 | |
parent | be557caec03d8298646f9fff6d07f7fb6e3a8716 (diff) | |
download | nextcloud-server-fix/files-reload.tar.gz nextcloud-server-fix/files-reload.zip |
fix(files): allow triggering a Files reload directlyfix/files-reload
Signed-off-by: skjnldsv <skjnldsv@protonmail.com>
-rw-r--r-- | apps/files/src/actions/convertAction.ts | 6 | ||||
-rw-r--r-- | apps/files/src/actions/convertUtils.ts | 78 | ||||
-rw-r--r-- | apps/files/src/views/FilesList.vue | 7 |
3 files changed, 42 insertions, 49 deletions
diff --git a/apps/files/src/actions/convertAction.ts b/apps/files/src/actions/convertAction.ts index a8b4d537eb2..86719a2e31e 100644 --- a/apps/files/src/actions/convertAction.ts +++ b/apps/files/src/actions/convertAction.ts @@ -11,7 +11,7 @@ import { t } from '@nextcloud/l10n' import AutoRenewSvg from '@mdi/svg/svg/autorenew.svg?raw' -import { convertFile, convertFiles, getParentFolder } from './convertUtils' +import { convertFile, convertFiles } from './convertUtils' type ConversionsProvider = { from: string, @@ -35,7 +35,7 @@ export const registerConvertActions = () => { async exec(node: Node, view: View, dir: string) { // If we're here, we know that the node has a fileid - convertFile(node.fileid as number, to, getParentFolder(view, dir)) + convertFile(node.fileid as number, to) // Silently terminate, we'll handle the UI in the background return null @@ -43,7 +43,7 @@ export const registerConvertActions = () => { async execBatch(nodes: Node[], view: View, dir: string) { const fileIds = nodes.map(node => node.fileid).filter(Boolean) as number[] - convertFiles(fileIds, to, getParentFolder(view, dir)) + convertFiles(fileIds, to) // Silently terminate, we'll handle the UI in the background return Array(nodes.length).fill(null) diff --git a/apps/files/src/actions/convertUtils.ts b/apps/files/src/actions/convertUtils.ts index f32dbed0cd1..27571a41e94 100644 --- a/apps/files/src/actions/convertUtils.ts +++ b/apps/files/src/actions/convertUtils.ts @@ -3,9 +3,9 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ import type { AxiosResponse } from '@nextcloud/axios' -import type { Folder, View } from '@nextcloud/files' +import type { OCSResponse } from '@nextcloud/typings/ocs' -import { emit } from '@nextcloud/event-bus' +import { AxiosError } from 'axios' import { generateOcsUrl } from '@nextcloud/router' import { showError, showLoading, showSuccess } from '@nextcloud/dialogs' import { t } from '@nextcloud/l10n' @@ -13,20 +13,31 @@ import axios from '@nextcloud/axios' import PQueue from 'p-queue' import logger from '../logger' -import { useFilesStore } from '../store/files' -import { getPinia } from '../store' -import { usePathsStore } from '../store/paths' const queue = new PQueue({ concurrency: 5 }) -const requestConversion = function(fileId: number, targetMimeType: string): Promise<AxiosResponse> { +type ConversionResponse = { + path: string + fileId: number +} + +interface PromiseRejectedResult<T> { + status: 'rejected' + reason: T +} + +type PromiseSettledResult<T, E> = PromiseFulfilledResult<T> | PromiseRejectedResult<E>; +type ConversionSuccess = AxiosResponse<OCSResponse<ConversionResponse>> +type ConversionError = AxiosError<OCSResponse<ConversionResponse>> + +const requestConversion = function(fileId: number, targetMimeType: string): Promise<AxiosResponse<OCSResponse<ConversionResponse>>> { return axios.post(generateOcsUrl('/apps/files/api/v1/convert'), { fileId, targetMimeType, }) } -export const convertFiles = async function(fileIds: number[], targetMimeType: string, parentFolder: Folder | null) { +export const convertFiles = async function(fileIds: number[], targetMimeType: string) { const conversions = fileIds.map(fileId => queue.add(() => requestConversion(fileId, targetMimeType))) // Start conversion @@ -34,14 +45,14 @@ export const convertFiles = async function(fileIds: number[], targetMimeType: st // Handle results try { - const results = await Promise.allSettled(conversions) - const failed = results.filter(result => result.status === 'rejected') + const results = await Promise.allSettled(conversions) as PromiseSettledResult<ConversionSuccess, ConversionError>[] + const failed = results.filter(result => result.status === 'rejected') as PromiseRejectedResult<ConversionError>[] if (failed.length > 0) { - const messages = failed.map(result => result.reason?.response?.data?.ocs?.meta?.message) as string[] + const messages = failed.map(result => result.reason?.response?.data?.ocs?.meta?.message) logger.error('Failed to convert files', { fileIds, targetMimeType, messages }) // If all failed files have the same error message, show it - if (new Set(messages).size === 1) { + if (new Set(messages).size === 1 && typeof messages[0] === 'string') { showError(t('files', 'Failed to convert files: {message}', { message: messages[0] })) return } @@ -75,14 +86,14 @@ export const convertFiles = async function(fileIds: number[], targetMimeType: st showSuccess(t('files', 'Files successfully converted')) // Trigger a reload of the file list - if (parentFolder) { - emit('files:node:updated', parentFolder) - } + await window.OCP?.Files?.App?.reload?.() + + // Find the first file that is within the current folder // Switch to the new files - const firstSuccess = results[0] as PromiseFulfilledResult<AxiosResponse> + const firstSuccess = results[0] as PromiseFulfilledResult<ConversionSuccess> const newFileId = firstSuccess.value.data.ocs.data.fileId - window.OCP.Files.Router.goToRoute(null, { ...window.OCP.Files.Router.params, fileid: newFileId }, window.OCP.Files.Router.query) + window.OCP.Files.Router.goToRoute(null, { ...window.OCP.Files.Router.params, fileid: newFileId.toString() }, window.OCP.Files.Router.query) } catch (error) { // Should not happen as we use allSettled and handle errors above showError(t('files', 'Failed to convert files')) @@ -93,24 +104,22 @@ export const convertFiles = async function(fileIds: number[], targetMimeType: st } } -export const convertFile = async function(fileId: number, targetMimeType: string, parentFolder: Folder | null) { +export const convertFile = async function(fileId: number, targetMimeType: string) { const toast = showLoading(t('files', 'Converting fileā¦')) try { - const result = await queue.add(() => requestConversion(fileId, targetMimeType)) as AxiosResponse + const result = await queue.add(() => requestConversion(fileId, targetMimeType)) as AxiosResponse<OCSResponse<ConversionResponse>> showSuccess(t('files', 'File successfully converted')) // Trigger a reload of the file list - if (parentFolder) { - emit('files:node:updated', parentFolder) - } + await window.OCP?.Files?.App?.reload?.() // Switch to the new file const newFileId = result.data.ocs.data.fileId - window.OCP.Files.Router.goToRoute(null, { ...window.OCP.Files.Router.params, fileid: newFileId }, window.OCP.Files.Router.query) + window.OCP.Files.Router.goToRoute(null, { ...window.OCP.Files.Router.params, fileid: newFileId.toString() }, window.OCP.Files.Router.query) } catch (error) { // If the server returned an error message, show it - if (error.response?.data?.ocs?.meta?.message) { + if (error instanceof AxiosError && error?.response?.data?.ocs?.meta?.message) { showError(t('files', 'Failed to convert file: {message}', { message: error.response.data.ocs.meta.message })) return } @@ -122,26 +131,3 @@ export const convertFile = async function(fileId: number, targetMimeType: string toast.hideToast() } } - -/** - * Get the parent folder of a path - * - * TODO: replace by the parent node straight away when we - * update the Files actions api accordingly. - * - * @param view The current view - * @param path The path to the file - * @returns The parent folder - */ -export const getParentFolder = function(view: View, path: string): Folder | null { - const filesStore = useFilesStore(getPinia()) - const pathsStore = usePathsStore(getPinia()) - - const parentSource = pathsStore.getPath(view.id, path) - if (!parentSource) { - return null - } - - const parentFolder = filesStore.getNode(parentSource) as Folder | undefined - return parentFolder ?? null -} diff --git a/apps/files/src/views/FilesList.vue b/apps/files/src/views/FilesList.vue index 52868e459b9..eaded7070ea 100644 --- a/apps/files/src/views/FilesList.vue +++ b/apps/files/src/views/FilesList.vue @@ -533,6 +533,13 @@ export default defineComponent({ // reload on settings change subscribe('files:config:updated', this.fetchContent) + + // Init the global OCP.Files.App object + // OCP.Files is already initialized at this point + if (!window?.OCP?.Files?.App) { + window.OCP.Files.App = {} + } + Object.assign(window.OCP.Files.App, { ...window.OCP.Files.App, reload: this.fetchContent }) }, unmounted() { |