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 #977

Merged
merged 13 commits into from
Mar 4, 2024

Conversation

jennantilla
Copy link
Contributor

@jennantilla jennantilla commented Feb 14, 2024

Description

One Line Summary

Update Push Subscription/Permission Getters to Async

Details

Motivation

We received reports of listeners not behaving as expected; certain getters were returning null due to the value not being available until returned from the native bridge. Updating getter methods to async will address this issue.

Scope

New async methods were added while also marking old methods as deprecated. Also updated requestPermission to account for changes made to these getters.

Testing

Manual testing

Tested running and building app on Android 14 emulator and iOS 17.2 Emulator, to ensure new methods work as expected.

Affected code checklist

  • Notifications
    • Display
    • Open
    • Push Processing
    • Confirm Deliveries
  • Outcomes
  • Sessions
  • In-App Messaging
  • REST API requests
  • Public API changes

Checklist

Overview

  • I have filled out all REQUIRED sections above
  • PR does one thing
    • If it is hard to explain how any codes changes are related to each other then it most likely needs to be more than one PR
  • Any Public API changes are explained in the PR details and conform to existing APIs

Testing

  • I have included test coverage for these changes, or explained why they are not needed
  • All automated tests pass, or I explained why that is not possible
  • I have personally tested this on my device, or explained why that is not possible

Final pass

  • Code is as readable as possible.
    • Simplify with less code, followed by splitting up code into well named functions and variables, followed by adding comments to the code.
  • I have reviewed this PR myself, ensuring it meets each checklist item
    • WIP (Work In Progress) is ok, but explain what is still in progress and what you would like feedback on. Start the PR title with "WIP" to indicate this.

This change is Reviewable

Copy link
Contributor

@nan-li nan-li left a comment

Choose a reason for hiding this comment

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

We also should change the getId and getToken to return null when it is not available, right now it is still taking what Android gives, which is "".

Also same for the push subscription observer, when you log the event and something is not available, it should log {"optedIn": "false", "id": null, token: null}.

www/NotificationsNamespace.ts Outdated Show resolved Hide resolved
www/NotificationsNamespace.ts Outdated Show resolved Hide resolved
www/NotificationsNamespace.ts Show resolved Hide resolved
www/PushSubscriptionNamespace.ts Outdated Show resolved Hide resolved
www/PushSubscriptionNamespace.ts Outdated Show resolved Hide resolved
www/PushSubscriptionNamespace.ts Outdated Show resolved Hide resolved
www/PushSubscriptionNamespace.ts Outdated Show resolved Hide resolved
www/PushSubscriptionNamespace.ts Outdated Show resolved Hide resolved
www/PushSubscriptionNamespace.ts Outdated Show resolved Hide resolved
@jennantilla
Copy link
Contributor Author

jennantilla commented Feb 17, 2024

Thank you so much for all the feedback, @nan-li!

Question about iOS:

Also same for the push subscription observer, when you log the event and something is not available, it should log {"optedIn": "false", "id": null, token: null}.

Currently the push subscription listener on iOS gives a JSONRepresentation of OSPushSubscriptionChangedState state, which returns "nil". Is that ok or should I update onPushSubscriptionDidChangeWithState to ensure null is passed?

@nan-li
Copy link
Contributor

nan-li commented Feb 17, 2024

You'll have to extract them with state.id, state.token etc just like you did for the user observer.

@jennantilla jennantilla mentioned this pull request Feb 19, 2024
8 tasks
Instead of returning an object with a boolean value
- Create new async methods
- Mark old getters as deprecated
- Ensure ids are nullable and remove undefined
- Update push optedIn getter to return boolean in callback
@nan-li
Copy link
Contributor

nan-li commented Feb 24, 2024

Rebased on feat/add_get_ids so this PR can use the null helper methods added for IDs.

@nan-li nan-li changed the base branch from user_model/main to feat/add_get_ids February 24, 2024 01:28
* Instead of making dictionaries just to pass strings over the bridge, pass the strings directly, when appropriate.
* Do this by creating helper methods in iOS and Android called `callbackSuccessString` and `successCallbackString`.
* To explain why they are still there
* Move Android requestPermission resolving into the bridge to improve readability of the method.
@nan-li
Copy link
Contributor

nan-li commented Feb 27, 2024

Pushed some changes, these are my testing scenarios:

  1. On a new app install, immediately call these new getters for push subscription properties and permission.
    See they are null and false. Which is correct at the beginning of a new installation.
 OneSignal.initialize("YOUR_APP_ID")
 const perm = await OneSignal.Notifications.getPermissionAsync() // false
 const optedIn = await OneSignal.User.pushSubscription.getOptedInAsync() // false
 const token = await OneSignal.User.pushSubscription.getTokenAsync() // null
 const id = await OneSignal.User.pushSubscription.getIdAsync() // null
  1. When changes to push subscription or permission occur, these new async getters return the correct values immediately, whereas the previous getters were still returning old data if called too early after the changes.
// User grants permission and permission observer fires
// Once the observer fires, Immediately call these methods

// New async getter returns `true` correctly
const optedIn = await OneSignal.User.pushSubscription.getOptedInAsync(); // true

// Old getter returns `false` still as it has not been updated yet
const optedIn = OneSignal.User.pushSubscription.optedIn; // still false
  1. On new cold starts (not first install), get these values immediately after initialization.
    See that the new async getters return the correct values.
    The old getters were returning false and undefined when called this early in the app startup process.
OneSignal.initialize("YOUR_APP_ID")
const perm = await OneSignal.Notifications.getPermissionAsync() // true
const optedIn = await OneSignal.User.pushSubscription.getOptedInAsync() // true
const token = await OneSignal.User.pushSubscription.getTokenAsync() // some real value
const id = await OneSignal.User.pushSubscription.getIdAsync() // some real value

const perm =  OneSignal.Notifications.hasPermission(); // false
const optedIn OneSignal.User.pushSubscription.optedIn; // false
const token = OneSignal.User.pushSubscription.token; // undefined
const id = OneSignal.User.pushSubscription.id; // undefined
  1. Confirm the old getters still "work" and are still being updated and supported. A few second after step 3 above, call those getters and see they do still provide the correct values when they are called later after app start.
// Called several seconds after SDK initialization returns the correct data

const perm =  OneSignal.Notifications.hasPermission(); // true
const optedIn OneSignal.User.pushSubscription.optedIn; // true
const token = OneSignal.User.pushSubscription.token; // some real value
const id = OneSignal.User.pushSubscription.id; // some real value
  1. Additionally, our API says the PushSubscriptionState callback to observers has optional properties id and token.
interface PushSubscriptionState {
    id                  ?: string;
    token               ?: string;
    optedIn             : boolean;
}

However, we had actually been passing along the empty string "" or the string literal "nil". That is also fixed in this PR

// Observer now firing when subscription ID is received has null properties when logged
{
    "current": { "id": "abcd-abcd-abcd-abcd", "token": null, "optedIn":false}, 
    "previous": {"id": null, "token": null, "optedIn": false}
}

Base automatically changed from feat/add_get_ids to user_model/main March 4, 2024 22:08
@jennantilla jennantilla merged commit 85f3dbd into user_model/main Mar 4, 2024
1 of 2 checks passed
@jennantilla jennantilla deleted the fix/property_getters branch March 4, 2024 22:09
@jennantilla jennantilla mentioned this pull request Mar 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants