Merge branch 'release/1.6.5'

This commit is contained in:
Julian Raufelder 2021-11-29 17:31:46 +01:00
commit 515a5f1766
No known key found for this signature in database
GPG Key ID: 17EE71F6634E381D
8 changed files with 64 additions and 56 deletions

View File

@ -1,7 +1,9 @@
name: Build name: Build
on: on:
[push, pull_request] push:
pull_request_target:
types: [labeled]
jobs: jobs:
build: build:

View File

@ -2,7 +2,7 @@ apply from: 'buildsystem/dependencies.gradle'
apply plugin: "com.vanniktech.android.junit.jacoco" apply plugin: "com.vanniktech.android.junit.jacoco"
buildscript { buildscript {
ext.kotlin_version = '1.5.31' ext.kotlin_version = '1.6.0'
repositories { repositories {
mavenCentral() mavenCentral()
google() google()
@ -39,7 +39,7 @@ allprojects {
ext { ext {
androidApplicationId = 'org.cryptomator' androidApplicationId = 'org.cryptomator'
androidVersionCode = getVersionCode() androidVersionCode = getVersionCode()
androidVersionName = '1.6.4' androidVersionName = '1.6.5'
} }
repositories { repositories {
mavenCentral() mavenCentral()

View File

@ -29,12 +29,12 @@ ext {
rxAndroidVersion = '2.1.1' rxAndroidVersion = '2.1.1'
rxBindingVersion = '2.2.0' rxBindingVersion = '2.2.0'
daggerVersion = '2.40' daggerVersion = '2.40.2'
gsonVersion = '2.8.8' gsonVersion = '2.8.9'
okHttpVersion = '4.9.2' okHttpVersion = '4.9.2'
okHttpDigestVersion = '2.5' okHttpDigestVersion = '2.6'
velocityVersion = '2.3' velocityVersion = '2.3'
@ -74,9 +74,9 @@ ext {
// testing dependencies // testing dependencies
jUnitVersion = '5.8.1' jUnitVersion = '5.8.2'
assertJVersion = '1.7.1' assertJVersion = '1.7.1'
mockitoVersion = '4.0.0' mockitoVersion = '4.1.0'
mockitoKotlinVersion = '4.0.0' mockitoKotlinVersion = '4.0.0'
hamcrestVersion = '1.3' hamcrestVersion = '1.3'
dexmakerVersion = '1.0' dexmakerVersion = '1.0'

View File

@ -0,0 +1,7 @@
package org.cryptomator.domain.exception;
public class FileRemovedDuringUploadException extends BackendException {
public FileRemovedDuringUploadException() {
}
}

View File

@ -12,6 +12,7 @@ import androidx.multidex.MultiDexApplication
import org.cryptomator.data.cloud.crypto.Cryptors import org.cryptomator.data.cloud.crypto.Cryptors
import org.cryptomator.data.cloud.crypto.CryptorsModule import org.cryptomator.data.cloud.crypto.CryptorsModule
import org.cryptomator.data.repository.RepositoryModule import org.cryptomator.data.repository.RepositoryModule
import org.cryptomator.domain.Cloud
import org.cryptomator.presentation.di.HasComponent import org.cryptomator.presentation.di.HasComponent
import org.cryptomator.presentation.di.component.ApplicationComponent import org.cryptomator.presentation.di.component.ApplicationComponent
import org.cryptomator.presentation.di.component.DaggerApplicationComponent import org.cryptomator.presentation.di.component.DaggerApplicationComponent
@ -20,6 +21,7 @@ import org.cryptomator.presentation.di.module.ThreadModule
import org.cryptomator.presentation.logging.CrashLogging.Companion.setup import org.cryptomator.presentation.logging.CrashLogging.Companion.setup
import org.cryptomator.presentation.logging.DebugLogger import org.cryptomator.presentation.logging.DebugLogger
import org.cryptomator.presentation.logging.ReleaseLogger import org.cryptomator.presentation.logging.ReleaseLogger
import org.cryptomator.presentation.service.AutoUploadNotification
import org.cryptomator.presentation.service.AutoUploadService import org.cryptomator.presentation.service.AutoUploadService
import org.cryptomator.presentation.service.CryptorsService import org.cryptomator.presentation.service.CryptorsService
import org.cryptomator.util.NoOpActivityLifecycleCallbacks import org.cryptomator.util.NoOpActivityLifecycleCallbacks
@ -37,7 +39,7 @@ class CryptomatorApp : MultiDexApplication(), HasComponent<ApplicationComponent>
private var cryptoServiceBinder: CryptorsService.Binder? = null private var cryptoServiceBinder: CryptorsService.Binder? = null
@Volatile @Volatile
private lateinit var autoUploadServiceBinder: AutoUploadService.Binder private var autoUploadServiceBinder: AutoUploadService.Binder? = null
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
@ -59,8 +61,8 @@ class CryptomatorApp : MultiDexApplication(), HasComponent<ApplicationComponent>
) )
Timber.tag("App").d("appId %s", BuildConfig.APPLICATION_ID) Timber.tag("App").d("appId %s", BuildConfig.APPLICATION_ID)
launchServices()
initializeInjector() initializeInjector()
launchServices()
registerActivityLifecycleCallbacks(serviceNotifier) registerActivityLifecycleCallbacks(serviceNotifier)
AppCompatDelegate.setDefaultNightMode(SharedPreferencesHandler(applicationContext()).screenStyleMode) AppCompatDelegate.setDefaultNightMode(SharedPreferencesHandler(applicationContext()).screenStyleMode)
cleanupCache() cleanupCache()
@ -106,7 +108,7 @@ class CryptomatorApp : MultiDexApplication(), HasComponent<ApplicationComponent>
override fun onServiceConnected(name: ComponentName, service: IBinder) { override fun onServiceConnected(name: ComponentName, service: IBinder) {
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(), //
@ -120,6 +122,10 @@ class CryptomatorApp : MultiDexApplication(), HasComponent<ApplicationComponent>
}, BIND_AUTO_CREATE) }, BIND_AUTO_CREATE)
} }
fun startAutoUpload(cloud: Cloud) {
autoUploadServiceBinder?.startUpload(cloud)
}
fun startAutoUpload() { fun startAutoUpload() {
val sharedPreferencesHandler = SharedPreferencesHandler(applicationContext()) val sharedPreferencesHandler = SharedPreferencesHandler(applicationContext())
if (checkToStartAutoImageUpload(sharedPreferencesHandler)) { if (checkToStartAutoImageUpload(sharedPreferencesHandler)) {
@ -130,9 +136,13 @@ class CryptomatorApp : MultiDexApplication(), HasComponent<ApplicationComponent>
} }
if (vault?.isUnlocked == true) { if (vault?.isUnlocked == true) {
val cloud = applicationComponent.cloudRepository().decryptedViewOf(vault) val cloud = applicationComponent.cloudRepository().decryptedViewOf(vault)
applicationContext().startService(AutoUploadService.startAutoUploadIntent(applicationContext(), cloud)) startAutoUpload(cloud)
} else if (vault == null) { } else if (vault == null) {
applicationContext().startService(AutoUploadService.vaultNotFoundUploadIntent(applicationContext())) autoUploadServiceBinder?.vaultNotFound()
?: run {
Timber.tag("App").i("autoUploadServiceBinder not yet initialized, manually show notification")
AutoUploadNotification(applicationContext, 0).showVaultNotFoundNotification()
}
} }
} }
} }

View File

@ -33,6 +33,7 @@ import org.cryptomator.domain.usecases.vault.RenameVaultUseCase
import org.cryptomator.domain.usecases.vault.SaveVaultUseCase import org.cryptomator.domain.usecases.vault.SaveVaultUseCase
import org.cryptomator.generator.Callback import org.cryptomator.generator.Callback
import org.cryptomator.presentation.BuildConfig import org.cryptomator.presentation.BuildConfig
import org.cryptomator.presentation.CryptomatorApp
import org.cryptomator.presentation.R import org.cryptomator.presentation.R
import org.cryptomator.presentation.exception.ExceptionHandlers import org.cryptomator.presentation.exception.ExceptionHandlers
import org.cryptomator.presentation.intent.Intents import org.cryptomator.presentation.intent.Intents
@ -42,7 +43,6 @@ import org.cryptomator.presentation.model.CloudTypeModel
import org.cryptomator.presentation.model.ProgressModel import org.cryptomator.presentation.model.ProgressModel
import org.cryptomator.presentation.model.VaultModel import org.cryptomator.presentation.model.VaultModel
import org.cryptomator.presentation.model.mappers.CloudFolderModelMapper import org.cryptomator.presentation.model.mappers.CloudFolderModelMapper
import org.cryptomator.presentation.service.AutoUploadService
import org.cryptomator.presentation.ui.activity.LicenseCheckActivity import org.cryptomator.presentation.ui.activity.LicenseCheckActivity
import org.cryptomator.presentation.ui.activity.view.VaultListView import org.cryptomator.presentation.ui.activity.view.VaultListView
import org.cryptomator.presentation.ui.dialog.AppIsObscuredInfoDialog import org.cryptomator.presentation.ui.dialog.AppIsObscuredInfoDialog
@ -386,12 +386,14 @@ class VaultListPresenter @Inject constructor( //
.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 cryptoCloud = (folder.cloud as CryptoCloud)
val vault = 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)) val cryptomatorApp = activity().application as CryptomatorApp
cryptomatorApp.startAutoUpload(cryptoCloud)
} }
} }
}) })

