You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
val onRefreshTokenExpired: OnRefreshTokenExpiredListener?
suspend fun authorize(options: AuthorizeOptions)
suspend fun logout()
The design has 2 small problems.
Same state, multiple handlers
Current design mandates caller of authorize and logout to handle success/failure, when the results of these actions, i.e. changes of session state, might be depended upon by several distinct, unrelated components of an app. For example, a user-preference repository might pre-fetch user-preference in the background once user had logged in. Since there is no delegate for login success, user is forced to call userPreferenceRepository.fetch() after authorize returns success. This gets worse if there are more components which "reacts" on session state.
Same handler, multiple call site
It is also likely that user would want to perform the same action upon logout and token expiry. Current design only provide token expiry delegate, but not logout, forcing user to perform the same action at possibly two logically separated portion of an app, e.g. start up (it is usually where global delegate is configured) and setting/logout screen.
This problem gets worse as the app provides more paths to logout/authorize: each time the user calls authorize, he would need to remember to call the corresponding handler (e.g. there might be login button in both setting screen, login screen, post feedback screen, etc). Granted, this can be mitigated by developer's own good abstraction (e.g. an app-wide app.handleLogin(), app.handleLogout()), but this adds unnecessary complexity to developers.
Snippets that demonstrate this problem:
// Setting screen:
mLoginButton.setOnClickListener(view -> mAuthgear.authorize(new Listener {
@Override
void onTokenObtained() {
// Do something with the token that is not specific to login flow in this screen
settingScreenSpecificUiUpdate();
}
}));
// Login screen:
mLoginButton.setOnClickListener(view -> mAuthgear.authorize(new Listener {
@Override
void onTokenObtained() {
// Do the same something with the token that is not specific to login flow in this screen
navigateToMain();
}
}));
// Post feed back screen:
mLoginButton.setOnClickListener(view -> mAuthgear.authorize(new Listener {
@Override
void onTokenObtained() {
// Do the same something with the token that is not specific to login flow in this screen
populateSenderWithUserInfo();
}
}));
Depending on the app's DI setup, it is likely that the portion that repeats would be wrapped in some kind of utility function/specific services. Worst case scenario is that said portion gets copy and pasted a bunch of times.
Proposal
Core
If we view session state as a reactive state, and whatever actions that mutate them (authorize and logout) would simply trigger a new event for the new state, the two problems can be solved easily:
The same state can be observed by multiple observers
The same observer would be triggered regardless of triggers
Thus this proposal suggest the following addition and removal:
+ interface OnSessionStateChangedListener { /*Omitted for brevity*/ }
+ val sessionState: SessionState
+ val onSessionStateChanged: List<OnSessionStateChangedListener>
+ fun addOnSessionStateChangedListener(listener: OnSessionStateChangedListener)
+ fun removeOnSessionStateChangedListener(listener: OnSessionStateChangedListener)
- val onRefreshTokenExpired: OnRefreshTokenExpiredListener?
Note that this does not mean authorize and logout should not have return value/callback, since users probably still need to know when these specific actions finishe. This proposal only adds the ability to handle more general cases without removing the ability to handle specific code paths.
Change trigger
@kiootic suggests that user might still want to distinguish between logout/expiry in the listener, thus we can modify OnSessionStateListener to also supply an enum ChangeTrigger, as follows:
enum class ChangeTrigger {
NoToken,
FoundToken,
Authorize,
Logout,
Expiry
}
// State diagram:
Logout/Expiry
+-----------------------------------------+
v |
SessionState.Unknown --- NoToken ----> SessionState.NoSession ---- Authorize -----> SessionState.LoggedIn
| ^
+------------------------------------------------------------------------------------+
FoundToken
Motivation
Given the current design as follows:
The design has 2 small problems.
Same state, multiple handlers
Current design mandates caller of
authorize
andlogout
to handle success/failure, when the results of these actions, i.e. changes of session state, might be depended upon by several distinct, unrelated components of an app. For example, a user-preference repository might pre-fetch user-preference in the background once user had logged in. Since there is no delegate for login success, user is forced to calluserPreferenceRepository.fetch()
after authorize returns success. This gets worse if there are more components which "reacts" on session state.Same handler, multiple call site
It is also likely that user would want to perform the same action upon logout and token expiry. Current design only provide token expiry delegate, but not logout, forcing user to perform the same action at possibly two logically separated portion of an app, e.g. start up (it is usually where global delegate is configured) and setting/logout screen.
This problem gets worse as the app provides more paths to logout/authorize: each time the user calls
authorize
, he would need to remember to call the corresponding handler (e.g. there might be login button in both setting screen, login screen, post feedback screen, etc). Granted, this can be mitigated by developer's own good abstraction (e.g. an app-wideapp.handleLogin()
,app.handleLogout()
), but this adds unnecessary complexity to developers.Snippets that demonstrate this problem:
Depending on the app's DI setup, it is likely that the portion that repeats would be wrapped in some kind of utility function/specific services. Worst case scenario is that said portion gets copy and pasted a bunch of times.
Proposal
Core
If we view session state as a reactive state, and whatever actions that mutate them (
authorize
andlogout
) would simply trigger a new event for the new state, the two problems can be solved easily:Thus this proposal suggest the following addition and removal:
Note that this does not mean
authorize
andlogout
should not have return value/callback, since users probably still need to know when these specific actions finishe. This proposal only adds the ability to handle more general cases without removing the ability to handle specific code paths.Change trigger
@kiootic suggests that user might still want to distinguish between logout/expiry in the listener, thus we can modify
OnSessionStateListener
to also supply an enumChangeTrigger
, as follows:How it Solves the Problem
Same state, multiple handlers
Same handler, multiple call site
The text was updated successfully, but these errors were encountered: