Skip to content

Commit

Permalink
#519 save and restore state for view models
Browse files Browse the repository at this point in the history
  • Loading branch information
sds100 committed Dec 11, 2020
1 parent c877450 commit db867e4
Show file tree
Hide file tree
Showing 29 changed files with 638 additions and 584 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.github.sds100.keymapper.data.model

import android.os.Parcelable
import androidx.annotation.IntDef
import androidx.annotation.StringDef
import com.github.salomonbrys.kotson.byArray
Expand All @@ -10,7 +11,7 @@ import io.github.sds100.keymapper.R
import io.github.sds100.keymapper.util.result.ExtraNotFound
import io.github.sds100.keymapper.util.result.Result
import io.github.sds100.keymapper.util.result.Success
import java.io.Serializable
import kotlinx.android.parcel.Parcelize

/**
* Created by sds100 on 17/03/2020.
Expand Down Expand Up @@ -44,12 +45,13 @@ annotation class ConstraintMode
)
annotation class ConstraintCategory

@Parcelize
data class Constraint(@ConstraintType
@SerializedName(NAME_TYPE)
val type: String,

@SerializedName(NAME_EXTRAS)
val extras: List<Extra>) : Serializable {
val extras: List<Extra>) : Parcelable {

constructor(type: String, vararg extra: Extra) : this(type, extra.toList())

Expand Down
21 changes: 12 additions & 9 deletions app/src/main/java/io/github/sds100/keymapper/data/model/KeyMap.kt
Original file line number Diff line number Diff line change
@@ -1,54 +1,57 @@
package io.github.sds100.keymapper.data.model

import android.os.Parcelable
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.github.salomonbrys.kotson.*
import com.google.gson.annotations.SerializedName
import io.github.sds100.keymapper.data.db.dao.KeyMapDao
import kotlinx.android.parcel.Parcelize

/**
* Created by sds100 on 12/07/2018.
*/

