mirror of
https://codeberg.org/timelimit/timelimit-android.git
synced 2025-10-06 03:50:23 +02:00
Keep annoy unblock counter during reboot
This commit is contained in:
parent
d72b6801dd
commit
d4bfa37caf
6 changed files with 1323 additions and 6 deletions
1225
app/schemas/io.timelimit.android.data.RoomDatabase/39.json
Normal file
1225
app/schemas/io.timelimit.android.data.RoomDatabase/39.json
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* TimeLimit Copyright <C> 2019 - 2021 Jonas Lochmann
|
* TimeLimit Copyright <C> 2019 - 2022 Jonas Lochmann
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -274,4 +274,10 @@ object DatabaseMigrations {
|
||||||
database.execSQL("ALTER TABLE category ADD COLUMN block_notification_delay INTEGER NOT NULL DEFAULT 0")
|
database.execSQL("ALTER TABLE category ADD COLUMN block_notification_delay INTEGER NOT NULL DEFAULT 0")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val MIGRATE_TO_V39 = object: Migration(38, 39) {
|
||||||
|
override fun migrate(database: SupportSQLiteDatabase) {
|
||||||
|
// nothing to do, there was just a new config item type added
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ import java.util.concurrent.TimeUnit
|
||||||
UserLimitLoginCategory::class,
|
UserLimitLoginCategory::class,
|
||||||
CategoryNetworkId::class,
|
CategoryNetworkId::class,
|
||||||
ChildTask::class
|
ChildTask::class
|
||||||
], version = 38)
|
], version = 39)
|
||||||
abstract class RoomDatabase: RoomDatabase(), io.timelimit.android.data.Database {
|
abstract class RoomDatabase: RoomDatabase(), io.timelimit.android.data.Database {
|
||||||
companion object {
|
companion object {
|
||||||
private val lock = Object()
|
private val lock = Object()
|
||||||
|
@ -123,7 +123,8 @@ abstract class RoomDatabase: RoomDatabase(), io.timelimit.android.data.Database
|
||||||
DatabaseMigrations.MIGRATE_TO_V35,
|
DatabaseMigrations.MIGRATE_TO_V35,
|
||||||
DatabaseMigrations.MIGRATE_TO_V36,
|
DatabaseMigrations.MIGRATE_TO_V36,
|
||||||
DatabaseMigrations.MIGRATE_TO_V37,
|
DatabaseMigrations.MIGRATE_TO_V37,
|
||||||
DatabaseMigrations.MIGRATE_TO_V38
|
DatabaseMigrations.MIGRATE_TO_V38,
|
||||||
|
DatabaseMigrations.MIGRATE_TO_V39
|
||||||
)
|
)
|
||||||
.setQueryExecutor(Threads.database)
|
.setQueryExecutor(Threads.database)
|
||||||
.addCallback(object: Callback() {
|
.addCallback(object: Callback() {
|
||||||
|
|
|
@ -327,4 +327,7 @@ abstract class ConfigDao {
|
||||||
fun getServerApiLevelSync() = getValueOfKeySync(ConfigurationItemType.ServerApiLevel).let { it?.toInt() ?: 0 }
|
fun getServerApiLevelSync() = getValueOfKeySync(ConfigurationItemType.ServerApiLevel).let { it?.toInt() ?: 0 }
|
||||||
fun getServerApiLevelLive() = getValueOfKeyAsync(ConfigurationItemType.ServerApiLevel).map { it?.toInt() ?: 0 }
|
fun getServerApiLevelLive() = getValueOfKeyAsync(ConfigurationItemType.ServerApiLevel).map { it?.toInt() ?: 0 }
|
||||||
fun setServerApiLevelSync(serverApiLevel: Int) { updateValueSync(ConfigurationItemType.ServerApiLevel, serverApiLevel.toString()) }
|
fun setServerApiLevelSync(serverApiLevel: Int) { updateValueSync(ConfigurationItemType.ServerApiLevel, serverApiLevel.toString()) }
|
||||||
|
|
||||||
|
fun getAnnoyManualUnblockCounter() = getValueOfKeySync(ConfigurationItemType.AnnoyManualUnblockCounter).let { it?.toInt() ?: 0 }
|
||||||
|
fun setAnoyManualUnblockCounterSync(counter: Int) { updateValueSync(ConfigurationItemType.AnnoyManualUnblockCounter, counter.toString()) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,7 +99,8 @@ enum class ConfigurationItemType {
|
||||||
EnableUpdates,
|
EnableUpdates,
|
||||||
UpdateStatus,
|
UpdateStatus,
|
||||||
CustomOrganizationName,
|
CustomOrganizationName,
|
||||||
ServerApiLevel
|
ServerApiLevel,
|
||||||
|
AnnoyManualUnblockCounter,
|
||||||
}
|
}
|
||||||
|
|
||||||
object ConfigurationItemTypeUtil {
|
object ConfigurationItemTypeUtil {
|
||||||
|
@ -126,6 +127,7 @@ object ConfigurationItemTypeUtil {
|
||||||
private const val UPDATE_STATUS = 22
|
private const val UPDATE_STATUS = 22
|
||||||
private const val CUSTOM_ORGANIZATION_NAME = 23
|
private const val CUSTOM_ORGANIZATION_NAME = 23
|
||||||
private const val SERVER_API_LEVEL = 24
|
private const val SERVER_API_LEVEL = 24
|
||||||
|
private const val ANNOY_MANUAL_UNBLOCK_COUNTER = 25
|
||||||
|
|
||||||
val TYPES = listOf(
|
val TYPES = listOf(
|
||||||
ConfigurationItemType.OwnDeviceId,
|
ConfigurationItemType.OwnDeviceId,
|
||||||
|
@ -150,7 +152,8 @@ object ConfigurationItemTypeUtil {
|
||||||
ConfigurationItemType.EnableUpdates,
|
ConfigurationItemType.EnableUpdates,
|
||||||
ConfigurationItemType.UpdateStatus,
|
ConfigurationItemType.UpdateStatus,
|
||||||
ConfigurationItemType.CustomOrganizationName,
|
ConfigurationItemType.CustomOrganizationName,
|
||||||
ConfigurationItemType.ServerApiLevel
|
ConfigurationItemType.ServerApiLevel,
|
||||||
|
ConfigurationItemType.AnnoyManualUnblockCounter
|
||||||
)
|
)
|
||||||
|
|
||||||
fun serialize(value: ConfigurationItemType) = when(value) {
|
fun serialize(value: ConfigurationItemType) = when(value) {
|
||||||
|
@ -177,6 +180,7 @@ object ConfigurationItemTypeUtil {
|
||||||
ConfigurationItemType.UpdateStatus -> UPDATE_STATUS
|
ConfigurationItemType.UpdateStatus -> UPDATE_STATUS
|
||||||
ConfigurationItemType.CustomOrganizationName -> CUSTOM_ORGANIZATION_NAME
|
ConfigurationItemType.CustomOrganizationName -> CUSTOM_ORGANIZATION_NAME
|
||||||
ConfigurationItemType.ServerApiLevel -> SERVER_API_LEVEL
|
ConfigurationItemType.ServerApiLevel -> SERVER_API_LEVEL
|
||||||
|
ConfigurationItemType.AnnoyManualUnblockCounter -> ANNOY_MANUAL_UNBLOCK_COUNTER
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parse(value: Int) = when(value) {
|
fun parse(value: Int) = when(value) {
|
||||||
|
@ -203,6 +207,7 @@ object ConfigurationItemTypeUtil {
|
||||||
UPDATE_STATUS -> ConfigurationItemType.UpdateStatus
|
UPDATE_STATUS -> ConfigurationItemType.UpdateStatus
|
||||||
CUSTOM_ORGANIZATION_NAME -> ConfigurationItemType.CustomOrganizationName
|
CUSTOM_ORGANIZATION_NAME -> ConfigurationItemType.CustomOrganizationName
|
||||||
SERVER_API_LEVEL -> ConfigurationItemType.ServerApiLevel
|
SERVER_API_LEVEL -> ConfigurationItemType.ServerApiLevel
|
||||||
|
ANNOY_MANUAL_UNBLOCK_COUNTER -> ConfigurationItemType.AnnoyManualUnblockCounter
|
||||||
else -> throw IllegalArgumentException()
|
else -> throw IllegalArgumentException()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package io.timelimit.android.logic
|
package io.timelimit.android.logic
|
||||||
|
|
||||||
import android.os.Build
|
import android.util.Log
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import io.timelimit.android.BuildConfig
|
import io.timelimit.android.BuildConfig
|
||||||
import io.timelimit.android.async.Threads
|
import io.timelimit.android.async.Threads
|
||||||
|
import io.timelimit.android.coroutines.executeAndWait
|
||||||
|
import io.timelimit.android.coroutines.runAsync
|
||||||
import io.timelimit.android.integration.platform.ProtectionLevel
|
import io.timelimit.android.integration.platform.ProtectionLevel
|
||||||
import io.timelimit.android.livedata.*
|
import io.timelimit.android.livedata.*
|
||||||
|
|
||||||
|
@ -27,6 +29,7 @@ class AnnoyLogic (val appLogic: AppLogic) {
|
||||||
// config
|
// config
|
||||||
companion object {
|
companion object {
|
||||||
private const val ENABLE = !BuildConfig.storeCompilant
|
private const val ENABLE = !BuildConfig.storeCompilant
|
||||||
|
private const val LOG_TAG = "AnnoyLogic"
|
||||||
|
|
||||||
private const val TEMP_UNBLOCK_DURATION = 1000 * 45L
|
private const val TEMP_UNBLOCK_DURATION = 1000 * 45L
|
||||||
private const val TEMP_UNBLOCK_PARENT_DURATION = 1000 * 60 * 10L
|
private const val TEMP_UNBLOCK_PARENT_DURATION = 1000 * 60 * 10L
|
||||||
|
@ -87,6 +90,7 @@ class AnnoyLogic (val appLogic: AppLogic) {
|
||||||
nextManualUnblockTimestamp = now + manualUnblockDelay(manualUnblockCounter)
|
nextManualUnblockTimestamp = now + manualUnblockDelay(manualUnblockCounter)
|
||||||
|
|
||||||
enableTempDisabled(TEMP_UNBLOCK_DURATION)
|
enableTempDisabled(TEMP_UNBLOCK_DURATION)
|
||||||
|
saveManualUnblockCounterAsync()
|
||||||
}
|
}
|
||||||
|
|
||||||
// input: trigger temp unblock by parents (event)
|
// input: trigger temp unblock by parents (event)
|
||||||
|
@ -95,8 +99,10 @@ class AnnoyLogic (val appLogic: AppLogic) {
|
||||||
nextManualUnblockTimestamp = now()
|
nextManualUnblockTimestamp = now()
|
||||||
|
|
||||||
enableTempDisabled(TEMP_UNBLOCK_PARENT_DURATION)
|
enableTempDisabled(TEMP_UNBLOCK_PARENT_DURATION)
|
||||||
|
saveManualUnblockCounterAsync()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// helper functions
|
||||||
private fun enableTempDisabled(duration: Long) {
|
private fun enableTempDisabled(duration: Long) {
|
||||||
annoyTempDisabled.value = true
|
annoyTempDisabled.value = true
|
||||||
|
|
||||||
|
@ -104,4 +110,75 @@ class AnnoyLogic (val appLogic: AppLogic) {
|
||||||
Threads.mainThreadHandler.postDelayed(annoyTempDisabledSetFalse, duration)
|
Threads.mainThreadHandler.postDelayed(annoyTempDisabledSetFalse, duration)
|
||||||
isManipulated.observeForever(resetTempDisabledObserver)
|
isManipulated.observeForever(resetTempDisabledObserver)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// state saving and restoring
|
||||||
|
private fun saveManualUnblockCounterAsync() {
|
||||||
|
Threads.mainThreadHandler.removeCallbacks(saveZeroUnblockCounterRunnable)
|
||||||
|
|
||||||
|
Threads.database.execute {
|
||||||
|
try {
|
||||||
|
appLogic.database.config().setAnoyManualUnblockCounterSync(manualUnblockCounter)
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
Log.w(LOG_TAG, "could not save unblock counter value", ex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eventuallyScheduleResetOfStoredCounter()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun eventuallyScheduleResetOfStoredCounter() {
|
||||||
|
if (manualUnblockCounter > 0) {
|
||||||
|
val now = now()
|
||||||
|
val resetTimestamp = nextManualUnblockTimestamp + manualUnblockDelay(manualUnblockCounter)
|
||||||
|
val resetDelay = resetTimestamp - now
|
||||||
|
|
||||||
|
if (resetDelay > 0) {
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
Log.d(LOG_TAG, "scheduled counter reset in ${resetDelay/1000} seconds")
|
||||||
|
}
|
||||||
|
|
||||||
|
Threads.mainThreadHandler.postDelayed(saveZeroUnblockCounterRunnable, resetDelay)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val saveZeroUnblockCounterRunnable = Runnable {
|
||||||
|
Threads.database.execute {
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
Log.d(LOG_TAG, "reset counter now")
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
appLogic.database.config().setAnoyManualUnblockCounterSync(0)
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
Log.w(LOG_TAG, "could not reset saved counter value", ex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
runAsync {
|
||||||
|
try {
|
||||||
|
val counter = Threads.database.executeAndWait {
|
||||||
|
appLogic.database.config().getAnnoyManualUnblockCounter()
|
||||||
|
}
|
||||||
|
val now = now()
|
||||||
|
|
||||||
|
if (counter > 0) {
|
||||||
|
manualUnblockCounter = counter
|
||||||
|
nextManualUnblockTimestamp = now + manualUnblockDelay(manualUnblockCounter)
|
||||||
|
|
||||||
|
eventuallyScheduleResetOfStoredCounter()
|
||||||
|
}
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
Log.w(LOG_TAG, "could not load saved counter", ex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue