Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ ktor = "3.2.2"
publish-plugin = "0.34.0"
sqljs = "1.8.0"
copyWebpackPlugin = "9.1.0"
firebase-messaging = "24.0.0"
firebase-installations = "18.0.0"
play-services-base = "18.5.0"
datetime = "0.6.1"
androidx-core-ktx = "1.15.0"

[libraries]
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
Expand Down Expand Up @@ -58,6 +63,11 @@ androidx-test-ext-junit = { module = "androidx.test.ext:junit", version.ref = "a
androidx-test-runner = { module = "androidx.test:runner", version.ref = "androidx-test-runner" }
androidx-compose-ui-test-junit4 = { module = "androidx.compose.ui:ui-test-junit4", version.ref = "androidx-compose-ui" }
androidx-compose-ui-test-manifest = { module = "androidx.compose.ui:ui-test-manifest", version.ref = "androidx-compose-ui" }
firebase-messaging = { module = "com.google.firebase:firebase-messaging-ktx", version.ref = "firebase-messaging" }
firebase-installations = { module = "com.google.firebase:firebase-installations-ktx", version.ref = "firebase-installations" }
play-services-base = { module = "com.google.android.gms:play-services-base", version.ref = "play-services-base" }
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "datetime" }
androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "androidx-core-ktx" }

[plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,8 @@ public enum class ModuleDescription(
title = "Overlay",
description = "Floating debug panel over the app that updates in real time. Shows live key/value metrics."
),
FIREBASE_CLOUD_MESSAGING(
title = "Firebase Cloud Messaging",
description = "Inspect FCM tokens, installation id, delivered pushes and emulate notifications."
),
}
102 changes: 102 additions & 0 deletions module/firebase/firebase-cloud-messaging-stub/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

plugins {
alias(libs.plugins.kotlinMultiplatform)
alias(libs.plugins.androidLibrary)
alias(libs.plugins.jetbrainsCompose)
alias(libs.plugins.compose.compiler)
alias(libs.plugins.kotlinSerialization)
alias(libs.plugins.publish.plugin)
id("publish-convention")
}

group = "ru.bartwell.kick"
version = extra["libraryVersionName"] as String

kotlin {
androidTarget {
compilations.all {
compileTaskProvider.configure {
compilerOptions {
jvmTarget.set(JvmTarget.JVM_1_8)
}
}
}
}

@Suppress("OPT_IN_USAGE")
wasmJs {
browser()
}

jvm()

listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach {
it.binaries.framework {
baseName = "firebase-cloud-messaging-stub"
isStatic = true
}
}

sourceSets {
commonMain.dependencies {
implementation(projects.mainCore)
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.material3)
implementation(compose.materialIconsExtended)
implementation(libs.decompose)
implementation(libs.decompose.extensions.compose)
implementation(libs.decompose.essenty.lifecycle.coroutines)
implementation(libs.kotlinx.serialization.json)
implementation(libs.kotlinx.datetime)
}
commonTest.dependencies {
implementation(libs.kotlin.test)
}
androidMain.dependencies {
implementation(libs.androidx.activity.compose)
implementation(libs.firebase.messaging)
}
jvmMain.dependencies {
implementation(compose.desktop.currentOs)
}
wasmJsMain.dependencies {
implementation(libs.kotlinx.serialization.json)
}
iosTest.dependencies {
@OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class)
implementation(compose.uiTest)
implementation(libs.kotlin.test)
}
}

explicitApi()
}

android {
namespace = "ru.bartwell.kick"
compileSdk = 35

defaultConfig {
minSdk = 24
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}

buildFeatures {
compose = true
}
}

