Merge branch 'release/1.6.8'

This commit is contained in:
Julian Raufelder 2021-12-07 11:55:15 +01:00
commit cf5c7b924a
No known key found for this signature in database
GPG Key ID: 17EE71F6634E381D
27 changed files with 134 additions and 43 deletions

View File

@ -39,7 +39,7 @@ allprojects {
ext { ext {
androidApplicationId = 'org.cryptomator' androidApplicationId = 'org.cryptomator'
androidVersionCode = getVersionCode() androidVersionCode = getVersionCode()
androidVersionName = '1.6.7' androidVersionName = '1.6.8'
} }
repositories { repositories {
mavenCentral() mavenCentral()

View File

@ -56,5 +56,9 @@ class DropboxClientFactory {
return HttpLoggingInterceptor(logger, context) return HttpLoggingInterceptor(logger, context)
} }
fun logout() {
instance = null
}
} }
} }

View File

@ -203,7 +203,7 @@ internal class DropboxCloudContentRepository(private val cloud: DropboxCloud, co
@Throws(BackendException::class) @Throws(BackendException::class)
override fun logout(cloud: DropboxCloud) { override fun logout(cloud: DropboxCloud) {
// empty this.cloud.logout()
} }
} }

View File

@ -372,6 +372,10 @@ internal class DropboxImpl(cloud: DropboxCloud, context: Context) {
return currentAccount.name.displayName return currentAccount.name.displayName
} }
fun logout() {
DropboxClientFactory.logout()
}
companion object { companion object {
private const val CHUNKED_UPLOAD_CHUNK_SIZE = 8L shl 20 private const val CHUNKED_UPLOAD_CHUNK_SIZE = 8L shl 20

View File

@ -59,5 +59,10 @@ class OnedriveClientFactory private constructor() {
return HttpLoggingInterceptor(logger, context) return HttpLoggingInterceptor(logger, context)
} }
@Synchronized
fun logout() {
instance = null
}
} }
} }

View File

@ -481,6 +481,8 @@ internal class OnedriveImpl(cloud: OnedriveCloud, context: Context, nodeInfoCach
} catch (e: ExecutionException) { } catch (e: ExecutionException) {
throw FatalBackendException(e) throw FatalBackendException(e)
} }
OnedriveClientFactory.logout()
} }
companion object { companion object {

View File

@ -53,5 +53,10 @@ class PCloudClientFactory {
return HttpLoggingInterceptor(logger, context) return HttpLoggingInterceptor(logger, context)
} }
@Synchronized
fun logout() {
instance = null
}
} }
} }

View File

@ -171,7 +171,7 @@ internal class PCloudContentRepository(private val cloud: PCloud, context: Conte
@Throws(BackendException::class) @Throws(BackendException::class)
override fun logout(cloud: PCloud) { override fun logout(cloud: PCloud) {
// empty this.cloud.logout()
} }
} }

View File

@ -359,6 +359,10 @@ internal class PCloudImpl(context: Context, cloud: PCloud) {
} }
} }
fun logout() {
PCloudClientFactory.logout()
}
init { init {
if (cloud.accessToken() == null) { if (cloud.accessToken() == null) {
throw NoAuthenticationProvidedException(cloud) throw NoAuthenticationProvidedException(cloud)

View File

@ -85,5 +85,10 @@ class S3ClientFactory private constructor() {
val activeNetworkInfo = connectivityManager.activeNetworkInfo val activeNetworkInfo = connectivityManager.activeNetworkInfo
return activeNetworkInfo != null && activeNetworkInfo.isConnected return activeNetworkInfo != null && activeNetworkInfo.isConnected
} }
@Synchronized
fun logout() {
instance = null
}
} }
} }

View File

@ -169,7 +169,7 @@ internal class S3CloudContentRepository(private val cloud: S3Cloud, context: Con
@Throws(BackendException::class) @Throws(BackendException::class)
override fun logout(cloud: S3Cloud) { override fun logout(cloud: S3Cloud) {
// empty this.cloud.logout()
} }
} }

View File

