summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
m---------3rdparty0
-rw-r--r--CODE_OF_CONDUCT.md9
-rw-r--r--apps/dav/lib/Upload/UploadHome.php3
-rw-r--r--apps/files/js/file-upload.js14
-rw-r--r--apps/files/js/filelist.js2
-rw-r--r--apps/files/js/mainfileinfodetailview.js9
-rw-r--r--apps/files/l10n/en_GB.js3
-rw-r--r--apps/files/l10n/en_GB.json3
-rw-r--r--apps/files/l10n/es.js3
-rw-r--r--apps/files/l10n/es.json3
-rw-r--r--apps/files/l10n/fr.js2
-rw-r--r--apps/files/l10n/fr.json2
-rw-r--r--apps/files/l10n/ka_GE.js3
-rw-r--r--apps/files/l10n/ka_GE.json3
-rw-r--r--apps/files/l10n/ko.js4
-rw-r--r--apps/files/l10n/ko.json4
-rw-r--r--apps/files/l10n/nb.js2
-rw-r--r--apps/files/l10n/nb.json2
-rw-r--r--apps/files/l10n/nl.js3
-rw-r--r--apps/files/l10n/nl.json3
-rw-r--r--apps/files/l10n/ro.js129
-rw-r--r--apps/files/l10n/ro.json129
-rw-r--r--apps/files/l10n/ru.js3
-rw-r--r--apps/files/l10n/ru.json3
-rw-r--r--apps/files/l10n/tr.js3
-rw-r--r--apps/files/l10n/tr.json3
-rw-r--r--apps/files/lib/AppInfo/Application.php5
-rw-r--r--apps/files/lib/Service/TagService.php16
-rw-r--r--apps/files/tests/Service/TagServiceTest.php8
-rw-r--r--apps/files/tests/js/filelistSpec.js49
-rw-r--r--apps/files/tests/js/mainfileinfodetailviewSpec.js29
-rw-r--r--apps/files_external/l10n/de.js1
-rw-r--r--apps/files_external/l10n/de.json1
-rw-r--r--apps/files_external/l10n/de_DE.js1
-rw-r--r--apps/files_external/l10n/de_DE.json1
-rw-r--r--apps/files_external/l10n/en_GB.js1
-rw-r--r--apps/files_external/l10n/en_GB.json1
-rw-r--r--apps/files_external/l10n/es.js1
-rw-r--r--apps/files_external/l10n/es.json1
-rw-r--r--apps/files_external/l10n/hu.js1
-rw-r--r--apps/files_external/l10n/hu.json1
-rw-r--r--apps/files_external/l10n/it.js1
-rw-r--r--apps/files_external/l10n/it.json1
-rw-r--r--apps/files_external/l10n/ka_GE.js1
-rw-r--r--apps/files_external/l10n/ka_GE.json1
-rw-r--r--apps/files_external/l10n/ko.js1
-rw-r--r--apps/files_external/l10n/ko.json1
-rw-r--r--apps/files_external/l10n/nl.js1
-rw-r--r--apps/files_external/l10n/nl.json1
-rw-r--r--apps/files_external/l10n/pt_BR.js1
-rw-r--r--apps/files_external/l10n/pt_BR.json1
-rw-r--r--apps/files_external/l10n/sr.js1
-rw-r--r--apps/files_external/l10n/sr.json1
-rw-r--r--apps/files_external/l10n/tr.js1
-rw-r--r--apps/files_external/l10n/tr.json1
-rw-r--r--apps/files_sharing/l10n/ko.js12
-rw-r--r--apps/files_sharing/l10n/ko.json12
-rw-r--r--apps/files_sharing/lib/External/Mount.php10
-rw-r--r--apps/sharebymail/l10n/sv.js18
-rw-r--r--apps/sharebymail/l10n/sv.json18
-rw-r--r--apps/theming/css/theming.scss28
-rw-r--r--apps/theming/lib/Capabilities.php2
-rw-r--r--apps/theming/lib/Controller/ThemingController.php4
-rw-r--r--apps/theming/lib/ThemingDefaults.php15
-rw-r--r--apps/theming/lib/Util.php47
-rw-r--r--apps/theming/tests/CapabilitiesTest.php46
-rw-r--r--apps/theming/tests/ThemingDefaultsTest.php44
-rw-r--r--apps/theming/tests/UtilTest.php53
-rw-r--r--apps/updatenotification/js/notification.js7
-rw-r--r--apps/user_ldap/composer/composer/autoload_classmap.php2
-rw-r--r--apps/user_ldap/composer/composer/autoload_static.php2
-rw-r--r--apps/user_ldap/lib/AccessFactory.php61
-rw-r--r--apps/user_ldap/lib/ConnectionFactory.php38
-rw-r--r--apps/user_ldap/lib/Jobs/Sync.php37
-rw-r--r--apps/user_ldap/tests/Jobs/SyncTest.php225
-rw-r--r--build/files-checker.php1
-rw-r--r--config/config.sample.php17
-rw-r--r--core/Controller/OCJSController.php8
-rw-r--r--core/css/apps.scss1
-rw-r--r--core/css/fixes.scss3
-rw-r--r--core/css/guest.css6
-rw-r--r--core/css/header.scss9
-rw-r--r--core/css/styles.scss63
-rw-r--r--core/css/tooltip.scss2
-rw-r--r--core/js/jquery.avatar.js5
-rw-r--r--core/js/js.js7
-rw-r--r--core/js/lostpassword.js1
-rw-r--r--core/js/placeholder.js1
-rw-r--r--core/js/public/comments.js2
-rw-r--r--core/js/sharedialogshareelistview.js19
-rw-r--r--core/js/tests/specs/coreSpec.js61
-rw-r--r--core/js/tests/specs/jquery.avatarSpec.js2
-rw-r--r--core/templates/layout.user.php14
-rw-r--r--core/templates/login.php12
-rw-r--r--lib/l10n/ko.js4
-rw-r--r--lib/l10n/ko.json4
-rw-r--r--lib/l10n/ru.js4
-rw-r--r--lib/l10n/ru.json4
-rw-r--r--lib/l10n/sv.js8
-rw-r--r--lib/l10n/sv.json8
-rw-r--r--lib/private/Preview/Generator.php56
-rw-r--r--lib/private/Settings/Manager.php3
-rw-r--r--lib/private/Share20/DefaultShareProvider.php6
-rw-r--r--lib/private/Template/JSConfigHelper.php1
-rw-r--r--lib/private/TemplateLayout.php2
-rw-r--r--lib/private/legacy/image.php19
-rw-r--r--lib/public/IImage.php6
-rw-r--r--ocs/v1.php4
-rw-r--r--settings/css/settings.scss42
-rw-r--r--settings/js/users/users.js11
-rw-r--r--settings/l10n/en_GB.js6
-rw-r--r--settings/l10n/en_GB.json6
-rw-r--r--settings/l10n/es.js6
-rw-r--r--settings/l10n/es.json6
-rw-r--r--settings/l10n/ka_GE.js6
-rw-r--r--settings/l10n/ka_GE.json6
-rw-r--r--settings/l10n/ko.js4
-rw-r--r--settings/l10n/ko.json4
-rw-r--r--settings/l10n/nb.js3
-rw-r--r--settings/l10n/nb.json3
-rw-r--r--settings/l10n/nl.js6
-rw-r--r--settings/l10n/nl.json6
-rw-r--r--settings/l10n/ro.js67
-rw-r--r--settings/l10n/ro.json67
-rw-r--r--settings/l10n/ru.js6
-rw-r--r--settings/l10n/ru.json6
-rw-r--r--settings/l10n/sv.js2
-rw-r--r--settings/l10n/sv.json2
-rw-r--r--settings/l10n/tr.js6
-rw-r--r--settings/l10n/tr.json6
-rw-r--r--settings/templates/users/part.userlist.php31
-rw-r--r--tests/acceptance/features/app-files.feature7
-rw-r--r--tests/acceptance/features/bootstrap/FilesAppContext.php50
-rw-r--r--tests/acceptance/features/bootstrap/LoginPageContext.php2
-rw-r--r--tests/lib/Preview/GeneratorTest.php8
-rw-r--r--version.php4
136 files changed, 1480 insertions, 421 deletions
diff --git a/3rdparty b/3rdparty
-Subproject 696f7683651fa2ee1f59cbde08c6f5fefbcaad0
+Subproject 3cec97e2cbdbac0a07dc6269e7fc80048596b41
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 00000000000..d9060072e46
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,9 @@
+In the Nextcloud community, participants from all over the world come together to create Free Software for a free internet. This is made possible by the support, hard work and enthusiasm of thousands of people, including those who create and use Nextcloud software.
+
+Our code of conduct offers some guidance to ensure Nextcloud participants can cooperate effectively in a positive and inspiring atmosphere, and to explain how together we can strengthen and support each other.
+
+The Code of Conduct is shared by all contributors and users who engage with the Nextcloud team and its community services. It presents a summary of the shared values and “common sense” thinking in our community.
+
+You can find our full code of conduct on our website: https://nextcloud.com/code-of-conduct/
+
+Please, keep our CoC in mind when you contribute! That way, everyone can be a part of our community in a productive, positive, creative and fun way.
diff --git a/apps/dav/lib/Upload/UploadHome.php b/apps/dav/lib/Upload/UploadHome.php
index 9f4ae0e8a2c..ec31e93f4f9 100644
--- a/apps/dav/lib/Upload/UploadHome.php
+++ b/apps/dav/lib/Upload/UploadHome.php
@@ -66,7 +66,8 @@ class UploadHome implements ICollection {
}
function getName() {
- return 'uploads';
+ list(,$name) = \Sabre\Uri\split($this->principalInfo['uri']);
+ return $name;
}
function setName($name) {
diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js
index 8e95abcb5e8..ad56492730e 100644
--- a/apps/files/js/file-upload.js
+++ b/apps/files/js/file-upload.js
@@ -235,7 +235,7 @@ OC.FileUpload.prototype = {
) {
data.isChunked = true;
chunkFolderPromise = this.uploader.davClient.createDirectory(
- 'uploads/' + encodeURIComponent(OC.getCurrentUser().uid) + '/' + encodeURIComponent(this.getId())
+ 'uploads/' + OC.getCurrentUser().uid + '/' + this.getId()
);
// TODO: if fails, it means same id already existed, need to retry
} else {
@@ -272,8 +272,8 @@ OC.FileUpload.prototype = {
}
return this.uploader.davClient.move(
- 'uploads/' + encodeURIComponent(uid) + '/' + encodeURIComponent(this.getId()) + '/.file',
- 'files/' + encodeURIComponent(uid) + '/' + OC.joinPaths(this.getFullPath(), this.getFileName()),
+ 'uploads/' + uid + '/' + this.getId() + '/.file',
+ 'files/' + uid + '/' + OC.joinPaths(this.getFullPath(), this.getFileName()),
true,
headers
);
@@ -282,7 +282,7 @@ OC.FileUpload.prototype = {
_deleteChunkFolder: function() {
// delete transfer directory for this upload
this.uploader.davClient.remove(
- 'uploads/' + encodeURIComponent(OC.getCurrentUser().uid) + '/' + encodeURIComponent(this.getId())
+ 'uploads/' + OC.getCurrentUser().uid + '/' + this.getId()
);
},
@@ -1166,9 +1166,9 @@ OC.Uploader.prototype = _.extend({
var chunkId = range.split('/')[0].split('-')[0];
data.url = OC.getRootPath() +
'/remote.php/dav/uploads' +
- '/' + encodeURIComponent(OC.getCurrentUser().uid) +
- '/' + encodeURIComponent(upload.getId()) +
- '/' + encodeURIComponent(chunkId);
+ '/' + OC.getCurrentUser().uid +
+ '/' + upload.getId() +
+ '/' + chunkId;
delete data.contentRange;
delete data.headers['Content-Range'];
});
diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js
index 7a4ea492752..e50b402dea8 100644
--- a/apps/files/js/filelist.js
+++ b/apps/files/js/filelist.js
@@ -2266,7 +2266,7 @@
function updateInList(fileInfo) {
self.updateRow(tr, fileInfo);
- self._updateDetailsView(fileInfo, false);
+ self._updateDetailsView(fileInfo.name, false);
}
// TODO: too many nested blocks, move parts into functions
diff --git a/apps/files/js/mainfileinfodetailview.js b/apps/files/js/mainfileinfodetailview.js
index ea3063f6176..626ab86ded3 100644
--- a/apps/files/js/mainfileinfodetailview.js
+++ b/apps/files/js/mainfileinfodetailview.js
@@ -20,9 +20,11 @@
'</a>' +
'</div>' +
' <div class="file-details ellipsis">' +
+ ' {{#if hasFavoriteAction}}' +
' <a href="#" class="action action-favorite favorite permanent">' +
' <span class="icon {{starClass}}" title="{{starAltText}}"></span>' +
' </a>' +
+ ' {{/if}}' +
' {{#if hasSize}}<span class="size" title="{{altSize}}">{{size}}</span>, {{/if}}<span class="date live-relative-timestamp" data-timestamp="{{timestamp}}" title="{{altDate}}">{{date}}</span>' +
' </div>' +
'</div>' +
@@ -175,6 +177,12 @@
if (this.model) {
var isFavorite = (this.model.get('tags') || []).indexOf(OC.TAG_FAVORITE) >= 0;
+ var availableActions = this._fileActions.get(
+ this.model.get('mimetype'),
+ this.model.get('type'),
+ this.model.get('permissions')
+ );
+ var hasFavoriteAction = 'Favorite' in availableActions;
this.$el.html(this.template({
type: this.model.isImage()? 'image': '',
nameLabel: t('files', 'Name'),
@@ -189,6 +197,7 @@
altDate: OC.Util.formatDate(this.model.get('mtime')),
timestamp: this.model.get('mtime'),
date: OC.Util.relativeModifiedDate(this.model.get('mtime')),
+ hasFavoriteAction: hasFavoriteAction,
starAltText: isFavorite ? t('files', 'Favorited') : t('files', 'Favorite'),
starClass: isFavorite ? 'icon-starred' : 'icon-star',
permalink: this._makePermalink(this.model.get('id')),
diff --git a/apps/files/l10n/en_GB.js b/apps/files/l10n/en_GB.js
index 424d470d970..21f6e339784 100644
--- a/apps/files/l10n/en_GB.js
+++ b/apps/files/l10n/en_GB.js
@@ -62,8 +62,11 @@ OC.L10N.register(
"You don’t have permission to upload or create files here" : "You don’t have permission to upload or create files here",
"_Uploading %n file_::_Uploading %n files_" : ["Uploading %n file","Uploading %n files"],
"New" : "New",
+ "{used} of {quota} used" : "{used} of {quota} used",
+ "{used} used" : "{used} used",
"\"{name}\" is an invalid file name." : "\"{name}\" is an invalid file name.",
"File name cannot be empty." : "File name cannot be empty.",
+ "\"/\" is not allowed inside a file name." : "\"/\" is not allowed inside a file name.",
"\"{name}\" is not an allowed filetype" : "\"{name}\" is not an allowed filetype",
"Storage of {owner} is full, files can not be updated or synced anymore!" : "Storage of {owner} is full, files can not be updated or synced anymore!",
"Your storage is full, files can not be updated or synced anymore!" : "Your storage is full, files can not be updated or synced anymore!",
diff --git a/apps/files/l10n/en_GB.json b/apps/files/l10n/en_GB.json
index 1ac5d53c7a6..f8ff0a553b5 100644
--- a/apps/files/l10n/en_GB.json
+++ b/apps/files/l10n/en_GB.json
@@ -60,8 +60,11 @@
"You don’t have permission to upload or create files here" : "You don’t have permission to upload or create files here",
"_Uploading %n file_::_Uploading %n files_" : ["Uploading %n file","Uploading %n files"],
"New" : "New",
+ "{used} of {quota} used" : "{used} of {quota} used",
+ "{used} used" : "{used} used",
"\"{name}\" is an invalid file name." : "\"{name}\" is an invalid file name.",
"File name cannot be empty." : "File name cannot be empty.",
+ "\"/\" is not allowed inside a file name." : "\"/\" is not allowed inside a file name.",
"\"{name}\" is not an allowed filetype" : "\"{name}\" is not an allowed filetype",
"Storage of {owner} is full, files can not be updated or synced anymore!" : "Storage of {owner} is full, files can not be updated or synced anymore!",
"Your storage is full, files can not be updated or synced anymore!" : "Your storage is full, files can not be updated or synced anymore!",
diff --git a/apps/files/l10n/es.js b/apps/files/l10n/es.js
index a4666bd7bdf..0852da86efc 100644
--- a/apps/files/l10n/es.js
+++ b/apps/files/l10n/es.js
@@ -62,8 +62,11 @@ OC.L10N.register(
"You don’t have permission to upload or create files here" : "No tiene permisos para subir o crear archivos aquí",
"_Uploading %n file_::_Uploading %n files_" : ["Subiendo %n archivo","Subiendo %n archivos"],
"New" : "Nuevo",
+ "{used} of {quota} used" : "{used} usados de {quota}",
+ "{used} used" : "{used} usados",
"\"{name}\" is an invalid file name." : "\"{name}\" es un nombre de archivo inválido.",
"File name cannot be empty." : "El nombre de archivo no puede estar vacío.",
+ "\"/\" is not allowed inside a file name." : "\"/\" no se permite dentro de un nombre de archivo.",
"\"{name}\" is not an allowed filetype" : "\"{name}\" no es un tipo de archivo permitido",
"Storage of {owner} is full, files can not be updated or synced anymore!" : "El almacén de {owner} está repleto, ¡los archivos no se actualizarán ni sincronizarán más!",
"Your storage is full, files can not be updated or synced anymore!" : "Su almacenamiento está lleno, ¡los archivos no se actualizarán ni sincronizarán más!",
diff --git a/apps/files/l10n/es.json b/apps/files/l10n/es.json
index 44db92002f2..db8baad60b3 100644
--- a/apps/files/l10n/es.json
+++ b/apps/files/l10n/es.json
@@ -60,8 +60,11 @@
"You don’t have permission to upload or create files here" : "No tiene permisos para subir o crear archivos aquí",
"_Uploading %n file_::_Uploading %n files_" : ["Subiendo %n archivo","Subiendo %n archivos"],
"New" : "Nuevo",
+ "{used} of {quota} used" : "{used} usados de {quota}",
+ "{used} used" : "{used} usados",
"\"{name}\" is an invalid file name." : "\"{name}\" es un nombre de archivo inválido.",
"File name cannot be empty." : "El nombre de archivo no puede estar vacío.",
+ "\"/\" is not allowed inside a file name." : "\"/\" no se permite dentro de un nombre de archivo.",
"\"{name}\" is not an allowed filetype" : "\"{name}\" no es un tipo de archivo permitido",
"Storage of {owner} is full, files can not be updated or synced anymore!" : "El almacén de {owner} está repleto, ¡los archivos no se actualizarán ni sincronizarán más!",
"Your storage is full, files can not be updated or synced anymore!" : "Su almacenamiento está lleno, ¡los archivos no se actualizarán ni sincronizarán más!",
diff --git a/apps/files/l10n/fr.js b/apps/files/l10n/fr.js
index b5035e6a1a3..ccce056d631 100644
--- a/apps/files/l10n/fr.js
+++ b/apps/files/l10n/fr.js
@@ -62,9 +62,11 @@ OC.L10N.register(
"You don’t have permission to upload or create files here" : "Vous n'avez pas la permission d'envoyer ou de créer des fichiers ici",
"_Uploading %n file_::_Uploading %n files_" : ["Téléversement de %n fichier","Téléversement de %n fichiers"],
"New" : "Nouveau",
+ "{used} of {quota} used" : "{used} de {quota} utilisé",
"{used} used" : "{used} utilisé",
"\"{name}\" is an invalid file name." : "\"{name}\" n'est pas un nom de fichier valide.",
"File name cannot be empty." : "Le nom de fichier ne peut être vide.",
+ "\"/\" is not allowed inside a file name." : "\"/\" n'est pas autorisé dans les noms de fichier.",
"\"{name}\" is not an allowed filetype" : "\"{name}\" n'est pas un nom de fichier autorisé.",
"Storage of {owner} is full, files can not be updated or synced anymore!" : "L'espace de stockage de {owner} est plein. Les fichiers ne peuvent plus être mis à jour ni synchronisés !",
"Your storage is full, files can not be updated or synced anymore!" : "Votre espace de stockage est plein. Les fichiers ne peuvent plus être mis à jour ni synchronisés !",
diff --git a/apps/files/l10n/fr.json b/apps/files/l10n/fr.json
index d65a471164e..d1e1320c0dc 100644
--- a/apps/files/l10n/fr.json
+++ b/apps/files/l10n/fr.json
@@ -60,9 +60,11 @@
"You don’t have permission to upload or create files here" : "Vous n'avez pas la permission d'envoyer ou de créer des fichiers ici",
"_Uploading %n file_::_Uploading %n files_" : ["Téléversement de %n fichier","Téléversement de %n fichiers"],
"New" : "Nouveau",
+ "{used} of {quota} used" : "{used} de {quota} utilisé",
"{used} used" : "{used} utilisé",
"\"{name}\" is an invalid file name." : "\"{name}\" n'est pas un nom de fichier valide.",
"File name cannot be empty." : "Le nom de fichier ne peut être vide.",
+ "\"/\" is not allowed inside a file name." : "\"/\" n'est pas autorisé dans les noms de fichier.",
"\"{name}\" is not an allowed filetype" : "\"{name}\" n'est pas un nom de fichier autorisé.",
"Storage of {owner} is full, files can not be updated or synced anymore!" : "L'espace de stockage de {owner} est plein. Les fichiers ne peuvent plus être mis à jour ni synchronisés !",
"Your storage is full, files can not be updated or synced anymore!" : "Votre espace de stockage est plein. Les fichiers ne peuvent plus être mis à jour ni synchronisés !",
diff --git a/apps/files/l10n/ka_GE.js b/apps/files/l10n/ka_GE.js
index 401b93a0e6a..b2b68baa747 100644
--- a/apps/files/l10n/ka_GE.js
+++ b/apps/files/l10n/ka_GE.js
@@ -62,8 +62,11 @@ OC.L10N.register(
"You don’t have permission to upload or create files here" : "აქ ფაილების შექმნის ან ატვირთვის უფლება არ გაქვთ",
"_Uploading %n file_::_Uploading %n files_" : ["ვტვირთავთ %n ფაილს"],
"New" : "ახალი",
+ "{used} of {quota} used" : "გამოყენებულია {used} სულ {quota}-დან",
+ "{used} used" : "გამოყენებულია {used}",
"\"{name}\" is an invalid file name." : "\"{name}\" არასწორი ფაილის სახელია.",
"File name cannot be empty." : "ფაილის სახელი არ შეიძლება იყოს ცარიელი.",
+ "\"/\" is not allowed inside a file name." : "\"/\" ფაილის სახელში არაა ნებადართული.",
"\"{name}\" is not an allowed filetype" : "\"{name}\" არაა დაშვებული ფაილის ტიპი",
"Storage of {owner} is full, files can not be updated or synced anymore!" : "{owner}-ის საცავი სავსეა, ფაილები მეტი ვეღარ განახლდება/სინქრონიზირდება!",
"Your storage is full, files can not be updated or synced anymore!" : "თქვენი საცავი გადაივსო. ფაილების განახლება და სინქრონიზირება ვერ მოხერხდება!",
diff --git a/apps/files/l10n/ka_GE.json b/apps/files/l10n/ka_GE.json
index 36f2400edd8..5c496dc08cf 100644
--- a/apps/files/l10n/ka_GE.json
+++ b/apps/files/l10n/ka_GE.json
@@ -60,8 +60,11 @@
"You don’t have permission to upload or create files here" : "აქ ფაილების შექმნის ან ატვირთვის უფლება არ გაქვთ",
"_Uploading %n file_::_Uploading %n files_" : ["ვტვირთავთ %n ფაილს"],
"New" : "ახალი",
+ "{used} of {quota} used" : "გამოყენებულია {used} სულ {quota}-დან",
+ "{used} used" : "გამოყენებულია {used}",
"\"{name}\" is an invalid file name." : "\"{name}\" არასწორი ფაილის სახელია.",
"File name cannot be empty." : "ფაილის სახელი არ შეიძლება იყოს ცარიელი.",
+ "\"/\" is not allowed inside a file name." : "\"/\" ფაილის სახელში არაა ნებადართული.",
"\"{name}\" is not an allowed filetype" : "\"{name}\" არაა დაშვებული ფაილის ტიპი",
"Storage of {owner} is full, files can not be updated or synced anymore!" : "{owner}-ის საცავი სავსეა, ფაილები მეტი ვეღარ განახლდება/სინქრონიზირდება!",
"Your storage is full, files can not be updated or synced anymore!" : "თქვენი საცავი გადაივსო. ფაილების განახლება და სინქრონიზირება ვერ მოხერხდება!",
diff --git a/apps/files/l10n/ko.js b/apps/files/l10n/ko.js
index 8b6ab2b51b0..cfe3b955df7 100644
--- a/apps/files/l10n/ko.js
+++ b/apps/files/l10n/ko.js
@@ -13,9 +13,9 @@ OC.L10N.register(
"Could not create folder \"{dir}\"" : "폴더 \"{dir}\"을(를) 만들 수 없음",
"Upload cancelled." : "업로드가 취소되었습니다.",
"Unable to upload {filename} as it is a directory or has 0 bytes" : "{filename}을(를) 업로드할 수 없습니다. 폴더이거나 0 바이트 파일입니다.",
- "Not enough free space, you are uploading {size1} but only {size2} is left" : "빈 공간이 부족합니다. 업로드할 파일 크기는 {size1}이지만 현재 {size2}만큼 비었습니다",
+ "Not enough free space, you are uploading {size1} but only {size2} is left" : "남은 공간이 부족합니다. 업로드할 파일 크기는 {size1}이지만 현재 {size2}만큼 남아 있습니다",
"Target folder \"{dir}\" does not exist any more" : "대상 폴더 \"{dir}\"이(가) 더 이상 존재하지 않습니다",
- "Not enough free space" : "빈 공간이 부족합니다",
+ "Not enough free space" : "남은 공간이 부족함",
"Uploading …" : "업로드 중…",
"…" : "…",
"{loadedSize} of {totalSize} ({bitrate})" : "{loadedSize}/{totalSize}({bitrate})",
diff --git a/apps/files/l10n/ko.json b/apps/files/l10n/ko.json
index b9ea23ab0b9..0854c201bf9 100644
--- a/apps/files/l10n/ko.json
+++ b/apps/files/l10n/ko.json
@@ -11,9 +11,9 @@
"Could not create folder \"{dir}\"" : "폴더 \"{dir}\"을(를) 만들 수 없음",
"Upload cancelled." : "업로드가 취소되었습니다.",
"Unable to upload {filename} as it is a directory or has 0 bytes" : "{filename}을(를) 업로드할 수 없습니다. 폴더이거나 0 바이트 파일입니다.",
- "Not enough free space, you are uploading {size1} but only {size2} is left" : "빈 공간이 부족합니다. 업로드할 파일 크기는 {size1}이지만 현재 {size2}만큼 비었습니다",
+ "Not enough free space, you are uploading {size1} but only {size2} is left" : "남은 공간이 부족합니다. 업로드할 파일 크기는 {size1}이지만 현재 {size2}만큼 남아 있습니다",
"Target folder \"{dir}\" does not exist any more" : "대상 폴더 \"{dir}\"이(가) 더 이상 존재하지 않습니다",
- "Not enough free space" : "빈 공간이 부족합니다",
+ "Not enough free space" : "남은 공간이 부족함",
"Uploading …" : "업로드 중…",
"…" : "…",
"{loadedSize} of {totalSize} ({bitrate})" : "{loadedSize}/{totalSize}({bitrate})",
diff --git a/apps/files/l10n/nb.js b/apps/files/l10n/nb.js
index b9e3ee0a1b8..45b9027f782 100644
--- a/apps/files/l10n/nb.js
+++ b/apps/files/l10n/nb.js
@@ -62,6 +62,8 @@ OC.L10N.register(
"You don’t have permission to upload or create files here" : "Du har ikke tillatelse til å laste opp eller opprette filer her",
"_Uploading %n file_::_Uploading %n files_" : ["Laster opp %n fil","Laster opp %n filer"],
"New" : "Ny",
+ "{used} of {quota} used" : "{used} av {quota} brukt",
+ "{used} used" : "{used} brukt",
"\"{name}\" is an invalid file name." : "\"{name}\" er et uglydig filnavn.",
"File name cannot be empty." : "Filnavn kan ikke være tomt.",
"\"{name}\" is not an allowed filetype" : "\"{name}\" er ikke en tillatt filtype",
diff --git a/apps/files/l10n/nb.json b/apps/files/l10n/nb.json
index 4c4e0622362..0328ceb283a 100644
--- a/apps/files/l10n/nb.json
+++ b/apps/files/l10n/nb.json
@@ -60,6 +60,8 @@
"You don’t have permission to upload or create files here" : "Du har ikke tillatelse til å laste opp eller opprette filer her",
"_Uploading %n file_::_Uploading %n files_" : ["Laster opp %n fil","Laster opp %n filer"],
"New" : "Ny",
+ "{used} of {quota} used" : "{used} av {quota} brukt",
+ "{used} used" : "{used} brukt",
"\"{name}\" is an invalid file name." : "\"{name}\" er et uglydig filnavn.",
"File name cannot be empty." : "Filnavn kan ikke være tomt.",
"\"{name}\" is not an allowed filetype" : "\"{name}\" er ikke en tillatt filtype",
diff --git a/apps/files/l10n/nl.js b/apps/files/l10n/nl.js
index 73a52503cef..5ee5d8c6181 100644
--- a/apps/files/l10n/nl.js
+++ b/apps/files/l10n/nl.js
@@ -62,8 +62,11 @@ OC.L10N.register(
"You don’t have permission to upload or create files here" : "Je hebt geen toestemming om hier te uploaden of bestanden te maken",
"_Uploading %n file_::_Uploading %n files_" : ["%n bestand aan het uploaden","%n bestanden aan het uploaden"],
"New" : "Nieuw",
+ "{used} of {quota} used" : "{used} van {quota} gebruikt",
+ "{used} used" : "{used} gebruikt",
"\"{name}\" is an invalid file name." : "\"{name}\" is een ongeldige bestandsnaam.",
"File name cannot be empty." : "Bestandsnaam kan niet leeg zijn.",
+ "\"/\" is not allowed inside a file name." : "\"/\" is niet toegestaan binnen een bestandsnaam.",
"\"{name}\" is not an allowed filetype" : "\"{name}\" bestandstype is een niet toegestaande",
"Storage of {owner} is full, files can not be updated or synced anymore!" : "Opslagruimte van {owner} zit vol, bestanden kunnen niet meer worden geüpload of gesynchroniseerd!",
"Your storage is full, files can not be updated or synced anymore!" : "Je opslagruimte zit vol. Bestanden kunnen niet meer worden gewijzigd of gesynchroniseerd!",
diff --git a/apps/files/l10n/nl.json b/apps/files/l10n/nl.json
index 55c83f970ba..2cc15f1f564 100644
--- a/apps/files/l10n/nl.json
+++ b/apps/files/l10n/nl.json
@@ -60,8 +60,11 @@
"You don’t have permission to upload or create files here" : "Je hebt geen toestemming om hier te uploaden of bestanden te maken",
"_Uploading %n file_::_Uploading %n files_" : ["%n bestand aan het uploaden","%n bestanden aan het uploaden"],
"New" : "Nieuw",
+ "{used} of {quota} used" : "{used} van {quota} gebruikt",
+ "{used} used" : "{used} gebruikt",
"\"{name}\" is an invalid file name." : "\"{name}\" is een ongeldige bestandsnaam.",
"File name cannot be empty." : "Bestandsnaam kan niet leeg zijn.",
+ "\"/\" is not allowed inside a file name." : "\"/\" is niet toegestaan binnen een bestandsnaam.",
"\"{name}\" is not an allowed filetype" : "\"{name}\" bestandstype is een niet toegestaande",
"Storage of {owner} is full, files can not be updated or synced anymore!" : "Opslagruimte van {owner} zit vol, bestanden kunnen niet meer worden geüpload of gesynchroniseerd!",
"Your storage is full, files can not be updated or synced anymore!" : "Je opslagruimte zit vol. Bestanden kunnen niet meer worden gewijzigd of gesynchroniseerd!",
diff --git a/apps/files/l10n/ro.js b/apps/files/l10n/ro.js
index e7b93b7b005..285604b1ea1 100644
--- a/apps/files/l10n/ro.js
+++ b/apps/files/l10n/ro.js
@@ -1,10 +1,12 @@
OC.L10N.register(
"files",
{
+ "Storage is temporarily not available" : "Spațiu de stocare este indisponibil temporar",
"Storage invalid" : "Spațiu de stocare invalid",
"Unknown error" : "Eroare necunoscută",
- "Files" : "Fișiere",
- "All files" : "Toate fișierele.",
+ "All files" : "Toate fișierele",
+ "Recent" : "Recente",
+ "File could not be found" : "Fișierul nu a fost găsit",
"Home" : "Acasă",
"Close" : "Închide",
"Favorites" : "Favorite",
@@ -12,21 +14,21 @@ OC.L10N.register(
"Upload cancelled." : "Încărcare anulată.",
"Unable to upload {filename} as it is a directory or has 0 bytes" : "Nu se poate încărca {filename} deoarece este un director sau are mărimea de 0 octeți",
"Not enough free space, you are uploading {size1} but only {size2} is left" : "Spațiu liber insuficient, încărcați {size1} însă doar {size2} disponibil rămas",
- "Uploading..." : "Încărcare",
- "..." : "...",
- "{hours}:{minutes}h" : "{hours}:{minutes}h",
- "{minutes}:{seconds}m" : "{minutes}:{seconds}m",
- "{seconds} second{plural_s} left" : "{seconds} secunde{plural_s} rămase",
- "{seconds}s" : "{seconds}s",
- "Any moment now..." : "În orice moment...",
- "Soon..." : "În curând...",
- "File upload is in progress. Leaving the page now will cancel the upload." : "Fișierul este în curs de încărcare. Părăsirea paginii va întrerupe încărcarea.",
+ "Target folder \"{dir}\" does not exist any more" : "Directorul \"{dir}\" nu mai există",
+ "Not enough free space" : "Spațiu insuficient",
+ "Uploading …" : "Încărcare...",
+ "…" : "...",
+ "{loadedSize} of {totalSize} ({bitrate})" : "{loadedSize} din {totalSize} ({bitrate})",
+ "Target folder does not exist any more" : "Directorul destinație nu mai există",
"Actions" : "Acțiuni",
"Download" : "Descarcă",
"Rename" : "Redenumește",
+ "Move or copy" : "Mută sau copiază",
+ "Target folder" : "Directorul destinație",
"Delete" : "Șterge",
"Disconnect storage" : "Deconectează stocarea",
"Unshare" : "Nu mai partaja",
+ "Files" : "Fișiere",
"Details" : "Detalii",
"Select" : "Alege",
"Pending" : "În așteptare",
@@ -35,6 +37,8 @@ OC.L10N.register(
"This directory is unavailable, please check the logs or contact the administrator" : "Acest director nu este disponibil, te rugăm verifică logurile sau contactează un administrator",
"Could not move \"{file}\", target exists" : "Nu s-a putut muta fișierul \"{file}\", există deja un altul cu același nume în directorul destinație",
"Could not move \"{file}\"" : "Nu s-a putut muta fișierul \"{file}\"",
+ "Could not copy \"{file}\"" : "Nu s-a putut copia \"{file}\"",
+ "Copied {origin} inside {destination}" : "S-a copiat {origin} în {destination}",
"{newName} already exists" : "{newName} există deja",
"Could not rename \"{fileName}\", it does not exist any more" : "Nu s-a putut redenumi \"{fileName}\", fișierul nu mai există",
"The name \"{targetName}\" is already used in the folder \"{dir}\". Please choose a different name." : "Numele \"{targetName}\" este deja folosit în directorul \"{dir}\". Alege un nume diferit.",
@@ -52,73 +56,98 @@ OC.L10N.register(
"You don’t have permission to upload or create files here" : "Nu aveți permisiunea de a încărca sau crea fișiere aici",
"_Uploading %n file_::_Uploading %n files_" : ["Se încarcă %n fișier.","Se încarcă %n fișiere.","Se încarcă %n fișiere."],
"New" : "Nou",
+ "{used} of {quota} used" : "{used} din {quota} folosiți",
+ "{used} used" : "{used} folosiți",
"\"{name}\" is an invalid file name." : "\"{name}\" este un nume de fișier nevalid.",
"File name cannot be empty." : "Numele fișierului nu poate rămâne gol.",
+ "\"{name}\" is not an allowed filetype" : "\"{name}\" ",
+ "Storage of {owner} is full, files can not be updated or synced anymore!" : "Spațiul de stocare pentru {owner} este plin, fișierele nu mai pot fi incărcate sau sincronizate!",
"Your storage is full, files can not be updated or synced anymore!" : "Spațiul de stocare este plin, fișierele nu mai pot fi actualizate sau sincronizate!",
+ "Storage of {owner} is almost full ({usedSpacePercent}%)" : "Spațiul de stocare pentru {owner} este aproape plin ({usedSpacePercent}%)",
"Your storage is almost full ({usedSpacePercent}%)" : "Spațiul de stocare este aproape plin ({usedSpacePercent}%)",
+ "Copied!" : "S-a copiat!",
+ "Copy direct link (only works for users who have access to this file/folder)" : "Copiază link direct (funcționeză numai pentru utilizatorii care au acces la acest fișier/director)",
"Path" : "Cale",
"_%n byte_::_%n bytes_" : ["%n octet","%n octeți","%n octeți"],
"Favorited" : "Adăugate la favorite",
"Favorite" : "Favorit",
- "Local link" : "Legătură locală",
- "Folder" : "Dosar",
"New folder" : "Un nou dosar",
- "Upload" : "Încărcă",
+ "Upload file" : "Încarcă fișier",
+ "Remove from favorites" : "Șterge din favorite",
+ "Add to favorites" : "Adaugă la favorite",
"An error occurred while trying to update the tags" : "A apărut o eroare în timpul actualizării etichetelor",
- "A new file or folder has been <strong>created</strong>" : "Un nou fișier sau dosar a fost <strong>creat</strong>",
- "A file or folder has been <strong>deleted</strong>" : "Un nou fișier sau dosar a fost <strong>șters</strong>",
+ "Added to favorites" : "Adaugat la favorite",
+ "Removed from favorites" : "Șters din favorite",
+ "You added {file} to your favorites" : "Ai adaugat {file} în favorite",
+ "You removed {file} from your favorites" : "Ai șters {file} din favorite",
+ "Created by {user}" : "Creat de {user}",
+ "Changed by {user}" : "Modificat de {user}",
+ "Deleted by {user}" : "Șters de {user}",
+ "Restored by {user}" : "Restaurat de {user}",
+ "Renamed by {user}" : "Redenumit de {user}",
+ "Moved by {user}" : "Mutat de {user}",
+ "\"remote user\"" : "\"utilizator la distanță\"",
+ "You created {file}" : "Ai creat {file}",
+ "{user} created {file}" : "{user} a creat {file}",
+ "{file} was created in a public folder" : "{file} a fost creat într-un director public ",
+ "You changed {file}" : "Ai modificat {file}",
+ "{user} changed {file}" : "{user} a modificat {file}",
+ "You deleted {file}" : "Ai șters {file}",
+ "{user} deleted {file}" : "{user} a șters {file}",
+ "You restored {file}" : "Ai restaurat {file}",
+ "{user} restored {file}" : "{user} a restaurat {file}",
+ "You renamed {oldfile} to {newfile}" : "Ai redenumit {oldfile} în {newfile}",
+ "{user} renamed {oldfile} to {newfile}" : "{user} a redenumit {oldfile} în {newfile}",
+ "You moved {oldfile} to {newfile}" : "Ai mutat{oldfile} în {newfile}",
+ "{user} moved {oldfile} to {newfile}" : "{user} a mutat {oldfile} în {newfile}",
+ "A file has been added to or removed from your <strong>favorites</strong>" : "Un fișier a fost adăugat în sau șters din <strong>favorites</strong>",
+ "A file or folder has been <strong>changed</strong> or <strong>renamed</strong>" : "Un fișier sau director a fost <strong>modificat</strong> sau <strong>redenumit</strong>",
+ "A new file or folder has been <strong>created</strong>" : "Un nou fișier sau director a fost <strong>creat</strong>",
+ "A file or folder has been <strong>deleted</strong>" : "Un fișier sau director a fost <strong>șters</strong>",
"A file or folder has been <strong>restored</strong>" : "Un fișier sau dosar a fost <strong>restaurat</strong>",
- "You created %1$s" : "Ai creat %1$s",
- "%2$s created %1$s" : "%2$s a creat %1$s",
- "%1$s was created in a public folder" : "%1$s a fost creat în dosarul public",
- "You changed %1$s" : "Ai schimbat %1$s",
- "%2$s changed %1$s" : "%2$s a schimbat %1$s",
- "You deleted %1$s" : "Ai şters %1$s",
- "%2$s deleted %1$s" : "%2$s a șters %1$s",
- "You restored %1$s" : "Ai restaurat %1$s",
- "%2$s restored %1$s" : "%2$s a restaurat %1$s",
- "Changed by %2$s" : "Modificat de %2$s",
- "Deleted by %2$s" : "Șters de %2$s",
- "Restored by %2$s" : "Restaurat de %2$s",
"Upload (max. %s)" : "Încarcă (max. %s)",
"File handling" : "Manipulare fișiere",
"Maximum upload size" : "Dimensiune maximă admisă la încărcare",
"max. possible: " : "max. posibil:",
"Save" : "Salvează",
+ "With PHP-FPM it might take 5 minutes for changes to be applied." : "Cu PHP-FPM poate dura 5 minute pentru a aplica schimbările..",
"Missing permissions to edit from here." : "Nu ai permisiuni pentru a edita aici.",
+ "%s of %s used" : "%s din %s folosiți",
+ "%s used" : "%s folosiți",
"Settings" : "Setări",
"Show hidden files" : "Arată fișierele ascunse",
"WebDAV" : "WebDAV",
+ "Use this address to <a href=\"%s\" target=\"_blank\" rel=\"noreferrer noopener\">access your Files via WebDAV</a>" : "Folosește această adresă <a href=\"%s\" target=\"_blank\" rel=\"noreferrer noopener\">pentru a accesa Fișierele prin WebDAV</a>",
+ "Cancel upload" : "Anulează încărcarea",
"No files in here" : "Niciun fișier aici",
"Upload some content or sync with your devices!" : "Încarcă ceva conținut sau sincronizează cu dispozitivele tale!",
"No entries found in this folder" : "Niciun element găsit în acest director",
"Select all" : "Selectează tot",
"Upload too large" : "Fișierul încărcat este prea mare",
"The files you are trying to upload exceed the maximum size for file uploads on this server." : "Fișierele pe care încerci să le încarci depășesc limita de încărcare maximă admisă pe acest server.",
- "No favorites" : "Fără favorite",
+ "No favorites yet" : "Nu aveți favorite încă",
"Files and folders you mark as favorite will show up here" : "FIșierele și directoarele pe care le marchezi ca favorite vor apărea aici",
+ "Shared with you" : "Partajat cu tine",
+ "Shared with others" : "Partajat cu alții",
+ "Shared by link" : "Partajat prin link",
+ "Tags" : "Etichete",
+ "Deleted files" : "Fișiere șterse",
"Text file" : "Fișier text",
"New text file.txt" : "New text file.txt",
- "Storage not available" : "Spațiu de stocare indisponibil",
- "Unable to set upload directory." : "Imposibil de a seta directorul pentru încărcare.",
- "Invalid Token" : "Jeton Invalid",
- "No file was uploaded. Unknown error" : "Niciun fișier nu a fost încărcat. Eroare necunoscută",
- "There is no error, the file uploaded with success" : "Nu a apărut nici o eroare, fișierul a fost încărcat cu succes",
- "The uploaded file exceeds the upload_max_filesize directive in php.ini: " : "Fișierul încărcat depășește directiva upload_max_filesize din php.ini:",
- "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" : "Fișierul încărcat depășește directiva MAX_FILE_SIZE specificată în formularul HTML",
- "The uploaded file was only partially uploaded" : "Fișierul a fost încărcat doar parțial",
- "No file was uploaded" : "Nu a fost încărcat niciun fișier",
- "Missing a temporary folder" : "Lipsește un dosar temporar",
- "Failed to write to disk" : "Eroare la scrierea pe disc",
- "Not enough storage available" : "Nu este disponibil suficient spațiu pe disc",
- "The target folder has been moved or deleted." : "Dosarul țintă a fost mutat sau șters.",
- "Upload failed. Could not find uploaded file" : "Încărcare eșuată. Nu se poate găsi fișierul încărcat",
- "Upload failed. Could not get file info." : "Încărcare eșuată. Nu se pot obține informații despre fișier.",
- "Invalid directory." : "Dosar invalid.",
- "Total file size {size1} exceeds upload limit {size2}" : "Mărimea fișierului este {size1} ce depășește limita de încărcare de {size2}",
- "Could not get result from server." : "Nu se poate obține rezultatul de la server.",
- "No entries in this folder match '{filter}'" : "Niciun element din acest director nu se potrivește cu '{filter}'",
- "{newname} already exists" : "{newname} există deja",
- "A file or folder has been <strong>changed</strong>" : "Un nou fișier sau dosar a fost <strong>modificat</strong>"
+ "Uploading..." : "Încărcare",
+ "..." : "...",
+ "{hours}:{minutes}h" : "{hours}:{minutes}h",
+ "{minutes}:{seconds}m" : "{minutes}:{seconds}m",
+ "{seconds}s" : "{seconds}s",
+ "Any moment now..." : "În orice moment...",
+ "Soon..." : "În curând...",
+ "File upload is in progress. Leaving the page now will cancel the upload." : "Fișierul este în curs de încărcare. Părăsirea paginii va întrerupe încărcarea.",
+ "Move" : "Mută",
+ "Folder" : "Dosar",
+ "Upload" : "Încărcă",
+ "A new file or folder has been <strong>deleted</strong>" : "Un nou fișier sau director a fost <strong>șters</strong>",
+ "A new file or folder has been <strong>restored</strong>" : "Un fișier sau director a fost <strong>restaurat</strong>",
+ "Use this address to <a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">access your Files via WebDAV</a>" : "Folosește această adresă <a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">pentru a accesa Fișierele prin WebDAV</a>",
+ "No favorites" : "Fără favorite"
},
"nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));");
diff --git a/apps/files/l10n/ro.json b/apps/files/l10n/ro.json
index 45c55d2becc..8d41bb52adc 100644
--- a/apps/files/l10n/ro.json
+++ b/apps/files/l10n/ro.json
@@ -1,8 +1,10 @@
{ "translations": {
+ "Storage is temporarily not available" : "Spațiu de stocare este indisponibil temporar",
"Storage invalid" : "Spațiu de stocare invalid",
"Unknown error" : "Eroare necunoscută",
- "Files" : "Fișiere",
- "All files" : "Toate fișierele.",
+ "All files" : "Toate fișierele",
+ "Recent" : "Recente",
+ "File could not be found" : "Fișierul nu a fost găsit",
"Home" : "Acasă",
"Close" : "Închide",
"Favorites" : "Favorite",
@@ -10,21 +12,21 @@
"Upload cancelled." : "Încărcare anulată.",
"Unable to upload {filename} as it is a directory or has 0 bytes" : "Nu se poate încărca {filename} deoarece este un director sau are mărimea de 0 octeți",
"Not enough free space, you are uploading {size1} but only {size2} is left" : "Spațiu liber insuficient, încărcați {size1} însă doar {size2} disponibil rămas",
- "Uploading..." : "Încărcare",
- "..." : "...",
- "{hours}:{minutes}h" : "{hours}:{minutes}h",
- "{minutes}:{seconds}m" : "{minutes}:{seconds}m",
- "{seconds} second{plural_s} left" : "{seconds} secunde{plural_s} rămase",
- "{seconds}s" : "{seconds}s",
- "Any moment now..." : "În orice moment...",
- "Soon..." : "În curând...",
- "File upload is in progress. Leaving the page now will cancel the upload." : "Fișierul este în curs de încărcare. Părăsirea paginii va întrerupe încărcarea.",
+ "Target folder \"{dir}\" does not exist any more" : "Directorul \"{dir}\" nu mai există",
+ "Not enough free space" : "Spațiu insuficient",
+ "Uploading …" : "Încărcare...",
+ "…" : "...",
+ "{loadedSize} of {totalSize} ({bitrate})" : "{loadedSize} din {totalSize} ({bitrate})",
+ "Target folder does not exist any more" : "Directorul destinație nu mai există",
"Actions" : "Acțiuni",
"Download" : "Descarcă",
"Rename" : "Redenumește",
+ "Move or copy" : "Mută sau copiază",
+ "Target folder" : "Directorul destinație",
"Delete" : "Șterge",
"Disconnect storage" : "Deconectează stocarea",
"Unshare" : "Nu mai partaja",
+ "Files" : "Fișiere",
"Details" : "Detalii",
"Select" : "Alege",
"Pending" : "În așteptare",
@@ -33,6 +35,8 @@
"This directory is unavailable, please check the logs or contact the administrator" : "Acest director nu este disponibil, te rugăm verifică logurile sau contactează un administrator",
"Could not move \"{file}\", target exists" : "Nu s-a putut muta fișierul \"{file}\", există deja un altul cu același nume în directorul destinație",
"Could not move \"{file}\"" : "Nu s-a putut muta fișierul \"{file}\"",
+ "Could not copy \"{file}\"" : "Nu s-a putut copia \"{file}\"",
+ "Copied {origin} inside {destination}" : "S-a copiat {origin} în {destination}",
"{newName} already exists" : "{newName} există deja",
"Could not rename \"{fileName}\", it does not exist any more" : "Nu s-a putut redenumi \"{fileName}\", fișierul nu mai există",
"The name \"{targetName}\" is already used in the folder \"{dir}\". Please choose a different name." : "Numele \"{targetName}\" este deja folosit în directorul \"{dir}\". Alege un nume diferit.",
@@ -50,73 +54,98 @@
"You don’t have permission to upload or create files here" : "Nu aveți permisiunea de a încărca sau crea fișiere aici",
"_Uploading %n file_::_Uploading %n files_" : ["Se încarcă %n fișier.","Se încarcă %n fișiere.","Se încarcă %n fișiere."],
"New" : "Nou",
+ "{used} of {quota} used" : "{used} din {quota} folosiți",
+ "{used} used" : "{used} folosiți",
"\"{name}\" is an invalid file name." : "\"{name}\" este un nume de fișier nevalid.",
"File name cannot be empty." : "Numele fișierului nu poate rămâne gol.",
+ "\"{name}\" is not an allowed filetype" : "\"{name}\" ",
+ "Storage of {owner} is full, files can not be updated or synced anymore!" : "Spațiul de stocare pentru {owner} este plin, fișierele nu mai pot fi incărcate sau sincronizate!",
"Your storage is full, files can not be updated or synced anymore!" : "Spațiul de stocare este plin, fișierele nu mai pot fi actualizate sau sincronizate!",
+ "Storage of {owner} is almost full ({usedSpacePercent}%)" : "Spațiul de stocare pentru {owner} este aproape plin ({usedSpacePercent}%)",
"Your storage is almost full ({usedSpacePercent}%)" : "Spațiul de stocare este aproape plin ({usedSpacePercent}%)",
+ "Copied!" : "S-a copiat!",
+ "Copy direct link (only works for users who have access to this file/folder)" : "Copiază link direct (funcționeză numai pentru utilizatorii care au acces la acest fișier/director)",
"Path" : "Cale",
"_%n byte_::_%n bytes_" : ["%n octet","%n octeți","%n octeți"],
"Favorited" : "Adăugate la favorite",
"Favorite" : "Favorit",
- "Local link" : "Legătură locală",
- "Folder" : "Dosar",
"New folder" : "Un nou dosar",
- "Upload" : "Încărcă",
+ "Upload file" : "Încarcă fișier",
+ "Remove from favorites" : "Șterge din favorite",
+ "Add to favorites" : "Adaugă la favorite",
"An error occurred while trying to update the tags" : "A apărut o eroare în timpul actualizării etichetelor",
- "A new file or folder has been <strong>created</strong>" : "Un nou fișier sau dosar a fost <strong>creat</strong>",
- "A file or folder has been <strong>deleted</strong>" : "Un nou fișier sau dosar a fost <strong>șters</strong>",
+ "Added to favorites" : "Adaugat la favorite",
+ "Removed from favorites" : "Șters din favorite",
+ "You added {file} to your favorites" : "Ai adaugat {file} în favorite",
+ "You removed {file} from your favorites" : "Ai șters {file} din favorite",
+ "Created by {user}" : "Creat de {user}",
+ "Changed by {user}" : "Modificat de {user}",
+ "Deleted by {user}" : "Șters de {user}",
+ "Restored by {user}" : "Restaurat de {user}",
+ "Renamed by {user}" : "Redenumit de {user}",
+ "Moved by {user}" : "Mutat de {user}",
+ "\"remote user\"" : "\"utilizator la distanță\"",
+ "You created {file}" : "Ai creat {file}",
+ "{user} created {file}" : "{user} a creat {file}",
+ "{file} was created in a public folder" : "{file} a fost creat într-un director public ",
+ "You changed {file}" : "Ai modificat {file}",
+ "{user} changed {file}" : "{user} a modificat {file}",
+ "You deleted {file}" : "Ai șters {file}",
+ "{user} deleted {file}" : "{user} a șters {file}",
+ "You restored {file}" : "Ai restaurat {file}",
+ "{user} restored {file}" : "{user} a restaurat {file}",
+ "You renamed {oldfile} to {newfile}" : "Ai redenumit {oldfile} în {newfile}",
+ "{user} renamed {oldfile} to {newfile}" : "{user} a redenumit {oldfile} în {newfile}",
+ "You moved {oldfile} to {newfile}" : "Ai mutat{oldfile} în {newfile}",
+ "{user} moved {oldfile} to {newfile}" : "{user} a mutat {oldfile} în {newfile}",
+ "A file has been added to or removed from your <strong>favorites</strong>" : "Un fișier a fost adăugat în sau șters din <strong>favorites</strong>",
+ "A file or folder has been <strong>changed</strong> or <strong>renamed</strong>" : "Un fișier sau director a fost <strong>modificat</strong> sau <strong>redenumit</strong>",
+ "A new file or folder has been <strong>created</strong>" : "Un nou fișier sau director a fost <strong>creat</strong>",
+ "A file or folder has been <strong>deleted</strong>" : "Un fișier sau director a fost <strong>șters</strong>",
"A file or folder has been <strong>restored</strong>" : "Un fișier sau dosar a fost <strong>restaurat</strong>",
- "You created %1$s" : "Ai creat %1$s",
- "%2$s created %1$s" : "%2$s a creat %1$s",
- "%1$s was created in a public folder" : "%1$s a fost creat în dosarul public",
- "You changed %1$s" : "Ai schimbat %1$s",
- "%2$s changed %1$s" : "%2$s a schimbat %1$s",
- "You deleted %1$s" : "Ai şters %1$s",
- "%2$s deleted %1$s" : "%2$s a șters %1$s",
- "You restored %1$s" : "Ai restaurat %1$s",
- "%2$s restored %1$s" : "%2$s a restaurat %1$s",
- "Changed by %2$s" : "Modificat de %2$s",
- "Deleted by %2$s" : "Șters de %2$s",
- "Restored by %2$s" : "Restaurat de %2$s",
"Upload (max. %s)" : "Încarcă (max. %s)",
"File handling" : "Manipulare fișiere",
"Maximum upload size" : "Dimensiune maximă admisă la încărcare",
"max. possible: " : "max. posibil:",
"Save" : "Salvează",
+ "With PHP-FPM it might take 5 minutes for changes to be applied." : "Cu PHP-FPM poate dura 5 minute pentru a aplica schimbările..",
"Missing permissions to edit from here." : "Nu ai permisiuni pentru a edita aici.",
+ "%s of %s used" : "%s din %s folosiți",
+ "%s used" : "%s folosiți",
"Settings" : "Setări",
"Show hidden files" : "Arată fișierele ascunse",
"WebDAV" : "WebDAV",
+ "Use this address to <a href=\"%s\" target=\"_blank\" rel=\"noreferrer noopener\">access your Files via WebDAV</a>" : "Folosește această adresă <a href=\"%s\" target=\"_blank\" rel=\"noreferrer noopener\">pentru a accesa Fișierele prin WebDAV</a>",
+ "Cancel upload" : "Anulează încărcarea",
"No files in here" : "Niciun fișier aici",
"Upload some content or sync with your devices!" : "Încarcă ceva conținut sau sincronizează cu dispozitivele tale!",
"No entries found in this folder" : "Niciun element găsit în acest director",
"Select all" : "Selectează tot",
"Upload too large" : "Fișierul încărcat este prea mare",
"The files you are trying to upload exceed the maximum size for file uploads on this server." : "Fișierele pe care încerci să le încarci depășesc limita de încărcare maximă admisă pe acest server.",
- "No favorites" : "Fără favorite",
+ "No favorites yet" : "Nu aveți favorite încă",
"Files and folders you mark as favorite will show up here" : "FIșierele și directoarele pe care le marchezi ca favorite vor apărea aici",
+ "Shared with you" : "Partajat cu tine",
+ "Shared with others" : "Partajat cu alții",
+ "Shared by link" : "Partajat prin link",
+ "Tags" : "Etichete",
+ "Deleted files" : "Fișiere șterse",
"Text file" : "Fișier text",
"New text file.txt" : "New text file.txt",
- "Storage not available" : "Spațiu de stocare indisponibil",
- "Unable to set upload directory." : "Imposibil de a seta directorul pentru încărcare.",
- "Invalid Token" : "Jeton Invalid",
- "No file was uploaded. Unknown error" : "Niciun fișier nu a fost încărcat. Eroare necunoscută",
- "There is no error, the file uploaded with success" : "Nu a apărut nici o eroare, fișierul a fost încărcat cu succes",
- "The uploaded file exceeds the upload_max_filesize directive in php.ini: " : "Fișierul încărcat depășește directiva upload_max_filesize din php.ini:",
- "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" : "Fișierul încărcat depășește directiva MAX_FILE_SIZE specificată în formularul HTML",
- "The uploaded file was only partially uploaded" : "Fișierul a fost încărcat doar parțial",
- "No file was uploaded" : "Nu a fost încărcat niciun fișier",
- "Missing a temporary folder" : "Lipsește un dosar temporar",
- "Failed to write to disk" : "Eroare la scrierea pe disc",
- "Not enough storage available" : "Nu este disponibil suficient spațiu pe disc",
- "The target folder has been moved or deleted." : "Dosarul țintă a fost mutat sau șters.",
- "Upload failed. Could not find uploaded file" : "Încărcare eșuată. Nu se poate găsi fișierul încărcat",
- "Upload failed. Could not get file info." : "Încărcare eșuată. Nu se pot obține informații despre fișier.",
- "Invalid directory." : "Dosar invalid.",
- "Total file size {size1} exceeds upload limit {size2}" : "Mărimea fișierului este {size1} ce depășește limita de încărcare de {size2}",
- "Could not get result from server." : "Nu se poate obține rezultatul de la server.",
- "No entries in this folder match '{filter}'" : "Niciun element din acest director nu se potrivește cu '{filter}'",
- "{newname} already exists" : "{newname} există deja",
- "A file or folder has been <strong>changed</strong>" : "Un nou fișier sau dosar a fost <strong>modificat</strong>"
+ "Uploading..." : "Încărcare",
+ "..." : "...",
+ "{hours}:{minutes}h" : "{hours}:{minutes}h",
+ "{minutes}:{seconds}m" : "{minutes}:{seconds}m",
+ "{seconds}s" : "{seconds}s",
+ "Any moment now..." : "În orice moment...",
+ "Soon..." : "În curând...",
+ "File upload is in progress. Leaving the page now will cancel the upload." : "Fișierul este în curs de încărcare. Părăsirea paginii va întrerupe încărcarea.",
+ "Move" : "Mută",
+ "Folder" : "Dosar",
+ "Upload" : "Încărcă",
+ "A new file or folder has been <strong>deleted</strong>" : "Un nou fișier sau director a fost <strong>șters</strong>",
+ "A new file or folder has been <strong>restored</strong>" : "Un fișier sau director a fost <strong>restaurat</strong>",
+ "Use this address to <a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">access your Files via WebDAV</a>" : "Folosește această adresă <a href=\"%s\" target=\"_blank\" rel=\"noreferrer\">pentru a accesa Fișierele prin WebDAV</a>",
+ "No favorites" : "Fără favorite"
},"pluralForm" :"nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));"
} \ No newline at end of file
diff --git a/apps/files/l10n/ru.js b/apps/files/l10n/ru.js
index b6222725a72..9878e2f78dd 100644
--- a/apps/files/l10n/ru.js
+++ b/apps/files/l10n/ru.js
@@ -62,8 +62,11 @@ OC.L10N.register(
"You don’t have permission to upload or create files here" : "У вас нет разрешений на создание или загрузку файлов в эту папку.",
"_Uploading %n file_::_Uploading %n files_" : ["Выгружа%nется файл","Выгружаются %n файла","Выгружаются %n файлов","Загружаются %n файлов"],
"New" : "Новый",
+ "{used} of {quota} used" : "использовано {used} из {quota}",
+ "{used} used" : "использовано {used}",
"\"{name}\" is an invalid file name." : "«{name}» — недопустимое имя файла.",
"File name cannot be empty." : "Имя файла не может быть пустым.",
+ "\"/\" is not allowed inside a file name." : "Символ «/» недопустим в имени файла.",
"\"{name}\" is not an allowed filetype" : "«{name}» - недопустимый тип файла.",
"Storage of {owner} is full, files can not be updated or synced anymore!" : "Хранилище {owner} переполнено, файлы больше не могут быть обновлены или синхронизированы!",
"Your storage is full, files can not be updated or synced anymore!" : "Ваше хранилище переполнено, файлы больше не могут быть обновлены или синхронизированы!",
diff --git a/apps/files/l10n/ru.json b/apps/files/l10n/ru.json
index e989cdd3183..be07497fda4 100644
--- a/apps/files/l10n/ru.json
+++ b/apps/files/l10n/ru.json
@@ -60,8 +60,11 @@
"You don’t have permission to upload or create files here" : "У вас нет разрешений на создание или загрузку файлов в эту папку.",
"_Uploading %n file_::_Uploading %n files_" : ["Выгружа%nется файл","Выгружаются %n файла","Выгружаются %n файлов","Загружаются %n файлов"],
"New" : "Новый",
+ "{used} of {quota} used" : "использовано {used} из {quota}",
+ "{used} used" : "использовано {used}",
"\"{name}\" is an invalid file name." : "«{name}» — недопустимое имя файла.",
"File name cannot be empty." : "Имя файла не может быть пустым.",
+ "\"/\" is not allowed inside a file name." : "Символ «/» недопустим в имени файла.",
"\"{name}\" is not an allowed filetype" : "«{name}» - недопустимый тип файла.",
"Storage of {owner} is full, files can not be updated or synced anymore!" : "Хранилище {owner} переполнено, файлы больше не могут быть обновлены или синхронизированы!",
"Your storage is full, files can not be updated or synced anymore!" : "Ваше хранилище переполнено, файлы больше не могут быть обновлены или синхронизированы!",
diff --git a/apps/files/l10n/tr.js b/apps/files/l10n/tr.js
index 6d68c8889bc..e1252d20b18 100644
--- a/apps/files/l10n/tr.js
+++ b/apps/files/l10n/tr.js
@@ -62,8 +62,11 @@ OC.L10N.register(
"You don’t have permission to upload or create files here" : "Buraya dosya yükleme veya ekleme izniniz yok",
"_Uploading %n file_::_Uploading %n files_" : ["%n dosya yükleniyor","%n dosya yükleniyor"],
"New" : "Yeni",
+ "{used} of {quota} used" : "{used} / {quota} kullanılmış",
+ "{used} used" : "{used} kullanılmış",
"\"{name}\" is an invalid file name." : "\"{name}\" geçersiz bir dosya adı.",
"File name cannot be empty." : "Dosya adı boş olamaz.",
+ "\"/\" is not allowed inside a file name." : "Dosya adında \"/\" kullanılamaz.",
"\"{name}\" is not an allowed filetype" : "\"{name}\" dosya türüne izin verilmiyor",
"Storage of {owner} is full, files can not be updated or synced anymore!" : "{owner} için boş depolama alanı kalmadı. Artık dosyalar güncellenmeyecek ya da eşitlenmeyecek!",
"Your storage is full, files can not be updated or synced anymore!" : "Boş depolama alanınız kalmadı. Artık dosyalar güncellenmeyecek ya da eşitlenmeyecek!",
diff --git a/apps/files/l10n/tr.json b/apps/files/l10n/tr.json
index cde68e5b35b..ca8bfbf8028 100644
--- a/apps/files/l10n/tr.json
+++ b/apps/files/l10n/tr.json
@@ -60,8 +60,11 @@
"You don’t have permission to upload or create files here" : "Buraya dosya yükleme veya ekleme izniniz yok",
"_Uploading %n file_::_Uploading %n files_" : ["%n dosya yükleniyor","%n dosya yükleniyor"],
"New" : "Yeni",
+ "{used} of {quota} used" : "{used} / {quota} kullanılmış",
+ "{used} used" : "{used} kullanılmış",
"\"{name}\" is an invalid file name." : "\"{name}\" geçersiz bir dosya adı.",
"File name cannot be empty." : "Dosya adı boş olamaz.",
+ "\"/\" is not allowed inside a file name." : "Dosya adında \"/\" kullanılamaz.",
"\"{name}\" is not an allowed filetype" : "\"{name}\" dosya türüne izin verilmiyor",
"Storage of {owner} is full, files can not be updated or synced anymore!" : "{owner} için boş depolama alanı kalmadı. Artık dosyalar güncellenmeyecek ya da eşitlenmeyecek!",
"Your storage is full, files can not be updated or synced anymore!" : "Boş depolama alanınız kalmadı. Artık dosyalar güncellenmeyecek ya da eşitlenmeyecek!",
diff --git a/apps/files/lib/AppInfo/Application.php b/apps/files/lib/AppInfo/Application.php
index 7042af10ca2..e55d1c549a5 100644
--- a/apps/files/lib/AppInfo/Application.php
+++ b/apps/files/lib/AppInfo/Application.php
@@ -81,13 +81,14 @@ class Application extends App {
$container->registerService('Tagger', function(IContainer $c) {
return $c->query('ServerContainer')->getTagManager()->load('files');
});
- $container->registerService('TagService', function(IContainer $c) {
+ $container->registerService('TagService', function(IContainer $c) use ($server) {
$homeFolder = $c->query('ServerContainer')->getUserFolder();
return new TagService(
$c->query('ServerContainer')->getUserSession(),
$c->query('ServerContainer')->getActivityManager(),
$c->query('Tagger'),
- $homeFolder
+ $homeFolder,
+ $server->getEventDispatcher()
);
});
diff --git a/apps/files/lib/Service/TagService.php b/apps/files/lib/Service/TagService.php
index d812b16c30e..7437f0c31ad 100644
--- a/apps/files/lib/Service/TagService.php
+++ b/apps/files/lib/Service/TagService.php
@@ -31,6 +31,8 @@ use OCP\Files\Folder;
use OCP\ITags;
use OCP\IUser;
use OCP\IUserSession;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use Symfony\Component\EventDispatcher\GenericEvent;
/**
* Service class to manage tags on files.
@@ -45,23 +47,28 @@ class TagService {
private $tagger;
/** @var Folder */
private $homeFolder;
+ /** @var EventDispatcherInterface */
+ private $dispatcher;
/**
* @param IUserSession $userSession
* @param IManager $activityManager
* @param ITags $tagger
* @param Folder $homeFolder
+ * @param EventDispatcherInterface $dispatcher
*/
public function __construct(
IUserSession $userSession,
IManager $activityManager,
ITags $tagger,
- Folder $homeFolder
+ Folder $homeFolder,
+ EventDispatcherInterface $dispatcher
) {
$this->userSession = $userSession;
$this->activityManager = $activityManager;
$this->tagger = $tagger;
$this->homeFolder = $homeFolder;
+ $this->dispatcher = $dispatcher;
}
/**
@@ -114,6 +121,13 @@ class TagService {
return;
}
+ $eventName = $addToFavorite ? 'addFavorite' : 'removeFavorite';
+ $this->dispatcher->dispatch(self::class . '::' . $eventName, new GenericEvent(null, [
+ 'userId' => $user->getUID(),
+ 'fileId' => $fileId,
+ 'path' => $path,
+ ]));
+
$event = $this->activityManager->generateEvent();
try {
$event->setApp('files')
diff --git a/apps/files/tests/Service/TagServiceTest.php b/apps/files/tests/Service/TagServiceTest.php
index 1c4ac2328ec..4e2aeb84246 100644
--- a/apps/files/tests/Service/TagServiceTest.php
+++ b/apps/files/tests/Service/TagServiceTest.php
@@ -28,6 +28,7 @@ use OC\Tags;
use OCA\Files\Service\TagService;
use OCP\Activity\IManager;
use OCP\IUserSession;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
/**
* Class TagServiceTest
@@ -54,6 +55,9 @@ class TagServiceTest extends \Test\TestCase {
*/
private $root;
+ /** @var EventDispatcherInterface|\PHPUnit_Framework_MockObject_MockObject */
+ private $dispatcher;
+
/**
* @var \OCA\Files\Service\TagService|\PHPUnit_Framework_MockObject_MockObject
*/
@@ -66,7 +70,7 @@ class TagServiceTest extends \Test\TestCase {
protected function setUp() {
parent::setUp();
- $this->user = $this->getUniqueID('user');
+ $this->user = static::getUniqueID('user');
$this->activityManager = $this->createMock(IManager::class);
\OC::$server->getUserManager()->createUser($this->user, 'test');
\OC_User::setUserId($this->user);
@@ -83,6 +87,7 @@ class TagServiceTest extends \Test\TestCase {
->will($this->returnValue($user));
$this->root = \OC::$server->getUserFolder();
+ $this->dispatcher = $this->createMock(EventDispatcherInterface::class);
$this->tagger = \OC::$server->getTagManager()->load('files');
$this->tagService = $this->getTagService(['addActivity']);
@@ -99,6 +104,7 @@ class TagServiceTest extends \Test\TestCase {
$this->activityManager,
$this->tagger,
$this->root,
+ $this->dispatcher,
])
->setMethods($methods)
->getMock();
diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js
index fc5a6c18f95..08da15b8a88 100644
--- a/apps/files/tests/js/filelistSpec.js
+++ b/apps/files/tests/js/filelistSpec.js
@@ -612,6 +612,12 @@ describe('OCA.Files.FileList tests', function() {
beforeEach(function() {
deferredRename = $.Deferred();
renameStub = sinon.stub(filesClient, 'move').returns(deferredRename.promise());
+
+ for (var i = 0; i < testFiles.length; i++) {
+ var file = testFiles[i];
+ file.path = '/some/subdir';
+ fileList.add(file, {silent: true});
+ }
});
afterEach(function() {
renameStub.restore();
@@ -619,9 +625,6 @@ describe('OCA.Files.FileList tests', function() {
function doCancelRename() {
var $input;
- for (var i = 0; i < testFiles.length; i++) {
- fileList.add(testFiles[i]);
- }
// trigger rename prompt
fileList.rename('One.txt');
@@ -636,12 +639,6 @@ describe('OCA.Files.FileList tests', function() {
function doRename() {
var $input;
- for (var i = 0; i < testFiles.length; i++) {
- var file = testFiles[i];
- file.path = '/some/subdir';
- fileList.add(file, {silent: true});
- }
-
// trigger rename prompt
fileList.rename('One.txt');
$input = fileList.$fileList.find('input.filename');
@@ -677,6 +674,36 @@ describe('OCA.Files.FileList tests', function() {
expect(notificationStub.calledOnce).toEqual(true);
});
+ it('Shows renamed file details if rename ajax call suceeded', function() {
+ fileList.showDetailsView('One.txt');
+
+ expect($('#app-sidebar').hasClass('disappear')).toEqual(false);
+ expect(fileList._detailsView.getFileInfo().get('id')).toEqual(1);
+ expect(fileList._detailsView.getFileInfo().get('name')).toEqual('One.txt');
+
+ doRename();
+
+ deferredRename.resolve(201);
+
+ expect($('#app-sidebar').hasClass('disappear')).toEqual(false);
+ expect(fileList._detailsView.getFileInfo().get('id')).toEqual(1);
+ expect(fileList._detailsView.getFileInfo().get('name')).toEqual('Tu_after_three.txt');
+ });
+ it('Shows again file details if rename ajax call failed', function() {
+ fileList.showDetailsView('One.txt');
+
+ expect($('#app-sidebar').hasClass('disappear')).toEqual(false);
+ expect(fileList._detailsView.getFileInfo().get('id')).toEqual(1);
+ expect(fileList._detailsView.getFileInfo().get('name')).toEqual('One.txt');
+
+ doRename();
+
+ deferredRename.reject(403);
+
+ expect($('#app-sidebar').hasClass('disappear')).toEqual(false);
+ expect(fileList._detailsView.getFileInfo().get('id')).toEqual(1);
+ expect(fileList._detailsView.getFileInfo().get('name')).toEqual('One.txt');
+ });
it('Correctly updates file link after rename', function() {
var $tr;
doRename();
@@ -731,10 +758,6 @@ describe('OCA.Files.FileList tests', function() {
it('Validates the file name', function() {
var $input, $tr;
- for (var i = 0; i < testFiles.length; i++) {
- fileList.add(testFiles[i], {silent: true});
- }
-
$tr = fileList.findFileEl('One.txt');
expect($tr.find('a.name').css('display')).not.toEqual('none');
diff --git a/apps/files/tests/js/mainfileinfodetailviewSpec.js b/apps/files/tests/js/mainfileinfodetailviewSpec.js
index faf0faa8d8f..0201429a472 100644
--- a/apps/files/tests/js/mainfileinfodetailviewSpec.js
+++ b/apps/files/tests/js/mainfileinfodetailviewSpec.js
@@ -68,6 +68,12 @@ describe('OCA.Files.MainFileInfoDetailView tests', function() {
.toEqual(OC.getProtocol() + '://' + OC.getHost() + OC.generateUrl('/f/5'));
});
it('displays favorite icon', function() {
+ fileActions.registerAction({
+ name: 'Favorite',
+ mime: 'all',
+ permissions: OC.PERMISSION_NONE
+ });
+
testFileInfo.set('tags', [OC.TAG_FAVORITE]);
view.setFileInfo(testFileInfo);
expect(view.$el.find('.action-favorite > span').hasClass('icon-starred')).toEqual(true);
@@ -78,6 +84,15 @@ describe('OCA.Files.MainFileInfoDetailView tests', function() {
expect(view.$el.find('.action-favorite > span').hasClass('icon-starred')).toEqual(false);
expect(view.$el.find('.action-favorite > span').hasClass('icon-star')).toEqual(true);
});
+ it('does not display favorite icon if favorite action is not available', function() {
+ testFileInfo.set('tags', [OC.TAG_FAVORITE]);
+ view.setFileInfo(testFileInfo);
+ expect(view.$el.find('.action-favorite').length).toEqual(0);
+
+ testFileInfo.set('tags', []);
+ view.setFileInfo(testFileInfo);
+ expect(view.$el.find('.action-favorite').length).toEqual(0);
+ });
it('displays mime icon', function() {
// File
var lazyLoadPreviewStub = sinon.stub(fileList, 'lazyLoadPreview');
@@ -183,6 +198,13 @@ describe('OCA.Files.MainFileInfoDetailView tests', function() {
expect(view.$el.find('.fileName h3').attr('title')).toEqual('hello.txt');
});
it('rerenders when changes are made on the model', function() {
+ // Show the "Favorite" icon
+ fileActions.registerAction({
+ name: 'Favorite',
+ mime: 'all',
+ permissions: OC.PERMISSION_NONE
+ });
+
view.setFileInfo(testFileInfo);
testFileInfo.set('tags', [OC.TAG_FAVORITE]);
@@ -196,6 +218,13 @@ describe('OCA.Files.MainFileInfoDetailView tests', function() {
expect(view.$el.find('.action-favorite > span').hasClass('icon-star')).toEqual(true);
});
it('unbinds change listener from model', function() {
+ // Show the "Favorite" icon
+ fileActions.registerAction({
+ name: 'Favorite',
+ mime: 'all',
+ permissions: OC.PERMISSION_NONE
+ });
+
view.setFileInfo(testFileInfo);
view.setFileInfo(new OCA.Files.FileInfoModel({
id: 999,
diff --git a/apps/files_external/l10n/de.js b/apps/files_external/l10n/de.js
index 40126676f0a..eb8fbdf0d8c 100644
--- a/apps/files_external/l10n/de.js
+++ b/apps/files_external/l10n/de.js
@@ -75,6 +75,7 @@ OC.L10N.register(
"Region" : "Region",
"Enable SSL" : "SSL aktivieren",
"Enable Path Style" : "Pfad-Stil aktivieren",
+ "Legacy (v2) authentication" : "Legacy-Authentifizierung (V2)",
"WebDAV" : "WebDAV",
"URL" : "URL",
"Remote subfolder" : "Entfernter Unterordner",
diff --git a/apps/files_external/l10n/de.json b/apps/files_external/l10n/de.json
index c93ba785568..53fd2e422fa 100644
--- a/apps/files_external/l10n/de.json
+++ b/apps/files_external/l10n/de.json
@@ -73,6 +73,7 @@
"Region" : "Region",
"Enable SSL" : "SSL aktivieren",
"Enable Path Style" : "Pfad-Stil aktivieren",
+ "Legacy (v2) authentication" : "Legacy-Authentifizierung (V2)",
"WebDAV" : "WebDAV",
"URL" : "URL",
"Remote subfolder" : "Entfernter Unterordner",
diff --git a/apps/files_external/l10n/de_DE.js b/apps/files_external/l10n/de_DE.js
index 6851466d426..5f01b5179de 100644
--- a/apps/files_external/l10n/de_DE.js
+++ b/apps/files_external/l10n/de_DE.js
@@ -75,6 +75,7 @@ OC.L10N.register(
"Region" : "Region",
"Enable SSL" : "SSL aktivieren",
"Enable Path Style" : "Pfadstil aktivieren",
+ "Legacy (v2) authentication" : "Legacy-Authentifizierung (V2)",
"WebDAV" : "WebDAV",
"URL" : "Adresse",
"Remote subfolder" : "Entfernter Unterordner",
diff --git a/apps/files_external/l10n/de_DE.json b/apps/files_external/l10n/de_DE.json
index 22e359c0378..e5f25c97a1f 100644
--- a/apps/files_external/l10n/de_DE.json
+++ b/apps/files_external/l10n/de_DE.json
@@ -73,6 +73,7 @@
"Region" : "Region",
"Enable SSL" : "SSL aktivieren",
"Enable Path Style" : "Pfadstil aktivieren",
+ "Legacy (v2) authentication" : "Legacy-Authentifizierung (V2)",
"WebDAV" : "WebDAV",
"URL" : "Adresse",
"Remote subfolder" : "Entfernter Unterordner",
diff --git a/apps/files_external/l10n/en_GB.js b/apps/files_external/l10n/en_GB.js
index 131c9af43ad..45fe58c0b36 100644
--- a/apps/files_external/l10n/en_GB.js
+++ b/apps/files_external/l10n/en_GB.js
@@ -75,6 +75,7 @@ OC.L10N.register(
"Region" : "Region",
"Enable SSL" : "Enable SSL",
"Enable Path Style" : "Enable Path Style",
+ "Legacy (v2) authentication" : "Legacy (v2) authentication",
"WebDAV" : "WebDAV",
"URL" : "URL",
"Remote subfolder" : "Remote subfolder",
diff --git a/apps/files_external/l10n/en_GB.json b/apps/files_external/l10n/en_GB.json
index 5c60ec6e344..f7ac7290e7a 100644
--- a/apps/files_external/l10n/en_GB.json
+++ b/apps/files_external/l10n/en_GB.json
@@ -73,6 +73,7 @@
"Region" : "Region",
"Enable SSL" : "Enable SSL",
"Enable Path Style" : "Enable Path Style",
+ "Legacy (v2) authentication" : "Legacy (v2) authentication",
"WebDAV" : "WebDAV",
"URL" : "URL",
"Remote subfolder" : "Remote subfolder",
diff --git a/apps/files_external/l10n/es.js b/apps/files_external/l10n/es.js
index b980588862e..7bfed57158d 100644
--- a/apps/files_external/l10n/es.js
+++ b/apps/files_external/l10n/es.js
@@ -75,6 +75,7 @@ OC.L10N.register(
"Region" : "Región",
"Enable SSL" : "Habilitar SSL",
"Enable Path Style" : "Habilitar Estilo de Ruta",
+ "Legacy (v2) authentication" : "Autenticación heredada (v2)",
"WebDAV" : "WebDAV",
"URL" : "URL",
"Remote subfolder" : "Subcarpeta remota",
diff --git a/apps/files_external/l10n/es.json b/apps/files_external/l10n/es.json
index 0c6ab09d88d..79c81accd58 100644
--- a/apps/files_external/l10n/es.json
+++ b/apps/files_external/l10n/es.json
@@ -73,6 +73,7 @@
"Region" : "Región",
"Enable SSL" : "Habilitar SSL",
"Enable Path Style" : "Habilitar Estilo de Ruta",
+ "Legacy (v2) authentication" : "Autenticación heredada (v2)",
"WebDAV" : "WebDAV",
"URL" : "URL",
"Remote subfolder" : "Subcarpeta remota",
diff --git a/apps/files_external/l10n/hu.js b/apps/files_external/l10n/hu.js
index 81eddd893a0..8dcecbaeffb 100644
--- a/apps/files_external/l10n/hu.js
+++ b/apps/files_external/l10n/hu.js
@@ -75,6 +75,7 @@ OC.L10N.register(
"Region" : "Megye",
"Enable SSL" : "SSL engedélyezése",
"Enable Path Style" : "Útvonal stílus engedélyezés",
+ "Legacy (v2) authentication" : "Elavult (v2) authetikáció",
"WebDAV" : "WebDAV",
"URL" : "URL",
"Remote subfolder" : "Távoli almappa",
diff --git a/apps/files_external/l10n/hu.json b/apps/files_external/l10n/hu.json
index f05459b00b9..fc51260454c 100644
--- a/apps/files_external/l10n/hu.json
+++ b/apps/files_external/l10n/hu.json
@@ -73,6 +73,7 @@
"Region" : "Megye",
"Enable SSL" : "SSL engedélyezése",
"Enable Path Style" : "Útvonal stílus engedélyezés",
+ "Legacy (v2) authentication" : "Elavult (v2) authetikáció",
"WebDAV" : "WebDAV",
"URL" : "URL",
"Remote subfolder" : "Távoli almappa",
diff --git a/apps/files_external/l10n/it.js b/apps/files_external/l10n/it.js
index e19f6a657db..4bd2908b431 100644
--- a/apps/files_external/l10n/it.js
+++ b/apps/files_external/l10n/it.js
@@ -75,6 +75,7 @@ OC.L10N.register(
"Region" : "Regione",
"Enable SSL" : "Abilita SSL",
"Enable Path Style" : "Abilita stile percorsi",
+ "Legacy (v2) authentication" : "Autenticazione tradizionale (v2)",
"WebDAV" : "WebDAV",
"URL" : "URL",
"Remote subfolder" : "Sottocartella remota",
diff --git a/apps/files_external/l10n/it.json b/apps/files_external/l10n/it.json
index ecb8d2082e6..36d4b296199 100644
--- a/apps/files_external/l10n/it.json
+++ b/apps/files_external/l10n/it.json
@@ -73,6 +73,7 @@
"Region" : "Regione",
"Enable SSL" : "Abilita SSL",
"Enable Path Style" : "Abilita stile percorsi",
+ "Legacy (v2) authentication" : "Autenticazione tradizionale (v2)",
"WebDAV" : "WebDAV",
"URL" : "URL",
"Remote subfolder" : "Sottocartella remota",
diff --git a/apps/files_external/l10n/ka_GE.js b/apps/files_external/l10n/ka_GE.js
index ff2f4e9afab..782242ae5dc 100644
--- a/apps/files_external/l10n/ka_GE.js
+++ b/apps/files_external/l10n/ka_GE.js
@@ -75,6 +75,7 @@ OC.L10N.register(
"Region" : "რეგიონი",
"Enable SSL" : "SSL-ის ამოქმედება",
"Enable Path Style" : "ბილიკის სტილის ამოქმედება",
+ "Legacy (v2) authentication" : "ლეგატი (ვ2) აუტენტიფიკაცია",
"WebDAV" : "WebDAV-ი",
"URL" : "URL",
"Remote subfolder" : "დისტანციური ქვე-დირექტორია",
diff --git a/apps/files_external/l10n/ka_GE.json b/apps/files_external/l10n/ka_GE.json
index 34f02298e85..7d9ebcdb3b1 100644
--- a/apps/files_external/l10n/ka_GE.json
+++ b/apps/files_external/l10n/ka_GE.json
@@ -73,6 +73,7 @@
"Region" : "რეგიონი",
"Enable SSL" : "SSL-ის ამოქმედება",
"Enable Path Style" : "ბილიკის სტილის ამოქმედება",
+ "Legacy (v2) authentication" : "ლეგატი (ვ2) აუტენტიფიკაცია",
"WebDAV" : "WebDAV-ი",
"URL" : "URL",
"Remote subfolder" : "დისტანციური ქვე-დირექტორია",
diff --git a/apps/files_external/l10n/ko.js b/apps/files_external/l10n/ko.js
index 192c5a1c5c0..f91f5f72320 100644
--- a/apps/files_external/l10n/ko.js
+++ b/apps/files_external/l10n/ko.js
@@ -75,6 +75,7 @@ OC.L10N.register(
"Region" : "지역",
"Enable SSL" : "SSL 사용",
"Enable Path Style" : "경로 스타일 사용",
+ "Legacy (v2) authentication" : "레거시(v2) 인증",
"WebDAV" : "WebDAV",
"URL" : "URL",
"Remote subfolder" : "원격 하위 폴더",
diff --git a/apps/files_external/l10n/ko.json b/apps/files_external/l10n/ko.json
index aa11d68aa48..4f2bd99e984 100644
--- a/apps/files_external/l10n/ko.json
+++ b/apps/files_external/l10n/ko.json
@@ -73,6 +73,7 @@
"Region" : "지역",
"Enable SSL" : "SSL 사용",
"Enable Path Style" : "경로 스타일 사용",
+ "Legacy (v2) authentication" : "레거시(v2) 인증",
"WebDAV" : "WebDAV",
"URL" : "URL",
"Remote subfolder" : "원격 하위 폴더",
diff --git a/apps/files_external/l10n/nl.js b/apps/files_external/l10n/nl.js
index 2749e59e11b..5e53b24ddc6 100644
--- a/apps/files_external/l10n/nl.js
+++ b/apps/files_external/l10n/nl.js
@@ -75,6 +75,7 @@ OC.L10N.register(
"Region" : "Regio",
"Enable SSL" : "Activeren SSL",
"Enable Path Style" : "Activeren pad stijl",
+ "Legacy (v2) authentication" : "Legacy (v2) authenticatie",
"WebDAV" : "WebDAV",
"URL" : "URL",
"Remote subfolder" : "Externe submap",
diff --git a/apps/files_external/l10n/nl.json b/apps/files_external/l10n/nl.json
index 8258427503a..ee2ffa25a93 100644
--- a/apps/files_external/l10n/nl.json
+++ b/apps/files_external/l10n/nl.json
@@ -73,6 +73,7 @@
"Region" : "Regio",
"Enable SSL" : "Activeren SSL",
"Enable Path Style" : "Activeren pad stijl",
+ "Legacy (v2) authentication" : "Legacy (v2) authenticatie",
"WebDAV" : "WebDAV",
"URL" : "URL",
"Remote subfolder" : "Externe submap",
diff --git a/apps/files_external/l10n/pt_BR.js b/apps/files_external/l10n/pt_BR.js
index 077b89e1cf7..c2fe422e7b3 100644
--- a/apps/files_external/l10n/pt_BR.js
+++ b/apps/files_external/l10n/pt_BR.js
@@ -75,6 +75,7 @@ OC.L10N.register(
"Region" : "Região",
"Enable SSL" : "Habilitar SSL",
"Enable Path Style" : "Habilitar Estilo do Caminho",
+ "Legacy (v2) authentication" : "Autenticação (v2) herdada",
"WebDAV" : "WebDAV",
"URL" : "URL",
"Remote subfolder" : "Subpasta remota",
diff --git a/apps/files_external/l10n/pt_BR.json b/apps/files_external/l10n/pt_BR.json
index f9472a5c79d..4f5550870c5 100644
--- a/apps/files_external/l10n/pt_BR.json
+++ b/apps/files_external/l10n/pt_BR.json
@@ -73,6 +73,7 @@
"Region" : "Região",
"Enable SSL" : "Habilitar SSL",
"Enable Path Style" : "Habilitar Estilo do Caminho",
+ "Legacy (v2) authentication" : "Autenticação (v2) herdada",
"WebDAV" : "WebDAV",
"URL" : "URL",
"Remote subfolder" : "Subpasta remota",
diff --git a/apps/files_external/l10n/sr.js b/apps/files_external/l10n/sr.js
index ddff1a6a318..bd94b6dd843 100644
--- a/apps/files_external/l10n/sr.js
+++ b/apps/files_external/l10n/sr.js
@@ -75,6 +75,7 @@ OC.L10N.register(
"Region" : "Регија",
"Enable SSL" : "Омогући ССЛ",
"Enable Path Style" : "Омогући стил путање",
+ "Legacy (v2) authentication" : "Стара (v2) провера идентитета",
"WebDAV" : "ВебДАВ",
"URL" : "УРЛ",
"Remote subfolder" : "Удаљена потфасцикла",
diff --git a/apps/files_external/l10n/sr.json b/apps/files_external/l10n/sr.json
index 15b84d8ac51..7aa88bfaade 100644
--- a/apps/files_external/l10n/sr.json
+++ b/apps/files_external/l10n/sr.json
@@ -73,6 +73,7 @@
"Region" : "Регија",
"Enable SSL" : "Омогући ССЛ",
"Enable Path Style" : "Омогући стил путање",
+ "Legacy (v2) authentication" : "Стара (v2) провера идентитета",
"WebDAV" : "ВебДАВ",
"URL" : "УРЛ",
"Remote subfolder" : "Удаљена потфасцикла",
diff --git a/apps/files_external/l10n/tr.js b/apps/files_external/l10n/tr.js
index 152963db282..1def1246fde 100644
--- a/apps/files_external/l10n/tr.js
+++ b/apps/files_external/l10n/tr.js
@@ -75,6 +75,7 @@ OC.L10N.register(
"Region" : "Bölge",
"Enable SSL" : "SSL Kullanılsın",
"Enable Path Style" : "Yol Stili Kullanılsın",
+ "Legacy (v2) authentication" : "Eski (v2) kimlik doğrulama",
"WebDAV" : "WebDAV",
"URL" : "Adres",
"Remote subfolder" : "Uzak alt klasör",
diff --git a/apps/files_external/l10n/tr.json b/apps/files_external/l10n/tr.json
index efa75513f54..ea9fbc84c5f 100644
--- a/apps/files_external/l10n/tr.json
+++ b/apps/files_external/l10n/tr.json
@@ -73,6 +73,7 @@
"Region" : "Bölge",
"Enable SSL" : "SSL Kullanılsın",
"Enable Path Style" : "Yol Stili Kullanılsın",
+ "Legacy (v2) authentication" : "Eski (v2) kimlik doğrulama",
"WebDAV" : "WebDAV",
"URL" : "Adres",
"Remote subfolder" : "Uzak alt klasör",
diff --git a/apps/files_sharing/l10n/ko.js b/apps/files_sharing/l10n/ko.js
index aad92ab9ef6..5f8e4374ab8 100644
--- a/apps/files_sharing/l10n/ko.js
+++ b/apps/files_sharing/l10n/ko.js
@@ -15,7 +15,7 @@ OC.L10N.register(
"Invalid server URL" : "잘못된 서버 URL",
"Failed to add the public link to your Nextcloud" : "Nextcloud에 공개 링크를 추가할 수 없음",
"Share" : "공유",
- "No expiration date set" : "만료 날짜가 설정되지 않음",
+ "No expiration date set" : "만료 날짜가 설정되지 않았음",
"Shared by" : "공유한 사용자:",
"Sharing" : "공유",
"File shares" : "파일 공유",
@@ -71,17 +71,17 @@ OC.L10N.register(
"Wrong path, file/folder doesn't exist" : "잘못된 경로, 파일/폴더가 존재하지 않음",
"Could not create share" : "공유를 만들 수 없음",
"invalid permissions" : "잘못된 권한",
- "Please specify a valid user" : "유효한 사용자를 지정하십시오",
- "Group sharing is disabled by the administrator" : "그룹 공유는 관리자에 의해 비활성화되어 있음",
- "Please specify a valid group" : "유효한 그룹을 지정하십시오",
- "Public link sharing is disabled by the administrator" : "공개 링크 공유는 관리자에 의해 비활성화되어 있음",
+ "Please specify a valid user" : "올바른 사용자를 지정하십시오",
+ "Group sharing is disabled by the administrator" : "관리자가 그룹 공유를 비활성화함",
+ "Please specify a valid group" : "올바른 그룹을 지정하십시오",
+ "Public link sharing is disabled by the administrator" : "관리자가 공개 링크 공유를 비활성화함",
"Public upload disabled by the administrator" : "공개 업로드는 관리자에 의해 비활성화되어 있음",
"Public upload is only possible for publicly shared folders" : "공개 공유 폴더에만 공개 업로드를 사용할 수 있음",
"Invalid date, date format must be YYYY-MM-DD" : "잘못된 날짜, YYYY-MM-DD 형식이어야 합니다.",
"Sharing %s failed because the back end does not allow shares from type %s" : "%s을(를) 공유할 수 없습니다. 백엔드에서 %s 형식의 공유를 지원하지 않습니다",
"You cannot share to a Circle if the app is not enabled" : "서클 앱이 활성화되어 있지 않으면 서클로 공유할 수 없음",
"Please specify a valid circle" : "올바른 서클을 지정하십시오",
- "Unknown share type" : "알 수 없는 공유 유형",
+ "Unknown share type" : "알 수 없는 공유 형식",
"Not a directory" : "디렉터리가 아님",
"Could not lock path" : "경로를 잠글 수 없음",
"Wrong or no update parameter given" : "업데이트 인자가 잘못되었거나 지정되지 않았음",
diff --git a/apps/files_sharing/l10n/ko.json b/apps/files_sharing/l10n/ko.json
index d60145d5faf..00c5d8b954a 100644
--- a/apps/files_sharing/l10n/ko.json
+++ b/apps/files_sharing/l10n/ko.json
@@ -13,7 +13,7 @@
"Invalid server URL" : "잘못된 서버 URL",
"Failed to add the public link to your Nextcloud" : "Nextcloud에 공개 링크를 추가할 수 없음",
"Share" : "공유",
- "No expiration date set" : "만료 날짜가 설정되지 않음",
+ "No expiration date set" : "만료 날짜가 설정되지 않았음",
"Shared by" : "공유한 사용자:",
"Sharing" : "공유",
"File shares" : "파일 공유",
@@ -69,17 +69,17 @@
"Wrong path, file/folder doesn't exist" : "잘못된 경로, 파일/폴더가 존재하지 않음",
"Could not create share" : "공유를 만들 수 없음",
"invalid permissions" : "잘못된 권한",
- "Please specify a valid user" : "유효한 사용자를 지정하십시오",
- "Group sharing is disabled by the administrator" : "그룹 공유는 관리자에 의해 비활성화되어 있음",
- "Please specify a valid group" : "유효한 그룹을 지정하십시오",
- "Public link sharing is disabled by the administrator" : "공개 링크 공유는 관리자에 의해 비활성화되어 있음",
+ "Please specify a valid user" : "올바른 사용자를 지정하십시오",
+ "Group sharing is disabled by the administrator" : "관리자가 그룹 공유를 비활성화함",
+ "Please specify a valid group" : "올바른 그룹을 지정하십시오",
+ "Public link sharing is disabled by the administrator" : "관리자가 공개 링크 공유를 비활성화함",
"Public upload disabled by the administrator" : "공개 업로드는 관리자에 의해 비활성화되어 있음",
"Public upload is only possible for publicly shared folders" : "공개 공유 폴더에만 공개 업로드를 사용할 수 있음",
"Invalid date, date format must be YYYY-MM-DD" : "잘못된 날짜, YYYY-MM-DD 형식이어야 합니다.",
"Sharing %s failed because the back end does not allow shares from type %s" : "%s을(를) 공유할 수 없습니다. 백엔드에서 %s 형식의 공유를 지원하지 않습니다",
"You cannot share to a Circle if the app is not enabled" : "서클 앱이 활성화되어 있지 않으면 서클로 공유할 수 없음",
"Please specify a valid circle" : "올바른 서클을 지정하십시오",
- "Unknown share type" : "알 수 없는 공유 유형",
+ "Unknown share type" : "알 수 없는 공유 형식",
"Not a directory" : "디렉터리가 아님",
"Could not lock path" : "경로를 잠글 수 없음",
"Wrong or no update parameter given" : "업데이트 인자가 잘못되었거나 지정되지 않았음",
diff --git a/apps/files_sharing/lib/External/Mount.php b/apps/files_sharing/lib/External/Mount.php
index d756a1830b2..e12f8823cd8 100644
--- a/apps/files_sharing/lib/External/Mount.php
+++ b/apps/files_sharing/lib/External/Mount.php
@@ -68,4 +68,14 @@ class Mount extends MountPoint implements MoveableMount {
public function removeMount() {
return $this->manager->removeShare($this->mountPoint);
}
+
+ /**
+ * Get the type of mount point, used to distinguish things like shares and external storages
+ * in the web interface
+ *
+ * @return string
+ */
+ public function getMountType() {
+ return 'shared';
+ }
}
diff --git a/apps/sharebymail/l10n/sv.js b/apps/sharebymail/l10n/sv.js
index eb3b8451e6b..03789a8af96 100644
--- a/apps/sharebymail/l10n/sv.js
+++ b/apps/sharebymail/l10n/sv.js
@@ -5,9 +5,9 @@ OC.L10N.register(
"Shared with {email}" : "Delad med {email}",
"Shared with %1$s by %2$s" : "Delad med %1$s av %2$s",
"Shared with {email} by {actor}" : "Delad med {email} av {actor}",
- "Password for mail share sent to %1$s" : "Lösenord för maildelning sändes till %1$s",
- "Password for mail share sent to {email}" : "Lösenord för maildelning skickat till {email}",
- "Password for mail share sent to you" : "Lösenord för epostdelning skickat till dig",
+ "Password for mail share sent to %1$s" : "Lösenord för e-postdelning sändes till %1$s",
+ "Password for mail share sent to {email}" : "Lösenord för e-postdelning skickat till {email}",
+ "Password for mail share sent to you" : "Lösenord för e-postdelning skickat till dig",
"You shared %1$s with %2$s by mail" : "Du delade %1$s med %2$s via e-post",
"You shared {file} with {email} by mail" : "Du delade {file} med {email} via e-post",
"%3$s shared %1$s with %2$s by mail" : "%3$s delade %1$s med %2$s via e-post",
@@ -17,15 +17,15 @@ OC.L10N.register(
"Password to access %1$s was sent to you" : "Lösenord för att nå %1$s sändes till dig",
"Password to access {file} was sent to you" : "Lösenord till {file} sändes till dig",
"Sharing %s failed, this item is already shared with %s" : "Delning av %s misslyckades, det är redan delat med %s",
- "We can't send you the auto-generated password. Please set a valid email address in your personal settings and try again." : "Vi kan inte sända dig det autogenererade lösenordet. Vänligen ange en giltig epost-adress i dina personliga inställningar och försök igen.",
+ "We can't send you the auto-generated password. Please set a valid email address in your personal settings and try again." : "Vi kan inte skicka det autogenererade lösenordet till dig. Vänligen ange en giltig e-postadress i dina personliga inställningar och försök igen.",
"Failed to send share by email" : "Misslyckades att sända delning med e-post",
"%s shared »%s« with you" : "%s delade »%s« med dig",
"%s shared »%s« with you." : "%s delade »%s« med dig.",
- "Click the button below to open it." : "Klicka knappen nedan för att öppna det.",
+ "Click the button below to open it." : "Klicka på knappen nedan för att öppna det.",
"Open »%s«" : "Öppna »%s«",
"%s via %s" : "%s via %s",
- "%s shared »%s« with you.\nYou should have already received a separate mail with a link to access it.\n" : "%s delade »%s« med dig.\nDu ska redan ha fått ett separat epost med en länk för att nå det.\n",
- "%s shared »%s« with you. You should have already received a separate mail with a link to access it." : "%s delade »%s« med dig. Du ska redan ha fått ett separat e-post med en länk för att nå det.",
+ "%s shared »%s« with you.\nYou should have already received a separate mail with a link to access it.\n" : "%s delade »%s« med dig.\nDu ska redan ha fått ett separat mail med en länk för att komma åt det.\n",
+ "%s shared »%s« with you. You should have already received a separate mail with a link to access it." : "%s delade »%s« med dig. Du ska redan ha fått ett separat mail med en länk för att komma åt det.",
"Password to access »%s« shared to you by %s" : "Lösenord för att få tillgång till »%s« delat med dig av %s",
"Password to access »%s«" : "Lösenord för att nå »%s«",
"It is protected with the following password: %s" : "Den är skyddad med följande lösenord: %s",
@@ -35,8 +35,8 @@ OC.L10N.register(
"You can choose a different password at any time in the share dialog." : "Du kan välja ett annat lösenord när som helst i delningsdialogen.",
"Could not find share" : "Kunde inte hitta delning",
"Share by mail" : "Dela via e-post",
- "Allows users to share a personalized link to a file or folder by putting in an email address." : "Tillåt användare att dela en personlig länk till en fil eller mapp genom att ange en e-post-adress",
- "Send password by mail" : "Skicka lösenord med e-post",
+ "Allows users to share a personalized link to a file or folder by putting in an email address." : "Tillåt användare att dela en personlig länk till en fil eller mapp genom att ange en e-postadress",
+ "Send password by mail" : "Skicka lösenord via e-post",
"Enforce password protection" : "Tvinga lösenordsskydd",
"Failed to send share by E-mail" : "Misslyckades att dela via e-post",
"%s shared »%s« with you on behalf of %s" : "%s delade »%s« med dig på begäran av %s",
diff --git a/apps/sharebymail/l10n/sv.json b/apps/sharebymail/l10n/sv.json
index 75e3bb9d299..ced3fece128 100644
--- a/apps/sharebymail/l10n/sv.json
+++ b/apps/sharebymail/l10n/sv.json
@@ -3,9 +3,9 @@
"Shared with {email}" : "Delad med {email}",
"Shared with %1$s by %2$s" : "Delad med %1$s av %2$s",
"Shared with {email} by {actor}" : "Delad med {email} av {actor}",
- "Password for mail share sent to %1$s" : "Lösenord för maildelning sändes till %1$s",
- "Password for mail share sent to {email}" : "Lösenord för maildelning skickat till {email}",
- "Password for mail share sent to you" : "Lösenord för epostdelning skickat till dig",
+ "Password for mail share sent to %1$s" : "Lösenord för e-postdelning sändes till %1$s",
+ "Password for mail share sent to {email}" : "Lösenord för e-postdelning skickat till {email}",
+ "Password for mail share sent to you" : "Lösenord för e-postdelning skickat till dig",
"You shared %1$s with %2$s by mail" : "Du delade %1$s med %2$s via e-post",
"You shared {file} with {email} by mail" : "Du delade {file} med {email} via e-post",
"%3$s shared %1$s with %2$s by mail" : "%3$s delade %1$s med %2$s via e-post",
@@ -15,15 +15,15 @@
"Password to access %1$s was sent to you" : "Lösenord för att nå %1$s sändes till dig",
"Password to access {file} was sent to you" : "Lösenord till {file} sändes till dig",
"Sharing %s failed, this item is already shared with %s" : "Delning av %s misslyckades, det är redan delat med %s",
- "We can't send you the auto-generated password. Please set a valid email address in your personal settings and try again." : "Vi kan inte sända dig det autogenererade lösenordet. Vänligen ange en giltig epost-adress i dina personliga inställningar och försök igen.",
+ "We can't send you the auto-generated password. Please set a valid email address in your personal settings and try again." : "Vi kan inte skicka det autogenererade lösenordet till dig. Vänligen ange en giltig e-postadress i dina personliga inställningar och försök igen.",
"Failed to send share by email" : "Misslyckades att sända delning med e-post",
"%s shared »%s« with you" : "%s delade »%s« med dig",
"%s shared »%s« with you." : "%s delade »%s« med dig.",
- "Click the button below to open it." : "Klicka knappen nedan för att öppna det.",
+ "Click the button below to open it." : "Klicka på knappen nedan för att öppna det.",
"Open »%s«" : "Öppna »%s«",
"%s via %s" : "%s via %s",
- "%s shared »%s« with you.\nYou should have already received a separate mail with a link to access it.\n" : "%s delade »%s« med dig.\nDu ska redan ha fått ett separat epost med en länk för att nå det.\n",
- "%s shared »%s« with you. You should have already received a separate mail with a link to access it." : "%s delade »%s« med dig. Du ska redan ha fått ett separat e-post med en länk för att nå det.",
+ "%s shared »%s« with you.\nYou should have already received a separate mail with a link to access it.\n" : "%s delade »%s« med dig.\nDu ska redan ha fått ett separat mail med en länk för att komma åt det.\n",
+ "%s shared »%s« with you. You should have already received a separate mail with a link to access it." : "%s delade »%s« med dig. Du ska redan ha fått ett separat mail med en länk för att komma åt det.",
"Password to access »%s« shared to you by %s" : "Lösenord för att få tillgång till »%s« delat med dig av %s",
"Password to access »%s«" : "Lösenord för att nå »%s«",
"It is protected with the following password: %s" : "Den är skyddad med följande lösenord: %s",
@@ -33,8 +33,8 @@
"You can choose a different password at any time in the share dialog." : "Du kan välja ett annat lösenord när som helst i delningsdialogen.",
"Could not find share" : "Kunde inte hitta delning",
"Share by mail" : "Dela via e-post",
- "Allows users to share a personalized link to a file or folder by putting in an email address." : "Tillåt användare att dela en personlig länk till en fil eller mapp genom att ange en e-post-adress",
- "Send password by mail" : "Skicka lösenord med e-post",
+ "Allows users to share a personalized link to a file or folder by putting in an email address." : "Tillåt användare att dela en personlig länk till en fil eller mapp genom att ange en e-postadress",
+ "Send password by mail" : "Skicka lösenord via e-post",
"Enforce password protection" : "Tvinga lösenordsskydd",
"Failed to send share by E-mail" : "Misslyckades att dela via e-post",
"%s shared »%s« with you on behalf of %s" : "%s delade »%s« med dig på begäran av %s",
diff --git a/apps/theming/css/theming.scss b/apps/theming/css/theming.scss
index 4474c232d94..63d466542e1 100644
--- a/apps/theming/css/theming.scss
+++ b/apps/theming/css/theming.scss
@@ -1,3 +1,12 @@
+/** Calculate luma as it is also used in OCA\Theming\Util::calculateLuma */
+@function luma($c) {
+ $-local-red: red(rgba($c, 1.0));
+ $-local-green: green(rgba($c, 1.0));
+ $-local-blue: blue(rgba($c, 1.0));
+
+ @return (0.2126 * $-local-red + 0.7152 * $-local-green + 0.0722 * $-local-blue) / 255;
+}
+
.nc-theming-main-background {
background-color: $color-primary;
}
@@ -10,7 +19,13 @@
color: $color-primary-text;
}
-@if (lightness($color-primary) > 55) {
+@if (luma($color-primary) > 0.6) {
+ #appmenu:not(.inverted) svg {
+ filter: invert(1);
+ }
+ #appmenu.inverted svg {
+ filter: none;
+ }
.searchbox input[type="search"] {
background: transparent url('../../../core/img/actions/search.svg') no-repeat 6px center;
}
@@ -53,6 +68,13 @@
background-color: nc-darken($color-primary-element, 30%) !important;
}
}
+} @else {
+ #appmenu:not(.inverted) svg {
+ filter: none;
+ }
+ #appmenu.inverted svg {
+ filter: invert(1);
+ }
}
/* Colorized svg images */
@@ -90,8 +112,8 @@ input.primary,
color: $color-primary-text;
}
-@if (lightness($color-primary) > 50) {
- #body-login #submit-icon.icon-confirm-white {
+@if (luma($color-primary) > 0.6) {
+ #body-login #submit-wrapper .icon-confirm-white {
background-image: url('../../../core/img/actions/confirm.svg');
}
}
diff --git a/apps/theming/lib/Capabilities.php b/apps/theming/lib/Capabilities.php
index 1b6bb8927be..a75403a1fd5 100644
--- a/apps/theming/lib/Capabilities.php
+++ b/apps/theming/lib/Capabilities.php
@@ -81,6 +81,8 @@ class Capabilities implements IPublicCapability {
'background' => $backgroundLogo === 'backgroundColor' ?
$this->theming->getColorPrimary() :
$this->url->getAbsoluteURL($this->theming->getBackground()),
+ 'background-plain' => $backgroundLogo === 'backgroundColor',
+ 'background-default' => !$this->util->isBackgroundThemed(),
],
];
}
diff --git a/apps/theming/lib/Controller/ThemingController.php b/apps/theming/lib/Controller/ThemingController.php
index b7777f1f907..6592eb7f7ab 100644
--- a/apps/theming/lib/Controller/ThemingController.php
+++ b/apps/theming/lib/Controller/ThemingController.php
@@ -176,7 +176,7 @@ class ThemingController extends Controller {
$this->themingDefaults->set($setting, $value);
// reprocess server scss for preview
- $cssCached = $this->scssCacher->process(\OC::$SERVERROOT, '/core/css/server.scss', 'core');
+ $cssCached = $this->scssCacher->process(\OC::$SERVERROOT, 'core/css/server.scss', 'core');
return new DataResponse(
[
@@ -324,7 +324,7 @@ class ThemingController extends Controller {
public function undo($setting) {
$value = $this->themingDefaults->undo($setting);
// reprocess server scss for preview
- $cssCached = $this->scssCacher->process(\OC::$SERVERROOT, '/core/css/server.scss', 'core');
+ $cssCached = $this->scssCacher->process(\OC::$SERVERROOT, 'core/css/server.scss', 'core');
if($setting === 'logoMime') {
try {
diff --git a/apps/theming/lib/ThemingDefaults.php b/apps/theming/lib/ThemingDefaults.php
index 05d387e6273..9dcc981817e 100644
--- a/apps/theming/lib/ThemingDefaults.php
+++ b/apps/theming/lib/ThemingDefaults.php
@@ -196,22 +196,13 @@ class ThemingDefaults extends \OC_Defaults {
* @return string
*/
public function getBackground() {
- $backgroundLogo = $this->config->getAppValue('theming', 'backgroundMime',false);
-
- $backgroundExists = true;
- try {
- $this->appData->getFolder('images')->getFile('background');
- } catch (\Exception $e) {
- $backgroundExists = false;
- }
-
$cacheBusterCounter = $this->config->getAppValue('theming', 'cachebuster', '0');
- if(!$backgroundLogo || !$backgroundExists) {
- return $this->urlGenerator->imagePath('core','background.png') . '?v=' . $cacheBusterCounter;
+ if($this->util->isBackgroundThemed()) {
+ return $this->urlGenerator->linkToRoute('theming.Theming.getLoginBackground') . '?v=' . $cacheBusterCounter;
}
- return $this->urlGenerator->linkToRoute('theming.Theming.getLoginBackground') . '?v=' . $cacheBusterCounter;
+ return $this->urlGenerator->imagePath('core','background.png') . '?v=' . $cacheBusterCounter;
}
/**
diff --git a/apps/theming/lib/Util.php b/apps/theming/lib/Util.php
index 194b5eeb0d0..2f6f4128365 100644
--- a/apps/theming/lib/Util.php
+++ b/apps/theming/lib/Util.php
@@ -63,8 +63,8 @@ class Util {
* @return bool
*/
public function invertTextColor($color) {
- $l = $this->calculateLuminance($color);
- if($l>0.55) {
+ $l = $this->calculateLuma($color);
+ if($l>0.6) {
return true;
} else {
return false;
@@ -90,6 +90,26 @@ class Util {
* @return float
*/
public function calculateLuminance($color) {
+ list($red, $green, $blue) = $this->hexToRGB($color);
+ $compiler = new Compiler();
+ $hsl = $compiler->toHSL($red, $green, $blue);
+ return $hsl[3]/100;
+ }
+
+ /**
+ * @param string $color rgb color value
+ * @return float
+ */
+ public function calculateLuma($color) {
+ list($red, $green, $blue) = $this->hexToRGB($color);
+ return (0.2126 * $red + 0.7152 * $green + 0.0722 * $blue) / 255;
+ }
+
+ /**
+ * @param string $color rgb color value
+ * @return int[]
+ */
+ public function hexToRGB($color) {
$hex = preg_replace("/[^0-9A-Fa-f]/", '', $color);
if (strlen($hex) === 3) {
$hex = $hex{0} . $hex{0} . $hex{1} . $hex{1} . $hex{2} . $hex{2};
@@ -97,12 +117,11 @@ class Util {
if (strlen($hex) !== 6) {
return 0;
}
- $red = hexdec(substr($hex, 0, 2));
- $green = hexdec(substr($hex, 2, 2));
- $blue = hexdec(substr($hex, 4, 2));
- $compiler = new Compiler();
- $hsl = $compiler->toHSL($red, $green, $blue);
- return $hsl[3]/100;
+ return [
+ hexdec(substr($hex, 0, 2)),
+ hexdec(substr($hex, 2, 2)),
+ hexdec(substr($hex, 4, 2))
+ ];
}
/**
@@ -216,4 +235,16 @@ class Util {
return false;
}
+ public function isBackgroundThemed() {
+ $backgroundLogo = $this->config->getAppValue('theming', 'backgroundMime',false);
+
+ $backgroundExists = true;
+ try {
+ $this->appData->getFolder('images')->getFile('background');
+ } catch (\Exception $e) {
+ $backgroundExists = false;
+ }
+ return $backgroundLogo && $backgroundLogo !== 'backgroundColor' && $backgroundExists;
+ }
+
}
diff --git a/apps/theming/tests/CapabilitiesTest.php b/apps/theming/tests/CapabilitiesTest.php
index c760c896425..31e0ae79970 100644
--- a/apps/theming/tests/CapabilitiesTest.php
+++ b/apps/theming/tests/CapabilitiesTest.php
@@ -50,6 +50,9 @@ class CapabilitiesTest extends TestCase {
/** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
protected $config;
+ /** @var Util|\PHPUnit_Framework_MockObject_MockObject */
+ protected $util;
+
/** @var Capabilities */
protected $capabilities;
@@ -59,13 +62,13 @@ class CapabilitiesTest extends TestCase {
$this->theming = $this->createMock(ThemingDefaults::class);
$this->url = $this->getMockBuilder(IURLGenerator::class)->getMock();
$this->config = $this->createMock(IConfig::class);
- $util = new Util($this->config, $this->createMock(IAppManager::class), $this->createMock(IAppData::class));
- $this->capabilities = new Capabilities($this->theming, $util, $this->url, $this->config);
+ $this->util = $this->createMock(Util::class);
+ $this->capabilities = new Capabilities($this->theming, $this->util, $this->url, $this->config);
}
public function dataGetCapabilities() {
return [
- ['name', 'url', 'slogan', '#FFFFFF', '#000000', 'logo', 'background', 'http://absolute/', [
+ ['name', 'url', 'slogan', '#FFFFFF', '#000000', 'logo', 'background', 'http://absolute/', true, [
'name' => 'name',
'url' => 'url',
'slogan' => 'slogan',
@@ -74,8 +77,10 @@ class CapabilitiesTest extends TestCase {
'color-element' => '#555555',
'logo' => 'http://absolute/logo',
'background' => 'http://absolute/background',
+ 'background-plain' => false,
+ 'background-default' => false,
]],
- ['name1', 'url2', 'slogan3', '#01e4a0', '#ffffff', 'logo5', 'background6', 'http://localhost/', [
+ ['name1', 'url2', 'slogan3', '#01e4a0', '#ffffff', 'logo5', 'background6', 'http://localhost/', false, [
'name' => 'name1',
'url' => 'url2',
'slogan' => 'slogan3',
@@ -84,8 +89,22 @@ class CapabilitiesTest extends TestCase {
'color-element' => '#01e4a0',
'logo' => 'http://localhost/logo5',
'background' => 'http://localhost/background6',
+ 'background-plain' => false,
+ 'background-default' => true,
+ ]],
+ ['name1', 'url2', 'slogan3', '#000000', '#ffffff', 'logo5', 'backgroundColor', 'http://localhost/', true, [
+ 'name' => 'name1',
+ 'url' => 'url2',
+ 'slogan' => 'slogan3',
+ 'color' => '#000000',
+ 'color-text' => '#ffffff',
+ 'color-element' => '#000000',
+ 'logo' => 'http://localhost/logo5',
+ 'background' => '#000000',
+ 'background-plain' => true,
+ 'background-default' => false,
]],
- ['name1', 'url2', 'slogan3', '#000000', '#ffffff', 'logo5', 'backgroundColor', 'http://localhost/', [
+ ['name1', 'url2', 'slogan3', '#000000', '#ffffff', 'logo5', 'backgroundColor', 'http://localhost/', false, [
'name' => 'name1',
'url' => 'url2',
'slogan' => 'slogan3',
@@ -94,6 +113,8 @@ class CapabilitiesTest extends TestCase {
'color-element' => '#000000',
'logo' => 'http://localhost/logo5',
'background' => '#000000',
+ 'background-plain' => true,
+ 'background-default' => true,
]],
];
}
@@ -104,13 +125,14 @@ class CapabilitiesTest extends TestCase {
* @param string $url
* @param string $slogan
* @param string $color
- * @param string $logo
* @param string $textColor
+ * @param string $logo
* @param string $background
* @param string $baseUrl
+ * @param bool $backgroundThemed
* @param string[] $expected
*/
- public function testGetCapabilities($name, $url, $slogan, $color, $textColor, $logo, $background, $baseUrl, array $expected) {
+ public function testGetCapabilities($name, $url, $slogan, $color, $textColor, $logo, $background, $baseUrl, $backgroundThemed, array $expected) {
$this->config->expects($this->once())
->method('getAppValue')
->willReturn($background);
@@ -133,6 +155,16 @@ class CapabilitiesTest extends TestCase {
->method('getTextColorPrimary')
->willReturn($textColor);
+ $util = new Util($this->config, $this->createMock(IAppManager::class), $this->createMock(IAppData::class));
+ $this->util->expects($this->once())
+ ->method('elementColor')
+ ->with($color)
+ ->willReturn($util->elementColor($color));
+
+ $this->util->expects($this->once())
+ ->method('isBackgroundThemed')
+ ->willReturn($backgroundThemed);
+
if($background !== 'backgroundColor') {
$this->theming->expects($this->once())
->method('getBackground')
diff --git a/apps/theming/tests/ThemingDefaultsTest.php b/apps/theming/tests/ThemingDefaultsTest.php
index 843c1d34f9e..d0dc6587f74 100644
--- a/apps/theming/tests/ThemingDefaultsTest.php
+++ b/apps/theming/tests/ThemingDefaultsTest.php
@@ -391,24 +391,14 @@ class ThemingDefaultsTest extends TestCase {
}
public function testGetBackgroundDefault() {
- $this->appData->expects($this->once())
- ->method('getFolder')
- ->willThrowException(new NotFoundException());
- $this->config
- ->expects($this->at(0))
- ->method('getAppValue')
- ->with('theming', 'backgroundMime')
- ->willReturn('');
$this->config
- ->expects($this->at(1))
+ ->expects($this->once())
->method('getAppValue')
->with('theming', 'cachebuster', '0')
->willReturn('0');
- $this->appData
- ->expects($this->once())
- ->method('getFolder')
- ->with('images')
- ->willThrowException(new \Exception());
+ $this->util->expects($this->once())
+ ->method('isBackgroundThemed')
+ ->willReturn(false);
$this->urlGenerator->expects($this->once())
->method('imagePath')
->with('core', 'background.png')
@@ -417,24 +407,14 @@ class ThemingDefaultsTest extends TestCase {
}
public function testGetBackgroundCustom() {
- $folder = $this->createMock(ISimpleFolder::class);
- $file = $this->createMock(ISimpleFile::class);
- $folder->expects($this->once())
- ->method('getFile')
- ->willReturn($file);
- $this->appData->expects($this->once())
- ->method('getFolder')
- ->willReturn($folder);
$this->config
- ->expects($this->at(0))
- ->method('getAppValue')
- ->with('theming', 'backgroundMime', false)
- ->willReturn('image/svg+xml');
- $this->config
- ->expects($this->at(1))
+ ->expects($this->once())
->method('getAppValue')
->with('theming', 'cachebuster', '0')
->willReturn('0');
+ $this->util->expects($this->once())
+ ->method('isBackgroundThemed')
+ ->willReturn(true);
$this->urlGenerator->expects($this->once())
->method('linkToRoute')
->with('theming.Theming.getLoginBackground')
@@ -513,12 +493,12 @@ class ThemingDefaultsTest extends TestCase {
$this->config->expects($this->at(2))->method('getAppValue')->with('theming', 'backgroundMime', false)->willReturn('jpeg');
$this->config->expects($this->at(3))->method('getAppValue')->with('theming', 'logoMime', false)->willReturn('jpeg');
$this->config->expects($this->at(4))->method('getAppValue')->with('theming', 'cachebuster', '0')->willReturn('0');
- $this->config->expects($this->at(5))->method('getAppValue')->with('theming', 'backgroundMime', false)->willReturn('jpeg');
- $this->config->expects($this->at(6))->method('getAppValue')->with('theming', 'cachebuster', '0')->willReturn('0');
- $this->config->expects($this->at(7))->method('getAppValue')->with('theming', 'color', null)->willReturn($this->defaults->getColorPrimary());
+ $this->util->expects($this->once())->method('isBackgroundThemed')->willReturn(true);
+ $this->config->expects($this->at(5))->method('getAppValue')->with('theming', 'cachebuster', '0')->willReturn('0');
+ $this->config->expects($this->at(6))->method('getAppValue')->with('theming', 'color', null)->willReturn($this->defaults->getColorPrimary());
+ $this->config->expects($this->at(7))->method('getAppValue')->with('theming', 'color', $this->defaults->getColorPrimary())->willReturn($this->defaults->getColorPrimary());
$this->config->expects($this->at(8))->method('getAppValue')->with('theming', 'color', $this->defaults->getColorPrimary())->willReturn($this->defaults->getColorPrimary());
$this->config->expects($this->at(9))->method('getAppValue')->with('theming', 'color', $this->defaults->getColorPrimary())->willReturn($this->defaults->getColorPrimary());
- $this->config->expects($this->at(10))->method('getAppValue')->with('theming', 'color', $this->defaults->getColorPrimary())->willReturn($this->defaults->getColorPrimary());
$this->util->expects($this->any())->method('invertTextColor')->with($this->defaults->getColorPrimary())->willReturn(false);
$this->util->expects($this->any())->method('elementColor')->with($this->defaults->getColorPrimary())->willReturn('#aaaaaa');
diff --git a/apps/theming/tests/UtilTest.php b/apps/theming/tests/UtilTest.php
index 94e4c9cbcc8..247bcbae0b2 100644
--- a/apps/theming/tests/UtilTest.php
+++ b/apps/theming/tests/UtilTest.php
@@ -53,14 +53,20 @@ class UtilTest extends TestCase {
$this->util = new Util($this->config, $this->appManager, $this->appData);
}
- public function testInvertTextColorLight() {
- $invert = $this->util->invertTextColor('#ffffff');
- $this->assertEquals(true, $invert);
+ public function dataInvertTextColor() {
+ return [
+ ['#ffffff', true],
+ ['#000000', false],
+ ['#0082C9', false],
+ ['#ffff00', true],
+ ];
}
-
- public function testInvertTextColorDark() {
- $invert = $this->util->invertTextColor('#000000');
- $this->assertEquals(false, $invert);
+ /**
+ * @dataProvider dataInvertTextColor
+ */
+ public function testInvertTextColor($color, $expected) {
+ $invert = $this->util->invertTextColor($color);
+ $this->assertEquals($expected, $invert);
}
public function testCalculateLuminanceLight() {
@@ -183,7 +189,6 @@ class UtilTest extends TestCase {
}
public function testIsAlreadyThemedFalse() {
- $theme = $this->config->getSystemValue('theme', '');
$this->config->expects($this->once())
->method('getSystemValue')
->with('theme', '')
@@ -193,7 +198,6 @@ class UtilTest extends TestCase {
}
public function testIsAlreadyThemedTrue() {
- $theme = $this->config->getSystemValue('theme', '');
$this->config->expects($this->once())
->method('getSystemValue')
->with('theme', '')
@@ -202,4 +206,35 @@ class UtilTest extends TestCase {
$this->assertTrue($actual);
}
+ public function dataIsBackgroundThemed() {
+ return [
+ [false, false, false],
+ ['png', true, true],
+ ['backgroundColor', false, false],
+ ];
+ }
+ /**
+ * @dataProvider dataIsBackgroundThemed
+ */
+ public function testIsBackgroundThemed($backgroundMime, $fileFound, $expected) {
+ $this->config->expects($this->once())
+ ->method('getAppValue')
+ ->with('theming', 'backgroundMime', false)
+ ->willReturn($backgroundMime);
+ $folder = $this->createMock(ISimpleFolder::class);
+ if ($fileFound) {
+ $folder->expects($this->once())
+ ->method('getFile')
+ ->willReturn($this->createMock(ISimpleFile::class));
+ } else {
+ $folder->expects($this->once())
+ ->method('getFile')
+ ->willThrowException(new NotFoundException());
+ }
+ $this->appData->expects($this->once())
+ ->method('getFolder')
+ ->willReturn($folder);
+ $this->assertEquals($expected, $this->util->isBackgroundThemed());
+ }
+
}
diff --git a/apps/updatenotification/js/notification.js b/apps/updatenotification/js/notification.js
index a2e78cecb09..a588ede5ffd 100644
--- a/apps/updatenotification/js/notification.js
+++ b/apps/updatenotification/js/notification.js
@@ -17,10 +17,5 @@ $(document).ready(function(){
var text = t('core', '{version} is available. Get more information on how to update.', {version: oc_updateState.updateVersion}),
element = $('<a>').attr('href', oc_updateState.updateLink).attr('target','_blank').text(text);
- OC.Notification.show(element,
- {
- isHTML: true,
- type: 'error'
- }
- );
+ OC.Notification.showHtml(element, { type: 'error' });
});
diff --git a/apps/user_ldap/composer/composer/autoload_classmap.php b/apps/user_ldap/composer/composer/autoload_classmap.php
index 7bade37d9f7..98a1bbfa1b7 100644
--- a/apps/user_ldap/composer/composer/autoload_classmap.php
+++ b/apps/user_ldap/composer/composer/autoload_classmap.php
@@ -7,6 +7,7 @@ $baseDir = $vendorDir;
return array(
'OCA\\User_LDAP\\Access' => $baseDir . '/../lib/Access.php',
+ 'OCA\\User_LDAP\\AccessFactory' => $baseDir . '/../lib/AccessFactory.php',
'OCA\\User_LDAP\\AppInfo\\Application' => $baseDir . '/../lib/AppInfo/Application.php',
'OCA\\User_LDAP\\BackendUtility' => $baseDir . '/../lib/BackendUtility.php',
'OCA\\User_LDAP\\Command\\CheckUser' => $baseDir . '/../lib/Command/CheckUser.php',
@@ -19,6 +20,7 @@ return array(
'OCA\\User_LDAP\\Command\\TestConfig' => $baseDir . '/../lib/Command/TestConfig.php',
'OCA\\User_LDAP\\Configuration' => $baseDir . '/../lib/Configuration.php',
'OCA\\User_LDAP\\Connection' => $baseDir . '/../lib/Connection.php',
+ 'OCA\\User_LDAP\\ConnectionFactory' => $baseDir . '/../lib/ConnectionFactory.php',
'OCA\\User_LDAP\\Controller\\ConfigAPIController' => $baseDir . '/../lib/Controller/ConfigAPIController.php',
'OCA\\User_LDAP\\Controller\\RenewPasswordController' => $baseDir . '/../lib/Controller/RenewPasswordController.php',
'OCA\\User_LDAP\\Exceptions\\ConstraintViolationException' => $baseDir . '/../lib/Exceptions/ConstraintViolationException.php',
diff --git a/apps/user_ldap/composer/composer/autoload_static.php b/apps/user_ldap/composer/composer/autoload_static.php
index fbe63285273..6c97237d62d 100644
--- a/apps/user_ldap/composer/composer/autoload_static.php
+++ b/apps/user_ldap/composer/composer/autoload_static.php
@@ -19,6 +19,7 @@ class ComposerStaticInitUser_LDAP
public static $classMap = array (
'OCA\\User_LDAP\\Access' => __DIR__ . '/..' . '/../lib/Access.php',
+ 'OCA\\User_LDAP\\AccessFactory' => __DIR__ . '/..' . '/../lib/AccessFactory.php',
'OCA\\User_LDAP\\AppInfo\\Application' => __DIR__ . '/..' . '/../lib/AppInfo/Application.php',
'OCA\\User_LDAP\\BackendUtility' => __DIR__ . '/..' . '/../lib/BackendUtility.php',
'OCA\\User_LDAP\\Command\\CheckUser' => __DIR__ . '/..' . '/../lib/Command/CheckUser.php',
@@ -31,6 +32,7 @@ class ComposerStaticInitUser_LDAP
'OCA\\User_LDAP\\Command\\TestConfig' => __DIR__ . '/..' . '/../lib/Command/TestConfig.php',
'OCA\\User_LDAP\\Configuration' => __DIR__ . '/..' . '/../lib/Configuration.php',
'OCA\\User_LDAP\\Connection' => __DIR__ . '/..' . '/../lib/Connection.php',
+ 'OCA\\User_LDAP\\ConnectionFactory' => __DIR__ . '/..' . '/../lib/ConnectionFactory.php',
'OCA\\User_LDAP\\Controller\\ConfigAPIController' => __DIR__ . '/..' . '/../lib/Controller/ConfigAPIController.php',
'OCA\\User_LDAP\\Controller\\RenewPasswordController' => __DIR__ . '/..' . '/../lib/Controller/RenewPasswordController.php',
'OCA\\User_LDAP\\Exceptions\\ConstraintViolationException' => __DIR__ . '/..' . '/../lib/Exceptions/ConstraintViolationException.php',
diff --git a/apps/user_ldap/lib/AccessFactory.php b/apps/user_ldap/lib/AccessFactory.php
new file mode 100644
index 00000000000..45ff779bb01
--- /dev/null
+++ b/apps/user_ldap/lib/AccessFactory.php
@@ -0,0 +1,61 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * 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/>.
+ *
+ */
+
+namespace OCA\User_LDAP;
+
+
+use OCA\User_LDAP\User\Manager;
+use OCP\IConfig;
+
+class AccessFactory {
+ /** @var ILDAPWrapper */
+ protected $ldap;
+ /** @var Manager */
+ protected $userManager;
+ /** @var Helper */
+ protected $helper;
+ /** @var IConfig */
+ protected $config;
+
+ public function __construct(
+ ILDAPWrapper $ldap,
+ Manager $userManager,
+ Helper $helper,
+ IConfig $config)
+ {
+ $this->ldap = $ldap;
+ $this->userManager = $userManager;
+ $this->helper = $helper;
+ $this->config = $config;
+ }
+
+ public function get(Connection $connection) {
+ return new Access(
+ $connection,
+ $this->ldap,
+ $this->userManager,
+ $this->helper,
+ $this->config
+ );
+ }
+}
diff --git a/apps/user_ldap/lib/ConnectionFactory.php b/apps/user_ldap/lib/ConnectionFactory.php
new file mode 100644
index 00000000000..0857afdcc8d
--- /dev/null
+++ b/apps/user_ldap/lib/ConnectionFactory.php
@@ -0,0 +1,38 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * 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/>.
+ *
+ */
+
+namespace OCA\User_LDAP;
+
+
+class ConnectionFactory {
+ /** @var ILDAPWrapper */
+ private $ldap;
+
+ public function __construct(ILDAPWrapper $ldap) {
+ $this->ldap = $ldap;
+ }
+
+ public function get($prefix) {
+ return new Connection($this->ldap, $prefix, 'user_ldap');
+ }
+}
diff --git a/apps/user_ldap/lib/Jobs/Sync.php b/apps/user_ldap/lib/Jobs/Sync.php
index d8e0e854718..b78a1947e27 100644
--- a/apps/user_ldap/lib/Jobs/Sync.php
+++ b/apps/user_ldap/lib/Jobs/Sync.php
@@ -26,8 +26,10 @@ namespace OCA\User_LDAP\Jobs;
use OC\BackgroundJob\TimedJob;
use OC\ServerNotAvailableException;
use OCA\User_LDAP\Access;
+use OCA\User_LDAP\AccessFactory;
use OCA\User_LDAP\Configuration;
use OCA\User_LDAP\Connection;
+use OCA\User_LDAP\ConnectionFactory;
use OCA\User_LDAP\FilesystemHelper;
use OCA\User_LDAP\Helper;
use OCA\User_LDAP\LDAP;
@@ -62,6 +64,10 @@ class Sync extends TimedJob {
protected $ncUserManager;
/** @var IManager */
protected $notificationManager;
+ /** @var ConnectionFactory */
+ protected $connectionFactory;
+ /** @var AccessFactory */
+ protected $accessFactory;
public function __construct() {
$this->setInterval(
@@ -112,7 +118,7 @@ class Sync extends TimedJob {
/**
* @param array $argument
*/
- protected function run($argument) {
+ public function run($argument) {
$this->setArgument($argument);
$isBackgroundJobModeAjax = $this->config
@@ -140,11 +146,11 @@ class Sync extends TimedJob {
if ($expectMoreResults) {
$this->increaseOffset($cycleData);
} else {
- $this->determineNextCycle();
+ $this->determineNextCycle($cycleData);
}
$this->updateInterval();
} catch (ServerNotAvailableException $e) {
- $this->determineNextCycle();
+ $this->determineNextCycle($cycleData);
}
}
@@ -153,8 +159,8 @@ class Sync extends TimedJob {
* @return bool whether more results are expected from the same configuration
*/
public function runCycle($cycleData) {
- $connection = new Connection($this->ldap, $cycleData['prefix']);
- $access = new Access($connection, $this->ldap, $this->userManager, $this->ldapHelper, $this->config);
+ $connection = $this->connectionFactory->get($cycleData['prefix']);
+ $access = $this->accessFactory->get($connection);
$access->setUserMapper($this->mapper);
$filter = $access->combineFilterWithAnd(array(
@@ -173,7 +179,7 @@ class Sync extends TimedJob {
if($connection->ldapPagingSize === 0) {
return true;
}
- return count($results) !== $connection->ldapPagingSize;
+ return count($results) >= $connection->ldapPagingSize;
}
/**
@@ -246,7 +252,7 @@ class Sync extends TimedJob {
* @param $cycleData
* @return bool
*/
- protected function qualifiesToRun($cycleData) {
+ public function qualifiesToRun($cycleData) {
$lastChange = $this->config->getAppValue('user_ldap', $cycleData['prefix'] . '_lastChange', 0);
if((time() - $lastChange) > 60 * 30) {
return true;
@@ -358,5 +364,22 @@ class Sync extends TimedJob {
} else {
$this->mapper = new UserMapping($this->dbc);
}
+
+ if(isset($argument['connectionFactory'])) {
+ $this->connectionFactory = $argument['connectionFactory'];
+ } else {
+ $this->connectionFactory = new ConnectionFactory($this->ldap);
+ }
+
+ if(isset($argument['accessFactory'])) {
+ $this->accessFactory = $argument['accessFactory'];
+ } else {
+ $this->accessFactory = new AccessFactory(
+ $this->ldap,
+ $this->userManager,
+ $this->ldapHelper,
+ $this->config
+ );
+ }
}
}
diff --git a/apps/user_ldap/tests/Jobs/SyncTest.php b/apps/user_ldap/tests/Jobs/SyncTest.php
index f8a44de87e8..f8852a46664 100644
--- a/apps/user_ldap/tests/Jobs/SyncTest.php
+++ b/apps/user_ldap/tests/Jobs/SyncTest.php
@@ -23,6 +23,10 @@
namespace OCA\User_LDAP\Tests\Jobs;
+use OCA\User_LDAP\Access;
+use OCA\User_LDAP\AccessFactory;
+use OCA\User_LDAP\Connection;
+use OCA\User_LDAP\ConnectionFactory;
use OCA\User_LDAP\Helper;
use OCA\User_LDAP\Jobs\Sync;
use OCA\User_LDAP\LDAP;
@@ -33,6 +37,7 @@ use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IUserManager;
use OCP\Notification\IManager;
+use function Sodium\memcmp;
use Test\TestCase;
class SyncTest extends TestCase {
@@ -59,6 +64,10 @@ class SyncTest extends TestCase {
protected $ncUserManager;
/** @var IManager|\PHPUnit_Framework_MockObject_MockObject */
protected $notificationManager;
+ /** @var ConnectionFactory|\PHPUnit_Framework_MockObject_MockObject */
+ protected $connectionFactory;
+ /** @var AccessFactory|\PHPUnit_Framework_MockObject_MockObject */
+ protected $accessFactory;
public function setUp() {
parent::setUp();
@@ -72,6 +81,8 @@ class SyncTest extends TestCase {
$this->dbc = $this->createMock(IDBConnection::class);
$this->ncUserManager = $this->createMock(IUserManager::class);
$this->notificationManager = $this->createMock(IManager::class);
+ $this->connectionFactory = $this->createMock(ConnectionFactory::class);
+ $this->accessFactory = $this->createMock(AccessFactory::class);
$this->arguments = [
'helper' => $this->helper,
@@ -83,6 +94,8 @@ class SyncTest extends TestCase {
'dbc' => $this->dbc,
'ncUserManager' => $this->ncUserManager,
'notificationManager' => $this->notificationManager,
+ 'connectionFactory' => $this->connectionFactory,
+ 'accessFactory' => $this->accessFactory,
];
$this->sync = new Sync();
@@ -141,4 +154,216 @@ class SyncTest extends TestCase {
$this->sync->updateInterval();
}
+ public function moreResultsProvider() {
+ return [
+ [ 3, 3, true ],
+ [ 3, 5, true ],
+ [ 3, 2, false]
+ ];
+ }
+
+ /**
+ * @dataProvider moreResultsProvider
+ */
+ public function testMoreResults($pagingSize, $results, $expected) {
+ $connection = $this->createMock(Connection::class);
+ $this->connectionFactory->expects($this->any())
+ ->method('get')
+ ->willReturn($connection);
+ $connection->expects($this->any())
+ ->method('__get')
+ ->willReturnCallback(function ($key) use ($pagingSize) {
+ if($key === 'ldapPagingSize') {
+ return $pagingSize;
+ }
+ return null;
+ });
+
+ /** @var Access|\PHPUnit_Framework_MockObject_MockObject $access */
+ $access = $this->createMock(Access::class);
+ $this->accessFactory->expects($this->any())
+ ->method('get')
+ ->with($connection)
+ ->willReturn($access);
+
+ $access->expects($this->once())
+ ->method('fetchListOfUsers')
+ ->willReturn(array_pad([], $results, 'someUser'));
+ $access->connection = $connection;
+ $access->userManager = $this->userManager;
+
+ $this->sync->setArgument($this->arguments);
+ $hasMoreResults = $this->sync->runCycle(['prefix' => 's01', 'offset' => 100]);
+ $this->assertSame($expected, $hasMoreResults);
+ }
+
+ public function cycleDataProvider() {
+ $lastCycle = ['prefix' => 's01', 'offset' => 1000];
+ $lastCycle2 = ['prefix' => '', 'offset' => 1000];
+ return [
+ [ null, ['s01'], ['prefix' => 's01', 'offset' => 0] ],
+ [ null, [''], ['prefix' => '', 'offset' => 0] ],
+ [ $lastCycle, ['s01', 's02'], ['prefix' => 's02', 'offset' => 0] ],
+ [ $lastCycle, [''], ['prefix' => '', 'offset' => 0] ],
+ [ $lastCycle2, ['', 's01'], ['prefix' => 's01', 'offset' => 0] ],
+ [ $lastCycle, [], null ],
+ ];
+ }
+
+ /**
+ * @dataProvider cycleDataProvider
+ */
+ public function testDetermineNextCycle($cycleData, $prefixes, $expectedCycle) {
+ $this->helper->expects($this->any())
+ ->method('getServerConfigurationPrefixes')
+ ->with(true)
+ ->willReturn($prefixes);
+
+ if(is_array($expectedCycle)) {
+ $this->config->expects($this->exactly(2))
+ ->method('setAppValue')
+ ->withConsecutive(
+ ['user_ldap', 'background_sync_prefix', $expectedCycle['prefix']],
+ ['user_ldap', 'background_sync_offset', $expectedCycle['offset']]
+ );
+ } else {
+ $this->config->expects($this->never())
+ ->method('setAppValue');
+ }
+
+ $this->sync->setArgument($this->arguments);
+ $nextCycle = $this->sync->determineNextCycle($cycleData);
+
+ if($expectedCycle === null) {
+ $this->assertNull($nextCycle);
+ } else {
+ $this->assertSame($expectedCycle['prefix'], $nextCycle['prefix']);
+ $this->assertSame($expectedCycle['offset'], $nextCycle['offset']);
+ }
+ }
+
+ public function testQualifiesToRun() {
+ $cycleData = ['prefix' => 's01'];
+
+ $this->config->expects($this->exactly(2))
+ ->method('getAppValue')
+ ->willReturnOnConsecutiveCalls(time() - 60*40, time() - 60*20);
+
+ $this->sync->setArgument($this->arguments);
+ $this->assertTrue($this->sync->qualifiesToRun($cycleData));
+ $this->assertFalse($this->sync->qualifiesToRun($cycleData));
+ }
+
+ public function runDataProvider() {
+ return [
+ #0 - one LDAP server, reset
+ [[
+ 'prefixes' => [''],
+ 'scheduledCycle' => ['prefix' => '', 'offset' => '4500'],
+ 'pagingSize' => 500,
+ 'usersThisCycle' => 0,
+ 'expectedNextCycle' => ['prefix' => '', 'offset' => '0'],
+ 'mappedUsers' => 123,
+ ]],
+ #1 - 2 LDAP servers, next prefix
+ [[
+ 'prefixes' => ['', 's01'],
+ 'scheduledCycle' => ['prefix' => '', 'offset' => '4500'],
+ 'pagingSize' => 500,
+ 'usersThisCycle' => 0,
+ 'expectedNextCycle' => ['prefix' => 's01', 'offset' => '0'],
+ 'mappedUsers' => 123,
+ ]],
+ #2 - 2 LDAP servers, rotate prefix
+ [[
+ 'prefixes' => ['', 's01'],
+ 'scheduledCycle' => ['prefix' => 's01', 'offset' => '4500'],
+ 'pagingSize' => 500,
+ 'usersThisCycle' => 0,
+ 'expectedNextCycle' => ['prefix' => '', 'offset' => '0'],
+ 'mappedUsers' => 123,
+ ]],
+ ];
+ }
+
+ /**
+ * @dataProvider runDataProvider
+ */
+ public function testRun($runData) {
+ $this->config->expects($this->any())
+ ->method('getAppValue')
+ ->willReturnCallback(function($app, $key, $default) use ($runData) {
+ if($app === 'core' && $key === 'backgroundjobs_mode') {
+ return 'cron';
+ }
+ if($app = 'user_ldap') {
+ // for getCycle()
+ if($key === 'background_sync_prefix') {
+ return $runData['scheduledCycle']['prefix'];
+ }
+ if($key === 'background_sync_offset') {
+ return $runData['scheduledCycle']['offset'];
+ }
+ // for qualifiesToRun()
+ if($key === $runData['scheduledCycle']['prefix'] . '_lastChange') {
+ return time() - 60*40;
+ }
+ // for getMinPagingSize
+ if($key === $runData['scheduledCycle']['prefix'] . 'ldap_paging_size') {
+ return $runData['pagingSize'];
+ }
+ }
+
+ return $default;
+ });
+ $this->config->expects($this->exactly(3))
+ ->method('setAppValue')
+ ->withConsecutive(
+ ['user_ldap', 'background_sync_prefix', $runData['expectedNextCycle']['prefix']],
+ ['user_ldap', 'background_sync_offset', $runData['expectedNextCycle']['offset']],
+ ['user_ldap', 'background_sync_interval', $this->anything()]
+ );
+ $this->config->expects($this->any())
+ ->method('getAppKeys')
+ ->with('user_ldap')
+ ->willReturn([$runData['scheduledCycle']['prefix'] . 'ldap_paging_size']);
+
+ $this->helper->expects($this->any())
+ ->method('getServerConfigurationPrefixes')
+ ->with(true)
+ ->willReturn($runData['prefixes']);
+
+ $connection = $this->createMock(Connection::class);
+ $this->connectionFactory->expects($this->any())
+ ->method('get')
+ ->willReturn($connection);
+ $connection->expects($this->any())
+ ->method('__get')
+ ->willReturnCallback(function ($key) use ($runData) {
+ if($key === 'ldapPagingSize') {
+ return $runData['pagingSize'];
+ }
+ return null;
+ });
+
+ /** @var Access|\PHPUnit_Framework_MockObject_MockObject $access */
+ $access = $this->createMock(Access::class);
+ $this->accessFactory->expects($this->any())
+ ->method('get')
+ ->with($connection)
+ ->willReturn($access);
+
+ $access->expects($this->once())
+ ->method('fetchListOfUsers')
+ ->willReturn(array_pad([], $runData['usersThisCycle'], 'someUser'));
+ $access->connection = $connection;
+ $access->userManager = $this->userManager;
+
+ $this->mapper->expects($this->any())
+ ->method('count')
+ ->willReturn($runData['mappedUsers']);
+
+ $this->sync->run($this->arguments);
+ }
+
}
diff --git a/build/files-checker.php b/build/files-checker.php
index 66c44bd971b..20d8b4b5f33 100644
--- a/build/files-checker.php
+++ b/build/files-checker.php
@@ -49,6 +49,7 @@ $expectedFiles = [
'build',
'buildjsdocs.sh',
'CHANGELOG.md',
+ 'CODE_OF_CONDUCT.md',
'composer.json',
'config',
'console.php',
diff --git a/config/config.sample.php b/config/config.sample.php
index 05efcaa2738..5f29933ec65 100644
--- a/config/config.sample.php
+++ b/config/config.sample.php
@@ -849,25 +849,16 @@ $CONFIG = array(
* The maximum width, in pixels, of a preview. A value of ``null`` means there
* is no limit.
*
- * Defaults to ``2048``
+ * Defaults to ``4096``
*/
-'preview_max_x' => 2048,
+'preview_max_x' => 4096,
/**
* The maximum height, in pixels, of a preview. A value of ``null`` means there
* is no limit.
*
- * Defaults to ``2048``
+ * Defaults to ``4096``
*/
-'preview_max_y' => 2048,
-/**
- * If a lot of small pictures are stored on the Nextcloud instance and the
- * preview system generates blurry previews, you might want to consider setting
- * a maximum scale factor. By default, pictures are upscaled to 10 times the
- * original size. A value of ``1`` or ``null`` disables scaling.
- *
- * Defaults to ``2``
- */
-'preview_max_scale_factor' => 10,
+'preview_max_y' => 4096,
/**
* max file size for generating image previews with imagegd (default behavior)
diff --git a/core/Controller/OCJSController.php b/core/Controller/OCJSController.php
index de880968a69..8db26dd3d38 100644
--- a/core/Controller/OCJSController.php
+++ b/core/Controller/OCJSController.php
@@ -34,11 +34,11 @@ use OCP\AppFramework\Http\DataDisplayResponse;
use OCP\Defaults;
use OCP\IConfig;
use OCP\IGroupManager;
-use OCP\IL10N;
use OCP\IRequest;
use OCP\ISession;
use OCP\IURLGenerator;
use OCP\IUserSession;
+use OCP\L10N\IFactory;
class OCJSController extends Controller {
@@ -50,7 +50,7 @@ class OCJSController extends Controller {
*
* @param string $appName
* @param IRequest $request
- * @param IL10N $l
+ * @param IFactory $l10nFactory
* @param Defaults $defaults
* @param IAppManager $appManager
* @param ISession $session
@@ -62,7 +62,7 @@ class OCJSController extends Controller {
*/
public function __construct($appName,
IRequest $request,
- IL10N $l,
+ IFactory $l10nFactory,
Defaults $defaults,
IAppManager $appManager,
ISession $session,
@@ -74,7 +74,7 @@ class OCJSController extends Controller {
parent::__construct($appName, $request);
$this->helper = new JSConfigHelper(
- $l,
+ $l10nFactory->get('lib'),
$defaults,
$appManager,
$session,
diff --git a/core/css/apps.scss b/core/css/apps.scss
index e6ead27e12b..41eea3bb524 100644
--- a/core/css/apps.scss
+++ b/core/css/apps.scss
@@ -235,6 +235,7 @@ kbd {
&:first-child img {
margin-right: 11px;
width: 16px;
+ height: 16px;
margin-left: -30px;
}
diff --git a/core/css/fixes.scss b/core/css/fixes.scss
index 0303b4d751a..09ab9c1d244 100644
--- a/core/css/fixes.scss
+++ b/core/css/fixes.scss
@@ -20,6 +20,7 @@ select {
.ie .header-left #navigation,
.ie .ui-datepicker,
.ie .ui-timepicker.ui-widget,
-.ie #appmenu li span {
+.ie #appmenu li span,
+.ie .tooltip-inner {
box-shadow: 0 1px 10px $color-box-shadow;
}
diff --git a/core/css/guest.css b/core/css/guest.css
index 4256c66302f..ecc3da9d081 100644
--- a/core/css/guest.css
+++ b/core/css/guest.css
@@ -93,7 +93,7 @@ body {
form {
position: relative;
width: 280px;
- margin: 16px auto;
+ margin: auto;
padding: 0;
}
form fieldset {
@@ -410,7 +410,6 @@ form .warning input[type='checkbox']+label {
padding: 12px;
margin-top: -6px;
color: #fff;
- opacity: .7;
}
#forgot-password {
padding: 11px;
@@ -579,8 +578,7 @@ fieldset.update legend + p {
margin-bottom: 15px;
}
p.info {
- margin: 0 auto;
- padding-top: 20px;
+ margin: 20px auto;
text-shadow: 0 0 2px rgba(0, 0, 0, .4); // better readability on bright background
-webkit-user-select: none;
-moz-user-select: none;
diff --git a/core/css/header.scss b/core/css/header.scss
index 98ea71f2ed2..7021762bf7f 100644
--- a/core/css/header.scss
+++ b/core/css/header.scss
@@ -206,12 +206,15 @@ nav {
margin-left: -54px;
}
-.header-left #navigation,
-.ui-datepicker,
-.ui-timepicker.ui-widget {
+.header-left #navigation {
position: relative;
left: -100%;
width: 160px;
+}
+
+.header-left #navigation,
+.ui-datepicker,
+.ui-timepicker.ui-widget {
background-color: $color-main-background;
filter: drop-shadow(0 1px 10px $color-box-shadow);
&:after {
diff --git a/core/css/styles.scss b/core/css/styles.scss
index c479d6df888..4b02041976b 100644
--- a/core/css/styles.scss
+++ b/core/css/styles.scss
@@ -234,7 +234,7 @@ body {
padding: 0;
margin: 0;
background-color: rgba($color-main-background, 0.95);
- z-index: 55;
+ z-index: 60;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
@@ -1035,15 +1035,6 @@ code {
background-color: inherit;
}
td {
- > * {
- border-radius: 50%;
- text-align: center;
- font-weight: normal;
- color: $color-main-text;
- padding: 6px;
- line-height: 12px;
- }
-
&.ui-datepicker-today a:not(.ui-state-hover) {
background-color: nc-lighten($color-main-text, 86%);
}
@@ -1056,7 +1047,7 @@ code {
font-weight: bold;
}
- &.ui-datepicker-week-end :not(.ui-state-hover),
+ &.ui-datepicker-week-end:not(.ui-state-disabled) :not(.ui-state-hover),
.ui-priority-secondary:not(.ui-state-hover) {
color: nc-lighten($color-main-text, 33%);
opacity: .8;
@@ -1099,26 +1090,25 @@ code {
font-weight: 300;
}
}
+ /* AM/PM fix */
+ table.ui-timepicker tr .ui-timepicker-hour-cell:first-child {
+ margin-left: 30px;
+ }
.ui-timepicker-table {
th {
font-weight: normal;
color: nc-lighten($color-main-text, 33%);
opacity: .8;
+ &.periods {
+ padding: 0;
+ width: 30px;
+ line-height: 30px;
+ }
}
tr:hover {
background-color: inherit;
}
td {
- > * {
- border-radius: 50%;
- text-align: center;
- font-weight: normal;
- color: $color-main-text;
- padding: 8px 7px;
- font-size: .9em;
- line-height: 12px;
- }
-
&.ui-timepicker-hour-cell a.ui-state-active,
&.ui-timepicker-minute-cell a.ui-state-active,
.ui-state-hover,
@@ -1139,6 +1129,37 @@ code {
}
}
+/* ---- jQuery UI datepicker & timepicker global rules ---- */
+.ui-widget.ui-datepicker .ui-datepicker-calendar,
+.ui-widget.ui-timepicker table.ui-timepicker {
+ tr {
+ display: flex;
+ flex-wrap: nowrap;
+ justify-content: space-between;
+ td {
+ display: block;
+ flex: 1 1;
+ margin: 0;
+ padding: 2px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ > * {
+ border-radius: 50%;
+ text-align: center;
+ font-weight: normal;
+ color: $color-main-text;
+ display: block;
+ line-height: 18px;
+ width: 18px;
+ height: 18px;
+ padding: 3px;
+ font-size: .9em;
+ }
+ }
+ }
+}
+
/* ---- DIALOGS ---- */
#oc-dialog-filepicker-content {
diff --git a/core/css/tooltip.scss b/core/css/tooltip.scss
index e9982b580ca..a974e05e1a6 100644
--- a/core/css/tooltip.scss
+++ b/core/css/tooltip.scss
@@ -31,6 +31,7 @@
font-size: 12px;
opacity: 0;
z-index: 100000;
+ filter: drop-shadow(0 1px 10px $color-box-shadow);
&.in {
opacity: 1;
}
@@ -115,7 +116,6 @@
padding: 5px 8px;
background-color: $color-main-background;
color: $color-main-text;
- box-shadow: 0 1px 10px $color-box-shadow;
text-align: center;
border-radius: $border-radius;
}
diff --git a/core/js/jquery.avatar.js b/core/js/jquery.avatar.js
index 958f0f9edd7..6da86341c1e 100644
--- a/core/js/jquery.avatar.js
+++ b/core/js/jquery.avatar.js
@@ -110,9 +110,8 @@
// If the new image loads successfully set it.
img.onload = function() {
- $div.text('');
- $div.append(img);
$div.clearimageplaceholder();
+ $div.append(img);
if(typeof callback === 'function') {
callback();
@@ -127,7 +126,6 @@
$div.imageplaceholder(user, displayname);
} else {
setAvatarForUnknownUser($div);
- $div.removeClass('icon-loading');
}
if(typeof callback === 'function') {
@@ -136,7 +134,6 @@
};
$div.addClass('icon-loading');
- $div.show();
img.width = size;
img.height = size;
img.src = url;
diff --git a/core/js/js.js b/core/js/js.js
index f9a5f2b3381..872761c02bb 100644
--- a/core/js/js.js
+++ b/core/js/js.js
@@ -1675,13 +1675,16 @@ function initCore() {
OC.PasswordConfirmation = {
callback: null,
-
+ pageLoadTime: null,
init: function() {
$('.password-confirm-required').on('click', _.bind(this.requirePasswordConfirmation, this));
+ this.pageLoadTime = moment.now();
},
requiresPasswordConfirmation: function() {
- var timeSinceLogin = moment.now() - (nc_lastLogin * 1000);
+ var serverTimeDiff = this.pageLoadTime - (nc_pageLoad * 1000);
+ var timeSinceLogin = moment.now() - (serverTimeDiff + (nc_lastLogin * 1000));
+
// if timeSinceLogin > 30 minutes and user backend allows password confirmation
return (backendAllowsPasswordConfirmation && timeSinceLogin > 30 * 60 * 1000);
},
diff --git a/core/js/lostpassword.js b/core/js/lostpassword.js
index b44962f552e..8c770047444 100644
--- a/core/js/lostpassword.js
+++ b/core/js/lostpassword.js
@@ -50,6 +50,7 @@ OC.Lostpassword = {
event.preventDefault();
$('#lost-password').hide();
+ $('.wrongPasswordMsg').hide();
$('#lost-password-back').slideDown().fadeIn();
$('.remember-login-container').slideUp().fadeOut();
$('#submit-wrapper').slideUp().fadeOut();
diff --git a/core/js/placeholder.js b/core/js/placeholder.js
index 5cf7b9095ad..29f91b6698d 100644
--- a/core/js/placeholder.js
+++ b/core/js/placeholder.js
@@ -156,6 +156,7 @@
this.css('text-align', '');
this.css('line-height', '');
this.css('font-size', '');
+ this.html('');
this.removeClass('icon-loading');
};
}(jQuery));
diff --git a/core/js/public/comments.js b/core/js/public/comments.js
index 6de7ff7d38a..ac0bf8e0ab7 100644
--- a/core/js/public/comments.js
+++ b/core/js/public/comments.js
@@ -43,7 +43,7 @@
}
var linkText = url.replace(self.protocolRegex, '');
- return '<a class="external" href="' + url + '">' + linkText + '</a>';
+ return '<a class="external" target="_blank" rel="noopener noreferrer" href="' + url + '">' + linkText + '</a>';
});
},
diff --git a/core/js/sharedialogshareelistview.js b/core/js/sharedialogshareelistview.js
index b4828e3b0dc..30cbeff3c64 100644
--- a/core/js/sharedialogshareelistview.js
+++ b/core/js/sharedialogshareelistview.js
@@ -116,7 +116,7 @@
'<label for="expireDate-{{cid}}-{{shareId}}">{{expireDateLabel}}</label>' +
'<div class="expirationDateContainer-{{cid}}-{{shareId}} {{#unless hasExpireDate}}hidden{{/unless}}">' +
' <label for="expirationDatePicker-{{cid}}-{{shareId}}" class="hidden-visually" value="{{expirationDate}}">{{expirationLabel}}</label>' +
- ' <input id="expirationDatePicker-{{cid}}-{{shareId}}" class="datepicker" type="text" placeholder="{{expirationDatePlaceholder}}" value="{{expireDate}}" />' +
+ ' <input id="expirationDatePicker-{{cid}}-{{shareId}}" class="datepicker" type="text" placeholder="{{expirationDatePlaceholder}}" value="{{#if hasExpireDate}}{{expireDate}}{{else}}{{defaultExpireDate}}{{/if}}" />' +
'</div>' +
'</span>' +
'</li>' +
@@ -266,6 +266,8 @@
expireDateLabel: t('core', 'Set expiration date'),
passwordLabel: t('core', 'Password protect'),
crudsLabel: t('core', 'Access control'),
+ expirationDatePlaceholder: t('core', 'Expiration date'),
+ defaultExpireDate: moment().add(1, 'day').format('DD-MM-YYYY'), // Can't expire today
triangleSImage: OC.imagePath('core', 'actions/triangle-s'),
isResharingAllowed: this.configModel.get('isResharingAllowed'),
isPasswordForMailSharesRequired: this.configModel.get('isPasswordForMailSharesRequired'),
@@ -513,19 +515,14 @@
var shareId = li.data('share-id');
var expirationDatePicker = '#expirationDatePicker-' + this.cid + '-' + shareId;
var view = this;
- $(expirationDatePicker).closest('div').datepicker({
+ $(expirationDatePicker).datepicker({
dateFormat : 'dd-mm-yy',
- onSelect:
- function (expireDate) {
- view.setExpirationDate(shareId, expireDate);
- },
- onClose:
- function () {
- $(expirationDatePicker).removeClass('hidden-visually');
- }
+ onSelect: function (expireDate) {
+ view.setExpirationDate(shareId, expireDate);
+ }
});
+ $(expirationDatePicker).focus();
- $(expirationDatePicker).addClass('hidden-visually');
},
setExpirationDate: function(shareId, expireDate) {
diff --git a/core/js/tests/specs/coreSpec.js b/core/js/tests/specs/coreSpec.js
index b6c617303cf..616e7509f7c 100644
--- a/core/js/tests/specs/coreSpec.js
+++ b/core/js/tests/specs/coreSpec.js
@@ -1539,4 +1539,65 @@ describe('Core base tests', function() {
expect(snapperStub.close.calledTwice).toBe(true);
});
});
+ describe('Requires password confirmation', function () {
+ var stubMomentNow;
+ var stubJsPageLoadTime;
+
+ afterEach(function () {
+ delete window.nc_pageLoad;
+ delete window.nc_lastLogin;
+ delete window.backendAllowsPasswordConfirmation;
+
+ stubMomentNow.restore();
+ stubJsPageLoadTime.restore();
+ });
+
+ it('should not show the password confirmation dialog when server time is earlier than local time', function () {
+ // add server variables
+ window.nc_pageLoad = parseInt(new Date(2018, 0, 3, 1, 15, 0).getTime() / 1000);
+ window.nc_lastLogin = parseInt(new Date(2018, 0, 3, 1, 0, 0).getTime() / 1000);
+ window.backendAllowsPasswordConfirmation = true;
+
+ stubJsPageLoadTime = sinon.stub(OC.PasswordConfirmation, 'pageLoadTime').value(new Date(2018, 0, 3, 12, 15, 0).getTime());
+ stubMomentNow = sinon.stub(moment, 'now').returns(new Date(2018, 0, 3, 12, 20, 0).getTime());
+
+ expect(OC.PasswordConfirmation.requiresPasswordConfirmation()).toBeFalsy();
+ });
+
+ it('should show the password confirmation dialog when server time is earlier than local time', function () {
+ // add server variables
+ window.nc_pageLoad = parseInt(new Date(2018, 0, 3, 1, 15, 0).getTime() / 1000);
+ window.nc_lastLogin = parseInt(new Date(2018, 0, 3, 1, 0, 0).getTime() / 1000);
+ window.backendAllowsPasswordConfirmation = true;
+
+ stubJsPageLoadTime = sinon.stub(OC.PasswordConfirmation, 'pageLoadTime').value(new Date(2018, 0, 3, 12, 15, 0).getTime());
+ stubMomentNow = sinon.stub(moment, 'now').returns(new Date(2018, 0, 3, 12, 31, 0).getTime());
+
+ expect(OC.PasswordConfirmation.requiresPasswordConfirmation()).toBeTruthy();
+ });
+
+ it('should not show the password confirmation dialog when server time is later than local time', function () {
+ // add server variables
+ window.nc_pageLoad = parseInt(new Date(2018, 0, 3, 23, 15, 0).getTime() / 1000);
+ window.nc_lastLogin = parseInt(new Date(2018, 0, 3, 23, 0, 0).getTime() / 1000);
+ window.backendAllowsPasswordConfirmation = true;
+
+ stubJsPageLoadTime = sinon.stub(OC.PasswordConfirmation, 'pageLoadTime').value(new Date(2018, 0, 3, 12, 15, 0).getTime());
+ stubMomentNow = sinon.stub(moment, 'now').returns(new Date(2018, 0, 3, 12, 20, 0).getTime());
+
+ expect(OC.PasswordConfirmation.requiresPasswordConfirmation()).toBeFalsy();
+ });
+
+ it('should show the password confirmation dialog when server time is later than local time', function () {
+ // add server variables
+ window.nc_pageLoad = parseInt(new Date(2018, 0, 3, 23, 15, 0).getTime() / 1000);
+ window.nc_lastLogin = parseInt(new Date(2018, 0, 3, 23, 0, 0).getTime() / 1000);
+ window.backendAllowsPasswordConfirmation = true;
+
+ stubJsPageLoadTime = sinon.stub(OC.PasswordConfirmation, 'pageLoadTime').value(new Date(2018, 0, 3, 12, 15, 0).getTime());
+ stubMomentNow = sinon.stub(moment, 'now').returns(new Date(2018, 0, 3, 12, 31, 0).getTime());
+
+ expect(OC.PasswordConfirmation.requiresPasswordConfirmation()).toBeTruthy();
+ });
+ });
});
diff --git a/core/js/tests/specs/jquery.avatarSpec.js b/core/js/tests/specs/jquery.avatarSpec.js
index bdd1fdcc163..4e13b7f26ff 100644
--- a/core/js/tests/specs/jquery.avatarSpec.js
+++ b/core/js/tests/specs/jquery.avatarSpec.js
@@ -202,8 +202,6 @@ describe('jquery.avatar tests', function() {
expect(window.Image().height).toEqual(32);
expect(window.Image().width).toEqual(32);
expect(window.Image().src).toEqual('http://localhost/index.php/avatar/foo/32');
-
- expect($div.css('display')).toEqual('block');
});
it('callback called', function() {
diff --git a/core/templates/layout.user.php b/core/templates/layout.user.php
index 127e794e120..32762e2c240 100644
--- a/core/templates/layout.user.php
+++ b/core/templates/layout.user.php
@@ -41,19 +41,17 @@
</div>
</a>
- <ul id="appmenu">
+ <ul id="appmenu" <?php if ($_['themingInvertMenu']) { ?>class="inverted"<?php } ?>>
<?php foreach ($_['navigation'] as $entry): ?>
<li data-id="<?php p($entry['id']); ?>" class="hidden">
<a href="<?php print_unescaped($entry['href']); ?>"
<?php if ($entry['active']): ?> class="active"<?php endif; ?>>
- <?php if ($_['themingInvertMenu']) { ?>
<svg width="20" height="20" viewBox="0 0 20 20">
- <defs><filter id="invertMenuMain-<?php p($entry['id']); ?>"><feColorMatrix in="SourceGraphic" type="matrix" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0" /></filter></defs>
- <image x="0" y="0" width="20" height="20" preserveAspectRatio="xMinYMin meet" filter="url(#invertMenuMain-<?php p($entry['id']); ?>)" xlink:href="<?php print_unescaped($entry['icon'] . '?v=' . $_['versionHash']); ?>" class="app-icon" /></svg>
- <?php } else { ?>
- <img src="<?php print_unescaped($entry['icon'] . '?v=' . $_['versionHash']); ?>"
- class="app-icon" alt="<?php p($entry['name']); ?>" />
- <?php } ?>
+ <?php if ($_['themingInvertMenu']) { ?>
+ <defs><filter id="invertMenuMain-<?php p($entry['id']); ?>"><feColorMatrix in="SourceGraphic" type="matrix" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0" /></filter></defs>
+ <?php } ?>
+ <image x="0" y="0" width="20" height="20" preserveAspectRatio="xMinYMin meet"<?php if ($_['themingInvertMenu']) { ?> filter="url(#invertMenuMain-<?php p($entry['id']); ?>)"<?php } ?> xlink:href="<?php print_unescaped($entry['icon'] . '?v=' . $_['versionHash']); ?>" class="app-icon" />
+ </svg>
<div class="icon-loading-small-dark"
style="display:none;"></div>
</a>
diff --git a/core/templates/login.php b/core/templates/login.php
index d28c92e36ef..de991e08d97 100644
--- a/core/templates/login.php
+++ b/core/templates/login.php
@@ -51,17 +51,17 @@ script('core', 'merged-login');
<label for="password" class="infield"><?php p($l->t('Password')); ?></label>
</p>
- <?php if (!empty($_['invalidpassword'])) { ?>
- <p class="warning">
- <?php p($l->t('Wrong password.')); ?>
- </p>
- <?php } ?>
-
<div id="submit-wrapper">
<input type="submit" id="submit" class="login primary" title="" value="<?php p($l->t('Log in')); ?>" disabled="disabled" />
<div class="submit-icon icon-confirm-white"></div>
</div>
+ <?php if (!empty($_['invalidpassword'])) { ?>
+ <p class="warning wrongPasswordMsg">
+ <?php p($l->t('Wrong password.')); ?>
+ </p>
+ <?php } ?>
+
<?php if (!empty($_['canResetPassword'])) { ?>
<div id="reset-password-wrapper" style="display: none;">
<input type="submit" id="reset-password-submit" class="login primary" title="" value="<?php p($l->t('Reset password')); ?>" disabled="disabled" />
diff --git a/lib/l10n/ko.js b/lib/l10n/ko.js
index ae4bb8404e7..8593058bf68 100644
--- a/lib/l10n/ko.js
+++ b/lib/l10n/ko.js
@@ -227,9 +227,9 @@ OC.L10N.register(
"Could not obtain lock type %d on \"%s\"." : "잠금 형식 %d을(를) \"%s\"에 대해 얻을 수 없습니다.",
"Storage unauthorized. %s" : "저장소가 인증되지 않았습니다. %s",
"Storage incomplete configuration. %s" : "저장소 설정이 완전하지 않습니다. %s",
- "Storage connection error. %s" : "저장소 연결 오류. %s",
+ "Storage connection error. %s" : "저장소 연결 오류입니다. %s",
"Storage is temporarily not available" : "저장소를 임시로 사용할 수 없음",
- "Storage connection timeout. %s" : "저장소 연결 시간 초과. %s",
+ "Storage connection timeout. %s" : "저장소 연결 시간이 초과되었습니다. %s",
"This can usually be fixed by %sgiving the webserver write access to the config directory%s." : "%sconfig 디렉터리에 웹 서버 쓰기 권한%s을 주면 해결됩니다.",
"Module with id: %s does not exist. Please enable it in your apps settings or contact your administrator." : "ID: %s인 모듈이 존재하지 않습니다. 앱 설정에서 활성화하거나 관리자에게 연락하십시오.",
"Server settings" : "서버 설정",
diff --git a/lib/l10n/ko.json b/lib/l10n/ko.json
index 22a4b05f37a..c8b3d0e8ee9 100644
--- a/lib/l10n/ko.json
+++ b/lib/l10n/ko.json
@@ -225,9 +225,9 @@
"Could not obtain lock type %d on \"%s\"." : "잠금 형식 %d을(를) \"%s\"에 대해 얻을 수 없습니다.",
"Storage unauthorized. %s" : "저장소가 인증되지 않았습니다. %s",
"Storage incomplete configuration. %s" : "저장소 설정이 완전하지 않습니다. %s",
- "Storage connection error. %s" : "저장소 연결 오류. %s",
+ "Storage connection error. %s" : "저장소 연결 오류입니다. %s",
"Storage is temporarily not available" : "저장소를 임시로 사용할 수 없음",
- "Storage connection timeout. %s" : "저장소 연결 시간 초과. %s",
+ "Storage connection timeout. %s" : "저장소 연결 시간이 초과되었습니다. %s",
"This can usually be fixed by %sgiving the webserver write access to the config directory%s." : "%sconfig 디렉터리에 웹 서버 쓰기 권한%s을 주면 해결됩니다.",
"Module with id: %s does not exist. Please enable it in your apps settings or contact your administrator." : "ID: %s인 모듈이 존재하지 않습니다. 앱 설정에서 활성화하거나 관리자에게 연락하십시오.",
"Server settings" : "서버 설정",
diff --git a/lib/l10n/ru.js b/lib/l10n/ru.js
index ed34349936f..e63656b4494 100644
--- a/lib/l10n/ru.js
+++ b/lib/l10n/ru.js
@@ -16,8 +16,8 @@ OC.L10N.register(
"Enterprise bundle" : "Корпоративный пакет",
"Groupware bundle" : "Пакет для групп",
"Social sharing bundle" : "Пакет для соц. сетей",
- "PHP %s or higher is required." : "Требуется PHP %s или выше",
- "PHP with a version lower than %s is required." : "Требуется версия PHP ниже %s.",
+ "PHP %s or higher is required." : "Требуется PHP версии %s или выше.",
+ "PHP with a version lower than %s is required." : "Требуется PHP версии ниже %s.",
"%sbit or higher PHP required." : "Требуется PHP с разрядностью %s бит или более.",
"Following databases are supported: %s" : "Поддерживаются следующие СУБД: %s",
"The command line tool %s could not be found" : "Утилита командной строки %s не найдена",
diff --git a/lib/l10n/ru.json b/lib/l10n/ru.json
index 9b867ec5285..980cd6b46d8 100644
--- a/lib/l10n/ru.json
+++ b/lib/l10n/ru.json
@@ -14,8 +14,8 @@
"Enterprise bundle" : "Корпоративный пакет",
"Groupware bundle" : "Пакет для групп",
"Social sharing bundle" : "Пакет для соц. сетей",
- "PHP %s or higher is required." : "Требуется PHP %s или выше",
- "PHP with a version lower than %s is required." : "Требуется версия PHP ниже %s.",
+ "PHP %s or higher is required." : "Требуется PHP версии %s или выше.",
+ "PHP with a version lower than %s is required." : "Требуется PHP версии ниже %s.",
"%sbit or higher PHP required." : "Требуется PHP с разрядностью %s бит или более.",
"Following databases are supported: %s" : "Поддерживаются следующие СУБД: %s",
"The command line tool %s could not be found" : "Утилита командной строки %s не найдена",
diff --git a/lib/l10n/sv.js b/lib/l10n/sv.js
index bda2c46d149..2e6c4defce8 100644
--- a/lib/l10n/sv.js
+++ b/lib/l10n/sv.js
@@ -30,9 +30,9 @@ OC.L10N.register(
"Unknown filetype" : "Okänd filtyp",
"Invalid image" : "Ogiltig bild",
"Avatar image is not square" : "Profilbilden är inte fyrkantig",
- "today" : "i dag",
- "tomorrow" : "i morgon",
- "yesterday" : "i går",
+ "today" : "idag",
+ "tomorrow" : "imorgon",
+ "yesterday" : "igår",
"_in %n day_::_in %n days_" : ["om %n dag","om %n dagar"],
"_%n day ago_::_%n days ago_" : ["%n dag sedan","%n dagar sedan"],
"next month" : "nästa månad",
@@ -66,7 +66,7 @@ OC.L10N.register(
"Unknown user" : "Okänd användare",
"APCu" : "APCu",
"Redis" : "Redis",
- "Basic settings" : "Vanliga inställningar",
+ "Basic settings" : "Generella inställningar",
"Sharing" : "Delning",
"Security" : "Säkerhet",
"Encryption" : "Kryptering",
diff --git a/lib/l10n/sv.json b/lib/l10n/sv.json
index 17b2ad1f22b..ab2183b6d86 100644
--- a/lib/l10n/sv.json
+++ b/lib/l10n/sv.json
@@ -28,9 +28,9 @@
"Unknown filetype" : "Okänd filtyp",
"Invalid image" : "Ogiltig bild",
"Avatar image is not square" : "Profilbilden är inte fyrkantig",
- "today" : "i dag",
- "tomorrow" : "i morgon",
- "yesterday" : "i går",
+ "today" : "idag",
+ "tomorrow" : "imorgon",
+ "yesterday" : "igår",
"_in %n day_::_in %n days_" : ["om %n dag","om %n dagar"],
"_%n day ago_::_%n days ago_" : ["%n dag sedan","%n dagar sedan"],
"next month" : "nästa månad",
@@ -64,7 +64,7 @@
"Unknown user" : "Okänd användare",
"APCu" : "APCu",
"Redis" : "Redis",
- "Basic settings" : "Vanliga inställningar",
+ "Basic settings" : "Generella inställningar",
"Sharing" : "Delning",
"Security" : "Säkerhet",
"Encryption" : "Kryptering",
diff --git a/lib/private/Preview/Generator.php b/lib/private/Preview/Generator.php
index 402732ecda9..448a7a57580 100644
--- a/lib/private/Preview/Generator.php
+++ b/lib/private/Preview/Generator.php
@@ -128,9 +128,13 @@ class Generator {
// Try to get a cached preview. Else generate (and store) one
try {
- $file = $this->getCachedPreview($previewFolder, $width, $height, $crop);
- } catch (NotFoundException $e) {
- $file = $this->generatePreview($previewFolder, $maxPreview, $width, $height, $crop, $maxWidth, $maxHeight);
+ try {
+ $file = $this->getCachedPreview($previewFolder, $width, $height, $crop, $maxPreview->getMimeType());
+ } catch (NotFoundException $e) {
+ $file = $this->generatePreview($previewFolder, $maxPreview, $width, $height, $crop, $maxWidth, $maxHeight);
+ }
+ } catch (\InvalidArgumentException $e) {
+ throw new NotFoundException();
}
return $file;
@@ -164,8 +168,8 @@ class Generator {
continue;
}
- $maxWidth = (int)$this->config->getSystemValue('preview_max_x', 2048);
- $maxHeight = (int)$this->config->getSystemValue('preview_max_y', 2048);
+ $maxWidth = (int)$this->config->getSystemValue('preview_max_x', 4096);
+ $maxHeight = (int)$this->config->getSystemValue('preview_max_y', 4096);
$preview = $this->helper->getThumbnail($provider, $file, $maxWidth, $maxHeight);
@@ -173,7 +177,15 @@ class Generator {
continue;
}
- $path = (string)$preview->width() . '-' . (string)$preview->height() . '-max.png';
+ // Try to get the extention.
+ try {
+ $ext = $this->getExtention($preview->dataMimeType());
+ } catch (\InvalidArgumentException $e) {
+ // Just continue to the next iteration if this preview doesn't have a valid mimetype
+ continue;
+ }
+
+ $path = (string)$preview->width() . '-' . (string)$preview->height() . '-max.' . $ext;
try {
$file = $previewFolder->newFile($path);
$file->putContent($preview->data());
@@ -201,14 +213,17 @@ class Generator {
* @param int $width
* @param int $height
* @param bool $crop
+ * @param string $mimeType
* @return string
*/
- private function generatePath($width, $height, $crop) {
+ private function generatePath($width, $height, $crop, $mimeType) {
$path = (string)$width . '-' . (string)$height;
if ($crop) {
$path .= '-crop';
}
- $path .= '.png';
+
+ $ext = $this->getExtention($mimeType);
+ $path .= '.' . $ext;
return $path;
}
@@ -340,7 +355,7 @@ class Generator {
}
- $path = $this->generatePath($width, $height, $crop);
+ $path = $this->generatePath($width, $height, $crop, $preview->dataMimeType());
try {
$file = $previewFolder->newFile($path);
$file->putContent($preview->data());
@@ -356,12 +371,13 @@ class Generator {
* @param int $width
* @param int $height
* @param bool $crop
+ * @param string $mimeType
* @return ISimpleFile
*
* @throws NotFoundException
*/
- private function getCachedPreview(ISimpleFolder $previewFolder, $width, $height, $crop) {
- $path = $this->generatePath($width, $height, $crop);
+ private function getCachedPreview(ISimpleFolder $previewFolder, $width, $height, $crop, $mimeType) {
+ $path = $this->generatePath($width, $height, $crop, $mimeType);
return $previewFolder->getFile($path);
}
@@ -381,4 +397,22 @@ class Generator {
return $folder;
}
+
+ /**
+ * @param string $mimeType
+ * @return null|string
+ * @throws \InvalidArgumentException
+ */
+ private function getExtention($mimeType) {
+ switch ($mimeType) {
+ case 'image/png':
+ return 'png';
+ case 'image/jpeg':
+ return 'jpg';
+ case 'image/gif':
+ return 'gif';
+ default:
+ throw new \InvalidArgumentException('Not a valid mimetype');
+ }
+ }
}
diff --git a/lib/private/Settings/Manager.php b/lib/private/Settings/Manager.php
index cd0af5e7bb2..efeedbe6fcc 100644
--- a/lib/private/Settings/Manager.php
+++ b/lib/private/Settings/Manager.php
@@ -47,6 +47,7 @@ use OCP\Lock\ILockingProvider;
use OCP\Settings\ISettings;
use OCP\Settings\IManager;
use OCP\Settings\ISection;
+use OCP\Util;
class Manager implements IManager {
/** @var ILogger */
@@ -344,7 +345,7 @@ class Manager implements IManager {
try {
return \OC::$server->query($className);
} catch (QueryException $e) {
- $this->log->logException($e);
+ $this->log->logException($e, ['level' => Util::INFO]);
throw $e;
}
}
diff --git a/lib/private/Share20/DefaultShareProvider.php b/lib/private/Share20/DefaultShareProvider.php
index 844b36b2994..b9ab7a46873 100644
--- a/lib/private/Share20/DefaultShareProvider.php
+++ b/lib/private/Share20/DefaultShareProvider.php
@@ -452,9 +452,9 @@ class DefaultShareProvider implements IShareProvider {
'uid_owner' => $qb->createNamedParameter($share->getShareOwner()),
'uid_initiator' => $qb->createNamedParameter($share->getSharedBy()),
'parent' => $qb->createNamedParameter($share->getId()),
- 'item_type' => $qb->createNamedParameter($share->getNode() instanceof File ? 'file' : 'folder'),
- 'item_source' => $qb->createNamedParameter($share->getNode()->getId()),
- 'file_source' => $qb->createNamedParameter($share->getNode()->getId()),
+ 'item_type' => $qb->createNamedParameter($share->getNodeType()),
+ 'item_source' => $qb->createNamedParameter($share->getNodeId()),
+ 'file_source' => $qb->createNamedParameter($share->getNodeId()),
'file_target' => $qb->createNamedParameter($share->getTarget()),
'permissions' => $qb->createNamedParameter($share->getPermissions()),
'stime' => $qb->createNamedParameter($share->getShareTime()->getTimestamp()),
diff --git a/lib/private/Template/JSConfigHelper.php b/lib/private/Template/JSConfigHelper.php
index bdb747e1c9f..9f93ef784bc 100644
--- a/lib/private/Template/JSConfigHelper.php
+++ b/lib/private/Template/JSConfigHelper.php
@@ -155,6 +155,7 @@ class JSConfigHelper {
"oc_appswebroots" => str_replace('\\/', '/', json_encode($apps_paths)), // Ugly unescape slashes waiting for better solution
"datepickerFormatDate" => json_encode($this->l->l('jsdate', null)),
'nc_lastLogin' => $lastConfirmTimestamp,
+ 'nc_pageLoad' => time(),
"dayNames" => json_encode([
(string)$this->l->t('Sunday'),
(string)$this->l->t('Monday'),
diff --git a/lib/private/TemplateLayout.php b/lib/private/TemplateLayout.php
index a8c4bbb0d16..5e6d432c805 100644
--- a/lib/private/TemplateLayout.php
+++ b/lib/private/TemplateLayout.php
@@ -146,7 +146,7 @@ class TemplateLayout extends \OC_Template {
if ($this->config->getSystemValue('installed', false) && $renderAs != 'error') {
if (\OC::$server->getContentSecurityPolicyNonceManager()->browserSupportsCspV3()) {
$jsConfigHelper = new JSConfigHelper(
- \OC::$server->getL10N('core'),
+ \OC::$server->getL10N('lib'),
\OC::$server->query(Defaults::class),
\OC::$server->getAppManager(),
\OC::$server->getSession(),
diff --git a/lib/private/legacy/image.php b/lib/private/legacy/image.php
index a7d702ac032..a0159b927f9 100644
--- a/lib/private/legacy/image.php
+++ b/lib/private/legacy/image.php
@@ -305,6 +305,25 @@ class OC_Image implements \OCP\IImage {
}
/**
+ * @return string Returns the mimetype of the data. Returns the empty string
+ * if the data is not valid.
+ */
+ public function dataMimeType() {
+ if (!$this->valid()) {
+ return '';
+ }
+
+ switch ($this->mimeType) {
+ case 'image/png':
+ case 'image/jpeg':
+ case 'image/gif':
+ return $this->mimeType;
+ default:
+ return 'image/png';
+ }
+ }
+
+ /**
* @return null|string Returns the raw image data.
*/
public function data() {
diff --git a/lib/public/IImage.php b/lib/public/IImage.php
index f63a1b8ca60..70e8b3cff75 100644
--- a/lib/public/IImage.php
+++ b/lib/public/IImage.php
@@ -103,6 +103,12 @@ interface IImage {
public function resource();
/**
+ * @return string Returns the raw data mimetype
+ * @since 13.0.0
+ */
+ public function dataMimeType();
+
+ /**
* @return string Returns the raw image data.
* @since 8.1.0
*/
diff --git a/ocs/v1.php b/ocs/v1.php
index 43a1c2d9e0e..b6ed5697a69 100644
--- a/ocs/v1.php
+++ b/ocs/v1.php
@@ -81,7 +81,7 @@ try {
$format = \OC::$server->getRequest()->getParam('format', 'xml');
$txt='Invalid query, please check the syntax. API specifications are here:'
- .' http://www.freedesktop.org/wiki/Specifications/open-collaboration-services. DEBUG OUTPUT:'."\n";
+ .' http://www.freedesktop.org/wiki/Specifications/open-collaboration-services.'."\n";
OC_API::respond(new \OC\OCS\Result(null, \OCP\API::RESPOND_NOT_FOUND, $txt), $format);
} catch (MethodNotAllowedException $e) {
OC_API::setContentType();
@@ -96,7 +96,7 @@ try {
$format = \OC::$server->getRequest()->getParam('format', 'xml');
$txt='Invalid query, please check the syntax. API specifications are here:'
- .' http://www.freedesktop.org/wiki/Specifications/open-collaboration-services. DEBUG OUTPUT:'."\n";
+ .' http://www.freedesktop.org/wiki/Specifications/open-collaboration-services.'."\n";
OC_API::respond(new \OC\OCS\Result(null, \OCP\API::RESPOND_NOT_FOUND, $txt), $format);
}
diff --git a/settings/css/settings.scss b/settings/css/settings.scss
index 268cb0eee5d..d2dd973e887 100644
--- a/settings/css/settings.scss
+++ b/settings/css/settings.scss
@@ -347,7 +347,7 @@ table.nostyle {
}
.token-list {
td > a.icon {
- opacity: 0;
+
transition: opacity 0.5s;
}
a.icon {
@@ -563,36 +563,26 @@ tr:hover > td {
}
td.userActions {
- width: 25px;
- text-align: center;
- position: relative;
- .action {
- position: relative;
- top: 3px;
- }
+ width: 44px;
.toggleUserActions {
- border: none;
- background-color: rgba(0, 0, 0, 0);
- width: 34px;
- height: 34px;
- margin: 0;
- opacity: 0.5;
- &:hover,
- &:focus {
- background-color: transparent;
- opacity: 1;
+ width: 44px;
+ height: 44px;
+ position: relative;
+ .action {
+ display: block;
+ padding: 14px;
+ opacity: 0.5;
+ .icon-more {
+ display: inline-block;
+ }
+ &:hover,
+ &:focus {
+ opacity: 1;
+ }
}
}
}
-tr.active td.userActions .action {
- opacity: 1;
-}
-
-td.userActions .action:hover {
- cursor: pointer;
-}
-
div.recoveryPassword {
left: 50em;
display: block;
diff --git a/settings/js/users/users.js b/settings/js/users/users.js
index 1d6cb93452a..5a337c38556 100644
--- a/settings/js/users/users.js
+++ b/settings/js/users/users.js
@@ -101,16 +101,9 @@ var UserList = {
$tdSubadmins.find('.action').tooltip({placement: 'top'});
/**
- * user actions menu
+ * hide user actions menu for current user
*/
- if ($tr.find('td.userActions > span > img').length === 0 && OC.currentUser !== user.name) {
- var menuImage = $('<img class="svg action">').attr({
- src: OC.imagePath('core', 'actions/more')
- });
- var menuLink = $('<span class="toggleUserActions"></span>')
- .append(menuImage);
- $tr.find('td.userActions > span').replaceWith(menuLink);
- } else if (OC.currentUser === user.name) {
+ if (OC.currentUser === user.name) {
$tr.find('td.userActions').empty();
}
diff --git a/settings/l10n/en_GB.js b/settings/l10n/en_GB.js
index a245b80eb8e..58bc68070e3 100644
--- a/settings/l10n/en_GB.js
+++ b/settings/l10n/en_GB.js
@@ -104,9 +104,15 @@ OC.L10N.register(
"Error: This app can not be enabled because it makes the server unstable" : "Error: This app can not be enabled because it makes the server unstable",
"Error: Could not disable broken app" : "Error: Could not disable broken app",
"Error while disabling broken app" : "Error whilst disabling broken app",
+ "App up to date" : "App up to date",
+ "Upgrading …" : "Upgrading …",
+ "Could not upgrade app" : "Could not upgrade app",
"Updated" : "Updated",
"Removing …" : "Removing …",
+ "Could not remove app" : "Could not remove app",
"Remove" : "Remove",
+ "The app has been enabled but needs to be upgraded. You will be redirected to the upgrade page in 5 seconds." : "The app has been enabled but needs to be upgraded. You will be redirected to the upgrade page in 5 seconds.",
+ "App upgrade" : "App upgrade",
"Approved" : "Approved",
"Experimental" : "Experimental",
"No apps found for {query}" : "No apps found for {query}",
diff --git a/settings/l10n/en_GB.json b/settings/l10n/en_GB.json
index 9d70d91483a..abe5fba5ed7 100644
--- a/settings/l10n/en_GB.json
+++ b/settings/l10n/en_GB.json
@@ -102,9 +102,15 @@
"Error: This app can not be enabled because it makes the server unstable" : "Error: This app can not be enabled because it makes the server unstable",
"Error: Could not disable broken app" : "Error: Could not disable broken app",
"Error while disabling broken app" : "Error whilst disabling broken app",
+ "App up to date" : "App up to date",
+ "Upgrading …" : "Upgrading …",
+ "Could not upgrade app" : "Could not upgrade app",
"Updated" : "Updated",
"Removing …" : "Removing …",
+ "Could not remove app" : "Could not remove app",
"Remove" : "Remove",
+ "The app has been enabled but needs to be upgraded. You will be redirected to the upgrade page in 5 seconds." : "The app has been enabled but needs to be upgraded. You will be redirected to the upgrade page in 5 seconds.",
+ "App upgrade" : "App upgrade",
"Approved" : "Approved",
"Experimental" : "Experimental",
"No apps found for {query}" : "No apps found for {query}",
diff --git a/settings/l10n/es.js b/settings/l10n/es.js
index bef3b13fcf5..041b63f6fc7 100644
--- a/settings/l10n/es.js
+++ b/settings/l10n/es.js
@@ -104,9 +104,15 @@ OC.L10N.register(
"Error: This app can not be enabled because it makes the server unstable" : "Error: Esta app no se puede activar porque desestabiliza el servidor",
"Error: Could not disable broken app" : "Error: No se ha podido desactivar una app estropeada",
"Error while disabling broken app" : "Error mientras deshabilitaba la App dañada",
+ "App up to date" : "App actualizada",
+ "Upgrading …" : "Actualizando...",
+ "Could not upgrade app" : "No se ha podido actualizar la app",
"Updated" : "Actualizado",
"Removing …" : "Eliminando...",
+ "Could not remove app" : "No se ha podido eliminar la app",
"Remove" : "Eliminar",
+ "The app has been enabled but needs to be upgraded. You will be redirected to the upgrade page in 5 seconds." : "La app ha sido activada pero tiene que actualizarse. Serás redirigido a la página de actualización en 5 segundos.",
+ "App upgrade" : "Actualización de la app",
"Approved" : "Aprobado",
"Experimental" : "Experimental",
"No apps found for {query}" : "No se han encontrado apps para {query}",
diff --git a/settings/l10n/es.json b/settings/l10n/es.json
index be7a4ecad19..9c8007c4848 100644
--- a/settings/l10n/es.json
+++ b/settings/l10n/es.json
@@ -102,9 +102,15 @@
"Error: This app can not be enabled because it makes the server unstable" : "Error: Esta app no se puede activar porque desestabiliza el servidor",
"Error: Could not disable broken app" : "Error: No se ha podido desactivar una app estropeada",
"Error while disabling broken app" : "Error mientras deshabilitaba la App dañada",
+ "App up to date" : "App actualizada",
+ "Upgrading …" : "Actualizando...",
+ "Could not upgrade app" : "No se ha podido actualizar la app",
"Updated" : "Actualizado",
"Removing …" : "Eliminando...",
+ "Could not remove app" : "No se ha podido eliminar la app",
"Remove" : "Eliminar",
+ "The app has been enabled but needs to be upgraded. You will be redirected to the upgrade page in 5 seconds." : "La app ha sido activada pero tiene que actualizarse. Serás redirigido a la página de actualización en 5 segundos.",
+ "App upgrade" : "Actualización de la app",
"Approved" : "Aprobado",
"Experimental" : "Experimental",
"No apps found for {query}" : "No se han encontrado apps para {query}",
diff --git a/settings/l10n/ka_GE.js b/settings/l10n/ka_GE.js
index 16d388195de..d395e0d6a2f 100644
--- a/settings/l10n/ka_GE.js
+++ b/settings/l10n/ka_GE.js
@@ -104,9 +104,15 @@ OC.L10N.register(
"Error: This app can not be enabled because it makes the server unstable" : "შეცდომა: ეს აპლიკაცია ვერ მოქმედდება რადგანაც სერვერს ხდის არასტაბილურს",
"Error: Could not disable broken app" : "შეცდომა: გაფუჭებული აპლიკაციის დეაქტივაცია ვერ მოხერხდა",
"Error while disabling broken app" : "გაფუჭებული აპლიკაციის დეაქტივაციისას წარმოიშვა შეცდომა",
+ "App up to date" : "აპლიკაცია ახალია",
+ "Upgrading …" : "ნახლდება …",
+ "Could not upgrade app" : "აპლიკაცია ვერ განახლდა",
"Updated" : "განახლებულია",
"Removing …" : "იშლება …",
+ "Could not remove app" : "აპლიკაცია ვერ გაუქმდა",
"Remove" : "წაშლა",
+ "The app has been enabled but needs to be upgraded. You will be redirected to the upgrade page in 5 seconds." : "აპლიკაცია მოქმედია, თუმცა საჭიროებს განახლებას. განახლების გვერდზე გადამისამართდებით 5 წამში.",
+ "App upgrade" : "აპლიკაციის განახლება",
"Approved" : "დამოწმებულია",
"Experimental" : "ექსპერიმენტალურია",
"No apps found for {query}" : "აპლიკაციები {query}-სთვის ვერ მოძებნა",
diff --git a/settings/l10n/ka_GE.json b/settings/l10n/ka_GE.json
index fdd581935bc..144fc0046d4 100644
--- a/settings/l10n/ka_GE.json
+++ b/settings/l10n/ka_GE.json
@@ -102,9 +102,15 @@
"Error: This app can not be enabled because it makes the server unstable" : "შეცდომა: ეს აპლიკაცია ვერ მოქმედდება რადგანაც სერვერს ხდის არასტაბილურს",
"Error: Could not disable broken app" : "შეცდომა: გაფუჭებული აპლიკაციის დეაქტივაცია ვერ მოხერხდა",
"Error while disabling broken app" : "გაფუჭებული აპლიკაციის დეაქტივაციისას წარმოიშვა შეცდომა",
+ "App up to date" : "აპლიკაცია ახალია",
+ "Upgrading …" : "ნახლდება …",
+ "Could not upgrade app" : "აპლიკაცია ვერ განახლდა",
"Updated" : "განახლებულია",
"Removing …" : "იშლება …",
+ "Could not remove app" : "აპლიკაცია ვერ გაუქმდა",
"Remove" : "წაშლა",
+ "The app has been enabled but needs to be upgraded. You will be redirected to the upgrade page in 5 seconds." : "აპლიკაცია მოქმედია, თუმცა საჭიროებს განახლებას. განახლების გვერდზე გადამისამართდებით 5 წამში.",
+ "App upgrade" : "აპლიკაციის განახლება",
"Approved" : "დამოწმებულია",
"Experimental" : "ექსპერიმენტალურია",
"No apps found for {query}" : "აპლიკაციები {query}-სთვის ვერ მოძებნა",
diff --git a/settings/l10n/ko.js b/settings/l10n/ko.js
index a03387d6acb..620ad0900c0 100644
--- a/settings/l10n/ko.js
+++ b/settings/l10n/ko.js
@@ -228,7 +228,7 @@ OC.L10N.register(
"Authentication required" : "인증 필요함",
"Server address" : "서버 주소",
"Port" : "포트",
- "Credentials" : "자격 정보",
+ "Credentials" : "인증 정보",
"SMTP Username" : "SMTP 사용자 이름",
"SMTP Password" : "SMTP 암호",
"Store credentials" : "인증 정보 저장",
@@ -424,7 +424,7 @@ OC.L10N.register(
"Last cron job execution: %s." : "마지막 cron 작업 실행: %s.",
"Last cron job execution: %s. Something seems wrong." : "마지막 cron 작업 실행: %s. 문제가 발생한 것 같습니다.",
"Cron was not executed yet!" : "Cron이 실행되지 않았습니다!",
- "cron.php is registered at a webcron service to call cron.php every 15 minutes over http." : "cron.php는 webcron 서비스에 등록되어 HTTP로 15분마다 cron.php에 접근합니다.",
+ "cron.php is registered at a webcron service to call cron.php every 15 minutes over http." : "15분마다 HTTP를 통해 cron.php를 실행하는 webcron 서비스에 cron.php가 등록되었습니다.",
"Use system's cron service to call the cron.php file every 15 minutes." : "시스템의 cron 서비스를 통하여 15분마다 cron.php 파일을 실행합니다.",
"To run this you need the PHP posix extension. See {linkstart}PHP documentation{linkend} for more details." : "실행하려면 PHP POSIX 확장이 필요합니다. 자세한 내용은 {linkstart}PHP 사용 설명서{linkend}를 참고하십시오.",
"Allow username autocompletion in share dialog. If this is disabled the full username needs to be entered." : "공유 대화 상자에서 사용자 이름 자동 완성을 사용합니다. 이 설정을 사용하지 않으면 전체 사용자 이름을 입력해야 합니다.",
diff --git a/settings/l10n/ko.json b/settings/l10n/ko.json
index d2fd97c6ab7..e1b56c2ee16 100644
--- a/settings/l10n/ko.json
+++ b/settings/l10n/ko.json
@@ -226,7 +226,7 @@
"Authentication required" : "인증 필요함",
"Server address" : "서버 주소",
"Port" : "포트",
- "Credentials" : "자격 정보",
+ "Credentials" : "인증 정보",
"SMTP Username" : "SMTP 사용자 이름",
"SMTP Password" : "SMTP 암호",
"Store credentials" : "인증 정보 저장",
@@ -422,7 +422,7 @@
"Last cron job execution: %s." : "마지막 cron 작업 실행: %s.",
"Last cron job execution: %s. Something seems wrong." : "마지막 cron 작업 실행: %s. 문제가 발생한 것 같습니다.",
"Cron was not executed yet!" : "Cron이 실행되지 않았습니다!",
- "cron.php is registered at a webcron service to call cron.php every 15 minutes over http." : "cron.php는 webcron 서비스에 등록되어 HTTP로 15분마다 cron.php에 접근합니다.",
+ "cron.php is registered at a webcron service to call cron.php every 15 minutes over http." : "15분마다 HTTP를 통해 cron.php를 실행하는 webcron 서비스에 cron.php가 등록되었습니다.",
"Use system's cron service to call the cron.php file every 15 minutes." : "시스템의 cron 서비스를 통하여 15분마다 cron.php 파일을 실행합니다.",
"To run this you need the PHP posix extension. See {linkstart}PHP documentation{linkend} for more details." : "실행하려면 PHP POSIX 확장이 필요합니다. 자세한 내용은 {linkstart}PHP 사용 설명서{linkend}를 참고하십시오.",
"Allow username autocompletion in share dialog. If this is disabled the full username needs to be entered." : "공유 대화 상자에서 사용자 이름 자동 완성을 사용합니다. 이 설정을 사용하지 않으면 전체 사용자 이름을 입력해야 합니다.",
diff --git a/settings/l10n/nb.js b/settings/l10n/nb.js
index 793ee8ff43b..e889a966092 100644
--- a/settings/l10n/nb.js
+++ b/settings/l10n/nb.js
@@ -104,6 +104,9 @@ OC.L10N.register(
"Error: This app can not be enabled because it makes the server unstable" : "Feil: Dette programmet kan ikke aktiveres fordi det gjør tjeneren ustabil",
"Error: Could not disable broken app" : "Feil: Kunne ikke deaktivere ustabilt program",
"Error while disabling broken app" : "Feil ved deaktivering av ustabilt program",
+ "App up to date" : "Appen er oppdatert",
+ "Upgrading …" : "Oppgraderer…",
+ "Could not upgrade app" : "Kunne ikke oppgradere appen",
"Updated" : "Oppdatert",
"Removing …" : "Fjerner…",
"Remove" : "Fjern",
diff --git a/settings/l10n/nb.json b/settings/l10n/nb.json
index c7f926f4acb..b95a39680b8 100644
--- a/settings/l10n/nb.json
+++ b/settings/l10n/nb.json
@@ -102,6 +102,9 @@
"Error: This app can not be enabled because it makes the server unstable" : "Feil: Dette programmet kan ikke aktiveres fordi det gjør tjeneren ustabil",
"Error: Could not disable broken app" : "Feil: Kunne ikke deaktivere ustabilt program",
"Error while disabling broken app" : "Feil ved deaktivering av ustabilt program",
+ "App up to date" : "Appen er oppdatert",
+ "Upgrading …" : "Oppgraderer…",
+ "Could not upgrade app" : "Kunne ikke oppgradere appen",
"Updated" : "Oppdatert",
"Removing …" : "Fjerner…",
"Remove" : "Fjern",
diff --git a/settings/l10n/nl.js b/settings/l10n/nl.js
index b16fb0c4576..6abb70048b0 100644
--- a/settings/l10n/nl.js
+++ b/settings/l10n/nl.js
@@ -104,9 +104,15 @@ OC.L10N.register(
"Error: This app can not be enabled because it makes the server unstable" : "Fout: Deze app kan niet ingeschakeld worden, omdat die de server onstabiel maakt",
"Error: Could not disable broken app" : "Fout: Kan de beschadigde app niet uitschakelen",
"Error while disabling broken app" : "Fout bij het uitschakelen van de beschadigde app",
+ "App up to date" : "App actueel",
+ "Upgrading …" : "Upgraden …",
+ "Could not upgrade app" : "Kon de app niet upgraden",
"Updated" : "Bijgewerkt",
"Removing …" : "Verwijderen ...",
+ "Could not remove app" : "Kon de app niet verwijderen",
"Remove" : "Verwijderen",
+ "The app has been enabled but needs to be upgraded. You will be redirected to the upgrade page in 5 seconds." : "De app is ingeschakeld maar moet worden ge-upgraded. Je wordt over 5 seconden doorgeleid naar de upgradepagina.",
+ "App upgrade" : "App upgrade",
"Approved" : "Goedgekeurd",
"Experimental" : "Experimenteel",
"No apps found for {query}" : "Geen apps gevonden voor {query}",
diff --git a/settings/l10n/nl.json b/settings/l10n/nl.json
index dbe67b7bf6c..f25fbe9dd1c 100644
--- a/settings/l10n/nl.json
+++ b/settings/l10n/nl.json
@@ -102,9 +102,15 @@
"Error: This app can not be enabled because it makes the server unstable" : "Fout: Deze app kan niet ingeschakeld worden, omdat die de server onstabiel maakt",
"Error: Could not disable broken app" : "Fout: Kan de beschadigde app niet uitschakelen",
"Error while disabling broken app" : "Fout bij het uitschakelen van de beschadigde app",
+ "App up to date" : "App actueel",
+ "Upgrading …" : "Upgraden …",
+ "Could not upgrade app" : "Kon de app niet upgraden",
"Updated" : "Bijgewerkt",
"Removing …" : "Verwijderen ...",
+ "Could not remove app" : "Kon de app niet verwijderen",
"Remove" : "Verwijderen",
+ "The app has been enabled but needs to be upgraded. You will be redirected to the upgrade page in 5 seconds." : "De app is ingeschakeld maar moet worden ge-upgraded. Je wordt over 5 seconden doorgeleid naar de upgradepagina.",
+ "App upgrade" : "App upgrade",
"Approved" : "Goedgekeurd",
"Experimental" : "Experimenteel",
"No apps found for {query}" : "Geen apps gevonden voor {query}",
diff --git a/settings/l10n/ro.js b/settings/l10n/ro.js
index e5172eeabc3..874c43c5594 100644
--- a/settings/l10n/ro.js
+++ b/settings/l10n/ro.js
@@ -1,6 +1,14 @@
OC.L10N.register(
"settings",
{
+ "You changed your password" : "Ți-ai schimbat parola",
+ "You changed your email address" : "Ți-ai schimbat adresa de email",
+ "Your email address was changed by an administrator" : "Adresa ta de email a fost modificată de un administrator",
+ "Security" : "Securitate",
+ "Your apps" : "Aplicațiile tale",
+ "Updates" : "Actualizări",
+ "Enabled apps" : "Aplicații active",
+ "Disabled apps" : "Aplicații inactive",
"Wrong password" : "Parolă greșită",
"Saved" : "Salvat",
"No user supplied" : "Nu a fost furnizat niciun utilizator",
@@ -12,24 +20,38 @@ OC.L10N.register(
"Group already exists." : "Grupul există deja.",
"Unable to add group." : "Nu se poate adăuga grupul.",
"Unable to delete group." : "Nu se poate șterge grupul.",
+ "Invalid SMTP password." : "Parolă SMTP invalidă.",
+ "Email setting test" : "Test setări email",
"A problem occurred while sending the email. Please revise your settings. (Error: %s)" : " A apărut o problemă la trimiterea emailului. Verifică-ți setărie. (Eroare: %s)",
"You need to set your user email before being able to send test emails." : "Trebuie să îți setezi emailul de utilizator înainte de a putea să trimiți emailuri.",
"Invalid mail address" : "Adresa mail invalidă",
+ "No valid group selected" : "Niciun grup valid selectat",
"A user with that name already exists." : "Există deja un utilizator cu acest nume.",
"Unable to create user." : "Imposibil de creat utilizatorul.",
"Unable to delete user." : "Imposibil de șters utilizatorul.",
+ "Error while enabling user." : "Eroare în timpul activării utilizatorului.",
+ "Error while disabling user." : "Eroare în timpul dezactivării utilizatorului.",
"Unable to change full name" : "Nu s-a putut schimba numele complet",
"Your full name has been changed." : "Numele tău complet a fost schimbat.",
"Forbidden" : "Interzis",
"Invalid user" : "Utilizator invalid",
"Unable to change mail address" : "Nu s-a putut schimba adresa email",
"Email saved" : "E-mail salvat",
+ "Email address changed for %s" : "Adresa de email schimbată în %s",
+ "The new email address is %s" : "Adresa de email nouă este%s",
"Your %s account was created" : "Contul tău %s a fost creat",
+ "Your username is: %s" : "Utilizatorul tău este: %s",
+ "Set your password" : "Setează parola",
+ "Install Client" : "Instalează client",
+ "Password confirmation is required" : "Confirmarea parolei este necesară",
"Couldn't remove app." : "Nu s-a putut înlătura aplicația.",
"Couldn't update app." : "Aplicaţia nu s-a putut actualiza.",
+ "Are you really sure you want add {domain} as trusted domain?" : "Ești sigur că vrei sa adaugi {domain} ca domeniu de încredere?",
"Add trusted domain" : "Adaugă domeniu de încredere",
"Migration in progress. Please wait until the migration is finished" : "Migrare în progres. Așteaptă până când migrarea este finalizată",
"Migration started …" : "Migrarea a început...",
+ "Not saved" : "Nu a fost salvat",
+ "Sending…" : "Se trimite...",
"Email sent" : "Mesajul a fost expediat",
"Official" : "Oficial",
"All" : "Toate ",
@@ -43,8 +65,25 @@ OC.L10N.register(
"Approved" : "Aprobat",
"Experimental" : "Experimental",
"Disconnect" : "Deconectare",
+ "Edge" : "Edge",
+ "Firefox" : "Firefox",
+ "Google Chrome" : "Google Chrome",
+ "Safari" : "Safari",
+ "Google Chrome for Android" : "Google Chrome for Android",
+ "iPhone iOS" : "iPhone iOS",
+ "iPad iOS" : "iPad iOS",
+ "iOS Client" : "iOS Client",
+ "Android Client" : "Android Client",
+ "Copy" : "Copiază",
+ "Copied!" : "S-a copiat!",
+ "Not supported!" : "Nu este suportat!",
+ "Press ⌘-C to copy." : "Apasă ⌘-C pentru copiere.",
+ "Press Ctrl-C to copy." : "Apasă Ctrl-C pentru copiere.",
"Valid until {date}" : "Valabil până la {date}",
"Delete" : "Șterge",
+ "Contacts" : "Contacte",
+ "Verify" : "Verifică",
+ "Verifying …" : "Se verifică ...",
"Select a profile picture" : "Selectează o imagine de profil",
"Very weak password" : "Parolă foarte slabă",
"Weak password" : "Parolă slabă",
@@ -57,8 +96,13 @@ OC.L10N.register(
"A valid group name must be provided" : "Trebuie furnizat un nume de grup valid",
"deleted {groupName}" : "{groupName} s-a șters",
"undo" : "Anulează ultima acțiune",
+ "{size} used" : "{size} folosită",
"never" : "niciodată",
"deleted {userName}" : "{userName} șters",
+ "Add group" : "Adaugă grup",
+ "Invalid quota value \"{val}\"" : "Valoare cotă invalidă \"{val}\"",
+ "no group" : "niciun grup",
+ "Password successfully changed" : "Parola a fost modificată cu succes.",
"Changing the password will result in data loss, because data recovery is not available for this user" : "Schimbarea parolei va rezulta în pierderea datelor deoarece recuperarea acestora nu este disponibilă pentru acest utilizator",
"A valid username must be provided" : "Trebuie să furnizaţi un nume de utilizator valid",
"Error creating user: {message}" : "Eroare la crearea utilizatorului: {message}",
@@ -87,7 +131,10 @@ OC.L10N.register(
"Commercial support" : "Suport comercial",
"None" : "Niciuna",
"Login" : "Autentificare",
+ "Plain" : "Plain",
"NT LAN Manager" : "NT LAN Manager",
+ "SSL/TLS" : "SSL/TLS",
+ "STARTTLS" : "STARTTLS",
"Email server" : "Server de email",
"Open documentation" : "Deschide documentația",
"Send mode" : "Modul de expediere",
@@ -132,24 +179,38 @@ OC.L10N.register(
"Advanced monitoring" : "Monitorizare avansată",
"Profile picture" : "Imagine de profil",
"Upload new" : "Încarcă una nouă",
+ "Select from Files" : "Selectează din fișiere",
"Remove image" : "Înlătură imagine",
"png or jpg, max. 20 MB" : "png sau jpg, max. 20 MB",
"Cancel" : "Anulare",
+ "Choose as profile picture" : "Alege ca imagine de profil",
"Full name" : "Nume complet",
"Email" : "Email",
"Your email address" : "Adresa ta de email",
+ "Phone number" : "Număr telefon",
+ "Your phone number" : "Numărul tău de telefon",
+ "Address" : "Adresă",
+ "Your postal address" : "Adresă poștală",
+ "Website" : "Site web",
+ "Link https://…" : "Link https://…",
+ "Twitter" : "Twitter",
"Language" : "Limba",
"Help translate" : "Ajută la traducere",
"Password" : "Parolă",
"Current password" : "Parola curentă",
"New password" : "Noua parolă",
"Change password" : "Schimbă parola",
+ "Device" : "Dispozitiv",
+ "App name" : "Numele aplicației",
"Username" : "Nume utilizator",
+ "Settings" : "Setări",
"E-Mail" : "Email",
"Create" : "Crează",
"Admin Recovery Password" : "Parolă de recuperare a Administratorului",
"Enter the recovery password in order to recover the users files during password change" : "Introdu parola de recuperare pentru a recupera fișierele utilizatorilor în timpul schimbării parolei",
+ "Everyone" : "Toți",
"Admins" : "Administratori",
+ "Disabled" : "Dezactivați",
"Unlimited" : "Nelimitată",
"Other" : "Altele",
"Quota" : "Cotă",
@@ -180,11 +241,15 @@ OC.L10N.register(
"Sync clients" : "Sincronizează clienții",
"The PHP module 'fileinfo' is missing. We strongly recommend to enable this module to get best results with mime-type detection." : "Modulul PHP \"Fileinfo\" lipsește. Va recomandam sa activaţi acest modul pentru a obține cele mai bune rezultate cu detectarea mime-type.",
"Cron" : "Cron",
+ "Cron was not executed yet!" : "Cron nu a fost executat înca!",
+ "Uninstall app" : "Dezinstalează aplicația",
"Cheers!" : "Noroc!",
"Get the apps to sync your files" : "Ia acum aplicatia pentru sincronizarea fisierelor ",
"Desktop client" : "Client Desktop",
"Android app" : "Aplicatie Android",
"iOS app" : "Aplicație iOS",
- "Name" : "Nume"
+ "Name" : "Nume",
+ "Group name" : "Numele grupului",
+ "Verifying" : "Se verifică"
},
"nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));");
diff --git a/settings/l10n/ro.json b/settings/l10n/ro.json
index 6ec743f02fb..44e45dbdc6d 100644
--- a/settings/l10n/ro.json
+++ b/settings/l10n/ro.json
@@ -1,4 +1,12 @@
{ "translations": {
+ "You changed your password" : "Ți-ai schimbat parola",
+ "You changed your email address" : "Ți-ai schimbat adresa de email",
+ "Your email address was changed by an administrator" : "Adresa ta de email a fost modificată de un administrator",
+ "Security" : "Securitate",
+ "Your apps" : "Aplicațiile tale",
+ "Updates" : "Actualizări",
+ "Enabled apps" : "Aplicații active",
+ "Disabled apps" : "Aplicații inactive",
"Wrong password" : "Parolă greșită",
"Saved" : "Salvat",
"No user supplied" : "Nu a fost furnizat niciun utilizator",
@@ -10,24 +18,38 @@
"Group already exists." : "Grupul există deja.",
"Unable to add group." : "Nu se poate adăuga grupul.",
"Unable to delete group." : "Nu se poate șterge grupul.",
+ "Invalid SMTP password." : "Parolă SMTP invalidă.",
+ "Email setting test" : "Test setări email",
"A problem occurred while sending the email. Please revise your settings. (Error: %s)" : " A apărut o problemă la trimiterea emailului. Verifică-ți setărie. (Eroare: %s)",
"You need to set your user email before being able to send test emails." : "Trebuie să îți setezi emailul de utilizator înainte de a putea să trimiți emailuri.",
"Invalid mail address" : "Adresa mail invalidă",
+ "No valid group selected" : "Niciun grup valid selectat",
"A user with that name already exists." : "Există deja un utilizator cu acest nume.",
"Unable to create user." : "Imposibil de creat utilizatorul.",
"Unable to delete user." : "Imposibil de șters utilizatorul.",
+ "Error while enabling user." : "Eroare în timpul activării utilizatorului.",
+ "Error while disabling user." : "Eroare în timpul dezactivării utilizatorului.",
"Unable to change full name" : "Nu s-a putut schimba numele complet",
"Your full name has been changed." : "Numele tău complet a fost schimbat.",
"Forbidden" : "Interzis",
"Invalid user" : "Utilizator invalid",
"Unable to change mail address" : "Nu s-a putut schimba adresa email",
"Email saved" : "E-mail salvat",
+ "Email address changed for %s" : "Adresa de email schimbată în %s",
+ "The new email address is %s" : "Adresa de email nouă este%s",
"Your %s account was created" : "Contul tău %s a fost creat",
+ "Your username is: %s" : "Utilizatorul tău este: %s",
+ "Set your password" : "Setează parola",
+ "Install Client" : "Instalează client",
+ "Password confirmation is required" : "Confirmarea parolei este necesară",
"Couldn't remove app." : "Nu s-a putut înlătura aplicația.",
"Couldn't update app." : "Aplicaţia nu s-a putut actualiza.",
+ "Are you really sure you want add {domain} as trusted domain?" : "Ești sigur că vrei sa adaugi {domain} ca domeniu de încredere?",
"Add trusted domain" : "Adaugă domeniu de încredere",
"Migration in progress. Please wait until the migration is finished" : "Migrare în progres. Așteaptă până când migrarea este finalizată",
"Migration started …" : "Migrarea a început...",
+ "Not saved" : "Nu a fost salvat",
+ "Sending…" : "Se trimite...",
"Email sent" : "Mesajul a fost expediat",
"Official" : "Oficial",
"All" : "Toate ",
@@ -41,8 +63,25 @@
"Approved" : "Aprobat",
"Experimental" : "Experimental",
"Disconnect" : "Deconectare",
+ "Edge" : "Edge",
+ "Firefox" : "Firefox",
+ "Google Chrome" : "Google Chrome",
+ "Safari" : "Safari",
+ "Google Chrome for Android" : "Google Chrome for Android",
+ "iPhone iOS" : "iPhone iOS",
+ "iPad iOS" : "iPad iOS",
+ "iOS Client" : "iOS Client",
+ "Android Client" : "Android Client",
+ "Copy" : "Copiază",
+ "Copied!" : "S-a copiat!",
+ "Not supported!" : "Nu este suportat!",
+ "Press ⌘-C to copy." : "Apasă ⌘-C pentru copiere.",
+ "Press Ctrl-C to copy." : "Apasă Ctrl-C pentru copiere.",
"Valid until {date}" : "Valabil până la {date}",
"Delete" : "Șterge",
+ "Contacts" : "Contacte",
+ "Verify" : "Verifică",
+ "Verifying …" : "Se verifică ...",
"Select a profile picture" : "Selectează o imagine de profil",
"Very weak password" : "Parolă foarte slabă",
"Weak password" : "Parolă slabă",
@@ -55,8 +94,13 @@
"A valid group name must be provided" : "Trebuie furnizat un nume de grup valid",
"deleted {groupName}" : "{groupName} s-a șters",
"undo" : "Anulează ultima acțiune",
+ "{size} used" : "{size} folosită",
"never" : "niciodată",
"deleted {userName}" : "{userName} șters",
+ "Add group" : "Adaugă grup",
+ "Invalid quota value \"{val}\"" : "Valoare cotă invalidă \"{val}\"",
+ "no group" : "niciun grup",
+ "Password successfully changed" : "Parola a fost modificată cu succes.",
"Changing the password will result in data loss, because data recovery is not available for this user" : "Schimbarea parolei va rezulta în pierderea datelor deoarece recuperarea acestora nu este disponibilă pentru acest utilizator",
"A valid username must be provided" : "Trebuie să furnizaţi un nume de utilizator valid",
"Error creating user: {message}" : "Eroare la crearea utilizatorului: {message}",
@@ -85,7 +129,10 @@
"Commercial support" : "Suport comercial",
"None" : "Niciuna",
"Login" : "Autentificare",
+ "Plain" : "Plain",
"NT LAN Manager" : "NT LAN Manager",
+ "SSL/TLS" : "SSL/TLS",
+ "STARTTLS" : "STARTTLS",
"Email server" : "Server de email",
"Open documentation" : "Deschide documentația",
"Send mode" : "Modul de expediere",
@@ -130,24 +177,38 @@
"Advanced monitoring" : "Monitorizare avansată",
"Profile picture" : "Imagine de profil",
"Upload new" : "Încarcă una nouă",
+ "Select from Files" : "Selectează din fișiere",
"Remove image" : "Înlătură imagine",
"png or jpg, max. 20 MB" : "png sau jpg, max. 20 MB",
"Cancel" : "Anulare",
+ "Choose as profile picture" : "Alege ca imagine de profil",
"Full name" : "Nume complet",
"Email" : "Email",
"Your email address" : "Adresa ta de email",
+ "Phone number" : "Număr telefon",
+ "Your phone number" : "Numărul tău de telefon",
+ "Address" : "Adresă",
+ "Your postal address" : "Adresă poștală",
+ "Website" : "Site web",
+ "Link https://…" : "Link https://…",
+ "Twitter" : "Twitter",
"Language" : "Limba",
"Help translate" : "Ajută la traducere",
"Password" : "Parolă",
"Current password" : "Parola curentă",
"New password" : "Noua parolă",
"Change password" : "Schimbă parola",
+ "Device" : "Dispozitiv",
+ "App name" : "Numele aplicației",
"Username" : "Nume utilizator",
+ "Settings" : "Setări",
"E-Mail" : "Email",
"Create" : "Crează",
"Admin Recovery Password" : "Parolă de recuperare a Administratorului",
"Enter the recovery password in order to recover the users files during password change" : "Introdu parola de recuperare pentru a recupera fișierele utilizatorilor în timpul schimbării parolei",
+ "Everyone" : "Toți",
"Admins" : "Administratori",
+ "Disabled" : "Dezactivați",
"Unlimited" : "Nelimitată",
"Other" : "Altele",
"Quota" : "Cotă",
@@ -178,11 +239,15 @@
"Sync clients" : "Sincronizează clienții",
"The PHP module 'fileinfo' is missing. We strongly recommend to enable this module to get best results with mime-type detection." : "Modulul PHP \"Fileinfo\" lipsește. Va recomandam sa activaţi acest modul pentru a obține cele mai bune rezultate cu detectarea mime-type.",
"Cron" : "Cron",
+ "Cron was not executed yet!" : "Cron nu a fost executat înca!",
+ "Uninstall app" : "Dezinstalează aplicația",
"Cheers!" : "Noroc!",
"Get the apps to sync your files" : "Ia acum aplicatia pentru sincronizarea fisierelor ",
"Desktop client" : "Client Desktop",
"Android app" : "Aplicatie Android",
"iOS app" : "Aplicație iOS",
- "Name" : "Nume"
+ "Name" : "Nume",
+ "Group name" : "Numele grupului",
+ "Verifying" : "Se verifică"
},"pluralForm" :"nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));"
} \ No newline at end of file
diff --git a/settings/l10n/ru.js b/settings/l10n/ru.js
index 8c11d9ea667..b5d98373e91 100644
--- a/settings/l10n/ru.js
+++ b/settings/l10n/ru.js
@@ -104,9 +104,15 @@ OC.L10N.register(
"Error: This app can not be enabled because it makes the server unstable" : "Ошибка: это приложение не может быть включено, так как оно сделает сервер нестабильным",
"Error: Could not disable broken app" : "Ошибка: невозможно отключить «сломанное» приложение",
"Error while disabling broken app" : "Ошибка при отключении сломанного приложения",
+ "App up to date" : "Приложение не нуждается в обновлении",
+ "Upgrading …" : "Обновление...",
+ "Could not upgrade app" : "Не удалось обновить приложение",
"Updated" : "Обновлено",
"Removing …" : "Удаление…",
+ "Could not remove app" : "Не удалось удалить приложение.",
"Remove" : "Удалить",
+ "The app has been enabled but needs to be upgraded. You will be redirected to the upgrade page in 5 seconds." : "Приложение было включено, но нуждается в обновлении. В течении 5 секунд будет выполнено перенаправление на страницу обновления.",
+ "App upgrade" : "Обновление приложения",
"Approved" : "Подтвержденное",
"Experimental" : "Экспериментальное",
"No apps found for {query}" : "Приложения не найдены по {query}",
diff --git a/settings/l10n/ru.json b/settings/l10n/ru.json
index bcacfeef65d..387973ffc82 100644
--- a/settings/l10n/ru.json
+++ b/settings/l10n/ru.json
@@ -102,9 +102,15 @@
"Error: This app can not be enabled because it makes the server unstable" : "Ошибка: это приложение не может быть включено, так как оно сделает сервер нестабильным",
"Error: Could not disable broken app" : "Ошибка: невозможно отключить «сломанное» приложение",
"Error while disabling broken app" : "Ошибка при отключении сломанного приложения",
+ "App up to date" : "Приложение не нуждается в обновлении",
+ "Upgrading …" : "Обновление...",
+ "Could not upgrade app" : "Не удалось обновить приложение",
"Updated" : "Обновлено",
"Removing …" : "Удаление…",
+ "Could not remove app" : "Не удалось удалить приложение.",
"Remove" : "Удалить",
+ "The app has been enabled but needs to be upgraded. You will be redirected to the upgrade page in 5 seconds." : "Приложение было включено, но нуждается в обновлении. В течении 5 секунд будет выполнено перенаправление на страницу обновления.",
+ "App upgrade" : "Обновление приложения",
"Approved" : "Подтвержденное",
"Experimental" : "Экспериментальное",
"No apps found for {query}" : "Приложения не найдены по {query}",
diff --git a/settings/l10n/sv.js b/settings/l10n/sv.js
index 5f34ce0a9fb..33b3f2ea33d 100644
--- a/settings/l10n/sv.js
+++ b/settings/l10n/sv.js
@@ -327,7 +327,7 @@ OC.L10N.register(
"Twitter handle @…" : "Twitter handle @…",
"You are member of the following groups:" : "Du är medlem i följande grupper:",
"Language" : "Språk",
- "Help translate" : "Hjälp att översätta",
+ "Help translate" : "Hjälp oss att översätta",
"Password" : "Lösenord",
"Current password" : "Nuvarande lösenord",
"New password" : "Nytt lösenord",
diff --git a/settings/l10n/sv.json b/settings/l10n/sv.json
index 27dea71ef5b..e8e77546259 100644
--- a/settings/l10n/sv.json
+++ b/settings/l10n/sv.json
@@ -325,7 +325,7 @@
"Twitter handle @…" : "Twitter handle @…",
"You are member of the following groups:" : "Du är medlem i följande grupper:",
"Language" : "Språk",
- "Help translate" : "Hjälp att översätta",
+ "Help translate" : "Hjälp oss att översätta",
"Password" : "Lösenord",
"Current password" : "Nuvarande lösenord",
"New password" : "Nytt lösenord",
diff --git a/settings/l10n/tr.js b/settings/l10n/tr.js
index 58e6952bbee..08b81502141 100644
--- a/settings/l10n/tr.js
+++ b/settings/l10n/tr.js
@@ -104,9 +104,15 @@ OC.L10N.register(
"Error: This app can not be enabled because it makes the server unstable" : "Hata: Bu uygulama sunucuda kararsızlığa yol açtığından etkinleştirilemez",
"Error: Could not disable broken app" : "Hata: Bozuk uygulama devre dışı bırakılamadı",
"Error while disabling broken app" : "Bozuk uygulama devre dışı bırakılırken sorun çıktı",
+ "App up to date" : "Uygulama güncel",
+ "Upgrading …" : "Güncelleniyor …",
+ "Could not upgrade app" : "Uygulama güncellenemedi",
"Updated" : "Güncellendi",
"Removing …" : "Kaldırılıyor...",
+ "Could not remove app" : "Uygulama kaldırılamadı",
"Remove" : "Kaldır",
+ "The app has been enabled but needs to be upgraded. You will be redirected to the upgrade page in 5 seconds." : "Uygulama etkinleştirilmiş fakat güncellenmesi gerekiyor. 5 saniye içinde güncelleme sayfasına yönlendirileceksiniz.",
+ "App upgrade" : "Uygulama güncellemesi",
"Approved" : "Onaylanmış",
"Experimental" : "Deneysel",
"No apps found for {query}" : "{query} aramasına uyan bir uygulama bulunamadı",
diff --git a/settings/l10n/tr.json b/settings/l10n/tr.json
index 0485390111f..a04b466a87b 100644
--- a/settings/l10n/tr.json
+++ b/settings/l10n/tr.json
@@ -102,9 +102,15 @@
"Error: This app can not be enabled because it makes the server unstable" : "Hata: Bu uygulama sunucuda kararsızlığa yol açtığından etkinleştirilemez",
"Error: Could not disable broken app" : "Hata: Bozuk uygulama devre dışı bırakılamadı",
"Error while disabling broken app" : "Bozuk uygulama devre dışı bırakılırken sorun çıktı",
+ "App up to date" : "Uygulama güncel",
+ "Upgrading …" : "Güncelleniyor …",
+ "Could not upgrade app" : "Uygulama güncellenemedi",
"Updated" : "Güncellendi",
"Removing …" : "Kaldırılıyor...",
+ "Could not remove app" : "Uygulama kaldırılamadı",
"Remove" : "Kaldır",
+ "The app has been enabled but needs to be upgraded. You will be redirected to the upgrade page in 5 seconds." : "Uygulama etkinleştirilmiş fakat güncellenmesi gerekiyor. 5 saniye içinde güncelleme sayfasına yönlendirileceksiniz.",
+ "App upgrade" : "Uygulama güncellemesi",
"Approved" : "Onaylanmış",
"Experimental" : "Deneysel",
"No apps found for {query}" : "{query} aramasına uyan bir uygulama bulunamadı",
diff --git a/settings/templates/users/part.userlist.php b/settings/templates/users/part.userlist.php
index 146e35d11ac..aaf20b6eaef 100644
--- a/settings/templates/users/part.userlist.php
+++ b/settings/templates/users/part.userlist.php
@@ -1,4 +1,4 @@
-<table id="userlist" class="hascontrols grid" data-groups="<?php p($_['allGroups']);?>">
+<table id="userlist" class="grid" data-groups="<?php p($_['allGroups']);?>">
<thead>
<tr>
<th id="headerAvatar" scope="col"></th>
@@ -64,19 +64,22 @@
<td class="storageLocation"></td>
<td class="userBackend"></td>
<td class="lastLogin"></td>
- <td class="userActions"><span></span>
- <div class="popovermenu bubble menu">
- <ul class="userActionsMenu">
- <li>
- <a href="#" class="menuitem action-togglestate permanent" data-action="togglestate"></a>
- </li>
- <li>
- <a href="#" class="menuitem action-remove permanent" data-action="remove">
- <span class="icon icon-delete"></span>
- <span><?php p($l->t('Delete')); ?></span>
- </a>
- </li>
- </ul>
+ <td class="userActions">
+ <div class="toggleUserActions">
+ <a class="action"><span class="icon-more"></span></a>
+ <div class="popovermenu bubble menu">
+ <ul class="userActionsMenu">
+ <li>
+ <a href="#" class="menuitem action-togglestate permanent" data-action="togglestate"></a>
+ </li>
+ <li>
+ <a href="#" class="menuitem action-remove permanent" data-action="remove">
+ <span class="icon icon-delete"></span>
+ <span><?php p($l->t('Delete')); ?></span>
+ </a>
+ </li>
+ </ul>
+ </div>
</div>
</td>
</tr>
diff --git a/tests/acceptance/features/app-files.feature b/tests/acceptance/features/app-files.feature
index 2cb43611b9a..ef3d07ae499 100644
--- a/tests/acceptance/features/app-files.feature
+++ b/tests/acceptance/features/app-files.feature
@@ -23,6 +23,13 @@ Feature: app-files
When I open the details view for "welcome.txt"
Then I see that the details view for "All files" section is open
+ Scenario: rename a file with the details view open
+ Given I am logged in
+ And I open the details view for "welcome.txt"
+ When I rename "welcome.txt" to "farewell.txt"
+ Then I see that the file list contains a file named "farewell.txt"
+ And I see that the file name shown in the details view is "farewell.txt"
+
Scenario: open the menu in a public shared link
Given I act as John
And I am logged in
diff --git a/tests/acceptance/features/bootstrap/FilesAppContext.php b/tests/acceptance/features/bootstrap/FilesAppContext.php
index 4951dc43f1d..117f3b54fb8 100644
--- a/tests/acceptance/features/bootstrap/FilesAppContext.php
+++ b/tests/acceptance/features/bootstrap/FilesAppContext.php
@@ -89,6 +89,15 @@ class FilesAppContext implements Context, ActorAwareInterface {
/**
* @return Locator
*/
+ public static function fileNameInCurrentSectionDetailsView() {
+ return Locator::forThe()->css(".fileName")->
+ descendantOf(self::currentSectionDetailsView())->
+ describedAs("File name in current section details view in Files app");
+ }
+
+ /**
+ * @return Locator
+ */
public static function fileDetailsInCurrentSectionDetailsViewWithText($fileDetailsText) {
return Locator::forThe()->xpath("//span[normalize-space() = '$fileDetailsText']")->
descendantOf(self::fileDetailsInCurrentSectionDetailsView())->
@@ -319,6 +328,14 @@ class FilesAppContext implements Context, ActorAwareInterface {
/**
* @return Locator
*/
+ public static function renameInputForFile($fileName) {
+ return Locator::forThe()->css("input.filename")->descendantOf(self::rowForFile($fileName))->
+ describedAs("Rename input for file $fileName in Files app");
+ }
+
+ /**
+ * @return Locator
+ */
public static function shareActionForFile($fileName) {
return Locator::forThe()->css(".action-share")->descendantOf(self::rowForFile($fileName))->
describedAs("Share action for file $fileName in Files app");
@@ -350,6 +367,13 @@ class FilesAppContext implements Context, ActorAwareInterface {
/**
* @return Locator
*/
+ public static function renameMenuItem() {
+ return self::fileActionsMenuItemFor("Rename");
+ }
+
+ /**
+ * @return Locator
+ */
public static function addToFavoritesMenuItem() {
return self::fileActionsMenuItemFor("Add to favorites");
}
@@ -418,6 +442,17 @@ class FilesAppContext implements Context, ActorAwareInterface {
}
/**
+ * @Given I rename :fileName1 to :fileName2
+ */
+ public function iRenameTo($fileName1, $fileName2) {
+ $this->actor->find(self::fileActionsMenuButtonForFile($fileName1), 10)->click();
+
+ $this->actor->find(self::renameMenuItem(), 2)->click();
+
+ $this->actor->find(self::renameInputForFile($fileName1), 10)->setValue($fileName2 . "\r");
+ }
+
+ /**
* @Given I mark :fileName as favorite
*/
public function iMarkAsFavorite($fileName) {
@@ -543,6 +578,13 @@ class FilesAppContext implements Context, ActorAwareInterface {
}
/**
+ * @Then I see that the file list contains a file named :fileName
+ */
+ public function iSeeThatTheFileListContainsAFileNamed($fileName) {
+ PHPUnit_Framework_Assert::assertNotNull($this->actor->find(self::rowForFile($fileName), 10));
+ }
+
+ /**
* @Then I see that :fileName1 precedes :fileName2 in the file list
*/
public function iSeeThatPrecedesInTheFileList($fileName1, $fileName2) {
@@ -564,6 +606,14 @@ class FilesAppContext implements Context, ActorAwareInterface {
}
/**
+ * @Then I see that the file name shown in the details view is :fileName
+ */
+ public function iSeeThatTheFileNameShownInTheDetailsViewIs($fileName) {
+ PHPUnit_Framework_Assert::assertEquals(
+ $this->actor->find(self::fileNameInCurrentSectionDetailsView(), 10)->getText(), $fileName);
+ }
+
+ /**
* @Then I see that the input field for tags in the details view is shown
*/
public function iSeeThatTheInputFieldForTagsInTheDetailsViewIsShown() {
diff --git a/tests/acceptance/features/bootstrap/LoginPageContext.php b/tests/acceptance/features/bootstrap/LoginPageContext.php
index 560dd83f308..1496e3030c2 100644
--- a/tests/acceptance/features/bootstrap/LoginPageContext.php
+++ b/tests/acceptance/features/bootstrap/LoginPageContext.php
@@ -66,7 +66,7 @@ class LoginPageContext implements Context, ActorAwareInterface {
* @return Locator
*/
public static function wrongPasswordMessage() {
- return Locator::forThe()->xpath("//*[@class = 'warning' and normalize-space() = 'Wrong password.']")->
+ return Locator::forThe()->xpath("//*[@class = 'warning wrongPasswordMsg' and normalize-space() = 'Wrong password.']")->
describedAs("Wrong password message in Login page");
}
diff --git a/tests/lib/Preview/GeneratorTest.php b/tests/lib/Preview/GeneratorTest.php
index f1383b0691b..130cccdf09e 100644
--- a/tests/lib/Preview/GeneratorTest.php
+++ b/tests/lib/Preview/GeneratorTest.php
@@ -93,6 +93,8 @@ class GeneratorTest extends \Test\TestCase {
$maxPreview = $this->createMock(ISimpleFile::class);
$maxPreview->method('getName')
->willReturn('1000-1000-max.png');
+ $maxPreview->method('getMimeType')
+ ->willReturn('image/png');
$previewFolder->method('getDirectoryListing')
->willReturn([$maxPreview]);
@@ -170,6 +172,7 @@ class GeneratorTest extends \Test\TestCase {
$image->method('width')->willReturn(2048);
$image->method('height')->willReturn(2048);
$image->method('valid')->willReturn(true);
+ $image->method('dataMimeType')->willReturn('image/png');
$this->helper->method('getThumbnail')
->will($this->returnCallback(function ($provider, $file, $x, $y) use ($invalidProvider, $validProvider, $image) {
@@ -185,6 +188,7 @@ class GeneratorTest extends \Test\TestCase {
$maxPreview = $this->createMock(ISimpleFile::class);
$maxPreview->method('getName')->willReturn('2048-2048-max.png');
+ $maxPreview->method('getMimeType')->willReturn('image/png');
$previewFile = $this->createMock(ISimpleFile::class);
@@ -219,6 +223,7 @@ class GeneratorTest extends \Test\TestCase {
$image->method('data')
->willReturn('my resized data');
$image->method('valid')->willReturn(true);
+ $image->method('dataMimeType')->willReturn('image/png');
$previewFile->expects($this->once())
->method('putContent')
@@ -362,6 +367,8 @@ class GeneratorTest extends \Test\TestCase {
$maxPreview = $this->createMock(ISimpleFile::class);
$maxPreview->method('getName')
->willReturn($maxX . '-' . $maxY . '-max.png');
+ $maxPreview->method('getMimeType')
+ ->willReturn('image/png');
$previewFolder->method('getDirectoryListing')
->willReturn([$maxPreview]);
@@ -382,6 +389,7 @@ class GeneratorTest extends \Test\TestCase {
$image->method('height')->willReturn($maxY);
$image->method('width')->willReturn($maxX);
$image->method('valid')->willReturn(true);
+ $image->method('dataMimeType')->willReturn('image/png');
$preview = $this->createMock(ISimpleFile::class);
$previewFolder->method('newFile')
diff --git a/version.php b/version.php
index 53272cf32fe..c94a897f4e7 100644
--- a/version.php
+++ b/version.php
@@ -29,10 +29,10 @@
// between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel
// when updating major/minor version number.
-$OC_Version = array(13, 0, 0, 8);
+$OC_Version = array(13, 0, 0, 9);
// The human readable string
-$OC_VersionString = '13.0.0 Beta 3';
+$OC_VersionString = '13.0.0 Beta 4';
$OC_VersionCanBeUpgradedFrom = [
'nextcloud' => [