Skip to content

Commit

Permalink
add retroactive tracking mode support to widgets, notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
Razeeman committed Oct 26, 2024
1 parent f45288b commit 4626c4a
Show file tree
Hide file tree
Showing 36 changed files with 518 additions and 140 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ class RecordRepoImpl @Inject constructor(
private fun clearCache() {
getFromRangeCache.evictAll()
getFromRangeByTypeCache.evictAll()
recordCache.evictAll()
isEmpty = null
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,31 @@ class AddRunningRecordMediator @Inject constructor(
timeStarted: Long? = null,
updateNotificationSwitch: Boolean = true,
) {
val actualTimeStarted = timeStarted ?: System.currentTimeMillis()
val retroactiveTrackingMode = prefsInteractor.getRetroactiveTrackingMode()
val prevRecord = if (retroactiveTrackingMode) {
recordInteractor.getPrev(actualTimeStarted).firstOrNull()
} else {
null
}
val rulesResult = processRules(
typeId = typeId,
timeStarted = timeStarted ?: System.currentTimeMillis(),
timeStarted = if (
retroactiveTrackingMode &&
prevRecord != null &&
shouldMergeWithPrevRecord(typeId, prevRecord)
) {
// If will merge - it will be one record,
// so need to check rules from original start.
prevRecord.timeStarted
} else {
actualTimeStarted
},
)
processMultitasking(
typeId = typeId,
isMultitaskingAllowedByRules = rulesResult.isMultitaskingAllowed,
timeEnded = actualTimeStarted,
)
val actualTags = getAllTags(
typeId = typeId,
Expand All @@ -84,11 +102,11 @@ class AddRunningRecordMediator @Inject constructor(
typeId = typeId,
comment = comment,
tagIds = actualTags,
timeStarted = timeStarted ?: System.currentTimeMillis(),
timeStarted = actualTimeStarted,
updateNotificationSwitch = updateNotificationSwitch,
)
if (prefsInteractor.getRetroactiveTrackingMode()) {
addRetroactiveModeInternal(startParams)
if (retroactiveTrackingMode) {
addRetroactiveModeInternal(startParams, prevRecord)
} else {
addInternal(startParams)
}
Expand Down Expand Up @@ -126,9 +144,11 @@ class AddRunningRecordMediator @Inject constructor(
}
}

private suspend fun addRetroactiveModeInternal(params: StartParams) {
private suspend fun addRetroactiveModeInternal(
params: StartParams,
prevRecord: Record?,
) {
val type = recordTypeInteractor.get(params.typeId) ?: return
val prevRecord = recordInteractor.getPrev(params.timeStarted).firstOrNull()

if (type.defaultDuration > 0L) {
val newTimeStarted = prevRecord?.timeEnded
Expand Down Expand Up @@ -186,18 +206,17 @@ class AddRunningRecordMediator @Inject constructor(
params: StartParams,
prevRecord: Record?,
) {
val shouldMergeWithPrevRecord = prevRecord != null &&
prevRecord.typeId == params.typeId &&
prevRecord.tagIds == params.tagIds

val record = if (prevRecord != null && shouldMergeWithPrevRecord) {
val shouldMerge = shouldMergeWithPrevRecord(params.typeId, prevRecord)
val record = if (prevRecord != null && shouldMerge) {
Record(
id = prevRecord.id, // Updates existing record.
typeId = params.typeId,
timeStarted = prevRecord.timeStarted,
timeEnded = params.timeStarted,
comment = params.comment,
tagIds = params.tagIds,
comment = params.comment.takeUnless { it.isEmpty() }
?: prevRecord.comment,
tagIds = params.tagIds.takeUnless { it.isEmpty() }
?: prevRecord.tagIds,
)
} else {
val newTimeStarted = prevRecord?.timeEnded
Expand Down Expand Up @@ -255,6 +274,7 @@ class AddRunningRecordMediator @Inject constructor(
private suspend fun processMultitasking(
typeId: Long,
isMultitaskingAllowedByRules: ResultContainer<Boolean>,
timeEnded: Long,
) {
val isMultitaskingAllowedByDefault = prefsInteractor.getAllowMultitasking()
val isMultitaskingAllowed = isMultitaskingAllowedByRules.getValueOrNull()
Expand All @@ -265,7 +285,13 @@ class AddRunningRecordMediator @Inject constructor(
// Widgets will update on adding.
runningRecordInteractor.getAll()
.filter { it.id != typeId }
.forEach { removeRunningRecordMediator.removeWithRecordAdd(it, updateWidgets = false) }
.forEach {
removeRunningRecordMediator.removeWithRecordAdd(
runningRecord = it,
updateWidgets = false,
timeEnded = timeEnded,
)
}
}
}

Expand All @@ -278,6 +304,13 @@ class AddRunningRecordMediator @Inject constructor(
return (tagIds + defaultTags + tagIdsFromRules).toSet().toList()
}

private fun shouldMergeWithPrevRecord(
typeId: Long,
prevRecord: Record?,
): Boolean {
return prevRecord != null && prevRecord.typeId == typeId
}

private data class StartParams(
val typeId: Long,
val timeStarted: Long,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,12 @@ class RecordInteractor @Inject constructor(

suspend fun addFromRunning(
runningRecord: RunningRecord,
timeEnded: Long,
) {
Record(
typeId = runningRecord.id,
timeStarted = runningRecord.timeStarted,
timeEnded = System.currentTimeMillis(),
timeEnded = timeEnded,
comment = runningRecord.comment,
tagIds = runningRecord.tagIds,
).let {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,19 @@ class RemoveRunningRecordMediator @Inject constructor(
runningRecord: RunningRecord,
updateWidgets: Boolean = true,
updateNotificationSwitch: Boolean = true,
timeEnded: Long? = null, // null - take current time.
) {
val recordTimeEnded = timeEnded ?: System.currentTimeMillis()
val durationToIgnore = prefsInteractor.getIgnoreShortRecordsDuration()
val duration = TimeUnit.MILLISECONDS
.toSeconds(System.currentTimeMillis() - runningRecord.timeStarted)
.toSeconds(recordTimeEnded - runningRecord.timeStarted)

if (duration > durationToIgnore || durationToIgnore == 0L) {
// No need to update widgets and notification because it will be done in running record remove.
recordInteractor.addFromRunning(runningRecord)
recordInteractor.addFromRunning(
runningRecord = runningRecord,
timeEnded = recordTimeEnded
)
}
activityStartedStoppedBroadcastInteractor.onActivityStopped(
typeId = runningRecord.id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class UpdateExternalViewsInteractor @Inject constructor(
private val notificationGoalTimeInteractor: NotificationGoalTimeInteractor,
private val widgetInteractor: WidgetInteractor,
private val wearInteractor: WearInteractor,
private val prefsInteractor: PrefsInteractor,
) {

// Also removes running records and records.
Expand All @@ -28,10 +29,12 @@ class UpdateExternalViewsInteractor @Inject constructor(
Update.GoalCancel(RecordTypeGoal.IdData.Type(typeId)),
Update.GoalReschedule(runningRecordIds + typeId),
Update.WidgetStatistics,
Update.WidgetSingleType(typeId),
Update.WidgetSingleTypes.takeIf { getRetroactiveTrackingMode() }
?: Update.WidgetSingleType(typeId),
Update.WidgetUniversal.takeIf { getRetroactiveTrackingMode() },
Update.Wear.takeIf { !fromArchive },
Update.NotificationTypes.takeIf { !fromArchive },
Update.NotificationWithControls.takeIf { !fromArchive }
Update.NotificationWithControls.takeIf { !fromArchive },
)
}

Expand Down Expand Up @@ -133,7 +136,9 @@ class UpdateExternalViewsInteractor @Inject constructor(
Update.NotificationWithControls,
Update.GoalReschedule(listOf(typeId)),
Update.WidgetStatistics,
Update.WidgetSingleType(typeId),
Update.WidgetSingleTypes.takeIf { getRetroactiveTrackingMode() }
?: Update.WidgetSingleType(typeId),
Update.WidgetUniversal.takeIf { getRetroactiveTrackingMode() },
)
}

Expand All @@ -146,7 +151,9 @@ class UpdateExternalViewsInteractor @Inject constructor(
Update.NotificationWithControls.takeIf { updateNotificationSwitch },
Update.GoalReschedule(listOf(typeId)),
Update.WidgetStatistics,
Update.WidgetSingleType(typeId),
Update.WidgetSingleTypes.takeIf { getRetroactiveTrackingMode() }
?: Update.WidgetSingleType(typeId),
Update.WidgetUniversal.takeIf { getRetroactiveTrackingMode() },
)
}

Expand Down Expand Up @@ -308,6 +315,15 @@ class UpdateExternalViewsInteractor @Inject constructor(
)
}

suspend fun onRetroactiveTrackingModeChange() {
runUpdates(
Update.WidgetSingleTypes,
Update.WidgetUniversal,
Update.NotificationWithControls,
Update.Wear
)
}

// Update all widgets.
suspend fun onWidgetsTransparencyChange() {
runUpdates(
Expand Down Expand Up @@ -377,6 +393,10 @@ class UpdateExternalViewsInteractor @Inject constructor(
)
}

private suspend fun getRetroactiveTrackingMode(): Boolean {
return prefsInteractor.getRetroactiveTrackingMode()
}

private suspend fun runUpdates(vararg updates: Update?) {
updates.filterNotNull().forEach { runUpdate(it) }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ class ChangeRecordActionsDelegateMapper @Inject constructor() {
updateViewData()
}

override suspend fun onSaveClickDelegate() {
parent?.onSaveClickDelegate()
override suspend fun onSaveClickDelegate(doAfter: suspend () -> Unit) {
parent?.onSaveClickDelegate(doAfter)
}
}
}
Expand Down Expand Up @@ -163,7 +163,7 @@ class ChangeRecordActionsDelegateMapper @Inject constructor() {
newTimeStarted = baseParams.newTimeStarted,
newComment = baseParams.newComment,
newCategoryIds = baseParams.newCategoryIds,
isAdditionalActionsAvailable = continueParams.isAdditionalActionsAvailable,
isAvailable = continueParams.isAvailable,
isButtonEnabled = baseParams.isButtonEnabled,
)
}
Expand All @@ -173,7 +173,7 @@ class ChangeRecordActionsDelegateMapper @Inject constructor() {
newTypeId = baseParams.newTypeId,
newComment = baseParams.newComment,
newCategoryIds = baseParams.newCategoryIds,
isAdditionalActionsAvailable = repeatParams.isAdditionalActionsAvailable,
isAvailable = repeatParams.isAvailable,
isButtonEnabled = baseParams.isButtonEnabled,
)
}
Expand All @@ -185,7 +185,7 @@ class ChangeRecordActionsDelegateMapper @Inject constructor() {
newTimeEnded = baseParams.newTimeEnded,
newComment = baseParams.newComment,
newCategoryIds = baseParams.newCategoryIds,
isAdditionalActionsAvailable = duplicateParams.isAdditionalActionsAvailable,
isAvailable = duplicateParams.isAvailable,
isButtonEnabled = baseParams.isButtonEnabled,
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.example.util.simpletimetracker.feature_change_record.viewModel

import com.example.util.simpletimetracker.core.repo.ResourceRepo
import com.example.util.simpletimetracker.domain.interactor.PrefsInteractor
import com.example.util.simpletimetracker.domain.interactor.RecordActionContinueMediator
import com.example.util.simpletimetracker.feature_base_adapter.ViewHolderType
import com.example.util.simpletimetracker.feature_base_adapter.hint.HintViewData
Expand All @@ -13,6 +14,7 @@ import javax.inject.Inject
class ChangeRecordActionsContinueDelegate @Inject constructor(
private val router: Router,
private val resourceRepo: ResourceRepo,
private val prefsInteractor: PrefsInteractor,
private val recordActionContinueMediator: RecordActionContinueMediator,
) : ChangeRecordActionsSubDelegate<ChangeRecordActionsContinueDelegate.Parent> {

Expand Down Expand Up @@ -57,10 +59,11 @@ class ChangeRecordActionsContinueDelegate @Inject constructor(
}
}

private fun loadContinueViewData(): List<ViewHolderType> {
private suspend fun loadContinueViewData(): List<ViewHolderType> {
val params = parent?.getViewDataParams()
?: return emptyList()
if (!params.isAdditionalActionsAvailable) return emptyList()
if (!params.isAvailable) return emptyList()
if (prefsInteractor.getRetroactiveTrackingMode()) return emptyList()

val result = mutableListOf<ViewHolderType>()
result += HintViewData(
Expand Down Expand Up @@ -89,7 +92,7 @@ class ChangeRecordActionsContinueDelegate @Inject constructor(
val newTimeStarted: Long,
val newComment: String,
val newCategoryIds: List<Long>,
val isAdditionalActionsAvailable: Boolean,
val isAvailable: Boolean,
val isButtonEnabled: Boolean,
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ interface ChangeRecordActionsDelegate {
checkTypeSelected: Boolean = true,
)

suspend fun onSaveClickDelegate()
suspend fun onSaveClickDelegate(doAfter: suspend () -> Unit = {})

suspend fun onSplitComplete()

Expand Down Expand Up @@ -49,16 +49,16 @@ interface ChangeRecordActionsDelegate {
)

data class DuplicateParams(
val isAdditionalActionsAvailable: Boolean,
val isAvailable: Boolean,
)

data class ContinueParams(
val originalRecordId: Long,
val isAdditionalActionsAvailable: Boolean,
val isAvailable: Boolean,
)

data class RepeatParams(
val isAdditionalActionsAvailable: Boolean,
val isAvailable: Boolean,
)

data class AdjustParams(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class ChangeRecordActionsDuplicateDelegate @Inject constructor(
private fun loadDuplicateViewData(): List<ViewHolderType> {
val params = parent?.getViewDataParams()
?: return emptyList()
if (!params.isAdditionalActionsAvailable) return emptyList()
if (!params.isAvailable) return emptyList()

val result = mutableListOf<ViewHolderType>()
result += HintViewData(
Expand Down Expand Up @@ -73,7 +73,7 @@ class ChangeRecordActionsDuplicateDelegate @Inject constructor(
val newTimeEnded: Long,
val newComment: String,
val newCategoryIds: List<Long>,
val isAdditionalActionsAvailable: Boolean,
val isAvailable: Boolean,
val isButtonEnabled: Boolean,
)
}
Expand Down
Loading

0 comments on commit 4626c4a

Please sign in to comment.