@amityco/social-plus-vise 0.14.28 → 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/CHANGELOG.md +40 -0
- package/README.md +6 -11
- package/dist/tools/ast.js +153 -28
- package/dist/tools/docs.js +48 -0
- package/dist/tools/sdkFacts.js +45 -1
- package/docs-cache/README.md +34 -0
- package/docs-cache/social-plus-sdk/core-concepts/foundation/logging.mdx +236 -0
- package/docs-cache/social-plus-sdk/core-concepts/realtime-communication/live-objects-collections/android.mdx +262 -0
- package/docs-cache/social-plus-sdk/core-concepts/realtime-communication/live-objects-collections/flutter.mdx +195 -0
- package/docs-cache/social-plus-sdk/core-concepts/realtime-communication/live-objects-collections/ios.mdx +452 -0
- package/docs-cache/social-plus-sdk/core-concepts/realtime-communication/live-objects-collections/overview.mdx +133 -0
- package/docs-cache/social-plus-sdk/core-concepts/realtime-communication/live-objects-collections/typescript.mdx +264 -0
- package/docs-cache/social-plus-sdk/core-concepts/realtime-communication/push-notifications/register-and-unregister-push-notifications-on-a-device.mdx +191 -0
- package/docs-cache/social-plus-sdk/core-concepts/realtime-communication/push-notifications/settings/overview.mdx +43 -0
- package/docs-cache/social-plus-sdk/core-concepts/realtime-communication/push-notifications/setup/android-setup.mdx +360 -0
- package/docs-cache/social-plus-sdk/core-concepts/realtime-communication/push-notifications/setup/flutter-setup.mdx +457 -0
- package/docs-cache/social-plus-sdk/core-concepts/realtime-communication/push-notifications/setup/ios-setup.mdx +423 -0
- package/docs-cache/social-plus-sdk/core-concepts/realtime-communication/push-notifications/setup/react-native-setup.mdx +384 -0
- package/docs-cache/social-plus-sdk/core-concepts/realtime-communication/realtime-events/overview.mdx +94 -0
- package/docs-cache/social-plus-sdk/getting-started/authentication.mdx +808 -0
- package/docs-cache/social-plus-sdk/getting-started/platform-setup/mobile/android-quick-start.mdx +304 -0
- package/docs-cache/social-plus-sdk/getting-started/platform-setup/mobile/flutter-quick-start.mdx +121 -0
- package/docs-cache/social-plus-sdk/getting-started/platform-setup/mobile/ios-quick-start.mdx +225 -0
- package/docs-cache/social-plus-sdk/getting-started/platform-setup/web/web-quick-start.mdx +99 -0
- package/docs-cache/social-plus-sdk/social/communities-spaces/organization/community-invitation.mdx +459 -0
- package/docs-cache/social-plus-sdk/social/communities-spaces/organization/join-leave-community.mdx +449 -0
- package/docs-cache/social-plus-sdk/social/communities-spaces/organization/query-community-members.mdx +376 -0
- package/docs-cache/social-plus-sdk/social/content-management/posts/creation/text-post.mdx +318 -0
- package/docs-cache/social-plus-sdk/social/discovery-engagement/notifications/notification-tray-status.mdx +399 -0
- package/docs-cache/social-plus-sdk/social/user-relationship/blocking/block-unblock-user.mdx +166 -0
- package/docs-cache/social-plus-sdk/social/user-relationship/following/get-follower-following-list.mdx +339 -0
- package/package.json +10 -3
- package/scripts/dart-model-extractor/bin/extract_models.dart +169 -0
- package/scripts/dart-model-extractor/pubspec.lock +149 -0
- package/scripts/dart-model-extractor/pubspec.yaml +16 -0
- package/scripts/extract-sdk-models.mjs +353 -12
- package/scripts/import-sdk-surface.mjs +10 -19
- package/sdk-surface/manifest.json +15 -15
- package/sdk-surface/models.android.json +1 -1
- package/sdk-surface/models.flutter.json +465 -465
- package/sdk-surface/models.ios.json +188 -188
- package/sdk-surface/models.typescript.json +1 -1
- package/skills/social-plus-vise/SKILL.md +14 -0
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
# TypeScript Live Objects/Collections
|
|
2
|
+
|
|
3
|
+
> Live Objects are supported in the TypeScript SDK with subscribable objects and collections for real-time data synchronization
|
|
4
|
+
|
|
5
|
+
In the social.plus TypeScript SDK, we have the concept of **Live Object** and **Live Collection**.
|
|
6
|
+
|
|
7
|
+
Live Object is represented by an instance of social.plus Object. It helps to observe changes in a single object whereas Live Collection is represented by an instance of social.plus LiveCollection. It helps to observe changes in a list of objects.
|
|
8
|
+
|
|
9
|
+
SDK handles lots of data received from various sources. Data can be present in the local cache. It may also be queried from the server or received from real-time events. What this means is that the same data is constantly updating. The data that you are accessing at the moment can get updated and become out of sync.
|
|
10
|
+
|
|
11
|
+
Live Object and Live Collection help in syncing data so you will always get the most recent one. New data gets automatically collected every time when there is an update and the user need not refresh to get the recent data.
|
|
12
|
+
|
|
13
|
+
Examples: `Amity.Post` for single objects or `Amity.LiveCollection<Amity.Post>` for collections.
|
|
14
|
+
|
|
15
|
+
## How it Works
|
|
16
|
+
|
|
17
|
+
SDK handles lots of data received from various sources. Data can be present in local cache. It might also be queried from the server or received from some real-time events. What this means is that same data is constantly updating. The data that you are accessing at the moment can get updated by other sources and becomes out of sync.
|
|
18
|
+
|
|
19
|
+
Live Object and Live Collection help in syncing the data so you will always get the most recent one. Whenever the data updates, you will be notified through subscribable objects and collections.
|
|
20
|
+
|
|
21
|
+
New data gets automatically collected everytime when there is an updation and user need not refresh to get the recent data.
|
|
22
|
+
|
|
23
|
+
### Data Sources
|
|
24
|
+
|
|
25
|
+
Data present in local storage
|
|
26
|
+
Data queried from the server
|
|
27
|
+
Data received from real-time events
|
|
28
|
+
|
|
29
|
+
## Live Object
|
|
30
|
+
|
|
31
|
+
Although live objects were introduced prior to v6. All getter methods for singular objects (example getPost) will now return a subscribe-able object.
|
|
32
|
+
|
|
33
|
+
This means that if an object gets updated and you have subscribed to real-time events, the object will get updated automatically via real-time events.
|
|
34
|
+
|
|
35
|
+
If for your use case, you don't require any real-time updates, you can unsubscribe immediately.
|
|
36
|
+
|
|
37
|
+
For further information about Live Object, please visit Live Object page.
|
|
38
|
+
|
|
39
|
+
### Getting Real Time Updates for an Object
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { PostRepository, subscribeTopic, getPostTopic } from '@amityco/ts-sdk';
|
|
43
|
+
import { FC, useEffect, useState } from 'react';
|
|
44
|
+
|
|
45
|
+
const disposers: Amity.Unsubscriber[] = [];
|
|
46
|
+
|
|
47
|
+
const GetPost: FC<{ postId: string }> = ({ postId }) => {
|
|
48
|
+
const [post, setPost] = useState<Amity.Post>();
|
|
49
|
+
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
|
|
52
|
+
const unsubscribePost = PostRepository.getPost(postId, ({ data }) => {
|
|
53
|
+
const { post, loading, error } = data
|
|
54
|
+
|
|
55
|
+
if (post) {
|
|
56
|
+
/*
|
|
57
|
+
* This step is important if you wish to recieve real time updates
|
|
58
|
+
* Here, you are letting the server know that you wish to recieve real time
|
|
59
|
+
* updates regarding this post
|
|
60
|
+
*/
|
|
61
|
+
disposers.push(subscribeTopic(getPostTopic(post)))
|
|
62
|
+
|
|
63
|
+
setPost(post)
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
disposers.push(unsubscribePost);
|
|
68
|
+
}, [postId]);
|
|
69
|
+
|
|
70
|
+
return null;
|
|
71
|
+
};
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Getting the object only once
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
import { PostRepository } from '@amityco/ts-sdk';
|
|
78
|
+
import { FC, useEffect, useState } from 'react';
|
|
79
|
+
|
|
80
|
+
const GetPostOnce: FC<{ postId: string }> = ({ postId }) => {
|
|
81
|
+
const [post, setPost] = useState<Amity.Post>();
|
|
82
|
+
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
const unsubscribePost = PostRepository.getPost(postId, ({ data }) => {
|
|
85
|
+
const { post, loading, error } = data
|
|
86
|
+
|
|
87
|
+
if (post) {
|
|
88
|
+
setPost(post)
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
unsubscribePost()
|
|
93
|
+
}, [postId]);
|
|
94
|
+
|
|
95
|
+
return null;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
## Live Collection
|
|
99
|
+
|
|
100
|
+
Although live collections were introduced prior to v6. All query methods for the collection of objects (example getPosts) will now return a subscribe-able collection.
|
|
101
|
+
|
|
102
|
+
This means that if an object in the collection gets updated and you have subscribed to real-time events, the collection will get updated automatically via real-time events.
|
|
103
|
+
|
|
104
|
+
If for your use case, you don't require any real-time updates, you can unsubscribe immediately. Similar to the live objects above.
|
|
105
|
+
|
|
106
|
+
<Info>
|
|
107
|
+
For further information about Live Collection, please visit Live Collection page.
|
|
108
|
+
</Info>
|
|
109
|
+
|
|
110
|
+
### Getting Real-Time updates for a collection
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
PostRepository,
|
|
114
|
+
subscribeTopic,
|
|
115
|
+
getUserTopic,
|
|
116
|
+
getCommunityTopic,
|
|
117
|
+
SubscriptionLevels,
|
|
118
|
+
} from '@amityco/ts-sdk';
|
|
119
|
+
|
|
120
|
+
const disposers: Amity.Unsubscriber[] = [];
|
|
121
|
+
|
|
122
|
+
const GetPosts: FC<{ targetId: string; targetType: string }> =
|
|
123
|
+
({ targetId, targetType }) => {
|
|
124
|
+
const [posts, setPosts] = useState<Amity.Post[]>();
|
|
125
|
+
|
|
126
|
+
useEffect(() => {
|
|
127
|
+
const unsubscribe = PostRepository.getPosts(
|
|
128
|
+
{ targetId, targetType },
|
|
129
|
+
({ data: posts, onNextPage, hasNextPage, loading, error }) => {
|
|
130
|
+
setPosts(posts);
|
|
131
|
+
/*
|
|
132
|
+
* this is only required if you want real time updates for each
|
|
133
|
+
* post in the collection
|
|
134
|
+
*/
|
|
135
|
+
subscribePostTopic(targetType, targetId);
|
|
136
|
+
},
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
disposers.push(unsubscribe);
|
|
140
|
+
|
|
141
|
+
return () => {
|
|
142
|
+
disposers.forEach(fn => fn());
|
|
143
|
+
};
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
return null;
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const subscribePostTopic = (targetType: string, targetId: string) => {
|
|
150
|
+
if (isSubscribed) return;
|
|
151
|
+
|
|
152
|
+
if (targetType === 'user') {
|
|
153
|
+
const user = {} as Amity.User; // use getUser to get user by targetId
|
|
154
|
+
disposers.push(
|
|
155
|
+
subscribeTopic(getUserTopic(user, SubscriptionLevels.POST), () => {
|
|
156
|
+
// use callback to handle errors with event subscription
|
|
157
|
+
}),
|
|
158
|
+
);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (targetType === 'community') {
|
|
163
|
+
// use getCommunity to get community by targetId
|
|
164
|
+
const community = {} as Amity.Community;
|
|
165
|
+
disposers.push(
|
|
166
|
+
subscribeTopic(getCommunityTopic(community, SubscriptionLevels.POST), () => {
|
|
167
|
+
// use callback to handle errors with event subscription
|
|
168
|
+
}),
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Getting paginated collection without real-time updates
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
PostRepository,
|
|
178
|
+
subscribeTopic,
|
|
179
|
+
getUserTopic,
|
|
180
|
+
getCommunityTopic,
|
|
181
|
+
SubscriptionLevels,
|
|
182
|
+
} from '@amityco/ts-sdk';
|
|
183
|
+
|
|
184
|
+
const GetPosts: FC<{ targetId: string; targetType: string }> =
|
|
185
|
+
({ targetId, targetType }) => {
|
|
186
|
+
const [posts, setPosts] = useState<Amity.Post[]>();
|
|
187
|
+
|
|
188
|
+
useEffect(() => {
|
|
189
|
+
const unsubscribe = PostRepository.getPosts(
|
|
190
|
+
{ targetId, targetType },
|
|
191
|
+
({ data: posts, onNextPage, hasNextPage, loading, error }) => {
|
|
192
|
+
if (posts)
|
|
193
|
+
setPosts(posts);
|
|
194
|
+
|
|
195
|
+
// to get next page use onNextPage()
|
|
196
|
+
},
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
unsubscribe()
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
return null;
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
## Best Practices
|
|
206
|
+
|
|
207
|
+
**Always Clean Up**: Prevent memory leaks by properly disposing of subscriptions and unsubscribers.
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
// Use a disposer pattern
|
|
211
|
+
const disposers: Amity.Unsubscriber[] = [];
|
|
212
|
+
|
|
213
|
+
useEffect(() => {
|
|
214
|
+
// Add subscriptions
|
|
215
|
+
disposers.push(PostRepository.getPost(postId, callback));
|
|
216
|
+
disposers.push(subscribeTopic(getPostTopic(post)));
|
|
217
|
+
|
|
218
|
+
return () => {
|
|
219
|
+
// Clean up all subscriptions
|
|
220
|
+
disposers.forEach(dispose => dispose());
|
|
221
|
+
};
|
|
222
|
+
}, []);
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
**Subscribe Selectively**: Only subscribe to real-time events when you need live updates to optimize performance.
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
// For static content, unsubscribe immediately
|
|
229
|
+
const unsubscribe = PostRepository.getPost(postId, callback);
|
|
230
|
+
unsubscribe(); // No real-time updates needed
|
|
231
|
+
|
|
232
|
+
// For live content, keep subscription active
|
|
233
|
+
const unsubscribe = PostRepository.getPost(postId, callback);
|
|
234
|
+
disposers.push(unsubscribe); // Keep for real-time updates
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
**Handle Subscription Errors**: Always provide error callbacks for topic subscriptions.
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
disposers.push(
|
|
241
|
+
subscribeTopic(getPostTopic(post), (error) => {
|
|
242
|
+
if (error) {
|
|
243
|
+
console.error('Subscription failed:', error);
|
|
244
|
+
// Handle fallback or retry logic
|
|
245
|
+
}
|
|
246
|
+
})
|
|
247
|
+
);
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
**Debounce Updates**: For frequently updating collections, consider debouncing UI updates.
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
import { debounce } from 'lodash';
|
|
254
|
+
|
|
255
|
+
const debouncedSetPosts = debounce(setPosts, 300);
|
|
256
|
+
|
|
257
|
+
PostRepository.getPosts(query, ({ data: posts }) => {
|
|
258
|
+
if (posts) {
|
|
259
|
+
debouncedSetPosts(posts);
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
---
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# Device Registration & Management
|
|
2
|
+
|
|
3
|
+
> Complete guide to registering and managing push notification devices across iOS, Android, React Native, Flutter, and Web platforms
|
|
4
|
+
|
|
5
|
+
Manage push notification device registrations to ensure users receive timely updates across all their devices. Handle registration, unregistration, and device lifecycle management with proper error handling and state management.
|
|
6
|
+
|
|
7
|
+
Device registration requires an active AmityClient instance and a valid push notification token. The SDK uses a "last write wins" strategy for device management.
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
Device registration is essential for delivering push notifications to your users. The social.plus SDK provides comprehensive device management capabilities across all platforms, ensuring reliable notification delivery while maintaining security and user privacy.
|
|
12
|
+
|
|
13
|
+
### Key Concepts
|
|
14
|
+
|
|
15
|
+
- **Device Token**: Unique identifier for each app installation (FCM token for Android, APNs token for iOS)
|
|
16
|
+
- **User Association**: Each device can be associated with only one user at a time
|
|
17
|
+
- **Token Lifecycle**: Tokens can change and require re-registration
|
|
18
|
+
- **Platform Differences**: Each platform has unique token requirements and behaviors
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
**Platform Setup Required**: Complete the platform-specific push notification setup before implementing device registration:
|
|
22
|
+
|
|
23
|
+
- **iOS**: [iOS Setup Guide](./setup/ios-setup)
|
|
24
|
+
- **Android**: [Android Setup Guide](./setup/android-setup)
|
|
25
|
+
- **React Native**: [React Native Setup Guide](./setup/react-native-setup)
|
|
26
|
+
- **Flutter**: [Flutter Setup Guide](./setup/flutter-setup)
|
|
27
|
+
- **Web**: [Web Setup Guide](./setup/web-setup)
|
|
28
|
+
|
|
29
|
+
## Device Registration
|
|
30
|
+
|
|
31
|
+
### Prerequisites
|
|
32
|
+
|
|
33
|
+
Before registering a device, ensure you have:
|
|
34
|
+
|
|
35
|
+
AmityClient instance properly initialized and authenticated
|
|
36
|
+
Platform-specific push notification token obtained
|
|
37
|
+
Push notification permissions granted by user
|
|
38
|
+
Active internet connection for registration
|
|
39
|
+
|
|
40
|
+
### Platform-Specific Registration
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
```swift iOS
|
|
44
|
+
do {
|
|
45
|
+
let result = try await client.registerPushNotification(withDeviceToken: "<token>")
|
|
46
|
+
} catch {
|
|
47
|
+
// Handle error here
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
```kotlin Android
|
|
52
|
+
fun registerNotification(fcmToken: String) {
|
|
53
|
+
AmityCoreClient.registerPushNotification()
|
|
54
|
+
.doOnComplete {
|
|
55
|
+
// Void
|
|
56
|
+
}
|
|
57
|
+
.doOnError {
|
|
58
|
+
// Exception
|
|
59
|
+
}
|
|
60
|
+
.subscribe()
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
```dart Flutter
|
|
64
|
+
void registerNotification(String fcmToken) {
|
|
65
|
+
/*
|
|
66
|
+
************ IMPORTANT ************
|
|
67
|
+
Example of getting token from firebase.
|
|
68
|
+
Please check the platform before getting the token and send token as per platform.
|
|
69
|
+
FirebaseMessaging messaging = FirebaseMessaging.instance;
|
|
70
|
+
if (Platform.isIOS) {
|
|
71
|
+
final fcmToken = await messaging.getAPNSToken();
|
|
72
|
+
} else {
|
|
73
|
+
final fcmToken = await messaging.getToken();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
*/
|
|
77
|
+
AmityCoreClient.registerDeviceNotification(fcmToken)
|
|
78
|
+
.then((value) => {
|
|
79
|
+
//success
|
|
80
|
+
})
|
|
81
|
+
.onError((error, stackTrace) => {
|
|
82
|
+
//handle error
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
## Device Unregistration
|
|
89
|
+
|
|
90
|
+
### When to Unregister
|
|
91
|
+
|
|
92
|
+
Unregister devices in these scenarios:
|
|
93
|
+
|
|
94
|
+
When user logs out of the app
|
|
95
|
+
When user deletes their account
|
|
96
|
+
When user disables notifications
|
|
97
|
+
Before app uninstallation (if possible)
|
|
98
|
+
|
|
99
|
+
### Unregistration Implementation
|
|
100
|
+
|
|
101
|
+
Unlike the registration, unregistering for push does not require the AmityClient instance to be associated with any user, therefore you can unregister the device from receiving push notifications as soon as the AmityClient has been initialized with a valid API key.
|
|
102
|
+
|
|
103
|
+
- if a valid `userId` is passed, social.plus's backend will stop sending push notifications to this device only if the currently active push notification associated with this device is also associated with that user. No action is taken otherwise.
|
|
104
|
+
- if no `userId` is passed, social.plus's backend will stop sending push notifications to this device.
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
{/* doc-as-test: skip (truly-illustrative: contains '...' ellipsis placeholder — pseudocode scaffold, not compilable Swift) */}
|
|
108
|
+
```swift iOS
|
|
109
|
+
// unregister from receiving push notifications for the user with id `userId`
|
|
110
|
+
client.unregisterDeviceForPushNotification(forUserId: userId) { [weak self] _, success, error in
|
|
111
|
+
...
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// unregister from receiving push notifications for this device
|
|
115
|
+
client.unregisterDeviceForPushNotification(forUserId: nil) { [weak self] _, success, error in
|
|
116
|
+
...
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
```kotlin Android
|
|
121
|
+
fun unregisterPushNotification(userId: String) {
|
|
122
|
+
AmityCoreClient.unregisterPushNotification()
|
|
123
|
+
.doOnComplete {
|
|
124
|
+
// Void
|
|
125
|
+
}
|
|
126
|
+
.doOnError {
|
|
127
|
+
// Exception
|
|
128
|
+
}
|
|
129
|
+
.subscribe()
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
```dart Flutter
|
|
134
|
+
void unregisterNotification() {
|
|
135
|
+
AmityCoreClient.unregisterDeviceNotification()
|
|
136
|
+
.then((value) => {
|
|
137
|
+
//success
|
|
138
|
+
})
|
|
139
|
+
.onError((error, stackTrace) => {
|
|
140
|
+
//handle error
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
## Troubleshooting
|
|
147
|
+
|
|
148
|
+
**Common Registration Issues**:
|
|
149
|
+
|
|
150
|
+
1. **Invalid Token**: Ensure token is properly formatted and not expired
|
|
151
|
+
2. **Network Issues**: Implement retry logic with exponential backoff
|
|
152
|
+
3. **Authentication**: Verify AmityClient is properly authenticated
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
**Token-Related Problems**:
|
|
156
|
+
|
|
157
|
+
1. **Token Refresh**: Handle token changes properly
|
|
158
|
+
2. **Platform Differences**: iOS requires APNs token availability
|
|
159
|
+
3. **Timing Issues**: Ensure token is available before registration
|
|
160
|
+
4. **Storage Issues**: Verify token persistence works correctly
|
|
161
|
+
|
|
162
|
+
**iOS Specific**:
|
|
163
|
+
- Requires APNs token before FCM token
|
|
164
|
+
- Simulator doesn't support push notifications
|
|
165
|
+
- Debug builds may have limitations
|
|
166
|
+
|
|
167
|
+
**Android Specific**:
|
|
168
|
+
- FCM service account required
|
|
169
|
+
- Android 13+ runtime permissions
|
|
170
|
+
- Google Play Services dependency
|
|
171
|
+
|
|
172
|
+
**React Native**:
|
|
173
|
+
- Platform-specific token handling
|
|
174
|
+
- Background message handling
|
|
175
|
+
- Proper cleanup of listeners
|
|
176
|
+
|
|
177
|
+
**Flutter**:
|
|
178
|
+
- Platform channel communication
|
|
179
|
+
- Firebase plugin configuration
|
|
180
|
+
- State management across rebuilds
|
|
181
|
+
|
|
182
|
+
## Related Resources
|
|
183
|
+
|
|
184
|
+
Complete iOS APNs certificate setup and configuration
|
|
185
|
+
Android FCM configuration and implementation
|
|
186
|
+
Cross-platform React Native push notification setup
|
|
187
|
+
Flutter push notification implementation guide
|
|
188
|
+
|
|
189
|
+
**Important**: Always test device registration and token refresh scenarios thoroughly before production deployment. Each platform has unique requirements and edge cases.
|
|
190
|
+
|
|
191
|
+
---
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Push Notification Settings
|
|
2
|
+
|
|
3
|
+
> Configure user, channel, and community-level push notification preferences and controls.
|
|
4
|
+
|
|
5
|
+
Configure push notification preferences at three levels: user, channel, and community. Settings at each level control which events trigger notifications and can be overridden or restricted by higher-level policies.
|
|
6
|
+
|
|
7
|
+
## Available Settings
|
|
8
|
+
|
|
9
|
+
Personal notification preferences and user-level controls
|
|
10
|
+
|
|
11
|
+
Channel-specific notification rules and moderation settings
|
|
12
|
+
|
|
13
|
+
Community-wide notification policies and administrative controls
|
|
14
|
+
|
|
15
|
+
## Settings Hierarchy
|
|
16
|
+
|
|
17
|
+
Understanding the notification settings hierarchy is crucial for proper implementation:
|
|
18
|
+
|
|
19
|
+
1. **Community Level**: Global policies and restrictions
|
|
20
|
+
2. **Channel Level**: Channel-specific rules and preferences
|
|
21
|
+
3. **User Level**: Personal preferences and overrides
|
|
22
|
+
|
|
23
|
+
User settings typically have the highest priority, unless restricted by community or channel policies.
|
|
24
|
+
|
|
25
|
+
## Key Features
|
|
26
|
+
|
|
27
|
+
- **Granular Control**: Fine-grained notification preferences
|
|
28
|
+
- **Smart Defaults**: Intelligent default settings based on user behavior
|
|
29
|
+
- **Bulk Management**: Efficient settings management for administrators
|
|
30
|
+
- **Real-time Updates**: Instant application of setting changes
|
|
31
|
+
- **Compliance**: Privacy and regulation compliance features
|
|
32
|
+
|
|
33
|
+
## Best Practices
|
|
34
|
+
|
|
35
|
+
- Provide clear, user-friendly setting descriptions
|
|
36
|
+
- Implement smart defaults to reduce configuration burden
|
|
37
|
+
- Respect user privacy and consent preferences
|
|
38
|
+
- Test notification delivery across different settings combinations
|
|
39
|
+
- Monitor settings usage and optimize based on user behavior
|
|
40
|
+
|
|
41
|
+
Start with [User Settings](/social-plus-sdk/core-concepts/realtime-communication/push-notifications/settings/user-settings) to understand personal preferences, then explore channel and community-level controls.
|
|
42
|
+
|
|
43
|
+
---
|