Cleanup store.

This commit is contained in:
Benoit Marty
2023-04-11 16:48:51 +02:00
committed by Benoit Marty
parent 80268156b5
commit f4a283567e
7 changed files with 40 additions and 137 deletions

View File

@@ -16,26 +16,8 @@
package io.element.android.libraries.push.api.store
import io.element.android.libraries.push.api.model.BackgroundSyncMode
import kotlinx.coroutines.flow.Flow
interface PushDataStore {
val pushCounterFlow: Flow<Int>
// TODO Move all those settings to the per user store...
fun areNotificationEnabledForDevice(): Boolean
fun setNotificationEnabledForDevice(enabled: Boolean)
fun backgroundSyncTimeOut(): Int
fun setBackgroundSyncTimeout(timeInSecond: Int)
fun backgroundSyncDelay(): Int
fun setBackgroundSyncDelay(timeInSecond: Int)
fun isBackgroundSyncEnabled(): Boolean
fun setFdroidSyncBackgroundMode(mode: BackgroundSyncMode)
fun getFdroidSyncBackgroundMode(): BackgroundSyncMode
/**
* Return true if Pin code is disabled, or if user set the settings to see full notification content.
*/
fun useCompleteNotificationFormat(): Boolean
}

View File

@@ -70,7 +70,8 @@ class NotificationDrawerManager @Inject constructor(
private var currentAppNavigationState: AppNavigationState? = null
private val firstThrottler = FirstThrottler(200)
private var useCompleteNotificationFormat = pushDataStore.useCompleteNotificationFormat()
// TODO EAx add a setting per user for this
private var useCompleteNotificationFormat = true
init {
handlerThread.start()
@@ -111,12 +112,6 @@ class NotificationDrawerManager @Inject constructor(
}
private fun NotificationEventQueue.onNotifiableEventReceived(notifiableEvent: NotifiableEvent) {
if (!pushDataStore.areNotificationEnabledForDevice()) {
Timber.i("Notification are disabled for this device")
return
}
// If we support multi session, event list should be per userId
// Currently only manage single session
if (buildMeta.lowPrivacyLoggingEnabled) {
Timber.d("onNotifiableEventReceived(): $notifiableEvent")
} else {
@@ -185,7 +180,7 @@ class NotificationDrawerManager @Inject constructor(
// TODO EAx Must be per account
fun notificationStyleChanged() {
updateEvents {
val newSettings = pushDataStore.useCompleteNotificationFormat()
val newSettings = true // pushDataStore.useCompleteNotificationFormat()
if (newSettings != useCompleteNotificationFormat) {
// Settings has changed, remove all current notifications
notificationRenderer.cancelAllNotifications()

View File

@@ -34,6 +34,7 @@ data class NotificationEventQueue constructor(
* Acts as a notification debouncer to stop already dismissed push notifications from
* displaying again when the /sync response is delayed.
*/
// TODO Should be per session, so the key must be Pair<SessionId, EventId>.
private val seenEventIds: CircularCache<EventId>
) {

View File

@@ -22,15 +22,12 @@ import android.os.Handler
import android.os.Looper
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.androidutils.network.WifiDetector
import io.element.android.libraries.core.log.logger.LoggerTag
import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.ApplicationContext
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
import io.element.android.libraries.push.api.store.PushDataStore
import io.element.android.libraries.push.impl.PushersManager
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret
import io.element.android.libraries.push.impl.log.pushLoggerTag
import io.element.android.libraries.push.impl.notifications.NotifiableEventResolver
import io.element.android.libraries.push.impl.notifications.NotificationActionIds
@@ -38,6 +35,8 @@ import io.element.android.libraries.push.impl.notifications.NotificationDrawerMa
import io.element.android.libraries.push.impl.store.DefaultPushDataStore
import io.element.android.libraries.push.providers.api.PushData
import io.element.android.libraries.push.providers.api.PushHandler
import io.element.android.libraries.pushstore.api.UserPushStoreFactory
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecret
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
@@ -51,17 +50,16 @@ private val loggerTag = LoggerTag("PushHandler", pushLoggerTag)
class DefaultPushHandler @Inject constructor(
private val notificationDrawerManager: NotificationDrawerManager,
private val notifiableEventResolver: NotifiableEventResolver,
private val pushDataStore: PushDataStore,
private val defaultPushDataStore: DefaultPushDataStore,
private val userPushStoreFactory: UserPushStoreFactory,
private val pushClientSecret: PushClientSecret,
private val actionIds: NotificationActionIds,
@ApplicationContext private val context: Context,
private val buildMeta: BuildMeta,
private val matrixAuthenticationService: MatrixAuthenticationService,
): PushHandler {
) : PushHandler {
private val coroutineScope = CoroutineScope(SupervisorJob())
private val wifiDetector: WifiDetector = WifiDetector(context)
// UI handler
private val mUIHandler by lazy {
@@ -89,12 +87,6 @@ class DefaultPushHandler @Inject constructor(
return
}
// TODO EAx Should be per user
if (!pushDataStore.areNotificationEnabledForDevice()) {
Timber.tag(loggerTag.value).i("Notification are disabled for this device")
return
}
mUIHandler.post {
coroutineScope.launch(Dispatchers.IO) { handleInternal(pushData) }
}
@@ -139,6 +131,13 @@ class DefaultPushHandler @Inject constructor(
return
}
val userPushStore = userPushStoreFactory.create(userId)
if (!userPushStore.areNotificationEnabledForDevice()) {
// TODO We need to check if this is an incoming call
Timber.tag(loggerTag.value).i("Notification are disabled for this device, ignore push.")
return
}
notificationDrawerManager.onNotifiableEventReceived(notificationData)
} catch (e: Exception) {
Timber.tag(loggerTag.value).e(e, "## handleInternal() failed")

View File

@@ -17,20 +17,15 @@
package io.element.android.libraries.push.impl.store
import android.content.Context
import android.content.SharedPreferences
import androidx.core.content.edit
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.core.data.tryOrNull
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.ApplicationContext
import io.element.android.libraries.di.DefaultPreferences
import io.element.android.libraries.di.SingleIn
import io.element.android.libraries.push.api.model.BackgroundSyncMode
import io.element.android.libraries.push.api.store.PushDataStore
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
@@ -42,7 +37,6 @@ private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(na
@ContributesBinding(AppScope::class)
class DefaultPushDataStore @Inject constructor(
@ApplicationContext private val context: Context,
@DefaultPreferences private val defaultPrefs: SharedPreferences,
) : PushDataStore {
private val pushCounter = intPreferencesKey("push_counter")
@@ -56,94 +50,4 @@ class DefaultPushDataStore @Inject constructor(
settings[pushCounter] = currentCounterValue + 1
}
}
override fun areNotificationEnabledForDevice(): Boolean {
return defaultPrefs.getBoolean(SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY, true)
}
override fun setNotificationEnabledForDevice(enabled: Boolean) {
defaultPrefs.edit {
putBoolean(SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY, enabled)
}
}
override fun backgroundSyncTimeOut(): Int {
return tryOrNull {
// The xml pref is saved as a string so use getString and parse
defaultPrefs.getString(SETTINGS_SET_SYNC_TIMEOUT_PREFERENCE_KEY, null)?.toInt()
} ?: BackgroundSyncMode.DEFAULT_SYNC_TIMEOUT_SECONDS
}
override fun setBackgroundSyncTimeout(timeInSecond: Int) {
defaultPrefs
.edit()
.putString(SETTINGS_SET_SYNC_TIMEOUT_PREFERENCE_KEY, timeInSecond.toString())
.apply()
}
override fun backgroundSyncDelay(): Int {
return tryOrNull {
// The xml pref is saved as a string so use getString and parse
defaultPrefs.getString(SETTINGS_SET_SYNC_DELAY_PREFERENCE_KEY, null)?.toInt()
} ?: BackgroundSyncMode.DEFAULT_SYNC_DELAY_SECONDS
}
override fun setBackgroundSyncDelay(timeInSecond: Int) {
defaultPrefs
.edit()
.putString(SETTINGS_SET_SYNC_DELAY_PREFERENCE_KEY, timeInSecond.toString())
.apply()
}
override fun isBackgroundSyncEnabled(): Boolean {
return getFdroidSyncBackgroundMode() != BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_DISABLED
}
override fun setFdroidSyncBackgroundMode(mode: BackgroundSyncMode) {
defaultPrefs
.edit()
.putString(SETTINGS_FDROID_BACKGROUND_SYNC_MODE, mode.name)
.apply()
}
override fun getFdroidSyncBackgroundMode(): BackgroundSyncMode {
return try {
val strPref = defaultPrefs
.getString(SETTINGS_FDROID_BACKGROUND_SYNC_MODE, BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_FOR_BATTERY.name)
BackgroundSyncMode.values().firstOrNull { it.name == strPref } ?: BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_FOR_BATTERY
} catch (e: Throwable) {
BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_FOR_BATTERY
}
}
/**
* Return true if Pin code is disabled, or if user set the settings to see full notification content.
*/
override fun useCompleteNotificationFormat(): Boolean {
return true
/*
return !useFlagPinCode() ||
defaultPrefs.getBoolean(SETTINGS_SECURITY_USE_COMPLETE_NOTIFICATIONS_FLAG, true)
*/
}
companion object {
// notifications
const val SETTINGS_ENABLE_ALL_NOTIF_PREFERENCE_KEY = "SETTINGS_ENABLE_ALL_NOTIF_PREFERENCE_KEY"
const val SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY = "SETTINGS_ENABLE_THIS_DEVICE_PREFERENCE_KEY"
// background sync
const val SETTINGS_START_ON_BOOT_PREFERENCE_KEY = "SETTINGS_START_ON_BOOT_PREFERENCE_KEY"
const val SETTINGS_ENABLE_BACKGROUND_SYNC_PREFERENCE_KEY = "SETTINGS_ENABLE_BACKGROUND_SYNC_PREFERENCE_KEY"
const val SETTINGS_SET_SYNC_TIMEOUT_PREFERENCE_KEY = "SETTINGS_SET_SYNC_TIMEOUT_PREFERENCE_KEY"
const val SETTINGS_SET_SYNC_DELAY_PREFERENCE_KEY = "SETTINGS_SET_SYNC_DELAY_PREFERENCE_KEY"
const val SETTINGS_FDROID_BACKGROUND_SYNC_MODE = "SETTINGS_FDROID_BACKGROUND_SYNC_MODE"
const val SETTINGS_BACKGROUND_SYNC_PREFERENCE_KEY = "SETTINGS_BACKGROUND_SYNC_PREFERENCE_KEY"
const val SETTINGS_SECURITY_USE_COMPLETE_NOTIFICATIONS_FLAG = "SETTINGS_SECURITY_USE_COMPLETE_NOTIFICATIONS_FLAG"
// notification method
const val SETTINGS_NOTIFICATION_METHOD_KEY = "SETTINGS_NOTIFICATION_METHOD_KEY"
}
}

View File

@@ -21,12 +21,17 @@ package io.element.android.libraries.pushstore.api
*/
interface UserPushStore {
suspend fun getPushProviderName(): String?
suspend fun setPushProviderName(value: String)
suspend fun getCurrentRegisteredPushKey(): String?
suspend fun setCurrentRegisteredPushKey(value: String)
suspend fun areNotificationEnabledForDevice(): Boolean
suspend fun setNotificationEnabledForDevice(enabled: Boolean)
/**
* Return true if Pin code is disabled, or if user set the settings to see full notification content.
*/
fun useCompleteNotificationFormat(): Boolean
suspend fun reset()
}

View File

@@ -19,9 +19,11 @@ package io.element.android.libraries.pushstore.impl
import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import io.element.android.libraries.core.bool.orTrue
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.pushstore.api.UserPushStore
import kotlinx.coroutines.flow.first
@@ -36,6 +38,7 @@ class UserPushStoreDataStore(
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "push_store_$userId")
private val pushProviderName = stringPreferencesKey("pushProviderName")
private val currentPushKey = stringPreferencesKey("currentPushKey")
private val notificationEnabled = booleanPreferencesKey("notificationEnabled")
override suspend fun getPushProviderName(): String? {
return context.dataStore.data.first()[pushProviderName]
@@ -57,6 +60,20 @@ class UserPushStoreDataStore(
}
}
override suspend fun areNotificationEnabledForDevice(): Boolean {
return context.dataStore.data.first()[notificationEnabled].orTrue()
}
override suspend fun setNotificationEnabledForDevice(enabled: Boolean) {
context.dataStore.edit {
it[notificationEnabled] = enabled
}
}
override fun useCompleteNotificationFormat(): Boolean {
return true
}
override suspend fun reset() {
context.dataStore.edit {
it.clear()