Skip to content

Commit

Permalink
Desktop support for local notification (#46)
Browse files Browse the repository at this point in the history
* Implementing Desktop support for local notification (#44)

* Initializing Desktop target

* Initial local notifier implementation

* Implementation of joptionspane for not supported tray notification

* Updating api, and ReadME
  • Loading branch information
mirzemehdi authored Jul 8, 2024
1 parent 6807e2d commit bcca06b
Show file tree
Hide file tree
Showing 24 changed files with 610 additions and 7 deletions.
39 changes: 37 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@

![badge-android](http://img.shields.io/badge/platform-android-6EDB8D.svg?style=flat)
![badge-ios](http://img.shields.io/badge/platform-ios-CDCDCD.svg?style=flat)
![badge-desktop](https://img.shields.io/badge/platform-desktop-3474eb.svg?style=flat)


Simple and easy to use Kotlin Multiplatform Push Notification library (using Firebase Cloud Messaging) targeting ios and android.
This library is used in [FindTravelNow](https://github.com/mirzemehdi/FindTravelNow-KMM/) production KMP project.
You can check out [Documentation](https://mirzemehdi.github.io/KMPNotifier) for full library api information.

## Features
- 🔔 Local and Push Notification (Firebase Cloud Messaging)
- 📱 Multiplatform (android and iOS)
- 📱 Multiplatform (android, iOS and desktop(alpha)) (Desktop supports only local notification for now)

## Installation
Before starting you need to setup basic setup using Firebase official guideline (like initializing project in Firebase, adding `google-services.json` to android, `GoogleService-Info.plist` to iOS).
Expand Down Expand Up @@ -64,7 +66,7 @@ plugins {


### Platform Setup
In both platforms on Application Start you need to initialize library using
In all platforms on Application Start you need to initialize library using
```kotlin
NotifierManager.initialize(NotificationPlatformConfiguration) //passing android or ios configuration depending on the platform
```
Expand Down Expand Up @@ -152,6 +154,39 @@ struct iOSApp: App {



</details>

<details>
<summary>Desktop</summary>

### Desktop Setup
You need to put notification icon into resources/common folder. For more information:
[Compose Desktop Resources](https://github.com/JetBrains/compose-multiplatform/blob/master/tutorials/Native_distributions_and_local_execution/README.md#packaging-resources)
```kotlin
fun main() = application {

NotifierManager.initialize(
NotificationPlatformConfiguration.Desktop(
showPushNotification = true,
notificationIconPath = composeDesktopResourcesPath() + File.separator + "ic_notification.png"
)
)

AppInitializer.onApplicationStart()
Window(
onCloseRequest = ::exitApplication,
title = "KMPNotifier Desktop",
) {
println("Desktop app is started")
App()

}
}
```




</details>

## Usage
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ plugins {

allprojects {
group = "io.github.mirzemehdi"
version = "1.0.1"
version = "1.1.0"
val sonatypeUsername = gradleLocalProperties(rootDir).getProperty("sonatypeUsername")
val sonatypePassword = gradleLocalProperties(rootDir).getProperty("sonatypePassword")
val gpgKeySecret = gradleLocalProperties(rootDir).getProperty("gpgKeySecret")
Expand Down
1 change: 0 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ koin-core = { group = "io.insert-koin", name = "koin-core", version.ref = "koin"
firebase-messaging = { group = "com.google.firebase", name = "firebase-messaging-ktx" ,version.ref="firebase-messaging"}



[plugins]
jetbrainsCompose = { id = "org.jetbrains.compose", version.ref = "compose-plugin" }
composeCompiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
Expand Down
117 changes: 117 additions & 0 deletions kmpnotifier/api/android/kmpnotifier.api
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
public final class com/mmk/kmpnotifier/extensions/NotifierManagerExtKt {
public static final fun onCreateOrOnNewIntent (Lcom/mmk/kmpnotifier/notification/NotifierManager;Landroid/content/Intent;)V
}

public abstract interface class com/mmk/kmpnotifier/notification/Notifier {
public abstract fun notify (ILjava/lang/String;Ljava/lang/String;Ljava/util/Map;)V
public abstract fun notify (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;)I
public abstract fun remove (I)V
public abstract fun removeAll ()V
}

public final class com/mmk/kmpnotifier/notification/Notifier$DefaultImpls {
public static synthetic fun notify$default (Lcom/mmk/kmpnotifier/notification/Notifier;ILjava/lang/String;Ljava/lang/String;Ljava/util/Map;ILjava/lang/Object;)V
public static synthetic fun notify$default (Lcom/mmk/kmpnotifier/notification/Notifier;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;ILjava/lang/Object;)I
}

public final class com/mmk/kmpnotifier/notification/NotifierManager {
public static final field INSTANCE Lcom/mmk/kmpnotifier/notification/NotifierManager;
public final fun addListener (Lcom/mmk/kmpnotifier/notification/NotifierManager$Listener;)V
public final fun getLocalNotifier ()Lcom/mmk/kmpnotifier/notification/Notifier;
public final fun getPermissionUtil ()Lcom/mmk/kmpnotifier/permission/PermissionUtil;
public final fun getPushNotifier ()Lcom/mmk/kmpnotifier/notification/PushNotifier;
public final fun initialize (Lcom/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration;)V
}

public abstract interface class com/mmk/kmpnotifier/notification/NotifierManager$Listener {
public abstract fun onNewToken (Ljava/lang/String;)V
public abstract fun onNotificationClicked (Ljava/util/Map;)V
public abstract fun onPayloadData (Ljava/util/Map;)V
public abstract fun onPushNotification (Ljava/lang/String;Ljava/lang/String;)V
}

public final class com/mmk/kmpnotifier/notification/NotifierManager$Listener$DefaultImpls {
public static fun onNewToken (Lcom/mmk/kmpnotifier/notification/NotifierManager$Listener;Ljava/lang/String;)V
public static fun onNotificationClicked (Lcom/mmk/kmpnotifier/notification/NotifierManager$Listener;Ljava/util/Map;)V
public static fun onPayloadData (Lcom/mmk/kmpnotifier/notification/NotifierManager$Listener;Ljava/util/Map;)V
public static fun onPushNotification (Lcom/mmk/kmpnotifier/notification/NotifierManager$Listener;Ljava/lang/String;Ljava/lang/String;)V
}

public abstract interface class com/mmk/kmpnotifier/notification/PushNotifier {
public abstract fun deleteMyToken (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun getToken (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun subscribeToTopic (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun unSubscribeFromTopic (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public abstract interface class com/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration {
}

public final class com/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration$Android : com/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration {
public fun <init> (ILjava/lang/Integer;Lcom/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration$Android$NotificationChannelData;Z)V
public synthetic fun <init> (ILjava/lang/Integer;Lcom/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration$Android$NotificationChannelData;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getNotificationChannelData ()Lcom/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration$Android$NotificationChannelData;
public final fun getNotificationIconColorResId ()Ljava/lang/Integer;
public final fun getNotificationIconResId ()I
public final fun getShowPushNotification ()Z
}

public final class com/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration$Android$NotificationChannelData {
public fun <init> ()V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getDescription ()Ljava/lang/String;
public final fun getId ()Ljava/lang/String;
public final fun getName ()Ljava/lang/String;
}

public final class com/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration$Desktop : com/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration {
public fun <init> ()V
public fun <init> (ZLjava/lang/String;)V
public synthetic fun <init> (ZLjava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Z
public final fun component2 ()Ljava/lang/String;
public final fun copy (ZLjava/lang/String;)Lcom/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration$Desktop;
public static synthetic fun copy$default (Lcom/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration$Desktop;ZLjava/lang/String;ILjava/lang/Object;)Lcom/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration$Desktop;
public fun equals (Ljava/lang/Object;)Z
public final fun getNotificationIconPath ()Ljava/lang/String;
public final fun getShowPushNotification ()Z
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class com/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration$Ios : com/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration {
public fun <init> ()V
public fun <init> (ZZ)V
public synthetic fun <init> (ZZILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Z
public final fun component2 ()Z
public final fun copy (ZZ)Lcom/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration$Ios;
public static synthetic fun copy$default (Lcom/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration$Ios;ZZILjava/lang/Object;)Lcom/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration$Ios;
public fun equals (Ljava/lang/Object;)Z
public final fun getAskNotificationPermissionOnStart ()Z
public final fun getShowPushNotification ()Z
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class com/mmk/kmpnotifier/permission/AndroidPermissionUtil {
public fun <init> (Landroidx/activity/ComponentActivity;)V
public final fun askNotificationPermission (Lkotlin/jvm/functions/Function1;)V
public static synthetic fun askNotificationPermission$default (Lcom/mmk/kmpnotifier/permission/AndroidPermissionUtil;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
}

public final class com/mmk/kmpnotifier/permission/AndroidPermissionUtilKt {
public static final fun permissionUtil (Landroidx/activity/ComponentActivity;)Lkotlin/Lazy;
}

public abstract interface class com/mmk/kmpnotifier/permission/PermissionUtil {
public abstract fun askNotificationPermission (Lkotlin/jvm/functions/Function0;)V
public abstract fun hasNotificationPermission (Lkotlin/jvm/functions/Function1;)V
}

public final class com/mmk/kmpnotifier/permission/PermissionUtil$DefaultImpls {
public static synthetic fun askNotificationPermission$default (Lcom/mmk/kmpnotifier/permission/PermissionUtil;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
public static synthetic fun hasNotificationPermission$default (Lcom/mmk/kmpnotifier/permission/PermissionUtil;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
}

107 changes: 107 additions & 0 deletions kmpnotifier/api/jvm/kmpnotifier.api
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
public final class com/mmk/kmpnotifier/extensions/DesktopPlatformExtKt {
public static final fun composeDesktopResourcesPath ()Ljava/lang/String;
}

public abstract interface class com/mmk/kmpnotifier/notification/Notifier {
public abstract fun notify (ILjava/lang/String;Ljava/lang/String;Ljava/util/Map;)V
public abstract fun notify (Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;)I
public abstract fun remove (I)V
public abstract fun removeAll ()V
}

public final class com/mmk/kmpnotifier/notification/Notifier$DefaultImpls {
public static synthetic fun notify$default (Lcom/mmk/kmpnotifier/notification/Notifier;ILjava/lang/String;Ljava/lang/String;Ljava/util/Map;ILjava/lang/Object;)V
public static synthetic fun notify$default (Lcom/mmk/kmpnotifier/notification/Notifier;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;ILjava/lang/Object;)I
}

public final class com/mmk/kmpnotifier/notification/NotifierManager {
public static final field INSTANCE Lcom/mmk/kmpnotifier/notification/NotifierManager;
public final fun addListener (Lcom/mmk/kmpnotifier/notification/NotifierManager$Listener;)V
public final fun getLocalNotifier ()Lcom/mmk/kmpnotifier/notification/Notifier;
public final fun getPermissionUtil ()Lcom/mmk/kmpnotifier/permission/PermissionUtil;
public final fun getPushNotifier ()Lcom/mmk/kmpnotifier/notification/PushNotifier;
public final fun initialize (Lcom/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration;)V
}

public abstract interface class com/mmk/kmpnotifier/notification/NotifierManager$Listener {
public abstract fun onNewToken (Ljava/lang/String;)V
public abstract fun onNotificationClicked (Ljava/util/Map;)V
public abstract fun onPayloadData (Ljava/util/Map;)V
public abstract fun onPushNotification (Ljava/lang/String;Ljava/lang/String;)V
}

public final class com/mmk/kmpnotifier/notification/NotifierManager$Listener$DefaultImpls {
public static fun onNewToken (Lcom/mmk/kmpnotifier/notification/NotifierManager$Listener;Ljava/lang/String;)V
public static fun onNotificationClicked (Lcom/mmk/kmpnotifier/notification/NotifierManager$Listener;Ljava/util/Map;)V
public static fun onPayloadData (Lcom/mmk/kmpnotifier/notification/NotifierManager$Listener;Ljava/util/Map;)V
public static fun onPushNotification (Lcom/mmk/kmpnotifier/notification/NotifierManager$Listener;Ljava/lang/String;Ljava/lang/String;)V
}

public abstract interface class com/mmk/kmpnotifier/notification/PushNotifier {
public abstract fun deleteMyToken (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun getToken (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun subscribeToTopic (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun unSubscribeFromTopic (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public abstract interface class com/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration {
}

public final class com/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration$Android : com/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration {
public fun <init> (ILjava/lang/Integer;Lcom/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration$Android$NotificationChannelData;Z)V
public synthetic fun <init> (ILjava/lang/Integer;Lcom/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration$Android$NotificationChannelData;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getNotificationChannelData ()Lcom/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration$Android$NotificationChannelData;
public final fun getNotificationIconColorResId ()Ljava/lang/Integer;
public final fun getNotificationIconResId ()I
public final fun getShowPushNotification ()Z
}

public final class com/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration$Android$NotificationChannelData {
public fun <init> ()V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getDescription ()Ljava/lang/String;
public final fun getId ()Ljava/lang/String;
public final fun getName ()Ljava/lang/String;
}

public final class com/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration$Desktop : com/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration {
public fun <init> ()V
public fun <init> (ZLjava/lang/String;)V
public synthetic fun <init> (ZLjava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Z
public final fun component2 ()Ljava/lang/String;
public final fun copy (ZLjava/lang/String;)Lcom/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration$Desktop;
public static synthetic fun copy$default (Lcom/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration$Desktop;ZLjava/lang/String;ILjava/lang/Object;)Lcom/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration$Desktop;
public fun equals (Ljava/lang/Object;)Z
public final fun getNotificationIconPath ()Ljava/lang/String;
public final fun getShowPushNotification ()Z
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class com/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration$Ios : com/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration {
public fun <init> ()V
public fun <init> (ZZ)V
public synthetic fun <init> (ZZILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Z
public final fun component2 ()Z
public final fun copy (ZZ)Lcom/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration$Ios;
public static synthetic fun copy$default (Lcom/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration$Ios;ZZILjava/lang/Object;)Lcom/mmk/kmpnotifier/notification/configuration/NotificationPlatformConfiguration$Ios;
public fun equals (Ljava/lang/Object;)Z
public final fun getAskNotificationPermissionOnStart ()Z
public final fun getShowPushNotification ()Z
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public abstract interface class com/mmk/kmpnotifier/permission/PermissionUtil {
public abstract fun askNotificationPermission (Lkotlin/jvm/functions/Function0;)V
public abstract fun hasNotificationPermission (Lkotlin/jvm/functions/Function1;)V
}

public final class com/mmk/kmpnotifier/permission/PermissionUtil$DefaultImpls {
public static synthetic fun askNotificationPermission$default (Lcom/mmk/kmpnotifier/permission/PermissionUtil;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
public static synthetic fun hasNotificationPermission$default (Lcom/mmk/kmpnotifier/permission/PermissionUtil;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
}

7 changes: 6 additions & 1 deletion kmpnotifier/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ kotlin {
}
}


jvm()
iosX64()
iosArm64()
iosSimulatorArm64()
Expand Down Expand Up @@ -47,6 +47,11 @@ kotlin {
implementation(libs.koin.core)
implementation(libs.kotlinx.coroutine)
}

commonTest.dependencies {
implementation(libs.kotlin.test)
}

}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,14 @@ private fun Koin.onLibraryInitialized() {
get<PushNotifier>() //This will make sure that that when lib is initialized, init method is called

when (platform) {
Platform.Android -> Unit //In Android platform permission should be asked in activity
Platform.Android, Platform.Desktop -> Unit //In Android platform permission should be asked in activity
Platform.Ios -> {
val askNotificationPermissionOnStart =
(configuration as? NotificationPlatformConfiguration.Ios)?.askNotificationPermissionOnStart
?: true
if (askNotificationPermissionOnStart) permissionUtil.askNotificationPermission()
}

}
}

Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ import org.koin.core.module.Module
internal sealed interface Platform {
data object Android : Platform
data object Ios : Platform
data object Desktop : Platform
}
internal expect val platformModule: Module
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.mmk.kmpnotifier.notification.configuration


/**
* You can configure some customization for notifications depending on the platform
*/
Expand Down Expand Up @@ -55,4 +56,10 @@ public sealed interface NotificationPlatformConfiguration {
public val showPushNotification: Boolean = true,
public val askNotificationPermissionOnStart: Boolean = true
) : NotificationPlatformConfiguration


public data class Desktop(
public val showPushNotification: Boolean = true,
public val notificationIconPath: String? = null
) : NotificationPlatformConfiguration
}
Loading

0 comments on commit bcca06b

Please sign in to comment.