@ -366,6 +366,10 @@ internal class S3Impl(context: Context, cloud: S3Cloud) {
} }
} }
fun logout() {
S3ClientFactory.logout()
}
companion object { companion object {
private const val DELIMITER = "/" private const val DELIMITER = "/"

View File

@ -110,12 +110,11 @@ internal class WebDavCompatibleHttpClient(cloud: WebDavCloud, context: Context)
val credentials = Credentials(webDavCloud.username(), decryptPassword(context, webDavCloud.password())) val credentials = Credentials(webDavCloud.username(), decryptPassword(context, webDavCloud.password()))
val basicAuthenticator = BasicAuthenticator(credentials, StandardCharsets.UTF_8) val basicAuthenticator = BasicAuthenticator(credentials, StandardCharsets.UTF_8)
val digestAuthenticator = DigestAuthenticator(credentials) val digestAuthenticator = DigestAuthenticator(credentials)
var result: Authenticator = DispatchingAuthenticator.Builder() // val authenticator = DispatchingAuthenticator.Builder() //
.with("digest", digestAuthenticator) // .with("digest", digestAuthenticator) //
.with("basic", basicAuthenticator) // .with("basic", basicAuthenticator) //
.build() .build()
result = CachingAuthenticatorDecorator(result, authCache) return CachingAuthenticatorDecorator(authenticator, authCache)
return result
} }
@Throws(UnableToDecryptWebdavPasswordException::class) @Throws(UnableToDecryptWebdavPasswordException::class)

View File

@ -61,5 +61,9 @@ class GoogleDriveClientFactory internal constructor() {
} }
.build() .build()
} }
fun invalidateClient() {
instance = null
}
} }
} }

View File

@ -188,7 +188,7 @@ internal class GoogleDriveCloudContentRepository(context: Context, private val c
@Throws(BackendException::class) @Throws(BackendException::class)
override fun logout(cloud: GoogleDriveCloud) { override fun logout(cloud: GoogleDriveCloud) {
// empty impl.logout()
} }
} }

View File

@ -382,6 +382,10 @@ internal class GoogleDriveImpl(context: Context, googleDriveCloud: GoogleDriveCl
return about.user.displayName return about.user.displayName
} }
fun logout() {
GoogleDriveClientFactory.invalidateClient()
}
companion object { companion object {
private const val STATUS_REQUEST_RANGE_NOT_SATISFIABLE = 416 private const val STATUS_REQUEST_RANGE_NOT_SATISFIABLE = 416

View File

@ -1 +1,2 @@
- Automatischer Upload bei Geräten mit Android Version 10 behoben - Zeige Dialog und Benachrichtigung an, wenn die Berechtigung "Dateien" widerrufen wird, erforderlich für den automatischen Upload
- Das Abmelden von einer Cloud löscht nun auch die Anmeldeinformationen einer aktiven Verbindung zu ihr

View File

@ -1 +1,2 @@
- Fixed auto upload via devices running Android version 10 - Show information when "Storage" permission revoked, required for auto upload
- Logging out of a cloud now also clears the credentials of an active connection to it

View File

@ -1,3 +1,4 @@
<ul> <ul>
<li>Fixed auto upload via devices running Android version 10</li> <li>Show information when "Storage" permission revoked, required for auto upload</li>
<li>Logging out of a cloud now also clears the credentials of an active connection to it</li>
</ul> </ul>

View File

@ -112,6 +112,7 @@ class UnlockVaultPresenter @Inject constructor(
view?.closeDialog() view?.closeDialog()
val error = result.getSingleResult(Throwable::class.java) val error = result.getSingleResult(Throwable::class.java)
error?.let { showError(it) } error?.let { showError(it) }
finishWithResult(null)
} }
} }
@ -219,6 +220,7 @@ class UnlockVaultPresenter @Inject constructor(
view?.closeDialog() view?.closeDialog()
val error = result.getSingleResult(Throwable::class.java) val error = result.getSingleResult(Throwable::class.java)
error?.let { showError(it) } error?.let { showError(it) }
finishWithResult(null)
} }
} }

View File

