capacitor-messenger-notifications 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/LICENSE +21 -0
  2. package/MessengerNotifications.podspec +18 -0
  3. package/Package.swift +26 -0
  4. package/README.md +152 -0
  5. package/android/build.gradle +62 -0
  6. package/android/src/main/AndroidManifest.xml +19 -0
  7. package/android/src/main/java/com/codecraft_studio/messenger/notifications/EncryptedMessageNotifier.java +68 -0
  8. package/android/src/main/java/com/codecraft_studio/messenger/notifications/FcmFetchManager.java +37 -0
  9. package/android/src/main/java/com/codecraft_studio/messenger/notifications/MessengerNotificationsPlugin.java +92 -0
  10. package/android/src/main/java/com/codecraft_studio/messenger/notifications/NativeCrypto.java +43 -0
  11. package/android/src/main/java/com/codecraft_studio/messenger/notifications/NotificationDismissReceiver.java +20 -0
  12. package/android/src/main/java/com/codecraft_studio/messenger/notifications/NotificationHelper.java +618 -0
  13. package/android/src/main/java/com/codecraft_studio/messenger/notifications/PersistentSocketService.java +213 -0
  14. package/dist/esm/definitions.d.ts +48 -0
  15. package/dist/esm/definitions.js +2 -0
  16. package/dist/esm/definitions.js.map +1 -0
  17. package/dist/esm/index.d.ts +4 -0
  18. package/dist/esm/index.js +7 -0
  19. package/dist/esm/index.js.map +1 -0
  20. package/dist/esm/web.d.ts +25 -0
  21. package/dist/esm/web.js +42 -0
  22. package/dist/esm/web.js.map +1 -0
  23. package/dist/plugin.cjs.js +56 -0
  24. package/dist/plugin.cjs.js.map +1 -0
  25. package/dist/plugin.js +59 -0
  26. package/dist/plugin.js.map +1 -0
  27. package/ios/Sources/MessengerNotificationsPlugin/MessengerNotificationsPlugin.swift +76 -0
  28. package/ios/Sources/MessengerNotificationsPlugin/NativeCrypto.swift +22 -0
  29. package/ios/Sources/MessengerNotificationsPlugin/NotificationHelper.swift +58 -0
  30. package/ios/Sources/MessengerNotificationsPlugin/SafeStorageStore.swift +28 -0
  31. package/ios/Sources/MessengerNotificationsPlugin/TemporarySocketSessionManager.swift +186 -0
  32. package/package.json +77 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 CodeCraft Studio
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,18 @@
1
+ require 'json'
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = 'MessengerNotifications'
7
+ s.version = package['version']
8
+ s.summary = package['description']
9
+ s.license = package['license']
10
+ s.homepage = package['repository']['url']
11
+ s.author = package['author']
12
+ s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
13
+ s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
14
+ s.ios.deployment_target = '13.0'
15
+ s.dependency 'Capacitor'
16
+ s.dependency 'Socket.io-client-swift', '~> 15.0'
17
+ s.swift_version = '5.1'
18
+ end
package/Package.swift ADDED
@@ -0,0 +1,26 @@
1
+ // swift-tools-version: 5.9
2
+ import PackageDescription
3
+
4
+ let package = Package(
5
+ name: "MessengerNotifications",
6
+ platforms: [.iOS(.v13)],
7
+ products: [
8
+ .library(
9
+ name: "MessengerNotifications",
10
+ targets: ["MessengerNotificationsPlugin"])
11
+ ],
12
+ dependencies: [
13
+ .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "7.1.0"),
14
+ .package(url: "https://github.com/socketio/socket.io-client-swift.git", from: "16.1.0")
15
+ ],
16
+ targets: [
17
+ .target(
18
+ name: "MessengerNotificationsPlugin",
19
+ dependencies: [
20
+ .product(name: "Capacitor", package: "capacitor-swift-pm"),
21
+ .product(name: "Cordova", package: "capacitor-swift-pm"),
22
+ .product(name: "SocketIO", package: "socket.io-client-swift")
23
+ ],
24
+ path: "ios/Sources/MessengerNotificationsPlugin")
25
+ ]
26
+ )
package/README.md ADDED
@@ -0,0 +1,152 @@
1
+ # capacitor-messenger-notifications
2
+
3
+ [![license](https://img.shields.io/npm/l/capacitor-messenger-notifications.svg)](https://github.com/imuhammadnadeem/capacitor-messenger-notifications/blob/main/LICENSE)
4
+
5
+ Capacitor plugin for managing messenger-style notifications with WebSocket support on Android and iOS. Built for end-to-end encrypted chat applications.
6
+
7
+ ## Table of Contents
8
+
9
+ - [Features](#features)
10
+ - [Requirements](#requirements)
11
+ - [Install](#install)
12
+ - [Usage](#usage)
13
+ - [JavaScript Examples](#javascript-examples)
14
+ - [Native Integration (Android/iOS)](#native-integration-androidios)
15
+ - [Configuration](#configuration)
16
+ - [Platform Implementation](#platform-implementation)
17
+ - [Setup by Platform](#setup-by-platform)
18
+ - [API](#api)
19
+ - [Troubleshooting](#troubleshooting)
20
+ - [Development](#development)
21
+ - [Contributing](#contributing)
22
+ - [License](#license)
23
+
24
+ ## Features
25
+
26
+ - **Native Notification Grouping**: Automatically groups messages by room ID using `MessagingStyle` (Android) and `threadIdentifier` (iOS).
27
+ - **Persistent WebSocket (Android)**: Foreground service that stays alive to receive messages even when the app is killed.
28
+ - **Background Fetch (iOS)**: Automatically wakes up to fetch unread messages when a silent push is received.
29
+ - **End-to-End Encryption Ready**: Designed to handle encrypted payloads and decrypt them on-device before showing notifications.
30
+
31
+ ## Requirements
32
+
33
+ - **Capacitor**: ^6.0.0 || ^7.0.0 || ^8.0.0
34
+ - **Node.js**: 18.x or higher
35
+ - **iOS**: 13.0 or higher
36
+ - **Android**: API level 22 (Android 5.1) or higher
37
+
38
+ ## Install
39
+
40
+ ```bash
41
+ npm install capacitor-messenger-notifications
42
+ npx cap sync
43
+ ```
44
+
45
+ ## Usage
46
+
47
+ ### JavaScript Examples
48
+
49
+ #### Start Persistent Socket (Android)
50
+
51
+ ```typescript
52
+ import { MessengerNotifications } from 'capacitor-messenger-notifications';
53
+
54
+ // Starts a foreground service on Android to maintain a heartbeat connection
55
+ await MessengerNotifications.startPersistentSocket({
56
+ url: 'wss://your-chat-server.com',
57
+ token: 'YOUR_AUTH_TOKEN'
58
+ });
59
+ ```
60
+
61
+ #### Show a Manual Notification
62
+
63
+ ```typescript
64
+ await MessengerNotifications.showNotification({
65
+ title: 'John Doe',
66
+ body: 'Hey, how are you?',
67
+ roomId: 101,
68
+ roomName: 'General Chat',
69
+ messageId: 'uuid-12345',
70
+ timestamp: Date.now()
71
+ });
72
+ ```
73
+
74
+ ### Native Integration (Android/iOS)
75
+
76
+ This plugin is often triggered from native background tasks (FCM / Silent Push).
77
+
78
+ - **Android**: Use `EncryptedMessageNotifier.notifyFromSocketPayload(context, data)` from your background services.
79
+ - **iOS**: Use `TemporarySocketSessionManager.shared.fetchAndNotify(...)` inside `didReceiveRemoteNotification`.
80
+
81
+ ## Configuration
82
+
83
+ Most configurations are handled dynamically via the API, but you can define defaults in **`capacitor.config.json`**:
84
+
85
+ ```json
86
+ {
87
+ "plugins": {
88
+ "MessengerNotifications": {
89
+ "defaultSocketUrl": "wss://your-default-server.com",
90
+ "notificationChannelId": "chat_messages",
91
+ "notificationChannelName": "Messenger Notifications"
92
+ }
93
+ }
94
+ }
95
+ ```
96
+
97
+ ## Platform Implementation
98
+
99
+ | Platform | Implementation |
100
+ | --- | --- |
101
+ | Android | Foreground Service + NotificationManager with `MessagingStyle`. |
102
+ | iOS | `UNNotificationContent` with `threadIdentifier` + SocketIO Task. |
103
+
104
+ ## Setup by Platform
105
+
106
+ > For full host‑app steps (Android & iOS), see `HOST_APP_SETUP.md`.
107
+
108
+ ### Android
109
+
110
+ - **AndroidManifest.xml**: Add `FOREGROUND_SERVICE` and `POST_NOTIFICATIONS` permissions.
111
+ - **ProGuard**: Add `-keep` rules for the plugin and Socket.IO.
112
+
113
+ ### iOS
114
+
115
+ - **Capabilities**: Enable **Push Notifications** and **Background Modes** (Background fetch, Remote notifications).
116
+
117
+ ## API
118
+
119
+ | Method | Description |
120
+ | --- | --- |
121
+ | `startPersistentSocket(options)` | Starts the background socket service (Android only). |
122
+ | `stopPersistentSocket()` | Stops the background socket service. |
123
+ | `showNotification(options)` | Manually triggers a native grouped notification. |
124
+ | `clearRoomNotification(options)` | Clears all notifications for a specific room. |
125
+ | `getPendingRoomId()` | Returns the roomId if the app was launched from a notification. |
126
+
127
+ ---
128
+
129
+ ## Troubleshooting
130
+
131
+ ### Android: Service is killed
132
+
133
+ Ensure you have added `android:foregroundServiceType="dataSync"` to the service declaration in `AndroidManifest.xml` as required by Android 14+.
134
+
135
+ ### iOS: Notifications aren't grouping
136
+
137
+ Ensure `threadIdentifier` is correctly set in the push payload or that you are passing the same `roomId` to `showNotification`.
138
+
139
+ ## Development
140
+
141
+ - **Build**: `npm run build`
142
+ - **Lint**: `npm run lint`
143
+ - **Format**: `npm run fmt`
144
+ - **Verify**: `npm run verify`
145
+
146
+ ## Contributing
147
+
148
+ Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details.
149
+
150
+ ## License
151
+
152
+ MIT
@@ -0,0 +1,62 @@
1
+ ext {
2
+ androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.6.1'
3
+ androidxCoreVersion = project.hasProperty('androidxCoreVersion') ? rootProject.ext.androidxCoreVersion : '1.12.0'
4
+ }
5
+
6
+ buildscript {
7
+ repositories {
8
+ google()
9
+ mavenCentral()
10
+ }
11
+ dependencies {
12
+ classpath 'com.android.tools.build:gradle:8.2.1'
13
+ }
14
+ }
15
+
16
+ apply plugin: 'com.android.library'
17
+
18
+ android {
19
+ namespace "com.codecraft_studio.messenger.notifications"
20
+ compileSdk project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 34
21
+ defaultConfig {
22
+ minSdk project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 22
23
+ targetSdk project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 34
24
+ versionCode 1
25
+ versionName "1.0"
26
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
27
+ }
28
+ buildTypes {
29
+ release {
30
+ minifyEnabled false
31
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
32
+ }
33
+ }
34
+ lintOptions {
35
+ abortOnError false
36
+ }
37
+ compileOptions {
38
+ sourceCompatibility JavaVersion.VERSION_17
39
+ targetCompatibility JavaVersion.VERSION_17
40
+ }
41
+ }
42
+
43
+ repositories {
44
+ google()
45
+ mavenCentral()
46
+ }
47
+
48
+ dependencies {
49
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
50
+ implementation project(':capacitor-android')
51
+ implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
52
+ implementation "androidx.core:core:$androidxCoreVersion"
53
+
54
+ // Socket.IO client for Android
55
+ implementation ('io.socket:socket.io-client:2.1.0') {
56
+ exclude group: 'org.json', module: 'json'
57
+ }
58
+
59
+ testImplementation 'junit:junit:4.13.2'
60
+ androidTestImplementation 'androidx.test.ext:junit:1.1.5'
61
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
62
+ }
@@ -0,0 +1,19 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+ <application>
3
+ <service
4
+ android:name="com.codecraft_studio.messenger.notifications.PersistentSocketService"
5
+ android:enabled="true"
6
+ android:exported="false"
7
+ android:foregroundServiceType="dataSync" />
8
+
9
+ <receiver
10
+ android:name="com.codecraft_studio.messenger.notifications.NotificationDismissReceiver"
11
+ android:enabled="true"
12
+ android:exported="false" />
13
+ </application>
14
+
15
+ <uses-permission android:name="android.permission.INTERNET" />
16
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
17
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
18
+ <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
19
+ </manifest>
@@ -0,0 +1,68 @@
1
+ package com.codecraft_studio.messenger.notifications;
2
+
3
+ import android.content.Context;
4
+ import android.util.Log;
5
+ import java.util.Map;
6
+ import org.json.JSONObject;
7
+
8
+ /**
9
+ * Handles incoming push/socket payloads, decrypts them, and triggers notifications.
10
+ */
11
+ public class EncryptedMessageNotifier {
12
+
13
+ private static final String TAG = "MessageNotifier";
14
+
15
+ public static boolean notifyFromPushData(Context context, Map<String, String> data) {
16
+ if (data == null || data.isEmpty()) return false;
17
+ try {
18
+ int roomId = Integer.parseInt(data.get("roomId") != null ? data.get("roomId") : data.get("room_id"));
19
+ String senderName = data.get("senderName") != null ? data.get("senderName") : data.get("title");
20
+ String body = data.get("body") != null ? data.get("body") : data.get("message");
21
+ String messageId = data.get("messageId") != null ? data.get("messageId") : data.get("id");
22
+ long timestamp = System.currentTimeMillis();
23
+
24
+ NotificationHelper.showRoomNotification(context, senderName, body, roomId, messageId, timestamp);
25
+ return true;
26
+ } catch (Exception e) {
27
+ Log.e(TAG, "Error processing push data", e);
28
+ }
29
+ return false;
30
+ }
31
+
32
+ public static boolean notifyFromSocketPayload(Context context, Object payload) {
33
+ if (!(payload instanceof JSONObject)) return false;
34
+ JSONObject obj = (JSONObject) payload;
35
+ try {
36
+ int roomId = obj.optInt("room_id", obj.optInt("roomId"));
37
+ if (roomId <= 0) return false;
38
+
39
+ String encryptedMsg = obj.optString("encrypted_message", obj.optString("encryptedMessage"));
40
+ String encryptedUser = obj.optString("encrypted_username", obj.optString("encryptedUsername"));
41
+ String encryptedRoom = obj.optString("encrypted_room_name", obj.optString("encryptedRoomName"));
42
+
43
+ String senderName = encryptedUser.isEmpty()
44
+ ? "New Message"
45
+ : NativeCrypto.decryptUserData(obj.optInt("sender_id"), encryptedUser).text;
46
+ String messageBody = encryptedMsg.isEmpty() ? "New encrypted message" : NativeCrypto.decryptRoomData(roomId, encryptedMsg).text;
47
+ String roomName = encryptedRoom.isEmpty() ? null : NativeCrypto.decryptRoomData(roomId, encryptedRoom).text;
48
+
49
+ String messageId = obj.optString("id", obj.optString("messageId"));
50
+ long timestamp = obj.optLong("timestamp", System.currentTimeMillis());
51
+
52
+ NotificationHelper.showRoomNotification(context, senderName, messageBody, roomId, roomName, messageId, timestamp, false);
53
+ return true;
54
+ } catch (Exception e) {
55
+ Log.e(TAG, "Error processing socket payload", e);
56
+ }
57
+ return false;
58
+ }
59
+
60
+ public static boolean notifyFromSyncMessagesResponse(Context context, Object arg) {
61
+ // For sync response, we just treat each message as a socket payload.
62
+ return notifyFromSocketPayload(context, arg);
63
+ }
64
+
65
+ public static void notifyFromUnreadApiRecord(Context context, JSONObject item) {
66
+ notifyFromSocketPayload(context, item);
67
+ }
68
+ }
@@ -0,0 +1,37 @@
1
+ package com.codecraft_studio.messenger.notifications;
2
+
3
+ import android.util.Log;
4
+ import java.util.Map;
5
+ import java.util.concurrent.ConcurrentHashMap;
6
+
7
+ /**
8
+ * Tracks when a notification was last shown per room ID.
9
+ * Used to avoid duplicate notifications.
10
+ */
11
+ public final class FcmFetchManager {
12
+
13
+ private static final String TAG = "FcmFetchManager";
14
+ private static final Map<Integer, Long> lastRoomNotificationMs = new ConcurrentHashMap<>();
15
+ private static final long NOTIFICATION_GRACE_MS = 10_000L;
16
+ private static volatile long lastAnyNotificationMs = 0L;
17
+
18
+ private FcmFetchManager() {}
19
+
20
+ public static void markNotificationShown(int roomId) {
21
+ long now = System.currentTimeMillis();
22
+ lastRoomNotificationMs.put(roomId, now);
23
+ lastAnyNotificationMs = now;
24
+ }
25
+
26
+ public static boolean wasNotificationShownRecently(int roomId) {
27
+ Long last = lastRoomNotificationMs.get(roomId);
28
+ if (last == null) return false;
29
+ return (System.currentTimeMillis() - last) < NOTIFICATION_GRACE_MS;
30
+ }
31
+
32
+ public static boolean wasAnyNotificationShownRecently(long windowMs) {
33
+ long last = lastAnyNotificationMs;
34
+ if (last <= 0L) return false;
35
+ return (System.currentTimeMillis() - last) < Math.max(0L, windowMs);
36
+ }
37
+ }
@@ -0,0 +1,92 @@
1
+ package com.codecraft_studio.messenger.notifications;
2
+
3
+ import android.os.Bundle;
4
+ import android.util.Log;
5
+ import com.getcapacitor.JSObject;
6
+ import com.getcapacitor.Plugin;
7
+ import com.getcapacitor.PluginCall;
8
+ import com.getcapacitor.PluginMethod;
9
+ import com.getcapacitor.annotation.CapacitorPlugin;
10
+
11
+ @CapacitorPlugin(name = "MessengerNotifications")
12
+ public class MessengerNotificationsPlugin extends Plugin {
13
+
14
+ private static final String TAG = "MessengerNotifications";
15
+
16
+ @Override
17
+ public void load() {
18
+ Log.i(TAG, "Plugin loaded");
19
+ }
20
+
21
+ @PluginMethod
22
+ public void showNotification(PluginCall call) {
23
+ String title = call.getString("title", "New Message");
24
+ String body = call.getString("body", "You have a new message");
25
+ int roomId = call.getInt("roomId", 0);
26
+ String messageId = call.getString("messageId");
27
+ long timestamp = call.getLong("timestamp", 0L);
28
+ String roomName = call.getString("roomName");
29
+
30
+ Log.i(TAG, "showNotification() title=" + title + " roomId=" + roomId + " messageId=" + messageId);
31
+
32
+ NotificationHelper.showRoomNotification(getContext(), title, body, roomId, roomName, messageId, timestamp, false);
33
+ call.resolve();
34
+ }
35
+
36
+ @PluginMethod
37
+ public void clearRoomNotification(PluginCall call) {
38
+ int roomId = call.getInt("roomId", 0);
39
+ if (roomId <= 0) {
40
+ call.resolve();
41
+ return;
42
+ }
43
+
44
+ Log.i(TAG, "clearRoomNotification() roomId=" + roomId);
45
+ NotificationHelper.clearRoomHistory(getContext(), roomId, true);
46
+ call.resolve();
47
+ }
48
+
49
+ @PluginMethod
50
+ public void getPendingRoomId(PluginCall call) {
51
+ JSObject result = new JSObject();
52
+ // Since we don't have MainActivity.pendingRoomId in a plugin,
53
+ // we might want to store it in SharedPreferences or through a static field in the plugin.
54
+ // For now, let's assume we store it in a static field here.
55
+ Integer roomId = NotificationHelper.getPendingRoomId();
56
+ if (roomId != null) {
57
+ result.put("roomId", roomId);
58
+ NotificationHelper.consumePendingRoomId();
59
+ } else {
60
+ result.put("roomId", JSObject.NULL);
61
+ }
62
+ call.resolve(result);
63
+ }
64
+
65
+ @PluginMethod
66
+ public void startPersistentSocket(PluginCall call) {
67
+ String url = call.getString("url");
68
+ String token = call.getString("token");
69
+
70
+ if (url == null || token == null) {
71
+ call.reject("Missing url or token");
72
+ return;
73
+ }
74
+
75
+ // Store these for the service to use (e.g. in SharedPreferences)
76
+ getContext()
77
+ .getSharedPreferences("messenger_plugin_prefs", android.content.Context.MODE_PRIVATE)
78
+ .edit()
79
+ .putString("socket_url", url)
80
+ .putString("auth_token", token)
81
+ .apply();
82
+
83
+ PersistentSocketService.start(getContext());
84
+ call.resolve();
85
+ }
86
+
87
+ @PluginMethod
88
+ public void stopPersistentSocket(PluginCall call) {
89
+ PersistentSocketService.stop(getContext());
90
+ call.resolve();
91
+ }
92
+ }
@@ -0,0 +1,43 @@
1
+ package com.codecraft_studio.messenger.notifications;
2
+
3
+ import android.util.Base64;
4
+ import android.util.Log;
5
+ import androidx.annotation.NonNull;
6
+ import java.nio.charset.StandardCharsets;
7
+
8
+ /**
9
+ * Native crypto logic picked from ChatE2EE.
10
+ * In a real plugin, this would interface with a security library or the app's keys.
11
+ */
12
+ public class NativeCrypto {
13
+
14
+ private static final String TAG = "NativeCrypto";
15
+
16
+ public static class DecryptResult {
17
+
18
+ public final String text;
19
+
20
+ public DecryptResult(String text) {
21
+ this.text = text;
22
+ }
23
+ }
24
+
25
+ /**
26
+ * Placeholder decryption logic.
27
+ * In the real app, this uses Lipsum or similar.
28
+ * For the plugin, we assume the host app might provide keys or we just return the ciphertext
29
+ * if we can't decrypt it yet.
30
+ */
31
+ public static DecryptResult decryptRoomData(int roomId, @NonNull String encryptedJSON) {
32
+ // This is a placeholder.
33
+ // In the original app, it calls a native method or a complex JS bridge.
34
+ // For the plugin, we'll try to decrypt if we have the keys, otherwise return as-is.
35
+ Log.d(TAG, "decryptRoomData() roomId=" + roomId);
36
+ return new DecryptResult(encryptedJSON); // Placeholder
37
+ }
38
+
39
+ public static DecryptResult decryptUserData(int userId, @NonNull String encryptedJSON) {
40
+ Log.d(TAG, "decryptUserData() userId=" + userId);
41
+ return new DecryptResult(encryptedJSON); // Placeholder
42
+ }
43
+ }
@@ -0,0 +1,20 @@
1
+ package com.codecraft_studio.messenger.notifications;
2
+
3
+ import android.content.BroadcastReceiver;
4
+ import android.content.Context;
5
+ import android.content.Intent;
6
+ import android.util.Log;
7
+
8
+ public class NotificationDismissReceiver extends BroadcastReceiver {
9
+
10
+ private static final String TAG = "NotificationDismiss";
11
+
12
+ @Override
13
+ public void onReceive(Context context, Intent intent) {
14
+ int roomId = intent.getIntExtra(NotificationHelper.EXTRA_ROOM_ID, 0);
15
+ Log.d(TAG, "Notification dismissed for roomId: " + roomId);
16
+ if (roomId > 0) {
17
+ NotificationHelper.onNotificationDismissed(context, roomId);
18
+ }
19
+ }
20
+ }