Create stores to manage shared preferences

This commit is contained in:
sim 2024-11-04 14:24:50 +00:00
parent 66a8a7a660
commit fa56b43a83
8 changed files with 150 additions and 117 deletions

View File

@ -0,0 +1,20 @@
package org.unifiedpush.distributor.nextpush
import android.content.Context
import org.unifiedpush.distributor.nextpush.account.AccountStore
class AppStore(context: Context) : Store(context) {
val account = AccountStore(context)
var deviceId: String?
get() = sharedPreferences
.getString(PREF_DEVICE_ID, null)
set(value) = sharedPreferences
.edit()
.putOrRemove(PREF_DEVICE_ID, value)
.apply()
companion object {
private const val PREF_DEVICE_ID = "deviceId"
}
}

View File

@ -0,0 +1,24 @@
package org.unifiedpush.distributor.nextpush
import android.content.Context
import android.content.SharedPreferences
open class Store(context: Context) {
val sharedPreferences: SharedPreferences = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
/**
* Put value in sharedpref or remove if null.
*/
fun SharedPreferences.Editor.putOrRemove(key: String, value: String?): SharedPreferences.Editor {
value?.let {
this.putString(key, value)
} ?: run {
this.remove(key)
}
return this
}
companion object {
internal const val PREF_NAME = "NextPush"
}
}

View File

