Skip to content

Commit

Permalink
Merge pull request #1627 from OneSignal/feat/add_get_ids
Browse files Browse the repository at this point in the history
Add getters and observer for onesignal ID and external ID
  • Loading branch information
jennantilla committed Mar 12, 2024
2 parents d789599 + d9cca19 commit 0b9fd76
Show file tree
Hide file tree
Showing 13 changed files with 241 additions and 5 deletions.
16 changes: 16 additions & 0 deletions MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,22 @@ The User namespace is accessible via `OneSignal.User` and provides access to use
| `OneSignal.User.removeTag("KEY")` | _Remove the data tag with the provided key from the current user._ |
| `OneSignal.User.removeTags(["KEY_01", "KEY_02"])` | _Remove multiple tags with the provided keys from the current user._ |
| `OneSignal.User.getTags()` | _Returns the local tags for the current user._|
| `OneSignal.User.addEventListener("change", (event: UserChangedState) => void)`<br><br>**_See below for usage_** | _Add a User State callback which contains the nullable onesignalId and externalId. The listener will be fired when these values change._|
| `await OneSignal.User.getOnesignalId()` | _Returns the OneSignal ID for the current user, which can be null if it is not yet available._|
| `await OneSignal.User.getExternalId()` | _Returns the External ID for the current user, which can be null if not set._|

### User State Listener

```typescript
const listener = (event: UserChangedState) => {
console.log("User changed: " + (event));
};

OneSignal.User.addEventListener("change", listener);
// Remove the listener
OneSignal.User.removeEventListener("change", listener);
```

## Push Subscription Namespace

The Push Subscription namespace is accessible via `OneSignal.User.pushSubscription` and provides access to push subscription-scoped functionality.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ of this software and associated documentation files (the "Software"), to deal
import com.onesignal.user.subscriptions.IPushSubscriptionObserver;
import com.onesignal.user.subscriptions.PushSubscriptionState;
import com.onesignal.user.subscriptions.PushSubscriptionChangedState;
import com.onesignal.user.state.UserState;
import com.onesignal.user.state.UserChangedState;
import com.onesignal.user.state.IUserStateObserver;
import org.json.JSONException;

