mirror of
https://codeberg.org/timelimit/timelimit-android.git
synced 2025-10-03 17:59:51 +02:00
Only update session duration start times after five seconds usage
This commit is contained in:
parent
a8bb991501
commit
adc333fd40
3 changed files with 136 additions and 27 deletions
|
@ -128,6 +128,7 @@ class BackgroundTaskLogic(val appLogic: AppLogic) {
|
|||
timeApi = appLogic.timeApi,
|
||||
longDuration = 1000 * 60 * 10 /* 10 minutes */
|
||||
)
|
||||
private val undisturbedCategoryUsageCounter = UndisturbedCategoryUsageCounter()
|
||||
|
||||
private val appTitleCache = QueryAppTitleCache(appLogic.platformIntegration)
|
||||
private val categoryHandlingCache = CategoryHandlingCache()
|
||||
|
@ -194,6 +195,7 @@ class BackgroundTaskLogic(val appLogic: AppLogic) {
|
|||
// app must be enabled
|
||||
if (!appLogic.enable.waitForNonNullValue()) {
|
||||
commitUsedTimeUpdaters()
|
||||
undisturbedCategoryUsageCounter.reset()
|
||||
appLogic.platformIntegration.setAppStatusMessage(null)
|
||||
appLogic.platformIntegration.setShowBlockingOverlay(false)
|
||||
setShowNotificationToRevokeTemporarilyAllowedApps(false)
|
||||
|
@ -215,6 +217,7 @@ class BackgroundTaskLogic(val appLogic: AppLogic) {
|
|||
// device must be used by a child
|
||||
if (deviceRelatedData == null || userRelatedData == null || userRelatedData.user.type != UserType.Child) {
|
||||
commitUsedTimeUpdaters()
|
||||
undisturbedCategoryUsageCounter.reset()
|
||||
|
||||
val shouldDoAutomaticSignOut = deviceRelatedData != null && DefaultUserLogic.hasAutomaticSignOut(deviceRelatedData) && deviceRelatedData.canSwitchToDefaultUser
|
||||
|
||||
|
@ -248,6 +251,7 @@ class BackgroundTaskLogic(val appLogic: AppLogic) {
|
|||
|
||||
val nowTimestamp = realTime.timeInMillis
|
||||
val nowTimezone = TimeZone.getTimeZone(userRelatedData.user.timeZone)
|
||||
val nowUptime = appLogic.timeApi.getCurrentUptimeInMillis()
|
||||
|
||||
val nowDate = DateInTimezone.getLocalDate(nowTimestamp, nowTimezone)
|
||||
val nowMinuteOfWeek = getMinuteOfWeek(nowTimestamp, nowTimezone)
|
||||
|
@ -323,6 +327,9 @@ class BackgroundTaskLogic(val appLogic: AppLogic) {
|
|||
if (it is AppBaseHandling.UseCategories) it.categoryIds else emptySet()
|
||||
}.flattenToSet()
|
||||
|
||||
undisturbedCategoryUsageCounter.report(nowUptime, currentCategoryIds)
|
||||
val recentlyStartedCategories = undisturbedCategoryUsageCounter.getRecentlyStartedCategories(nowUptime)
|
||||
|
||||
val needsNetworkId = allAppsBaseHandlings.find { it.needsNetworkId() } != null
|
||||
val networkId: NetworkId? = if (needsNetworkId) appLogic.platformIntegration.getCurrentNetworkId() else null
|
||||
|
||||
|
@ -496,7 +503,8 @@ class BackgroundTaskLogic(val appLogic: AppLogic) {
|
|||
duration = timeToSubtract,
|
||||
dayOfEpoch = dayOfEpoch,
|
||||
trustedTimestamp = if (realTime.shouldTrustTimePermanently) realTime.timeInMillis else 0,
|
||||
handlings = categoryHandlingsToCount
|
||||
handlings = categoryHandlingsToCount,
|
||||
recentlyStartedCategories = recentlyStartedCategories
|
||||
)
|
||||
|
||||
if (didAutoCommitOfUsedTimes) {
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* TimeLimit Copyright <C> 2019 - 2021 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.logic
|
||||
|
||||
class UndisturbedCategoryUsageCounter {
|
||||
private val data = mutableMapOf<String, Long>()
|
||||
|
||||
fun reset() {
|
||||
data.clear()
|
||||
}
|
||||
|
||||
fun report(uptime: Long, categories: Set<String>) {
|
||||
removeUnknown(categories)
|
||||
addNewCategories(categories, uptime)
|
||||
}
|
||||
|
||||
fun getRecentlyStartedCategories(uptime: Long): Set<String> {
|
||||
return data.filterValues { it >= uptime - 5000 }.keys
|
||||
}
|
||||
|
||||
private fun removeUnknown(currentCategories: Set<String>) {
|
||||
val iterator = data.iterator()
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
if (!currentCategories.contains(iterator.next().key)) {
|
||||
iterator.remove()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun addNewCategories(categories: Set<String>, uptime: Long) {
|
||||
categories.forEach { categoryId ->
|
||||
if (!data.containsKey(categoryId)) {
|
||||
data[categoryId] = uptime
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -32,6 +32,7 @@ class UsedTimeUpdateHelper (private val appLogic: AppLogic) {
|
|||
private var countedTime = 0
|
||||
private var lastCategoryHandlings = emptyList<CategoryItselfHandling>()
|
||||
private var categoryIds = emptySet<String>()
|
||||
private var recentlyStartedCategories = emptySet<String>()
|
||||
private var trustedTimestamp = 0L
|
||||
private var dayOfEpoch = 0
|
||||
private var maxTimeToAdd = Long.MAX_VALUE
|
||||
|
@ -40,7 +41,13 @@ class UsedTimeUpdateHelper (private val appLogic: AppLogic) {
|
|||
fun getCountedCategoryIds() = categoryIds
|
||||
|
||||
// returns true if it made a commit
|
||||
suspend fun report(duration: Int, handlings: List<CategoryItselfHandling>, trustedTimestamp: Long, dayOfEpoch: Int): Boolean {
|
||||
suspend fun report(
|
||||
duration: Int,
|
||||
handlings: List<CategoryItselfHandling>,
|
||||
recentlyStartedCategories: Set<String>,
|
||||
trustedTimestamp: Long,
|
||||
dayOfEpoch: Int
|
||||
): Boolean {
|
||||
if (handlings.find { !it.shouldCountTime } != null || duration < 0) {
|
||||
throw IllegalArgumentException()
|
||||
}
|
||||
|
@ -94,6 +101,7 @@ class UsedTimeUpdateHelper (private val appLogic: AppLogic) {
|
|||
}
|
||||
|
||||
this.lastCategoryHandlings = handlings
|
||||
this.recentlyStartedCategories = recentlyStartedCategories
|
||||
this.trustedTimestamp = trustedTimestamp
|
||||
this.dayOfEpoch = dayOfEpoch
|
||||
|
||||
|
@ -111,40 +119,82 @@ class UsedTimeUpdateHelper (private val appLogic: AppLogic) {
|
|||
val makeCommit = lastCategoryHandlings.isNotEmpty() && countedTime > 0
|
||||
|
||||
if (makeCommit) {
|
||||
try {
|
||||
ApplyActionUtil.applyAppLogicAction(
|
||||
action = AddUsedTimeActionVersion2(
|
||||
dayOfEpoch = dayOfEpoch,
|
||||
items = lastCategoryHandlings.map { handling ->
|
||||
AddUsedTimeActionItem(
|
||||
categoryId = handling.createdWithCategoryRelatedData.category.id,
|
||||
timeToAdd = countedTime,
|
||||
extraTimeToSubtract = if (handling.shouldCountExtraTime) countedTime else 0,
|
||||
additionalCountingSlots = handling.additionalTimeCountingSlots,
|
||||
sessionDurationLimits = handling.sessionDurationSlotsToCount
|
||||
)
|
||||
},
|
||||
trustedTimestamp = if (lastCategoryHandlings.find { it.sessionDurationSlotsToCount.isNotEmpty() } != null) trustedTimestamp else 0
|
||||
),
|
||||
appLogic = appLogic,
|
||||
ignoreIfDeviceIsNotConfigured = true
|
||||
val categoriesWithSessionDurationLimits = lastCategoryHandlings
|
||||
.filter { it.sessionDurationSlotsToCount.isNotEmpty() }
|
||||
.map { it.createdWithCategoryRelatedData.category.id }
|
||||
.toSet()
|
||||
|
||||
val categoriesWithSessionDurationLimitsWhichWereRecentlyStarted = categoriesWithSessionDurationLimits.intersect(recentlyStartedCategories)
|
||||
|
||||
if (categoriesWithSessionDurationLimitsWhichWereRecentlyStarted.isEmpty()) {
|
||||
commitSendAction(
|
||||
items = lastCategoryHandlings,
|
||||
sendTimestamp = categoriesWithSessionDurationLimits.isNotEmpty()
|
||||
)
|
||||
} catch (ex: CategoryNotFoundException) {
|
||||
} else {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.d(LOG_TAG, "could not commit used times", ex)
|
||||
Log.d(LOG_TAG, "skip updating the session duration last usage timestamps")
|
||||
}
|
||||
|
||||
// this is a very rare case if a category is deleted while it is used;
|
||||
// in this case there could be some lost time
|
||||
// changes for other categories, but it's no big problem
|
||||
if (categoriesWithSessionDurationLimits == categoriesWithSessionDurationLimitsWhichWereRecentlyStarted) {
|
||||
// no category needs the timestamp
|
||||
commitSendAction(
|
||||
items = lastCategoryHandlings,
|
||||
sendTimestamp = false
|
||||
)
|
||||
} else {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.d(LOG_TAG, "... but only for some categories")
|
||||
}
|
||||
|
||||
// some categories need the timestamp and others do not
|
||||
val items1 = lastCategoryHandlings.filter {
|
||||
categoriesWithSessionDurationLimitsWhichWereRecentlyStarted.contains(it.createdWithCategoryRelatedData.category.id)
|
||||
}
|
||||
val items2 = lastCategoryHandlings.filterNot {
|
||||
categoriesWithSessionDurationLimitsWhichWereRecentlyStarted.contains(it.createdWithCategoryRelatedData.category.id)
|
||||
}
|
||||
|
||||
commitSendAction(items = items1, sendTimestamp = false)
|
||||
commitSendAction(items = items2, sendTimestamp = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
countedTime = 0
|
||||
// doing this would cause a commit very soon again
|
||||
// lastCategoryHandlings = emptyList()
|
||||
// categoryIds = emptySet()
|
||||
|
||||
return makeCommit
|
||||
}
|
||||
|
||||
private suspend fun commitSendAction(items: List<CategoryItselfHandling>, sendTimestamp: Boolean) {
|
||||
try {
|
||||
ApplyActionUtil.applyAppLogicAction(
|
||||
action = AddUsedTimeActionVersion2(
|
||||
dayOfEpoch = dayOfEpoch,
|
||||
items = items.map { handling -> prepareHandling(handling) },
|
||||
trustedTimestamp = if (sendTimestamp) trustedTimestamp else 0
|
||||
),
|
||||
appLogic = appLogic,
|
||||
ignoreIfDeviceIsNotConfigured = true
|
||||
)
|
||||
} catch (ex: CategoryNotFoundException) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.d(LOG_TAG, "could not commit used times", ex)
|
||||
}
|
||||
|
||||
// this is a very rare case if a category is deleted while it is used;
|
||||
// in this case there could be some lost time
|
||||
// changes for other categories, but it's no big problem
|
||||
}
|
||||
}
|
||||
|
||||
private fun prepareHandling(handling: CategoryItselfHandling): AddUsedTimeActionItem {
|
||||
return AddUsedTimeActionItem(
|
||||
categoryId = handling.createdWithCategoryRelatedData.category.id,
|
||||
timeToAdd = countedTime,
|
||||
extraTimeToSubtract = if (handling.shouldCountExtraTime) countedTime else 0,
|
||||
additionalCountingSlots = handling.additionalTimeCountingSlots,
|
||||
sessionDurationLimits = handling.sessionDurationSlotsToCount
|
||||
)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue