From e5d103dc84c05fd451fd765b0bd8d4a8863fb755 Mon Sep 17 00:00:00 2001 From: Bas Buijsen Date: Thu, 6 Jun 2024 20:23:28 +0200 Subject: [PATCH 1/9] setup analytics --- firebase-analytics/build.gradle.kts | 173 ++++++++++++++++++ firebase-analytics/firebase_analytics.podspec | 39 ++++ firebase-analytics/package.json | 31 ++++ .../AndroidManifest.xml | 4 + .../gitlive/firebase/analytics/analytics.kt | 15 ++ .../gitlive/firebase/analytics/analytics.kt | 48 +++++ .../gitlive/firebase/analytics/analytics.kt | 9 + .../gitlive/firebase/analytics/analytics.kt | 65 +++++++ .../gitlive/firebase/analytics/analytics.kt | 38 ++++ .../gitlive/firebase/analytics/analytics.kt | 77 ++++++++ .../gitlive/firebase/analytics/analytics.kt | 12 ++ .../gitlive/firebase/analytics/analytics.kt | 85 +++++++++ .../firebase/analytics/externals/analytics.kt | 18 ++ .../firebase/analytics/analytics.jvm.kt | 21 +++ .../gitlive/firebase/analytics/analytics.kt | 13 ++ gradle.properties | 3 + settings.gradle.kts | 1 + 17 files changed, 652 insertions(+) create mode 100644 firebase-analytics/build.gradle.kts create mode 100644 firebase-analytics/firebase_analytics.podspec create mode 100644 firebase-analytics/package.json create mode 100644 firebase-analytics/src/androidInstrumentedTest/AndroidManifest.xml create mode 100644 firebase-analytics/src/androidInstrumentedTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt create mode 100644 firebase-analytics/src/androidMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt create mode 100644 firebase-analytics/src/androidUnitTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt create mode 100644 firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt create mode 100644 firebase-analytics/src/commonTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt create mode 100644 firebase-analytics/src/iosMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt create mode 100644 firebase-analytics/src/iosTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt create mode 100644 firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt create mode 100644 firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/externals/analytics.kt create mode 100644 firebase-analytics/src/jvmMain/kotlin/dev/gitlive/firebase/analytics/analytics.jvm.kt create mode 100644 firebase-analytics/src/jvmTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt diff --git a/firebase-analytics/build.gradle.kts b/firebase-analytics/build.gradle.kts new file mode 100644 index 000000000..4d68ac2c8 --- /dev/null +++ b/firebase-analytics/build.gradle.kts @@ -0,0 +1,173 @@ +import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSetTree + +/* + * Copyright (c) 2023 GitLive Ltd. Use of this source code is governed by the Apache 2.0 license. + */ + +version = project.property("firebase-analytics.version") as String + +plugins { + id("com.android.library") + kotlin("native.cocoapods") + kotlin("multiplatform") +} + +android { + val minSdkVersion: Int by project + val compileSdkVersion: Int by project + + compileSdk = compileSdkVersion + namespace = "dev.gitlive.firebase.analytics" + + defaultConfig { + minSdk = minSdkVersion + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + testOptions { + unitTests.apply { + isIncludeAndroidResources = true + } + } + packaging { + resources.pickFirsts.add("META-INF/kotlinx-serialization-core.kotlin_module") + resources.pickFirsts.add("META-INF/AL2.0") + resources.pickFirsts.add("META-INF/LGPL2.1") + } + lint { + abortOnError = false + } +} + +val supportIosTarget = project.property("skipIosTarget") != "true" + +kotlin { + + targets.configureEach { + compilations.configureEach { + kotlinOptions.freeCompilerArgs += "-Xexpect-actual-classes" + } + } + + @Suppress("OPT_IN_USAGE") + androidTarget { + instrumentedTestVariant.sourceSetTree.set(KotlinSourceSetTree.test) + unitTestVariant.sourceSetTree.set(KotlinSourceSetTree.test) + publishAllLibraryVariants() + compilations.configureEach { + kotlinOptions { + jvmTarget = "11" + } + } + } + + jvm { + compilations.getByName("main") { + kotlinOptions { + jvmTarget = "17" + } + } + compilations.getByName("test") { + kotlinOptions { + jvmTarget = "17" + } + } + } + + if (supportIosTarget) { + iosArm64() + iosX64() + iosSimulatorArm64() + cocoapods { + ios.deploymentTarget = "12.0" + framework { + baseName = "FirebaseAnalytics" + } + noPodspec() + pod("FirebaseAnalytics") { + version = "10.25.0" + extraOpts += listOf("-compiler-option", "-fmodules") + } + } + } + + js(IR) { + useCommonJs() + nodejs { + testTask( + Action { + useKarma { + useChromeHeadless() + } + } + ) + } + browser { + testTask( + Action { + useKarma { + useChromeHeadless() + } + } + ) + } + } + + sourceSets { + all { + languageSettings.apply { + val apiVersion: String by project + val languageVersion: String by project + this.apiVersion = apiVersion + this.languageVersion = languageVersion + progressiveMode = true + if (name.lowercase().contains("ios")) { + optIn("kotlinx.cinterop.ExperimentalForeignApi") + } + } + } + + getByName("commonMain") { + dependencies { + api(project(":firebase-app")) + implementation(project(":firebase-common")) + } + } + + getByName("commonTest") { + dependencies { + implementation(project(":test-utils")) + } + } + + getByName("androidMain") { + dependencies { + api("com.google.firebase:firebase-analytics") + } + } + } +} + +if (project.property("firebase-analytics.skipIosTests") == "true") { + tasks.forEach { + if (it.name.contains("ios", true) && it.name.contains("test", true)) { it.enabled = false } + } +} + +if (project.property("firebase-analytics.skipJsTests") == "true") { + tasks.forEach { + if (it.name.contains("js", true) && it.name.contains("test", true)) { it.enabled = false } + } +} + +signing { + val signingKey: String? by project + val signingPassword: String? by project + useInMemoryPgpKeys(signingKey, signingPassword) + sign(publishing.publications) +} diff --git a/firebase-analytics/firebase_analytics.podspec b/firebase-analytics/firebase_analytics.podspec new file mode 100644 index 000000000..74c7cb847 --- /dev/null +++ b/firebase-analytics/firebase_analytics.podspec @@ -0,0 +1,39 @@ +Pod::Spec.new do |spec| + spec.name = 'firebase_analytics' + spec.version = '1.8.1' + spec.homepage = '' + spec.source = { :http=> ''} + spec.authors = '' + spec.license = '' + spec.summary = '' + spec.vendored_frameworks = 'build/cocoapods/framework/firebase_analytics.framework' + spec.libraries = 'c++' + + + + spec.pod_target_xcconfig = { + 'KOTLIN_PROJECT_PATH' => ':firebase-analytics', + 'PRODUCT_MODULE_NAME' => 'firebase_analytics', + } + + spec.script_phases = [ + { + :name => 'Build firebase_analytics', + :execution_position => :before_compile, + :shell_path => '/bin/sh', + :script => <<-SCRIPT + if [ "YES" = "$OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED" ]; then + echo "Skipping Gradle build task invocation due to OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED environment variable set to \"YES\"" + exit 0 + fi + set -ev + REPO_ROOT="$PODS_TARGET_SRCROOT" + "$REPO_ROOT/../gradlew" -p "$REPO_ROOT" $KOTLIN_PROJECT_PATH:syncFramework \ + -Pkotlin.native.cocoapods.platform=$PLATFORM_NAME \ + -Pkotlin.native.cocoapods.archs="$ARCHS" \ + -Pkotlin.native.cocoapods.configuration="$CONFIGURATION" + SCRIPT + } + ] + +end diff --git a/firebase-analytics/package.json b/firebase-analytics/package.json new file mode 100644 index 000000000..9736e8e39 --- /dev/null +++ b/firebase-analytics/package.json @@ -0,0 +1,31 @@ +{ + "name": "@gitlive/firebase-analytics", + "version": "1.12.0", + "description": "Wrapper around firebase for usage in Kotlin Multiplatform projects", + "main": "firebase-analytics.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/GitLiveApp/firebase-kotlin-sdk.git" + }, + "keywords": [ + "kotlin", + "multiplatform", + "kotlin-js", + "firebase" + ], + "author": "dev.gitlive", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/GitLiveApp/firebase-kotlin-sdk/issues" + }, + "homepage": "https://github.com/GitLiveApp/firebase-kotlin-sdk", + "dependencies": { + "@gitlive/firebase-app": "1.12.0", + "firebase": "9.19.1", + "kotlin": "1.6.10", + "kotlinx-coroutines-core": "1.6.1-native-mt" + } +} diff --git a/firebase-analytics/src/androidInstrumentedTest/AndroidManifest.xml b/firebase-analytics/src/androidInstrumentedTest/AndroidManifest.xml new file mode 100644 index 000000000..3d8df4081 --- /dev/null +++ b/firebase-analytics/src/androidInstrumentedTest/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + diff --git a/firebase-analytics/src/androidInstrumentedTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/androidInstrumentedTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt new file mode 100644 index 000000000..9b6ae269a --- /dev/null +++ b/firebase-analytics/src/androidInstrumentedTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2020 GitLive Ltd. Use of this source code is governed by the Apache 2.0 license. + */ + +@file:JvmName("tests") +package dev.gitlive.firebase.analytics + +import androidx.test.platform.app.InstrumentationRegistry + +actual val emulatorHost: String = "10.0.2.2" + +actual val context: Any = InstrumentationRegistry.getInstrumentation().targetContext + +@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) +actual annotation class IgnoreForAndroidUnitTest diff --git a/firebase-analytics/src/androidMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/androidMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt new file mode 100644 index 000000000..de6243148 --- /dev/null +++ b/firebase-analytics/src/androidMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -0,0 +1,48 @@ +package dev.gitlive.firebase.analytics + +import android.os.Bundle +import com.google.firebase.analytics.analytics +import dev.gitlive.firebase.Firebase +import kotlinx.coroutines.tasks.await + +actual val Firebase.analytics: FirebaseAnalytics + get() = FirebaseAnalytics(com.google.firebase.Firebase.analytics) + +actual class FirebaseAnalytics(val android: com.google.firebase.analytics.FirebaseAnalytics) { + actual fun logEvent(name: String, parameters: Map) { + android.logEvent(name, parameters.toBundle()) + } + actual fun logEvent(name: String, block: FirebaseAnalyticsParameters.() -> Unit) { + val params = FirebaseAnalyticsParameters() + params.block() + logEvent(name, params.parameters) + } + actual fun setUserProperty(name: String, value: String) { + android.setUserProperty(name, value) + } + actual fun setUserId(id: String) { + android.setUserId(id) + } + actual fun resetAnalyticsData() { + android.resetAnalyticsData() + } + actual fun setDefaultEventParameters(parameters: Map) { + android.setDefaultEventParameters(parameters.toBundle()) + } + + actual fun setAnalyticsCollectionEnabled(enabled: Boolean) { + android.setAnalyticsCollectionEnabled(enabled) + } + + actual fun setSessionTimeoutInterval(sessionTimeoutInterval: Long) { + android.setSessionTimeoutDuration(sessionTimeoutInterval) + } + + actual suspend fun getSessionId(): Long? = android.sessionId.await() +} + +actual class FirebaseAnalyticsException(message: String): Exception(message) + +fun Map.toBundle() = Bundle().apply { + forEach { (key, value) -> putString(key, value) } +} diff --git a/firebase-analytics/src/androidUnitTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/androidUnitTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt new file mode 100644 index 000000000..aa0d883dd --- /dev/null +++ b/firebase-analytics/src/androidUnitTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -0,0 +1,9 @@ +package dev.gitlive.firebase.analytics + +import org.junit.Ignore + +actual val emulatorHost: String = "10.0.2.2" + +actual val context: Any = "" + +actual typealias IgnoreForAndroidUnitTest = Ignore diff --git a/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt new file mode 100644 index 000000000..30dac8071 --- /dev/null +++ b/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -0,0 +1,65 @@ +package dev.gitlive.firebase.analytics + +import dev.gitlive.firebase.Firebase + +expect val Firebase.analytics: FirebaseAnalytics + +expect class FirebaseAnalytics { + fun logEvent(name: String, parameters: Map) + fun logEvent(name: String, block: FirebaseAnalyticsParameters.() -> Unit) + fun setUserProperty(name: String, value: String) + fun setUserId(id: String) + fun setAnalyticsCollectionEnabled(enabled: Boolean) + fun setSessionTimeoutInterval(sessionTimeoutInterval: Long) + suspend fun getSessionId(): Long? + fun resetAnalyticsData() + fun setDefaultEventParameters(parameters: Map) +} + +expect class FirebaseAnalyticsException + +data class FirebaseAnalyticsParameters( + val parameters: MutableMap = mutableMapOf() +) { + fun param(key: String, value: String) { + parameters[key] = value + } +} + +object FirebaseAnalyticsEvents { + const val ADD_PAYMENT_INFO: String = "add_payment_info" + const val ADD_SHIPPING_INFO: String = "add_shipping_info" + const val ADD_TO_CART: String = "add_to_cart" + const val ADD_TO_WISHLIST: String = "add_to_wishlist" + const val AD_IMPRESSION: String = "ad_impression" + const val APP_OPEN: String = "app_open" + const val BEGIN_CHECKOUT: String = "begin_checkout" + const val CAMPAIGN_DETAILS: String = "campaign_details" + const val EARN_VIRTUAL_CURRENCY: String = "earn_virtual_currency" + const val GENERATE_LEAD: String = "generate_lead" + const val JOIN_GROUP: String = "join_group" + const val LEVEL_END: String = "level_end" + const val LEVEL_START: String = "level_start" + const val LEVEL_UP: String = "level_up" + const val LOGIN: String = "login" + const val POST_SCORE: String = "post_score" + const val PURCHASE: String = "purchase" + const val REFUND: String = "refund" + const val REMOVE_FROM_CART: String = "remove_from_cart" + const val SCREEN_VIEW: String = "screen_view" + const val SEARCH: String = "search" + const val SELECT_CONTENT: String = "select_content" + const val SELECT_ITEM: String = "select_item" + const val SELECT_PROMOTION: String = "select_promotion" + const val SHARE: String = "share" + const val SIGN_UP: String = "sign_up" + const val SPEND_VIRTUAL_CURRENCY: String = "spend_virtual_currency" + const val TUTORIAL_BEGIN: String = "tutorial_begin" + const val TUTORIAL_COMPLETE: String = "tutorial_complete" + const val UNLOCK_ACHIEVEMENT: String = "unlock_achievement" + const val VIEW_CART: String = "view_cart" + const val VIEW_ITEM: String = "view_item" + const val VIEW_ITEM_LIST: String = "view_item_list" + const val VIEW_PROMOTION: String = "view_promotion" + const val VIEW_SEARCH_RESULTS: String = "view_search_results" +} \ No newline at end of file diff --git a/firebase-analytics/src/commonTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/commonTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt new file mode 100644 index 000000000..9e95eaa6e --- /dev/null +++ b/firebase-analytics/src/commonTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020 GitLive Ltd. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.gitlive.firebase.analytics + +import dev.gitlive.firebase.Firebase +import dev.gitlive.firebase.FirebaseOptions +import dev.gitlive.firebase.apps +import dev.gitlive.firebase.initialize +import kotlin.test.BeforeTest + +expect val emulatorHost: String +expect val context: Any +expect annotation class IgnoreForAndroidUnitTest() + +@IgnoreForAndroidUnitTest +class FirebaseAnalyticsTest { + + lateinit var analytics: FirebaseAnalytics + + @BeforeTest + fun initializeFirebase() { + val app = Firebase.apps(context).firstOrNull() ?: Firebase.initialize( + context, + FirebaseOptions( + applicationId = "1:846484016111:ios:dd1f6688bad7af768c841a", + apiKey = "AIzaSyCK87dcMFhzCz_kJVs2cT2AVlqOTLuyWV0", + databaseUrl = "https://fir-kotlin-sdk.firebaseio.com", + storageBucket = "fir-kotlin-sdk.appspot.com", + projectId = "fir-kotlin-sdk", + gcmSenderId = "846484016111" + ) + ) + + analytics = Firebase.analytics + } +} \ No newline at end of file diff --git a/firebase-analytics/src/iosMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/iosMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt new file mode 100644 index 000000000..b29c98a77 --- /dev/null +++ b/firebase-analytics/src/iosMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -0,0 +1,77 @@ +package dev.gitlive.firebase.analytics + +import cocoapods.FirebaseAnalytics.FIRAnalytics +import dev.gitlive.firebase.Firebase +import dev.gitlive.firebase.FirebaseException +import kotlinx.coroutines.CompletableDeferred +import platform.Foundation.NSError +import platform.Foundation.NSTimeInterval + +actual val Firebase.analytics: FirebaseAnalytics + get() = FirebaseAnalytics(FIRAnalytics) + +actual class FirebaseAnalytics(val ios: FIRAnalytics.Companion) { + actual fun logEvent(name: String, parameters: Map) { + val mappedParameters: Map = parameters.map { + it.key to it.value + }.toMap() + ios.logEventWithName(name, mappedParameters) + } + actual fun logEvent(name: String, block: FirebaseAnalyticsParameters.() -> Unit) { + val params = FirebaseAnalyticsParameters() + params.block() + logEvent(name, params.parameters) + } + actual fun setUserProperty(name: String, value: String) { + ios.setUserPropertyString(value, name) + } + actual fun setUserId(id: String) { + ios.setUserID(id) + } + actual fun resetAnalyticsData() { + ios.resetAnalyticsData() + } + + actual fun setAnalyticsCollectionEnabled(enabled: Boolean) { + ios.setAnalyticsCollectionEnabled(enabled) + } + + actual fun setSessionTimeoutInterval(sessionTimeoutInterval: Long) { + ios.setSessionTimeoutInterval(sessionTimeoutInterval.toDouble()) + } + + actual suspend fun getSessionId(): Long? = ios.awaitResult { sessionIDWithCompletion(it) } + + actual fun setDefaultEventParameters(parameters: Map) { + val mappedParameters: Map = parameters.map { + it.key to it.value + }.toMap() + ios.setDefaultEventParameters(mappedParameters) + } +} + +actual class FirebaseAnalyticsException(message: String): FirebaseException(message) + +suspend inline fun T.await(function: T.(callback: (NSError?) -> Unit) -> Unit) { + val job = CompletableDeferred() + function { error -> + if(error == null) { + job.complete(Unit) + } else { + job.completeExceptionally(FirebaseAnalyticsException(error.toString())) + } + } + job.await() +} + +suspend inline fun T.awaitResult(function: T.(callback: (R?, NSError?) -> Unit) -> Unit): R { + val job = CompletableDeferred() + function { result, error -> + if(error == null) { + job.complete(result) + } else { + job.completeExceptionally(FirebaseAnalyticsException(error.toString())) + } + } + return job.await() as R +} \ No newline at end of file diff --git a/firebase-analytics/src/iosTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/iosTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt new file mode 100644 index 000000000..722724e53 --- /dev/null +++ b/firebase-analytics/src/iosTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2020 GitLive Ltd. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.gitlive.firebase.analytics + +actual val emulatorHost: String = "127.0.0.1" + +actual val context: Any = Unit + +@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) +actual annotation class IgnoreForAndroidUnitTest diff --git a/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt new file mode 100644 index 000000000..944ffaeb2 --- /dev/null +++ b/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -0,0 +1,85 @@ +package dev.gitlive.firebase.analytics + +import dev.gitlive.firebase.Firebase +import dev.gitlive.firebase.FirebaseException +import dev.gitlive.firebase.analytics.externals.getAnalytics +import dev.gitlive.firebase.analytics.externals.jsGetSessionId +import dev.gitlive.firebase.analytics.externals.jsLogEvent +import dev.gitlive.firebase.analytics.externals.jsResetAnalyticsData +import dev.gitlive.firebase.analytics.externals.jsSetAnalyticsCollectionEnabled +import dev.gitlive.firebase.analytics.externals.jsSetDefaultEventParameters +import dev.gitlive.firebase.analytics.externals.jsSetSessionTimeoutInterval +import dev.gitlive.firebase.analytics.externals.jsSetUserId +import dev.gitlive.firebase.analytics.externals.jsSetUserProperty +import kotlinx.coroutines.await + +actual val Firebase.analytics: FirebaseAnalytics + get() = FirebaseAnalytics(getAnalytics()) + +actual class FirebaseAnalytics(val js: dev.gitlive.firebase.analytics.externals.FirebaseAnalytics) { + actual fun logEvent( + name: String, + parameters: Map + ) { + jsLogEvent(js, name, parameters) + } + + actual fun logEvent( + name: String, + block: FirebaseAnalyticsParameters.() -> Unit + ) { + val params = FirebaseAnalyticsParameters() + params.block() + logEvent(name, params.parameters) + } + + actual fun setUserProperty(name: String, value: String) { + jsSetUserProperty(js, name, value) + } + + actual fun setUserId(id: String) { + jsSetUserId(js, id) + } + + actual fun setAnalyticsCollectionEnabled(enabled: Boolean) { + jsSetAnalyticsCollectionEnabled(js, enabled) + } + + actual fun setSessionTimeoutInterval(sessionTimeoutInterval: Long) { + jsSetSessionTimeoutInterval(js, sessionTimeoutInterval) + } + + actual suspend fun getSessionId(): Long? = rethrow { jsGetSessionId(js).await() } + + actual fun resetAnalyticsData() { + jsResetAnalyticsData(js) + } + + actual fun setDefaultEventParameters(parameters: Map) { + jsSetDefaultEventParameters(js, parameters) + } +} + +actual open class FirebaseAnalyticsException(code: String, cause: Throwable): FirebaseException(code, cause) + +internal inline fun rethrow(function: () -> R): R { + try { + return function() + } catch (e: Exception) { + throw e + } catch (e: dynamic) { + throw errorToException(e) + } +} + +internal fun errorToException(error: dynamic) = (error?.code ?: error?.message ?: "") + .toString() + .lowercase() + .let { code -> + when { + else -> { + println("Unknown error code in ${JSON.stringify(error)}") + FirebaseAnalyticsException(code, error) + } + } + } \ No newline at end of file diff --git a/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/externals/analytics.kt b/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/externals/analytics.kt new file mode 100644 index 000000000..416f39383 --- /dev/null +++ b/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/externals/analytics.kt @@ -0,0 +1,18 @@ +package dev.gitlive.firebase.analytics.externals + +import dev.gitlive.firebase.externals.FirebaseApp +import kotlin.js.Promise + + +external fun getAnalytics(app: FirebaseApp? = definedExternally): FirebaseAnalytics + +external fun jsLogEvent(app: FirebaseAnalytics, name: String, parameters: Map) +external fun jsSetUserProperty(app: FirebaseAnalytics, name: String, value: String) +external fun jsSetUserId(app: FirebaseAnalytics, id: String) +external fun jsResetAnalyticsData(app: FirebaseAnalytics) +external fun jsSetDefaultEventParameters(app: FirebaseAnalytics, parameters: Map) +external fun jsSetAnalyticsCollectionEnabled(app: FirebaseAnalytics, enabled: Boolean) +external fun jsSetSessionTimeoutInterval(app: FirebaseAnalytics, sessionTimeoutInterval: Long) +external fun jsGetSessionId(app: FirebaseAnalytics): Promise + +external interface FirebaseAnalytics \ No newline at end of file diff --git a/firebase-analytics/src/jvmMain/kotlin/dev/gitlive/firebase/analytics/analytics.jvm.kt b/firebase-analytics/src/jvmMain/kotlin/dev/gitlive/firebase/analytics/analytics.jvm.kt new file mode 100644 index 000000000..f714eef30 --- /dev/null +++ b/firebase-analytics/src/jvmMain/kotlin/dev/gitlive/firebase/analytics/analytics.jvm.kt @@ -0,0 +1,21 @@ +package dev.gitlive.firebase.analytics + +import dev.gitlive.firebase.Firebase +import dev.gitlive.firebase.FirebaseException + +actual val Firebase.analytics: FirebaseAnalytics + get() = TODO("Not yet implemented") + +actual class FirebaseAnalytics { + actual fun logEvent(name: String, parameters: Map) {} + actual fun logEvent(name: String, block: FirebaseAnalyticsParameters.() -> Unit) {} + actual fun setUserProperty(name: String, value: String) {} + actual fun setUserId(id: String) {} + actual fun resetAnalyticsData() {} + actual fun setAnalyticsCollectionEnabled(enabled: Boolean) {} + actual fun setSessionTimeoutInterval(sessionTimeoutInterval: Long) {} + actual suspend fun getSessionId(): Long? = TODO("Not yet implemented") + actual fun setDefaultEventParameters(parameters: Map) {} +} + +actual class FirebaseAnalyticsException internal constructor(message: String) : FirebaseException(message) \ No newline at end of file diff --git a/firebase-analytics/src/jvmTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/jvmTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt new file mode 100644 index 000000000..d907efc70 --- /dev/null +++ b/firebase-analytics/src/jvmTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2020 GitLive Ltd. Use of this source code is governed by the Apache 2.0 license. + */ + +@file:JvmName("tests") +package dev.gitlive.firebase.analytics + +actual val emulatorHost: String = "10.0.2.2" + +actual val context: Any = Unit + +@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) +actual annotation class IgnoreForAndroidUnitTest diff --git a/gradle.properties b/gradle.properties index 19068e9f3..66cabb376 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,6 +21,7 @@ kotlin.native.cacheKind=none # Set to true to skip tests and even compilation of the iOS target. skipIosTarget=false # Skip iOS Tests +firebase-analytics.skipIosTests=false firebase-app.skipIosTests=false # We are skipping auth ios tests due to an issue with keychain and simulator. firebase-auth.skipIosTests=true @@ -36,6 +37,7 @@ firebase-crashlytics.skipIosTests=false firebase-storage.skipIosTests=false # We can have the functionality to skip js tests, due to compatibility issues. +firebase-analytics.skipJsTests=false firebase-app.skipJsTests=false firebase-auth.skipJsTests=false firebase-common.skipJsTests=false @@ -49,6 +51,7 @@ firebase-perf.skipJsTests=false firebase-storage.skipJsTests=false # Versions: +firebase-analytics.version=1.12.0 firebase-app.version=1.12.0 firebase-auth.version=1.12.0 firebase-common.version=1.12.0 diff --git a/settings.gradle.kts b/settings.gradle.kts index 68af478a5..e0c99ccbd 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,4 +1,5 @@ include( + "firebase-analytics", "firebase-app", "firebase-auth", "firebase-common", From c6c591c9283de31c24b6cbcd5f3d1aee3ecb7464 Mon Sep 17 00:00:00 2001 From: Bas Buijsen Date: Thu, 6 Jun 2024 21:03:30 +0200 Subject: [PATCH 2/9] add ktx syntax and publishing config --- .github/workflows/publish.yml | 2 ++ build.gradle.kts | 1 + .../gitlive/firebase/analytics/analytics.kt | 4 ++-- .../gitlive/firebase/analytics/analytics.kt | 2 +- .../gitlive/firebase/analytics/analytics.kt | 21 +++++++++++++++++++ .../gitlive/firebase/analytics/analytics.kt | 6 +++--- .../gitlive/firebase/analytics/analytics.kt | 2 +- .../firebase/analytics/externals/analytics.kt | 2 +- .../firebase/analytics/analytics.jvm.kt | 2 +- 9 files changed, 33 insertions(+), 9 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 4f2821da7..f90211abb 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -28,6 +28,8 @@ jobs: run: ./gradlew :updateVersions - name: Grant execute permission for gradlew run: chmod +x gradlew + - name: Publish Firebase Analytics + run: ./gradlew :firebase-analytics:publish - name: Publish Firebase App run: ./gradlew :firebase-app:publish - name: Publish Firebase Auth diff --git a/build.gradle.kts b/build.gradle.kts index 7754e37c0..498970785 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -36,6 +36,7 @@ val minSdkVersion by extra(23) tasks { register("updateVersions") { dependsOn( + "firebase-analytics:updateVersion", "firebase-analytics:updateDependencyVersion", "firebase-app:updateVersion", "firebase-app:updateDependencyVersion", "firebase-auth:updateVersion", "firebase-auth:updateDependencyVersion", "firebase-common:updateVersion", "firebase-common:updateDependencyVersion", diff --git a/firebase-analytics/src/androidMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/androidMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt index de6243148..d412b5dd0 100644 --- a/firebase-analytics/src/androidMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt +++ b/firebase-analytics/src/androidMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -9,8 +9,8 @@ actual val Firebase.analytics: FirebaseAnalytics get() = FirebaseAnalytics(com.google.firebase.Firebase.analytics) actual class FirebaseAnalytics(val android: com.google.firebase.analytics.FirebaseAnalytics) { - actual fun logEvent(name: String, parameters: Map) { - android.logEvent(name, parameters.toBundle()) + actual fun logEvent(name: String, parameters: Map?) { + android.logEvent(name, parameters?.toBundle()) } actual fun logEvent(name: String, block: FirebaseAnalyticsParameters.() -> Unit) { val params = FirebaseAnalyticsParameters() diff --git a/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt index 30dac8071..f045972ce 100644 --- a/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt +++ b/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -5,7 +5,7 @@ import dev.gitlive.firebase.Firebase expect val Firebase.analytics: FirebaseAnalytics expect class FirebaseAnalytics { - fun logEvent(name: String, parameters: Map) + fun logEvent(name: String, parameters: Map? = null) fun logEvent(name: String, block: FirebaseAnalyticsParameters.() -> Unit) fun setUserProperty(name: String, value: String) fun setUserId(id: String) diff --git a/firebase-analytics/src/commonTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/commonTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt index 9e95eaa6e..ae05df26a 100644 --- a/firebase-analytics/src/commonTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt +++ b/firebase-analytics/src/commonTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -8,7 +8,11 @@ import dev.gitlive.firebase.Firebase import dev.gitlive.firebase.FirebaseOptions import dev.gitlive.firebase.apps import dev.gitlive.firebase.initialize +import dev.gitlive.firebase.runBlockingTest +import kotlin.test.AfterTest import kotlin.test.BeforeTest +import kotlin.test.Test +import kotlin.test.assertNotNull expect val emulatorHost: String expect val context: Any @@ -35,4 +39,21 @@ class FirebaseAnalyticsTest { analytics = Firebase.analytics } + + @AfterTest + fun deinitializeFirebase() = runBlockingTest { + Firebase.apps(context).forEach { + it.delete() + } + } + + @Test + fun testAnalyticsShouldNotCrash() { + assertNotNull(analytics) + + // This should not crash, otherwise the test will fail + analytics.logEvent("test") { + param("key", "value") + } + } } \ No newline at end of file diff --git a/firebase-analytics/src/iosMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/iosMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt index b29c98a77..a478cb53f 100644 --- a/firebase-analytics/src/iosMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt +++ b/firebase-analytics/src/iosMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -11,10 +11,10 @@ actual val Firebase.analytics: FirebaseAnalytics get() = FirebaseAnalytics(FIRAnalytics) actual class FirebaseAnalytics(val ios: FIRAnalytics.Companion) { - actual fun logEvent(name: String, parameters: Map) { - val mappedParameters: Map = parameters.map { + actual fun logEvent(name: String, parameters: Map?) { + val mappedParameters: Map? = parameters?.map { it.key to it.value - }.toMap() + }?.toMap() ios.logEventWithName(name, mappedParameters) } actual fun logEvent(name: String, block: FirebaseAnalyticsParameters.() -> Unit) { diff --git a/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt index 944ffaeb2..6377a921d 100644 --- a/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt +++ b/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -19,7 +19,7 @@ actual val Firebase.analytics: FirebaseAnalytics actual class FirebaseAnalytics(val js: dev.gitlive.firebase.analytics.externals.FirebaseAnalytics) { actual fun logEvent( name: String, - parameters: Map + parameters: Map? ) { jsLogEvent(js, name, parameters) } diff --git a/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/externals/analytics.kt b/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/externals/analytics.kt index 416f39383..26c3d2ac2 100644 --- a/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/externals/analytics.kt +++ b/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/externals/analytics.kt @@ -6,7 +6,7 @@ import kotlin.js.Promise external fun getAnalytics(app: FirebaseApp? = definedExternally): FirebaseAnalytics -external fun jsLogEvent(app: FirebaseAnalytics, name: String, parameters: Map) +external fun jsLogEvent(app: FirebaseAnalytics, name: String, parameters: Map?) external fun jsSetUserProperty(app: FirebaseAnalytics, name: String, value: String) external fun jsSetUserId(app: FirebaseAnalytics, id: String) external fun jsResetAnalyticsData(app: FirebaseAnalytics) diff --git a/firebase-analytics/src/jvmMain/kotlin/dev/gitlive/firebase/analytics/analytics.jvm.kt b/firebase-analytics/src/jvmMain/kotlin/dev/gitlive/firebase/analytics/analytics.jvm.kt index f714eef30..c17209eb7 100644 --- a/firebase-analytics/src/jvmMain/kotlin/dev/gitlive/firebase/analytics/analytics.jvm.kt +++ b/firebase-analytics/src/jvmMain/kotlin/dev/gitlive/firebase/analytics/analytics.jvm.kt @@ -7,7 +7,7 @@ actual val Firebase.analytics: FirebaseAnalytics get() = TODO("Not yet implemented") actual class FirebaseAnalytics { - actual fun logEvent(name: String, parameters: Map) {} + actual fun logEvent(name: String, parameters: Map?) {} actual fun logEvent(name: String, block: FirebaseAnalyticsParameters.() -> Unit) {} actual fun setUserProperty(name: String, value: String) {} actual fun setUserId(id: String) {} From 744b704d7b1624157a74c6c667ab3d6f71d6addf Mon Sep 17 00:00:00 2001 From: Bas Buijsen Date: Fri, 7 Jun 2024 12:25:02 +0200 Subject: [PATCH 3/9] add all constants --- .../analytics/AnalyticEventConstants.kt | 123 ++++++++++++++++++ .../gitlive/firebase/analytics/analytics.kt | 38 ------ 2 files changed, 123 insertions(+), 38 deletions(-) create mode 100644 firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/AnalyticEventConstants.kt diff --git a/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/AnalyticEventConstants.kt b/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/AnalyticEventConstants.kt new file mode 100644 index 000000000..9f562b057 --- /dev/null +++ b/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/AnalyticEventConstants.kt @@ -0,0 +1,123 @@ +package dev.gitlive.firebase.analytics + +val FirebaseAnalytics.Event: FirebaseAnalyticsEvents + get() = FirebaseAnalyticsEvents + +object FirebaseAnalyticsEvents { + const val ADD_PAYMENT_INFO: String = "add_payment_info" + const val ADD_SHIPPING_INFO: String = "add_shipping_info" + const val ADD_TO_CART: String = "add_to_cart" + const val ADD_TO_WISHLIST: String = "add_to_wishlist" + const val AD_IMPRESSION: String = "ad_impression" + const val APP_OPEN: String = "app_open" + const val BEGIN_CHECKOUT: String = "begin_checkout" + const val CAMPAIGN_DETAILS: String = "campaign_details" + const val EARN_VIRTUAL_CURRENCY: String = "earn_virtual_currency" + const val GENERATE_LEAD: String = "generate_lead" + const val JOIN_GROUP: String = "join_group" + const val LEVEL_END: String = "level_end" + const val LEVEL_START: String = "level_start" + const val LEVEL_UP: String = "level_up" + const val LOGIN: String = "login" + const val POST_SCORE: String = "post_score" + const val PURCHASE: String = "purchase" + const val REFUND: String = "refund" + const val REMOVE_FROM_CART: String = "remove_from_cart" + const val SCREEN_VIEW: String = "screen_view" + const val SEARCH: String = "search" + const val SELECT_CONTENT: String = "select_content" + const val SELECT_ITEM: String = "select_item" + const val SELECT_PROMOTION: String = "select_promotion" + const val SHARE: String = "share" + const val SIGN_UP: String = "sign_up" + const val SPEND_VIRTUAL_CURRENCY: String = "spend_virtual_currency" + const val TUTORIAL_BEGIN: String = "tutorial_begin" + const val TUTORIAL_COMPLETE: String = "tutorial_complete" + const val UNLOCK_ACHIEVEMENT: String = "unlock_achievement" + const val VIEW_CART: String = "view_cart" + const val VIEW_ITEM: String = "view_item" + const val VIEW_ITEM_LIST: String = "view_item_list" + const val VIEW_PROMOTION: String = "view_promotion" + const val VIEW_SEARCH_RESULTS: String = "view_search_results" +} + +val FirebaseAnalytics.Param: FirebaseAnalyticsParam + get() = FirebaseAnalyticsParam + +object FirebaseAnalyticsParam { + const val ACHIEVEMENT_ID: String = "achievement_id" + const val ACLID: String = "aclid" + const val AD_FORMAT: String = "ad_format" + const val AD_PLATFORM: String = "ad_platform" + const val AD_SOURCE: String = "ad_source" + const val AD_UNIT_NAME: String = "ad_unit_name" + const val AFFILIATION: String = "affiliation" + const val CAMPAIGN: String = "campaign" + const val CAMPAIGN_ID: String = "campaign_id" + const val CHARACTER: String = "character" + const val CONTENT: String = "content" + const val CONTENT_TYPE: String = "content_type" + const val COUPON: String = "coupon" + const val CP1: String = "cp1" + const val CREATIVE_FORMAT: String = "creative_format" + const val CREATIVE_NAME: String = "creative_name" + const val CREATIVE_SLOT: String = "creative_slot" + const val CURRENCY: String = "currency" + const val DESTINATION: String = "destination" + const val DISCOUNT: String = "discount" + const val END_DATE: String = "end_date" + const val EXTEND_SESSION: String = "extend_session" + const val FLIGHT_NUMBER: String = "flight_number" + const val GROUP_ID: String = "group_id" + const val INDEX: String = "index" + const val ITEMS: String = "items" + const val ITEM_BRAND: String = "item_brand" + const val ITEM_CATEGORY: String = "item_category" + const val ITEM_CATEGORY2: String = "item_category2" + const val ITEM_CATEGORY3: String = "item_category3" + const val ITEM_CATEGORY4: String = "item_category4" + const val ITEM_CATEGORY5: String = "item_category5" + const val ITEM_ID: String = "item_id" + const val ITEM_LIST_ID: String = "item_list_id" + const val ITEM_LIST_NAME: String = "item_list_name" + const val ITEM_NAME: String = "item_name" + const val ITEM_VARIANT: String = "item_variant" + const val LEVEL: String = "level" + const val LEVEL_NAME: String = "level_name" + const val LOCATION: String = "location" + const val LOCATION_ID: String = "location_id" + const val MARKETING_TACTIC: String = "marketing_tactic" + const val MEDIUM: String = "medium" + const val METHOD: String = "method" + const val NUMBER_OF_NIGHTS: String = "number_of_nights" + const val NUMBER_OF_PASSENGERS: String = "number_of_passengers" + const val NUMBER_OF_ROOMS: String = "number_of_rooms" + const val ORIGIN: String = "origin" + const val PAYMENT_TYPE: String = "payment_type" + const val PRICE: String = "price" + const val PROMOTION_ID: String = "promotion_id" + const val PROMOTION_NAME: String = "promotion_name" + const val QUANTITY: String = "quantity" + const val SCORE: String = "score" + const val SEARCH_TERM: String = "search_term" + const val SHIPPING: String = "shipping" + const val SHIPPING_TIER: String = "shipping_tier" + const val SOURCE: String = "source" + const val SOURCE_PLATFORM: String = "source_platform" + const val START_DATE: String = "start_date" + const val SUCCESS: String = "success" + const val TAX: String = "tax" + const val TERM: String = "term" + const val TRANSACTION_ID: String = "transaction_id" + const val TRAVEL_CLASS: String = "travel_class" + const val VALUE: String = "value" + const val VIRTUAL_CURRENCY_NAME: String = "virtual_currency_name" +} + +val FirebaseAnalytics.UserProperty: FirebaseAnalyticsUserProperty + get() = FirebaseAnalyticsUserProperty + +object FirebaseAnalyticsUserProperty { + const val ALLOW_AD_PERSONALIZATION_SIGNALS: String = "allow_personalized_ads" + const val SIGN_UP_METHOD: String = "sign_up_method" +} \ No newline at end of file diff --git a/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt index f045972ce..d86c4495f 100644 --- a/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt +++ b/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -24,42 +24,4 @@ data class FirebaseAnalyticsParameters( fun param(key: String, value: String) { parameters[key] = value } -} - -object FirebaseAnalyticsEvents { - const val ADD_PAYMENT_INFO: String = "add_payment_info" - const val ADD_SHIPPING_INFO: String = "add_shipping_info" - const val ADD_TO_CART: String = "add_to_cart" - const val ADD_TO_WISHLIST: String = "add_to_wishlist" - const val AD_IMPRESSION: String = "ad_impression" - const val APP_OPEN: String = "app_open" - const val BEGIN_CHECKOUT: String = "begin_checkout" - const val CAMPAIGN_DETAILS: String = "campaign_details" - const val EARN_VIRTUAL_CURRENCY: String = "earn_virtual_currency" - const val GENERATE_LEAD: String = "generate_lead" - const val JOIN_GROUP: String = "join_group" - const val LEVEL_END: String = "level_end" - const val LEVEL_START: String = "level_start" - const val LEVEL_UP: String = "level_up" - const val LOGIN: String = "login" - const val POST_SCORE: String = "post_score" - const val PURCHASE: String = "purchase" - const val REFUND: String = "refund" - const val REMOVE_FROM_CART: String = "remove_from_cart" - const val SCREEN_VIEW: String = "screen_view" - const val SEARCH: String = "search" - const val SELECT_CONTENT: String = "select_content" - const val SELECT_ITEM: String = "select_item" - const val SELECT_PROMOTION: String = "select_promotion" - const val SHARE: String = "share" - const val SIGN_UP: String = "sign_up" - const val SPEND_VIRTUAL_CURRENCY: String = "spend_virtual_currency" - const val TUTORIAL_BEGIN: String = "tutorial_begin" - const val TUTORIAL_COMPLETE: String = "tutorial_complete" - const val UNLOCK_ACHIEVEMENT: String = "unlock_achievement" - const val VIEW_CART: String = "view_cart" - const val VIEW_ITEM: String = "view_item" - const val VIEW_ITEM_LIST: String = "view_item_list" - const val VIEW_PROMOTION: String = "view_promotion" - const val VIEW_SEARCH_RESULTS: String = "view_search_results" } \ No newline at end of file From 35df799b3dccf550e84b427e1db79c876a841575 Mon Sep 17 00:00:00 2001 From: Bas Buijsen Date: Fri, 7 Jun 2024 12:58:42 +0200 Subject: [PATCH 4/9] add setConsent --- .../gitlive/firebase/analytics/analytics.kt | 41 +++++++++++++++++++ .../analytics/AnalyticEventConstants.kt | 2 +- .../gitlive/firebase/analytics/analytics.kt | 13 ++++++ .../gitlive/firebase/analytics/analytics.kt | 20 +++++++++ .../gitlive/firebase/analytics/analytics.kt | 41 +++++++++++++++---- .../firebase/analytics/externals/analytics.kt | 29 +++++++++---- 6 files changed, 128 insertions(+), 18 deletions(-) diff --git a/firebase-analytics/src/androidMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/androidMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt index d412b5dd0..6face1faa 100644 --- a/firebase-analytics/src/androidMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt +++ b/firebase-analytics/src/androidMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -2,6 +2,7 @@ package dev.gitlive.firebase.analytics import android.os.Bundle import com.google.firebase.analytics.analytics +import com.google.firebase.analytics.setConsent import dev.gitlive.firebase.Firebase import kotlinx.coroutines.tasks.await @@ -39,6 +40,46 @@ actual class FirebaseAnalytics(val android: com.google.firebase.analytics.Fireba } actual suspend fun getSessionId(): Long? = android.sessionId.await() + + actual fun setConsent(consentSettings: Map) { + consentSettings.entries.associate { + it.key to when (it.value) { + ConsentStatus.GRANTED -> com.google.firebase.analytics.FirebaseAnalytics.ConsentStatus.GRANTED + ConsentStatus.DENIED -> com.google.firebase.analytics.FirebaseAnalytics.ConsentStatus.DENIED + } + }.let { androidConsentSettings -> + android.setConsent { + androidConsentSettings.entries.forEach { + when (it.key) { + ConsentType.AD_PERSONALIZATION -> + this.adUserData = it.value + + ConsentType.AD_STORAGE -> + this.adUserData = it.value + + ConsentType.AD_USER_DATA -> + this.adUserData = it.value + + ConsentType.ANALYTICS_STORAGE -> + this.adUserData = it.value + } + } + + } + } + } + + actual enum class ConsentType { + AD_PERSONALIZATION, + AD_STORAGE, + AD_USER_DATA, + ANALYTICS_STORAGE + } + + actual enum class ConsentStatus { + GRANTED, + DENIED + } } actual class FirebaseAnalyticsException(message: String): Exception(message) diff --git a/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/AnalyticEventConstants.kt b/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/AnalyticEventConstants.kt index 9f562b057..0484537d1 100644 --- a/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/AnalyticEventConstants.kt +++ b/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/AnalyticEventConstants.kt @@ -120,4 +120,4 @@ val FirebaseAnalytics.UserProperty: FirebaseAnalyticsUserProperty object FirebaseAnalyticsUserProperty { const val ALLOW_AD_PERSONALIZATION_SIGNALS: String = "allow_personalized_ads" const val SIGN_UP_METHOD: String = "sign_up_method" -} \ No newline at end of file +} diff --git a/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt index d86c4495f..cdc9cca84 100644 --- a/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt +++ b/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -14,6 +14,19 @@ expect class FirebaseAnalytics { suspend fun getSessionId(): Long? fun resetAnalyticsData() fun setDefaultEventParameters(parameters: Map) + fun setConsent(consentSettings: Map) + + enum class ConsentType { + AD_PERSONALIZATION, + AD_STORAGE, + AD_USER_DATA, + ANALYTICS_STORAGE + } + + enum class ConsentStatus { + GRANTED, + DENIED + } } expect class FirebaseAnalyticsException diff --git a/firebase-analytics/src/iosMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/iosMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt index a478cb53f..1f7c21c62 100644 --- a/firebase-analytics/src/iosMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt +++ b/firebase-analytics/src/iosMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -1,6 +1,7 @@ package dev.gitlive.firebase.analytics import cocoapods.FirebaseAnalytics.FIRAnalytics +import cocoapods.FirebaseAnalytics.setConsent import dev.gitlive.firebase.Firebase import dev.gitlive.firebase.FirebaseException import kotlinx.coroutines.CompletableDeferred @@ -48,6 +49,25 @@ actual class FirebaseAnalytics(val ios: FIRAnalytics.Companion) { }.toMap() ios.setDefaultEventParameters(mappedParameters) } + + actual fun setConsent(consentSettings: Map) { + val mappedConsentSettings: Map = consentSettings.map { + it.key.name to it.value.name + }.toMap() + ios.setConsent(mappedConsentSettings) + } + + actual enum class ConsentType { + AD_PERSONALIZATION, + AD_STORAGE, + AD_USER_DATA, + ANALYTICS_STORAGE + } + + actual enum class ConsentStatus { + GRANTED, + DENIED + } } actual class FirebaseAnalyticsException(message: String): FirebaseException(message) diff --git a/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt index 6377a921d..e57bb3ebe 100644 --- a/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt +++ b/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -21,7 +21,7 @@ actual class FirebaseAnalytics(val js: dev.gitlive.firebase.analytics.externals. name: String, parameters: Map? ) { - jsLogEvent(js, name, parameters) + dev.gitlive.firebase.analytics.externals.logEvent(js, name, parameters) } actual fun logEvent( @@ -34,29 +34,54 @@ actual class FirebaseAnalytics(val js: dev.gitlive.firebase.analytics.externals. } actual fun setUserProperty(name: String, value: String) { - jsSetUserProperty(js, name, value) + dev.gitlive.firebase.analytics.externals.setUserProperty(js, name, value) } actual fun setUserId(id: String) { - jsSetUserId(js, id) + dev.gitlive.firebase.analytics.externals.setUserId(js, id) } actual fun setAnalyticsCollectionEnabled(enabled: Boolean) { - jsSetAnalyticsCollectionEnabled(js, enabled) + dev.gitlive.firebase.analytics.externals.setAnalyticsCollectionEnabled(js, enabled) } actual fun setSessionTimeoutInterval(sessionTimeoutInterval: Long) { - jsSetSessionTimeoutInterval(js, sessionTimeoutInterval) + dev.gitlive.firebase.analytics.externals.setSessionTimeoutInterval(js, sessionTimeoutInterval) } - actual suspend fun getSessionId(): Long? = rethrow { jsGetSessionId(js).await() } + actual suspend fun getSessionId(): Long? = rethrow { dev.gitlive.firebase.analytics.externals.getSessionId(js).await() } actual fun resetAnalyticsData() { - jsResetAnalyticsData(js) + dev.gitlive.firebase.analytics.externals.resetAnalyticsData(js) } actual fun setDefaultEventParameters(parameters: Map) { - jsSetDefaultEventParameters(js, parameters) + dev.gitlive.firebase.analytics.externals.setDefaultEventParameters(js, parameters) + } + + actual fun setConsent(consentSettings: Map) { + val consent = dev.gitlive.firebase.analytics.externals.ConsentSettings() + consentSettings.forEach { + when (it.key) { + ConsentType.AD_PERSONALIZATION -> consent.ad_personalization = it.value.name + ConsentType.AD_STORAGE -> consent.ad_storage = it.value.name + ConsentType.AD_USER_DATA -> consent.ad_user_data = it.value.name + ConsentType.ANALYTICS_STORAGE -> consent.analytics_storage = it.value.name + } + } + dev.gitlive.firebase.analytics.externals.setConsent(js, consent) + } + + actual enum class ConsentType { + AD_PERSONALIZATION, + AD_STORAGE, + AD_USER_DATA, + ANALYTICS_STORAGE + } + + actual enum class ConsentStatus { + GRANTED, + DENIED } } diff --git a/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/externals/analytics.kt b/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/externals/analytics.kt index 26c3d2ac2..cddea67e9 100644 --- a/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/externals/analytics.kt +++ b/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/externals/analytics.kt @@ -6,13 +6,24 @@ import kotlin.js.Promise external fun getAnalytics(app: FirebaseApp? = definedExternally): FirebaseAnalytics -external fun jsLogEvent(app: FirebaseAnalytics, name: String, parameters: Map?) -external fun jsSetUserProperty(app: FirebaseAnalytics, name: String, value: String) -external fun jsSetUserId(app: FirebaseAnalytics, id: String) -external fun jsResetAnalyticsData(app: FirebaseAnalytics) -external fun jsSetDefaultEventParameters(app: FirebaseAnalytics, parameters: Map) -external fun jsSetAnalyticsCollectionEnabled(app: FirebaseAnalytics, enabled: Boolean) -external fun jsSetSessionTimeoutInterval(app: FirebaseAnalytics, sessionTimeoutInterval: Long) -external fun jsGetSessionId(app: FirebaseAnalytics): Promise +external fun logEvent(app: FirebaseAnalytics, name: String, parameters: Map?) +external fun setUserProperty(app: FirebaseAnalytics, name: String, value: String) +external fun setUserId(app: FirebaseAnalytics, id: String) +external fun resetAnalyticsData(app: FirebaseAnalytics) +external fun setDefaultEventParameters(app: FirebaseAnalytics, parameters: Map) +external fun setAnalyticsCollectionEnabled(app: FirebaseAnalytics, enabled: Boolean) +external fun setSessionTimeoutInterval(app: FirebaseAnalytics, sessionTimeoutInterval: Long) +external fun getSessionId(app: FirebaseAnalytics): Promise +external fun setConsent(app: FirebaseAnalytics, consentSettings: ConsentSettings) -external interface FirebaseAnalytics \ No newline at end of file +external interface FirebaseAnalytics + +external class ConsentSettings() { + var ad_personalization: String? + var ad_storage: String? + var ad_user_data: String? + var analytics_storage: String? + var functionality_storage: String? + var personalization_storage: String? + var security_storage: String? +} From 65ab6cc6ad90a59dfdef161ac9704f69a4e5a07a Mon Sep 17 00:00:00 2001 From: Bas Buijsen Date: Fri, 7 Jun 2024 13:09:00 +0200 Subject: [PATCH 5/9] add builders as extensions --- .../gitlive/firebase/analytics/analytics.kt | 11 ++--- .../gitlive/firebase/analytics/analytics.kt | 49 ++++++++++++++++++- .../gitlive/firebase/analytics/analytics.kt | 5 -- .../gitlive/firebase/analytics/analytics.kt | 17 ------- 4 files changed, 51 insertions(+), 31 deletions(-) diff --git a/firebase-analytics/src/androidMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/androidMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt index 6face1faa..24256d461 100644 --- a/firebase-analytics/src/androidMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt +++ b/firebase-analytics/src/androidMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -13,11 +13,6 @@ actual class FirebaseAnalytics(val android: com.google.firebase.analytics.Fireba actual fun logEvent(name: String, parameters: Map?) { android.logEvent(name, parameters?.toBundle()) } - actual fun logEvent(name: String, block: FirebaseAnalyticsParameters.() -> Unit) { - val params = FirebaseAnalyticsParameters() - params.block() - logEvent(name, params.parameters) - } actual fun setUserProperty(name: String, value: String) { android.setUserProperty(name, value) } @@ -52,16 +47,16 @@ actual class FirebaseAnalytics(val android: com.google.firebase.analytics.Fireba androidConsentSettings.entries.forEach { when (it.key) { ConsentType.AD_PERSONALIZATION -> - this.adUserData = it.value + this.adPersonalization = it.value ConsentType.AD_STORAGE -> - this.adUserData = it.value + this.adStorage = it.value ConsentType.AD_USER_DATA -> this.adUserData = it.value ConsentType.ANALYTICS_STORAGE -> - this.adUserData = it.value + this.analyticsStorage = it.value } } diff --git a/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt index cdc9cca84..8e8c8f2e4 100644 --- a/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt +++ b/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -6,7 +6,6 @@ expect val Firebase.analytics: FirebaseAnalytics expect class FirebaseAnalytics { fun logEvent(name: String, parameters: Map? = null) - fun logEvent(name: String, block: FirebaseAnalyticsParameters.() -> Unit) fun setUserProperty(name: String, value: String) fun setUserId(id: String) fun setAnalyticsCollectionEnabled(enabled: Boolean) @@ -29,6 +28,18 @@ expect class FirebaseAnalytics { } } +fun FirebaseAnalytics.setConsent(builder: FirebaseAnalyticsConsentBuilder.() -> Unit) { + val consentBuilder = FirebaseAnalyticsConsentBuilder() + consentBuilder.builder() + setConsent(consentBuilder.consentSettings) +} + +fun FirebaseAnalytics.logEvent(name: String, builder: FirebaseAnalyticsParameters.() -> Unit) { + val params = FirebaseAnalyticsParameters() + params.builder() + logEvent(name, params.parameters) +} + expect class FirebaseAnalyticsException data class FirebaseAnalyticsParameters( @@ -37,4 +48,40 @@ data class FirebaseAnalyticsParameters( fun param(key: String, value: String) { parameters[key] = value } +} + +data class FirebaseAnalyticsConsentBuilder( + val consentSettings: MutableMap = mutableMapOf() +) { + var adPersonalization: FirebaseAnalytics.ConsentStatus? + get() = consentSettings[FirebaseAnalytics.ConsentType.AD_PERSONALIZATION] + set(value) { + value?.let { + consentSettings[FirebaseAnalytics.ConsentType.AD_PERSONALIZATION] = it + } + } + + var adStorage: FirebaseAnalytics.ConsentStatus? + get() = consentSettings[FirebaseAnalytics.ConsentType.AD_STORAGE] + set(value) { + value?.let { + consentSettings[FirebaseAnalytics.ConsentType.AD_STORAGE] = it + } + } + + var adUserData: FirebaseAnalytics.ConsentStatus? + get() = consentSettings[FirebaseAnalytics.ConsentType.AD_USER_DATA] + set(value) { + value?.let { + consentSettings[FirebaseAnalytics.ConsentType.AD_USER_DATA] = it + } + } + + var analyticsStorage: FirebaseAnalytics.ConsentStatus? + get() = consentSettings[FirebaseAnalytics.ConsentType.ANALYTICS_STORAGE] + set(value) { + value?.let { + consentSettings[FirebaseAnalytics.ConsentType.ANALYTICS_STORAGE] = it + } + } } \ No newline at end of file diff --git a/firebase-analytics/src/iosMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/iosMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt index 1f7c21c62..ae722a131 100644 --- a/firebase-analytics/src/iosMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt +++ b/firebase-analytics/src/iosMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -18,11 +18,6 @@ actual class FirebaseAnalytics(val ios: FIRAnalytics.Companion) { }?.toMap() ios.logEventWithName(name, mappedParameters) } - actual fun logEvent(name: String, block: FirebaseAnalyticsParameters.() -> Unit) { - val params = FirebaseAnalyticsParameters() - params.block() - logEvent(name, params.parameters) - } actual fun setUserProperty(name: String, value: String) { ios.setUserPropertyString(value, name) } diff --git a/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt index e57bb3ebe..8b97032e6 100644 --- a/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt +++ b/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -3,14 +3,6 @@ package dev.gitlive.firebase.analytics import dev.gitlive.firebase.Firebase import dev.gitlive.firebase.FirebaseException import dev.gitlive.firebase.analytics.externals.getAnalytics -import dev.gitlive.firebase.analytics.externals.jsGetSessionId -import dev.gitlive.firebase.analytics.externals.jsLogEvent -import dev.gitlive.firebase.analytics.externals.jsResetAnalyticsData -import dev.gitlive.firebase.analytics.externals.jsSetAnalyticsCollectionEnabled -import dev.gitlive.firebase.analytics.externals.jsSetDefaultEventParameters -import dev.gitlive.firebase.analytics.externals.jsSetSessionTimeoutInterval -import dev.gitlive.firebase.analytics.externals.jsSetUserId -import dev.gitlive.firebase.analytics.externals.jsSetUserProperty import kotlinx.coroutines.await actual val Firebase.analytics: FirebaseAnalytics @@ -24,15 +16,6 @@ actual class FirebaseAnalytics(val js: dev.gitlive.firebase.analytics.externals. dev.gitlive.firebase.analytics.externals.logEvent(js, name, parameters) } - actual fun logEvent( - name: String, - block: FirebaseAnalyticsParameters.() -> Unit - ) { - val params = FirebaseAnalyticsParameters() - params.block() - logEvent(name, params.parameters) - } - actual fun setUserProperty(name: String, value: String) { dev.gitlive.firebase.analytics.externals.setUserProperty(js, name, value) } From 3861ba1058323782b60ea0f3b6ec975ecbcb892a Mon Sep 17 00:00:00 2001 From: Bas Buijsen Date: Fri, 7 Jun 2024 14:00:34 +0200 Subject: [PATCH 6/9] support more types for logging events --- .../gitlive/firebase/analytics/analytics.kt | 22 +++++++++++++++---- .../gitlive/firebase/analytics/analytics.kt | 20 +++++++++++++++-- .../gitlive/firebase/analytics/analytics.kt | 14 ++++-------- .../gitlive/firebase/analytics/analytics.kt | 2 +- .../firebase/analytics/externals/analytics.kt | 2 +- 5 files changed, 42 insertions(+), 18 deletions(-) diff --git a/firebase-analytics/src/androidMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/androidMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt index 24256d461..c95809c79 100644 --- a/firebase-analytics/src/androidMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt +++ b/firebase-analytics/src/androidMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -1,16 +1,21 @@ package dev.gitlive.firebase.analytics import android.os.Bundle +import android.os.IBinder +import android.os.Parcelable +import android.util.Size +import android.util.SizeF import com.google.firebase.analytics.analytics import com.google.firebase.analytics.setConsent import dev.gitlive.firebase.Firebase import kotlinx.coroutines.tasks.await +import java.io.Serializable actual val Firebase.analytics: FirebaseAnalytics get() = FirebaseAnalytics(com.google.firebase.Firebase.analytics) actual class FirebaseAnalytics(val android: com.google.firebase.analytics.FirebaseAnalytics) { - actual fun logEvent(name: String, parameters: Map?) { + actual fun logEvent(name: String, parameters: Map?) { android.logEvent(name, parameters?.toBundle()) } actual fun setUserProperty(name: String, value: String) { @@ -79,6 +84,15 @@ actual class FirebaseAnalytics(val android: com.google.firebase.analytics.Fireba actual class FirebaseAnalyticsException(message: String): Exception(message) -fun Map.toBundle() = Bundle().apply { - forEach { (key, value) -> putString(key, value) } -} +fun Map.toBundle() = Bundle().apply { + forEach { (key, value) -> + when(value::class) { + String::class -> putString(key, value as String) + Int::class -> putInt(key, value as Int) + Long::class -> putLong(key, value as Long) + Double::class -> putDouble(key, value as Double) + Boolean::class -> putBoolean(key, value as Boolean) + } + + } +} \ No newline at end of file diff --git a/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt index 8e8c8f2e4..462e46e86 100644 --- a/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt +++ b/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -5,7 +5,7 @@ import dev.gitlive.firebase.Firebase expect val Firebase.analytics: FirebaseAnalytics expect class FirebaseAnalytics { - fun logEvent(name: String, parameters: Map? = null) + fun logEvent(name: String, parameters: Map? = null) fun setUserProperty(name: String, value: String) fun setUserId(id: String) fun setAnalyticsCollectionEnabled(enabled: Boolean) @@ -43,11 +43,27 @@ fun FirebaseAnalytics.logEvent(name: String, builder: FirebaseAnalyticsParameter expect class FirebaseAnalyticsException data class FirebaseAnalyticsParameters( - val parameters: MutableMap = mutableMapOf() + val parameters: MutableMap = mutableMapOf() ) { fun param(key: String, value: String) { parameters[key] = value } + + fun param(key: String, value: Double) { + parameters[key] = value + } + + fun param(key: String, value: Long) { + parameters[key] = value + } + + fun param(key: String, value: Int) { + parameters[key] = value + } + + fun param(key: String, value: Boolean) { + parameters[key] = value + } } data class FirebaseAnalyticsConsentBuilder( diff --git a/firebase-analytics/src/iosMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/iosMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt index ae722a131..1421930f0 100644 --- a/firebase-analytics/src/iosMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt +++ b/firebase-analytics/src/iosMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -12,10 +12,8 @@ actual val Firebase.analytics: FirebaseAnalytics get() = FirebaseAnalytics(FIRAnalytics) actual class FirebaseAnalytics(val ios: FIRAnalytics.Companion) { - actual fun logEvent(name: String, parameters: Map?) { - val mappedParameters: Map? = parameters?.map { - it.key to it.value - }?.toMap() + actual fun logEvent(name: String, parameters: Map?) { + val mappedParameters: Map? = parameters?.map { it.key to it.value }?.toMap() ios.logEventWithName(name, mappedParameters) } actual fun setUserProperty(name: String, value: String) { @@ -39,16 +37,12 @@ actual class FirebaseAnalytics(val ios: FIRAnalytics.Companion) { actual suspend fun getSessionId(): Long? = ios.awaitResult { sessionIDWithCompletion(it) } actual fun setDefaultEventParameters(parameters: Map) { - val mappedParameters: Map = parameters.map { - it.key to it.value - }.toMap() + val mappedParameters: Map = parameters.map { it.key to it.value }.toMap() ios.setDefaultEventParameters(mappedParameters) } actual fun setConsent(consentSettings: Map) { - val mappedConsentSettings: Map = consentSettings.map { - it.key.name to it.value.name - }.toMap() + val mappedConsentSettings: Map = consentSettings.map { it.key.name to it.value.name }.toMap() ios.setConsent(mappedConsentSettings) } diff --git a/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt index 8b97032e6..525557515 100644 --- a/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt +++ b/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -11,7 +11,7 @@ actual val Firebase.analytics: FirebaseAnalytics actual class FirebaseAnalytics(val js: dev.gitlive.firebase.analytics.externals.FirebaseAnalytics) { actual fun logEvent( name: String, - parameters: Map? + parameters: Map? ) { dev.gitlive.firebase.analytics.externals.logEvent(js, name, parameters) } diff --git a/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/externals/analytics.kt b/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/externals/analytics.kt index cddea67e9..ed47438df 100644 --- a/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/externals/analytics.kt +++ b/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/externals/analytics.kt @@ -6,7 +6,7 @@ import kotlin.js.Promise external fun getAnalytics(app: FirebaseApp? = definedExternally): FirebaseAnalytics -external fun logEvent(app: FirebaseAnalytics, name: String, parameters: Map?) +external fun logEvent(app: FirebaseAnalytics, name: String, parameters: Map?) external fun setUserProperty(app: FirebaseAnalytics, name: String, value: String) external fun setUserId(app: FirebaseAnalytics, id: String) external fun resetAnalyticsData(app: FirebaseAnalytics) From ee1368238efeac1350da325dfb2f38552c96f700 Mon Sep 17 00:00:00 2001 From: Bas Buijsen Date: Fri, 7 Jun 2024 19:48:43 +0200 Subject: [PATCH 7/9] fix build for jvm --- .../dev/gitlive/firebase/analytics/analytics.kt | 3 ++- .../dev/gitlive/firebase/analytics/analytics.jvm.kt | 13 +++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/firebase-analytics/src/androidMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/androidMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt index c95809c79..266cd3234 100644 --- a/firebase-analytics/src/androidMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt +++ b/firebase-analytics/src/androidMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -1,3 +1,4 @@ +@file:JvmName("analyticsAndroid") package dev.gitlive.firebase.analytics import android.os.Bundle @@ -84,7 +85,7 @@ actual class FirebaseAnalytics(val android: com.google.firebase.analytics.Fireba actual class FirebaseAnalyticsException(message: String): Exception(message) -fun Map.toBundle() = Bundle().apply { +private fun Map.toBundle() = Bundle().apply { forEach { (key, value) -> when(value::class) { String::class -> putString(key, value as String) diff --git a/firebase-analytics/src/jvmMain/kotlin/dev/gitlive/firebase/analytics/analytics.jvm.kt b/firebase-analytics/src/jvmMain/kotlin/dev/gitlive/firebase/analytics/analytics.jvm.kt index c17209eb7..c112c6392 100644 --- a/firebase-analytics/src/jvmMain/kotlin/dev/gitlive/firebase/analytics/analytics.jvm.kt +++ b/firebase-analytics/src/jvmMain/kotlin/dev/gitlive/firebase/analytics/analytics.jvm.kt @@ -7,8 +7,6 @@ actual val Firebase.analytics: FirebaseAnalytics get() = TODO("Not yet implemented") actual class FirebaseAnalytics { - actual fun logEvent(name: String, parameters: Map?) {} - actual fun logEvent(name: String, block: FirebaseAnalyticsParameters.() -> Unit) {} actual fun setUserProperty(name: String, value: String) {} actual fun setUserId(id: String) {} actual fun resetAnalyticsData() {} @@ -16,6 +14,17 @@ actual class FirebaseAnalytics { actual fun setSessionTimeoutInterval(sessionTimeoutInterval: Long) {} actual suspend fun getSessionId(): Long? = TODO("Not yet implemented") actual fun setDefaultEventParameters(parameters: Map) {} + actual fun logEvent(name: String, parameters: Map?) {} + + actual fun setConsent(consentSettings: Map) {} + + actual enum class ConsentType { + AD_PERSONALIZATION, AD_STORAGE, AD_USER_DATA, ANALYTICS_STORAGE + } + + actual enum class ConsentStatus { + GRANTED, DENIED + } } actual class FirebaseAnalyticsException internal constructor(message: String) : FirebaseException(message) \ No newline at end of file From ef4fdab780a5844e82b8a9a592a4103ba009a519 Mon Sep 17 00:00:00 2001 From: Bas Buijsen Date: Fri, 14 Jun 2024 16:12:24 +0200 Subject: [PATCH 8/9] fix js build --- .../kotlin/dev/gitlive/firebase/analytics/analytics.kt | 4 ++++ .../kotlin/dev/gitlive/firebase/analytics/analytics.kt | 4 ++++ .../kotlin/dev/gitlive/firebase/analytics/analytics.kt | 2 +- .../kotlin/dev/gitlive/firebase/analytics/analytics.kt | 3 +++ .../kotlin/dev/gitlive/firebase/analytics/analytics.kt | 4 ++++ .../dev/gitlive/firebase/analytics/externals/analytics.kt | 3 +++ .../kotlin/dev/gitlive/firebase/analytics/analytics.kt | 8 ++++++++ .../dev/gitlive/firebase/analytics/analytics.jvm.kt | 5 +++++ 8 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 firebase-analytics/src/jsTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt diff --git a/firebase-analytics/src/androidMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/androidMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt index 266cd3234..31795e294 100644 --- a/firebase-analytics/src/androidMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt +++ b/firebase-analytics/src/androidMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -9,12 +9,16 @@ import android.util.SizeF import com.google.firebase.analytics.analytics import com.google.firebase.analytics.setConsent import dev.gitlive.firebase.Firebase +import dev.gitlive.firebase.FirebaseApp import kotlinx.coroutines.tasks.await import java.io.Serializable actual val Firebase.analytics: FirebaseAnalytics get() = FirebaseAnalytics(com.google.firebase.Firebase.analytics) +actual fun Firebase.analytics(app: FirebaseApp) = + FirebaseAnalytics(com.google.firebase.Firebase.analytics) + actual class FirebaseAnalytics(val android: com.google.firebase.analytics.FirebaseAnalytics) { actual fun logEvent(name: String, parameters: Map?) { android.logEvent(name, parameters?.toBundle()) diff --git a/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt index 462e46e86..a46f1688c 100644 --- a/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt +++ b/firebase-analytics/src/commonMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -1,9 +1,13 @@ package dev.gitlive.firebase.analytics import dev.gitlive.firebase.Firebase +import dev.gitlive.firebase.FirebaseApp expect val Firebase.analytics: FirebaseAnalytics +/** Returns the [FirebaseStorage] instance of a given [FirebaseApp]. */ +expect fun Firebase.analytics(app: FirebaseApp): FirebaseAnalytics + expect class FirebaseAnalytics { fun logEvent(name: String, parameters: Map? = null) fun setUserProperty(name: String, value: String) diff --git a/firebase-analytics/src/commonTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/commonTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt index ae05df26a..0cd25e326 100644 --- a/firebase-analytics/src/commonTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt +++ b/firebase-analytics/src/commonTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -37,7 +37,7 @@ class FirebaseAnalyticsTest { ) ) - analytics = Firebase.analytics + analytics = Firebase.analytics(app) } @AfterTest diff --git a/firebase-analytics/src/iosMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/iosMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt index 1421930f0..aee47cbb6 100644 --- a/firebase-analytics/src/iosMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt +++ b/firebase-analytics/src/iosMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -3,6 +3,7 @@ package dev.gitlive.firebase.analytics import cocoapods.FirebaseAnalytics.FIRAnalytics import cocoapods.FirebaseAnalytics.setConsent import dev.gitlive.firebase.Firebase +import dev.gitlive.firebase.FirebaseApp import dev.gitlive.firebase.FirebaseException import kotlinx.coroutines.CompletableDeferred import platform.Foundation.NSError @@ -11,6 +12,8 @@ import platform.Foundation.NSTimeInterval actual val Firebase.analytics: FirebaseAnalytics get() = FirebaseAnalytics(FIRAnalytics) +actual fun Firebase.analytics(app: FirebaseApp): FirebaseAnalytics = FirebaseAnalytics(FIRAnalytics) + actual class FirebaseAnalytics(val ios: FIRAnalytics.Companion) { actual fun logEvent(name: String, parameters: Map?) { val mappedParameters: Map? = parameters?.map { it.key to it.value }?.toMap() diff --git a/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt index 525557515..413203706 100644 --- a/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt +++ b/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -1,6 +1,7 @@ package dev.gitlive.firebase.analytics import dev.gitlive.firebase.Firebase +import dev.gitlive.firebase.FirebaseApp import dev.gitlive.firebase.FirebaseException import dev.gitlive.firebase.analytics.externals.getAnalytics import kotlinx.coroutines.await @@ -8,6 +9,9 @@ import kotlinx.coroutines.await actual val Firebase.analytics: FirebaseAnalytics get() = FirebaseAnalytics(getAnalytics()) +actual fun Firebase.analytics(app: FirebaseApp) = + FirebaseAnalytics(getAnalytics(app.js)) + actual class FirebaseAnalytics(val js: dev.gitlive.firebase.analytics.externals.FirebaseAnalytics) { actual fun logEvent( name: String, diff --git a/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/externals/analytics.kt b/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/externals/analytics.kt index ed47438df..ceded59d4 100644 --- a/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/externals/analytics.kt +++ b/firebase-analytics/src/jsMain/kotlin/dev/gitlive/firebase/analytics/externals/analytics.kt @@ -1,3 +1,6 @@ +@file:JsModule("firebase/analytics") +@file:JsNonModule + package dev.gitlive.firebase.analytics.externals import dev.gitlive.firebase.externals.FirebaseApp diff --git a/firebase-analytics/src/jsTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt b/firebase-analytics/src/jsTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt new file mode 100644 index 000000000..117266228 --- /dev/null +++ b/firebase-analytics/src/jsTest/kotlin/dev/gitlive/firebase/analytics/analytics.kt @@ -0,0 +1,8 @@ +package dev.gitlive.firebase.analytics + +actual val emulatorHost: String = "10.0.2.2" + +actual val context: Any = Unit + +@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) +actual annotation class IgnoreForAndroidUnitTest \ No newline at end of file diff --git a/firebase-analytics/src/jvmMain/kotlin/dev/gitlive/firebase/analytics/analytics.jvm.kt b/firebase-analytics/src/jvmMain/kotlin/dev/gitlive/firebase/analytics/analytics.jvm.kt index c112c6392..50fb3da39 100644 --- a/firebase-analytics/src/jvmMain/kotlin/dev/gitlive/firebase/analytics/analytics.jvm.kt +++ b/firebase-analytics/src/jvmMain/kotlin/dev/gitlive/firebase/analytics/analytics.jvm.kt @@ -1,11 +1,16 @@ package dev.gitlive.firebase.analytics import dev.gitlive.firebase.Firebase +import dev.gitlive.firebase.FirebaseApp import dev.gitlive.firebase.FirebaseException actual val Firebase.analytics: FirebaseAnalytics get() = TODO("Not yet implemented") +actual fun Firebase.analytics(app: FirebaseApp): FirebaseAnalytics { + TODO("Not yetimplemented") +} + actual class FirebaseAnalytics { actual fun setUserProperty(name: String, value: String) {} actual fun setUserId(id: String) {} From 084635f1a9a7d33689178d5d5f4244d51ea62859 Mon Sep 17 00:00:00 2001 From: Bas Buijsen Date: Sat, 15 Jun 2024 16:47:28 +0200 Subject: [PATCH 9/9] skip ios tests for analytics --- gradle.properties | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 9df89c692..3fc365770 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,7 +21,8 @@ kotlin.native.cacheKind=none # Set to true to skip tests and even compilation of the iOS target. skipIosTarget=false # Skip iOS Tests -firebase-analytics.skipIosTests=false +# We are skipping analytics ios tests due to an issue with cocoapods not working as expected with binary distributed dependencies +firebase-analytics.skipIosTests=true firebase-app.skipIosTests=false # We are skipping auth ios tests due to an issue with keychain and simulator. firebase-auth.skipIosTests=true