import java.util.HashMap;
Expand All @@ -82,6 +85,7 @@ of this software and associated documentation files (the "Software"), to deal
public class RNOneSignal extends ReactContextBaseJavaModule implements
IPushSubscriptionObserver,
IPermissionObserver,
IUserStateObserver,
LifecycleEventListener,
INotificationLifecycleListener{
private ReactApplicationContext mReactApplicationContext;
Expand All @@ -90,6 +94,7 @@ public class RNOneSignal extends ReactContextBaseJavaModule implements
private boolean oneSignalInitDone;
private boolean hasSetPermissionObserver = false;
private boolean hasSetPushSubscriptionObserver = false;
private boolean hasSetUserStateObserver = false;

private HashMap<String, INotificationWillDisplayEvent> notificationWillDisplayCache;
private HashMap<String, INotificationWillDisplayEvent> preventDefaultCache;
Expand Down Expand Up @@ -162,6 +167,7 @@ public void onClick(INotificationClickEvent event) {
private void removeObservers() {
this.removePermissionObserver();
this.removePushSubscriptionObserver();
this.removeUserStateObserver();
}

private void removeHandlers() {
Expand Down Expand Up @@ -676,6 +682,53 @@ public void removeAliases(ReadableArray aliasLabels) {
OneSignal.getUser().removeAliases(RNUtils.convertReadableArrayIntoStringCollection(aliasLabels));
}

@ReactMethod
public void getOnesignalId(Promise promise) {
String onesignalId = OneSignal.getUser().getOnesignalId();
if (onesignalId.isEmpty()) {
onesignalId = null;
}
promise.resolve(onesignalId);

}

@ReactMethod
public void getExternalId(Promise promise) {
String externalId = OneSignal.getUser().getExternalId();
if (externalId.isEmpty()) {
externalId = null;
}
promise.resolve(externalId);
}

@ReactMethod
public void addUserStateObserver() {
if (!hasSetUserStateObserver) {
OneSignal.getUser().addObserver(this);
hasSetUserStateObserver = true;
}
}

@Override
public void onUserStateChange(UserChangedState state) {
try {
sendEvent("OneSignal-userStateChanged",
RNUtils.convertHashMapToWritableMap(
RNUtils.convertUserChangedStateToMap(state)));
Log.i("OneSignal", "sending user state change event");
} catch (JSONException e) {
e.printStackTrace();
}
}

@ReactMethod
public void removeUserStateObserver() {
if (hasSetUserStateObserver) {
OneSignal.getUser().removeObserver(this);
hasSetUserStateObserver = false;
}
}

/** Added for NativeEventEmitter */
@ReactMethod
public void addListener(String eventName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import com.onesignal.user.subscriptions.IPushSubscription;
import com.onesignal.user.subscriptions.PushSubscriptionState;
import com.onesignal.user.subscriptions.PushSubscriptionChangedState;
import com.onesignal.user.state.UserState;
import com.onesignal.user.state.UserChangedState;

import org.json.JSONArray;
import org.json.JSONException;
Expand Down Expand Up @@ -197,6 +199,25 @@ public static HashMap<String, Object> convertPushSubscriptionStateToMap(PushSubs
return hash;
}

public static HashMap<String, Object> convertUserStateToMap(UserState user) {
HashMap<String, Object> hash = new HashMap<>();

if (user.getExternalId() != null && !user.getExternalId().isEmpty()) {
hash.put("externalId", user.getExternalId());
}
else {
hash.put("externalId", JSONObject.NULL);
}
if (user.getOnesignalId() != null && !user.getOnesignalId().isEmpty()) {
hash.put("onesignalId", user.getOnesignalId());
}
else {
hash.put("onesignalId", JSONObject.NULL);
}

return hash;
}

public static HashMap<String, Object> convertPushSubscriptionChangedStateToMap(PushSubscriptionChangedState state) {
HashMap<String, Object> hash = new HashMap<>();
hash.put("current", convertPushSubscriptionStateToMap(state.getCurrent()));
Expand All @@ -205,6 +226,13 @@ public static HashMap<String, Object> convertPushSubscriptionChangedStateToMap(P
return hash;
}

public static HashMap<String, Object> convertUserChangedStateToMap(UserChangedState state) {
HashMap<String, Object> hash = new HashMap<>();
hash.put("current", convertUserStateToMap(state.getCurrent()));

return hash;
}

public static HashMap<String, Object> convertJSONObjectToHashMap(JSONObject object) throws JSONException {
HashMap<String, Object> hash = new HashMap<>();

Expand Down
22 changes: 20 additions & 2 deletions examples/RNOneSignalTS/src/OSButtons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -277,8 +277,8 @@ class OSButtons extends React.Component<Props> {
});

const getTagsButton = renderButtonView('Get tags', async () => {
const tags = await OneSignal.User.getTags();
loggingFunction('Tags:', tags);
const tags = await OneSignal.User.getTags();
loggingFunction('Tags:', tags);
});

const setLanguageButton = renderButtonView('Set Language', () => {
Expand Down Expand Up @@ -342,6 +342,22 @@ class OSButtons extends React.Component<Props> {
},
);

const getOnesignalIdButton = renderButtonView(
'Get OneSignal Id',
async () => {
const onesignalId = await OneSignal.User.getOnesignalId();
loggingFunction('OneSignal Id: ', onesignalId);
},
);

const getExternalIdButton = renderButtonView(
'Get External Id',
async () => {
const externalId = await OneSignal.User.getExternalId();
loggingFunction('External Id:', externalId);
},
);

return [
loginButton,
logoutButton,
Expand All @@ -359,6 +375,8 @@ class OSButtons extends React.Component<Props> {
removeAliasButton,
addAliasesButton,
removeAliasesButton,
getOnesignalIdButton,
getExternalIdButton,
];
}

Expand Down
4 changes: 4 additions & 0 deletions examples/RNOneSignalTS/src/OSDemo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ class OSDemo extends React.Component<Props, State> {
OneSignal.Notifications.addEventListener('permissionChange', (granted) => {
this.OSLog('OneSignal: permission changed:', granted);
});

OneSignal.User.addEventListener('change', (event) => {
this.OSLog('OneSignal: user changed: ', event);
});
}

OSLog = (message: string, optionalArg: any = null) => {
Expand Down
3 changes: 1 addition & 2 deletions ios/RCTOneSignal/RCTOneSignal.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
#import "../OneSignalFramework.h"
#endif

@interface RCTOneSignal : NSObject <OSPushSubscriptionObserver, OSNotificationPermissionObserver, OSInAppMessageLifecycleListener, OSInAppMessageClickListener, OSNotificationClickListener>

@interface RCTOneSignal : NSObject <OSPushSubscriptionObserver, OSNotificationPermissionObserver, OSInAppMessageLifecycleListener, OSInAppMessageClickListener, OSNotificationClickListener, OSUserStateObserver>
+ (RCTOneSignal *) sharedInstance;

@end
25 changes: 25 additions & 0 deletions ios/RCTOneSignal/RCTOneSignal.m
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,31 @@ - (void)sendEvent:(NSString *)eventName withBody:(NSDictionary *)body {
[RCTOneSignalEventEmitter sendEventWithName:eventName withBody:body];
}

- (void)onUserStateDidChangeWithState:(OSUserChangedState * _Nonnull)state {
NSString *onesignalId = state.current.onesignalId;
NSString *externalId = state.current.externalId;

NSMutableDictionary *currentDictionary = [NSMutableDictionary dictionary];

if (onesignalId.length > 0) {
[currentDictionary setObject:onesignalId forKey:@"onesignalId"];
}
else {
[currentDictionary setObject:[NSNull null] forKey:@"onesignalId"];
}

if (externalId.length > 0) {
[currentDictionary setObject:externalId forKey:@"externalId"];
}
else {
[currentDictionary setObject:[NSNull null] forKey:@"externalId"];
}

NSDictionary *result = @{@"current": currentDictionary};

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

- (void)onPushSubscriptionDidChangeWithState:(OSPushSubscriptionChangedState * _Nonnull)state {
NSMutableDictionary *result = [NSMutableDictionary new];

Expand Down
3 changes: 2 additions & 1 deletion ios/RCTOneSignal/RCTOneSignalEventEmitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
typedef NS_ENUM(NSInteger, OSNotificationEventTypes) {
PermissionChanged,
SubscriptionChanged,
UserStateChanged,
NotificationWillDisplayInForeground,
NotificationClicked,
InAppMessageClicked,
Expand All @@ -24,7 +25,7 @@ typedef NS_ENUM(NSInteger, OSNotificationEventTypes) {
InAppMessageDidDismiss,
};

#define OSNotificationEventTypesArray @[@"OneSignal-permissionChanged",@"OneSignal-subscriptionChanged",@"OneSignal-notificationWillDisplayInForeground",@"OneSignal-notificationClicked",@"OneSignal-inAppMessageClicked", @"OneSignal-inAppMessageWillDisplay", @"OneSignal-inAppMessageDidDisplay", @"OneSignal-inAppMessageWillDismiss", @"OneSignal-inAppMessageDidDismiss"]
#define OSNotificationEventTypesArray @[@"OneSignal-permissionChanged",@"OneSignal-subscriptionChanged",@"OneSignal-userStateChanged",@"OneSignal-notificationWillDisplayInForeground",@"OneSignal-notificationClicked",@"OneSignal-inAppMessageClicked", @"OneSignal-inAppMessageWillDisplay", @"OneSignal-inAppMessageDidDisplay", @"OneSignal-inAppMessageWillDismiss", @"OneSignal-inAppMessageDidDismiss"]

#define OSEventString(enum) [OSNotificationEventTypesArray objectAtIndex:enum]

Expand Down
32 changes: 32 additions & 0 deletions ios/RCTOneSignal/RCTOneSignalEventEmitter.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ @implementation RCTOneSignalEventEmitter {
BOOL _hasListeners;
BOOL _hasSetSubscriptionObserver;
BOOL _hasSetPermissionObserver;
BOOL _hasSetUserStateObserver;
BOOL _hasAddedNotificationClickListener;
BOOL _hasAddedNotificationForegroundLifecycleListener;
BOOL _hasAddedInAppMessageClickListener;
Expand Down Expand Up @@ -310,6 +311,13 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body {
}

// OneSignal.User namespace methods
RCT_EXPORT_METHOD(addUserStateObserver) {
if (!_hasSetUserStateObserver) {
[OneSignal.User addObserver:[RCTOneSignal sharedInstance]];
_hasSetUserStateObserver = true;
}
}

RCT_EXPORT_METHOD(addPushSubscriptionObserver) {
if (!_hasSetSubscriptionObserver) {
[OneSignal.User.pushSubscription addObserver:[RCTOneSignal sharedInstance]];
Expand Down Expand Up @@ -365,6 +373,30 @@ + (void)sendEventWithName:(NSString *)name withBody:(NSDictionary *)body {
resolve(tags);
}

RCT_REMAP_METHOD(getOnesignalId,
getOnesignalIdResolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
NSString *onesignalId = OneSignal.User.onesignalId;

if (onesignalId == nil || [onesignalId length] == 0) {
resolve([NSNull null]); // Resolve with null if nil or empty
} else {
resolve(onesignalId);
}
}

RCT_REMAP_METHOD(getExternalId,
getExternalIdResolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
NSString *externalId = OneSignal.User.externalId;

if (externalId == nil || [externalId length] == 0) {
resolve([NSNull null]); // Resolve with null if nil or empty
} else {
resolve(externalId);
}
}

RCT_EXPORT_METHOD(addAlias:(NSString *)label :(NSString *)id) {
[OneSignal.User addAliasWithLabel:label id:id];
}
Expand Down
2 changes: 2 additions & 0 deletions src/events/EventManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import NotificationWillDisplayEvent from './NotificationWillDisplayEvent';
import {
PERMISSION_CHANGED,
SUBSCRIPTION_CHANGED,
USER_STATE_CHANGED,
NOTIFICATION_WILL_DISPLAY,
NOTIFICATION_CLICKED,
IN_APP_MESSAGE_CLICKED,
Expand All @@ -20,6 +21,7 @@ import OSNotification from '../OSNotification';
const eventList = [
PERMISSION_CHANGED,
SUBSCRIPTION_CHANGED,
USER_STATE_CHANGED,
NOTIFICATION_WILL_DISPLAY,
NOTIFICATION_CLICKED,
IN_APP_MESSAGE_CLICKED,
Expand Down
1 change: 1 addition & 0 deletions src/events/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ export const IN_APP_MESSAGE_WILL_DISMISS = 'OneSignal-inAppMessageWillDismiss';
export const IN_APP_MESSAGE_DID_DISMISS = 'OneSignal-inAppMessageDidDismiss';
export const PERMISSION_CHANGED = 'OneSignal-permissionChanged';
export const SUBSCRIPTION_CHANGED = 'OneSignal-subscriptionChanged';
export const USER_STATE_CHANGED = 'OneSignal-userStateChanged';
Loading

0 comments on commit 0b9fd76

Please sign in to comment.