@ -2,54 +2,20 @@ package org.unifiedpush.distributor.nextpush.account
import android.content.Context
import android.util.Log
import org.unifiedpush.distributor.nextpush.AppStore
import org.unifiedpush.distributor.nextpush.utils.TAG
internal const val PREF_NAME = "NextPush"
private const val PREF_DEVICE_ID = "deviceId"
private const val PREF_ACCOUNT_TYPE = "account::type"
enum class AccountType {
SSO,
Direct;
fun toInt(): Int {
return this.ordinal
}
}
private fun Int.toAccountType(): AccountType {
return AccountType.entries.getOrNull(this) ?: AccountType.SSO
}
object AccountFactory {
private var account: Account<out Any>? = null
var Context.accountType: AccountType
get() = this.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
.getInt(PREF_ACCOUNT_TYPE, 0).toAccountType()
private set(value) = this.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
.edit().putInt(PREF_ACCOUNT_TYPE, value.toInt())
.apply()
var Context.npDeviceId: String?
get() = this.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
.getString(PREF_DEVICE_ID, null)
set(value) {
this.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
.edit()
.apply {
value?.let {
putString(PREF_DEVICE_ID, it)
} ?: run {
remove(PREF_DEVICE_ID)
}
}.apply()
}
fun getAccount(context: Context, connected: Boolean = true): Account<out Any>? {
return account
?: run {
Log.d(TAG, "New account, type=${context.accountType}")
when (context.accountType) {
val accountType = AccountStore(context).accountType
Log.d(TAG, "New account, type=$accountType")
when (accountType) {
AccountType.SSO -> SSOAccount(context)
AccountType.Direct -> DirectAccount(context)
}.takeIf { !connected || it.connected }.also {
@ -60,18 +26,18 @@ object AccountFactory {
fun logout(context: Context) {
getAccount(context)?.logout(context)
context.npDeviceId = null
AppStore(context).deviceId = null
}
fun Context.setTypeSSO() {
account = null
accountType = AccountType.SSO
AccountStore(this).accountType = AccountType.SSO
DirectAccount.setCredentials(this, null, null, null)
}
fun Context.setTypeDirect(url: String, username: String, password: String) {
account = null
accountType = AccountType.Direct
AccountStore(this).accountType = AccountType.Direct
DirectAccount.setCredentials(this, url, username, password)
}
}

View File

@ -0,0 +1,20 @@
package org.unifiedpush.distributor.nextpush.account
import android.content.Context
import org.unifiedpush.distributor.nextpush.Store
/**
* Manager SharedPreferences for Account related values
*/
open class AccountStore(context: Context) : Store(context) {
var accountType: AccountType
get() = sharedPreferences
.getInt(PREF_ACCOUNT_TYPE, 0).toAccountType()
set(value) = sharedPreferences
.edit().putInt(PREF_ACCOUNT_TYPE, value.toInt())
.apply()
companion object {
private const val PREF_ACCOUNT_TYPE = "account::type"
}
}

View File

@ -0,0 +1,14 @@
package org.unifiedpush.distributor.nextpush.account
enum class AccountType {
SSO,
Direct;
fun toInt(): Int {
return this.ordinal
}
}
fun Int.toAccountType(): AccountType {
return AccountType.entries.getOrNull(this) ?: AccountType.SSO
}

View File

@ -11,26 +11,22 @@ import org.unifiedpush.distributor.nextpush.api.provider.ApiProvider.Companion.m
import java.io.IOException
import java.util.concurrent.TimeUnit
private const val PREF_CONNECTED = "direct_account::connected"
private const val PREF_URL = "direct_account::url"
private const val PREF_USERNAME = "direct_account::username"
private const val PREF_PASSWORD = "direct_account::password"
class DirectAccount(context: Context) : Account<OkHttpClient> {
override val name: String? = context.username
override val url: String? = context.url
override var connected = context.connected
private fun setConnected(context: Context, value: Boolean) {
connected = value
context.connected = value
/** [DirectAccountStore] */
private val daStore = DirectAccountStore(context)
override val name: String? = daStore.username
override val url: String? = daStore.url
override var connected = daStore.connected
set(value) {
daStore.connected = value
field = value
}
override fun connect(activity: Activity) {
setConnected(activity, false)
connected = false
val client = getClient(activity) ?: return retActivity(activity)
val url = activity.url ?: return retActivity(activity)
val url = daStore.url ?: return retActivity(activity)
val request = try {
Request.Builder()
@ -51,7 +47,7 @@ class DirectAccount(context: Context) : Account<OkHttpClient> {
override fun onResponse(call: Call, response: Response) {
Log.d(TAG, "Status: ${response.code}")
setConnected(activity, response.code == 200)
connected = response.code == 200
response.close()
retActivity(activity)
}
@ -69,8 +65,8 @@ class DirectAccount(context: Context) : Account<OkHttpClient> {
}
override fun getClient(context: Context): OkHttpClient? {
val username = context.username ?: return null
val password = context.password ?: return null
val username = daStore.username ?: return null
val password = daStore.password ?: return null
return OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.authenticator(DirectAuth(username, password))
@ -79,7 +75,7 @@ class DirectAccount(context: Context) : Account<OkHttpClient> {
}
override fun logout(context: Context) {
setConnected(context, false)
connected = false
setCredentials(context, null, null, null)
}
@ -112,56 +108,11 @@ class DirectAccount(context: Context) : Account<OkHttpClient> {
}
companion object {
private var Context.url: String?
get() = this.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
.getString(PREF_URL, null)
set(value) = value?.let {
this.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
.edit().putString(PREF_URL, it)
.apply()
} ?: run {
this.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
.edit().remove(PREF_URL)
.apply()
}
private var Context.username: String?
get() = this.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
.getString(PREF_USERNAME, null)
set(value) = value?.let {
this.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
.edit().putString(PREF_USERNAME, it)
.apply()
} ?: run {
this.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
.edit().remove(PREF_USERNAME)
.apply()
}
private var Context.password: String?
get() = this.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
.getString(PREF_PASSWORD, null)
set(value) = value?.let {
this.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
.edit().putString(PREF_PASSWORD, it)
.apply()
} ?: run {
this.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
.edit().remove(PREF_PASSWORD)
.apply()
}
private var Context.connected: Boolean
get() = this.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
.getBoolean(PREF_CONNECTED, false)
set(value) = this.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
.edit().putBoolean(PREF_CONNECTED, value)
.apply()
fun setCredentials(context: Context, url: String?, username: String?, password: String?) {
context.url = url
context.username = username
context.password = password
val daStore = DirectAccountStore(context)
daStore.url = url
daStore.username = username
daStore.password = password
}
}
}

View File

@ -0,0 +1,38 @@
package org.unifiedpush.distributor.nextpush.account
import android.content.Context
import org.unifiedpush.distributor.nextpush.Store
class DirectAccountStore(context: Context) : Store(context) {
var url: String?
get() = sharedPreferences
.getString(PREF_URL, null)
set(value) = sharedPreferences
.edit().putOrRemove(PREF_URL, value).apply()
var username: String?
get() = sharedPreferences
.getString(PREF_USERNAME, null)
set(value) = sharedPreferences
.edit().putOrRemove(PREF_USERNAME, value).apply()
var password: String?
get() = sharedPreferences
.getString(PREF_PASSWORD, null)
set(value) = sharedPreferences
.edit().putOrRemove(PREF_PASSWORD, value).apply()
var connected: Boolean
get() = sharedPreferences
.getBoolean(PREF_CONNECTED, false)
set(value) = sharedPreferences
.edit().putBoolean(PREF_CONNECTED, value)
.apply()
companion object {
private const val PREF_CONNECTED = "direct_account::connected"
private const val PREF_URL = "direct_account::url"
private const val PREF_USERNAME = "direct_account::username"
private const val PREF_PASSWORD = "direct_account::password"
}
}

View File

@ -10,9 +10,8 @@ import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.sse.EventSource
import okhttp3.sse.EventSources
import org.unifiedpush.distributor.nextpush.account.AccountFactory.accountType
import org.unifiedpush.distributor.nextpush.AppStore
import org.unifiedpush.distributor.nextpush.account.AccountFactory.getAccount
import org.unifiedpush.distributor.nextpush.account.AccountFactory.npDeviceId
import org.unifiedpush.distributor.nextpush.account.AccountType
import org.unifiedpush.distributor.nextpush.api.provider.* // ktlint-disable no-wildcard-imports
import org.unifiedpush.distributor.nextpush.api.provider.ApiProvider.Companion.mApiEndpoint
@ -23,21 +22,21 @@ import java.util.concurrent.atomic.AtomicReference
class Api(context: Context) {
private val TAG = Api::class.java.simpleName
private val context = context.applicationContext
private val store = AppStore(context)
private val baseUrl: String
get() = getAccount(context)?.url ?: "http://0.0.0.0/"
private fun withApiProvider(block: (ApiProvider, then: () -> Unit) -> Unit) {
when (context.accountType) {
when (store.account.accountType) {
AccountType.SSO -> ApiSSOFactory(context)
AccountType.Direct -> ApiDirectFactory(context)
}.getProviderAndExecute(block)
}
private fun tryWithDeviceId(block: (String) -> Unit) {
context.npDeviceId?.let {
store.deviceId?.let {
block(it)
}
?: run {
@ -52,7 +51,7 @@ class Api(context: Context) {
?.subscribe(object : DisposableObserver<ApiResponse>() {
override fun onNext(response: ApiResponse) {
response.deviceId.let {
context.npDeviceId = it
store.deviceId = it
}
}
@ -64,7 +63,7 @@ class Api(context: Context) {
override fun onComplete() {
// Sync once it is registered
context.npDeviceId?.let {
store.deviceId?.let {
block(it)
}
Log.d(TAG, "mApi register: onComplete")
@ -132,7 +131,7 @@ class Api(context: Context) {
then()
}
})
context.npDeviceId = null
store.deviceId = null
}
} catch (e: NoProviderException) {
e.printStackTrace()
@ -216,6 +215,7 @@ class Api(context: Context) {
}
companion object {
private const val TAG = "Api"
private val syncSource: AtomicReference<EventSource?> = AtomicReference(null)
}
}