Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Push Subscription/Permission Getters to Async #1649

Merged
merged 7 commits into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,9 +218,12 @@ The Push Subscription namespace is accessible via `OneSignal.User.pushSubscripti

| **React Native** | **Description** |
| --------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `OneSignal.User.pushSubscription.getPushSubscriptionId()` | _The readonly push subscription ID._ |
| `OneSignal.User.pushSubscription.getPushSubscriptionToken()` | _The readonly push token._ |
| `OneSignal.User.pushSubscription.getOptedIn()` | _Gets a boolean value indicating whether the current user is opted in to push notifications. This returns `true` when the app has notifications permission and `optedOut` is called. **_Note:_** Does not take into account the existence of the subscription ID and push token. This boolean may return `true` but push notifications may still not be received by the user._ |
| `OneSignal.User.pushSubscription.getPushSubscriptionId()` | _**DEPRECATED**<br>use `getIdAsync`._ |
| `OneSignal.User.pushSubscription.getPushSubscriptionToken()` | _**DEPRECATED**<br>use `getTokenAsync`_ |
| `OneSignal.User.pushSubscription.getOptedIn()` | _**DEPRECATED**<br>use `getOptedInAsync`_ |
| `await OneSignal.User.pushSubscription.getIdAsync()` | _The readonly push subscription ID._ |
| `await OneSignal.User.pushSubscription.getTokenAsync()` | _The readonly push token._ |
| `await OneSignal.User.pushSubscription.getOptedInAsync()` | _Gets a boolean value indicating whether the current user is opted in to push notifications. This returns `true` when the app has notifications permission and `optedOut` is called. **_Note:_** Does not take into account the existence of the subscription ID and push token. This boolean may return `true` but push notifications may still not be received by the user._ |
| `OneSignal.User.pushSubscription.optIn()` | _Call this method to receive push notifications on the device or to resume receiving of push notifications after calling `optOut`. If needed, this method will prompt the user for push notifications permission._ |
| `OneSignal.User.pushSubscription.optOut()` | _If at any point you want the user to stop receiving push notifications on the current device (regardless of system-level permission status), you can call this method to opt out._ |
| `OneSignal.User.pushSubscription.addEventListener('change', listener: (event) => void)`<br><br>**_See below for usage_** | _Adds the listener to run when the push subscription changes._ |
Expand Down Expand Up @@ -254,7 +257,8 @@ The Notifications namespace is accessible via `OneSignal.Notifications` and prov

| **React Native** | **Description** |
|--------------------------------------- | --------------- |
| `OneSignal.Notifications.hasPermission()` | _Whether this app has push notification permission._ |
| `OneSignal.Notifications.hasPermission()` | _**DEPRECATED**<br>use `getPermissionAsync()`_ |
| `OneSignal.Notifications.getPermissionAsync()` | _Whether this app has push notification permission._ |
| `await OneSignal.Notifications.canRequestPermission()` | _Whether attempting to request notification permission will show a prompt. Returns `true` if the device has not been prompted for push notification permission already._ |
| `await OneSignal.Notifications.permissionNative()` | _(ios only) Returns the enum for the native permission of the device. It will be one of: NotDetermined, Denied, Authorized, Provisional (only available in iOS 12), Ephemeral (only available in iOS 14)_ |
| `OneSignal.Notifications.clearAll();` | _Removes all OneSignal notifications._ |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,12 @@ public void onNotificationPermissionChange(boolean permission) {

@ReactMethod
public void requestNotificationPermission(final boolean fallbackToSettings, Promise promise) {
// if permission already exists, return early as the method call will not resolve
if (OneSignal.getNotifications().getPermission()) {
promise.resolve(true);
return;
}

OneSignal.getNotifications().requestPermission(fallbackToSettings, Continue.with(result -> {
if (result.isSuccess()) {
promise.resolve(result.getData());
Expand All @@ -443,6 +449,16 @@ public void hasNotificationPermission(Promise promise) {
promise.resolve(OneSignal.getNotifications().getPermission());
}

@ReactMethod
public void permissionNative(Promise promise) {
if (OneSignal.getNotifications().getPermission()) {
promise.resolve(2);
}
else {
promise.resolve(1);
}
}

@ReactMethod
public void canRequestNotificationPermission(Promise promise) {
promise.resolve(OneSignal.getNotifications().getCanRequestPermission());
Expand All @@ -468,13 +484,23 @@ public void removeGroupedNotifications(String id) {
@ReactMethod
public void getPushSubscriptionId(Promise promise) {
IPushSubscription pushSubscription = OneSignal.getUser().getPushSubscription();
promise.resolve(pushSubscription.getId());
String pushId = pushSubscription.getId();
if (pushId != null && !pushId.isEmpty()){
promise.resolve(pushId);
} else {
promise.resolve(null);
}
}

@ReactMethod
public void getPushSubscriptionToken(Promise promise) {
IPushSubscription pushSubscription = OneSignal.getUser().getPushSubscription();
promise.resolve(pushSubscription.getToken());
String pushToken = pushSubscription.getToken();
if (pushToken != null && !pushToken.isEmpty()) {
promise.resolve(pushToken);
} else {
promise.resolve(null);
}
}

@ReactMethod
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,16 @@ public static HashMap<String, Object> convertInAppMessageClickEventToMap(IInAppM

public static HashMap<String, Object> convertPushSubscriptionStateToMap(PushSubscriptionState state) {
HashMap<String, Object> hash = new HashMap<>();

hash.put("token", state.getToken());
hash.put("id", state.getId());
if (state.getToken() != null && !state.getToken().isEmpty()) {
hash.put("token", state.getToken());
} else {
hash.put("token", JSONObject.NULL);
}
if (state.getId() != null && !state.getId().isEmpty()) {
hash.put("id", state.getId());
} else {
hash.put("id", JSONObject.NULL);
}
hash.put("optedIn", state.getOptedIn());

return hash;
Expand Down
12 changes: 5 additions & 7 deletions examples/RNOneSignalTS/src/OSButtons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ class OSButtons extends React.Component<Props> {

const hasPermissionButton = renderButtonView(
'Has Notification Permission',
() => {
const granted = OneSignal.Notifications.hasPermission();
async () => {
const granted = await OneSignal.Notifications.getPermissionAsync();
loggingFunction(`Has Notification Permission: ${granted}`);
},
);
Expand Down Expand Up @@ -368,23 +368,21 @@ class OSButtons extends React.Component<Props> {
const getPushSubscriptionIdButton = renderButtonView(
'Get Push Subscription Id',
async () => {
const id =
await OneSignal.User.pushSubscription.getPushSubscriptionId();
const id = await OneSignal.User.pushSubscription.getIdAsync();
loggingFunction('Push Subscription Id: ', id);
},
);

const getPushSubscriptionTokenButton = renderButtonView(
'Get Push Subscription Token',
async () => {
const token =
await OneSignal.User.pushSubscription.getPushSubscriptionToken();
const token = await OneSignal.User.pushSubscription.getTokenAsync();
loggingFunction('Push Subscription Token: ', token);
},
);

const getOptedInButton = renderButtonView('Is Opted In', async () => {
const optedIn = await OneSignal.User.pushSubscription.getOptedIn();
const optedIn = await OneSignal.User.pushSubscription.getOptedInAsync();
loggingFunction('Subscribed for the push notifications: ', optedIn);
});

Expand Down
18 changes: 17 additions & 1 deletion ios/RCTOneSignal/RCTOneSignal.m
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,23 @@ - (void)sendEvent:(NSString *)eventName withBody:(NSDictionary *)body {
}

- (void)onPushSubscriptionDidChangeWithState:(OSPushSubscriptionChangedState * _Nonnull)state {
[self sendEvent:OSEventString(SubscriptionChanged) withBody:[state jsonRepresentation]];
NSMutableDictionary *result = [NSMutableDictionary new];

//Previous state
NSMutableDictionary *previousObject = [NSMutableDictionary new];
previousObject[@"token"] = (state.previous.token && ![state.previous.token isEqualToString:@""]) ? state.previous.token : [NSNull null];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These lines get pretty complex, we can consider refactoring these into getter helpers, that can also be used for the User State observer., once this PR and that one are combined / merged.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also update the PR description to callout the API "breaking-sorta" change that the push subscription observer will be passed nullable properties now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for flagging these! I've edited the PR description with the minor breaking change and will be sure to include it in release notes. Refactoring mentioned above will happen in a future PR.

previousObject[@"id"] = (state.previous.id && ![state.previous.id isEqualToString:@""]) ? state.previous.id : [NSNull null];
previousObject[@"optedIn"] = @(state.previous.optedIn);
result[@"previous"] = previousObject;

//Current state
NSMutableDictionary *currentObject = [NSMutableDictionary new];
currentObject[@"token"] = (state.current.token && ![state.current.token isEqualToString:@""]) ? state.current.token : [NSNull null];
currentObject[@"id"] = (state.current.id && ![state.current.id isEqualToString:@""]) ? state.current.id : [NSNull null];
currentObject[@"optedIn"] = @(state.current.optedIn);
result[@"current"] = currentObject;

[self sendEvent:OSEventString(SubscriptionChanged) withBody:result];
}

- (void)onNotificationPermissionDidChange:(BOOL)permission {
Expand Down
14 changes: 12 additions & 2 deletions ios/RCTOneSignal/RCTOneSignalEventEmitter.m
Original file line number Diff line number Diff line change
Expand Up @@ -392,13 +392,23 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body {
RCT_REMAP_METHOD(getPushSubscriptionId,
getPushSubscriptionIdResolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
resolve(OneSignal.User.pushSubscription.id);
NSString *pushId = OneSignal.User.pushSubscription.id;
if (pushId && ![pushId isEqualToString:@""]) {
resolve(pushId);
} else {
resolve([NSNull null]);
}
}

RCT_REMAP_METHOD(getPushSubscriptionToken,
getPushSubscriptionTokenResolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
resolve(OneSignal.User.pushSubscription.token);
NSString *token = OneSignal.User.pushSubscription.token;
if (token && ![token isEqualToString:@""]) {
resolve(token);
} else {
resolve([NSNull null]);
}
}

RCT_EXPORT_METHOD(optIn) {
Expand Down
Loading
Loading