Skip to content

Commit

Permalink
Merge pull request #717 from grote/ask-if-restore
Browse files Browse the repository at this point in the history
Ask on first run if user wants restore
  • Loading branch information
grote authored Aug 21, 2024
2 parents cff5d20 + 7f934c8 commit 9923286
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 28 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* SPDX-FileCopyrightText: 2024 The Calyx Institute
* SPDX-License-Identifier: Apache-2.0
*/

package com.stevesoltys.seedvault.settings

import android.app.Dialog
import android.content.DialogInterface
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.DialogFragment
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.stevesoltys.seedvault.R
import com.stevesoltys.seedvault.restore.RestoreActivity

class FirstRunFragment : DialogFragment() {

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return MaterialAlertDialogBuilder(requireContext())
.setMessage(R.string.first_start_text)
.setPositiveButton(R.string.setup_button) { dialog, _ ->
parentFragmentManager.beginTransaction()
.replace(R.id.fragment, SettingsFragment(), null)
.commit()
dialog.dismiss()
}
.setNeutralButton(R.string.restore_backup_button) { dialog, _ ->
val i = Intent(requireContext(), RestoreActivity::class.java)
startActivity(i)
dialog.dismiss()
requireActivity().finish()
}
.create()
}

override fun onCancel(dialog: DialogInterface) {
requireActivity().finish()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,14 @@
package com.stevesoltys.seedvault.settings

import android.os.Bundle
import androidx.annotation.CallSuper
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceFragmentCompat.OnPreferenceStartFragmentCallback
import com.stevesoltys.seedvault.R
import com.stevesoltys.seedvault.ui.RequireProvisioningActivity
import com.stevesoltys.seedvault.ui.RequireProvisioningViewModel
import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager
import com.stevesoltys.seedvault.ui.recoverycode.ARG_FOR_NEW_CODE
import com.stevesoltys.seedvault.ui.storage.StorageCheckFragment
import org.koin.android.ext.android.inject
import org.koin.androidx.viewmodel.ext.android.viewModel

internal const val ACTION_APP_STATUS_LIST = "com.stevesoltys.seedvault.APP_STATUS_LIST"
Expand All @@ -25,7 +22,6 @@ private const val PREF_BACKUP_RECOVERY_CODE = "backup_recovery_code"
class SettingsActivity : RequireProvisioningActivity(), OnPreferenceStartFragmentCallback {

private val viewModel: SettingsViewModel by viewModel()
private val notificationManager: BackupNotificationManager by inject()

override fun getViewModel(): RequireProvisioningViewModel = viewModel

Expand All @@ -37,8 +33,13 @@ class SettingsActivity : RequireProvisioningActivity(), OnPreferenceStartFragmen
setSupportActionBar(requireViewById(R.id.toolbar))
supportActionBar!!.setDisplayHomeAsUpEnabled(true)

// always start with settings fragment as a base (when fresh start)
if (savedInstanceState == null) showFragment(SettingsFragment())
if (savedInstanceState == null && viewModel.isFirstStart) {
// let user choose whether to restore on first start
FirstRunFragment().show(supportFragmentManager, null)
} else if (savedInstanceState == null) {
// always start with settings fragment as a base (when fresh start)
showFragment(SettingsFragment())
}
// add app status fragment on the stack, if started via intent
if (intent?.action == ACTION_APP_STATUS_LIST) {
showFragment(AppStatusFragment(), true)
Expand All @@ -58,24 +59,6 @@ class SettingsActivity : RequireProvisioningActivity(), OnPreferenceStartFragmen
}
}

@CallSuper
override fun onResume() {
super.onResume()
// Activity results from the parent will get delivered before and might tell us to finish.
// Don't start any new activities when that happens.
// Note: onStart() can get called *before* results get delivered, so we use onResume() here
if (isFinishing) return

// check that backup is provisioned
if (!viewModel.recoveryCodeIsSet()) {
showRecoveryCodeActivity()
} else if (!viewModel.validLocationIsSet()) {
showStorageActivity()
// remove potential error notifications
notificationManager.onBackupErrorSeen()
}
}

override fun onPreferenceStartFragment(
caller: PreferenceFragmentCompat,
pref: Preference,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import com.stevesoltys.seedvault.permitDiskReads
import com.stevesoltys.seedvault.plugins.StoragePluginManager
import com.stevesoltys.seedvault.plugins.StorageProperties
import com.stevesoltys.seedvault.restore.RestoreActivity
import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager
import com.stevesoltys.seedvault.ui.toRelativeTime
import org.koin.android.ext.android.inject
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
Expand All @@ -42,6 +43,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
private val viewModel: SettingsViewModel by sharedViewModel()
private val storagePluginManager: StoragePluginManager by inject()
private val backupManager: IBackupManager by inject()
private val notificationManager: BackupNotificationManager by inject()

private lateinit var backup: TwoStatePreference
private lateinit var autoRestore: TwoStatePreference
Expand Down Expand Up @@ -184,6 +186,24 @@ class SettingsFragment : PreferenceFragmentCompat() {
setAppBackupSchedulingSummary(viewModel.appBackupWorkInfo.value)
}

override fun onResume() {
super.onResume()
// Activity results from the parent will get delivered before and might tell us to finish.
// Don't start any new activities when that happens.
// Note: onStart() can get called *before* results get delivered, so we use onResume() here
if (requireActivity().isFinishing) return

// check that backup is provisioned
val activity = requireActivity() as SettingsActivity
if (!viewModel.recoveryCodeIsSet()) {
activity.showRecoveryCodeActivity()
} else if (!viewModel.validLocationIsSet()) {
activity.showStorageActivity()
// remove potential error notifications
notificationManager.onBackupErrorSeen()
}
}

override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater)
inflater.inflate(R.menu.settings_menu, menu)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,14 @@ class SettingsManager(private val context: Context) {
.putBoolean(PREF_KEY_D2D_BACKUPS, enabled)
.apply()
}

/**
* This assumes that if there's no storage plugin set, it is the first start.
* We enforce a storage plugin and don't allow unsetting one,
* so this should be a safe assumption.
*/
val isFirstStart get() = prefs.getString(PREF_KEY_STORAGE_PLUGIN, null) == null

}

