diff options
author | Ferdinand Thiessen <opensource@fthiessen.de> | 2024-01-18 18:27:22 +0100 |
---|---|---|
committer | Ferdinand Thiessen <opensource@fthiessen.de> | 2024-01-20 15:41:53 +0100 |
commit | b29c0cca24188fdd01679045cfdd18c91fad9a15 (patch) | |
tree | f4f36a7095f0a4b3ac6498e8b7fab3f5a24c0343 /apps/files/src | |
parent | eaad30c3461a662f68bd87bb76463847e4969f7f (diff) | |
download | nextcloud-server-b29c0cca24188fdd01679045cfdd18c91fad9a15.tar.gz nextcloud-server-b29c0cca24188fdd01679045cfdd18c91fad9a15.zip |
fix(files): Adjust `getUniqueName` for custom suffix and reuse for copy-move-action
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Diffstat (limited to 'apps/files/src')
-rw-r--r-- | apps/files/src/actions/moveOrCopyAction.ts | 34 | ||||
-rw-r--r-- | apps/files/src/init-templates.ts | 5 | ||||
-rw-r--r-- | apps/files/src/init.ts | 3 | ||||
-rw-r--r-- | apps/files/src/newMenu/newFolder.ts | 14 | ||||
-rw-r--r-- | apps/files/src/types.ts | 9 | ||||
-rw-r--r-- | apps/files/src/utils/fileUtils.ts | 19 |
6 files changed, 43 insertions, 41 deletions
diff --git a/apps/files/src/actions/moveOrCopyAction.ts b/apps/files/src/actions/moveOrCopyAction.ts index ab533dc599e..42ae82bb261 100644 --- a/apps/files/src/actions/moveOrCopyAction.ts +++ b/apps/files/src/actions/moveOrCopyAction.ts @@ -39,6 +39,7 @@ import FolderMoveSvg from '@mdi/svg/svg/folder-move.svg?raw' import { MoveCopyAction, canCopy, canMove, getQueue } from './moveOrCopyActionUtils' import logger from '../logger' +import { getUniqueName } from '../utils/fileUtils' /** * Return the action that is possible for the given nodes @@ -67,30 +68,6 @@ const getActionForNodes = (nodes: Node[]): MoveCopyAction => { * @return {Promise<void>} A promise that resolves when the copy/move is done */ export const handleCopyMoveNodeTo = async (node: Node, destination: Folder, method: MoveCopyAction.COPY | MoveCopyAction.MOVE, overwrite = false) => { - /** - * Create an unique name for a node - * @param node Node that is copied - * @param otherNodes Other nodes in the target directory to check for unique name - * @return Either the node basename, if unique, or the name with a `(copy N)` suffix that is unique - */ - const makeUniqueName = (node: Node, otherNodes: Node[]|FileStat[]) => { - const basename = node.basename.slice(0, node.basename.lastIndexOf('.')) - let index = 0 - - const currentName = () => { - switch (index) { - case 0: return node.basename - case 1: return `${basename} (copy)${node.extension ?? ''}` - default: return `${basename} ${t('files', '(copy %n)', undefined, index)}${node.extension ?? ''}` // TRANSLATORS: Meaning it is the n'th copy of a file - } - } - - while (otherNodes.some((other: Node|FileStat) => currentName() === other.basename)) { - index += 1 - } - return currentName() - } - if (!destination) { return } @@ -122,6 +99,13 @@ export const handleCopyMoveNodeTo = async (node: Node, destination: Folder, meth const queue = getQueue() return await queue.add(async () => { + const copySuffix = (index: number) => { + if (index === 1) { + return t('files', '(copy)') // TRANSLATORS: Mark a file as a copy of another file + } + return t('files', '(copy %n)', undefined, index) // TRANSLATORS: Meaning it is the n'th copy of a file + } + try { const client = davGetClient() const currentPath = join(davRootPath, node.path) @@ -132,7 +116,7 @@ export const handleCopyMoveNodeTo = async (node: Node, destination: Folder, meth // If we do not allow overwriting then find an unique name if (!overwrite) { const otherNodes = await client.getDirectoryContents(destinationPath) as FileStat[] - target = makeUniqueName(node, otherNodes) + target = getUniqueName(node.basename, otherNodes.map((n) => n.basename), copySuffix) } await client.copyFile(currentPath, join(destinationPath, target)) // If the node is copied into current directory the view needs to be updated diff --git a/apps/files/src/init-templates.ts b/apps/files/src/init-templates.ts index 879b60d0ee4..6803143d4b2 100644 --- a/apps/files/src/init-templates.ts +++ b/apps/files/src/init-templates.ts @@ -21,6 +21,7 @@ * */ import type { Entry } from '@nextcloud/files' +import type { TemplateFile } from './types' import { Folder, Node, Permission, addNewFileMenuEntry, removeNewFileMenuEntry } from '@nextcloud/files' import { generateOcsUrl } from '@nextcloud/router' @@ -35,7 +36,7 @@ import Vue from 'vue' import PlusSvg from '@mdi/svg/svg/plus.svg?raw' import TemplatePickerView from './views/TemplatePicker.vue' -import { getUniqueName } from './newMenu/newFolder' +import { getUniqueName } from './utils/fileUtils.ts' import { getCurrentUser } from '@nextcloud/auth' // Set up logger @@ -58,7 +59,7 @@ TemplatePickerRoot.id = 'template-picker' document.body.appendChild(TemplatePickerRoot) // Retrieve and init templates -let templates = loadState('files', 'templates', []) +let templates = loadState<TemplateFile[]>('files', 'templates', []) let templatesPath = loadState('files', 'templates_path', false) logger.debug('Templates providers', { templates }) logger.debug('Templates folder', { templatesPath }) diff --git a/apps/files/src/init.ts b/apps/files/src/init.ts index aa855ed69b2..8002f33ff56 100644 --- a/apps/files/src/init.ts +++ b/apps/files/src/init.ts @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ -import MenuIcon from '@mdi/svg/svg/sun-compass.svg?raw' -import { FileAction, addNewFileMenuEntry, registerDavProperty, registerFileAction } from '@nextcloud/files' +import { addNewFileMenuEntry, registerDavProperty, registerFileAction } from '@nextcloud/files' import { action as deleteAction } from './actions/deleteAction' import { action as downloadAction } from './actions/downloadAction' diff --git a/apps/files/src/newMenu/newFolder.ts b/apps/files/src/newMenu/newFolder.ts index d4da1baaab7..37dcf6d3d89 100644 --- a/apps/files/src/newMenu/newFolder.ts +++ b/apps/files/src/newMenu/newFolder.ts @@ -21,7 +21,7 @@ */ import type { Entry, Node } from '@nextcloud/files' -import { basename, extname } from 'path' +import { basename } from 'path' import { emit } from '@nextcloud/event-bus' import { getCurrentUser } from '@nextcloud/auth' import { Permission, Folder } from '@nextcloud/files' @@ -31,6 +31,7 @@ import axios from '@nextcloud/axios' import FolderPlusSvg from '@mdi/svg/svg/folder-plus.svg?raw' +import { getUniqueName } from '../utils/fileUtils.ts' import logger from '../logger' type createFolderResponse = { @@ -55,17 +56,6 @@ const createNewFolder = async (root: Folder, name: string): Promise<createFolder } } -// TODO: move to @nextcloud/files -export const getUniqueName = (name: string, names: string[]): string => { - let newName = name - let i = 1 - while (names.includes(newName)) { - const ext = extname(name) - newName = `${basename(name, ext)} (${i++})${ext}` - } - return newName -} - export const entry = { id: 'newFolder', displayName: t('files', 'New folder'), diff --git a/apps/files/src/types.ts b/apps/files/src/types.ts index 778e9ff2971..d2bfcaed0ee 100644 --- a/apps/files/src/types.ts +++ b/apps/files/src/types.ts @@ -111,3 +111,12 @@ export interface UploaderStore { export interface DragAndDropStore { dragging: FileId[] } + +export interface TemplateFile { + app: string + label: string + extension: string + iconClass?: string + mimetypes: string[] + ratio?: number +} diff --git a/apps/files/src/utils/fileUtils.ts b/apps/files/src/utils/fileUtils.ts index 9e2bfc44417..126739242a0 100644 --- a/apps/files/src/utils/fileUtils.ts +++ b/apps/files/src/utils/fileUtils.ts @@ -21,6 +21,25 @@ */ import { FileType, type Node } from '@nextcloud/files' import { translate as t, translatePlural as n } from '@nextcloud/l10n' +import { basename, extname } from 'path' + +// TODO: move to @nextcloud/files +/** + * Create an unique file name + * @param name The initial name to use + * @param otherNames Other names that are already used + * @param suffix A function that takes an index an returns a suffix to add, defaults to '(index)' + * @return Either the initial name, if unique, or the name with the suffix so that the name is unique + */ +export const getUniqueName = (name: string, otherNames: string[], suffix = (n: number) => `(${n})`): string => { + let newName = name + let i = 1 + while (otherNames.includes(newName)) { + const ext = extname(name) + newName = `${basename(name, ext)} ${suffix(i++)}${ext}` + } + return newName +} export const encodeFilePath = function(path) { const pathSections = (path.startsWith('/') ? path : `/${path}`).split('/') |