Reformat code using new Kotlin formatting rule

This commit is contained in:
Julian Raufelder 2021-05-17 18:26:07 +02:00
parent bb07076ba8
commit 5c024dbda9
No known key found for this signature in database
GPG Key ID: 17EE71F6634E381D
122 changed files with 2235 additions and 2008 deletions

View File

@ -88,7 +88,8 @@ public class CryptoCloudFactory {
case MASTERKEY_SCHEME: {
return new MasterkeyCryptoCloudProvider(cloudContentRepository, cryptoCloudContentRepositoryFactory, secureRandom);
}
default: throw new IllegalStateException(String.format("Provider with scheme %s not supported", unverifiedVaultConfigOptional.get().getKeyId().getScheme()));
default:
throw new IllegalStateException(String.format("Provider with scheme %s not supported", unverifiedVaultConfigOptional.get().getKeyId().getScheme()));
}
} else {
return new MasterkeyCryptoCloudProvider(cloudContentRepository, cryptoCloudContentRepositoryFactory, secureRandom);

View File

@ -162,7 +162,7 @@ public class MasterkeyCryptoCloudProvider implements CryptoCloudProvider {
private CloudFile masterkeyFile(CloudFolder vaultLocation, UnverifiedVaultConfig unverifiedVaultConfig) throws BackendException {
String path = unverifiedVaultConfig.getKeyId().getSchemeSpecificPart();
if(!path.equals(MASTERKEY_FILE_NAME)) {
if (!path.equals(MASTERKEY_FILE_NAME)) {
throw new UnsupportedMasterkeyLocationException(unverifiedVaultConfig);
}
return cloudContentRepository.file(vaultLocation, path);

View File

@ -28,13 +28,13 @@ class VaultConfig private constructor(builder: VaultConfigBuilder) {
fun toToken(rawKey: ByteArray): String {
return Jwts.builder()
.setHeaderParam(JSON_KEY_ID, keyId.toASCIIString()) //
.setId(id) //
.claim(JSON_KEY_VAULTFORMAT, vaultFormat) //
.claim(JSON_KEY_CIPHERCONFIG, cipherCombo.name) //
.claim(JSON_KEY_SHORTENING_THRESHOLD, shorteningThreshold) //
.signWith(Keys.hmacShaKeyFor(rawKey)) //
.compact()
.setHeaderParam(JSON_KEY_ID, keyId.toASCIIString()) //
.setId(id) //
.claim(JSON_KEY_VAULTFORMAT, vaultFormat) //
.claim(JSON_KEY_CIPHERCONFIG, cipherCombo.name) //
.claim(JSON_KEY_SHORTENING_THRESHOLD, shorteningThreshold) //
.signWith(Keys.hmacShaKeyFor(rawKey)) //
.compact()
}
class VaultConfigBuilder {
@ -101,18 +101,18 @@ class VaultConfig private constructor(builder: VaultConfigBuilder) {
fun verify(rawKey: ByteArray, unverifiedVaultConfig: UnverifiedVaultConfig): VaultConfig {
return try {
val parser = Jwts //
.parserBuilder() //
.setSigningKey(rawKey) //
.require(JSON_KEY_VAULTFORMAT, unverifiedVaultConfig.vaultFormat) //
.build() //
.parseClaimsJws(unverifiedVaultConfig.jwt)
.parserBuilder() //
.setSigningKey(rawKey) //
.require(JSON_KEY_VAULTFORMAT, unverifiedVaultConfig.vaultFormat) //
.build() //
.parseClaimsJws(unverifiedVaultConfig.jwt)
val vaultConfigBuilder = createVaultConfig() //
.keyId(unverifiedVaultConfig.keyId)
.id(parser.header[JSON_KEY_ID] as String) //
.cipherCombo(VaultCipherCombo.valueOf(parser.body.get(JSON_KEY_CIPHERCONFIG, String::class.java))) //
.vaultFormat(unverifiedVaultConfig.vaultFormat) //
.shorteningThreshold(parser.body[JSON_KEY_SHORTENING_THRESHOLD] as Int)
.keyId(unverifiedVaultConfig.keyId)
.id(parser.header[JSON_KEY_ID] as String) //
.cipherCombo(VaultCipherCombo.valueOf(parser.body.get(JSON_KEY_CIPHERCONFIG, String::class.java))) //
.vaultFormat(unverifiedVaultConfig.vaultFormat) //
.shorteningThreshold(parser.body[JSON_KEY_SHORTENING_THRESHOLD] as Int)
VaultConfig(vaultConfigBuilder)
} catch (e: Exception) {

View File

@ -33,6 +33,30 @@ class S3ClientFactory {
return new HttpLoggingInterceptor(message -> Timber.tag("OkHttp").d(message), context);
}
private static Interceptor provideOfflineCacheInterceptor(final Context context) {
return chain -> {
Request request = chain.request();
if (isNetworkAvailable(context)) {
final CacheControl cacheControl = new CacheControl.Builder() //
.maxAge(0, TimeUnit.DAYS) //
.build();
request = request.newBuilder() //
.cacheControl(cacheControl) //
.build();
}
return chain.proceed(request);
};
}
private static boolean isNetworkAvailable(final Context context) {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
public MinioClient getClient(S3Cloud cloud, Context context) {
if (apiClient == null) {
apiClient = createApiClient(cloud, context);
@ -66,30 +90,6 @@ class S3ClientFactory {
.build();
}
private static Interceptor provideOfflineCacheInterceptor(final Context context) {
return chain -> {
Request request = chain.request();
if (isNetworkAvailable(context)) {
final CacheControl cacheControl = new CacheControl.Builder() //
.maxAge(0, TimeUnit.DAYS) //
.build();
request = request.newBuilder() //
.cacheControl(cacheControl) //
.build();
}
return chain.proceed(request);
};
}
private static boolean isNetworkAvailable(final Context context) {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
private String decrypt(String password, Context context) {
return CredentialCryptor //
.getInstance(context) //

View File

@ -1,14 +1,7 @@
package org.cryptomator.data.cloud.s3;
public enum S3CloudApiErrorCodes {
ACCESS_DENIED("AccessDenied"),
ACCOUNT_PROBLEM("AccountProblem"),
INTERNAL_ERROR("InternalError"),
INVALID_ACCESS_KEY_ID("InvalidAccessKeyId"),
INVALID_BUCKET_NAME("InvalidBucketName"),
INVALID_OBJECT_STATE("InvalidObjectState"),
NO_SUCH_BUCKET("NoSuchBucket"),
NO_SUCH_KEY("NoSuchKey");
ACCESS_DENIED("AccessDenied"), ACCOUNT_PROBLEM("AccountProblem"), INTERNAL_ERROR("InternalError"), INVALID_ACCESS_KEY_ID("InvalidAccessKeyId"), INVALID_BUCKET_NAME("InvalidBucketName"), INVALID_OBJECT_STATE("InvalidObjectState"), NO_SUCH_BUCKET("NoSuchBucket"), NO_SUCH_KEY("NoSuchKey");
private final String value;

View File

@ -3,9 +3,7 @@ package org.cryptomator.data.cloud.s3;
public class S3CloudApiExceptions {
public static boolean isAccessProblem(String errorCode) {
return errorCode.equals(S3CloudApiErrorCodes.ACCESS_DENIED.getValue())
|| errorCode.equals(S3CloudApiErrorCodes.ACCOUNT_PROBLEM.getValue())
|| errorCode.equals(S3CloudApiErrorCodes.INVALID_ACCESS_KEY_ID.getValue());
return errorCode.equals(S3CloudApiErrorCodes.ACCESS_DENIED.getValue()) || errorCode.equals(S3CloudApiErrorCodes.ACCOUNT_PROBLEM.getValue()) || errorCode.equals(S3CloudApiErrorCodes.INVALID_ACCESS_KEY_ID.getValue());
}
public static boolean isNoSuchBucketException(String errorCode) {

View File

@ -63,7 +63,7 @@ class S3CloudContentRepository extends InterceptingCloudContentRepository<S3Clou
if (S3CloudApiExceptions.isAccessProblem(errorCode)) {
throw new WrongCredentialsException(cloud);
}
} else if(e instanceof ForbiddenException) {
} else if (e instanceof ForbiddenException) {
throw new WrongCredentialsException(cloud);
}
}

View File

@ -107,7 +107,7 @@ class S3Impl {
public boolean exists(S3Node node) throws BackendException {
String key = node.getKey();
try {
if(!(node instanceof RootS3Folder)) {
if (!(node instanceof RootS3Folder)) {
client().statObject(StatObjectArgs.builder().bucket(cloud.s3Bucket()).object(key).build());
return true;
} else {
@ -256,7 +256,7 @@ class S3Impl {
Date lastModified = objectWriteResponse.headers().getDate("Last-Modified");
if(lastModified == null) {
if (lastModified == null) {
StatObjectResponse statObjectResponse = client().statObject(StatObjectArgs //
.builder() //
.bucket(cloud.s3Bucket()) //

View File

@ -14,19 +14,19 @@ internal class Upgrade2To3 @Inject constructor(private val context: Context) : D
db.beginTransaction()
try {
Sql.query("CLOUD_ENTITY")
.columns(listOf("ACCESS_TOKEN"))
.where("TYPE", Sql.eq("DROPBOX"))
.executeOn(db).use {
if (it.moveToFirst()) {
Sql.update("CLOUD_ENTITY")
.set("ACCESS_TOKEN", Sql.toString(encrypt(it.getString(it.getColumnIndex("ACCESS_TOKEN")))))
.where("TYPE", Sql.eq("DROPBOX"));
}
.columns(listOf("ACCESS_TOKEN"))
.where("TYPE", Sql.eq("DROPBOX"))
.executeOn(db).use {
if (it.moveToFirst()) {
Sql.update("CLOUD_ENTITY")
.set("ACCESS_TOKEN", Sql.toString(encrypt(it.getString(it.getColumnIndex("ACCESS_TOKEN")))))
.where("TYPE", Sql.eq("DROPBOX"));
}
}
Sql.update("CLOUD_ENTITY")
.set("ACCESS_TOKEN", Sql.toString(encrypt(onedriveToken())))
.where("TYPE", Sql.eq("ONEDRIVE"));
.set("ACCESS_TOKEN", Sql.toString(encrypt(onedriveToken())))
.where("TYPE", Sql.eq("ONEDRIVE"));
db.setTransactionSuccessful()
} finally {
@ -36,8 +36,8 @@ internal class Upgrade2To3 @Inject constructor(private val context: Context) : D
private fun encrypt(token: String?): String? {
return if (token == null) null else CredentialCryptor //
.getInstance(context) //
.encrypt(token)
.getInstance(context) //
.encrypt(token)
}
private fun onedriveToken(): String? {

View File

@ -25,42 +25,42 @@ internal class Upgrade3To4 @Inject constructor() : DatabaseUpgrade(3, 4) {
private fun addPositionToVaultSchema(db: Database) {
Sql.alterTable("VAULT_ENTITY").renameTo("VAULT_ENTITY_OLD").executeOn(db)
Sql.createTable("VAULT_ENTITY") //
.id() //
.optionalInt("FOLDER_CLOUD_ID") //
.optionalText("FOLDER_PATH") //
.optionalText("FOLDER_NAME") //
.requiredText("CLOUD_TYPE") //
.optionalText("PASSWORD") //
.optionalInt("POSITION") //
.foreignKey("FOLDER_CLOUD_ID", "CLOUD_ENTITY", ForeignKeyBehaviour.ON_DELETE_SET_NULL) //
.executeOn(db)
.id() //
.optionalInt("FOLDER_CLOUD_ID") //
.optionalText("FOLDER_PATH") //
.optionalText("FOLDER_NAME") //
.requiredText("CLOUD_TYPE") //
.optionalText("PASSWORD") //
.optionalInt("POSITION") //
.foreignKey("FOLDER_CLOUD_ID", "CLOUD_ENTITY", ForeignKeyBehaviour.ON_DELETE_SET_NULL) //
.executeOn(db)
Sql.insertInto("VAULT_ENTITY") //
.select("_id", "FOLDER_CLOUD_ID", "FOLDER_PATH", "FOLDER_NAME", "PASSWORD", "CLOUD_ENTITY.TYPE") //
.columns("_id", "FOLDER_CLOUD_ID", "FOLDER_PATH", "FOLDER_NAME", "PASSWORD", "CLOUD_TYPE") //
.from("VAULT_ENTITY_OLD") //
.join("CLOUD_ENTITY", "VAULT_ENTITY_OLD.FOLDER_CLOUD_ID") //
.executeOn(db)
.select("_id", "FOLDER_CLOUD_ID", "FOLDER_PATH", "FOLDER_NAME", "PASSWORD", "CLOUD_ENTITY.TYPE") //
.columns("_id", "FOLDER_CLOUD_ID", "FOLDER_PATH", "FOLDER_NAME", "PASSWORD", "CLOUD_TYPE") //
.from("VAULT_ENTITY_OLD") //
.join("CLOUD_ENTITY", "VAULT_ENTITY_OLD.FOLDER_CLOUD_ID") //
.executeOn(db)
Sql.dropIndex("IDX_VAULT_ENTITY_FOLDER_PATH_FOLDER_CLOUD_ID").executeOn(db)
Sql.createUniqueIndex("IDX_VAULT_ENTITY_FOLDER_PATH_FOLDER_CLOUD_ID") //
.on("VAULT_ENTITY") //
.asc("FOLDER_PATH") //
.asc("FOLDER_CLOUD_ID") //
.executeOn(db)
.on("VAULT_ENTITY") //
.asc("FOLDER_PATH") //
.asc("FOLDER_CLOUD_ID") //
.executeOn(db)
Sql.dropTable("VAULT_ENTITY_OLD").executeOn(db)
}
private fun initVaultPositionUsingCurrentSortOrder(db: Database) {
CloudEntityDao(DaoConfig(db, VaultEntityDao::class.java)) //
.loadAll() //
.map {
Sql.update("VAULT_ENTITY") //
.where("_id", Sql.eq(it.id)) //
.set("POSITION", Sql.toInteger(it.id - 1)) //
.executeOn(db)
}
.loadAll() //
.map {
Sql.update("VAULT_ENTITY") //
.where("_id", Sql.eq(it.id)) //
.set("POSITION", Sql.toInteger(it.id - 1)) //
.executeOn(db)
}
}
}

View File

@ -21,19 +21,19 @@ internal class Upgrade4To5 @Inject constructor() : DatabaseUpgrade(4, 5) {
Sql.alterTable("CLOUD_ENTITY").renameTo("CLOUD_ENTITY_OLD").executeOn(db)
Sql.createTable("CLOUD_ENTITY") //
.id() //
.requiredText("TYPE") //
.optionalText("ACCESS_TOKEN") //
.optionalText("URL") //
.optionalText("USERNAME") //
.optionalText("WEBDAV_CERTIFICATE") //
.executeOn(db);
.id() //
.requiredText("TYPE") //
.optionalText("ACCESS_TOKEN") //
.optionalText("URL") //
.optionalText("USERNAME") //
.optionalText("WEBDAV_CERTIFICATE") //
.executeOn(db);
Sql.insertInto("CLOUD_ENTITY") //
.select("_id", "TYPE", "ACCESS_TOKEN", "WEBDAV_URL", "USERNAME", "WEBDAV_CERTIFICATE") //
.columns("_id", "TYPE", "ACCESS_TOKEN", "URL", "USERNAME", "WEBDAV_CERTIFICATE") //
.from("CLOUD_ENTITY_OLD") //
.executeOn(db)
.select("_id", "TYPE", "ACCESS_TOKEN", "WEBDAV_URL", "USERNAME", "WEBDAV_CERTIFICATE") //
.columns("_id", "TYPE", "ACCESS_TOKEN", "URL", "USERNAME", "WEBDAV_CERTIFICATE") //
.from("CLOUD_ENTITY_OLD") //
.executeOn(db)
recreateVaultEntity(db)
@ -43,30 +43,30 @@ internal class Upgrade4To5 @Inject constructor() : DatabaseUpgrade(4, 5) {
private fun recreateVaultEntity(db: Database) {
Sql.alterTable("VAULT_ENTITY").renameTo("VAULT_ENTITY_OLD").executeOn(db)
Sql.createTable("VAULT_ENTITY") //
.id() //
.optionalInt("FOLDER_CLOUD_ID") //
.optionalText("FOLDER_PATH") //
.optionalText("FOLDER_NAME") //
.requiredText("CLOUD_TYPE") //
.optionalText("PASSWORD") //
.optionalInt("POSITION") //
.foreignKey("FOLDER_CLOUD_ID", "CLOUD_ENTITY", Sql.SqlCreateTableBuilder.ForeignKeyBehaviour.ON_DELETE_SET_NULL) //
.executeOn(db)
.id() //
.optionalInt("FOLDER_CLOUD_ID") //
.optionalText("FOLDER_PATH") //
.optionalText("FOLDER_NAME") //
.requiredText("CLOUD_TYPE") //
.optionalText("PASSWORD") //
.optionalInt("POSITION") //
.foreignKey("FOLDER_CLOUD_ID", "CLOUD_ENTITY", Sql.SqlCreateTableBuilder.ForeignKeyBehaviour.ON_DELETE_SET_NULL) //
.executeOn(db)
Sql.insertInto("VAULT_ENTITY") //
.select("_id", "FOLDER_CLOUD_ID", "FOLDER_PATH", "FOLDER_NAME", "PASSWORD", "POSITION", "CLOUD_ENTITY.TYPE") //
.columns("_id", "FOLDER_CLOUD_ID", "FOLDER_PATH", "FOLDER_NAME", "PASSWORD", "POSITION", "CLOUD_TYPE") //
.from("VAULT_ENTITY_OLD") //
.join("CLOUD_ENTITY", "VAULT_ENTITY_OLD.FOLDER_CLOUD_ID") //
.executeOn(db)
.select("_id", "FOLDER_CLOUD_ID", "FOLDER_PATH", "FOLDER_NAME", "PASSWORD", "POSITION", "CLOUD_ENTITY.TYPE") //
.columns("_id", "FOLDER_CLOUD_ID", "FOLDER_PATH", "FOLDER_NAME", "PASSWORD", "POSITION", "CLOUD_TYPE") //
.from("VAULT_ENTITY_OLD") //
.join("CLOUD_ENTITY", "VAULT_ENTITY_OLD.FOLDER_CLOUD_ID") //
.executeOn(db)
Sql.dropIndex("IDX_VAULT_ENTITY_FOLDER_PATH_FOLDER_CLOUD_ID").executeOn(db)
Sql.createUniqueIndex("IDX_VAULT_ENTITY_FOLDER_PATH_FOLDER_CLOUD_ID") //
.on("VAULT_ENTITY") //
.asc("FOLDER_PATH") //
.asc("FOLDER_CLOUD_ID") //
.executeOn(db)
.on("VAULT_ENTITY") //
.asc("FOLDER_PATH") //
.asc("FOLDER_CLOUD_ID") //
.executeOn(db)
Sql.dropTable("VAULT_ENTITY_OLD").executeOn(db)
}

View File

@ -21,22 +21,22 @@ internal class Upgrade5To6 @Inject constructor() : DatabaseUpgrade(5, 6) {
Sql.alterTable("CLOUD_ENTITY").renameTo("CLOUD_ENTITY_OLD").executeOn(db)
Sql.createTable("CLOUD_ENTITY") //
.id() //
.requiredText("TYPE") //
.optionalText("ACCESS_TOKEN") //
.optionalText("URL") //
.optionalText("USERNAME") //
.optionalText("WEBDAV_CERTIFICATE") //
.optionalText("S3_BUCKET") //
.optionalText("S3_REGION") //
.optionalText("S3_SECRET_KEY") //
.executeOn(db);
.id() //
.requiredText("TYPE") //
.optionalText("ACCESS_TOKEN") //
.optionalText("URL") //
.optionalText("USERNAME") //
.optionalText("WEBDAV_CERTIFICATE") //
.optionalText("S3_BUCKET") //
.optionalText("S3_REGION") //
.optionalText("S3_SECRET_KEY") //
.executeOn(db);
Sql.insertInto("CLOUD_ENTITY") //
.select("_id", "TYPE", "ACCESS_TOKEN", "URL", "USERNAME", "WEBDAV_CERTIFICATE") //
.columns("_id", "TYPE", "ACCESS_TOKEN", "URL", "USERNAME", "WEBDAV_CERTIFICATE") //
.from("CLOUD_ENTITY_OLD") //
.executeOn(db)
.select("_id", "TYPE", "ACCESS_TOKEN", "URL", "USERNAME", "WEBDAV_CERTIFICATE") //
.columns("_id", "TYPE", "ACCESS_TOKEN", "URL", "USERNAME", "WEBDAV_CERTIFICATE") //
.from("CLOUD_ENTITY_OLD") //
.executeOn(db)
recreateVaultEntity(db)
@ -46,30 +46,30 @@ internal class Upgrade5To6 @Inject constructor() : DatabaseUpgrade(5, 6) {
private fun recreateVaultEntity(db: Database) {
Sql.alterTable("VAULT_ENTITY").renameTo("VAULT_ENTITY_OLD").executeOn(db)
Sql.createTable("VAULT_ENTITY") //
.id() //
.optionalInt("FOLDER_CLOUD_ID") //
.optionalText("FOLDER_PATH") //
.optionalText("FOLDER_NAME") //
.requiredText("CLOUD_TYPE") //
.optionalText("PASSWORD") //
.optionalInt("POSITION") //
.foreignKey("FOLDER_CLOUD_ID", "CLOUD_ENTITY", Sql.SqlCreateTableBuilder.ForeignKeyBehaviour.ON_DELETE_SET_NULL) //
.executeOn(db)
.id() //
.optionalInt("FOLDER_CLOUD_ID") //
.optionalText("FOLDER_PATH") //
.optionalText("FOLDER_NAME") //
.requiredText("CLOUD_TYPE") //
.optionalText("PASSWORD") //
.optionalInt("POSITION") //
.foreignKey("FOLDER_CLOUD_ID", "CLOUD_ENTITY", Sql.SqlCreateTableBuilder.ForeignKeyBehaviour.ON_DELETE_SET_NULL) //
.executeOn(db)
Sql.insertInto("VAULT_ENTITY") //
.select("_id", "FOLDER_CLOUD_ID", "FOLDER_PATH", "FOLDER_NAME", "PASSWORD", "POSITION", "CLOUD_ENTITY.TYPE") //
.columns("_id", "FOLDER_CLOUD_ID", "FOLDER_PATH", "FOLDER_NAME", "PASSWORD", "POSITION", "CLOUD_TYPE") //
.from("VAULT_ENTITY_OLD") //
.join("CLOUD_ENTITY", "VAULT_ENTITY_OLD.FOLDER_CLOUD_ID") //
.executeOn(db)
.select("_id", "FOLDER_CLOUD_ID", "FOLDER_PATH", "FOLDER_NAME", "PASSWORD", "POSITION", "CLOUD_ENTITY.TYPE") //
.columns("_id", "FOLDER_CLOUD_ID", "FOLDER_PATH", "FOLDER_NAME", "PASSWORD", "POSITION", "CLOUD_TYPE") //
.from("VAULT_ENTITY_OLD") //
.join("CLOUD_ENTITY", "VAULT_ENTITY_OLD.FOLDER_CLOUD_ID") //
.executeOn(db)
Sql.dropIndex("IDX_VAULT_ENTITY_FOLDER_PATH_FOLDER_CLOUD_ID").executeOn(db)
Sql.createUniqueIndex("IDX_VAULT_ENTITY_FOLDER_PATH_FOLDER_CLOUD_ID") //
.on("VAULT_ENTITY") //
.asc("FOLDER_PATH") //
.asc("FOLDER_CLOUD_ID") //
.executeOn(db)
.on("VAULT_ENTITY") //
.asc("FOLDER_PATH") //
.asc("FOLDER_CLOUD_ID") //
.executeOn(db)
Sql.dropTable("VAULT_ENTITY_OLD").executeOn(db)
}

View File

@ -21,20 +21,20 @@ internal class Upgrade6To7 @Inject constructor() : DatabaseUpgrade(6, 7) {
Sql.alterTable("UPDATE_CHECK_ENTITY").renameTo("UPDATE_CHECK_ENTITY_OLD").executeOn(db)
Sql.createTable("UPDATE_CHECK_ENTITY") //
.id() //
.optionalText("LICENSE_TOKEN") //
.optionalText("RELEASE_NOTE") //
.optionalText("VERSION") //
.optionalText("URL_TO_APK") //
.optionalText("APK_SHA256") //
.optionalText("URL_TO_RELEASE_NOTE") //
.executeOn(db)
.id() //
.optionalText("LICENSE_TOKEN") //
.optionalText("RELEASE_NOTE") //
.optionalText("VERSION") //
.optionalText("URL_TO_APK") //
.optionalText("APK_SHA256") //
.optionalText("URL_TO_RELEASE_NOTE") //
.executeOn(db)
Sql.insertInto("UPDATE_CHECK_ENTITY") //
.select("_id", "LICENSE_TOKEN", "RELEASE_NOTE", "VERSION", "URL_TO_APK", "URL_TO_RELEASE_NOTE") //
.columns("_id", "LICENSE_TOKEN", "RELEASE_NOTE", "VERSION", "URL_TO_APK", "URL_TO_RELEASE_NOTE") //
.from("UPDATE_CHECK_ENTITY_OLD") //
.executeOn(db)
.select("_id", "LICENSE_TOKEN", "RELEASE_NOTE", "VERSION", "URL_TO_APK", "URL_TO_RELEASE_NOTE") //
.columns("_id", "LICENSE_TOKEN", "RELEASE_NOTE", "VERSION", "URL_TO_APK", "URL_TO_RELEASE_NOTE") //
.from("UPDATE_CHECK_ENTITY_OLD") //
.executeOn(db)
Sql.dropTable("UPDATE_CHECK_ENTITY_OLD").executeOn(db)
}

View File

@ -26,8 +26,7 @@ public class UpdateCheckEntity extends DatabaseEntity {
}
@Generated(hash = 67239496)
public UpdateCheckEntity(Long id, String licenseToken, String releaseNote, String version, String urlToApk, String apkSha256,
String urlToReleaseNote) {
public UpdateCheckEntity(Long id, String licenseToken, String releaseNote, String version, String urlToApk, String apkSha256, String urlToReleaseNote) {
this.id = id;
this.licenseToken = licenseToken;
this.releaseNote = releaseNote;

View File

@ -182,7 +182,9 @@ public class VaultEntity extends DatabaseEntity {
this.position = position;
}
/** called by internal mechanisms, do not call yourself. */
/**
* called by internal mechanisms, do not call yourself.
*/
@Generated(hash = 674742652)
public void __setDaoSession(DaoSession daoSession) {
this.daoSession = daoSession;

View File

@ -120,7 +120,7 @@ public class UpdateCheckRepositoryImpl implements UpdateCheckRepository {
String apkSha256 = calculateSha256(file);
if(!apkSha256.equals(entity.getApkSha256())) {
if (!apkSha256.equals(entity.getApkSha256())) {
file.delete();
throw new HashMismatchUpdateCheckException(String.format( //
"Sha of calculated hash (%s) doesn't match the specified one (%s)", //
@ -138,9 +138,9 @@ public class UpdateCheckRepositoryImpl implements UpdateCheckRepository {
private String calculateSha256(File file) throws GeneralUpdateErrorException {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
try(DigestInputStream digestInputStream = new DigestInputStream(context.getContentResolver().openInputStream(Uri.fromFile(file)), digest)) {
try (DigestInputStream digestInputStream = new DigestInputStream(context.getContentResolver().openInputStream(Uri.fromFile(file)), digest)) {
byte[] buffer = new byte[8192];
while(digestInputStream.read(buffer) > -1) {
while (digestInputStream.read(buffer) > -1) {
}
}
return new String(Hex.encodeHex(digest.digest()));

View File

@ -3,4 +3,5 @@ package org.cryptomator.domain.exception.vaultconfig;
import org.cryptomator.domain.exception.BackendException;
public class VaultKeyInvalidException extends BackendException {
}

View File

@ -20,7 +20,8 @@ class ChangePassword {
private final Vault vault;
private final Optional<UnverifiedVaultConfig> unverifiedVaultConfig;
private final String oldPassword;
private final String newPassword;;
private final String newPassword;
;
public ChangePassword(CloudRepository cloudRepository, //
@Parameter Vault vault, //

View File

@ -14,9 +14,8 @@ class UnlockVaultUsingMasterkey {
private final CloudRepository cloudRepository;
private final VaultOrUnlockToken vaultOrUnlockToken;
private Optional<UnverifiedVaultConfig> unverifiedVaultConfig;
private final String password;
private Optional<UnverifiedVaultConfig> unverifiedVaultConfig;
private volatile boolean cancelled;
private final Flag cancelledFlag = new Flag() {
@Override

View File

@ -61,21 +61,22 @@ import timber.log.Timber
@PerView
class AuthenticateCloudPresenter @Inject constructor( //
exceptionHandlers: ExceptionHandlers, //
private val cloudModelMapper: CloudModelMapper, //
private val addOrChangeCloudConnectionUseCase: AddOrChangeCloudConnectionUseCase, //
private val getCloudsUseCase: GetCloudsUseCase, //
private val getUsernameUseCase: GetUsernameUseCase, //
private val addExistingVaultWorkflow: AddExistingVaultWorkflow, //
private val createNewVaultWorkflow: CreateNewVaultWorkflow) : Presenter<AuthenticateCloudView>(exceptionHandlers) {
exceptionHandlers: ExceptionHandlers, //
private val cloudModelMapper: CloudModelMapper, //
private val addOrChangeCloudConnectionUseCase: AddOrChangeCloudConnectionUseCase, //
private val getCloudsUseCase: GetCloudsUseCase, //
private val getUsernameUseCase: GetUsernameUseCase, //
private val addExistingVaultWorkflow: AddExistingVaultWorkflow, //
private val createNewVaultWorkflow: CreateNewVaultWorkflow
) : Presenter<AuthenticateCloudView>(exceptionHandlers) {
private val strategies = arrayOf( //
DropboxAuthStrategy(), //
OnedriveAuthStrategy(), //
PCloudAuthStrategy(), //
WebDAVAuthStrategy(), //
S3AuthStrategy(), //
LocalStorageAuthStrategy() //
DropboxAuthStrategy(), //
OnedriveAuthStrategy(), //
PCloudAuthStrategy(), //
WebDAVAuthStrategy(), //
S3AuthStrategy(), //
LocalStorageAuthStrategy() //
)
override fun workflows(): Iterable<Workflow<*>> {
@ -128,17 +129,17 @@ class AuthenticateCloudPresenter @Inject constructor( //
private fun succeedAuthenticationWith(cloud: Cloud) {
addOrChangeCloudConnectionUseCase //
.withCloud(cloud) //
.run(object : DefaultResultHandler<Void?>() {
override fun onSuccess(void: Void?) {
finishWithResult(cloudModelMapper.toModel(cloud))
}
.withCloud(cloud) //
.run(object : DefaultResultHandler<Void?>() {
override fun onSuccess(void: Void?) {
finishWithResult(cloudModelMapper.toModel(cloud))
}
override fun onError(e: Throwable) {
super.onError(e)
finish()
}
})
override fun onError(e: Throwable) {
super.onError(e)
finish()
}
})
}
private fun failAuthentication(cloudName: Int) {
@ -180,9 +181,10 @@ class AuthenticateCloudPresenter @Inject constructor( //
failAuthentication(cloudModel.name())
} else {
getUsernameAndSuceedAuthentication( //
DropboxCloud.aCopyOf(cloudModel.toCloud() as DropboxCloud) //
.withAccessToken(encrypt(authToken)) //
.build())
DropboxCloud.aCopyOf(cloudModel.toCloud() as DropboxCloud) //
.withAccessToken(encrypt(authToken)) //
.build()
)
}
}
}
@ -200,10 +202,12 @@ class AuthenticateCloudPresenter @Inject constructor( //
fun onGoogleDriveAuthenticated(result: ActivityResult, cloud: CloudModel) {
if (result.isResultOk) {
val accountName = result.intent()?.extras?.getString(AccountManager.KEY_ACCOUNT_NAME)
succeedAuthenticationWith(GoogleDriveCloud.aCopyOf(cloud.toCloud() as GoogleDriveCloud) //
succeedAuthenticationWith(
GoogleDriveCloud.aCopyOf(cloud.toCloud() as GoogleDriveCloud) //
.withUsername(accountName) //
.withAccessToken(accountName) //
.build())
.build()
)
} else {
failAuthentication(cloud.name())
}
@ -245,9 +249,10 @@ class AuthenticateCloudPresenter @Inject constructor( //
private fun handleAuthenticationResult(cloud: CloudModel, accessToken: String) {
getUsernameAndSuceedAuthentication( //
OnedriveCloud.aCopyOf(cloud.toCloud() as OnedriveCloud) //
.withAccessToken(accessToken) //
.build())
OnedriveCloud.aCopyOf(cloud.toCloud() as OnedriveCloud) //
.withAccessToken(accessToken) //
.build()
)
}
}
@ -265,9 +270,10 @@ class AuthenticateCloudPresenter @Inject constructor( //
if (!authenticationStarted) {
startAuthentication()
Toast.makeText(
context(),
String.format(getString(R.string.error_authentication_failed_re_authenticate), intent.cloud().username()),
Toast.LENGTH_LONG).show()
context(),
String.format(getString(R.string.error_authentication_failed_re_authenticate), intent.cloud().username()),
Toast.LENGTH_LONG
).show()
}
}
else -> {
@ -280,15 +286,18 @@ class AuthenticateCloudPresenter @Inject constructor( //
private fun startAuthentication() {
authenticationStarted = true
val authIntent: Intent = AuthorizationActivity.createIntent(
context(),
AuthorizationRequest.create()
.setType(AuthorizationRequest.Type.TOKEN)
.setClientId(BuildConfig.PCLOUD_CLIENT_ID)
.setForceAccessApproval(true)
.addPermission("manageshares")
.build())
requestActivityResult(ActivityResultCallbacks.pCloudReAuthenticationFinished(), //
authIntent)
context(),
AuthorizationRequest.create()
.setType(AuthorizationRequest.Type.TOKEN)
.setClientId(BuildConfig.PCLOUD_CLIENT_ID)
.setForceAccessApproval(true)
.addPermission("manageshares")
.build()
)
requestActivityResult(
ActivityResultCallbacks.pCloudReAuthenticationFinished(), //
authIntent
)
}
}
@ -300,19 +309,19 @@ class AuthenticateCloudPresenter @Inject constructor( //
when (result) {
AuthorizationResult.ACCESS_GRANTED -> {
val accessToken: String = CredentialCryptor //
.getInstance(context()) //
.encrypt(authData.token)
.getInstance(context()) //
.encrypt(authData.token)
val pCloudSkeleton: PCloud = PCloud.aPCloud() //
.withAccessToken(accessToken)
.withUrl(authData.apiHost)
.build();
.withAccessToken(accessToken)
.withUrl(authData.apiHost)
.build();
getUsernameUseCase //
.withCloud(pCloudSkeleton) //
.run(object : DefaultResultHandler<String>() {
override fun onSuccess(username: String?) {
prepareForSavingPCloud(PCloud.aCopyOf(pCloudSkeleton).withUsername(username).build())
}
})
.withCloud(pCloudSkeleton) //
.run(object : DefaultResultHandler<String>() {
override fun onSuccess(username: String?) {
prepareForSavingPCloud(PCloud.aCopyOf(pCloudSkeleton).withUsername(username).build())
}
})
}
AuthorizationResult.ACCESS_DENIED -> {
Timber.tag("CloudConnListPresenter").e("Account access denied")
@ -331,20 +340,22 @@ class AuthenticateCloudPresenter @Inject constructor( //
fun prepareForSavingPCloud(cloud: PCloud) {
getCloudsUseCase //
.withCloudType(cloud.type()) //
.run(object : DefaultResultHandler<List<Cloud>>() {
override fun onSuccess(clouds: List<Cloud>) {
clouds.firstOrNull {
(it as PCloud).username() == cloud.username()
}?.let {
it as PCloud
succeedAuthenticationWith(PCloud.aCopyOf(it) //
.withUrl(cloud.url())
.withAccessToken(cloud.accessToken())
.build())
} ?: succeedAuthenticationWith(cloud)
}
})
.withCloudType(cloud.type()) //
.run(object : DefaultResultHandler<List<Cloud>>() {
override fun onSuccess(clouds: List<Cloud>) {
clouds.firstOrNull {
(it as PCloud).username() == cloud.username()
}?.let {
it as PCloud
succeedAuthenticationWith(
PCloud.aCopyOf(it) //
.withUrl(cloud.url())
.withAccessToken(cloud.accessToken())
.build()
)
} ?: succeedAuthenticationWith(cloud)
}
})
}
private inner class WebDAVAuthStrategy : AuthStrategy {
@ -392,11 +403,13 @@ class AuthenticateCloudPresenter @Inject constructor( //
fun onAcceptWebDavCertificateClicked(cloud: WebDavCloud?, certificate: X509Certificate?) {
try {
val webDavCloudWithAcceptedCert = WebDavCloud.aCopyOf(cloud) //
.withCertificate(X509CertificateHelper.convertToPem(certificate)) //
.build()
finishWithResultAndExtra(cloudModelMapper.toModel(webDavCloudWithAcceptedCert), //
WEBDAV_ACCEPTED_UNTRUSTED_CERTIFICATE, //
true)
.withCertificate(X509CertificateHelper.convertToPem(certificate)) //
.build()
finishWithResultAndExtra(
cloudModelMapper.toModel(webDavCloudWithAcceptedCert), //
WEBDAV_ACCEPTED_UNTRUSTED_CERTIFICATE, //
true
)
} catch (e: CertificateEncodingException) {
Timber.tag("AuthicateCloudPrester").e(e)
throw FatalBackendException(e)
@ -421,9 +434,10 @@ class AuthenticateCloudPresenter @Inject constructor( //
if (!authenticationStarted) {
startAuthentication(intent.cloud())
Toast.makeText(
context(),
String.format(getString(R.string.error_authentication_failed), intent.cloud().username()),
Toast.LENGTH_LONG).show()
context(),
String.format(getString(R.string.error_authentication_failed), intent.cloud().username()),
Toast.LENGTH_LONG
).show()
}
}
else -> {
@ -454,10 +468,12 @@ class AuthenticateCloudPresenter @Inject constructor( //
private fun startAuthentication(cloud: CloudModel) {
authenticationStarted = true
requestPermissions(PermissionsResultCallbacks.onLocalStorageAuthenticated(cloud), //
R.string.permission_snackbar_auth_local_vault, //
Manifest.permission.READ_EXTERNAL_STORAGE, //
Manifest.permission.WRITE_EXTERNAL_STORAGE)
requestPermissions(
PermissionsResultCallbacks.onLocalStorageAuthenticated(cloud), //
R.string.permission_snackbar_auth_local_vault, //
Manifest.permission.READ_EXTERNAL_STORAGE, //
Manifest.permission.WRITE_EXTERNAL_STORAGE
)
}
}
@ -472,8 +488,8 @@ class AuthenticateCloudPresenter @Inject constructor( //
private fun encrypt(password: String): String {
return CredentialCryptor //
.getInstance(context()) //
.encrypt(password)
.getInstance(context()) //
.encrypt(password)
}
private inner class FailingAuthStrategy : AuthStrategy {

View File

@ -97,9 +97,10 @@
</intent-filter>
</activity>
<activity android:name=".ui.activity.UnlockVaultActivity"
android:theme="@style/TransparentAlertDialogCustom"
android:label=""/>
<activity
android:name=".ui.activity.UnlockVaultActivity"
android:label=""
android:theme="@style/TransparentAlertDialogCustom" />
<activity android:name=".ui.activity.EmptyDirIdFileInfoActivity" />
<!-- Settings -->

View File

@ -51,10 +51,12 @@ class CryptomatorApp : MultiDexApplication(), HasComponent<ApplicationComponent>
}
else -> "Google Play Edition"
}
Timber.tag("App").i("Cryptomator v%s (%d) \"%s\" started on android %s / API%d using a %s", //
BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE, flavor, //
Build.VERSION.RELEASE, Build.VERSION.SDK_INT, //
Build.MODEL)
Timber.tag("App").i(
"Cryptomator v%s (%d) \"%s\" started on android %s / API%d using a %s", //
BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE, flavor, //
Build.VERSION.RELEASE, Build.VERSION.SDK_INT, //
Build.MODEL
)
Timber.tag("App").d("appId %s", BuildConfig.APPLICATION_ID)
launchServices()
@ -105,10 +107,11 @@ class CryptomatorApp : MultiDexApplication(), HasComponent<ApplicationComponent>
Timber.tag("App").i("Auto upload service connected")
autoUploadServiceBinder = service as AutoUploadService.Binder
autoUploadServiceBinder.init( //
applicationComponent.cloudContentRepository(), //
applicationComponent.fileUtil(), //
applicationComponent.contentResolverUtil(), //
Companion.applicationContext)
applicationComponent.cloudContentRepository(), //
applicationComponent.fileUtil(), //
applicationComponent.contentResolverUtil(), //
Companion.applicationContext
)
}
override fun onServiceDisconnected(name: ComponentName) {
@ -124,11 +127,11 @@ class CryptomatorApp : MultiDexApplication(), HasComponent<ApplicationComponent>
private fun initializeInjector() {
applicationComponent = DaggerApplicationComponent.builder() //
.applicationModule(ApplicationModule(this)) //
.threadModule(ThreadModule()) //
.repositoryModule(RepositoryModule()) //
.cryptorsModule(CryptorsModule(appCryptors)) //
.build()
.applicationModule(ApplicationModule(this)) //
.threadModule(ThreadModule()) //
.repositoryModule(RepositoryModule()) //
.cryptorsModule(CryptorsModule(appCryptors)) //
.build()
}
private fun cleanupCache() {

View File

@ -15,7 +15,7 @@ class MissingCryptorExceptionHandler : ExceptionHandler() {
public override fun doHandle(view: View, e: Throwable) {
view.showMessage(R.string.error_vault_has_been_locked)
Intents.vaultListIntent() //
.preventGoingBackInHistory() //
.startActivity(view)
.preventGoingBackInHistory() //
.startActivity(view)
}
}

View File

@ -12,10 +12,7 @@ public interface UnlockVaultIntent {
VaultAction vaultAction();
enum VaultAction {
UNLOCK,
UNLOCK_FOR_BIOMETRIC_AUTH,
ENCRYPT_PASSWORD,
CHANGE_PASSWORD
UNLOCK, UNLOCK_FOR_BIOMETRIC_AUTH, ENCRYPT_PASSWORD, CHANGE_PASSWORD
}
}

View File

@ -12,7 +12,7 @@ object Logfiles {
* Maximum size of all logfiles
*/
private const val MAX_LOGS_SIZE = (1 shl 20 // 1 MiB
.toLong().toInt()).toLong()
.toLong().toInt()).toLong()
/**
* When this size is reached a logfile is rotated

View File

@ -8,14 +8,14 @@ import timber.log.Timber
class ReleaseLogger(context: Context) : Timber.Tree() {
private val priorityNames = charArrayOf( //
'?', //
'?', //
'V', //
'D', //
'I', //
'W', //
'E', //
'A' //
'?', //
'?', //
'V', //
'D', //
'I', //
'W', //
'E', //
'A' //
)
private val log: LogRotator
@ -26,10 +26,10 @@ class ReleaseLogger(context: Context) : Timber.Tree() {
override fun log(priority: Int, tag: String?, message: String, throwable: Throwable?) {
val line = StringBuilder()
line //
.append(priorityNames[validPriority(priority)]).append('\t') //
.append(FormattedTime.now()).append('\t') //
.append(tag ?: "App").append('\t') //
.append(message)
.append(priorityNames[validPriority(priority)]).append('\t') //
.append(FormattedTime.now()).append('\t') //
.append(tag ?: "App").append('\t') //
.append(message)
if (throwable != null) {
line.append("\nErrorCode: ").append(GeneratedErrorCode.of(throwable))
}

View File

@ -3,7 +3,7 @@ package org.cryptomator.presentation.model
import java.io.Serializable
data class AutoUploadFilesStore(
val uris: Set<String>
val uris: Set<String>
) : Serializable {
companion object {

View File

@ -6,38 +6,52 @@ import org.cryptomator.presentation.R
enum class CloudTypeModel(builder: Builder) {
CRYPTO(Builder("CRYPTO", R.string.cloud_names_crypto)), //
DROPBOX(Builder("DROPBOX", R.string.cloud_names_dropbox) //
DROPBOX(
Builder("DROPBOX", R.string.cloud_names_dropbox) //
.withCloudImageResource(R.drawable.dropbox) //
.withVaultImageResource(R.drawable.dropbox_vault) //
.withVaultSelectedImageResource(R.drawable.dropbox_vault_selected)), //
GOOGLE_DRIVE(Builder("GOOGLE_DRIVE", R.string.cloud_names_google_drive) //
.withVaultSelectedImageResource(R.drawable.dropbox_vault_selected)
), //
GOOGLE_DRIVE(
Builder("GOOGLE_DRIVE", R.string.cloud_names_google_drive) //
.withCloudImageResource(R.drawable.google_drive) //
.withVaultImageResource(R.drawable.google_drive_vault) //
.withVaultSelectedImageResource(R.drawable.google_drive_vault_selected)), //
ONEDRIVE(Builder("ONEDRIVE", R.string.cloud_names_onedrive) //
.withVaultSelectedImageResource(R.drawable.google_drive_vault_selected)
), //
ONEDRIVE(
Builder("ONEDRIVE", R.string.cloud_names_onedrive) //
.withCloudImageResource(R.drawable.onedrive) //
.withVaultImageResource(R.drawable.onedrive_vault) //
.withVaultSelectedImageResource(R.drawable.onedrive_vault_selected)), //
PCLOUD(Builder("PCLOUD", R.string.cloud_names_pcloud) //
.withVaultSelectedImageResource(R.drawable.onedrive_vault_selected)
), //
PCLOUD(
Builder("PCLOUD", R.string.cloud_names_pcloud) //
.withCloudImageResource(R.drawable.pcloud) //
.withVaultImageResource(R.drawable.pcloud_vault) //
.withVaultSelectedImageResource(R.drawable.pcloud_vault_selected) //
.withMultiInstances()), //
WEBDAV(Builder("WEBDAV", R.string.cloud_names_webdav) //
.withMultiInstances()
), //
WEBDAV(
Builder("WEBDAV", R.string.cloud_names_webdav) //
.withCloudImageResource(R.drawable.webdav) //
.withVaultImageResource(R.drawable.webdav_vault) //
.withVaultSelectedImageResource(R.drawable.webdav_vault_selected) //
.withMultiInstances()), //
S3(Builder("S3", R.string.cloud_names_s3) //
.withMultiInstances()
), //
S3(
Builder("S3", R.string.cloud_names_s3) //
.withCloudImageResource(R.drawable.s3) //
.withVaultImageResource(R.drawable.s3_vault) //
.withVaultSelectedImageResource(R.drawable.s3_vault_selected) //
.withMultiInstances()), //
LOCAL(Builder("LOCAL", R.string.cloud_names_local_storage) //
.withMultiInstances()
), //
LOCAL(
Builder("LOCAL", R.string.cloud_names_local_storage) //
.withCloudImageResource(R.drawable.local_fs) //
.withVaultImageResource(R.drawable.local_fs_vault) //
.withVaultSelectedImageResource(R.drawable.local_fs_vault_selected) //
.withMultiInstances());
.withMultiInstances()
);
val cloudName: String = builder.cloudName
val displayNameResource: Int = builder.displayNameResource

View File

@ -8,6 +8,6 @@ import kotlinx.android.parcel.Parcelize
@Parcelize
@SuppressLint("ParcelCreator")
data class ImagePreviewFile(
val cloudFileModel: CloudFileModel,
var uri: Uri?
val cloudFileModel: CloudFileModel,
var uri: Uri?
) : Parcelable

View File

@ -3,6 +3,6 @@ package org.cryptomator.presentation.model
import java.io.Serializable
data class ImagePreviewFilesStore(
val cloudFileModels: ArrayList<CloudFileModel>,
var index: Int
val cloudFileModels: ArrayList<CloudFileModel>,
var index: Int
) : Serializable

View File

@ -31,21 +31,29 @@ class ProgressStateModelMapper @Inject internal constructor(private val fileUtil
fun toModel(state: UploadState): ProgressStateModel {
return if (state.isUpload) {
FileProgressStateModel(state.file(), FileIcon.fileIconFor(state.file().name, fileUtil), FileProgressStateModel.UPLOAD, ProgressStateModel.image(R.drawable.ic_file_upload),
ProgressStateModel.text(R.string.dialog_progress_upload_file))
FileProgressStateModel(
state.file(), FileIcon.fileIconFor(state.file().name, fileUtil), FileProgressStateModel.UPLOAD, ProgressStateModel.image(R.drawable.ic_file_upload),
ProgressStateModel.text(R.string.dialog_progress_upload_file)
)
} else {
FileProgressStateModel(state.file(), FileIcon.fileIconFor(state.file().name, fileUtil), FileProgressStateModel.ENCRYPTION, ProgressStateModel.image(R.drawable.ic_lock_closed),
ProgressStateModel.text(R.string.dialog_progress_encryption))
FileProgressStateModel(
state.file(), FileIcon.fileIconFor(state.file().name, fileUtil), FileProgressStateModel.ENCRYPTION, ProgressStateModel.image(R.drawable.ic_lock_closed),
ProgressStateModel.text(R.string.dialog_progress_encryption)
)
}
}
fun toModel(state: DownloadState): ProgressStateModel {
return if (state.isDownload) {
FileProgressStateModel(state.file(), FileIcon.fileIconFor(state.file().name, fileUtil), FileProgressStateModel.DOWNLOAD, ProgressStateModel.image(R.drawable.ic_file_download),
ProgressStateModel.text(R.string.dialog_progress_download_file))
FileProgressStateModel(
state.file(), FileIcon.fileIconFor(state.file().name, fileUtil), FileProgressStateModel.DOWNLOAD, ProgressStateModel.image(R.drawable.ic_file_download),
ProgressStateModel.text(R.string.dialog_progress_download_file)
)
} else {
FileProgressStateModel(state.file(), FileIcon.fileIconFor(state.file().name, fileUtil), FileProgressStateModel.DECRYPTION, ProgressStateModel.image(R.drawable.ic_lock_open),
ProgressStateModel.text(R.string.dialog_progress_decryption))
FileProgressStateModel(
state.file(), FileIcon.fileIconFor(state.file().name, fileUtil), FileProgressStateModel.DECRYPTION, ProgressStateModel.image(R.drawable.ic_lock_open),
ProgressStateModel.text(R.string.dialog_progress_decryption)
)
}
}
}

View File

@ -26,13 +26,14 @@ import javax.inject.Inject
@PerView
class AutoUploadChooseVaultPresenter @Inject constructor( //
private val getVaultListUseCase: GetVaultListUseCase, //
private val getRootFolderUseCase: GetRootFolderUseCase, //
private val getDecryptedCloudForVaultUseCase: GetDecryptedCloudForVaultUseCase, //
private val cloudFolderModelMapper: CloudFolderModelMapper, //
private val sharedPreferencesHandler: SharedPreferencesHandler, //
private val authenticationExceptionHandler: AuthenticationExceptionHandler, //
exceptionMappings: ExceptionHandlers) : Presenter<AutoUploadChooseVaultView>(exceptionMappings) {
private val getVaultListUseCase: GetVaultListUseCase, //
private val getRootFolderUseCase: GetRootFolderUseCase, //
private val getDecryptedCloudForVaultUseCase: GetDecryptedCloudForVaultUseCase, //
private val cloudFolderModelMapper: CloudFolderModelMapper, //
private val sharedPreferencesHandler: SharedPreferencesHandler, //
private val authenticationExceptionHandler: AuthenticationExceptionHandler, //
exceptionMappings: ExceptionHandlers
) : Presenter<AutoUploadChooseVaultView>(exceptionMappings) {
private var selectedVault: VaultModel? = null
private var location: CloudFolderModel? = null
@ -79,8 +80,9 @@ class AutoUploadChooseVaultPresenter @Inject constructor( //
} else {
if (!isPaused) {
requestActivityResult( //
ActivityResultCallbacks.vaultUnlockedAutoUpload(), //
Intents.unlockVaultIntent().withVaultModel(VaultModel(authenticatedVault)).withVaultAction(UnlockVaultIntent.VaultAction.UNLOCK))
ActivityResultCallbacks.vaultUnlockedAutoUpload(), //
Intents.unlockVaultIntent().withVaultModel(VaultModel(authenticatedVault)).withVaultAction(UnlockVaultIntent.VaultAction.UNLOCK)
)
}
}
}
@ -95,24 +97,25 @@ class AutoUploadChooseVaultPresenter @Inject constructor( //
}
private fun decryptedCloudFor(vault: Vault) {
getDecryptedCloudForVaultUseCase //
.withVault(vault) //
.run(object : DefaultResultHandler<Cloud>() {
override fun onSuccess(cloud: Cloud) {
rootFolderFor(cloud)
}
.withVault(vault) //
.run(object : DefaultResultHandler<Cloud>() {
override fun onSuccess(cloud: Cloud) {
rootFolderFor(cloud)
}
override fun onError(e: Throwable) {
if (!authenticationExceptionHandler.handleAuthenticationException( //
this@AutoUploadChooseVaultPresenter, //
e, //
ActivityResultCallbacks.decryptedCloudForAfterAuthInAutoPhotoUpload(vault))) {
super.onError(e)
}
override fun onError(e: Throwable) {
if (!authenticationExceptionHandler.handleAuthenticationException( //
this@AutoUploadChooseVaultPresenter, //
e, //
ActivityResultCallbacks.decryptedCloudForAfterAuthInAutoPhotoUpload(vault)
)
) {
super.onError(e)
}
})
}
})
}
@Callback
@ -123,33 +126,35 @@ class AutoUploadChooseVaultPresenter @Inject constructor( //
private fun rootFolderFor(cloud: Cloud) {
getRootFolderUseCase //
.withCloud(cloud) //
.run(object : DefaultResultHandler<CloudFolder>() {
override fun onSuccess(folder: CloudFolder) {
when (authenticationState) {
AuthenticationState.CHOOSE_LOCATION -> {
location = cloudFolderModelMapper.toModel(folder)
selectedVault?.let { navigateToVaultContent(it, location) }
}
AuthenticationState.INIT_ROOT -> location = cloudFolderModelMapper.toModel(folder)
.withCloud(cloud) //
.run(object : DefaultResultHandler<CloudFolder>() {
override fun onSuccess(folder: CloudFolder) {
when (authenticationState) {
AuthenticationState.CHOOSE_LOCATION -> {
location = cloudFolderModelMapper.toModel(folder)
selectedVault?.let { navigateToVaultContent(it, location) }
}
AuthenticationState.INIT_ROOT -> location = cloudFolderModelMapper.toModel(folder)
}
})
}
})
}
private fun navigateToVaultContent(vaultModel: VaultModel, decryptedRoot: CloudFolderModel?) {
requestActivityResult( //
ActivityResultCallbacks.onAutoUploadChooseLocation(vaultModel), //
Intents.browseFilesIntent() //
.withFolder(decryptedRoot) //
.withTitle(vaultModel.name) //
.withChooseCloudNodeSettings( //
ChooseCloudNodeSettings.chooseCloudNodeSettings() //
.withExtraTitle(context().getString(R.string.screen_file_browser_share_destination_title)) //
.withExtraToolbarIcon(R.drawable.ic_clear) //
.withButtonText(context().getString(R.string.screen_file_browser_share_button_text)) //
.selectingFolders() //
.build()))
ActivityResultCallbacks.onAutoUploadChooseLocation(vaultModel), //
Intents.browseFilesIntent() //
.withFolder(decryptedRoot) //
.withTitle(vaultModel.name) //
.withChooseCloudNodeSettings( //
ChooseCloudNodeSettings.chooseCloudNodeSettings() //
.withExtraTitle(context().getString(R.string.screen_file_browser_share_destination_title)) //
.withExtraToolbarIcon(R.drawable.ic_clear) //
.withButtonText(context().getString(R.string.screen_file_browser_share_button_text)) //
.selectingFolders() //
.build()
)
)
}
@Callback

View File

@ -22,11 +22,12 @@ import timber.log.Timber
@PerView
class BiometricAuthSettingsPresenter @Inject constructor( //
private val getVaultListUseCase: GetVaultListUseCase, //
private val saveVaultUseCase: SaveVaultUseCase, //
private val lockVaultUseCase: LockVaultUseCase, //
exceptionMappings: ExceptionHandlers, //
private val sharedPreferencesHandler: SharedPreferencesHandler) : Presenter<BiometricAuthSettingsView>(exceptionMappings) {
private val getVaultListUseCase: GetVaultListUseCase, //
private val saveVaultUseCase: SaveVaultUseCase, //
private val lockVaultUseCase: LockVaultUseCase, //
exceptionMappings: ExceptionHandlers, //
private val sharedPreferencesHandler: SharedPreferencesHandler
) : Presenter<BiometricAuthSettingsView>(exceptionMappings) {
fun loadVaultList() {
updateVaultListView()
@ -55,19 +56,21 @@ class BiometricAuthSettingsPresenter @Inject constructor( //
Timber.tag("BiomtricAuthSettngsPres").i("Checking entered vault password")
if (vaultModel.isLocked) {
requestActivityResult( //
ActivityResultCallbacks.vaultUnlockedBiometricAuthPres(vaultModel), //
Intents.unlockVaultIntent().withVaultModel(vaultModel).withVaultAction(UnlockVaultIntent.VaultAction.UNLOCK_FOR_BIOMETRIC_AUTH))
ActivityResultCallbacks.vaultUnlockedBiometricAuthPres(vaultModel), //
Intents.unlockVaultIntent().withVaultModel(vaultModel).withVaultAction(UnlockVaultIntent.VaultAction.UNLOCK_FOR_BIOMETRIC_AUTH)
)
} else {
lockVaultUseCase
.withVault(vaultModel.toVault())
.run(object : DefaultResultHandler<Vault>() {
override fun onSuccess(vault: Vault) {
super.onSuccess(vault)
requestActivityResult( //
ActivityResultCallbacks.vaultUnlockedBiometricAuthPres(vaultModel), //
Intents.unlockVaultIntent().withVaultModel(vaultModel).withVaultAction(UnlockVaultIntent.VaultAction.UNLOCK_FOR_BIOMETRIC_AUTH))
}
})
.withVault(vaultModel.toVault())
.run(object : DefaultResultHandler<Vault>() {
override fun onSuccess(vault: Vault) {
super.onSuccess(vault)
requestActivityResult( //
ActivityResultCallbacks.vaultUnlockedBiometricAuthPres(vaultModel), //
Intents.unlockVaultIntent().withVaultModel(vaultModel).withVaultAction(UnlockVaultIntent.VaultAction.UNLOCK_FOR_BIOMETRIC_AUTH)
)
}
})
}
}
@ -78,8 +81,9 @@ class BiometricAuthSettingsPresenter @Inject constructor( //
val vault = Vault.aCopyOf(vaultModel.toVault()).withCloud(cloud).withSavedPassword(password).build()
when {
result.isResultOk -> requestActivityResult( //
ActivityResultCallbacks.encryptVaultPassword(vaultModel), //
Intents.unlockVaultIntent().withVaultModel(VaultModel(vault)).withVaultAction(UnlockVaultIntent.VaultAction.ENCRYPT_PASSWORD))
ActivityResultCallbacks.encryptVaultPassword(vaultModel), //
Intents.unlockVaultIntent().withVaultModel(VaultModel(vault)).withVaultAction(UnlockVaultIntent.VaultAction.ENCRYPT_PASSWORD)
)
else -> TODO("Not yet implemented")
}
}
@ -96,12 +100,12 @@ class BiometricAuthSettingsPresenter @Inject constructor( //
private fun saveVault(vault: Vault?) {
saveVaultUseCase //
.withVault(vault) //
.run(object : ProgressCompletingResultHandler<Vault>() {
override fun onSuccess(vault: Vault) {
Timber.tag("BiomtricAuthSettngsPres").i("Saved updated vault successfully")
}
})
.withVault(vault) //
.run(object : ProgressCompletingResultHandler<Vault>() {
override fun onSuccess(vault: Vault) {
Timber.tag("BiomtricAuthSettngsPres").i("Saved updated vault successfully")
}
})
}
fun switchedGeneralBiometricAuthSettings(isChecked: Boolean) {
@ -124,9 +128,9 @@ class BiometricAuthSettingsPresenter @Inject constructor( //
private fun removePasswordAndSave(vault: Vault) {
val vaultWithRemovedPassword = Vault //
.aCopyOf(vault) //
.withSavedPassword(null) //
.build()
.aCopyOf(vault) //
.withSavedPassword(null) //
.build()
saveVault(vaultWithRemovedPassword)
}

View File

@ -20,11 +20,12 @@ import javax.inject.Inject
@PerView
class ChooseCloudServicePresenter @Inject constructor( //
private val getCloudsUseCase: GetCloudsUseCase, //
private val cloudModelMapper: CloudModelMapper, //
private val addExistingVaultWorkflow: AddExistingVaultWorkflow, //
private val createNewVaultWorkflow: CreateNewVaultWorkflow, //
exceptionMappings: ExceptionHandlers) : Presenter<ChooseCloudServiceView>(exceptionMappings) {
private val getCloudsUseCase: GetCloudsUseCase, //
private val cloudModelMapper: CloudModelMapper, //
private val addExistingVaultWorkflow: AddExistingVaultWorkflow, //
private val createNewVaultWorkflow: CreateNewVaultWorkflow, //
exceptionMappings: ExceptionHandlers
) : Presenter<ChooseCloudServiceView>(exceptionMappings) {
override fun workflows(): Iterable<Workflow<*>> {
return listOf(addExistingVaultWorkflow, createNewVaultWorkflow)
@ -55,11 +56,12 @@ class ChooseCloudServicePresenter @Inject constructor( //
private fun startCloudConnectionListActivity(cloudTypeModel: CloudTypeModel) {
requestActivityResult( //
ActivityResultCallbacks.cloudConnectionListFinished(), //
Intents.cloudConnectionListIntent() //
.withCloudType(cloudTypeModel) //
.withDialogTitle(context().getString(R.string.screen_cloud_connections_title)) //
.withFinishOnCloudItemClick(true))
ActivityResultCallbacks.cloudConnectionListFinished(), //
Intents.cloudConnectionListIntent() //
.withCloudType(cloudTypeModel) //
.withDialogTitle(context().getString(R.string.screen_cloud_connections_title)) //
.withFinishOnCloudItemClick(true)
)
}
@Callback
@ -70,15 +72,15 @@ class ChooseCloudServicePresenter @Inject constructor( //
private fun handleSingleInstanceClouds(cloudTypeModel: CloudTypeModel) {
getCloudsUseCase //
.withCloudType(CloudTypeModel.valueOf(cloudTypeModel)) //
.run(object : DefaultResultHandler<List<Cloud>>() {
override fun onSuccess(clouds: List<Cloud>) {
if (clouds.size > 1) {
throw FatalBackendException("More then one cloud")
}
onCloudSelected(clouds[0])
.withCloudType(CloudTypeModel.valueOf(cloudTypeModel)) //
.run(object : DefaultResultHandler<List<Cloud>>() {
override fun onSuccess(clouds: List<Cloud>) {
if (clouds.size > 1) {
throw FatalBackendException("More then one cloud")
}
})
onCloudSelected(clouds[0])
}
})
}
private fun onCloudSelected(cloud: Cloud) {

View File

@ -42,14 +42,15 @@ import timber.log.Timber
@PerView
class CloudConnectionListPresenter @Inject constructor( //
private val getCloudsUseCase: GetCloudsUseCase, //
private val getUsernameUseCase: GetUsernameUseCase, //
private val removeCloudUseCase: RemoveCloudUseCase, //
private val addOrChangeCloudConnectionUseCase: AddOrChangeCloudConnectionUseCase, //
private val getVaultListUseCase: GetVaultListUseCase, //
private val deleteVaultUseCase: DeleteVaultUseCase, //
private val cloudModelMapper: CloudModelMapper, //
exceptionMappings: ExceptionHandlers) : Presenter<CloudConnectionListView>(exceptionMappings) {
private val getCloudsUseCase: GetCloudsUseCase, //
private val getUsernameUseCase: GetUsernameUseCase, //
private val removeCloudUseCase: RemoveCloudUseCase, //
private val addOrChangeCloudConnectionUseCase: AddOrChangeCloudConnectionUseCase, //
private val getVaultListUseCase: GetVaultListUseCase, //
private val deleteVaultUseCase: DeleteVaultUseCase, //
private val cloudModelMapper: CloudModelMapper, //
exceptionMappings: ExceptionHandlers
) : Presenter<CloudConnectionListView>(exceptionMappings) {
private val selectedCloudType = AtomicReference<CloudTypeModel>()
private var defaultLocalStorageCloud: LocalStorageCloud? = null
@ -59,22 +60,22 @@ class CloudConnectionListPresenter @Inject constructor( //
fun loadCloudList() {
getCloudsUseCase //
.withCloudType(CloudTypeModel.valueOf(selectedCloudType.get())) //
.run(object : DefaultResultHandler<List<Cloud>>() {
override fun onSuccess(clouds: List<Cloud>) {
val cloudModels: MutableList<CloudModel> = ArrayList()
clouds.forEach { cloud ->
if (CloudTypeModel.LOCAL == selectedCloudType.get()) {
if ((cloud as LocalStorageCloud).rootUri() == null) {
defaultLocalStorageCloud = cloud
return@forEach
}
.withCloudType(CloudTypeModel.valueOf(selectedCloudType.get())) //
.run(object : DefaultResultHandler<List<Cloud>>() {
override fun onSuccess(clouds: List<Cloud>) {
val cloudModels: MutableList<CloudModel> = ArrayList()
clouds.forEach { cloud ->
if (CloudTypeModel.LOCAL == selectedCloudType.get()) {
if ((cloud as LocalStorageCloud).rootUri() == null) {
defaultLocalStorageCloud = cloud
return@forEach
}
cloudModels.add(cloudModelMapper.toModel(cloud))
}
view?.showCloudModels(cloudModels)
cloudModels.add(cloudModelMapper.toModel(cloud))
}
})
view?.showCloudModels(cloudModels)
}
})
}
fun onDeleteCloudClicked(cloudModel: CloudModel) {
@ -120,32 +121,39 @@ class CloudConnectionListPresenter @Inject constructor( //
private fun deleteCloud(cloud: Cloud) {
removeCloudUseCase //
.withCloud(cloud) //
.run(object : DefaultResultHandler<Void?>() {
override fun onSuccess(ignore: Void?) {
loadCloudList()
}
})
.withCloud(cloud) //
.run(object : DefaultResultHandler<Void?>() {
override fun onSuccess(ignore: Void?) {
loadCloudList()
}
})
}
fun onAddConnectionClicked() {
when (selectedCloudType.get()) {
CloudTypeModel.WEBDAV -> requestActivityResult(ActivityResultCallbacks.addChangeMultiCloud(), //
Intents.webDavAddOrChangeIntent())
CloudTypeModel.WEBDAV -> requestActivityResult(
ActivityResultCallbacks.addChangeMultiCloud(), //
Intents.webDavAddOrChangeIntent()
)
CloudTypeModel.PCLOUD -> {
val authIntent: Intent = AuthorizationActivity.createIntent(
this.context(),
AuthorizationRequest.create()
.setType(AuthorizationRequest.Type.TOKEN)
.setClientId(BuildConfig.PCLOUD_CLIENT_ID)
.setForceAccessApproval(true)
.addPermission("manageshares")
.build())
requestActivityResult(ActivityResultCallbacks.pCloudAuthenticationFinished(), //
authIntent)
this.context(),
AuthorizationRequest.create()
.setType(AuthorizationRequest.Type.TOKEN)
.setClientId(BuildConfig.PCLOUD_CLIENT_ID)
.setForceAccessApproval(true)
.addPermission("manageshares")
.build()
)
requestActivityResult(
ActivityResultCallbacks.pCloudAuthenticationFinished(), //
authIntent
)
}
CloudTypeModel.S3 -> requestActivityResult(ActivityResultCallbacks.addChangeMultiCloud(), //
Intents.s3AddOrChangeIntent())
CloudTypeModel.S3 -> requestActivityResult(
ActivityResultCallbacks.addChangeMultiCloud(), //
Intents.s3AddOrChangeIntent()
)
CloudTypeModel.LOCAL -> openDocumentTree()
}
}
@ -154,15 +162,17 @@ class CloudConnectionListPresenter @Inject constructor( //
private fun openDocumentTree() {
try {
requestActivityResult( //
ActivityResultCallbacks.pickedLocalStorageLocation(), //
Intent(Intent.ACTION_OPEN_DOCUMENT_TREE))
ActivityResultCallbacks.pickedLocalStorageLocation(), //
Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
)
} catch (exception: ActivityNotFoundException) {
Toast //
.makeText( //
activity().applicationContext, //
context().getText(R.string.screen_cloud_local_error_no_content_provider), //
Toast.LENGTH_SHORT) //
.show()
.makeText( //
activity().applicationContext, //
context().getText(R.string.screen_cloud_local_error_no_content_provider), //
Toast.LENGTH_SHORT
) //
.show()
Timber.tag("CloudConnListPresenter").e(exception, "No ContentProvider on system")
}
}
@ -170,14 +180,18 @@ class CloudConnectionListPresenter @Inject constructor( //
fun onChangeCloudClicked(cloudModel: CloudModel) {
when {
cloudModel.cloudType() == CloudTypeModel.WEBDAV -> {
requestActivityResult(ActivityResultCallbacks.addChangeMultiCloud(), //
Intents.webDavAddOrChangeIntent() //
.withWebDavCloud(cloudModel as WebDavCloudModel))
requestActivityResult(
ActivityResultCallbacks.addChangeMultiCloud(), //
Intents.webDavAddOrChangeIntent() //
.withWebDavCloud(cloudModel as WebDavCloudModel)
)
}
cloudModel.cloudType() == CloudTypeModel.S3 -> {
requestActivityResult(ActivityResultCallbacks.addChangeMultiCloud(), //
Intents.s3AddOrChangeIntent() //
.withS3Cloud(cloudModel as S3CloudModel))
requestActivityResult(
ActivityResultCallbacks.addChangeMultiCloud(), //
Intents.s3AddOrChangeIntent() //
.withS3Cloud(cloudModel as S3CloudModel)
)
}
else -> {
throw IllegalStateException("Change cloud with type " + cloudModel.cloudType() + " is not supported")
@ -202,19 +216,19 @@ class CloudConnectionListPresenter @Inject constructor( //
when (result) {
AuthorizationResult.ACCESS_GRANTED -> {
val accessToken: String = CredentialCryptor //
.getInstance(this.context()) //
.encrypt(authData.token)
.getInstance(this.context()) //
.encrypt(authData.token)
val pCloudSkeleton: PCloud = PCloud.aPCloud() //
.withAccessToken(accessToken)
.withUrl(authData.apiHost)
.build();
.withAccessToken(accessToken)
.withUrl(authData.apiHost)
.build();
getUsernameUseCase //
.withCloud(pCloudSkeleton) //
.run(object : DefaultResultHandler<String>() {
override fun onSuccess(username: String?) {
prepareForSavingPCloud(PCloud.aCopyOf(pCloudSkeleton).withUsername(username).build())
}
})
.withCloud(pCloudSkeleton) //
.run(object : DefaultResultHandler<String>() {
override fun onSuccess(username: String?) {
prepareForSavingPCloud(PCloud.aCopyOf(pCloudSkeleton).withUsername(username).build())
}
})
}
AuthorizationResult.ACCESS_DENIED -> {
Timber.tag("CloudConnListPresenter").e("Account access denied")
@ -233,30 +247,32 @@ class CloudConnectionListPresenter @Inject constructor( //
fun prepareForSavingPCloud(cloud: PCloud) {
getCloudsUseCase //
.withCloudType(CloudTypeModel.valueOf(selectedCloudType.get())) //
.run(object : DefaultResultHandler<List<Cloud>>() {
override fun onSuccess(clouds: List<Cloud>) {
clouds.firstOrNull {
(it as PCloud).username() == cloud.username()
}?.let {
it as PCloud
saveCloud(PCloud.aCopyOf(it) //
.withUrl(cloud.url())
.withAccessToken(cloud.accessToken())
.build())
} ?: saveCloud(cloud)
}
})
.withCloudType(CloudTypeModel.valueOf(selectedCloudType.get())) //
.run(object : DefaultResultHandler<List<Cloud>>() {
override fun onSuccess(clouds: List<Cloud>) {
clouds.firstOrNull {
(it as PCloud).username() == cloud.username()
}?.let {
it as PCloud
saveCloud(
PCloud.aCopyOf(it) //
.withUrl(cloud.url())
.withAccessToken(cloud.accessToken())
.build()
)
} ?: saveCloud(cloud)
}
})
}
fun saveCloud(cloud: PCloud) {
addOrChangeCloudConnectionUseCase //
.withCloud(cloud) //
.run(object : DefaultResultHandler<Void?>() {
override fun onSuccess(void: Void?) {
loadCloudList()
}
})
.withCloud(cloud) //
.run(object : DefaultResultHandler<Void?>() {
override fun onSuccess(void: Void?) {
loadCloudList()
}
})
}
@Callback
@ -264,34 +280,38 @@ class CloudConnectionListPresenter @Inject constructor( //
fun pickedLocalStorageLocation(result: ActivityResult) {
val rootTreeUriOfLocalStorage = result.intent().data
persistUriPermission(rootTreeUriOfLocalStorage)
addOrChangeCloudConnectionUseCase.withCloud(LocalStorageCloud.aLocalStorage() //
addOrChangeCloudConnectionUseCase.withCloud(
LocalStorageCloud.aLocalStorage() //
.withRootUri(rootTreeUriOfLocalStorage.toString()) //
.build()) //
.run(object : DefaultResultHandler<Void?>() {
override fun onSuccess(void: Void?) {
loadCloudList()
}
})
.build()
) //
.run(object : DefaultResultHandler<Void?>() {
override fun onSuccess(void: Void?) {
loadCloudList()
}
})
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
private fun persistUriPermission(rootTreeUriOfLocalStorage: Uri?) {
rootTreeUriOfLocalStorage?.let {
context() //
.contentResolver //
.takePersistableUriPermission( //
it, //
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
.contentResolver //
.takePersistableUriPermission( //
it, //
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
)
}
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
private fun releaseUriPermission(uri: String) {
context() //
.contentResolver //
.releasePersistableUriPermission( //
Uri.parse(uri), //
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
.contentResolver //
.releasePersistableUriPermission( //
Uri.parse(uri), //
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
)
}
fun onCloudConnectionClicked(cloudModel: CloudModel) {

View File

@ -29,18 +29,20 @@ import javax.inject.Inject
@PerView
class CloudSettingsPresenter @Inject constructor( //
private val getAllCloudsUseCase: GetAllCloudsUseCase, //
private val getCloudsUseCase: GetCloudsUseCase, //
private val logoutCloudUsecase: LogoutCloudUseCase, //
private val cloudModelMapper: CloudModelMapper, //
exceptionMappings: ExceptionHandlers) : Presenter<CloudSettingsView>(exceptionMappings) {
private val getAllCloudsUseCase: GetAllCloudsUseCase, //
private val getCloudsUseCase: GetCloudsUseCase, //
private val logoutCloudUsecase: LogoutCloudUseCase, //
private val cloudModelMapper: CloudModelMapper, //
exceptionMappings: ExceptionHandlers
) : Presenter<CloudSettingsView>(exceptionMappings) {
private val nonSingleLoginClouds: Set<CloudTypeModel> = EnumSet.of( //
CloudTypeModel.CRYPTO, //
CloudTypeModel.LOCAL, //
CloudTypeModel.PCLOUD, //
CloudTypeModel.S3, //
CloudTypeModel.WEBDAV)
CloudTypeModel.CRYPTO, //
CloudTypeModel.LOCAL, //
CloudTypeModel.PCLOUD, //
CloudTypeModel.S3, //
CloudTypeModel.WEBDAV
)
fun loadClouds() {
getAllCloudsUseCase.run(CloudsSubscriber())
@ -52,12 +54,12 @@ class CloudSettingsPresenter @Inject constructor( //
} else {
if (isLoggedIn(cloudModel)) {
logoutCloudUsecase //
.withCloud(cloudModel.toCloud()) //
.run(object : DefaultResultHandler<Cloud>() {
override fun onSuccess(cloud: Cloud) {
loadClouds()
}
})
.withCloud(cloudModel.toCloud()) //
.run(object : DefaultResultHandler<Cloud>() {
override fun onSuccess(cloud: Cloud) {
loadClouds()
}
})
} else {
loginCloud(cloudModel)
}
@ -66,15 +68,15 @@ class CloudSettingsPresenter @Inject constructor( //
private fun loginCloud(cloudModel: CloudModel) {
getCloudsUseCase //
.withCloudType(CloudTypeModel.valueOf(cloudModel.cloudType())) //
.run(object : DefaultResultHandler<List<Cloud>>() {
override fun onSuccess(clouds: List<Cloud>) {
if (clouds.size > 1) {
throw FatalBackendException("More then one cloud")
}
startAuthentication(clouds[0])
.withCloudType(CloudTypeModel.valueOf(cloudModel.cloudType())) //
.run(object : DefaultResultHandler<List<Cloud>>() {
override fun onSuccess(clouds: List<Cloud>) {
if (clouds.size > 1) {
throw FatalBackendException("More then one cloud")
}
})
startAuthentication(clouds[0])
}
})
}
private fun isLoggedIn(cloudModel: CloudModel): Boolean {
@ -83,11 +85,12 @@ class CloudSettingsPresenter @Inject constructor( //
private fun startConnectionListActivity(cloudTypeModel: CloudTypeModel) {
requestActivityResult( //
ActivityResultCallbacks.webDavConnectionListFinisheds(), //
Intents.cloudConnectionListIntent() //
.withCloudType(cloudTypeModel) //
.withDialogTitle(effectiveTitle(cloudTypeModel)) //
.withFinishOnCloudItemClick(false))
ActivityResultCallbacks.webDavConnectionListFinisheds(), //
Intents.cloudConnectionListIntent() //
.withCloudType(cloudTypeModel) //
.withDialogTitle(effectiveTitle(cloudTypeModel)) //
.withFinishOnCloudItemClick(false)
)
}
private fun effectiveTitle(cloudTypeModel: CloudTypeModel): String {
@ -108,9 +111,10 @@ class CloudSettingsPresenter @Inject constructor( //
private fun startAuthentication(cloud: Cloud) {
requestActivityResult( //
ActivityResultCallbacks.onCloudAuthenticated(), //
Intents.authenticateCloudIntent() //
.withCloud(cloudModelMapper.toModel(cloud)))
ActivityResultCallbacks.onCloudAuthenticated(), //
Intents.authenticateCloudIntent() //
.withCloud(cloudModelMapper.toModel(cloud))
)
}
@Callback
@ -122,15 +126,15 @@ class CloudSettingsPresenter @Inject constructor( //
override fun onSuccess(clouds: List<Cloud>) {
val cloudModel = cloudModelMapper.toModels(clouds) //
.filter { isSingleLoginCloud(it) } //
.filter { cloud -> !(BuildConfig.FLAVOR == "fdroid" && cloud.cloudType() == CloudTypeModel.GOOGLE_DRIVE) } //
.toMutableList() //
.also {
it.add(aPCloud())
it.add(aWebdavCloud())
it.add(aS3Cloud())
it.add(aLocalCloud())
}
.filter { isSingleLoginCloud(it) } //
.filter { cloud -> !(BuildConfig.FLAVOR == "fdroid" && cloud.cloudType() == CloudTypeModel.GOOGLE_DRIVE) } //
.toMutableList() //
.also {
it.add(aPCloud())
it.add(aWebdavCloud())
it.add(aS3Cloud())
it.add(aLocalCloud())
}
view?.render(cloudModel)
}

View File

@ -11,8 +11,9 @@ import javax.inject.Inject
@PerView
class CreateVaultPresenter @Inject constructor( //
private val createNewVaultWorkflow: CreateNewVaultWorkflow, //
exceptionMappings: ExceptionHandlers) : Presenter<CreateVaultView>(exceptionMappings) {
private val createNewVaultWorkflow: CreateNewVaultWorkflow, //
exceptionMappings: ExceptionHandlers
) : Presenter<CreateVaultView>(exceptionMappings) {
override fun workflows(): Iterable<Workflow<*>> {
return setOf(createNewVaultWorkflow)

View File

@ -42,15 +42,16 @@ import timber.log.Timber
@PerView
class ImagePreviewPresenter @Inject constructor( //
exceptionMappings: ExceptionHandlers, //
private val shareFileHelper: ShareFileHelper, //
private val contentResolverUtil: ContentResolverUtil, //
private val copyDataUseCase: CopyDataUseCase, //
private val downloadFilesUseCase: DownloadFilesUseCase, //
private val deleteNodesUseCase: DeleteNodesUseCase, //
private val downloadFileUtil: DownloadFileUtil, //
private val fileUtil: FileUtil, //
private val cloudFileModelMapper: CloudFileModelMapper) : Presenter<ImagePreviewView>(exceptionMappings) {
exceptionMappings: ExceptionHandlers, //
private val shareFileHelper: ShareFileHelper, //
private val contentResolverUtil: ContentResolverUtil, //
private val copyDataUseCase: CopyDataUseCase, //
private val downloadFilesUseCase: DownloadFilesUseCase, //
private val deleteNodesUseCase: DeleteNodesUseCase, //
private val downloadFileUtil: DownloadFileUtil, //
private val fileUtil: FileUtil, //
private val cloudFileModelMapper: CloudFileModelMapper
) : Presenter<ImagePreviewView>(exceptionMappings) {
private var isSystemUiVisible = true
@ -66,8 +67,10 @@ class ImagePreviewPresenter @Inject constructor( //
}
private fun copyFileToDownloadDirectory(uri: Uri) {
requestPermissions(PermissionsResultCallbacks.copyFileToDownloadDirectory(uri.toString()), //
R.string.permission_message_export_file, Manifest.permission.WRITE_EXTERNAL_STORAGE)
requestPermissions(
PermissionsResultCallbacks.copyFileToDownloadDirectory(uri.toString()), //
R.string.permission_message_export_file, Manifest.permission.WRITE_EXTERNAL_STORAGE
)
}
@Callback
@ -95,13 +98,13 @@ class ImagePreviewPresenter @Inject constructor( //
throw FatalBackendException("Input- or OutputStream is null")
}
copyDataUseCase //
.withSource(source) //
.andTarget(target) //
.run(object : DefaultResultHandler<Void?>() {
override fun onFinished() {
view?.showMessage(R.string.screen_file_browser_msg_file_exported)
}
})
.withSource(source) //
.andTarget(target) //
.run(object : DefaultResultHandler<Void?>() {
override fun onFinished() {
view?.showMessage(R.string.screen_file_browser_msg_file_exported)
}
})
}
private fun copyFileToUserSelectedLocation(uri: Uri) {
@ -114,17 +117,21 @@ class ImagePreviewPresenter @Inject constructor( //
@Callback
fun copyFileToUserSelectedLocation(result: ActivityResult, sourceUri: String?) {
requestPermissions(PermissionsResultCallbacks.copyFileToUserSelectedLocation(result.intent()?.dataString, sourceUri), //
R.string.permission_message_export_file, //
Manifest.permission.READ_EXTERNAL_STORAGE)
requestPermissions(
PermissionsResultCallbacks.copyFileToUserSelectedLocation(result.intent()?.dataString, sourceUri), //
R.string.permission_message_export_file, //
Manifest.permission.READ_EXTERNAL_STORAGE
)
}
@Callback
fun copyFileToUserSelectedLocation(result: PermissionsResult, targetUri: String?, sourceUri: String?) {
if (result.granted()) {
try {
copyFile(contentResolverUtil.openInputStream(Uri.parse(sourceUri)), //
contentResolverUtil.openOutputStream(Uri.parse(targetUri)))
copyFile(
contentResolverUtil.openInputStream(Uri.parse(sourceUri)), //
contentResolverUtil.openOutputStream(Uri.parse(targetUri))
)
} catch (e: FileNotFoundException) {
showError(e)
}
@ -142,18 +149,18 @@ class ImagePreviewPresenter @Inject constructor( //
fun onDeleteImageConfirmed(imagePreviewFile: ImagePreviewFile, index: Int) {
view?.showProgress(ProgressModel.GENERIC)
deleteNodesUseCase
.withCloudNodes(listOf(imagePreviewFile.cloudFileModel.toCloudNode()))
.run(object : ProgressCompletingResultHandler<List<CloudNode?>?>() {
override fun onFinished() {
view?.showProgress(ProgressModel.COMPLETED)
view?.onImageDeleted(index)
}
.withCloudNodes(listOf(imagePreviewFile.cloudFileModel.toCloudNode()))
.run(object : ProgressCompletingResultHandler<List<CloudNode?>?>() {
override fun onFinished() {
view?.showProgress(ProgressModel.COMPLETED)
view?.onImageDeleted(index)
}
override fun onError(e: Throwable) {
Timber.tag("ImagePreviewPresenter").e(e, "Failed to delete preview image")
view?.showProgress(ProgressModel.COMPLETED)
}
})
override fun onError(e: Throwable) {
Timber.tag("ImagePreviewPresenter").e(e, "Failed to delete preview image")
view?.showProgress(ProgressModel.COMPLETED)
}
})
}
fun onImagePreviewClicked() {
@ -167,24 +174,24 @@ class ImagePreviewPresenter @Inject constructor( //
fun onMissingImagePreviewFile(imagePreviewFile: ImagePreviewFile) {
downloadFilesUseCase //
.withDownloadFiles(downloadFileUtil.createDownloadFilesFor(this, listOf(imagePreviewFile.cloudFileModel))) //
.run(object : DefaultProgressAwareResultHandler<List<CloudFile>, DownloadState>() {
override fun onSuccess(result: List<CloudFile>) {
cloudFileModelMapper.toModel(result[0])
imagePreviewFile.uri = fileUtil.contentUriFor(cloudFileModelMapper.toModel(result[0]))
view?.showImagePreview(imagePreviewFile)
view?.hideProgressBar(imagePreviewFile)
}
.withDownloadFiles(downloadFileUtil.createDownloadFilesFor(this, listOf(imagePreviewFile.cloudFileModel))) //
.run(object : DefaultProgressAwareResultHandler<List<CloudFile>, DownloadState>() {
override fun onSuccess(result: List<CloudFile>) {
cloudFileModelMapper.toModel(result[0])
imagePreviewFile.uri = fileUtil.contentUriFor(cloudFileModelMapper.toModel(result[0]))
view?.showImagePreview(imagePreviewFile)
view?.hideProgressBar(imagePreviewFile)
}
override fun onError(e: Throwable) {
if (ExceptionUtil.contains(e, IOException::class.java, ExceptionUtil.thatContainsMessage("Stream Closed"))) {
// ignore error
Timber.tag("ImagePreviewPresenter").d("User swiped to quickly and close the stream before finishing the download.")
} else {
super.onError(e)
}
override fun onError(e: Throwable) {
if (ExceptionUtil.contains(e, IOException::class.java, ExceptionUtil.thatContainsMessage("Stream Closed"))) {
// ignore error
Timber.tag("ImagePreviewPresenter").d("User swiped to quickly and close the stream before finishing the download.")
} else {
super.onError(e)
}
})
}
})
}
fun getImagePreviewFileStore(path: String): ImagePreviewFilesStore {

View File

@ -11,24 +11,25 @@ import javax.inject.Inject
import timber.log.Timber
class LicenseCheckPresenter @Inject internal constructor(
exceptionHandlers: ExceptionHandlers, //
private val doLicenseCheckUsecase: DoLicenseCheckUseCase, //
private val sharedPreferencesHandler: SharedPreferencesHandler) : Presenter<UpdateLicenseView>(exceptionHandlers) {
exceptionHandlers: ExceptionHandlers, //
private val doLicenseCheckUsecase: DoLicenseCheckUseCase, //
private val sharedPreferencesHandler: SharedPreferencesHandler
) : Presenter<UpdateLicenseView>(exceptionHandlers) {
fun validate(data: Uri?) {
data?.let {
val license = it.fragment ?: it.lastPathSegment ?: ""
view?.showOrUpdateLicenseDialog(license)
doLicenseCheckUsecase
.withLicense(license)
.run(CheckLicenseStatusSubscriber())
.withLicense(license)
.run(CheckLicenseStatusSubscriber())
}
}
fun validateDialogAware(license: String?) {
doLicenseCheckUsecase
.withLicense(license)
.run(CheckLicenseStatusSubscriber())
.withLicense(license)
.run(CheckLicenseStatusSubscriber())
}
private inner class CheckLicenseStatusSubscriber : NoOpResultHandler<LicenseCheck>() {

View File

@ -76,23 +76,23 @@ abstract class Presenter<V : View> protected constructor(private val exceptionMa
fun finishWithResult(resultName: String, result: Serializable?) {
activeWorkflow()?.dispatch(result)
?: run {
val data = Intent()
when (result) {
null -> {
activity().setResult(Activity.RESULT_CANCELED)
}
is Throwable -> {
data.putExtra(resultName, result)
activity().setResult(Activity.RESULT_CANCELED, data)
}
else -> {
data.putExtra(resultName, result)
activity().setResult(Activity.RESULT_OK, data)
}
?: run {
val data = Intent()
when (result) {
null -> {
activity().setResult(Activity.RESULT_CANCELED)
}
is Throwable -> {
data.putExtra(resultName, result)
activity().setResult(Activity.RESULT_CANCELED, data)
}
else -> {
data.putExtra(resultName, result)
activity().setResult(Activity.RESULT_OK, data)
}
finish()
}
finish()
}
}
private fun activeWorkflow(): Workflow<*>? {

View File

@ -16,9 +16,10 @@ import javax.inject.Inject
@PerView
class S3AddOrChangePresenter @Inject internal constructor( //
private val addOrChangeCloudConnectionUseCase: AddOrChangeCloudConnectionUseCase, //
private val connectToS3UseCase: ConnectToS3UseCase, //
exceptionMappings: ExceptionHandlers) : Presenter<S3AddOrChangeView>(exceptionMappings) {
private val addOrChangeCloudConnectionUseCase: AddOrChangeCloudConnectionUseCase, //
private val connectToS3UseCase: ConnectToS3UseCase, //
exceptionMappings: ExceptionHandlers
) : Presenter<S3AddOrChangeView>(exceptionMappings) {
fun checkUserInput(accessKey: String, secretKey: String, bucket: String, endpoint: String?, region: String?, cloudId: Long?, displayName: String) {
var statusMessage: String? = null
@ -48,19 +49,19 @@ class S3AddOrChangePresenter @Inject internal constructor( //
private fun encrypt(text: String): String {
return CredentialCryptor //
.getInstance(context()) //
.encrypt(text)
.getInstance(context()) //
.encrypt(text)
}
private fun mapToCloud(accessKey: String, secretKey: String, bucket: String, endpoint: String?, region: String?, cloudId: Long?, displayName: String): S3Cloud {
var builder = S3Cloud //
.aS3Cloud() //
.withAccessKey(accessKey) //
.withSecretKey(secretKey) //
.withS3Bucket(bucket) //
.withS3Endpoint(endpoint) //
.withS3Region(region) //
.withDisplayName(displayName)
.aS3Cloud() //
.withAccessKey(accessKey) //
.withSecretKey(secretKey) //
.withS3Bucket(bucket) //
.withS3Endpoint(endpoint) //
.withS3Region(region) //
.withDisplayName(displayName)
cloudId?.let { builder = builder.withId(cloudId) }
@ -74,17 +75,17 @@ class S3AddOrChangePresenter @Inject internal constructor( //
private fun authenticate(cloud: S3Cloud) {
view?.showProgress(ProgressModel(ProgressStateModel.AUTHENTICATION))
connectToS3UseCase //
.withCloud(cloud) //
.run(object : DefaultResultHandler<Void?>() {
override fun onSuccess(void: Void?) {
onCloudAuthenticated(cloud)
}
.withCloud(cloud) //
.run(object : DefaultResultHandler<Void?>() {
override fun onSuccess(void: Void?) {
onCloudAuthenticated(cloud)
}
override fun onError(e: Throwable) {
view?.showProgress(ProgressModel.COMPLETED)
super.onError(e)
}
})
override fun onError(e: Throwable) {
view?.showProgress(ProgressModel.COMPLETED)
super.onError(e)
}
})
}
private fun onCloudAuthenticated(cloud: Cloud) {
@ -94,8 +95,8 @@ class S3AddOrChangePresenter @Inject internal constructor( //
private fun save(cloud: Cloud) {
addOrChangeCloudConnectionUseCase //
.withCloud(cloud) //
.run(DefaultResultHandler())
.withCloud(cloud) //
.run(DefaultResultHandler())
}
init {

View File

@ -10,8 +10,9 @@ import javax.inject.Inject
@PerView
class SetPasswordPresenter @Inject constructor( //
private val createNewVaultWorkflow: CreateNewVaultWorkflow, //
exceptionMappings: ExceptionHandlers) : Presenter<SetPasswordView>(exceptionMappings) {
private val createNewVaultWorkflow: CreateNewVaultWorkflow, //
exceptionMappings: ExceptionHandlers
) : Presenter<SetPasswordView>(exceptionMappings) {
override fun workflows(): Iterable<Workflow<*>> {
return setOf(createNewVaultWorkflow)

View File

@ -39,12 +39,13 @@ import timber.log.Timber
@PerView
class SettingsPresenter @Inject internal constructor(
private val updateCheckUseCase: DoUpdateCheckUseCase, //
private val updateUseCase: DoUpdateUseCase, //
private val networkConnectionCheck: NetworkConnectionCheck, //
exceptionMappings: ExceptionHandlers, //
private val fileUtil: FileUtil, //
private val sharedPreferencesHandler: SharedPreferencesHandler) : Presenter<SettingsView>(exceptionMappings) {
private val updateCheckUseCase: DoUpdateCheckUseCase, //
private val updateUseCase: DoUpdateUseCase, //
private val networkConnectionCheck: NetworkConnectionCheck, //
exceptionMappings: ExceptionHandlers, //
private val fileUtil: FileUtil, //
private val sharedPreferencesHandler: SharedPreferencesHandler
) : Presenter<SettingsView>(exceptionMappings) {
fun onSendErrorReportClicked() {
view?.showProgress(ProgressModel.GENERIC)
@ -58,11 +59,11 @@ class SettingsPresenter @Inject internal constructor(
private fun sendErrorReport(attachment: File) {
EmailBuilder.anEmail() //
.to("support@cryptomator.org") //
.withSubject(context().getString(R.string.error_report_subject)) //
.withBody(errorReportEmailBody()) //
.attach(attachment) //
.send(activity())
.to("support@cryptomator.org") //
.withSubject(context().getString(R.string.error_report_subject)) //
.withBody(errorReportEmailBody()) //
.attach(attachment) //
.send(activity())
}
private fun errorReportEmailBody(): String {
@ -76,20 +77,22 @@ class SettingsPresenter @Inject internal constructor(
else -> "Google Play"
}
return StringBuilder().append("## ").append(context().getString(R.string.error_report_subject)).append("\n\n") //
.append("### ").append(context().getString(R.string.error_report_section_summary)).append('\n') //
.append(context().getString(R.string.error_report_summary_description)).append("\n\n") //
.append("### ").append(context().getString(R.string.error_report_section_device)).append("\n") //
.append("Cryptomator v").append(BuildConfig.VERSION_NAME).append(" (").append(BuildConfig.VERSION_CODE).append(") ").append(variant).append("\n") //
.append("Android ").append(Build.VERSION.RELEASE).append(" / API").append(Build.VERSION.SDK_INT).append("\n") //
.append("Device ").append(Build.MODEL) //
.toString()
.append("### ").append(context().getString(R.string.error_report_section_summary)).append('\n') //
.append(context().getString(R.string.error_report_summary_description)).append("\n\n") //
.append("### ").append(context().getString(R.string.error_report_section_device)).append("\n") //
.append("Cryptomator v").append(BuildConfig.VERSION_NAME).append(" (").append(BuildConfig.VERSION_CODE).append(") ").append(variant).append("\n") //
.append("Android ").append(Build.VERSION.RELEASE).append(" / API").append(Build.VERSION.SDK_INT).append("\n") //
.append("Device ").append(Build.MODEL) //
.toString()
}
fun grantLocalStoragePermissionForAutoUpload() {
requestPermissions(PermissionsResultCallbacks.onLocalStoragePermissionGranted(), //
R.string.permission_snackbar_auth_auto_upload, //
Manifest.permission.READ_EXTERNAL_STORAGE, //
Manifest.permission.WRITE_EXTERNAL_STORAGE)
requestPermissions(
PermissionsResultCallbacks.onLocalStoragePermissionGranted(), //
R.string.permission_snackbar_auth_auto_upload, //
Manifest.permission.READ_EXTERNAL_STORAGE, //
Manifest.permission.WRITE_EXTERNAL_STORAGE
)
}
@Callback
@ -106,23 +109,23 @@ class SettingsPresenter @Inject internal constructor(
fun onCheckUpdateClicked() {
if (networkConnectionCheck.isPresent) {
updateCheckUseCase //
.withVersion(BuildConfig.VERSION_NAME)
.run(object : NoOpResultHandler<Optional<UpdateCheck?>?>() {
override fun onSuccess(result: Optional<UpdateCheck?>?) {
if (result?.isPresent == true) {
result.get()?.let { updateStatusRetrieved(it, context()) }
} else {
Timber.tag("SettingsPresenter").i("UpdateCheck finished, latest version")
Toast.makeText(context(), getString(R.string.notification_update_check_finished_latest), Toast.LENGTH_SHORT).show()
}
sharedPreferencesHandler.updateExecuted()
view?.refreshUpdateTimeView()
.withVersion(BuildConfig.VERSION_NAME)
.run(object : NoOpResultHandler<Optional<UpdateCheck?>?>() {
override fun onSuccess(result: Optional<UpdateCheck?>?) {
if (result?.isPresent == true) {
result.get()?.let { updateStatusRetrieved(it, context()) }
} else {
Timber.tag("SettingsPresenter").i("UpdateCheck finished, latest version")
Toast.makeText(context(), getString(R.string.notification_update_check_finished_latest), Toast.LENGTH_SHORT).show()
}
sharedPreferencesHandler.updateExecuted()
view?.refreshUpdateTimeView()
}
override fun onError(e: Throwable) {
showError(e)
}
})
override fun onError(e: Throwable) {
showError(e)
}
})
} else {
Toast.makeText(context(), R.string.error_update_no_internet, Toast.LENGTH_SHORT).show()
}
@ -145,21 +148,21 @@ class SettingsPresenter @Inject internal constructor(
val uri = fileUtil.contentUriForNewTempFile("cryptomator.apk")
val file = fileUtil.tempFile("cryptomator.apk")
updateUseCase //
.withFile(file) //
.run(object : NoOpResultHandler<Void?>() {
override fun onError(e: Throwable) {
showError(e)
}
.withFile(file) //
.run(object : NoOpResultHandler<Void?>() {
override fun onError(e: Throwable) {
showError(e)
}
override fun onSuccess(result: Void?) {
super.onSuccess(result)
val intent = Intent(Intent.ACTION_VIEW)
intent.setDataAndType(uri, "application/vnd.android.package-archive")
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
context().startActivity(intent)
}
})
override fun onSuccess(result: Void?) {
super.onSuccess(result)
val intent = Intent(Intent.ACTION_VIEW)
intent.setDataAndType(uri, "application/vnd.android.package-archive")
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
context().startActivity(intent)
}
})
}
private inner class CreateErrorReportArchiveTask : AsyncTask<Void?, IOException?, File?>() {

View File

@ -32,17 +32,18 @@ import timber.log.Timber
@PerView
class SharedFilesPresenter @Inject constructor( //
private val getVaultListUseCase: GetVaultListUseCase, //
private val getRootFolderUseCase: GetRootFolderUseCase, //
private val getDecryptedCloudForVaultUseCase: GetDecryptedCloudForVaultUseCase, //
private val uploadFilesUseCase: UploadFilesUseCase, //
private val getCloudListUseCase: GetCloudListUseCase, //
private val contentResolverUtil: ContentResolverUtil, //
private val fileCacheUtils: FileCacheUtils, //
private val authenticationExceptionHandler: AuthenticationExceptionHandler, //
private val cloudFolderModelMapper: CloudFolderModelMapper, //
private val progressModelMapper: ProgressModelMapper, //
exceptionMappings: ExceptionHandlers) : Presenter<SharedFilesView>(exceptionMappings) {
private val getVaultListUseCase: GetVaultListUseCase, //
private val getRootFolderUseCase: GetRootFolderUseCase, //
private val getDecryptedCloudForVaultUseCase: GetDecryptedCloudForVaultUseCase, //
private val uploadFilesUseCase: UploadFilesUseCase, //
private val getCloudListUseCase: GetCloudListUseCase, //
private val contentResolverUtil: ContentResolverUtil, //
private val fileCacheUtils: FileCacheUtils, //
private val authenticationExceptionHandler: AuthenticationExceptionHandler, //
private val cloudFolderModelMapper: CloudFolderModelMapper, //
private val progressModelMapper: ProgressModelMapper, //
exceptionMappings: ExceptionHandlers
) : Presenter<SharedFilesView>(exceptionMappings) {
private val filesForUpload: MutableSet<UploadFile> = HashSet()
private val existingFilesForUpload: MutableSet<UploadFile> = HashSet()
@ -65,8 +66,8 @@ class SharedFilesPresenter @Inject constructor( //
} else {
Timber.tag("SharedFile").i("Received 1 file")
contentResolverUtil.fileName(uri)
?.let { filesForUpload.add(createUploadFile(it, uri)) }
?: Timber.tag("SharedFile").i("The file doesn't have a path in the URI")
?.let { filesForUpload.add(createUploadFile(it, uri)) }
?: Timber.tag("SharedFile").i("The file doesn't have a path in the URI")
}
}
@ -74,8 +75,8 @@ class SharedFilesPresenter @Inject constructor( //
Timber.tag("SharedFile").i("Received %d files", uris.size)
uris.forEach { uri ->
contentResolverUtil.fileName(uri)
?.let { filesForUpload.add(createUploadFile(it, uri)) }
?: Timber.tag("SharedFile").i("The file doesn't have a path in the URI")
?.let { filesForUpload.add(createUploadFile(it, uri)) }
?: Timber.tag("SharedFile").i("The file doesn't have a path in the URI")
}
}
@ -128,8 +129,9 @@ class SharedFilesPresenter @Inject constructor( //
} else {
if (!isPaused) {
requestActivityResult( //
ActivityResultCallbacks.vaultUnlockedSharedFiles(), //
Intents.unlockVaultIntent().withVaultModel(VaultModel(authenticatedVault)).withVaultAction(UnlockVaultIntent.VaultAction.UNLOCK))
ActivityResultCallbacks.vaultUnlockedSharedFiles(), //
Intents.unlockVaultIntent().withVaultModel(VaultModel(authenticatedVault)).withVaultAction(UnlockVaultIntent.VaultAction.UNLOCK)
)
}
}
}
@ -146,18 +148,18 @@ class SharedFilesPresenter @Inject constructor( //
private fun decryptedCloudFor(vault: Vault) {
getDecryptedCloudForVaultUseCase //
.withVault(vault) //
.run(object : DefaultResultHandler<Cloud>() {
override fun onSuccess(cloud: Cloud) {
rootFolderFor(cloud)
}
.withVault(vault) //
.run(object : DefaultResultHandler<Cloud>() {
override fun onSuccess(cloud: Cloud) {
rootFolderFor(cloud)
}
override fun onError(e: Throwable) {
if (!authenticationExceptionHandler.handleAuthenticationException(this@SharedFilesPresenter, e, ActivityResultCallbacks.decryptedCloudForAfterAuth(vault))) {
super.onError(e)
}
override fun onError(e: Throwable) {
if (!authenticationExceptionHandler.handleAuthenticationException(this@SharedFilesPresenter, e, ActivityResultCallbacks.decryptedCloudForAfterAuth(vault))) {
super.onError(e)
}
})
}
})
}
@Callback
@ -168,18 +170,18 @@ class SharedFilesPresenter @Inject constructor( //
private fun rootFolderFor(cloud: Cloud) {
getRootFolderUseCase //
.withCloud(cloud) //
.run(object : DefaultResultHandler<CloudFolder>() {
override fun onSuccess(folder: CloudFolder) {
when (authenticationState) {
AuthenticationState.CHOOSE_LOCATION -> navigateToVaultContent((folder.cloud as CryptoCloud).vault, folder)
AuthenticationState.INIT_ROOT -> {
location = cloudFolderModelMapper.toModel(folder)
checkForUsedFileNames(folder)
}
.withCloud(cloud) //
.run(object : DefaultResultHandler<CloudFolder>() {
override fun onSuccess(folder: CloudFolder) {
when (authenticationState) {
AuthenticationState.CHOOSE_LOCATION -> navigateToVaultContent((folder.cloud as CryptoCloud).vault, folder)
AuthenticationState.INIT_ROOT -> {
location = cloudFolderModelMapper.toModel(folder)
checkForUsedFileNames(folder)
}
}
})
}
})
}
private fun navigateToVaultContent(vault: Vault, folder: CloudFolder) {
@ -192,9 +194,11 @@ class SharedFilesPresenter @Inject constructor( //
this.location = location
}
private fun uploadFiles(nonReplacing: Set<UploadFile>, //
replacing: Set<UploadFile>, //
folder: CloudFolder) {
private fun uploadFiles(
nonReplacing: Set<UploadFile>, //
replacing: Set<UploadFile>, //
folder: CloudFolder
) {
if (nonReplacing.size + replacing.size == 0) {
view?.finish()
}
@ -207,17 +211,17 @@ class SharedFilesPresenter @Inject constructor( //
private fun uploadFiles(folder: CloudFolder, files: List<UploadFile>) {
uploadFilesUseCase //
.withParent(folder) //
.andFiles(files) //
.run(object : DefaultProgressAwareResultHandler<List<CloudFile>, UploadState>() {
override fun onProgress(progress: Progress<UploadState>) {
view?.showProgress(progressModelMapper.toModel(progress))
}
.withParent(folder) //
.andFiles(files) //
.run(object : DefaultProgressAwareResultHandler<List<CloudFile>, UploadState>() {
override fun onProgress(progress: Progress<UploadState>) {
view?.showProgress(progressModelMapper.toModel(progress))
}
override fun onFinished() {
onFileUploadCompleted()
}
})
override fun onFinished() {
onFileUploadCompleted()
}
})
}
private fun onFileUploadCompleted() {
@ -248,12 +252,12 @@ class SharedFilesPresenter @Inject constructor( //
private fun checkForUsedFileNames(folder: CloudFolder) {
view?.showProgress(ProgressModel.GENERIC)
getCloudListUseCase //
.withFolder(folder) //
.run(object : DefaultResultHandler<List<CloudNode>>() {
override fun onSuccess(currentCloudNodes: List<CloudNode>) {
checkForExistingFilesOrUploadFiles(folder, currentCloudNodes)
}
})
.withFolder(folder) //
.run(object : DefaultResultHandler<List<CloudNode>>() {
override fun onSuccess(currentCloudNodes: List<CloudNode>) {
checkForExistingFilesOrUploadFiles(folder, currentCloudNodes)
}
})
}
private fun hasUsedFileNamesAtLocation(currentCloudNodes: List<CloudNode>): Boolean {
@ -264,9 +268,10 @@ class SharedFilesPresenter @Inject constructor( //
if (cloudNode is CloudFile) {
filesForUpload.remove(uploadFileWithName.get())
existingFilesForUpload.add( //
UploadFile.aCopyOf(uploadFileWithName.get()) //
.thatIsReplacing(true) //
.build())
UploadFile.aCopyOf(uploadFileWithName.get()) //
.thatIsReplacing(true) //
.build()
)
} else {
// remove file when name is used by a folder
filesForUpload.remove(uploadFileWithName.get())
@ -278,9 +283,9 @@ class SharedFilesPresenter @Inject constructor( //
private fun fileForUploadWithName(name: String): Optional<UploadFile> {
return filesForUpload
.firstOrNull { it.fileName == name }
?.let { Optional.of(it) }
?: Optional.empty()
.firstOrNull { it.fileName == name }
?.let { Optional.of(it) }
?: Optional.empty()
}
private fun checkForExistingFilesOrUploadFiles(folder: CloudFolder, currentCloudNodes: List<CloudNode>) {
@ -297,7 +302,7 @@ class SharedFilesPresenter @Inject constructor( //
private fun prepareSavingFiles() {
location?.let { checkForUsedFileNames(it.toCloudNode()) }
?: authenticate(selectedVault, AuthenticationState.INIT_ROOT)
?: authenticate(selectedVault, AuthenticationState.INIT_ROOT)
}
fun onSaveButtonPressed(filesForUpload: List<SharedFileModel>) {
@ -310,9 +315,11 @@ class SharedFilesPresenter @Inject constructor( //
view?.showMessage(R.string.error_names_contains_invalid_characters)
}
else -> {
requestPermissions(PermissionsResultCallbacks.saveFilesPermissionCallback(), //
R.string.permission_message_share_file, //
Manifest.permission.READ_EXTERNAL_STORAGE)
requestPermissions(
PermissionsResultCallbacks.saveFilesPermissionCallback(), //
R.string.permission_message_share_file, //
Manifest.permission.READ_EXTERNAL_STORAGE
)
}
}
}
@ -335,17 +342,19 @@ class SharedFilesPresenter @Inject constructor( //
private fun navigateToVaultContent(vaultModel: VaultModel, decryptedRoot: CloudFolderModel) {
requestActivityResult( //
ActivityResultCallbacks.onChooseLocation(vaultModel), //
Intents.browseFilesIntent() //
.withFolder(decryptedRoot) //
.withTitle(vaultModel.name) //
.withChooseCloudNodeSettings( //
ChooseCloudNodeSettings.chooseCloudNodeSettings() //
.withExtraTitle(context().getString(R.string.screen_file_browser_share_destination_title)) //
.withExtraToolbarIcon(R.drawable.ic_clear) //
.withButtonText(context().getString(R.string.screen_file_browser_share_button_text)) //
.selectingFolders() //
.build()))
ActivityResultCallbacks.onChooseLocation(vaultModel), //
Intents.browseFilesIntent() //
.withFolder(decryptedRoot) //
.withTitle(vaultModel.name) //
.withChooseCloudNodeSettings( //
ChooseCloudNodeSettings.chooseCloudNodeSettings() //
.withExtraTitle(context().getString(R.string.screen_file_browser_share_destination_title)) //
.withExtraToolbarIcon(R.drawable.ic_clear) //
.withButtonText(context().getString(R.string.screen_file_browser_share_button_text)) //
.selectingFolders() //
.build()
)
)
}
@Callback
@ -396,18 +405,19 @@ class SharedFilesPresenter @Inject constructor( //
private fun createUploadFile(fileName: String, uri: Uri): UploadFile {
return UploadFile.anUploadFile() //
.withFileName(fileName) //
.withDataSource(UriBasedDataSource.from(uri)) //
.thatIsReplacing(false) //
.build()
.withFileName(fileName) //
.withDataSource(UriBasedDataSource.from(uri)) //
.thatIsReplacing(false) //
.build()
}
init {
unsubscribeOnDestroy( //
getRootFolderUseCase, //
getVaultListUseCase, //
getDecryptedCloudForVaultUseCase, //
uploadFilesUseCase, //
getCloudListUseCase)
getRootFolderUseCase, //
getVaultListUseCase, //
getDecryptedCloudForVaultUseCase, //
uploadFilesUseCase, //
getCloudListUseCase
)
}
}

View File

@ -21,11 +21,12 @@ import javax.inject.Inject
@PerView
class TextEditorPresenter @Inject constructor( //
private val fileCacheUtils: FileCacheUtils, //
private val fileUtil: FileUtil, //
private val contentResolverUtil: ContentResolverUtil, //
private val uploadFilesUseCase: UploadFilesUseCase, //
exceptionMappings: ExceptionHandlers) : Presenter<TextEditorView>(exceptionMappings) {
private val fileCacheUtils: FileCacheUtils, //
private val fileUtil: FileUtil, //
private val contentResolverUtil: ContentResolverUtil, //
private val uploadFilesUseCase: UploadFilesUseCase, //
exceptionMappings: ExceptionHandlers
) : Presenter<TextEditorView>(exceptionMappings) {
private val textFile = AtomicReference<CloudFileModel>()
@ -64,34 +65,36 @@ class TextEditorPresenter @Inject constructor( //
view?.let {
it.showProgress(ProgressModel.GENERIC)
val uri = fileCacheUtils.tmpFile() //
.withContent(it.textFileContent) //
.create()
.withContent(it.textFileContent) //
.create()
uploadFile(textFile.get().name, UriBasedDataSource.from(uri))
}
}
private fun uploadFile(fileName: String, dataSource: DataSource) {
uploadFilesUseCase //
.withParent(textFile.get().parent.toCloudNode()) //
.andFiles(listOf( //
UploadFile.anUploadFile() //
.withFileName(fileName) //
.withDataSource(dataSource) //
.thatIsReplacing(true) //
.build() //
)) //
.run(object : DefaultProgressAwareResultHandler<List<CloudFile?>, UploadState>() {
override fun onFinished() {
view?.showProgress(ProgressModel.COMPLETED)
view?.finish()
view?.showMessage(R.string.screen_text_editor_save_success)
}
.withParent(textFile.get().parent.toCloudNode()) //
.andFiles(
listOf( //
UploadFile.anUploadFile() //
.withFileName(fileName) //
.withDataSource(dataSource) //
.thatIsReplacing(true) //
.build() //
)
) //
.run(object : DefaultProgressAwareResultHandler<List<CloudFile?>, UploadState>() {
override fun onFinished() {
view?.showProgress(ProgressModel.COMPLETED)
view?.finish()
view?.showMessage(R.string.screen_text_editor_save_success)
}
override fun onError(e: Throwable) {
view?.showProgress(ProgressModel.COMPLETED)
showError(e)
}
})
override fun onError(e: Throwable) {
view?.showProgress(ProgressModel.COMPLETED)
showError(e)
}
})
}
fun loadFileContent() {

View File

@ -40,17 +40,18 @@ import timber.log.Timber
@PerView
class UnlockVaultPresenter @Inject constructor(
private val changePasswordUseCase: ChangePasswordUseCase,
private val deleteVaultUseCase: DeleteVaultUseCase,
private val getUnverifiedVaultConfigUseCase: GetUnverifiedVaultConfigUseCase,
private val lockVaultUseCase: LockVaultUseCase,
private val unlockVaultUsingMasterkeyUseCase: UnlockVaultUsingMasterkeyUseCase,
private val prepareUnlockUseCase: PrepareUnlockUseCase,
private val removeStoredVaultPasswordsUseCase: RemoveStoredVaultPasswordsUseCase,
private val saveVaultUseCase: SaveVaultUseCase,
private val authenticationExceptionHandler: AuthenticationExceptionHandler,
private val sharedPreferencesHandler: SharedPreferencesHandler,
exceptionMappings: ExceptionHandlers) : Presenter<UnlockVaultView>(exceptionMappings) {
private val changePasswordUseCase: ChangePasswordUseCase,
private val deleteVaultUseCase: DeleteVaultUseCase,
private val getUnverifiedVaultConfigUseCase: GetUnverifiedVaultConfigUseCase,
private val lockVaultUseCase: LockVaultUseCase,
private val unlockVaultUsingMasterkeyUseCase: UnlockVaultUsingMasterkeyUseCase,
private val prepareUnlockUseCase: PrepareUnlockUseCase,
private val removeStoredVaultPasswordsUseCase: RemoveStoredVaultPasswordsUseCase,
private val saveVaultUseCase: SaveVaultUseCase,
private val authenticationExceptionHandler: AuthenticationExceptionHandler,
private val sharedPreferencesHandler: SharedPreferencesHandler,
exceptionMappings: ExceptionHandlers
) : Presenter<UnlockVaultView>(exceptionMappings) {
private var startedUsingPrepareUnlock = false
private var retryUnlockHandler: Handler? = null
@ -77,27 +78,27 @@ class UnlockVaultPresenter @Inject constructor(
}
getUnverifiedVaultConfigUseCase
.withVault(intent.vaultModel().toVault())
.run(object : DefaultResultHandler<Optional<UnverifiedVaultConfig>>() {
override fun onSuccess(unverifiedVaultConfig: Optional<UnverifiedVaultConfig>) {
if (unverifiedVaultConfig.isAbsent || unverifiedVaultConfig.get().keyId.scheme == CryptoConstants.MASTERKEY_SCHEME) {
when (intent.vaultAction()) {
UnlockVaultIntent.VaultAction.UNLOCK, UnlockVaultIntent.VaultAction.UNLOCK_FOR_BIOMETRIC_AUTH -> {
startedUsingPrepareUnlock = sharedPreferencesHandler.backgroundUnlockPreparation()
pendingUnlockFor(intent.vaultModel().toVault())?.unverifiedVaultConfig = unverifiedVaultConfig.orElse(null)
unlockVault(intent.vaultModel())
}
UnlockVaultIntent.VaultAction.CHANGE_PASSWORD -> view?.showChangePasswordDialog(intent.vaultModel(), unverifiedVaultConfig.orElse(null))
else -> TODO("Not yet implemented")
.withVault(intent.vaultModel().toVault())
.run(object : DefaultResultHandler<Optional<UnverifiedVaultConfig>>() {
override fun onSuccess(unverifiedVaultConfig: Optional<UnverifiedVaultConfig>) {
if (unverifiedVaultConfig.isAbsent || unverifiedVaultConfig.get().keyId.scheme == CryptoConstants.MASTERKEY_SCHEME) {
when (intent.vaultAction()) {
UnlockVaultIntent.VaultAction.UNLOCK, UnlockVaultIntent.VaultAction.UNLOCK_FOR_BIOMETRIC_AUTH -> {
startedUsingPrepareUnlock = sharedPreferencesHandler.backgroundUnlockPreparation()
pendingUnlockFor(intent.vaultModel().toVault())?.unverifiedVaultConfig = unverifiedVaultConfig.orElse(null)
unlockVault(intent.vaultModel())
}
UnlockVaultIntent.VaultAction.CHANGE_PASSWORD -> view?.showChangePasswordDialog(intent.vaultModel(), unverifiedVaultConfig.orElse(null))
else -> TODO("Not yet implemented")
}
}
}
override fun onError(e: Throwable) {
super.onError(e)
finishWithResult(null)
}
})
override fun onError(e: Throwable) {
super.onError(e)
finishWithResult(null)
}
})
}
private fun unlockVault(vaultModel: VaultModel) {
@ -134,8 +135,8 @@ class UnlockVaultPresenter @Inject constructor(
private fun canUseBiometricOn(vault: VaultModel): Boolean {
return vault.password != null && BiometricManager //
.from(context()) //
.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG) == BiometricManager.BIOMETRIC_SUCCESS
.from(context()) //
.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG) == BiometricManager.BIOMETRIC_SUCCESS
}
fun onUnlockCanceled() {
@ -146,31 +147,31 @@ class UnlockVaultPresenter @Inject constructor(
fun startPrepareUnlockUseCase(vault: Vault) {
prepareUnlockUseCase //
.withVault(vault) //
.andUnverifiedVaultConfig(Optional.ofNullable(pendingUnlockFor(intent.vaultModel().toVault())?.unverifiedVaultConfig))
.run(object : DefaultResultHandler<UnlockToken>() {
override fun onSuccess(unlockToken: UnlockToken) {
if (!startedUsingPrepareUnlock && vault.password != null) {
doUnlock(unlockToken, vault.password, pendingUnlockFor(intent.vaultModel().toVault())?.unverifiedVaultConfig)
} else {
unlockTokenObtained(unlockToken)
}
.withVault(vault) //
.andUnverifiedVaultConfig(Optional.ofNullable(pendingUnlockFor(intent.vaultModel().toVault())?.unverifiedVaultConfig))
.run(object : DefaultResultHandler<UnlockToken>() {
override fun onSuccess(unlockToken: UnlockToken) {
if (!startedUsingPrepareUnlock && vault.password != null) {
doUnlock(unlockToken, vault.password, pendingUnlockFor(intent.vaultModel().toVault())?.unverifiedVaultConfig)
} else {
unlockTokenObtained(unlockToken)
}
}
override fun onError(e: Throwable) {
if (e is AuthenticationException) {
view?.cancelBasicAuthIfRunning()
}
if (!authenticationExceptionHandler.handleAuthenticationException(this@UnlockVaultPresenter, e, ActivityResultCallbacks.authenticatedAfterUnlock(vault))) {
super.onError(e)
if (e is NetworkConnectionException) {
running = true
retryUnlockHandler = Handler()
restartUnlockUseCase(vault)
}
override fun onError(e: Throwable) {
if (e is AuthenticationException) {
view?.cancelBasicAuthIfRunning()
}
if (!authenticationExceptionHandler.handleAuthenticationException(this@UnlockVaultPresenter, e, ActivityResultCallbacks.authenticatedAfterUnlock(vault))) {
super.onError(e)
if (e is NetworkConnectionException) {
running = true
retryUnlockHandler = Handler()
restartUnlockUseCase(vault)
}
}
})
}
})
}
@Callback(dispatchResultOkOnly = false)
@ -197,22 +198,22 @@ class UnlockVaultPresenter @Inject constructor(
retryUnlockHandler?.postDelayed({
if (running) {
prepareUnlockUseCase //
.withVault(vault) //
.run(object : DefaultResultHandler<UnlockToken>() {
override fun onSuccess(unlockToken: UnlockToken) {
if (!startedUsingPrepareUnlock && vault.password != null) {
doUnlock(unlockToken, vault.password, pendingUnlockFor(intent.vaultModel().toVault())?.unverifiedVaultConfig)
} else {
unlockTokenObtained(unlockToken)
}
.withVault(vault) //
.run(object : DefaultResultHandler<UnlockToken>() {
override fun onSuccess(unlockToken: UnlockToken) {
if (!startedUsingPrepareUnlock && vault.password != null) {
doUnlock(unlockToken, vault.password, pendingUnlockFor(intent.vaultModel().toVault())?.unverifiedVaultConfig)
} else {
unlockTokenObtained(unlockToken)
}
}
override fun onError(e: Throwable) {
if (e is NetworkConnectionException) {
restartUnlockUseCase(vault)
}
override fun onError(e: Throwable) {
if (e is NetworkConnectionException) {
restartUnlockUseCase(vault)
}
})
}
})
}
}, 1000)
}
@ -228,28 +229,28 @@ class UnlockVaultPresenter @Inject constructor(
private fun doUnlock(token: UnlockToken, password: String, unverifiedVaultConfig: UnverifiedVaultConfig?) {
unlockVaultUsingMasterkeyUseCase //
.withVaultOrUnlockToken(VaultOrUnlockToken.from(token)) //
.andUnverifiedVaultConfig(Optional.ofNullable(unverifiedVaultConfig)) //
.andPassword(password) //
.run(object : DefaultResultHandler<Cloud>() {
override fun onSuccess(cloud: Cloud) {
when (intent.vaultAction()) {
UnlockVaultIntent.VaultAction.ENCRYPT_PASSWORD, UnlockVaultIntent.VaultAction.UNLOCK_FOR_BIOMETRIC_AUTH -> {
handleUnlockVaultSuccess(token.vault, cloud, password)
}
UnlockVaultIntent.VaultAction.UNLOCK -> finishWithResult(cloud)
else -> TODO("Not yet implemented")
.withVaultOrUnlockToken(VaultOrUnlockToken.from(token)) //
.andUnverifiedVaultConfig(Optional.ofNullable(unverifiedVaultConfig)) //
.andPassword(password) //
.run(object : DefaultResultHandler<Cloud>() {
override fun onSuccess(cloud: Cloud) {
when (intent.vaultAction()) {
UnlockVaultIntent.VaultAction.ENCRYPT_PASSWORD, UnlockVaultIntent.VaultAction.UNLOCK_FOR_BIOMETRIC_AUTH -> {
handleUnlockVaultSuccess(token.vault, cloud, password)
}
UnlockVaultIntent.VaultAction.UNLOCK -> finishWithResult(cloud)
else -> TODO("Not yet implemented")
}
}
override fun onError(e: Throwable) {
super.onError(e)
// finish in case of biometric auth, otherwise show error in dialog
if(view?.isShowingDialog(EnterPasswordDialog::class) == false) {
finishWithResult(null)
}
override fun onError(e: Throwable) {
super.onError(e)
// finish in case of biometric auth, otherwise show error in dialog
if (view?.isShowingDialog(EnterPasswordDialog::class) == false) {
finishWithResult(null)
}
})
}
})
}
private fun handleUnlockVaultSuccess(vault: Vault, cloud: Cloud, password: String) {
@ -295,12 +296,12 @@ class UnlockVaultPresenter @Inject constructor(
}
UnlockVaultIntent.VaultAction.CHANGE_PASSWORD -> {
saveVaultUseCase //
.withVault(vaultModel.toVault()) //
.run(object : DefaultResultHandler<Vault>() {
override fun onSuccess(vault: Vault) {
finishWithResult(vaultModel)
}
})
.withVault(vaultModel.toVault()) //
.run(object : DefaultResultHandler<Vault>() {
override fun onSuccess(vault: Vault) {
finishWithResult(vaultModel)
}
})
}
else -> TODO("Not yet implemented")
}
@ -309,31 +310,36 @@ class UnlockVaultPresenter @Inject constructor(
fun onChangePasswordClick(vaultModel: VaultModel, unverifiedVaultConfig: UnverifiedVaultConfig?, oldPassword: String, newPassword: String) {
view?.showProgress(ProgressModel(ProgressStateModel.CHANGING_PASSWORD))
changePasswordUseCase.withVault(vaultModel.toVault()) //
.andUnverifiedVaultConfig(Optional.ofNullable(unverifiedVaultConfig)) //
.andOldPassword(oldPassword) //
.andNewPassword(newPassword) //
.run(object : DefaultResultHandler<Void?>() {
override fun onSuccess(void: Void?) {
view?.showProgress(ProgressModel.COMPLETED)
view?.showMessage(R.string.screen_vault_list_change_password_successful)
if (canUseBiometricOn(vaultModel)) {
view?.getEncryptedPasswordWithBiometricAuthentication(VaultModel( //
Vault.aCopyOf(vaultModel.toVault()) //
.withSavedPassword(newPassword) //
.build()))
} else {
finishWithResult(vaultModel)
}
.andUnverifiedVaultConfig(Optional.ofNullable(unverifiedVaultConfig)) //
.andOldPassword(oldPassword) //
.andNewPassword(newPassword) //
.run(object : DefaultResultHandler<Void?>() {
override fun onSuccess(void: Void?) {
view?.showProgress(ProgressModel.COMPLETED)
view?.showMessage(R.string.screen_vault_list_change_password_successful)
if (canUseBiometricOn(vaultModel)) {
view?.getEncryptedPasswordWithBiometricAuthentication(
VaultModel( //
Vault.aCopyOf(vaultModel.toVault()) //
.withSavedPassword(newPassword) //
.build()
)
)
} else {
finishWithResult(vaultModel)
}
}
override fun onError(e: Throwable) {
if (!authenticationExceptionHandler.handleAuthenticationException( //
this@UnlockVaultPresenter, e, //
ActivityResultCallbacks.changePasswordAfterAuthentication(vaultModel.toVault(), unverifiedVaultConfig, oldPassword, newPassword))) {
showError(e)
}
override fun onError(e: Throwable) {
if (!authenticationExceptionHandler.handleAuthenticationException( //
this@UnlockVaultPresenter, e, //
ActivityResultCallbacks.changePasswordAfterAuthentication(vaultModel.toVault(), unverifiedVaultConfig, oldPassword, newPassword)
)
) {
showError(e)
}
})
}
})
}
@Callback
@ -346,22 +352,22 @@ class UnlockVaultPresenter @Inject constructor(
fun saveVaultAfterChangePasswordButFailedBiometricAuth(vault: Vault) {
Timber.tag("UnlockVaultPresenter").e("Save vault without password because biometric auth failed after changing vault password")
saveVaultUseCase //
.withVault(vault) //
.run(object : DefaultResultHandler<Vault>() {
override fun onSuccess(vault: Vault) {
finishWithResult(vault)
}
})
.withVault(vault) //
.run(object : DefaultResultHandler<Vault>() {
override fun onSuccess(vault: Vault) {
finishWithResult(vault)
}
})
}
fun onDeleteMissingVaultClicked(vault: Vault) {
deleteVaultUseCase //
.withVault(vault) //
.run(object : DefaultResultHandler<Long>() {
override fun onSuccess(vaultId: Long) {
finishWithResult(null)
}
})
.withVault(vault) //
.run(object : DefaultResultHandler<Long>() {
override fun onSuccess(vaultId: Long) {
finishWithResult(null)
}
})
}
fun onCancelMissingVaultClicked(vault: Vault) {
@ -410,14 +416,15 @@ class UnlockVaultPresenter @Inject constructor(
init {
unsubscribeOnDestroy( //
changePasswordUseCase, //
deleteVaultUseCase, //
getUnverifiedVaultConfigUseCase, //
lockVaultUseCase, //
unlockVaultUsingMasterkeyUseCase, //
prepareUnlockUseCase, //
removeStoredVaultPasswordsUseCase, //
saveVaultUseCase)
changePasswordUseCase, //
deleteVaultUseCase, //
getUnverifiedVaultConfigUseCase, //
lockVaultUseCase, //
unlockVaultUsingMasterkeyUseCase, //
prepareUnlockUseCase, //
removeStoredVaultPasswordsUseCase, //
saveVaultUseCase
)
}
}

View File

@ -61,25 +61,26 @@ import timber.log.Timber
@PerView
class VaultListPresenter @Inject constructor( //
private val getVaultListUseCase: GetVaultListUseCase, //
private val deleteVaultUseCase: DeleteVaultUseCase, //
private val renameVaultUseCase: RenameVaultUseCase, //
private val lockVaultUseCase: LockVaultUseCase, //
private val getDecryptedCloudForVaultUseCase: GetDecryptedCloudForVaultUseCase, //
private val getRootFolderUseCase: GetRootFolderUseCase, //
private val addExistingVaultWorkflow: AddExistingVaultWorkflow, //
private val createNewVaultWorkflow: CreateNewVaultWorkflow, //
private val saveVaultUseCase: SaveVaultUseCase, //
private val moveVaultPositionUseCase: MoveVaultPositionUseCase, //
private val licenseCheckUseCase: DoLicenseCheckUseCase, //
private val updateCheckUseCase: DoUpdateCheckUseCase, //
private val updateUseCase: DoUpdateUseCase, //
private val networkConnectionCheck: NetworkConnectionCheck, //
private val fileUtil: FileUtil, //
private val authenticationExceptionHandler: AuthenticationExceptionHandler, //
private val cloudFolderModelMapper: CloudFolderModelMapper, //
private val sharedPreferencesHandler: SharedPreferencesHandler, //
exceptionMappings: ExceptionHandlers) : Presenter<VaultListView>(exceptionMappings) {
private val getVaultListUseCase: GetVaultListUseCase, //
private val deleteVaultUseCase: DeleteVaultUseCase, //
private val renameVaultUseCase: RenameVaultUseCase, //
private val lockVaultUseCase: LockVaultUseCase, //
private val getDecryptedCloudForVaultUseCase: GetDecryptedCloudForVaultUseCase, //
private val getRootFolderUseCase: GetRootFolderUseCase, //
private val addExistingVaultWorkflow: AddExistingVaultWorkflow, //
private val createNewVaultWorkflow: CreateNewVaultWorkflow, //
private val saveVaultUseCase: SaveVaultUseCase, //
private val moveVaultPositionUseCase: MoveVaultPositionUseCase, //
private val licenseCheckUseCase: DoLicenseCheckUseCase, //
private val updateCheckUseCase: DoUpdateCheckUseCase, //
private val updateUseCase: DoUpdateUseCase, //
private val networkConnectionCheck: NetworkConnectionCheck, //
private val fileUtil: FileUtil, //
private val authenticationExceptionHandler: AuthenticationExceptionHandler, //
private val cloudFolderModelMapper: CloudFolderModelMapper, //
private val sharedPreferencesHandler: SharedPreferencesHandler, //
exceptionMappings: ExceptionHandlers
) : Presenter<VaultListView>(exceptionMappings) {
private var vaultAction: VaultAction? = null
@ -107,56 +108,56 @@ class VaultListPresenter @Inject constructor( //
private fun checkLicense() {
if (BuildConfig.FLAVOR == "apkstore" || BuildConfig.FLAVOR == "fdroid") {
licenseCheckUseCase //
.withLicense("") //
.run(object : NoOpResultHandler<LicenseCheck>() {
override fun onSuccess(licenseCheck: LicenseCheck) {
if (BuildConfig.FLAVOR == "apkstore" && sharedPreferencesHandler.doUpdate()) {
checkForAppUpdates()
}
.withLicense("") //
.run(object : NoOpResultHandler<LicenseCheck>() {
override fun onSuccess(licenseCheck: LicenseCheck) {
if (BuildConfig.FLAVOR == "apkstore" && sharedPreferencesHandler.doUpdate()) {
checkForAppUpdates()
}
}
override fun onError(e: Throwable) {
var license: String? = ""
if (e is LicenseNotValidException) {
license = e.license
}
val intent = Intent(context(), LicenseCheckActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
intent.data = Uri.parse(String.format("app://cryptomator/%s", license))
try {
context().startActivity(intent)
} catch (e: ActivityNotFoundException) {
Toast.makeText(context(), "Please contact the support.", Toast.LENGTH_LONG).show()
finish()
}
override fun onError(e: Throwable) {
var license: String? = ""
if (e is LicenseNotValidException) {
license = e.license
}
})
val intent = Intent(context(), LicenseCheckActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
intent.data = Uri.parse(String.format("app://cryptomator/%s", license))
try {
context().startActivity(intent)
} catch (e: ActivityNotFoundException) {
Toast.makeText(context(), "Please contact the support.", Toast.LENGTH_LONG).show()
finish()
}
}
})
}
}
private fun checkForAppUpdates() {
if (networkConnectionCheck.isPresent) {
updateCheckUseCase //
.withVersion(BuildConfig.VERSION_NAME) //
.run(object : NoOpResultHandler<Optional<UpdateCheck>>() {
override fun onSuccess(updateCheck: Optional<UpdateCheck>) {
if (updateCheck.isPresent) {
updateStatusRetrieved(updateCheck.get(), context())
} else {
Timber.tag("VaultListPresenter").i("UpdateCheck finished, latest version")
}
sharedPreferencesHandler.updateExecuted()
.withVersion(BuildConfig.VERSION_NAME) //
.run(object : NoOpResultHandler<Optional<UpdateCheck>>() {
override fun onSuccess(updateCheck: Optional<UpdateCheck>) {
if (updateCheck.isPresent) {
updateStatusRetrieved(updateCheck.get(), context())
} else {
Timber.tag("VaultListPresenter").i("UpdateCheck finished, latest version")
}
sharedPreferencesHandler.updateExecuted()
}
override fun onError(e: Throwable) {
if (e is SSLHandshakePreAndroid5UpdateCheckException) {
Timber.tag("SettingsPresenter").e(e, "Update check failed due to Android pre 5 and SSL Handshake not accepted")
} else {
showError(e)
}
override fun onError(e: Throwable) {
if (e is SSLHandshakePreAndroid5UpdateCheckException) {
Timber.tag("SettingsPresenter").e(e, "Update check failed due to Android pre 5 and SSL Handshake not accepted")
} else {
showError(e)
}
})
}
})
} else {
Timber.tag("VaultListPresenter").i("Update check not started due to no internal connection")
}
@ -193,32 +194,34 @@ class VaultListPresenter @Inject constructor( //
fun deleteVault(vaultModel: VaultModel) {
deleteVaultUseCase //
.withVault(vaultModel.toVault()) //
.run(object : DefaultResultHandler<Long>() {
override fun onSuccess(vaultId: Long) {
view?.deleteVaultFromAdapter(vaultId)
}
})
.withVault(vaultModel.toVault()) //
.run(object : DefaultResultHandler<Long>() {
override fun onSuccess(vaultId: Long) {
view?.deleteVaultFromAdapter(vaultId)
}
})
}
fun renameVault(vaultModel: VaultModel, newVaultName: String?) {
renameVaultUseCase //
.withVault(vaultModel.toVault()) //
.andNewVaultName(newVaultName) //
.run(object : DefaultResultHandler<Vault>() {
override fun onSuccess(vault: Vault) {
view?.renameVault(VaultModel(vault))
view?.closeDialog()
}
.withVault(vaultModel.toVault()) //
.andNewVaultName(newVaultName) //
.run(object : DefaultResultHandler<Vault>() {
override fun onSuccess(vault: Vault) {
view?.renameVault(VaultModel(vault))
view?.closeDialog()
}
override fun onError(e: Throwable) {
if (!authenticationExceptionHandler.handleAuthenticationException( //
this@VaultListPresenter, e, //
ActivityResultCallbacks.renameVaultAfterAuthentication(vaultModel.toVault(), newVaultName))) {
showError(e)
}
override fun onError(e: Throwable) {
if (!authenticationExceptionHandler.handleAuthenticationException( //
this@VaultListPresenter, e, //
ActivityResultCallbacks.renameVaultAfterAuthentication(vaultModel.toVault(), newVaultName)
)
) {
showError(e)
}
})
}
})
}
@Callback
@ -230,32 +233,32 @@ class VaultListPresenter @Inject constructor( //
private fun browseFilesOf(vault: VaultModel) {
getDecryptedCloudForVaultUseCase //
.withVault(vault.toVault()) //
.run(object : DefaultResultHandler<Cloud>() {
override fun onSuccess(cloud: Cloud) {
getRootFolderAndNavigateInto(cloud)
}
})
.withVault(vault.toVault()) //
.run(object : DefaultResultHandler<Cloud>() {
override fun onSuccess(cloud: Cloud) {
getRootFolderAndNavigateInto(cloud)
}
})
}
private fun getRootFolderAndNavigateInto(cloud: Cloud) {
getRootFolderUseCase //
.withCloud(cloud) //
.run(object : DefaultResultHandler<CloudFolder>() {
override fun onSuccess(folder: CloudFolder) {
navigateToVaultContent((folder.cloud as CryptoCloud).vault, folder)
}
})
.withCloud(cloud) //
.run(object : DefaultResultHandler<CloudFolder>() {
override fun onSuccess(folder: CloudFolder) {
navigateToVaultContent((folder.cloud as CryptoCloud).vault, folder)
}
})
}
private fun lockVault(vaultModel: VaultModel) {
lockVaultUseCase //
.withVault(vaultModel.toVault()) //
.run(object : DefaultResultHandler<Vault>() {
override fun onSuccess(vault: Vault) {
view?.addOrUpdateVault(VaultModel(vault))
}
})
.withVault(vaultModel.toVault()) //
.run(object : DefaultResultHandler<Vault>() {
override fun onSuccess(vault: Vault) {
view?.addOrUpdateVault(VaultModel(vault))
}
})
}
private val vaultList: Unit
@ -297,12 +300,12 @@ class VaultListPresenter @Inject constructor( //
onVaultWithoutCloudClickedAndLocked(vault)
} else {
lockVaultUseCase //
.withVault(vault.toVault()) //
.run(object : DefaultResultHandler<Vault>() {
override fun onSuccess(vault: Vault) {
onVaultWithoutCloudClickedAndLocked(VaultModel(vault))
}
})
.withVault(vault.toVault()) //
.run(object : DefaultResultHandler<Vault>() {
override fun onSuccess(vault: Vault) {
onVaultWithoutCloudClickedAndLocked(VaultModel(vault))
}
})
}
}
}
@ -310,11 +313,12 @@ class VaultListPresenter @Inject constructor( //
private fun onVaultWithoutCloudClickedAndLocked(vault: VaultModel) {
if (isWebdavOrLocal(vault.cloudType)) {
requestActivityResult( //
ActivityResultCallbacks.cloudConnectionForVaultSelected(vault), //
Intents.cloudConnectionListIntent() //
.withCloudType(vault.cloudType) //
.withDialogTitle(context().getString(R.string.screen_cloud_connections_title)) //
.withFinishOnCloudItemClick(true))
ActivityResultCallbacks.cloudConnectionForVaultSelected(vault), //
Intents.cloudConnectionListIntent() //
.withCloudType(vault.cloudType) //
.withDialogTitle(context().getString(R.string.screen_cloud_connections_title)) //
.withFinishOnCloudItemClick(true)
)
}
}
@ -326,16 +330,16 @@ class VaultListPresenter @Inject constructor( //
fun cloudConnectionForVaultSelected(result: ActivityResult, vaultModel: VaultModel) {
val cloud = result.intent().getSerializableExtra(CloudConnectionListPresenter.SELECTED_CLOUD) as Cloud
val vault = Vault.aCopyOf(vaultModel.toVault()) //
.withCloud(cloud) //
.build()
.withCloud(cloud) //
.build()
saveVaultUseCase //
.withVault(vault) //
.run(object : DefaultResultHandler<Vault>() {
override fun onSuccess(vault: Vault) {
view?.addOrUpdateVault(VaultModel(vault))
onCloudOfVaultAuthenticated(vault)
}
})
.withVault(vault) //
.run(object : DefaultResultHandler<Vault>() {
override fun onSuccess(vault: Vault) {
view?.addOrUpdateVault(VaultModel(vault))
onCloudOfVaultAuthenticated(vault)
}
})
}
private fun onCloudOfVaultAuthenticated(authenticatedVault: Vault) {
@ -352,8 +356,9 @@ class VaultListPresenter @Inject constructor( //
if (authenticatedVault.isLocked) {
if (!isPaused) {
requestActivityResult( //
ActivityResultCallbacks.vaultUnlockedVaultList(), //
Intents.unlockVaultIntent().withVaultModel(authenticatedVault).withVaultAction(UnlockVaultIntent.VaultAction.UNLOCK))
ActivityResultCallbacks.vaultUnlockedVaultList(), //
Intents.unlockVaultIntent().withVaultModel(authenticatedVault).withVaultAction(UnlockVaultIntent.VaultAction.UNLOCK)
)
}
} else {
browseFilesOf(authenticatedVault)
@ -371,18 +376,18 @@ class VaultListPresenter @Inject constructor( //
private fun navigateToVaultContent(cloud: Cloud) {
getRootFolderUseCase //
.withCloud(cloud) //
.run(object : DefaultResultHandler<CloudFolder>() {
override fun onSuccess(folder: CloudFolder) {
val vault = (folder.cloud as CryptoCloud).vault
view?.addOrUpdateVault(VaultModel(vault))
navigateToVaultContent(vault, folder)
view?.showProgress(ProgressModel.COMPLETED)
if (checkToStartAutoImageUpload(vault)) {
context().startService(AutoUploadService.startAutoUploadIntent(context(), folder.cloud))
}
.withCloud(cloud) //
.run(object : DefaultResultHandler<CloudFolder>() {
override fun onSuccess(folder: CloudFolder) {
val vault = (folder.cloud as CryptoCloud).vault
view?.addOrUpdateVault(VaultModel(vault))
navigateToVaultContent(vault, folder)
view?.showProgress(ProgressModel.COMPLETED)
if (checkToStartAutoImageUpload(vault)) {
context().startService(AutoUploadService.startAutoUploadIntent(context(), folder.cloud))
}
})
}
})
}
private fun checkToStartAutoImageUpload(vault: Vault): Boolean {
@ -407,10 +412,10 @@ class VaultListPresenter @Inject constructor( //
fun onChangePasswordClicked(vaultModel: VaultModel) {
Intents
.unlockVaultIntent()
.withVaultModel(vaultModel)
.withVaultAction(UnlockVaultIntent.VaultAction.CHANGE_PASSWORD)
.startActivity(this)
.unlockVaultIntent()
.withVaultModel(vaultModel)
.withVaultAction(UnlockVaultIntent.VaultAction.CHANGE_PASSWORD)
.startActivity(this)
}
fun onVaultSettingsClicked(vaultModel: VaultModel) {
@ -446,17 +451,17 @@ class VaultListPresenter @Inject constructor( //
fun onVaultMoved(fromPosition: Int, toPosition: Int) {
moveVaultPositionUseCase
.withFromPosition(fromPosition) //
.andToPosition(toPosition) //
.run(object : DefaultResultHandler<List<Vault>>() {
override fun onSuccess(vaults: List<Vault>) {
view?.vaultMoved(vaults.mapTo(ArrayList()) { VaultModel(it) })
}
.withFromPosition(fromPosition) //
.andToPosition(toPosition) //
.run(object : DefaultResultHandler<List<Vault>>() {
override fun onSuccess(vaults: List<Vault>) {
view?.vaultMoved(vaults.mapTo(ArrayList()) { VaultModel(it) })
}
override fun onError(e: Throwable) {
Timber.tag("VaultListPresenter").e(e, "Failed to execute MoveVaultUseCase")
}
})
override fun onError(e: Throwable) {
Timber.tag("VaultListPresenter").e(e, "Failed to execute MoveVaultUseCase")
}
})
}
private enum class VaultAction {
@ -468,33 +473,34 @@ class VaultListPresenter @Inject constructor( //
val uri = fileUtil.contentUriForNewTempFile("cryptomator.apk")
val file = fileUtil.tempFile("cryptomator.apk")
updateUseCase //
.withFile(file) //
.run(object : NoOpResultHandler<Void?>() {
override fun onError(e: Throwable) {
showError(e)
}
.withFile(file) //
.run(object : NoOpResultHandler<Void?>() {
override fun onError(e: Throwable) {
showError(e)
}
override fun onSuccess(aVoid: Void?) {
super.onSuccess(aVoid)
val intent = Intent(Intent.ACTION_VIEW)
intent.setDataAndType(uri, "application/vnd.android.package-archive")
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
context().startActivity(intent)
}
})
override fun onSuccess(aVoid: Void?) {
super.onSuccess(aVoid)
val intent = Intent(Intent.ACTION_VIEW)
intent.setDataAndType(uri, "application/vnd.android.package-archive")
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
context().startActivity(intent)
}
})
}
init {
unsubscribeOnDestroy( //
deleteVaultUseCase, //
renameVaultUseCase, //
lockVaultUseCase, //
getVaultListUseCase, //
saveVaultUseCase, //
moveVaultPositionUseCase, //
licenseCheckUseCase, //
updateCheckUseCase, //
updateUseCase)
deleteVaultUseCase, //
renameVaultUseCase, //
lockVaultUseCase, //
getVaultListUseCase, //
saveVaultUseCase, //
moveVaultPositionUseCase, //
licenseCheckUseCase, //
updateCheckUseCase, //
updateUseCase
)
}
}

View File

@ -21,10 +21,11 @@ import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
@PerView
class WebDavAddOrChangePresenter @Inject internal constructor( //
private val addOrChangeCloudConnectionUseCase: AddOrChangeCloudConnectionUseCase, //
private val connectToWebDavUseCase: ConnectToWebDavUseCase, //
private val authenticationExceptionHandler: AuthenticationExceptionHandler, //
exceptionMappings: ExceptionHandlers) : Presenter<WebDavAddOrChangeView>(exceptionMappings) {
private val addOrChangeCloudConnectionUseCase: AddOrChangeCloudConnectionUseCase, //
private val connectToWebDavUseCase: ConnectToWebDavUseCase, //
private val authenticationExceptionHandler: AuthenticationExceptionHandler, //
exceptionMappings: ExceptionHandlers
) : Presenter<WebDavAddOrChangeView>(exceptionMappings) {
fun checkUserInput(urlPort: String, username: String, password: String, cloudId: Long?, certificate: String?) {
var statusMessage: String? = null
@ -55,8 +56,8 @@ class WebDavAddOrChangePresenter @Inject internal constructor( //
private fun encryptPassword(password: String): String {
return CredentialCryptor //
.getInstance(context()) //
.encrypt(password)
.getInstance(context()) //
.encrypt(password)
}
private fun isValid(urlPort: String): Boolean {
@ -65,10 +66,10 @@ class WebDavAddOrChangePresenter @Inject internal constructor( //
private fun mapToCloud(username: String, password: String, hostPort: String, id: Long?, certificate: String?): WebDavCloud {
var builder = WebDavCloud //
.aWebDavCloudCloud() //
.withUrl(hostPort) //
.withUsername(username) //
.withPassword(password)
.aWebDavCloudCloud() //
.withUrl(hostPort) //
.withUsername(username) //
.withPassword(password)
if (id != null) {
builder = builder.withId(id)
@ -88,19 +89,19 @@ class WebDavAddOrChangePresenter @Inject internal constructor( //
private fun authenticate(cloud: WebDavCloud) {
view?.showProgress(ProgressModel(ProgressStateModel.AUTHENTICATION))
connectToWebDavUseCase //
.withCloud(cloud) //
.run(object : DefaultResultHandler<Void?>() {
override fun onSuccess(void: Void?) {
onCloudAuthenticated(cloud)
}
.withCloud(cloud) //
.run(object : DefaultResultHandler<Void?>() {
override fun onSuccess(void: Void?) {
onCloudAuthenticated(cloud)
}
override fun onError(e: Throwable) {
view?.showProgress(ProgressModel.COMPLETED)
if (!authenticationExceptionHandler.handleAuthenticationException(this@WebDavAddOrChangePresenter, e, ActivityResultCallbacks.handledAuthenticationWebDavCloud())) {
super.onError(e)
}
override fun onError(e: Throwable) {
view?.showProgress(ProgressModel.COMPLETED)
if (!authenticationExceptionHandler.handleAuthenticationException(this@WebDavAddOrChangePresenter, e, ActivityResultCallbacks.handledAuthenticationWebDavCloud())) {
super.onError(e)
}
})
}
})
}
@Callback
@ -117,8 +118,8 @@ class WebDavAddOrChangePresenter @Inject internal constructor( //
private fun save(cloud: Cloud) {
addOrChangeCloudConnectionUseCase //
.withCloud(cloud) //
.run(DefaultResultHandler())
.withCloud(cloud) //
.run(DefaultResultHandler())
}
init {

View File

@ -29,26 +29,27 @@ class AutoUploadNotification(private val context: Context, private val amountOfP
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
val notificationChannel = NotificationChannel( //
NOTIFICATION_CHANNEL_ID, //
NOTIFICATION_CHANNEL_NAME, //
IMPORTANCE_LOW)
NOTIFICATION_CHANNEL_ID, //
NOTIFICATION_CHANNEL_NAME, //
IMPORTANCE_LOW
)
notificationManager?.createNotificationChannel(notificationChannel)
}
this.builder = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) //
.setContentTitle(context.getString(R.string.notification_auto_upload_title)) //
.setSmallIcon(R.drawable.background_splash_cryptomator) //
.setColor(getColor(R.color.colorPrimary)) //
.addAction(cancelNowAction())
.setGroup(NOTIFICATION_GROUP_KEY)
.setOngoing(true)
.setContentTitle(context.getString(R.string.notification_auto_upload_title)) //
.setSmallIcon(R.drawable.background_splash_cryptomator) //
.setColor(getColor(R.color.colorPrimary)) //
.addAction(cancelNowAction())
.setGroup(NOTIFICATION_GROUP_KEY)
.setOngoing(true)
}
private fun cancelNowAction(): NotificationCompat.Action {
return NotificationCompat.Action.Builder( //
R.drawable.ic_lock, //
getString(R.string.notification_cancel_auto_upload), //
cancelNowIntent() //
R.drawable.ic_lock, //
getString(R.string.notification_cancel_auto_upload), //
cancelNowIntent() //
).build()
}
@ -67,11 +68,14 @@ class AutoUploadNotification(private val context: Context, private val amountOfP
fun update(progress: Int) {
builder.setContentIntent(startTheActivity())
builder //
.setContentText( //
String.format(context.getString(R.string.notification_auto_upload_message), //
alreadyUploadedPictures + 1, //
amountOfPictures)) //
.setProgress(100, progress, false)
.setContentText( //
String.format(
context.getString(R.string.notification_auto_upload_message), //
alreadyUploadedPictures + 1, //
amountOfPictures
)
) //
.setProgress(100, progress, false)
show()
}
@ -95,24 +99,24 @@ class AutoUploadNotification(private val context: Context, private val amountOfP
private fun showErrorWithMessage(message: String) {
builder.setContentIntent(startTheActivity())
builder //
.setContentTitle(context.getString(R.string.notification_auto_upload_failed_title))
.setContentText(message) //
.setProgress(0, 0, false)
.setAutoCancel(true)
.setOngoing(false)
.mActions.clear()
.setContentTitle(context.getString(R.string.notification_auto_upload_failed_title))
.setContentText(message) //
.setProgress(0, 0, false)
.setAutoCancel(true)
.setOngoing(false)
.mActions.clear()
show()
}
fun showUploadFinished(size: Int) {
builder.setContentIntent(startTheActivity())
builder //
.setContentTitle(context.getString(R.string.notification_auto_upload_finished_title))
.setContentText(format(context.getString(R.string.notification_auto_upload_finished_message), size)) //
.setProgress(0, 0, false)
.setAutoCancel(true)
.setOngoing(false)
.mActions.clear()
.setContentTitle(context.getString(R.string.notification_auto_upload_finished_title))
.setContentText(format(context.getString(R.string.notification_auto_upload_finished_message), size)) //
.setProgress(0, 0, false)
.setAutoCancel(true)
.setOngoing(false)
.mActions.clear()
show()
}

View File

@ -26,27 +26,28 @@ class OpenWritableFileNotification(private val context: Context, private val uri
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
val notificationChannel = NotificationChannel( //
NOTIFICATION_CHANNEL_ID, //
NOTIFICATION_CHANNEL_NAME, //
IMPORTANCE_LOW)
NOTIFICATION_CHANNEL_ID, //
NOTIFICATION_CHANNEL_NAME, //
IMPORTANCE_LOW
)
notificationManager?.createNotificationChannel(notificationChannel)
}
this.builder = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) //
.setContentTitle(context.getString(R.string.notification_open_writable_file_title)) //
.setContentText(context.getString(R.string.notification_open_writable_file_message)) //
.setSmallIcon(R.drawable.background_splash_cryptomator) //
.setColor(getColor(R.color.colorPrimary)) //
.setGroup(NOTIFICATION_GROUP_KEY)
.setOngoing(true)
.addAction(cancelNowAction())
.setContentTitle(context.getString(R.string.notification_open_writable_file_title)) //
.setContentText(context.getString(R.string.notification_open_writable_file_message)) //
.setSmallIcon(R.drawable.background_splash_cryptomator) //
.setColor(getColor(R.color.colorPrimary)) //
.setGroup(NOTIFICATION_GROUP_KEY)
.setOngoing(true)
.addAction(cancelNowAction())
}
private fun cancelNowAction(): NotificationCompat.Action {
return NotificationCompat.Action.Builder( //
R.drawable.ic_lock, //
ResourceHelper.getString(R.string.notification_cancel_open_writable_file), //
cancelNowIntent() //
R.drawable.ic_lock, //
ResourceHelper.getString(R.string.notification_cancel_open_writable_file), //
cancelNowIntent() //
).build()
}

View File

@ -75,12 +75,16 @@ class PhotoContentJob : JobService() {
private fun getContentResolvers(ids: Set<String>): Array<Cursor?> {
val selection = buildSelection(ids)
var resolvers = arrayOf(contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, PROJECTION_IMAGES, selection, null, null),
contentResolver.query(MediaStore.Images.Media.INTERNAL_CONTENT_URI, PROJECTION_IMAGES, selection, null, null))
var resolvers = arrayOf(
contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, PROJECTION_IMAGES, selection, null, null),
contentResolver.query(MediaStore.Images.Media.INTERNAL_CONTENT_URI, PROJECTION_IMAGES, selection, null, null)
)
if (SharedPreferencesHandler(applicationContext).autoPhotoUploadIncludingVideos()) {
resolvers += arrayOf(contentResolver.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, PROJECTION_VIDEOS, selection, null, null),
contentResolver.query(MediaStore.Video.Media.INTERNAL_CONTENT_URI, PROJECTION_VIDEOS, selection, null, null))
resolvers += arrayOf(
contentResolver.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, PROJECTION_VIDEOS, selection, null, null),
contentResolver.query(MediaStore.Video.Media.INTERNAL_CONTENT_URI, PROJECTION_VIDEOS, selection, null, null)
)
}
return resolvers
@ -88,14 +92,14 @@ class PhotoContentJob : JobService() {
private fun getIds(params: JobParameters): Set<String>? {
return params.triggeredContentUris
?.map { it.pathSegments }
?.filter {
it != null && (it.size == MediaStore.Images.Media.EXTERNAL_CONTENT_URI.pathSegments.size + 1
|| it.size == MediaStore.Video.Media.EXTERNAL_CONTENT_URI.pathSegments.size + 1
|| it.size == MediaStore.Images.Media.INTERNAL_CONTENT_URI.pathSegments.size + 1
|| it.size == MediaStore.Video.Media.INTERNAL_CONTENT_URI.pathSegments.size + 1)
}
?.mapTo(HashSet()) { it[it.size - 1] }
?.map { it.pathSegments }
?.filter {
it != null && (it.size == MediaStore.Images.Media.EXTERNAL_CONTENT_URI.pathSegments.size + 1
|| it.size == MediaStore.Video.Media.EXTERNAL_CONTENT_URI.pathSegments.size + 1
|| it.size == MediaStore.Images.Media.INTERNAL_CONTENT_URI.pathSegments.size + 1
|| it.size == MediaStore.Video.Media.INTERNAL_CONTENT_URI.pathSegments.size + 1)
}
?.mapTo(HashSet()) { it[it.size - 1] }
}
private fun buildSelection(ids: Set<String>): String {

View File

@ -15,8 +15,8 @@ import javax.inject.Inject
@Activity(layout = R.layout.activity_empty)
class AuthenticateCloudActivity : BaseActivity(),
AuthenticateCloudView,
AssignSslCertificateDialog.Callback {
AuthenticateCloudView,
AssignSslCertificateDialog.Callback {
@Inject
lateinit var presenter: AuthenticateCloudPresenter

View File

@ -14,8 +14,8 @@ import kotlinx.android.synthetic.main.toolbar_layout.toolbar
@Activity
class AutoUploadChooseVaultActivity : BaseActivity(), //
AutoUploadChooseVaultView, //
NotEnoughVaultsDialog.Callback {
AutoUploadChooseVaultView, //
NotEnoughVaultsDialog.Callback {
@Inject
lateinit var presenter: AutoUploadChooseVaultPresenter
@ -42,9 +42,9 @@ class AutoUploadChooseVaultActivity : BaseActivity(), //
override fun displayDialogUnableToUploadFiles() {
NotEnoughVaultsDialog //
.withContext(this) //
.andTitle(getString(R.string.dialog_unable_to_auto_upload_files_title)) //
.show()
.withContext(this) //
.andTitle(getString(R.string.dialog_unable_to_auto_upload_files_title)) //
.show()
}
override fun onNotEnoughVaultsOkClicked() {

View File

@ -162,9 +162,9 @@ abstract class BaseActivity : AppCompatActivity(), View, ActivityCompat.OnReques
private fun initializeDagger(): ActivityComponent {
val activityComponent = DaggerActivityComponent.builder()
.applicationComponent(applicationComponent)
.activityModule(ActivityModule(this))
.build()
.applicationComponent(applicationComponent)
.activityModule(ActivityModule(this))
.build()
Activities.inject(activityComponent, this)
return activityComponent
}
@ -316,7 +316,7 @@ abstract class BaseActivity : AppCompatActivity(), View, ActivityCompat.OnReques
internal open fun snackbarView(): android.view.View {
return activity().findViewById(R.id.locationsRecyclerView) as android.view.View?
?: return activity().findViewById(R.id.coordinatorLayout)
?: return activity().findViewById(R.id.coordinatorLayout)
}
internal fun getCurrentFragment(fragmentContainer: Int): Fragment? = supportFragmentManager.findFragmentById(fragmentContainer)
@ -374,10 +374,11 @@ abstract class BaseActivity : AppCompatActivity(), View, ActivityCompat.OnReques
}
internal enum class FragmentAnimation constructor(
val enter: Int,
val exit: Int,
val popEnter: Int,
val popExit: Int) {
val enter: Int,
val exit: Int,
val popEnter: Int,
val popExit: Int
) {
NAVIGATE_IN_TO_FOLDER(R.animator.enter_from_right, R.animator.exit_to_left, R.animator.enter_from_left, R.animator.exit_to_right), //
NAVIGATE_OUT_OF_FOLDER(R.animator.enter_from_left, R.animator.exit_to_right, R.animator.enter_from_right, R.animator.exit_to_left)

View File

@ -14,8 +14,8 @@ import kotlinx.android.synthetic.main.toolbar_layout.toolbar
@Activity
class BiometricAuthSettingsActivity : BaseActivity(), //
BiometricAuthSettingsView, //
EnrollSystemBiometricDialog.Callback {
BiometricAuthSettingsView, //
EnrollSystemBiometricDialog.Callback {
@Inject
lateinit var presenter: BiometricAuthSettingsPresenter
@ -29,8 +29,8 @@ class BiometricAuthSettingsActivity : BaseActivity(), //
override fun showSetupBiometricAuthDialog() {
val biometricAuthenticationAvailable = BiometricManager //
.from(context()) //
.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG)
.from(context()) //
.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG)
if (biometricAuthenticationAvailable == BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED) {
showDialog(EnrollSystemBiometricDialog.newInstance())
}

View File

@ -51,17 +51,17 @@ import kotlinx.android.synthetic.main.toolbar_layout.toolbar
@Activity
class BrowseFilesActivity : BaseActivity(), //
BrowseFilesView, //
BrowseFilesCallback, //
ReplaceDialog.Callback, //
FileNameDialog.Callback, //
ConfirmDeleteCloudNodeDialog.Callback, //
UploadCloudFileDialog.Callback,
ExportCloudFilesDialog.Callback,
SymLinkDialog.CallBack,
NoDirFileDialog.CallBack,
SearchView.OnQueryTextListener,
SearchView.OnCloseListener {
BrowseFilesView, //
BrowseFilesCallback, //
ReplaceDialog.Callback, //
FileNameDialog.Callback, //
ConfirmDeleteCloudNodeDialog.Callback, //
UploadCloudFileDialog.Callback,
ExportCloudFilesDialog.Callback,
SymLinkDialog.CallBack,
NoDirFileDialog.CallBack,
SearchView.OnQueryTextListener,
SearchView.OnCloseListener {
@Inject
lateinit var browseFilesPresenter: BrowseFilesPresenter
@ -97,8 +97,10 @@ class BrowseFilesActivity : BaseActivity(), //
get() = browseFilesFragment().folder
override fun createFragment(): Fragment =
BrowseFilesFragment.newInstance(browseFilesIntent.folder(),
browseFilesIntent.chooseCloudNodeSettings())
BrowseFilesFragment.newInstance(
browseFilesIntent.folder(),
browseFilesIntent.chooseCloudNodeSettings()
)
override fun onBackPressed() {
browseFilesPresenter.onBackPressed()
@ -121,7 +123,7 @@ class BrowseFilesActivity : BaseActivity(), //
private fun isNavigationMode(navigationMode: ChooseCloudNodeSettings.NavigationMode): Boolean = this.navigationMode == navigationMode
private fun hasCloudNodeSettings(): Boolean =
browseFilesIntent.chooseCloudNodeSettings() != null
browseFilesIntent.chooseCloudNodeSettings() != null
override fun getCustomMenuResource(): Int {
return when {
@ -160,14 +162,17 @@ class BrowseFilesActivity : BaseActivity(), //
true
}
R.id.action_move_items -> {
browseFilesPresenter.onMoveNodesClicked(folder, //
browseFilesFragment().selectedCloudNodes as ArrayList<CloudNodeModel<*>>)
browseFilesPresenter.onMoveNodesClicked(
folder, //
browseFilesFragment().selectedCloudNodes as ArrayList<CloudNodeModel<*>>
)
true
}
R.id.action_export_items -> {
browseFilesPresenter.onExportNodesClicked( //
browseFilesFragment().selectedCloudNodes as ArrayList<CloudNodeModel<*>>, //
BrowseFilesPresenter.EXPORT_TRIGGERED_BY_USER)
browseFilesFragment().selectedCloudNodes as ArrayList<CloudNodeModel<*>>, //
BrowseFilesPresenter.EXPORT_TRIGGERED_BY_USER
)
true
}
R.id.action_share_items -> {
@ -398,14 +403,18 @@ class BrowseFilesActivity : BaseActivity(), //
}
override fun navigateTo(folder: CloudFolderModel) {
replaceFragment(BrowseFilesFragment.newInstance(folder,
browseFilesIntent.chooseCloudNodeSettings()),
FragmentAnimation.NAVIGATE_IN_TO_FOLDER)
replaceFragment(
BrowseFilesFragment.newInstance(
folder,
browseFilesIntent.chooseCloudNodeSettings()
),
FragmentAnimation.NAVIGATE_IN_TO_FOLDER
)
}
override fun showAddContentDialog() {
VaultContentActionBottomSheet.newInstance(browseFilesFragment().folder)
.show(supportFragmentManager, "AddContentDialog")
.show(supportFragmentManager, "AddContentDialog")
}
override fun updateTitle(folder: CloudFolderModel) {
@ -484,10 +493,14 @@ class BrowseFilesActivity : BaseActivity(), //
}
private fun createBackStackFor(sourceParent: CloudFolderModel) {
replaceFragment(BrowseFilesFragment.newInstance(sourceParent,
browseFilesIntent.chooseCloudNodeSettings()),
FragmentAnimation.NAVIGATE_OUT_OF_FOLDER,
false)
replaceFragment(
BrowseFilesFragment.newInstance(
sourceParent,
browseFilesIntent.chooseCloudNodeSettings()
),
FragmentAnimation.NAVIGATE_OUT_OF_FOLDER,
false
)
}
override fun onRenameCloudNodeClicked(cloudNodeModel: CloudNodeModel<*>, newCloudNodeName: String) {

View File

@ -18,9 +18,9 @@ import kotlinx.android.synthetic.main.toolbar_layout.toolbar
@Activity
class CloudConnectionListActivity : BaseActivity(),
CloudConnectionListView,
CloudConnectionSettingsBottomSheet.Callback,
DeleteCloudConnectionWithVaultsDialog.Callback {
CloudConnectionListView,
CloudConnectionSettingsBottomSheet.Callback,
DeleteCloudConnectionWithVaultsDialog.Callback {
@Inject
lateinit var presenter: CloudConnectionListPresenter
@ -55,7 +55,7 @@ class CloudConnectionListActivity : BaseActivity(),
override fun showNodeSettings(cloudModel: CloudModel) {
val cloudNodeSettingDialog = //
CloudConnectionSettingsBottomSheet.newInstance(cloudModel)
CloudConnectionSettingsBottomSheet.newInstance(cloudModel)
cloudNodeSettingDialog.show(supportFragmentManager, "CloudNodeSettings")
}

View File

@ -24,14 +24,16 @@ class EmptyDirIdFileInfoActivity : BaseActivity(), EmptyDirFileView {
}
private fun setupToolbar() {
toolbar.title = getString(R.string.screen_empty_dir_file_info_title,
emptyDirIdFileInfoIntent.dirName())
toolbar.title = getString(
R.string.screen_empty_dir_file_info_title,
emptyDirIdFileInfoIntent.dirName()
)
setSupportActionBar(toolbar)
}
override fun onResume() {
super.onResume()
(supportFragmentManager.findFragmentByTag("EmptyDirIdFileInfoFragment") as EmptyDirIdFileInfoFragment)
.setDirFilePath(emptyDirIdFileInfoIntent.dirFilePath())
.setDirFilePath(emptyDirIdFileInfoIntent.dirFilePath())
}
}

View File

@ -180,10 +180,10 @@ class ImagePreviewActivity : BaseActivity(), ImagePreviewView, ConfirmDeleteClou
private fun fragmentFor(imagePreviewFile: ImagePreviewFile): Optional<ImagePreviewFragment> {
return supportFragmentManager.fragments
.map { it as ImagePreviewFragment }
.firstOrNull { it.imagePreviewFile() == imagePreviewFile }
?.let { Optional.of(it) }
?: Optional.empty()
.map { it as ImagePreviewFragment }
.firstOrNull { it.imagePreviewFile() == imagePreviewFile }
?.let { Optional.of(it) }
?: Optional.empty()
}
override fun hideProgressBar(imagePreviewFile: ImagePreviewFile) {

View File

@ -63,7 +63,7 @@ class LicenseCheckActivity : BaseActivity(), UpdateLicenseDialog.Callback, Licen
override fun licenseConfirmationClicked() {
vaultListIntent() //
.preventGoingBackInHistory() //
.startActivity(this) //
.preventGoingBackInHistory() //
.startActivity(this) //
}
}

View File

@ -19,12 +19,12 @@ import kotlinx.android.synthetic.main.toolbar_layout.toolbar
@Activity(layout = R.layout.activity_settings)
class SettingsActivity : BaseActivity(),
SettingsView,
DebugModeDisclaimerDialog.Callback,
DisableAppWhenObscuredDisclaimerDialog.Callback,
DisableSecureScreenDisclaimerDialog.Callback,
UpdateAppAvailableDialog.Callback, //
UpdateAppDialog.Callback {
SettingsView,
DebugModeDisclaimerDialog.Callback,
DisableAppWhenObscuredDisclaimerDialog.Callback,
DisableSecureScreenDisclaimerDialog.Callback,
UpdateAppAvailableDialog.Callback, //
UpdateAppDialog.Callback {
@Inject
lateinit var presenter: SettingsPresenter

View File

@ -26,10 +26,10 @@ import timber.log.Timber
@Activity
class SharedFilesActivity : BaseActivity(), //
SharedFilesView, //
ReplaceDialog.Callback, //
NotEnoughVaultsDialog.Callback, //
UploadCloudFileDialog.Callback {
SharedFilesView, //
ReplaceDialog.Callback, //
NotEnoughVaultsDialog.Callback, //
UploadCloudFileDialog.Callback {
@Inject
lateinit var presenter: SharedFilesPresenter
@ -92,8 +92,8 @@ class SharedFilesActivity : BaseActivity(), //
val uriList = ArrayList<Uri>(clipData.itemCount)
(0 until clipData.itemCount).forEach { i ->
clipData.getItemAt(i).uri
?.let { uriList.add(it) }
?: Timber.tag("Sharing").i("Item %d without uri", i)
?.let { uriList.add(it) }
?: Timber.tag("Sharing").i("Item %d without uri", i)
}
return uriList
}
@ -173,10 +173,10 @@ class SharedFilesActivity : BaseActivity(), //
override fun onNotEnoughVaultsCreateVaultClicked() {
packageManager.getLaunchIntentForPackage(packageName)
?.let {
it.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(it)
}
?.let {
it.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(it)
}
finish()
}

View File

@ -17,9 +17,9 @@ import kotlinx.android.synthetic.main.toolbar_layout.toolbar
@Activity
class TextEditorActivity : BaseActivity(),
TextEditorView,
UnsavedChangesDialog.Callback,
SearchView.OnQueryTextListener {
TextEditorView,
UnsavedChangesDialog.Callback,
SearchView.OnQueryTextListener {
@Inject
lateinit var textEditorPresenter: TextEditorPresenter
@ -45,18 +45,18 @@ class TextEditorActivity : BaseActivity(),
super.onCreateOptionsMenu(menu)
menu.findItem(R.id.action_search)
.setOnActionExpandListener(object : MenuItem.OnActionExpandListener {
override fun onMenuItemActionExpand(item: MenuItem?): Boolean {
menu.findItem(R.id.action_search_previous).isVisible = true
menu.findItem(R.id.action_search_next).isVisible = true
return true
}
.setOnActionExpandListener(object : MenuItem.OnActionExpandListener {
override fun onMenuItemActionExpand(item: MenuItem?): Boolean {
menu.findItem(R.id.action_search_previous).isVisible = true
menu.findItem(R.id.action_search_next).isVisible = true
return true
}
override fun onMenuItemActionCollapse(item: MenuItem?): Boolean {
invalidateOptionsMenu()
return true
}
})
override fun onMenuItemActionCollapse(item: MenuItem?): Boolean {
invalidateOptionsMenu()
return true
}
})
return true
}

View File

@ -21,10 +21,10 @@ import javax.inject.Inject
@Activity(layout = R.layout.activity_unlock_vault)
class UnlockVaultActivity : BaseActivity(), //
UnlockVaultView, //
BiometricAuthentication.Callback,
ChangePasswordDialog.Callback,
VaultNotFoundDialog.Callback {
UnlockVaultView, //
BiometricAuthentication.Callback,
ChangePasswordDialog.Callback,
VaultNotFoundDialog.Callback {
@Inject
lateinit var presenter: UnlockVaultPresenter
@ -84,7 +84,7 @@ class UnlockVaultActivity : BaseActivity(), //
override fun onBiometricAuthenticationFailed(vault: VaultModel) {
val vaultWithoutPassword = Vault.aCopyOf(vault.toVault()).withSavedPassword(null).build()
when(unlockVaultIntent.vaultAction()) {
when (unlockVaultIntent.vaultAction()) {
UnlockVaultIntent.VaultAction.CHANGE_PASSWORD -> presenter.saveVaultAfterChangePasswordButFailedBiometricAuth(vaultWithoutPassword)
else -> {
if (!presenter.startedUsingPrepareUnlock()) {
@ -100,7 +100,7 @@ class UnlockVaultActivity : BaseActivity(), //
}
private fun unlockVaultFragment(): UnlockVaultFragment = //
getCurrentFragment(R.id.fragmentContainer) as UnlockVaultFragment
getCurrentFragment(R.id.fragmentContainer) as UnlockVaultFragment
override fun showChangePasswordDialog(vaultModel: VaultModel, unverifiedVaultConfig: UnverifiedVaultConfig?) {
showDialog(ChangePasswordDialog.newInstance(vaultModel, unverifiedVaultConfig))

View File

@ -35,12 +35,12 @@ import kotlinx.android.synthetic.main.toolbar_layout.toolbar
@Activity(layout = R.layout.activity_layout_obscure_aware)
class VaultListActivity : BaseActivity(), //
VaultListView, //
VaultListCallback, //
AskForLockScreenDialog.Callback, //
UpdateAppAvailableDialog.Callback, //
UpdateAppDialog.Callback, //
BetaConfirmationDialog.Callback {
VaultListView, //
VaultListCallback, //
AskForLockScreenDialog.Callback, //
UpdateAppAvailableDialog.Callback, //
UpdateAppDialog.Callback, //
BetaConfirmationDialog.Callback {
@Inject
lateinit var vaultListPresenter: VaultListPresenter
@ -122,7 +122,7 @@ class VaultListActivity : BaseActivity(), //
override fun showVaultSettingsDialog(vaultModel: VaultModel) {
val vaultSettingDialog = //
SettingsVaultBottomSheet.newInstance(vaultModel)
SettingsVaultBottomSheet.newInstance(vaultModel)
vaultSettingDialog.show(supportFragmentManager, "VaultSettings")
}
@ -164,7 +164,7 @@ class VaultListActivity : BaseActivity(), //
override fun onDeleteVaultClick(vaultModel: VaultModel) {
VaultDeleteConfirmationDialog.newInstance(vaultModel) //
.show(supportFragmentManager, "VaultDeleteConfirmationDialog")
.show(supportFragmentManager, "VaultDeleteConfirmationDialog")
}
override fun onRenameVaultClick(vaultModel: VaultModel) {
@ -192,7 +192,7 @@ class VaultListActivity : BaseActivity(), //
}
private fun vaultListFragment(): VaultListFragment = //
getCurrentFragment(R.id.fragmentContainer) as VaultListFragment
getCurrentFragment(R.id.fragmentContainer) as VaultListFragment
override fun onUpdateAppDialogLoaded() {
showProgress(ProgressModel.GENERIC)

View File

@ -17,8 +17,8 @@ import kotlinx.android.synthetic.main.toolbar_layout.toolbar
@Activity
class WebDavAddOrChangeActivity : BaseActivity(),
WebDavAddOrChangeView,
WebDavAskForHttpDialog.Callback {
WebDavAddOrChangeView,
WebDavAskForHttpDialog.Callback {
@Inject
lateinit var webDavAddOrChangePresenter: WebDavAddOrChangePresenter

View File

@ -45,10 +45,12 @@ import kotlinx.android.synthetic.main.view_cloud_folder_content.view.cloudFolder
import kotlinx.android.synthetic.main.view_cloud_folder_content.view.cloudFolderText
class BrowseFilesAdapter @Inject
constructor(private val dateHelper: DateHelper, //
private val fileSizeHelper: FileSizeHelper, //
private val fileUtil: FileUtil, //
private val sharedPreferencesHandler: SharedPreferencesHandler) : RecyclerViewBaseAdapter<CloudNodeModel<*>, BrowseFilesAdapter.ItemClickListener, VaultContentViewHolder>(CloudNodeModelNameAZComparator()), FastScrollRecyclerView.SectionedAdapter {
constructor(
private val dateHelper: DateHelper, //
private val fileSizeHelper: FileSizeHelper, //
private val fileUtil: FileUtil, //
private val sharedPreferencesHandler: SharedPreferencesHandler
) : RecyclerViewBaseAdapter<CloudNodeModel<*>, BrowseFilesAdapter.ItemClickListener, VaultContentViewHolder>(CloudNodeModelNameAZComparator()), FastScrollRecyclerView.SectionedAdapter {
private var chooseCloudNodeSettings: ChooseCloudNodeSettings? = null
private var navigationMode: ChooseCloudNodeSettings.NavigationMode? = null

View File

@ -7,4 +7,5 @@ import org.cryptomator.presentation.ui.dialog.CloudNodeRenameDialog
import org.cryptomator.presentation.ui.dialog.CreateFolderDialog
import org.cryptomator.presentation.ui.dialog.FileTypeNotSupportedDialog
interface BrowseFilesCallback : CreateFolderDialog.Callback, VaultContentActionBottomSheet.Callback, FileSettingsBottomSheet.Callback, FolderSettingsBottomSheet.Callback, CloudNodeRenameDialog.Callback, FileTypeNotSupportedDialog.Callback
interface BrowseFilesCallback : CreateFolderDialog.Callback, VaultContentActionBottomSheet.Callback, FileSettingsBottomSheet.Callback, FolderSettingsBottomSheet.Callback, CloudNodeRenameDialog.Callback,
FileTypeNotSupportedDialog.Callback

View File

@ -7,6 +7,6 @@ import org.cryptomator.presentation.ui.dialog.VaultRenameDialog
// FIXME delete this file and add this interfaces to VaultListView.kt
interface VaultListCallback : AddVaultBottomSheet.Callback, //
SettingsVaultBottomSheet.Callback, //
VaultDeleteConfirmationDialog.Callback, //
VaultRenameDialog.Callback
SettingsVaultBottomSheet.Callback, //
VaultDeleteConfirmationDialog.Callback, //
VaultRenameDialog.Callback

View File

@ -14,8 +14,8 @@ class AppIsObscuredInfoDialog : BaseDialog<Activity>() {
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
builder //
.setTitle(R.string.dialog_app_is_obscured_info_title) //
.setNeutralButton(R.string.dialog_app_is_obscured_info_neutral_button) { dialog: DialogInterface, _: Int -> dialog.dismiss() }
.setTitle(R.string.dialog_app_is_obscured_info_title) //
.setNeutralButton(R.string.dialog_app_is_obscured_info_neutral_button) { dialog: DialogInterface, _: Int -> dialog.dismiss() }
return builder.create()
}

View File

@ -17,8 +17,8 @@ class AskForLockScreenDialog : BaseDialog<AskForLockScreenDialog.Callback>() {
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
builder //
.setTitle(R.string.dialog_no_screen_lock_title) //
.setNeutralButton(getString(R.string.dialog_unable_to_share_positive_button)) { _: DialogInterface, _: Int -> callback?.onAskForLockScreenFinished(cb_select_screen_lock.isChecked) }
.setTitle(R.string.dialog_no_screen_lock_title) //
.setNeutralButton(getString(R.string.dialog_unable_to_share_positive_button)) { _: DialogInterface, _: Int -> callback?.onAskForLockScreenFinished(cb_select_screen_lock.isChecked) }
return builder.create()
}

View File

@ -29,14 +29,14 @@ class AssignSslCertificateDialog : BaseDialog<AssignSslCertificateDialog.Callbac
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
builder //
.setTitle(requireContext().getString(R.string.dialog_accept_ssl_certificate_title))
.setPositiveButton(requireActivity().getString(R.string.dialog_unable_to_share_positive_button)) { _: DialogInterface, _: Int ->
val cloud = requireArguments().getSerializable(WEBDAV_CLOUD) as WebDavCloud
callback?.onAcceptCertificateClicked(cloud, certificate)
} //
.setNegativeButton(requireContext().getString(R.string.dialog_button_cancel)) { _: DialogInterface, _: Int ->
callback?.onAcceptCertificateDenied()
}
.setTitle(requireContext().getString(R.string.dialog_accept_ssl_certificate_title))
.setPositiveButton(requireActivity().getString(R.string.dialog_unable_to_share_positive_button)) { _: DialogInterface, _: Int ->
val cloud = requireArguments().getSerializable(WEBDAV_CLOUD) as WebDavCloud
callback?.onAcceptCertificateClicked(cloud, certificate)
} //
.setNegativeButton(requireContext().getString(R.string.dialog_button_cancel)) { _: DialogInterface, _: Int ->
callback?.onAcceptCertificateDenied()
}
return builder.create()
}

View File

@ -16,8 +16,8 @@ class BetaConfirmationDialog : BaseDialog<BetaConfirmationDialog.Callback>() {
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
builder //
.setTitle(R.string.dialog_beta_confirmation_title) //
.setNeutralButton(getString(R.string.dialog_unable_to_share_positive_button)) { _: DialogInterface, _: Int -> callback?.onAskForBetaConfirmationFinished() }
.setTitle(R.string.dialog_beta_confirmation_title) //
.setNeutralButton(getString(R.string.dialog_unable_to_share_positive_button)) { _: DialogInterface, _: Int -> callback?.onAskForBetaConfirmationFinished() }
return builder.create()
}

View File

@ -10,8 +10,8 @@ class BiometricAuthKeyInvalidatedDialog : BaseDialog<BiometricAuthKeyInvalidated
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
builder //
.setTitle(R.string.dialog_biometric_auth_key_invalidated_title) //
.setNegativeButton(getString(R.string.dialog_biometric_auth_key_invalidated_neutral_button)) { _: DialogInterface, _: Int -> }
.setTitle(R.string.dialog_biometric_auth_key_invalidated_title) //
.setNegativeButton(getString(R.string.dialog_biometric_auth_key_invalidated_neutral_button)) { _: DialogInterface, _: Int -> }
return builder.create()
}

View File

@ -35,13 +35,18 @@ class ChangePasswordDialog : BaseProgressErrorDialog<ChangePasswordDialog.Callba
changePasswordButton?.setOnClickListener {
val vaultModel = requireArguments().getSerializable(VAULT_ARG) as VaultModel
val unverifiedVaultConfig = requireArguments().getSerializable(VAULT_CONFIG_ARG) as UnverifiedVaultConfig?
if (valid(et_old_password.text.toString(), //
et_new_password.text.toString(), //
et_new_retype_password.text.toString())) {
callback?.onChangePasswordClick(vaultModel, //
unverifiedVaultConfig, //
et_old_password.text.toString(), //
et_new_password.text.toString())
if (valid(
et_old_password.text.toString(), //
et_new_password.text.toString(), //
et_new_retype_password.text.toString()
)
) {
callback?.onChangePasswordClick(
vaultModel, //
unverifiedVaultConfig, //
et_old_password.text.toString(), //
et_new_password.text.toString()
)
onWaitForResponse(et_old_password)
} else {
hideKeyboard(et_old_password)
@ -58,10 +63,12 @@ class ChangePasswordDialog : BaseProgressErrorDialog<ChangePasswordDialog.Callba
registerOnEditorDoneActionAndPerformButtonClick(et_new_retype_password) { changePasswordButton }
PasswordStrengthUtil() //
.startUpdatingPasswordStrengthMeter(et_new_password, //
progressBarPwStrengthIndicator, //
textViewPwStrengthIndicator, //
changePasswordButton)
.startUpdatingPasswordStrengthMeter(
et_new_password, //
progressBarPwStrengthIndicator, //
textViewPwStrengthIndicator, //
changePasswordButton
)
}
}
@ -86,10 +93,10 @@ class ChangePasswordDialog : BaseProgressErrorDialog<ChangePasswordDialog.Callba
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
val vaultModel = requireArguments().getSerializable(VAULT_ARG) as VaultModel
return builder //
.setTitle(vaultModel.name) //
.setPositiveButton(getString(R.string.dialog_change_password)) { _: DialogInterface, _: Int -> } //
.setNegativeButton(getString(R.string.dialog_button_cancel)) { _: DialogInterface?, _: Int -> } //
.create()
.setTitle(vaultModel.name) //
.setPositiveButton(getString(R.string.dialog_change_password)) { _: DialogInterface, _: Int -> } //
.setNegativeButton(getString(R.string.dialog_button_cancel)) { _: DialogInterface?, _: Int -> } //
.create()
}
override fun setupView() {

View File

@ -50,10 +50,10 @@ class CloudNodeRenameDialog : BaseProgressErrorDialog<CloudNodeRenameDialog.Call
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
val cloudNodeModel = requireArguments().getSerializable(CLOUD_NODE_ARG) as CloudNodeModel<*>
return builder
.setTitle(getTitle(cloudNodeModel))
.setPositiveButton(requireActivity().getString(R.string.dialog_rename_node_positive_button)) { _: DialogInterface, _: Int -> }
.setNegativeButton(requireActivity().getString(R.string.dialog_button_cancel)) { _: DialogInterface, _: Int -> }
.create()
.setTitle(getTitle(cloudNodeModel))
.setPositiveButton(requireActivity().getString(R.string.dialog_rename_node_positive_button)) { _: DialogInterface, _: Int -> }
.setNegativeButton(requireActivity().getString(R.string.dialog_button_cancel)) { _: DialogInterface, _: Int -> }
.create()
}
private fun getTitle(cloudNodeModel: CloudNodeModel<*>): String {

View File

@ -27,10 +27,10 @@ class ConfirmDeleteCloudNodeDialog : BaseDialog<ConfirmDeleteCloudNodeDialog.Cal
title = nodes[0].name
}
return builder //
.setTitle(title) //
.setPositiveButton(getString(R.string.dialog_confirm_delete_positive_button)) { _: DialogInterface, _: Int -> callback?.onDeleteCloudNodeConfirmed(nodes) } //
.setNegativeButton(getString(R.string.dialog_confirm_delete_negative_button)) { _: DialogInterface, _: Int -> } //
.create()
.setTitle(title) //
.setPositiveButton(getString(R.string.dialog_confirm_delete_positive_button)) { _: DialogInterface, _: Int -> callback?.onDeleteCloudNodeConfirmed(nodes) } //
.setNegativeButton(getString(R.string.dialog_confirm_delete_negative_button)) { _: DialogInterface, _: Int -> } //
.create()
}
private fun getMessage(cloudNodeModel: CloudNodeModel<*>): String {

View File

@ -44,9 +44,9 @@ class CreateFolderDialog : BaseProgressErrorDialog<CreateFolderDialog.Callback>(
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
return builder.setTitle(requireContext().getString(R.string.dialog_create_folder_title))
.setPositiveButton(requireContext().getString(R.string.dialog_create_folder_positive_button)) { _: DialogInterface, _: Int -> }
.setNegativeButton(requireContext().getString(R.string.dialog_button_cancel)) { _: DialogInterface, _: Int -> }
.create()
.setPositiveButton(requireContext().getString(R.string.dialog_create_folder_positive_button)) { _: DialogInterface, _: Int -> }
.setNegativeButton(requireContext().getString(R.string.dialog_button_cancel)) { _: DialogInterface, _: Int -> }
.create()
}
override fun setupView() {

View File

@ -17,9 +17,9 @@ class DebugModeDisclaimerDialog : BaseDialog<DebugModeDisclaimerDialog.Callback>
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
builder //
.setTitle(R.string.dialog_debug_mode_disclaimer_title) //
.setPositiveButton(getString(R.string.dialog_debug_mode_positive_button)) { _: DialogInterface, _: Int -> callback?.onDisclaimerAccepted() } //
.setNegativeButton(getString(R.string.dialog_debug_mode_negative_button)) { _: DialogInterface, _: Int -> callback?.onDisclaimerRejected() }
.setTitle(R.string.dialog_debug_mode_disclaimer_title) //
.setPositiveButton(getString(R.string.dialog_debug_mode_positive_button)) { _: DialogInterface, _: Int -> callback?.onDisclaimerAccepted() } //
.setNegativeButton(getString(R.string.dialog_debug_mode_negative_button)) { _: DialogInterface, _: Int -> callback?.onDisclaimerRejected() }
return builder.create()
}

View File

@ -20,11 +20,11 @@ class DeleteCloudConnectionWithVaultsDialog : BaseDialog<DeleteCloudConnectionWi
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
val cloudModel = requireArguments().getSerializable(ARG_CLOUD) as CloudModel
builder.setTitle(cloudModel.name()) //
.setPositiveButton(getString(R.string.dialog_delete_cloud_connection_with_vaults_positive_button)) { _: DialogInterface, _: Int ->
val vaultsOfCloud = requireArguments().getSerializable(ARG_VAULTS) as ArrayList<Vault>
callback?.onDeleteCloudConnectionAndVaults(cloudModel, vaultsOfCloud)
dismiss()
}.setNegativeButton(getString(R.string.dialog_delete_cloud_connection_with_vaults_negative_button)) { _: DialogInterface, _: Int -> }
.setPositiveButton(getString(R.string.dialog_delete_cloud_connection_with_vaults_positive_button)) { _: DialogInterface, _: Int ->
val vaultsOfCloud = requireArguments().getSerializable(ARG_VAULTS) as ArrayList<Vault>
callback?.onDeleteCloudConnectionAndVaults(cloudModel, vaultsOfCloud)
dismiss()
}.setNegativeButton(getString(R.string.dialog_delete_cloud_connection_with_vaults_negative_button)) { _: DialogInterface, _: Int -> }
return builder.create()
}

View File

@ -19,9 +19,9 @@ class DisableAppWhenObscuredDisclaimerDialog : BaseDialog<DisableAppWhenObscured
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
builder //
.setTitle(R.string.dialog_disable_app_obscured_disclaimer_title) //
.setPositiveButton(getString(R.string.dialog_disable_app_obscured_positive_button)) { _: DialogInterface, _: Int -> callback?.onDisableAppObscuredDisclaimerAccepted() } //
.setNegativeButton(getString(R.string.dialog_disable_app_obscured_negative_button)) { _: DialogInterface, _: Int -> callback?.onDisableAppObscuredDisclaimerRejected() }
.setTitle(R.string.dialog_disable_app_obscured_disclaimer_title) //
.setPositiveButton(getString(R.string.dialog_disable_app_obscured_positive_button)) { _: DialogInterface, _: Int -> callback?.onDisableAppObscuredDisclaimerAccepted() } //
.setNegativeButton(getString(R.string.dialog_disable_app_obscured_negative_button)) { _: DialogInterface, _: Int -> callback?.onDisableAppObscuredDisclaimerRejected() }
return builder.create()
}

View File

@ -19,9 +19,9 @@ class DisableSecureScreenDisclaimerDialog : BaseDialog<DisableSecureScreenDiscla
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
builder //
.setTitle(R.string.dialog_disable_app_obscured_disclaimer_title) //
.setPositiveButton(getString(R.string.dialog_disable_app_obscured_positive_button)) { _: DialogInterface, _: Int -> callback?.onDisableSecureScreenDisclaimerAccepted() } //
.setNegativeButton(getString(R.string.dialog_disable_app_obscured_negative_button)) { _: DialogInterface, _: Int -> callback?.onDisableSecureScreenDisclaimerRejected() }
.setTitle(R.string.dialog_disable_app_obscured_disclaimer_title) //
.setPositiveButton(getString(R.string.dialog_disable_app_obscured_positive_button)) { _: DialogInterface, _: Int -> callback?.onDisableSecureScreenDisclaimerAccepted() } //
.setNegativeButton(getString(R.string.dialog_disable_app_obscured_negative_button)) { _: DialogInterface, _: Int -> callback?.onDisableSecureScreenDisclaimerRejected() }
return builder.create()
}

View File

@ -21,11 +21,13 @@ class EnrollSystemBiometricDialog : BaseDialog<EnrollSystemBiometricDialog.Callb
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
builder //
.setTitle(getString(R.string.dialog_no_biometric_auth_set_up_title)) //
.setPositiveButton(getString(R.string.dialog_unable_to_share_positive_button) //
) { _: DialogInterface, _: Int -> callback?.onSetupBiometricAuthInSystemClicked() }
.setNegativeButton(getString(R.string.dialog_button_cancel) //
) { _: DialogInterface?, _: Int -> callback?.onCancelSetupBiometricAuthInSystemClicked() }
.setTitle(getString(R.string.dialog_no_biometric_auth_set_up_title)) //
.setPositiveButton(
getString(R.string.dialog_unable_to_share_positive_button) //
) { _: DialogInterface, _: Int -> callback?.onSetupBiometricAuthInSystemClicked() }
.setNegativeButton(
getString(R.string.dialog_button_cancel) //
) { _: DialogInterface?, _: Int -> callback?.onCancelSetupBiometricAuthInSystemClicked() }
return builder.create()
}

View File

@ -51,12 +51,12 @@ class EnterPasswordDialog : BaseProgressErrorDialog<EnterPasswordDialog.Callback
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
return builder //
.setTitle(vaultModel().name) //
.setPositiveButton(getString(R.string.dialog_enter_password_positive_button)) { _: DialogInterface, _: Int -> }
.setNegativeButton(getString(R.string.dialog_button_cancel)) { _: DialogInterface, _: Int ->
callback?.onUnlockCanceled()
callback?.closeDialog()
}.create()
.setTitle(vaultModel().name) //
.setPositiveButton(getString(R.string.dialog_enter_password_positive_button)) { _: DialogInterface, _: Int -> }
.setNegativeButton(getString(R.string.dialog_button_cancel)) { _: DialogInterface, _: Int ->
callback?.onUnlockCanceled()
callback?.closeDialog()
}.create()
}
fun vaultModel(): VaultModel {

View File

@ -19,8 +19,8 @@ class ExistingFileDialog : BaseDialog<ExistingFileDialog.Callback>() {
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
val fileUri = requireArguments().getParcelable<Uri>(FILE_URI_ARG)
builder.setTitle(getString(R.string.dialog_existing_file_title)) //
.setPositiveButton(getString(R.string.dialog_existing_file_positive_button)) { _: DialogInterface?, _: Int -> fileUri?.let { callback?.onReplaceClick(it) } } //
.setNegativeButton(getString(R.string.dialog_button_cancel)) { _: DialogInterface?, _: Int -> }
.setPositiveButton(getString(R.string.dialog_existing_file_positive_button)) { _: DialogInterface?, _: Int -> fileUri?.let { callback?.onReplaceClick(it) } } //
.setNegativeButton(getString(R.string.dialog_button_cancel)) { _: DialogInterface?, _: Int -> }
return builder.create()
}

View File

@ -32,15 +32,17 @@ class ExportCloudFilesDialog : BaseProgressErrorDialog<ExportCloudFilesDialog.Ca
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
return builder //
.setTitle(effectiveTitle(1)) //
.setNeutralButton(getString(R.string.dialog_export_file_cancel_button)) { _: DialogInterface, _: Int -> callback?.onExportCancelled() } //
.create()
.setTitle(effectiveTitle(1)) //
.setNeutralButton(getString(R.string.dialog_export_file_cancel_button)) { _: DialogInterface, _: Int -> callback?.onExportCancelled() } //
.create()
}
private fun effectiveTitle(seenFiles: Int): String {
return String.format(getString(R.string.dialog_export_file_title), //
seenFiles, //
requireArguments().getInt(ARG_NUMBER_OF_FILES))
return String.format(
getString(R.string.dialog_export_file_title), //
seenFiles, //
requireArguments().getInt(ARG_NUMBER_OF_FILES)
)
}
override fun setupView() {}

View File

@ -46,9 +46,9 @@ class FileNameDialog : BaseProgressErrorDialog<FileNameDialog.Callback>() {
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
return builder.setTitle(R.string.dialog_file_name_title) //
.setPositiveButton(R.string.dialog_file_name_create) { _: DialogInterface, _: Int -> } //
.setNegativeButton(R.string.dialog_file_name_cancel) { _: DialogInterface, _: Int -> } //
.create()
.setPositiveButton(R.string.dialog_file_name_create) { _: DialogInterface, _: Int -> } //
.setNegativeButton(R.string.dialog_file_name_cancel) { _: DialogInterface, _: Int -> } //
.create()
}
private fun effectiveNewFileName(newFileName: String): String {

View File

@ -18,8 +18,8 @@ class FileTypeNotSupportedDialog : BaseDialog<FileTypeNotSupportedDialog.Callbac
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
val cloudFileModel = requireArguments().getSerializable(CLOUD_FILE_ARG) as CloudFileModel
builder.setTitle(String.format(getString(R.string.dialog_filetype_not_supported_title), cloudFileModel.name))
.setPositiveButton(getString(R.string.dialog_filetype_not_supported_positive_button)) { _: DialogInterface, _: Int -> callback?.onExportFileAfterAppChooserClicked(cloudFileModel) } //
.setNegativeButton(getString(R.string.dialog_button_cancel)) { _: DialogInterface, _: Int -> }
.setPositiveButton(getString(R.string.dialog_filetype_not_supported_positive_button)) { _: DialogInterface, _: Int -> callback?.onExportFileAfterAppChooserClicked(cloudFileModel) } //
.setNegativeButton(getString(R.string.dialog_button_cancel)) { _: DialogInterface, _: Int -> }
return builder.create()
}

View File

@ -17,8 +17,8 @@ class LicenseConfirmationDialog : BaseDialog<LicenseConfirmationDialog.Callback>
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
builder //
.setTitle(getString(R.string.dialog_license_confirmation_title)) //
.setNeutralButton(getText(R.string.dialog_license_confirmation_ok_btn)) { _: DialogInterface, _: Int -> callback?.licenseConfirmationClicked() }
.setTitle(getString(R.string.dialog_license_confirmation_title)) //
.setNeutralButton(getText(R.string.dialog_license_confirmation_ok_btn)) { _: DialogInterface, _: Int -> callback?.licenseConfirmationClicked() }
return builder.create()
}

View File

@ -18,11 +18,11 @@ class NoDirFileDialog : BaseDialog<NoDirFileDialog.CallBack>() {
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
builder //
.setTitle(R.string.dialog_no_dir_file_title) //
.setNeutralButton(R.string.dialog_no_dir_file_back_button) { dialog: DialogInterface, _: Int ->
callback?.navigateFolderBackBecauseNoDirFile()
dialog.dismiss()
}
.setTitle(R.string.dialog_no_dir_file_title) //
.setNeutralButton(R.string.dialog_no_dir_file_back_button) { dialog: DialogInterface, _: Int ->
callback?.navigateFolderBackBecauseNoDirFile()
dialog.dismiss()
}
return builder.create()
}

View File

@ -24,13 +24,13 @@ class NotEnoughVaultsDialog private constructor(private val context: Context) {
fun show() {
AlertDialog.Builder(context) //
.setCancelable(false) //
.setTitle(title) //
.setMessage(ResourceHelper.getString(R.string.dialog_unable_to_share_message)) //
.setPositiveButton(ResourceHelper.getString(R.string.dialog_unable_to_share_positive_button)) { _: DialogInterface, _: Int -> callback.onNotEnoughVaultsOkClicked() } //
.setNegativeButton(ResourceHelper.getString(R.string.dialog_unable_to_share_negative_button)) { _: DialogInterface, _: Int -> callback.onNotEnoughVaultsCreateVaultClicked() } //
.create() //
.show()
.setCancelable(false) //
.setTitle(title) //
.setMessage(ResourceHelper.getString(R.string.dialog_unable_to_share_message)) //
.setPositiveButton(ResourceHelper.getString(R.string.dialog_unable_to_share_positive_button)) { _: DialogInterface, _: Int -> callback.onNotEnoughVaultsOkClicked() } //
.setNegativeButton(ResourceHelper.getString(R.string.dialog_unable_to_share_negative_button)) { _: DialogInterface, _: Int -> callback.onNotEnoughVaultsCreateVaultClicked() } //
.create() //
.show()
}
companion object {

View File

@ -20,11 +20,11 @@ class ReplaceDialog private constructor(private val context: Context) {
fun show(existingFiles: List<String>, uploadingFilesCount: Int) {
val existingFilesCount = existingFiles.size
val alertDialogBuilder = AlertDialog.Builder(context) //
.setTitle(effectiveReplaceDialogTitle(existingFilesCount)) //
.setMessage(effectiveReplaceDialogMessage(existingFiles, uploadingFilesCount))
.setPositiveButton(effectiveReplaceDialogPositiveButton(existingFilesCount, uploadingFilesCount)) { _: DialogInterface, _: Int -> callback.onReplacePositiveClicked() } //
.setNeutralButton(effectiveReplaceDialogNeutralButton()) { _: DialogInterface, _: Int -> callback.onReplaceCanceled() } //
.setOnCancelListener { callback.onReplaceCanceled() }
.setTitle(effectiveReplaceDialogTitle(existingFilesCount)) //
.setMessage(effectiveReplaceDialogMessage(existingFiles, uploadingFilesCount))
.setPositiveButton(effectiveReplaceDialogPositiveButton(existingFilesCount, uploadingFilesCount)) { _: DialogInterface, _: Int -> callback.onReplacePositiveClicked() } //
.setNeutralButton(effectiveReplaceDialogNeutralButton()) { _: DialogInterface, _: Int -> callback.onReplaceCanceled() } //
.setOnCancelListener { callback.onReplaceCanceled() }
if (uploadingFilesCount > 1 && existingFilesCount != uploadingFilesCount) {
alertDialogBuilder.setNegativeButton(effectiveReplaceDialogNegativeButton()) { _: DialogInterface, _: Int -> callback.onReplaceNegativeClicked() }
}

View File

@ -18,11 +18,11 @@ class SymLinkDialog : BaseDialog<SymLinkDialog.CallBack?>() {
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
builder //
.setTitle(R.string.dialog_sym_link_title) //
.setNeutralButton(R.string.dialog_sym_link_back_button) { dialog: DialogInterface, _: Int ->
callback?.navigateFolderBackBecauseSymlink()
dialog.dismiss()
}
.setTitle(R.string.dialog_sym_link_title) //
.setNeutralButton(R.string.dialog_sym_link_back_button) { dialog: DialogInterface, _: Int ->
callback?.navigateFolderBackBecauseSymlink()
dialog.dismiss()
}
return builder.create()
}

View File

@ -17,12 +17,12 @@ class UnsavedChangesDialog private constructor(private val context: Context) {
fun show() {
AlertDialog.Builder(context) //
.setCancelable(false) //
.setTitle(R.string.dialog_unsaved_changes_title) //
.setMessage(R.string.dialog_unsaved_changes_message) //
.setPositiveButton(R.string.dialog_unsaved_changes_save) { _: DialogInterface?, _: Int -> callback.onSaveChangesClicked() } //
.setNegativeButton(R.string.dialog_unsaved_changes_discard) { _: DialogInterface?, _: Int -> callback.onDiscardChangesClicked() } //
.create().show()
.setCancelable(false) //
.setTitle(R.string.dialog_unsaved_changes_title) //
.setMessage(R.string.dialog_unsaved_changes_message) //
.setPositiveButton(R.string.dialog_unsaved_changes_save) { _: DialogInterface?, _: Int -> callback.onSaveChangesClicked() } //
.setNegativeButton(R.string.dialog_unsaved_changes_discard) { _: DialogInterface?, _: Int -> callback.onDiscardChangesClicked() } //
.create().show()
}
companion object {

View File

@ -22,12 +22,12 @@ class UpdateAppAvailableDialog : BaseProgressErrorDialog<UpdateAppAvailableDialo
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
return builder //
.setTitle(getString(R.string.dialog_update_available_title)) //
.setPositiveButton(getString(R.string.dialog_update_available_update)) { _: DialogInterface, _: Int -> callback?.installUpdate() } //
.setNeutralButton(getString(R.string.dialog_update_available_download_site)) { _: DialogInterface, _: Int -> callback?.showUpdateWebsite() }
.setNegativeButton(getText(R.string.dialog_update_available_cancel)) { _: DialogInterface, _: Int -> callback?.cancelUpdateClicked() } //
.setCancelable(false) //
.create()
.setTitle(getString(R.string.dialog_update_available_title)) //
.setPositiveButton(getString(R.string.dialog_update_available_update)) { _: DialogInterface, _: Int -> callback?.installUpdate() } //
.setNeutralButton(getString(R.string.dialog_update_available_download_site)) { _: DialogInterface, _: Int -> callback?.showUpdateWebsite() }
.setNegativeButton(getText(R.string.dialog_update_available_cancel)) { _: DialogInterface, _: Int -> callback?.cancelUpdateClicked() } //
.setCancelable(false) //
.create()
}
public override fun setupView() {

View File

@ -21,9 +21,9 @@ class UpdateAppDialog : BaseProgressErrorDialog<UpdateAppDialog.Callback>() {
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
return builder //
.setTitle(getString(R.string.dialog_download_update_title)) //
.setCancelable(false) //
.create()
.setTitle(getString(R.string.dialog_download_update_title)) //
.setCancelable(false) //
.create()
}
public override fun setupView() {

View File

@ -39,10 +39,10 @@ class UpdateLicenseDialog : BaseProgressErrorDialog<UpdateLicenseDialog.Callback
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
return builder //
.setTitle(getString(R.string.dialog_enter_license_title)) //
.setPositiveButton(getText(R.string.dialog_enter_license_ok_button)) { _: DialogInterface, _: Int -> } //
.setNegativeButton(getText(R.string.dialog_enter_license_decline_button)) { _: DialogInterface, _: Int -> callback?.onCheckLicenseCanceled() } //
.create()
.setTitle(getString(R.string.dialog_enter_license_title)) //
.setPositiveButton(getText(R.string.dialog_enter_license_ok_button)) { _: DialogInterface, _: Int -> } //
.setNegativeButton(getText(R.string.dialog_enter_license_decline_button)) { _: DialogInterface, _: Int -> callback?.onCheckLicenseCanceled() } //
.create()
}
public override fun setupView() {

View File

@ -41,9 +41,9 @@ class UploadCloudFileDialog : BaseProgressErrorDialog<UploadCloudFileDialog.Call
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
return builder //
.setTitle(effectiveTitle()) //
.setNeutralButton(getString(R.string.dialog_upload_file_cancel_button)) { _: DialogInterface?, _: Int -> } //
.create()
.setTitle(effectiveTitle()) //
.setNeutralButton(getString(R.string.dialog_upload_file_cancel_button)) { _: DialogInterface?, _: Int -> } //
.create()
}
private fun effectiveTitle(): String {

View File

@ -19,8 +19,8 @@ class VaultDeleteConfirmationDialog : BaseDialog<VaultDeleteConfirmationDialog.C
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
val vaultModel = requireArguments().getSerializable(VAULT_ARG) as VaultModel
builder.setTitle(vaultModel.name) //
.setPositiveButton(getString(R.string.dialog_delete_vault_positive_button_text)) { _: DialogInterface, _: Int -> callback?.onDeleteConfirmedClick(vaultModel) } //
.setNegativeButton(getString(R.string.dialog_button_cancel)) { _: DialogInterface, _: Int -> }
.setPositiveButton(getString(R.string.dialog_delete_vault_positive_button_text)) { _: DialogInterface, _: Int -> callback?.onDeleteConfirmedClick(vaultModel) } //
.setNegativeButton(getString(R.string.dialog_button_cancel)) { _: DialogInterface, _: Int -> }
return builder.create()
}

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