dependencies {
debugImplementation(libs.androidx.compose.ui.test.manifest)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ru.bartwell.kick.module.firebase.cloudmessaging

import com.google.firebase.messaging.RemoteMessage

public fun FirebaseCloudMessagingAccessor.handleFcm(message: RemoteMessage) {
// No-op in the stub artifact.
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package ru.bartwell.kick.module.firebase.cloudmessaging.core.data

import android.app.PendingIntent

public actual typealias PlatformPendingIntent = PendingIntent
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ru.bartwell.kick.module.firebase.cloudmessaging

import ru.bartwell.kick.module.firebase.cloudmessaging.core.data.FirebaseMessage

public class FirebaseCloudMessagingAccessor internal constructor() {
public fun log(message: FirebaseMessage) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package ru.bartwell.kick.module.firebase.cloudmessaging

import androidx.compose.runtime.Composable
import com.arkivanov.decompose.ComponentContext
import com.arkivanov.decompose.router.stack.StackNavigation
import kotlinx.serialization.modules.PolymorphicModuleBuilder
import ru.bartwell.kick.core.component.Child
import ru.bartwell.kick.core.component.Config
import ru.bartwell.kick.core.component.StubConfig
import ru.bartwell.kick.core.data.Module
import ru.bartwell.kick.core.data.ModuleDescription
import ru.bartwell.kick.core.data.PlatformContext

@Suppress("UNUSED_PARAMETER")
public class FirebaseCloudMessagingModule(
context: PlatformContext,
) : Module {

override val description: ModuleDescription = ModuleDescription.FIREBASE_CLOUD_MESSAGING
override val startConfig: Config = StubConfig(description)

override fun getComponent(
componentContext: ComponentContext,
nav: StackNavigation<Config>,
config: Config,
): Child<*>? = null

@Composable
override fun Content(instance: Child<*>) {}

override fun registerSubclasses(builder: PolymorphicModuleBuilder<Config>) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package ru.bartwell.kick.module.firebase.cloudmessaging

import ru.bartwell.kick.Kick

public val Kick.Companion.firebaseCloudMessaging: FirebaseCloudMessagingAccessor
get() = FirebaseCloudMessagingAccessor()
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package ru.bartwell.kick.module.firebase.cloudmessaging.core.data

public data class FirebaseLocalNotificationRequest(
val title: String?,
val body: String?,
val data: Map<String, String>,
val channelId: String?,
val channelName: String? = null,
val channelImportance: FirebaseNotificationImportance? = null,
val smallIconResId: Int? = null,
val pendingIntent: PlatformPendingIntent? = null,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package ru.bartwell.kick.module.firebase.cloudmessaging.core.data

/**
* Lightweight representation of a Firebase Cloud Messaging push notification.
*/
public data class FirebaseMessage(
val title: String? = null,
val body: String? = null,
val data: Map<String, String> = emptyMap(),
val from: String? = null,
val to: String? = null,
val messageId: String? = null,
val sentTimeMillis: Long? = null,
val collapseKey: String? = null,
val channelId: String? = null,
val category: String? = null,
val threadId: String? = null,
val badge: String? = null,
val sound: String? = null,
val tag: String? = null,
val imageUrl: String? = null,
val priority: String? = null,
val ttlSeconds: Long? = null,
val raw: Map<String, String> = emptyMap(),
val receivedAtMillis: Long = 0L,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package ru.bartwell.kick.module.firebase.cloudmessaging.core.data

public enum class FirebaseNotificationImportance {
MIN,
LOW,
DEFAULT,
HIGH,
MAX,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package ru.bartwell.kick.module.firebase.cloudmessaging.core.data

public data class FirebaseNotificationStatus(
val iosPermission: IosNotificationPermissionStatus? = null,
val androidChannel: AndroidNotificationChannelStatus? = null,
val isGooglePlayServicesAvailable: Boolean? = null,
)

public enum class IosNotificationPermissionStatus(public val description: String) {
NotDetermined("Not determined"),
Denied("Denied"),
Authorized("Authorized"),
Provisional("Provisional"),
Ephemeral("Ephemeral"),
Unknown("Unknown"),
}

public data class AndroidNotificationChannelStatus(
val id: String,
val name: String? = null,
val description: String? = null,
val importance: String? = null,
val isEnabled: Boolean? = null,
val isAppNotificationsEnabled: Boolean? = null,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package ru.bartwell.kick.module.firebase.cloudmessaging.core.data

public expect class PlatformPendingIntent
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package ru.bartwell.kick.module.firebase.cloudmessaging

import platform.Foundation.NSDictionary
import platform.UserNotifications.UNNotification

public fun FirebaseCloudMessagingAccessor.handleApnsPayload(userInfo: NSDictionary) {
// No-op in the stub artifact.
}

public fun FirebaseCloudMessagingAccessor.handleApnsPayload(userInfo: Map<Any?, *>) {
// No-op in the stub artifact.
}

public fun FirebaseCloudMessagingAccessor.handleApnsNotification(notification: UNNotification) {
// No-op in the stub artifact.
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package ru.bartwell.kick.module.firebase.cloudmessaging.core.data

public actual class PlatformPendingIntent
94 changes: 94 additions & 0 deletions module/firebase/firebase-cloud-messaging/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

plugins {
alias(libs.plugins.kotlinMultiplatform)
alias(libs.plugins.androidLibrary)
alias(libs.plugins.jetbrainsCompose)
alias(libs.plugins.compose.compiler)
alias(libs.plugins.kotlinSerialization)
alias(libs.plugins.publish.plugin)
id("publish-convention")
}

group = "ru.bartwell.kick"
version = extra["libraryVersionName"] as String

kotlin {
androidTarget {
compilations.all {
compileTaskProvider.configure {
compilerOptions {
jvmTarget.set(JvmTarget.JVM_1_8)
}
}
}
}

listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach {
it.binaries.framework {
baseName = "firebase-cloud-messaging"
isStatic = true
}
}

sourceSets {
commonMain.dependencies {
implementation(projects.mainCore)
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.material3)
implementation(compose.materialIconsExtended)
implementation(libs.decompose)
implementation(libs.decompose.extensions.compose)
implementation(libs.decompose.essenty.lifecycle.coroutines)
implementation(libs.kotlinx.serialization.json)
implementation(libs.kotlinx.datetime)
}
commonTest.dependencies {
implementation(libs.kotlin.test)
}
androidMain.dependencies {
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.core.ktx)
implementation(libs.firebase.messaging)
implementation(libs.firebase.installations)
implementation(libs.play.services.base)
}
appleMain.dependencies {
}
iosTest.dependencies {
@OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class)
implementation(compose.uiTest)
implementation(libs.kotlin.test)
}
}

explicitApi()
}

android {
namespace = "ru.bartwell.kick"
compileSdk = 35

defaultConfig {
minSdk = 24
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}

buildFeatures {
compose = true
}
}

dependencies {
debugImplementation(libs.androidx.compose.ui.test.manifest)
}
Loading
Loading