aboutsummaryrefslogtreecommitdiffstats
path: root/apps/files/src
diff options
context:
space:
mode:
authorFerdinand Thiessen <opensource@fthiessen.de>2024-01-18 18:27:22 +0100
committerFerdinand Thiessen <opensource@fthiessen.de>2024-01-20 15:41:53 +0100
commitb29c0cca24188fdd01679045cfdd18c91fad9a15 (patch)
treef4f36a7095f0a4b3ac6498e8b7fab3f5a24c0343 /apps/files/src
parenteaad30c3461a662f68bd87bb76463847e4969f7f (diff)
downloadnextcloud-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.ts34
-rw-r--r--apps/files/src/init-templates.ts5
-rw-r--r--apps/files/src/init.ts3
-rw-r--r--apps/files/src/newMenu/newFolder.ts14
-rw-r--r--apps/files/src/types.ts9
-rw-r--r--apps/files/src/utils/fileUtils.ts19
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('/')