aboutsummaryrefslogtreecommitdiffstats
path: root/core/src/OC
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/OC')
-rw-r--r--core/src/OC/admin.js22
-rw-r--r--core/src/OC/appconfig.js29
-rw-r--r--core/src/OC/apps.js25
-rw-r--r--core/src/OC/appsettings.js97
-rw-r--r--core/src/OC/appswebroots.js21
-rw-r--r--core/src/OC/backbone-webdav.js23
-rw-r--r--core/src/OC/backbone.js24
-rw-r--r--core/src/OC/capabilities.js25
-rw-r--r--core/src/OC/config.js21
-rw-r--r--core/src/OC/constants.js22
-rw-r--r--core/src/OC/contactsmenu.js468
-rw-r--r--core/src/OC/contactsmenu/contact.handlebars70
-rw-r--r--core/src/OC/contactsmenu/error.handlebars4
-rw-r--r--core/src/OC/contactsmenu/list.handlebars12
-rw-r--r--core/src/OC/contactsmenu/loading.handlebars4
-rw-r--r--core/src/OC/contactsmenu/menu.handlebars4
-rw-r--r--core/src/OC/currentuser.js22
-rw-r--r--core/src/OC/debug.js21
-rw-r--r--core/src/OC/dialogs.js1110
-rw-r--r--core/src/OC/eventsource.js32
-rw-r--r--core/src/OC/get_set.js22
-rw-r--r--core/src/OC/host.js22
-rw-r--r--core/src/OC/index.js110
-rw-r--r--core/src/OC/l10n-registry.js90
-rw-r--r--core/src/OC/l10n.js328
-rw-r--r--core/src/OC/legacy-loader.js79
-rw-r--r--core/src/OC/menu.js27
-rw-r--r--core/src/OC/msg.js23
-rw-r--r--core/src/OC/navigation.js22
-rw-r--r--core/src/OC/notification.js38
-rw-r--r--core/src/OC/password-confirmation.js118
-rw-r--r--core/src/OC/plugins.js22
-rw-r--r--core/src/OC/query-string.js27
-rw-r--r--core/src/OC/requesttoken.js57
-rw-r--r--core/src/OC/requesttoken.ts49
-rw-r--r--core/src/OC/routing.js23
-rw-r--r--core/src/OC/theme.js21
-rw-r--r--core/src/OC/util-history.js26
-rw-r--r--core/src/OC/util.js34
-rw-r--r--core/src/OC/webroot.js21
-rw-r--r--core/src/OC/xhr-error.js40
41 files changed, 470 insertions, 2785 deletions
diff --git a/core/src/OC/admin.js b/core/src/OC/admin.js
index 5c939415266..d29e4cf676b 100644
--- a/core/src/OC/admin.js
+++ b/core/src/OC/admin.js
@@ -1,24 +1,6 @@
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @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/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
const isAdmin = !!window._oc_isadmin
diff --git a/core/src/OC/appconfig.js b/core/src/OC/appconfig.js
index 4b03f8db5fb..350ffc3f21c 100644
--- a/core/src/OC/appconfig.js
+++ b/core/src/OC/appconfig.js
@@ -1,32 +1,11 @@
/**
- * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Vincent Petry <vincent@nextcloud.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/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2014 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
/* eslint-disable */
- import { getValue, setValue, getApps, getKeys, deleteKey } from '../OCP/appconfig'
+ import { getValue, setValue, getApps, getKeys, deleteKey } from '../OCP/appconfig.js'
export const appConfig = window.oc_appconfig || {}
diff --git a/core/src/OC/apps.js b/core/src/OC/apps.js
index bbda177409e..dec2b94bfbb 100644
--- a/core/src/OC/apps.js
+++ b/core/src/OC/apps.js
@@ -1,24 +1,7 @@
/**
- * @copyright Bernhard Posselt 2014
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @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/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2014 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
import $ from 'jquery'
@@ -90,6 +73,7 @@ export const registerAppsSlideToggle = () => {
})
area.removeClass('opened')
$(button).removeClass('opened')
+ $(button).attr('aria-expanded', 'false')
}
/**
@@ -101,6 +85,7 @@ export const registerAppsSlideToggle = () => {
})
area.addClass('opened')
$(button).addClass('opened')
+ $(button).attr('aria-expanded', 'true')
const input = $(areaSelector + ' [autofocus]')
if (input.length === 1) {
input.focus()
diff --git a/core/src/OC/appsettings.js b/core/src/OC/appsettings.js
deleted file mode 100644
index a81708ca461..00000000000
--- a/core/src/OC/appsettings.js
+++ /dev/null
@@ -1,97 +0,0 @@
-/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @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/>.
- *
- */
-
-/* eslint-disable */
-import $ from 'jquery'
-import { filePath } from './routing'
-import { generateFilePath } from "@nextcloud/router"
-
-/**
- * Opens a popup with the setting for an app.
- * @param {string} appid The ID of the app e.g. 'calendar', 'contacts' or 'files'.
- * @param {boolean|string} loadJS If true 'js/settings.js' is loaded. If it's a string
- * it will attempt to load a script by that name in the 'js' directory.
- * @param {boolean} [cache] If true the javascript file won't be forced refreshed. Defaults to true.
- * @param {string} [scriptName] The name of the PHP file to load. Defaults to 'settings.php' in
- * the root of the app directory hierarchy.
- *
- * @deprecated 17.0.0 this method is unused and will be removed with Nextcloud 18
- */
-export const appSettings = args => {
- console.warn('OC.appSettings is deprecated and will be removed with Nextcloud 18')
-
- if (typeof args === 'undefined' || typeof args.appid === 'undefined') {
- throw {
- name: 'MissingParameter',
- message: 'The parameter appid is missing'
- }
- }
- var props = { scriptName: 'settings.php', cache: true }
- $.extend(props, args)
- var settings = $('#appsettings')
- if (settings.length === 0) {
- throw {
- name: 'MissingDOMElement',
- message: 'There has be be an element with id "appsettings" for the popup to show.'
- }
- }
- var popup = $('#appsettings_popup')
- if (popup.length === 0) {
- $('body').prepend('<div class="popup hidden" id="appsettings_popup"></div>')
- popup = $('#appsettings_popup')
- popup.addClass(settings.hasClass('topright') ? 'topright' : 'bottomleft')
- }
- if (popup.is(':visible')) {
- popup.hide().remove()
- } else {
- const arrowclass = settings.hasClass('topright') ? 'up' : 'left'
- $.get(generateFilePath(props.appid, '', props.scriptName), function(data) {
- popup.html(data).ready(function() {
- popup.prepend('<span class="arrow ' + arrowclass + '"></span><h2>' + t('core', 'Settings') + '</h2><a class="close"></a>').show()
- popup.find('.close').bind('click', function() {
- popup.remove()
- })
- if (typeof props.loadJS !== 'undefined') {
- var scriptname
- if (props.loadJS === true) {
- scriptname = 'settings.js'
- } else if (typeof props.loadJS === 'string') {
- scriptname = props.loadJS
- } else {
- throw {
- name: 'InvalidParameter',
- message: 'The "loadJS" parameter must be either boolean or a string.'
- }
- }
- if (props.cache) {
- $.ajaxSetup({ cache: true })
- }
- $.getScript(generateFilePath(props.appid, 'js', scriptname))
- .fail(function(jqxhr, settings, e) {
- throw e
- })
- }
- }).show()
- }, 'html')
- }
-}
diff --git a/core/src/OC/appswebroots.js b/core/src/OC/appswebroots.js
index ec2420eeed5..debbd2084bf 100644
--- a/core/src/OC/appswebroots.js
+++ b/core/src/OC/appswebroots.js
@@ -1,23 +1,6 @@
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @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/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
const appswebroots = (window._oc_appswebroots !== undefined) ? window._oc_appswebroots : false
diff --git a/core/src/OC/backbone-webdav.js b/core/src/OC/backbone-webdav.js
index ab234e22005..318c50e8ee5 100644
--- a/core/src/OC/backbone-webdav.js
+++ b/core/src/OC/backbone-webdav.js
@@ -1,25 +1,6 @@
/**
- * Copyright (c) 2015
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Julius Härtl <jus@bitgrid.net>
- *
- * @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/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
/* eslint-disable */
diff --git a/core/src/OC/backbone.js b/core/src/OC/backbone.js
index 17ef1c87109..08520e278f6 100644
--- a/core/src/OC/backbone.js
+++ b/core/src/OC/backbone.js
@@ -1,28 +1,10 @@
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @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/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
import VendorBackbone from 'backbone'
-import { davCall, davSync } from './backbone-webdav'
+import { davCall, davSync } from './backbone-webdav.js'
const Backbone = VendorBackbone.noConflict()
diff --git a/core/src/OC/capabilities.js b/core/src/OC/capabilities.js
index c7df9b4f3d1..10623229625 100644
--- a/core/src/OC/capabilities.js
+++ b/core/src/OC/capabilities.js
@@ -1,25 +1,6 @@
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @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/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { getCapabilities as realGetCapabilities } from '@nextcloud/capabilities'
@@ -32,6 +13,6 @@ import { getCapabilities as realGetCapabilities } from '@nextcloud/capabilities'
* @since 14.0.0
*/
export const getCapabilities = () => {
- console.warn('OC.getCapabilities is deprecated and will be removed in Nextcloud 21. See @nextcloud/capabilities')
+ OC.debug && console.warn('OC.getCapabilities is deprecated and will be removed in Nextcloud 21. See @nextcloud/capabilities')
return realGetCapabilities()
}
diff --git a/core/src/OC/config.js b/core/src/OC/config.js
index 702105a4836..c47df61f6e6 100644
--- a/core/src/OC/config.js
+++ b/core/src/OC/config.js
@@ -1,23 +1,6 @@
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @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/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
const config = window._oc_config || {}
diff --git a/core/src/OC/constants.js b/core/src/OC/constants.js
index f2ba7bf7a97..5298107e94d 100644
--- a/core/src/OC/constants.js
+++ b/core/src/OC/constants.js
@@ -1,24 +1,6 @@
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @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/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
export const coreApps = ['', 'admin', 'log', 'core/search', 'core', '3rdparty']
diff --git a/core/src/OC/contactsmenu.js b/core/src/OC/contactsmenu.js
deleted file mode 100644
index b9f4b0fc064..00000000000
--- a/core/src/OC/contactsmenu.js
+++ /dev/null
@@ -1,468 +0,0 @@
-/**
- * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @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/>.
- *
- */
-
-/* eslint-disable */
-import _ from 'underscore'
-import $ from 'jquery'
-import { Collection, Model, View } from 'backbone'
-
-import OC from './index'
-
-/**
- * @class Contact
- */
-const Contact = Model.extend({
- defaults: {
- fullName: '',
- lastMessage: '',
- actions: [],
- hasOneAction: false,
- hasTwoActions: false,
- hasManyActions: false
- },
-
- /**
- * @returns {undefined}
- */
- initialize: function() {
- // Add needed property for easier template rendering
- if (this.get('actions').length === 0) {
- this.set('hasOneAction', true)
- } else if (this.get('actions').length === 1) {
- this.set('hasTwoActions', true)
- this.set('secondAction', this.get('actions')[0])
- } else {
- this.set('hasManyActions', true)
- }
- }
-})
-
-/**
- * @class ContactCollection
- * @private
- */
-const ContactCollection = Collection.extend({
- model: Contact
-})
-
-/**
- * @class ContactsListView
- * @private
- */
-const ContactsListView = View.extend({
-
- /** @type {ContactCollection} */
- _collection: undefined,
-
- /** @type {array} */
- _subViews: [],
-
- /**
- * @param {object} options
- * @returns {undefined}
- */
- initialize: function(options) {
- this._collection = options.collection
- },
-
- /**
- * @returns {self}
- */
- render: function() {
- var self = this
- self.$el.html('')
- self._subViews = []
-
- self._collection.forEach(function(contact) {
- var item = new ContactsListItemView({
- model: contact
- })
- item.render()
- self.$el.append(item.$el)
- item.on('toggle:actionmenu', self._onChildActionMenuToggle, self)
- self._subViews.push(item)
- })
-
- return self
- },
-
- /**
- * Event callback to propagate opening (another) entry's action menu
- *
- * @param {type} $src
- * @returns {undefined}
- */
- _onChildActionMenuToggle: function($src) {
- this._subViews.forEach(function(view) {
- view.trigger('parent:toggle:actionmenu', $src)
- })
- }
-})
-
-/**
- * @class ContactsListItemView
- * @private
- */
-const ContactsListItemView = View.extend({
-
- /** @type {string} */
- className: 'contact',
-
- /** @type {undefined|function} */
- _template: undefined,
-
- /** @type {Contact} */
- _model: undefined,
-
- /** @type {boolean} */
- _actionMenuShown: false,
-
- events: {
- 'click .icon-more': '_onToggleActionsMenu'
- },
-
- contactTemplate: require('./contactsmenu/contact.handlebars'),
-
- /**
- * @param {object} data
- * @returns {undefined}
- */
- template: function(data) {
- return this.contactTemplate(data)
- },
-
- /**
- * @param {object} options
- * @returns {undefined}
- */
- initialize: function(options) {
- this._model = options.model
- this.on('parent:toggle:actionmenu', this._onOtherActionMenuOpened, this)
- },
-
- /**
- * @returns {self}
- */
- render: function() {
- this.$el.html(this.template({
- contact: this._model.toJSON()
- }))
- this.delegateEvents()
-
- // Show placeholder if no avatar is available (avatar is rendered as img, not div)
- this.$('div.avatar').imageplaceholder(this._model.get('fullName'))
-
- // Show tooltip for top action
- this.$('.top-action').tooltip({ placement: 'left' })
- // Show tooltip for second action
- this.$('.second-action').tooltip({ placement: 'left' })
-
- return this
- },
-
- /**
- * Toggle the visibility of the action popover menu
- *
- * @private
- * @returns {undefined}
- */
- _onToggleActionsMenu: function() {
- this._actionMenuShown = !this._actionMenuShown
- if (this._actionMenuShown) {
- this.$('.menu').show()
- } else {
- this.$('.menu').hide()
- }
- this.trigger('toggle:actionmenu', this.$el)
- },
-
- /**
- * @private
- * @argument {jQuery} $src
- * @returns {undefined}
- */
- _onOtherActionMenuOpened: function($src) {
- if (this.$el.is($src)) {
- // Ignore
- return
- }
- this._actionMenuShown = false
- this.$('.menu').hide()
- }
-})
-
-/**
- * @class ContactsMenuView
- * @private
- */
-const ContactsMenuView = View.extend({
-
- /** @type {undefined|function} */
- _loadingTemplate: undefined,
-
- /** @type {undefined|function} */
- _errorTemplate: undefined,
-
- /** @type {undefined|function} */
- _contentTemplate: undefined,
-
- /** @type {undefined|function} */
- _contactsTemplate: undefined,
-
- /** @type {undefined|ContactCollection} */
- _contacts: undefined,
-
- /** @type {string} */
- _searchTerm: '',
-
- events: {
- 'input #contactsmenu-search': '_onSearch'
- },
-
- templates: {
- loading: require('./contactsmenu/loading.handlebars'),
- error: require('./contactsmenu/error.handlebars'),
- menu: require('./contactsmenu/menu.handlebars'),
- list: require('./contactsmenu/list.handlebars')
- },
-
- /**
- * @returns {undefined}
- */
- _onSearch: _.debounce(function(e) {
- var searchTerm = this.$('#contactsmenu-search').val()
- // IE11 triggers an 'input' event after the view has been rendered
- // resulting in an endless loading loop. To prevent this, we remember
- // the last search term to savely ignore some events
- // See https://github.com/nextcloud/server/issues/5281
- if (searchTerm !== this._searchTerm) {
- this.trigger('search', this.$('#contactsmenu-search').val())
- this._searchTerm = searchTerm
- }
- }, 700),
-
- /**
- * @param {object} data
- * @returns {string}
- */
- loadingTemplate: function(data) {
- return this.templates.loading(data)
- },
-
- /**
- * @param {object} data
- * @returns {string}
- */
- errorTemplate: function(data) {
- return this.templates.error(
- _.extend({
- couldNotLoadText: t('core', 'Could not load your contacts')
- }, data)
- )
- },
-
- /**
- * @param {object} data
- * @returns {string}
- */
- contentTemplate: function(data) {
- return this.templates.menu(
- _.extend({
- searchContactsText: t('core', 'Search contacts …')
- }, data)
- )
- },
-
- /**
- * @param {object} data
- * @returns {string}
- */
- contactsTemplate: function(data) {
- return this.templates.list(
- _.extend({
- noContactsFoundText: t('core', 'No contacts found'),
- showAllContactsText: t('core', 'Show all contacts …'),
- contactsAppMgmtText: t('core', 'Install the Contacts app')
- }, data)
- )
- },
-
- /**
- * @param {object} options
- * @returns {undefined}
- */
- initialize: function(options) {
- this.options = options
- },
-
- /**
- * @param {string} text
- * @returns {undefined}
- */
- showLoading: function(text) {
- this.render()
- this._contacts = undefined
- this.$('.content').html(this.loadingTemplate({
- loadingText: text
- }))
- },
-
- /**
- * @returns {undefined}
- */
- showError: function() {
- this.render()
- this._contacts = undefined
- this.$('.content').html(this.errorTemplate())
- },
-
- /**
- * @param {object} viewData
- * @param {string} searchTerm
- * @returns {undefined}
- */
- showContacts: function(viewData, searchTerm) {
- this._contacts = viewData.contacts
- this.render({
- contacts: viewData.contacts
- })
-
- var list = new ContactsListView({
- collection: viewData.contacts
- })
- list.render()
- this.$('.content').html(this.contactsTemplate({
- contacts: viewData.contacts,
- searchTerm: searchTerm,
- contactsAppEnabled: viewData.contactsAppEnabled,
- contactsAppURL: OC.generateUrl('/apps/contacts'),
- canInstallApp: OC.isUserAdmin(),
- contactsAppMgmtURL: OC.generateUrl('/settings/apps/social/contacts')
- }))
- this.$('#contactsmenu-contacts').html(list.$el)
- },
-
- /**
- * @param {object} data
- * @returns {self}
- */
- render: function(data) {
- var searchVal = this.$('#contactsmenu-search').val()
- this.$el.html(this.contentTemplate(data))
-
- // Focus search
- this.$('#contactsmenu-search').val(searchVal)
- this.$('#contactsmenu-search').focus()
- return this
- }
-
-})
-
-/**
- * @param {Object} options
- * @param {string} options.el
- * @class ContactsMenu
- * @memberOf OC
- */
-const ContactsMenu = function(options) {
- this.initialize(options)
-}
-
-ContactsMenu.prototype = {
- /** @type {string} */
- $el: undefined,
-
- /** @type {ContactsMenuView} */
- _view: undefined,
-
- /** @type {Promise} */
- _contactsPromise: undefined,
-
- /**
- * @param {Object} options
- * @param {string} options.el - the selector of the element to render the menu in
- * @returns {undefined}
- */
- initialize: function(options) {
- this.$el = $(options.el)
-
- this._view = new ContactsMenuView({
- el: this.$el,
- })
-
- this._view.on('search', function(searchTerm) {
- this.loadContacts(searchTerm)
- }, this)
- },
-
- /**
- * @private
- * @param {string|undefined} searchTerm
- * @returns {Promise}
- */
- _getContacts: function(searchTerm) {
- var url = OC.generateUrl('/contactsmenu/contacts')
- return Promise.resolve($.ajax(url, {
- method: 'POST',
- data: {
- filter: searchTerm
- }
- }))
- },
-
- /**
- * @param {string|undefined} searchTerm
- * @returns {undefined}
- */
- loadContacts: function(searchTerm) {
- var self = this
-
- if (!self._contactsPromise) {
- self._contactsPromise = self._getContacts(searchTerm)
- }
-
- if (_.isUndefined(searchTerm) || searchTerm === '') {
- self._view.showLoading(t('core', 'Loading your contacts …'))
- } else {
- self._view.showLoading(t('core', 'Looking for {term} …', {
- term: searchTerm
- }))
- }
- return self._contactsPromise.then(function(data) {
- // Convert contact entries to Backbone collection
- data.contacts = new ContactCollection(data.contacts)
-
- self._view.showContacts(data, searchTerm)
- }, function(e) {
- self._view.showError()
- console.error('There was an error loading your contacts', e)
- }).then(function() {
- // Delete promise, so that contacts are fetched again when the
- // menu is opened the next time.
- delete self._contactsPromise
- }).catch(console.error.bind(this))
- }
-}
-
-export default ContactsMenu
diff --git a/core/src/OC/contactsmenu/contact.handlebars b/core/src/OC/contactsmenu/contact.handlebars
deleted file mode 100644
index afb2f627663..00000000000
--- a/core/src/OC/contactsmenu/contact.handlebars
+++ /dev/null
@@ -1,70 +0,0 @@
-{{#if contact.avatar}}
- {{#if contact.profileUrl}}
- {{#if contact.profileTitle}}
- <a class="profile-link--avatar" href="{{contact.profileUrl}}">
- <img src="{{contact.avatar}}&size=32" class="avatar" srcset="{{contact.avatar}}&size=32 1x, {{contact.avatar}}&size=64 2x, {{contact.avatar}}&size=128 4x" alt="">
- </a>
- {{/if}}
- {{else}}
- <img src="{{contact.avatar}}&size=32" class="avatar" srcset="{{contact.avatar}}&size=32 1x, {{contact.avatar}}&size=64 2x, {{contact.avatar}}&size=128 4x" alt="">
- {{/if}}
-{{else}}
- {{#if contact.profileUrl}}
- {{#if contact.profileTitle}}
- <a class="profile-link--avatar" href="{{contact.profileUrl}}">
- <div class="avatar"></div>
- </a>
- {{/if}}
- {{else}}
- <div class="avatar"></div>
- {{/if}}
-{{/if}}
-{{#if contact.profileUrl}}
- {{#if contact.profileTitle}}
- <a class="body profile-link--full-name" href="{{contact.profileUrl}}">
- <div class="full-name">{{contact.fullName}}</div>
- <div class="last-message">{{contact.lastMessage}}</div>
- <div class="email-address">{{contact.emailAddresses}}</div>
- </a>
- {{/if}}
- {{#if contact.topAction}}
- <a class="top-action" href="{{contact.topAction.hyperlink}}" title="{{contact.topAction.title}}">
- <img src="{{contact.topAction.icon}}" alt="{{contact.topAction.title}}">
- </a>
- {{/if}}
-{{else if contact.topAction}}
- <a class="body" href="{{contact.topAction.hyperlink}}">
- <div class="full-name">{{contact.fullName}}</div>
- <div class="last-message">{{contact.lastMessage}}</div>
- <div class="email-address">{{contact.emailAddresses}}</div>
- </a>
- <a class="top-action" href="{{contact.topAction.hyperlink}}" title="{{contact.topAction.title}}">
- <img src="{{contact.topAction.icon}}" alt="{{contact.topAction.title}}">
- </a>
-{{else}}
- <div class="body">
- <div class="full-name">{{contact.fullName}}</div>
- <div class="last-message">{{contact.lastMessage}}</div>
- <div class="email-address">{{contact.emailAddresses}}</div>
- </div>
-{{/if}}
-{{#if contact.hasTwoActions}}
-<a class="second-action" href="{{contact.secondAction.hyperlink}}" title="{{contact.secondAction.title}}">
- <img src="{{contact.secondAction.icon}}" alt="{{contact.secondAction.title}}">
-</a>
-{{/if}}
-{{#if contact.hasManyActions}}
- <button class="other-actions icon-more"></button>
- <div class="menu popovermenu">
- <ul>
- {{#each contact.actions}}
- <li>
- <a href="{{hyperlink}}">
- <img src="{{icon}}" alt="">
- <span>{{title}}</span>
- </a>
- </li>
- {{/each}}
- </ul>
- </div>
-{{/if}}
diff --git a/core/src/OC/contactsmenu/error.handlebars b/core/src/OC/contactsmenu/error.handlebars
deleted file mode 100644
index 5115595b4e1..00000000000
--- a/core/src/OC/contactsmenu/error.handlebars
+++ /dev/null
@@ -1,4 +0,0 @@
-<div class="emptycontent">
- <div class="icon-search"></div>
- <h2>{{couldNotLoadText}}</h2>
-</div>
diff --git a/core/src/OC/contactsmenu/list.handlebars b/core/src/OC/contactsmenu/list.handlebars
deleted file mode 100644
index 0bcff7d1a85..00000000000
--- a/core/src/OC/contactsmenu/list.handlebars
+++ /dev/null
@@ -1,12 +0,0 @@
-{{#unless contacts.length}}
-<div class="emptycontent">
- <div class="icon-search"></div>
- <h2>{{noContactsFoundText}}</h2>
-</div>
-{{/unless}}
-<div id="contactsmenu-contacts"></div>
-{{#if contactsAppEnabled}}
-<div class="footer"><a href="{{contactsAppURL}}">{{showAllContactsText}}</a></div>
-{{else if canInstallApp}}
-<div class="footer"><a href="{{contactsAppMgmtURL}}">{{contactsAppMgmtText}}</a></div>
-{{/if}}
diff --git a/core/src/OC/contactsmenu/loading.handlebars b/core/src/OC/contactsmenu/loading.handlebars
deleted file mode 100644
index 7fb22a6ed8e..00000000000
--- a/core/src/OC/contactsmenu/loading.handlebars
+++ /dev/null
@@ -1,4 +0,0 @@
-<div class="emptycontent">
- <div class="icon-loading"></div>
- <h2>{{loadingText}}</h2>
-</div>
diff --git a/core/src/OC/contactsmenu/menu.handlebars b/core/src/OC/contactsmenu/menu.handlebars
deleted file mode 100644
index 7d7697e780c..00000000000
--- a/core/src/OC/contactsmenu/menu.handlebars
+++ /dev/null
@@ -1,4 +0,0 @@
-<label class="hidden-visually" for="contactsmenu-search">{{searchContactsText}}</label>
-<input id="contactsmenu-search" type="search" placeholder="{{searchContactsText}}" value="{{searchTerm}}">
-<div class="content">
-</div>
diff --git a/core/src/OC/currentuser.js b/core/src/OC/currentuser.js
index c6e8a8ee62c..a022698eab0 100644
--- a/core/src/OC/currentuser.js
+++ b/core/src/OC/currentuser.js
@@ -1,24 +1,6 @@
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.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/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
const rawUid = document
diff --git a/core/src/OC/debug.js b/core/src/OC/debug.js
index 25a6eae9597..52a9ef28145 100644
--- a/core/src/OC/debug.js
+++ b/core/src/OC/debug.js
@@ -1,23 +1,6 @@
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @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/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
const base = window._oc_debug
diff --git a/core/src/OC/dialogs.js b/core/src/OC/dialogs.js
index 286f9848290..5c6934e67a2 100644
--- a/core/src/OC/dialogs.js
+++ b/core/src/OC/dialogs.js
@@ -1,79 +1,51 @@
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- * @copyright Copyright (c) 2019 Gary Kim <gary@garykim.dev>
- *
- * @author Bartek Przybylski <bart.p.pl@gmail.com>
- * @author Christopher Schäpers <kondou@ts.unde.re>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Calviño Sánchez <danxuliu@gmail.com>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Florian Schunk <florian.schunk@rwth-aachen.de>
- * @author Gary Kim <gary@garykim.dev>
- * @author Hendrik Leppelsack <hendrik@leppelsack.de>
- * @author Jan-Christoph Borchardt <hey@jancborchardt.net>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author Loïc Hermann <loic.hermann@sciam.fr>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Olivier Paroz <github@oparoz.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Sujith Haridasan <Sujith_Haridasan@mentor.com>
- * @author Thomas Citharel <nextcloud@tcit.fr>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Thomas Tanghus <thomas@tanghus.net>
- * @author Vincent Petry <vincent@nextcloud.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/>.
- *
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2015 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
/* eslint-disable */
import _ from 'underscore'
import $ from 'jquery'
-import OC from './index'
-import OCA from '../OCA/index'
-import { isA11yActivation } from '../Util/a11y'
+import IconMove from '@mdi/svg/svg/folder-move.svg?raw'
+import IconCopy from '@mdi/svg/svg/folder-multiple-outline.svg?raw'
+
+import OC from './index.js'
+import { DialogBuilder, FilePickerType, getFilePickerBuilder, spawnDialog } from '@nextcloud/dialogs'
+import { translate as t } from '@nextcloud/l10n'
+import { basename } from 'path'
+import { defineAsyncComponent } from 'vue'
/**
* this class to ease the usage of jquery dialogs
*/
const Dialogs = {
// dialog button types
+ /** @deprecated use `@nextcloud/dialogs` */
YES_NO_BUTTONS: 70,
+ /** @deprecated use `@nextcloud/dialogs` */
OK_BUTTONS: 71,
+ /** @deprecated use FilePickerType from `@nextcloud/dialogs` */
FILEPICKER_TYPE_CHOOSE: 1,
+ /** @deprecated use FilePickerType from `@nextcloud/dialogs` */
FILEPICKER_TYPE_MOVE: 2,
+ /** @deprecated use FilePickerType from `@nextcloud/dialogs` */
FILEPICKER_TYPE_COPY: 3,
+ /** @deprecated use FilePickerType from `@nextcloud/dialogs` */
FILEPICKER_TYPE_COPY_MOVE: 4,
+ /** @deprecated use FilePickerType from `@nextcloud/dialogs` */
FILEPICKER_TYPE_CUSTOM: 5,
- // used to name each dialog
- dialogsCounter: 0,
-
/**
* displays alert dialog
* @param {string} text content of dialog
* @param {string} title dialog title
* @param {function} callback which will be triggered when user presses OK
* @param {boolean} [modal] make the dialog modal
+ *
+ * @deprecated 30.0.0 Use `@nextcloud/dialogs` instead or build your own with `@nextcloud/vue` NcDialog
*/
alert: function(text, title, callback, modal) {
this.message(
@@ -85,12 +57,15 @@ const Dialogs = {
modal
)
},
+
/**
* displays info dialog
* @param {string} text content of dialog
* @param {string} title dialog title
* @param {function} callback which will be triggered when user presses OK
* @param {boolean} [modal] make the dialog modal
+ *
+ * @deprecated 30.0.0 Use `@nextcloud/dialogs` instead or build your own with `@nextcloud/vue` NcDialog
*/
info: function(text, title, callback, modal) {
this.message(text, title, 'info', Dialogs.OK_BUTTON, callback, modal)
@@ -103,6 +78,8 @@ const Dialogs = {
* @param {function} callback which will be triggered when user presses OK (true or false would be passed to callback respectively)
* @param {boolean} [modal] make the dialog modal
* @returns {Promise}
+ *
+ * @deprecated 30.0.0 Use `@nextcloud/dialogs` instead or build your own with `@nextcloud/vue` NcDialog
*/
confirm: function(text, title, callback, modal) {
return this.message(
@@ -122,16 +99,34 @@ const Dialogs = {
* @param {function} callback which will be triggered when user presses OK (true or false would be passed to callback respectively)
* @param {boolean} [modal] make the dialog modal
* @returns {Promise}
+ *
+ * @deprecated 30.0.0 Use `@nextcloud/dialogs` instead or build your own with `@nextcloud/vue` NcDialog
*/
- confirmDestructive: function(text, title, buttons, callback, modal) {
- return this.message(
- text,
- title,
- 'none',
- buttons,
- callback,
- modal === undefined ? true : modal
- )
+ confirmDestructive: function(text, title, buttons = Dialogs.OK_BUTTONS, callback = () => {}, modal) {
+ return (new DialogBuilder())
+ .setName(title)
+ .setText(text)
+ .setButtons(
+ buttons === Dialogs.OK_BUTTONS
+ ? [
+ {
+ label: t('core', 'Yes'),
+ type: 'error',
+ callback: () => {
+ callback.clicked = true
+ callback(true)
+ },
+ }
+ ]
+ : Dialogs._getLegacyButtons(buttons, callback)
+ )
+ .build()
+ .show()
+ .then(() => {
+ if (!callback.clicked) {
+ callback(false)
+ }
+ })
},
/**
* displays confirmation dialog
@@ -140,17 +135,35 @@ const Dialogs = {
* @param {function} callback which will be triggered when user presses OK (true or false would be passed to callback respectively)
* @param {boolean} [modal] make the dialog modal
* @returns {Promise}
+ *
+ * @deprecated 30.0.0 Use `@nextcloud/dialogs` instead or build your own with `@nextcloud/vue` NcDialog
*/
confirmHtml: function(text, title, callback, modal) {
- return this.message(
- text,
- title,
- 'notice',
- Dialogs.YES_NO_BUTTONS,
- callback,
- modal,
- true
- )
+ return (new DialogBuilder())
+ .setName(title)
+ .setText('')
+ .setButtons([
+ {
+ label: t('core', 'No'),
+ callback: () => {},
+ },
+ {
+ label: t('core', 'Yes'),
+ type: 'primary',
+ callback: () => {
+ callback.clicked = true
+ callback(true)
+ },
+ },
+ ])
+ .build()
+ .setHTML(text)
+ .show()
+ .then(() => {
+ if (!callback.clicked) {
+ callback(false)
+ }
+ })
},
/**
* displays prompt dialog
@@ -161,73 +174,32 @@ const Dialogs = {
* @param {string} name name of the input field
* @param {boolean} password whether the input should be a password input
* @returns {Promise}
+ *
+ * @deprecated Use NcDialog from `@nextcloud/vue` instead
*/
prompt: function(text, title, callback, modal, name, password) {
- return $.when(this._getMessageTemplate()).then(function($tmpl) {
- var dialogName = 'oc-dialog-' + Dialogs.dialogsCounter + '-content'
- var dialogId = '#' + dialogName
- var $dlg = $tmpl.octemplate({
- dialog_name: dialogName,
- title: title,
- message: text,
- type: 'notice'
- })
- var input = $('<input/>')
- input.attr('type', password ? 'password' : 'text').attr('id', dialogName + '-input').attr('placeholder', name)
- var label = $('<label/>').attr('for', dialogName + '-input').text(name + ': ')
- $dlg.append(label)
- $dlg.append(input)
- if (modal === undefined) {
- modal = false
- }
- $('body').append($dlg)
-
- // wrap callback in _.once():
- // only call callback once and not twice (button handler and close
- // event) but call it for the close event, if ESC or the x is hit
- if (callback !== undefined) {
- callback = _.once(callback)
- }
-
- var buttonlist = [{
- text: t('core', 'No'),
- click: function() {
- if (callback !== undefined) {
- // eslint-disable-next-line standard/no-callback-literal
- callback(false, input.val())
- }
- $(dialogId).ocdialog('close')
- }
- }, {
- text: t('core', 'Yes'),
- click: function() {
- if (callback !== undefined) {
- // eslint-disable-next-line standard/no-callback-literal
- callback(true, input.val())
- }
- $(dialogId).ocdialog('close')
+ return new Promise((resolve) => {
+ spawnDialog(
+ defineAsyncComponent(() => import('../components/LegacyDialogPrompt.vue')),
+ {
+ text,
+ name: title,
+ callback,
+ inputName: name,
+ isPassword: !!password
},
- defaultButton: true
- }]
-
- $(dialogId).ocdialog({
- closeOnEscape: true,
- modal: modal,
- buttons: buttonlist,
- close: function() {
- // callback is already fired if Yes/No is clicked directly
- if (callback !== undefined) {
- // eslint-disable-next-line standard/no-callback-literal
- callback(false, input.val())
- }
- }
- })
- input.focus()
- Dialogs.dialogsCounter++
+ (...args) => {
+ callback(...args)
+ resolve()
+ },
+ )
})
},
+
/**
- * show a file picker to pick a file from
+ * Legacy wrapper to the new Vue based filepicker from `@nextcloud/dialogs`
+ *
+ * Prefer to use the Vue filepicker directly instead.
*
* In order to pick several types of mime types they need to be passed as an
* array of strings.
@@ -237,441 +209,196 @@ const Dialogs = {
* should be used instead.
*
* @param {string} title dialog title
- * @param {function} callback which will be triggered when user presses Choose
+ * @param {Function} callback which will be triggered when user presses Choose
* @param {boolean} [multiselect] whether it should be possible to select multiple files
- * @param {string[]} [mimetypeFilter] mimetype to filter by - directories will always be included
- * @param {boolean} [modal] make the dialog modal
+ * @param {string[]} [mimetype] mimetype to filter by - directories will always be included
+ * @param {boolean} [_modal] do not use
* @param {string} [type] Type of file picker : Choose, copy, move, copy and move
* @param {string} [path] path to the folder that the the file can be picket from
- * @param {Object} [options] additonal options that need to be set
+ * @param {object} [options] additonal options that need to be set
* @param {Function} [options.filter] filter function for advanced filtering
+ * @param {boolean} [options.allowDirectoryChooser] Allow to select directories
+ * @deprecated since 27.1.0 use the filepicker from `@nextcloud/dialogs` instead
*/
- filepicker: function(title, callback, multiselect, mimetypeFilter, modal, type, path, options) {
- var self = this
-
- this.filepicker.sortField = 'name'
- this.filepicker.sortOrder = 'asc'
- // avoid opening the picker twice
- if (this.filepicker.loading) {
- return
- }
+ filepicker(title, callback, multiselect = false, mimetype = undefined, _modal = undefined, type = FilePickerType.Choose, path = undefined, options = undefined) {
- if (type === undefined) {
- type = this.FILEPICKER_TYPE_CHOOSE
- }
-
- var emptyText = t('core', 'No files in here')
- var newText = t('files', 'New folder')
- if (type === this.FILEPICKER_TYPE_COPY || type === this.FILEPICKER_TYPE_MOVE || type === this.FILEPICKER_TYPE_COPY_MOVE) {
- emptyText = t('core', 'No more subfolders in here')
- }
-
- this.filepicker.loading = true
- this.filepicker.filesClient = (OCA.Sharing && OCA.Sharing.PublicApp && OCA.Sharing.PublicApp.fileList) ? OCA.Sharing.PublicApp.fileList.filesClient : OC.Files.getClient()
-
- this.filelist = null
- path = path || ''
- options = Object.assign({
- allowDirectoryChooser: false
- }, options)
-
- $.when(this._getFilePickerTemplate()).then(function($tmpl) {
- self.filepicker.loading = false
- var dialogName = 'oc-dialog-filepicker-content'
- if (self.$filePicker) {
- self.$filePicker.ocdialog('close')
- }
-
- if (mimetypeFilter === undefined || mimetypeFilter === null) {
- mimetypeFilter = []
- }
- if (typeof (mimetypeFilter) === 'string') {
- mimetypeFilter = [mimetypeFilter]
- }
-
- self.$filePicker = $tmpl.octemplate({
- dialog_name: dialogName,
- title: title,
- emptytext: emptyText,
- newtext: newText,
- nameCol: t('core', 'Name'),
- sizeCol: t('core', 'Size'),
- modifiedCol: t('core', 'Modified')
- }).data('path', path).data('multiselect', multiselect).data('mimetype', mimetypeFilter).data('allowDirectoryChooser', options.allowDirectoryChooser)
- if (typeof(options.filter) === 'function') {
- self.$filePicker.data('filter', options.filter)
+ /**
+ * Create legacy callback wrapper to support old filepicker syntax
+ * @param fn The original callback
+ * @param type The file picker type which was used to pick the file(s)
+ */
+ const legacyCallback = (fn, type) => {
+ const getPath = (node) => {
+ const root = node?.root || ''
+ let path = node?.path || ''
+ // TODO: Fix this in @nextcloud/files
+ if (path.startsWith(root)) {
+ path = path.slice(root.length) || '/'
+ }
+ return path
}
- if (modal === undefined) {
- modal = false
- }
- if (multiselect === undefined) {
- multiselect = false
+ if (multiselect) {
+ return (nodes) => fn(nodes.map(getPath), type)
+ } else {
+ return (nodes) => fn(getPath(nodes[0]), type)
}
+ }
- $('body').prepend(self.$filePicker)
-
- self.$showGridView = $('button#picker-showgridview')
- self.$showGridView.on('click keydown', function(event) {
- if (isA11yActivation(event)) {
- self._onGridviewChange()
- }
- })
- self._getGridSettings()
+ /**
+ * Coverting a Node into a legacy file info to support the OC.dialogs.filepicker filter function
+ * @param node The node to convert
+ */
+ const nodeToLegacyFile = (node) => ({
+ id: node.fileid || null,
+ path: node.path,
+ mimetype: node.mime || null,
+ mtime: node.mtime?.getTime() || null,
+ permissions: node.permissions,
+ name: node.attributes?.displayName || node.basename,
+ etag: node.attributes?.etag || null,
+ hasPreview: node.attributes?.hasPreview || null,
+ mountType: node.attributes?.mountType || null,
+ quotaAvailableBytes: node.attributes?.quotaAvailableBytes || null,
+ icon: null,
+ sharePermissions: null,
+ })
- var newButton = self.$filePicker.find('.actions.creatable .button-add')
- if (type === self.FILEPICKER_TYPE_CHOOSE && !options.allowDirectoryChooser) {
- self.$filePicker.find('.actions.creatable').hide()
- }
- newButton.on('focus', function() {
- self.$filePicker.ocdialog('setEnterCallback', function(event) {
- event.stopImmediatePropagation()
- event.preventDefault()
- newButton.click()
- })
- })
- newButton.on('blur', function() {
- self.$filePicker.ocdialog('unsetEnterCallback')
- })
+ const builder = getFilePickerBuilder(title)
- OC.registerMenu(newButton, self.$filePicker.find('.menu'), function() {
- $input.tooltip('hide')
- $input.focus()
- self.$filePicker.ocdialog('setEnterCallback', function(event) {
- event.stopImmediatePropagation()
- event.preventDefault()
- self.$filePicker.submit()
+ // Setup buttons
+ if (type === this.FILEPICKER_TYPE_CUSTOM) {
+ (options.buttons || []).forEach((button) => {
+ builder.addButton({
+ callback: legacyCallback(callback, button.type),
+ label: button.text,
+ type: button.defaultButton ? 'primary' : 'secondary',
})
- var newName = $input.val()
- var lastPos = newName.lastIndexOf('.')
- if (lastPos === -1) {
- lastPos = newName.length
- }
- $input.selectRange(0, lastPos)
})
- var $form = self.$filePicker.find('.filenameform')
- var $input = $form.find('input[type=\'text\']')
- var $submit = $form.find('input[type=\'submit\']')
- $input.on('keydown', function(event) {
- if (isA11yActivation(event)) {
- event.stopImmediatePropagation()
- event.preventDefault()
- $form.submit()
- }
- })
- $submit.on('click', function(event) {
- event.stopImmediatePropagation()
- event.preventDefault()
- $form.submit()
- })
-
- /**
- * Checks whether the given file name is valid.
- *
- * @param name file name to check
- * @return true if the file name is valid.
- * @throws a string exception with an error message if
- * the file name is not valid
- *
- * NOTE: This function is duplicated in the files app:
- * https://github.com/nextcloud/server/blob/b9bc2417e7a8dc81feb0abe20359bedaf864f790/apps/files/js/files.js#L127-L148
- */
- var isFileNameValid = function (name) {
- var trimmedName = name.trim();
- if (trimmedName === '.' || trimmedName === '..')
- {
- throw t('files', '"{name}" is an invalid file name.', {name: name})
- } else if (trimmedName.length === 0) {
- throw t('files', 'File name cannot be empty.')
- } else if (trimmedName.indexOf('/') !== -1) {
- throw t('files', '"/" is not allowed inside a file name.')
- } else if (!!(trimmedName.match(OC.config.blacklist_files_regex))) {
- throw t('files', '"{name}" is not an allowed filetype', {name: name})
+ } else {
+ builder.setButtonFactory((nodes, path) => {
+ const buttons = []
+ const [node] = nodes
+ const target = node?.displayname || node?.basename || basename(path)
+
+ if (type === FilePickerType.Choose) {
+ buttons.push({
+ callback: legacyCallback(callback, FilePickerType.Choose),
+ label: node && !this.multiSelect ? t('core', 'Choose {file}', { file: target }) : t('core', 'Choose'),
+ type: 'primary',
+ })
}
-
- return true
- }
-
- var checkInput = function() {
- var filename = $input.val()
- try {
- if (!isFileNameValid(filename)) {
- // isFileNameValid(filename) throws an exception itself
- } else if (self.filelist.find(function(file) {
- return file.name === this
- }, filename)) {
- throw t('files', '{newName} already exists', { newName: filename }, undefined, {
- escape: false
- })
- } else {
- return true
- }
- } catch (error) {
- $input.attr('title', error)
- $input.tooltip({
- placement: 'right',
- trigger: 'manual',
- 'container': '.newFolderMenu'
+ if (type === FilePickerType.CopyMove || type === FilePickerType.Copy) {
+ buttons.push({
+ callback: legacyCallback(callback, FilePickerType.Copy),
+ label: target ? t('core', 'Copy to {target}', { target }) : t('core', 'Copy'),
+ type: 'primary',
+ icon: IconCopy,
})
- $input.tooltip('_fixTitle')
- $input.tooltip('show')
- $input.addClass('error')
}
- return false
- }
-
- $form.on('submit', function(event) {
- event.stopPropagation()
- event.preventDefault()
-
- if (checkInput()) {
- var newname = $input.val()
- self.filepicker.filesClient.createDirectory(self.$filePicker.data('path') + "/" + newname).always(function (status) {
- self._fillFilePicker(self.$filePicker.data('path') + "/" + newname)
+ if (type === FilePickerType.Move || type === FilePickerType.CopyMove) {
+ buttons.push({
+ callback: legacyCallback(callback, FilePickerType.Move),
+ label: target ? t('core', 'Move to {target}', { target }) : t('core', 'Move'),
+ type: type === FilePickerType.Move ? 'primary' : 'secondary',
+ icon: IconMove,
})
- OC.hideMenus()
- self.$filePicker.ocdialog('unsetEnterCallback')
- self.$filePicker.click()
- $input.val(newText)
}
+ return buttons
})
- $input.on('input', function(event) {
- $input.tooltip('hide')
- })
-
- self.$filePicker.ready(function() {
- self.$fileListHeader = self.$filePicker.find('.filelist thead tr')
- self.$filelist = self.$filePicker.find('.filelist tbody')
- self.$filelistContainer = self.$filePicker.find('.filelist-container')
- self.$dirTree = self.$filePicker.find('.dirtree')
- self.$dirTree.on('click keydown', 'div:not(:last-child)', self, function(event) {
- if (isA11yActivation(event)) {
- self._handleTreeListSelect(event, type)
- }
- })
- self.$filelist.on('click keydown', 'tr', function(event) {
- if (isA11yActivation(event)) {
- self._handlePickerClick(event, $(this), type)
- }
- })
- self.$fileListHeader.on('click keydown', 'a', function(event) {
- if (isA11yActivation(event)) {
- var dir = self.$filePicker.data('path')
- self.filepicker.sortField = $(event.currentTarget).data('sort')
- self.filepicker.sortOrder = self.filepicker.sortOrder === 'asc' ? 'desc' : 'asc'
- self._fillFilePicker(dir)
- }
- })
- self._fillFilePicker(path)
- })
-
- // build buttons
- var functionToCall = function(returnType) {
- if (callback !== undefined) {
- var datapath
- if (multiselect === true) {
- datapath = []
- self.$filelist.find('tr.filepicker_element_selected').each(function(index, element) {
- datapath.push(self.$filePicker.data('path') + '/' + $(element).data('entryname'))
- })
- } else {
- datapath = self.$filePicker.data('path')
- var selectedName = self.$filelist.find('tr.filepicker_element_selected').data('entryname')
- if (selectedName) {
- datapath += '/' + selectedName
- }
- }
- callback(datapath, returnType)
- self.$filePicker.ocdialog('close')
- }
- }
-
- var chooseCallback = function() {
- functionToCall(Dialogs.FILEPICKER_TYPE_CHOOSE)
- }
-
- var copyCallback = function() {
- functionToCall(Dialogs.FILEPICKER_TYPE_COPY)
- }
+ }
- var moveCallback = function() {
- functionToCall(Dialogs.FILEPICKER_TYPE_MOVE)
- }
+ if (mimetype) {
+ builder.setMimeTypeFilter(typeof mimetype === 'string' ? [mimetype] : (mimetype || []))
+ }
+ if (typeof options?.filter === 'function') {
+ builder.setFilter((node) => options.filter(nodeToLegacyFile(node)))
+ }
+ builder.allowDirectories(options?.allowDirectoryChooser === true || mimetype?.includes('httpd/unix-directory') || false)
+ .setMultiSelect(multiselect)
+ .startAt(path)
+ .build()
+ .pick()
+ },
- var buttonlist = []
- if (type === Dialogs.FILEPICKER_TYPE_CHOOSE) {
- buttonlist.push({
- text: t('core', 'Choose'),
- click: chooseCallback,
- defaultButton: true
- })
- } else if (type === Dialogs.FILEPICKER_TYPE_CUSTOM) {
- options.buttons.forEach(function(button) {
- buttonlist.push({
- text: button.text,
- click: function() {
- functionToCall(button.type)
- },
- defaultButton: button.defaultButton
- })
- })
- } else {
- if (type === Dialogs.FILEPICKER_TYPE_COPY || type === Dialogs.FILEPICKER_TYPE_COPY_MOVE) {
- buttonlist.push({
- text: t('core', 'Copy'),
- click: copyCallback,
- defaultButton: false
- })
- }
- if (type === Dialogs.FILEPICKER_TYPE_MOVE || type === Dialogs.FILEPICKER_TYPE_COPY_MOVE) {
- buttonlist.push({
- text: t('core', 'Move'),
- click: moveCallback,
- defaultButton: true
- })
- }
- }
+ /**
+ * Displays raw dialog
+ * You better use a wrapper instead ...
+ *
+ * @deprecated 30.0.0 Use `@nextcloud/dialogs` instead or build your own with `@nextcloud/vue` NcDialog
+ */
+ message: function(content, title, dialogType, buttons, callback = () => {}, modal, allowHtml) {
+ const builder = (new DialogBuilder())
+ .setName(title)
+ .setText(allowHtml ? '' : content)
+ .setButtons(Dialogs._getLegacyButtons(buttons, callback))
+
+ switch (dialogType) {
+ case 'alert':
+ builder.setSeverity('warning')
+ break
+ case 'notice':
+ builder.setSeverity('info')
+ break
+ default:
+ break
+ }
- self.$filePicker.ocdialog({
- closeOnEscape: true,
- // max-width of 600
- width: 600,
- height: 500,
- modal: modal,
- buttons: buttonlist,
- style: {
- buttons: 'aside'
- },
- close: function() {
- try {
- $(this).ocdialog('destroy').remove()
- } catch (e) {
- }
- self.$filePicker = null
- }
- })
+ const dialog = builder.build()
+
+ if (allowHtml) {
+ dialog.setHTML(content)
+ }
- // We can access primary class only from oc-dialog.
- // Hence this is one of the approach to get the choose button.
- var getOcDialog = self.$filePicker.closest('.oc-dialog')
- var buttonEnableDisable = getOcDialog.find('.primary')
- if (self.$filePicker.data('mimetype').indexOf('httpd/unix-directory') !== -1 || self.$filePicker.data('allowDirectoryChooser')) {
- buttonEnableDisable.prop('disabled', false)
- } else {
- buttonEnableDisable.prop('disabled', true)
+ return dialog.show().then(() => {
+ if(!callback._clicked) {
+ callback(false)
}
})
- .fail(function(status, error) {
- // If the method is called while navigating away
- // from the page, it is probably not needed ;)
- self.filepicker.loading = false
- if (status !== 0) {
- alert(t('core', 'Error loading file picker template: {error}', { error: error }))
- }
- })
},
+
/**
- * Displays raw dialog
- * You better use a wrapper instead ...
+ * Helper for legacy API
+ * @deprecated
*/
- message: function(content, title, dialogType, buttons, callback, modal, allowHtml) {
- return $.when(this._getMessageTemplate()).then(function($tmpl) {
- var dialogName = 'oc-dialog-' + Dialogs.dialogsCounter + '-content'
- var dialogId = '#' + dialogName
- var $dlg = $tmpl.octemplate({
- dialog_name: dialogName,
- title: title,
- message: content,
- type: dialogType
- }, allowHtml ? { escapeFunction: '' } : {})
- if (modal === undefined) {
- modal = false
- }
- $('body').append($dlg)
- var buttonlist = []
- switch (buttons) {
+ _getLegacyButtons(buttons, callback) {
+ const buttonList = []
+
+ switch (typeof buttons === 'object' ? buttons.type : buttons) {
case Dialogs.YES_NO_BUTTONS:
- buttonlist = [{
- text: t('core', 'No'),
- click: function() {
- if (callback !== undefined) {
- callback(false)
- }
- $(dialogId).ocdialog('close')
- }
- },
- {
- text: t('core', 'Yes'),
- click: function() {
- if (callback !== undefined) {
- callback(true)
- }
- $(dialogId).ocdialog('close')
+ buttonList.push({
+ label: buttons?.cancel ?? t('core', 'No'),
+ callback: () => {
+ callback._clicked = true
+ callback(false)
},
- defaultButton: true
- }]
+ })
+ buttonList.push({
+ label: buttons?.confirm ?? t('core', 'Yes'),
+ type: 'primary',
+ callback: () => {
+ callback._clicked = true
+ callback(true)
+ },
+ })
break
- case Dialogs.OK_BUTTON:
- var functionToCall = function() {
- $(dialogId).ocdialog('close')
- if (callback !== undefined) {
- callback()
- }
- }
- buttonlist[0] = {
- text: t('core', 'OK'),
- click: functionToCall,
- defaultButton: true
- }
+ case Dialogs.OK_BUTTONS:
+ buttonList.push({
+ label: buttons?.confirm ?? t('core', 'OK'),
+ type: 'primary',
+ callback: () => {
+ callback._clicked = true
+ callback(true)
+ },
+ })
break
default:
- if (typeof(buttons) === 'object') {
- switch (buttons.type) {
- case Dialogs.YES_NO_BUTTONS:
- buttonlist = [{
- text: buttons.cancel || t('core', 'No'),
- click: function() {
- if (callback !== undefined) {
- callback(false)
- }
- $(dialogId).ocdialog('close')
- }
- },
- {
- text: buttons.confirm || t('core', 'Yes'),
- click: function() {
- if (callback !== undefined) {
- callback(true)
- }
- $(dialogId).ocdialog('close')
- },
- defaultButton: true,
- classes: buttons.confirmClasses
- }]
- break
- }
- }
+ console.error('Invalid call to OC.dialogs')
break
- }
-
- $(dialogId).ocdialog({
- closeOnEscape: true,
- closeCallback: () => { callback && callback(false) },
- modal: modal,
- buttons: buttonlist
- })
- Dialogs.dialogsCounter++
- })
- .fail(function(status, error) {
- // If the method is called while navigating away from
- // the page, we still want to deliver the message.
- if (status === 0) {
- alert(title + ': ' + content)
- } else {
- alert(t('core', 'Error loading message template: {error}', { error: error }))
- }
- })
+ }
+ return buttonList
},
+
_fileexistsshown: false,
/**
* Displays file exists dialog
@@ -680,6 +407,8 @@ const Dialogs = {
* @param {object} replacement file with name, size and mtime
* @param {object} controller with onCancel, onSkip, onReplace and onRename methods
* @returns {Promise} jquery promise that resolves after the dialog template was loaded
+ *
+ * @deprecated 29.0.0 Use openConflictPicker from the @nextcloud/upload package instead
*/
fileexists: function(data, original, replacement, controller) {
var self = this
@@ -1038,73 +767,12 @@ const Dialogs = {
// }
return dialogDeferred.promise()
},
- // get the gridview setting and set the input accordingly
- _getGridSettings: function() {
- const self = this
- $.get(OC.generateUrl('/apps/files/api/v1/showgridview'), function(response) {
- self.$showGridView
- .removeClass('icon-toggle-filelist icon-toggle-pictures')
- .addClass(response.gridview ? 'icon-toggle-filelist' : 'icon-toggle-pictures')
- self.$showGridView.attr(
- 'aria-label',
- response.gridview ? t('files', 'Show list view') : t('files', 'Show grid view'),
- )
- $('.list-container').toggleClass('view-grid', response.gridview)
- })
- },
- _onGridviewChange: function() {
- const isGridView = this.$showGridView.hasClass('icon-toggle-filelist')
- // only save state if user is logged in
- if (OC.currentUser) {
- $.post(OC.generateUrl('/apps/files/api/v1/showgridview'), { show: !isGridView })
- }
- this.$showGridView
- .removeClass('icon-toggle-filelist icon-toggle-pictures')
- .addClass(isGridView ? 'icon-toggle-pictures' : 'icon-toggle-filelist')
- this.$showGridView.attr(
- 'aria-label',
- isGridView ? t('files', 'Show grid view') : t('files', 'Show list view'),
- )
- this.$filePicker.find('.list-container').toggleClass('view-grid', !isGridView)
- },
- _getFilePickerTemplate: function() {
- var defer = $.Deferred()
- if (!this.$filePickerTemplate) {
- var self = this
- $.get(OC.filePath('core', 'templates', 'filepicker.html'), function(tmpl) {
- self.$filePickerTemplate = $(tmpl)
- self.$listTmpl = self.$filePickerTemplate.find('.filelist tbody tr:first-child').detach()
- defer.resolve(self.$filePickerTemplate)
- })
- .fail(function(jqXHR, textStatus, errorThrown) {
- defer.reject(jqXHR.status, errorThrown)
- })
- } else {
- defer.resolve(this.$filePickerTemplate)
- }
- return defer.promise()
- },
- _getMessageTemplate: function() {
- var defer = $.Deferred()
- if (!this.$messageTemplate) {
- var self = this
- $.get(OC.filePath('core', 'templates', 'message.html'), function(tmpl) {
- self.$messageTemplate = $(tmpl)
- defer.resolve(self.$messageTemplate)
- })
- .fail(function(jqXHR, textStatus, errorThrown) {
- defer.reject(jqXHR.status, errorThrown)
- })
- } else {
- defer.resolve(this.$messageTemplate)
- }
- return defer.promise()
- },
+
_getFileExistsTemplate: function() {
var defer = $.Deferred()
if (!this.$fileexistsTemplate) {
var self = this
- $.get(OC.filePath('files', 'templates', 'fileexists.html'), function(tmpl) {
+ $.get(OC.filePath('core', 'templates/legacy', 'fileexists.html'), function(tmpl) {
self.$fileexistsTemplate = $(tmpl)
defer.resolve(self.$fileexistsTemplate)
})
@@ -1116,270 +784,6 @@ const Dialogs = {
}
return defer.promise()
},
-
- /**
- * fills the filepicker with files
- */
- _fillFilePicker: async function(dir) {
- var self = this
- this.$filelist.empty()
- this.$filePicker.find('.emptycontent').hide()
- this.$filelistContainer.addClass('icon-loading')
- this.$filePicker.data('path', dir)
- var filter = this.$filePicker.data('mimetype')
- var advancedFilter = this.$filePicker.data('filter')
- if (typeof (filter) === 'string') {
- filter = [filter]
- }
- self.$fileListHeader.find('.sort-indicator').addClass('hidden').removeClass('icon-triangle-n').removeClass('icon-triangle-s')
- self.$fileListHeader.find('[data-sort=' + self.filepicker.sortField + '] .sort-indicator').removeClass('hidden')
- if (self.filepicker.sortOrder === 'asc') {
- self.$fileListHeader.find('[data-sort=' + self.filepicker.sortField + '] .sort-indicator').addClass('icon-triangle-n')
- } else {
- self.$fileListHeader.find('[data-sort=' + self.filepicker.sortField + '] .sort-indicator').addClass('icon-triangle-s')
- }
-
- // Wrap within a method because a promise cannot return multiple values
- // But the client impleemntation still does it...
- var getFolderContents = async function(dir) {
- return self.filepicker.filesClient.getFolderContents(dir)
- .then((status, files) => {
- return files
- })
- }
-
- try {
- var files = await getFolderContents(dir)
- } catch (error) {
- // fallback to root if requested dir is non-existent
- console.error('Requested path does not exists, falling back to root')
- var files = await getFolderContents('/')
- this.$filePicker.data('path', '/')
- }
-
- self.filelist = files
- if (filter && filter.length > 0 && filter.indexOf('*') === -1) {
- files = files.filter(function(file) {
- return file.type === 'dir' || filter.indexOf(file.mimetype) !== -1
- })
- }
-
- if (advancedFilter) {
- files = files.filter(advancedFilter)
- }
-
- // Check if the showHidden input field exist and if it exist follow it
- // Otherwise just show the hidden files
- const showHiddenInput = document.getElementById('showHiddenFiles')
- const showHidden = showHiddenInput === null || showHiddenInput.value === "1"
- if (!showHidden) {
- files = files.filter(function(file) {
- return !file.name.startsWith('.')
- })
- }
-
- var Comparators = {
- name: function(fileInfo1, fileInfo2) {
- if (fileInfo1.type === 'dir' && fileInfo2.type !== 'dir') {
- return -1
- }
- if (fileInfo1.type !== 'dir' && fileInfo2.type === 'dir') {
- return 1
- }
- return OC.Util.naturalSortCompare(fileInfo1.name, fileInfo2.name)
- },
- size: function(fileInfo1, fileInfo2) {
- return fileInfo1.size - fileInfo2.size
- },
- mtime: function(fileInfo1, fileInfo2) {
- return fileInfo1.mtime - fileInfo2.mtime
- }
- }
- var comparator = Comparators[self.filepicker.sortField] || Comparators.name
- files = files.sort(function(file1, file2) {
- var isFavorite = function(fileInfo) {
- return fileInfo.tags && fileInfo.tags.indexOf(OC.TAG_FAVORITE) >= 0
- }
-
- if (isFavorite(file1) && !isFavorite(file2)) {
- return -1
- } else if (!isFavorite(file1) && isFavorite(file2)) {
- return 1
- }
-
- return self.filepicker.sortOrder === 'asc' ? comparator(file1, file2) : -comparator(file1, file2)
- })
-
- self._fillSlug()
-
- if (files.length === 0) {
- self.$filePicker.find('.emptycontent').show()
- self.$fileListHeader.hide()
- } else {
- self.$filePicker.find('.emptycontent').hide()
- self.$fileListHeader.show()
- }
-
- self.$filelist.empty();
-
- $.each(files, function(idx, entry) {
- if (entry.isEncrypted && entry.mimetype === 'httpd/unix-directory') {
- entry.icon = OC.MimeType.getIconUrl('dir-encrypted')
- } else {
- entry.icon = OC.MimeType.getIconUrl(entry.mimetype)
- }
-
- var simpleSize, sizeColor
- if (typeof (entry.size) !== 'undefined' && entry.size >= 0) {
- simpleSize = OC.Util.humanFileSize(parseInt(entry.size, 10), true)
- sizeColor = Math.round(160 - Math.pow((entry.size / (1024 * 1024)), 2))
- } else {
- simpleSize = t('files', 'Pending')
- sizeColor = 80
- }
-
- // split the filename in half if the size is bigger than 20 char
- // for ellipsis
- if (entry.name.length >= 10) {
- // leave maximum 10 letters
- var split = Math.min(Math.floor(entry.name.length / 2), 10)
- var filename1 = entry.name.substr(0, entry.name.length - split)
- var filename2 = entry.name.substr(entry.name.length - split)
- } else {
- var filename1 = entry.name
- var filename2 = ''
- }
-
- var $row = self.$listTmpl.octemplate({
- type: entry.type,
- dir: dir,
- filename: entry.name,
- filename1: filename1,
- filename2: filename2,
- date: OC.Util.relativeModifiedDate(entry.mtime),
- size: simpleSize,
- sizeColor: sizeColor,
- icon: entry.icon
- })
- if (entry.type === 'file') {
- var urlSpec = {
- file: dir + '/' + entry.name,
- x: 100,
- y: 100
- }
- var img = new Image()
- var previewUrl = OC.generateUrl('/core/preview.png?') + $.param(urlSpec)
- img.onload = function() {
- if (img.width > 5) {
- $row.find('td.filename').attr('style', 'background-image:url(' + previewUrl + ')')
- }
- }
- img.src = previewUrl
- }
- self.$filelist.append($row)
- })
-
- self.$filelistContainer.removeClass('icon-loading')
- },
- /**
- * fills the tree list with directories
- */
- _fillSlug: function() {
- var addButton = this.$dirTree.find('.actions.creatable').detach()
- this.$dirTree.empty()
- var self = this
-
- self.$dirTree.append(addButton)
-
- var dir
- var path = this.$filePicker.data('path')
- var $template = $('<div data-dir="{dir}" tabindex="0"><a>{name}</a></div>').addClass('crumb')
- if (path) {
- var paths = path.split('/')
- $.each(paths, function(index, dir) {
- dir = paths.pop()
- if (dir === '') {
- return false
- }
- self.$dirTree.prepend($template.octemplate({
- dir: paths.join('/') + '/' + dir,
- name: dir
- }))
- })
- }
-
- $template.octemplate({
- dir: '',
- name: '' // Ugly but works ;)
- }, { escapeFunction: null }).prependTo(this.$dirTree)
-
- },
- /**
- * handle selection made in the tree list
- */
- _handleTreeListSelect: function(event, type) {
- var self = event.data
- var dir = $(event.target).closest('.crumb').data('dir')
- self._fillFilePicker(dir)
- var getOcDialog = (event.target).closest('.oc-dialog')
- var buttonEnableDisable = $('.primary', getOcDialog)
- this._changeButtonsText(type, dir.split(/[/]+/).pop())
- if (this.$filePicker.data('mimetype').indexOf('httpd/unix-directory') !== -1 || this.$filePicker.data('allowDirectoryChooser')) {
- buttonEnableDisable.prop('disabled', false)
- } else {
- buttonEnableDisable.prop('disabled', true)
- }
- },
- /**
- * handle clicks made in the filepicker
- */
- _handlePickerClick: function(event, $element, type) {
- var getOcDialog = this.$filePicker.closest('.oc-dialog')
- var buttonEnableDisable = getOcDialog.find('.primary')
- if ($element.data('type') === 'file') {
- if (this.$filePicker.data('multiselect') !== true || !event.ctrlKey) {
- this.$filelist.find('.filepicker_element_selected').removeClass('filepicker_element_selected')
- }
- $element.toggleClass('filepicker_element_selected')
- buttonEnableDisable.prop('disabled', false)
- } else if ($element.data('type') === 'dir') {
- this._fillFilePicker(this.$filePicker.data('path') + '/' + $element.data('entryname'))
- this._changeButtonsText(type, $element.data('entryname'))
- if (this.$filePicker.data('mimetype').indexOf('httpd/unix-directory') !== -1 || this.$filePicker.data('allowDirectoryChooser')) {
- buttonEnableDisable.prop('disabled', false)
- } else {
- buttonEnableDisable.prop('disabled', true)
- }
- }
- },
-
- /**
- * Handle
- * @param type of action
- * @param dir on which to change buttons text
- * @private
- */
- _changeButtonsText: function(type, dir) {
- var copyText = dir === '' ? t('core', 'Copy') : t('core', 'Copy to {folder}', { folder: dir })
- var moveText = dir === '' ? t('core', 'Move') : t('core', 'Move to {folder}', { folder: dir })
- var buttons = $('.oc-dialog-buttonrow button')
- switch (type) {
- case this.FILEPICKER_TYPE_CHOOSE:
- break
- case this.FILEPICKER_TYPE_CUSTOM:
- break
- case this.FILEPICKER_TYPE_COPY:
- buttons.text(copyText)
- break
- case this.FILEPICKER_TYPE_MOVE:
- buttons.text(moveText)
- break
- case this.FILEPICKER_TYPE_COPY_MOVE:
- buttons.eq(0).text(copyText)
- buttons.eq(1).text(moveText)
- break
- }
- }
}
export default Dialogs
diff --git a/core/src/OC/eventsource.js b/core/src/OC/eventsource.js
index 537d68cb434..090c351c057 100644
--- a/core/src/OC/eventsource.js
+++ b/core/src/OC/eventsource.js
@@ -1,35 +1,13 @@
/**
- * @copyright 2012 Robin Appelman icewind1991@gmail.com
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.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/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2015 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
/* eslint-disable */
import $ from 'jquery'
-import { getToken } from './requesttoken'
+import { getRequestToken } from './requesttoken.ts'
/**
* Create a new event source
@@ -50,7 +28,7 @@ const OCEventSource = function(src, data) {
dataStr += name + '=' + encodeURIComponent(data[name]) + '&'
}
}
- dataStr += 'requesttoken=' + encodeURIComponent(getToken())
+ dataStr += 'requesttoken=' + encodeURIComponent(getRequestToken())
if (!this.useFallBack && typeof EventSource !== 'undefined') {
joinChar = '&'
if (src.indexOf('?') === -1) {
diff --git a/core/src/OC/get_set.js b/core/src/OC/get_set.js
index 32f202ad35b..0c909ad04fd 100644
--- a/core/src/OC/get_set.js
+++ b/core/src/OC/get_set.js
@@ -1,24 +1,6 @@
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @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/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
export const get = context => name => {
diff --git a/core/src/OC/host.js b/core/src/OC/host.js
index 31f13d01a7f..75c7d63804b 100644
--- a/core/src/OC/host.js
+++ b/core/src/OC/host.js
@@ -1,24 +1,6 @@
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @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/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
export const getProtocol = () => window.location.protocol.split(':')[0]
diff --git a/core/src/OC/index.js b/core/src/OC/index.js
index 5267e2491f4..5afc941b396 100644
--- a/core/src/OC/index.js
+++ b/core/src/OC/index.js
@@ -1,40 +1,19 @@
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @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/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { subscribe } from '@nextcloud/event-bus'
-import { addScript, addStyle } from './legacy-loader'
import {
ajaxConnectionLostHandler,
processAjaxError,
registerXHRForErrorProcessing,
-} from './xhr-error'
-import Apps from './apps'
-import { AppConfig, appConfig } from './appconfig'
-import { appSettings } from './appsettings'
-import appswebroots from './appswebroots'
-import Backbone from './backbone'
+} from './xhr-error.js'
+import Apps from './apps.js'
+import { AppConfig, appConfig } from './appconfig.js'
+import appswebroots from './appswebroots.js'
+import Backbone from './backbone.js'
import {
basename,
dirname,
@@ -45,8 +24,8 @@ import {
import {
build as buildQueryString,
parse as parseQueryString,
-} from './query-string'
-import Config from './config'
+} from './query-string.js'
+import Config from './config.js'
import {
coreApps,
menuSpeed,
@@ -58,35 +37,31 @@ import {
PERMISSION_SHARE,
PERMISSION_UPDATE,
TAG_FAVORITE,
-} from './constants'
-import ContactsMenu from './contactsmenu'
-import { currentUser, getCurrentUser } from './currentuser'
-import Dialogs from './dialogs'
-import EventSource from './eventsource'
-import { get, set } from './get_set'
-import { getCapabilities } from './capabilities'
+} from './constants.js'
+import { currentUser, getCurrentUser } from './currentuser.js'
+import Dialogs from './dialogs.js'
+import EventSource from './eventsource.js'
+import { get, set } from './get_set.js'
+import { getCapabilities } from './capabilities.js'
import {
getHost,
getHostName,
getPort,
getProtocol,
-} from './host'
-import {
- getToken as getRequestToken,
-} from './requesttoken'
+} from './host.js'
+import { getRequestToken } from './requesttoken.ts'
import {
hideMenus,
registerMenu,
showMenu,
unregisterMenu,
-} from './menu'
-import { isUserAdmin } from './admin'
-import L10N, {
- getLanguage,
- getLocale,
-} from './l10n'
+} from './menu.js'
+import { isUserAdmin } from './admin.js'
+import L10N from './l10n.js'
import {
getCanonicalLocale,
+ getLanguage,
+ getLocale,
} from '@nextcloud/l10n'
import {
@@ -101,16 +76,16 @@ import {
import {
linkToRemoteBase,
-} from './routing'
-import msg from './msg'
-import Notification from './notification'
-import PasswordConfirmation from './password-confirmation'
-import Plugins from './plugins'
-import { theme } from './theme'
-import Util from './util'
-import { debug } from './debug'
-import { redirect, reload } from './navigation'
-import webroot from './webroot'
+} from './routing.js'
+import msg from './msg.js'
+import Notification from './notification.js'
+import PasswordConfirmation from './password-confirmation.js'
+import Plugins from './plugins.js'
+import { theme } from './theme.js'
+import Util from './util.js'
+import { debug } from './debug.js'
+import { redirect, reload } from './navigation.js'
+import webroot from './webroot.js'
/** @namespace OC */
export default {
@@ -139,16 +114,11 @@ export default {
* @deprecated 17.0.0
*/
fileIsBlacklisted: file => !!(file.match(Config.blacklist_files_regex)),
-
- addScript,
- addStyle,
Apps,
AppConfig,
appConfig,
- appSettings,
appswebroots,
Backbone,
- ContactsMenu,
config: Config,
/**
* Currently logged in user or null if none
@@ -231,17 +201,14 @@ export default {
* @deprecated 20.0.0 use `getCanonicalLocale` from https://www.npmjs.com/package/@nextcloud/l10n
*/
getCanonicalLocale,
+ /**
+ * @deprecated 26.0.0 use `getLocale` from https://www.npmjs.com/package/@nextcloud/l10n
+ */
getLocale,
- getLanguage,
/**
- * Loads translations for the given app asynchronously.
- *
- * @param {string} app app name
- * @param {Function} callback callback to call after loading
- * @return {Promise}
- * @deprecated 17.0.0 use OC.L10N.load instead
+ * @deprecated 26.0.0 use `getLanguage` from https://www.npmjs.com/package/@nextcloud/l10n
*/
- addTranslations: L10N.load,
+ getLanguage,
/**
* Query string helpers
@@ -251,6 +218,9 @@ export default {
msg,
Notification,
+ /**
+ * @deprecated 28.0.0 use methods from '@nextcloud/password-confirmation'
+ */
PasswordConfirmation,
Plugins,
theme,
diff --git a/core/src/OC/l10n-registry.js b/core/src/OC/l10n-registry.js
deleted file mode 100644
index 9e542b1aa8c..00000000000
--- a/core/src/OC/l10n-registry.js
+++ /dev/null
@@ -1,90 +0,0 @@
-/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @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/>.
- *
- */
-
-// This var is global because it's shared across webpack bundles
-window._oc_l10n_registry_translations = window._oc_l10n_registry_translations || {}
-window._oc_l10n_registry_plural_functions = window._oc_l10n_registry_plural_functions || {}
-
-/**
- * @param {string} appId the app id
- * @param {object} translations the translations list
- * @param {Function} pluralFunction the translations list
- */
-const register = (appId, translations, pluralFunction) => {
- window._oc_l10n_registry_translations[appId] = translations
- window._oc_l10n_registry_plural_functions[appId] = pluralFunction
-}
-
-/**
- * @param {string} appId the app id
- * @param {object} translations the translations list
- * @param {Function} pluralFunction the translations list
- */
-const extend = (appId, translations, pluralFunction) => {
- window._oc_l10n_registry_translations[appId] = Object.assign(
- window._oc_l10n_registry_translations[appId],
- translations
- )
- window._oc_l10n_registry_plural_functions[appId] = pluralFunction
-}
-
-/**
- * @param {string} appId the app id
- * @param {object} translations the translations list
- * @param {Function} pluralFunction the translations list
- */
-export const registerAppTranslations = (appId, translations, pluralFunction) => {
- if (!hasAppTranslations(appId)) {
- register(appId, translations, pluralFunction)
- } else {
- extend(appId, translations, pluralFunction)
- }
-}
-
-/**
- * @param {string} appId the app id
- */
-export const unregisterAppTranslations = appId => {
- delete window._oc_l10n_registry_translations[appId]
- delete window._oc_l10n_registry_plural_functions[appId]
-}
-
-/**
- * @param {string} appId the app id
- * @return {boolean}
- */
-export const hasAppTranslations = appId => {
- return window._oc_l10n_registry_translations[appId] !== undefined
- && window._oc_l10n_registry_plural_functions[appId] !== undefined
-}
-
-/**
- * @param {string} appId the app id
- * @return {object}
- */
-export const getAppTranslations = appId => {
- return {
- translations: window._oc_l10n_registry_translations[appId] || {},
- pluralFunction: window._oc_l10n_registry_plural_functions[appId],
- }
-}
diff --git a/core/src/OC/l10n.js b/core/src/OC/l10n.js
index 2a4569ee272..02f912d6a99 100644
--- a/core/src/OC/l10n.js
+++ b/core/src/OC/l10n.js
@@ -1,106 +1,60 @@
/**
- * Copyright (c) 2014 Vincent Petry <pvince81@owncloud.com>
- * Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
- * Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Kesselberg <mail@danielkesselberg.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Vincent Petry <vincent@nextcloud.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/>.
- *
+ * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2014 ownCloud, Inc.
+ * SPDX-FileCopyrightText: 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
-import _ from 'underscore'
-import $ from 'jquery'
-import DOMPurify from 'dompurify'
import Handlebars from 'handlebars'
-import identity from 'lodash/fp/identity'
-import escapeHTML from 'escape-html'
-import { generateFilePath } from '@nextcloud/router'
-
-import OC from './index'
import {
- getAppTranslations,
- hasAppTranslations,
- registerAppTranslations,
- unregisterAppTranslations,
-} from './l10n-registry'
+ loadTranslations,
+ translate,
+ translatePlural,
+ register,
+ unregister,
+} from '@nextcloud/l10n'
/**
* L10N namespace with localization functions.
*
* @namespace OC.L10n
+ * @deprecated 26.0.0 use https://www.npmjs.com/package/@nextcloud/l10n
*/
const L10n = {
/**
* Load an app's translation bundle if not loaded already.
*
+ * @deprecated 26.0.0 use `loadTranslations` from https://www.npmjs.com/package/@nextcloud/l10n
+ *
* @param {string} appName name of the app
* @param {Function} callback callback to be called when
* the translations are loaded
* @return {Promise} promise
*/
- load(appName, callback) {
- // already available ?
- if (hasAppTranslations(appName) || OC.getLocale() === 'en') {
- const deferred = $.Deferred()
- const promise = deferred.promise()
- promise.then(callback)
- deferred.resolve()
- return promise
- }
-
- const self = this
- const url = generateFilePath(appName, 'l10n', OC.getLocale() + '.json')
-
- // load JSON translation bundle per AJAX
- return $.get(url)
- .then(
- function(result) {
- if (result.translations) {
- self.register(appName, result.translations, result.pluralForm)
- }
- })
- .then(callback)
- },
+ load: loadTranslations,
/**
* Register an app's translation bundle.
*
+ * @deprecated 26.0.0 use `register` from https://www.npmjs.com/package/@nextcloud/l10
+ *
* @param {string} appName name of the app
- * @param {Object<string, string>} bundle bundle
+ * @param {Record<string, string>} bundle bundle
*/
- register(appName, bundle) {
- registerAppTranslations(appName, bundle, this._getPlural)
- },
+ register,
/**
* @private
+ * @deprecated 26.0.0 use `unregister` from https://www.npmjs.com/package/@nextcloud/l10n
*/
- _unregister: unregisterAppTranslations,
+ _unregister: unregister,
/**
* Translate a string
*
+ * @deprecated 26.0.0 use `translate` from https://www.npmjs.com/package/@nextcloud/l10n
+ *
* @param {string} app the id of the app for which to translate the string
* @param {string} text the string to translate
* @param {object} [vars] map of placeholder key to value
@@ -110,49 +64,13 @@ const L10n = {
* @param {boolean} [options.sanitize=true] enable/disable sanitization (by default enabled)
* @return {string}
*/
- translate(app, text, vars, count, options) {
- const defaultOptions = {
- escape: true,
- sanitize: true,
- }
- const allOptions = options || {}
- _.defaults(allOptions, defaultOptions)
-
- const optSanitize = allOptions.sanitize ? DOMPurify.sanitize : identity
- const optEscape = allOptions.escape ? escapeHTML : identity
-
- // TODO: cache this function to avoid inline recreation
- // of the same function over and over again in case
- // translate() is used in a loop
- const _build = function(text, vars, count) {
- return text.replace(/%n/g, count).replace(/{([^{}]*)}/g,
- function(a, b) {
- const r = vars[b]
- if (typeof r === 'string' || typeof r === 'number') {
- return optSanitize(optEscape(r))
- } else {
- return optSanitize(a)
- }
- }
- )
- }
- let translation = text
- const bundle = getAppTranslations(app)
- const value = bundle.translations[text]
- if (typeof (value) !== 'undefined') {
- translation = value
- }
-
- if (typeof vars === 'object' || count !== undefined) {
- return optSanitize(_build(translation, vars, count))
- } else {
- return optSanitize(translation)
- }
- },
+ translate,
/**
* Translate a plural string
*
+ * @deprecated 26.0.0 use `translatePlural` from https://www.npmjs.com/package/@nextcloud/l10n
+ *
* @param {string} app the id of the app for which to translate the string
* @param {string} textSingular the string to translate for exactly one object
* @param {string} textPlural the string to translate for n objects
@@ -162,203 +80,11 @@ const L10n = {
* @param {boolean} [options.escape=true] enable/disable auto escape of placeholders (by default enabled)
* @return {string} Translated string
*/
- translatePlural(app, textSingular, textPlural, count, vars, options) {
- const identifier = '_' + textSingular + '_::_' + textPlural + '_'
- const bundle = getAppTranslations(app)
- const value = bundle.translations[identifier]
- if (typeof (value) !== 'undefined') {
- const translation = value
- if ($.isArray(translation)) {
- const plural = bundle.pluralFunction(count)
- return this.translate(app, translation[plural], vars, count, options)
- }
- }
-
- if (count === 1) {
- return this.translate(app, textSingular, vars, count, options)
- } else {
- return this.translate(app, textPlural, vars, count, options)
- }
- },
-
- /**
- * The plural function taken from symfony
- *
- * @param {number} number the number of elements
- * @return {number}
- * @private
- */
- _getPlural(number) {
- let language = OC.getLanguage()
- if (language === 'pt-BR') {
- // temporary set a locale for brazilian
- language = 'xbr'
- }
-
- if (typeof language === 'undefined' || language === '') {
- return (number === 1) ? 0 : 1
- }
-
- if (language.length > 3) {
- language = language.substring(0, language.lastIndexOf('-'))
- }
-
- /*
- * The plural rules are derived from code of the Zend Framework (2010-09-25),
- * which is subject to the new BSD license (http://framework.zend.com/license/new-bsd).
- * Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
- */
- switch (language) {
- case 'az':
- case 'bo':
- case 'dz':
- case 'id':
- case 'ja':
- case 'jv':
- case 'ka':
- case 'km':
- case 'kn':
- case 'ko':
- case 'ms':
- case 'th':
- case 'tr':
- case 'vi':
- case 'zh':
- return 0
-
- case 'af':
- case 'bn':
- case 'bg':
- case 'ca':
- case 'da':
- case 'de':
- case 'el':
- case 'en':
- case 'eo':
- case 'es':
- case 'et':
- case 'eu':
- case 'fa':
- case 'fi':
- case 'fo':
- case 'fur':
- case 'fy':
- case 'gl':
- case 'gu':
- case 'ha':
- case 'he':
- case 'hu':
- case 'is':
- case 'it':
- case 'ku':
- case 'lb':
- case 'ml':
- case 'mn':
- case 'mr':
- case 'nah':
- case 'nb':
- case 'ne':
- case 'nl':
- case 'nn':
- case 'no':
- case 'oc':
- case 'om':
- case 'or':
- case 'pa':
- case 'pap':
- case 'ps':
- case 'pt':
- case 'so':
- case 'sq':
- case 'sv':
- case 'sw':
- case 'ta':
- case 'te':
- case 'tk':
- case 'ur':
- case 'zu':
- return (number === 1) ? 0 : 1
-
- case 'am':
- case 'bh':
- case 'fil':
- case 'fr':
- case 'gun':
- case 'hi':
- case 'hy':
- case 'ln':
- case 'mg':
- case 'nso':
- case 'xbr':
- case 'ti':
- case 'wa':
- return ((number === 0) || (number === 1)) ? 0 : 1
-
- case 'be':
- case 'bs':
- case 'hr':
- case 'ru':
- case 'sh':
- case 'sr':
- case 'uk':
- return ((number % 10 === 1) && (number % 100 !== 11)) ? 0 : (((number % 10 >= 2) && (number % 10 <= 4) && ((number % 100 < 10) || (number % 100 >= 20))) ? 1 : 2)
-
- case 'cs':
- case 'sk':
- return (number === 1) ? 0 : (((number >= 2) && (number <= 4)) ? 1 : 2)
-
- case 'ga':
- return (number === 1) ? 0 : ((number === 2) ? 1 : 2)
-
- case 'lt':
- return ((number % 10 === 1) && (number % 100 !== 11)) ? 0 : (((number % 10 >= 2) && ((number % 100 < 10) || (number % 100 >= 20))) ? 1 : 2)
-
- case 'sl':
- return (number % 100 === 1) ? 0 : ((number % 100 === 2) ? 1 : (((number % 100 === 3) || (number % 100 === 4)) ? 2 : 3))
-
- case 'mk':
- return (number % 10 === 1) ? 0 : 1
-
- case 'mt':
- return (number === 1) ? 0 : (((number === 0) || ((number % 100 > 1) && (number % 100 < 11))) ? 1 : (((number % 100 > 10) && (number % 100 < 20)) ? 2 : 3))
-
- case 'lv':
- return (number === 0) ? 0 : (((number % 10 === 1) && (number % 100 !== 11)) ? 1 : 2)
-
- case 'pl':
- return (number === 1) ? 0 : (((number % 10 >= 2) && (number % 10 <= 4) && ((number % 100 < 12) || (number % 100 > 14))) ? 1 : 2)
-
- case 'cy':
- return (number === 1) ? 0 : ((number === 2) ? 1 : (((number === 8) || (number === 11)) ? 2 : 3))
-
- case 'ro':
- return (number === 1) ? 0 : (((number === 0) || ((number % 100 > 0) && (number % 100 < 20))) ? 1 : 2)
-
- case 'ar':
- return (number === 0) ? 0 : ((number === 1) ? 1 : ((number === 2) ? 2 : (((number % 100 >= 3) && (number % 100 <= 10)) ? 3 : (((number % 100 >= 11) && (number % 100 <= 99)) ? 4 : 5))))
-
- default:
- return 0
- }
- },
+ translatePlural,
}
export default L10n
-/**
- * Returns the user's locale
- *
- * @return {string} locale string
- */
-export const getLocale = () => $('html').data('locale') ?? 'en'
-
-/**
- * Returns the user's language
- *
- * @return {string} language string
- */
-export const getLanguage = () => $('html').prop('lang')
-
Handlebars.registerHelper('t', function(app, text) {
- return L10n.translate(app, text)
+ return translate(app, text)
})
diff --git a/core/src/OC/legacy-loader.js b/core/src/OC/legacy-loader.js
deleted file mode 100644
index e5bbac8f3a0..00000000000
--- a/core/src/OC/legacy-loader.js
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @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/>.
- *
- */
-
-/** @typedef {import('jquery')} jQuery */
-import $ from 'jquery'
-import { generateFilePath } from '@nextcloud/router'
-
-const loadedScripts = {}
-const loadedStyles = []
-
-/**
- * Load a script for the server and load it. If the script is already loaded,
- * the event handler will be called directly
- *
- * @param {string} app the app id to which the script belongs
- * @param {string} script the filename of the script
- * @param {Function} ready event handler to be called when the script is loaded
- * @return {jQuery.Deferred}
- * @deprecated 16.0.0 Use OCP.Loader.loadScript
- */
-export const addScript = (app, script, ready) => {
- console.warn('OC.addScript is deprecated, use OCP.Loader.loadScript instead')
-
- let deferred
- const path = generateFilePath(app, 'js', script + '.js')
- if (!loadedScripts[path]) {
- deferred = $.Deferred()
- $.getScript(path, () => deferred.resolve())
- loadedScripts[path] = deferred
- } else {
- if (ready) {
- ready()
- }
- }
- return loadedScripts[path]
-}
-
-/**
- * Loads a CSS file
- *
- * @param {string} app the app id to which the css style belongs
- * @param {string} style the filename of the css file
- * @deprecated 16.0.0 Use OCP.Loader.loadStylesheet
- */
-export const addStyle = (app, style) => {
- console.warn('OC.addStyle is deprecated, use OCP.Loader.loadStylesheet instead')
-
- const path = generateFilePath(app, 'css', style + '.css')
- if (loadedStyles.indexOf(path) === -1) {
- loadedStyles.push(path)
- if (document.createStyleSheet) {
- document.createStyleSheet(path)
- } else {
- style = $('<link rel="stylesheet" type="text/css" href="' + path + '"/>')
- $('head').append(style)
- }
- }
-}
diff --git a/core/src/OC/menu.js b/core/src/OC/menu.js
index 7d4d2f91a6c..4b4eb658592 100644
--- a/core/src/OC/menu.js
+++ b/core/src/OC/menu.js
@@ -1,32 +1,13 @@
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Calviño Sánchez <danxuliu@gmail.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/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
import _ from 'underscore'
/** @typedef {import('jquery')} jQuery */
import $ from 'jquery'
-import { menuSpeed } from './constants'
+import { menuSpeed } from './constants.js'
export let currentMenu = null
export let currentMenuToggle = null
@@ -123,7 +104,7 @@ export const hideMenus = function(complete) {
/**
* Shows a given element as menu
*
- * @param {object} [$toggle=null] menu toggle
+ * @param {object} [$toggle] menu toggle
* @param {object} $menuEl menu element
* @param {Function} complete callback when the showing animation is done
*/
diff --git a/core/src/OC/msg.js b/core/src/OC/msg.js
index ef6f9ec0f09..655631a03ff 100644
--- a/core/src/OC/msg.js
+++ b/core/src/OC/msg.js
@@ -1,25 +1,6 @@
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author rakekniven <mark.ziegler@rakekniven.de>
- *
- * @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/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
import $ from 'jquery'
diff --git a/core/src/OC/navigation.js b/core/src/OC/navigation.js
index 2102c37b3f5..b279b9a60f3 100644
--- a/core/src/OC/navigation.js
+++ b/core/src/OC/navigation.js
@@ -1,24 +1,6 @@
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @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/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
export const redirect = targetURL => { window.location = targetURL }
diff --git a/core/src/OC/notification.js b/core/src/OC/notification.js
index 949df6a519c..b658f4163bb 100644
--- a/core/src/OC/notification.js
+++ b/core/src/OC/notification.js
@@ -1,28 +1,6 @@
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Daniel Calviño Sánchez <danxuliu@gmail.com>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Julius Härtl <jus@bitgrid.net>
- * @author npmbuildbot[bot] "npmbuildbot[bot]@users.noreply.github.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/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
import _ from 'underscore'
@@ -98,7 +76,7 @@ export default {
* @param {string} html Message to display
* @param {object} [options] options
* @param {string} [options.type] notification type
- * @param {number} [options.timeout=0] timeout value, defaults to 0 (permanent)
+ * @param {number} [options.timeout] timeout value, defaults to 0 (permanent)
* @return {jQuery} jQuery element for notification row
* @deprecated 17.0.0 use the `@nextcloud/dialogs` package
*/
@@ -117,7 +95,7 @@ export default {
* @param {string} text Message to display
* @param {object} [options] options
* @param {string} [options.type] notification type
- * @param {number} [options.timeout=0] timeout value, defaults to 0 (permanent)
+ * @param {number} [options.timeout] timeout value, defaults to 0 (permanent)
* @return {jQuery} jQuery element for notification row
* @deprecated 17.0.0 use the `@nextcloud/dialogs` package
*/
@@ -142,7 +120,7 @@ export default {
* Updates (replaces) a sanitized notification.
*
* @param {string} text Message to display
- * @return {jQuery} JQuery element for notificaiton row
+ * @return {jQuery} JQuery element for notification row
* @deprecated 17.0.0 use the `@nextcloud/dialogs` package
*/
showUpdate(text) {
@@ -160,10 +138,10 @@ export default {
*
* @param {string} text Message to show
* @param {Array} [options] options array
- * @param {number} [options.timeout=7] timeout in seconds, if this is 0 it will show the message permanently
- * @param {boolean} [options.isHTML=false] an indicator for HTML notifications (true) or text (false)
+ * @param {number} [options.timeout] timeout in seconds, if this is 0 it will show the message permanently
+ * @param {boolean} [options.isHTML] an indicator for HTML notifications (true) or text (false)
* @param {string} [options.type] notification type
- * @return {JQuery} the toast element
+ * @return {jQuery} the toast element
* @deprecated 17.0.0 use the `@nextcloud/dialogs` package
*/
showTemporary(text, options) {
diff --git a/core/src/OC/password-confirmation.js b/core/src/OC/password-confirmation.js
index 4aa643c19fb..621f7a0695f 100644
--- a/core/src/OC/password-confirmation.js
+++ b/core/src/OC/password-confirmation.js
@@ -1,130 +1,26 @@
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @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/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
-import _ from 'underscore'
-import $ from 'jquery'
-import moment from 'moment'
-import { generateUrl } from '@nextcloud/router'
-
-import OC from './index'
+import { confirmPassword, isPasswordConfirmationRequired } from '@nextcloud/password-confirmation'
+import '@nextcloud/password-confirmation/dist/style.css'
/**
* @namespace OC.PasswordConfirmation
*/
export default {
- callback: null,
-
- pageLoadTime: null,
-
- init() {
- $('.password-confirm-required').on('click', _.bind(this.requirePasswordConfirmation, this))
- this.pageLoadTime = moment.now()
- },
requiresPasswordConfirmation() {
- const serverTimeDiff = this.pageLoadTime - (window.nc_pageLoad * 1000)
- const timeSinceLogin = moment.now() - (serverTimeDiff + (window.nc_lastLogin * 1000))
-
- // if timeSinceLogin > 30 minutes and user backend allows password confirmation
- return (window.backendAllowsPasswordConfirmation && timeSinceLogin > 30 * 60 * 1000)
+ return isPasswordConfirmationRequired()
},
/**
* @param {Function} callback success callback function
- * @param {object} options options
+ * @param {object} options options currently not used by confirmPassword
* @param {Function} rejectCallback error callback function
*/
requirePasswordConfirmation(callback, options, rejectCallback) {
- options = typeof options !== 'undefined' ? options : {}
- const defaults = {
- title: t('core', 'Authentication required'),
- text: t(
- 'core',
- 'This action requires you to confirm your password'
- ),
- confirm: t('core', 'Confirm'),
- label: t('core', 'Password'),
- error: '',
- }
-
- const config = _.extend(defaults, options)
-
- const self = this
-
- if (this.requiresPasswordConfirmation()) {
- OC.dialogs.prompt(
- config.text,
- config.title,
- function(result, password) {
- if (result && password !== '') {
- self._confirmPassword(password, config)
- } else if (_.isFunction(rejectCallback)) {
- rejectCallback()
- }
- },
- true,
- config.label,
- true
- ).then(function() {
- const $dialog = $('.oc-dialog:visible')
- $dialog.find('.ui-icon').remove()
- $dialog.addClass('password-confirmation')
- if (config.error !== '') {
- const $error = $('<p></p>').addClass('msg warning').text(config.error)
- $dialog.find('.oc-dialog-content').append($error)
- }
- $dialog.find('.oc-dialog-buttonrow').addClass('aside')
-
- const $buttons = $dialog.find('button')
- $buttons.eq(0).hide()
- $buttons.eq(1).text(config.confirm)
- })
- }
-
- this.callback = callback
- },
-
- _confirmPassword(password, config) {
- const self = this
-
- $.ajax({
- url: generateUrl('/login/confirm'),
- data: {
- password,
- },
- type: 'POST',
- success(response) {
- window.nc_lastLogin = response.lastLogin
-
- if (_.isFunction(self.callback)) {
- self.callback()
- }
- },
- error() {
- config.error = t('core', 'Failed to authenticate, try again')
- OC.PasswordConfirmation.requirePasswordConfirmation(self.callback, config)
- },
- })
+ confirmPassword().then(callback, rejectCallback)
},
}
diff --git a/core/src/OC/plugins.js b/core/src/OC/plugins.js
index 4425c118589..8212fc0b4ee 100644
--- a/core/src/OC/plugins.js
+++ b/core/src/OC/plugins.js
@@ -1,24 +1,6 @@
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @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/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
export default {
diff --git a/core/src/OC/query-string.js b/core/src/OC/query-string.js
index 56bf85186fb..df0f366133a 100644
--- a/core/src/OC/query-string.js
+++ b/core/src/OC/query-string.js
@@ -1,25 +1,6 @@
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @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/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
import $ from 'jquery'
@@ -28,7 +9,7 @@ import $ from 'jquery'
* Parses a URL query string into a JS map
*
* @param {string} queryString query string in the format param1=1234&param2=abcde&param3=xyz
- * @return {Object<string, string>} map containing key/values matching the URL parameters
+ * @return {Record<string, string>} map containing key/values matching the URL parameters
*/
export const parse = queryString => {
let pos
@@ -77,7 +58,7 @@ export const parse = queryString => {
/**
* Builds a URL query from a JS map.
*
- * @param {Object<string, string>} params map containing key/values matching the URL parameters
+ * @param {Record<string, string>} params map containing key/values matching the URL parameters
* @return {string} String containing a URL query (without question) mark
*/
export const build = params => {
diff --git a/core/src/OC/requesttoken.js b/core/src/OC/requesttoken.js
deleted file mode 100644
index eba15e88e08..00000000000
--- a/core/src/OC/requesttoken.js
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @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 { emit } from '@nextcloud/event-bus'
-
-/**
- * @private
- * @param {Document} global the document to read the initial value from
- * @param {Function} emit the function to invoke for every new token
- * @return {object}
- */
-export const manageToken = (global, emit) => {
- let token = global.getElementsByTagName('head')[0].getAttribute('data-requesttoken')
-
- return {
- getToken: () => token,
- setToken: newToken => {
- token = newToken
-
- emit('csrf-token-update', {
- token,
- })
- },
- }
-}
-
-const manageFromDocument = manageToken(document, emit)
-
-/**
- * @return {string}
- */
-export const getToken = manageFromDocument.getToken
-
-/**
- * @param {string} newToken new token
- */
-export const setToken = manageFromDocument.setToken
diff --git a/core/src/OC/requesttoken.ts b/core/src/OC/requesttoken.ts
new file mode 100644
index 00000000000..8ecf0b3de7e
--- /dev/null
+++ b/core/src/OC/requesttoken.ts
@@ -0,0 +1,49 @@
+/**
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+import { emit } from '@nextcloud/event-bus'
+import { generateUrl } from '@nextcloud/router'
+
+/**
+ * Get the current CSRF token.
+ */
+export function getRequestToken(): string {
+ return document.head.dataset.requesttoken!
+}
+
+/**
+ * Set a new CSRF token (e.g. because of session refresh).
+ * This also emits an event bus event for the updated token.
+ *
+ * @param token - The new token
+ * @fires Error - If the passed token is not a potential valid token
+ */
+export function setRequestToken(token: string): void {
+ if (!token || typeof token !== 'string') {
+ throw new Error('Invalid CSRF token given', { cause: { token } })
+ }
+
+ document.head.dataset.requesttoken = token
+ emit('csrf-token-update', { token })
+}
+
+/**
+ * Fetch the request token from the API.
+ * This does also set it on the current context, see `setRequestToken`.
+ *
+ * @fires Error - If the request failed
+ */
+export async function fetchRequestToken(): Promise<string> {
+ const url = generateUrl('/csrftoken')
+
+ const response = await fetch(url)
+ if (!response.ok) {
+ throw new Error('Could not fetch CSRF token from API', { cause: response })
+ }
+
+ const { token } = await response.json()
+ setRequestToken(token)
+ return token
+}
diff --git a/core/src/OC/routing.js b/core/src/OC/routing.js
index 8752aa3883e..4b81714d6f0 100644
--- a/core/src/OC/routing.js
+++ b/core/src/OC/routing.js
@@ -1,25 +1,6 @@
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- *
- * @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/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
import {
diff --git a/core/src/OC/theme.js b/core/src/OC/theme.js
index b7fcfd8ce4d..af45c37de7e 100644
--- a/core/src/OC/theme.js
+++ b/core/src/OC/theme.js
@@ -1,23 +1,6 @@
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @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/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
export const theme = window._theme || {}
diff --git a/core/src/OC/util-history.js b/core/src/OC/util-history.js
index a7398b4a2fc..7ecd0e098c6 100644
--- a/core/src/OC/util-history.js
+++ b/core/src/OC/util-history.js
@@ -1,28 +1,10 @@
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @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/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
import _ from 'underscore'
-import OC from './index'
+import OC from './index.js'
/**
* Utility class for the history API,
@@ -45,7 +27,7 @@ export default {
* or a map
* @param {string} [url] URL to be used, otherwise the current URL will be used,
* using the params as query string
- * @param {boolean} [replace=false] whether to replace instead of pushing
+ * @param {boolean} [replace] whether to replace instead of pushing
*/
_pushState(params, url, replace) {
let strParams
diff --git a/core/src/OC/util.js b/core/src/OC/util.js
index e1a2f8f0687..c46d9a141b1 100644
--- a/core/src/OC/util.js
+++ b/core/src/OC/util.js
@@ -1,30 +1,12 @@
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @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/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
import moment from 'moment'
-import History from './util-history'
-import OC from './index'
+import History from './util-history.js'
+import OC from './index.js'
import { formatFileSize as humanFileSize } from '@nextcloud/files'
/**
@@ -64,7 +46,7 @@ export default {
History,
/**
- * @deprecated use https://nextcloud.github.io/nextcloud-files/modules/_humanfilesize_.html#formatfilesize
+ * @deprecated use https://nextcloud.github.io/nextcloud-files/functions/formatFileSize.html
*/
humanFileSize,
@@ -73,7 +55,7 @@ export default {
* Makes 2kB to 2048.
* Inspired by computerFileSize in helper.php
*
- * @param {string} string file size in human readable format
+ * @param {string} string file size in human-readable format
* @return {number} or null if string could not be parsed
*
*
@@ -124,7 +106,7 @@ export default {
*/
formatDate(timestamp, format) {
if (window.TESTING === undefined) {
- console.warn('OC.Util.formatDate is deprecated and will be removed in Nextcloud 21. See @nextcloud/moment')
+ OC.debug && console.warn('OC.Util.formatDate is deprecated and will be removed in Nextcloud 21. See @nextcloud/moment')
}
format = format || 'LLL'
return moment(timestamp).format(format)
@@ -136,7 +118,7 @@ export default {
*/
relativeModifiedDate(timestamp) {
if (window.TESTING === undefined) {
- console.warn('OC.Util.relativeModifiedDate is deprecated and will be removed in Nextcloud 21. See @nextcloud/moment')
+ OC.debug && console.warn('OC.Util.relativeModifiedDate is deprecated and will be removed in Nextcloud 21. See @nextcloud/moment')
}
const diff = moment().diff(moment(timestamp))
if (diff >= 0 && diff < 45000) {
diff --git a/core/src/OC/webroot.js b/core/src/OC/webroot.js
index f5d063d6b50..cbe5a6190e1 100644
--- a/core/src/OC/webroot.js
+++ b/core/src/OC/webroot.js
@@ -1,23 +1,6 @@
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @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/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
let webroot = window._oc_webroot
diff --git a/core/src/OC/xhr-error.js b/core/src/OC/xhr-error.js
index 990340a1fda..233aaf60350 100644
--- a/core/src/OC/xhr-error.js
+++ b/core/src/OC/xhr-error.js
@@ -1,41 +1,25 @@
/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @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/>.
- *
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
import _ from 'underscore'
import $ from 'jquery'
-import OC from './index'
-import Notification from './notification'
+import OC from './index.js'
+import Notification from './notification.js'
+import { getCurrentUser } from '@nextcloud/auth'
+import { showWarning } from '@nextcloud/dialogs'
/**
* Warn users that the connection to the server was lost temporarily
*
- * This function is throttled to prevent stacked notfications.
+ * This function is throttled to prevent stacked notifications.
* After 7sec the first notification is gone, then we can show another one
* if necessary.
*/
export const ajaxConnectionLostHandler = _.throttle(() => {
- Notification.showTemporary(t('core', 'Connection to server lost'))
+ showWarning(t('core', 'Connection to server lost'))
}, 7 * 1000, { trailing: false })
/**
@@ -46,13 +30,13 @@ export const ajaxConnectionLostHandler = _.throttle(() => {
*/
export const processAjaxError = xhr => {
// purposefully aborted request ?
- // OC._userIsNavigatingAway needed to distinguish ajax calls cancelled by navigating away
- // from calls cancelled by failed cross-domain ajax due to SSO redirect
+ // OC._userIsNavigatingAway needed to distinguish Ajax calls cancelled by navigating away
+ // from calls cancelled by failed cross-domain Ajax due to SSO redirect
if (xhr.status === 0 && (xhr.statusText === 'abort' || xhr.statusText === 'timeout' || OC._reloadCalled)) {
return
}
- if (_.contains([302, 303, 307, 401], xhr.status) && OC.currentUser) {
+ if ([302, 303, 307, 401].includes(xhr.status) && getCurrentUser()) {
// sometimes "beforeunload" happens later, so need to defer the reload a bit
setTimeout(function() {
if (!OC._userIsNavigatingAway && !OC._reloadCalled) {
@@ -65,7 +49,7 @@ export const processAjaxError = xhr => {
OC.reload()
}
timer++
- }, 1000 // 1 second interval
+ }, 1000, // 1 second interval
)
// only call reload once