Remove unused actions and action helper functions

This commit is contained in:
Jonas Lochmann 2020-09-21 02:00:00 +02:00
parent bb27a01b73
commit d0357170e2
No known key found for this signature in database
GPG key ID: 8B8C9AEE10FA5B36
6 changed files with 79 additions and 392 deletions

View file

@ -107,12 +107,9 @@ class Actions {
)
@Test
fun testActionSerializationAndDeserializationWorks() {
appLogicActions.forEach { originalAction ->
val serializedAction = SerializationUtil.serializeAction(originalAction)
val parsedAction = ActionParser.parseAppLogicAction(JSONObject(serializedAction))
assert(parsedAction == originalAction)
fun testCanSerializeAppLogicActions() {
appLogicActions.forEach {
SerializationUtil.serializeAction(it)
}
}

View file

@ -99,51 +99,6 @@ sealed class ChildAction: Action()
const val TYPE = "type"
data class AddUsedTimeAction(val categoryId: String, val dayOfEpoch: Int, val timeToAdd: Int, val extraTimeToSubtract: Int): AppLogicAction() {
init {
IdGenerator.assertIdValid(categoryId)
if (dayOfEpoch < 0) {
throw IllegalArgumentException()
}
if (timeToAdd < 0) {
throw IllegalArgumentException()
}
if (extraTimeToSubtract < 0) {
throw IllegalArgumentException()
}
}
companion object {
const val TYPE_VALUE = "ADD_USED_TIME"
private const val CATEGORY_ID = "categoryId"
private const val DAY_OF_EPOCH = "day"
private const val TIME_TO_ADD = "timeToAdd"
private const val EXTRA_TIME_TO_SUBTRACT = "extraTimeToSubtract"
fun parse(action: JSONObject) = AddUsedTimeAction(
categoryId = action.getString(CATEGORY_ID),
dayOfEpoch = action.getInt(DAY_OF_EPOCH),
timeToAdd = action.getInt(TIME_TO_ADD),
extraTimeToSubtract = action.getInt(EXTRA_TIME_TO_SUBTRACT)
)
}
override fun serialize(writer: JsonWriter) {
writer.beginObject()
writer.name(TYPE).value(TYPE_VALUE)
writer.name(CATEGORY_ID).value(this.categoryId)
writer.name(DAY_OF_EPOCH).value(dayOfEpoch)
writer.name(TIME_TO_ADD).value(this.timeToAdd)
writer.name(EXTRA_TIME_TO_SUBTRACT).value(this.extraTimeToSubtract)
writer.endObject()
}
}
data class AddUsedTimeActionVersion2(
val dayOfEpoch: Int,
val items: List<AddUsedTimeActionItem>,
@ -155,6 +110,8 @@ data class AddUsedTimeActionVersion2(
private const val ITEMS = "i"
private const val TRUSTED_TIMESTAMP = "t"
fun doesMatch(action: JSONObject) = action.getString(TYPE) == TYPE_VALUE
fun parse(action: JSONObject): AddUsedTimeActionVersion2 = AddUsedTimeActionVersion2(
dayOfEpoch = action.getInt(DAY_OF_EPOCH),
items = ParseUtils.readObjectArray(action.getJSONArray(ITEMS)).map { AddUsedTimeActionItem.parse(it) },
@ -338,13 +295,6 @@ data class InstalledApp(val packageName: String, val title: String, val isLaunch
private const val IS_LAUNCHABLE = "isLaunchable"
private const val RECOMMENDATION = "recommendation"
fun parse(item: JSONObject) = InstalledApp(
packageName = item.getString(PACKAGE_NAME),
title = item.getString(TITLE),
isLaunchable = item.getBoolean(IS_LAUNCHABLE),
recommendation = AppRecommendationJson.parse(item.getString(RECOMMENDATION))
)
fun parse(reader: JsonReader): InstalledApp {
var packageName: String? = null
var title: String? = null
@ -399,10 +349,6 @@ data class AddInstalledAppsAction(val apps: List<InstalledApp>): AppLogicAction(
companion object {
const val TYPE_VALUE = "ADD_INSTALLED_APPS"
private const val APPS = "apps"
fun parse(action: JSONObject) = AddInstalledAppsAction(
apps = ParseUtils.readObjectArray(action.getJSONArray(APPS)).map { InstalledApp.parse(it) }
)
}
init {
@ -426,10 +372,6 @@ data class RemoveInstalledAppsAction(val packageNames: List<String>): AppLogicAc
companion object {
const val TYPE_VALUE = "REMOVE_INSTALLED_APPS"
private const val PACKAGE_NAMES = "packageNames"
fun parse(action: JSONObject) = RemoveInstalledAppsAction(
packageNames = ParseUtils.readStringArray(action.getJSONArray(PACKAGE_NAMES))
)
}
init {
@ -459,12 +401,6 @@ data class AppActivityItem (
private const val CLASS_NAME = "c"
private const val TITLE = "t"
fun parse(item: JSONObject) = AppActivityItem(
packageName = item.getString(PACKAGE_NAME),
className = item.getString(CLASS_NAME),
title = item.getString(TITLE)
)
fun parse(reader: JsonReader): AppActivityItem {
var packageName: String? = null
var className: String? = null
@ -508,15 +444,6 @@ data class UpdateAppActivitiesAction(
const val TYPE_VALUE = "UPDATE_APP_ACTIVITIES"
private const val REMOVED = "removed"
private const val UPDATED_OR_ADDED = "updatedOrAdded"
fun parse(data: JSONObject) = UpdateAppActivitiesAction(
removedActivities = data.getJSONArray(REMOVED).toJsonArrayArray().map { item ->
ParseUtils.readStringPair(item)
},
updatedOrAddedActivities = data.getJSONArray(UPDATED_OR_ADDED).toJsonObjectArray().map { item ->
AppActivityItem.parse(item)
}
)
}
init {
@ -571,10 +498,6 @@ data class AddCategoryAppsAction(val categoryId: String, val packageNames: List<
private const val CATEGORY_ID = "categoryId"
private const val PACKAGE_NAMES = "packageNames"
fun parse(action: JSONObject) = AddCategoryAppsAction(
categoryId = action.getString(CATEGORY_ID),
packageNames = ParseUtils.readStringArray(action.getJSONArray(PACKAGE_NAMES))
)
}
init {
@ -601,11 +524,6 @@ data class RemoveCategoryAppsAction(val categoryId: String, val packageNames: Li
const val TYPE_VALUE = "REMOVE_CATEGORY_APPS"
private const val CATEGORY_ID = "categoryId"
private const val PACKAGE_NAMES = "packageNames"
fun parse(action: JSONObject) = RemoveCategoryAppsAction(
categoryId = action.getString(CATEGORY_ID),
packageNames = ParseUtils.readStringArray(action.getJSONArray(PACKAGE_NAMES))
)
}
init {
@ -634,12 +552,6 @@ data class CreateCategoryAction(val childId: String, val categoryId: String, val
private const val CHILD_ID = "childId"
private const val CATEGORY_ID = "categoryId"
private const val TITLE = "title"
fun parse(action: JSONObject) = CreateCategoryAction(
childId = action.getString(CHILD_ID),
categoryId = action.getString(CATEGORY_ID),
title = action.getString(TITLE)
)
}
init {
@ -662,10 +574,6 @@ data class DeleteCategoryAction(val categoryId: String): ParentAction() {
companion object {
const val TYPE_VALUE = "DELETE_CATEGORY"
private const val CATEGORY_ID = "categoryId"
fun parse(action: JSONObject) = DeleteCategoryAction(
categoryId = action.getString(CATEGORY_ID)
)
}
init {
@ -686,11 +594,6 @@ data class UpdateCategoryTitleAction(val categoryId: String, val newTitle: Strin
const val TYPE_VALUE = "UPDATE_CATEGORY_TITLE"
private const val CATEGORY_ID = "categoryId"
private const val NEW_TITLE = "newTitle"
fun parse(action: JSONObject) = UpdateCategoryTitleAction(
categoryId = action.getString(CATEGORY_ID),
newTitle = action.getString(NEW_TITLE)
)
}
init {
@ -713,12 +616,6 @@ data class SetCategoryExtraTimeAction(val categoryId: String, val newExtraTime:
private const val CATEGORY_ID = "categoryId"
private const val NEW_EXTRA_TIME = "newExtraTime"
private const val DAY = "day"
fun parse(action: JSONObject) = SetCategoryExtraTimeAction(
categoryId = action.getString(CATEGORY_ID),
newExtraTime = action.getLong(NEW_EXTRA_TIME),
extraTimeDay = if (action.has(DAY)) action.getInt(DAY) else -1
)
}
init {
@ -753,12 +650,6 @@ data class IncrementCategoryExtraTimeAction(val categoryId: String, val addedExt
private const val CATEGORY_ID = "categoryId"
private const val ADDED_EXTRA_TIME = "addedExtraTime"
private const val DAY = "day"
fun parse(action: JSONObject) = IncrementCategoryExtraTimeAction(
categoryId = action.getString(CATEGORY_ID),
addedExtraTime = action.getLong(ADDED_EXTRA_TIME),
extraTimeDay = if (action.has(DAY)) action.getInt(DAY) else -1
)
}
init {
@ -793,12 +684,6 @@ data class UpdateCategoryTemporarilyBlockedAction(val categoryId: String, val bl
private const val CATEGORY_ID = "categoryId"
private const val BLOCKED = "blocked"
private const val END_TIME = "endTime"
fun parse(action: JSONObject) = UpdateCategoryTemporarilyBlockedAction(
categoryId = action.getString(CATEGORY_ID),
blocked = action.getBoolean(BLOCKED),
endTime = if (action.has(END_TIME)) action.getLong(END_TIME) else null
)
}
init {
@ -829,12 +714,6 @@ data class UpdateCategoryTimeWarningsAction(val categoryId: String, val enable:
private const val CATEGORY_ID = "categoryId"
private const val ENABLE = "enable"
private const val FLAGS = "flags"
fun parse(action: JSONObject) = UpdateCategoryTimeWarningsAction(
categoryId = action.getString(CATEGORY_ID),
enable = action.getBoolean(ENABLE),
flags = action.getInt(FLAGS)
)
}
init {
@ -1058,32 +937,6 @@ data class UpdateDeviceStatusAction(
didReboot = false,
isQOrLaterNow = false
)
fun parse(value: JSONObject) = UpdateDeviceStatusAction(
newProtectionLevel = if (value.has(NEW_PROTECTION_LEVEL))
ProtectionLevelUtil.parse(value.getString(NEW_PROTECTION_LEVEL))
else
null,
newUsageStatsPermissionStatus = if (value.has(NEW_USAGE_STATS_PERMISSION_STATUS))
RuntimePermissionStatusUtil.parse(value.getString(NEW_USAGE_STATS_PERMISSION_STATUS))
else
null,
newNotificationAccessPermission = if (value.has(NEW_NOTIFICATION_ACCESS_PERMISSION))
NewPermissionStatusUtil.parse(value.getString(NEW_NOTIFICATION_ACCESS_PERMISSION))
else
null,
newOverlayPermission = if (value.has(NEW_OVERLAY_PERMISSION))
RuntimePermissionStatusUtil.parse(value.getString(NEW_OVERLAY_PERMISSION))
else
null,
newAccessibilityServiceEnabled = if (value.has(NEW_ACCESSIBILITY_SERVICE_ENABLED))
value.getBoolean(NEW_ACCESSIBILITY_SERVICE_ENABLED)
else
null,
newAppVersion = if (value.has(NEW_APP_VERSION)) value.getInt(NEW_APP_VERSION) else null,
didReboot = if (value.has(DID_REBOOT)) value.getBoolean(DID_REBOOT) else false,
isQOrLaterNow = if (value.has(IS_Q_OR_LATER_NOW)) value.getBoolean(IS_Q_OR_LATER_NOW) else false
)
}
init {
@ -1530,10 +1383,6 @@ data class DeleteTimeLimitRuleAction(val ruleId: String): ParentAction() {
companion object {
const val TYPE_VALUE = "DELETE_TIMELIMIT_RULE"
private const val RULE_ID = "ruleId"
fun parse(action: JSONObject) = DeleteTimeLimitRuleAction(
ruleId = action.getString(RULE_ID)
)
}
init {
@ -1559,23 +1408,6 @@ data class AddUserAction(val name: String, val userType: UserType, val password:
private const val NAME = "name"
private const val PASSWORD = "password"
private const val TIMEZONE = "timeZone"
fun parse(action: JSONObject): AddUserAction {
var password: ParentPassword? = null
val passwordObject = action.optJSONObject(PASSWORD)
if (passwordObject != null) {
password = ParentPassword.parse(passwordObject)
}
return AddUserAction(
name = action.getString(NAME),
userType = UserTypeJson.parse(action.getString(USER_TYPE)),
password = password,
userId = action.getString(USER_ID),
timeZone = action.getString(TIMEZONE)
)
}
}
init {
@ -1927,4 +1759,4 @@ data class ChildChangePasswordAction(val password: ParentPassword): ChildAction(
writer.endObject()
}
}
}

View file

@ -1,78 +0,0 @@
/*
* TimeLimit Copyright <C> 2019 - 2020 Jonas Lochmann
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package io.timelimit.android.sync.actions
import org.json.JSONObject
object ActionParser {
fun parseAppLogicAction(action: JSONObject): AppLogicAction = when(action.getString(TYPE)) {
AddUsedTimeAction.TYPE_VALUE -> AddUsedTimeAction.parse(action)
AddInstalledAppsAction.TYPE_VALUE -> AddInstalledAppsAction.parse(action)
RemoveInstalledAppsAction.TYPE_VALUE -> RemoveInstalledAppsAction.parse(action)
TriedDisablingDeviceAdminAction.TYPE_VALUE -> TriedDisablingDeviceAdminAction
SignOutAtDeviceAction.TYPE_VALUE -> SignOutAtDeviceAction
UpdateAppActivitiesAction.TYPE_VALUE -> UpdateAppActivitiesAction.parse(action)
UpdateDeviceStatusAction.TYPE_VALUE -> UpdateDeviceStatusAction.parse(action)
AddUsedTimeActionVersion2.TYPE_VALUE -> AddUsedTimeActionVersion2.parse(action)
ForceSyncAction.TYPE_VALUE -> ForceSyncAction
else -> throw IllegalStateException()
}
fun parseParentAction(action: JSONObject): ParentAction = when(action.getString(TYPE)) {
AddCategoryAppsAction.TYPE_VALUE -> AddCategoryAppsAction.parse(action)
RemoveCategoryAppsAction.TYPE_VALUE -> RemoveCategoryAppsAction.parse(action)
CreateCategoryAction.TYPE_VALUE -> CreateCategoryAction.parse(action)
DeleteCategoryAction.TYPE_VALUE -> DeleteCategoryAction.parse(action)
UpdateCategoryTitleAction.TYPE_VALUE -> UpdateCategoryTitleAction.parse(action)
SetCategoryExtraTimeAction.TYPE_VALUE -> SetCategoryExtraTimeAction.parse(action)
IncrementCategoryExtraTimeAction.TYPE_VALUE -> IncrementCategoryExtraTimeAction.parse(action)
UpdateCategoryTemporarilyBlockedAction.TYPE_VALUE -> UpdateCategoryTemporarilyBlockedAction.parse(action)
DeleteTimeLimitRuleAction.TYPE_VALUE -> DeleteTimeLimitRuleAction.parse(action)
AddUserAction.TYPE_VALUE -> AddUserAction.parse(action)
// actions without parser:
// UpdateCategoryBlockedTimesAction
// AddTimeLimitRuleAction
// UpdateTimeLimitRuleAction
// UpdateNetworkTimeVerificationAction
// SetDeviceUserAction
// SetUserDisableLimitsUntilAction
// UpdateDeviceNameAction
// RemoveUserAction
// ChangeParentPasswordAction
// IgnoreManipulationAction
// SetKeepSignedInAction
// SetCategoryForUnassignedApps
// SetParentCategory
// SetRelaxPrimaryDeviceAction
// SetUserTimezoneAction
// SetDeviceDefaultUserAction
// SetChildPasswordAction
// SetDeviceDefaultUserTimeoutAction
// SetConsiderRebootManipulationAction
// RenameChildAction
// UpdateParentNotificationFlagsAction
// UpdateCategoryBlockAllNotificationsAction
// UpdateEnableActivityLevelBlocking
// UpdateCategoryTimeWarningsAction
// UpdateCategoryBatteryLimit
// UpdateCategorySorting
// UpdateUserFlagsAction
// UpdateUserLimitLoginCategory
// AddCategoryNetworkId
// ResetCategoryNetworkIds
else -> throw IllegalStateException()
}
}

View file

@ -82,106 +82,85 @@ object ApplyActionUtil {
LocalDatabaseAppLogicActionDispatcher.dispatchAppLogicActionSync(action, ownDeviceId!!, database, manipulationLogic)
if (isSyncEnabled(database)) {
if (action is AddUsedTimeAction) {
if (action is AddUsedTimeActionVersion2) {
val previousAction = database.pendingSyncAction().getLatestUnscheduledActionSync()
if (previousAction != null && previousAction.type == PendingSyncActionType.AppLogic) {
val parsed = ActionParser.parseAppLogicAction(JSONObject(previousAction.encodedAction))
val jsonObject = JSONObject(previousAction.encodedAction)
if (parsed is AddUsedTimeAction && parsed.categoryId == action.categoryId && parsed.dayOfEpoch == action.dayOfEpoch) {
// update the previous action
database.pendingSyncAction().updateEncodedActionSync(
sequenceNumber = previousAction.sequenceNumber,
action = StringWriter().apply {
JsonWriter(this).apply {
parsed.copy(
timeToAdd = parsed.timeToAdd + action.timeToAdd,
extraTimeToSubtract = parsed.extraTimeToSubtract + action.extraTimeToSubtract
).serialize(this)
}
}.toString()
)
if (AddUsedTimeActionVersion2.doesMatch(jsonObject)) {
val parsed = AddUsedTimeActionVersion2.parse(jsonObject)
syncUtil.requestVeryUnimportantSync()
if (parsed.dayOfEpoch == action.dayOfEpoch) {
var updatedAction: AddUsedTimeActionVersion2 = parsed
var issues = false
return@runInTransaction
}
}
} else if (action is AddUsedTimeActionVersion2) {
val previousAction = database.pendingSyncAction().getLatestUnscheduledActionSync()
if (parsed.trustedTimestamp != 0L && action.trustedTimestamp != 0L) {
issues = action.items.map { it.categoryId } != parsed.items.map { it.categoryId } ||
parsed.trustedTimestamp >= action.trustedTimestamp
if (previousAction != null && previousAction.type == PendingSyncActionType.AppLogic) {
val parsed = ActionParser.parseAppLogicAction(JSONObject(previousAction.encodedAction))
updatedAction = updatedAction.copy(trustedTimestamp = action.trustedTimestamp)
if (parsed is AddUsedTimeActionVersion2 && parsed.dayOfEpoch == action.dayOfEpoch) {
var updatedAction: AddUsedTimeActionVersion2 = parsed
var issues = false
// keep timestamp of the old action
} else if (parsed.trustedTimestamp != 0L || action.trustedTimestamp != 0L) {
issues = true
}
if (parsed.trustedTimestamp != 0L && action.trustedTimestamp != 0L) {
issues = action.items.map { it.categoryId } != parsed.items.map { it.categoryId } ||
parsed.trustedTimestamp >= action.trustedTimestamp
action.items.forEach { newItem ->
if (issues) return@forEach
updatedAction = updatedAction.copy(trustedTimestamp = action.trustedTimestamp)
val oldItem = updatedAction.items.find { it.categoryId == newItem.categoryId }
// keep timestamp of the old action
} else if (parsed.trustedTimestamp != 0L || action.trustedTimestamp != 0L) {
issues = true
}
action.items.forEach { newItem ->
if (issues) return@forEach
val oldItem = updatedAction.items.find { it.categoryId == newItem.categoryId }
if (oldItem == null) {
updatedAction = updatedAction.copy(
items = updatedAction.items + listOf(newItem)
)
} else {
if (
oldItem.additionalCountingSlots != newItem.additionalCountingSlots ||
oldItem.sessionDurationLimits != newItem.sessionDurationLimits
) {
issues = true
}
if (parsed.trustedTimestamp != 0L && action.trustedTimestamp != 0L) {
val timeBeforeCurrentItem = action.trustedTimestamp - newItem.timeToAdd
val diff = Math.abs(timeBeforeCurrentItem - parsed.trustedTimestamp)
if (diff > 2 * 1000) {
if (oldItem == null) {
updatedAction = updatedAction.copy(
items = updatedAction.items + listOf(newItem)
)
} else {
if (
oldItem.additionalCountingSlots != newItem.additionalCountingSlots ||
oldItem.sessionDurationLimits != newItem.sessionDurationLimits
) {
issues = true
}
}
val mergedItem = AddUsedTimeActionItem(
timeToAdd = oldItem.timeToAdd + newItem.timeToAdd,
extraTimeToSubtract = oldItem.extraTimeToSubtract + newItem.extraTimeToSubtract,
categoryId = newItem.categoryId,
additionalCountingSlots = oldItem.additionalCountingSlots,
sessionDurationLimits = oldItem.sessionDurationLimits
)
if (parsed.trustedTimestamp != 0L && action.trustedTimestamp != 0L) {
val timeBeforeCurrentItem = action.trustedTimestamp - newItem.timeToAdd
val diff = Math.abs(timeBeforeCurrentItem - parsed.trustedTimestamp)
updatedAction = updatedAction.copy(
items = updatedAction.items.filter { it.categoryId != mergedItem.categoryId } + listOf(mergedItem)
)
}
}
if (!issues) {
// update the previous action
database.pendingSyncAction().updateEncodedActionSync(
sequenceNumber = previousAction.sequenceNumber,
action = StringWriter().apply {
JsonWriter(this).apply {
updatedAction.serialize(this)
if (diff > 2 * 1000) {
issues = true
}
}.toString()
)
}
syncUtil.requestVeryUnimportantSync()
val mergedItem = AddUsedTimeActionItem(
timeToAdd = oldItem.timeToAdd + newItem.timeToAdd,
extraTimeToSubtract = oldItem.extraTimeToSubtract + newItem.extraTimeToSubtract,
categoryId = newItem.categoryId,
additionalCountingSlots = oldItem.additionalCountingSlots,
sessionDurationLimits = oldItem.sessionDurationLimits
)
return@runInTransaction
updatedAction = updatedAction.copy(
items = updatedAction.items.filter { it.categoryId != mergedItem.categoryId } + listOf(mergedItem)
)
}
}
if (!issues) {
// update the previous action
database.pendingSyncAction().updateEncodedActionSync(
sequenceNumber = previousAction.sequenceNumber,
action = StringWriter().apply {
JsonWriter(this).apply {
updatedAction.serialize(this)
}
}.toString()
)
syncUtil.requestVeryUnimportantSync()
return@runInTransaction
}
}
}
}
@ -202,7 +181,7 @@ object ApplyActionUtil {
userId = ""
))
if (action is AddUsedTimeAction || action is AddUsedTimeActionVersion2) {
if (action is AddUsedTimeActionVersion2) {
syncUtil.requestVeryUnimportantSync()
} else {
if (BuildConfig.DEBUG) {

View file

@ -35,56 +35,6 @@ object LocalDatabaseAppLogicActionDispatcher {
database.runInTransaction {
when(action) {
is AddUsedTimeAction -> {
val categoryEntry = database.category().getCategoryByIdSync(action.categoryId)!!
val parentCategoryEntry = if (categoryEntry.parentCategoryId.isNotEmpty())
database.category().getCategoryByIdSync(categoryEntry.parentCategoryId)
else
null
fun handleAddUsedTime(categoryId: String) {
val lengthInMinutes = MinuteOfDay.LENGTH
val lengthInMs = lengthInMinutes * 1000 * 60
// try to update
val updatedRows = database.usedTimes().addUsedTime(
categoryId = categoryId,
timeToAdd = action.timeToAdd,
dayOfEpoch = action.dayOfEpoch,
start = MinuteOfDay.MIN,
end = MinuteOfDay.MAX,
maximum = lengthInMs
)
if (updatedRows == 0) {
// create new entry
database.usedTimes().insertUsedTime(UsedTimeItem(
categoryId = categoryId,
dayOfEpoch = action.dayOfEpoch,
usedMillis = action.timeToAdd.coerceAtMost(lengthInMs).toLong(),
startTimeOfDay = MinuteOfDay.MIN,
endTimeOfDay = MinuteOfDay.MAX
))
}
if (action.extraTimeToSubtract != 0) {
database.category().subtractCategoryExtraTime(
categoryId = categoryId,
removedExtraTime = action.extraTimeToSubtract
)
}
}
handleAddUsedTime(categoryEntry.id)
if (parentCategoryEntry?.childId == categoryEntry.childId) {
handleAddUsedTime(parentCategoryEntry.id)
}
null
}
is AddUsedTimeActionVersion2 -> {
action.items.forEach { item ->
database.category().getCategoryByIdSync(item.categoryId)

View file

@ -187,11 +187,18 @@ data class OfflineModeStatus(
// add used times
val thisUsedTimes = usedTimes.filter { it.categoryId == category.id }
thisUsedTimes.forEach { usedTime ->
apply(AddUsedTimeAction(
categoryId = category.id,
extraTimeToSubtract = 0,
apply(AddUsedTimeActionVersion2(
dayOfEpoch = usedTime.dayOfEpoch,
timeToAdd = usedTime.usedMillis.toInt()
items = listOf(
AddUsedTimeActionItem(
categoryId = category.id,
timeToAdd = usedTime.usedMillis.toInt(),
extraTimeToSubtract = 0,
sessionDurationLimits = emptySet(),
additionalCountingSlots = emptySet()
)
),
trustedTimestamp = 0
))
}