From d3631bf14f8d4da9f85ed05586933324f9787248 Mon Sep 17 00:00:00 2001
From: razeeman <freeraz@mail.ru>
Date: Sun, 15 Sep 2024 21:53:25 +0300
Subject: [PATCH] add ability to send multiple tags for automated tracking

---
 .../recevier/NotificationReceiver.kt          | 19 ++++++++----
 .../NotificationTypeBroadcastController.kt    | 12 +++----
 ...ctivityStartStopFromBroadcastInteractor.kt | 31 ++++++++++---------
 ...tyStartedStoppedBroadcastInteractorImpl.kt | 29 ++++++++---------
 4 files changed, 49 insertions(+), 42 deletions(-)

diff --git a/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/recevier/NotificationReceiver.kt b/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/recevier/NotificationReceiver.kt
index 1dc036ad5..b23354cb6 100644
--- a/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/recevier/NotificationReceiver.kt
+++ b/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/recevier/NotificationReceiver.kt
@@ -129,11 +129,12 @@ class NotificationReceiver : BroadcastReceiver() {
             ACTION_START_ACTIVITY -> {
                 val name = intent.getStringExtra(EXTRA_ACTIVITY_NAME)
                 val comment = intent.getStringExtra(EXTRA_RECORD_COMMENT)
-                val tagName = intent.getStringExtra(EXTRA_RECORD_TAG_NAME)
+                val tagNames = intent.getStringExtra(EXTRA_RECORD_TAG_NAME)
+                    ?.slipTagNames().orEmpty()
                 typeController.onActionActivityStart(
                     name = name,
                     comment = comment,
-                    tagName = tagName,
+                    tagNames = tagNames,
                 )
             }
             ACTION_STOP_ACTIVITY -> {
@@ -151,10 +152,11 @@ class NotificationReceiver : BroadcastReceiver() {
             }
             ACTION_RESTART_ACTIVITY -> {
                 val comment = intent.getStringExtra(EXTRA_RECORD_COMMENT)
-                val tagName = intent.getStringExtra(EXTRA_RECORD_TAG_NAME)
+                val tagNames = intent.getStringExtra(EXTRA_RECORD_TAG_NAME)
+                    ?.slipTagNames().orEmpty()
                 typeController.onActionActivityRestart(
                     comment = comment,
-                    tagName = tagName,
+                    tagNames = tagNames,
                 )
             }
             ACTION_ADD_RECORD -> {
@@ -162,13 +164,14 @@ class NotificationReceiver : BroadcastReceiver() {
                 val timeStarted = intent.getStringExtra(EXTRA_TIME_STARTED)
                 val timeEnded = intent.getStringExtra(EXTRA_TIME_ENDED)
                 val comment = intent.getStringExtra(EXTRA_RECORD_COMMENT)
-                val tagName = intent.getStringExtra(EXTRA_RECORD_TAG_NAME)
+                val tagNames = intent.getStringExtra(EXTRA_RECORD_TAG_NAME)
+                    ?.slipTagNames().orEmpty()
                 typeController.onActionRecordAdd(
                     name = name,
                     timeStarted = timeStarted,
                     timeEnded = timeEnded,
                     comment = comment,
-                    tagName = tagName,
+                    tagNames = tagNames,
                 )
             }
             ACTION_NOTIFICATION_STOP -> {
@@ -233,6 +236,10 @@ class NotificationReceiver : BroadcastReceiver() {
         pomodoroController.onBootCompleted()
     }
 
+    private fun String.slipTagNames(): List<String> {
+        return split(',').map(String::trim)
+    }
+
     companion object {
         const val ACTION_INACTIVITY_REMINDER =
             "com.razeeman.util.simpletimetracker.ACTION_INACTIVITY_REMINDER"
diff --git a/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/recordType/controller/NotificationTypeBroadcastController.kt b/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/recordType/controller/NotificationTypeBroadcastController.kt
index ea8149e46..31838300a 100644
--- a/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/recordType/controller/NotificationTypeBroadcastController.kt
+++ b/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/recordType/controller/NotificationTypeBroadcastController.kt
@@ -16,12 +16,12 @@ class NotificationTypeBroadcastController @Inject constructor(
     fun onActionActivityStart(
         name: String?,
         comment: String?,
-        tagName: String?,
+        tagNames: List<String>,
     ) {
         name ?: return
         GlobalScope.launch {
             activityStartStopFromBroadcastInteractor.onActionActivityStart(
-                name = name, comment = comment, tagName = tagName,
+                name = name, comment = comment, tagNames = tagNames,
             )
         }
     }
@@ -64,11 +64,11 @@ class NotificationTypeBroadcastController @Inject constructor(
 
     fun onActionActivityRestart(
         comment: String?,
-        tagName: String?,
+        tagNames: List<String>,
     ) {
         GlobalScope.launch {
             activityStartStopFromBroadcastInteractor.onActionActivityRestart(
-                comment = comment, tagName = tagName,
+                comment = comment, tagNames = tagNames,
             )
         }
     }
@@ -78,7 +78,7 @@ class NotificationTypeBroadcastController @Inject constructor(
         timeStarted: String?,
         timeEnded: String?,
         comment: String?,
-        tagName: String?,
+        tagNames: List<String>,
     ) {
         name ?: return
         timeStarted ?: return
@@ -89,7 +89,7 @@ class NotificationTypeBroadcastController @Inject constructor(
                 timeStarted = timeStarted,
                 timeEnded = timeEnded,
                 comment = comment,
-                tagName = tagName,
+                tagNames = tagNames,
             )
         }
     }
diff --git a/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/recordType/interactor/ActivityStartStopFromBroadcastInteractor.kt b/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/recordType/interactor/ActivityStartStopFromBroadcastInteractor.kt
index 55ae08024..8c28715fc 100644
--- a/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/recordType/interactor/ActivityStartStopFromBroadcastInteractor.kt
+++ b/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/recordType/interactor/ActivityStartStopFromBroadcastInteractor.kt
@@ -3,6 +3,7 @@ package com.example.util.simpletimetracker.feature_notification.recordType.inter
 import com.example.util.simpletimetracker.core.interactor.CompleteTypesStateInteractor
 import com.example.util.simpletimetracker.core.interactor.RecordRepeatInteractor
 import com.example.util.simpletimetracker.domain.REPEAT_BUTTON_ITEM_ID
+import com.example.util.simpletimetracker.domain.extension.orEmpty
 import com.example.util.simpletimetracker.domain.extension.orZero
 import com.example.util.simpletimetracker.domain.interactor.AddRecordMediator
 import com.example.util.simpletimetracker.domain.interactor.AddRunningRecordMediator
@@ -36,17 +37,17 @@ class ActivityStartStopFromBroadcastInteractor @Inject constructor(
     suspend fun onActionActivityStart(
         name: String,
         comment: String?,
-        tagName: String?,
+        tagNames: List<String>,
     ) {
         val typeId = getTypeIdByName(name) ?: return
         val runningRecord = runningRecordInteractor.get(typeId)
         if (runningRecord != null) return // Already running.
-        val tagId = findTagIdByName(tagName, typeId)
+        val tagIds = findTagIdByName(tagNames, typeId)
 
         addRunningRecordMediator.startTimer(
             typeId = typeId,
             comment = comment.orEmpty(),
-            tagIds = listOfNotNull(tagId),
+            tagIds = tagIds,
         )
     }
 
@@ -87,20 +88,20 @@ class ActivityStartStopFromBroadcastInteractor @Inject constructor(
 
     suspend fun onActionActivityRestart(
         comment: String?,
-        tagName: String?,
+        tagNames: List<String>,
     ) {
         val previousRecord = recordInteractor.getPrev(
             timeStarted = System.currentTimeMillis(),
         ).firstOrNull() ?: return
         val typeId = previousRecord.typeId
-        val tagId = findTagIdByName(tagName, typeId)
+        val tagIds = findTagIdByName(tagNames, typeId)
 
         addRunningRecordMediator.startTimer(
             typeId = typeId,
             comment = comment
                 ?: previousRecord.comment,
-            tagIds = listOfNotNull(tagId)
-                .takeUnless { tagName == null }
+            tagIds = tagIds
+                .takeUnless { tagNames.isEmpty() }
                 ?: previousRecord.tagIds,
         )
     }
@@ -110,12 +111,12 @@ class ActivityStartStopFromBroadcastInteractor @Inject constructor(
         timeStarted: String,
         timeEnded: String,
         comment: String?,
-        tagName: String?,
+        tagNames: List<String>,
     ) {
         val typeId = getTypeIdByName(name) ?: return
         val newTimeStarted = parseTimestamp(timeStarted) ?: return
         val newTimeEnded = parseTimestamp(timeEnded) ?: return
-        val tagId = findTagIdByName(tagName, typeId)
+        val tagIds = findTagIdByName(tagNames, typeId)
 
         Record(
             id = 0, // Zero creates new record.
@@ -123,7 +124,7 @@ class ActivityStartStopFromBroadcastInteractor @Inject constructor(
             timeStarted = newTimeStarted,
             timeEnded = newTimeEnded,
             comment = comment.orEmpty(),
-            tagIds = listOfNotNull(tagId),
+            tagIds = tagIds,
         ).let {
             addRecordMediator.add(it)
             recordsUpdateInteractor.send()
@@ -191,12 +192,14 @@ class ActivityStartStopFromBroadcastInteractor @Inject constructor(
     }
 
     private suspend fun findTagIdByName(
-        name: String?,
+        names: List<String>,
         typeId: Long,
-    ): Long? {
-        name ?: return null
+    ): List<Long> {
+        if (names.isEmpty()) return emptyList()
         return getSelectableTagsInteractor.execute(typeId)
-            .firstOrNull { it.name == name && !it.archived }?.id
+            .filter { it.name in names && !it.archived }
+            .map { it.id }
+            .orEmpty()
     }
 
     /**
diff --git a/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/recordType/interactor/ActivityStartedStoppedBroadcastInteractorImpl.kt b/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/recordType/interactor/ActivityStartedStoppedBroadcastInteractorImpl.kt
index 753149b8f..404f04705 100644
--- a/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/recordType/interactor/ActivityStartedStoppedBroadcastInteractorImpl.kt
+++ b/features/feature_notification/src/main/java/com/example/util/simpletimetracker/feature_notification/recordType/interactor/ActivityStartedStoppedBroadcastInteractorImpl.kt
@@ -11,6 +11,7 @@ import com.example.util.simpletimetracker.domain.interactor.ActivityStartedStopp
 import com.example.util.simpletimetracker.domain.interactor.PrefsInteractor
 import com.example.util.simpletimetracker.domain.interactor.RecordTagInteractor
 import com.example.util.simpletimetracker.domain.interactor.RecordTypeInteractor
+import com.example.util.simpletimetracker.domain.model.RecordTag
 import dagger.hilt.android.qualifiers.ApplicationContext
 import javax.inject.Inject
 
@@ -28,14 +29,11 @@ class ActivityStartedStoppedBroadcastInteractorImpl @Inject constructor(
     ) {
         if (!prefsInteractor.getAutomatedTrackingSendEvents()) return
 
-        val activityName = getActivityName(typeId) ?: return
-        val tagName = getTagName(tagIds.firstOrNull())
-
         sendBroadcast(
             actionString = EVENT_STARTED_ACTIVITY,
-            activityName = activityName,
+            activityName = getActivityName(typeId) ?: return,
             comment = comment,
-            tagName = tagName,
+            tagNames = getTagNames(tagIds),
         )
     }
 
@@ -46,14 +44,11 @@ class ActivityStartedStoppedBroadcastInteractorImpl @Inject constructor(
     ) {
         if (!prefsInteractor.getAutomatedTrackingSendEvents()) return
 
-        val activityName = getActivityName(typeId) ?: return
-        val tagName = getTagName(tagIds.firstOrNull())
-
         sendBroadcast(
             actionString = EVENT_STOPPED_ACTIVITY,
-            activityName = activityName,
+            activityName = getActivityName(typeId) ?: return,
             comment = comment,
-            tagName = tagName,
+            tagNames = getTagNames(tagIds),
         )
     }
 
@@ -61,13 +56,14 @@ class ActivityStartedStoppedBroadcastInteractorImpl @Inject constructor(
         actionString: String,
         activityName: String,
         comment: String,
-        tagName: String,
+        tagNames: List<String>,
     ) {
+        val tagsString = tagNames.joinToString(separator = ",")
         Intent().apply {
             action = actionString
             putExtra(EXTRA_ACTIVITY_NAME, activityName)
             if (comment.isNotEmpty()) putExtra(EXTRA_RECORD_COMMENT, comment)
-            if (tagName.isNotEmpty()) putExtra(EXTRA_RECORD_TAG_NAME, tagName)
+            if (tagNames.isNotEmpty()) putExtra(EXTRA_RECORD_TAG_NAME, tagsString)
         }.let(context::sendBroadcast)
     }
 
@@ -77,9 +73,10 @@ class ActivityStartedStoppedBroadcastInteractorImpl @Inject constructor(
         return recordTypeInteractor.get(typeId)?.name
     }
 
-    private suspend fun getTagName(
-        tagId: Long?,
-    ): String {
-        return recordTagInteractor.getAll().firstOrNull { it.id == tagId }?.name.orEmpty()
+    private suspend fun getTagNames(
+        tagIds: List<Long>,
+    ): List<String> {
+        val tags = recordTagInteractor.getAll().associateBy(RecordTag::id)
+        return tagIds.mapNotNull { tagId -> tags[tagId]?.name }
     }
 }
\ No newline at end of file