Skip to content

Commit

Permalink
Merge pull request #959 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 authored Mar 4, 2024
2 parents 1f770f5 + 2eed867 commit 3124470
Show file tree
Hide file tree
Showing 8 changed files with 248 additions and 1 deletion.
13 changes: 13 additions & 0 deletions MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,21 @@ The User name space is accessible via `OneSignal.User` and provides access to us
| `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

**Cordova/Ionic**
```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

Expand Down
28 changes: 28 additions & 0 deletions src/android/com/onesignal/cordova/OneSignalController.java
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,34 @@ public static boolean getTags(CallbackContext callbackContext) {
return true;
}

public static boolean getOnesignalId(CallbackContext callbackContext) {
String onesignalId = OneSignal.getUser().getOnesignalId();
try {
JSONObject onesignalIdObject = new JSONObject ();
if (!onesignalId.isEmpty()) {
onesignalIdObject.put("value", onesignalId);
}
CallbackHelper.callbackSuccess(callbackContext, onesignalIdObject);
} catch (JSONException e){
e.printStackTrace();
}
return true;
}

public static boolean getExternalId(CallbackContext callbackContext) {
String externalId = OneSignal.getUser().getExternalId();
try {
JSONObject externalIdObject = new JSONObject ();
if (!externalId.isEmpty()) {
externalIdObject.put("value", externalId);
}
CallbackHelper.callbackSuccess(callbackContext, externalIdObject);
} catch (JSONException e){
e.printStackTrace();
}
return true;
}

/**
* Notifications
*/
Expand Down
56 changes: 56 additions & 0 deletions src/android/com/onesignal/cordova/OneSignalObserverController.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,18 @@
import com.onesignal.user.subscriptions.PushSubscriptionChangedState;
import com.onesignal.user.subscriptions.PushSubscriptionState;
import com.onesignal.notifications.IPermissionObserver;
import com.onesignal.user.state.UserState;
import com.onesignal.user.state.UserChangedState;
import com.onesignal.user.state.IUserStateObserver;

