Implement local storage migration by removing them with a hint #251
This commit is contained in:
parent
302a74a0ba
commit
810a9877ca
@ -50,7 +50,7 @@ class UpgradeDatabaseTest {
|
||||
Upgrade6To7().applyTo(db, 6)
|
||||
Upgrade7To8().applyTo(db, 7)
|
||||
Upgrade8To9(sharedPreferencesHandler).applyTo(db, 8)
|
||||
Upgrade9To10().applyTo(db, 9)
|
||||
Upgrade9To10(sharedPreferencesHandler).applyTo(db, 9)
|
||||
|
||||
CloudEntityDao(DaoConfig(db, CloudEntityDao::class.java)).loadAll()
|
||||
VaultEntityDao(DaoConfig(db, VaultEntityDao::class.java)).loadAll()
|
||||
@ -446,7 +446,7 @@ class UpgradeDatabaseTest {
|
||||
Sql.insertInto("VAULT_ENTITY") //
|
||||
.integer("_id", 26) //
|
||||
.integer("FOLDER_CLOUD_ID", 4) //
|
||||
.text("FOLDER_PATH", "path") //
|
||||
.text("FOLDER_PATH", "pathOfVault26") //
|
||||
.text("FOLDER_NAME", "name") //
|
||||
.text("CLOUD_TYPE", CloudType.LOCAL.name) //
|
||||
.text("PASSWORD", "password") //
|
||||
@ -457,18 +457,17 @@ class UpgradeDatabaseTest {
|
||||
Assert.assertThat(it.count, CoreMatchers.`is`(5))
|
||||
}
|
||||
|
||||
Upgrade9To10().applyTo(db, 9)
|
||||
Upgrade9To10(sharedPreferencesHandler).applyTo(db, 9)
|
||||
|
||||
Sql.query("VAULT_ENTITY").executeOn(db).use {
|
||||
it.moveToFirst()
|
||||
Assert.assertThat(it.getString(it.getColumnIndex("FOLDER_CLOUD_ID")), CoreMatchers.`is`("15"))
|
||||
it.moveToNext()
|
||||
Assert.assertThat(it.getString(it.getColumnIndex("FOLDER_CLOUD_ID")), CoreMatchers.nullValue())
|
||||
Assert.assertThat(it.count, CoreMatchers.`is`(1))
|
||||
}
|
||||
|
||||
Sql.query("CLOUD_ENTITY").executeOn(db).use {
|
||||
Assert.assertThat(it.count, CoreMatchers.`is`(4))
|
||||
}
|
||||
|
||||
Assert.assertThat(sharedPreferencesHandler.vaultsRemovedDuringMigration(), CoreMatchers.`is`(Pair("LOCAL", arrayListOf("pathOfVault26"))))
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,23 +1,42 @@
|
||||
package org.cryptomator.data.db
|
||||
|
||||
import org.cryptomator.domain.CloudType
|
||||
import org.cryptomator.util.SharedPreferencesHandler
|
||||
import org.greenrobot.greendao.database.Database
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
import timber.log.Timber
|
||||
|
||||
@Singleton
|
||||
internal class Upgrade9To10 @Inject constructor() : DatabaseUpgrade(9, 10) {
|
||||
internal class Upgrade9To10 @Inject constructor(private val sharedPreferencesHandler: SharedPreferencesHandler) : DatabaseUpgrade(9, 10) {
|
||||
|
||||
private val defaultLocalStorageCloudId = 4L
|
||||
|
||||
override fun internalApplyTo(db: Database, origin: Int) {
|
||||
db.beginTransaction()
|
||||
|
||||
try {
|
||||
Sql.update("VAULT_ENTITY")
|
||||
.set("FOLDER_CLOUD_ID", Sql.toString(null))
|
||||
.where("FOLDER_CLOUD_ID", Sql.eq(4))
|
||||
Sql.query("VAULT_ENTITY")
|
||||
.columns(listOf("FOLDER_PATH"))
|
||||
.where("FOLDER_CLOUD_ID", Sql.eq(defaultLocalStorageCloudId))
|
||||
.executeOn(db).use {
|
||||
val vaultsToBeRemoved = ArrayList<String>()
|
||||
while (it.moveToNext()) {
|
||||
val folderPath = it.getString(it.getColumnIndex("FOLDER_PATH"))
|
||||
vaultsToBeRemoved.add(folderPath)
|
||||
}
|
||||
if (vaultsToBeRemoved.isNotEmpty()) {
|
||||
sharedPreferencesHandler.vaultsRemovedDuringMigration(Pair(CloudType.LOCAL.name, vaultsToBeRemoved))
|
||||
Timber.tag("Upgrade9To10").i("Added %s to the removeDuringMigrations", vaultsToBeRemoved)
|
||||
}
|
||||
}
|
||||
|
||||
Sql.deleteFrom("VAULT_ENTITY")
|
||||
.where("FOLDER_CLOUD_ID", Sql.eq(defaultLocalStorageCloudId))
|
||||
.executeOn(db)
|
||||
|
||||
Sql.deleteFrom("CLOUD_ENTITY")
|
||||
.where("_id", Sql.eq(4))
|
||||
.where("_id", Sql.eq(defaultLocalStorageCloudId))
|
||||
.where("TYPE", Sql.eq("LOCAL"))
|
||||
.executeOn(db)
|
||||
|
||||
|
@ -12,6 +12,7 @@ import org.cryptomator.data.cloud.crypto.CryptoCloud
|
||||
import org.cryptomator.data.util.NetworkConnectionCheck
|
||||
import org.cryptomator.domain.Cloud
|
||||
import org.cryptomator.domain.CloudFolder
|
||||
import org.cryptomator.domain.CloudType
|
||||
import org.cryptomator.domain.Vault
|
||||
import org.cryptomator.domain.di.PerView
|
||||
import org.cryptomator.domain.exception.license.LicenseNotValidException
|
||||
@ -49,6 +50,7 @@ import org.cryptomator.presentation.ui.dialog.AskForLockScreenDialog
|
||||
import org.cryptomator.presentation.ui.dialog.EnterPasswordDialog
|
||||
import org.cryptomator.presentation.ui.dialog.UpdateAppAvailableDialog
|
||||
import org.cryptomator.presentation.ui.dialog.UpdateAppDialog
|
||||
import org.cryptomator.presentation.ui.dialog.VaultsRemovedDuringMigrationDialog
|
||||
import org.cryptomator.presentation.util.FileUtil
|
||||
import org.cryptomator.presentation.workflow.ActivityResult
|
||||
import org.cryptomator.presentation.workflow.AddExistingVaultWorkflow
|
||||
@ -103,6 +105,12 @@ class VaultListPresenter @Inject constructor( //
|
||||
sharedPreferencesHandler.setScreenLockDialogAlreadyShown()
|
||||
}
|
||||
|
||||
sharedPreferencesHandler.vaultsRemovedDuringMigration()?.let {
|
||||
val cloudNameString = getString(CloudTypeModel.valueOf(CloudType.valueOf(it.first)).displayNameResource)
|
||||
view?.showDialog(VaultsRemovedDuringMigrationDialog.newInstance(Pair(cloudNameString, it.second)))
|
||||
sharedPreferencesHandler.vaultsRemovedDuringMigration(null)
|
||||
}
|
||||
|
||||
checkLicense()
|
||||
}
|
||||
|
||||
@ -118,9 +126,10 @@ class VaultListPresenter @Inject constructor( //
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
var license: String? = ""
|
||||
if (e is LicenseNotValidException) {
|
||||
license = e.license
|
||||
val license = if (e is LicenseNotValidException) {
|
||||
e.license
|
||||
} else {
|
||||
""
|
||||
}
|
||||
val intent = Intent(context(), LicenseCheckActivity::class.java)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
|
@ -13,10 +13,10 @@ import kotlinx.android.synthetic.main.dialog_app_is_obscured_info.tv_app_is_obsc
|
||||
class AppIsObscuredInfoDialog : BaseDialog<Activity>() {
|
||||
|
||||
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||
builder //
|
||||
return builder //
|
||||
.setTitle(R.string.dialog_app_is_obscured_info_title) //
|
||||
.setNeutralButton(R.string.dialog_app_is_obscured_info_neutral_button) { dialog: DialogInterface, _: Int -> dialog.dismiss() }
|
||||
return builder.create()
|
||||
.setNeutralButton(R.string.dialog_app_is_obscured_info_neutral_button) { dialog: DialogInterface, _: Int -> dialog.dismiss() } //
|
||||
.create()
|
||||
}
|
||||
|
||||
override fun disableDialogWhenObscured(): Boolean {
|
||||
|
@ -0,0 +1,47 @@
|
||||
package org.cryptomator.presentation.ui.dialog
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.DialogInterface
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import org.cryptomator.generator.Dialog
|
||||
import org.cryptomator.presentation.R
|
||||
import kotlinx.android.synthetic.main.dialog_vaults_removed_during_migration.tv_message
|
||||
|
||||
@Dialog(R.layout.dialog_vaults_removed_during_migration)
|
||||
class VaultsRemovedDuringMigrationDialog : BaseDialog<Activity>() {
|
||||
|
||||
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
|
||||
val vaultsRemovedDuringMigration = requireArguments().getSerializable(VAULTS_REMOVED_ARG) as Pair<String, ArrayList<String>>
|
||||
|
||||
return builder //
|
||||
.setTitle(String.format(getString(R.string.dialog_vaults_removed_during_migration_title), vaultsRemovedDuringMigration.first)) //
|
||||
.setNeutralButton(R.string.dialog_vaults_removed_during_migration_neutral_button) { dialog: DialogInterface, _: Int -> dialog.dismiss() }
|
||||
.create()
|
||||
}
|
||||
|
||||
public override fun setupView() {
|
||||
val vaultsRemovedDuringMigration = requireArguments().getSerializable(VAULTS_REMOVED_ARG) as Pair<String, ArrayList<String>>
|
||||
|
||||
val vaultsRemovedDuringMigrationString = vaultsRemovedDuringMigration
|
||||
.second
|
||||
.map { path -> "* $path" }
|
||||
.reduce { acc, s -> "$acc\n$s" }
|
||||
|
||||
tv_message.text = String.format(getString(R.string.dialog_vaults_removed_during_migration_hint), vaultsRemovedDuringMigrationString)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private const val VAULTS_REMOVED_ARG = "vaultsRemovedArg"
|
||||
|
||||
fun newInstance(vaultsRemovedDuringMigration: Pair<String, List<String>>): DialogFragment {
|
||||
val args = Bundle()
|
||||
args.putSerializable(VAULTS_REMOVED_ARG, vaultsRemovedDuringMigration)
|
||||
val fragment = VaultsRemovedDuringMigrationDialog()
|
||||
fragment.arguments = args
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="@dimen/activity_vertical_margin">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_message"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:text="@string/dialog_vaults_removed_during_migration_hint" />
|
||||
|
||||
</RelativeLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
@ -166,7 +166,6 @@
|
||||
<string name="screen_cloud_settings_option_delete" translatable="false">@string/screen_vault_list_vault_action_delete</string>
|
||||
<string name="screen_cloud_connections_no_connections">Click here to add locations</string>
|
||||
<string name="screen_cloud_error_webdav_not_supported">Server doesn\'t seem to be WebDAV compatible</string>
|
||||
<string name="screen_cloud_local_custom_storage_title">Custom locations</string>
|
||||
<string name="screen_cloud_local_error_no_content_provider">No additional locations available.</string>
|
||||
|
||||
<!-- ## screen: webdav settings -->
|
||||
@ -416,6 +415,12 @@
|
||||
<string name="dialog_app_is_obscured_info_hint">Another app is displaying something on top of Cryptomator (e.g., a blue light filter or night mode app). For security reasons, Cryptomator is disabled.\n\n<a href="https://docs.cryptomator.org/en/1.5/android/settings/#block-app-when-obscured">How to enable Cryptomator</a></string>
|
||||
<string name="dialog_app_is_obscured_info_neutral_button">Close</string>
|
||||
|
||||
|
||||
<string name="dialog_vaults_removed_during_migration_title">Please re-add vaults for %1s cloud</string>
|
||||
<string name="dialog_vaults_removed_during_migration_hint">While migrating to this app version we need to remove the following vaults from the app:\n%2s \n\nThose vaults aren\'t removed from the cloud but only from this app. Sorry for the inconvenience and please re-add these vaults to continue working with them.</string>
|
||||
<string name="dialog_vaults_removed_during_migration_neutral_button" translatable="false">@string/dialog_unable_to_share_positive_button</string>
|
||||
|
||||
|
||||
<string name="dialog_disable_secure_screen_disclaimer_hint">This setting is a security feature and prevents other apps from tricking users into doing things they do not wan\'t to do.\n\nBy disabling, you confirm that you are <a href="https://docs.cryptomator.org/en/1.5/android/settings/#screen-security">aware of the risks</a>.</string>
|
||||
|
||||
<string name="dialog_delete_cloud_connection_with_vaults_message">Are you sure you want to remove this cloud connection?</string>
|
||||
|
@ -236,6 +236,31 @@ constructor(context: Context) : SharedPreferences.OnSharedPreferenceChangeListen
|
||||
return defaultSharedPreferences.getBoolean(BACKGROUND_UNLOCK_PREPARATION, true)
|
||||
}
|
||||
|
||||
fun vaultsRemovedDuringMigration(vaultsToBeRemoved: Pair<String, List<String>>?) {
|
||||
vaultsToBeRemoved?.let {
|
||||
val vaultsToBeRemovedString = if (it.second.isNotEmpty()) {
|
||||
it.second.reduce { acc, s -> "$acc,$s" }
|
||||
} else {
|
||||
""
|
||||
}
|
||||
defaultSharedPreferences.setValue(VAULTS_REMOVED_DURING_MIGRATION_TYPE, it.first)
|
||||
defaultSharedPreferences.setValue(VAULTS_REMOVED_DURING_MIGRATION, vaultsToBeRemovedString)
|
||||
} ?: run {
|
||||
defaultSharedPreferences.setValue(VAULTS_REMOVED_DURING_MIGRATION_TYPE, null)
|
||||
defaultSharedPreferences.setValue(VAULTS_REMOVED_DURING_MIGRATION, null)
|
||||
}
|
||||
}
|
||||
|
||||
fun vaultsRemovedDuringMigration(): Pair<String, List<String>>? {
|
||||
val vaultsRemovedDuringMigrationType = defaultSharedPreferences.getString(VAULTS_REMOVED_DURING_MIGRATION_TYPE, null)
|
||||
val vaultsRemovedDuringMigration = defaultSharedPreferences.getString(VAULTS_REMOVED_DURING_MIGRATION, null)
|
||||
return if(vaultsRemovedDuringMigrationType != null && vaultsRemovedDuringMigration != null) {
|
||||
Pair(vaultsRemovedDuringMigrationType, ArrayList(vaultsRemovedDuringMigration.split(',')))
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private const val SCREEN_LOCK_DIALOG_SHOWN = "askForScreenLockDialogShown"
|
||||
@ -248,6 +273,8 @@ constructor(context: Context) : SharedPreferences.OnSharedPreferenceChangeListen
|
||||
private const val GLOB_SEARCH = "globSearch"
|
||||
private const val KEEP_UNLOCKED_WHILE_EDITING = "keepUnlockedWhileEditing"
|
||||
private const val BACKGROUND_UNLOCK_PREPARATION = "backgroundUnlockPreparation"
|
||||
private const val VAULTS_REMOVED_DURING_MIGRATION = "vaultsRemovedDuringMigration"
|
||||
private const val VAULTS_REMOVED_DURING_MIGRATION_TYPE = "vaultsRemovedDuringMigrationType"
|
||||
const val DEBUG_MODE = "debugMode"
|
||||
const val DISABLE_APP_WHEN_OBSCURED = "disableAppWhenObscured"
|
||||
const val SECURE_SCREEN = "secureScreen"
|
||||
|
Loading…
x
Reference in New Issue
Block a user