Split push module into several modules: Firebase, UnifiedPush, store
This commit is contained in:
parent
1134f50090
commit
219b97eea7
53 changed files with 768 additions and 276 deletions
|
|
@ -45,6 +45,7 @@ dependencies {
|
||||||
implementation(projects.libraries.architecture)
|
implementation(projects.libraries.architecture)
|
||||||
implementation(projects.libraries.matrix.api)
|
implementation(projects.libraries.matrix.api)
|
||||||
implementation(projects.libraries.push.api)
|
implementation(projects.libraries.push.api)
|
||||||
|
implementation(projects.libraries.pushproviders.api)
|
||||||
implementation(projects.libraries.designsystem)
|
implementation(projects.libraries.designsystem)
|
||||||
implementation(projects.libraries.matrixui)
|
implementation(projects.libraries.matrixui)
|
||||||
implementation(projects.libraries.uiStrings)
|
implementation(projects.libraries.uiStrings)
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,9 @@ class LoggedInPresenter @Inject constructor(
|
||||||
override fun present(): LoggedInState {
|
override fun present(): LoggedInState {
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
// Ensure pusher is registered
|
// Ensure pusher is registered
|
||||||
pushService.registerFirebasePusher(matrixClient)
|
// TODO Register with Firebase for now
|
||||||
|
val pushProvider = pushService.getAvailablePushProviders().firstOrNull() ?: return@LaunchedEffect
|
||||||
|
pushService.registerWith(matrixClient, pushProvider, pushProvider.getDistributorNames().first())
|
||||||
}
|
}
|
||||||
|
|
||||||
val permissionsState = postNotificationPermissionsPresenter.present()
|
val permissionsState = postNotificationPermissionsPresenter.present()
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||||
import io.element.android.libraries.permissions.api.PermissionsPresenter
|
import io.element.android.libraries.permissions.api.PermissionsPresenter
|
||||||
import io.element.android.libraries.permissions.noop.NoopPermissionsPresenter
|
import io.element.android.libraries.permissions.noop.NoopPermissionsPresenter
|
||||||
import io.element.android.libraries.push.api.PushService
|
import io.element.android.libraries.push.api.PushService
|
||||||
|
import io.element.android.libraries.push.providers.api.PushProvider
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
@ -55,7 +56,11 @@ class LoggedInPresenterTest {
|
||||||
override fun notificationStyleChanged() {
|
override fun notificationStyleChanged() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun registerFirebasePusher(matrixClient: MatrixClient) {
|
override fun getAvailablePushProviders(): List<PushProvider> {
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun registerWith(matrixClient: MatrixClient, pushProvider: PushProvider, distributorName: String) {
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun testPush() {
|
override suspend fun testPush() {
|
||||||
|
|
|
||||||
|
|
@ -26,4 +26,5 @@ dependencies {
|
||||||
implementation(libs.androidx.corektx)
|
implementation(libs.androidx.corektx)
|
||||||
implementation(libs.coroutines.core)
|
implementation(libs.coroutines.core)
|
||||||
implementation(projects.libraries.matrix.api)
|
implementation(projects.libraries.matrix.api)
|
||||||
|
implementation(projects.libraries.pushproviders.api)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,21 @@
|
||||||
package io.element.android.libraries.push.api
|
package io.element.android.libraries.push.api
|
||||||
|
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
|
import io.element.android.libraries.push.providers.api.PushProvider
|
||||||
|
|
||||||
interface PushService {
|
interface PushService {
|
||||||
|
// TODO Move away
|
||||||
fun notificationStyleChanged()
|
fun notificationStyleChanged()
|
||||||
|
|
||||||
// Ensure pusher is registered
|
fun getAvailablePushProviders(): List<PushProvider>
|
||||||
suspend fun registerFirebasePusher(matrixClient: MatrixClient)
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will unregister any previous pusher and register a new one with the provided [PushProvider].
|
||||||
|
*
|
||||||
|
* The method has effect only if the [PushProvider] is different than the current one.
|
||||||
|
*/
|
||||||
|
suspend fun registerWith(matrixClient: MatrixClient, pushProvider: PushProvider, distributorName: String)
|
||||||
|
|
||||||
|
// TODO Move away
|
||||||
suspend fun testPush()
|
suspend fun testPush()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,8 @@ dependencies {
|
||||||
implementation(projects.libraries.androidutils)
|
implementation(projects.libraries.androidutils)
|
||||||
implementation(projects.libraries.network)
|
implementation(projects.libraries.network)
|
||||||
implementation(projects.libraries.matrix.api)
|
implementation(projects.libraries.matrix.api)
|
||||||
|
api(projects.libraries.pushproviders.api)
|
||||||
|
api(projects.libraries.pushstore.api)
|
||||||
api(projects.libraries.push.api)
|
api(projects.libraries.push.api)
|
||||||
|
|
||||||
implementation(projects.services.analytics.api)
|
implementation(projects.services.analytics.api)
|
||||||
|
|
@ -53,12 +55,10 @@ dependencies {
|
||||||
exclude(group = "com.android.support", module = "support-annotations")
|
exclude(group = "com.android.support", module = "support-annotations")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO Remove
|
||||||
implementation(platform(libs.google.firebase.bom))
|
implementation(platform(libs.google.firebase.bom))
|
||||||
implementation("com.google.firebase:firebase-messaging-ktx")
|
implementation("com.google.firebase:firebase-messaging-ktx")
|
||||||
|
|
||||||
// UnifiedPush
|
|
||||||
api(libs.unifiedpush)
|
|
||||||
|
|
||||||
testImplementation(libs.test.junit)
|
testImplementation(libs.test.junit)
|
||||||
testImplementation(libs.test.mockk)
|
testImplementation(libs.test.mockk)
|
||||||
testImplementation(libs.test.truth)
|
testImplementation(libs.test.truth)
|
||||||
|
|
|
||||||
|
|
@ -14,63 +14,15 @@
|
||||||
~ limitations under the License.
|
~ limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||||
|
|
||||||
<application>
|
<application>
|
||||||
|
|
||||||
<!-- Firebase components -->
|
|
||||||
<meta-data
|
|
||||||
android:name="firebase_analytics_collection_deactivated"
|
|
||||||
android:value="true" />
|
|
||||||
|
|
||||||
<service
|
|
||||||
android:name=".firebase.VectorFirebaseMessagingService"
|
|
||||||
android:exported="false">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
|
||||||
</intent-filter>
|
|
||||||
</service>
|
|
||||||
|
|
||||||
<!-- UnifiedPush -->
|
|
||||||
<receiver
|
|
||||||
android:name=".unifiedpush.VectorUnifiedPushMessagingReceiver"
|
|
||||||
android:enabled="true"
|
|
||||||
android:exported="true"
|
|
||||||
tools:ignore="ExportedReceiver">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="org.unifiedpush.android.connector.MESSAGE" />
|
|
||||||
<action android:name="org.unifiedpush.android.connector.UNREGISTERED" />
|
|
||||||
<action android:name="org.unifiedpush.android.connector.NEW_ENDPOINT" />
|
|
||||||
<action android:name="org.unifiedpush.android.connector.REGISTRATION_FAILED" />
|
|
||||||
<action android:name="org.unifiedpush.android.connector.REGISTRATION_REFUSED" />
|
|
||||||
</intent-filter>
|
|
||||||
</receiver>
|
|
||||||
|
|
||||||
<receiver
|
|
||||||
android:name=".unifiedpush.KeepInternalDistributor"
|
|
||||||
android:enabled="true"
|
|
||||||
android:exported="false">
|
|
||||||
<intent-filter>
|
|
||||||
<!--
|
|
||||||
This action is checked to track installed and uninstalled distributors.
|
|
||||||
We declare it to keep the background sync as an internal
|
|
||||||
unifiedpush distributor.
|
|
||||||
-->
|
|
||||||
<action android:name="org.unifiedpush.android.distributor.REGISTER" />
|
|
||||||
</intent-filter>
|
|
||||||
</receiver>
|
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".notifications.TestNotificationReceiver"
|
android:name=".notifications.TestNotificationReceiver"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".notifications.NotificationBroadcastReceiver"
|
android:name=".notifications.NotificationBroadcastReceiver"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
||||||
|
|
@ -20,27 +20,29 @@ import com.squareup.anvil.annotations.ContributesBinding
|
||||||
import io.element.android.libraries.di.AppScope
|
import io.element.android.libraries.di.AppScope
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
import io.element.android.libraries.push.api.PushService
|
import io.element.android.libraries.push.api.PushService
|
||||||
import io.element.android.libraries.push.impl.config.PushConfig
|
|
||||||
import io.element.android.libraries.push.impl.log.pushLoggerTag
|
|
||||||
import io.element.android.libraries.push.impl.notifications.NotificationDrawerManager
|
import io.element.android.libraries.push.impl.notifications.NotificationDrawerManager
|
||||||
import timber.log.Timber
|
import io.element.android.libraries.push.providers.api.PushProvider
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ContributesBinding(AppScope::class)
|
@ContributesBinding(AppScope::class)
|
||||||
class DefaultPushService @Inject constructor(
|
class DefaultPushService @Inject constructor(
|
||||||
private val notificationDrawerManager: NotificationDrawerManager,
|
private val notificationDrawerManager: NotificationDrawerManager,
|
||||||
private val pushersManager: PushersManager,
|
private val pushersManager: PushersManager,
|
||||||
private val fcmHelper: FcmHelper,
|
private val pushProviders: Set<@JvmSuppressWildcards PushProvider>,
|
||||||
) : PushService {
|
) : PushService {
|
||||||
override fun notificationStyleChanged() {
|
override fun notificationStyleChanged() {
|
||||||
notificationDrawerManager.notificationStyleChanged()
|
notificationDrawerManager.notificationStyleChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun registerFirebasePusher(matrixClient: MatrixClient) {
|
override fun getAvailablePushProviders(): List<PushProvider> {
|
||||||
val pushKey = fcmHelper.getFcmToken() ?: return Unit.also {
|
// TODO Sort by priority?
|
||||||
Timber.tag(pushLoggerTag.value).w("Unable to register pusher, Firebase token is not known.")
|
return pushProviders.toList()
|
||||||
}
|
}
|
||||||
pushersManager.registerPusher(matrixClient, pushKey, PushConfig.pusher_http_url)
|
|
||||||
|
override suspend fun registerWith(matrixClient: MatrixClient, pushProvider: PushProvider, distributorName: String) {
|
||||||
|
// TODO Get current push provider, compare with provided one, then unregister and register if different, and store change
|
||||||
|
|
||||||
|
pushProvider.registerWith(matrixClient, distributorName)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun testPush() {
|
override suspend fun testPush() {
|
||||||
|
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2022 New Vector Ltd
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl
|
|
||||||
|
|
||||||
interface FcmHelper {
|
|
||||||
fun isFirebaseAvailable(): Boolean
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the FCM registration token.
|
|
||||||
*
|
|
||||||
* @return the FCM token or null if not received from FCM.
|
|
||||||
*/
|
|
||||||
fun getFcmToken(): String?
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store FCM token to the SharedPrefs.
|
|
||||||
*
|
|
||||||
* @param token the token to store.
|
|
||||||
*/
|
|
||||||
fun storeFcmToken(token: String?)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* onNewToken may not be called on application upgrade, so ensure my shared pref is set.
|
|
||||||
*
|
|
||||||
* @param pushersManager the instance to register the pusher on.
|
|
||||||
* @param registerPusher whether the pusher should be registered.
|
|
||||||
*/
|
|
||||||
fun ensureFcmTokenIsRetrieved(pushersManager: PushersManager, registerPusher: Boolean)
|
|
||||||
|
|
||||||
/*
|
|
||||||
fun onEnterForeground(activeSessionHolder: ActiveSessionHolder)
|
|
||||||
|
|
||||||
fun onEnterBackground(activeSessionHolder: ActiveSessionHolder)
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
@ -16,7 +16,9 @@
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl
|
package io.element.android.libraries.push.impl
|
||||||
|
|
||||||
|
import com.squareup.anvil.annotations.ContributesBinding
|
||||||
import io.element.android.libraries.core.log.logger.LoggerTag
|
import io.element.android.libraries.core.log.logger.LoggerTag
|
||||||
|
import io.element.android.libraries.di.AppScope
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
||||||
import io.element.android.libraries.matrix.api.core.EventId
|
import io.element.android.libraries.matrix.api.core.EventId
|
||||||
|
|
@ -26,10 +28,9 @@ import io.element.android.libraries.push.impl.clientsecret.PushClientSecret
|
||||||
import io.element.android.libraries.push.impl.config.PushConfig
|
import io.element.android.libraries.push.impl.config.PushConfig
|
||||||
import io.element.android.libraries.push.impl.log.pushLoggerTag
|
import io.element.android.libraries.push.impl.log.pushLoggerTag
|
||||||
import io.element.android.libraries.push.impl.pushgateway.PushGatewayNotifyRequest
|
import io.element.android.libraries.push.impl.pushgateway.PushGatewayNotifyRequest
|
||||||
import io.element.android.libraries.push.impl.userpushstore.UserPushStoreFactory
|
import io.element.android.libraries.push.providers.api.PusherSubscriber
|
||||||
import io.element.android.libraries.push.impl.userpushstore.isFirebase
|
import io.element.android.libraries.pushstore.api.UserPushStoreFactory
|
||||||
import io.element.android.libraries.sessionstorage.api.SessionStore
|
import io.element.android.libraries.sessionstorage.api.SessionStore
|
||||||
import io.element.android.libraries.sessionstorage.api.toUserList
|
|
||||||
import io.element.android.services.toolbox.api.appname.AppNameProvider
|
import io.element.android.services.toolbox.api.appname.AppNameProvider
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
@ -38,8 +39,9 @@ internal const val DEFAULT_PUSHER_FILE_TAG = "mobile"
|
||||||
|
|
||||||
private val loggerTag = LoggerTag("PushersManager", pushLoggerTag)
|
private val loggerTag = LoggerTag("PushersManager", pushLoggerTag)
|
||||||
|
|
||||||
|
@ContributesBinding(AppScope::class)
|
||||||
class PushersManager @Inject constructor(
|
class PushersManager @Inject constructor(
|
||||||
private val unifiedPushHelper: UnifiedPushHelper,
|
// private val unifiedPushHelper: UnifiedPushHelper,
|
||||||
// private val localeProvider: LocaleProvider,
|
// private val localeProvider: LocaleProvider,
|
||||||
private val appNameProvider: AppNameProvider,
|
private val appNameProvider: AppNameProvider,
|
||||||
// private val getDeviceInfoUseCase: GetDeviceInfoUseCase,
|
// private val getDeviceInfoUseCase: GetDeviceInfoUseCase,
|
||||||
|
|
@ -48,14 +50,14 @@ class PushersManager @Inject constructor(
|
||||||
private val sessionStore: SessionStore,
|
private val sessionStore: SessionStore,
|
||||||
private val matrixAuthenticationService: MatrixAuthenticationService,
|
private val matrixAuthenticationService: MatrixAuthenticationService,
|
||||||
private val userPushStoreFactory: UserPushStoreFactory,
|
private val userPushStoreFactory: UserPushStoreFactory,
|
||||||
private val fcmHelper: FcmHelper,
|
): PusherSubscriber {
|
||||||
) {
|
// TODO Move this to the PushProvider API
|
||||||
suspend fun testPush() {
|
suspend fun testPush() {
|
||||||
pushGatewayNotifyRequest.execute(
|
pushGatewayNotifyRequest.execute(
|
||||||
PushGatewayNotifyRequest.Params(
|
PushGatewayNotifyRequest.Params(
|
||||||
url = unifiedPushHelper.getPushGateway() ?: return,
|
url = "TODO", // unifiedPushHelper.getPushGateway() ?: return,
|
||||||
appId = PushConfig.pusher_app_id,
|
appId = PushConfig.pusher_app_id,
|
||||||
pushKey = unifiedPushHelper.getEndpointOrToken().orEmpty(),
|
pushKey = "TODO", // unifiedPushHelper.getEndpointOrToken().orEmpty(),
|
||||||
eventId = TEST_EVENT_ID
|
eventId = TEST_EVENT_ID
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
@ -73,26 +75,10 @@ class PushersManager @Inject constructor(
|
||||||
TODO()
|
TODO()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun onNewFirebaseToken(firebaseToken: String) {
|
|
||||||
fcmHelper.storeFcmToken(firebaseToken)
|
|
||||||
|
|
||||||
// Register the pusher for all the sessions
|
|
||||||
sessionStore.getAllSessions().toUserList().forEach { userId ->
|
|
||||||
val userDataStore = userPushStoreFactory.create(userId)
|
|
||||||
if (userDataStore.isFirebase()) {
|
|
||||||
matrixAuthenticationService.restoreSession(SessionId(userId)).getOrNull()?.use { client ->
|
|
||||||
registerPusher(client, firebaseToken, PushConfig.pusher_http_url)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Timber.tag(loggerTag.value).d("This session is not using Firebase pusher")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a pusher to the server if not done yet.
|
* Register a pusher to the server if not done yet.
|
||||||
*/
|
*/
|
||||||
suspend fun registerPusher(matrixClient: MatrixClient, pushKey: String, gateway: String) {
|
override suspend fun registerPusher(matrixClient: MatrixClient, pushKey: String, gateway: String) {
|
||||||
val userDataStore = userPushStoreFactory.create(matrixClient.sessionId.value)
|
val userDataStore = userPushStoreFactory.create(matrixClient.sessionId.value)
|
||||||
if (userDataStore.getCurrentRegisteredPushKey() == pushKey) {
|
if (userDataStore.getCurrentRegisteredPushKey() == pushKey) {
|
||||||
Timber.tag(loggerTag.value).d("Unnecessary to register again the same pusher")
|
Timber.tag(loggerTag.value).d("Unnecessary to register again the same pusher")
|
||||||
|
|
|
||||||
|
|
@ -17,25 +17,8 @@
|
||||||
package io.element.android.libraries.push.impl.config
|
package io.element.android.libraries.push.impl.config
|
||||||
|
|
||||||
object PushConfig {
|
object PushConfig {
|
||||||
/**
|
|
||||||
* It is the push gateway for FCM embedded distributor.
|
|
||||||
* Note: pusher_http_url should have path '/_matrix/push/v1/notify' -->
|
|
||||||
*/
|
|
||||||
const val pusher_http_url: String = "https://matrix.org/_matrix/push/v1/notify"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* It is the push gateway for UnifiedPush.
|
|
||||||
* Note: default_push_gateway_http_url should have path '/_matrix/push/v1/notify'
|
|
||||||
*/
|
|
||||||
const val default_push_gateway_http_url: String = "https://matrix.gateway.unifiedpush.org/_matrix/push/v1/notify"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note: pusher_app_id cannot exceed 64 chars.
|
* Note: pusher_app_id cannot exceed 64 chars.
|
||||||
*/
|
*/
|
||||||
const val pusher_app_id: String = "im.vector.app.android"
|
const val pusher_app_id: String = "im.vector.app.android"
|
||||||
|
|
||||||
/**
|
|
||||||
* Set to true to allow external push distributor such as Ntfy.
|
|
||||||
*/
|
|
||||||
const val allowExternalUnifiedPushDistributors: Boolean = false
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,11 @@ import android.content.Intent
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||||
|
import com.squareup.anvil.annotations.ContributesBinding
|
||||||
import io.element.android.libraries.androidutils.network.WifiDetector
|
import io.element.android.libraries.androidutils.network.WifiDetector
|
||||||
import io.element.android.libraries.core.log.logger.LoggerTag
|
import io.element.android.libraries.core.log.logger.LoggerTag
|
||||||
import io.element.android.libraries.core.meta.BuildMeta
|
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.di.ApplicationContext
|
||||||
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
||||||
import io.element.android.libraries.push.api.store.PushDataStore
|
import io.element.android.libraries.push.api.store.PushDataStore
|
||||||
|
|
@ -34,6 +36,8 @@ import io.element.android.libraries.push.impl.notifications.NotifiableEventResol
|
||||||
import io.element.android.libraries.push.impl.notifications.NotificationActionIds
|
import io.element.android.libraries.push.impl.notifications.NotificationActionIds
|
||||||
import io.element.android.libraries.push.impl.notifications.NotificationDrawerManager
|
import io.element.android.libraries.push.impl.notifications.NotificationDrawerManager
|
||||||
import io.element.android.libraries.push.impl.store.DefaultPushDataStore
|
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 kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
|
@ -43,7 +47,8 @@ import javax.inject.Inject
|
||||||
|
|
||||||
private val loggerTag = LoggerTag("PushHandler", pushLoggerTag)
|
private val loggerTag = LoggerTag("PushHandler", pushLoggerTag)
|
||||||
|
|
||||||
class PushHandler @Inject constructor(
|
@ContributesBinding(AppScope::class)
|
||||||
|
class DefaultPushHandler @Inject constructor(
|
||||||
private val notificationDrawerManager: NotificationDrawerManager,
|
private val notificationDrawerManager: NotificationDrawerManager,
|
||||||
private val notifiableEventResolver: NotifiableEventResolver,
|
private val notifiableEventResolver: NotifiableEventResolver,
|
||||||
private val pushDataStore: PushDataStore,
|
private val pushDataStore: PushDataStore,
|
||||||
|
|
@ -53,7 +58,7 @@ class PushHandler @Inject constructor(
|
||||||
@ApplicationContext private val context: Context,
|
@ApplicationContext private val context: Context,
|
||||||
private val buildMeta: BuildMeta,
|
private val buildMeta: BuildMeta,
|
||||||
private val matrixAuthenticationService: MatrixAuthenticationService,
|
private val matrixAuthenticationService: MatrixAuthenticationService,
|
||||||
) {
|
): PushHandler {
|
||||||
|
|
||||||
private val coroutineScope = CoroutineScope(SupervisorJob())
|
private val coroutineScope = CoroutineScope(SupervisorJob())
|
||||||
private val wifiDetector: WifiDetector = WifiDetector(context)
|
private val wifiDetector: WifiDetector = WifiDetector(context)
|
||||||
|
|
@ -68,7 +73,7 @@ class PushHandler @Inject constructor(
|
||||||
*
|
*
|
||||||
* @param pushData the data received in the push.
|
* @param pushData the data received in the push.
|
||||||
*/
|
*/
|
||||||
suspend fun handle(pushData: PushData) {
|
override suspend fun handle(pushData: PushData) {
|
||||||
Timber.tag(loggerTag.value).d("## handling pushData")
|
Timber.tag(loggerTag.value).d("## handling pushData")
|
||||||
|
|
||||||
if (buildMeta.lowPrivacyLoggingEnabled) {
|
if (buildMeta.lowPrivacyLoggingEnabled) {
|
||||||
28
libraries/pushproviders/api/build.gradle.kts
Normal file
28
libraries/pushproviders/api/build.gradle.kts
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id("io.element.android-library")
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "io.element.android.libraries.push.providers.api"
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(projects.libraries.core)
|
||||||
|
implementation(projects.libraries.matrix.api)
|
||||||
|
}
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.push
|
package io.element.android.libraries.push.providers.api
|
||||||
|
|
||||||
import io.element.android.libraries.matrix.api.core.EventId
|
import io.element.android.libraries.matrix.api.core.EventId
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
|
|
@ -28,8 +28,8 @@ import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
* @property clientSecret data used when the pusher was configured, to be able to determine the session.
|
* @property clientSecret data used when the pusher was configured, to be able to determine the session.
|
||||||
*/
|
*/
|
||||||
data class PushData(
|
data class PushData(
|
||||||
val eventId: EventId,
|
val eventId: EventId,
|
||||||
val roomId: RoomId,
|
val roomId: RoomId,
|
||||||
val unread: Int?,
|
val unread: Int?,
|
||||||
val clientSecret: String?,
|
val clientSecret: String?,
|
||||||
)
|
)
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.push.providers.api
|
||||||
|
|
||||||
|
interface PushHandler {
|
||||||
|
suspend fun handle(pushData: PushData)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.push.providers.api
|
||||||
|
|
||||||
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the main API for this module
|
||||||
|
*/
|
||||||
|
interface PushProvider {
|
||||||
|
fun getDistributorNames(): List<String>
|
||||||
|
suspend fun registerWith(matrixClient: MatrixClient, distributorName: String)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.push.providers.api
|
||||||
|
|
||||||
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
|
|
||||||
|
interface PusherSubscriber {
|
||||||
|
suspend fun registerPusher(matrixClient: MatrixClient, pushKey: String, gateway: String)
|
||||||
|
}
|
||||||
48
libraries/pushproviders/firebase/build.gradle.kts
Normal file
48
libraries/pushproviders/firebase/build.gradle.kts
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id("io.element.android-library")
|
||||||
|
alias(libs.plugins.anvil)
|
||||||
|
// kotlin("plugin.serialization") version "1.8.10"
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "io.element.android.libraries.push.providers.firebase"
|
||||||
|
}
|
||||||
|
|
||||||
|
anvil {
|
||||||
|
generateDaggerFactories.set(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(libs.dagger)
|
||||||
|
implementation(libs.androidx.corektx)
|
||||||
|
implementation(projects.libraries.architecture)
|
||||||
|
implementation(projects.libraries.core)
|
||||||
|
implementation(projects.libraries.di)
|
||||||
|
implementation(projects.libraries.matrix.api)
|
||||||
|
|
||||||
|
implementation(projects.libraries.pushstore.api)
|
||||||
|
implementation(projects.libraries.pushproviders.api)
|
||||||
|
|
||||||
|
implementation(platform(libs.google.firebase.bom))
|
||||||
|
implementation("com.google.firebase:firebase-messaging-ktx")
|
||||||
|
|
||||||
|
testImplementation(libs.test.junit)
|
||||||
|
testImplementation(libs.test.truth)
|
||||||
|
testImplementation(projects.libraries.matrix.test)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Copyright (c) 2023 New Vector Ltd
|
||||||
|
~
|
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ you may not use this file except in compliance with the License.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<application>
|
||||||
|
<!-- Firebase components -->
|
||||||
|
<meta-data
|
||||||
|
android:name="firebase_analytics_collection_deactivated"
|
||||||
|
android:value="true" />
|
||||||
|
<service
|
||||||
|
android:name="io.element.android.libraries.push.providers.firebase.VectorFirebaseMessagingService"
|
||||||
|
android:exported="false">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
||||||
|
</intent-filter>
|
||||||
|
</service>
|
||||||
|
</application>
|
||||||
|
</manifest>
|
||||||
|
|
@ -14,24 +14,22 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.firebase
|
package io.element.android.libraries.push.providers.firebase
|
||||||
|
|
||||||
import io.element.android.libraries.push.impl.FcmHelper
|
|
||||||
import io.element.android.libraries.push.impl.PushersManager
|
|
||||||
import io.element.android.libraries.push.impl.UnifiedPushHelper
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
// TODO
|
||||||
class EnsureFcmTokenIsRetrievedUseCase @Inject constructor(
|
class EnsureFcmTokenIsRetrievedUseCase @Inject constructor(
|
||||||
private val unifiedPushHelper: UnifiedPushHelper,
|
// private val unifiedPushHelper: UnifiedPushHelper,
|
||||||
private val fcmHelper: FcmHelper,
|
// private val fcmHelper: FcmHelper,
|
||||||
// private val activeSessionHolder: ActiveSessionHolder,
|
// private val activeSessionHolder: ActiveSessionHolder,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun execute(pushersManager: PushersManager, registerPusher: Boolean) {
|
// fun execute(pushersManager: PushersManager, registerPusher: Boolean) {
|
||||||
if (unifiedPushHelper.isEmbeddedDistributor()) {
|
// if (unifiedPushHelper.isEmbeddedDistributor()) {
|
||||||
fcmHelper.ensureFcmTokenIsRetrieved(pushersManager, shouldAddHttpPusher(registerPusher))
|
// fcmHelper.ensureFcmTokenIsRetrieved(pushersManager, shouldAddHttpPusher(registerPusher))
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
private fun shouldAddHttpPusher(registerPusher: Boolean) = if (registerPusher) {
|
private fun shouldAddHttpPusher(registerPusher: Boolean) = if (registerPusher) {
|
||||||
/*
|
/*
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.push.providers.firebase
|
||||||
|
|
||||||
|
object FirebaseConfig {
|
||||||
|
/**
|
||||||
|
* It is the push gateway for firebase.
|
||||||
|
* Note: pusher_http_url should have path '/_matrix/push/v1/notify' -->
|
||||||
|
*/
|
||||||
|
const val pusher_http_url: String = "https://matrix.org/_matrix/push/v1/notify"
|
||||||
|
|
||||||
|
const val internalName = "NOTIFICATION_METHOD_FIREBASE"
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2022 New Vector Ltd
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -14,9 +14,9 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.firebase
|
package io.element.android.libraries.push.providers.firebase
|
||||||
|
|
||||||
import io.element.android.libraries.push.impl.push.PushData
|
import io.element.android.libraries.push.providers.api.PushData
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class FirebasePushParser @Inject constructor() {
|
class FirebasePushParser @Inject constructor() {
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.push.providers.firebase
|
||||||
|
|
||||||
|
import io.element.android.libraries.core.log.logger.LoggerTag
|
||||||
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
|
import io.element.android.libraries.push.providers.api.PushProvider
|
||||||
|
import io.element.android.libraries.push.providers.api.PusherSubscriber
|
||||||
|
import timber.log.Timber
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
private val loggerTag = LoggerTag("FirebasePushProvider")
|
||||||
|
|
||||||
|
class FirebasePushProvider @Inject constructor(
|
||||||
|
private val googleFcmHelper: GoogleFcmHelper,
|
||||||
|
private val pusherSubscriber: PusherSubscriber,
|
||||||
|
) : PushProvider {
|
||||||
|
|
||||||
|
override fun getDistributorNames(): List<String> {
|
||||||
|
// Must return an non-empty list for now
|
||||||
|
return listOf("unused")
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun registerWith(matrixClient: MatrixClient, distributorName: String) {
|
||||||
|
val pushKey = googleFcmHelper.getFcmToken() ?: return Unit.also {
|
||||||
|
Timber.tag(loggerTag.value).w("Unable to register pusher, Firebase token is not known.")
|
||||||
|
}
|
||||||
|
pusherSubscriber.registerPusher(matrixClient, pushKey, FirebaseConfig.pusher_http_url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.push.providers.firebase
|
||||||
|
|
||||||
|
import io.element.android.libraries.core.log.logger.LoggerTag
|
||||||
|
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
||||||
|
import io.element.android.libraries.matrix.api.core.SessionId
|
||||||
|
import io.element.android.libraries.push.providers.api.PusherSubscriber
|
||||||
|
import io.element.android.libraries.pushstore.api.UserPushStoreFactory
|
||||||
|
import io.element.android.libraries.sessionstorage.api.SessionStore
|
||||||
|
import io.element.android.libraries.sessionstorage.api.toUserList
|
||||||
|
import timber.log.Timber
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
private val loggerTag = LoggerTag("FirebaseSetPusher")
|
||||||
|
|
||||||
|
// TODO Rename
|
||||||
|
class FirebaseSetPusher @Inject constructor(
|
||||||
|
private val pusherSubscriber: PusherSubscriber,
|
||||||
|
private val sessionStore: SessionStore,
|
||||||
|
private val userPushStoreFactory: UserPushStoreFactory,
|
||||||
|
private val matrixAuthenticationService: MatrixAuthenticationService,
|
||||||
|
) {
|
||||||
|
suspend fun onNewFirebaseToken(firebaseToken: String) {
|
||||||
|
// Register the pusher for all the sessions
|
||||||
|
sessionStore.getAllSessions().toUserList().forEach { userId ->
|
||||||
|
val userDataStore = userPushStoreFactory.create(userId)
|
||||||
|
if (userDataStore.getNotificationMethod() == FirebaseConfig.internalName) {
|
||||||
|
matrixAuthenticationService.restoreSession(SessionId(userId)).getOrNull()?.use { client ->
|
||||||
|
pusherSubscriber.registerPusher(client, firebaseToken, FirebaseConfig.pusher_http_url)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Timber.tag(loggerTag.value).d("This session is not using Firebase pusher")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -14,44 +14,37 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl
|
package io.element.android.libraries.push.providers.firebase
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
import com.google.android.gms.common.ConnectionResult
|
import com.google.android.gms.common.ConnectionResult
|
||||||
import com.google.android.gms.common.GoogleApiAvailability
|
import com.google.android.gms.common.GoogleApiAvailability
|
||||||
import com.google.firebase.messaging.FirebaseMessaging
|
|
||||||
import com.squareup.anvil.annotations.ContributesBinding
|
|
||||||
import io.element.android.libraries.di.AppScope
|
|
||||||
import io.element.android.libraries.di.ApplicationContext
|
import io.element.android.libraries.di.ApplicationContext
|
||||||
import io.element.android.libraries.di.DefaultPreferences
|
import io.element.android.libraries.di.DefaultPreferences
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
import timber.log.Timber
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class store the FCM token in SharedPrefs and ensure this token is retrieved.
|
* This class store the FCM token in SharedPrefs and ensure this token is retrieved.
|
||||||
* It has an alter ego in the fdroid variant.
|
* It has an alter ego in the fdroid variant.
|
||||||
*/
|
*/
|
||||||
@ContributesBinding(AppScope::class)
|
// TODO Rename to store?
|
||||||
class GoogleFcmHelper @Inject constructor(
|
class GoogleFcmHelper @Inject constructor(
|
||||||
@ApplicationContext private val context: Context,
|
@ApplicationContext private val context: Context,
|
||||||
@DefaultPreferences private val sharedPrefs: SharedPreferences,
|
@DefaultPreferences private val sharedPrefs: SharedPreferences,
|
||||||
) : FcmHelper {
|
) {
|
||||||
override fun isFirebaseAvailable(): Boolean = true
|
fun getFcmToken(): String? {
|
||||||
|
|
||||||
override fun getFcmToken(): String? {
|
|
||||||
return sharedPrefs.getString(PREFS_KEY_FCM_TOKEN, null)
|
return sharedPrefs.getString(PREFS_KEY_FCM_TOKEN, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun storeFcmToken(token: String?) {
|
fun storeFcmToken(token: String?) {
|
||||||
sharedPrefs.edit {
|
sharedPrefs.edit {
|
||||||
putString(PREFS_KEY_FCM_TOKEN, token)
|
putString(PREFS_KEY_FCM_TOKEN, token)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
override fun ensureFcmTokenIsRetrieved(pushersManager: PushersManager, registerPusher: Boolean) {
|
override fun ensureFcmTokenIsRetrieved(pushersManager: PushersManager, registerPusher: Boolean) {
|
||||||
// 'app should always check the device for a compatible Google Play services APK before accessing Google Play services features'
|
// 'app should always check the device for a compatible Google Play services APK before accessing Google Play services features'
|
||||||
if (checkPlayServices(context)) {
|
if (checkPlayServices(context)) {
|
||||||
|
|
@ -76,6 +69,7 @@ class GoogleFcmHelper @Inject constructor(
|
||||||
Timber.e("No valid Google Play Services found. Cannot use FCM.")
|
Timber.e("No valid Google Play Services found. Cannot use FCM.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check the device to make sure it has the Google Play Services APK. If
|
* Check the device to make sure it has the Google Play Services APK. If
|
||||||
|
|
@ -14,11 +14,11 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.firebase
|
package io.element.android.libraries.push.providers.firebase
|
||||||
|
|
||||||
import io.element.android.libraries.matrix.api.core.asEventId
|
import io.element.android.libraries.matrix.api.core.asEventId
|
||||||
import io.element.android.libraries.matrix.api.core.asRoomId
|
import io.element.android.libraries.matrix.api.core.asRoomId
|
||||||
import io.element.android.libraries.push.impl.push.PushData
|
import io.element.android.libraries.push.providers.api.PushData
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In this case, the format is:
|
* In this case, the format is:
|
||||||
|
|
@ -14,27 +14,26 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.firebase
|
package io.element.android.libraries.push.providers.firebase
|
||||||
|
|
||||||
import com.google.firebase.messaging.FirebaseMessagingService
|
import com.google.firebase.messaging.FirebaseMessagingService
|
||||||
import com.google.firebase.messaging.RemoteMessage
|
import com.google.firebase.messaging.RemoteMessage
|
||||||
import io.element.android.libraries.architecture.bindings
|
import io.element.android.libraries.architecture.bindings
|
||||||
import io.element.android.libraries.core.log.logger.LoggerTag
|
import io.element.android.libraries.core.log.logger.LoggerTag
|
||||||
import io.element.android.libraries.push.impl.PushersManager
|
import io.element.android.libraries.push.providers.api.PushHandler
|
||||||
import io.element.android.libraries.push.impl.log.pushLoggerTag
|
|
||||||
import io.element.android.libraries.push.impl.push.PushHandler
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
private val loggerTag = LoggerTag("Firebase", pushLoggerTag)
|
private val loggerTag = LoggerTag("Firebase")
|
||||||
|
|
||||||
class VectorFirebaseMessagingService : FirebaseMessagingService() {
|
class VectorFirebaseMessagingService : FirebaseMessagingService() {
|
||||||
@Inject lateinit var pushersManager: PushersManager
|
@Inject lateinit var firebaseSetPusher: FirebaseSetPusher
|
||||||
@Inject lateinit var pushParser: FirebasePushParser
|
@Inject lateinit var pushParser: FirebasePushParser
|
||||||
@Inject lateinit var pushHandler: PushHandler
|
@Inject lateinit var pushHandler: PushHandler
|
||||||
|
@Inject lateinit var googleFcmHelper: GoogleFcmHelper
|
||||||
|
|
||||||
private val coroutineScope = CoroutineScope(SupervisorJob())
|
private val coroutineScope = CoroutineScope(SupervisorJob())
|
||||||
|
|
||||||
|
|
@ -45,8 +44,9 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
|
||||||
|
|
||||||
override fun onNewToken(token: String) {
|
override fun onNewToken(token: String) {
|
||||||
Timber.tag(loggerTag.value).d("New Firebase token")
|
Timber.tag(loggerTag.value).d("New Firebase token")
|
||||||
|
googleFcmHelper.storeFcmToken(token)
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
pushersManager.onNewFirebaseToken(token)
|
firebaseSetPusher.onNewFirebaseToken(token)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.firebase
|
package io.element.android.libraries.push.providers.firebase
|
||||||
|
|
||||||
import com.squareup.anvil.annotations.ContributesTo
|
import com.squareup.anvil.annotations.ContributesTo
|
||||||
import io.element.android.libraries.di.AppScope
|
import io.element.android.libraries.di.AppScope
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.push.providers.firebase.di
|
||||||
|
|
||||||
|
import com.squareup.anvil.annotations.ContributesTo
|
||||||
|
import dagger.Binds
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.multibindings.IntoSet
|
||||||
|
import io.element.android.libraries.di.AppScope
|
||||||
|
import io.element.android.libraries.push.providers.api.PushProvider
|
||||||
|
import io.element.android.libraries.push.providers.firebase.FirebasePushProvider
|
||||||
|
|
||||||
|
@Module
|
||||||
|
@ContributesTo(AppScope::class)
|
||||||
|
interface FirebaseModule {
|
||||||
|
@Binds
|
||||||
|
@IntoSet
|
||||||
|
fun bind(pushProvider: FirebasePushProvider): PushProvider
|
||||||
|
}
|
||||||
|
|
@ -14,12 +14,12 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.firebase
|
package io.element.android.libraries.push.providers.firebase
|
||||||
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import io.element.android.libraries.matrix.test.AN_EVENT_ID
|
import io.element.android.libraries.matrix.test.AN_EVENT_ID
|
||||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||||
import io.element.android.libraries.push.impl.push.PushData
|
import io.element.android.libraries.push.providers.api.PushData
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
class FirebasePushParserTest {
|
class FirebasePushParserTest {
|
||||||
49
libraries/pushproviders/unifiedpush/build.gradle.kts
Normal file
49
libraries/pushproviders/unifiedpush/build.gradle.kts
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id("io.element.android-library")
|
||||||
|
alias(libs.plugins.anvil)
|
||||||
|
kotlin("plugin.serialization") version "1.8.10"
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "io.element.android.libraries.push.providers.unifiedpush"
|
||||||
|
}
|
||||||
|
|
||||||
|
anvil {
|
||||||
|
generateDaggerFactories.set(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(libs.dagger)
|
||||||
|
implementation(projects.libraries.core)
|
||||||
|
implementation(projects.libraries.matrix.api)
|
||||||
|
|
||||||
|
implementation(projects.libraries.pushproviders.api)
|
||||||
|
implementation(projects.libraries.architecture)
|
||||||
|
implementation(projects.libraries.core)
|
||||||
|
implementation(projects.services.toolbox.api)
|
||||||
|
|
||||||
|
implementation(libs.serialization.json)
|
||||||
|
|
||||||
|
// UnifiedPush library
|
||||||
|
api(libs.unifiedpush)
|
||||||
|
|
||||||
|
testImplementation(libs.test.junit)
|
||||||
|
testImplementation(libs.test.truth)
|
||||||
|
testImplementation(projects.libraries.matrix.test)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ Copyright (c) 2023 New Vector Ltd
|
||||||
|
~
|
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ you may not use this file except in compliance with the License.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
<application>
|
||||||
|
<receiver
|
||||||
|
android:name=".VectorUnifiedPushMessagingReceiver"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="true"
|
||||||
|
tools:ignore="ExportedReceiver">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="org.unifiedpush.android.connector.MESSAGE" />
|
||||||
|
<action android:name="org.unifiedpush.android.connector.UNREGISTERED" />
|
||||||
|
<action android:name="org.unifiedpush.android.connector.NEW_ENDPOINT" />
|
||||||
|
<action android:name="org.unifiedpush.android.connector.REGISTRATION_FAILED" />
|
||||||
|
<action android:name="org.unifiedpush.android.connector.REGISTRATION_REFUSED" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
<receiver
|
||||||
|
android:name=".KeepInternalDistributor"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="false">
|
||||||
|
<intent-filter>
|
||||||
|
<!--
|
||||||
|
This action is checked to track installed and uninstalled distributors.
|
||||||
|
We declare it to keep the background sync as an internal
|
||||||
|
unifiedpush distributor.
|
||||||
|
-->
|
||||||
|
<action android:name="org.unifiedpush.android.distributor.REGISTER" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
</application>
|
||||||
|
</manifest>
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.unifiedpush
|
package io.element.android.libraries.push.providers.unifiedpush
|
||||||
|
|
||||||
import com.squareup.anvil.annotations.ContributesBinding
|
import com.squareup.anvil.annotations.ContributesBinding
|
||||||
import io.element.android.libraries.di.AppScope
|
import io.element.android.libraries.di.AppScope
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2022 New Vector Ltd
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.unifiedpush
|
package io.element.android.libraries.push.providers.unifiedpush
|
||||||
|
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
|
@ -14,11 +14,11 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.unifiedpush
|
package io.element.android.libraries.push.providers.unifiedpush
|
||||||
|
|
||||||
import io.element.android.libraries.matrix.api.core.asEventId
|
import io.element.android.libraries.matrix.api.core.asEventId
|
||||||
import io.element.android.libraries.matrix.api.core.asRoomId
|
import io.element.android.libraries.matrix.api.core.asRoomId
|
||||||
import io.element.android.libraries.push.impl.push.PushData
|
import io.element.android.libraries.push.providers.api.PushData
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
|
@ -14,11 +14,10 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.unifiedpush
|
package io.element.android.libraries.push.providers.unifiedpush
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import io.element.android.libraries.di.ApplicationContext
|
import io.element.android.libraries.di.ApplicationContext
|
||||||
import io.element.android.libraries.push.impl.config.PushConfig
|
|
||||||
import org.unifiedpush.android.connector.UnifiedPush
|
import org.unifiedpush.android.connector.UnifiedPush
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
@ -37,11 +36,6 @@ class RegisterUnifiedPushUseCase @Inject constructor(
|
||||||
return RegisterUnifiedPushResult.Success
|
return RegisterUnifiedPushResult.Success
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PushConfig.allowExternalUnifiedPushDistributors) {
|
|
||||||
saveAndRegisterApp(context.packageName)
|
|
||||||
return RegisterUnifiedPushResult.Success
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UnifiedPush.getDistributor(context).isNotEmpty()) {
|
if (UnifiedPush.getDistributor(context).isNotEmpty()) {
|
||||||
registerApp()
|
registerApp()
|
||||||
return RegisterUnifiedPushResult.Success
|
return RegisterUnifiedPushResult.Success
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.push.providers.unifiedpush
|
||||||
|
|
||||||
|
object UnifiedPushConfig {
|
||||||
|
/**
|
||||||
|
* It is the push gateway for UnifiedPush.
|
||||||
|
* Note: default_push_gateway_http_url should have path '/_matrix/push/v1/notify'
|
||||||
|
*/
|
||||||
|
const val default_push_gateway_http_url: String = "https://matrix.gateway.unifiedpush.org/_matrix/push/v1/notify"
|
||||||
|
|
||||||
|
const val internalName = "NOTIFICATION_METHOD_UNIFIEDPUSH"
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2022 New Vector Ltd
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -14,12 +14,10 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl
|
package io.element.android.libraries.push.providers.unifiedpush
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import io.element.android.libraries.androidutils.system.getApplicationLabel
|
|
||||||
import io.element.android.libraries.di.ApplicationContext
|
import io.element.android.libraries.di.ApplicationContext
|
||||||
import io.element.android.libraries.push.impl.config.PushConfig
|
|
||||||
import io.element.android.services.toolbox.api.strings.StringProvider
|
import io.element.android.services.toolbox.api.strings.StringProvider
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
@ -31,8 +29,6 @@ import javax.inject.Inject
|
||||||
class UnifiedPushHelper @Inject constructor(
|
class UnifiedPushHelper @Inject constructor(
|
||||||
@ApplicationContext private val context: Context,
|
@ApplicationContext private val context: Context,
|
||||||
private val unifiedPushStore: UnifiedPushStore,
|
private val unifiedPushStore: UnifiedPushStore,
|
||||||
// private val matrix: Matrix,
|
|
||||||
private val fcmHelper: FcmHelper,
|
|
||||||
private val stringProvider: StringProvider,
|
private val stringProvider: StringProvider,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
|
@ -95,11 +91,14 @@ class UnifiedPushHelper @Inject constructor(
|
||||||
// if we use the embedded distributor,
|
// if we use the embedded distributor,
|
||||||
// register app_id type upfcm on sygnal
|
// register app_id type upfcm on sygnal
|
||||||
// the pushkey if FCM key
|
// the pushkey if FCM key
|
||||||
|
/*
|
||||||
if (UnifiedPush.getDistributor(context) == context.packageName) {
|
if (UnifiedPush.getDistributor(context) == context.packageName) {
|
||||||
unifiedPushStore.storePushGateway(PushConfig.pusher_http_url)
|
unifiedPushStore.storePushGateway(PushConfig.pusher_http_url)
|
||||||
onDoneRunnable?.run()
|
onDoneRunnable?.run()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
/* TODO EAx UnifiedPush
|
/* TODO EAx UnifiedPush
|
||||||
// else, unifiedpush, and pushkey is an endpoint
|
// else, unifiedpush, and pushkey is an endpoint
|
||||||
val gateway = PushConfig.default_push_gateway_http_url
|
val gateway = PushConfig.default_push_gateway_http_url
|
||||||
|
|
@ -132,19 +131,25 @@ class UnifiedPushHelper @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getCurrentDistributorName(): String {
|
fun getCurrentDistributorName(): String {
|
||||||
|
TODO()
|
||||||
|
/*
|
||||||
return when {
|
return when {
|
||||||
isEmbeddedDistributor() -> stringProvider.getString(R.string.push_distributor_firebase_android)
|
isEmbeddedDistributor() -> stringProvider.getString(R.string.push_distributor_firebase_android)
|
||||||
isBackgroundSync() -> stringProvider.getString(R.string.push_distributor_background_sync_android)
|
isBackgroundSync() -> stringProvider.getString(R.string.push_distributor_background_sync_android)
|
||||||
else -> context.getApplicationLabel(UnifiedPush.getDistributor(context))
|
else -> context.getApplicationLabel(UnifiedPush.getDistributor(context))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isEmbeddedDistributor(): Boolean {
|
fun isEmbeddedDistributor(): Boolean {
|
||||||
return isInternalDistributor() && fcmHelper.isFirebaseAvailable()
|
TODO()
|
||||||
|
//return isInternalDistributor() && fcmHelper.isFirebaseAvailable()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isBackgroundSync(): Boolean {
|
fun isBackgroundSync(): Boolean {
|
||||||
return isInternalDistributor() && !fcmHelper.isFirebaseAvailable()
|
TODO()
|
||||||
|
//return isInternalDistributor() && !fcmHelper.isFirebaseAvailable()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isInternalDistributor(): Boolean {
|
private fun isInternalDistributor(): Boolean {
|
||||||
|
|
@ -168,12 +173,13 @@ class UnifiedPushHelper @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getEndpointOrToken(): String? {
|
fun getEndpointOrToken(): String? {
|
||||||
return if (isEmbeddedDistributor()) fcmHelper.getFcmToken()
|
// TODO
|
||||||
|
return if (isEmbeddedDistributor()) "" // fcmHelper.getFcmToken()
|
||||||
else unifiedPushStore.getEndpoint()
|
else unifiedPushStore.getEndpoint()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getPushGateway(): String? {
|
fun getPushGateway(): String? {
|
||||||
return if (isEmbeddedDistributor()) PushConfig.pusher_http_url
|
return if (isEmbeddedDistributor()) "" // PushConfig.pusher_http_url
|
||||||
else unifiedPushStore.getPushGateway()
|
else unifiedPushStore.getPushGateway()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2022 New Vector Ltd
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -14,10 +14,10 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.unifiedpush
|
package io.element.android.libraries.push.providers.unifiedpush
|
||||||
|
|
||||||
import io.element.android.libraries.core.data.tryOrNull
|
import io.element.android.libraries.core.data.tryOrNull
|
||||||
import io.element.android.libraries.push.impl.push.PushData
|
import io.element.android.libraries.push.providers.api.PushData
|
||||||
import kotlinx.serialization.decodeFromString
|
import kotlinx.serialization.decodeFromString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.push.providers.unifiedpush
|
||||||
|
|
||||||
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
|
import io.element.android.libraries.push.providers.api.PushProvider
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class UnifiedPushProvider @Inject constructor(): PushProvider {
|
||||||
|
override fun getDistributorNames(): List<String> {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun registerWith(matrixClient: MatrixClient, distributorName: String) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2022 New Vector Ltd
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl
|
package io.element.android.libraries.push.providers.unifiedpush
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
|
|
@ -14,19 +14,9 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.unifiedpush
|
package io.element.android.libraries.push.providers.unifiedpush
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import io.element.android.libraries.di.ApplicationContext
|
|
||||||
import io.element.android.libraries.push.api.model.BackgroundSyncMode
|
|
||||||
import io.element.android.libraries.push.api.store.PushDataStore
|
|
||||||
import io.element.android.libraries.push.impl.PushersManager
|
|
||||||
import io.element.android.libraries.push.impl.UnifiedPushHelper
|
|
||||||
import io.element.android.libraries.push.impl.UnifiedPushStore
|
|
||||||
import org.unifiedpush.android.connector.UnifiedPush
|
|
||||||
import timber.log.Timber
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
|
/*
|
||||||
class UnregisterUnifiedPushUseCase @Inject constructor(
|
class UnregisterUnifiedPushUseCase @Inject constructor(
|
||||||
@ApplicationContext private val context: Context,
|
@ApplicationContext private val context: Context,
|
||||||
private val pushDataStore: PushDataStore,
|
private val pushDataStore: PushDataStore,
|
||||||
|
|
@ -50,3 +40,4 @@ class UnregisterUnifiedPushUseCase @Inject constructor(
|
||||||
UnifiedPush.unregisterApp(context)
|
UnifiedPush.unregisterApp(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
@ -14,40 +14,29 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.unifiedpush
|
package io.element.android.libraries.push.providers.unifiedpush
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.widget.Toast
|
|
||||||
import io.element.android.libraries.architecture.bindings
|
import io.element.android.libraries.architecture.bindings
|
||||||
import io.element.android.libraries.core.log.logger.LoggerTag
|
import io.element.android.libraries.core.log.logger.LoggerTag
|
||||||
import io.element.android.libraries.push.api.model.BackgroundSyncMode
|
import io.element.android.libraries.push.providers.api.PushHandler
|
||||||
import io.element.android.libraries.push.api.store.PushDataStore
|
|
||||||
import io.element.android.libraries.push.impl.PushersManager
|
|
||||||
import io.element.android.libraries.push.impl.UnifiedPushHelper
|
|
||||||
import io.element.android.libraries.push.impl.UnifiedPushStore
|
|
||||||
import io.element.android.libraries.push.impl.log.pushLoggerTag
|
|
||||||
import io.element.android.libraries.push.impl.push.PushHandler
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
import org.unifiedpush.android.connector.MessagingReceiver
|
import org.unifiedpush.android.connector.MessagingReceiver
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
private val loggerTag = LoggerTag("Unified", pushLoggerTag)
|
private val loggerTag = LoggerTag("VectorUnifiedPushMessagingReceiver")
|
||||||
|
|
||||||
class VectorUnifiedPushMessagingReceiver : MessagingReceiver() {
|
class VectorUnifiedPushMessagingReceiver : MessagingReceiver() {
|
||||||
@Inject lateinit var pushersManager: PushersManager
|
|
||||||
@Inject lateinit var pushParser: UnifiedPushParser
|
@Inject lateinit var pushParser: UnifiedPushParser
|
||||||
|
// @Inject lateinit var pushDataStore: PushDataStore
|
||||||
//@Inject lateinit var activeSessionHolder: ActiveSessionHolder
|
|
||||||
@Inject lateinit var pushDataStore: PushDataStore
|
|
||||||
@Inject lateinit var pushHandler: PushHandler
|
@Inject lateinit var pushHandler: PushHandler
|
||||||
@Inject lateinit var guardServiceStarter: GuardServiceStarter
|
@Inject lateinit var guardServiceStarter: GuardServiceStarter
|
||||||
@Inject lateinit var unifiedPushStore: UnifiedPushStore
|
// @Inject lateinit var unifiedPushStore: UnifiedPushStore
|
||||||
@Inject lateinit var unifiedPushHelper: UnifiedPushHelper
|
// @Inject lateinit var unifiedPushHelper: UnifiedPushHelper
|
||||||
|
|
||||||
private val coroutineScope = CoroutineScope(SupervisorJob())
|
private val coroutineScope = CoroutineScope(SupervisorJob())
|
||||||
|
|
||||||
|
|
@ -77,6 +66,8 @@ class VectorUnifiedPushMessagingReceiver : MessagingReceiver() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNewEndpoint(context: Context, endpoint: String, instance: String) {
|
override fun onNewEndpoint(context: Context, endpoint: String, instance: String) {
|
||||||
|
TODO()
|
||||||
|
/*
|
||||||
Timber.tag(loggerTag.value).i("onNewEndpoint: adding $endpoint")
|
Timber.tag(loggerTag.value).i("onNewEndpoint: adding $endpoint")
|
||||||
if (pushDataStore.areNotificationEnabledForDevice() /* TODO EAx && activeSessionHolder.hasActiveSession() */) {
|
if (pushDataStore.areNotificationEnabledForDevice() /* TODO EAx && activeSessionHolder.hasActiveSession() */) {
|
||||||
// If the endpoint has changed
|
// If the endpoint has changed
|
||||||
|
|
@ -99,16 +90,22 @@ class VectorUnifiedPushMessagingReceiver : MessagingReceiver() {
|
||||||
val mode = BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_DISABLED
|
val mode = BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_DISABLED
|
||||||
pushDataStore.setFdroidSyncBackgroundMode(mode)
|
pushDataStore.setFdroidSyncBackgroundMode(mode)
|
||||||
guardServiceStarter.stop()
|
guardServiceStarter.stop()
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onRegistrationFailed(context: Context, instance: String) {
|
override fun onRegistrationFailed(context: Context, instance: String) {
|
||||||
|
TODO()
|
||||||
|
/*
|
||||||
Toast.makeText(context, "Push service registration failed", Toast.LENGTH_SHORT).show()
|
Toast.makeText(context, "Push service registration failed", Toast.LENGTH_SHORT).show()
|
||||||
val mode = BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_FOR_REALTIME
|
val mode = BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_FOR_REALTIME
|
||||||
pushDataStore.setFdroidSyncBackgroundMode(mode)
|
pushDataStore.setFdroidSyncBackgroundMode(mode)
|
||||||
guardServiceStarter.start()
|
guardServiceStarter.start()
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onUnregistered(context: Context, instance: String) {
|
override fun onUnregistered(context: Context, instance: String) {
|
||||||
|
TODO()
|
||||||
|
/*
|
||||||
Timber.tag(loggerTag.value).d("Unifiedpush: Unregistered")
|
Timber.tag(loggerTag.value).d("Unifiedpush: Unregistered")
|
||||||
val mode = BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_FOR_REALTIME
|
val mode = BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_FOR_REALTIME
|
||||||
pushDataStore.setFdroidSyncBackgroundMode(mode)
|
pushDataStore.setFdroidSyncBackgroundMode(mode)
|
||||||
|
|
@ -120,5 +117,6 @@ class VectorUnifiedPushMessagingReceiver : MessagingReceiver() {
|
||||||
Timber.tag(loggerTag.value).d("Probably unregistering a non existing pusher")
|
Timber.tag(loggerTag.value).d("Probably unregistering a non existing pusher")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.unifiedpush
|
package io.element.android.libraries.push.providers.unifiedpush
|
||||||
|
|
||||||
import com.squareup.anvil.annotations.ContributesTo
|
import com.squareup.anvil.annotations.ContributesTo
|
||||||
import io.element.android.libraries.di.AppScope
|
import io.element.android.libraries.di.AppScope
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.push.providers.unifiedpush.di
|
||||||
|
|
||||||
|
import com.squareup.anvil.annotations.ContributesTo
|
||||||
|
import dagger.Binds
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.multibindings.IntoSet
|
||||||
|
import io.element.android.libraries.di.AppScope
|
||||||
|
import io.element.android.libraries.push.providers.api.PushProvider
|
||||||
|
import io.element.android.libraries.push.providers.unifiedpush.UnifiedPushProvider
|
||||||
|
|
||||||
|
@Module
|
||||||
|
@ContributesTo(AppScope::class)
|
||||||
|
interface UnifiedPushModule {
|
||||||
|
@Binds
|
||||||
|
@IntoSet
|
||||||
|
fun bind(pushProvider: UnifiedPushProvider): PushProvider
|
||||||
|
}
|
||||||
|
|
@ -14,12 +14,12 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.unifiedpush
|
package io.element.android.libraries.push.providers.unifiedpush
|
||||||
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import io.element.android.libraries.matrix.test.AN_EVENT_ID
|
import io.element.android.libraries.matrix.test.AN_EVENT_ID
|
||||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||||
import io.element.android.libraries.push.impl.push.PushData
|
import io.element.android.libraries.push.providers.api.PushData
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
class UnifiedPushParserTest {
|
class UnifiedPushParserTest {
|
||||||
26
libraries/pushstore/api/build.gradle.kts
Normal file
26
libraries/pushstore/api/build.gradle.kts
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id("io.element.android-library")
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "io.element.android.libraries.pushstore.api"
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
}
|
||||||
|
|
@ -14,10 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.userpushstore
|
package io.element.android.libraries.pushstore.api
|
||||||
|
|
||||||
const val NOTIFICATION_METHOD_FIREBASE = "NOTIFICATION_METHOD_FIREBASE"
|
|
||||||
const val NOTIFICATION_METHOD_UNIFIEDPUSH = "NOTIFICATION_METHOD_UNIFIEDPUSH"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store data related to push about a user.
|
* Store data related to push about a user.
|
||||||
|
|
@ -26,7 +23,7 @@ interface UserPushStore {
|
||||||
/**
|
/**
|
||||||
* [NOTIFICATION_METHOD_FIREBASE] or [NOTIFICATION_METHOD_UNIFIEDPUSH].
|
* [NOTIFICATION_METHOD_FIREBASE] or [NOTIFICATION_METHOD_UNIFIEDPUSH].
|
||||||
*/
|
*/
|
||||||
suspend fun getNotificationMethod(): String
|
suspend fun getNotificationMethod(): String?
|
||||||
|
|
||||||
suspend fun setNotificationMethod(value: String)
|
suspend fun setNotificationMethod(value: String)
|
||||||
|
|
||||||
|
|
@ -36,5 +33,3 @@ interface UserPushStore {
|
||||||
|
|
||||||
suspend fun reset()
|
suspend fun reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun UserPushStore.isFirebase(): Boolean = getNotificationMethod() == NOTIFICATION_METHOD_FIREBASE
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.pushstore.api
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store data related to push about a user.
|
||||||
|
*/
|
||||||
|
interface UserPushStoreFactory {
|
||||||
|
fun create(userId: String): UserPushStore
|
||||||
|
}
|
||||||
38
libraries/pushstore/impl/build.gradle.kts
Normal file
38
libraries/pushstore/impl/build.gradle.kts
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id("io.element.android-library")
|
||||||
|
alias(libs.plugins.anvil)
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "io.element.android.libraries.push.pushstore.impl"
|
||||||
|
}
|
||||||
|
|
||||||
|
anvil {
|
||||||
|
generateDaggerFactories.set(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(libs.dagger)
|
||||||
|
implementation(projects.libraries.architecture)
|
||||||
|
implementation(projects.libraries.core)
|
||||||
|
implementation(projects.libraries.pushstore.api)
|
||||||
|
implementation(projects.libraries.sessionStorage.api)
|
||||||
|
implementation(libs.androidx.corektx)
|
||||||
|
implementation(libs.androidx.datastore.preferences)
|
||||||
|
}
|
||||||
|
|
@ -14,28 +14,32 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.userpushstore
|
package io.element.android.libraries.pushstore.impl
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import com.squareup.anvil.annotations.ContributesBinding
|
||||||
import io.element.android.libraries.di.AppScope
|
import io.element.android.libraries.di.AppScope
|
||||||
import io.element.android.libraries.di.ApplicationContext
|
import io.element.android.libraries.di.ApplicationContext
|
||||||
import io.element.android.libraries.di.SingleIn
|
import io.element.android.libraries.di.SingleIn
|
||||||
|
import io.element.android.libraries.pushstore.api.UserPushStore
|
||||||
|
import io.element.android.libraries.pushstore.api.UserPushStoreFactory
|
||||||
import io.element.android.libraries.sessionstorage.api.observer.SessionListener
|
import io.element.android.libraries.sessionstorage.api.observer.SessionListener
|
||||||
import io.element.android.libraries.sessionstorage.api.observer.SessionObserver
|
import io.element.android.libraries.sessionstorage.api.observer.SessionObserver
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@SingleIn(AppScope::class)
|
@SingleIn(AppScope::class)
|
||||||
class UserPushStoreFactory @Inject constructor(
|
@ContributesBinding(AppScope::class, boundType = UserPushStoreFactory::class)
|
||||||
|
class DefaultUserPushStoreFactory @Inject constructor(
|
||||||
@ApplicationContext private val context: Context,
|
@ApplicationContext private val context: Context,
|
||||||
private val sessionObserver: SessionObserver,
|
private val sessionObserver: SessionObserver,
|
||||||
) : SessionListener {
|
) : UserPushStoreFactory, SessionListener {
|
||||||
init {
|
init {
|
||||||
observeSessions()
|
observeSessions()
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can have only one class accessing a single data store, so keep a cache of them.
|
// We can have only one class accessing a single data store, so keep a cache of them.
|
||||||
private val cache = mutableMapOf<String, UserPushStore>()
|
private val cache = mutableMapOf<String, UserPushStore>()
|
||||||
fun create(userId: String): UserPushStore {
|
override fun create(userId: String): UserPushStore {
|
||||||
return cache.getOrPut(userId) {
|
return cache.getOrPut(userId) {
|
||||||
UserPushStoreDataStore(
|
UserPushStoreDataStore(
|
||||||
context = context,
|
context = context,
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.userpushstore
|
package io.element.android.libraries.pushstore.impl
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.datastore.core.DataStore
|
import androidx.datastore.core.DataStore
|
||||||
|
|
@ -22,6 +22,7 @@ import androidx.datastore.preferences.core.Preferences
|
||||||
import androidx.datastore.preferences.core.edit
|
import androidx.datastore.preferences.core.edit
|
||||||
import androidx.datastore.preferences.core.stringPreferencesKey
|
import androidx.datastore.preferences.core.stringPreferencesKey
|
||||||
import androidx.datastore.preferences.preferencesDataStore
|
import androidx.datastore.preferences.preferencesDataStore
|
||||||
|
import io.element.android.libraries.pushstore.api.UserPushStore
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -35,8 +36,8 @@ class UserPushStoreDataStore(
|
||||||
private val notificationMethod = stringPreferencesKey("notificationMethod")
|
private val notificationMethod = stringPreferencesKey("notificationMethod")
|
||||||
private val currentPushKey = stringPreferencesKey("currentPushKey")
|
private val currentPushKey = stringPreferencesKey("currentPushKey")
|
||||||
|
|
||||||
override suspend fun getNotificationMethod(): String {
|
override suspend fun getNotificationMethod(): String? {
|
||||||
return context.dataStore.data.first()[notificationMethod] ?: NOTIFICATION_METHOD_FIREBASE
|
return context.dataStore.data.first()[notificationMethod]
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun setNotificationMethod(value: String) {
|
override suspend fun setNotificationMethod(value: String) {
|
||||||
|
|
@ -75,6 +75,12 @@ fun DependencyHandlerScope.allLibrariesImpl() {
|
||||||
implementation(project(":libraries:core"))
|
implementation(project(":libraries:core"))
|
||||||
implementation(project(":libraries:permissions:impl"))
|
implementation(project(":libraries:permissions:impl"))
|
||||||
implementation(project(":libraries:push:impl"))
|
implementation(project(":libraries:push:impl"))
|
||||||
|
implementation(project(":libraries:push:impl"))
|
||||||
|
// Comment to not include firebase in the project
|
||||||
|
implementation(project(":libraries:pushproviders:firebase"))
|
||||||
|
// Comment to not include unified push in the project
|
||||||
|
// implementation(project(":libraries:pushproviders:unifiedpush"))
|
||||||
|
implementation(project(":libraries:pushstore:impl"))
|
||||||
implementation(project(":libraries:architecture"))
|
implementation(project(":libraries:architecture"))
|
||||||
implementation(project(":libraries:dateformatter:impl"))
|
implementation(project(":libraries:dateformatter:impl"))
|
||||||
implementation(project(":libraries:di"))
|
implementation(project(":libraries:di"))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue