You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

newFolder.ts 2.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /**
  2. * @copyright Copyright (c) 2023 John Molakvoæ <skjnldsv@protonmail.com>
  3. *
  4. * @author John Molakvoæ <skjnldsv@protonmail.com>
  5. *
  6. * @license AGPL-3.0-or-later
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU Affero General Public License as
  10. * published by the Free Software Foundation, either version 3 of the
  11. * License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU Affero General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Affero General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. *
  21. */
  22. import type { Entry, Node } from '@nextcloud/files'
  23. import { addNewFileMenuEntry, Permission, Folder } from '@nextcloud/files'
  24. import { basename, extname } from 'path'
  25. import { emit } from '@nextcloud/event-bus'
  26. import { getCurrentUser } from '@nextcloud/auth'
  27. import { showSuccess } from '@nextcloud/dialogs'
  28. import { translate as t } from '@nextcloud/l10n'
  29. import axios from '@nextcloud/axios'
  30. import FolderPlusSvg from '@mdi/svg/svg/folder-plus.svg?raw'
  31. import Vue from 'vue'
  32. type createFolderResponse = {
  33. fileid: number
  34. source: string
  35. }
  36. const createNewFolder = async (root: string, name: string): Promise<createFolderResponse> => {
  37. const source = root + '/' + name
  38. const response = await axios({
  39. method: 'MKCOL',
  40. url: source,
  41. headers: {
  42. Overwrite: 'F',
  43. },
  44. })
  45. return {
  46. fileid: parseInt(response.headers['oc-fileid']),
  47. source,
  48. }
  49. }
  50. // TODO: move to @nextcloud/files
  51. export const getUniqueName = (name: string, names: string[]): string => {
  52. let newName = name
  53. let i = 1
  54. while (names.includes(newName)) {
  55. const ext = extname(name)
  56. newName = `${basename(name, ext)} (${i++})${ext}`
  57. }
  58. return newName
  59. }
  60. const entry = {
  61. id: 'newFolder',
  62. displayName: t('files', 'New folder'),
  63. if: (context: Folder) => (context.permissions & Permission.CREATE) !== 0,
  64. iconSvgInline: FolderPlusSvg,
  65. async handler(context: Folder, content: Node[]) {
  66. const contentNames = content.map((node: Node) => node.basename)
  67. const name = getUniqueName(t('files', 'New folder'), contentNames)
  68. const { fileid, source } = await createNewFolder(context.source, name)
  69. // Create the folder in the store
  70. const folder = new Folder({
  71. source,
  72. id: fileid,
  73. mtime: new Date(),
  74. owner: getCurrentUser()?.uid || null,
  75. permissions: Permission.ALL,
  76. root: context?.root || '/files/' + getCurrentUser()?.uid,
  77. })
  78. if (!context._children) {
  79. Vue.set(context, '_children', [])
  80. }
  81. context._children.push(folder.fileid)
  82. showSuccess(t('files', 'Created new folder "{name}"', { name: basename(source) }))
  83. emit('files:node:created', folder)
  84. emit('files:node:rename', folder)
  85. },
  86. } as Entry
  87. addNewFileMenuEntry(entry)