mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
fix: Dialog progress tasks
This commit is contained in:
@@ -18,11 +18,11 @@ import com.kunzisoft.keepass.activities.dialogs.DatabaseChangedDialogFragment.Co
|
||||
import com.kunzisoft.keepass.activities.stylish.StylishActivity
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.DatabaseTaskProvider.Companion.startDatabaseService
|
||||
import com.kunzisoft.keepass.database.ProgressMessage
|
||||
import com.kunzisoft.keepass.model.SnapFileDatabaseInfo
|
||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||
import com.kunzisoft.keepass.tasks.ProgressTaskDialogFragment
|
||||
import com.kunzisoft.keepass.tasks.ProgressTaskDialogFragment.Companion.PROGRESS_TASK_DIALOG_TAG
|
||||
import com.kunzisoft.keepass.tasks.ProgressTaskViewModel
|
||||
import com.kunzisoft.keepass.viewmodels.DatabaseViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -32,6 +32,7 @@ abstract class DatabaseActivity : StylishActivity(), DatabaseRetrieval {
|
||||
protected val mDatabase: ContextualDatabase?
|
||||
get() = mDatabaseViewModel.database
|
||||
|
||||
private val progressTaskViewModel: ProgressTaskViewModel by viewModels()
|
||||
private var progressTaskDialogFragment: ProgressTaskDialogFragment? = null
|
||||
private var databaseChangedDialogFragment: DatabaseChangedDialogFragment? = null
|
||||
|
||||
@@ -81,13 +82,13 @@ abstract class DatabaseActivity : StylishActivity(), DatabaseRetrieval {
|
||||
)
|
||||
}
|
||||
is DatabaseViewModel.ActionState.OnDatabaseActionStarted -> {
|
||||
showDialog(uiState.progressMessage)
|
||||
progressTaskViewModel.start(uiState.progressMessage)
|
||||
}
|
||||
is DatabaseViewModel.ActionState.OnDatabaseActionUpdated -> {
|
||||
showDialog(uiState.progressMessage)
|
||||
progressTaskViewModel.update(uiState.progressMessage)
|
||||
}
|
||||
is DatabaseViewModel.ActionState.OnDatabaseActionStopped -> {
|
||||
stopDialog()
|
||||
progressTaskViewModel.stop()
|
||||
}
|
||||
is DatabaseViewModel.ActionState.OnDatabaseActionFinished -> {
|
||||
onDatabaseActionFinished(
|
||||
@@ -95,12 +96,24 @@ abstract class DatabaseActivity : StylishActivity(), DatabaseRetrieval {
|
||||
uiState.actionTask,
|
||||
uiState.result
|
||||
)
|
||||
stopDialog()
|
||||
progressTaskViewModel.stop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
lifecycleScope.launch {
|
||||
repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
||||
progressTaskViewModel.progressTaskState.collect { state ->
|
||||
when (state) {
|
||||
ProgressTaskViewModel.ProgressTaskState.Start ->
|
||||
showDialog()
|
||||
ProgressTaskViewModel.ProgressTaskState.Stop ->
|
||||
stopDialog()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
lifecycleScope.launch {
|
||||
repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
||||
mDatabaseViewModel.databaseState.collect { database ->
|
||||
@@ -194,7 +207,7 @@ abstract class DatabaseActivity : StylishActivity(), DatabaseRetrieval {
|
||||
}
|
||||
}
|
||||
|
||||
private fun showDialog(progressMessage: ProgressMessage) {
|
||||
private fun showDialog() {
|
||||
lifecycleScope.launch {
|
||||
if (showDatabaseDialog()) {
|
||||
if (progressTaskDialogFragment == null) {
|
||||
@@ -208,12 +221,6 @@ abstract class DatabaseActivity : StylishActivity(), DatabaseRetrieval {
|
||||
PROGRESS_TASK_DIALOG_TAG
|
||||
)
|
||||
}
|
||||
progressTaskDialogFragment?.apply {
|
||||
updateTitle(progressMessage.titleId)
|
||||
updateMessage(progressMessage.messageId)
|
||||
updateWarning(progressMessage.warningId)
|
||||
setCancellable(progressMessage.cancelable)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
package com.kunzisoft.keepass.database
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
|
||||
data class ProgressMessage(
|
||||
@StringRes
|
||||
var titleId: Int,
|
||||
@StringRes
|
||||
var messageId: Int? = null,
|
||||
@StringRes
|
||||
var warningId: Int? = null,
|
||||
var title: String,
|
||||
var message: String? = null,
|
||||
var warning: String? = null,
|
||||
var cancelable: (() -> Unit)? = null
|
||||
)
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.activities.GroupActivity
|
||||
import com.kunzisoft.keepass.app.database.CipherDatabaseAction
|
||||
import com.kunzisoft.keepass.app.database.FileDatabaseHistoryAction
|
||||
import com.kunzisoft.keepass.credentialprovider.activity.HardwareKeyActivity
|
||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||
import com.kunzisoft.keepass.database.MainCredential
|
||||
import com.kunzisoft.keepass.database.ProgressMessage
|
||||
@@ -61,7 +62,6 @@ import com.kunzisoft.keepass.database.element.node.Node
|
||||
import com.kunzisoft.keepass.database.element.node.NodeId
|
||||
import com.kunzisoft.keepass.database.element.node.Type
|
||||
import com.kunzisoft.keepass.hardware.HardwareKey
|
||||
import com.kunzisoft.keepass.credentialprovider.activity.HardwareKeyActivity
|
||||
import com.kunzisoft.keepass.model.CipherEncryptDatabase
|
||||
import com.kunzisoft.keepass.model.SnapFileDatabaseInfo
|
||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||
@@ -112,7 +112,7 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
private var mTaskRemovedRequested = false
|
||||
private var mSaveState = false
|
||||
|
||||
private var mProgressMessage: ProgressMessage = ProgressMessage(R.string.database_opened)
|
||||
private lateinit var mProgressMessage: ProgressMessage
|
||||
|
||||
override fun retrieveChannelId(): String {
|
||||
return CHANNEL_DATABASE_ID
|
||||
@@ -305,6 +305,13 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
mResponseChallengeChannel = null
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
mProgressMessage = ProgressMessage(
|
||||
title = getString(R.string.database_opened)
|
||||
)
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent): IBinder? {
|
||||
super.onBind(intent)
|
||||
return mActionTaskBinder
|
||||
@@ -391,9 +398,9 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
TimeoutHelper.temporarilyDisableTimeout()
|
||||
|
||||
sendBroadcast(Intent(DATABASE_START_TASK_ACTION).apply {
|
||||
putExtra(DATABASE_TASK_TITLE_KEY, mProgressMessage.titleId)
|
||||
putExtra(DATABASE_TASK_MESSAGE_KEY, mProgressMessage.messageId)
|
||||
putExtra(DATABASE_TASK_WARNING_KEY, mProgressMessage.warningId)
|
||||
putExtra(DATABASE_TASK_TITLE_KEY, mProgressMessage.title)
|
||||
putExtra(DATABASE_TASK_MESSAGE_KEY, mProgressMessage.message)
|
||||
putExtra(DATABASE_TASK_WARNING_KEY, mProgressMessage.warning)
|
||||
})
|
||||
|
||||
mActionTaskListeners.forEach { actionTaskListener ->
|
||||
@@ -506,8 +513,8 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
R.drawable.notification_ic_database_action
|
||||
|
||||
// Title depending on action
|
||||
mProgressMessage.titleId =
|
||||
if (intentAction == null) {
|
||||
mProgressMessage.title =
|
||||
getString(if (intentAction == null) {
|
||||
R.string.database_opened
|
||||
} else when (intentAction) {
|
||||
ACTION_DATABASE_CREATE_TASK -> R.string.creating_database
|
||||
@@ -522,24 +529,22 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
else
|
||||
R.string.command_execution
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Updated later
|
||||
mProgressMessage.messageId = null
|
||||
mProgressMessage.message = null
|
||||
|
||||
// Warning if data is saved
|
||||
mProgressMessage.warningId =
|
||||
mProgressMessage.warning =
|
||||
if (mSaveState)
|
||||
R.string.do_not_kill_app
|
||||
getString(R.string.do_not_kill_app)
|
||||
else
|
||||
null
|
||||
|
||||
val notificationBuilder = buildNewNotification().apply {
|
||||
setSmallIcon(iconId)
|
||||
intent?.let {
|
||||
setContentTitle(getString(
|
||||
intent.getIntExtra(DATABASE_TASK_TITLE_KEY, mProgressMessage.titleId))
|
||||
)
|
||||
setContentTitle(intent.getStringExtra(DATABASE_TASK_TITLE_KEY))
|
||||
}
|
||||
setAutoCancel(false)
|
||||
setContentIntent(null)
|
||||
@@ -661,8 +666,8 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateMessage(resId: Int) {
|
||||
mProgressMessage.messageId = resId
|
||||
private fun updateMessage(@StringRes resId: Int) {
|
||||
mProgressMessage.message = getString(resId)
|
||||
notifyProgressMessage()
|
||||
}
|
||||
|
||||
@@ -708,7 +713,7 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
initializeChallengeResponse()
|
||||
val previousMessage = mProgressMessage.copy()
|
||||
mProgressMessage.apply {
|
||||
messageId = R.string.waiting_challenge_request
|
||||
message = getString(R.string.waiting_challenge_request)
|
||||
cancelable = {
|
||||
cancelChallengeResponse(R.string.error_cancel_by_user)
|
||||
}
|
||||
@@ -723,7 +728,7 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
||||
)
|
||||
// Wait the response
|
||||
mProgressMessage.apply {
|
||||
messageId = R.string.waiting_challenge_response
|
||||
message = getString(R.string.waiting_challenge_response)
|
||||
}
|
||||
notifyProgressMessage()
|
||||
response = mResponseChallengeChannel?.receive() ?: byteArrayOf()
|
||||
|
||||
@@ -27,32 +27,27 @@ import android.view.View
|
||||
import android.widget.Button
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import com.kunzisoft.keepass.R
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
open class ProgressTaskDialogFragment : DialogFragment() {
|
||||
|
||||
@StringRes
|
||||
private var title = UNDEFINED
|
||||
@StringRes
|
||||
private var message = UNDEFINED
|
||||
@StringRes
|
||||
private var warning = UNDEFINED
|
||||
private var cancellable: (() -> Unit)? = null
|
||||
|
||||
private var titleView: TextView? = null
|
||||
private var messageView: TextView? = null
|
||||
private var warningView: TextView? = null
|
||||
private var cancelButton: Button? = null
|
||||
private var progressView: ProgressBar? = null
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
private val progressTaskViewModel: ProgressTaskViewModel by activityViewModels()
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
try {
|
||||
activity?.let {
|
||||
val builder = AlertDialog.Builder(it)
|
||||
@@ -71,68 +66,48 @@ open class ProgressTaskDialogFragment : DialogFragment() {
|
||||
cancelButton = root.findViewById(R.id.progress_dialog_cancel)
|
||||
progressView = root.findViewById(R.id.progress_dialog_bar)
|
||||
|
||||
updateTitle(title)
|
||||
updateMessage(message)
|
||||
updateWarning(warning)
|
||||
setCancellable(cancellable)
|
||||
|
||||
isCancelable = false
|
||||
|
||||
return builder.create()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Unable to create progress dialog")
|
||||
Log.e(TAG, "Unable to create progress dialog", e)
|
||||
}
|
||||
return super.onCreateDialog(savedInstanceState)
|
||||
}
|
||||
|
||||
fun setTitle(@StringRes titleId: Int) {
|
||||
this.title = titleId
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
lifecycleScope.launch {
|
||||
repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
||||
progressTaskViewModel.progressMessageState.collect { state ->
|
||||
updateView(titleView, state.title)
|
||||
updateView(messageView, state.message)
|
||||
updateView(warningView, state.warning)
|
||||
activity?.lifecycleScope?.launch {
|
||||
cancelButton?.isVisible = state.cancelable != null
|
||||
cancelButton?.setOnClickListener {
|
||||
state.cancelable?.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateView(textView: TextView?, @StringRes resId: Int) {
|
||||
private fun updateView(textView: TextView?, value: String?) {
|
||||
activity?.lifecycleScope?.launch {
|
||||
if (resId == UNDEFINED) {
|
||||
if (value == null) {
|
||||
textView?.visibility = View.GONE
|
||||
} else {
|
||||
textView?.setText(resId)
|
||||
textView?.text = value
|
||||
textView?.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateCancelable() {
|
||||
activity?.lifecycleScope?.launch {
|
||||
cancelButton?.isVisible = cancellable != null
|
||||
cancelButton?.setOnClickListener {
|
||||
cancellable?.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun updateTitle(@StringRes resId: Int?) {
|
||||
this.title = resId ?: UNDEFINED
|
||||
updateView(titleView, title)
|
||||
}
|
||||
|
||||
fun updateMessage(@StringRes resId: Int?) {
|
||||
this.message = resId ?: UNDEFINED
|
||||
updateView(messageView, message)
|
||||
}
|
||||
|
||||
fun updateWarning(@StringRes resId: Int?) {
|
||||
this.warning = resId ?: UNDEFINED
|
||||
updateView(warningView, warning)
|
||||
}
|
||||
|
||||
fun setCancellable(cancellable: (() -> Unit)?) {
|
||||
this.cancellable = cancellable
|
||||
updateCancelable()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = ProgressTaskDialogFragment::class.java.simpleName
|
||||
const val PROGRESS_TASK_DIALOG_TAG = "progressDialogFragment"
|
||||
const val UNDEFINED = -1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.kunzisoft.keepass.tasks
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.kunzisoft.keepass.database.ProgressMessage
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
class ProgressTaskViewModel: ViewModel() {
|
||||
|
||||
private val mProgressMessageState = MutableStateFlow(ProgressMessage(""))
|
||||
val progressMessageState: StateFlow<ProgressMessage> = mProgressMessageState
|
||||
|
||||
private val mProgressTaskState = MutableStateFlow<ProgressTaskState>(ProgressTaskState.Stop)
|
||||
val progressTaskState: StateFlow<ProgressTaskState> = mProgressTaskState
|
||||
|
||||
fun update(value: ProgressMessage) {
|
||||
mProgressMessageState.value = value
|
||||
}
|
||||
|
||||
fun start(value: ProgressMessage) {
|
||||
mProgressTaskState.value = ProgressTaskState.Start
|
||||
update(value)
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
mProgressTaskState.value = ProgressTaskState.Stop
|
||||
}
|
||||
|
||||
sealed class ProgressTaskState {
|
||||
object Start: ProgressTaskState()
|
||||
object Stop: ProgressTaskState()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user