feat(files): add uploader

Signed-off-by: John Molakvoæ <skjnldsv@protonmail.com>
pull/39945/head
John Molakvoæ 9 months ago
parent 4711c775b8
commit 52590a762f
No known key found for this signature in database
GPG Key ID: 60C25B8C072916CF

@ -11,6 +11,11 @@
<Home :size="20" />
</template>
</NcBreadcrumb>
<!-- Forward the actions slot -->
<template #actions>
<slot name="actions" />
</template>
</NcBreadcrumbs>
</template>

@ -171,7 +171,7 @@ import { debounce } from 'debounce'
import { emit } from '@nextcloud/event-bus'
import { extname } from 'path'
import { generateUrl } from '@nextcloud/router'
import { getFileActions, DefaultType, FileType, formatFileSize, Permission } from '@nextcloud/files'
import { getFileActions, DefaultType, FileType, formatFileSize, Permission, NodeStatus } from '@nextcloud/files'
import { showError, showSuccess } from '@nextcloud/dialogs'
import { translate } from '@nextcloud/l10n'
import { vOnClickOutside } from '@vueuse/components'
@ -521,8 +521,10 @@ export default Vue.extend({
* If renaming starts, select the file name
* in the input, without the extension.
*/
isRenaming() {
this.startRenaming()
isRenaming(renaming) {
if (renaming) {
this.startRenaming()
}
},
},
@ -718,9 +720,10 @@ export default Vue.extend({
* input validity using browser's native validation.
* @param event the keyup event
*/
checkInputValidity(event: KeyboardEvent) {
const input = event?.target as HTMLInputElement
checkInputValidity(event?: KeyboardEvent) {
const input = event.target as HTMLInputElement
const newName = this.newName.trim?.() || ''
logger.debug('Checking input validity', { newName })
try {
this.isFileNameValid(newName)
input.setCustomValidity('')
@ -753,10 +756,10 @@ export default Vue.extend({
},
startRenaming() {
this.checkInputValidity()
this.$nextTick(() => {
const extLength = (this.source.extension || '').length
const length = this.source.basename.length - extLength
// Using split to get the true string length
const extLength = (this.source.extension || '').split('').length
const length = this.source.basename.split('').length - extLength
const input = this.$refs.renameInput?.$refs?.inputField?.$refs?.input
if (!input) {
logger.error('Could not find the rename input')
@ -764,6 +767,9 @@ export default Vue.extend({
}
input.setSelectionRange(0, length)
input.focus()
// Trigger a keyup event to update the input validity
input.dispatchEvent(new Event('keyup'))
})
},
stopRenaming() {
@ -816,6 +822,8 @@ export default Vue.extend({
emit('files:node:updated', this.source)
emit('files:node:renamed', this.source)
showSuccess(this.t('files', 'Renamed "{oldName}" to "{newName}"', { oldName, newName }))
// Reset the renaming store
this.stopRenaming()
this.$nextTick(() => {
this.$refs.basename.focus()

@ -10,10 +10,12 @@ import './actions/openInFilesAction.js'
import './actions/renameAction'
import './actions/sidebarAction'
import './actions/viewInFolderAction'
import './newMenu/newFolder'
import Vue from 'vue'
import { createPinia, PiniaVuePlugin } from 'pinia'
import { getNavigation } from '@nextcloud/files'
import { getRequestToken } from '@nextcloud/auth'
import FilesListView from './views/FilesList.vue'
import NavigationView from './views/Navigation.vue'
@ -26,6 +28,9 @@ import RouterService from './services/RouterService'
import SettingsModel from './models/Setting.js'
import SettingsService from './services/Settings.js'
// @ts-expect-error __webpack_nonce__ is injected by webpack
__webpack_nonce__ = btoa(getRequestToken())
declare global {
interface Window {
OC: any;

@ -0,0 +1,96 @@
/**
* @copyright Copyright (c) 2023 John Molakvoæ <skjnldsv@protonmail.com>
*
* @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import type { Entry, Node } from '@nextcloud/files'
import { addNewFileMenuEntry, Permission, Folder } from '@nextcloud/files'
import { basename, extname } from 'path'
import { emit } from '@nextcloud/event-bus'
import { getCurrentUser } from '@nextcloud/auth'
import { showSuccess } from '@nextcloud/dialogs'
import { translate as t } from '@nextcloud/l10n'
import axios from '@nextcloud/axios'
import FolderPlusSvg from '@mdi/svg/svg/folder-plus.svg?raw'
import Vue from 'vue'
type createFolderResponse = {
fileid: number
source: string
}
const createNewFolder = async (root: string, name: string): Promise<createFolderResponse> => {
const source = root + '/' + name
const response = await axios({
method: 'MKCOL',
url: source,
headers: {
Overwrite: 'F',
},
})
return {
fileid: parseInt(response.headers['oc-fileid']),
source,
}
}
// 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
}
const entry = {
id: 'newFolder',
displayName: t('files', 'New folder'),
if: (context: Folder) => (context.permissions & Permission.CREATE) !== 0,
iconSvgInline: FolderPlusSvg,
async handler(context: Folder, content: Node[]) {
const contentNames = content.map((node: Node) => node.basename)
const name = getUniqueName(t('files', 'New Folder'), contentNames)
const { fileid, source } = await createNewFolder(context.source, name)
// Create the folder in the store
const folder = new Folder({
source,
id: fileid,
mtime: new Date(),
owner: getCurrentUser()?.uid || null,
permissions: Permission.ALL,
root: context?.root || '/files/' + getCurrentUser()?.uid,
})
if (!context._children) {
Vue.set(context, '_children', [])
}
context._children.push(folder.fileid)
showSuccess(t('files', 'Created new folder "{name}"', { name: basename(source) }))
emit('files:node:created', folder)
emit('files:node:rename', folder)
},
} as Entry
addNewFileMenuEntry(entry)

@ -22,6 +22,7 @@
import type { ContentsWithRoot } from '@nextcloud/files'
import type { FileStat, ResponseDataDetailed, DAVResultResponseProps } from 'webdav'
import { cancelable, CancelablePromise } from 'cancelable-promise'
import { File, Folder, davParsePermissions } from '@nextcloud/files'
import { generateRemoteUrl } from '@nextcloud/router'
import { getCurrentUser } from '@nextcloud/auth'
@ -73,30 +74,39 @@ const resultToNode = function(node: FileStat): File | Folder {
: new Folder(nodeData)
}
export const getContents = async (path = '/'): Promise<ContentsWithRoot> => {
export const getContents = (path = '/'): Promise<ContentsWithRoot> => {
const controller = new AbortController()
const propfindPayload = getDefaultPropfind()
const contentsResponse = await client.getDirectoryContents(path, {
details: true,
data: propfindPayload,
includeSelf: true,
}) as ResponseDataDetailed<FileStat[]>
return new CancelablePromise(async (resolve, reject, onCancel) => {
onCancel(() => controller.abort())
try {
const contentsResponse = await client.getDirectoryContents(path, {
details: true,
data: propfindPayload,
includeSelf: true,
signal: controller.signal,
}) as ResponseDataDetailed<FileStat[]>
const root = contentsResponse.data[0]
const contents = contentsResponse.data.slice(1)
if (root.filename !== path) {
throw new Error('Root node does not match requested path')
}
return {
folder: resultToNode(root) as Folder,
contents: contents.map(result => {
try {
return resultToNode(result)
} catch (error) {
logger.error(`Invalid node detected '${result.basename}'`, { error })
return null
const root = contentsResponse.data[0]
const contents = contentsResponse.data.slice(1)
if (root.filename !== path) {
throw new Error('Root node does not match requested path')
}
}).filter(Boolean) as File[],
}
resolve({
folder: resultToNode(root) as Folder,
contents: contents.map(result => {
try {
return resultToNode(result)
} catch (error) {
logger.error(`Invalid node detected '${result.basename}'`, { error })
return null
}
}).filter(Boolean) as File[],
})
} catch (error) {
reject(error)
}
})
}

@ -83,13 +83,17 @@ export const useFilesStore = function(...args) {
onDeletedNode(node: Node) {
this.deleteNodes([node])
},
onCreatedNode(node: Node) {
this.updateNodes([node])
},
},
})
const fileStore = store(...args)
// Make sure we only register the listeners once
if (!fileStore._initialized) {
// subscribe('files:node:created', fileStore.onCreatedNode)
subscribe('files:node:created', fileStore.onCreatedNode)
subscribe('files:node:deleted', fileStore.onDeletedNode)
// subscribe('files:node:moved', fileStore.onMovedNode)
// subscribe('files:node:updated', fileStore.onUpdatedNode)

@ -19,9 +19,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import { Node, getNavigation } from '@nextcloud/files'
import type { FileId, PathsStore, PathOptions, ServicesState } from '../types'
import { defineStore } from 'pinia'
import Vue from 'vue'
import logger from '../logger'
import { subscribe } from '@nextcloud/event-bus'
export const usePathsStore = function(...args) {
const store = defineStore('paths', {
@ -50,6 +53,19 @@ export const usePathsStore = function(...args) {
// Now we can set the provided path
Vue.set(this.paths[payload.service], payload.path, payload.fileid)
},
onCreatedNode(node: Node) {
const currentView = getNavigation().active
if (!node.fileid) {
logger.error('Node has no fileid', { node })
return
}
this.addPath({
service: currentView?.id || 'files',
path: node.path,
fileid: node.fileid,
})
},
},
})
@ -57,7 +73,7 @@ export const usePathsStore = function(...args) {
// Make sure we only register the listeners once
if (!pathsStore._initialized) {
// TODO: watch folders to update paths?
// subscribe('files:node:created', pathsStore.onCreatedNode)
subscribe('files:node:created', pathsStore.onCreatedNode)
// subscribe('files:node:deleted', pathsStore.onDeletedNode)
// subscribe('files:node:moved', pathsStore.onMovedNode)

@ -0,0 +1,41 @@
/**
* @copyright Copyright (c) 2023 John Molakvoæ <skjnldsv@protonmail.com>
*
* @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import type { Uploader } from '@nextcloud/upload'
import type { UploaderStore } from '../types'
import { defineStore } from 'pinia'
import { getUploader } from '@nextcloud/upload'
let uploader: Uploader
export const useUploaderStore = function(...args) {
// Only init on runtime
uploader = getUploader()
const store = defineStore('uploader', {
state: () => ({
queue: uploader.queue,
} as UploaderStore),
})
return store(...args)
}

@ -20,6 +20,7 @@
*
*/
import type { Folder, Node } from '@nextcloud/files'
import type { Upload } from '@nextcloud/upload'
// Global definitions
export type Service = string
@ -100,3 +101,8 @@ export interface RenamingStore {
renamingNode?: Node
newName: string
}
// Uploader store
export interface UploaderStore {
queue: Upload[]
}

@ -23,7 +23,16 @@
<NcAppContent data-cy-files-content>
<div class="files-list__header">
<!-- Current folder breadcrumbs -->
<BreadCrumbs :path="dir" @reload="fetchContent" />
<BreadCrumbs :path="dir" @reload="fetchContent">
<template #actions>
<!-- Uploader -->
<UploadPicker v-if="currentFolder"
:content="dirContents"
:destination="currentFolder"
:multiple="true"
@uploaded="onUpload" />
</template>
</BreadCrumbs>
<!-- Secondary loading indicator -->
<NcLoadingIcon v-if="isRefreshing" class="files-list__refresh-icon" />
@ -64,11 +73,15 @@
<script lang="ts">
import type { Route } from 'vue-router'
import type { Upload } from '@nextcloud/upload'
import type { UserConfig } from '../types.ts'
import type { View, ContentsWithRoot } from '@nextcloud/files'
import { Folder, Node, type View, type ContentsWithRoot, join } from 'path'
import { Folder, Node } from '@nextcloud/files'
import { join, dirname } from 'path'
import { orderBy } from 'natural-orderby'
import { translate } from '@nextcloud/l10n'
import { UploadPicker } from '@nextcloud/upload'
import NcAppContent from '@nextcloud/vue/dist/Components/NcAppContent.js'
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
import NcEmptyContent from '@nextcloud/vue/dist/Components/NcEmptyContent.js'
@ -79,6 +92,7 @@ import Vue from 'vue'
import { useFilesStore } from '../store/files.ts'
import { usePathsStore } from '../store/paths.ts'
import { useSelectionStore } from '../store/selection.ts'
import { useUploaderStore } from '../store/uploader.ts'
import { useUserConfigStore } from '../store/userconfig.ts'
import { useViewConfigStore } from '../store/viewConfig.ts'
import BreadCrumbs from '../components/BreadCrumbs.vue'
@ -97,6 +111,7 @@ export default Vue.extend({
NcEmptyContent,
NcIconSvgWrapper,
NcLoadingIcon,
UploadPicker,
},
mixins: [
@ -107,12 +122,14 @@ export default Vue.extend({
const filesStore = useFilesStore()
const pathsStore = usePathsStore()
const selectionStore = useSelectionStore()
const uploaderStore = useUploaderStore()
const userConfigStore = useUserConfigStore()
const viewConfigStore = useViewConfigStore()
return {
filesStore,
pathsStore,
selectionStore,
uploaderStore,
userConfigStore,
viewConfigStore,
}
@ -273,6 +290,7 @@ export default Vue.extend({
this.filesStore.updateNodes(contents)
// Define current directory children
// TODO: make it more official
folder._children = contents.map(node => node.fileid)
// If we're in the root dir, define the root
@ -308,10 +326,28 @@ export default Vue.extend({
* @param {number} fileId the file id to get
* @return {Folder|File}
*/
getNode(fileId) {
getNode(fileId) {
return this.filesStore.getNode(fileId)
},
/**
* The upload manager have finished handling the queue
* @param {Upload} upload the uploaded data
*/
onUpload(upload: Upload) {
// Let's only refresh the current Folder
// Navigating to a different folder will refresh it anyway
const destinationSource = dirname(upload.source)
const needsRefresh = destinationSource === this.currentFolder?.source
// TODO: fetch uploaded files data only
// Use parseInt(upload.response?.headers?.['oc-fileid']) to get the fileid
if (needsRefresh) {
// fetchContent will cancel the previous ongoing promise
this.fetchContent()
}
},
t: translate,
},
})

2
dist/2719-2719.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/3609-3609.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/4221-4221.js vendored

@ -0,0 +1,2 @@
"use strict";(self.webpackChunknextcloud=self.webpackChunknextcloud||[]).push([[4221],{84221:function(e,t,l){l.r(t),l.d(t,{confirm:function(){return y},filepicker:function(){return c}});var a=l(62520),i=l(41861),o=(l(52442),l(20144)),n=l(30050),s="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGlkPSJtZGktZm9sZGVyLW11bHRpcGxlIiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxwYXRoIGQ9Ik0yMiw0SDE0TDEyLDJINkEyLDIgMCAwLDAgNCw0VjE2QTIsMiAwIDAsMCA2LDE4SDIyQTIsMiAwIDAsMCAyNCwxNlY2QTIsMiAwIDAsMCAyMiw0TTIsNkgwVjExSDBWMjBBMiwyIDAgMCwwIDIsMjJIMjBWMjBIMlY2WiIgLz48L3N2Zz4=",u="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGlkPSJtZGktZm9sZGVyLW1vdmUiIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTE0LDE4VjE1SDEwVjExSDE0VjhMMTksMTNNMjAsNkgxMkwxMCw0SDRDMi44OSw0IDIsNC44OSAyLDZWMThBMiwyIDAgMCwwIDQsMjBIMjBBMiwyIDAgMCwwIDIyLDE4VjhDMjIsNi44OSAyMS4xLDYgMjAsNloiIC8+PC9zdmc+";const r=(e,t,l=(()=>{}))=>{const a=document.createElement("div");(document.querySelector(null==t?void 0:t.container)||document.body).appendChild(a);const i=new o.default({el:a,name:"VueDialogHelper",render:a=>a(e,{props:t,on:{close:()=>{l(),i.$destroy()}}})})};async function c(e,t,l=!1,o,n,c,y,m){const d=(e,t)=>{const a=e=>{const t=(null==e?void 0:e.root)||"";let l=(null==e?void 0:e.path)||"";return l.startsWith(t)&&(l=l.slice(t.length)||"/"),l};return l?l=>e(l.map(a),t):l=>e(a(l[0]),t)};let M;c===i.a.Custom?(M=[],(m.buttons||[]).forEach((e=>{M.push({callback:d(t,e.type),label:e.text,type:e.defaultButton?"primary":"secondary"})}))):M=(e,o)=>{var n,r,y;const m=[],M=(null==(r=null==(n=null==e?void 0:e[0])?void 0:n.attributes)?void 0:r.displayName)||(null==(y=null==e?void 0:e[0])?void 0:y.basename),p=M||(0,a.basename)(o);return c===i.a.Choose&&m.push({callback:d(t,i.a.Choose),label:M&&!l?(0,i.t)("Choose {file}",{file:M}):(0,i.t)("Choose"),type:"primary"}),(c===i.a.CopyMove||c===i.a.Copy)&&m.push({callback:d(t,i.a.Copy),label:p?(0,i.t)("Copy to {target}",{target:p}):(0,i.t)("Copy"),type:"primary",icon:s}),(c===i.a.Move||c===i.a.CopyMove)&&m.push({callback:d(t,i.a.Move),label:p?(0,i.t)("Move to {target}",{target:p}):(0,i.t)("Move"),type:c===i.a.Move?"primary":"secondary",icon:u}),m};const p={};"function"==typeof(null==m?void 0:m.filter)&&(p.filterFn=e=>m.filter((e=>{var t,l,a,i,o,n;return{id:e.fileid||null,path:e.path,mimetype:e.mime||null,mtime:(null==(t=e.mtime)?void 0:t.getTime())||null,permissions:e.permissions,name:(null==(l=e.attributes)?void 0:l.displayname)||e.basename,etag:(null==(a=e.attributes)?void 0:a.etag)||null,hasPreview:(null==(i=e.attributes)?void 0:i.hasPreview)||null,mountType:(null==(o=e.attributes)?void 0:o.mountType)||null,quotaAvailableBytes:(null==(n=e.attributes)?void 0:n.quotaAvailableBytes)||null,icon:null,sharePermissions:null}})(e)));const v="string"==typeof o?[o]:o||[];r(i.c,{...p,name:e,buttons:M,multiselect:l,path:y,mimetypeFilter:v,allowPickDirectory:!0===(null==m?void 0:m.allowDirectoryChooser)||v.includes("httpd/unix-directory")})}async function y(e,t,l,a){r(n.D,{name:t,message:e,buttons:[{label:"No",callback:()=>l(!1)},{label:"Yes",type:"primary",callback:()=>l(!0)}],size:"small"},(()=>l(!1)))}}}]);
//# sourceMappingURL=4221-4221.js.map?v=8176a71aa66260e1e1b2

File diff suppressed because one or more lines are too long

3
dist/50-50.js vendored

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
/*! For license information please see index.module.js.LICENSE.txt */

1
dist/50-50.js.map vendored

File diff suppressed because one or more lines are too long

2
dist/6870-6870.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/9223-9223.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
dist/9872-9872.js vendored

File diff suppressed because one or more lines are too long

@ -20,23 +20,10 @@
*
*/
/*!
* Determine if an object is a Buffer
*
* @author Feross Aboukhadijeh <https://feross.org>
* @license MIT
*/
/*! For license information please see NcDatetimePicker.js.LICENSE.txt */
/*! For license information please see NcInputField.js.LICENSE.txt */
/*! Hammer.JS - v2.0.7 - 2016-04-22
* http://hammerjs.github.io/
*
* Copyright (c) 2016 Jorik Tangelder;
* Licensed under the MIT license */
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
/**

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -128,6 +128,8 @@
/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
/*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
/**

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
dist/core-main.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -20,6 +20,13 @@
*
*/
/*!
* The buffer module from node.js, for the browser.
*
* @author Feross Aboukhadijeh <https://feross.org>
* @license MIT
*/
/*!
* pinia v2.1.6
* (c) 2023 Eduardo San Martin Morote

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -82,7 +82,7 @@ class MimeIconProvider implements IMimeIconProvider {
}
}
// Previously, we used to pass thi through Theming
// Previously, we used to pass this through Theming
// But it was only used to colour icons containing
// 0082c9. Since with vue we moved to inline svg icons,
// we can just use the default core icons.

178
package-lock.json generated

@ -19,7 +19,7 @@
"@nextcloud/capabilities": "^1.0.4",
"@nextcloud/dialogs": "^5.0.0-beta.2",
"@nextcloud/event-bus": "^3.1.0",
"@nextcloud/files": "^3.0.0-beta.19",
"@nextcloud/files": "^3.0.0-beta.21",
"@nextcloud/initial-state": "^2.0.0",
"@nextcloud/l10n": "^2.1.0",
"@nextcloud/logger": "^2.5.0",
@ -28,6 +28,7 @@
"@nextcloud/paths": "^2.1.0",
"@nextcloud/router": "^2.1.2",
"@nextcloud/sharing": "^0.1.0",
"@nextcloud/upload": "^1.0.0-beta.17",
"@nextcloud/vue": "^8.0.0-beta.5",
"@nextcloud/vue-dashboard": "^2.0.1",
"@skjnldsv/sanitize-svg": "^1.0.2",
@ -3680,9 +3681,9 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
"node_modules/@nextcloud/files": {
"version": "3.0.0-beta.19",
"resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-3.0.0-beta.19.tgz",
"integrity": "sha512-4VYTlscjR7f4svcZbSjrZrq+KKi3GYPels8PvyolYqMOBLWC4xjOrp5HFa20D7hnL/2Ynwymz3WeJBMP5YW1AQ==",
"version": "3.0.0-beta.21",
"resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-3.0.0-beta.21.tgz",
"integrity": "sha512-haydsUhF3t7DTUcC48lveztXZA1KMAkn+DRZUwSWu0S0VF4tTjn/+ZM7pqnNBIqOkPMTW9azAU8h6mmENpvd9w==",
"dependencies": {
"@nextcloud/auth": "^2.1.0",
"@nextcloud/l10n": "^2.2.0",
@ -3950,6 +3951,162 @@
"npm": "^7.0.0 || ^8.0.0"
}
},
"node_modules/@nextcloud/upload": {
"version": "1.0.0-beta.17",
"resolved": "https://registry.npmjs.org/@nextcloud/upload/-/upload-1.0.0-beta.17.tgz",
"integrity": "sha512-lrIv+eCwIJHmBDtLpqyMUDZoR7QsZn8MeQdNNz5siedKbbTJB4cAaYMCc9qf5kbWOwy5CVPoqUb9pQZtI9o4YQ==",
"dependencies": {
"@nextcloud/auth": "^2.1.0",
"@nextcloud/axios": "^2.4.0",
"@nextcloud/dialogs": "^4.2.0-beta.4",
"@nextcloud/files": "^3.0.0-beta.21",
"@nextcloud/l10n": "^2.2.0",
"@nextcloud/logger": "^2.5.0",
"@nextcloud/router": "^2.1.2",
"@nextcloud/vue": "^8.0.0-beta.3",
"buffer": "^6.0.3",
"crypto-browserify": "^3.12.0",
"p-cancelable": "^4.0.1",
"p-limit": "^4.0.0",
"p-queue": "^7.3.0",
"simple-eta": "^3.0.2",
"vue-material-design-icons": "^5.2.0"
},
"engines": {
"node": "^20.0.0",
"npm": "^9.0.0"
}
},
"node_modules/@nextcloud/upload/node_modules/@nextcloud/dialogs": {
"version": "4.2.0-beta.4",
"resolved": "https://registry.npmjs.org/@nextcloud/dialogs/-/dialogs-4.2.0-beta.4.tgz",
"integrity": "sha512-nk3hvO2DrxVGvj8U03feJVQuOZadiIxvtylxqYO/2/5ZS6ETUVRZgNFa5hK3Kf+a/OEkznVOxWTYOB2JbgRAzQ==",
"dependencies": {
"@mdi/svg": "^7.2.96",
"@nextcloud/files": "^3.0.0-beta.14",
"@nextcloud/l10n": "^2.2.0",
"@nextcloud/router": "^2.1.2",
"@nextcloud/typings": "^1.7.0",
"@nextcloud/vue": "^7.12.2",
"@types/toastify-js": "^1.12.0",
"@vueuse/core": "^10.3.0",
"toastify-js": "^1.12.0",
"vue-frag": "^1.4.3",
"vue-material-design-icons": "^5.2.0",
"webdav": "^5.2.3"
},
"engines": {
"node": "^20.0.0",
"npm": "^9.0.0"
},
"peerDependencies": {
"vue": "^2.7.14"
}
},
"node_modules/@nextcloud/upload/node_modules/@nextcloud/dialogs/node_modules/@nextcloud/dialogs": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/@nextcloud/dialogs/-/dialogs-4.1.0.tgz",
"integrity": "sha512-7e0QMdJKL1Pn/RxOA6Fjm2PMSEUSvhRXuyoZqNFN/rvvVK9mXOCvkRI+vYwuCBCzoTi1Bv3k12BoXxB2UHAufQ==",
"dependencies": {
"@nextcloud/l10n": "^2.1.0",
"@nextcloud/typings": "^1.7.0",
"core-js": "^3.31.0",
"toastify-js": "^1.12.0"
},
"engines": {
"node": "^20.0.0",
"npm": "^9.0.0"
}
},
"node_modules/@nextcloud/upload/node_modules/@nextcloud/dialogs/node_modules/@nextcloud/vue": {
"version": "7.12.4",
"resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-7.12.4.tgz",
"integrity": "sha512-ZW3DtIhD+aoaj9S4EB+X/kXCfIKgKXXMKKbECHkxl/CqtIvASmtxCNpt9DAlIETYKHwfuT3GWduxSnFCuLe1bQ==",
"dependencies": {
"@floating-ui/dom": "^1.1.0",
"@nextcloud/auth": "^2.0.0",
"@nextcloud/axios": "^2.0.0",
"@nextcloud/browser-storage": "^0.2.0",
"@nextcloud/calendar-js": "^6.0.0",
"@nextcloud/capabilities": "^1.0.4",
"@nextcloud/dialogs": "^4.0.0",
"@nextcloud/event-bus": "^3.0.0",
"@nextcloud/initial-state": "^2.0.0",
"@nextcloud/l10n": "^2.0.1",
"@nextcloud/logger": "^2.2.1",
"@nextcloud/router": "^2.0.0",
"@nextcloud/vue-select": "^3.21.2",
"@skjnldsv/sanitize-svg": "^1.0.2",
"@vueuse/components": "^10.0.2",
"clone": "^2.1.2",
"debounce": "1.2.1",
"emoji-mart-vue-fast": "^12.0.1",
"escape-html": "^1.0.3",
"floating-vue": "^1.0.0-beta.19",
"focus-trap": "^7.4.3",
"hammerjs": "^2.0.8",
"linkify-string": "^4.0.0",
"md5": "^2.3.0",
"node-polyfill-webpack-plugin": "^2.0.1",
"rehype-react": "^7.1.2",
"remark-breaks": "^3.0.2",
"remark-external-links": "^9.0.1",
"remark-parse": "^10.0.1",
"remark-rehype": "^10.1.0",
"splitpanes": "^2.4.1",
"string-length": "^5.0.1",
"striptags": "^3.2.0",
"tributejs": "^5.1.3",
"unified": "^10.1.2",
"unist-builder": "^3.0.1",
"unist-util-visit": "^4.1.2",
"vue": "^2.7.14",
"vue-color": "^2.8.1",
"vue-frag": "^1.4.3",
"vue-material-design-icons": "^5.1.2",
"vue-multiselect": "^2.1.6",
"vue2-datepicker": "^3.11.0"
},
"engines": {
"node": "^16.0.0",
"npm": "^7.0.0 || ^8.0.0"
}
},
"node_modules/@nextcloud/upload/node_modules/buffer": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.2.1"
}
},
"node_modules/@nextcloud/upload/node_modules/emoji-mart-vue-fast": {
"version": "12.0.5",
"resolved": "https://registry.npmjs.org/emoji-mart-vue-fast/-/emoji-mart-vue-fast-12.0.5.tgz",
"integrity": "sha512-XFNwIk+ConSAjC4tmk//s6btlo3oQco7TBgP914Qytg/15jLa/0VrWNg271W2MTv+8N8BxYl2dDn3cZJxcreqw==",
"dependencies": {
"@babel/runtime": "^7.18.6",
"core-js": "^3.23.5"
},
"peerDependencies": {
"vue": ">2.0.0"
}
},
"node_modules/@nextcloud/vue": {
"version": "8.0.0-beta.5",
"resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-8.0.0-beta.5.tgz",
@ -19626,6 +19783,14 @@
"integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==",
"dev": true
},
"node_modules/p-cancelable": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-4.0.1.tgz",
"integrity": "sha512-wBowNApzd45EIKdO1LaU+LrMBwAcjfPaYtVzV3lmfM3gf8Z4CHZsiIqlM8TZZ8okYvh5A1cP6gTfCRQtwUpaUg==",
"engines": {
"node": ">=14.16"
}
},
"node_modules/p-limit": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz",
@ -22241,6 +22406,11 @@
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
},
"node_modules/simple-eta": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/simple-eta/-/simple-eta-3.0.2.tgz",
"integrity": "sha512-+OmPgi01yHK/bRNQDoehUcV8fqs9nNJkG2DoWCnnLvj0lmowab7BH3v9776BG0y7dGEOLh0F7mfd37k+ht26Yw=="
},
"node_modules/sinon": {
"version": "5.0.7",
"resolved": "https://registry.npmjs.org/sinon/-/sinon-5.0.7.tgz",

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save