public class OneSignalObserverController {
private static CallbackContext jsPermissionObserverCallBack;
private static CallbackContext jsSubscriptionObserverCallBack;
private static CallbackContext jsUserObserverCallBack;

private static IPermissionObserver permissionObserver;
private static IPushSubscriptionObserver pushSubscriptionObserver;
private static IUserStateObserver userStateObserver;

public static boolean addPermissionObserver(CallbackContext callbackContext) {
jsPermissionObserverCallBack = callbackContext;
Expand Down Expand Up @@ -65,6 +70,57 @@ public void onPushSubscriptionChange(PushSubscriptionChangedState state) {
return true;
}

public static boolean addUserStateObserver(CallbackContext callbackContext) {
jsUserObserverCallBack = callbackContext;
if (userStateObserver == null) {
userStateObserver = new IUserStateObserver() {
@Override
public void onUserStateChange(UserChangedState state) {
UserState current = state.getCurrent();

if (!(current instanceof UserState)) {
return;
}

try {
JSONObject hash = new JSONObject();
hash.put("current", createUserIds(current));

CallbackHelper.callbackSuccess(jsUserObserverCallBack, hash);

} catch (Exception e) {
e.printStackTrace();
}
}
};
OneSignal.getUser().addObserver(userStateObserver);
}
return true;
}

/** Helper method to return JSONObject.NULL if string is empty or nil **/
private static Object getStringOrJSONObjectNull(String str) {
if (str != null && !str.isEmpty()) {
return str;
} else {
return JSONObject.NULL;
}
}

private static JSONObject createUserIds(UserState user) {
JSONObject userIds = new JSONObject();
try {
String externalId = user.getExternalId();
String onesignalId = user.getOnesignalId();

userIds.put("externalId", getStringOrJSONObjectNull(externalId));
userIds.put("onesignalId", getStringOrJSONObjectNull(onesignalId));
} catch (JSONException e) {
e.printStackTrace();
}
return userIds;
}

private static JSONObject createPushSubscriptionProperties(PushSubscriptionState pushSubscription) {
JSONObject pushSubscriptionProperties = new JSONObject();
try {
Expand Down
16 changes: 16 additions & 0 deletions src/android/com/onesignal/cordova/OneSignalPush.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ public class OneSignalPush extends CordovaPlugin implements INotificationLifecyc

private static final String ADD_PERMISSION_OBSERVER = "addPermissionObserver";
private static final String ADD_PUSH_SUBSCRIPTION_OBSERVER = "addPushSubscriptionObserver";
private static final String ADD_USER_STATE_OBSERVER = "addUserStateObserver";

private static final String GET_ONESIGNAL_ID = "getOnesignalId";
private static final String GET_EXTERNAL_ID = "getExternalId";

private static final String OPT_IN = "optInPushSubscription";
private static final String OPT_OUT = "optOutPushSubscription";
Expand Down Expand Up @@ -432,6 +436,18 @@ public boolean execute(String action, JSONArray data, CallbackContext callbackCo
result = OneSignalObserverController.addPushSubscriptionObserver(callbackContext);
break;

case ADD_USER_STATE_OBSERVER:
result = OneSignalObserverController.addUserStateObserver(callbackContext);
break;

case GET_ONESIGNAL_ID:
result = OneSignalController.getOnesignalId(callbackContext);
break;

case GET_EXTERNAL_ID:
result = OneSignalController.getExternalId(callbackContext);
break;

case OPT_IN:
result = OneSignalController.optInPushSubscription();
break;
Expand Down
7 changes: 6 additions & 1 deletion src/ios/OneSignalPush.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

#import <OneSignalFramework/OneSignalFramework.h>

@interface OneSignalPush : CDVPlugin <OSNotificationPermissionObserver, OSNotificationLifecycleListener, OSNotificationClickListener, OSPushSubscriptionObserver, OSInAppMessageLifecycleListener, OSInAppMessageClickListener>
@interface OneSignalPush : CDVPlugin <OSNotificationPermissionObserver, OSNotificationLifecycleListener, OSNotificationClickListener, OSPushSubscriptionObserver, OSInAppMessageLifecycleListener, OSInAppMessageClickListener, OSUserStateObserver>

- (void)setProvidesNotificationSettingsView:(CDVInvokedUrlCommand* _Nonnull)command;
- (void)addForegroundLifecycleListener:(CDVInvokedUrlCommand* _Nonnull)command;
Expand All @@ -53,6 +53,10 @@
- (void)removeTags:(CDVInvokedUrlCommand* _Nonnull)command;
- (void)getTags:(CDVInvokedUrlCommand* _Nonnull)command;

- (void)addUserStateObserver:(CDVInvokedUrlCommand* _Nonnull)command;
- (void)getOnesignalId:(CDVInvokedUrlCommand* _Nonnull)command;
- (void)getExternalId:(CDVInvokedUrlCommand* _Nonnull)command;

// Push Subscription
- (void)addPushSubscriptionObserver:(CDVInvokedUrlCommand* _Nonnull)command;
- (void)getPushSubscriptionId:(CDVInvokedUrlCommand* _Nonnull)command;
Expand All @@ -69,6 +73,7 @@
- (void)canRequestPermission:(CDVInvokedUrlCommand* _Nonnull)command;
- (void)registerForProvisionalAuthorization:(CDVInvokedUrlCommand* _Nonnull)command;
- (void)clearAllNotifications:(CDVInvokedUrlCommand* _Nonnull)command;

// Android Only - Notifications
- (void)removeNotification:(CDVInvokedUrlCommand* _Nonnull)command;
- (void)removeGroupedNotifications:(CDVInvokedUrlCommand* _Nonnull)command;
Expand Down
54 changes: 54 additions & 0 deletions src/ios/OneSignalPush.m
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
NSString* inAppMessageWillDismissCallbackId;
NSString* inAppMessageDidDismissCallbackId;
NSString* inAppMessageClickedCallbackId;
NSString* userObserverCallbackId;

OSNotificationClickEvent *actionNotification;
OSNotification *notification;
Expand Down Expand Up @@ -104,6 +105,16 @@ void initOneSignalObject(NSDictionary* launchOptions) {
initialLaunchFired = true;
}

/** Helper method to return NSNull if string is empty or nil **/
NSString* getStringOrNSNull(NSString* string) {
// length method can be used on nil and strings
if (string.length > 0) {
return string;
} else {
return [NSNull null];
}
}

@implementation UIApplication(OneSignalCordovaPush)

static void injectSelectorCordova(Class newClass, SEL newSel, Class addToClass, SEL makeLikeSel) {
Expand Down Expand Up @@ -165,6 +176,41 @@ - (void)onPushSubscriptionDidChangeWithState:(OSPushSubscriptionChangedState *)s
successCallback(subscriptionObserverCallbackId, [state jsonRepresentation]);
}

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

NSMutableDictionary *result = [NSMutableDictionary new];

NSMutableDictionary *currentObject = [NSMutableDictionary new];

currentObject[@"onesignalId"] = getStringOrNSNull(onesignalId);
currentObject[@"externalId"] = getStringOrNSNull(externalId);
result[@"current"] = currentObject;

successCallback(userObserverCallbackId, result);
}

- (void)getOnesignalId:(CDVInvokedUrlCommand *)command {
NSString *onesignalId = OneSignal.User.onesignalId;

NSDictionary *result = @{
@"value" : (onesignalId ? onesignalId : [NSNull null])
};

successCallback(command.callbackId, result);
}

- (void)getExternalId:(CDVInvokedUrlCommand *)command {
NSString *externalId = OneSignal.User.externalId;

NSDictionary *result = @{
@"value" : (externalId ? externalId : [NSNull null])
};

successCallback(command.callbackId, result);
}

- (void)setProvidesNotificationSettingsView:(CDVInvokedUrlCommand *)command {
BOOL providesView = command.arguments[0];
[OneSignal setProvidesNotificationSettingsView:providesView];
Expand Down Expand Up @@ -272,6 +318,14 @@ - (void)addPushSubscriptionObserver:(CDVInvokedUrlCommand*)command {
[OneSignal.User.pushSubscription addObserver:self];
}

- (void)addUserStateObserver:(CDVInvokedUrlCommand*)command {
bool first = userObserverCallbackId == nil;
userObserverCallbackId = command.callbackId;
if (first) {
[OneSignal.User addObserver:self];
}
}

- (void)getPushSubscriptionId:(CDVInvokedUrlCommand*)command {
NSString *pushId = OneSignal.User.pushSubscription.id;
if (pushId) {
Expand Down
70 changes: 70 additions & 0 deletions www/UserNamespace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,28 @@ import PushSubscription from "./PushSubscriptionNamespace";
// Suppress TS warnings about window.cordova
declare let window: any; // turn off type checking

// Represents the current user state
export interface UserState {
onesignalId ?: string;
externalId ?: string;
}

export interface UserChangedState {
current: UserState;
}

export default class User {
// The push subscription associated to the current user.
pushSubscription: PushSubscription = new PushSubscription();

private _userStateObserverList: ((event:UserChangedState)=>void)[] = [];

private _processFunctionList(array: ((event:UserChangedState)=>void)[], param: UserChangedState): void {
for (let i = 0; i < array.length; i++) {
array[i](param);
}
}

/**
* Explicitly set a 2-character language code for the user.
* @param {string} language
Expand Down Expand Up @@ -159,4 +177,56 @@ export default class User {
window.cordova.exec(resolve, reject, "OneSignalPush", "getTags", []);
});
};

/**
* Add a callback that fires when the OneSignal User state changes.
* Important: When using the observer to retrieve the onesignalId, check the externalId as well to confirm the values are associated with the expected user.
* @param {(event: UserChangedState)=>void} listener
* @returns void
*/
addEventListener(event: "change", listener: (event: UserChangedState) => void) {
this._userStateObserverList.push(listener as (event: UserChangedState) => void);
const userCallBackProcessor = (state: UserChangedState) => {
this._processFunctionList(this._userStateObserverList, state);
};
window.cordova.exec(userCallBackProcessor, function(){}, "OneSignalPush", "addUserStateObserver", []);
}

/**
* Remove a User State observer that has been previously added.
* @param {(event: UserChangedState)=>void} listener
* @returns void
*/
removeEventListener(event: "change", listener: (event: UserChangedState) => void) {
let index = this._userStateObserverList.indexOf(listener);
if (index !== -1) {
this._userStateObserverList.splice(index, 1);
}
}

/**
* Get the nullable OneSignal Id associated with the current user.
* @returns {Promise<string | null>}
*/
async getOnesignalId(): Promise<string | null> {
return new Promise<string | null>((resolve, reject) => {
const callback = (response: {value: string}) => {
resolve(response.value ? response.value : null)
};
window.cordova.exec(callback, reject, "OneSignalPush", "getOnesignalId", []);
});
}

/**
* Get the nullable External Id associated with the current user.
* @returns {Promise<string | null>}
*/
async getExternalId(): Promise<string | null> {
return new Promise<string | null>((resolve, reject) => {
const callback = (response: {value: string}) => {
resolve(response.value ? response.value : null)
};
window.cordova.exec(callback, reject, "OneSignalPush", "getExternalId", []);
});
}
}
5 changes: 5 additions & 0 deletions www/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,4 +140,9 @@ export {
InAppMessageActionUrlType,
} from "./models/InAppMessage";

export {
UserState,
UserChangedState,
} from "./UserNamespace";

export default OneSignal;

0 comments on commit 3124470

Please sign in to comment.