11package com.example.util.simpletimetracker.domain.record.interactor
22
3+ import com.example.util.simpletimetracker.domain.base.CurrentTimestampProvider
4+ import com.example.util.simpletimetracker.domain.base.SuspendLazy
5+ import com.example.util.simpletimetracker.domain.base.suspendLazy
36import com.example.util.simpletimetracker.domain.notifications.interactor.ActivityStartedStoppedBroadcastInteractor
4- import com.example.util.simpletimetracker.domain.complexRule.interactor.ComplexRuleProcessActionInteractor
57import com.example.util.simpletimetracker.domain.notifications.interactor.NotificationGoalCountInteractor
8+ import com.example.util.simpletimetracker.domain.notifications.interactor.UpdateExternalViewsInteractor
69import com.example.util.simpletimetracker.domain.pomodoro.interactor.PomodoroStartInteractor
710import com.example.util.simpletimetracker.domain.prefs.interactor.PrefsInteractor
8- import com.example.util.simpletimetracker.domain.recordTag.interactor.RecordTagInteractor
9- import com.example.util.simpletimetracker.domain.recordTag.model.RecordTagValueType
10- import com.example.util.simpletimetracker.domain.recordType.interactor.RecordTypeInteractor
11- import com.example.util.simpletimetracker.domain.recordTag.interactor.RecordTypeToDefaultTagInteractor
12- import com.example.util.simpletimetracker.domain.notifications.interactor.UpdateExternalViewsInteractor
13- import com.example.util.simpletimetracker.domain.recordType.model.RecordType
14- import com.example.util.simpletimetracker.domain.base.ResultContainer
15- import com.example.util.simpletimetracker.domain.base.CurrentTimestampProvider
16- import com.example.util.simpletimetracker.domain.base.SuspendLazy
17- import com.example.util.simpletimetracker.domain.base.suspendLazy
1811import com.example.util.simpletimetracker.domain.record.model.Record
1912import com.example.util.simpletimetracker.domain.record.model.RecordBase
2013import com.example.util.simpletimetracker.domain.record.model.RecordDataSelectionDialogResult
2114import com.example.util.simpletimetracker.domain.record.model.RunningRecord
22- import com.example.util.simpletimetracker.domain.recordTag.model.RecordTag
23- import kotlinx.coroutines.coroutineScope
15+ import com.example.util.simpletimetracker.domain.recordType.interactor.RecordTypeInteractor
16+ import com.example.util.simpletimetracker.domain.recordType.model.RecordType
2417import java.util.concurrent.TimeUnit
2518import javax.inject.Inject
2619
@@ -29,15 +22,13 @@ class AddRunningRecordMediator @Inject constructor(
2922 private val removeRunningRecordMediator : RemoveRunningRecordMediator ,
3023 private val recordInteractor : RecordInteractor ,
3124 private val runningRecordInteractor : RunningRecordInteractor ,
32- private val recordTagInteractor : RecordTagInteractor ,
3325 private val recordTypeInteractor : RecordTypeInteractor ,
3426 private val addRecordMediator : AddRecordMediator ,
35- private val recordTypeToDefaultTagInteractor : RecordTypeToDefaultTagInteractor ,
3627 private val notificationGoalCountInteractor : NotificationGoalCountInteractor ,
3728 private val activityStartedStoppedBroadcastInteractor : ActivityStartedStoppedBroadcastInteractor ,
3829 private val shouldShowRecordDataSelectionInteractor : ShouldShowRecordDataSelectionInteractor ,
3930 private val pomodoroStartInteractor : PomodoroStartInteractor ,
40- private val complexRuleProcessActionInteractor : ComplexRuleProcessActionInteractor ,
31+ private val processRulesInteractor : ProcessRulesInteractor ,
4132 private val updateExternalViewsInteractor : UpdateExternalViewsInteractor ,
4233 private val currentTimestampProvider : CurrentTimestampProvider ,
4334) {
@@ -50,42 +41,17 @@ class AddRunningRecordMediator @Inject constructor(
5041 updateNotificationSwitch : Boolean = true,
5142 commentInputAvailable : Boolean = true,
5243 onNeedToShowTagSelection : suspend (RecordDataSelectionDialogResult ) -> Unit ,
53- ): Boolean = coroutineScope {
44+ ): Boolean {
5445 // Already running
55- if (runningRecordInteractor.get(typeId) != null ) return @coroutineScope false
46+ if (runningRecordInteractor.get(typeId) != null ) return false
5647
5748 val shouldShowTagSelectionResult = shouldShowRecordDataSelectionInteractor.execute(
5849 typeId = typeId,
5950 commentInputAvailable = commentInputAvailable,
6051 )
61- val currentTime = currentTimestampProvider.get()
62- val prevRecords = suspendLazy { recordInteractor.getAllPrev(currentTime) }
63- val rulesResult = getRulesResultForStart(
64- typeId = typeId,
65- timeStarted = currentTime,
66- prevRecords = prevRecords,
67- retroactiveTrackingMode = prefsInteractor.getRetroactiveTrackingMode(),
68- )
69- val requiredTagValueSelectionTagIds = filterNumericTagValueSelectionTagIds(
70- tagIds = rulesResult.tagIdsToSelectValueOnStart,
71- )
72- val dialogFields = shouldShowTagSelectionResult.fields.toMutableList()
73- if (requiredTagValueSelectionTagIds.isNotEmpty() &&
74- dialogFields.none { it is RecordDataSelectionDialogResult .Field .Tags }
75- ) {
76- // Force tag selection dialog if any tags need value.
77- dialogFields + = RecordDataSelectionDialogResult .Field .Tags
78- }
79- val needsSelection = dialogFields.isNotEmpty() ||
80- requiredTagValueSelectionTagIds.isNotEmpty()
8152
82- return @coroutineScope if (needsSelection) {
83- onNeedToShowTagSelection(
84- RecordDataSelectionDialogResult (
85- fields = dialogFields,
86- requiredTagValueSelectionTagIds = requiredTagValueSelectionTagIds,
87- ),
88- )
53+ return if (shouldShowTagSelectionResult.fields.isNotEmpty()) {
54+ onNeedToShowTagSelection(shouldShowTagSelectionResult)
8955 false
9056 } else {
9157 startTimer(
@@ -106,7 +72,7 @@ class AddRunningRecordMediator @Inject constructor(
10672 updateNotificationSwitch : Boolean = true,
10773 checkDefaultDuration : Boolean = true,
10874 useSelectedTags : Boolean = false,
109- ) = coroutineScope {
75+ ) {
11076 val currentTime = currentTimestampProvider.get()
11177 val actualTimeStarted = when (timeStarted) {
11278 is StartTime .Current -> timeStarted.currentTimeStampMs
@@ -117,7 +83,7 @@ class AddRunningRecordMediator @Inject constructor(
11783 val actualPrevRecords = suspendLazy {
11884 recordInteractor.getAllPrev(actualTimeStarted)
11985 }
120- val rulesResult = getRulesResultForStart(
86+ val rulesResult = processRulesInteractor. getRulesResultForStart(
12187 typeId = typeId,
12288 timeStarted = actualTimeStarted,
12389 prevRecords = actualPrevRecords,
@@ -139,7 +105,7 @@ class AddRunningRecordMediator @Inject constructor(
139105 val actualTags = if (useSelectedTags) {
140106 tags
141107 } else {
142- getAllTags(
108+ processRulesInteractor. getAllTags(
143109 typeId = typeId,
144110 currentTags = tags,
145111 tagValuesFromRules = rulesResult.tags,
@@ -271,7 +237,7 @@ class AddRunningRecordMediator @Inject constructor(
271237 params : StartParams ,
272238 prevRecords : SuspendLazy <List <Record >>,
273239 ) {
274- val prevRecord = getPrevRecordToMergeWith(params.typeId, prevRecords)
240+ val prevRecord = processRulesInteractor. getPrevRecordToMergeWith(params.typeId, prevRecords)
275241 val sameTags = prevRecord?.tags.orEmpty().sortedBy { it.tagId } == params.tags.sortedBy { it.tagId }
276242 val shouldMerge = sameTags || params.tags.isEmpty()
277243
@@ -304,68 +270,6 @@ class AddRunningRecordMediator @Inject constructor(
304270 )
305271 }
306272
307- suspend fun processRules (
308- typeId : Long ,
309- timeStarted : Long ,
310- prevRecords : SuspendLazy <List <Record >>,
311- ): ComplexRuleProcessActionInteractor .Result {
312- // If no rules - no need to check them.
313- return if (complexRuleProcessActionInteractor.hasRules()) {
314- val currentRecords = runningRecordInteractor.getAll()
315- val hasAnyRunningTimersOnTimeStarted = currentRecords.any {
316- it.timeStarted <= timeStarted
317- }
318- val takeCurrentRecords = currentRecords.isNotEmpty() &&
319- hasAnyRunningTimersOnTimeStarted
320-
321- // If no current records - check closest previous.
322- val records = if (takeCurrentRecords) currentRecords else prevRecords()
323-
324- val currentTypeIds = records
325- .map { it.typeIds }
326- .flatten()
327- .toSet()
328-
329- complexRuleProcessActionInteractor.processRules(
330- timeStarted = timeStarted,
331- startingTypeId = typeId,
332- currentTypeIds = currentTypeIds,
333- )
334- } else {
335- ComplexRuleProcessActionInteractor .Result (
336- isMultitaskingAllowed = ResultContainer .Undefined ,
337- disallowOnlyPreviousTypeIds = emptySet(),
338- tags = emptyList(),
339- tagIdsToSelectValueOnStart = emptySet(),
340- )
341- }
342- }
343-
344- private suspend fun getRulesResultForStart (
345- typeId : Long ,
346- timeStarted : Long ,
347- prevRecords : SuspendLazy <List <Record >>,
348- retroactiveTrackingMode : Boolean ,
349- ): ComplexRuleProcessActionInteractor .Result {
350- return if (
351- retroactiveTrackingMode &&
352- getPrevRecordToMergeWith(typeId, prevRecords) != null
353- ) {
354- ComplexRuleProcessActionInteractor .Result (
355- isMultitaskingAllowed = ResultContainer .Undefined ,
356- disallowOnlyPreviousTypeIds = emptySet(),
357- tags = emptyList(),
358- tagIdsToSelectValueOnStart = emptySet(),
359- )
360- } else {
361- processRules(
362- typeId = typeId,
363- timeStarted = timeStarted,
364- prevRecords = prevRecords,
365- )
366- }
367- }
368-
369273 private suspend fun processMultitasking (
370274 typeId : Long ,
371275 isMultitaskingAllowed : Boolean ,
@@ -403,7 +307,7 @@ class AddRunningRecordMediator @Inject constructor(
403307 if (! params.isMultitaskingAllowed) return
404308
405309 val recordTypesMap = recordTypeInteractor.getAll().associateBy(RecordType ::id)
406- val mergedRecord = getPrevRecordToMergeWith(params.typeId, prevRecords)
310+ val mergedRecord = processRulesInteractor. getPrevRecordToMergeWith(params.typeId, prevRecords)
407311
408312 // Extend prev records to current time.
409313 prevRecords().filter {
@@ -427,42 +331,6 @@ class AddRunningRecordMediator @Inject constructor(
427331 }
428332 }
429333
430- suspend fun getAllTags (
431- typeId : Long ,
432- currentTags : List <RecordBase .Tag >,
433- tagValuesFromRules : List <RecordBase .Tag >,
434- ): List <RecordBase .Tag > {
435- val defaultTags = recordTypeToDefaultTagInteractor.getTags(typeId)
436- val merged = linkedMapOf<Long , RecordBase .Tag >()
437-
438- fun merge (tag : RecordBase .Tag ) {
439- val existing = merged[tag.tagId]
440- // Tags with values takes precedence.
441- if (existing == null || (existing.numericValue == null && tag.numericValue != null )) {
442- merged[tag.tagId] = tag
443- }
444- }
445-
446- currentTags.forEach(::merge)
447- defaultTags.map { RecordBase .Tag (tagId = it, numericValue = null ) }.forEach(::merge)
448- tagValuesFromRules.forEach(::merge)
449-
450- return merged.values.toList()
451- }
452-
453- private suspend fun filterNumericTagValueSelectionTagIds (tagIds : Set <Long >): List <Long > {
454- if (tagIds.isEmpty()) return emptyList()
455- val tags = recordTagInteractor.getAll().associateBy(RecordTag ::id)
456- return tagIds.filter { tags[it]?.valueType == RecordTagValueType .NUMERIC }
457- }
458-
459- private suspend fun getPrevRecordToMergeWith (
460- typeId : Long ,
461- prevRecords : SuspendLazy <List <Record >>,
462- ): Record ? {
463- return prevRecords().firstOrNull { it.typeId == typeId }
464- }
465-
466334 private data class StartParams (
467335 val typeId : Long ,
468336 val timeStarted : Long ,
0 commit comments