View File

@ -17,6 +17,7 @@ import org.cryptomator.presentation.ui.activity.VaultListActivity
import org.cryptomator.presentation.util.ResourceHelper.Companion.getColor import org.cryptomator.presentation.util.ResourceHelper.Companion.getColor
import org.cryptomator.presentation.util.ResourceHelper.Companion.getString import org.cryptomator.presentation.util.ResourceHelper.Companion.getString
import java.lang.String.format import java.lang.String.format
import timber.log.Timber
class AutoUploadNotification(private val context: Context, private val amountOfPictures: Int) { class AutoUploadNotification(private val context: Context, private val amountOfPictures: Int) {
@ -85,18 +86,22 @@ class AutoUploadNotification(private val context: Context, private val amountOfP
} }
fun showFolderMissing() { fun showFolderMissing() {
Timber.tag("AutoUploadNotification").i("Show folder not found notification")
showErrorWithMessage(context.getString(R.string.notification_auto_upload_failed_due_to_folder_not_exists)) showErrorWithMessage(context.getString(R.string.notification_auto_upload_failed_due_to_folder_not_exists))
} }
fun showVaultLockedDuringUpload() { fun showVaultLockedDuringUpload() {
Timber.tag("AutoUploadNotification").i("Show vault locked during upload notification")
showErrorWithMessage(context.getString(R.string.notification_auto_upload_failed_due_to_vault_locked)) showErrorWithMessage(context.getString(R.string.notification_auto_upload_failed_due_to_vault_locked))
} }
fun showGeneralErrorDuringUpload() { fun showGeneralErrorDuringUpload() {
Timber.tag("AutoUploadNotification").i("Show general error during upload notficiation")
showErrorWithMessage(context.getString(R.string.notification_auto_upload_failed_general_error)) showErrorWithMessage(context.getString(R.string.notification_auto_upload_failed_general_error))
} }
fun showVaultNotFoundNotification() { fun showVaultNotFoundNotification() {
Timber.tag("AutoUploadNotification").i("Show vault not found notification")
showErrorWithMessage(context.getString(R.string.notification_auto_upload_failed_due_to_vault_not_found)) showErrorWithMessage(context.getString(R.string.notification_auto_upload_failed_due_to_vault_not_found))
} }

View File

@ -1,5 +1,8 @@
package org.cryptomator.presentation.service; package org.cryptomator.presentation.service;
import static org.cryptomator.domain.usecases.cloud.UploadFile.anUploadFile;
import static java.lang.String.format;
import android.app.Service; import android.app.Service;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@ -17,6 +20,7 @@ import org.cryptomator.domain.exception.BackendException;
import org.cryptomator.domain.exception.CancellationException; import org.cryptomator.domain.exception.CancellationException;
import org.cryptomator.domain.exception.CloudNodeAlreadyExistsException; import org.cryptomator.domain.exception.CloudNodeAlreadyExistsException;
import org.cryptomator.domain.exception.FatalBackendException; import org.cryptomator.domain.exception.FatalBackendException;
import org.cryptomator.domain.exception.FileRemovedDuringUploadException;
import org.cryptomator.domain.exception.MissingCryptorException; import org.cryptomator.domain.exception.MissingCryptorException;
import org.cryptomator.domain.exception.NoSuchCloudFileException; import org.cryptomator.domain.exception.NoSuchCloudFileException;
import org.cryptomator.domain.repository.CloudContentRepository; import org.cryptomator.domain.repository.CloudContentRepository;
@ -42,16 +46,10 @@ import java.util.Set;
import timber.log.Timber; import timber.log.Timber;
import static java.lang.String.format;
import static org.cryptomator.domain.usecases.cloud.UploadFile.anUploadFile;
public class AutoUploadService extends Service { public class AutoUploadService extends Service {
private static final String ACTION_START_AUTO_UPLOAD = "START_AUTO_UPLOAD";
private static final String ACTION_CANCEL_AUTO_UPLOAD = "CANCEL_AUTO_UPLOAD"; private static final String ACTION_CANCEL_AUTO_UPLOAD = "CANCEL_AUTO_UPLOAD";
private static final String ACTION_VAULT_NOT_FOUND = "VAULT_NOT_FOUND";
private static Cloud cloud;
private AutoUploadNotification notification; private AutoUploadNotification notification;
private CloudContentRepository cloudContentRepository; private CloudContentRepository cloudContentRepository;
private ContentResolverUtil contentResolverUtil; private ContentResolverUtil contentResolverUtil;
@ -70,25 +68,12 @@ public class AutoUploadService extends Service {
} }
}; };
public static Intent startAutoUploadIntent(Context context, Cloud myCloud) {
cloud = myCloud;
Intent startAutoUpload = new Intent(context, AutoUploadService.class);
startAutoUpload.setAction(ACTION_START_AUTO_UPLOAD);
return startAutoUpload;
}
public static Intent cancelAutoUploadIntent(Context context) { public static Intent cancelAutoUploadIntent(Context context) {
Intent cancelAutoUploadIntent = new Intent(context, AutoUploadService.class); Intent cancelAutoUploadIntent = new Intent(context, AutoUploadService.class);
cancelAutoUploadIntent.setAction(ACTION_CANCEL_AUTO_UPLOAD); cancelAutoUploadIntent.setAction(ACTION_CANCEL_AUTO_UPLOAD);
return cancelAutoUploadIntent; return cancelAutoUploadIntent;
} }
public static Intent vaultNotFoundUploadIntent(Context context) {
Intent cancelAutoUploadIntent = new Intent(context, AutoUploadService.class);
cancelAutoUploadIntent.setAction(ACTION_VAULT_NOT_FOUND);
return cancelAutoUploadIntent;
}
private void startBackgroundImageUpload(Cloud cloud) { private void startBackgroundImageUpload(Cloud cloud) {
try { try {
uploadFiles = getUploadFiles(fileUtil.getAutoUploadFilesStore()); uploadFiles = getUploadFiles(fileUtil.getAutoUploadFilesStore());
@ -182,7 +167,11 @@ public class AutoUploadService extends Service {
} catch (CloudNodeAlreadyExistsException e) { } catch (CloudNodeAlreadyExistsException e) {
Timber.tag("AutoUploadService").i("Not uploading file because it already exists in the cloud"); Timber.tag("AutoUploadService").i("Not uploading file because it already exists in the cloud");
Timber.tag("AutoUploadService").v(format("Not uploading file because it already exists in the cloud %s", file.getFileName())); Timber.tag("AutoUploadService").v(format("Not uploading file because it already exists in the cloud %s", file.getFileName()));
} catch (Exception e) { } catch (FileRemovedDuringUploadException e) {
Timber.tag("AutoUploadService").i("Not uploading file because it was removed during upload");
Timber.tag("AutoUploadService").v(format("Not uploading file because it was removed during upload %s", file.getFileName()));
}
catch (Exception e) {
cancelled = true; cancelled = true;
fileUtil.removeImagesFromAutoUploads(uploadedCloudFileNames); fileUtil.removeImagesFromAutoUploads(uploadedCloudFileNames);
throw e; throw e;
@ -211,6 +200,9 @@ public class AutoUploadService extends Service {
private CloudFile writeCloudFile(String fileName, CancelAwareDataSource dataSource, boolean replacing, ProgressAware<UploadState> progressAware) throws BackendException { private CloudFile writeCloudFile(String fileName, CancelAwareDataSource dataSource, boolean replacing, ProgressAware<UploadState> progressAware) throws BackendException {
Long size = dataSource.size(context); Long size = dataSource.size(context);
if(size == null) {
throw new FileRemovedDuringUploadException();
}
CloudFile source = cloudContentRepository.file(parent, fileName, size); CloudFile source = cloudContentRepository.file(parent, fileName, size);
return cloudContentRepository.write(source, dataSource, progressAware, replacing, size); return cloudContentRepository.write(source, dataSource, progressAware, replacing, size);
} }
@ -225,36 +217,18 @@ public class AutoUploadService extends Service {
@Override @Override
public int onStartCommand(Intent intent, int flags, int startId) { public int onStartCommand(Intent intent, int flags, int startId) {
Timber.tag("AutoUploadService").i("started"); Timber.tag("AutoUploadService").i("started");
if (isStartAutoUpload(intent)) { if (isCancelAutoUpload(intent)) {
Timber.tag("AutoUploadService").i("Received start upload");
startBackgroundImageUpload(cloud);
} else if (isCancelAutoUpload(intent)) {
Timber.tag("AutoUploadService").i("Received stop auto upload"); Timber.tag("AutoUploadService").i("Received stop auto upload");
cancelled = true; cancelled = true;
hideNotification(); hideNotification();
} else if(isVaultNotFound(intent)) {
Timber.tag("AutoUploadService").i("Received show vault not found notification");
notification.showVaultNotFoundNotification();
} }
return START_STICKY; return START_STICKY;
} }
private boolean isStartAutoUpload(Intent intent) {
return intent != null //
&& ACTION_START_AUTO_UPLOAD.equals(intent.getAction());
}
private boolean isCancelAutoUpload(Intent intent) { private boolean isCancelAutoUpload(Intent intent) {
return intent != null // return intent != null && ACTION_CANCEL_AUTO_UPLOAD.equals(intent.getAction());
&& ACTION_CANCEL_AUTO_UPLOAD.equals(intent.getAction());
}
private boolean isVaultNotFound(Intent intent) {
return intent != null //
&& ACTION_VAULT_NOT_FOUND.equals(intent.getAction());
} }
@Override @Override
@ -294,5 +268,13 @@ public class AutoUploadService extends Service {
contentResolverUtil = myContentResolverUtil; contentResolverUtil = myContentResolverUtil;
context = myContext; context = myContext;
} }
public void startUpload(Cloud cloud) {
startBackgroundImageUpload(cloud);
}
public void vaultNotFound() {
notification.showVaultNotFoundNotification();
}
} }
} }