@Parcelize
@Entity(tableName = KeyMapDao.TABLE_NAME)
data class KeyMap(
@SerializedName(NAME_ID)
@PrimaryKey(autoGenerate = true)
var id: Long,
val id: Long,

@SerializedName(NAME_TRIGGER)
@ColumnInfo(name = KeyMapDao.KEY_TRIGGER)
var trigger: Trigger = Trigger(),
val trigger: Trigger = Trigger(),

@SerializedName(NAME_ACTION_LIST)
@ColumnInfo(name = KeyMapDao.KEY_ACTION_LIST)
var actionList: List<Action> = listOf(),
val actionList: List<Action> = listOf(),

@SerializedName(NAME_CONSTRAINT_LIST)
@ColumnInfo(name = KeyMapDao.KEY_CONSTRAINT_LIST)
var constraintList: List<Constraint> = listOf(),
val constraintList: List<Constraint> = listOf(),

@ConstraintMode
@SerializedName(NAME_CONSTRAINT_MODE)
@ColumnInfo(name = KeyMapDao.KEY_CONSTRAINT_MODE)
var constraintMode: Int = Constraint.DEFAULT_MODE,
val constraintMode: Int = Constraint.DEFAULT_MODE,

@SerializedName(NAME_FLAGS)
@ColumnInfo(name = KeyMapDao.KEY_FLAGS)
/**
* Flags are stored as bits.
*/
var flags: Int = 0,
val flags: Int = 0,

@SerializedName(NAME_FOLDER_NAME)
@ColumnInfo(name = KeyMapDao.KEY_FOLDER_NAME)
var folderName: String? = null,
val folderName: String? = null,

@SerializedName(NAME_IS_ENABLED)
@ColumnInfo(name = KeyMapDao.KEY_ENABLED)
var isEnabled: Boolean = true
) {
val isEnabled: Boolean = true
) : Parcelable {
companion object {

//DON'T CHANGE THESE. Used for JSON serialization and parsing.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
package io.github.sds100.keymapper.data.model.options

import io.github.sds100.keymapper.data.model.Action
import io.github.sds100.keymapper.data.model.getData
import io.github.sds100.keymapper.data.model.options.BehaviorOption.Companion.applyBehaviorOption
import io.github.sds100.keymapper.util.ActionUtils
import io.github.sds100.keymapper.util.result.valueOrNull
import splitties.bitflags.hasFlag
import java.io.Serializable
import io.github.sds100.keymapper.data.model.options.BoolOption.Companion.saveBoolOption
import io.github.sds100.keymapper.data.model.options.IntOption.Companion.saveIntOption
import io.github.sds100.keymapper.util.*
import kotlinx.android.parcel.Parcelize

/**
* Created by sds100 on 22/11/20.
*/
class ActionShortcutOptions(action: Action,
actionCount: Int) : Serializable, BaseOptions<Action> {
@Parcelize
class ActionShortcutOptions(
override val id: String,
val showVolumeUi: BoolOption,
val showPerformingActionToast: BoolOption,
val delayBeforeNextAction: IntOption,
val multiplier: IntOption
) : BaseOptions<Action> {

companion object {
const val ID_SHOW_VOLUME_UI = "show_volume_ui"
Expand All @@ -21,43 +25,34 @@ class ActionShortcutOptions(action: Action,
const val ID_DELAY_BEFORE_NEXT_ACTION = "delay_before_next_action"
}

override val id = action.uid

val showVolumeUi = BehaviorOption(
id = ID_SHOW_VOLUME_UI,
value = action.flags.hasFlag(Action.ACTION_FLAG_SHOW_VOLUME_UI),
isAllowed = ActionUtils.isVolumeAction(action.data)
)

val showPerformingActionToast = BehaviorOption(
id = ID_SHOW_PERFORMING_ACTION_TOAST,
value = action.flags.hasFlag(Action.ACTION_FLAG_SHOW_PERFORMING_ACTION_TOAST),
isAllowed = true
)

private val delayBeforeNextAction: BehaviorOption<Int>

private val multiplier = BehaviorOption(
id = ID_MULTIPLIER,
value = action.extras.getData(Action.EXTRA_MULTIPLIER).valueOrNull()?.toInt() ?: BehaviorOption.DEFAULT,
isAllowed = true
)

/*
It is very important that any new options are only allowed with a valid combination of other options. Make sure
the "isAllowed" property considers all the other options.
*/

init {
val delayBeforeNextActionValue =
action.extras.getData(Action.EXTRA_DELAY_BEFORE_NEXT_ACTION).valueOrNull()?.toInt()

delayBeforeNextAction = BehaviorOption(
constructor(action: Action,
actionCount: Int) : this(
id = action.uid,

showVolumeUi = BoolOption(
id = ID_SHOW_VOLUME_UI,
value = action.showVolumeUi,
isAllowed = ActionUtils.isVolumeAction(action.data)
),

showPerformingActionToast = BoolOption(
id = ID_SHOW_PERFORMING_ACTION_TOAST,
value = action.showPerformingActionToast,
isAllowed = true
),

multiplier = IntOption(
id = ID_MULTIPLIER,
value = action.multiplier ?: IntOption.DEFAULT,
isAllowed = true
),

delayBeforeNextAction = IntOption(
id = ID_DELAY_BEFORE_NEXT_ACTION,
value = delayBeforeNextActionValue ?: BehaviorOption.DEFAULT,
value = action.delayBeforeNextAction ?: IntOption.DEFAULT,
isAllowed = actionCount > 0
)
}
)

override val intOptions = listOf(
delayBeforeNextAction,
Expand Down Expand Up @@ -90,12 +85,12 @@ class ActionShortcutOptions(action: Action,

override fun apply(old: Action): Action {
val newFlags = old.flags
.applyBehaviorOption(showVolumeUi, Action.ACTION_FLAG_SHOW_VOLUME_UI)
.applyBehaviorOption(showPerformingActionToast, Action.ACTION_FLAG_SHOW_PERFORMING_ACTION_TOAST)
.saveBoolOption(showVolumeUi, Action.ACTION_FLAG_SHOW_VOLUME_UI)
.saveBoolOption(showPerformingActionToast, Action.ACTION_FLAG_SHOW_PERFORMING_ACTION_TOAST)

val newExtras = old.extras
.applyBehaviorOption(multiplier, Action.EXTRA_MULTIPLIER)
.applyBehaviorOption(delayBeforeNextAction, Action.EXTRA_DELAY_BEFORE_NEXT_ACTION)
.saveIntOption(multiplier, Action.EXTRA_MULTIPLIER)
.saveIntOption(delayBeforeNextAction, Action.EXTRA_DELAY_BEFORE_NEXT_ACTION)

newExtras.removeAll {
it.id in arrayOf(Action.EXTRA_CUSTOM_STOP_REPEAT_BEHAVIOUR, Action.EXTRA_CUSTOM_HOLD_DOWN_BEHAVIOUR)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
package io.github.sds100.keymapper.data.model.options

import java.io.Serializable
import android.os.Parcelable

/**
* Created by sds100 on 21/11/20.
*/
interface BaseOptions<T> : Serializable {

/**
* Make sure to add Parcelize annotation
*/
interface BaseOptions<T> : Parcelable {
val id: String

val intOptions: List<BehaviorOption<Int>>
val boolOptions: List<BehaviorOption<Boolean>>
val intOptions: List<IntOption>
val boolOptions: List<BoolOption>

fun setValue(id: String, value: Int): BaseOptions<T>
fun setValue(id: String, value: Boolean): BaseOptions<T>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,46 @@ package io.github.sds100.keymapper.data.model.options

import io.github.sds100.keymapper.data.model.FingerprintGestureMap
import io.github.sds100.keymapper.data.model.getData
import io.github.sds100.keymapper.data.model.options.BehaviorOption.Companion.applyBehaviorOption
import io.github.sds100.keymapper.data.model.options.BoolOption.Companion.saveBoolOption
import io.github.sds100.keymapper.data.model.options.IntOption.Companion.saveIntOption
import io.github.sds100.keymapper.util.result.valueOrNull
import kotlinx.android.parcel.Parcelize
import splitties.bitflags.hasFlag
import java.io.Serializable

/**
* Created by sds100 on 18/11/20.
*/

class FingerprintGestureMapOptions(val gestureId: String, fingerprintGestureMap: FingerprintGestureMap) : Serializable {
@Parcelize
class FingerprintGestureMapOptions(
override val id: String,
val vibrate: BoolOption,
val vibrateDuration: IntOption
) : BaseOptions<FingerprintGestureMap> {
companion object {
const val ID_VIBRATE = "vibrate"
const val ID_VIBRATION_DURATION = "vibration_duration"
}

val vibrate = BehaviorOption(
id = ID_VIBRATE,
value = fingerprintGestureMap.flags.hasFlag(FingerprintGestureMap.FLAG_VIBRATE),
isAllowed = true
)

val vibrateDuration: BehaviorOption<Int>
constructor(gestureId: String, fingerprintGestureMap: FingerprintGestureMap) : this(
id = gestureId,

init {
val vibrateDurationValue =
fingerprintGestureMap.extras.getData(FingerprintGestureMap.EXTRA_VIBRATION_DURATION).valueOrNull()?.toInt()
vibrate = BoolOption(
id = ID_VIBRATE,
value = fingerprintGestureMap.flags.hasFlag(FingerprintGestureMap.FLAG_VIBRATE),
isAllowed = true
),

vibrateDuration = BehaviorOption(
vibrateDuration = IntOption(
id = ID_VIBRATION_DURATION,
value = vibrateDurationValue ?: BehaviorOption.DEFAULT,
isAllowed = vibrate.value
value = fingerprintGestureMap.extras
.getData(FingerprintGestureMap.EXTRA_VIBRATION_DURATION).valueOrNull()?.toInt()
?: IntOption.DEFAULT,
isAllowed = fingerprintGestureMap.flags.hasFlag(FingerprintGestureMap.FLAG_VIBRATE)
)
)

}

fun setValue(id: String, value: Boolean): FingerprintGestureMapOptions {
override fun setValue(id: String, value: Boolean): FingerprintGestureMapOptions {
when (id) {
ID_VIBRATE -> {
vibrate.value = value
Expand All @@ -48,21 +52,27 @@ class FingerprintGestureMapOptions(val gestureId: String, fingerprintGestureMap:
return this
}

fun setValue(id: String, value: Int): FingerprintGestureMapOptions {
override fun setValue(id: String, value: Int): FingerprintGestureMapOptions {
when (id) {
ID_VIBRATION_DURATION -> vibrateDuration.value = value
}

return this
}

fun applyToFingerprintGestureMap(fingerprintGestureMap: FingerprintGestureMap): FingerprintGestureMap {
val newFlags = fingerprintGestureMap.flags
.applyBehaviorOption(vibrate, FingerprintGestureMap.FLAG_VIBRATE)
override val intOptions: List<IntOption>
get() = listOf(vibrateDuration)

override val boolOptions: List<BoolOption>
get() = listOf(vibrate)

override fun apply(old: FingerprintGestureMap): FingerprintGestureMap {
val newFlags = old.flags
.saveBoolOption(vibrate, FingerprintGestureMap.FLAG_VIBRATE)

val newExtras = fingerprintGestureMap.extras
.applyBehaviorOption(vibrateDuration, FingerprintGestureMap.EXTRA_VIBRATION_DURATION)
val newExtras = old.extras
.saveIntOption(vibrateDuration, FingerprintGestureMap.EXTRA_VIBRATION_DURATION)

return fingerprintGestureMap.copy(flags = newFlags, extras = newExtras)
return old.copy(flags = newFlags, extras = newExtras)
}
}
Loading

0 comments on commit db867e4

Please sign in to comment.