@ -1,5 +1,6 @@
package org.cryptomator.presentation.presenter package org.cryptomator.presentation.presenter
import android.Manifest
import android.app.KeyguardManager import android.app.KeyguardManager
import android.app.admin.DevicePolicyManager import android.app.admin.DevicePolicyManager
import android.content.ActivityNotFoundException import android.content.ActivityNotFoundException
@ -56,6 +57,7 @@ import org.cryptomator.presentation.workflow.ActivityResult
import org.cryptomator.presentation.workflow.AddExistingVaultWorkflow import org.cryptomator.presentation.workflow.AddExistingVaultWorkflow
import org.cryptomator.presentation.workflow.AuthenticationExceptionHandler import org.cryptomator.presentation.workflow.AuthenticationExceptionHandler
import org.cryptomator.presentation.workflow.CreateNewVaultWorkflow import org.cryptomator.presentation.workflow.CreateNewVaultWorkflow
import org.cryptomator.presentation.workflow.PermissionsResult
import org.cryptomator.presentation.workflow.Workflow import org.cryptomator.presentation.workflow.Workflow
import org.cryptomator.util.SharedPreferencesHandler import org.cryptomator.util.SharedPreferencesHandler
import javax.inject.Inject import javax.inject.Inject
@ -112,6 +114,10 @@ class VaultListPresenter @Inject constructor( //
} }
checkLicense() checkLicense()
if(sharedPreferencesHandler.usePhotoUpload()) {
checkLocalStoragePermissionRegardingAutoUpload()
}
} }
private fun checkLicense() { private fun checkLicense() {
@ -185,6 +191,27 @@ class VaultListPresenter @Inject constructor( //
} }
} }
private fun checkLocalStoragePermissionRegardingAutoUpload() {
requestPermissions(
PermissionsResultCallbacks.onLocalStoragePermissionGrantedForAutoUpload(), //
R.string.permission_snackbar_auth_auto_upload, //
Manifest.permission.READ_EXTERNAL_STORAGE
)
}
@Callback
fun onLocalStoragePermissionGrantedForAutoUpload(result: PermissionsResult) {
if (!result.granted()) {
Timber.tag("VaultListPresenter").e("Local storage permission not granted, auto upload will not work")
}
}
fun loadVaultList() {
view?.hideVaultCreationHint()
vaultList
assertUnlockingVaultIsLocked()
}
private fun assertUnlockingVaultIsLocked() { private fun assertUnlockingVaultIsLocked() {
if (view?.isShowingDialog(EnterPasswordDialog::class) == true) { if (view?.isShowingDialog(EnterPasswordDialog::class) == true) {
if (view?.currentDialog() != null) { if (view?.currentDialog() != null) {
@ -196,12 +223,6 @@ class VaultListPresenter @Inject constructor( //
} }
} }
fun loadVaultList() {
view?.hideVaultCreationHint()
vaultList
assertUnlockingVaultIsLocked()
}
fun deleteVault(vaultModel: VaultModel) { fun deleteVault(vaultModel: VaultModel) {
deleteVaultUseCase // deleteVaultUseCase //
.withVault(vaultModel.toVault()) // .withVault(vaultModel.toVault()) //

View File

@ -47,18 +47,15 @@ class AutoUploadNotification(private val context: Context, private val amountOfP
} }
private fun cancelNowAction(): NotificationCompat.Action { private fun cancelNowAction(): NotificationCompat.Action {
val intentAction = cancelAutoUploadIntent(context)
val cancelIntent = PendingIntent.getService(context, 0, intentAction, FLAG_CANCEL_CURRENT)
return NotificationCompat.Action.Builder( // return NotificationCompat.Action.Builder( //
R.drawable.ic_lock, // R.drawable.ic_lock, //
getString(R.string.notification_cancel_auto_upload), // getString(R.string.notification_cancel_auto_upload), //
cancelNowIntent() // cancelIntent //
).build() ).build()
} }
private fun cancelNowIntent(): PendingIntent {
val intentAction = cancelAutoUploadIntent(context)
return PendingIntent.getService(context, 0, intentAction, FLAG_CANCEL_CURRENT)
}
private fun startTheActivity(): PendingIntent { private fun startTheActivity(): PendingIntent {
val startTheActivity = Intent(context, VaultListActivity::class.java) val startTheActivity = Intent(context, VaultListActivity::class.java)
startTheActivity.action = ACTION_MAIN startTheActivity.action = ACTION_MAIN
@ -67,8 +64,8 @@ class AutoUploadNotification(private val context: Context, private val amountOfP
} }
fun update(progress: Int) { fun update(progress: Int) {
builder.setContentIntent(startTheActivity())
builder // builder //
.setContentIntent(startTheActivity())
.setContentText( // .setContentText( //
String.format( String.format(
context.getString(R.string.notification_auto_upload_message), // context.getString(R.string.notification_auto_upload_message), //
@ -105,27 +102,32 @@ class AutoUploadNotification(private val context: Context, private val amountOfP
showErrorWithMessage(context.getString(R.string.notification_auto_upload_failed_due_to_vault_not_found)) showErrorWithMessage(context.getString(R.string.notification_auto_upload_failed_due_to_vault_not_found))
} }
fun showPermissionNotGrantedNotification() {
Timber.tag("AutoUploadNotification").i("Show storage permission required notification")
showErrorWithMessage(context.getString(R.string.notification_auto_upload_permission_not_granted))
}
private fun showErrorWithMessage(message: String) { private fun showErrorWithMessage(message: String) {
builder.setContentIntent(startTheActivity()) builder
builder // .setContentIntent(startTheActivity())
.setContentTitle(context.getString(R.string.notification_auto_upload_failed_title)) .setContentTitle(context.getString(R.string.notification_auto_upload_failed_title))
.setContentText(message) // .setContentText(message) //
.setProgress(0, 0, false) .setProgress(0, 0, false)
.setAutoCancel(true) .setAutoCancel(true)
.setOngoing(false) .setOngoing(false)
.mActions.clear() .clearActions()
show() show()
} }
fun showUploadFinished(size: Int) { fun showUploadFinished(size: Int) {
builder.setContentIntent(startTheActivity()) builder
builder // .setContentIntent(startTheActivity())
.setContentTitle(context.getString(R.string.notification_auto_upload_finished_title)) .setContentTitle(context.getString(R.string.notification_auto_upload_finished_title))
.setContentText(format(context.getString(R.string.notification_auto_upload_finished_message), size)) // .setContentText(format(context.getString(R.string.notification_auto_upload_finished_message), size))
.setProgress(0, 0, false) .setProgress(0, 0, false)
.setAutoCancel(true) .setAutoCancel(true)
.setOngoing(false) .setOngoing(false)
.mActions.clear() .clearActions()
show() show()
} }

View File

@ -10,6 +10,8 @@ import android.net.Uri;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
import android.os.Looper; import android.os.Looper;
import android.system.ErrnoException;
import android.system.OsConstants;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@ -37,6 +39,7 @@ import org.cryptomator.presentation.util.FileUtil;
import org.cryptomator.util.SharedPreferencesHandler; import org.cryptomator.util.SharedPreferencesHandler;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
@ -111,6 +114,8 @@ public class AutoUploadService extends Service {
notification.showVaultLockedDuringUpload(); notification.showVaultLockedDuringUpload();
} else if (e instanceof CancellationException) { } else if (e instanceof CancellationException) {
Timber.tag("AutoUploadService").i("Upload canceled by user"); Timber.tag("AutoUploadService").i("Upload canceled by user");
} else if (wrappedStoragePermissionException(e)) {
notification.showPermissionNotGrantedNotification();
} else { } else {
notification.showGeneralErrorDuringUpload(); notification.showGeneralErrorDuringUpload();
} }
@ -122,6 +127,14 @@ public class AutoUploadService extends Service {
worker.start(); worker.start();
} }
private boolean wrappedStoragePermissionException(Exception e) {
return e.getCause() != null //
&& e.getCause() instanceof FileNotFoundException //
&& e.getCause().getCause() != null //
&& e.getCause().getCause() instanceof ErrnoException //
&& ((ErrnoException) e.getCause().getCause()).errno == OsConstants.EACCES;
}
private void updateNotification(int asPercentage) { private void updateNotification(int asPercentage) {
if (elapsedTimeAutoUploadNotificationDelay > 200 && !cancelled) { if (elapsedTimeAutoUploadNotificationDelay > 200 && !cancelled) {
new Handler(Looper.getMainLooper()).post(() -> { new Handler(Looper.getMainLooper()).post(() -> {
@ -170,8 +183,7 @@ public class AutoUploadService extends Service {
} catch (FileRemovedDuringUploadException e) { } catch (FileRemovedDuringUploadException e) {
Timber.tag("AutoUploadService").i("Not uploading file because it was removed during upload"); Timber.tag("AutoUploadService").i("Not uploading file because it was removed during upload");
Timber.tag("AutoUploadService").v(format("Not uploading file because it was removed during upload %s", file.getFileName())); Timber.tag("AutoUploadService").v(format("Not uploading file because it was removed during upload %s", file.getFileName()));
} } catch (Exception e) {
catch (Exception e) {
cancelled = true; cancelled = true;
fileUtil.removeImagesFromAutoUploads(uploadedCloudFileNames); fileUtil.removeImagesFromAutoUploads(uploadedCloudFileNames);
throw e; throw e;

View File

@ -13,10 +13,10 @@
<string name="error_vault_already_exists">Le coffre-fort existe déjà.</string> <string name="error_vault_already_exists">Le coffre-fort existe déjà.</string>
<string name="error_no_such_file">Le fichier n\'existe pas.</string> <string name="error_no_such_file">Le fichier n\'existe pas.</string>
<string name="error_vault_has_been_locked">Le coffre-fort a été verrouillé.</string> <string name="error_vault_has_been_locked">Le coffre-fort a été verrouillé.</string>
<string name="error_cloud_already_exists">Cloud existant.</string> <string name="error_cloud_already_exists">Compte Cloud déjà existant.</string>
<string name="error_activity_not_found">Veuillez télécharger une application qui peut ouvrir ce fichier.</string> <string name="error_activity_not_found">Veuillez télécharger une application qui peut ouvrir ce fichier.</string>
<string name="error_server_not_found">Serveur introuvable.</string> <string name="error_server_not_found">Serveur introuvable.</string>
<string name="error_device_policy_manager_not_found">Veuillez ouvrir les paramètres de votre appareil et régler le verrouillage de l\'écran à la main</string> <string name="error_device_policy_manager_not_found">Veuillez ouvrir les paramètres de votre appareil et activer le verrouillage manuel de l\'écran</string>
<string name="error_export_illegal_file_name">L\'exportation a échoué. Essayez de supprimer les caractères spéciaux des noms de fichiers et d\'exporter à nouveau.</string> <string name="error_export_illegal_file_name">L\'exportation a échoué. Essayez de supprimer les caractères spéciaux des noms de fichiers et d\'exporter à nouveau.</string>
<string name="error_name_contains_invalid_characters">Ne peut pas contenir de caractères spéciaux.</string> <string name="error_name_contains_invalid_characters">Ne peut pas contenir de caractères spéciaux.</string>
<string name="error_names_contains_invalid_characters">Les noms de fichiers ne peuvent pas contenir de caractères spéciaux.</string> <string name="error_names_contains_invalid_characters">Les noms de fichiers ne peuvent pas contenir de caractères spéciaux.</string>
@ -24,24 +24,24 @@
<string name="error_general_update">La vérification de la mise à jour a échoué. Une erreur générale s\'est produite.</string> <string name="error_general_update">La vérification de la mise à jour a échoué. Une erreur générale s\'est produite.</string>
<string name="error_hash_mismatch_update">La vérification de la mise à jour a échoué. Le hachage calculé ne correspond pas au fichier téléchargé</string> <string name="error_hash_mismatch_update">La vérification de la mise à jour a échoué. Le hachage calculé ne correspond pas au fichier téléchargé</string>
<string name="error_update_no_internet">La vérification de la mise à jour a échoué. Pas de connexion Internet.</string> <string name="error_update_no_internet">La vérification de la mise à jour a échoué. Pas de connexion Internet.</string>
<string name="error_failed_to_decrypt_webdav_password">Echec lors du déchiffrement du mot de passe WebDAV, veuillez l\'ajouter une nouvelle fois dans les paramètres</string> <string name="error_failed_to_decrypt_webdav_password">Échec lors du déchiffrement du mot de passe WebDAV, veuillez l\'ajouter une nouvelle fois dans les paramètres</string>
<string name="error_play_services_not_available">Les services Google Play ne sont pas installés</string> <string name="error_play_services_not_available">Les services Google Play ne sont pas installés</string>
<string name="error_biometric_auth_aborted">Authentification biométrique avortée</string> <string name="error_biometric_auth_aborted">Authentification biométrique avortée</string>
<string name="error_vault_version_mismatch">La version spécifiée dans %1$s est différente de %2$s</string> <string name="error_vault_version_mismatch">La version spécifiée dans %1$s est différente de %2$s</string>
<string name="error_vault_key_invalid">%1$s ne correspond pas à ce %2$s</string> <string name="error_vault_key_invalid">%1$s ne correspond pas à ce %2$s</string>
<string name="error_vault_config_loading">Erreur générale lors du chargement de la configuration du coffre</string> <string name="error_vault_config_loading">Erreur générale lors du chargement de la configuration du coffre</string>
<string name="error_file_not_found_after_opening_using_3party">Le fichier local n\'est plus présent après le retour à Cryptomator. Les éventuels modifications ne peuvent être propagées au nuage.</string> <string name="error_file_not_found_after_opening_using_3party">Le fichier local n\'est plus présent après le retour à Cryptomator. Les éventuelles modifications ne peuvent être propagées dans le cloud.</string>
<string name="error_no_such_bucket">Aucun compartiment de ce type</string> <string name="error_no_such_bucket">Aucun bucket correspondant</string>
<string name="error_masterkey_location_not_supported">Localisation personnalisée de Masterkey pas encore prise en charge</string> <string name="error_masterkey_location_not_supported">Localisation personnalisée de la Masterkey n\'est pas encore prise en charge</string>
<!-- # clouds --> <!-- # clouds -->
<!-- ## cloud names --> <!-- ## cloud names -->
<string name="cloud_names_local_storage">Stockage local</string> <string name="cloud_names_local_storage">Stockage local</string>
<!-- # permission --> <!-- # permission -->
<!-- ## permission messages --> <!-- ## permission messages -->
<string name="permission_message_export_file">Cryptomator a besoin de l\'accès au stockage pour exporter des fichiers</string> <string name="permission_message_export_file">Cryptomator a besoin de l\'accès au stockage pour exporter des fichiers</string>
<string name="permission_message_upload_file">Cryptomateur a besoin de l\'accès au stockage pour téléverser des fichiers</string> <string name="permission_message_upload_file">Cryptomator a besoin de l\'accès au stockage pour envoyer des fichiers</string>
<string name="permission_message_share_file">Cryptomator a besoin de l\'accès au stockage pour partager des fichiers</string> <string name="permission_message_share_file">Cryptomator a besoin de l\'accès au stockage pour partager des fichiers</string>
<string name="permission_revoked_re_request_permission">Cryptomator n\'a plus accès à cet emplacement. Merci de resélectionner ce répertoire pour restaurer les droits d\'accès.</string> <string name="permission_revoked_re_request_permission">Cryptomator n\'a plus accès à cet emplacement. Merci de re-sélectionner ce répertoire pour restaurer les droits d\'accès.</string>
<string name="snack_bar_action_title_settings">Paramètres</string> <string name="snack_bar_action_title_settings">Paramètres</string>
<string name="snack_bar_action_title_search">Rechercher</string> <string name="snack_bar_action_title_search">Rechercher</string>
<string name="snack_bar_action_title_search_previous">Précédent</string> <string name="snack_bar_action_title_search_previous">Précédent</string>
@ -50,7 +50,7 @@
<string name="snack_bar_action_title_sort_az">A - Z</string> <string name="snack_bar_action_title_sort_az">A - Z</string>
<string name="snack_bar_action_title_sort_za">Z - A</string> <string name="snack_bar_action_title_sort_za">Z - A</string>
<string name="snack_bar_action_title_sort_newest">Récent d\'abord</string> <string name="snack_bar_action_title_sort_newest">Récent d\'abord</string>
<string name="snack_bar_action_title_sort_oldest">Plus ancien</string> <string name="snack_bar_action_title_sort_oldest">Ancien d\'abord</string>
<string name="snack_bar_action_title_sort_biggest">Taille décroissante</string> <string name="snack_bar_action_title_sort_biggest">Taille décroissante</string>
<string name="snack_bar_action_title_sort_smallest">Taille croissante</string> <string name="snack_bar_action_title_sort_smallest">Taille croissante</string>
<!-- # screens --> <!-- # screens -->

View File

@ -368,6 +368,7 @@
<string name="notification_auto_upload_failed_general_error">Errore generale durante il caricamento.</string> <string name="notification_auto_upload_failed_general_error">Errore generale durante il caricamento.</string>
<string name="notification_auto_upload_failed_due_to_folder_not_exists">La cartella selezionata per il caricamento non è più disponibile. Vai alle impostazioni e sceglierne una nuova</string> <string name="notification_auto_upload_failed_due_to_folder_not_exists">La cartella selezionata per il caricamento non è più disponibile. Vai alle impostazioni e sceglierne una nuova</string>
<string name="notification_auto_upload_failed_due_to_vault_locked">Cassaforte bloccata durante il caricamento, riapri la cassaforte per continuare</string> <string name="notification_auto_upload_failed_due_to_vault_locked">Cassaforte bloccata durante il caricamento, riapri la cassaforte per continuare</string>
<string name="notification_auto_upload_failed_due_to_vault_not_found">La cassaforte specificata per il caricamento automatico non esiste più.</string>
<string name="notification_open_writable_file_title">Apri file scrivibile</string> <string name="notification_open_writable_file_title">Apri file scrivibile</string>
<string name="notification_open_writable_file_message">La cassaforte rimane sbloccata fino alla modifica completata</string> <string name="notification_open_writable_file_message">La cassaforte rimane sbloccata fino alla modifica completata</string>
<string name="notification_update_check_finished_latest">Ultima versione installata</string> <string name="notification_update_check_finished_latest">Ultima versione installata</string>

View File

@ -9,10 +9,19 @@
<string name="error_no_network_connection">Ingen nettverkstilkobling</string> <string name="error_no_network_connection">Ingen nettverkstilkobling</string>
<string name="error_invalid_passphrase">Feil passord</string> <string name="error_invalid_passphrase">Feil passord</string>
<string name="error_file_or_folder_exists">En fil eller mappe finnes allerede.</string> <string name="error_file_or_folder_exists">En fil eller mappe finnes allerede.</string>
<string name="error_vault_version_not_supported">Hvelvet støttes ikke. Dette hvelvet er laget med en annen versjon av Cryptomator.</string>
<string name="error_vault_already_exists">Hvelvet finnes allerede.</string> <string name="error_vault_already_exists">Hvelvet finnes allerede.</string>
<string name="error_no_such_file">Filen finnes ikke.</string> <string name="error_no_such_file">Filen finnes ikke.</string>
<string name="error_vault_has_been_locked">Hvelvet har blitt låst.</string> <string name="error_vault_has_been_locked">Hvelvet har blitt låst.</string>
<string name="error_cloud_already_exists">Skylagringen finnes allerede.</string> <string name="error_cloud_already_exists">Skylagringen finnes allerede.</string>
<string name="error_activity_not_found">Vennligst last ned en app som kan åpne denne filen.</string>
<string name="error_server_not_found">Serveren ble ikke funnet.</string>
<string name="error_device_policy_manager_not_found">Vennligst åpne enhetsinnstillingene og angi skjermlås manuelt</string>
<string name="error_export_illegal_file_name">Eksporteringen mislyktes. Prøv å fjerne spesialtegn fra filnavnet og eksporter på nytt.</string>
<string name="error_name_contains_invalid_characters">Kan ikke inneholde spesialtegn.</string>
<string name="error_names_contains_invalid_characters">Filnavn kan ikke inneholde spesialtegn.</string>
<string name="error_vault_name_contains_invalid_characters">Navn på hvelvet kan ikke inneholde spesialtegn.</string>
<string name="error_general_update">Oppdateringskontrollen mislyktes. Det oppstod en generell feil.</string>
<!-- # clouds --> <!-- # clouds -->
<!-- ## cloud names --> <!-- ## cloud names -->
<string name="cloud_names_local_storage">Lokal lagring</string> <string name="cloud_names_local_storage">Lokal lagring</string>

View File

@ -538,6 +538,7 @@
<string name="notification_auto_upload_failed_due_to_folder_not_exists">Selected folder for upload isn\'t available anymore. Go to settings and choose a new one</string> <string name="notification_auto_upload_failed_due_to_folder_not_exists">Selected folder for upload isn\'t available anymore. Go to settings and choose a new one</string>
<string name="notification_auto_upload_failed_due_to_vault_locked">Vault locked during upload, please reopen vault to continue</string> <string name="notification_auto_upload_failed_due_to_vault_locked">Vault locked during upload, please reopen vault to continue</string>
<string name="notification_auto_upload_failed_due_to_vault_not_found">Vault specified for auto upload doesn\'t exist anymore.</string> <string name="notification_auto_upload_failed_due_to_vault_not_found">Vault specified for auto upload doesn\'t exist anymore.</string>
<string name="notification_auto_upload_permission_not_granted" translatable="false">@string/permission_snackbar_auth_auto_upload</string>
<string name="notification_cancel_open_writable_file" translatable="false">@string/dialog_button_cancel</string> <string name="notification_cancel_open_writable_file" translatable="false">@string/dialog_button_cancel</string>
<string name="notification_open_writable_file_title">Open writable file</string> <string name="notification_open_writable_file_title">Open writable file</string>