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.
- package/LICENSE +21 -0
- package/MessengerNotifications.podspec +18 -0
- package/Package.swift +26 -0
- package/README.md +152 -0
- package/android/build.gradle +62 -0
- package/android/src/main/AndroidManifest.xml +19 -0
- package/android/src/main/java/com/codecraft_studio/messenger/notifications/EncryptedMessageNotifier.java +68 -0
- package/android/src/main/java/com/codecraft_studio/messenger/notifications/FcmFetchManager.java +37 -0
- package/android/src/main/java/com/codecraft_studio/messenger/notifications/MessengerNotificationsPlugin.java +92 -0
- package/android/src/main/java/com/codecraft_studio/messenger/notifications/NativeCrypto.java +43 -0
- package/android/src/main/java/com/codecraft_studio/messenger/notifications/NotificationDismissReceiver.java +20 -0
- package/android/src/main/java/com/codecraft_studio/messenger/notifications/NotificationHelper.java +618 -0
- package/android/src/main/java/com/codecraft_studio/messenger/notifications/PersistentSocketService.java +213 -0
- package/dist/esm/definitions.d.ts +48 -0
- package/dist/esm/definitions.js +2 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +25 -0
- package/dist/esm/web.js +42 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +56 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +59 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Sources/MessengerNotificationsPlugin/MessengerNotificationsPlugin.swift +76 -0
- package/ios/Sources/MessengerNotificationsPlugin/NativeCrypto.swift +22 -0
- package/ios/Sources/MessengerNotificationsPlugin/NotificationHelper.swift +58 -0
- package/ios/Sources/MessengerNotificationsPlugin/SafeStorageStore.swift +28 -0
- package/ios/Sources/MessengerNotificationsPlugin/TemporarySocketSessionManager.swift +186 -0
- package/package.json +77 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
package com.codecraft_studio.messenger.notifications;
|
|
2
|
+
|
|
3
|
+
import android.app.Notification;
|
|
4
|
+
import android.app.NotificationChannel;
|
|
5
|
+
import android.app.NotificationManager;
|
|
6
|
+
import android.app.PendingIntent;
|
|
7
|
+
import android.app.Service;
|
|
8
|
+
import android.content.Context;
|
|
9
|
+
import android.content.Intent;
|
|
10
|
+
import android.content.SharedPreferences;
|
|
11
|
+
import android.os.Build;
|
|
12
|
+
import android.os.IBinder;
|
|
13
|
+
import android.text.TextUtils;
|
|
14
|
+
import android.util.Log;
|
|
15
|
+
import androidx.annotation.Nullable;
|
|
16
|
+
import androidx.core.app.NotificationCompat;
|
|
17
|
+
import io.socket.client.IO;
|
|
18
|
+
import io.socket.client.Socket;
|
|
19
|
+
import io.socket.engineio.client.transports.Polling;
|
|
20
|
+
import io.socket.engineio.client.transports.WebSocket;
|
|
21
|
+
import java.net.URISyntaxException;
|
|
22
|
+
import java.util.Arrays;
|
|
23
|
+
import java.util.HashMap;
|
|
24
|
+
import java.util.HashSet;
|
|
25
|
+
import java.util.Map;
|
|
26
|
+
import java.util.Set;
|
|
27
|
+
import org.json.JSONObject;
|
|
28
|
+
|
|
29
|
+
public class PersistentSocketService extends Service {
|
|
30
|
+
|
|
31
|
+
private static final String TAG = "PersistentSocketSvc";
|
|
32
|
+
private static final String CHANNEL_ID = "persistent_socket_channel";
|
|
33
|
+
private static final int NOTIFICATION_ID = 91005;
|
|
34
|
+
|
|
35
|
+
private static final Set<String> MESSAGE_EVENTS = new HashSet<>(
|
|
36
|
+
Arrays.asList("sync_messages_response", "sync:messages", "room:message_notification")
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
private Socket mSocket;
|
|
40
|
+
private SharedPreferences.OnSharedPreferenceChangeListener mPrefsListener;
|
|
41
|
+
private String mCurrentToken;
|
|
42
|
+
|
|
43
|
+
public static void start(Context context) {
|
|
44
|
+
Intent intent = new Intent(context, PersistentSocketService.class);
|
|
45
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
46
|
+
context.startForegroundService(intent);
|
|
47
|
+
} else {
|
|
48
|
+
context.startService(intent);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
public static void stop(Context context) {
|
|
53
|
+
context.stopService(new Intent(context, PersistentSocketService.class));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@Override
|
|
57
|
+
public void onCreate() {
|
|
58
|
+
super.onCreate();
|
|
59
|
+
ensureChannel();
|
|
60
|
+
startForeground(NOTIFICATION_ID, buildNotification("Messaging Active"));
|
|
61
|
+
setupPrefsListener();
|
|
62
|
+
connectSocket();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@Override
|
|
66
|
+
public int onStartCommand(Intent intent, int flags, int startId) {
|
|
67
|
+
return START_STICKY;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@Override
|
|
71
|
+
public void onDestroy() {
|
|
72
|
+
super.onDestroy();
|
|
73
|
+
if (mPrefsListener != null) {
|
|
74
|
+
getSharedPreferences("messenger_plugin_prefs", MODE_PRIVATE).unregisterOnSharedPreferenceChangeListener(mPrefsListener);
|
|
75
|
+
}
|
|
76
|
+
disconnectSocket();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@Nullable
|
|
80
|
+
@Override
|
|
81
|
+
public IBinder onBind(Intent intent) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private void setupPrefsListener() {
|
|
86
|
+
mPrefsListener = (prefs, key) -> {
|
|
87
|
+
if ("auth_token".equals(key)) {
|
|
88
|
+
String newToken = prefs.getString("auth_token", null);
|
|
89
|
+
if (!TextUtils.equals(newToken, mCurrentToken)) {
|
|
90
|
+
disconnectSocket();
|
|
91
|
+
connectSocket();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
getSharedPreferences("messenger_plugin_prefs", MODE_PRIVATE).registerOnSharedPreferenceChangeListener(mPrefsListener);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
private synchronized void connectSocket() {
|
|
99
|
+
if (mSocket != null && mSocket.connected()) return;
|
|
100
|
+
|
|
101
|
+
SharedPreferences prefs = getSharedPreferences("messenger_plugin_prefs", Context.MODE_PRIVATE);
|
|
102
|
+
mCurrentToken = prefs.getString("auth_token", null);
|
|
103
|
+
String socketUrl = prefs.getString("socket_url", null);
|
|
104
|
+
|
|
105
|
+
if (TextUtils.isEmpty(mCurrentToken) || TextUtils.isEmpty(socketUrl)) {
|
|
106
|
+
updateNotification("Waiting for credentials...");
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
IO.Options options = new IO.Options();
|
|
112
|
+
options.forceNew = true;
|
|
113
|
+
options.reconnection = true;
|
|
114
|
+
options.reconnectionDelay = 5000;
|
|
115
|
+
options.reconnectionDelayMax = 30000;
|
|
116
|
+
options.timeout = 20000;
|
|
117
|
+
options.transports = new String[] { WebSocket.NAME, Polling.NAME };
|
|
118
|
+
|
|
119
|
+
// Socket.IO v4.x auth mechanism
|
|
120
|
+
Map<String, String> auth = new HashMap<>();
|
|
121
|
+
auth.put("token", mCurrentToken);
|
|
122
|
+
options.auth = auth;
|
|
123
|
+
|
|
124
|
+
mSocket = IO.socket(socketUrl, options);
|
|
125
|
+
|
|
126
|
+
mSocket.on(Socket.EVENT_CONNECT, (args) -> {
|
|
127
|
+
updateNotification("Connected");
|
|
128
|
+
mSocket.emit("sync_messages");
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
mSocket.on(Socket.EVENT_DISCONNECT, (args) -> {
|
|
132
|
+
updateNotification("Reconnecting...");
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
mSocket.on(Socket.EVENT_CONNECT_ERROR, (args) -> {
|
|
136
|
+
updateNotification("Connection error, retrying...");
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
mSocket.onAnyIncoming((args) -> {
|
|
140
|
+
if (args != null && args.length > 0) {
|
|
141
|
+
String event = String.valueOf(args[0]);
|
|
142
|
+
if (MESSAGE_EVENTS.contains(event)) {
|
|
143
|
+
Object[] payloadArgs = args.length > 1 ? Arrays.copyOfRange(args, 1, args.length) : new Object[0];
|
|
144
|
+
handleSocketMessage(event, payloadArgs);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
mSocket.connect();
|
|
150
|
+
} catch (URISyntaxException e) {
|
|
151
|
+
Log.e(TAG, "Invalid socket URL", e);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
private void handleSocketMessage(String event, Object[] args) {
|
|
156
|
+
if (args == null || args.length == 0) return;
|
|
157
|
+
boolean syncReceived = "sync_messages_response".equals(event);
|
|
158
|
+
for (Object arg : args) {
|
|
159
|
+
if (syncReceived) {
|
|
160
|
+
EncryptedMessageNotifier.notifyFromSyncMessagesResponse(this, arg);
|
|
161
|
+
} else {
|
|
162
|
+
EncryptedMessageNotifier.notifyFromSocketPayload(this, arg);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
private void disconnectSocket() {
|
|
168
|
+
if (mSocket != null) {
|
|
169
|
+
mSocket.off();
|
|
170
|
+
mSocket.disconnect();
|
|
171
|
+
mSocket.close();
|
|
172
|
+
mSocket = null;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
private void ensureChannel() {
|
|
177
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
178
|
+
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "Messaging Connection", NotificationManager.IMPORTANCE_LOW);
|
|
179
|
+
channel.setDescription("Maintains messaging connection background");
|
|
180
|
+
NotificationManager manager = getSystemService(NotificationManager.class);
|
|
181
|
+
if (manager != null) manager.createNotificationChannel(channel);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
private Notification buildNotification(String contentText) {
|
|
186
|
+
Intent launchIntent = getPackageManager().getLaunchIntentForPackage(getPackageName());
|
|
187
|
+
PendingIntent pendingIntent = null;
|
|
188
|
+
if (launchIntent != null) {
|
|
189
|
+
launchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
|
190
|
+
pendingIntent = PendingIntent.getActivity(
|
|
191
|
+
this,
|
|
192
|
+
0,
|
|
193
|
+
launchIntent,
|
|
194
|
+
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return new NotificationCompat.Builder(this, CHANNEL_ID)
|
|
199
|
+
.setSmallIcon(getApplicationInfo().icon)
|
|
200
|
+
.setContentTitle("Chat Messenger")
|
|
201
|
+
.setContentText(contentText)
|
|
202
|
+
.setOngoing(true)
|
|
203
|
+
.setCategory(NotificationCompat.CATEGORY_SERVICE)
|
|
204
|
+
.setOnlyAlertOnce(true)
|
|
205
|
+
.setContentIntent(pendingIntent)
|
|
206
|
+
.build();
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
private void updateNotification(String contentText) {
|
|
210
|
+
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
|
211
|
+
if (manager != null) manager.notify(NOTIFICATION_ID, buildNotification(contentText));
|
|
212
|
+
}
|
|
213
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { PermissionState } from '@capacitor/core';
|
|
2
|
+
export interface PermissionStatus {
|
|
3
|
+
notifications: PermissionState;
|
|
4
|
+
}
|
|
5
|
+
export interface MessengerNotificationsPlugin {
|
|
6
|
+
/**
|
|
7
|
+
* Shows a native notification, grouped by room.
|
|
8
|
+
*/
|
|
9
|
+
showNotification(options: {
|
|
10
|
+
title: string;
|
|
11
|
+
body: string;
|
|
12
|
+
roomId: number;
|
|
13
|
+
messageId?: string;
|
|
14
|
+
timestamp?: number;
|
|
15
|
+
roomName?: string;
|
|
16
|
+
}): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Clears notifications for a specific room.
|
|
19
|
+
*/
|
|
20
|
+
clearRoomNotification(options: {
|
|
21
|
+
roomId: number;
|
|
22
|
+
}): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Returns the roomId that triggered the app launch, if any.
|
|
25
|
+
*/
|
|
26
|
+
getPendingRoomId(): Promise<{
|
|
27
|
+
roomId: number | null;
|
|
28
|
+
}>;
|
|
29
|
+
/**
|
|
30
|
+
* Starts a persistent background service (Android only) that maintains a socket connection.
|
|
31
|
+
*/
|
|
32
|
+
startPersistentSocket(options: {
|
|
33
|
+
url: string;
|
|
34
|
+
token: string;
|
|
35
|
+
}): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Stops the persistent background service.
|
|
38
|
+
*/
|
|
39
|
+
stopPersistentSocket(): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Check notification permissions.
|
|
42
|
+
*/
|
|
43
|
+
checkPermissions(): Promise<PermissionStatus>;
|
|
44
|
+
/**
|
|
45
|
+
* Request notification permissions.
|
|
46
|
+
*/
|
|
47
|
+
requestPermissions(): Promise<PermissionStatus>;
|
|
48
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["import type { PermissionState } from '@capacitor/core';\n\nexport interface PermissionStatus {\n notifications: PermissionState;\n}\n\nexport interface MessengerNotificationsPlugin {\n /**\n * Shows a native notification, grouped by room.\n */\n showNotification(options: {\n title: string;\n body: string;\n roomId: number;\n messageId?: string;\n timestamp?: number;\n roomName?: string;\n }): Promise<void>;\n\n /**\n * Clears notifications for a specific room.\n */\n clearRoomNotification(options: { roomId: number }): Promise<void>;\n\n /**\n * Returns the roomId that triggered the app launch, if any.\n */\n getPendingRoomId(): Promise<{ roomId: number | null }>;\n\n /**\n * Starts a persistent background service (Android only) that maintains a socket connection.\n */\n startPersistentSocket(options: { url: string; token: string }): Promise<void>;\n\n /**\n * Stops the persistent background service.\n */\n stopPersistentSocket(): Promise<void>;\n\n /**\n * Check notification permissions.\n */\n checkPermissions(): Promise<PermissionStatus>;\n\n /**\n * Request notification permissions.\n */\n requestPermissions(): Promise<PermissionStatus>;\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { registerPlugin } from '@capacitor/core';
|
|
2
|
+
const MessengerNotifications = registerPlugin('MessengerNotifications', {
|
|
3
|
+
web: () => import('./web').then((m) => new m.MessengerNotificationsWeb()),
|
|
4
|
+
});
|
|
5
|
+
export * from './definitions';
|
|
6
|
+
export { MessengerNotifications };
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAIjD,MAAM,sBAAsB,GAAG,cAAc,CAA+B,wBAAwB,EAAE;IACpG,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,yBAAyB,EAAE,CAAC;CAC1E,CAAC,CAAC;AAEH,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,sBAAsB,EAAE,CAAC","sourcesContent":["import { registerPlugin } from '@capacitor/core';\n\nimport type { MessengerNotificationsPlugin } from './definitions';\n\nconst MessengerNotifications = registerPlugin<MessengerNotificationsPlugin>('MessengerNotifications', {\n web: () => import('./web').then((m) => new m.MessengerNotificationsWeb()),\n});\n\nexport * from './definitions';\nexport { MessengerNotifications };\n"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { WebPlugin } from '@capacitor/core';
|
|
2
|
+
import type { MessengerNotificationsPlugin, PermissionStatus } from './definitions';
|
|
3
|
+
export declare class MessengerNotificationsWeb extends WebPlugin implements MessengerNotificationsPlugin {
|
|
4
|
+
showNotification(options: {
|
|
5
|
+
title: string;
|
|
6
|
+
body: string;
|
|
7
|
+
roomId: number;
|
|
8
|
+
messageId?: string;
|
|
9
|
+
timestamp?: number;
|
|
10
|
+
roomName?: string;
|
|
11
|
+
}): Promise<void>;
|
|
12
|
+
clearRoomNotification(options: {
|
|
13
|
+
roomId: number;
|
|
14
|
+
}): Promise<void>;
|
|
15
|
+
getPendingRoomId(): Promise<{
|
|
16
|
+
roomId: number | null;
|
|
17
|
+
}>;
|
|
18
|
+
startPersistentSocket(options: {
|
|
19
|
+
url: string;
|
|
20
|
+
token: string;
|
|
21
|
+
}): Promise<void>;
|
|
22
|
+
stopPersistentSocket(): Promise<void>;
|
|
23
|
+
checkPermissions(): Promise<PermissionStatus>;
|
|
24
|
+
requestPermissions(): Promise<PermissionStatus>;
|
|
25
|
+
}
|
package/dist/esm/web.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { WebPlugin } from '@capacitor/core';
|
|
2
|
+
export class MessengerNotificationsWeb extends WebPlugin {
|
|
3
|
+
async showNotification(options) {
|
|
4
|
+
console.log('[MessengerNotificationsWeb] showNotification:', options);
|
|
5
|
+
if ('Notification' in window) {
|
|
6
|
+
if (Notification.permission === 'granted') {
|
|
7
|
+
new Notification(options.title, {
|
|
8
|
+
body: options.body,
|
|
9
|
+
data: { roomId: options.roomId, messageId: options.messageId },
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
async clearRoomNotification(options) {
|
|
15
|
+
console.log('[MessengerNotificationsWeb] clearRoomNotification:', options);
|
|
16
|
+
}
|
|
17
|
+
async getPendingRoomId() {
|
|
18
|
+
return { roomId: null };
|
|
19
|
+
}
|
|
20
|
+
async startPersistentSocket(options) {
|
|
21
|
+
console.log('[MessengerNotificationsWeb] startPersistentSocket (not supported on web):', options);
|
|
22
|
+
}
|
|
23
|
+
async stopPersistentSocket() {
|
|
24
|
+
console.log('[MessengerNotificationsWeb] stopPersistentSocket (not supported on web)');
|
|
25
|
+
}
|
|
26
|
+
async checkPermissions() {
|
|
27
|
+
if ('Notification' in window) {
|
|
28
|
+
const state = Notification.permission === 'granted' ? 'granted' : Notification.permission === 'denied' ? 'denied' : 'prompt';
|
|
29
|
+
return { notifications: state };
|
|
30
|
+
}
|
|
31
|
+
return { notifications: 'denied' };
|
|
32
|
+
}
|
|
33
|
+
async requestPermissions() {
|
|
34
|
+
if ('Notification' in window) {
|
|
35
|
+
const permission = await Notification.requestPermission();
|
|
36
|
+
const state = permission === 'granted' ? 'granted' : permission === 'denied' ? 'denied' : 'prompt';
|
|
37
|
+
return { notifications: state };
|
|
38
|
+
}
|
|
39
|
+
return { notifications: 'denied' };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=web.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI5C,MAAM,OAAO,yBAA0B,SAAQ,SAAS;IACtD,KAAK,CAAC,gBAAgB,CAAC,OAOtB;QACC,OAAO,CAAC,GAAG,CAAC,+CAA+C,EAAE,OAAO,CAAC,CAAC;QACtE,IAAI,cAAc,IAAI,MAAM,EAAE,CAAC;YAC7B,IAAI,YAAY,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;gBAC1C,IAAI,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE;oBAC9B,IAAI,EAAE,OAAO,CAAC,IAAI;oBAClB,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE;iBAC/D,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,qBAAqB,CAAC,OAA2B;QACrD,OAAO,CAAC,GAAG,CAAC,oDAAoD,EAAE,OAAO,CAAC,CAAC;IAC7E,CAAC;IAED,KAAK,CAAC,gBAAgB;QACpB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,qBAAqB,CAAC,OAAuC;QACjE,OAAO,CAAC,GAAG,CAAC,2EAA2E,EAAE,OAAO,CAAC,CAAC;IACpG,CAAC;IAED,KAAK,CAAC,oBAAoB;QACxB,OAAO,CAAC,GAAG,CAAC,yEAAyE,CAAC,CAAC;IACzF,CAAC;IAED,KAAK,CAAC,gBAAgB;QACpB,IAAI,cAAc,IAAI,MAAM,EAAE,CAAC;YAC7B,MAAM,KAAK,GACT,YAAY,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;YACjH,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC;QAClC,CAAC;QACD,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,kBAAkB;QACtB,IAAI,cAAc,IAAI,MAAM,EAAE,CAAC;YAC7B,MAAM,UAAU,GAAG,MAAM,YAAY,CAAC,iBAAiB,EAAE,CAAC;YAC1D,MAAM,KAAK,GAAG,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;YACnG,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC;QAClC,CAAC;QACD,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC;IACrC,CAAC;CACF","sourcesContent":["import { WebPlugin } from '@capacitor/core';\n\nimport type { MessengerNotificationsPlugin, PermissionStatus } from './definitions';\n\nexport class MessengerNotificationsWeb extends WebPlugin implements MessengerNotificationsPlugin {\n async showNotification(options: {\n title: string;\n body: string;\n roomId: number;\n messageId?: string;\n timestamp?: number;\n roomName?: string;\n }): Promise<void> {\n console.log('[MessengerNotificationsWeb] showNotification:', options);\n if ('Notification' in window) {\n if (Notification.permission === 'granted') {\n new Notification(options.title, {\n body: options.body,\n data: { roomId: options.roomId, messageId: options.messageId },\n });\n }\n }\n }\n\n async clearRoomNotification(options: { roomId: number }): Promise<void> {\n console.log('[MessengerNotificationsWeb] clearRoomNotification:', options);\n }\n\n async getPendingRoomId(): Promise<{ roomId: number | null }> {\n return { roomId: null };\n }\n\n async startPersistentSocket(options: { url: string; token: string }): Promise<void> {\n console.log('[MessengerNotificationsWeb] startPersistentSocket (not supported on web):', options);\n }\n\n async stopPersistentSocket(): Promise<void> {\n console.log('[MessengerNotificationsWeb] stopPersistentSocket (not supported on web)');\n }\n\n async checkPermissions(): Promise<PermissionStatus> {\n if ('Notification' in window) {\n const state =\n Notification.permission === 'granted' ? 'granted' : Notification.permission === 'denied' ? 'denied' : 'prompt';\n return { notifications: state };\n }\n return { notifications: 'denied' };\n }\n\n async requestPermissions(): Promise<PermissionStatus> {\n if ('Notification' in window) {\n const permission = await Notification.requestPermission();\n const state = permission === 'granted' ? 'granted' : permission === 'denied' ? 'denied' : 'prompt';\n return { notifications: state };\n }\n return { notifications: 'denied' };\n }\n}\n"]}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var core = require('@capacitor/core');
|
|
4
|
+
|
|
5
|
+
const MessengerNotifications = core.registerPlugin('MessengerNotifications', {
|
|
6
|
+
web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.MessengerNotificationsWeb()),
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
class MessengerNotificationsWeb extends core.WebPlugin {
|
|
10
|
+
async showNotification(options) {
|
|
11
|
+
console.log('[MessengerNotificationsWeb] showNotification:', options);
|
|
12
|
+
if ('Notification' in window) {
|
|
13
|
+
if (Notification.permission === 'granted') {
|
|
14
|
+
new Notification(options.title, {
|
|
15
|
+
body: options.body,
|
|
16
|
+
data: { roomId: options.roomId, messageId: options.messageId },
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
async clearRoomNotification(options) {
|
|
22
|
+
console.log('[MessengerNotificationsWeb] clearRoomNotification:', options);
|
|
23
|
+
}
|
|
24
|
+
async getPendingRoomId() {
|
|
25
|
+
return { roomId: null };
|
|
26
|
+
}
|
|
27
|
+
async startPersistentSocket(options) {
|
|
28
|
+
console.log('[MessengerNotificationsWeb] startPersistentSocket (not supported on web):', options);
|
|
29
|
+
}
|
|
30
|
+
async stopPersistentSocket() {
|
|
31
|
+
console.log('[MessengerNotificationsWeb] stopPersistentSocket (not supported on web)');
|
|
32
|
+
}
|
|
33
|
+
async checkPermissions() {
|
|
34
|
+
if ('Notification' in window) {
|
|
35
|
+
const state = Notification.permission === 'granted' ? 'granted' : Notification.permission === 'denied' ? 'denied' : 'prompt';
|
|
36
|
+
return { notifications: state };
|
|
37
|
+
}
|
|
38
|
+
return { notifications: 'denied' };
|
|
39
|
+
}
|
|
40
|
+
async requestPermissions() {
|
|
41
|
+
if ('Notification' in window) {
|
|
42
|
+
const permission = await Notification.requestPermission();
|
|
43
|
+
const state = permission === 'granted' ? 'granted' : permission === 'denied' ? 'denied' : 'prompt';
|
|
44
|
+
return { notifications: state };
|
|
45
|
+
}
|
|
46
|
+
return { notifications: 'denied' };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
var web = /*#__PURE__*/Object.freeze({
|
|
51
|
+
__proto__: null,
|
|
52
|
+
MessengerNotificationsWeb: MessengerNotificationsWeb
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
exports.MessengerNotifications = MessengerNotifications;
|
|
56
|
+
//# sourceMappingURL=plugin.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst MessengerNotifications = registerPlugin('MessengerNotifications', {\n web: () => import('./web').then((m) => new m.MessengerNotificationsWeb()),\n});\nexport * from './definitions';\nexport { MessengerNotifications };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class MessengerNotificationsWeb extends WebPlugin {\n async showNotification(options) {\n console.log('[MessengerNotificationsWeb] showNotification:', options);\n if ('Notification' in window) {\n if (Notification.permission === 'granted') {\n new Notification(options.title, {\n body: options.body,\n data: { roomId: options.roomId, messageId: options.messageId },\n });\n }\n }\n }\n async clearRoomNotification(options) {\n console.log('[MessengerNotificationsWeb] clearRoomNotification:', options);\n }\n async getPendingRoomId() {\n return { roomId: null };\n }\n async startPersistentSocket(options) {\n console.log('[MessengerNotificationsWeb] startPersistentSocket (not supported on web):', options);\n }\n async stopPersistentSocket() {\n console.log('[MessengerNotificationsWeb] stopPersistentSocket (not supported on web)');\n }\n async checkPermissions() {\n if ('Notification' in window) {\n const state = Notification.permission === 'granted' ? 'granted' : Notification.permission === 'denied' ? 'denied' : 'prompt';\n return { notifications: state };\n }\n return { notifications: 'denied' };\n }\n async requestPermissions() {\n if ('Notification' in window) {\n const permission = await Notification.requestPermission();\n const state = permission === 'granted' ? 'granted' : permission === 'denied' ? 'denied' : 'prompt';\n return { notifications: state };\n }\n return { notifications: 'denied' };\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;;AACK,MAAC,sBAAsB,GAAGA,mBAAc,CAAC,wBAAwB,EAAE;AACxE,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,yBAAyB,EAAE,CAAC;AAC7E,CAAC;;ACFM,MAAM,yBAAyB,SAASC,cAAS,CAAC;AACzD,IAAI,MAAM,gBAAgB,CAAC,OAAO,EAAE;AACpC,QAAQ,OAAO,CAAC,GAAG,CAAC,+CAA+C,EAAE,OAAO,CAAC;AAC7E,QAAQ,IAAI,cAAc,IAAI,MAAM,EAAE;AACtC,YAAY,IAAI,YAAY,CAAC,UAAU,KAAK,SAAS,EAAE;AACvD,gBAAgB,IAAI,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE;AAChD,oBAAoB,IAAI,EAAE,OAAO,CAAC,IAAI;AACtC,oBAAoB,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE;AAClF,iBAAiB,CAAC;AAClB,YAAY;AACZ,QAAQ;AACR,IAAI;AACJ,IAAI,MAAM,qBAAqB,CAAC,OAAO,EAAE;AACzC,QAAQ,OAAO,CAAC,GAAG,CAAC,oDAAoD,EAAE,OAAO,CAAC;AAClF,IAAI;AACJ,IAAI,MAAM,gBAAgB,GAAG;AAC7B,QAAQ,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE;AAC/B,IAAI;AACJ,IAAI,MAAM,qBAAqB,CAAC,OAAO,EAAE;AACzC,QAAQ,OAAO,CAAC,GAAG,CAAC,2EAA2E,EAAE,OAAO,CAAC;AACzG,IAAI;AACJ,IAAI,MAAM,oBAAoB,GAAG;AACjC,QAAQ,OAAO,CAAC,GAAG,CAAC,yEAAyE,CAAC;AAC9F,IAAI;AACJ,IAAI,MAAM,gBAAgB,GAAG;AAC7B,QAAQ,IAAI,cAAc,IAAI,MAAM,EAAE;AACtC,YAAY,MAAM,KAAK,GAAG,YAAY,CAAC,UAAU,KAAK,SAAS,GAAG,SAAS,GAAG,YAAY,CAAC,UAAU,KAAK,QAAQ,GAAG,QAAQ,GAAG,QAAQ;AACxI,YAAY,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE;AAC3C,QAAQ;AACR,QAAQ,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE;AAC1C,IAAI;AACJ,IAAI,MAAM,kBAAkB,GAAG;AAC/B,QAAQ,IAAI,cAAc,IAAI,MAAM,EAAE;AACtC,YAAY,MAAM,UAAU,GAAG,MAAM,YAAY,CAAC,iBAAiB,EAAE;AACrE,YAAY,MAAM,KAAK,GAAG,UAAU,KAAK,SAAS,GAAG,SAAS,GAAG,UAAU,KAAK,QAAQ,GAAG,QAAQ,GAAG,QAAQ;AAC9G,YAAY,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE;AAC3C,QAAQ;AACR,QAAQ,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE;AAC1C,IAAI;AACJ;;;;;;;;;"}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
var capacitorLEAN = (function (exports, core) {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const MessengerNotifications = core.registerPlugin('MessengerNotifications', {
|
|
5
|
+
web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.MessengerNotificationsWeb()),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
class MessengerNotificationsWeb extends core.WebPlugin {
|
|
9
|
+
async showNotification(options) {
|
|
10
|
+
console.log('[MessengerNotificationsWeb] showNotification:', options);
|
|
11
|
+
if ('Notification' in window) {
|
|
12
|
+
if (Notification.permission === 'granted') {
|
|
13
|
+
new Notification(options.title, {
|
|
14
|
+
body: options.body,
|
|
15
|
+
data: { roomId: options.roomId, messageId: options.messageId },
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
async clearRoomNotification(options) {
|
|
21
|
+
console.log('[MessengerNotificationsWeb] clearRoomNotification:', options);
|
|
22
|
+
}
|
|
23
|
+
async getPendingRoomId() {
|
|
24
|
+
return { roomId: null };
|
|
25
|
+
}
|
|
26
|
+
async startPersistentSocket(options) {
|
|
27
|
+
console.log('[MessengerNotificationsWeb] startPersistentSocket (not supported on web):', options);
|
|
28
|
+
}
|
|
29
|
+
async stopPersistentSocket() {
|
|
30
|
+
console.log('[MessengerNotificationsWeb] stopPersistentSocket (not supported on web)');
|
|
31
|
+
}
|
|
32
|
+
async checkPermissions() {
|
|
33
|
+
if ('Notification' in window) {
|
|
34
|
+
const state = Notification.permission === 'granted' ? 'granted' : Notification.permission === 'denied' ? 'denied' : 'prompt';
|
|
35
|
+
return { notifications: state };
|
|
36
|
+
}
|
|
37
|
+
return { notifications: 'denied' };
|
|
38
|
+
}
|
|
39
|
+
async requestPermissions() {
|
|
40
|
+
if ('Notification' in window) {
|
|
41
|
+
const permission = await Notification.requestPermission();
|
|
42
|
+
const state = permission === 'granted' ? 'granted' : permission === 'denied' ? 'denied' : 'prompt';
|
|
43
|
+
return { notifications: state };
|
|
44
|
+
}
|
|
45
|
+
return { notifications: 'denied' };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
var web = /*#__PURE__*/Object.freeze({
|
|
50
|
+
__proto__: null,
|
|
51
|
+
MessengerNotificationsWeb: MessengerNotificationsWeb
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
exports.MessengerNotifications = MessengerNotifications;
|
|
55
|
+
|
|
56
|
+
return exports;
|
|
57
|
+
|
|
58
|
+
})({}, capacitorExports);
|
|
59
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst MessengerNotifications = registerPlugin('MessengerNotifications', {\n web: () => import('./web').then((m) => new m.MessengerNotificationsWeb()),\n});\nexport * from './definitions';\nexport { MessengerNotifications };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class MessengerNotificationsWeb extends WebPlugin {\n async showNotification(options) {\n console.log('[MessengerNotificationsWeb] showNotification:', options);\n if ('Notification' in window) {\n if (Notification.permission === 'granted') {\n new Notification(options.title, {\n body: options.body,\n data: { roomId: options.roomId, messageId: options.messageId },\n });\n }\n }\n }\n async clearRoomNotification(options) {\n console.log('[MessengerNotificationsWeb] clearRoomNotification:', options);\n }\n async getPendingRoomId() {\n return { roomId: null };\n }\n async startPersistentSocket(options) {\n console.log('[MessengerNotificationsWeb] startPersistentSocket (not supported on web):', options);\n }\n async stopPersistentSocket() {\n console.log('[MessengerNotificationsWeb] stopPersistentSocket (not supported on web)');\n }\n async checkPermissions() {\n if ('Notification' in window) {\n const state = Notification.permission === 'granted' ? 'granted' : Notification.permission === 'denied' ? 'denied' : 'prompt';\n return { notifications: state };\n }\n return { notifications: 'denied' };\n }\n async requestPermissions() {\n if ('Notification' in window) {\n const permission = await Notification.requestPermission();\n const state = permission === 'granted' ? 'granted' : permission === 'denied' ? 'denied' : 'prompt';\n return { notifications: state };\n }\n return { notifications: 'denied' };\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;AACK,UAAC,sBAAsB,GAAGA,mBAAc,CAAC,wBAAwB,EAAE;IACxE,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,yBAAyB,EAAE,CAAC;IAC7E,CAAC;;ICFM,MAAM,yBAAyB,SAASC,cAAS,CAAC;IACzD,IAAI,MAAM,gBAAgB,CAAC,OAAO,EAAE;IACpC,QAAQ,OAAO,CAAC,GAAG,CAAC,+CAA+C,EAAE,OAAO,CAAC;IAC7E,QAAQ,IAAI,cAAc,IAAI,MAAM,EAAE;IACtC,YAAY,IAAI,YAAY,CAAC,UAAU,KAAK,SAAS,EAAE;IACvD,gBAAgB,IAAI,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE;IAChD,oBAAoB,IAAI,EAAE,OAAO,CAAC,IAAI;IACtC,oBAAoB,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE;IAClF,iBAAiB,CAAC;IAClB,YAAY;IACZ,QAAQ;IACR,IAAI;IACJ,IAAI,MAAM,qBAAqB,CAAC,OAAO,EAAE;IACzC,QAAQ,OAAO,CAAC,GAAG,CAAC,oDAAoD,EAAE,OAAO,CAAC;IAClF,IAAI;IACJ,IAAI,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE;IAC/B,IAAI;IACJ,IAAI,MAAM,qBAAqB,CAAC,OAAO,EAAE;IACzC,QAAQ,OAAO,CAAC,GAAG,CAAC,2EAA2E,EAAE,OAAO,CAAC;IACzG,IAAI;IACJ,IAAI,MAAM,oBAAoB,GAAG;IACjC,QAAQ,OAAO,CAAC,GAAG,CAAC,yEAAyE,CAAC;IAC9F,IAAI;IACJ,IAAI,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,IAAI,cAAc,IAAI,MAAM,EAAE;IACtC,YAAY,MAAM,KAAK,GAAG,YAAY,CAAC,UAAU,KAAK,SAAS,GAAG,SAAS,GAAG,YAAY,CAAC,UAAU,KAAK,QAAQ,GAAG,QAAQ,GAAG,QAAQ;IACxI,YAAY,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE;IAC3C,QAAQ;IACR,QAAQ,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE;IAC1C,IAAI;IACJ,IAAI,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,IAAI,cAAc,IAAI,MAAM,EAAE;IACtC,YAAY,MAAM,UAAU,GAAG,MAAM,YAAY,CAAC,iBAAiB,EAAE;IACrE,YAAY,MAAM,KAAK,GAAG,UAAU,KAAK,SAAS,GAAG,SAAS,GAAG,UAAU,KAAK,QAAQ,GAAG,QAAQ,GAAG,QAAQ;IAC9G,YAAY,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE;IAC3C,QAAQ;IACR,QAAQ,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE;IAC1C,IAAI;IACJ;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Capacitor
|
|
3
|
+
|
|
4
|
+
@objc(MessengerNotificationsPlugin)
|
|
5
|
+
public class MessengerNotificationsPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
6
|
+
public let identifier = "MessengerNotificationsPlugin"
|
|
7
|
+
public let jsName = "MessengerNotifications"
|
|
8
|
+
public let pluginMethods: [CAPPluginMethod] = [
|
|
9
|
+
CAPPluginMethod(name: "showNotification", returnType: CAPPluginReturnPromise),
|
|
10
|
+
CAPPluginMethod(name: "clearRoomNotification", returnType: CAPPluginReturnPromise),
|
|
11
|
+
CAPPluginMethod(name: "getPendingRoomId", returnType: CAPPluginReturnPromise),
|
|
12
|
+
CAPPluginMethod(name: "startPersistentSocket", returnType: CAPPluginReturnPromise),
|
|
13
|
+
CAPPluginMethod(name: "stopPersistentSocket", returnType: CAPPluginReturnPromise)
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
private static var _pendingRoomId: Int? = nil
|
|
17
|
+
public static var pendingRoomId: Int? {
|
|
18
|
+
get { return _pendingRoomId }
|
|
19
|
+
set { _pendingRoomId = newValue }
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@objc func showNotification(_ call: CAPPluginCall) {
|
|
23
|
+
let title = call.getString("title") ?? "New Message"
|
|
24
|
+
let body = call.getString("body") ?? "You have a new message"
|
|
25
|
+
let roomId = call.getInt("roomId") ?? 0
|
|
26
|
+
let messageId = call.getString("messageId")
|
|
27
|
+
let timestamp = call.getInt("timestamp") ?? 0
|
|
28
|
+
let roomName = call.getString("roomName")
|
|
29
|
+
|
|
30
|
+
NotificationHelper.showRoomNotification(
|
|
31
|
+
title: title,
|
|
32
|
+
body: body,
|
|
33
|
+
roomId: roomId,
|
|
34
|
+
messageId: messageId,
|
|
35
|
+
timestamp: Int64(timestamp),
|
|
36
|
+
isSync: false
|
|
37
|
+
)
|
|
38
|
+
call.resolve()
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@objc func clearRoomNotification(_ call: CAPPluginCall) {
|
|
42
|
+
let roomId = call.getInt("roomId") ?? 0
|
|
43
|
+
if roomId > 0 {
|
|
44
|
+
NotificationHelper.clearRoomHistory(roomId: roomId)
|
|
45
|
+
}
|
|
46
|
+
call.resolve()
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@objc func getPendingRoomId(_ call: CAPPluginCall) {
|
|
50
|
+
if let rid = MessengerNotificationsPlugin.pendingRoomId {
|
|
51
|
+
call.resolve(["roomId": rid])
|
|
52
|
+
MessengerNotificationsPlugin.pendingRoomId = nil
|
|
53
|
+
} else {
|
|
54
|
+
call.resolve(["roomId": NSNull()])
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@objc func startPersistentSocket(_ call: CAPPluginCall) {
|
|
59
|
+
guard let url = call.getString("url"), let token = call.getString("token") else {
|
|
60
|
+
call.reject("Missing URL or token")
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// On iOS, persistent sockets are usually handled differently (or not at all in same way as Android service)
|
|
65
|
+
// because of background limits. But for now we'll store them.
|
|
66
|
+
SafeStorageStore.set("socket_url", value: url)
|
|
67
|
+
SafeStorageStore.set("auth_token", value: token)
|
|
68
|
+
|
|
69
|
+
// We'll call complete for now.
|
|
70
|
+
call.resolve()
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@objc func stopPersistentSocket(_ call: CAPPluginCall) {
|
|
74
|
+
call.resolve()
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Native crypto logic picked from ChatE2EE-IOS.
|
|
5
|
+
*/
|
|
6
|
+
public enum NativeCrypto {
|
|
7
|
+
public struct DecryptResult {
|
|
8
|
+
public let text: String
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Placeholder decryption logic.
|
|
13
|
+
*/
|
|
14
|
+
public static func decryptRoomData(roomId: Int, encryptedJSON: String) throws -> DecryptResult {
|
|
15
|
+
// Placeholder return the encrypted text
|
|
16
|
+
return DecryptResult(text: encryptedJSON)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public static func decryptUserData(userId: Int, encryptedJSON: String) throws -> DecryptResult {
|
|
20
|
+
return DecryptResult(text: encryptedJSON)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import UserNotifications
|
|
3
|
+
import os.log
|
|
4
|
+
|
|
5
|
+
enum NotificationHelper {
|
|
6
|
+
private static let log = OSLog(subsystem: Bundle.main.bundleIdentifier ?? "com.codecraft_studio.messenger.notifications",
|
|
7
|
+
category: "Notifications")
|
|
8
|
+
|
|
9
|
+
private static let historyKey = "notification_history_map"
|
|
10
|
+
private static let dismissedUntilKey = "dismissed_until_by_room"
|
|
11
|
+
private static let maxMessagesPerRoom = 20
|
|
12
|
+
|
|
13
|
+
static func showRoomNotification(title: String,
|
|
14
|
+
body: String,
|
|
15
|
+
roomId: Int,
|
|
16
|
+
messageId: String? = nil,
|
|
17
|
+
timestamp: Int64 = 0,
|
|
18
|
+
isSync: Bool = false) {
|
|
19
|
+
|
|
20
|
+
let center = UNUserNotificationCenter.current()
|
|
21
|
+
let identifier = "\(roomId)"
|
|
22
|
+
let threadIdentifier = "room_\(roomId)"
|
|
23
|
+
|
|
24
|
+
// Add to history for summary logic
|
|
25
|
+
addToHistory(roomId: roomId, title: title, body: body, messageId: messageId, timestamp: timestamp)
|
|
26
|
+
|
|
27
|
+
let content = UNMutableNotificationContent()
|
|
28
|
+
content.title = title
|
|
29
|
+
content.body = body
|
|
30
|
+
content.sound = .default
|
|
31
|
+
content.userInfo = ["roomId": roomId, "messageId": messageId ?? ""]
|
|
32
|
+
content.threadIdentifier = threadIdentifier
|
|
33
|
+
content.categoryIdentifier = "CHAT_MESSAGE"
|
|
34
|
+
|
|
35
|
+
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: nil)
|
|
36
|
+
center.add(request) { error in
|
|
37
|
+
if let error = error {
|
|
38
|
+
os_log("❌ Failed to add notification: %{public}@", log: log, type: .error, error.localizedDescription)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
static func clearRoomHistory(roomId: Int) {
|
|
44
|
+
let center = UNUserNotificationCenter.current()
|
|
45
|
+
center.removeDeliveredNotifications(withIdentifiers: ["\(roomId)"])
|
|
46
|
+
// Also remove summary if any
|
|
47
|
+
clearHistory(roomId: roomId)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private static func addToHistory(roomId: Int, title: String, body: String, messageId: String?, timestamp: Int64) {
|
|
51
|
+
// Implementation for history if needed for summaries on iOS.
|
|
52
|
+
// On iOS, system handles grouping by threadIdentifier automatically if supported.
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private static func clearHistory(roomId: Int) {
|
|
56
|
+
// Implementation
|
|
57
|
+
}
|
|
58
|
+
}
|