data class FlashDrive(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ internal class SettingsViewModel(
private val workManager = WorkManager.getInstance(app)

override val isRestoreOperation = false
val isFirstStart get() = settingsManager.isFirstStart

val isBackupRunning: StateFlow<Boolean>
private val mBackupPossible = MutableLiveData(false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,20 +56,20 @@ abstract class RequireProvisioningActivity : BackupActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

getViewModel().chooseBackupLocation.observeEvent(this, { show ->
getViewModel().chooseBackupLocation.observeEvent(this) { show ->
if (show) showStorageActivity()
})
}
}

protected fun showStorageActivity() {
fun showStorageActivity() {
val intent = Intent(this, StorageActivity::class.java).apply {
putExtra(INTENT_EXTRA_IS_RESTORE, getViewModel().isRestoreOperation)
putExtra(INTENT_EXTRA_IS_SETUP_WIZARD, isSetupWizard)
}
requestLocation.launch(intent)
}

protected fun showRecoveryCodeActivity() {
fun showRecoveryCodeActivity() {
val intent = Intent(this, RecoveryCodeActivity::class.java).apply {
putExtra(INTENT_EXTRA_IS_RESTORE, getViewModel().isRestoreOperation)
putExtra(INTENT_EXTRA_IS_SETUP_WIZARD, isSetupWizard)
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
<string name="data_management_label">Seedvault Backup</string>
<string name="current_destination_string">Backup status and settings</string>

<string name="first_start_text">Do you want to restore your device from an existing backup or start a new backup?</string>
<string name="restore_backup_button">Restore backup</string>
<string name="setup_button">Start new</string>

<!-- Settings -->
<string name="settings_category_apps">App backup</string>
Expand Down

0 comments on commit 9923286

Please sign in to comment.