From 77669bf8b8bb5e46b5e75e6a2868cb9e93fe792e Mon Sep 17 00:00:00 2001 From: "goksu.turker" Date: Wed, 27 Aug 2025 17:10:19 +0300 Subject: [PATCH] ANDDEV-8972 | Add event key exclusion implementation while copying to clipboard - Add event key highlight implementation in detail page --- .../publish/PublishConventionPlugin.kt | 15 ++++- .../analytics-logger-no-op/build.gradle.kts | 2 +- libraries/analytics-logger/build.gradle.kts | 2 +- .../data/repository/ExcludeKeysRepository.kt | 23 ++++++++ .../internal/di/AnalyticsContainer.kt | 10 ++++ .../domain/usecase/ExcludeKeysUseCase.kt | 56 ++++++++++++++++++ .../internal/ui/detail/DetailFragment.kt | 58 ++++++++++++++++++- .../analytics_logger_fragment_detail.xml | 56 ++++++++++++++++-- .../src/main/res/values/strings.xml | 3 + 9 files changed, 215 insertions(+), 10 deletions(-) create mode 100644 libraries/analytics-logger/src/main/java/com/trendyol/android/devtools/analyticslogger/internal/data/repository/ExcludeKeysRepository.kt create mode 100644 libraries/analytics-logger/src/main/java/com/trendyol/android/devtools/analyticslogger/internal/domain/usecase/ExcludeKeysUseCase.kt diff --git a/convention-plugins/plugins/src/main/kotlin/com/trendyol/android/devtools/plugins/publish/PublishConventionPlugin.kt b/convention-plugins/plugins/src/main/kotlin/com/trendyol/android/devtools/plugins/publish/PublishConventionPlugin.kt index 46cb7bf..3161294 100644 --- a/convention-plugins/plugins/src/main/kotlin/com/trendyol/android/devtools/plugins/publish/PublishConventionPlugin.kt +++ b/convention-plugins/plugins/src/main/kotlin/com/trendyol/android/devtools/plugins/publish/PublishConventionPlugin.kt @@ -47,7 +47,20 @@ class PublishConventionPlugin : Plugin { } } } - signAllPublications() + + if (hasSigningKeys()) { + signAllPublications() + } } } + + private fun hasSigningKeys(): Boolean { + val signingKeyId = System.getenv("ORG_GRADLE_PROJECT_signingInMemoryKeyId") + val signingKeyPassword = System.getenv("ORG_GRADLE_PROJECT_signingInMemoryKeyPassword") + val signingKey = System.getenv("ORG_GRADLE_PROJECT_signingInMemoryKey") + + return !signingKeyId.isNullOrBlank() && + !signingKeyPassword.isNullOrBlank() && + !signingKey.isNullOrBlank() + } } diff --git a/libraries/analytics-logger-no-op/build.gradle.kts b/libraries/analytics-logger-no-op/build.gradle.kts index 5e49cbf..0d5e0de 100644 --- a/libraries/analytics-logger-no-op/build.gradle.kts +++ b/libraries/analytics-logger-no-op/build.gradle.kts @@ -33,7 +33,7 @@ android { } group = "com.trendyol.android.devtools" -version = "0.6.0" +version = "0.7.0" publishConfig { defaultConfiguration( diff --git a/libraries/analytics-logger/build.gradle.kts b/libraries/analytics-logger/build.gradle.kts index fd910c5..f77886d 100644 --- a/libraries/analytics-logger/build.gradle.kts +++ b/libraries/analytics-logger/build.gradle.kts @@ -39,7 +39,7 @@ android { } group = "com.trendyol.android.devtools" -version = "0.6.0" +version = "0.7.0" publishConfig { defaultConfiguration( diff --git a/libraries/analytics-logger/src/main/java/com/trendyol/android/devtools/analyticslogger/internal/data/repository/ExcludeKeysRepository.kt b/libraries/analytics-logger/src/main/java/com/trendyol/android/devtools/analyticslogger/internal/data/repository/ExcludeKeysRepository.kt new file mode 100644 index 0000000..2afa5ad --- /dev/null +++ b/libraries/analytics-logger/src/main/java/com/trendyol/android/devtools/analyticslogger/internal/data/repository/ExcludeKeysRepository.kt @@ -0,0 +1,23 @@ +package com.trendyol.android.devtools.analyticslogger.internal.data.repository + +import android.content.SharedPreferences +import androidx.core.content.edit + +internal class ExcludeKeysRepository( + private val sharedPreferences: SharedPreferences +) { + + fun saveExcludedKeys(keys: String) { + sharedPreferences.edit { + putString(EXCLUDED_KEYS_KEY, keys) + } + } + + fun getExcludedKeys(): String { + return sharedPreferences.getString(EXCLUDED_KEYS_KEY, "").orEmpty() + } + + companion object { + private const val EXCLUDED_KEYS_KEY = "excluded_event_keys" + } +} diff --git a/libraries/analytics-logger/src/main/java/com/trendyol/android/devtools/analyticslogger/internal/di/AnalyticsContainer.kt b/libraries/analytics-logger/src/main/java/com/trendyol/android/devtools/analyticslogger/internal/di/AnalyticsContainer.kt index 7f12c8b..32c3040 100644 --- a/libraries/analytics-logger/src/main/java/com/trendyol/android/devtools/analyticslogger/internal/di/AnalyticsContainer.kt +++ b/libraries/analytics-logger/src/main/java/com/trendyol/android/devtools/analyticslogger/internal/di/AnalyticsContainer.kt @@ -7,8 +7,10 @@ import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import com.trendyol.android.devtools.analyticslogger.internal.data.database.EventDatabase import com.trendyol.android.devtools.analyticslogger.internal.data.repository.EventRepository import com.trendyol.android.devtools.analyticslogger.internal.data.repository.EventRepositoryImpl +import com.trendyol.android.devtools.analyticslogger.internal.data.repository.ExcludeKeysRepository import com.trendyol.android.devtools.analyticslogger.internal.domain.manager.EventManager import com.trendyol.android.devtools.analyticslogger.internal.domain.manager.EventManagerImpl +import com.trendyol.android.devtools.analyticslogger.internal.domain.usecase.ExcludeKeysUseCase internal class AnalyticsContainer(private val context: Context) { @@ -25,4 +27,12 @@ internal class AnalyticsContainer(private val context: Context) { val sharedPreferencesManager: SharedPreferences by lazy { context.getSharedPreferences("analytics_logger", Context.MODE_PRIVATE) } + + private val excludeKeysRepository: ExcludeKeysRepository by lazy { + ExcludeKeysRepository(sharedPreferencesManager) + } + + val excludeKeysUseCase: ExcludeKeysUseCase by lazy { + ExcludeKeysUseCase(excludeKeysRepository) + } } diff --git a/libraries/analytics-logger/src/main/java/com/trendyol/android/devtools/analyticslogger/internal/domain/usecase/ExcludeKeysUseCase.kt b/libraries/analytics-logger/src/main/java/com/trendyol/android/devtools/analyticslogger/internal/domain/usecase/ExcludeKeysUseCase.kt new file mode 100644 index 0000000..c459190 --- /dev/null +++ b/libraries/analytics-logger/src/main/java/com/trendyol/android/devtools/analyticslogger/internal/domain/usecase/ExcludeKeysUseCase.kt @@ -0,0 +1,56 @@ +package com.trendyol.android.devtools.analyticslogger.internal.domain.usecase + +import android.util.Log +import com.trendyol.android.devtools.analyticslogger.internal.data.repository.ExcludeKeysRepository +import org.json.JSONException +import org.json.JSONObject + +internal class ExcludeKeysUseCase( + private val excludeKeysRepository: ExcludeKeysRepository +) { + + fun saveExcludedKeys(keys: String) { + excludeKeysRepository.saveExcludedKeys(keys) + } + + fun getExcludedKeys(): String { + return excludeKeysRepository.getExcludedKeys() + } + + fun getExcludedKeysList(): List { + return getExcludedKeys() + .split(" ") + .map { it.trim() } + .filter { it.isNotEmpty() } + } + + fun filterJsonByExcludedKeys(jsonString: String, excludedKeys: List): String { + if (excludedKeys.isEmpty() || jsonString.isEmpty()) { + return jsonString + } + + return try { + val jsonObject = JSONObject(jsonString) + excludedKeys.forEach { key -> + removeKeyRecursively(jsonObject, key) + } + jsonObject.toString(4) + } catch (e: JSONException) { + Log.e("AnalyticsLogger", e.message.toString()) + jsonString + } + } + + private fun removeKeyRecursively(jsonObject: JSONObject, keyToRemove: String) { + jsonObject.remove(keyToRemove) + + val keys = jsonObject.keys() + while (keys.hasNext()) { + val key = keys.next() + val value = jsonObject.opt(key) + if (value is JSONObject) { + removeKeyRecursively(value, keyToRemove) + } + } + } +} diff --git a/libraries/analytics-logger/src/main/java/com/trendyol/android/devtools/analyticslogger/internal/ui/detail/DetailFragment.kt b/libraries/analytics-logger/src/main/java/com/trendyol/android/devtools/analyticslogger/internal/ui/detail/DetailFragment.kt index 14c9abf..a3ffdb0 100644 --- a/libraries/analytics-logger/src/main/java/com/trendyol/android/devtools/analyticslogger/internal/ui/detail/DetailFragment.kt +++ b/libraries/analytics-logger/src/main/java/com/trendyol/android/devtools/analyticslogger/internal/ui/detail/DetailFragment.kt @@ -4,8 +4,11 @@ import android.content.ClipData import android.content.ClipboardManager import android.content.Context import android.content.res.ColorStateList +import android.graphics.Color import android.graphics.drawable.GradientDrawable import android.os.Bundle +import android.text.SpannableString +import android.text.style.BackgroundColorSpan import android.view.LayoutInflater import android.view.Menu import android.view.MenuInflater @@ -33,7 +36,12 @@ internal class DetailFragment : Fragment() { ContextContainer.mainContainer.MainViewModelFactory() } + private val excludeKeysUseCase by lazy { + ContextContainer.analyticsContainer.excludeKeysUseCase + } + private var _binding: AnalyticsLoggerFragmentDetailBinding? = null + private var originalJsonText: String = "" private val binding get() = _binding!! @@ -62,6 +70,15 @@ internal class DetailFragment : Fragment() { checkboxShowJSTransformFunction.setOnCheckedChangeListener { _, isChecked -> editTextjsTransformFunction.visibility = if (isChecked) View.VISIBLE else View.GONE } + + editTextExcludeEventKeys.setText(excludeKeysUseCase.getExcludedKeys()) + editTextExcludeEventKeys.doAfterTextChanged { editable -> + excludeKeysUseCase.saveExcludedKeys(editable.toString()) + } + + editTextHighlightEventText.doAfterTextChanged { editable -> + highlightTextInJsonView(editable.toString()) + } } private fun observeData() { @@ -76,7 +93,8 @@ internal class DetailFragment : Fragment() { if (state is DetailState.Selected) { textViewKey.text = state.event.key textViewSource.text = state.event.source - textViewValue.text = state.event.json + originalJsonText = state.event.json.orEmpty() + highlightTextInJsonView(editTextHighlightEventText.text.toString()) textViewDate.text = state.event.date textViewPlatform.text = state.event.platform textViewPlatform.background = createPlatformBackground(state.event.platform) @@ -104,10 +122,44 @@ internal class DetailFragment : Fragment() { } } + private fun highlightTextInJsonView(searchText: String) { + if (originalJsonText.isEmpty()) { + return + } + + if (searchText.isEmpty()) { + binding.textViewValue.text = originalJsonText + return + } + + val spannableString = SpannableString(originalJsonText) + val searchTextLower = searchText.lowercase() + val originalTextLower = originalJsonText.lowercase() + val highlightColor = Color.YELLOW + + var startIndex = 0 + while (true) { + val index = originalTextLower.indexOf(searchTextLower, startIndex) + if (index == -1) break + + spannableString.setSpan( + BackgroundColorSpan(highlightColor), + index, + index + searchText.length, + SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE + ) + startIndex = index + 1 + } + + binding.textViewValue.text = spannableString + } + private fun copyToClipboard() { val clipboard = context?.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager - val data = (viewModel.detailState.value as? DetailState.Selected)?.event?.json.orEmpty() - clipboard.setPrimaryClip(ClipData.newPlainText(CLIPBOARD_LABEL, data)) + val originalData = (viewModel.detailState.value as? DetailState.Selected)?.event?.json.orEmpty() + val excludedKeys = excludeKeysUseCase.getExcludedKeysList() + val filteredData = excludeKeysUseCase.filterJsonByExcludedKeys(originalData, excludedKeys) + clipboard.setPrimaryClip(ClipData.newPlainText(CLIPBOARD_LABEL, filteredData)) Toast.makeText(context, R.string.analytics_logger_toast_copied, Toast.LENGTH_SHORT).show() } diff --git a/libraries/analytics-logger/src/main/res/layout/analytics_logger_fragment_detail.xml b/libraries/analytics-logger/src/main/res/layout/analytics_logger_fragment_detail.xml index 84a6b85..7bd72d4 100644 --- a/libraries/analytics-logger/src/main/res/layout/analytics_logger_fragment_detail.xml +++ b/libraries/analytics-logger/src/main/res/layout/analytics_logger_fragment_detail.xml @@ -35,7 +35,7 @@ app:layout_constraintEnd_toStartOf="@id/textViewPlatform" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/textViewKey" - tools:text="12.00PM"/> + tools:text="12.00PM" /> + + + + + + + + + + + @@ -102,9 +150,9 @@ android:id="@+id/editTextjsTransformFunction" android:layout_width="0dp" android:layout_height="wrap_content" + android:visibility="gone" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - android:visibility="gone" app:layout_constraintTop_toBottomOf="@+id/checkboxShowJSTransformFunction" /> diff --git a/libraries/analytics-logger/src/main/res/values/strings.xml b/libraries/analytics-logger/src/main/res/values/strings.xml index bb6ad53..af82d61 100644 --- a/libraries/analytics-logger/src/main/res/values/strings.xml +++ b/libraries/analytics-logger/src/main/res/values/strings.xml @@ -11,4 +11,7 @@ Source Copied to the clipboard. + + Event keys to exclude (space separated) + Highlight event text