Skip to content

Commit a3c6cd6

Browse files
committed
Add UserStateObserver that returns both previous and current use states
1 parent 35500db commit a3c6cd6

File tree

19 files changed

+214
-19
lines changed

19 files changed

+214
-19
lines changed

Examples/OneSignalDemo/app/src/main/java/com/onesignal/sdktest/model/MainActivityViewModel.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@
2828

2929
import com.onesignal.Continue;
3030
import com.onesignal.OneSignal;
31+
import com.onesignal.debug.internal.logging.Logging;
3132
import com.onesignal.sdktest.adapter.SubscriptionRecyclerViewAdapter;
33+
import com.onesignal.user.IUserStateObserver;
34+
import com.onesignal.user.UserChangedState;
35+
import com.onesignal.user.UserState;
3236
import com.onesignal.user.subscriptions.IEmailSubscription;
3337
import com.onesignal.user.subscriptions.IPushSubscription;
3438
import com.onesignal.user.subscriptions.ISmsSubscription;
@@ -63,7 +67,7 @@
6367
import java.util.Map;
6468

6569
@RequiresApi(api = Build.VERSION_CODES.N)
66-
public class MainActivityViewModel implements ActivityViewModel, IPushSubscriptionObserver {
70+
public class MainActivityViewModel implements ActivityViewModel, IPushSubscriptionObserver, IUserStateObserver {
6771

6872
private Animate animate;
6973
private Dialog dialog;
@@ -293,6 +297,7 @@ public ActivityViewModel onActivityCreated(Context context) {
293297
triggerArrayList = new ArrayList<>();
294298

295299
OneSignal.getUser().getPushSubscription().addObserver(this);
300+
OneSignal.getUser().addObserver(this);
296301
return this;
297302
}
298303

@@ -501,6 +506,17 @@ public void onPushSubscriptionChange(@NonNull PushSubscriptionChangedState state
501506
refreshSubscriptionState();
502507
}
503508

509+
@Override
510+
public void onUserStateChange(@NonNull UserChangedState state) {
511+
UserState currentState = state.getCurrent();
512+
UserState prevState = state.getPrevious();
513+
Logging.debug("onUserStateChanged; previous onesignalId: " + String.valueOf(prevState.getOnesignalId())
514+
+ ", previous externalId: " + String.valueOf(prevState.getExternalId())
515+
+ ", current onesignalId: " + String.valueOf(currentState.getOnesignalId())
516+
+ ", current externalId: " + String.valueOf(currentState.getExternalId()),
517+
null);
518+
}
519+
504520
private class DummySubscription implements ISubscription {
505521

506522
private String _id;

OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/IDManager.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,19 @@ object IDManager {
2626
* @return true if the [id] provided was created via [createLocalId].
2727
*/
2828
fun isLocalId(id: String): Boolean = id.startsWith(LOCAL_PREFIX)
29+
30+
/**
31+
* Get non local ID or null.
32+
*
33+
* @param id The ID to test.
34+
*
35+
* @return [id] or null if the [id] provided was created via [createLocalId].
36+
*/
37+
fun getNonLocalIDOrNull(id: String): String? {
38+
if (isLocalId(id)) {
39+
return null
40+
}
41+
42+
return id
43+
}
2944
}

OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/events/EventProducer.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,11 @@ open class EventProducer<THandler> : IEventNotifier<THandler> {
3838
*
3939
* @param callback The callback will be invoked for each subscribed handler, allowing you to call the handler.
4040
*/
41-
fun fire(callback: (THandler) -> Unit) {
42-
for (s in subscribers) {
43-
callback(s)
41+
open fun fire(callback: (THandler) -> Unit) {
42+
synchronized(subscribers) {
43+
for (s in subscribers) {
44+
callback(s)
45+
}
4446
}
4547
}
4648

OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/IModelChangedHandler.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,14 @@ class ModelChangedArgs(
4949
*/
5050
val newValue: Any?,
5151
)
52+
53+
/**
54+
* The arguments passed to the [IModelChangedHandler] handler when subscribed via [Model.subscribe]
55+
*/
56+
class ModelReplacedArgs<TModel>(
57+
/**
58+
* The full model in its previous and current state.
59+
*/
60+
val oldModel: TModel,
61+
val newModel: TModel,
62+
) where TModel : Model

OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/ISingletonModelStoreChangeHandler.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ interface ISingletonModelStoreChangeHandler<TModel> where TModel : Model {
1212
* @param tag The tag which identifies how/why the model was replaced.
1313
*/
1414
fun onModelReplaced(
15-
model: TModel,
15+
model: ModelReplacedArgs<TModel>,
1616
tag: String,
1717
)
1818

OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/SingletonModelStore.kt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,14 @@ open class SingletonModelStore<TModel>(
3535
model: TModel,
3636
tag: String,
3737
) {
38-
val existingModel = this.model
39-
existingModel.initializeFromModel(singletonId, model)
40-
store.persist()
41-
changeSubscription.fire { it.onModelReplaced(existingModel, tag) }
38+
synchronized(replaceLock) {
39+
val oldModel = this.store.create() ?: throw Exception("Unable to initialize model from store $store")
40+
oldModel.initializeFromModel(singletonId, this.model)
41+
val existingModel = this.model
42+
existingModel.initializeFromModel(singletonId, model)
43+
store.persist()
44+
changeSubscription.fire { it.onModelReplaced(ModelReplacedArgs(oldModel, existingModel), tag) }
45+
}
4246
}
4347

4448
override fun subscribe(handler: ISingletonModelStoreChangeHandler<TModel>) = changeSubscription.subscribe(handler)

OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/config/impl/ConfigModelStoreListener.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.onesignal.common.exceptions.BackendException
44
import com.onesignal.common.modeling.ISingletonModelStoreChangeHandler
55
import com.onesignal.common.modeling.ModelChangeTags
66
import com.onesignal.common.modeling.ModelChangedArgs
7+
import com.onesignal.common.modeling.ModelReplacedArgs
78
import com.onesignal.common.threading.suspendifyOnThread
89
import com.onesignal.core.internal.backend.IParamsBackendService
910
import com.onesignal.core.internal.config.ConfigModel
@@ -43,7 +44,7 @@ internal class ConfigModelStoreListener(
4344
}
4445

4546
override fun onModelReplaced(
46-
model: ConfigModel,
47+
model: ModelReplacedArgs<ConfigModel>,
4748
tag: String,
4849
) {
4950
if (tag != ModelChangeTags.NORMAL) {

OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/operations/listeners/SingletonModelStoreListener.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import com.onesignal.common.modeling.ISingletonModelStoreChangeHandler
55
import com.onesignal.common.modeling.Model
66
import com.onesignal.common.modeling.ModelChangeTags
77
import com.onesignal.common.modeling.ModelChangedArgs
8+
import com.onesignal.common.modeling.ModelReplacedArgs
89
import com.onesignal.common.modeling.SingletonModelStore
910
import com.onesignal.core.internal.operations.IOperationRepo
1011
import com.onesignal.core.internal.operations.Operation
@@ -30,7 +31,7 @@ internal abstract class SingletonModelStoreListener<TModel>(
3031
}
3132

3233
override fun onModelReplaced(
33-
model: TModel,
34+
model: ModelReplacedArgs<TModel>,
3435
tag: String,
3536
) {
3637
if (tag != ModelChangeTags.NORMAL) {
@@ -62,7 +63,7 @@ internal abstract class SingletonModelStoreListener<TModel>(
6263
*
6364
* @return The operation to enqueue when the model has been replaced, or null if no operation should be enqueued.
6465
*/
65-
abstract fun getReplaceOperation(model: TModel): Operation?
66+
abstract fun getReplaceOperation(model: ModelReplacedArgs<TModel>): Operation?
6667

6768
/**
6869
* Called when the model has been updated.

OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/IUserManager.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,4 +138,15 @@ interface IUserManager {
138138
* Return a copy of all local tags from the current user.
139139
*/
140140
fun getTags(): Map<String, String>
141+
142+
/**
143+
* Add an observer to the user state, allowing the provider to be
144+
* notified whenever the user state has changed.
145+
*/
146+
fun addObserver(observer: IUserStateObserver)
147+
148+
/**
149+
* Remove an observer from the user state.
150+
*/
151+
fun removeObserver(observer: IUserStateObserver)
141152
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.onesignal.user
2+
3+
/**
4+
* A user state changed handler. Implement this interface and provide the implementation
5+
* to be notified when the user has changed.
6+
*/
7+
interface IUserStateObserver {
8+
/**
9+
* Called when the user state this change handler was added to, has changed. A
10+
* user state can change when user has logged in or out
11+
*
12+
* @param state The user changed state.
13+
*/
14+
fun onUserStateChange(state: UserChangedState)
15+
}

0 commit comments

Comments
 (0)