Reformat code using new Kotlin formatting rule
This commit is contained in:
parent
bb07076ba8
commit
5c024dbda9
@ -88,7 +88,8 @@ public class CryptoCloudFactory {
|
|||||||
case MASTERKEY_SCHEME: {
|
case MASTERKEY_SCHEME: {
|
||||||
return new MasterkeyCryptoCloudProvider(cloudContentRepository, cryptoCloudContentRepositoryFactory, secureRandom);
|
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 {
|
} else {
|
||||||
return new MasterkeyCryptoCloudProvider(cloudContentRepository, cryptoCloudContentRepositoryFactory, secureRandom);
|
return new MasterkeyCryptoCloudProvider(cloudContentRepository, cryptoCloudContentRepositoryFactory, secureRandom);
|
||||||
|
@ -162,7 +162,7 @@ public class MasterkeyCryptoCloudProvider implements CryptoCloudProvider {
|
|||||||
|
|
||||||
private CloudFile masterkeyFile(CloudFolder vaultLocation, UnverifiedVaultConfig unverifiedVaultConfig) throws BackendException {
|
private CloudFile masterkeyFile(CloudFolder vaultLocation, UnverifiedVaultConfig unverifiedVaultConfig) throws BackendException {
|
||||||
String path = unverifiedVaultConfig.getKeyId().getSchemeSpecificPart();
|
String path = unverifiedVaultConfig.getKeyId().getSchemeSpecificPart();
|
||||||
if(!path.equals(MASTERKEY_FILE_NAME)) {
|
if (!path.equals(MASTERKEY_FILE_NAME)) {
|
||||||
throw new UnsupportedMasterkeyLocationException(unverifiedVaultConfig);
|
throw new UnsupportedMasterkeyLocationException(unverifiedVaultConfig);
|
||||||
}
|
}
|
||||||
return cloudContentRepository.file(vaultLocation, path);
|
return cloudContentRepository.file(vaultLocation, path);
|
||||||
|
@ -28,13 +28,13 @@ class VaultConfig private constructor(builder: VaultConfigBuilder) {
|
|||||||
|
|
||||||
fun toToken(rawKey: ByteArray): String {
|
fun toToken(rawKey: ByteArray): String {
|
||||||
return Jwts.builder()
|
return Jwts.builder()
|
||||||
.setHeaderParam(JSON_KEY_ID, keyId.toASCIIString()) //
|
.setHeaderParam(JSON_KEY_ID, keyId.toASCIIString()) //
|
||||||
.setId(id) //
|
.setId(id) //
|
||||||
.claim(JSON_KEY_VAULTFORMAT, vaultFormat) //
|
.claim(JSON_KEY_VAULTFORMAT, vaultFormat) //
|
||||||
.claim(JSON_KEY_CIPHERCONFIG, cipherCombo.name) //
|
.claim(JSON_KEY_CIPHERCONFIG, cipherCombo.name) //
|
||||||
.claim(JSON_KEY_SHORTENING_THRESHOLD, shorteningThreshold) //
|
.claim(JSON_KEY_SHORTENING_THRESHOLD, shorteningThreshold) //
|
||||||
.signWith(Keys.hmacShaKeyFor(rawKey)) //
|
.signWith(Keys.hmacShaKeyFor(rawKey)) //
|
||||||
.compact()
|
.compact()
|
||||||
}
|
}
|
||||||
|
|
||||||
class VaultConfigBuilder {
|
class VaultConfigBuilder {
|
||||||
@ -101,18 +101,18 @@ class VaultConfig private constructor(builder: VaultConfigBuilder) {
|
|||||||
fun verify(rawKey: ByteArray, unverifiedVaultConfig: UnverifiedVaultConfig): VaultConfig {
|
fun verify(rawKey: ByteArray, unverifiedVaultConfig: UnverifiedVaultConfig): VaultConfig {
|
||||||
return try {
|
return try {
|
||||||
val parser = Jwts //
|
val parser = Jwts //
|
||||||
.parserBuilder() //
|
.parserBuilder() //
|
||||||
.setSigningKey(rawKey) //
|
.setSigningKey(rawKey) //
|
||||||
.require(JSON_KEY_VAULTFORMAT, unverifiedVaultConfig.vaultFormat) //
|
.require(JSON_KEY_VAULTFORMAT, unverifiedVaultConfig.vaultFormat) //
|
||||||
.build() //
|
.build() //
|
||||||
.parseClaimsJws(unverifiedVaultConfig.jwt)
|
.parseClaimsJws(unverifiedVaultConfig.jwt)
|
||||||
|
|
||||||
val vaultConfigBuilder = createVaultConfig() //
|
val vaultConfigBuilder = createVaultConfig() //
|
||||||
.keyId(unverifiedVaultConfig.keyId)
|
.keyId(unverifiedVaultConfig.keyId)
|
||||||
.id(parser.header[JSON_KEY_ID] as String) //
|
.id(parser.header[JSON_KEY_ID] as String) //
|
||||||
.cipherCombo(VaultCipherCombo.valueOf(parser.body.get(JSON_KEY_CIPHERCONFIG, String::class.java))) //
|
.cipherCombo(VaultCipherCombo.valueOf(parser.body.get(JSON_KEY_CIPHERCONFIG, String::class.java))) //
|
||||||
.vaultFormat(unverifiedVaultConfig.vaultFormat) //
|
.vaultFormat(unverifiedVaultConfig.vaultFormat) //
|
||||||
.shorteningThreshold(parser.body[JSON_KEY_SHORTENING_THRESHOLD] as Int)
|
.shorteningThreshold(parser.body[JSON_KEY_SHORTENING_THRESHOLD] as Int)
|
||||||
|
|
||||||
VaultConfig(vaultConfigBuilder)
|
VaultConfig(vaultConfigBuilder)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
@ -33,6 +33,30 @@ class S3ClientFactory {
|
|||||||
return new HttpLoggingInterceptor(message -> Timber.tag("OkHttp").d(message), context);
|
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) {
|
public MinioClient getClient(S3Cloud cloud, Context context) {
|
||||||
if (apiClient == null) {
|
if (apiClient == null) {
|
||||||
apiClient = createApiClient(cloud, context);
|
apiClient = createApiClient(cloud, context);
|
||||||
@ -66,30 +90,6 @@ class S3ClientFactory {
|
|||||||
.build();
|
.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) {
|
private String decrypt(String password, Context context) {
|
||||||
return CredentialCryptor //
|
return CredentialCryptor //
|
||||||
.getInstance(context) //
|
.getInstance(context) //
|
||||||
|
@ -1,14 +1,7 @@
|
|||||||
package org.cryptomator.data.cloud.s3;
|
package org.cryptomator.data.cloud.s3;
|
||||||
|
|
||||||
public enum S3CloudApiErrorCodes {
|
public enum S3CloudApiErrorCodes {
|
||||||
ACCESS_DENIED("AccessDenied"),
|
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");
|
||||||
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;
|
private final String value;
|
||||||
|
|
||||||
|
@ -3,9 +3,7 @@ package org.cryptomator.data.cloud.s3;
|
|||||||
public class S3CloudApiExceptions {
|
public class S3CloudApiExceptions {
|
||||||
|
|
||||||
public static boolean isAccessProblem(String errorCode) {
|
public static boolean isAccessProblem(String errorCode) {
|
||||||
return errorCode.equals(S3CloudApiErrorCodes.ACCESS_DENIED.getValue())
|
return errorCode.equals(S3CloudApiErrorCodes.ACCESS_DENIED.getValue()) || errorCode.equals(S3CloudApiErrorCodes.ACCOUNT_PROBLEM.getValue()) || errorCode.equals(S3CloudApiErrorCodes.INVALID_ACCESS_KEY_ID.getValue());
|
||||||
|| errorCode.equals(S3CloudApiErrorCodes.ACCOUNT_PROBLEM.getValue())
|
|
||||||
|| errorCode.equals(S3CloudApiErrorCodes.INVALID_ACCESS_KEY_ID.getValue());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isNoSuchBucketException(String errorCode) {
|
public static boolean isNoSuchBucketException(String errorCode) {
|
||||||
|
@ -63,7 +63,7 @@ class S3CloudContentRepository extends InterceptingCloudContentRepository<S3Clou
|
|||||||
if (S3CloudApiExceptions.isAccessProblem(errorCode)) {
|
if (S3CloudApiExceptions.isAccessProblem(errorCode)) {
|
||||||
throw new WrongCredentialsException(cloud);
|
throw new WrongCredentialsException(cloud);
|
||||||
}
|
}
|
||||||
} else if(e instanceof ForbiddenException) {
|
} else if (e instanceof ForbiddenException) {
|
||||||
throw new WrongCredentialsException(cloud);
|
throw new WrongCredentialsException(cloud);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ class S3Impl {
|
|||||||
public boolean exists(S3Node node) throws BackendException {
|
public boolean exists(S3Node node) throws BackendException {
|
||||||
String key = node.getKey();
|
String key = node.getKey();
|
||||||
try {
|
try {
|
||||||
if(!(node instanceof RootS3Folder)) {
|
if (!(node instanceof RootS3Folder)) {
|
||||||
client().statObject(StatObjectArgs.builder().bucket(cloud.s3Bucket()).object(key).build());
|
client().statObject(StatObjectArgs.builder().bucket(cloud.s3Bucket()).object(key).build());
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@ -256,7 +256,7 @@ class S3Impl {
|
|||||||
|
|
||||||
Date lastModified = objectWriteResponse.headers().getDate("Last-Modified");
|
Date lastModified = objectWriteResponse.headers().getDate("Last-Modified");
|
||||||
|
|
||||||
if(lastModified == null) {
|
if (lastModified == null) {
|
||||||
StatObjectResponse statObjectResponse = client().statObject(StatObjectArgs //
|
StatObjectResponse statObjectResponse = client().statObject(StatObjectArgs //
|
||||||
.builder() //
|
.builder() //
|
||||||
.bucket(cloud.s3Bucket()) //
|
.bucket(cloud.s3Bucket()) //
|
||||||
|
@ -14,19 +14,19 @@ internal class Upgrade2To3 @Inject constructor(private val context: Context) : D
|
|||||||
db.beginTransaction()
|
db.beginTransaction()
|
||||||
try {
|
try {
|
||||||
Sql.query("CLOUD_ENTITY")
|
Sql.query("CLOUD_ENTITY")
|
||||||
.columns(listOf("ACCESS_TOKEN"))
|
.columns(listOf("ACCESS_TOKEN"))
|
||||||
.where("TYPE", Sql.eq("DROPBOX"))
|
.where("TYPE", Sql.eq("DROPBOX"))
|
||||||
.executeOn(db).use {
|
.executeOn(db).use {
|
||||||
if (it.moveToFirst()) {
|
if (it.moveToFirst()) {
|
||||||
Sql.update("CLOUD_ENTITY")
|
Sql.update("CLOUD_ENTITY")
|
||||||
.set("ACCESS_TOKEN", Sql.toString(encrypt(it.getString(it.getColumnIndex("ACCESS_TOKEN")))))
|
.set("ACCESS_TOKEN", Sql.toString(encrypt(it.getString(it.getColumnIndex("ACCESS_TOKEN")))))
|
||||||
.where("TYPE", Sql.eq("DROPBOX"));
|
.where("TYPE", Sql.eq("DROPBOX"));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Sql.update("CLOUD_ENTITY")
|
Sql.update("CLOUD_ENTITY")
|
||||||
.set("ACCESS_TOKEN", Sql.toString(encrypt(onedriveToken())))
|
.set("ACCESS_TOKEN", Sql.toString(encrypt(onedriveToken())))
|
||||||
.where("TYPE", Sql.eq("ONEDRIVE"));
|
.where("TYPE", Sql.eq("ONEDRIVE"));
|
||||||
|
|
||||||
db.setTransactionSuccessful()
|
db.setTransactionSuccessful()
|
||||||
} finally {
|
} finally {
|
||||||
@ -36,8 +36,8 @@ internal class Upgrade2To3 @Inject constructor(private val context: Context) : D
|
|||||||
|
|
||||||
private fun encrypt(token: String?): String? {
|
private fun encrypt(token: String?): String? {
|
||||||
return if (token == null) null else CredentialCryptor //
|
return if (token == null) null else CredentialCryptor //
|
||||||
.getInstance(context) //
|
.getInstance(context) //
|
||||||
.encrypt(token)
|
.encrypt(token)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onedriveToken(): String? {
|
private fun onedriveToken(): String? {
|
||||||
|
@ -25,42 +25,42 @@ internal class Upgrade3To4 @Inject constructor() : DatabaseUpgrade(3, 4) {
|
|||||||
private fun addPositionToVaultSchema(db: Database) {
|
private fun addPositionToVaultSchema(db: Database) {
|
||||||
Sql.alterTable("VAULT_ENTITY").renameTo("VAULT_ENTITY_OLD").executeOn(db)
|
Sql.alterTable("VAULT_ENTITY").renameTo("VAULT_ENTITY_OLD").executeOn(db)
|
||||||
Sql.createTable("VAULT_ENTITY") //
|
Sql.createTable("VAULT_ENTITY") //
|
||||||
.id() //
|
.id() //
|
||||||
.optionalInt("FOLDER_CLOUD_ID") //
|
.optionalInt("FOLDER_CLOUD_ID") //
|
||||||
.optionalText("FOLDER_PATH") //
|
.optionalText("FOLDER_PATH") //
|
||||||
.optionalText("FOLDER_NAME") //
|
.optionalText("FOLDER_NAME") //
|
||||||
.requiredText("CLOUD_TYPE") //
|
.requiredText("CLOUD_TYPE") //
|
||||||
.optionalText("PASSWORD") //
|
.optionalText("PASSWORD") //
|
||||||
.optionalInt("POSITION") //
|
.optionalInt("POSITION") //
|
||||||
.foreignKey("FOLDER_CLOUD_ID", "CLOUD_ENTITY", ForeignKeyBehaviour.ON_DELETE_SET_NULL) //
|
.foreignKey("FOLDER_CLOUD_ID", "CLOUD_ENTITY", ForeignKeyBehaviour.ON_DELETE_SET_NULL) //
|
||||||
.executeOn(db)
|
.executeOn(db)
|
||||||
|
|
||||||
Sql.insertInto("VAULT_ENTITY") //
|
Sql.insertInto("VAULT_ENTITY") //
|
||||||
.select("_id", "FOLDER_CLOUD_ID", "FOLDER_PATH", "FOLDER_NAME", "PASSWORD", "CLOUD_ENTITY.TYPE") //
|
.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") //
|
.columns("_id", "FOLDER_CLOUD_ID", "FOLDER_PATH", "FOLDER_NAME", "PASSWORD", "CLOUD_TYPE") //
|
||||||
.from("VAULT_ENTITY_OLD") //
|
.from("VAULT_ENTITY_OLD") //
|
||||||
.join("CLOUD_ENTITY", "VAULT_ENTITY_OLD.FOLDER_CLOUD_ID") //
|
.join("CLOUD_ENTITY", "VAULT_ENTITY_OLD.FOLDER_CLOUD_ID") //
|
||||||
.executeOn(db)
|
.executeOn(db)
|
||||||
|
|
||||||
Sql.dropIndex("IDX_VAULT_ENTITY_FOLDER_PATH_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") //
|
Sql.createUniqueIndex("IDX_VAULT_ENTITY_FOLDER_PATH_FOLDER_CLOUD_ID") //
|
||||||
.on("VAULT_ENTITY") //
|
.on("VAULT_ENTITY") //
|
||||||
.asc("FOLDER_PATH") //
|
.asc("FOLDER_PATH") //
|
||||||
.asc("FOLDER_CLOUD_ID") //
|
.asc("FOLDER_CLOUD_ID") //
|
||||||
.executeOn(db)
|
.executeOn(db)
|
||||||
|
|
||||||
Sql.dropTable("VAULT_ENTITY_OLD").executeOn(db)
|
Sql.dropTable("VAULT_ENTITY_OLD").executeOn(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initVaultPositionUsingCurrentSortOrder(db: Database) {
|
private fun initVaultPositionUsingCurrentSortOrder(db: Database) {
|
||||||
CloudEntityDao(DaoConfig(db, VaultEntityDao::class.java)) //
|
CloudEntityDao(DaoConfig(db, VaultEntityDao::class.java)) //
|
||||||
.loadAll() //
|
.loadAll() //
|
||||||
.map {
|
.map {
|
||||||
Sql.update("VAULT_ENTITY") //
|
Sql.update("VAULT_ENTITY") //
|
||||||
.where("_id", Sql.eq(it.id)) //
|
.where("_id", Sql.eq(it.id)) //
|
||||||
.set("POSITION", Sql.toInteger(it.id - 1)) //
|
.set("POSITION", Sql.toInteger(it.id - 1)) //
|
||||||
.executeOn(db)
|
.executeOn(db)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,19 +21,19 @@ internal class Upgrade4To5 @Inject constructor() : DatabaseUpgrade(4, 5) {
|
|||||||
Sql.alterTable("CLOUD_ENTITY").renameTo("CLOUD_ENTITY_OLD").executeOn(db)
|
Sql.alterTable("CLOUD_ENTITY").renameTo("CLOUD_ENTITY_OLD").executeOn(db)
|
||||||
|
|
||||||
Sql.createTable("CLOUD_ENTITY") //
|
Sql.createTable("CLOUD_ENTITY") //
|
||||||
.id() //
|
.id() //
|
||||||
.requiredText("TYPE") //
|
.requiredText("TYPE") //
|
||||||
.optionalText("ACCESS_TOKEN") //
|
.optionalText("ACCESS_TOKEN") //
|
||||||
.optionalText("URL") //
|
.optionalText("URL") //
|
||||||
.optionalText("USERNAME") //
|
.optionalText("USERNAME") //
|
||||||
.optionalText("WEBDAV_CERTIFICATE") //
|
.optionalText("WEBDAV_CERTIFICATE") //
|
||||||
.executeOn(db);
|
.executeOn(db);
|
||||||
|
|
||||||
Sql.insertInto("CLOUD_ENTITY") //
|
Sql.insertInto("CLOUD_ENTITY") //
|
||||||
.select("_id", "TYPE", "ACCESS_TOKEN", "WEBDAV_URL", "USERNAME", "WEBDAV_CERTIFICATE") //
|
.select("_id", "TYPE", "ACCESS_TOKEN", "WEBDAV_URL", "USERNAME", "WEBDAV_CERTIFICATE") //
|
||||||
.columns("_id", "TYPE", "ACCESS_TOKEN", "URL", "USERNAME", "WEBDAV_CERTIFICATE") //
|
.columns("_id", "TYPE", "ACCESS_TOKEN", "URL", "USERNAME", "WEBDAV_CERTIFICATE") //
|
||||||
.from("CLOUD_ENTITY_OLD") //
|
.from("CLOUD_ENTITY_OLD") //
|
||||||
.executeOn(db)
|
.executeOn(db)
|
||||||
|
|
||||||
recreateVaultEntity(db)
|
recreateVaultEntity(db)
|
||||||
|
|
||||||
@ -43,30 +43,30 @@ internal class Upgrade4To5 @Inject constructor() : DatabaseUpgrade(4, 5) {
|
|||||||
private fun recreateVaultEntity(db: Database) {
|
private fun recreateVaultEntity(db: Database) {
|
||||||
Sql.alterTable("VAULT_ENTITY").renameTo("VAULT_ENTITY_OLD").executeOn(db)
|
Sql.alterTable("VAULT_ENTITY").renameTo("VAULT_ENTITY_OLD").executeOn(db)
|
||||||
Sql.createTable("VAULT_ENTITY") //
|
Sql.createTable("VAULT_ENTITY") //
|
||||||
.id() //
|
.id() //
|
||||||
.optionalInt("FOLDER_CLOUD_ID") //
|
.optionalInt("FOLDER_CLOUD_ID") //
|
||||||
.optionalText("FOLDER_PATH") //
|
.optionalText("FOLDER_PATH") //
|
||||||
.optionalText("FOLDER_NAME") //
|
.optionalText("FOLDER_NAME") //
|
||||||
.requiredText("CLOUD_TYPE") //
|
.requiredText("CLOUD_TYPE") //
|
||||||
.optionalText("PASSWORD") //
|
.optionalText("PASSWORD") //
|
||||||
.optionalInt("POSITION") //
|
.optionalInt("POSITION") //
|
||||||
.foreignKey("FOLDER_CLOUD_ID", "CLOUD_ENTITY", Sql.SqlCreateTableBuilder.ForeignKeyBehaviour.ON_DELETE_SET_NULL) //
|
.foreignKey("FOLDER_CLOUD_ID", "CLOUD_ENTITY", Sql.SqlCreateTableBuilder.ForeignKeyBehaviour.ON_DELETE_SET_NULL) //
|
||||||
.executeOn(db)
|
.executeOn(db)
|
||||||
|
|
||||||
Sql.insertInto("VAULT_ENTITY") //
|
Sql.insertInto("VAULT_ENTITY") //
|
||||||
.select("_id", "FOLDER_CLOUD_ID", "FOLDER_PATH", "FOLDER_NAME", "PASSWORD", "POSITION", "CLOUD_ENTITY.TYPE") //
|
.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") //
|
.columns("_id", "FOLDER_CLOUD_ID", "FOLDER_PATH", "FOLDER_NAME", "PASSWORD", "POSITION", "CLOUD_TYPE") //
|
||||||
.from("VAULT_ENTITY_OLD") //
|
.from("VAULT_ENTITY_OLD") //
|
||||||
.join("CLOUD_ENTITY", "VAULT_ENTITY_OLD.FOLDER_CLOUD_ID") //
|
.join("CLOUD_ENTITY", "VAULT_ENTITY_OLD.FOLDER_CLOUD_ID") //
|
||||||
.executeOn(db)
|
.executeOn(db)
|
||||||
|
|
||||||
Sql.dropIndex("IDX_VAULT_ENTITY_FOLDER_PATH_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") //
|
Sql.createUniqueIndex("IDX_VAULT_ENTITY_FOLDER_PATH_FOLDER_CLOUD_ID") //
|
||||||
.on("VAULT_ENTITY") //
|
.on("VAULT_ENTITY") //
|
||||||
.asc("FOLDER_PATH") //
|
.asc("FOLDER_PATH") //
|
||||||
.asc("FOLDER_CLOUD_ID") //
|
.asc("FOLDER_CLOUD_ID") //
|
||||||
.executeOn(db)
|
.executeOn(db)
|
||||||
|
|
||||||
Sql.dropTable("VAULT_ENTITY_OLD").executeOn(db)
|
Sql.dropTable("VAULT_ENTITY_OLD").executeOn(db)
|
||||||
}
|
}
|
||||||
|
@ -21,22 +21,22 @@ internal class Upgrade5To6 @Inject constructor() : DatabaseUpgrade(5, 6) {
|
|||||||
Sql.alterTable("CLOUD_ENTITY").renameTo("CLOUD_ENTITY_OLD").executeOn(db)
|
Sql.alterTable("CLOUD_ENTITY").renameTo("CLOUD_ENTITY_OLD").executeOn(db)
|
||||||
|
|
||||||
Sql.createTable("CLOUD_ENTITY") //
|
Sql.createTable("CLOUD_ENTITY") //
|
||||||
.id() //
|
.id() //
|
||||||
.requiredText("TYPE") //
|
.requiredText("TYPE") //
|
||||||
.optionalText("ACCESS_TOKEN") //
|
.optionalText("ACCESS_TOKEN") //
|
||||||
.optionalText("URL") //
|
.optionalText("URL") //
|
||||||
.optionalText("USERNAME") //
|
.optionalText("USERNAME") //
|
||||||
.optionalText("WEBDAV_CERTIFICATE") //
|
.optionalText("WEBDAV_CERTIFICATE") //
|
||||||
.optionalText("S3_BUCKET") //
|
.optionalText("S3_BUCKET") //
|
||||||
.optionalText("S3_REGION") //
|
.optionalText("S3_REGION") //
|
||||||
.optionalText("S3_SECRET_KEY") //
|
.optionalText("S3_SECRET_KEY") //
|
||||||
.executeOn(db);
|
.executeOn(db);
|
||||||
|
|
||||||
Sql.insertInto("CLOUD_ENTITY") //
|
Sql.insertInto("CLOUD_ENTITY") //
|
||||||
.select("_id", "TYPE", "ACCESS_TOKEN", "URL", "USERNAME", "WEBDAV_CERTIFICATE") //
|
.select("_id", "TYPE", "ACCESS_TOKEN", "URL", "USERNAME", "WEBDAV_CERTIFICATE") //
|
||||||
.columns("_id", "TYPE", "ACCESS_TOKEN", "URL", "USERNAME", "WEBDAV_CERTIFICATE") //
|
.columns("_id", "TYPE", "ACCESS_TOKEN", "URL", "USERNAME", "WEBDAV_CERTIFICATE") //
|
||||||
.from("CLOUD_ENTITY_OLD") //
|
.from("CLOUD_ENTITY_OLD") //
|
||||||
.executeOn(db)
|
.executeOn(db)
|
||||||
|
|
||||||
recreateVaultEntity(db)
|
recreateVaultEntity(db)
|
||||||
|
|
||||||
@ -46,30 +46,30 @@ internal class Upgrade5To6 @Inject constructor() : DatabaseUpgrade(5, 6) {
|
|||||||
private fun recreateVaultEntity(db: Database) {
|
private fun recreateVaultEntity(db: Database) {
|
||||||
Sql.alterTable("VAULT_ENTITY").renameTo("VAULT_ENTITY_OLD").executeOn(db)
|
Sql.alterTable("VAULT_ENTITY").renameTo("VAULT_ENTITY_OLD").executeOn(db)
|
||||||
Sql.createTable("VAULT_ENTITY") //
|
Sql.createTable("VAULT_ENTITY") //
|
||||||
.id() //
|
.id() //
|
||||||
.optionalInt("FOLDER_CLOUD_ID") //
|
.optionalInt("FOLDER_CLOUD_ID") //
|
||||||
.optionalText("FOLDER_PATH") //
|
.optionalText("FOLDER_PATH") //
|
||||||
.optionalText("FOLDER_NAME") //
|
.optionalText("FOLDER_NAME") //
|
||||||
.requiredText("CLOUD_TYPE") //
|
.requiredText("CLOUD_TYPE") //
|
||||||
.optionalText("PASSWORD") //
|
.optionalText("PASSWORD") //
|
||||||
.optionalInt("POSITION") //
|
.optionalInt("POSITION") //
|
||||||
.foreignKey("FOLDER_CLOUD_ID", "CLOUD_ENTITY", Sql.SqlCreateTableBuilder.ForeignKeyBehaviour.ON_DELETE_SET_NULL) //
|
.foreignKey("FOLDER_CLOUD_ID", "CLOUD_ENTITY", Sql.SqlCreateTableBuilder.ForeignKeyBehaviour.ON_DELETE_SET_NULL) //
|
||||||
.executeOn(db)
|
.executeOn(db)
|
||||||
|
|
||||||
Sql.insertInto("VAULT_ENTITY") //
|
Sql.insertInto("VAULT_ENTITY") //
|
||||||
.select("_id", "FOLDER_CLOUD_ID", "FOLDER_PATH", "FOLDER_NAME", "PASSWORD", "POSITION", "CLOUD_ENTITY.TYPE") //
|
.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") //
|
.columns("_id", "FOLDER_CLOUD_ID", "FOLDER_PATH", "FOLDER_NAME", "PASSWORD", "POSITION", "CLOUD_TYPE") //
|
||||||
.from("VAULT_ENTITY_OLD") //
|
.from("VAULT_ENTITY_OLD") //
|
||||||
.join("CLOUD_ENTITY", "VAULT_ENTITY_OLD.FOLDER_CLOUD_ID") //
|
.join("CLOUD_ENTITY", "VAULT_ENTITY_OLD.FOLDER_CLOUD_ID") //
|
||||||
.executeOn(db)
|
.executeOn(db)
|
||||||
|
|
||||||
Sql.dropIndex("IDX_VAULT_ENTITY_FOLDER_PATH_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") //
|
Sql.createUniqueIndex("IDX_VAULT_ENTITY_FOLDER_PATH_FOLDER_CLOUD_ID") //
|
||||||
.on("VAULT_ENTITY") //
|
.on("VAULT_ENTITY") //
|
||||||
.asc("FOLDER_PATH") //
|
.asc("FOLDER_PATH") //
|
||||||
.asc("FOLDER_CLOUD_ID") //
|
.asc("FOLDER_CLOUD_ID") //
|
||||||
.executeOn(db)
|
.executeOn(db)
|
||||||
|
|
||||||
Sql.dropTable("VAULT_ENTITY_OLD").executeOn(db)
|
Sql.dropTable("VAULT_ENTITY_OLD").executeOn(db)
|
||||||
}
|
}
|
||||||
|
@ -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.alterTable("UPDATE_CHECK_ENTITY").renameTo("UPDATE_CHECK_ENTITY_OLD").executeOn(db)
|
||||||
|
|
||||||
Sql.createTable("UPDATE_CHECK_ENTITY") //
|
Sql.createTable("UPDATE_CHECK_ENTITY") //
|
||||||
.id() //
|
.id() //
|
||||||
.optionalText("LICENSE_TOKEN") //
|
.optionalText("LICENSE_TOKEN") //
|
||||||
.optionalText("RELEASE_NOTE") //
|
.optionalText("RELEASE_NOTE") //
|
||||||
.optionalText("VERSION") //
|
.optionalText("VERSION") //
|
||||||
.optionalText("URL_TO_APK") //
|
.optionalText("URL_TO_APK") //
|
||||||
.optionalText("APK_SHA256") //
|
.optionalText("APK_SHA256") //
|
||||||
.optionalText("URL_TO_RELEASE_NOTE") //
|
.optionalText("URL_TO_RELEASE_NOTE") //
|
||||||
.executeOn(db)
|
.executeOn(db)
|
||||||
|
|
||||||
Sql.insertInto("UPDATE_CHECK_ENTITY") //
|
Sql.insertInto("UPDATE_CHECK_ENTITY") //
|
||||||
.select("_id", "LICENSE_TOKEN", "RELEASE_NOTE", "VERSION", "URL_TO_APK", "URL_TO_RELEASE_NOTE") //
|
.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") //
|
.columns("_id", "LICENSE_TOKEN", "RELEASE_NOTE", "VERSION", "URL_TO_APK", "URL_TO_RELEASE_NOTE") //
|
||||||
.from("UPDATE_CHECK_ENTITY_OLD") //
|
.from("UPDATE_CHECK_ENTITY_OLD") //
|
||||||
.executeOn(db)
|
.executeOn(db)
|
||||||
|
|
||||||
Sql.dropTable("UPDATE_CHECK_ENTITY_OLD").executeOn(db)
|
Sql.dropTable("UPDATE_CHECK_ENTITY_OLD").executeOn(db)
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,7 @@ public class UpdateCheckEntity extends DatabaseEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Generated(hash = 67239496)
|
@Generated(hash = 67239496)
|
||||||
public UpdateCheckEntity(Long id, String licenseToken, String releaseNote, String version, String urlToApk, String apkSha256,
|
public UpdateCheckEntity(Long id, String licenseToken, String releaseNote, String version, String urlToApk, String apkSha256, String urlToReleaseNote) {
|
||||||
String urlToReleaseNote) {
|
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.licenseToken = licenseToken;
|
this.licenseToken = licenseToken;
|
||||||
this.releaseNote = releaseNote;
|
this.releaseNote = releaseNote;
|
||||||
|
@ -182,7 +182,9 @@ public class VaultEntity extends DatabaseEntity {
|
|||||||
this.position = position;
|
this.position = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** called by internal mechanisms, do not call yourself. */
|
/**
|
||||||
|
* called by internal mechanisms, do not call yourself.
|
||||||
|
*/
|
||||||
@Generated(hash = 674742652)
|
@Generated(hash = 674742652)
|
||||||
public void __setDaoSession(DaoSession daoSession) {
|
public void __setDaoSession(DaoSession daoSession) {
|
||||||
this.daoSession = daoSession;
|
this.daoSession = daoSession;
|
||||||
|
@ -120,7 +120,7 @@ public class UpdateCheckRepositoryImpl implements UpdateCheckRepository {
|
|||||||
|
|
||||||
String apkSha256 = calculateSha256(file);
|
String apkSha256 = calculateSha256(file);
|
||||||
|
|
||||||
if(!apkSha256.equals(entity.getApkSha256())) {
|
if (!apkSha256.equals(entity.getApkSha256())) {
|
||||||
file.delete();
|
file.delete();
|
||||||
throw new HashMismatchUpdateCheckException(String.format( //
|
throw new HashMismatchUpdateCheckException(String.format( //
|
||||||
"Sha of calculated hash (%s) doesn't match the specified one (%s)", //
|
"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 {
|
private String calculateSha256(File file) throws GeneralUpdateErrorException {
|
||||||
try {
|
try {
|
||||||
MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
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];
|
byte[] buffer = new byte[8192];
|
||||||
while(digestInputStream.read(buffer) > -1) {
|
while (digestInputStream.read(buffer) > -1) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new String(Hex.encodeHex(digest.digest()));
|
return new String(Hex.encodeHex(digest.digest()));
|
||||||
|
@ -3,4 +3,5 @@ package org.cryptomator.domain.exception.vaultconfig;
|
|||||||
import org.cryptomator.domain.exception.BackendException;
|
import org.cryptomator.domain.exception.BackendException;
|
||||||
|
|
||||||
public class VaultKeyInvalidException extends BackendException {
|
public class VaultKeyInvalidException extends BackendException {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,8 @@ class ChangePassword {
|
|||||||
private final Vault vault;
|
private final Vault vault;
|
||||||
private final Optional<UnverifiedVaultConfig> unverifiedVaultConfig;
|
private final Optional<UnverifiedVaultConfig> unverifiedVaultConfig;
|
||||||
private final String oldPassword;
|
private final String oldPassword;
|
||||||
private final String newPassword;;
|
private final String newPassword;
|
||||||
|
;
|
||||||
|
|
||||||
public ChangePassword(CloudRepository cloudRepository, //
|
public ChangePassword(CloudRepository cloudRepository, //
|
||||||
@Parameter Vault vault, //
|
@Parameter Vault vault, //
|
||||||
|
@ -14,9 +14,8 @@ class UnlockVaultUsingMasterkey {
|
|||||||
|
|
||||||
private final CloudRepository cloudRepository;
|
private final CloudRepository cloudRepository;
|
||||||
private final VaultOrUnlockToken vaultOrUnlockToken;
|
private final VaultOrUnlockToken vaultOrUnlockToken;
|
||||||
private Optional<UnverifiedVaultConfig> unverifiedVaultConfig;
|
|
||||||
private final String password;
|
private final String password;
|
||||||
|
private Optional<UnverifiedVaultConfig> unverifiedVaultConfig;
|
||||||
private volatile boolean cancelled;
|
private volatile boolean cancelled;
|
||||||
private final Flag cancelledFlag = new Flag() {
|
private final Flag cancelledFlag = new Flag() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -61,21 +61,22 @@ import timber.log.Timber
|
|||||||
|
|
||||||
@PerView
|
@PerView
|
||||||
class AuthenticateCloudPresenter @Inject constructor( //
|
class AuthenticateCloudPresenter @Inject constructor( //
|
||||||
exceptionHandlers: ExceptionHandlers, //
|
exceptionHandlers: ExceptionHandlers, //
|
||||||
private val cloudModelMapper: CloudModelMapper, //
|
private val cloudModelMapper: CloudModelMapper, //
|
||||||
private val addOrChangeCloudConnectionUseCase: AddOrChangeCloudConnectionUseCase, //
|
private val addOrChangeCloudConnectionUseCase: AddOrChangeCloudConnectionUseCase, //
|
||||||
private val getCloudsUseCase: GetCloudsUseCase, //
|
private val getCloudsUseCase: GetCloudsUseCase, //
|
||||||
private val getUsernameUseCase: GetUsernameUseCase, //
|
private val getUsernameUseCase: GetUsernameUseCase, //
|
||||||
private val addExistingVaultWorkflow: AddExistingVaultWorkflow, //
|
private val addExistingVaultWorkflow: AddExistingVaultWorkflow, //
|
||||||
private val createNewVaultWorkflow: CreateNewVaultWorkflow) : Presenter<AuthenticateCloudView>(exceptionHandlers) {
|
private val createNewVaultWorkflow: CreateNewVaultWorkflow
|
||||||
|
) : Presenter<AuthenticateCloudView>(exceptionHandlers) {
|
||||||
|
|
||||||
private val strategies = arrayOf( //
|
private val strategies = arrayOf( //
|
||||||
DropboxAuthStrategy(), //
|
DropboxAuthStrategy(), //
|
||||||
OnedriveAuthStrategy(), //
|
OnedriveAuthStrategy(), //
|
||||||
PCloudAuthStrategy(), //
|
PCloudAuthStrategy(), //
|
||||||
WebDAVAuthStrategy(), //
|
WebDAVAuthStrategy(), //
|
||||||
S3AuthStrategy(), //
|
S3AuthStrategy(), //
|
||||||
LocalStorageAuthStrategy() //
|
LocalStorageAuthStrategy() //
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun workflows(): Iterable<Workflow<*>> {
|
override fun workflows(): Iterable<Workflow<*>> {
|
||||||
@ -128,17 +129,17 @@ class AuthenticateCloudPresenter @Inject constructor( //
|
|||||||
|
|
||||||
private fun succeedAuthenticationWith(cloud: Cloud) {
|
private fun succeedAuthenticationWith(cloud: Cloud) {
|
||||||
addOrChangeCloudConnectionUseCase //
|
addOrChangeCloudConnectionUseCase //
|
||||||
.withCloud(cloud) //
|
.withCloud(cloud) //
|
||||||
.run(object : DefaultResultHandler<Void?>() {
|
.run(object : DefaultResultHandler<Void?>() {
|
||||||
override fun onSuccess(void: Void?) {
|
override fun onSuccess(void: Void?) {
|
||||||
finishWithResult(cloudModelMapper.toModel(cloud))
|
finishWithResult(cloudModelMapper.toModel(cloud))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
super.onError(e)
|
super.onError(e)
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun failAuthentication(cloudName: Int) {
|
private fun failAuthentication(cloudName: Int) {
|
||||||
@ -180,9 +181,10 @@ class AuthenticateCloudPresenter @Inject constructor( //
|
|||||||
failAuthentication(cloudModel.name())
|
failAuthentication(cloudModel.name())
|
||||||
} else {
|
} else {
|
||||||
getUsernameAndSuceedAuthentication( //
|
getUsernameAndSuceedAuthentication( //
|
||||||
DropboxCloud.aCopyOf(cloudModel.toCloud() as DropboxCloud) //
|
DropboxCloud.aCopyOf(cloudModel.toCloud() as DropboxCloud) //
|
||||||
.withAccessToken(encrypt(authToken)) //
|
.withAccessToken(encrypt(authToken)) //
|
||||||
.build())
|
.build()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -200,10 +202,12 @@ class AuthenticateCloudPresenter @Inject constructor( //
|
|||||||
fun onGoogleDriveAuthenticated(result: ActivityResult, cloud: CloudModel) {
|
fun onGoogleDriveAuthenticated(result: ActivityResult, cloud: CloudModel) {
|
||||||
if (result.isResultOk) {
|
if (result.isResultOk) {
|
||||||
val accountName = result.intent()?.extras?.getString(AccountManager.KEY_ACCOUNT_NAME)
|
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) //
|
.withUsername(accountName) //
|
||||||
.withAccessToken(accountName) //
|
.withAccessToken(accountName) //
|
||||||
.build())
|
.build()
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
failAuthentication(cloud.name())
|
failAuthentication(cloud.name())
|
||||||
}
|
}
|
||||||
@ -245,9 +249,10 @@ class AuthenticateCloudPresenter @Inject constructor( //
|
|||||||
|
|
||||||
private fun handleAuthenticationResult(cloud: CloudModel, accessToken: String) {
|
private fun handleAuthenticationResult(cloud: CloudModel, accessToken: String) {
|
||||||
getUsernameAndSuceedAuthentication( //
|
getUsernameAndSuceedAuthentication( //
|
||||||
OnedriveCloud.aCopyOf(cloud.toCloud() as OnedriveCloud) //
|
OnedriveCloud.aCopyOf(cloud.toCloud() as OnedriveCloud) //
|
||||||
.withAccessToken(accessToken) //
|
.withAccessToken(accessToken) //
|
||||||
.build())
|
.build()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,9 +270,10 @@ class AuthenticateCloudPresenter @Inject constructor( //
|
|||||||
if (!authenticationStarted) {
|
if (!authenticationStarted) {
|
||||||
startAuthentication()
|
startAuthentication()
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
context(),
|
context(),
|
||||||
String.format(getString(R.string.error_authentication_failed_re_authenticate), intent.cloud().username()),
|
String.format(getString(R.string.error_authentication_failed_re_authenticate), intent.cloud().username()),
|
||||||
Toast.LENGTH_LONG).show()
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
@ -280,15 +286,18 @@ class AuthenticateCloudPresenter @Inject constructor( //
|
|||||||
private fun startAuthentication() {
|
private fun startAuthentication() {
|
||||||
authenticationStarted = true
|
authenticationStarted = true
|
||||||
val authIntent: Intent = AuthorizationActivity.createIntent(
|
val authIntent: Intent = AuthorizationActivity.createIntent(
|
||||||
context(),
|
context(),
|
||||||
AuthorizationRequest.create()
|
AuthorizationRequest.create()
|
||||||
.setType(AuthorizationRequest.Type.TOKEN)
|
.setType(AuthorizationRequest.Type.TOKEN)
|
||||||
.setClientId(BuildConfig.PCLOUD_CLIENT_ID)
|
.setClientId(BuildConfig.PCLOUD_CLIENT_ID)
|
||||||
.setForceAccessApproval(true)
|
.setForceAccessApproval(true)
|
||||||
.addPermission("manageshares")
|
.addPermission("manageshares")
|
||||||
.build())
|
.build()
|
||||||
requestActivityResult(ActivityResultCallbacks.pCloudReAuthenticationFinished(), //
|
)
|
||||||
authIntent)
|
requestActivityResult(
|
||||||
|
ActivityResultCallbacks.pCloudReAuthenticationFinished(), //
|
||||||
|
authIntent
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,19 +309,19 @@ class AuthenticateCloudPresenter @Inject constructor( //
|
|||||||
when (result) {
|
when (result) {
|
||||||
AuthorizationResult.ACCESS_GRANTED -> {
|
AuthorizationResult.ACCESS_GRANTED -> {
|
||||||
val accessToken: String = CredentialCryptor //
|
val accessToken: String = CredentialCryptor //
|
||||||
.getInstance(context()) //
|
.getInstance(context()) //
|
||||||
.encrypt(authData.token)
|
.encrypt(authData.token)
|
||||||
val pCloudSkeleton: PCloud = PCloud.aPCloud() //
|
val pCloudSkeleton: PCloud = PCloud.aPCloud() //
|
||||||
.withAccessToken(accessToken)
|
.withAccessToken(accessToken)
|
||||||
.withUrl(authData.apiHost)
|
.withUrl(authData.apiHost)
|
||||||
.build();
|
.build();
|
||||||
getUsernameUseCase //
|
getUsernameUseCase //
|
||||||
.withCloud(pCloudSkeleton) //
|
.withCloud(pCloudSkeleton) //
|
||||||
.run(object : DefaultResultHandler<String>() {
|
.run(object : DefaultResultHandler<String>() {
|
||||||
override fun onSuccess(username: String?) {
|
override fun onSuccess(username: String?) {
|
||||||
prepareForSavingPCloud(PCloud.aCopyOf(pCloudSkeleton).withUsername(username).build())
|
prepareForSavingPCloud(PCloud.aCopyOf(pCloudSkeleton).withUsername(username).build())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
AuthorizationResult.ACCESS_DENIED -> {
|
AuthorizationResult.ACCESS_DENIED -> {
|
||||||
Timber.tag("CloudConnListPresenter").e("Account access denied")
|
Timber.tag("CloudConnListPresenter").e("Account access denied")
|
||||||
@ -331,20 +340,22 @@ class AuthenticateCloudPresenter @Inject constructor( //
|
|||||||
|
|
||||||
fun prepareForSavingPCloud(cloud: PCloud) {
|
fun prepareForSavingPCloud(cloud: PCloud) {
|
||||||
getCloudsUseCase //
|
getCloudsUseCase //
|
||||||
.withCloudType(cloud.type()) //
|
.withCloudType(cloud.type()) //
|
||||||
.run(object : DefaultResultHandler<List<Cloud>>() {
|
.run(object : DefaultResultHandler<List<Cloud>>() {
|
||||||
override fun onSuccess(clouds: List<Cloud>) {
|
override fun onSuccess(clouds: List<Cloud>) {
|
||||||
clouds.firstOrNull {
|
clouds.firstOrNull {
|
||||||
(it as PCloud).username() == cloud.username()
|
(it as PCloud).username() == cloud.username()
|
||||||
}?.let {
|
}?.let {
|
||||||
it as PCloud
|
it as PCloud
|
||||||
succeedAuthenticationWith(PCloud.aCopyOf(it) //
|
succeedAuthenticationWith(
|
||||||
.withUrl(cloud.url())
|
PCloud.aCopyOf(it) //
|
||||||
.withAccessToken(cloud.accessToken())
|
.withUrl(cloud.url())
|
||||||
.build())
|
.withAccessToken(cloud.accessToken())
|
||||||
} ?: succeedAuthenticationWith(cloud)
|
.build()
|
||||||
}
|
)
|
||||||
})
|
} ?: succeedAuthenticationWith(cloud)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class WebDAVAuthStrategy : AuthStrategy {
|
private inner class WebDAVAuthStrategy : AuthStrategy {
|
||||||
@ -392,11 +403,13 @@ class AuthenticateCloudPresenter @Inject constructor( //
|
|||||||
fun onAcceptWebDavCertificateClicked(cloud: WebDavCloud?, certificate: X509Certificate?) {
|
fun onAcceptWebDavCertificateClicked(cloud: WebDavCloud?, certificate: X509Certificate?) {
|
||||||
try {
|
try {
|
||||||
val webDavCloudWithAcceptedCert = WebDavCloud.aCopyOf(cloud) //
|
val webDavCloudWithAcceptedCert = WebDavCloud.aCopyOf(cloud) //
|
||||||
.withCertificate(X509CertificateHelper.convertToPem(certificate)) //
|
.withCertificate(X509CertificateHelper.convertToPem(certificate)) //
|
||||||
.build()
|
.build()
|
||||||
finishWithResultAndExtra(cloudModelMapper.toModel(webDavCloudWithAcceptedCert), //
|
finishWithResultAndExtra(
|
||||||
WEBDAV_ACCEPTED_UNTRUSTED_CERTIFICATE, //
|
cloudModelMapper.toModel(webDavCloudWithAcceptedCert), //
|
||||||
true)
|
WEBDAV_ACCEPTED_UNTRUSTED_CERTIFICATE, //
|
||||||
|
true
|
||||||
|
)
|
||||||
} catch (e: CertificateEncodingException) {
|
} catch (e: CertificateEncodingException) {
|
||||||
Timber.tag("AuthicateCloudPrester").e(e)
|
Timber.tag("AuthicateCloudPrester").e(e)
|
||||||
throw FatalBackendException(e)
|
throw FatalBackendException(e)
|
||||||
@ -421,9 +434,10 @@ class AuthenticateCloudPresenter @Inject constructor( //
|
|||||||
if (!authenticationStarted) {
|
if (!authenticationStarted) {
|
||||||
startAuthentication(intent.cloud())
|
startAuthentication(intent.cloud())
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
context(),
|
context(),
|
||||||
String.format(getString(R.string.error_authentication_failed), intent.cloud().username()),
|
String.format(getString(R.string.error_authentication_failed), intent.cloud().username()),
|
||||||
Toast.LENGTH_LONG).show()
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
@ -454,10 +468,12 @@ class AuthenticateCloudPresenter @Inject constructor( //
|
|||||||
|
|
||||||
private fun startAuthentication(cloud: CloudModel) {
|
private fun startAuthentication(cloud: CloudModel) {
|
||||||
authenticationStarted = true
|
authenticationStarted = true
|
||||||
requestPermissions(PermissionsResultCallbacks.onLocalStorageAuthenticated(cloud), //
|
requestPermissions(
|
||||||
R.string.permission_snackbar_auth_local_vault, //
|
PermissionsResultCallbacks.onLocalStorageAuthenticated(cloud), //
|
||||||
Manifest.permission.READ_EXTERNAL_STORAGE, //
|
R.string.permission_snackbar_auth_local_vault, //
|
||||||
Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
Manifest.permission.READ_EXTERNAL_STORAGE, //
|
||||||
|
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -472,8 +488,8 @@ class AuthenticateCloudPresenter @Inject constructor( //
|
|||||||
|
|
||||||
private fun encrypt(password: String): String {
|
private fun encrypt(password: String): String {
|
||||||
return CredentialCryptor //
|
return CredentialCryptor //
|
||||||
.getInstance(context()) //
|
.getInstance(context()) //
|
||||||
.encrypt(password)
|
.encrypt(password)
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class FailingAuthStrategy : AuthStrategy {
|
private inner class FailingAuthStrategy : AuthStrategy {
|
||||||
|
@ -97,9 +97,10 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity android:name=".ui.activity.UnlockVaultActivity"
|
<activity
|
||||||
android:theme="@style/TransparentAlertDialogCustom"
|
android:name=".ui.activity.UnlockVaultActivity"
|
||||||
android:label=""/>
|
android:label=""
|
||||||
|
android:theme="@style/TransparentAlertDialogCustom" />
|
||||||
<activity android:name=".ui.activity.EmptyDirIdFileInfoActivity" />
|
<activity android:name=".ui.activity.EmptyDirIdFileInfoActivity" />
|
||||||
|
|
||||||
<!-- Settings -->
|
<!-- Settings -->
|
||||||
|
@ -51,10 +51,12 @@ class CryptomatorApp : MultiDexApplication(), HasComponent<ApplicationComponent>
|
|||||||
}
|
}
|
||||||
else -> "Google Play Edition"
|
else -> "Google Play Edition"
|
||||||
}
|
}
|
||||||
Timber.tag("App").i("Cryptomator v%s (%d) \"%s\" started on android %s / API%d using a %s", //
|
Timber.tag("App").i(
|
||||||
BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE, flavor, //
|
"Cryptomator v%s (%d) \"%s\" started on android %s / API%d using a %s", //
|
||||||
Build.VERSION.RELEASE, Build.VERSION.SDK_INT, //
|
BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE, flavor, //
|
||||||
Build.MODEL)
|
Build.VERSION.RELEASE, Build.VERSION.SDK_INT, //
|
||||||
|
Build.MODEL
|
||||||
|
)
|
||||||
Timber.tag("App").d("appId %s", BuildConfig.APPLICATION_ID)
|
Timber.tag("App").d("appId %s", BuildConfig.APPLICATION_ID)
|
||||||
|
|
||||||
launchServices()
|
launchServices()
|
||||||
@ -105,10 +107,11 @@ class CryptomatorApp : MultiDexApplication(), HasComponent<ApplicationComponent>
|
|||||||
Timber.tag("App").i("Auto upload service connected")
|
Timber.tag("App").i("Auto upload service connected")
|
||||||
autoUploadServiceBinder = service as AutoUploadService.Binder
|
autoUploadServiceBinder = service as AutoUploadService.Binder
|
||||||
autoUploadServiceBinder.init( //
|
autoUploadServiceBinder.init( //
|
||||||
applicationComponent.cloudContentRepository(), //
|
applicationComponent.cloudContentRepository(), //
|
||||||
applicationComponent.fileUtil(), //
|
applicationComponent.fileUtil(), //
|
||||||
applicationComponent.contentResolverUtil(), //
|
applicationComponent.contentResolverUtil(), //
|
||||||
Companion.applicationContext)
|
Companion.applicationContext
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onServiceDisconnected(name: ComponentName) {
|
override fun onServiceDisconnected(name: ComponentName) {
|
||||||
@ -124,11 +127,11 @@ class CryptomatorApp : MultiDexApplication(), HasComponent<ApplicationComponent>
|
|||||||
|
|
||||||
private fun initializeInjector() {
|
private fun initializeInjector() {
|
||||||
applicationComponent = DaggerApplicationComponent.builder() //
|
applicationComponent = DaggerApplicationComponent.builder() //
|
||||||
.applicationModule(ApplicationModule(this)) //
|
.applicationModule(ApplicationModule(this)) //
|
||||||
.threadModule(ThreadModule()) //
|
.threadModule(ThreadModule()) //
|
||||||
.repositoryModule(RepositoryModule()) //
|
.repositoryModule(RepositoryModule()) //
|
||||||
.cryptorsModule(CryptorsModule(appCryptors)) //
|
.cryptorsModule(CryptorsModule(appCryptors)) //
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun cleanupCache() {
|
private fun cleanupCache() {
|
||||||
|
@ -15,7 +15,7 @@ class MissingCryptorExceptionHandler : ExceptionHandler() {
|
|||||||
public override fun doHandle(view: View, e: Throwable) {
|
public override fun doHandle(view: View, e: Throwable) {
|
||||||
view.showMessage(R.string.error_vault_has_been_locked)
|
view.showMessage(R.string.error_vault_has_been_locked)
|
||||||
Intents.vaultListIntent() //
|
Intents.vaultListIntent() //
|
||||||
.preventGoingBackInHistory() //
|
.preventGoingBackInHistory() //
|
||||||
.startActivity(view)
|
.startActivity(view)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,10 +12,7 @@ public interface UnlockVaultIntent {
|
|||||||
VaultAction vaultAction();
|
VaultAction vaultAction();
|
||||||
|
|
||||||
enum VaultAction {
|
enum VaultAction {
|
||||||
UNLOCK,
|
UNLOCK, UNLOCK_FOR_BIOMETRIC_AUTH, ENCRYPT_PASSWORD, CHANGE_PASSWORD
|
||||||
UNLOCK_FOR_BIOMETRIC_AUTH,
|
|
||||||
ENCRYPT_PASSWORD,
|
|
||||||
CHANGE_PASSWORD
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ object Logfiles {
|
|||||||
* Maximum size of all logfiles
|
* Maximum size of all logfiles
|
||||||
*/
|
*/
|
||||||
private const val MAX_LOGS_SIZE = (1 shl 20 // 1 MiB
|
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
|
* When this size is reached a logfile is rotated
|
||||||
|
@ -8,14 +8,14 @@ import timber.log.Timber
|
|||||||
class ReleaseLogger(context: Context) : Timber.Tree() {
|
class ReleaseLogger(context: Context) : Timber.Tree() {
|
||||||
|
|
||||||
private val priorityNames = charArrayOf( //
|
private val priorityNames = charArrayOf( //
|
||||||
'?', //
|
'?', //
|
||||||
'?', //
|
'?', //
|
||||||
'V', //
|
'V', //
|
||||||
'D', //
|
'D', //
|
||||||
'I', //
|
'I', //
|
||||||
'W', //
|
'W', //
|
||||||
'E', //
|
'E', //
|
||||||
'A' //
|
'A' //
|
||||||
)
|
)
|
||||||
private val log: LogRotator
|
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?) {
|
override fun log(priority: Int, tag: String?, message: String, throwable: Throwable?) {
|
||||||
val line = StringBuilder()
|
val line = StringBuilder()
|
||||||
line //
|
line //
|
||||||
.append(priorityNames[validPriority(priority)]).append('\t') //
|
.append(priorityNames[validPriority(priority)]).append('\t') //
|
||||||
.append(FormattedTime.now()).append('\t') //
|
.append(FormattedTime.now()).append('\t') //
|
||||||
.append(tag ?: "App").append('\t') //
|
.append(tag ?: "App").append('\t') //
|
||||||
.append(message)
|
.append(message)
|
||||||
if (throwable != null) {
|
if (throwable != null) {
|
||||||
line.append("\nErrorCode: ").append(GeneratedErrorCode.of(throwable))
|
line.append("\nErrorCode: ").append(GeneratedErrorCode.of(throwable))
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ package org.cryptomator.presentation.model
|
|||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
|
||||||
data class AutoUploadFilesStore(
|
data class AutoUploadFilesStore(
|
||||||
val uris: Set<String>
|
val uris: Set<String>
|
||||||
) : Serializable {
|
) : Serializable {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -6,38 +6,52 @@ import org.cryptomator.presentation.R
|
|||||||
enum class CloudTypeModel(builder: Builder) {
|
enum class CloudTypeModel(builder: Builder) {
|
||||||
|
|
||||||
CRYPTO(Builder("CRYPTO", R.string.cloud_names_crypto)), //
|
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) //
|
.withCloudImageResource(R.drawable.dropbox) //
|
||||||
.withVaultImageResource(R.drawable.dropbox_vault) //
|
.withVaultImageResource(R.drawable.dropbox_vault) //
|
||||||
.withVaultSelectedImageResource(R.drawable.dropbox_vault_selected)), //
|
.withVaultSelectedImageResource(R.drawable.dropbox_vault_selected)
|
||||||
GOOGLE_DRIVE(Builder("GOOGLE_DRIVE", R.string.cloud_names_google_drive) //
|
), //
|
||||||
|
GOOGLE_DRIVE(
|
||||||
|
Builder("GOOGLE_DRIVE", R.string.cloud_names_google_drive) //
|
||||||
.withCloudImageResource(R.drawable.google_drive) //
|
.withCloudImageResource(R.drawable.google_drive) //
|
||||||
.withVaultImageResource(R.drawable.google_drive_vault) //
|
.withVaultImageResource(R.drawable.google_drive_vault) //
|
||||||
.withVaultSelectedImageResource(R.drawable.google_drive_vault_selected)), //
|
.withVaultSelectedImageResource(R.drawable.google_drive_vault_selected)
|
||||||
ONEDRIVE(Builder("ONEDRIVE", R.string.cloud_names_onedrive) //
|
), //
|
||||||
|
ONEDRIVE(
|
||||||
|
Builder("ONEDRIVE", R.string.cloud_names_onedrive) //
|
||||||
.withCloudImageResource(R.drawable.onedrive) //
|
.withCloudImageResource(R.drawable.onedrive) //
|
||||||
.withVaultImageResource(R.drawable.onedrive_vault) //
|
.withVaultImageResource(R.drawable.onedrive_vault) //
|
||||||
.withVaultSelectedImageResource(R.drawable.onedrive_vault_selected)), //
|
.withVaultSelectedImageResource(R.drawable.onedrive_vault_selected)
|
||||||
PCLOUD(Builder("PCLOUD", R.string.cloud_names_pcloud) //
|
), //
|
||||||
|
PCLOUD(
|
||||||
|
Builder("PCLOUD", R.string.cloud_names_pcloud) //
|
||||||
.withCloudImageResource(R.drawable.pcloud) //
|
.withCloudImageResource(R.drawable.pcloud) //
|
||||||
.withVaultImageResource(R.drawable.pcloud_vault) //
|
.withVaultImageResource(R.drawable.pcloud_vault) //
|
||||||
.withVaultSelectedImageResource(R.drawable.pcloud_vault_selected) //
|
.withVaultSelectedImageResource(R.drawable.pcloud_vault_selected) //
|
||||||
.withMultiInstances()), //
|
.withMultiInstances()
|
||||||
WEBDAV(Builder("WEBDAV", R.string.cloud_names_webdav) //
|
), //
|
||||||
|
WEBDAV(
|
||||||
|
Builder("WEBDAV", R.string.cloud_names_webdav) //
|
||||||
.withCloudImageResource(R.drawable.webdav) //
|
.withCloudImageResource(R.drawable.webdav) //
|
||||||
.withVaultImageResource(R.drawable.webdav_vault) //
|
.withVaultImageResource(R.drawable.webdav_vault) //
|
||||||
.withVaultSelectedImageResource(R.drawable.webdav_vault_selected) //
|
.withVaultSelectedImageResource(R.drawable.webdav_vault_selected) //
|
||||||
.withMultiInstances()), //
|
.withMultiInstances()
|
||||||
S3(Builder("S3", R.string.cloud_names_s3) //
|
), //
|
||||||
|
S3(
|
||||||
|
Builder("S3", R.string.cloud_names_s3) //
|
||||||
.withCloudImageResource(R.drawable.s3) //
|
.withCloudImageResource(R.drawable.s3) //
|
||||||
.withVaultImageResource(R.drawable.s3_vault) //
|
.withVaultImageResource(R.drawable.s3_vault) //
|
||||||
.withVaultSelectedImageResource(R.drawable.s3_vault_selected) //
|
.withVaultSelectedImageResource(R.drawable.s3_vault_selected) //
|
||||||
.withMultiInstances()), //
|
.withMultiInstances()
|
||||||
LOCAL(Builder("LOCAL", R.string.cloud_names_local_storage) //
|
), //
|
||||||
|
LOCAL(
|
||||||
|
Builder("LOCAL", R.string.cloud_names_local_storage) //
|
||||||
.withCloudImageResource(R.drawable.local_fs) //
|
.withCloudImageResource(R.drawable.local_fs) //
|
||||||
.withVaultImageResource(R.drawable.local_fs_vault) //
|
.withVaultImageResource(R.drawable.local_fs_vault) //
|
||||||
.withVaultSelectedImageResource(R.drawable.local_fs_vault_selected) //
|
.withVaultSelectedImageResource(R.drawable.local_fs_vault_selected) //
|
||||||
.withMultiInstances());
|
.withMultiInstances()
|
||||||
|
);
|
||||||
|
|
||||||
val cloudName: String = builder.cloudName
|
val cloudName: String = builder.cloudName
|
||||||
val displayNameResource: Int = builder.displayNameResource
|
val displayNameResource: Int = builder.displayNameResource
|
||||||
|
@ -8,6 +8,6 @@ import kotlinx.android.parcel.Parcelize
|
|||||||
@Parcelize
|
@Parcelize
|
||||||
@SuppressLint("ParcelCreator")
|
@SuppressLint("ParcelCreator")
|
||||||
data class ImagePreviewFile(
|
data class ImagePreviewFile(
|
||||||
val cloudFileModel: CloudFileModel,
|
val cloudFileModel: CloudFileModel,
|
||||||
var uri: Uri?
|
var uri: Uri?
|
||||||
) : Parcelable
|
) : Parcelable
|
||||||
|
@ -3,6 +3,6 @@ package org.cryptomator.presentation.model
|
|||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
|
||||||
data class ImagePreviewFilesStore(
|
data class ImagePreviewFilesStore(
|
||||||
val cloudFileModels: ArrayList<CloudFileModel>,
|
val cloudFileModels: ArrayList<CloudFileModel>,
|
||||||
var index: Int
|
var index: Int
|
||||||
) : Serializable
|
) : Serializable
|
||||||
|
@ -31,21 +31,29 @@ class ProgressStateModelMapper @Inject internal constructor(private val fileUtil
|
|||||||
|
|
||||||
fun toModel(state: UploadState): ProgressStateModel {
|
fun toModel(state: UploadState): ProgressStateModel {
|
||||||
return if (state.isUpload) {
|
return if (state.isUpload) {
|
||||||
FileProgressStateModel(state.file(), FileIcon.fileIconFor(state.file().name, fileUtil), FileProgressStateModel.UPLOAD, ProgressStateModel.image(R.drawable.ic_file_upload),
|
FileProgressStateModel(
|
||||||
ProgressStateModel.text(R.string.dialog_progress_upload_file))
|
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 {
|
} else {
|
||||||
FileProgressStateModel(state.file(), FileIcon.fileIconFor(state.file().name, fileUtil), FileProgressStateModel.ENCRYPTION, ProgressStateModel.image(R.drawable.ic_lock_closed),
|
FileProgressStateModel(
|
||||||
ProgressStateModel.text(R.string.dialog_progress_encryption))
|
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 {
|
fun toModel(state: DownloadState): ProgressStateModel {
|
||||||
return if (state.isDownload) {
|
return if (state.isDownload) {
|
||||||
FileProgressStateModel(state.file(), FileIcon.fileIconFor(state.file().name, fileUtil), FileProgressStateModel.DOWNLOAD, ProgressStateModel.image(R.drawable.ic_file_download),
|
FileProgressStateModel(
|
||||||
ProgressStateModel.text(R.string.dialog_progress_download_file))
|
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 {
|
} else {
|
||||||
FileProgressStateModel(state.file(), FileIcon.fileIconFor(state.file().name, fileUtil), FileProgressStateModel.DECRYPTION, ProgressStateModel.image(R.drawable.ic_lock_open),
|
FileProgressStateModel(
|
||||||
ProgressStateModel.text(R.string.dialog_progress_decryption))
|
state.file(), FileIcon.fileIconFor(state.file().name, fileUtil), FileProgressStateModel.DECRYPTION, ProgressStateModel.image(R.drawable.ic_lock_open),
|
||||||
|
ProgressStateModel.text(R.string.dialog_progress_decryption)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,13 +26,14 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
@PerView
|
@PerView
|
||||||
class AutoUploadChooseVaultPresenter @Inject constructor( //
|
class AutoUploadChooseVaultPresenter @Inject constructor( //
|
||||||
private val getVaultListUseCase: GetVaultListUseCase, //
|
private val getVaultListUseCase: GetVaultListUseCase, //
|
||||||
private val getRootFolderUseCase: GetRootFolderUseCase, //
|
private val getRootFolderUseCase: GetRootFolderUseCase, //
|
||||||
private val getDecryptedCloudForVaultUseCase: GetDecryptedCloudForVaultUseCase, //
|
private val getDecryptedCloudForVaultUseCase: GetDecryptedCloudForVaultUseCase, //
|
||||||
private val cloudFolderModelMapper: CloudFolderModelMapper, //
|
private val cloudFolderModelMapper: CloudFolderModelMapper, //
|
||||||
private val sharedPreferencesHandler: SharedPreferencesHandler, //
|
private val sharedPreferencesHandler: SharedPreferencesHandler, //
|
||||||
private val authenticationExceptionHandler: AuthenticationExceptionHandler, //
|
private val authenticationExceptionHandler: AuthenticationExceptionHandler, //
|
||||||
exceptionMappings: ExceptionHandlers) : Presenter<AutoUploadChooseVaultView>(exceptionMappings) {
|
exceptionMappings: ExceptionHandlers
|
||||||
|
) : Presenter<AutoUploadChooseVaultView>(exceptionMappings) {
|
||||||
|
|
||||||
private var selectedVault: VaultModel? = null
|
private var selectedVault: VaultModel? = null
|
||||||
private var location: CloudFolderModel? = null
|
private var location: CloudFolderModel? = null
|
||||||
@ -79,8 +80,9 @@ class AutoUploadChooseVaultPresenter @Inject constructor( //
|
|||||||
} else {
|
} else {
|
||||||
if (!isPaused) {
|
if (!isPaused) {
|
||||||
requestActivityResult( //
|
requestActivityResult( //
|
||||||
ActivityResultCallbacks.vaultUnlockedAutoUpload(), //
|
ActivityResultCallbacks.vaultUnlockedAutoUpload(), //
|
||||||
Intents.unlockVaultIntent().withVaultModel(VaultModel(authenticatedVault)).withVaultAction(UnlockVaultIntent.VaultAction.UNLOCK))
|
Intents.unlockVaultIntent().withVaultModel(VaultModel(authenticatedVault)).withVaultAction(UnlockVaultIntent.VaultAction.UNLOCK)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,24 +97,25 @@ class AutoUploadChooseVaultPresenter @Inject constructor( //
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private fun decryptedCloudFor(vault: Vault) {
|
private fun decryptedCloudFor(vault: Vault) {
|
||||||
getDecryptedCloudForVaultUseCase //
|
getDecryptedCloudForVaultUseCase //
|
||||||
.withVault(vault) //
|
.withVault(vault) //
|
||||||
.run(object : DefaultResultHandler<Cloud>() {
|
.run(object : DefaultResultHandler<Cloud>() {
|
||||||
override fun onSuccess(cloud: Cloud) {
|
override fun onSuccess(cloud: Cloud) {
|
||||||
rootFolderFor(cloud)
|
rootFolderFor(cloud)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
if (!authenticationExceptionHandler.handleAuthenticationException( //
|
if (!authenticationExceptionHandler.handleAuthenticationException( //
|
||||||
this@AutoUploadChooseVaultPresenter, //
|
this@AutoUploadChooseVaultPresenter, //
|
||||||
e, //
|
e, //
|
||||||
ActivityResultCallbacks.decryptedCloudForAfterAuthInAutoPhotoUpload(vault))) {
|
ActivityResultCallbacks.decryptedCloudForAfterAuthInAutoPhotoUpload(vault)
|
||||||
super.onError(e)
|
)
|
||||||
}
|
) {
|
||||||
|
super.onError(e)
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback
|
@Callback
|
||||||
@ -123,33 +126,35 @@ class AutoUploadChooseVaultPresenter @Inject constructor( //
|
|||||||
|
|
||||||
private fun rootFolderFor(cloud: Cloud) {
|
private fun rootFolderFor(cloud: Cloud) {
|
||||||
getRootFolderUseCase //
|
getRootFolderUseCase //
|
||||||
.withCloud(cloud) //
|
.withCloud(cloud) //
|
||||||
.run(object : DefaultResultHandler<CloudFolder>() {
|
.run(object : DefaultResultHandler<CloudFolder>() {
|
||||||
override fun onSuccess(folder: CloudFolder) {
|
override fun onSuccess(folder: CloudFolder) {
|
||||||
when (authenticationState) {
|
when (authenticationState) {
|
||||||
AuthenticationState.CHOOSE_LOCATION -> {
|
AuthenticationState.CHOOSE_LOCATION -> {
|
||||||
location = cloudFolderModelMapper.toModel(folder)
|
location = cloudFolderModelMapper.toModel(folder)
|
||||||
selectedVault?.let { navigateToVaultContent(it, location) }
|
selectedVault?.let { navigateToVaultContent(it, location) }
|
||||||
}
|
|
||||||
AuthenticationState.INIT_ROOT -> location = cloudFolderModelMapper.toModel(folder)
|
|
||||||
}
|
}
|
||||||
|
AuthenticationState.INIT_ROOT -> location = cloudFolderModelMapper.toModel(folder)
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun navigateToVaultContent(vaultModel: VaultModel, decryptedRoot: CloudFolderModel?) {
|
private fun navigateToVaultContent(vaultModel: VaultModel, decryptedRoot: CloudFolderModel?) {
|
||||||
requestActivityResult( //
|
requestActivityResult( //
|
||||||
ActivityResultCallbacks.onAutoUploadChooseLocation(vaultModel), //
|
ActivityResultCallbacks.onAutoUploadChooseLocation(vaultModel), //
|
||||||
Intents.browseFilesIntent() //
|
Intents.browseFilesIntent() //
|
||||||
.withFolder(decryptedRoot) //
|
.withFolder(decryptedRoot) //
|
||||||
.withTitle(vaultModel.name) //
|
.withTitle(vaultModel.name) //
|
||||||
.withChooseCloudNodeSettings( //
|
.withChooseCloudNodeSettings( //
|
||||||
ChooseCloudNodeSettings.chooseCloudNodeSettings() //
|
ChooseCloudNodeSettings.chooseCloudNodeSettings() //
|
||||||
.withExtraTitle(context().getString(R.string.screen_file_browser_share_destination_title)) //
|
.withExtraTitle(context().getString(R.string.screen_file_browser_share_destination_title)) //
|
||||||
.withExtraToolbarIcon(R.drawable.ic_clear) //
|
.withExtraToolbarIcon(R.drawable.ic_clear) //
|
||||||
.withButtonText(context().getString(R.string.screen_file_browser_share_button_text)) //
|
.withButtonText(context().getString(R.string.screen_file_browser_share_button_text)) //
|
||||||
.selectingFolders() //
|
.selectingFolders() //
|
||||||
.build()))
|
.build()
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback
|
@Callback
|
||||||
|
@ -22,11 +22,12 @@ import timber.log.Timber
|
|||||||
|
|
||||||
@PerView
|
@PerView
|
||||||
class BiometricAuthSettingsPresenter @Inject constructor( //
|
class BiometricAuthSettingsPresenter @Inject constructor( //
|
||||||
private val getVaultListUseCase: GetVaultListUseCase, //
|
private val getVaultListUseCase: GetVaultListUseCase, //
|
||||||
private val saveVaultUseCase: SaveVaultUseCase, //
|
private val saveVaultUseCase: SaveVaultUseCase, //
|
||||||
private val lockVaultUseCase: LockVaultUseCase, //
|
private val lockVaultUseCase: LockVaultUseCase, //
|
||||||
exceptionMappings: ExceptionHandlers, //
|
exceptionMappings: ExceptionHandlers, //
|
||||||
private val sharedPreferencesHandler: SharedPreferencesHandler) : Presenter<BiometricAuthSettingsView>(exceptionMappings) {
|
private val sharedPreferencesHandler: SharedPreferencesHandler
|
||||||
|
) : Presenter<BiometricAuthSettingsView>(exceptionMappings) {
|
||||||
|
|
||||||
fun loadVaultList() {
|
fun loadVaultList() {
|
||||||
updateVaultListView()
|
updateVaultListView()
|
||||||
@ -55,19 +56,21 @@ class BiometricAuthSettingsPresenter @Inject constructor( //
|
|||||||
Timber.tag("BiomtricAuthSettngsPres").i("Checking entered vault password")
|
Timber.tag("BiomtricAuthSettngsPres").i("Checking entered vault password")
|
||||||
if (vaultModel.isLocked) {
|
if (vaultModel.isLocked) {
|
||||||
requestActivityResult( //
|
requestActivityResult( //
|
||||||
ActivityResultCallbacks.vaultUnlockedBiometricAuthPres(vaultModel), //
|
ActivityResultCallbacks.vaultUnlockedBiometricAuthPres(vaultModel), //
|
||||||
Intents.unlockVaultIntent().withVaultModel(vaultModel).withVaultAction(UnlockVaultIntent.VaultAction.UNLOCK_FOR_BIOMETRIC_AUTH))
|
Intents.unlockVaultIntent().withVaultModel(vaultModel).withVaultAction(UnlockVaultIntent.VaultAction.UNLOCK_FOR_BIOMETRIC_AUTH)
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
lockVaultUseCase
|
lockVaultUseCase
|
||||||
.withVault(vaultModel.toVault())
|
.withVault(vaultModel.toVault())
|
||||||
.run(object : DefaultResultHandler<Vault>() {
|
.run(object : DefaultResultHandler<Vault>() {
|
||||||
override fun onSuccess(vault: Vault) {
|
override fun onSuccess(vault: Vault) {
|
||||||
super.onSuccess(vault)
|
super.onSuccess(vault)
|
||||||
requestActivityResult( //
|
requestActivityResult( //
|
||||||
ActivityResultCallbacks.vaultUnlockedBiometricAuthPres(vaultModel), //
|
ActivityResultCallbacks.vaultUnlockedBiometricAuthPres(vaultModel), //
|
||||||
Intents.unlockVaultIntent().withVaultModel(vaultModel).withVaultAction(UnlockVaultIntent.VaultAction.UNLOCK_FOR_BIOMETRIC_AUTH))
|
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()
|
val vault = Vault.aCopyOf(vaultModel.toVault()).withCloud(cloud).withSavedPassword(password).build()
|
||||||
when {
|
when {
|
||||||
result.isResultOk -> requestActivityResult( //
|
result.isResultOk -> requestActivityResult( //
|
||||||
ActivityResultCallbacks.encryptVaultPassword(vaultModel), //
|
ActivityResultCallbacks.encryptVaultPassword(vaultModel), //
|
||||||
Intents.unlockVaultIntent().withVaultModel(VaultModel(vault)).withVaultAction(UnlockVaultIntent.VaultAction.ENCRYPT_PASSWORD))
|
Intents.unlockVaultIntent().withVaultModel(VaultModel(vault)).withVaultAction(UnlockVaultIntent.VaultAction.ENCRYPT_PASSWORD)
|
||||||
|
)
|
||||||
else -> TODO("Not yet implemented")
|
else -> TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -96,12 +100,12 @@ class BiometricAuthSettingsPresenter @Inject constructor( //
|
|||||||
|
|
||||||
private fun saveVault(vault: Vault?) {
|
private fun saveVault(vault: Vault?) {
|
||||||
saveVaultUseCase //
|
saveVaultUseCase //
|
||||||
.withVault(vault) //
|
.withVault(vault) //
|
||||||
.run(object : ProgressCompletingResultHandler<Vault>() {
|
.run(object : ProgressCompletingResultHandler<Vault>() {
|
||||||
override fun onSuccess(vault: Vault) {
|
override fun onSuccess(vault: Vault) {
|
||||||
Timber.tag("BiomtricAuthSettngsPres").i("Saved updated vault successfully")
|
Timber.tag("BiomtricAuthSettngsPres").i("Saved updated vault successfully")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fun switchedGeneralBiometricAuthSettings(isChecked: Boolean) {
|
fun switchedGeneralBiometricAuthSettings(isChecked: Boolean) {
|
||||||
@ -124,9 +128,9 @@ class BiometricAuthSettingsPresenter @Inject constructor( //
|
|||||||
|
|
||||||
private fun removePasswordAndSave(vault: Vault) {
|
private fun removePasswordAndSave(vault: Vault) {
|
||||||
val vaultWithRemovedPassword = Vault //
|
val vaultWithRemovedPassword = Vault //
|
||||||
.aCopyOf(vault) //
|
.aCopyOf(vault) //
|
||||||
.withSavedPassword(null) //
|
.withSavedPassword(null) //
|
||||||
.build()
|
.build()
|
||||||
saveVault(vaultWithRemovedPassword)
|
saveVault(vaultWithRemovedPassword)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -20,11 +20,12 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
@PerView
|
@PerView
|
||||||
class ChooseCloudServicePresenter @Inject constructor( //
|
class ChooseCloudServicePresenter @Inject constructor( //
|
||||||
private val getCloudsUseCase: GetCloudsUseCase, //
|
private val getCloudsUseCase: GetCloudsUseCase, //
|
||||||
private val cloudModelMapper: CloudModelMapper, //
|
private val cloudModelMapper: CloudModelMapper, //
|
||||||
private val addExistingVaultWorkflow: AddExistingVaultWorkflow, //
|
private val addExistingVaultWorkflow: AddExistingVaultWorkflow, //
|
||||||
private val createNewVaultWorkflow: CreateNewVaultWorkflow, //
|
private val createNewVaultWorkflow: CreateNewVaultWorkflow, //
|
||||||
exceptionMappings: ExceptionHandlers) : Presenter<ChooseCloudServiceView>(exceptionMappings) {
|
exceptionMappings: ExceptionHandlers
|
||||||
|
) : Presenter<ChooseCloudServiceView>(exceptionMappings) {
|
||||||
|
|
||||||
override fun workflows(): Iterable<Workflow<*>> {
|
override fun workflows(): Iterable<Workflow<*>> {
|
||||||
return listOf(addExistingVaultWorkflow, createNewVaultWorkflow)
|
return listOf(addExistingVaultWorkflow, createNewVaultWorkflow)
|
||||||
@ -55,11 +56,12 @@ class ChooseCloudServicePresenter @Inject constructor( //
|
|||||||
|
|
||||||
private fun startCloudConnectionListActivity(cloudTypeModel: CloudTypeModel) {
|
private fun startCloudConnectionListActivity(cloudTypeModel: CloudTypeModel) {
|
||||||
requestActivityResult( //
|
requestActivityResult( //
|
||||||
ActivityResultCallbacks.cloudConnectionListFinished(), //
|
ActivityResultCallbacks.cloudConnectionListFinished(), //
|
||||||
Intents.cloudConnectionListIntent() //
|
Intents.cloudConnectionListIntent() //
|
||||||
.withCloudType(cloudTypeModel) //
|
.withCloudType(cloudTypeModel) //
|
||||||
.withDialogTitle(context().getString(R.string.screen_cloud_connections_title)) //
|
.withDialogTitle(context().getString(R.string.screen_cloud_connections_title)) //
|
||||||
.withFinishOnCloudItemClick(true))
|
.withFinishOnCloudItemClick(true)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback
|
@Callback
|
||||||
@ -70,15 +72,15 @@ class ChooseCloudServicePresenter @Inject constructor( //
|
|||||||
|
|
||||||
private fun handleSingleInstanceClouds(cloudTypeModel: CloudTypeModel) {
|
private fun handleSingleInstanceClouds(cloudTypeModel: CloudTypeModel) {
|
||||||
getCloudsUseCase //
|
getCloudsUseCase //
|
||||||
.withCloudType(CloudTypeModel.valueOf(cloudTypeModel)) //
|
.withCloudType(CloudTypeModel.valueOf(cloudTypeModel)) //
|
||||||
.run(object : DefaultResultHandler<List<Cloud>>() {
|
.run(object : DefaultResultHandler<List<Cloud>>() {
|
||||||
override fun onSuccess(clouds: List<Cloud>) {
|
override fun onSuccess(clouds: List<Cloud>) {
|
||||||
if (clouds.size > 1) {
|
if (clouds.size > 1) {
|
||||||
throw FatalBackendException("More then one cloud")
|
throw FatalBackendException("More then one cloud")
|
||||||
}
|
|
||||||
onCloudSelected(clouds[0])
|
|
||||||
}
|
}
|
||||||
})
|
onCloudSelected(clouds[0])
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onCloudSelected(cloud: Cloud) {
|
private fun onCloudSelected(cloud: Cloud) {
|
||||||
|
@ -42,14 +42,15 @@ import timber.log.Timber
|
|||||||
|
|
||||||
@PerView
|
@PerView
|
||||||
class CloudConnectionListPresenter @Inject constructor( //
|
class CloudConnectionListPresenter @Inject constructor( //
|
||||||
private val getCloudsUseCase: GetCloudsUseCase, //
|
private val getCloudsUseCase: GetCloudsUseCase, //
|
||||||
private val getUsernameUseCase: GetUsernameUseCase, //
|
private val getUsernameUseCase: GetUsernameUseCase, //
|
||||||
private val removeCloudUseCase: RemoveCloudUseCase, //
|
private val removeCloudUseCase: RemoveCloudUseCase, //
|
||||||
private val addOrChangeCloudConnectionUseCase: AddOrChangeCloudConnectionUseCase, //
|
private val addOrChangeCloudConnectionUseCase: AddOrChangeCloudConnectionUseCase, //
|
||||||
private val getVaultListUseCase: GetVaultListUseCase, //
|
private val getVaultListUseCase: GetVaultListUseCase, //
|
||||||
private val deleteVaultUseCase: DeleteVaultUseCase, //
|
private val deleteVaultUseCase: DeleteVaultUseCase, //
|
||||||
private val cloudModelMapper: CloudModelMapper, //
|
private val cloudModelMapper: CloudModelMapper, //
|
||||||
exceptionMappings: ExceptionHandlers) : Presenter<CloudConnectionListView>(exceptionMappings) {
|
exceptionMappings: ExceptionHandlers
|
||||||
|
) : Presenter<CloudConnectionListView>(exceptionMappings) {
|
||||||
|
|
||||||
private val selectedCloudType = AtomicReference<CloudTypeModel>()
|
private val selectedCloudType = AtomicReference<CloudTypeModel>()
|
||||||
private var defaultLocalStorageCloud: LocalStorageCloud? = null
|
private var defaultLocalStorageCloud: LocalStorageCloud? = null
|
||||||
@ -59,22 +60,22 @@ class CloudConnectionListPresenter @Inject constructor( //
|
|||||||
|
|
||||||
fun loadCloudList() {
|
fun loadCloudList() {
|
||||||
getCloudsUseCase //
|
getCloudsUseCase //
|
||||||
.withCloudType(CloudTypeModel.valueOf(selectedCloudType.get())) //
|
.withCloudType(CloudTypeModel.valueOf(selectedCloudType.get())) //
|
||||||
.run(object : DefaultResultHandler<List<Cloud>>() {
|
.run(object : DefaultResultHandler<List<Cloud>>() {
|
||||||
override fun onSuccess(clouds: List<Cloud>) {
|
override fun onSuccess(clouds: List<Cloud>) {
|
||||||
val cloudModels: MutableList<CloudModel> = ArrayList()
|
val cloudModels: MutableList<CloudModel> = ArrayList()
|
||||||
clouds.forEach { cloud ->
|
clouds.forEach { cloud ->
|
||||||
if (CloudTypeModel.LOCAL == selectedCloudType.get()) {
|
if (CloudTypeModel.LOCAL == selectedCloudType.get()) {
|
||||||
if ((cloud as LocalStorageCloud).rootUri() == null) {
|
if ((cloud as LocalStorageCloud).rootUri() == null) {
|
||||||
defaultLocalStorageCloud = cloud
|
defaultLocalStorageCloud = cloud
|
||||||
return@forEach
|
return@forEach
|
||||||
}
|
|
||||||
}
|
}
|
||||||
cloudModels.add(cloudModelMapper.toModel(cloud))
|
|
||||||
}
|
}
|
||||||
view?.showCloudModels(cloudModels)
|
cloudModels.add(cloudModelMapper.toModel(cloud))
|
||||||
}
|
}
|
||||||
})
|
view?.showCloudModels(cloudModels)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onDeleteCloudClicked(cloudModel: CloudModel) {
|
fun onDeleteCloudClicked(cloudModel: CloudModel) {
|
||||||
@ -120,32 +121,39 @@ class CloudConnectionListPresenter @Inject constructor( //
|
|||||||
|
|
||||||
private fun deleteCloud(cloud: Cloud) {
|
private fun deleteCloud(cloud: Cloud) {
|
||||||
removeCloudUseCase //
|
removeCloudUseCase //
|
||||||
.withCloud(cloud) //
|
.withCloud(cloud) //
|
||||||
.run(object : DefaultResultHandler<Void?>() {
|
.run(object : DefaultResultHandler<Void?>() {
|
||||||
override fun onSuccess(ignore: Void?) {
|
override fun onSuccess(ignore: Void?) {
|
||||||
loadCloudList()
|
loadCloudList()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onAddConnectionClicked() {
|
fun onAddConnectionClicked() {
|
||||||
when (selectedCloudType.get()) {
|
when (selectedCloudType.get()) {
|
||||||
CloudTypeModel.WEBDAV -> requestActivityResult(ActivityResultCallbacks.addChangeMultiCloud(), //
|
CloudTypeModel.WEBDAV -> requestActivityResult(
|
||||||
Intents.webDavAddOrChangeIntent())
|
ActivityResultCallbacks.addChangeMultiCloud(), //
|
||||||
|
Intents.webDavAddOrChangeIntent()
|
||||||
|
)
|
||||||
CloudTypeModel.PCLOUD -> {
|
CloudTypeModel.PCLOUD -> {
|
||||||
val authIntent: Intent = AuthorizationActivity.createIntent(
|
val authIntent: Intent = AuthorizationActivity.createIntent(
|
||||||
this.context(),
|
this.context(),
|
||||||
AuthorizationRequest.create()
|
AuthorizationRequest.create()
|
||||||
.setType(AuthorizationRequest.Type.TOKEN)
|
.setType(AuthorizationRequest.Type.TOKEN)
|
||||||
.setClientId(BuildConfig.PCLOUD_CLIENT_ID)
|
.setClientId(BuildConfig.PCLOUD_CLIENT_ID)
|
||||||
.setForceAccessApproval(true)
|
.setForceAccessApproval(true)
|
||||||
.addPermission("manageshares")
|
.addPermission("manageshares")
|
||||||
.build())
|
.build()
|
||||||
requestActivityResult(ActivityResultCallbacks.pCloudAuthenticationFinished(), //
|
)
|
||||||
authIntent)
|
requestActivityResult(
|
||||||
|
ActivityResultCallbacks.pCloudAuthenticationFinished(), //
|
||||||
|
authIntent
|
||||||
|
)
|
||||||
}
|
}
|
||||||
CloudTypeModel.S3 -> requestActivityResult(ActivityResultCallbacks.addChangeMultiCloud(), //
|
CloudTypeModel.S3 -> requestActivityResult(
|
||||||
Intents.s3AddOrChangeIntent())
|
ActivityResultCallbacks.addChangeMultiCloud(), //
|
||||||
|
Intents.s3AddOrChangeIntent()
|
||||||
|
)
|
||||||
CloudTypeModel.LOCAL -> openDocumentTree()
|
CloudTypeModel.LOCAL -> openDocumentTree()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -154,15 +162,17 @@ class CloudConnectionListPresenter @Inject constructor( //
|
|||||||
private fun openDocumentTree() {
|
private fun openDocumentTree() {
|
||||||
try {
|
try {
|
||||||
requestActivityResult( //
|
requestActivityResult( //
|
||||||
ActivityResultCallbacks.pickedLocalStorageLocation(), //
|
ActivityResultCallbacks.pickedLocalStorageLocation(), //
|
||||||
Intent(Intent.ACTION_OPEN_DOCUMENT_TREE))
|
Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
||||||
|
)
|
||||||
} catch (exception: ActivityNotFoundException) {
|
} catch (exception: ActivityNotFoundException) {
|
||||||
Toast //
|
Toast //
|
||||||
.makeText( //
|
.makeText( //
|
||||||
activity().applicationContext, //
|
activity().applicationContext, //
|
||||||
context().getText(R.string.screen_cloud_local_error_no_content_provider), //
|
context().getText(R.string.screen_cloud_local_error_no_content_provider), //
|
||||||
Toast.LENGTH_SHORT) //
|
Toast.LENGTH_SHORT
|
||||||
.show()
|
) //
|
||||||
|
.show()
|
||||||
Timber.tag("CloudConnListPresenter").e(exception, "No ContentProvider on system")
|
Timber.tag("CloudConnListPresenter").e(exception, "No ContentProvider on system")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -170,14 +180,18 @@ class CloudConnectionListPresenter @Inject constructor( //
|
|||||||
fun onChangeCloudClicked(cloudModel: CloudModel) {
|
fun onChangeCloudClicked(cloudModel: CloudModel) {
|
||||||
when {
|
when {
|
||||||
cloudModel.cloudType() == CloudTypeModel.WEBDAV -> {
|
cloudModel.cloudType() == CloudTypeModel.WEBDAV -> {
|
||||||
requestActivityResult(ActivityResultCallbacks.addChangeMultiCloud(), //
|
requestActivityResult(
|
||||||
Intents.webDavAddOrChangeIntent() //
|
ActivityResultCallbacks.addChangeMultiCloud(), //
|
||||||
.withWebDavCloud(cloudModel as WebDavCloudModel))
|
Intents.webDavAddOrChangeIntent() //
|
||||||
|
.withWebDavCloud(cloudModel as WebDavCloudModel)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
cloudModel.cloudType() == CloudTypeModel.S3 -> {
|
cloudModel.cloudType() == CloudTypeModel.S3 -> {
|
||||||
requestActivityResult(ActivityResultCallbacks.addChangeMultiCloud(), //
|
requestActivityResult(
|
||||||
Intents.s3AddOrChangeIntent() //
|
ActivityResultCallbacks.addChangeMultiCloud(), //
|
||||||
.withS3Cloud(cloudModel as S3CloudModel))
|
Intents.s3AddOrChangeIntent() //
|
||||||
|
.withS3Cloud(cloudModel as S3CloudModel)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
throw IllegalStateException("Change cloud with type " + cloudModel.cloudType() + " is not supported")
|
throw IllegalStateException("Change cloud with type " + cloudModel.cloudType() + " is not supported")
|
||||||
@ -202,19 +216,19 @@ class CloudConnectionListPresenter @Inject constructor( //
|
|||||||
when (result) {
|
when (result) {
|
||||||
AuthorizationResult.ACCESS_GRANTED -> {
|
AuthorizationResult.ACCESS_GRANTED -> {
|
||||||
val accessToken: String = CredentialCryptor //
|
val accessToken: String = CredentialCryptor //
|
||||||
.getInstance(this.context()) //
|
.getInstance(this.context()) //
|
||||||
.encrypt(authData.token)
|
.encrypt(authData.token)
|
||||||
val pCloudSkeleton: PCloud = PCloud.aPCloud() //
|
val pCloudSkeleton: PCloud = PCloud.aPCloud() //
|
||||||
.withAccessToken(accessToken)
|
.withAccessToken(accessToken)
|
||||||
.withUrl(authData.apiHost)
|
.withUrl(authData.apiHost)
|
||||||
.build();
|
.build();
|
||||||
getUsernameUseCase //
|
getUsernameUseCase //
|
||||||
.withCloud(pCloudSkeleton) //
|
.withCloud(pCloudSkeleton) //
|
||||||
.run(object : DefaultResultHandler<String>() {
|
.run(object : DefaultResultHandler<String>() {
|
||||||
override fun onSuccess(username: String?) {
|
override fun onSuccess(username: String?) {
|
||||||
prepareForSavingPCloud(PCloud.aCopyOf(pCloudSkeleton).withUsername(username).build())
|
prepareForSavingPCloud(PCloud.aCopyOf(pCloudSkeleton).withUsername(username).build())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
AuthorizationResult.ACCESS_DENIED -> {
|
AuthorizationResult.ACCESS_DENIED -> {
|
||||||
Timber.tag("CloudConnListPresenter").e("Account access denied")
|
Timber.tag("CloudConnListPresenter").e("Account access denied")
|
||||||
@ -233,30 +247,32 @@ class CloudConnectionListPresenter @Inject constructor( //
|
|||||||
|
|
||||||
fun prepareForSavingPCloud(cloud: PCloud) {
|
fun prepareForSavingPCloud(cloud: PCloud) {
|
||||||
getCloudsUseCase //
|
getCloudsUseCase //
|
||||||
.withCloudType(CloudTypeModel.valueOf(selectedCloudType.get())) //
|
.withCloudType(CloudTypeModel.valueOf(selectedCloudType.get())) //
|
||||||
.run(object : DefaultResultHandler<List<Cloud>>() {
|
.run(object : DefaultResultHandler<List<Cloud>>() {
|
||||||
override fun onSuccess(clouds: List<Cloud>) {
|
override fun onSuccess(clouds: List<Cloud>) {
|
||||||
clouds.firstOrNull {
|
clouds.firstOrNull {
|
||||||
(it as PCloud).username() == cloud.username()
|
(it as PCloud).username() == cloud.username()
|
||||||
}?.let {
|
}?.let {
|
||||||
it as PCloud
|
it as PCloud
|
||||||
saveCloud(PCloud.aCopyOf(it) //
|
saveCloud(
|
||||||
.withUrl(cloud.url())
|
PCloud.aCopyOf(it) //
|
||||||
.withAccessToken(cloud.accessToken())
|
.withUrl(cloud.url())
|
||||||
.build())
|
.withAccessToken(cloud.accessToken())
|
||||||
} ?: saveCloud(cloud)
|
.build()
|
||||||
}
|
)
|
||||||
})
|
} ?: saveCloud(cloud)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveCloud(cloud: PCloud) {
|
fun saveCloud(cloud: PCloud) {
|
||||||
addOrChangeCloudConnectionUseCase //
|
addOrChangeCloudConnectionUseCase //
|
||||||
.withCloud(cloud) //
|
.withCloud(cloud) //
|
||||||
.run(object : DefaultResultHandler<Void?>() {
|
.run(object : DefaultResultHandler<Void?>() {
|
||||||
override fun onSuccess(void: Void?) {
|
override fun onSuccess(void: Void?) {
|
||||||
loadCloudList()
|
loadCloudList()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback
|
@Callback
|
||||||
@ -264,34 +280,38 @@ class CloudConnectionListPresenter @Inject constructor( //
|
|||||||
fun pickedLocalStorageLocation(result: ActivityResult) {
|
fun pickedLocalStorageLocation(result: ActivityResult) {
|
||||||
val rootTreeUriOfLocalStorage = result.intent().data
|
val rootTreeUriOfLocalStorage = result.intent().data
|
||||||
persistUriPermission(rootTreeUriOfLocalStorage)
|
persistUriPermission(rootTreeUriOfLocalStorage)
|
||||||
addOrChangeCloudConnectionUseCase.withCloud(LocalStorageCloud.aLocalStorage() //
|
addOrChangeCloudConnectionUseCase.withCloud(
|
||||||
|
LocalStorageCloud.aLocalStorage() //
|
||||||
.withRootUri(rootTreeUriOfLocalStorage.toString()) //
|
.withRootUri(rootTreeUriOfLocalStorage.toString()) //
|
||||||
.build()) //
|
.build()
|
||||||
.run(object : DefaultResultHandler<Void?>() {
|
) //
|
||||||
override fun onSuccess(void: Void?) {
|
.run(object : DefaultResultHandler<Void?>() {
|
||||||
loadCloudList()
|
override fun onSuccess(void: Void?) {
|
||||||
}
|
loadCloudList()
|
||||||
})
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||||
private fun persistUriPermission(rootTreeUriOfLocalStorage: Uri?) {
|
private fun persistUriPermission(rootTreeUriOfLocalStorage: Uri?) {
|
||||||
rootTreeUriOfLocalStorage?.let {
|
rootTreeUriOfLocalStorage?.let {
|
||||||
context() //
|
context() //
|
||||||
.contentResolver //
|
.contentResolver //
|
||||||
.takePersistableUriPermission( //
|
.takePersistableUriPermission( //
|
||||||
it, //
|
it, //
|
||||||
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||||
private fun releaseUriPermission(uri: String) {
|
private fun releaseUriPermission(uri: String) {
|
||||||
context() //
|
context() //
|
||||||
.contentResolver //
|
.contentResolver //
|
||||||
.releasePersistableUriPermission( //
|
.releasePersistableUriPermission( //
|
||||||
Uri.parse(uri), //
|
Uri.parse(uri), //
|
||||||
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onCloudConnectionClicked(cloudModel: CloudModel) {
|
fun onCloudConnectionClicked(cloudModel: CloudModel) {
|
||||||
|
@ -29,18 +29,20 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
@PerView
|
@PerView
|
||||||
class CloudSettingsPresenter @Inject constructor( //
|
class CloudSettingsPresenter @Inject constructor( //
|
||||||
private val getAllCloudsUseCase: GetAllCloudsUseCase, //
|
private val getAllCloudsUseCase: GetAllCloudsUseCase, //
|
||||||
private val getCloudsUseCase: GetCloudsUseCase, //
|
private val getCloudsUseCase: GetCloudsUseCase, //
|
||||||
private val logoutCloudUsecase: LogoutCloudUseCase, //
|
private val logoutCloudUsecase: LogoutCloudUseCase, //
|
||||||
private val cloudModelMapper: CloudModelMapper, //
|
private val cloudModelMapper: CloudModelMapper, //
|
||||||
exceptionMappings: ExceptionHandlers) : Presenter<CloudSettingsView>(exceptionMappings) {
|
exceptionMappings: ExceptionHandlers
|
||||||
|
) : Presenter<CloudSettingsView>(exceptionMappings) {
|
||||||
|
|
||||||
private val nonSingleLoginClouds: Set<CloudTypeModel> = EnumSet.of( //
|
private val nonSingleLoginClouds: Set<CloudTypeModel> = EnumSet.of( //
|
||||||
CloudTypeModel.CRYPTO, //
|
CloudTypeModel.CRYPTO, //
|
||||||
CloudTypeModel.LOCAL, //
|
CloudTypeModel.LOCAL, //
|
||||||
CloudTypeModel.PCLOUD, //
|
CloudTypeModel.PCLOUD, //
|
||||||
CloudTypeModel.S3, //
|
CloudTypeModel.S3, //
|
||||||
CloudTypeModel.WEBDAV)
|
CloudTypeModel.WEBDAV
|
||||||
|
)
|
||||||
|
|
||||||
fun loadClouds() {
|
fun loadClouds() {
|
||||||
getAllCloudsUseCase.run(CloudsSubscriber())
|
getAllCloudsUseCase.run(CloudsSubscriber())
|
||||||
@ -52,12 +54,12 @@ class CloudSettingsPresenter @Inject constructor( //
|
|||||||
} else {
|
} else {
|
||||||
if (isLoggedIn(cloudModel)) {
|
if (isLoggedIn(cloudModel)) {
|
||||||
logoutCloudUsecase //
|
logoutCloudUsecase //
|
||||||
.withCloud(cloudModel.toCloud()) //
|
.withCloud(cloudModel.toCloud()) //
|
||||||
.run(object : DefaultResultHandler<Cloud>() {
|
.run(object : DefaultResultHandler<Cloud>() {
|
||||||
override fun onSuccess(cloud: Cloud) {
|
override fun onSuccess(cloud: Cloud) {
|
||||||
loadClouds()
|
loadClouds()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
loginCloud(cloudModel)
|
loginCloud(cloudModel)
|
||||||
}
|
}
|
||||||
@ -66,15 +68,15 @@ class CloudSettingsPresenter @Inject constructor( //
|
|||||||
|
|
||||||
private fun loginCloud(cloudModel: CloudModel) {
|
private fun loginCloud(cloudModel: CloudModel) {
|
||||||
getCloudsUseCase //
|
getCloudsUseCase //
|
||||||
.withCloudType(CloudTypeModel.valueOf(cloudModel.cloudType())) //
|
.withCloudType(CloudTypeModel.valueOf(cloudModel.cloudType())) //
|
||||||
.run(object : DefaultResultHandler<List<Cloud>>() {
|
.run(object : DefaultResultHandler<List<Cloud>>() {
|
||||||
override fun onSuccess(clouds: List<Cloud>) {
|
override fun onSuccess(clouds: List<Cloud>) {
|
||||||
if (clouds.size > 1) {
|
if (clouds.size > 1) {
|
||||||
throw FatalBackendException("More then one cloud")
|
throw FatalBackendException("More then one cloud")
|
||||||
}
|
|
||||||
startAuthentication(clouds[0])
|
|
||||||
}
|
}
|
||||||
})
|
startAuthentication(clouds[0])
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isLoggedIn(cloudModel: CloudModel): Boolean {
|
private fun isLoggedIn(cloudModel: CloudModel): Boolean {
|
||||||
@ -83,11 +85,12 @@ class CloudSettingsPresenter @Inject constructor( //
|
|||||||
|
|
||||||
private fun startConnectionListActivity(cloudTypeModel: CloudTypeModel) {
|
private fun startConnectionListActivity(cloudTypeModel: CloudTypeModel) {
|
||||||
requestActivityResult( //
|
requestActivityResult( //
|
||||||
ActivityResultCallbacks.webDavConnectionListFinisheds(), //
|
ActivityResultCallbacks.webDavConnectionListFinisheds(), //
|
||||||
Intents.cloudConnectionListIntent() //
|
Intents.cloudConnectionListIntent() //
|
||||||
.withCloudType(cloudTypeModel) //
|
.withCloudType(cloudTypeModel) //
|
||||||
.withDialogTitle(effectiveTitle(cloudTypeModel)) //
|
.withDialogTitle(effectiveTitle(cloudTypeModel)) //
|
||||||
.withFinishOnCloudItemClick(false))
|
.withFinishOnCloudItemClick(false)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun effectiveTitle(cloudTypeModel: CloudTypeModel): String {
|
private fun effectiveTitle(cloudTypeModel: CloudTypeModel): String {
|
||||||
@ -108,9 +111,10 @@ class CloudSettingsPresenter @Inject constructor( //
|
|||||||
|
|
||||||
private fun startAuthentication(cloud: Cloud) {
|
private fun startAuthentication(cloud: Cloud) {
|
||||||
requestActivityResult( //
|
requestActivityResult( //
|
||||||
ActivityResultCallbacks.onCloudAuthenticated(), //
|
ActivityResultCallbacks.onCloudAuthenticated(), //
|
||||||
Intents.authenticateCloudIntent() //
|
Intents.authenticateCloudIntent() //
|
||||||
.withCloud(cloudModelMapper.toModel(cloud)))
|
.withCloud(cloudModelMapper.toModel(cloud))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback
|
@Callback
|
||||||
@ -122,15 +126,15 @@ class CloudSettingsPresenter @Inject constructor( //
|
|||||||
|
|
||||||
override fun onSuccess(clouds: List<Cloud>) {
|
override fun onSuccess(clouds: List<Cloud>) {
|
||||||
val cloudModel = cloudModelMapper.toModels(clouds) //
|
val cloudModel = cloudModelMapper.toModels(clouds) //
|
||||||
.filter { isSingleLoginCloud(it) } //
|
.filter { isSingleLoginCloud(it) } //
|
||||||
.filter { cloud -> !(BuildConfig.FLAVOR == "fdroid" && cloud.cloudType() == CloudTypeModel.GOOGLE_DRIVE) } //
|
.filter { cloud -> !(BuildConfig.FLAVOR == "fdroid" && cloud.cloudType() == CloudTypeModel.GOOGLE_DRIVE) } //
|
||||||
.toMutableList() //
|
.toMutableList() //
|
||||||
.also {
|
.also {
|
||||||
it.add(aPCloud())
|
it.add(aPCloud())
|
||||||
it.add(aWebdavCloud())
|
it.add(aWebdavCloud())
|
||||||
it.add(aS3Cloud())
|
it.add(aS3Cloud())
|
||||||
it.add(aLocalCloud())
|
it.add(aLocalCloud())
|
||||||
}
|
}
|
||||||
view?.render(cloudModel)
|
view?.render(cloudModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,8 +11,9 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
@PerView
|
@PerView
|
||||||
class CreateVaultPresenter @Inject constructor( //
|
class CreateVaultPresenter @Inject constructor( //
|
||||||
private val createNewVaultWorkflow: CreateNewVaultWorkflow, //
|
private val createNewVaultWorkflow: CreateNewVaultWorkflow, //
|
||||||
exceptionMappings: ExceptionHandlers) : Presenter<CreateVaultView>(exceptionMappings) {
|
exceptionMappings: ExceptionHandlers
|
||||||
|
) : Presenter<CreateVaultView>(exceptionMappings) {
|
||||||
|
|
||||||
override fun workflows(): Iterable<Workflow<*>> {
|
override fun workflows(): Iterable<Workflow<*>> {
|
||||||
return setOf(createNewVaultWorkflow)
|
return setOf(createNewVaultWorkflow)
|
||||||
|
@ -42,15 +42,16 @@ import timber.log.Timber
|
|||||||
|
|
||||||
@PerView
|
@PerView
|
||||||
class ImagePreviewPresenter @Inject constructor( //
|
class ImagePreviewPresenter @Inject constructor( //
|
||||||
exceptionMappings: ExceptionHandlers, //
|
exceptionMappings: ExceptionHandlers, //
|
||||||
private val shareFileHelper: ShareFileHelper, //
|
private val shareFileHelper: ShareFileHelper, //
|
||||||
private val contentResolverUtil: ContentResolverUtil, //
|
private val contentResolverUtil: ContentResolverUtil, //
|
||||||
private val copyDataUseCase: CopyDataUseCase, //
|
private val copyDataUseCase: CopyDataUseCase, //
|
||||||
private val downloadFilesUseCase: DownloadFilesUseCase, //
|
private val downloadFilesUseCase: DownloadFilesUseCase, //
|
||||||
private val deleteNodesUseCase: DeleteNodesUseCase, //
|
private val deleteNodesUseCase: DeleteNodesUseCase, //
|
||||||
private val downloadFileUtil: DownloadFileUtil, //
|
private val downloadFileUtil: DownloadFileUtil, //
|
||||||
private val fileUtil: FileUtil, //
|
private val fileUtil: FileUtil, //
|
||||||
private val cloudFileModelMapper: CloudFileModelMapper) : Presenter<ImagePreviewView>(exceptionMappings) {
|
private val cloudFileModelMapper: CloudFileModelMapper
|
||||||
|
) : Presenter<ImagePreviewView>(exceptionMappings) {
|
||||||
|
|
||||||
private var isSystemUiVisible = true
|
private var isSystemUiVisible = true
|
||||||
|
|
||||||
@ -66,8 +67,10 @@ class ImagePreviewPresenter @Inject constructor( //
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun copyFileToDownloadDirectory(uri: Uri) {
|
private fun copyFileToDownloadDirectory(uri: Uri) {
|
||||||
requestPermissions(PermissionsResultCallbacks.copyFileToDownloadDirectory(uri.toString()), //
|
requestPermissions(
|
||||||
R.string.permission_message_export_file, Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
PermissionsResultCallbacks.copyFileToDownloadDirectory(uri.toString()), //
|
||||||
|
R.string.permission_message_export_file, Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback
|
@Callback
|
||||||
@ -95,13 +98,13 @@ class ImagePreviewPresenter @Inject constructor( //
|
|||||||
throw FatalBackendException("Input- or OutputStream is null")
|
throw FatalBackendException("Input- or OutputStream is null")
|
||||||
}
|
}
|
||||||
copyDataUseCase //
|
copyDataUseCase //
|
||||||
.withSource(source) //
|
.withSource(source) //
|
||||||
.andTarget(target) //
|
.andTarget(target) //
|
||||||
.run(object : DefaultResultHandler<Void?>() {
|
.run(object : DefaultResultHandler<Void?>() {
|
||||||
override fun onFinished() {
|
override fun onFinished() {
|
||||||
view?.showMessage(R.string.screen_file_browser_msg_file_exported)
|
view?.showMessage(R.string.screen_file_browser_msg_file_exported)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun copyFileToUserSelectedLocation(uri: Uri) {
|
private fun copyFileToUserSelectedLocation(uri: Uri) {
|
||||||
@ -114,17 +117,21 @@ class ImagePreviewPresenter @Inject constructor( //
|
|||||||
|
|
||||||
@Callback
|
@Callback
|
||||||
fun copyFileToUserSelectedLocation(result: ActivityResult, sourceUri: String?) {
|
fun copyFileToUserSelectedLocation(result: ActivityResult, sourceUri: String?) {
|
||||||
requestPermissions(PermissionsResultCallbacks.copyFileToUserSelectedLocation(result.intent()?.dataString, sourceUri), //
|
requestPermissions(
|
||||||
R.string.permission_message_export_file, //
|
PermissionsResultCallbacks.copyFileToUserSelectedLocation(result.intent()?.dataString, sourceUri), //
|
||||||
Manifest.permission.READ_EXTERNAL_STORAGE)
|
R.string.permission_message_export_file, //
|
||||||
|
Manifest.permission.READ_EXTERNAL_STORAGE
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback
|
@Callback
|
||||||
fun copyFileToUserSelectedLocation(result: PermissionsResult, targetUri: String?, sourceUri: String?) {
|
fun copyFileToUserSelectedLocation(result: PermissionsResult, targetUri: String?, sourceUri: String?) {
|
||||||
if (result.granted()) {
|
if (result.granted()) {
|
||||||
try {
|
try {
|
||||||
copyFile(contentResolverUtil.openInputStream(Uri.parse(sourceUri)), //
|
copyFile(
|
||||||
contentResolverUtil.openOutputStream(Uri.parse(targetUri)))
|
contentResolverUtil.openInputStream(Uri.parse(sourceUri)), //
|
||||||
|
contentResolverUtil.openOutputStream(Uri.parse(targetUri))
|
||||||
|
)
|
||||||
} catch (e: FileNotFoundException) {
|
} catch (e: FileNotFoundException) {
|
||||||
showError(e)
|
showError(e)
|
||||||
}
|
}
|
||||||
@ -142,18 +149,18 @@ class ImagePreviewPresenter @Inject constructor( //
|
|||||||
fun onDeleteImageConfirmed(imagePreviewFile: ImagePreviewFile, index: Int) {
|
fun onDeleteImageConfirmed(imagePreviewFile: ImagePreviewFile, index: Int) {
|
||||||
view?.showProgress(ProgressModel.GENERIC)
|
view?.showProgress(ProgressModel.GENERIC)
|
||||||
deleteNodesUseCase
|
deleteNodesUseCase
|
||||||
.withCloudNodes(listOf(imagePreviewFile.cloudFileModel.toCloudNode()))
|
.withCloudNodes(listOf(imagePreviewFile.cloudFileModel.toCloudNode()))
|
||||||
.run(object : ProgressCompletingResultHandler<List<CloudNode?>?>() {
|
.run(object : ProgressCompletingResultHandler<List<CloudNode?>?>() {
|
||||||
override fun onFinished() {
|
override fun onFinished() {
|
||||||
view?.showProgress(ProgressModel.COMPLETED)
|
view?.showProgress(ProgressModel.COMPLETED)
|
||||||
view?.onImageDeleted(index)
|
view?.onImageDeleted(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
Timber.tag("ImagePreviewPresenter").e(e, "Failed to delete preview image")
|
Timber.tag("ImagePreviewPresenter").e(e, "Failed to delete preview image")
|
||||||
view?.showProgress(ProgressModel.COMPLETED)
|
view?.showProgress(ProgressModel.COMPLETED)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onImagePreviewClicked() {
|
fun onImagePreviewClicked() {
|
||||||
@ -167,24 +174,24 @@ class ImagePreviewPresenter @Inject constructor( //
|
|||||||
|
|
||||||
fun onMissingImagePreviewFile(imagePreviewFile: ImagePreviewFile) {
|
fun onMissingImagePreviewFile(imagePreviewFile: ImagePreviewFile) {
|
||||||
downloadFilesUseCase //
|
downloadFilesUseCase //
|
||||||
.withDownloadFiles(downloadFileUtil.createDownloadFilesFor(this, listOf(imagePreviewFile.cloudFileModel))) //
|
.withDownloadFiles(downloadFileUtil.createDownloadFilesFor(this, listOf(imagePreviewFile.cloudFileModel))) //
|
||||||
.run(object : DefaultProgressAwareResultHandler<List<CloudFile>, DownloadState>() {
|
.run(object : DefaultProgressAwareResultHandler<List<CloudFile>, DownloadState>() {
|
||||||
override fun onSuccess(result: List<CloudFile>) {
|
override fun onSuccess(result: List<CloudFile>) {
|
||||||
cloudFileModelMapper.toModel(result[0])
|
cloudFileModelMapper.toModel(result[0])
|
||||||
imagePreviewFile.uri = fileUtil.contentUriFor(cloudFileModelMapper.toModel(result[0]))
|
imagePreviewFile.uri = fileUtil.contentUriFor(cloudFileModelMapper.toModel(result[0]))
|
||||||
view?.showImagePreview(imagePreviewFile)
|
view?.showImagePreview(imagePreviewFile)
|
||||||
view?.hideProgressBar(imagePreviewFile)
|
view?.hideProgressBar(imagePreviewFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
if (ExceptionUtil.contains(e, IOException::class.java, ExceptionUtil.thatContainsMessage("Stream Closed"))) {
|
if (ExceptionUtil.contains(e, IOException::class.java, ExceptionUtil.thatContainsMessage("Stream Closed"))) {
|
||||||
// ignore error
|
// ignore error
|
||||||
Timber.tag("ImagePreviewPresenter").d("User swiped to quickly and close the stream before finishing the download.")
|
Timber.tag("ImagePreviewPresenter").d("User swiped to quickly and close the stream before finishing the download.")
|
||||||
} else {
|
} else {
|
||||||
super.onError(e)
|
super.onError(e)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getImagePreviewFileStore(path: String): ImagePreviewFilesStore {
|
fun getImagePreviewFileStore(path: String): ImagePreviewFilesStore {
|
||||||
|
@ -11,24 +11,25 @@ import javax.inject.Inject
|
|||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
class LicenseCheckPresenter @Inject internal constructor(
|
class LicenseCheckPresenter @Inject internal constructor(
|
||||||
exceptionHandlers: ExceptionHandlers, //
|
exceptionHandlers: ExceptionHandlers, //
|
||||||
private val doLicenseCheckUsecase: DoLicenseCheckUseCase, //
|
private val doLicenseCheckUsecase: DoLicenseCheckUseCase, //
|
||||||
private val sharedPreferencesHandler: SharedPreferencesHandler) : Presenter<UpdateLicenseView>(exceptionHandlers) {
|
private val sharedPreferencesHandler: SharedPreferencesHandler
|
||||||
|
) : Presenter<UpdateLicenseView>(exceptionHandlers) {
|
||||||
|
|
||||||
fun validate(data: Uri?) {
|
fun validate(data: Uri?) {
|
||||||
data?.let {
|
data?.let {
|
||||||
val license = it.fragment ?: it.lastPathSegment ?: ""
|
val license = it.fragment ?: it.lastPathSegment ?: ""
|
||||||
view?.showOrUpdateLicenseDialog(license)
|
view?.showOrUpdateLicenseDialog(license)
|
||||||
doLicenseCheckUsecase
|
doLicenseCheckUsecase
|
||||||
.withLicense(license)
|
.withLicense(license)
|
||||||
.run(CheckLicenseStatusSubscriber())
|
.run(CheckLicenseStatusSubscriber())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun validateDialogAware(license: String?) {
|
fun validateDialogAware(license: String?) {
|
||||||
doLicenseCheckUsecase
|
doLicenseCheckUsecase
|
||||||
.withLicense(license)
|
.withLicense(license)
|
||||||
.run(CheckLicenseStatusSubscriber())
|
.run(CheckLicenseStatusSubscriber())
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class CheckLicenseStatusSubscriber : NoOpResultHandler<LicenseCheck>() {
|
private inner class CheckLicenseStatusSubscriber : NoOpResultHandler<LicenseCheck>() {
|
||||||
|
@ -76,23 +76,23 @@ abstract class Presenter<V : View> protected constructor(private val exceptionMa
|
|||||||
|
|
||||||
fun finishWithResult(resultName: String, result: Serializable?) {
|
fun finishWithResult(resultName: String, result: Serializable?) {
|
||||||
activeWorkflow()?.dispatch(result)
|
activeWorkflow()?.dispatch(result)
|
||||||
?: run {
|
?: run {
|
||||||
val data = Intent()
|
val data = Intent()
|
||||||
when (result) {
|
when (result) {
|
||||||
null -> {
|
null -> {
|
||||||
activity().setResult(Activity.RESULT_CANCELED)
|
activity().setResult(Activity.RESULT_CANCELED)
|
||||||
}
|
}
|
||||||
is Throwable -> {
|
is Throwable -> {
|
||||||
data.putExtra(resultName, result)
|
data.putExtra(resultName, result)
|
||||||
activity().setResult(Activity.RESULT_CANCELED, data)
|
activity().setResult(Activity.RESULT_CANCELED, data)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
data.putExtra(resultName, result)
|
data.putExtra(resultName, result)
|
||||||
activity().setResult(Activity.RESULT_OK, data)
|
activity().setResult(Activity.RESULT_OK, data)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
finish()
|
|
||||||
}
|
}
|
||||||
|
finish()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun activeWorkflow(): Workflow<*>? {
|
private fun activeWorkflow(): Workflow<*>? {
|
||||||
|
@ -16,9 +16,10 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
@PerView
|
@PerView
|
||||||
class S3AddOrChangePresenter @Inject internal constructor( //
|
class S3AddOrChangePresenter @Inject internal constructor( //
|
||||||
private val addOrChangeCloudConnectionUseCase: AddOrChangeCloudConnectionUseCase, //
|
private val addOrChangeCloudConnectionUseCase: AddOrChangeCloudConnectionUseCase, //
|
||||||
private val connectToS3UseCase: ConnectToS3UseCase, //
|
private val connectToS3UseCase: ConnectToS3UseCase, //
|
||||||
exceptionMappings: ExceptionHandlers) : Presenter<S3AddOrChangeView>(exceptionMappings) {
|
exceptionMappings: ExceptionHandlers
|
||||||
|
) : Presenter<S3AddOrChangeView>(exceptionMappings) {
|
||||||
|
|
||||||
fun checkUserInput(accessKey: String, secretKey: String, bucket: String, endpoint: String?, region: String?, cloudId: Long?, displayName: String) {
|
fun checkUserInput(accessKey: String, secretKey: String, bucket: String, endpoint: String?, region: String?, cloudId: Long?, displayName: String) {
|
||||||
var statusMessage: String? = null
|
var statusMessage: String? = null
|
||||||
@ -48,19 +49,19 @@ class S3AddOrChangePresenter @Inject internal constructor( //
|
|||||||
|
|
||||||
private fun encrypt(text: String): String {
|
private fun encrypt(text: String): String {
|
||||||
return CredentialCryptor //
|
return CredentialCryptor //
|
||||||
.getInstance(context()) //
|
.getInstance(context()) //
|
||||||
.encrypt(text)
|
.encrypt(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun mapToCloud(accessKey: String, secretKey: String, bucket: String, endpoint: String?, region: String?, cloudId: Long?, displayName: String): S3Cloud {
|
private fun mapToCloud(accessKey: String, secretKey: String, bucket: String, endpoint: String?, region: String?, cloudId: Long?, displayName: String): S3Cloud {
|
||||||
var builder = S3Cloud //
|
var builder = S3Cloud //
|
||||||
.aS3Cloud() //
|
.aS3Cloud() //
|
||||||
.withAccessKey(accessKey) //
|
.withAccessKey(accessKey) //
|
||||||
.withSecretKey(secretKey) //
|
.withSecretKey(secretKey) //
|
||||||
.withS3Bucket(bucket) //
|
.withS3Bucket(bucket) //
|
||||||
.withS3Endpoint(endpoint) //
|
.withS3Endpoint(endpoint) //
|
||||||
.withS3Region(region) //
|
.withS3Region(region) //
|
||||||
.withDisplayName(displayName)
|
.withDisplayName(displayName)
|
||||||
|
|
||||||
cloudId?.let { builder = builder.withId(cloudId) }
|
cloudId?.let { builder = builder.withId(cloudId) }
|
||||||
|
|
||||||
@ -74,17 +75,17 @@ class S3AddOrChangePresenter @Inject internal constructor( //
|
|||||||
private fun authenticate(cloud: S3Cloud) {
|
private fun authenticate(cloud: S3Cloud) {
|
||||||
view?.showProgress(ProgressModel(ProgressStateModel.AUTHENTICATION))
|
view?.showProgress(ProgressModel(ProgressStateModel.AUTHENTICATION))
|
||||||
connectToS3UseCase //
|
connectToS3UseCase //
|
||||||
.withCloud(cloud) //
|
.withCloud(cloud) //
|
||||||
.run(object : DefaultResultHandler<Void?>() {
|
.run(object : DefaultResultHandler<Void?>() {
|
||||||
override fun onSuccess(void: Void?) {
|
override fun onSuccess(void: Void?) {
|
||||||
onCloudAuthenticated(cloud)
|
onCloudAuthenticated(cloud)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
view?.showProgress(ProgressModel.COMPLETED)
|
view?.showProgress(ProgressModel.COMPLETED)
|
||||||
super.onError(e)
|
super.onError(e)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onCloudAuthenticated(cloud: Cloud) {
|
private fun onCloudAuthenticated(cloud: Cloud) {
|
||||||
@ -94,8 +95,8 @@ class S3AddOrChangePresenter @Inject internal constructor( //
|
|||||||
|
|
||||||
private fun save(cloud: Cloud) {
|
private fun save(cloud: Cloud) {
|
||||||
addOrChangeCloudConnectionUseCase //
|
addOrChangeCloudConnectionUseCase //
|
||||||
.withCloud(cloud) //
|
.withCloud(cloud) //
|
||||||
.run(DefaultResultHandler())
|
.run(DefaultResultHandler())
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
@ -10,8 +10,9 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
@PerView
|
@PerView
|
||||||
class SetPasswordPresenter @Inject constructor( //
|
class SetPasswordPresenter @Inject constructor( //
|
||||||
private val createNewVaultWorkflow: CreateNewVaultWorkflow, //
|
private val createNewVaultWorkflow: CreateNewVaultWorkflow, //
|
||||||
exceptionMappings: ExceptionHandlers) : Presenter<SetPasswordView>(exceptionMappings) {
|
exceptionMappings: ExceptionHandlers
|
||||||
|
) : Presenter<SetPasswordView>(exceptionMappings) {
|
||||||
|
|
||||||
override fun workflows(): Iterable<Workflow<*>> {
|
override fun workflows(): Iterable<Workflow<*>> {
|
||||||
return setOf(createNewVaultWorkflow)
|
return setOf(createNewVaultWorkflow)
|
||||||
|
@ -39,12 +39,13 @@ import timber.log.Timber
|
|||||||
|
|
||||||
@PerView
|
@PerView
|
||||||
class SettingsPresenter @Inject internal constructor(
|
class SettingsPresenter @Inject internal constructor(
|
||||||
private val updateCheckUseCase: DoUpdateCheckUseCase, //
|
private val updateCheckUseCase: DoUpdateCheckUseCase, //
|
||||||
private val updateUseCase: DoUpdateUseCase, //
|
private val updateUseCase: DoUpdateUseCase, //
|
||||||
private val networkConnectionCheck: NetworkConnectionCheck, //
|
private val networkConnectionCheck: NetworkConnectionCheck, //
|
||||||
exceptionMappings: ExceptionHandlers, //
|
exceptionMappings: ExceptionHandlers, //
|
||||||
private val fileUtil: FileUtil, //
|
private val fileUtil: FileUtil, //
|
||||||
private val sharedPreferencesHandler: SharedPreferencesHandler) : Presenter<SettingsView>(exceptionMappings) {
|
private val sharedPreferencesHandler: SharedPreferencesHandler
|
||||||
|
) : Presenter<SettingsView>(exceptionMappings) {
|
||||||
|
|
||||||
fun onSendErrorReportClicked() {
|
fun onSendErrorReportClicked() {
|
||||||
view?.showProgress(ProgressModel.GENERIC)
|
view?.showProgress(ProgressModel.GENERIC)
|
||||||
@ -58,11 +59,11 @@ class SettingsPresenter @Inject internal constructor(
|
|||||||
|
|
||||||
private fun sendErrorReport(attachment: File) {
|
private fun sendErrorReport(attachment: File) {
|
||||||
EmailBuilder.anEmail() //
|
EmailBuilder.anEmail() //
|
||||||
.to("support@cryptomator.org") //
|
.to("support@cryptomator.org") //
|
||||||
.withSubject(context().getString(R.string.error_report_subject)) //
|
.withSubject(context().getString(R.string.error_report_subject)) //
|
||||||
.withBody(errorReportEmailBody()) //
|
.withBody(errorReportEmailBody()) //
|
||||||
.attach(attachment) //
|
.attach(attachment) //
|
||||||
.send(activity())
|
.send(activity())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun errorReportEmailBody(): String {
|
private fun errorReportEmailBody(): String {
|
||||||
@ -76,20 +77,22 @@ class SettingsPresenter @Inject internal constructor(
|
|||||||
else -> "Google Play"
|
else -> "Google Play"
|
||||||
}
|
}
|
||||||
return StringBuilder().append("## ").append(context().getString(R.string.error_report_subject)).append("\n\n") //
|
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("### ").append(context().getString(R.string.error_report_section_summary)).append('\n') //
|
||||||
.append(context().getString(R.string.error_report_summary_description)).append("\n\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("### ").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("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("Android ").append(Build.VERSION.RELEASE).append(" / API").append(Build.VERSION.SDK_INT).append("\n") //
|
||||||
.append("Device ").append(Build.MODEL) //
|
.append("Device ").append(Build.MODEL) //
|
||||||
.toString()
|
.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun grantLocalStoragePermissionForAutoUpload() {
|
fun grantLocalStoragePermissionForAutoUpload() {
|
||||||
requestPermissions(PermissionsResultCallbacks.onLocalStoragePermissionGranted(), //
|
requestPermissions(
|
||||||
R.string.permission_snackbar_auth_auto_upload, //
|
PermissionsResultCallbacks.onLocalStoragePermissionGranted(), //
|
||||||
Manifest.permission.READ_EXTERNAL_STORAGE, //
|
R.string.permission_snackbar_auth_auto_upload, //
|
||||||
Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
Manifest.permission.READ_EXTERNAL_STORAGE, //
|
||||||
|
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback
|
@Callback
|
||||||
@ -106,23 +109,23 @@ class SettingsPresenter @Inject internal constructor(
|
|||||||
fun onCheckUpdateClicked() {
|
fun onCheckUpdateClicked() {
|
||||||
if (networkConnectionCheck.isPresent) {
|
if (networkConnectionCheck.isPresent) {
|
||||||
updateCheckUseCase //
|
updateCheckUseCase //
|
||||||
.withVersion(BuildConfig.VERSION_NAME)
|
.withVersion(BuildConfig.VERSION_NAME)
|
||||||
.run(object : NoOpResultHandler<Optional<UpdateCheck?>?>() {
|
.run(object : NoOpResultHandler<Optional<UpdateCheck?>?>() {
|
||||||
override fun onSuccess(result: Optional<UpdateCheck?>?) {
|
override fun onSuccess(result: Optional<UpdateCheck?>?) {
|
||||||
if (result?.isPresent == true) {
|
if (result?.isPresent == true) {
|
||||||
result.get()?.let { updateStatusRetrieved(it, context()) }
|
result.get()?.let { updateStatusRetrieved(it, context()) }
|
||||||
} else {
|
} else {
|
||||||
Timber.tag("SettingsPresenter").i("UpdateCheck finished, latest version")
|
Timber.tag("SettingsPresenter").i("UpdateCheck finished, latest version")
|
||||||
Toast.makeText(context(), getString(R.string.notification_update_check_finished_latest), Toast.LENGTH_SHORT).show()
|
Toast.makeText(context(), getString(R.string.notification_update_check_finished_latest), Toast.LENGTH_SHORT).show()
|
||||||
}
|
|
||||||
sharedPreferencesHandler.updateExecuted()
|
|
||||||
view?.refreshUpdateTimeView()
|
|
||||||
}
|
}
|
||||||
|
sharedPreferencesHandler.updateExecuted()
|
||||||
|
view?.refreshUpdateTimeView()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
showError(e)
|
showError(e)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(context(), R.string.error_update_no_internet, Toast.LENGTH_SHORT).show()
|
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 uri = fileUtil.contentUriForNewTempFile("cryptomator.apk")
|
||||||
val file = fileUtil.tempFile("cryptomator.apk")
|
val file = fileUtil.tempFile("cryptomator.apk")
|
||||||
updateUseCase //
|
updateUseCase //
|
||||||
.withFile(file) //
|
.withFile(file) //
|
||||||
.run(object : NoOpResultHandler<Void?>() {
|
.run(object : NoOpResultHandler<Void?>() {
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
showError(e)
|
showError(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSuccess(result: Void?) {
|
override fun onSuccess(result: Void?) {
|
||||||
super.onSuccess(result)
|
super.onSuccess(result)
|
||||||
val intent = Intent(Intent.ACTION_VIEW)
|
val intent = Intent(Intent.ACTION_VIEW)
|
||||||
intent.setDataAndType(uri, "application/vnd.android.package-archive")
|
intent.setDataAndType(uri, "application/vnd.android.package-archive")
|
||||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||||
context().startActivity(intent)
|
context().startActivity(intent)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class CreateErrorReportArchiveTask : AsyncTask<Void?, IOException?, File?>() {
|
private inner class CreateErrorReportArchiveTask : AsyncTask<Void?, IOException?, File?>() {
|
||||||
|
@ -32,17 +32,18 @@ import timber.log.Timber
|
|||||||
|
|
||||||
@PerView
|
@PerView
|
||||||
class SharedFilesPresenter @Inject constructor( //
|
class SharedFilesPresenter @Inject constructor( //
|
||||||
private val getVaultListUseCase: GetVaultListUseCase, //
|
private val getVaultListUseCase: GetVaultListUseCase, //
|
||||||
private val getRootFolderUseCase: GetRootFolderUseCase, //
|
private val getRootFolderUseCase: GetRootFolderUseCase, //
|
||||||
private val getDecryptedCloudForVaultUseCase: GetDecryptedCloudForVaultUseCase, //
|
private val getDecryptedCloudForVaultUseCase: GetDecryptedCloudForVaultUseCase, //
|
||||||
private val uploadFilesUseCase: UploadFilesUseCase, //
|
private val uploadFilesUseCase: UploadFilesUseCase, //
|
||||||
private val getCloudListUseCase: GetCloudListUseCase, //
|
private val getCloudListUseCase: GetCloudListUseCase, //
|
||||||
private val contentResolverUtil: ContentResolverUtil, //
|
private val contentResolverUtil: ContentResolverUtil, //
|
||||||
private val fileCacheUtils: FileCacheUtils, //
|
private val fileCacheUtils: FileCacheUtils, //
|
||||||
private val authenticationExceptionHandler: AuthenticationExceptionHandler, //
|
private val authenticationExceptionHandler: AuthenticationExceptionHandler, //
|
||||||
private val cloudFolderModelMapper: CloudFolderModelMapper, //
|
private val cloudFolderModelMapper: CloudFolderModelMapper, //
|
||||||
private val progressModelMapper: ProgressModelMapper, //
|
private val progressModelMapper: ProgressModelMapper, //
|
||||||
exceptionMappings: ExceptionHandlers) : Presenter<SharedFilesView>(exceptionMappings) {
|
exceptionMappings: ExceptionHandlers
|
||||||
|
) : Presenter<SharedFilesView>(exceptionMappings) {
|
||||||
|
|
||||||
private val filesForUpload: MutableSet<UploadFile> = HashSet()
|
private val filesForUpload: MutableSet<UploadFile> = HashSet()
|
||||||
private val existingFilesForUpload: MutableSet<UploadFile> = HashSet()
|
private val existingFilesForUpload: MutableSet<UploadFile> = HashSet()
|
||||||
@ -65,8 +66,8 @@ class SharedFilesPresenter @Inject constructor( //
|
|||||||
} else {
|
} else {
|
||||||
Timber.tag("SharedFile").i("Received 1 file")
|
Timber.tag("SharedFile").i("Received 1 file")
|
||||||
contentResolverUtil.fileName(uri)
|
contentResolverUtil.fileName(uri)
|
||||||
?.let { filesForUpload.add(createUploadFile(it, uri)) }
|
?.let { filesForUpload.add(createUploadFile(it, uri)) }
|
||||||
?: Timber.tag("SharedFile").i("The file doesn't have a path in the 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)
|
Timber.tag("SharedFile").i("Received %d files", uris.size)
|
||||||
uris.forEach { uri ->
|
uris.forEach { uri ->
|
||||||
contentResolverUtil.fileName(uri)
|
contentResolverUtil.fileName(uri)
|
||||||
?.let { filesForUpload.add(createUploadFile(it, uri)) }
|
?.let { filesForUpload.add(createUploadFile(it, uri)) }
|
||||||
?: Timber.tag("SharedFile").i("The file doesn't have a path in the URI")
|
?: Timber.tag("SharedFile").i("The file doesn't have a path in the URI")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,8 +129,9 @@ class SharedFilesPresenter @Inject constructor( //
|
|||||||
} else {
|
} else {
|
||||||
if (!isPaused) {
|
if (!isPaused) {
|
||||||
requestActivityResult( //
|
requestActivityResult( //
|
||||||
ActivityResultCallbacks.vaultUnlockedSharedFiles(), //
|
ActivityResultCallbacks.vaultUnlockedSharedFiles(), //
|
||||||
Intents.unlockVaultIntent().withVaultModel(VaultModel(authenticatedVault)).withVaultAction(UnlockVaultIntent.VaultAction.UNLOCK))
|
Intents.unlockVaultIntent().withVaultModel(VaultModel(authenticatedVault)).withVaultAction(UnlockVaultIntent.VaultAction.UNLOCK)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -146,18 +148,18 @@ class SharedFilesPresenter @Inject constructor( //
|
|||||||
|
|
||||||
private fun decryptedCloudFor(vault: Vault) {
|
private fun decryptedCloudFor(vault: Vault) {
|
||||||
getDecryptedCloudForVaultUseCase //
|
getDecryptedCloudForVaultUseCase //
|
||||||
.withVault(vault) //
|
.withVault(vault) //
|
||||||
.run(object : DefaultResultHandler<Cloud>() {
|
.run(object : DefaultResultHandler<Cloud>() {
|
||||||
override fun onSuccess(cloud: Cloud) {
|
override fun onSuccess(cloud: Cloud) {
|
||||||
rootFolderFor(cloud)
|
rootFolderFor(cloud)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
if (!authenticationExceptionHandler.handleAuthenticationException(this@SharedFilesPresenter, e, ActivityResultCallbacks.decryptedCloudForAfterAuth(vault))) {
|
if (!authenticationExceptionHandler.handleAuthenticationException(this@SharedFilesPresenter, e, ActivityResultCallbacks.decryptedCloudForAfterAuth(vault))) {
|
||||||
super.onError(e)
|
super.onError(e)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback
|
@Callback
|
||||||
@ -168,18 +170,18 @@ class SharedFilesPresenter @Inject constructor( //
|
|||||||
|
|
||||||
private fun rootFolderFor(cloud: Cloud) {
|
private fun rootFolderFor(cloud: Cloud) {
|
||||||
getRootFolderUseCase //
|
getRootFolderUseCase //
|
||||||
.withCloud(cloud) //
|
.withCloud(cloud) //
|
||||||
.run(object : DefaultResultHandler<CloudFolder>() {
|
.run(object : DefaultResultHandler<CloudFolder>() {
|
||||||
override fun onSuccess(folder: CloudFolder) {
|
override fun onSuccess(folder: CloudFolder) {
|
||||||
when (authenticationState) {
|
when (authenticationState) {
|
||||||
AuthenticationState.CHOOSE_LOCATION -> navigateToVaultContent((folder.cloud as CryptoCloud).vault, folder)
|
AuthenticationState.CHOOSE_LOCATION -> navigateToVaultContent((folder.cloud as CryptoCloud).vault, folder)
|
||||||
AuthenticationState.INIT_ROOT -> {
|
AuthenticationState.INIT_ROOT -> {
|
||||||
location = cloudFolderModelMapper.toModel(folder)
|
location = cloudFolderModelMapper.toModel(folder)
|
||||||
checkForUsedFileNames(folder)
|
checkForUsedFileNames(folder)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun navigateToVaultContent(vault: Vault, folder: CloudFolder) {
|
private fun navigateToVaultContent(vault: Vault, folder: CloudFolder) {
|
||||||
@ -192,9 +194,11 @@ class SharedFilesPresenter @Inject constructor( //
|
|||||||
this.location = location
|
this.location = location
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun uploadFiles(nonReplacing: Set<UploadFile>, //
|
private fun uploadFiles(
|
||||||
replacing: Set<UploadFile>, //
|
nonReplacing: Set<UploadFile>, //
|
||||||
folder: CloudFolder) {
|
replacing: Set<UploadFile>, //
|
||||||
|
folder: CloudFolder
|
||||||
|
) {
|
||||||
if (nonReplacing.size + replacing.size == 0) {
|
if (nonReplacing.size + replacing.size == 0) {
|
||||||
view?.finish()
|
view?.finish()
|
||||||
}
|
}
|
||||||
@ -207,17 +211,17 @@ class SharedFilesPresenter @Inject constructor( //
|
|||||||
|
|
||||||
private fun uploadFiles(folder: CloudFolder, files: List<UploadFile>) {
|
private fun uploadFiles(folder: CloudFolder, files: List<UploadFile>) {
|
||||||
uploadFilesUseCase //
|
uploadFilesUseCase //
|
||||||
.withParent(folder) //
|
.withParent(folder) //
|
||||||
.andFiles(files) //
|
.andFiles(files) //
|
||||||
.run(object : DefaultProgressAwareResultHandler<List<CloudFile>, UploadState>() {
|
.run(object : DefaultProgressAwareResultHandler<List<CloudFile>, UploadState>() {
|
||||||
override fun onProgress(progress: Progress<UploadState>) {
|
override fun onProgress(progress: Progress<UploadState>) {
|
||||||
view?.showProgress(progressModelMapper.toModel(progress))
|
view?.showProgress(progressModelMapper.toModel(progress))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFinished() {
|
override fun onFinished() {
|
||||||
onFileUploadCompleted()
|
onFileUploadCompleted()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onFileUploadCompleted() {
|
private fun onFileUploadCompleted() {
|
||||||
@ -248,12 +252,12 @@ class SharedFilesPresenter @Inject constructor( //
|
|||||||
private fun checkForUsedFileNames(folder: CloudFolder) {
|
private fun checkForUsedFileNames(folder: CloudFolder) {
|
||||||
view?.showProgress(ProgressModel.GENERIC)
|
view?.showProgress(ProgressModel.GENERIC)
|
||||||
getCloudListUseCase //
|
getCloudListUseCase //
|
||||||
.withFolder(folder) //
|
.withFolder(folder) //
|
||||||
.run(object : DefaultResultHandler<List<CloudNode>>() {
|
.run(object : DefaultResultHandler<List<CloudNode>>() {
|
||||||
override fun onSuccess(currentCloudNodes: List<CloudNode>) {
|
override fun onSuccess(currentCloudNodes: List<CloudNode>) {
|
||||||
checkForExistingFilesOrUploadFiles(folder, currentCloudNodes)
|
checkForExistingFilesOrUploadFiles(folder, currentCloudNodes)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hasUsedFileNamesAtLocation(currentCloudNodes: List<CloudNode>): Boolean {
|
private fun hasUsedFileNamesAtLocation(currentCloudNodes: List<CloudNode>): Boolean {
|
||||||
@ -264,9 +268,10 @@ class SharedFilesPresenter @Inject constructor( //
|
|||||||
if (cloudNode is CloudFile) {
|
if (cloudNode is CloudFile) {
|
||||||
filesForUpload.remove(uploadFileWithName.get())
|
filesForUpload.remove(uploadFileWithName.get())
|
||||||
existingFilesForUpload.add( //
|
existingFilesForUpload.add( //
|
||||||
UploadFile.aCopyOf(uploadFileWithName.get()) //
|
UploadFile.aCopyOf(uploadFileWithName.get()) //
|
||||||
.thatIsReplacing(true) //
|
.thatIsReplacing(true) //
|
||||||
.build())
|
.build()
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
// remove file when name is used by a folder
|
// remove file when name is used by a folder
|
||||||
filesForUpload.remove(uploadFileWithName.get())
|
filesForUpload.remove(uploadFileWithName.get())
|
||||||
@ -278,9 +283,9 @@ class SharedFilesPresenter @Inject constructor( //
|
|||||||
|
|
||||||
private fun fileForUploadWithName(name: String): Optional<UploadFile> {
|
private fun fileForUploadWithName(name: String): Optional<UploadFile> {
|
||||||
return filesForUpload
|
return filesForUpload
|
||||||
.firstOrNull { it.fileName == name }
|
.firstOrNull { it.fileName == name }
|
||||||
?.let { Optional.of(it) }
|
?.let { Optional.of(it) }
|
||||||
?: Optional.empty()
|
?: Optional.empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkForExistingFilesOrUploadFiles(folder: CloudFolder, currentCloudNodes: List<CloudNode>) {
|
private fun checkForExistingFilesOrUploadFiles(folder: CloudFolder, currentCloudNodes: List<CloudNode>) {
|
||||||
@ -297,7 +302,7 @@ class SharedFilesPresenter @Inject constructor( //
|
|||||||
|
|
||||||
private fun prepareSavingFiles() {
|
private fun prepareSavingFiles() {
|
||||||
location?.let { checkForUsedFileNames(it.toCloudNode()) }
|
location?.let { checkForUsedFileNames(it.toCloudNode()) }
|
||||||
?: authenticate(selectedVault, AuthenticationState.INIT_ROOT)
|
?: authenticate(selectedVault, AuthenticationState.INIT_ROOT)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onSaveButtonPressed(filesForUpload: List<SharedFileModel>) {
|
fun onSaveButtonPressed(filesForUpload: List<SharedFileModel>) {
|
||||||
@ -310,9 +315,11 @@ class SharedFilesPresenter @Inject constructor( //
|
|||||||
view?.showMessage(R.string.error_names_contains_invalid_characters)
|
view?.showMessage(R.string.error_names_contains_invalid_characters)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
requestPermissions(PermissionsResultCallbacks.saveFilesPermissionCallback(), //
|
requestPermissions(
|
||||||
R.string.permission_message_share_file, //
|
PermissionsResultCallbacks.saveFilesPermissionCallback(), //
|
||||||
Manifest.permission.READ_EXTERNAL_STORAGE)
|
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) {
|
private fun navigateToVaultContent(vaultModel: VaultModel, decryptedRoot: CloudFolderModel) {
|
||||||
requestActivityResult( //
|
requestActivityResult( //
|
||||||
ActivityResultCallbacks.onChooseLocation(vaultModel), //
|
ActivityResultCallbacks.onChooseLocation(vaultModel), //
|
||||||
Intents.browseFilesIntent() //
|
Intents.browseFilesIntent() //
|
||||||
.withFolder(decryptedRoot) //
|
.withFolder(decryptedRoot) //
|
||||||
.withTitle(vaultModel.name) //
|
.withTitle(vaultModel.name) //
|
||||||
.withChooseCloudNodeSettings( //
|
.withChooseCloudNodeSettings( //
|
||||||
ChooseCloudNodeSettings.chooseCloudNodeSettings() //
|
ChooseCloudNodeSettings.chooseCloudNodeSettings() //
|
||||||
.withExtraTitle(context().getString(R.string.screen_file_browser_share_destination_title)) //
|
.withExtraTitle(context().getString(R.string.screen_file_browser_share_destination_title)) //
|
||||||
.withExtraToolbarIcon(R.drawable.ic_clear) //
|
.withExtraToolbarIcon(R.drawable.ic_clear) //
|
||||||
.withButtonText(context().getString(R.string.screen_file_browser_share_button_text)) //
|
.withButtonText(context().getString(R.string.screen_file_browser_share_button_text)) //
|
||||||
.selectingFolders() //
|
.selectingFolders() //
|
||||||
.build()))
|
.build()
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback
|
@Callback
|
||||||
@ -396,18 +405,19 @@ class SharedFilesPresenter @Inject constructor( //
|
|||||||
|
|
||||||
private fun createUploadFile(fileName: String, uri: Uri): UploadFile {
|
private fun createUploadFile(fileName: String, uri: Uri): UploadFile {
|
||||||
return UploadFile.anUploadFile() //
|
return UploadFile.anUploadFile() //
|
||||||
.withFileName(fileName) //
|
.withFileName(fileName) //
|
||||||
.withDataSource(UriBasedDataSource.from(uri)) //
|
.withDataSource(UriBasedDataSource.from(uri)) //
|
||||||
.thatIsReplacing(false) //
|
.thatIsReplacing(false) //
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
unsubscribeOnDestroy( //
|
unsubscribeOnDestroy( //
|
||||||
getRootFolderUseCase, //
|
getRootFolderUseCase, //
|
||||||
getVaultListUseCase, //
|
getVaultListUseCase, //
|
||||||
getDecryptedCloudForVaultUseCase, //
|
getDecryptedCloudForVaultUseCase, //
|
||||||
uploadFilesUseCase, //
|
uploadFilesUseCase, //
|
||||||
getCloudListUseCase)
|
getCloudListUseCase
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,11 +21,12 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
@PerView
|
@PerView
|
||||||
class TextEditorPresenter @Inject constructor( //
|
class TextEditorPresenter @Inject constructor( //
|
||||||
private val fileCacheUtils: FileCacheUtils, //
|
private val fileCacheUtils: FileCacheUtils, //
|
||||||
private val fileUtil: FileUtil, //
|
private val fileUtil: FileUtil, //
|
||||||
private val contentResolverUtil: ContentResolverUtil, //
|
private val contentResolverUtil: ContentResolverUtil, //
|
||||||
private val uploadFilesUseCase: UploadFilesUseCase, //
|
private val uploadFilesUseCase: UploadFilesUseCase, //
|
||||||
exceptionMappings: ExceptionHandlers) : Presenter<TextEditorView>(exceptionMappings) {
|
exceptionMappings: ExceptionHandlers
|
||||||
|
) : Presenter<TextEditorView>(exceptionMappings) {
|
||||||
|
|
||||||
private val textFile = AtomicReference<CloudFileModel>()
|
private val textFile = AtomicReference<CloudFileModel>()
|
||||||
|
|
||||||
@ -64,34 +65,36 @@ class TextEditorPresenter @Inject constructor( //
|
|||||||
view?.let {
|
view?.let {
|
||||||
it.showProgress(ProgressModel.GENERIC)
|
it.showProgress(ProgressModel.GENERIC)
|
||||||
val uri = fileCacheUtils.tmpFile() //
|
val uri = fileCacheUtils.tmpFile() //
|
||||||
.withContent(it.textFileContent) //
|
.withContent(it.textFileContent) //
|
||||||
.create()
|
.create()
|
||||||
uploadFile(textFile.get().name, UriBasedDataSource.from(uri))
|
uploadFile(textFile.get().name, UriBasedDataSource.from(uri))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun uploadFile(fileName: String, dataSource: DataSource) {
|
private fun uploadFile(fileName: String, dataSource: DataSource) {
|
||||||
uploadFilesUseCase //
|
uploadFilesUseCase //
|
||||||
.withParent(textFile.get().parent.toCloudNode()) //
|
.withParent(textFile.get().parent.toCloudNode()) //
|
||||||
.andFiles(listOf( //
|
.andFiles(
|
||||||
UploadFile.anUploadFile() //
|
listOf( //
|
||||||
.withFileName(fileName) //
|
UploadFile.anUploadFile() //
|
||||||
.withDataSource(dataSource) //
|
.withFileName(fileName) //
|
||||||
.thatIsReplacing(true) //
|
.withDataSource(dataSource) //
|
||||||
.build() //
|
.thatIsReplacing(true) //
|
||||||
)) //
|
.build() //
|
||||||
.run(object : DefaultProgressAwareResultHandler<List<CloudFile?>, UploadState>() {
|
)
|
||||||
override fun onFinished() {
|
) //
|
||||||
view?.showProgress(ProgressModel.COMPLETED)
|
.run(object : DefaultProgressAwareResultHandler<List<CloudFile?>, UploadState>() {
|
||||||
view?.finish()
|
override fun onFinished() {
|
||||||
view?.showMessage(R.string.screen_text_editor_save_success)
|
view?.showProgress(ProgressModel.COMPLETED)
|
||||||
}
|
view?.finish()
|
||||||
|
view?.showMessage(R.string.screen_text_editor_save_success)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
view?.showProgress(ProgressModel.COMPLETED)
|
view?.showProgress(ProgressModel.COMPLETED)
|
||||||
showError(e)
|
showError(e)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadFileContent() {
|
fun loadFileContent() {
|
||||||
|
@ -40,17 +40,18 @@ import timber.log.Timber
|
|||||||
|
|
||||||
@PerView
|
@PerView
|
||||||
class UnlockVaultPresenter @Inject constructor(
|
class UnlockVaultPresenter @Inject constructor(
|
||||||
private val changePasswordUseCase: ChangePasswordUseCase,
|
private val changePasswordUseCase: ChangePasswordUseCase,
|
||||||
private val deleteVaultUseCase: DeleteVaultUseCase,
|
private val deleteVaultUseCase: DeleteVaultUseCase,
|
||||||
private val getUnverifiedVaultConfigUseCase: GetUnverifiedVaultConfigUseCase,
|
private val getUnverifiedVaultConfigUseCase: GetUnverifiedVaultConfigUseCase,
|
||||||
private val lockVaultUseCase: LockVaultUseCase,
|
private val lockVaultUseCase: LockVaultUseCase,
|
||||||
private val unlockVaultUsingMasterkeyUseCase: UnlockVaultUsingMasterkeyUseCase,
|
private val unlockVaultUsingMasterkeyUseCase: UnlockVaultUsingMasterkeyUseCase,
|
||||||
private val prepareUnlockUseCase: PrepareUnlockUseCase,
|
private val prepareUnlockUseCase: PrepareUnlockUseCase,
|
||||||
private val removeStoredVaultPasswordsUseCase: RemoveStoredVaultPasswordsUseCase,
|
private val removeStoredVaultPasswordsUseCase: RemoveStoredVaultPasswordsUseCase,
|
||||||
private val saveVaultUseCase: SaveVaultUseCase,
|
private val saveVaultUseCase: SaveVaultUseCase,
|
||||||
private val authenticationExceptionHandler: AuthenticationExceptionHandler,
|
private val authenticationExceptionHandler: AuthenticationExceptionHandler,
|
||||||
private val sharedPreferencesHandler: SharedPreferencesHandler,
|
private val sharedPreferencesHandler: SharedPreferencesHandler,
|
||||||
exceptionMappings: ExceptionHandlers) : Presenter<UnlockVaultView>(exceptionMappings) {
|
exceptionMappings: ExceptionHandlers
|
||||||
|
) : Presenter<UnlockVaultView>(exceptionMappings) {
|
||||||
|
|
||||||
private var startedUsingPrepareUnlock = false
|
private var startedUsingPrepareUnlock = false
|
||||||
private var retryUnlockHandler: Handler? = null
|
private var retryUnlockHandler: Handler? = null
|
||||||
@ -77,27 +78,27 @@ class UnlockVaultPresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
getUnverifiedVaultConfigUseCase
|
getUnverifiedVaultConfigUseCase
|
||||||
.withVault(intent.vaultModel().toVault())
|
.withVault(intent.vaultModel().toVault())
|
||||||
.run(object : DefaultResultHandler<Optional<UnverifiedVaultConfig>>() {
|
.run(object : DefaultResultHandler<Optional<UnverifiedVaultConfig>>() {
|
||||||
override fun onSuccess(unverifiedVaultConfig: Optional<UnverifiedVaultConfig>) {
|
override fun onSuccess(unverifiedVaultConfig: Optional<UnverifiedVaultConfig>) {
|
||||||
if (unverifiedVaultConfig.isAbsent || unverifiedVaultConfig.get().keyId.scheme == CryptoConstants.MASTERKEY_SCHEME) {
|
if (unverifiedVaultConfig.isAbsent || unverifiedVaultConfig.get().keyId.scheme == CryptoConstants.MASTERKEY_SCHEME) {
|
||||||
when (intent.vaultAction()) {
|
when (intent.vaultAction()) {
|
||||||
UnlockVaultIntent.VaultAction.UNLOCK, UnlockVaultIntent.VaultAction.UNLOCK_FOR_BIOMETRIC_AUTH -> {
|
UnlockVaultIntent.VaultAction.UNLOCK, UnlockVaultIntent.VaultAction.UNLOCK_FOR_BIOMETRIC_AUTH -> {
|
||||||
startedUsingPrepareUnlock = sharedPreferencesHandler.backgroundUnlockPreparation()
|
startedUsingPrepareUnlock = sharedPreferencesHandler.backgroundUnlockPreparation()
|
||||||
pendingUnlockFor(intent.vaultModel().toVault())?.unverifiedVaultConfig = unverifiedVaultConfig.orElse(null)
|
pendingUnlockFor(intent.vaultModel().toVault())?.unverifiedVaultConfig = unverifiedVaultConfig.orElse(null)
|
||||||
unlockVault(intent.vaultModel())
|
unlockVault(intent.vaultModel())
|
||||||
}
|
|
||||||
UnlockVaultIntent.VaultAction.CHANGE_PASSWORD -> view?.showChangePasswordDialog(intent.vaultModel(), unverifiedVaultConfig.orElse(null))
|
|
||||||
else -> TODO("Not yet implemented")
|
|
||||||
}
|
}
|
||||||
|
UnlockVaultIntent.VaultAction.CHANGE_PASSWORD -> view?.showChangePasswordDialog(intent.vaultModel(), unverifiedVaultConfig.orElse(null))
|
||||||
|
else -> TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
super.onError(e)
|
super.onError(e)
|
||||||
finishWithResult(null)
|
finishWithResult(null)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun unlockVault(vaultModel: VaultModel) {
|
private fun unlockVault(vaultModel: VaultModel) {
|
||||||
@ -134,8 +135,8 @@ class UnlockVaultPresenter @Inject constructor(
|
|||||||
|
|
||||||
private fun canUseBiometricOn(vault: VaultModel): Boolean {
|
private fun canUseBiometricOn(vault: VaultModel): Boolean {
|
||||||
return vault.password != null && BiometricManager //
|
return vault.password != null && BiometricManager //
|
||||||
.from(context()) //
|
.from(context()) //
|
||||||
.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG) == BiometricManager.BIOMETRIC_SUCCESS
|
.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG) == BiometricManager.BIOMETRIC_SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onUnlockCanceled() {
|
fun onUnlockCanceled() {
|
||||||
@ -146,31 +147,31 @@ class UnlockVaultPresenter @Inject constructor(
|
|||||||
|
|
||||||
fun startPrepareUnlockUseCase(vault: Vault) {
|
fun startPrepareUnlockUseCase(vault: Vault) {
|
||||||
prepareUnlockUseCase //
|
prepareUnlockUseCase //
|
||||||
.withVault(vault) //
|
.withVault(vault) //
|
||||||
.andUnverifiedVaultConfig(Optional.ofNullable(pendingUnlockFor(intent.vaultModel().toVault())?.unverifiedVaultConfig))
|
.andUnverifiedVaultConfig(Optional.ofNullable(pendingUnlockFor(intent.vaultModel().toVault())?.unverifiedVaultConfig))
|
||||||
.run(object : DefaultResultHandler<UnlockToken>() {
|
.run(object : DefaultResultHandler<UnlockToken>() {
|
||||||
override fun onSuccess(unlockToken: UnlockToken) {
|
override fun onSuccess(unlockToken: UnlockToken) {
|
||||||
if (!startedUsingPrepareUnlock && vault.password != null) {
|
if (!startedUsingPrepareUnlock && vault.password != null) {
|
||||||
doUnlock(unlockToken, vault.password, pendingUnlockFor(intent.vaultModel().toVault())?.unverifiedVaultConfig)
|
doUnlock(unlockToken, vault.password, pendingUnlockFor(intent.vaultModel().toVault())?.unverifiedVaultConfig)
|
||||||
} else {
|
} else {
|
||||||
unlockTokenObtained(unlockToken)
|
unlockTokenObtained(unlockToken)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
if (e is AuthenticationException) {
|
if (e is AuthenticationException) {
|
||||||
view?.cancelBasicAuthIfRunning()
|
view?.cancelBasicAuthIfRunning()
|
||||||
}
|
}
|
||||||
if (!authenticationExceptionHandler.handleAuthenticationException(this@UnlockVaultPresenter, e, ActivityResultCallbacks.authenticatedAfterUnlock(vault))) {
|
if (!authenticationExceptionHandler.handleAuthenticationException(this@UnlockVaultPresenter, e, ActivityResultCallbacks.authenticatedAfterUnlock(vault))) {
|
||||||
super.onError(e)
|
super.onError(e)
|
||||||
if (e is NetworkConnectionException) {
|
if (e is NetworkConnectionException) {
|
||||||
running = true
|
running = true
|
||||||
retryUnlockHandler = Handler()
|
retryUnlockHandler = Handler()
|
||||||
restartUnlockUseCase(vault)
|
restartUnlockUseCase(vault)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback(dispatchResultOkOnly = false)
|
@Callback(dispatchResultOkOnly = false)
|
||||||
@ -197,22 +198,22 @@ class UnlockVaultPresenter @Inject constructor(
|
|||||||
retryUnlockHandler?.postDelayed({
|
retryUnlockHandler?.postDelayed({
|
||||||
if (running) {
|
if (running) {
|
||||||
prepareUnlockUseCase //
|
prepareUnlockUseCase //
|
||||||
.withVault(vault) //
|
.withVault(vault) //
|
||||||
.run(object : DefaultResultHandler<UnlockToken>() {
|
.run(object : DefaultResultHandler<UnlockToken>() {
|
||||||
override fun onSuccess(unlockToken: UnlockToken) {
|
override fun onSuccess(unlockToken: UnlockToken) {
|
||||||
if (!startedUsingPrepareUnlock && vault.password != null) {
|
if (!startedUsingPrepareUnlock && vault.password != null) {
|
||||||
doUnlock(unlockToken, vault.password, pendingUnlockFor(intent.vaultModel().toVault())?.unverifiedVaultConfig)
|
doUnlock(unlockToken, vault.password, pendingUnlockFor(intent.vaultModel().toVault())?.unverifiedVaultConfig)
|
||||||
} else {
|
} else {
|
||||||
unlockTokenObtained(unlockToken)
|
unlockTokenObtained(unlockToken)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
if (e is NetworkConnectionException) {
|
if (e is NetworkConnectionException) {
|
||||||
restartUnlockUseCase(vault)
|
restartUnlockUseCase(vault)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}, 1000)
|
}, 1000)
|
||||||
}
|
}
|
||||||
@ -228,28 +229,28 @@ class UnlockVaultPresenter @Inject constructor(
|
|||||||
|
|
||||||
private fun doUnlock(token: UnlockToken, password: String, unverifiedVaultConfig: UnverifiedVaultConfig?) {
|
private fun doUnlock(token: UnlockToken, password: String, unverifiedVaultConfig: UnverifiedVaultConfig?) {
|
||||||
unlockVaultUsingMasterkeyUseCase //
|
unlockVaultUsingMasterkeyUseCase //
|
||||||
.withVaultOrUnlockToken(VaultOrUnlockToken.from(token)) //
|
.withVaultOrUnlockToken(VaultOrUnlockToken.from(token)) //
|
||||||
.andUnverifiedVaultConfig(Optional.ofNullable(unverifiedVaultConfig)) //
|
.andUnverifiedVaultConfig(Optional.ofNullable(unverifiedVaultConfig)) //
|
||||||
.andPassword(password) //
|
.andPassword(password) //
|
||||||
.run(object : DefaultResultHandler<Cloud>() {
|
.run(object : DefaultResultHandler<Cloud>() {
|
||||||
override fun onSuccess(cloud: Cloud) {
|
override fun onSuccess(cloud: Cloud) {
|
||||||
when (intent.vaultAction()) {
|
when (intent.vaultAction()) {
|
||||||
UnlockVaultIntent.VaultAction.ENCRYPT_PASSWORD, UnlockVaultIntent.VaultAction.UNLOCK_FOR_BIOMETRIC_AUTH -> {
|
UnlockVaultIntent.VaultAction.ENCRYPT_PASSWORD, UnlockVaultIntent.VaultAction.UNLOCK_FOR_BIOMETRIC_AUTH -> {
|
||||||
handleUnlockVaultSuccess(token.vault, cloud, password)
|
handleUnlockVaultSuccess(token.vault, cloud, password)
|
||||||
}
|
|
||||||
UnlockVaultIntent.VaultAction.UNLOCK -> finishWithResult(cloud)
|
|
||||||
else -> TODO("Not yet implemented")
|
|
||||||
}
|
}
|
||||||
|
UnlockVaultIntent.VaultAction.UNLOCK -> finishWithResult(cloud)
|
||||||
|
else -> TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
super.onError(e)
|
super.onError(e)
|
||||||
// finish in case of biometric auth, otherwise show error in dialog
|
// finish in case of biometric auth, otherwise show error in dialog
|
||||||
if(view?.isShowingDialog(EnterPasswordDialog::class) == false) {
|
if (view?.isShowingDialog(EnterPasswordDialog::class) == false) {
|
||||||
finishWithResult(null)
|
finishWithResult(null)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleUnlockVaultSuccess(vault: Vault, cloud: Cloud, password: String) {
|
private fun handleUnlockVaultSuccess(vault: Vault, cloud: Cloud, password: String) {
|
||||||
@ -295,12 +296,12 @@ class UnlockVaultPresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
UnlockVaultIntent.VaultAction.CHANGE_PASSWORD -> {
|
UnlockVaultIntent.VaultAction.CHANGE_PASSWORD -> {
|
||||||
saveVaultUseCase //
|
saveVaultUseCase //
|
||||||
.withVault(vaultModel.toVault()) //
|
.withVault(vaultModel.toVault()) //
|
||||||
.run(object : DefaultResultHandler<Vault>() {
|
.run(object : DefaultResultHandler<Vault>() {
|
||||||
override fun onSuccess(vault: Vault) {
|
override fun onSuccess(vault: Vault) {
|
||||||
finishWithResult(vaultModel)
|
finishWithResult(vaultModel)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
else -> TODO("Not yet implemented")
|
else -> TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
@ -309,31 +310,36 @@ class UnlockVaultPresenter @Inject constructor(
|
|||||||
fun onChangePasswordClick(vaultModel: VaultModel, unverifiedVaultConfig: UnverifiedVaultConfig?, oldPassword: String, newPassword: String) {
|
fun onChangePasswordClick(vaultModel: VaultModel, unverifiedVaultConfig: UnverifiedVaultConfig?, oldPassword: String, newPassword: String) {
|
||||||
view?.showProgress(ProgressModel(ProgressStateModel.CHANGING_PASSWORD))
|
view?.showProgress(ProgressModel(ProgressStateModel.CHANGING_PASSWORD))
|
||||||
changePasswordUseCase.withVault(vaultModel.toVault()) //
|
changePasswordUseCase.withVault(vaultModel.toVault()) //
|
||||||
.andUnverifiedVaultConfig(Optional.ofNullable(unverifiedVaultConfig)) //
|
.andUnverifiedVaultConfig(Optional.ofNullable(unverifiedVaultConfig)) //
|
||||||
.andOldPassword(oldPassword) //
|
.andOldPassword(oldPassword) //
|
||||||
.andNewPassword(newPassword) //
|
.andNewPassword(newPassword) //
|
||||||
.run(object : DefaultResultHandler<Void?>() {
|
.run(object : DefaultResultHandler<Void?>() {
|
||||||
override fun onSuccess(void: Void?) {
|
override fun onSuccess(void: Void?) {
|
||||||
view?.showProgress(ProgressModel.COMPLETED)
|
view?.showProgress(ProgressModel.COMPLETED)
|
||||||
view?.showMessage(R.string.screen_vault_list_change_password_successful)
|
view?.showMessage(R.string.screen_vault_list_change_password_successful)
|
||||||
if (canUseBiometricOn(vaultModel)) {
|
if (canUseBiometricOn(vaultModel)) {
|
||||||
view?.getEncryptedPasswordWithBiometricAuthentication(VaultModel( //
|
view?.getEncryptedPasswordWithBiometricAuthentication(
|
||||||
Vault.aCopyOf(vaultModel.toVault()) //
|
VaultModel( //
|
||||||
.withSavedPassword(newPassword) //
|
Vault.aCopyOf(vaultModel.toVault()) //
|
||||||
.build()))
|
.withSavedPassword(newPassword) //
|
||||||
} else {
|
.build()
|
||||||
finishWithResult(vaultModel)
|
)
|
||||||
}
|
)
|
||||||
|
} else {
|
||||||
|
finishWithResult(vaultModel)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
if (!authenticationExceptionHandler.handleAuthenticationException( //
|
if (!authenticationExceptionHandler.handleAuthenticationException( //
|
||||||
this@UnlockVaultPresenter, e, //
|
this@UnlockVaultPresenter, e, //
|
||||||
ActivityResultCallbacks.changePasswordAfterAuthentication(vaultModel.toVault(), unverifiedVaultConfig, oldPassword, newPassword))) {
|
ActivityResultCallbacks.changePasswordAfterAuthentication(vaultModel.toVault(), unverifiedVaultConfig, oldPassword, newPassword)
|
||||||
showError(e)
|
)
|
||||||
}
|
) {
|
||||||
|
showError(e)
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback
|
@Callback
|
||||||
@ -346,22 +352,22 @@ class UnlockVaultPresenter @Inject constructor(
|
|||||||
fun saveVaultAfterChangePasswordButFailedBiometricAuth(vault: Vault) {
|
fun saveVaultAfterChangePasswordButFailedBiometricAuth(vault: Vault) {
|
||||||
Timber.tag("UnlockVaultPresenter").e("Save vault without password because biometric auth failed after changing vault password")
|
Timber.tag("UnlockVaultPresenter").e("Save vault without password because biometric auth failed after changing vault password")
|
||||||
saveVaultUseCase //
|
saveVaultUseCase //
|
||||||
.withVault(vault) //
|
.withVault(vault) //
|
||||||
.run(object : DefaultResultHandler<Vault>() {
|
.run(object : DefaultResultHandler<Vault>() {
|
||||||
override fun onSuccess(vault: Vault) {
|
override fun onSuccess(vault: Vault) {
|
||||||
finishWithResult(vault)
|
finishWithResult(vault)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onDeleteMissingVaultClicked(vault: Vault) {
|
fun onDeleteMissingVaultClicked(vault: Vault) {
|
||||||
deleteVaultUseCase //
|
deleteVaultUseCase //
|
||||||
.withVault(vault) //
|
.withVault(vault) //
|
||||||
.run(object : DefaultResultHandler<Long>() {
|
.run(object : DefaultResultHandler<Long>() {
|
||||||
override fun onSuccess(vaultId: Long) {
|
override fun onSuccess(vaultId: Long) {
|
||||||
finishWithResult(null)
|
finishWithResult(null)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onCancelMissingVaultClicked(vault: Vault) {
|
fun onCancelMissingVaultClicked(vault: Vault) {
|
||||||
@ -410,14 +416,15 @@ class UnlockVaultPresenter @Inject constructor(
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
unsubscribeOnDestroy( //
|
unsubscribeOnDestroy( //
|
||||||
changePasswordUseCase, //
|
changePasswordUseCase, //
|
||||||
deleteVaultUseCase, //
|
deleteVaultUseCase, //
|
||||||
getUnverifiedVaultConfigUseCase, //
|
getUnverifiedVaultConfigUseCase, //
|
||||||
lockVaultUseCase, //
|
lockVaultUseCase, //
|
||||||
unlockVaultUsingMasterkeyUseCase, //
|
unlockVaultUsingMasterkeyUseCase, //
|
||||||
prepareUnlockUseCase, //
|
prepareUnlockUseCase, //
|
||||||
removeStoredVaultPasswordsUseCase, //
|
removeStoredVaultPasswordsUseCase, //
|
||||||
saveVaultUseCase)
|
saveVaultUseCase
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -61,25 +61,26 @@ import timber.log.Timber
|
|||||||
|
|
||||||
@PerView
|
@PerView
|
||||||
class VaultListPresenter @Inject constructor( //
|
class VaultListPresenter @Inject constructor( //
|
||||||
private val getVaultListUseCase: GetVaultListUseCase, //
|
private val getVaultListUseCase: GetVaultListUseCase, //
|
||||||
private val deleteVaultUseCase: DeleteVaultUseCase, //
|
private val deleteVaultUseCase: DeleteVaultUseCase, //
|
||||||
private val renameVaultUseCase: RenameVaultUseCase, //
|
private val renameVaultUseCase: RenameVaultUseCase, //
|
||||||
private val lockVaultUseCase: LockVaultUseCase, //
|
private val lockVaultUseCase: LockVaultUseCase, //
|
||||||
private val getDecryptedCloudForVaultUseCase: GetDecryptedCloudForVaultUseCase, //
|
private val getDecryptedCloudForVaultUseCase: GetDecryptedCloudForVaultUseCase, //
|
||||||
private val getRootFolderUseCase: GetRootFolderUseCase, //
|
private val getRootFolderUseCase: GetRootFolderUseCase, //
|
||||||
private val addExistingVaultWorkflow: AddExistingVaultWorkflow, //
|
private val addExistingVaultWorkflow: AddExistingVaultWorkflow, //
|
||||||
private val createNewVaultWorkflow: CreateNewVaultWorkflow, //
|
private val createNewVaultWorkflow: CreateNewVaultWorkflow, //
|
||||||
private val saveVaultUseCase: SaveVaultUseCase, //
|
private val saveVaultUseCase: SaveVaultUseCase, //
|
||||||
private val moveVaultPositionUseCase: MoveVaultPositionUseCase, //
|
private val moveVaultPositionUseCase: MoveVaultPositionUseCase, //
|
||||||
private val licenseCheckUseCase: DoLicenseCheckUseCase, //
|
private val licenseCheckUseCase: DoLicenseCheckUseCase, //
|
||||||
private val updateCheckUseCase: DoUpdateCheckUseCase, //
|
private val updateCheckUseCase: DoUpdateCheckUseCase, //
|
||||||
private val updateUseCase: DoUpdateUseCase, //
|
private val updateUseCase: DoUpdateUseCase, //
|
||||||
private val networkConnectionCheck: NetworkConnectionCheck, //
|
private val networkConnectionCheck: NetworkConnectionCheck, //
|
||||||
private val fileUtil: FileUtil, //
|
private val fileUtil: FileUtil, //
|
||||||
private val authenticationExceptionHandler: AuthenticationExceptionHandler, //
|
private val authenticationExceptionHandler: AuthenticationExceptionHandler, //
|
||||||
private val cloudFolderModelMapper: CloudFolderModelMapper, //
|
private val cloudFolderModelMapper: CloudFolderModelMapper, //
|
||||||
private val sharedPreferencesHandler: SharedPreferencesHandler, //
|
private val sharedPreferencesHandler: SharedPreferencesHandler, //
|
||||||
exceptionMappings: ExceptionHandlers) : Presenter<VaultListView>(exceptionMappings) {
|
exceptionMappings: ExceptionHandlers
|
||||||
|
) : Presenter<VaultListView>(exceptionMappings) {
|
||||||
|
|
||||||
private var vaultAction: VaultAction? = null
|
private var vaultAction: VaultAction? = null
|
||||||
|
|
||||||
@ -107,56 +108,56 @@ class VaultListPresenter @Inject constructor( //
|
|||||||
private fun checkLicense() {
|
private fun checkLicense() {
|
||||||
if (BuildConfig.FLAVOR == "apkstore" || BuildConfig.FLAVOR == "fdroid") {
|
if (BuildConfig.FLAVOR == "apkstore" || BuildConfig.FLAVOR == "fdroid") {
|
||||||
licenseCheckUseCase //
|
licenseCheckUseCase //
|
||||||
.withLicense("") //
|
.withLicense("") //
|
||||||
.run(object : NoOpResultHandler<LicenseCheck>() {
|
.run(object : NoOpResultHandler<LicenseCheck>() {
|
||||||
override fun onSuccess(licenseCheck: LicenseCheck) {
|
override fun onSuccess(licenseCheck: LicenseCheck) {
|
||||||
if (BuildConfig.FLAVOR == "apkstore" && sharedPreferencesHandler.doUpdate()) {
|
if (BuildConfig.FLAVOR == "apkstore" && sharedPreferencesHandler.doUpdate()) {
|
||||||
checkForAppUpdates()
|
checkForAppUpdates()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
var license: String? = ""
|
var license: String? = ""
|
||||||
if (e is LicenseNotValidException) {
|
if (e is LicenseNotValidException) {
|
||||||
license = e.license
|
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()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
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() {
|
private fun checkForAppUpdates() {
|
||||||
if (networkConnectionCheck.isPresent) {
|
if (networkConnectionCheck.isPresent) {
|
||||||
updateCheckUseCase //
|
updateCheckUseCase //
|
||||||
.withVersion(BuildConfig.VERSION_NAME) //
|
.withVersion(BuildConfig.VERSION_NAME) //
|
||||||
.run(object : NoOpResultHandler<Optional<UpdateCheck>>() {
|
.run(object : NoOpResultHandler<Optional<UpdateCheck>>() {
|
||||||
override fun onSuccess(updateCheck: Optional<UpdateCheck>) {
|
override fun onSuccess(updateCheck: Optional<UpdateCheck>) {
|
||||||
if (updateCheck.isPresent) {
|
if (updateCheck.isPresent) {
|
||||||
updateStatusRetrieved(updateCheck.get(), context())
|
updateStatusRetrieved(updateCheck.get(), context())
|
||||||
} else {
|
} else {
|
||||||
Timber.tag("VaultListPresenter").i("UpdateCheck finished, latest version")
|
Timber.tag("VaultListPresenter").i("UpdateCheck finished, latest version")
|
||||||
}
|
|
||||||
sharedPreferencesHandler.updateExecuted()
|
|
||||||
}
|
}
|
||||||
|
sharedPreferencesHandler.updateExecuted()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
if (e is SSLHandshakePreAndroid5UpdateCheckException) {
|
if (e is SSLHandshakePreAndroid5UpdateCheckException) {
|
||||||
Timber.tag("SettingsPresenter").e(e, "Update check failed due to Android pre 5 and SSL Handshake not accepted")
|
Timber.tag("SettingsPresenter").e(e, "Update check failed due to Android pre 5 and SSL Handshake not accepted")
|
||||||
} else {
|
} else {
|
||||||
showError(e)
|
showError(e)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
Timber.tag("VaultListPresenter").i("Update check not started due to no internal connection")
|
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) {
|
fun deleteVault(vaultModel: VaultModel) {
|
||||||
deleteVaultUseCase //
|
deleteVaultUseCase //
|
||||||
.withVault(vaultModel.toVault()) //
|
.withVault(vaultModel.toVault()) //
|
||||||
.run(object : DefaultResultHandler<Long>() {
|
.run(object : DefaultResultHandler<Long>() {
|
||||||
override fun onSuccess(vaultId: Long) {
|
override fun onSuccess(vaultId: Long) {
|
||||||
view?.deleteVaultFromAdapter(vaultId)
|
view?.deleteVaultFromAdapter(vaultId)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fun renameVault(vaultModel: VaultModel, newVaultName: String?) {
|
fun renameVault(vaultModel: VaultModel, newVaultName: String?) {
|
||||||
renameVaultUseCase //
|
renameVaultUseCase //
|
||||||
.withVault(vaultModel.toVault()) //
|
.withVault(vaultModel.toVault()) //
|
||||||
.andNewVaultName(newVaultName) //
|
.andNewVaultName(newVaultName) //
|
||||||
.run(object : DefaultResultHandler<Vault>() {
|
.run(object : DefaultResultHandler<Vault>() {
|
||||||
override fun onSuccess(vault: Vault) {
|
override fun onSuccess(vault: Vault) {
|
||||||
view?.renameVault(VaultModel(vault))
|
view?.renameVault(VaultModel(vault))
|
||||||
view?.closeDialog()
|
view?.closeDialog()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
if (!authenticationExceptionHandler.handleAuthenticationException( //
|
if (!authenticationExceptionHandler.handleAuthenticationException( //
|
||||||
this@VaultListPresenter, e, //
|
this@VaultListPresenter, e, //
|
||||||
ActivityResultCallbacks.renameVaultAfterAuthentication(vaultModel.toVault(), newVaultName))) {
|
ActivityResultCallbacks.renameVaultAfterAuthentication(vaultModel.toVault(), newVaultName)
|
||||||
showError(e)
|
)
|
||||||
}
|
) {
|
||||||
|
showError(e)
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback
|
@Callback
|
||||||
@ -230,32 +233,32 @@ class VaultListPresenter @Inject constructor( //
|
|||||||
|
|
||||||
private fun browseFilesOf(vault: VaultModel) {
|
private fun browseFilesOf(vault: VaultModel) {
|
||||||
getDecryptedCloudForVaultUseCase //
|
getDecryptedCloudForVaultUseCase //
|
||||||
.withVault(vault.toVault()) //
|
.withVault(vault.toVault()) //
|
||||||
.run(object : DefaultResultHandler<Cloud>() {
|
.run(object : DefaultResultHandler<Cloud>() {
|
||||||
override fun onSuccess(cloud: Cloud) {
|
override fun onSuccess(cloud: Cloud) {
|
||||||
getRootFolderAndNavigateInto(cloud)
|
getRootFolderAndNavigateInto(cloud)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getRootFolderAndNavigateInto(cloud: Cloud) {
|
private fun getRootFolderAndNavigateInto(cloud: Cloud) {
|
||||||
getRootFolderUseCase //
|
getRootFolderUseCase //
|
||||||
.withCloud(cloud) //
|
.withCloud(cloud) //
|
||||||
.run(object : DefaultResultHandler<CloudFolder>() {
|
.run(object : DefaultResultHandler<CloudFolder>() {
|
||||||
override fun onSuccess(folder: CloudFolder) {
|
override fun onSuccess(folder: CloudFolder) {
|
||||||
navigateToVaultContent((folder.cloud as CryptoCloud).vault, folder)
|
navigateToVaultContent((folder.cloud as CryptoCloud).vault, folder)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun lockVault(vaultModel: VaultModel) {
|
private fun lockVault(vaultModel: VaultModel) {
|
||||||
lockVaultUseCase //
|
lockVaultUseCase //
|
||||||
.withVault(vaultModel.toVault()) //
|
.withVault(vaultModel.toVault()) //
|
||||||
.run(object : DefaultResultHandler<Vault>() {
|
.run(object : DefaultResultHandler<Vault>() {
|
||||||
override fun onSuccess(vault: Vault) {
|
override fun onSuccess(vault: Vault) {
|
||||||
view?.addOrUpdateVault(VaultModel(vault))
|
view?.addOrUpdateVault(VaultModel(vault))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private val vaultList: Unit
|
private val vaultList: Unit
|
||||||
@ -297,12 +300,12 @@ class VaultListPresenter @Inject constructor( //
|
|||||||
onVaultWithoutCloudClickedAndLocked(vault)
|
onVaultWithoutCloudClickedAndLocked(vault)
|
||||||
} else {
|
} else {
|
||||||
lockVaultUseCase //
|
lockVaultUseCase //
|
||||||
.withVault(vault.toVault()) //
|
.withVault(vault.toVault()) //
|
||||||
.run(object : DefaultResultHandler<Vault>() {
|
.run(object : DefaultResultHandler<Vault>() {
|
||||||
override fun onSuccess(vault: Vault) {
|
override fun onSuccess(vault: Vault) {
|
||||||
onVaultWithoutCloudClickedAndLocked(VaultModel(vault))
|
onVaultWithoutCloudClickedAndLocked(VaultModel(vault))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -310,11 +313,12 @@ class VaultListPresenter @Inject constructor( //
|
|||||||
private fun onVaultWithoutCloudClickedAndLocked(vault: VaultModel) {
|
private fun onVaultWithoutCloudClickedAndLocked(vault: VaultModel) {
|
||||||
if (isWebdavOrLocal(vault.cloudType)) {
|
if (isWebdavOrLocal(vault.cloudType)) {
|
||||||
requestActivityResult( //
|
requestActivityResult( //
|
||||||
ActivityResultCallbacks.cloudConnectionForVaultSelected(vault), //
|
ActivityResultCallbacks.cloudConnectionForVaultSelected(vault), //
|
||||||
Intents.cloudConnectionListIntent() //
|
Intents.cloudConnectionListIntent() //
|
||||||
.withCloudType(vault.cloudType) //
|
.withCloudType(vault.cloudType) //
|
||||||
.withDialogTitle(context().getString(R.string.screen_cloud_connections_title)) //
|
.withDialogTitle(context().getString(R.string.screen_cloud_connections_title)) //
|
||||||
.withFinishOnCloudItemClick(true))
|
.withFinishOnCloudItemClick(true)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,16 +330,16 @@ class VaultListPresenter @Inject constructor( //
|
|||||||
fun cloudConnectionForVaultSelected(result: ActivityResult, vaultModel: VaultModel) {
|
fun cloudConnectionForVaultSelected(result: ActivityResult, vaultModel: VaultModel) {
|
||||||
val cloud = result.intent().getSerializableExtra(CloudConnectionListPresenter.SELECTED_CLOUD) as Cloud
|
val cloud = result.intent().getSerializableExtra(CloudConnectionListPresenter.SELECTED_CLOUD) as Cloud
|
||||||
val vault = Vault.aCopyOf(vaultModel.toVault()) //
|
val vault = Vault.aCopyOf(vaultModel.toVault()) //
|
||||||
.withCloud(cloud) //
|
.withCloud(cloud) //
|
||||||
.build()
|
.build()
|
||||||
saveVaultUseCase //
|
saveVaultUseCase //
|
||||||
.withVault(vault) //
|
.withVault(vault) //
|
||||||
.run(object : DefaultResultHandler<Vault>() {
|
.run(object : DefaultResultHandler<Vault>() {
|
||||||
override fun onSuccess(vault: Vault) {
|
override fun onSuccess(vault: Vault) {
|
||||||
view?.addOrUpdateVault(VaultModel(vault))
|
view?.addOrUpdateVault(VaultModel(vault))
|
||||||
onCloudOfVaultAuthenticated(vault)
|
onCloudOfVaultAuthenticated(vault)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onCloudOfVaultAuthenticated(authenticatedVault: Vault) {
|
private fun onCloudOfVaultAuthenticated(authenticatedVault: Vault) {
|
||||||
@ -352,8 +356,9 @@ class VaultListPresenter @Inject constructor( //
|
|||||||
if (authenticatedVault.isLocked) {
|
if (authenticatedVault.isLocked) {
|
||||||
if (!isPaused) {
|
if (!isPaused) {
|
||||||
requestActivityResult( //
|
requestActivityResult( //
|
||||||
ActivityResultCallbacks.vaultUnlockedVaultList(), //
|
ActivityResultCallbacks.vaultUnlockedVaultList(), //
|
||||||
Intents.unlockVaultIntent().withVaultModel(authenticatedVault).withVaultAction(UnlockVaultIntent.VaultAction.UNLOCK))
|
Intents.unlockVaultIntent().withVaultModel(authenticatedVault).withVaultAction(UnlockVaultIntent.VaultAction.UNLOCK)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
browseFilesOf(authenticatedVault)
|
browseFilesOf(authenticatedVault)
|
||||||
@ -371,18 +376,18 @@ class VaultListPresenter @Inject constructor( //
|
|||||||
|
|
||||||
private fun navigateToVaultContent(cloud: Cloud) {
|
private fun navigateToVaultContent(cloud: Cloud) {
|
||||||
getRootFolderUseCase //
|
getRootFolderUseCase //
|
||||||
.withCloud(cloud) //
|
.withCloud(cloud) //
|
||||||
.run(object : DefaultResultHandler<CloudFolder>() {
|
.run(object : DefaultResultHandler<CloudFolder>() {
|
||||||
override fun onSuccess(folder: CloudFolder) {
|
override fun onSuccess(folder: CloudFolder) {
|
||||||
val vault = (folder.cloud as CryptoCloud).vault
|
val vault = (folder.cloud as CryptoCloud).vault
|
||||||
view?.addOrUpdateVault(VaultModel(vault))
|
view?.addOrUpdateVault(VaultModel(vault))
|
||||||
navigateToVaultContent(vault, folder)
|
navigateToVaultContent(vault, folder)
|
||||||
view?.showProgress(ProgressModel.COMPLETED)
|
view?.showProgress(ProgressModel.COMPLETED)
|
||||||
if (checkToStartAutoImageUpload(vault)) {
|
if (checkToStartAutoImageUpload(vault)) {
|
||||||
context().startService(AutoUploadService.startAutoUploadIntent(context(), folder.cloud))
|
context().startService(AutoUploadService.startAutoUploadIntent(context(), folder.cloud))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkToStartAutoImageUpload(vault: Vault): Boolean {
|
private fun checkToStartAutoImageUpload(vault: Vault): Boolean {
|
||||||
@ -407,10 +412,10 @@ class VaultListPresenter @Inject constructor( //
|
|||||||
|
|
||||||
fun onChangePasswordClicked(vaultModel: VaultModel) {
|
fun onChangePasswordClicked(vaultModel: VaultModel) {
|
||||||
Intents
|
Intents
|
||||||
.unlockVaultIntent()
|
.unlockVaultIntent()
|
||||||
.withVaultModel(vaultModel)
|
.withVaultModel(vaultModel)
|
||||||
.withVaultAction(UnlockVaultIntent.VaultAction.CHANGE_PASSWORD)
|
.withVaultAction(UnlockVaultIntent.VaultAction.CHANGE_PASSWORD)
|
||||||
.startActivity(this)
|
.startActivity(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onVaultSettingsClicked(vaultModel: VaultModel) {
|
fun onVaultSettingsClicked(vaultModel: VaultModel) {
|
||||||
@ -446,17 +451,17 @@ class VaultListPresenter @Inject constructor( //
|
|||||||
|
|
||||||
fun onVaultMoved(fromPosition: Int, toPosition: Int) {
|
fun onVaultMoved(fromPosition: Int, toPosition: Int) {
|
||||||
moveVaultPositionUseCase
|
moveVaultPositionUseCase
|
||||||
.withFromPosition(fromPosition) //
|
.withFromPosition(fromPosition) //
|
||||||
.andToPosition(toPosition) //
|
.andToPosition(toPosition) //
|
||||||
.run(object : DefaultResultHandler<List<Vault>>() {
|
.run(object : DefaultResultHandler<List<Vault>>() {
|
||||||
override fun onSuccess(vaults: List<Vault>) {
|
override fun onSuccess(vaults: List<Vault>) {
|
||||||
view?.vaultMoved(vaults.mapTo(ArrayList()) { VaultModel(it) })
|
view?.vaultMoved(vaults.mapTo(ArrayList()) { VaultModel(it) })
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
Timber.tag("VaultListPresenter").e(e, "Failed to execute MoveVaultUseCase")
|
Timber.tag("VaultListPresenter").e(e, "Failed to execute MoveVaultUseCase")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum class VaultAction {
|
private enum class VaultAction {
|
||||||
@ -468,33 +473,34 @@ class VaultListPresenter @Inject constructor( //
|
|||||||
val uri = fileUtil.contentUriForNewTempFile("cryptomator.apk")
|
val uri = fileUtil.contentUriForNewTempFile("cryptomator.apk")
|
||||||
val file = fileUtil.tempFile("cryptomator.apk")
|
val file = fileUtil.tempFile("cryptomator.apk")
|
||||||
updateUseCase //
|
updateUseCase //
|
||||||
.withFile(file) //
|
.withFile(file) //
|
||||||
.run(object : NoOpResultHandler<Void?>() {
|
.run(object : NoOpResultHandler<Void?>() {
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
showError(e)
|
showError(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSuccess(aVoid: Void?) {
|
override fun onSuccess(aVoid: Void?) {
|
||||||
super.onSuccess(aVoid)
|
super.onSuccess(aVoid)
|
||||||
val intent = Intent(Intent.ACTION_VIEW)
|
val intent = Intent(Intent.ACTION_VIEW)
|
||||||
intent.setDataAndType(uri, "application/vnd.android.package-archive")
|
intent.setDataAndType(uri, "application/vnd.android.package-archive")
|
||||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||||
context().startActivity(intent)
|
context().startActivity(intent)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
unsubscribeOnDestroy( //
|
unsubscribeOnDestroy( //
|
||||||
deleteVaultUseCase, //
|
deleteVaultUseCase, //
|
||||||
renameVaultUseCase, //
|
renameVaultUseCase, //
|
||||||
lockVaultUseCase, //
|
lockVaultUseCase, //
|
||||||
getVaultListUseCase, //
|
getVaultListUseCase, //
|
||||||
saveVaultUseCase, //
|
saveVaultUseCase, //
|
||||||
moveVaultPositionUseCase, //
|
moveVaultPositionUseCase, //
|
||||||
licenseCheckUseCase, //
|
licenseCheckUseCase, //
|
||||||
updateCheckUseCase, //
|
updateCheckUseCase, //
|
||||||
updateUseCase)
|
updateUseCase
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,10 +21,11 @@ import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
|||||||
|
|
||||||
@PerView
|
@PerView
|
||||||
class WebDavAddOrChangePresenter @Inject internal constructor( //
|
class WebDavAddOrChangePresenter @Inject internal constructor( //
|
||||||
private val addOrChangeCloudConnectionUseCase: AddOrChangeCloudConnectionUseCase, //
|
private val addOrChangeCloudConnectionUseCase: AddOrChangeCloudConnectionUseCase, //
|
||||||
private val connectToWebDavUseCase: ConnectToWebDavUseCase, //
|
private val connectToWebDavUseCase: ConnectToWebDavUseCase, //
|
||||||
private val authenticationExceptionHandler: AuthenticationExceptionHandler, //
|
private val authenticationExceptionHandler: AuthenticationExceptionHandler, //
|
||||||
exceptionMappings: ExceptionHandlers) : Presenter<WebDavAddOrChangeView>(exceptionMappings) {
|
exceptionMappings: ExceptionHandlers
|
||||||
|
) : Presenter<WebDavAddOrChangeView>(exceptionMappings) {
|
||||||
|
|
||||||
fun checkUserInput(urlPort: String, username: String, password: String, cloudId: Long?, certificate: String?) {
|
fun checkUserInput(urlPort: String, username: String, password: String, cloudId: Long?, certificate: String?) {
|
||||||
var statusMessage: String? = null
|
var statusMessage: String? = null
|
||||||
@ -55,8 +56,8 @@ class WebDavAddOrChangePresenter @Inject internal constructor( //
|
|||||||
|
|
||||||
private fun encryptPassword(password: String): String {
|
private fun encryptPassword(password: String): String {
|
||||||
return CredentialCryptor //
|
return CredentialCryptor //
|
||||||
.getInstance(context()) //
|
.getInstance(context()) //
|
||||||
.encrypt(password)
|
.encrypt(password)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isValid(urlPort: String): Boolean {
|
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 {
|
private fun mapToCloud(username: String, password: String, hostPort: String, id: Long?, certificate: String?): WebDavCloud {
|
||||||
var builder = WebDavCloud //
|
var builder = WebDavCloud //
|
||||||
.aWebDavCloudCloud() //
|
.aWebDavCloudCloud() //
|
||||||
.withUrl(hostPort) //
|
.withUrl(hostPort) //
|
||||||
.withUsername(username) //
|
.withUsername(username) //
|
||||||
.withPassword(password)
|
.withPassword(password)
|
||||||
|
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
builder = builder.withId(id)
|
builder = builder.withId(id)
|
||||||
@ -88,19 +89,19 @@ class WebDavAddOrChangePresenter @Inject internal constructor( //
|
|||||||
private fun authenticate(cloud: WebDavCloud) {
|
private fun authenticate(cloud: WebDavCloud) {
|
||||||
view?.showProgress(ProgressModel(ProgressStateModel.AUTHENTICATION))
|
view?.showProgress(ProgressModel(ProgressStateModel.AUTHENTICATION))
|
||||||
connectToWebDavUseCase //
|
connectToWebDavUseCase //
|
||||||
.withCloud(cloud) //
|
.withCloud(cloud) //
|
||||||
.run(object : DefaultResultHandler<Void?>() {
|
.run(object : DefaultResultHandler<Void?>() {
|
||||||
override fun onSuccess(void: Void?) {
|
override fun onSuccess(void: Void?) {
|
||||||
onCloudAuthenticated(cloud)
|
onCloudAuthenticated(cloud)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
view?.showProgress(ProgressModel.COMPLETED)
|
view?.showProgress(ProgressModel.COMPLETED)
|
||||||
if (!authenticationExceptionHandler.handleAuthenticationException(this@WebDavAddOrChangePresenter, e, ActivityResultCallbacks.handledAuthenticationWebDavCloud())) {
|
if (!authenticationExceptionHandler.handleAuthenticationException(this@WebDavAddOrChangePresenter, e, ActivityResultCallbacks.handledAuthenticationWebDavCloud())) {
|
||||||
super.onError(e)
|
super.onError(e)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@Callback
|
@Callback
|
||||||
@ -117,8 +118,8 @@ class WebDavAddOrChangePresenter @Inject internal constructor( //
|
|||||||
|
|
||||||
private fun save(cloud: Cloud) {
|
private fun save(cloud: Cloud) {
|
||||||
addOrChangeCloudConnectionUseCase //
|
addOrChangeCloudConnectionUseCase //
|
||||||
.withCloud(cloud) //
|
.withCloud(cloud) //
|
||||||
.run(DefaultResultHandler())
|
.run(DefaultResultHandler())
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
@ -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) {
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
||||||
val notificationChannel = NotificationChannel( //
|
val notificationChannel = NotificationChannel( //
|
||||||
NOTIFICATION_CHANNEL_ID, //
|
NOTIFICATION_CHANNEL_ID, //
|
||||||
NOTIFICATION_CHANNEL_NAME, //
|
NOTIFICATION_CHANNEL_NAME, //
|
||||||
IMPORTANCE_LOW)
|
IMPORTANCE_LOW
|
||||||
|
)
|
||||||
notificationManager?.createNotificationChannel(notificationChannel)
|
notificationManager?.createNotificationChannel(notificationChannel)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.builder = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) //
|
this.builder = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) //
|
||||||
.setContentTitle(context.getString(R.string.notification_auto_upload_title)) //
|
.setContentTitle(context.getString(R.string.notification_auto_upload_title)) //
|
||||||
.setSmallIcon(R.drawable.background_splash_cryptomator) //
|
.setSmallIcon(R.drawable.background_splash_cryptomator) //
|
||||||
.setColor(getColor(R.color.colorPrimary)) //
|
.setColor(getColor(R.color.colorPrimary)) //
|
||||||
.addAction(cancelNowAction())
|
.addAction(cancelNowAction())
|
||||||
.setGroup(NOTIFICATION_GROUP_KEY)
|
.setGroup(NOTIFICATION_GROUP_KEY)
|
||||||
.setOngoing(true)
|
.setOngoing(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun cancelNowAction(): NotificationCompat.Action {
|
private fun cancelNowAction(): NotificationCompat.Action {
|
||||||
return NotificationCompat.Action.Builder( //
|
return NotificationCompat.Action.Builder( //
|
||||||
R.drawable.ic_lock, //
|
R.drawable.ic_lock, //
|
||||||
getString(R.string.notification_cancel_auto_upload), //
|
getString(R.string.notification_cancel_auto_upload), //
|
||||||
cancelNowIntent() //
|
cancelNowIntent() //
|
||||||
).build()
|
).build()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,11 +68,14 @@ class AutoUploadNotification(private val context: Context, private val amountOfP
|
|||||||
fun update(progress: Int) {
|
fun update(progress: Int) {
|
||||||
builder.setContentIntent(startTheActivity())
|
builder.setContentIntent(startTheActivity())
|
||||||
builder //
|
builder //
|
||||||
.setContentText( //
|
.setContentText( //
|
||||||
String.format(context.getString(R.string.notification_auto_upload_message), //
|
String.format(
|
||||||
alreadyUploadedPictures + 1, //
|
context.getString(R.string.notification_auto_upload_message), //
|
||||||
amountOfPictures)) //
|
alreadyUploadedPictures + 1, //
|
||||||
.setProgress(100, progress, false)
|
amountOfPictures
|
||||||
|
)
|
||||||
|
) //
|
||||||
|
.setProgress(100, progress, false)
|
||||||
show()
|
show()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,24 +99,24 @@ class AutoUploadNotification(private val context: Context, private val amountOfP
|
|||||||
private fun showErrorWithMessage(message: String) {
|
private fun showErrorWithMessage(message: String) {
|
||||||
builder.setContentIntent(startTheActivity())
|
builder.setContentIntent(startTheActivity())
|
||||||
builder //
|
builder //
|
||||||
.setContentTitle(context.getString(R.string.notification_auto_upload_failed_title))
|
.setContentTitle(context.getString(R.string.notification_auto_upload_failed_title))
|
||||||
.setContentText(message) //
|
.setContentText(message) //
|
||||||
.setProgress(0, 0, false)
|
.setProgress(0, 0, false)
|
||||||
.setAutoCancel(true)
|
.setAutoCancel(true)
|
||||||
.setOngoing(false)
|
.setOngoing(false)
|
||||||
.mActions.clear()
|
.mActions.clear()
|
||||||
show()
|
show()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showUploadFinished(size: Int) {
|
fun showUploadFinished(size: Int) {
|
||||||
builder.setContentIntent(startTheActivity())
|
builder.setContentIntent(startTheActivity())
|
||||||
builder //
|
builder //
|
||||||
.setContentTitle(context.getString(R.string.notification_auto_upload_finished_title))
|
.setContentTitle(context.getString(R.string.notification_auto_upload_finished_title))
|
||||||
.setContentText(format(context.getString(R.string.notification_auto_upload_finished_message), size)) //
|
.setContentText(format(context.getString(R.string.notification_auto_upload_finished_message), size)) //
|
||||||
.setProgress(0, 0, false)
|
.setProgress(0, 0, false)
|
||||||
.setAutoCancel(true)
|
.setAutoCancel(true)
|
||||||
.setOngoing(false)
|
.setOngoing(false)
|
||||||
.mActions.clear()
|
.mActions.clear()
|
||||||
show()
|
show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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) {
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
||||||
val notificationChannel = NotificationChannel( //
|
val notificationChannel = NotificationChannel( //
|
||||||
NOTIFICATION_CHANNEL_ID, //
|
NOTIFICATION_CHANNEL_ID, //
|
||||||
NOTIFICATION_CHANNEL_NAME, //
|
NOTIFICATION_CHANNEL_NAME, //
|
||||||
IMPORTANCE_LOW)
|
IMPORTANCE_LOW
|
||||||
|
)
|
||||||
notificationManager?.createNotificationChannel(notificationChannel)
|
notificationManager?.createNotificationChannel(notificationChannel)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.builder = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) //
|
this.builder = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) //
|
||||||
.setContentTitle(context.getString(R.string.notification_open_writable_file_title)) //
|
.setContentTitle(context.getString(R.string.notification_open_writable_file_title)) //
|
||||||
.setContentText(context.getString(R.string.notification_open_writable_file_message)) //
|
.setContentText(context.getString(R.string.notification_open_writable_file_message)) //
|
||||||
.setSmallIcon(R.drawable.background_splash_cryptomator) //
|
.setSmallIcon(R.drawable.background_splash_cryptomator) //
|
||||||
.setColor(getColor(R.color.colorPrimary)) //
|
.setColor(getColor(R.color.colorPrimary)) //
|
||||||
.setGroup(NOTIFICATION_GROUP_KEY)
|
.setGroup(NOTIFICATION_GROUP_KEY)
|
||||||
.setOngoing(true)
|
.setOngoing(true)
|
||||||
.addAction(cancelNowAction())
|
.addAction(cancelNowAction())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun cancelNowAction(): NotificationCompat.Action {
|
private fun cancelNowAction(): NotificationCompat.Action {
|
||||||
return NotificationCompat.Action.Builder( //
|
return NotificationCompat.Action.Builder( //
|
||||||
R.drawable.ic_lock, //
|
R.drawable.ic_lock, //
|
||||||
ResourceHelper.getString(R.string.notification_cancel_open_writable_file), //
|
ResourceHelper.getString(R.string.notification_cancel_open_writable_file), //
|
||||||
cancelNowIntent() //
|
cancelNowIntent() //
|
||||||
).build()
|
).build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,12 +75,16 @@ class PhotoContentJob : JobService() {
|
|||||||
private fun getContentResolvers(ids: Set<String>): Array<Cursor?> {
|
private fun getContentResolvers(ids: Set<String>): Array<Cursor?> {
|
||||||
val selection = buildSelection(ids)
|
val selection = buildSelection(ids)
|
||||||
|
|
||||||
var resolvers = arrayOf(contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, PROJECTION_IMAGES, selection, null, null),
|
var resolvers = arrayOf(
|
||||||
contentResolver.query(MediaStore.Images.Media.INTERNAL_CONTENT_URI, PROJECTION_IMAGES, selection, null, null))
|
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()) {
|
if (SharedPreferencesHandler(applicationContext).autoPhotoUploadIncludingVideos()) {
|
||||||
resolvers += arrayOf(contentResolver.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, PROJECTION_VIDEOS, selection, null, null),
|
resolvers += arrayOf(
|
||||||
contentResolver.query(MediaStore.Video.Media.INTERNAL_CONTENT_URI, PROJECTION_VIDEOS, selection, null, null))
|
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
|
return resolvers
|
||||||
@ -88,14 +92,14 @@ class PhotoContentJob : JobService() {
|
|||||||
|
|
||||||
private fun getIds(params: JobParameters): Set<String>? {
|
private fun getIds(params: JobParameters): Set<String>? {
|
||||||
return params.triggeredContentUris
|
return params.triggeredContentUris
|
||||||
?.map { it.pathSegments }
|
?.map { it.pathSegments }
|
||||||
?.filter {
|
?.filter {
|
||||||
it != null && (it.size == MediaStore.Images.Media.EXTERNAL_CONTENT_URI.pathSegments.size + 1
|
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.Video.Media.EXTERNAL_CONTENT_URI.pathSegments.size + 1
|
||||||
|| it.size == MediaStore.Images.Media.INTERNAL_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)
|
|| it.size == MediaStore.Video.Media.INTERNAL_CONTENT_URI.pathSegments.size + 1)
|
||||||
}
|
}
|
||||||
?.mapTo(HashSet()) { it[it.size - 1] }
|
?.mapTo(HashSet()) { it[it.size - 1] }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildSelection(ids: Set<String>): String {
|
private fun buildSelection(ids: Set<String>): String {
|
||||||
|
@ -15,8 +15,8 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
@Activity(layout = R.layout.activity_empty)
|
@Activity(layout = R.layout.activity_empty)
|
||||||
class AuthenticateCloudActivity : BaseActivity(),
|
class AuthenticateCloudActivity : BaseActivity(),
|
||||||
AuthenticateCloudView,
|
AuthenticateCloudView,
|
||||||
AssignSslCertificateDialog.Callback {
|
AssignSslCertificateDialog.Callback {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var presenter: AuthenticateCloudPresenter
|
lateinit var presenter: AuthenticateCloudPresenter
|
||||||
|
@ -14,8 +14,8 @@ import kotlinx.android.synthetic.main.toolbar_layout.toolbar
|
|||||||
|
|
||||||
@Activity
|
@Activity
|
||||||
class AutoUploadChooseVaultActivity : BaseActivity(), //
|
class AutoUploadChooseVaultActivity : BaseActivity(), //
|
||||||
AutoUploadChooseVaultView, //
|
AutoUploadChooseVaultView, //
|
||||||
NotEnoughVaultsDialog.Callback {
|
NotEnoughVaultsDialog.Callback {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var presenter: AutoUploadChooseVaultPresenter
|
lateinit var presenter: AutoUploadChooseVaultPresenter
|
||||||
@ -42,9 +42,9 @@ class AutoUploadChooseVaultActivity : BaseActivity(), //
|
|||||||
|
|
||||||
override fun displayDialogUnableToUploadFiles() {
|
override fun displayDialogUnableToUploadFiles() {
|
||||||
NotEnoughVaultsDialog //
|
NotEnoughVaultsDialog //
|
||||||
.withContext(this) //
|
.withContext(this) //
|
||||||
.andTitle(getString(R.string.dialog_unable_to_auto_upload_files_title)) //
|
.andTitle(getString(R.string.dialog_unable_to_auto_upload_files_title)) //
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNotEnoughVaultsOkClicked() {
|
override fun onNotEnoughVaultsOkClicked() {
|
||||||
|
@ -162,9 +162,9 @@ abstract class BaseActivity : AppCompatActivity(), View, ActivityCompat.OnReques
|
|||||||
|
|
||||||
private fun initializeDagger(): ActivityComponent {
|
private fun initializeDagger(): ActivityComponent {
|
||||||
val activityComponent = DaggerActivityComponent.builder()
|
val activityComponent = DaggerActivityComponent.builder()
|
||||||
.applicationComponent(applicationComponent)
|
.applicationComponent(applicationComponent)
|
||||||
.activityModule(ActivityModule(this))
|
.activityModule(ActivityModule(this))
|
||||||
.build()
|
.build()
|
||||||
Activities.inject(activityComponent, this)
|
Activities.inject(activityComponent, this)
|
||||||
return activityComponent
|
return activityComponent
|
||||||
}
|
}
|
||||||
@ -316,7 +316,7 @@ abstract class BaseActivity : AppCompatActivity(), View, ActivityCompat.OnReques
|
|||||||
|
|
||||||
internal open fun snackbarView(): android.view.View {
|
internal open fun snackbarView(): android.view.View {
|
||||||
return activity().findViewById(R.id.locationsRecyclerView) as 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)
|
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(
|
internal enum class FragmentAnimation constructor(
|
||||||
val enter: Int,
|
val enter: Int,
|
||||||
val exit: Int,
|
val exit: Int,
|
||||||
val popEnter: Int,
|
val popEnter: Int,
|
||||||
val popExit: 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_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)
|
NAVIGATE_OUT_OF_FOLDER(R.animator.enter_from_left, R.animator.exit_to_right, R.animator.enter_from_right, R.animator.exit_to_left)
|
||||||
|
@ -14,8 +14,8 @@ import kotlinx.android.synthetic.main.toolbar_layout.toolbar
|
|||||||
|
|
||||||
@Activity
|
@Activity
|
||||||
class BiometricAuthSettingsActivity : BaseActivity(), //
|
class BiometricAuthSettingsActivity : BaseActivity(), //
|
||||||
BiometricAuthSettingsView, //
|
BiometricAuthSettingsView, //
|
||||||
EnrollSystemBiometricDialog.Callback {
|
EnrollSystemBiometricDialog.Callback {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var presenter: BiometricAuthSettingsPresenter
|
lateinit var presenter: BiometricAuthSettingsPresenter
|
||||||
@ -29,8 +29,8 @@ class BiometricAuthSettingsActivity : BaseActivity(), //
|
|||||||
|
|
||||||
override fun showSetupBiometricAuthDialog() {
|
override fun showSetupBiometricAuthDialog() {
|
||||||
val biometricAuthenticationAvailable = BiometricManager //
|
val biometricAuthenticationAvailable = BiometricManager //
|
||||||
.from(context()) //
|
.from(context()) //
|
||||||
.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG)
|
.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG)
|
||||||
if (biometricAuthenticationAvailable == BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED) {
|
if (biometricAuthenticationAvailable == BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED) {
|
||||||
showDialog(EnrollSystemBiometricDialog.newInstance())
|
showDialog(EnrollSystemBiometricDialog.newInstance())
|
||||||
}
|
}
|
||||||
|
@ -51,17 +51,17 @@ import kotlinx.android.synthetic.main.toolbar_layout.toolbar
|
|||||||
|
|
||||||
@Activity
|
@Activity
|
||||||
class BrowseFilesActivity : BaseActivity(), //
|
class BrowseFilesActivity : BaseActivity(), //
|
||||||
BrowseFilesView, //
|
BrowseFilesView, //
|
||||||
BrowseFilesCallback, //
|
BrowseFilesCallback, //
|
||||||
ReplaceDialog.Callback, //
|
ReplaceDialog.Callback, //
|
||||||
FileNameDialog.Callback, //
|
FileNameDialog.Callback, //
|
||||||
ConfirmDeleteCloudNodeDialog.Callback, //
|
ConfirmDeleteCloudNodeDialog.Callback, //
|
||||||
UploadCloudFileDialog.Callback,
|
UploadCloudFileDialog.Callback,
|
||||||
ExportCloudFilesDialog.Callback,
|
ExportCloudFilesDialog.Callback,
|
||||||
SymLinkDialog.CallBack,
|
SymLinkDialog.CallBack,
|
||||||
NoDirFileDialog.CallBack,
|
NoDirFileDialog.CallBack,
|
||||||
SearchView.OnQueryTextListener,
|
SearchView.OnQueryTextListener,
|
||||||
SearchView.OnCloseListener {
|
SearchView.OnCloseListener {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var browseFilesPresenter: BrowseFilesPresenter
|
lateinit var browseFilesPresenter: BrowseFilesPresenter
|
||||||
@ -97,8 +97,10 @@ class BrowseFilesActivity : BaseActivity(), //
|
|||||||
get() = browseFilesFragment().folder
|
get() = browseFilesFragment().folder
|
||||||
|
|
||||||
override fun createFragment(): Fragment =
|
override fun createFragment(): Fragment =
|
||||||
BrowseFilesFragment.newInstance(browseFilesIntent.folder(),
|
BrowseFilesFragment.newInstance(
|
||||||
browseFilesIntent.chooseCloudNodeSettings())
|
browseFilesIntent.folder(),
|
||||||
|
browseFilesIntent.chooseCloudNodeSettings()
|
||||||
|
)
|
||||||
|
|
||||||
override fun onBackPressed() {
|
override fun onBackPressed() {
|
||||||
browseFilesPresenter.onBackPressed()
|
browseFilesPresenter.onBackPressed()
|
||||||
@ -121,7 +123,7 @@ class BrowseFilesActivity : BaseActivity(), //
|
|||||||
private fun isNavigationMode(navigationMode: ChooseCloudNodeSettings.NavigationMode): Boolean = this.navigationMode == navigationMode
|
private fun isNavigationMode(navigationMode: ChooseCloudNodeSettings.NavigationMode): Boolean = this.navigationMode == navigationMode
|
||||||
|
|
||||||
private fun hasCloudNodeSettings(): Boolean =
|
private fun hasCloudNodeSettings(): Boolean =
|
||||||
browseFilesIntent.chooseCloudNodeSettings() != null
|
browseFilesIntent.chooseCloudNodeSettings() != null
|
||||||
|
|
||||||
override fun getCustomMenuResource(): Int {
|
override fun getCustomMenuResource(): Int {
|
||||||
return when {
|
return when {
|
||||||
@ -160,14 +162,17 @@ class BrowseFilesActivity : BaseActivity(), //
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
R.id.action_move_items -> {
|
R.id.action_move_items -> {
|
||||||
browseFilesPresenter.onMoveNodesClicked(folder, //
|
browseFilesPresenter.onMoveNodesClicked(
|
||||||
browseFilesFragment().selectedCloudNodes as ArrayList<CloudNodeModel<*>>)
|
folder, //
|
||||||
|
browseFilesFragment().selectedCloudNodes as ArrayList<CloudNodeModel<*>>
|
||||||
|
)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
R.id.action_export_items -> {
|
R.id.action_export_items -> {
|
||||||
browseFilesPresenter.onExportNodesClicked( //
|
browseFilesPresenter.onExportNodesClicked( //
|
||||||
browseFilesFragment().selectedCloudNodes as ArrayList<CloudNodeModel<*>>, //
|
browseFilesFragment().selectedCloudNodes as ArrayList<CloudNodeModel<*>>, //
|
||||||
BrowseFilesPresenter.EXPORT_TRIGGERED_BY_USER)
|
BrowseFilesPresenter.EXPORT_TRIGGERED_BY_USER
|
||||||
|
)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
R.id.action_share_items -> {
|
R.id.action_share_items -> {
|
||||||
@ -398,14 +403,18 @@ class BrowseFilesActivity : BaseActivity(), //
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun navigateTo(folder: CloudFolderModel) {
|
override fun navigateTo(folder: CloudFolderModel) {
|
||||||
replaceFragment(BrowseFilesFragment.newInstance(folder,
|
replaceFragment(
|
||||||
browseFilesIntent.chooseCloudNodeSettings()),
|
BrowseFilesFragment.newInstance(
|
||||||
FragmentAnimation.NAVIGATE_IN_TO_FOLDER)
|
folder,
|
||||||
|
browseFilesIntent.chooseCloudNodeSettings()
|
||||||
|
),
|
||||||
|
FragmentAnimation.NAVIGATE_IN_TO_FOLDER
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showAddContentDialog() {
|
override fun showAddContentDialog() {
|
||||||
VaultContentActionBottomSheet.newInstance(browseFilesFragment().folder)
|
VaultContentActionBottomSheet.newInstance(browseFilesFragment().folder)
|
||||||
.show(supportFragmentManager, "AddContentDialog")
|
.show(supportFragmentManager, "AddContentDialog")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateTitle(folder: CloudFolderModel) {
|
override fun updateTitle(folder: CloudFolderModel) {
|
||||||
@ -484,10 +493,14 @@ class BrowseFilesActivity : BaseActivity(), //
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createBackStackFor(sourceParent: CloudFolderModel) {
|
private fun createBackStackFor(sourceParent: CloudFolderModel) {
|
||||||
replaceFragment(BrowseFilesFragment.newInstance(sourceParent,
|
replaceFragment(
|
||||||
browseFilesIntent.chooseCloudNodeSettings()),
|
BrowseFilesFragment.newInstance(
|
||||||
FragmentAnimation.NAVIGATE_OUT_OF_FOLDER,
|
sourceParent,
|
||||||
false)
|
browseFilesIntent.chooseCloudNodeSettings()
|
||||||
|
),
|
||||||
|
FragmentAnimation.NAVIGATE_OUT_OF_FOLDER,
|
||||||
|
false
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onRenameCloudNodeClicked(cloudNodeModel: CloudNodeModel<*>, newCloudNodeName: String) {
|
override fun onRenameCloudNodeClicked(cloudNodeModel: CloudNodeModel<*>, newCloudNodeName: String) {
|
||||||
|
@ -18,9 +18,9 @@ import kotlinx.android.synthetic.main.toolbar_layout.toolbar
|
|||||||
|
|
||||||
@Activity
|
@Activity
|
||||||
class CloudConnectionListActivity : BaseActivity(),
|
class CloudConnectionListActivity : BaseActivity(),
|
||||||
CloudConnectionListView,
|
CloudConnectionListView,
|
||||||
CloudConnectionSettingsBottomSheet.Callback,
|
CloudConnectionSettingsBottomSheet.Callback,
|
||||||
DeleteCloudConnectionWithVaultsDialog.Callback {
|
DeleteCloudConnectionWithVaultsDialog.Callback {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var presenter: CloudConnectionListPresenter
|
lateinit var presenter: CloudConnectionListPresenter
|
||||||
@ -55,7 +55,7 @@ class CloudConnectionListActivity : BaseActivity(),
|
|||||||
|
|
||||||
override fun showNodeSettings(cloudModel: CloudModel) {
|
override fun showNodeSettings(cloudModel: CloudModel) {
|
||||||
val cloudNodeSettingDialog = //
|
val cloudNodeSettingDialog = //
|
||||||
CloudConnectionSettingsBottomSheet.newInstance(cloudModel)
|
CloudConnectionSettingsBottomSheet.newInstance(cloudModel)
|
||||||
cloudNodeSettingDialog.show(supportFragmentManager, "CloudNodeSettings")
|
cloudNodeSettingDialog.show(supportFragmentManager, "CloudNodeSettings")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,14 +24,16 @@ class EmptyDirIdFileInfoActivity : BaseActivity(), EmptyDirFileView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setupToolbar() {
|
private fun setupToolbar() {
|
||||||
toolbar.title = getString(R.string.screen_empty_dir_file_info_title,
|
toolbar.title = getString(
|
||||||
emptyDirIdFileInfoIntent.dirName())
|
R.string.screen_empty_dir_file_info_title,
|
||||||
|
emptyDirIdFileInfoIntent.dirName()
|
||||||
|
)
|
||||||
setSupportActionBar(toolbar)
|
setSupportActionBar(toolbar)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
(supportFragmentManager.findFragmentByTag("EmptyDirIdFileInfoFragment") as EmptyDirIdFileInfoFragment)
|
(supportFragmentManager.findFragmentByTag("EmptyDirIdFileInfoFragment") as EmptyDirIdFileInfoFragment)
|
||||||
.setDirFilePath(emptyDirIdFileInfoIntent.dirFilePath())
|
.setDirFilePath(emptyDirIdFileInfoIntent.dirFilePath())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,10 +180,10 @@ class ImagePreviewActivity : BaseActivity(), ImagePreviewView, ConfirmDeleteClou
|
|||||||
|
|
||||||
private fun fragmentFor(imagePreviewFile: ImagePreviewFile): Optional<ImagePreviewFragment> {
|
private fun fragmentFor(imagePreviewFile: ImagePreviewFile): Optional<ImagePreviewFragment> {
|
||||||
return supportFragmentManager.fragments
|
return supportFragmentManager.fragments
|
||||||
.map { it as ImagePreviewFragment }
|
.map { it as ImagePreviewFragment }
|
||||||
.firstOrNull { it.imagePreviewFile() == imagePreviewFile }
|
.firstOrNull { it.imagePreviewFile() == imagePreviewFile }
|
||||||
?.let { Optional.of(it) }
|
?.let { Optional.of(it) }
|
||||||
?: Optional.empty()
|
?: Optional.empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hideProgressBar(imagePreviewFile: ImagePreviewFile) {
|
override fun hideProgressBar(imagePreviewFile: ImagePreviewFile) {
|
||||||
|
@ -63,7 +63,7 @@ class LicenseCheckActivity : BaseActivity(), UpdateLicenseDialog.Callback, Licen
|
|||||||
|
|
||||||
override fun licenseConfirmationClicked() {
|
override fun licenseConfirmationClicked() {
|
||||||
vaultListIntent() //
|
vaultListIntent() //
|
||||||
.preventGoingBackInHistory() //
|
.preventGoingBackInHistory() //
|
||||||
.startActivity(this) //
|
.startActivity(this) //
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,12 +19,12 @@ import kotlinx.android.synthetic.main.toolbar_layout.toolbar
|
|||||||
|
|
||||||
@Activity(layout = R.layout.activity_settings)
|
@Activity(layout = R.layout.activity_settings)
|
||||||
class SettingsActivity : BaseActivity(),
|
class SettingsActivity : BaseActivity(),
|
||||||
SettingsView,
|
SettingsView,
|
||||||
DebugModeDisclaimerDialog.Callback,
|
DebugModeDisclaimerDialog.Callback,
|
||||||
DisableAppWhenObscuredDisclaimerDialog.Callback,
|
DisableAppWhenObscuredDisclaimerDialog.Callback,
|
||||||
DisableSecureScreenDisclaimerDialog.Callback,
|
DisableSecureScreenDisclaimerDialog.Callback,
|
||||||
UpdateAppAvailableDialog.Callback, //
|
UpdateAppAvailableDialog.Callback, //
|
||||||
UpdateAppDialog.Callback {
|
UpdateAppDialog.Callback {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var presenter: SettingsPresenter
|
lateinit var presenter: SettingsPresenter
|
||||||
|
@ -26,10 +26,10 @@ import timber.log.Timber
|
|||||||
|
|
||||||
@Activity
|
@Activity
|
||||||
class SharedFilesActivity : BaseActivity(), //
|
class SharedFilesActivity : BaseActivity(), //
|
||||||
SharedFilesView, //
|
SharedFilesView, //
|
||||||
ReplaceDialog.Callback, //
|
ReplaceDialog.Callback, //
|
||||||
NotEnoughVaultsDialog.Callback, //
|
NotEnoughVaultsDialog.Callback, //
|
||||||
UploadCloudFileDialog.Callback {
|
UploadCloudFileDialog.Callback {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var presenter: SharedFilesPresenter
|
lateinit var presenter: SharedFilesPresenter
|
||||||
@ -92,8 +92,8 @@ class SharedFilesActivity : BaseActivity(), //
|
|||||||
val uriList = ArrayList<Uri>(clipData.itemCount)
|
val uriList = ArrayList<Uri>(clipData.itemCount)
|
||||||
(0 until clipData.itemCount).forEach { i ->
|
(0 until clipData.itemCount).forEach { i ->
|
||||||
clipData.getItemAt(i).uri
|
clipData.getItemAt(i).uri
|
||||||
?.let { uriList.add(it) }
|
?.let { uriList.add(it) }
|
||||||
?: Timber.tag("Sharing").i("Item %d without uri", i)
|
?: Timber.tag("Sharing").i("Item %d without uri", i)
|
||||||
}
|
}
|
||||||
return uriList
|
return uriList
|
||||||
}
|
}
|
||||||
@ -173,10 +173,10 @@ class SharedFilesActivity : BaseActivity(), //
|
|||||||
|
|
||||||
override fun onNotEnoughVaultsCreateVaultClicked() {
|
override fun onNotEnoughVaultsCreateVaultClicked() {
|
||||||
packageManager.getLaunchIntentForPackage(packageName)
|
packageManager.getLaunchIntentForPackage(packageName)
|
||||||
?.let {
|
?.let {
|
||||||
it.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
|
it.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
startActivity(it)
|
startActivity(it)
|
||||||
}
|
}
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,9 +17,9 @@ import kotlinx.android.synthetic.main.toolbar_layout.toolbar
|
|||||||
|
|
||||||
@Activity
|
@Activity
|
||||||
class TextEditorActivity : BaseActivity(),
|
class TextEditorActivity : BaseActivity(),
|
||||||
TextEditorView,
|
TextEditorView,
|
||||||
UnsavedChangesDialog.Callback,
|
UnsavedChangesDialog.Callback,
|
||||||
SearchView.OnQueryTextListener {
|
SearchView.OnQueryTextListener {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var textEditorPresenter: TextEditorPresenter
|
lateinit var textEditorPresenter: TextEditorPresenter
|
||||||
@ -45,18 +45,18 @@ class TextEditorActivity : BaseActivity(),
|
|||||||
super.onCreateOptionsMenu(menu)
|
super.onCreateOptionsMenu(menu)
|
||||||
|
|
||||||
menu.findItem(R.id.action_search)
|
menu.findItem(R.id.action_search)
|
||||||
.setOnActionExpandListener(object : MenuItem.OnActionExpandListener {
|
.setOnActionExpandListener(object : MenuItem.OnActionExpandListener {
|
||||||
override fun onMenuItemActionExpand(item: MenuItem?): Boolean {
|
override fun onMenuItemActionExpand(item: MenuItem?): Boolean {
|
||||||
menu.findItem(R.id.action_search_previous).isVisible = true
|
menu.findItem(R.id.action_search_previous).isVisible = true
|
||||||
menu.findItem(R.id.action_search_next).isVisible = true
|
menu.findItem(R.id.action_search_next).isVisible = true
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMenuItemActionCollapse(item: MenuItem?): Boolean {
|
override fun onMenuItemActionCollapse(item: MenuItem?): Boolean {
|
||||||
invalidateOptionsMenu()
|
invalidateOptionsMenu()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,10 +21,10 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
@Activity(layout = R.layout.activity_unlock_vault)
|
@Activity(layout = R.layout.activity_unlock_vault)
|
||||||
class UnlockVaultActivity : BaseActivity(), //
|
class UnlockVaultActivity : BaseActivity(), //
|
||||||
UnlockVaultView, //
|
UnlockVaultView, //
|
||||||
BiometricAuthentication.Callback,
|
BiometricAuthentication.Callback,
|
||||||
ChangePasswordDialog.Callback,
|
ChangePasswordDialog.Callback,
|
||||||
VaultNotFoundDialog.Callback {
|
VaultNotFoundDialog.Callback {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var presenter: UnlockVaultPresenter
|
lateinit var presenter: UnlockVaultPresenter
|
||||||
@ -84,7 +84,7 @@ class UnlockVaultActivity : BaseActivity(), //
|
|||||||
|
|
||||||
override fun onBiometricAuthenticationFailed(vault: VaultModel) {
|
override fun onBiometricAuthenticationFailed(vault: VaultModel) {
|
||||||
val vaultWithoutPassword = Vault.aCopyOf(vault.toVault()).withSavedPassword(null).build()
|
val vaultWithoutPassword = Vault.aCopyOf(vault.toVault()).withSavedPassword(null).build()
|
||||||
when(unlockVaultIntent.vaultAction()) {
|
when (unlockVaultIntent.vaultAction()) {
|
||||||
UnlockVaultIntent.VaultAction.CHANGE_PASSWORD -> presenter.saveVaultAfterChangePasswordButFailedBiometricAuth(vaultWithoutPassword)
|
UnlockVaultIntent.VaultAction.CHANGE_PASSWORD -> presenter.saveVaultAfterChangePasswordButFailedBiometricAuth(vaultWithoutPassword)
|
||||||
else -> {
|
else -> {
|
||||||
if (!presenter.startedUsingPrepareUnlock()) {
|
if (!presenter.startedUsingPrepareUnlock()) {
|
||||||
@ -100,7 +100,7 @@ class UnlockVaultActivity : BaseActivity(), //
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun unlockVaultFragment(): UnlockVaultFragment = //
|
private fun unlockVaultFragment(): UnlockVaultFragment = //
|
||||||
getCurrentFragment(R.id.fragmentContainer) as UnlockVaultFragment
|
getCurrentFragment(R.id.fragmentContainer) as UnlockVaultFragment
|
||||||
|
|
||||||
override fun showChangePasswordDialog(vaultModel: VaultModel, unverifiedVaultConfig: UnverifiedVaultConfig?) {
|
override fun showChangePasswordDialog(vaultModel: VaultModel, unverifiedVaultConfig: UnverifiedVaultConfig?) {
|
||||||
showDialog(ChangePasswordDialog.newInstance(vaultModel, unverifiedVaultConfig))
|
showDialog(ChangePasswordDialog.newInstance(vaultModel, unverifiedVaultConfig))
|
||||||
|
@ -35,12 +35,12 @@ import kotlinx.android.synthetic.main.toolbar_layout.toolbar
|
|||||||
|
|
||||||
@Activity(layout = R.layout.activity_layout_obscure_aware)
|
@Activity(layout = R.layout.activity_layout_obscure_aware)
|
||||||
class VaultListActivity : BaseActivity(), //
|
class VaultListActivity : BaseActivity(), //
|
||||||
VaultListView, //
|
VaultListView, //
|
||||||
VaultListCallback, //
|
VaultListCallback, //
|
||||||
AskForLockScreenDialog.Callback, //
|
AskForLockScreenDialog.Callback, //
|
||||||
UpdateAppAvailableDialog.Callback, //
|
UpdateAppAvailableDialog.Callback, //
|
||||||
UpdateAppDialog.Callback, //
|
UpdateAppDialog.Callback, //
|
||||||
BetaConfirmationDialog.Callback {
|
BetaConfirmationDialog.Callback {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var vaultListPresenter: VaultListPresenter
|
lateinit var vaultListPresenter: VaultListPresenter
|
||||||
@ -122,7 +122,7 @@ class VaultListActivity : BaseActivity(), //
|
|||||||
|
|
||||||
override fun showVaultSettingsDialog(vaultModel: VaultModel) {
|
override fun showVaultSettingsDialog(vaultModel: VaultModel) {
|
||||||
val vaultSettingDialog = //
|
val vaultSettingDialog = //
|
||||||
SettingsVaultBottomSheet.newInstance(vaultModel)
|
SettingsVaultBottomSheet.newInstance(vaultModel)
|
||||||
vaultSettingDialog.show(supportFragmentManager, "VaultSettings")
|
vaultSettingDialog.show(supportFragmentManager, "VaultSettings")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,7 +164,7 @@ class VaultListActivity : BaseActivity(), //
|
|||||||
|
|
||||||
override fun onDeleteVaultClick(vaultModel: VaultModel) {
|
override fun onDeleteVaultClick(vaultModel: VaultModel) {
|
||||||
VaultDeleteConfirmationDialog.newInstance(vaultModel) //
|
VaultDeleteConfirmationDialog.newInstance(vaultModel) //
|
||||||
.show(supportFragmentManager, "VaultDeleteConfirmationDialog")
|
.show(supportFragmentManager, "VaultDeleteConfirmationDialog")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onRenameVaultClick(vaultModel: VaultModel) {
|
override fun onRenameVaultClick(vaultModel: VaultModel) {
|
||||||
@ -192,7 +192,7 @@ class VaultListActivity : BaseActivity(), //
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun vaultListFragment(): VaultListFragment = //
|
private fun vaultListFragment(): VaultListFragment = //
|
||||||
getCurrentFragment(R.id.fragmentContainer) as VaultListFragment
|
getCurrentFragment(R.id.fragmentContainer) as VaultListFragment
|
||||||
|
|
||||||
override fun onUpdateAppDialogLoaded() {
|
override fun onUpdateAppDialogLoaded() {
|
||||||
showProgress(ProgressModel.GENERIC)
|
showProgress(ProgressModel.GENERIC)
|
||||||
|
@ -17,8 +17,8 @@ import kotlinx.android.synthetic.main.toolbar_layout.toolbar
|
|||||||
|
|
||||||
@Activity
|
@Activity
|
||||||
class WebDavAddOrChangeActivity : BaseActivity(),
|
class WebDavAddOrChangeActivity : BaseActivity(),
|
||||||
WebDavAddOrChangeView,
|
WebDavAddOrChangeView,
|
||||||
WebDavAskForHttpDialog.Callback {
|
WebDavAskForHttpDialog.Callback {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var webDavAddOrChangePresenter: WebDavAddOrChangePresenter
|
lateinit var webDavAddOrChangePresenter: WebDavAddOrChangePresenter
|
||||||
|
@ -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
|
import kotlinx.android.synthetic.main.view_cloud_folder_content.view.cloudFolderText
|
||||||
|
|
||||||
class BrowseFilesAdapter @Inject
|
class BrowseFilesAdapter @Inject
|
||||||
constructor(private val dateHelper: DateHelper, //
|
constructor(
|
||||||
private val fileSizeHelper: FileSizeHelper, //
|
private val dateHelper: DateHelper, //
|
||||||
private val fileUtil: FileUtil, //
|
private val fileSizeHelper: FileSizeHelper, //
|
||||||
private val sharedPreferencesHandler: SharedPreferencesHandler) : RecyclerViewBaseAdapter<CloudNodeModel<*>, BrowseFilesAdapter.ItemClickListener, VaultContentViewHolder>(CloudNodeModelNameAZComparator()), FastScrollRecyclerView.SectionedAdapter {
|
private val fileUtil: FileUtil, //
|
||||||
|
private val sharedPreferencesHandler: SharedPreferencesHandler
|
||||||
|
) : RecyclerViewBaseAdapter<CloudNodeModel<*>, BrowseFilesAdapter.ItemClickListener, VaultContentViewHolder>(CloudNodeModelNameAZComparator()), FastScrollRecyclerView.SectionedAdapter {
|
||||||
|
|
||||||
private var chooseCloudNodeSettings: ChooseCloudNodeSettings? = null
|
private var chooseCloudNodeSettings: ChooseCloudNodeSettings? = null
|
||||||
private var navigationMode: ChooseCloudNodeSettings.NavigationMode? = null
|
private var navigationMode: ChooseCloudNodeSettings.NavigationMode? = null
|
||||||
|
@ -7,4 +7,5 @@ import org.cryptomator.presentation.ui.dialog.CloudNodeRenameDialog
|
|||||||
import org.cryptomator.presentation.ui.dialog.CreateFolderDialog
|
import org.cryptomator.presentation.ui.dialog.CreateFolderDialog
|
||||||
import org.cryptomator.presentation.ui.dialog.FileTypeNotSupportedDialog
|
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
|
||||||
|
@ -7,6 +7,6 @@ import org.cryptomator.presentation.ui.dialog.VaultRenameDialog
|
|||||||
|
|
||||||
// FIXME delete this file and add this interfaces to VaultListView.kt
|
// FIXME delete this file and add this interfaces to VaultListView.kt
|
||||||
interface VaultListCallback : AddVaultBottomSheet.Callback, //
|
interface VaultListCallback : AddVaultBottomSheet.Callback, //
|
||||||
SettingsVaultBottomSheet.Callback, //
|
SettingsVaultBottomSheet.Callback, //
|
||||||
VaultDeleteConfirmationDialog.Callback, //
|
VaultDeleteConfirmationDialog.Callback, //
|
||||||
VaultRenameDialog.Callback
|
VaultRenameDialog.Callback
|
||||||
|
@ -14,8 +14,8 @@ class AppIsObscuredInfoDialog : BaseDialog<Activity>() {
|
|||||||
|
|
||||||
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||||
builder //
|
builder //
|
||||||
.setTitle(R.string.dialog_app_is_obscured_info_title) //
|
.setTitle(R.string.dialog_app_is_obscured_info_title) //
|
||||||
.setNeutralButton(R.string.dialog_app_is_obscured_info_neutral_button) { dialog: DialogInterface, _: Int -> dialog.dismiss() }
|
.setNeutralButton(R.string.dialog_app_is_obscured_info_neutral_button) { dialog: DialogInterface, _: Int -> dialog.dismiss() }
|
||||||
return builder.create()
|
return builder.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,8 +17,8 @@ class AskForLockScreenDialog : BaseDialog<AskForLockScreenDialog.Callback>() {
|
|||||||
|
|
||||||
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||||
builder //
|
builder //
|
||||||
.setTitle(R.string.dialog_no_screen_lock_title) //
|
.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) }
|
.setNeutralButton(getString(R.string.dialog_unable_to_share_positive_button)) { _: DialogInterface, _: Int -> callback?.onAskForLockScreenFinished(cb_select_screen_lock.isChecked) }
|
||||||
return builder.create()
|
return builder.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,14 +29,14 @@ class AssignSslCertificateDialog : BaseDialog<AssignSslCertificateDialog.Callbac
|
|||||||
|
|
||||||
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||||
builder //
|
builder //
|
||||||
.setTitle(requireContext().getString(R.string.dialog_accept_ssl_certificate_title))
|
.setTitle(requireContext().getString(R.string.dialog_accept_ssl_certificate_title))
|
||||||
.setPositiveButton(requireActivity().getString(R.string.dialog_unable_to_share_positive_button)) { _: DialogInterface, _: Int ->
|
.setPositiveButton(requireActivity().getString(R.string.dialog_unable_to_share_positive_button)) { _: DialogInterface, _: Int ->
|
||||||
val cloud = requireArguments().getSerializable(WEBDAV_CLOUD) as WebDavCloud
|
val cloud = requireArguments().getSerializable(WEBDAV_CLOUD) as WebDavCloud
|
||||||
callback?.onAcceptCertificateClicked(cloud, certificate)
|
callback?.onAcceptCertificateClicked(cloud, certificate)
|
||||||
} //
|
} //
|
||||||
.setNegativeButton(requireContext().getString(R.string.dialog_button_cancel)) { _: DialogInterface, _: Int ->
|
.setNegativeButton(requireContext().getString(R.string.dialog_button_cancel)) { _: DialogInterface, _: Int ->
|
||||||
callback?.onAcceptCertificateDenied()
|
callback?.onAcceptCertificateDenied()
|
||||||
}
|
}
|
||||||
return builder.create()
|
return builder.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,8 +16,8 @@ class BetaConfirmationDialog : BaseDialog<BetaConfirmationDialog.Callback>() {
|
|||||||
|
|
||||||
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||||
builder //
|
builder //
|
||||||
.setTitle(R.string.dialog_beta_confirmation_title) //
|
.setTitle(R.string.dialog_beta_confirmation_title) //
|
||||||
.setNeutralButton(getString(R.string.dialog_unable_to_share_positive_button)) { _: DialogInterface, _: Int -> callback?.onAskForBetaConfirmationFinished() }
|
.setNeutralButton(getString(R.string.dialog_unable_to_share_positive_button)) { _: DialogInterface, _: Int -> callback?.onAskForBetaConfirmationFinished() }
|
||||||
return builder.create()
|
return builder.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,8 +10,8 @@ class BiometricAuthKeyInvalidatedDialog : BaseDialog<BiometricAuthKeyInvalidated
|
|||||||
|
|
||||||
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||||
builder //
|
builder //
|
||||||
.setTitle(R.string.dialog_biometric_auth_key_invalidated_title) //
|
.setTitle(R.string.dialog_biometric_auth_key_invalidated_title) //
|
||||||
.setNegativeButton(getString(R.string.dialog_biometric_auth_key_invalidated_neutral_button)) { _: DialogInterface, _: Int -> }
|
.setNegativeButton(getString(R.string.dialog_biometric_auth_key_invalidated_neutral_button)) { _: DialogInterface, _: Int -> }
|
||||||
return builder.create()
|
return builder.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,13 +35,18 @@ class ChangePasswordDialog : BaseProgressErrorDialog<ChangePasswordDialog.Callba
|
|||||||
changePasswordButton?.setOnClickListener {
|
changePasswordButton?.setOnClickListener {
|
||||||
val vaultModel = requireArguments().getSerializable(VAULT_ARG) as VaultModel
|
val vaultModel = requireArguments().getSerializable(VAULT_ARG) as VaultModel
|
||||||
val unverifiedVaultConfig = requireArguments().getSerializable(VAULT_CONFIG_ARG) as UnverifiedVaultConfig?
|
val unverifiedVaultConfig = requireArguments().getSerializable(VAULT_CONFIG_ARG) as UnverifiedVaultConfig?
|
||||||
if (valid(et_old_password.text.toString(), //
|
if (valid(
|
||||||
et_new_password.text.toString(), //
|
et_old_password.text.toString(), //
|
||||||
et_new_retype_password.text.toString())) {
|
et_new_password.text.toString(), //
|
||||||
callback?.onChangePasswordClick(vaultModel, //
|
et_new_retype_password.text.toString()
|
||||||
unverifiedVaultConfig, //
|
)
|
||||||
et_old_password.text.toString(), //
|
) {
|
||||||
et_new_password.text.toString())
|
callback?.onChangePasswordClick(
|
||||||
|
vaultModel, //
|
||||||
|
unverifiedVaultConfig, //
|
||||||
|
et_old_password.text.toString(), //
|
||||||
|
et_new_password.text.toString()
|
||||||
|
)
|
||||||
onWaitForResponse(et_old_password)
|
onWaitForResponse(et_old_password)
|
||||||
} else {
|
} else {
|
||||||
hideKeyboard(et_old_password)
|
hideKeyboard(et_old_password)
|
||||||
@ -58,10 +63,12 @@ class ChangePasswordDialog : BaseProgressErrorDialog<ChangePasswordDialog.Callba
|
|||||||
registerOnEditorDoneActionAndPerformButtonClick(et_new_retype_password) { changePasswordButton }
|
registerOnEditorDoneActionAndPerformButtonClick(et_new_retype_password) { changePasswordButton }
|
||||||
|
|
||||||
PasswordStrengthUtil() //
|
PasswordStrengthUtil() //
|
||||||
.startUpdatingPasswordStrengthMeter(et_new_password, //
|
.startUpdatingPasswordStrengthMeter(
|
||||||
progressBarPwStrengthIndicator, //
|
et_new_password, //
|
||||||
textViewPwStrengthIndicator, //
|
progressBarPwStrengthIndicator, //
|
||||||
changePasswordButton)
|
textViewPwStrengthIndicator, //
|
||||||
|
changePasswordButton
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,10 +93,10 @@ class ChangePasswordDialog : BaseProgressErrorDialog<ChangePasswordDialog.Callba
|
|||||||
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||||
val vaultModel = requireArguments().getSerializable(VAULT_ARG) as VaultModel
|
val vaultModel = requireArguments().getSerializable(VAULT_ARG) as VaultModel
|
||||||
return builder //
|
return builder //
|
||||||
.setTitle(vaultModel.name) //
|
.setTitle(vaultModel.name) //
|
||||||
.setPositiveButton(getString(R.string.dialog_change_password)) { _: DialogInterface, _: Int -> } //
|
.setPositiveButton(getString(R.string.dialog_change_password)) { _: DialogInterface, _: Int -> } //
|
||||||
.setNegativeButton(getString(R.string.dialog_button_cancel)) { _: DialogInterface?, _: Int -> } //
|
.setNegativeButton(getString(R.string.dialog_button_cancel)) { _: DialogInterface?, _: Int -> } //
|
||||||
.create()
|
.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setupView() {
|
override fun setupView() {
|
||||||
|
@ -50,10 +50,10 @@ class CloudNodeRenameDialog : BaseProgressErrorDialog<CloudNodeRenameDialog.Call
|
|||||||
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||||
val cloudNodeModel = requireArguments().getSerializable(CLOUD_NODE_ARG) as CloudNodeModel<*>
|
val cloudNodeModel = requireArguments().getSerializable(CLOUD_NODE_ARG) as CloudNodeModel<*>
|
||||||
return builder
|
return builder
|
||||||
.setTitle(getTitle(cloudNodeModel))
|
.setTitle(getTitle(cloudNodeModel))
|
||||||
.setPositiveButton(requireActivity().getString(R.string.dialog_rename_node_positive_button)) { _: DialogInterface, _: Int -> }
|
.setPositiveButton(requireActivity().getString(R.string.dialog_rename_node_positive_button)) { _: DialogInterface, _: Int -> }
|
||||||
.setNegativeButton(requireActivity().getString(R.string.dialog_button_cancel)) { _: DialogInterface, _: Int -> }
|
.setNegativeButton(requireActivity().getString(R.string.dialog_button_cancel)) { _: DialogInterface, _: Int -> }
|
||||||
.create()
|
.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getTitle(cloudNodeModel: CloudNodeModel<*>): String {
|
private fun getTitle(cloudNodeModel: CloudNodeModel<*>): String {
|
||||||
|
@ -27,10 +27,10 @@ class ConfirmDeleteCloudNodeDialog : BaseDialog<ConfirmDeleteCloudNodeDialog.Cal
|
|||||||
title = nodes[0].name
|
title = nodes[0].name
|
||||||
}
|
}
|
||||||
return builder //
|
return builder //
|
||||||
.setTitle(title) //
|
.setTitle(title) //
|
||||||
.setPositiveButton(getString(R.string.dialog_confirm_delete_positive_button)) { _: DialogInterface, _: Int -> callback?.onDeleteCloudNodeConfirmed(nodes) } //
|
.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 -> } //
|
.setNegativeButton(getString(R.string.dialog_confirm_delete_negative_button)) { _: DialogInterface, _: Int -> } //
|
||||||
.create()
|
.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getMessage(cloudNodeModel: CloudNodeModel<*>): String {
|
private fun getMessage(cloudNodeModel: CloudNodeModel<*>): String {
|
||||||
|
@ -44,9 +44,9 @@ class CreateFolderDialog : BaseProgressErrorDialog<CreateFolderDialog.Callback>(
|
|||||||
|
|
||||||
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||||
return builder.setTitle(requireContext().getString(R.string.dialog_create_folder_title))
|
return builder.setTitle(requireContext().getString(R.string.dialog_create_folder_title))
|
||||||
.setPositiveButton(requireContext().getString(R.string.dialog_create_folder_positive_button)) { _: DialogInterface, _: Int -> }
|
.setPositiveButton(requireContext().getString(R.string.dialog_create_folder_positive_button)) { _: DialogInterface, _: Int -> }
|
||||||
.setNegativeButton(requireContext().getString(R.string.dialog_button_cancel)) { _: DialogInterface, _: Int -> }
|
.setNegativeButton(requireContext().getString(R.string.dialog_button_cancel)) { _: DialogInterface, _: Int -> }
|
||||||
.create()
|
.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setupView() {
|
override fun setupView() {
|
||||||
|
@ -17,9 +17,9 @@ class DebugModeDisclaimerDialog : BaseDialog<DebugModeDisclaimerDialog.Callback>
|
|||||||
|
|
||||||
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||||
builder //
|
builder //
|
||||||
.setTitle(R.string.dialog_debug_mode_disclaimer_title) //
|
.setTitle(R.string.dialog_debug_mode_disclaimer_title) //
|
||||||
.setPositiveButton(getString(R.string.dialog_debug_mode_positive_button)) { _: DialogInterface, _: Int -> callback?.onDisclaimerAccepted() } //
|
.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() }
|
.setNegativeButton(getString(R.string.dialog_debug_mode_negative_button)) { _: DialogInterface, _: Int -> callback?.onDisclaimerRejected() }
|
||||||
return builder.create()
|
return builder.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,11 +20,11 @@ class DeleteCloudConnectionWithVaultsDialog : BaseDialog<DeleteCloudConnectionWi
|
|||||||
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||||
val cloudModel = requireArguments().getSerializable(ARG_CLOUD) as CloudModel
|
val cloudModel = requireArguments().getSerializable(ARG_CLOUD) as CloudModel
|
||||||
builder.setTitle(cloudModel.name()) //
|
builder.setTitle(cloudModel.name()) //
|
||||||
.setPositiveButton(getString(R.string.dialog_delete_cloud_connection_with_vaults_positive_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>
|
val vaultsOfCloud = requireArguments().getSerializable(ARG_VAULTS) as ArrayList<Vault>
|
||||||
callback?.onDeleteCloudConnectionAndVaults(cloudModel, vaultsOfCloud)
|
callback?.onDeleteCloudConnectionAndVaults(cloudModel, vaultsOfCloud)
|
||||||
dismiss()
|
dismiss()
|
||||||
}.setNegativeButton(getString(R.string.dialog_delete_cloud_connection_with_vaults_negative_button)) { _: DialogInterface, _: Int -> }
|
}.setNegativeButton(getString(R.string.dialog_delete_cloud_connection_with_vaults_negative_button)) { _: DialogInterface, _: Int -> }
|
||||||
return builder.create()
|
return builder.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,9 +19,9 @@ class DisableAppWhenObscuredDisclaimerDialog : BaseDialog<DisableAppWhenObscured
|
|||||||
|
|
||||||
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||||
builder //
|
builder //
|
||||||
.setTitle(R.string.dialog_disable_app_obscured_disclaimer_title) //
|
.setTitle(R.string.dialog_disable_app_obscured_disclaimer_title) //
|
||||||
.setPositiveButton(getString(R.string.dialog_disable_app_obscured_positive_button)) { _: DialogInterface, _: Int -> callback?.onDisableAppObscuredDisclaimerAccepted() } //
|
.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() }
|
.setNegativeButton(getString(R.string.dialog_disable_app_obscured_negative_button)) { _: DialogInterface, _: Int -> callback?.onDisableAppObscuredDisclaimerRejected() }
|
||||||
return builder.create()
|
return builder.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,9 +19,9 @@ class DisableSecureScreenDisclaimerDialog : BaseDialog<DisableSecureScreenDiscla
|
|||||||
|
|
||||||
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||||
builder //
|
builder //
|
||||||
.setTitle(R.string.dialog_disable_app_obscured_disclaimer_title) //
|
.setTitle(R.string.dialog_disable_app_obscured_disclaimer_title) //
|
||||||
.setPositiveButton(getString(R.string.dialog_disable_app_obscured_positive_button)) { _: DialogInterface, _: Int -> callback?.onDisableSecureScreenDisclaimerAccepted() } //
|
.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() }
|
.setNegativeButton(getString(R.string.dialog_disable_app_obscured_negative_button)) { _: DialogInterface, _: Int -> callback?.onDisableSecureScreenDisclaimerRejected() }
|
||||||
return builder.create()
|
return builder.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,11 +21,13 @@ class EnrollSystemBiometricDialog : BaseDialog<EnrollSystemBiometricDialog.Callb
|
|||||||
|
|
||||||
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||||
builder //
|
builder //
|
||||||
.setTitle(getString(R.string.dialog_no_biometric_auth_set_up_title)) //
|
.setTitle(getString(R.string.dialog_no_biometric_auth_set_up_title)) //
|
||||||
.setPositiveButton(getString(R.string.dialog_unable_to_share_positive_button) //
|
.setPositiveButton(
|
||||||
) { _: DialogInterface, _: Int -> callback?.onSetupBiometricAuthInSystemClicked() }
|
getString(R.string.dialog_unable_to_share_positive_button) //
|
||||||
.setNegativeButton(getString(R.string.dialog_button_cancel) //
|
) { _: DialogInterface, _: Int -> callback?.onSetupBiometricAuthInSystemClicked() }
|
||||||
) { _: DialogInterface?, _: Int -> callback?.onCancelSetupBiometricAuthInSystemClicked() }
|
.setNegativeButton(
|
||||||
|
getString(R.string.dialog_button_cancel) //
|
||||||
|
) { _: DialogInterface?, _: Int -> callback?.onCancelSetupBiometricAuthInSystemClicked() }
|
||||||
return builder.create()
|
return builder.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,12 +51,12 @@ class EnterPasswordDialog : BaseProgressErrorDialog<EnterPasswordDialog.Callback
|
|||||||
|
|
||||||
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||||
return builder //
|
return builder //
|
||||||
.setTitle(vaultModel().name) //
|
.setTitle(vaultModel().name) //
|
||||||
.setPositiveButton(getString(R.string.dialog_enter_password_positive_button)) { _: DialogInterface, _: Int -> }
|
.setPositiveButton(getString(R.string.dialog_enter_password_positive_button)) { _: DialogInterface, _: Int -> }
|
||||||
.setNegativeButton(getString(R.string.dialog_button_cancel)) { _: DialogInterface, _: Int ->
|
.setNegativeButton(getString(R.string.dialog_button_cancel)) { _: DialogInterface, _: Int ->
|
||||||
callback?.onUnlockCanceled()
|
callback?.onUnlockCanceled()
|
||||||
callback?.closeDialog()
|
callback?.closeDialog()
|
||||||
}.create()
|
}.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun vaultModel(): VaultModel {
|
fun vaultModel(): VaultModel {
|
||||||
|
@ -19,8 +19,8 @@ class ExistingFileDialog : BaseDialog<ExistingFileDialog.Callback>() {
|
|||||||
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||||
val fileUri = requireArguments().getParcelable<Uri>(FILE_URI_ARG)
|
val fileUri = requireArguments().getParcelable<Uri>(FILE_URI_ARG)
|
||||||
builder.setTitle(getString(R.string.dialog_existing_file_title)) //
|
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) } } //
|
.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 -> }
|
.setNegativeButton(getString(R.string.dialog_button_cancel)) { _: DialogInterface?, _: Int -> }
|
||||||
return builder.create()
|
return builder.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,15 +32,17 @@ class ExportCloudFilesDialog : BaseProgressErrorDialog<ExportCloudFilesDialog.Ca
|
|||||||
|
|
||||||
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||||
return builder //
|
return builder //
|
||||||
.setTitle(effectiveTitle(1)) //
|
.setTitle(effectiveTitle(1)) //
|
||||||
.setNeutralButton(getString(R.string.dialog_export_file_cancel_button)) { _: DialogInterface, _: Int -> callback?.onExportCancelled() } //
|
.setNeutralButton(getString(R.string.dialog_export_file_cancel_button)) { _: DialogInterface, _: Int -> callback?.onExportCancelled() } //
|
||||||
.create()
|
.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun effectiveTitle(seenFiles: Int): String {
|
private fun effectiveTitle(seenFiles: Int): String {
|
||||||
return String.format(getString(R.string.dialog_export_file_title), //
|
return String.format(
|
||||||
seenFiles, //
|
getString(R.string.dialog_export_file_title), //
|
||||||
requireArguments().getInt(ARG_NUMBER_OF_FILES))
|
seenFiles, //
|
||||||
|
requireArguments().getInt(ARG_NUMBER_OF_FILES)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setupView() {}
|
override fun setupView() {}
|
||||||
|
@ -46,9 +46,9 @@ class FileNameDialog : BaseProgressErrorDialog<FileNameDialog.Callback>() {
|
|||||||
|
|
||||||
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||||
return builder.setTitle(R.string.dialog_file_name_title) //
|
return builder.setTitle(R.string.dialog_file_name_title) //
|
||||||
.setPositiveButton(R.string.dialog_file_name_create) { _: DialogInterface, _: Int -> } //
|
.setPositiveButton(R.string.dialog_file_name_create) { _: DialogInterface, _: Int -> } //
|
||||||
.setNegativeButton(R.string.dialog_file_name_cancel) { _: DialogInterface, _: Int -> } //
|
.setNegativeButton(R.string.dialog_file_name_cancel) { _: DialogInterface, _: Int -> } //
|
||||||
.create()
|
.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun effectiveNewFileName(newFileName: String): String {
|
private fun effectiveNewFileName(newFileName: String): String {
|
||||||
|
@ -18,8 +18,8 @@ class FileTypeNotSupportedDialog : BaseDialog<FileTypeNotSupportedDialog.Callbac
|
|||||||
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||||
val cloudFileModel = requireArguments().getSerializable(CLOUD_FILE_ARG) as CloudFileModel
|
val cloudFileModel = requireArguments().getSerializable(CLOUD_FILE_ARG) as CloudFileModel
|
||||||
builder.setTitle(String.format(getString(R.string.dialog_filetype_not_supported_title), cloudFileModel.name))
|
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) } //
|
.setPositiveButton(getString(R.string.dialog_filetype_not_supported_positive_button)) { _: DialogInterface, _: Int -> callback?.onExportFileAfterAppChooserClicked(cloudFileModel) } //
|
||||||
.setNegativeButton(getString(R.string.dialog_button_cancel)) { _: DialogInterface, _: Int -> }
|
.setNegativeButton(getString(R.string.dialog_button_cancel)) { _: DialogInterface, _: Int -> }
|
||||||
return builder.create()
|
return builder.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,8 +17,8 @@ class LicenseConfirmationDialog : BaseDialog<LicenseConfirmationDialog.Callback>
|
|||||||
|
|
||||||
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||||
builder //
|
builder //
|
||||||
.setTitle(getString(R.string.dialog_license_confirmation_title)) //
|
.setTitle(getString(R.string.dialog_license_confirmation_title)) //
|
||||||
.setNeutralButton(getText(R.string.dialog_license_confirmation_ok_btn)) { _: DialogInterface, _: Int -> callback?.licenseConfirmationClicked() }
|
.setNeutralButton(getText(R.string.dialog_license_confirmation_ok_btn)) { _: DialogInterface, _: Int -> callback?.licenseConfirmationClicked() }
|
||||||
return builder.create()
|
return builder.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,11 +18,11 @@ class NoDirFileDialog : BaseDialog<NoDirFileDialog.CallBack>() {
|
|||||||
|
|
||||||
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||||
builder //
|
builder //
|
||||||
.setTitle(R.string.dialog_no_dir_file_title) //
|
.setTitle(R.string.dialog_no_dir_file_title) //
|
||||||
.setNeutralButton(R.string.dialog_no_dir_file_back_button) { dialog: DialogInterface, _: Int ->
|
.setNeutralButton(R.string.dialog_no_dir_file_back_button) { dialog: DialogInterface, _: Int ->
|
||||||
callback?.navigateFolderBackBecauseNoDirFile()
|
callback?.navigateFolderBackBecauseNoDirFile()
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
}
|
}
|
||||||
return builder.create()
|
return builder.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,13 +24,13 @@ class NotEnoughVaultsDialog private constructor(private val context: Context) {
|
|||||||
|
|
||||||
fun show() {
|
fun show() {
|
||||||
AlertDialog.Builder(context) //
|
AlertDialog.Builder(context) //
|
||||||
.setCancelable(false) //
|
.setCancelable(false) //
|
||||||
.setTitle(title) //
|
.setTitle(title) //
|
||||||
.setMessage(ResourceHelper.getString(R.string.dialog_unable_to_share_message)) //
|
.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() } //
|
.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() } //
|
.setNegativeButton(ResourceHelper.getString(R.string.dialog_unable_to_share_negative_button)) { _: DialogInterface, _: Int -> callback.onNotEnoughVaultsCreateVaultClicked() } //
|
||||||
.create() //
|
.create() //
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -20,11 +20,11 @@ class ReplaceDialog private constructor(private val context: Context) {
|
|||||||
fun show(existingFiles: List<String>, uploadingFilesCount: Int) {
|
fun show(existingFiles: List<String>, uploadingFilesCount: Int) {
|
||||||
val existingFilesCount = existingFiles.size
|
val existingFilesCount = existingFiles.size
|
||||||
val alertDialogBuilder = AlertDialog.Builder(context) //
|
val alertDialogBuilder = AlertDialog.Builder(context) //
|
||||||
.setTitle(effectiveReplaceDialogTitle(existingFilesCount)) //
|
.setTitle(effectiveReplaceDialogTitle(existingFilesCount)) //
|
||||||
.setMessage(effectiveReplaceDialogMessage(existingFiles, uploadingFilesCount))
|
.setMessage(effectiveReplaceDialogMessage(existingFiles, uploadingFilesCount))
|
||||||
.setPositiveButton(effectiveReplaceDialogPositiveButton(existingFilesCount, uploadingFilesCount)) { _: DialogInterface, _: Int -> callback.onReplacePositiveClicked() } //
|
.setPositiveButton(effectiveReplaceDialogPositiveButton(existingFilesCount, uploadingFilesCount)) { _: DialogInterface, _: Int -> callback.onReplacePositiveClicked() } //
|
||||||
.setNeutralButton(effectiveReplaceDialogNeutralButton()) { _: DialogInterface, _: Int -> callback.onReplaceCanceled() } //
|
.setNeutralButton(effectiveReplaceDialogNeutralButton()) { _: DialogInterface, _: Int -> callback.onReplaceCanceled() } //
|
||||||
.setOnCancelListener { callback.onReplaceCanceled() }
|
.setOnCancelListener { callback.onReplaceCanceled() }
|
||||||
if (uploadingFilesCount > 1 && existingFilesCount != uploadingFilesCount) {
|
if (uploadingFilesCount > 1 && existingFilesCount != uploadingFilesCount) {
|
||||||
alertDialogBuilder.setNegativeButton(effectiveReplaceDialogNegativeButton()) { _: DialogInterface, _: Int -> callback.onReplaceNegativeClicked() }
|
alertDialogBuilder.setNegativeButton(effectiveReplaceDialogNegativeButton()) { _: DialogInterface, _: Int -> callback.onReplaceNegativeClicked() }
|
||||||
}
|
}
|
||||||
|
@ -18,11 +18,11 @@ class SymLinkDialog : BaseDialog<SymLinkDialog.CallBack?>() {
|
|||||||
|
|
||||||
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||||
builder //
|
builder //
|
||||||
.setTitle(R.string.dialog_sym_link_title) //
|
.setTitle(R.string.dialog_sym_link_title) //
|
||||||
.setNeutralButton(R.string.dialog_sym_link_back_button) { dialog: DialogInterface, _: Int ->
|
.setNeutralButton(R.string.dialog_sym_link_back_button) { dialog: DialogInterface, _: Int ->
|
||||||
callback?.navigateFolderBackBecauseSymlink()
|
callback?.navigateFolderBackBecauseSymlink()
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
}
|
}
|
||||||
return builder.create()
|
return builder.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,12 +17,12 @@ class UnsavedChangesDialog private constructor(private val context: Context) {
|
|||||||
|
|
||||||
fun show() {
|
fun show() {
|
||||||
AlertDialog.Builder(context) //
|
AlertDialog.Builder(context) //
|
||||||
.setCancelable(false) //
|
.setCancelable(false) //
|
||||||
.setTitle(R.string.dialog_unsaved_changes_title) //
|
.setTitle(R.string.dialog_unsaved_changes_title) //
|
||||||
.setMessage(R.string.dialog_unsaved_changes_message) //
|
.setMessage(R.string.dialog_unsaved_changes_message) //
|
||||||
.setPositiveButton(R.string.dialog_unsaved_changes_save) { _: DialogInterface?, _: Int -> callback.onSaveChangesClicked() } //
|
.setPositiveButton(R.string.dialog_unsaved_changes_save) { _: DialogInterface?, _: Int -> callback.onSaveChangesClicked() } //
|
||||||
.setNegativeButton(R.string.dialog_unsaved_changes_discard) { _: DialogInterface?, _: Int -> callback.onDiscardChangesClicked() } //
|
.setNegativeButton(R.string.dialog_unsaved_changes_discard) { _: DialogInterface?, _: Int -> callback.onDiscardChangesClicked() } //
|
||||||
.create().show()
|
.create().show()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -22,12 +22,12 @@ class UpdateAppAvailableDialog : BaseProgressErrorDialog<UpdateAppAvailableDialo
|
|||||||
|
|
||||||
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||||
return builder //
|
return builder //
|
||||||
.setTitle(getString(R.string.dialog_update_available_title)) //
|
.setTitle(getString(R.string.dialog_update_available_title)) //
|
||||||
.setPositiveButton(getString(R.string.dialog_update_available_update)) { _: DialogInterface, _: Int -> callback?.installUpdate() } //
|
.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() }
|
.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() } //
|
.setNegativeButton(getText(R.string.dialog_update_available_cancel)) { _: DialogInterface, _: Int -> callback?.cancelUpdateClicked() } //
|
||||||
.setCancelable(false) //
|
.setCancelable(false) //
|
||||||
.create()
|
.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun setupView() {
|
public override fun setupView() {
|
||||||
|
@ -21,9 +21,9 @@ class UpdateAppDialog : BaseProgressErrorDialog<UpdateAppDialog.Callback>() {
|
|||||||
|
|
||||||
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||||
return builder //
|
return builder //
|
||||||
.setTitle(getString(R.string.dialog_download_update_title)) //
|
.setTitle(getString(R.string.dialog_download_update_title)) //
|
||||||
.setCancelable(false) //
|
.setCancelable(false) //
|
||||||
.create()
|
.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun setupView() {
|
public override fun setupView() {
|
||||||
|
@ -39,10 +39,10 @@ class UpdateLicenseDialog : BaseProgressErrorDialog<UpdateLicenseDialog.Callback
|
|||||||
|
|
||||||
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||||
return builder //
|
return builder //
|
||||||
.setTitle(getString(R.string.dialog_enter_license_title)) //
|
.setTitle(getString(R.string.dialog_enter_license_title)) //
|
||||||
.setPositiveButton(getText(R.string.dialog_enter_license_ok_button)) { _: DialogInterface, _: Int -> } //
|
.setPositiveButton(getText(R.string.dialog_enter_license_ok_button)) { _: DialogInterface, _: Int -> } //
|
||||||
.setNegativeButton(getText(R.string.dialog_enter_license_decline_button)) { _: DialogInterface, _: Int -> callback?.onCheckLicenseCanceled() } //
|
.setNegativeButton(getText(R.string.dialog_enter_license_decline_button)) { _: DialogInterface, _: Int -> callback?.onCheckLicenseCanceled() } //
|
||||||
.create()
|
.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun setupView() {
|
public override fun setupView() {
|
||||||
|
@ -41,9 +41,9 @@ class UploadCloudFileDialog : BaseProgressErrorDialog<UploadCloudFileDialog.Call
|
|||||||
|
|
||||||
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||||
return builder //
|
return builder //
|
||||||
.setTitle(effectiveTitle()) //
|
.setTitle(effectiveTitle()) //
|
||||||
.setNeutralButton(getString(R.string.dialog_upload_file_cancel_button)) { _: DialogInterface?, _: Int -> } //
|
.setNeutralButton(getString(R.string.dialog_upload_file_cancel_button)) { _: DialogInterface?, _: Int -> } //
|
||||||
.create()
|
.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun effectiveTitle(): String {
|
private fun effectiveTitle(): String {
|
||||||
|
@ -19,8 +19,8 @@ class VaultDeleteConfirmationDialog : BaseDialog<VaultDeleteConfirmationDialog.C
|
|||||||
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||||
val vaultModel = requireArguments().getSerializable(VAULT_ARG) as VaultModel
|
val vaultModel = requireArguments().getSerializable(VAULT_ARG) as VaultModel
|
||||||
builder.setTitle(vaultModel.name) //
|
builder.setTitle(vaultModel.name) //
|
||||||
.setPositiveButton(getString(R.string.dialog_delete_vault_positive_button_text)) { _: DialogInterface, _: Int -> callback?.onDeleteConfirmedClick(vaultModel) } //
|
.setPositiveButton(getString(R.string.dialog_delete_vault_positive_button_text)) { _: DialogInterface, _: Int -> callback?.onDeleteConfirmedClick(vaultModel) } //
|
||||||
.setNegativeButton(getString(R.string.dialog_button_cancel)) { _: DialogInterface, _: Int -> }
|
.setNegativeButton(getString(R.string.dialog_button_cancel)) { _: DialogInterface, _: Int -> }
|
||||||
return builder.create()
|
return builder.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user