mirror of
https://github.com/yogeshpaliyal/KeyPass.git
synced 2026-01-12 17:30:33 -06:00
feat: batch actions (#1062)
This commit is contained in:
committed by
GitHub
parent
7831511ed6
commit
35cae1f1b0
@@ -20,6 +20,7 @@ import com.yogeshpaliyal.common.dbhelper.restoreBackup
|
|||||||
import com.yogeshpaliyal.common.utils.BACKUP_KEY_LENGTH
|
import com.yogeshpaliyal.common.utils.BACKUP_KEY_LENGTH
|
||||||
import com.yogeshpaliyal.keypass.R
|
import com.yogeshpaliyal.keypass.R
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.Action
|
import com.yogeshpaliyal.keypass.ui.redux.actions.Action
|
||||||
|
import com.yogeshpaliyal.keypass.ui.redux.actions.BatchActions
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.RestoreAccountsAction
|
import com.yogeshpaliyal.keypass.ui.redux.actions.RestoreAccountsAction
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.ToastAction
|
import com.yogeshpaliyal.keypass.ui.redux.actions.ToastAction
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.UpdateDialogAction
|
import com.yogeshpaliyal.keypass.ui.redux.actions.UpdateDialogAction
|
||||||
@@ -68,9 +69,13 @@ fun RestoreKeyPassBackupDialog(
|
|||||||
restoreBackup(keyphrase, context.contentResolver, selectedFile)
|
restoreBackup(keyphrase, context.contentResolver, selectedFile)
|
||||||
|
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
dispatchAction(RestoreAccountsAction(result))
|
dispatchAction(
|
||||||
dispatchAction(UpdateDialogAction(null))
|
BatchActions(
|
||||||
dispatchAction(ToastAction(R.string.backup_restored))
|
RestoreAccountsAction(result),
|
||||||
|
UpdateDialogAction(null),
|
||||||
|
ToastAction(R.string.backup_restored)
|
||||||
|
)
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
dispatchAction(ToastAction(R.string.invalid_keyphrase))
|
dispatchAction(ToastAction(R.string.invalid_keyphrase))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import com.yogeshpaliyal.keypass.ui.commonComponents.DefaultBottomAppBar
|
|||||||
import com.yogeshpaliyal.keypass.ui.commonComponents.KeyPassInputField
|
import com.yogeshpaliyal.keypass.ui.commonComponents.KeyPassInputField
|
||||||
import com.yogeshpaliyal.keypass.ui.nav.LocalUserSettings
|
import com.yogeshpaliyal.keypass.ui.nav.LocalUserSettings
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.Action
|
import com.yogeshpaliyal.keypass.ui.redux.actions.Action
|
||||||
|
import com.yogeshpaliyal.keypass.ui.redux.actions.BatchActions
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.GoBackAction
|
import com.yogeshpaliyal.keypass.ui.redux.actions.GoBackAction
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.ToastAction
|
import com.yogeshpaliyal.keypass.ui.redux.actions.ToastAction
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -54,8 +55,7 @@ fun PasswordHintScreen() {
|
|||||||
Button(modifier = Modifier.fillMaxWidth(1f), onClick = {
|
Button(modifier = Modifier.fillMaxWidth(1f), onClick = {
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
context.setPasswordHint(passwordHint)
|
context.setPasswordHint(passwordHint)
|
||||||
dispatchAction(ToastAction(R.string.hint_change_success))
|
dispatchAction(BatchActions(GoBackAction, ToastAction(R.string.hint_change_success)))
|
||||||
dispatchAction(GoBackAction)
|
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
Text(text = stringResource(id = R.string.change_app_hint))
|
Text(text = stringResource(id = R.string.change_app_hint))
|
||||||
@@ -64,8 +64,7 @@ fun PasswordHintScreen() {
|
|||||||
OutlinedButton(modifier = Modifier.fillMaxWidth(1f), onClick = {
|
OutlinedButton(modifier = Modifier.fillMaxWidth(1f), onClick = {
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
context.setPasswordHint(null)
|
context.setPasswordHint(null)
|
||||||
dispatchAction(ToastAction(R.string.hint_removed_success))
|
dispatchAction(BatchActions(GoBackAction, ToastAction(R.string.hint_removed_success)))
|
||||||
dispatchAction(GoBackAction)
|
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
Text(text = stringResource(id = R.string.remove_app_hint))
|
Text(text = stringResource(id = R.string.remove_app_hint))
|
||||||
|
|||||||
@@ -1,22 +1,16 @@
|
|||||||
package com.yogeshpaliyal.keypass.ui.redux
|
package com.yogeshpaliyal.keypass.ui.redux
|
||||||
|
|
||||||
import android.content.ClipData
|
import com.yogeshpaliyal.keypass.ui.redux.actions.BatchActions
|
||||||
import android.content.ClipboardManager
|
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.core.content.ContextCompat
|
|
||||||
import com.yogeshpaliyal.keypass.R
|
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.BottomSheetAction
|
import com.yogeshpaliyal.keypass.ui.redux.actions.BottomSheetAction
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.CopyToClipboard
|
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.GoBackAction
|
import com.yogeshpaliyal.keypass.ui.redux.actions.GoBackAction
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.NavigationAction
|
import com.yogeshpaliyal.keypass.ui.redux.actions.NavigationAction
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.RestoreAccountsAction
|
import com.yogeshpaliyal.keypass.ui.redux.actions.RestoreAccountsAction
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.StateUpdateAction
|
import com.yogeshpaliyal.keypass.ui.redux.actions.StateUpdateAction
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.ToastAction
|
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.ToastActionStr
|
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.UpdateContextAction
|
import com.yogeshpaliyal.keypass.ui.redux.actions.UpdateContextAction
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.UpdateDialogAction
|
import com.yogeshpaliyal.keypass.ui.redux.actions.UpdateDialogAction
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.UpdateViewModalAction
|
import com.yogeshpaliyal.keypass.ui.redux.actions.UpdateViewModalAction
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.middlewares.intentNavigationMiddleware
|
import com.yogeshpaliyal.keypass.ui.redux.middlewares.intentNavigationMiddleware
|
||||||
|
import com.yogeshpaliyal.keypass.ui.redux.middlewares.utilityMiddleware
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.states.BottomSheetState
|
import com.yogeshpaliyal.keypass.ui.redux.states.BottomSheetState
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.states.KeyPassState
|
import com.yogeshpaliyal.keypass.ui.redux.states.KeyPassState
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.states.ScreenState
|
import com.yogeshpaliyal.keypass.ui.redux.states.ScreenState
|
||||||
@@ -32,7 +26,17 @@ object KeyPassRedux {
|
|||||||
fun getLastScreen() = arrPages.lastOrNull()
|
fun getLastScreen() = arrPages.lastOrNull()
|
||||||
|
|
||||||
private val reducer: Reducer<KeyPassState> = { state, action ->
|
private val reducer: Reducer<KeyPassState> = { state, action ->
|
||||||
when (action) {
|
if (action is BatchActions) {
|
||||||
|
action.actions.fold(state) { acc, act ->
|
||||||
|
handleAction(act, acc)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
handleAction(action, state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleAction(action: Any, state: KeyPassState): KeyPassState {
|
||||||
|
return when (action) {
|
||||||
is NavigationAction -> {
|
is NavigationAction -> {
|
||||||
if (action.clearBackStack) {
|
if (action.clearBackStack) {
|
||||||
arrPages.clear()
|
arrPages.clear()
|
||||||
@@ -49,43 +53,10 @@ object KeyPassRedux {
|
|||||||
state.copy(currentScreen = action.state)
|
state.copy(currentScreen = action.state)
|
||||||
}
|
}
|
||||||
|
|
||||||
is CopyToClipboard -> {
|
|
||||||
state.context?.let {
|
|
||||||
val clipboard = ContextCompat.getSystemService(
|
|
||||||
it,
|
|
||||||
ClipboardManager::class.java
|
|
||||||
)
|
|
||||||
val clip = ClipData.newPlainText("KeyPass", action.password)
|
|
||||||
clipboard?.setPrimaryClip(clip)
|
|
||||||
|
|
||||||
Toast.makeText(
|
|
||||||
it,
|
|
||||||
R.string.copied_to_clipboard,
|
|
||||||
Toast.LENGTH_SHORT
|
|
||||||
)
|
|
||||||
.show()
|
|
||||||
}
|
|
||||||
state
|
|
||||||
}
|
|
||||||
|
|
||||||
is UpdateContextAction -> {
|
is UpdateContextAction -> {
|
||||||
state.copy(context = action.context)
|
state.copy(context = action.context)
|
||||||
}
|
}
|
||||||
|
|
||||||
is ToastAction -> {
|
|
||||||
state.context?.let {
|
|
||||||
Toast.makeText(it, action.text, Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
state
|
|
||||||
}
|
|
||||||
|
|
||||||
is ToastActionStr -> {
|
|
||||||
state.context?.let {
|
|
||||||
Toast.makeText(it, action.text, Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
state
|
|
||||||
}
|
|
||||||
|
|
||||||
is GoBackAction -> {
|
is GoBackAction -> {
|
||||||
val lastItem = arrPages.removeLastOrNull()
|
val lastItem = arrPages.removeLastOrNull()
|
||||||
if (lastItem != null) {
|
if (lastItem != null) {
|
||||||
@@ -104,6 +75,7 @@ object KeyPassRedux {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
is UpdateDialogAction -> {
|
is UpdateDialogAction -> {
|
||||||
state.copy(dialog = action.dialogState)
|
state.copy(dialog = action.dialogState)
|
||||||
}
|
}
|
||||||
@@ -125,6 +97,6 @@ object KeyPassRedux {
|
|||||||
createStore(
|
createStore(
|
||||||
reducer,
|
reducer,
|
||||||
generateDefaultState(),
|
generateDefaultState(),
|
||||||
applyMiddleware(intentNavigationMiddleware)
|
applyMiddleware(utilityMiddleware, intentNavigationMiddleware)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,12 +8,45 @@ import com.yogeshpaliyal.keypass.ui.redux.states.ScreenState
|
|||||||
|
|
||||||
sealed interface Action
|
sealed interface Action
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Batch Multiples Actions to send to ingest in one go
|
||||||
|
*/
|
||||||
|
class BatchActions(vararg val actions: Action) : Action
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to update context value in redux store
|
||||||
|
*/
|
||||||
class UpdateContextAction(val context: Context?) : Action
|
class UpdateContextAction(val context: Context?) : Action
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to update ViewModal in redux store
|
||||||
|
*/
|
||||||
class UpdateViewModalAction(val viewModal: DashboardViewModel?) : Action
|
class UpdateViewModalAction(val viewModal: DashboardViewModel?) : Action
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to navigate from 1 state to another
|
||||||
|
* @param state: ScreenState New State where to navigate
|
||||||
|
* @param clearBackStack: Boolean Clear BackStack or not
|
||||||
|
*/
|
||||||
data class NavigationAction(val state: ScreenState, val clearBackStack: Boolean = false) : Action
|
data class NavigationAction(val state: ScreenState, val clearBackStack: Boolean = false) : Action
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to send Accounts list which we want to restore
|
||||||
|
*/
|
||||||
data class RestoreAccountsAction(val accounts: List<AccountModel>) : Action
|
data class RestoreAccountsAction(val accounts: List<AccountModel>) : Action
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to update Screen State in redux store
|
||||||
|
*/
|
||||||
data class StateUpdateAction(val state: ScreenState) : Action
|
data class StateUpdateAction(val state: ScreenState) : Action
|
||||||
|
|
||||||
|
/**
|
||||||
|
* used to update dialog state of the app
|
||||||
|
* @param dialogState: DialogState? New Dialog State or send null to dismiss the dialog
|
||||||
|
*/
|
||||||
data class UpdateDialogAction(val dialogState: DialogState? = null) : Action
|
data class UpdateDialogAction(val dialogState: DialogState? = null) : Action
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to go back to previous screen
|
||||||
|
*/
|
||||||
|
object GoBackAction : Action
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ package com.yogeshpaliyal.keypass.ui.redux.actions
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.BottomSheetRoutes
|
import com.yogeshpaliyal.keypass.ui.redux.BottomSheetRoutes
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bottom Sheet action to open bottom sheet for different routes
|
||||||
|
*/
|
||||||
sealed class BottomSheetAction(
|
sealed class BottomSheetAction(
|
||||||
val route: String,
|
val route: String,
|
||||||
val globalIsBottomSheetOpen: Boolean,
|
val globalIsBottomSheetOpen: Boolean,
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
package com.yogeshpaliyal.keypass.ui.redux.actions
|
package com.yogeshpaliyal.keypass.ui.redux.actions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intent Navigation actions, used to navigate to different activities
|
||||||
|
* handled in {@link IntentNavigationMiddleware}
|
||||||
|
*/
|
||||||
sealed interface IntentNavigation : Action {
|
sealed interface IntentNavigation : Action {
|
||||||
object GeneratePassword : IntentNavigation
|
object GeneratePassword : IntentNavigation
|
||||||
object BackupActivity : IntentNavigation
|
|
||||||
object ShareApp : IntentNavigation
|
object ShareApp : IntentNavigation
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
package com.yogeshpaliyal.keypass.ui.redux.actions
|
package com.yogeshpaliyal.keypass.ui.redux.actions
|
||||||
|
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
|
import com.yogeshpaliyal.keypass.R
|
||||||
|
|
||||||
data class ToastAction(@StringRes val text: Int) : Action
|
interface UtilityAction : Action
|
||||||
data class ToastActionStr(val text: String) : Action
|
|
||||||
data class CopyToClipboard(val password: String) : Action
|
|
||||||
|
|
||||||
object GoBackAction : Action
|
data class ToastAction(@StringRes val text: Int) : UtilityAction
|
||||||
|
data class ToastActionStr(val text: String) : UtilityAction
|
||||||
|
data class CopyToClipboard(val password: String, @StringRes val successMessage: Int = R.string.copied_to_clipboard) : UtilityAction
|
||||||
|
|||||||
@@ -4,23 +4,35 @@ import android.content.Intent
|
|||||||
import com.yogeshpaliyal.keypass.BuildConfig
|
import com.yogeshpaliyal.keypass.BuildConfig
|
||||||
import com.yogeshpaliyal.keypass.R
|
import com.yogeshpaliyal.keypass.R
|
||||||
import com.yogeshpaliyal.keypass.ui.generate.GeneratePasswordActivity
|
import com.yogeshpaliyal.keypass.ui.generate.GeneratePasswordActivity
|
||||||
|
import com.yogeshpaliyal.keypass.ui.redux.actions.BatchActions
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.IntentNavigation
|
import com.yogeshpaliyal.keypass.ui.redux.actions.IntentNavigation
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.states.KeyPassState
|
import com.yogeshpaliyal.keypass.ui.redux.states.KeyPassState
|
||||||
|
import org.reduxkotlin.Store
|
||||||
import org.reduxkotlin.middleware
|
import org.reduxkotlin.middleware
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Middleware to handle intent navigation
|
||||||
|
*/
|
||||||
val intentNavigationMiddleware = middleware<KeyPassState> { store, next, action ->
|
val intentNavigationMiddleware = middleware<KeyPassState> { store, next, action ->
|
||||||
val state = store.state
|
val state = store.state
|
||||||
|
if (action is BatchActions) {
|
||||||
|
action.actions.forEach {
|
||||||
|
store.handleAction(it, state)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
store.handleAction(action, state)
|
||||||
|
}
|
||||||
|
|
||||||
|
next(action)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Store<KeyPassState>.handleAction(action: Any, state: KeyPassState) {
|
||||||
when (action) {
|
when (action) {
|
||||||
is IntentNavigation.GeneratePassword -> {
|
is IntentNavigation.GeneratePassword -> {
|
||||||
val intent = Intent(state.context, GeneratePasswordActivity::class.java)
|
val intent = Intent(state.context, GeneratePasswordActivity::class.java)
|
||||||
state.context?.startActivity(intent)
|
state.context?.startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
is IntentNavigation.BackupActivity -> {
|
|
||||||
// BackupActivity.start(state.context)
|
|
||||||
}
|
|
||||||
|
|
||||||
is IntentNavigation.ShareApp -> {
|
is IntentNavigation.ShareApp -> {
|
||||||
val sendIntent = Intent()
|
val sendIntent = Intent()
|
||||||
sendIntent.action = Intent.ACTION_SEND
|
sendIntent.action = Intent.ACTION_SEND
|
||||||
@@ -37,5 +49,4 @@ val intentNavigationMiddleware = middleware<KeyPassState> { store, next, action
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
next(action)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package com.yogeshpaliyal.keypass.ui.redux.middlewares
|
||||||
|
|
||||||
|
import android.content.ClipData
|
||||||
|
import android.content.ClipboardManager
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import com.yogeshpaliyal.keypass.ui.redux.actions.BatchActions
|
||||||
|
import com.yogeshpaliyal.keypass.ui.redux.actions.CopyToClipboard
|
||||||
|
import com.yogeshpaliyal.keypass.ui.redux.actions.ToastAction
|
||||||
|
import com.yogeshpaliyal.keypass.ui.redux.actions.ToastActionStr
|
||||||
|
import com.yogeshpaliyal.keypass.ui.redux.actions.UtilityAction
|
||||||
|
import com.yogeshpaliyal.keypass.ui.redux.states.KeyPassState
|
||||||
|
import org.reduxkotlin.Store
|
||||||
|
import org.reduxkotlin.middleware
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Middle ware to handle utility functions like copy to clipboard and toast
|
||||||
|
*/
|
||||||
|
val utilityMiddleware = middleware<KeyPassState> { store, next, action ->
|
||||||
|
val state = store.state
|
||||||
|
if (action is BatchActions) {
|
||||||
|
action.actions.forEach {
|
||||||
|
store.handleAction(it, state)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
store.handleAction(action, state)
|
||||||
|
}
|
||||||
|
next(action)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Store<KeyPassState>.handleAction(action: Any, state: KeyPassState) {
|
||||||
|
if (action is UtilityAction) {
|
||||||
|
when (action) {
|
||||||
|
is ToastActionStr -> {
|
||||||
|
state.context?.let {
|
||||||
|
Toast.makeText(it, action.text, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
is ToastAction -> {
|
||||||
|
state.context?.let {
|
||||||
|
Toast.makeText(it, action.text, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
is CopyToClipboard -> {
|
||||||
|
state.context?.let {
|
||||||
|
val clipboard = ContextCompat.getSystemService(
|
||||||
|
it,
|
||||||
|
ClipboardManager::class.java
|
||||||
|
)
|
||||||
|
val clip = ClipData.newPlainText("KeyPass", action.password)
|
||||||
|
clipboard?.setPrimaryClip(clip)
|
||||||
|
dispatch(ToastAction(action.successMessage))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user