Browse Source

Cleanup + Add per user store.

test/jme/compound-poc
Benoit Marty 1 year ago
parent
commit
6ecbe1f856
  1. 2
      appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInPresenter.kt
  2. 2
      libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/PushService.kt
  3. 6
      libraries/push/impl/src/main/AndroidManifest.xml
  4. 49
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/AutoAcceptInvites.kt
  5. 15
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/DefaultPushService.kt
  6. 58
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/PushersManager.kt
  7. 1
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/UnifiedPushHelper.kt
  8. 11
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/firebase/EnsureFcmTokenIsRetrievedUseCase.kt
  9. 33
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/firebase/FirebasePushParser.kt
  10. 9
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/firebase/PushDataFirebase.kt
  11. 40
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/firebase/VectorFirebaseMessagingService.kt
  12. 5
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/firebase/VectorFirebaseMessagingServiceBindings.kt
  13. 21
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/log/LoggerTag.kt
  14. 10
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventProcessor.kt
  15. 57
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/parser/PushParser.kt
  16. 2
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/PushData.kt
  17. 17
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/PushHandler.kt
  18. 4
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/unifiedpush/GuardServiceStarter.kt
  19. 2
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/unifiedpush/KeepInternalDistributor.kt
  20. 5
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/unifiedpush/PushDataUnifiedPush.kt
  21. 4
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/unifiedpush/RegisterUnifiedPushUseCase.kt
  22. 29
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/unifiedpush/UnifiedPushParser.kt
  23. 7
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/unifiedpush/UnregisterUnifiedPushUseCase.kt
  24. 22
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/unifiedpush/VectorUnifiedPushMessagingReceiver.kt
  25. 3
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/unifiedpush/VectorUnifiedPushMessagingReceiverBindings.kt
  26. 40
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/userpushstore/UserPushStore.kt
  27. 63
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/userpushstore/UserPushStoreDataStore.kt
  28. 32
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/userpushstore/UserPushStoreFactory.kt
  29. 4
      libraries/session-storage/api/src/main/kotlin/io/element/android/libraries/sessionstorage/api/SessionStore.kt

2
appnav/src/main/kotlin/io/element/android/appnav/loggedin/LoggedInPresenter.kt

@ -46,7 +46,7 @@ class LoggedInPresenter @Inject constructor( @@ -46,7 +46,7 @@ class LoggedInPresenter @Inject constructor(
override fun present(): LoggedInState {
LaunchedEffect(Unit) {
// Ensure pusher is registered
pushService.registerPusher(matrixClient)
pushService.registerFirebasePusher(matrixClient)
}
val permissionsState = postNotificationPermissionsPresenter.present()

2
libraries/push/api/src/main/kotlin/io/element/android/libraries/push/api/PushService.kt

@ -28,7 +28,7 @@ interface PushService { @@ -28,7 +28,7 @@ interface PushService {
fun notificationStyleChanged()
// Ensure pusher is registered
suspend fun registerPusher(matrixClient: MatrixClient)
suspend fun registerFirebasePusher(matrixClient: MatrixClient)
suspend fun testPush()
}

6
libraries/push/impl/src/main/AndroidManifest.xml

@ -26,7 +26,7 @@ @@ -26,7 +26,7 @@
android:value="true" />
<service
android:name="VectorFirebaseMessagingService"
android:name=".firebase.VectorFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
@ -35,7 +35,7 @@ @@ -35,7 +35,7 @@
<!-- UnifiedPush -->
<receiver
android:name="VectorUnifiedPushMessagingReceiver"
android:name=".unifiedpush.VectorUnifiedPushMessagingReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
@ -48,7 +48,7 @@ @@ -48,7 +48,7 @@
</receiver>
<receiver
android:name="KeepInternalDistributor"
android:name=".unifiedpush.KeepInternalDistributor"
android:enabled="true"
android:exported="false">
<intent-filter>

49
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/AutoAcceptInvites.kt

@ -1,49 +0,0 @@ @@ -1,49 +0,0 @@
/*
* Copyright (c) 2021 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
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.di.AppScope
import javax.inject.Inject
// TODO Move away
/**
* This interface defines 2 flags so you can handle auto accept invites.
* At the moment we only have [CompileTimeAutoAcceptInvites] implementation.
*/
interface AutoAcceptInvites {
/**
* Enable auto-accept invites. It means, as soon as you got an invite from the sync, it will try to join it.
*/
val isEnabled: Boolean
/**
* Hide invites from the UI (from notifications, notification count and room list). By default invites are hidden when [isEnabled] is true
*/
val hideInvites: Boolean
get() = isEnabled
}
fun AutoAcceptInvites.showInvites() = !hideInvites
/**
* Simple compile time implementation of AutoAcceptInvites flags.
*/
@ContributesBinding(AppScope::class)
class CompileTimeAutoAcceptInvites @Inject constructor() : AutoAcceptInvites {
override val isEnabled = false
}

15
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/DefaultPushService.kt

@ -20,13 +20,17 @@ import com.squareup.anvil.annotations.ContributesBinding @@ -20,13 +20,17 @@ import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.matrix.api.MatrixClient
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 timber.log.Timber
import javax.inject.Inject
@ContributesBinding(AppScope::class)
class DefaultPushService @Inject constructor(
private val notificationDrawerManager: NotificationDrawerManager,
private val pusherManager: PushersManager,
private val pushersManager: PushersManager,
private val fcmHelper: FcmHelper,
) : PushService {
override fun setCurrentRoom(roomId: String?) {
notificationDrawerManager.setCurrentRoom(roomId)
@ -40,11 +44,14 @@ class DefaultPushService @Inject constructor( @@ -40,11 +44,14 @@ class DefaultPushService @Inject constructor(
notificationDrawerManager.notificationStyleChanged()
}
override suspend fun registerPusher(matrixClient: MatrixClient) {
pusherManager.registerPusher(matrixClient)
override suspend fun registerFirebasePusher(matrixClient: MatrixClient) {
val pushKey = fcmHelper.getFcmToken() ?: return Unit.also {
Timber.tag(pushLoggerTag.value).w("Unable to register pusher, Firebase token is not known.")
}
pushersManager.registerPusher(matrixClient, pushKey, PushConfig.pusher_http_url)
}
override suspend fun testPush() {
pusherManager.testPush()
pushersManager.testPush()
}
}

58
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/PushersManager.kt

@ -23,8 +23,12 @@ import io.element.android.libraries.matrix.api.pusher.SetHttpPusherData @@ -23,8 +23,12 @@ import io.element.android.libraries.matrix.api.pusher.SetHttpPusherData
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.pushgateway.PushGatewayNotifyRequest
import io.element.android.libraries.push.impl.userpushstore.UserPushStoreFactory
import io.element.android.libraries.push.impl.userpushstore.isFirebase
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 timber.log.Timber
import javax.inject.Inject
internal const val DEFAULT_PUSHER_FILE_TAG = "mobile"
@ -40,6 +44,7 @@ class PushersManager @Inject constructor( @@ -40,6 +44,7 @@ class PushersManager @Inject constructor(
private val pushClientSecret: PushClientSecret,
private val sessionStore: SessionStore,
private val matrixAuthenticationService: MatrixAuthenticationService,
private val userPushStoreFactory: UserPushStoreFactory,
private val fcmHelper: FcmHelper,
) {
suspend fun testPush() {
@ -54,29 +59,54 @@ class PushersManager @Inject constructor( @@ -54,29 +59,54 @@ class PushersManager @Inject constructor(
}
suspend fun enqueueRegisterPusherWithFcmKey(pushKey: String) {
return enqueueRegisterPusher(pushKey, PushConfig.pusher_http_url)
// return onNewFirebaseToken(pushKey, PushConfig.pusher_http_url)
TODO()
}
// TODO Rename
suspend fun enqueueRegisterPusher(
suspend fun onNewUnifiedPushEndpoint(
pushKey: String,
gateway: String
) {
TODO()
}
suspend fun onNewFirebaseToken(firebaseToken: String) {
fcmHelper.storeFcmToken(firebaseToken)
// Register the pusher for all the sessions
sessionStore.getAllSessions().forEach { sessionData ->
val client = matrixAuthenticationService.restoreSession(SessionId(sessionData.userId)).getOrNull()
client ?: return@forEach
client.pushersService().setHttpPusher(createHttpPusher(pushKey, gateway, sessionData.userId))
// TODO EAx Close sessions
sessionStore.getAllSessions().toUserList().forEach { userId ->
val userDataStore = userPushStoreFactory.create(userId)
if (userDataStore.isFirebase()) {
val client = matrixAuthenticationService.restoreSession(SessionId(userId)).getOrNull()
client ?: return@forEach
registerPusher(client, firebaseToken, PushConfig.pusher_http_url)
// TODO EAx Close sessions
} else {
Timber.d("This session is not using Firebase pusher")
}
}
}
suspend fun registerPusher(matrixClient: MatrixClient) {
val pushKey = fcmHelper.getFcmToken() ?: return
// Register the pusher for the session
matrixClient.pushersService().setHttpPusher(
createHttpPusher(pushKey, PushConfig.pusher_http_url, matrixClient.sessionId.value)
)
/**
* Register a pusher to the server if not done yet.
*/
suspend fun registerPusher(matrixClient: MatrixClient, pushKey: String, gateway: String) {
val userDataStore = userPushStoreFactory.create(matrixClient.sessionId.value)
if (userDataStore.getCurrentRegisteredPushKey() == pushKey) {
Timber.d("Unnecessary to register again the same pusher")
} else {
// Register the pusher to the server
matrixClient.pushersService().setHttpPusher(
createHttpPusher(pushKey, gateway, matrixClient.sessionId.value)
).fold(
{
userDataStore.setCurrentRegisteredPushKey(pushKey)
},
{ throwable ->
Timber.e(throwable, "Unable to register the pusher")
}
)
}
}
private suspend fun createHttpPusher(

1
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/UnifiedPushHelper.kt

@ -27,7 +27,6 @@ import org.unifiedpush.android.connector.UnifiedPush @@ -27,7 +27,6 @@ import org.unifiedpush.android.connector.UnifiedPush
import timber.log.Timber
import java.net.URL
import javax.inject.Inject
import io.element.android.libraries.ui.strings.R as StringR
class UnifiedPushHelper @Inject constructor(
@ApplicationContext private val context: Context,

11
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/EnsureFcmTokenIsRetrievedUseCase.kt → libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/firebase/EnsureFcmTokenIsRetrievedUseCase.kt

@ -1,5 +1,5 @@ @@ -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");
* you may not use this file except in compliance with the License.
@ -14,13 +14,16 @@ @@ -14,13 +14,16 @@
* limitations under the License.
*/
package io.element.android.libraries.push.impl
package io.element.android.libraries.push.impl.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
class EnsureFcmTokenIsRetrievedUseCase @Inject constructor(
private val unifiedPushHelper: UnifiedPushHelper,
private val fcmHelper: FcmHelper,
private val unifiedPushHelper: UnifiedPushHelper,
private val fcmHelper: FcmHelper,
// private val activeSessionHolder: ActiveSessionHolder,
) {

33
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/firebase/FirebasePushParser.kt

@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
/*
* 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.firebase
import io.element.android.libraries.core.data.tryOrNull
import io.element.android.libraries.push.impl.push.PushData
import javax.inject.Inject
class FirebasePushParser @Inject constructor() {
fun parse(message: Map<String, String?>): PushData {
val pushDataFirebase = PushDataFirebase(
eventId = message["event_id"],
roomId = message["room_id"],
unread = message["unread"]?.let { tryOrNull { Integer.parseInt(it) } },
clientSecret = message["cs"],
)
return pushDataFirebase.toPushData()
}
}

9
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/model/PushDataFcm.kt → libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/firebase/PushDataFirebase.kt

@ -1,5 +1,5 @@ @@ -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");
* you may not use this file except in compliance with the License.
@ -14,9 +14,10 @@ @@ -14,9 +14,10 @@
* limitations under the License.
*/
package io.element.android.libraries.push.impl.model
package io.element.android.libraries.push.impl.firebase
import io.element.android.libraries.matrix.api.core.MatrixPatterns
import io.element.android.libraries.push.impl.push.PushData
/**
* In this case, the format is:
@ -31,14 +32,14 @@ import io.element.android.libraries.matrix.api.core.MatrixPatterns @@ -31,14 +32,14 @@ import io.element.android.libraries.matrix.api.core.MatrixPatterns
* </pre>
* .
*/
data class PushDataFcm(
data class PushDataFirebase(
val eventId: String?,
val roomId: String?,
var unread: Int?,
val clientSecret: String?
)
fun PushDataFcm.toPushData() = PushData(
fun PushDataFirebase.toPushData() = PushData(
eventId = eventId?.takeIf { MatrixPatterns.isEventId(it) },
roomId = roomId?.takeIf { MatrixPatterns.isRoomId(it) },
unread = unread,

40
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/VectorFirebaseMessagingService.kt → libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/firebase/VectorFirebaseMessagingService.kt

@ -14,58 +14,50 @@ @@ -14,58 +14,50 @@
* limitations under the License.
*/
package io.element.android.libraries.push.impl
package io.element.android.libraries.push.impl.firebase
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import io.element.android.libraries.architecture.bindings
import io.element.android.libraries.core.log.logger.LoggerTag
import io.element.android.libraries.push.api.store.PushDataStore
import io.element.android.libraries.push.impl.config.PushConfig
import io.element.android.libraries.push.impl.di.FirebaseMessagingServiceBindings
import io.element.android.libraries.push.impl.parser.PushParser
import io.element.android.libraries.push.impl.PushersManager
import io.element.android.libraries.push.impl.push.PushHandler
import io.element.android.libraries.push.impl.log.pushLoggerTag
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
private val loggerTag = LoggerTag("Push", LoggerTag.SYNC)
private val loggerTag = LoggerTag("Firebase", pushLoggerTag)
class VectorFirebaseMessagingService : FirebaseMessagingService() {
@Inject lateinit var fcmHelper: FcmHelper
@Inject lateinit var pushDataStore: PushDataStore
// @Inject lateinit var activeSessionHolder: ActiveSessionHolder
@Inject lateinit var pushersManager: PushersManager
@Inject lateinit var pushParser: PushParser
@Inject lateinit var vectorPushHandler: VectorPushHandler
@Inject lateinit var unifiedPushHelper: UnifiedPushHelper
@Inject
lateinit var pushParser: FirebasePushParser
@Inject
lateinit var pushHandler: PushHandler
private val coroutineScope = CoroutineScope(SupervisorJob())
override fun onCreate() {
super.onCreate()
applicationContext.bindings<FirebaseMessagingServiceBindings>().inject(this)
applicationContext.bindings<VectorFirebaseMessagingServiceBindings>().inject(this)
}
override fun onNewToken(token: String) {
Timber.tag(loggerTag.value).d("New Firebase token")
fcmHelper.storeFcmToken(token)
if (
// pushDataStore.areNotificationEnabledForDevice() &&
// TODO EAx activeSessionHolder.hasActiveSession() &&
unifiedPushHelper.isEmbeddedDistributor()
) {
coroutineScope.launch {
pushersManager.enqueueRegisterPusher(token, PushConfig.pusher_http_url)
}
coroutineScope.launch {
pushersManager.onNewFirebaseToken(token)
}
}
override fun onMessageReceived(message: RemoteMessage) {
Timber.tag(loggerTag.value).d("New Firebase message")
pushParser.parsePushDataFcm(message.data).let {
vectorPushHandler.handle(it)
pushParser.parse(message.data).let {
pushHandler.handle(it)
}
}
}

5
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/di/FirebaseMessagingServiceBindings.kt → libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/firebase/VectorFirebaseMessagingServiceBindings.kt

@ -14,13 +14,12 @@ @@ -14,13 +14,12 @@
* limitations under the License.
*/
package io.element.android.libraries.push.impl.di
package io.element.android.libraries.push.impl.firebase
import com.squareup.anvil.annotations.ContributesTo
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.push.impl.VectorFirebaseMessagingService
@ContributesTo(AppScope::class)
interface FirebaseMessagingServiceBindings {
interface VectorFirebaseMessagingServiceBindings {
fun inject(service: VectorFirebaseMessagingService)
}

21
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/log/LoggerTag.kt

@ -0,0 +1,21 @@ @@ -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.impl.log
import io.element.android.libraries.core.log.logger.LoggerTag
internal val pushLoggerTag = LoggerTag("Push")

10
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventProcessor.kt

@ -16,12 +16,7 @@ @@ -16,12 +16,7 @@
package io.element.android.libraries.push.impl.notifications
import io.element.android.libraries.push.impl.AutoAcceptInvites
import io.element.android.libraries.push.impl.notifications.model.InviteNotifiableEvent
import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent
import io.element.android.libraries.push.impl.notifications.model.NotifiableMessageEvent
import io.element.android.libraries.push.impl.notifications.model.SimpleNotifiableEvent
import io.element.android.libraries.push.impl.notifications.model.shouldIgnoreMessageEventInRoom
import io.element.android.libraries.push.impl.notifications.model.*
import timber.log.Timber
import javax.inject.Inject
@ -29,13 +24,12 @@ private typealias ProcessedEvents = List<ProcessedEvent<NotifiableEvent>> @@ -29,13 +24,12 @@ private typealias ProcessedEvents = List<ProcessedEvent<NotifiableEvent>>
class NotifiableEventProcessor @Inject constructor(
private val outdatedDetector: OutdatedEventDetector,
private val autoAcceptInvites: AutoAcceptInvites
) {
fun process(queuedEvents: List<NotifiableEvent>, currentRoomId: String?, currentThreadId: String?, renderedEvents: ProcessedEvents): ProcessedEvents {
val processedEvents = queuedEvents.map {
val type = when (it) {
is InviteNotifiableEvent -> if (autoAcceptInvites.hideInvites) ProcessedEvent.Type.REMOVE else ProcessedEvent.Type.KEEP
is InviteNotifiableEvent -> ProcessedEvent.Type.KEEP
is NotifiableMessageEvent -> when {
it.shouldIgnoreMessageEventInRoom(currentRoomId, currentThreadId) -> {
ProcessedEvent.Type.REMOVE

57
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/parser/PushParser.kt

@ -1,57 +0,0 @@ @@ -1,57 +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.parser
import io.element.android.libraries.core.data.tryOrNull
import io.element.android.libraries.push.impl.model.PushData
import io.element.android.libraries.push.impl.model.PushDataFcm
import io.element.android.libraries.push.impl.model.PushDataUnifiedPush
import io.element.android.libraries.push.impl.model.toPushData
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import javax.inject.Inject
/**
* Parse the received data from Push. Json format are different depending on the source.
*
* Notifications received by FCM are formatted by the matrix gateway [1]. The data send to FCM is the content
* of the "notification" attribute of the json sent to the gateway [2][3].
* On the other side, with UnifiedPush, the content of the message received is the content posted to the push
* gateway endpoint [3].
*
* *Note*: If we want to get the same content with FCM and unifiedpush, we can do a new sygnal pusher [4].
*
* [1] https://github.com/matrix-org/sygnal/blob/main/sygnal/gcmpushkin.py
* [2] https://github.com/matrix-org/sygnal/blob/main/sygnal/gcmpushkin.py#L366
* [3] https://spec.matrix.org/latest/push-gateway-api/
* [4] https://github.com/p1gp1g/sygnal/blob/unifiedpush/sygnal/upfcmpushkin.py (Not tested for a while)
*/
class PushParser @Inject constructor() {
fun parsePushDataUnifiedPush(message: ByteArray): PushData? {
return tryOrNull { Json.decodeFromString<PushDataUnifiedPush>(String(message)) }?.toPushData()
}
fun parsePushDataFcm(message: Map<String, String?>): PushData {
val pushDataFcm = PushDataFcm(
eventId = message["event_id"],
roomId = message["room_id"],
unread = message["unread"]?.let { tryOrNull { Integer.parseInt(it) } },
clientSecret = message["cs"],
)
return pushDataFcm.toPushData()
}
}

2
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/model/PushData.kt → libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/PushData.kt

@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.element.android.libraries.push.impl.model
package io.element.android.libraries.push.impl.push
/**
* Represent parsed data that the app has received from a Push content.

17
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/VectorPushHandler.kt → libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/PushHandler.kt

@ -1,5 +1,5 @@ @@ -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");
* you may not use this file except in compliance with the License.
@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.element.android.libraries.push.impl
package io.element.android.libraries.push.impl.push
import android.content.Context
import android.content.Intent
@ -30,19 +30,24 @@ import io.element.android.libraries.di.ApplicationContext @@ -30,19 +30,24 @@ import io.element.android.libraries.di.ApplicationContext
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.push.api.store.PushDataStore
import io.element.android.libraries.push.impl.PushersManager
import io.element.android.libraries.push.impl.clientsecret.PushClientSecret
import io.element.android.libraries.push.impl.model.PushData
import io.element.android.libraries.push.impl.notifications.NotifiableEventResolver
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.log.pushLoggerTag
import io.element.android.libraries.push.impl.store.DefaultPushDataStore
import kotlinx.coroutines.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import timber.log.Timber
import javax.inject.Inject
private val loggerTag = LoggerTag("Push", LoggerTag.SYNC)
private val loggerTag = LoggerTag("Push", pushLoggerTag)
class VectorPushHandler @Inject constructor(
class PushHandler @Inject constructor(
private val notificationDrawerManager: NotificationDrawerManager,
private val notifiableEventResolver: NotifiableEventResolver,
// private val activeSessionHolder: ActiveSessionHolder,

4
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/GuardServiceStarter.kt → libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/unifiedpush/GuardServiceStarter.kt

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 New Vector Ltd
* 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.
@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.element.android.libraries.push.impl
package io.element.android.libraries.push.impl.unifiedpush
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.di.AppScope

2
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/KeepInternalDistributor.kt → libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/unifiedpush/KeepInternalDistributor.kt

@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.element.android.libraries.push.impl
package io.element.android.libraries.push.impl.unifiedpush
import android.content.BroadcastReceiver
import android.content.Context

5
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/model/PushDataUnifiedPush.kt → libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/unifiedpush/PushDataUnifiedPush.kt

@ -1,5 +1,5 @@ @@ -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");
* you may not use this file except in compliance with the License.
@ -14,9 +14,10 @@ @@ -14,9 +14,10 @@
* limitations under the License.
*/
package io.element.android.libraries.push.impl.model
package io.element.android.libraries.push.impl.unifiedpush
import io.element.android.libraries.matrix.api.core.MatrixPatterns
import io.element.android.libraries.push.impl.push.PushData
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

4
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/RegisterUnifiedPushUseCase.kt → libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/unifiedpush/RegisterUnifiedPushUseCase.kt

@ -1,5 +1,5 @@ @@ -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");
* you may not use this file except in compliance with the License.
@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
* limitations under the License.
*/
package io.element.android.libraries.push.impl
package io.element.android.libraries.push.impl.unifiedpush
import android.content.Context
import io.element.android.libraries.di.ApplicationContext

29
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/unifiedpush/UnifiedPushParser.kt

@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
/*
* 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.unifiedpush
import io.element.android.libraries.core.data.tryOrNull
import io.element.android.libraries.push.impl.push.PushData
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import javax.inject.Inject
class UnifiedPushParser @Inject constructor() {
fun parse(message: ByteArray): PushData? {
return tryOrNull { Json.decodeFromString<PushDataUnifiedPush>(String(message)) }?.toPushData()
}
}

7
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/UnregisterUnifiedPushUseCase.kt → libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/unifiedpush/UnregisterUnifiedPushUseCase.kt

@ -1,5 +1,5 @@ @@ -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");
* you may not use this file except in compliance with the License.
@ -14,12 +14,15 @@ @@ -14,12 +14,15 @@
* limitations under the License.
*/
package io.element.android.libraries.push.impl
package io.element.android.libraries.push.impl.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

22
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/VectorUnifiedPushMessagingReceiver.kt → libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/unifiedpush/VectorUnifiedPushMessagingReceiver.kt

@ -1,5 +1,5 @@ @@ -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");
* you may not use this file except in compliance with the License.
@ -14,18 +14,18 @@ @@ -14,18 +14,18 @@
* limitations under the License.
*/
package io.element.android.libraries.push.impl
package io.element.android.libraries.push.impl.unifiedpush
import android.content.Context
import android.content.Intent
import android.widget.Toast
import io.element.android.libraries.architecture.bindings
import io.element.android.libraries.core.log.logger.LoggerTag
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.di.VectorUnifiedPushMessagingReceiverBindings
import io.element.android.libraries.push.impl.parser.PushParser
import io.element.android.libraries.push.impl.*
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.SupervisorJob
import kotlinx.coroutines.launch
@ -34,15 +34,15 @@ import org.unifiedpush.android.connector.MessagingReceiver @@ -34,15 +34,15 @@ import org.unifiedpush.android.connector.MessagingReceiver
import timber.log.Timber
import javax.inject.Inject
private val loggerTag = LoggerTag("Push", LoggerTag.SYNC)
private val loggerTag = LoggerTag("Unified", pushLoggerTag)
class VectorUnifiedPushMessagingReceiver : MessagingReceiver() {
@Inject lateinit var pushersManager: PushersManager
@Inject lateinit var pushParser: PushParser
@Inject lateinit var pushParser: UnifiedPushParser
//@Inject lateinit var activeSessionHolder: ActiveSessionHolder
@Inject lateinit var pushDataStore: PushDataStore
@Inject lateinit var vectorPushHandler: VectorPushHandler
@Inject lateinit var pushHandler: PushHandler
@Inject lateinit var guardServiceStarter: GuardServiceStarter
@Inject lateinit var unifiedPushStore: UnifiedPushStore
@Inject lateinit var unifiedPushHelper: UnifiedPushHelper
@ -64,8 +64,8 @@ class VectorUnifiedPushMessagingReceiver : MessagingReceiver() { @@ -64,8 +64,8 @@ class VectorUnifiedPushMessagingReceiver : MessagingReceiver() {
*/
override fun onMessage(context: Context, message: ByteArray, instance: String) {
Timber.tag(loggerTag.value).d("New message")
pushParser.parsePushDataUnifiedPush(message)?.let {
vectorPushHandler.handle(it)
pushParser.parse(message)?.let {
pushHandler.handle(it)
} ?: run {
Timber.tag(loggerTag.value).w("Invalid received data Json format")
}
@ -82,7 +82,7 @@ class VectorUnifiedPushMessagingReceiver : MessagingReceiver() { @@ -82,7 +82,7 @@ class VectorUnifiedPushMessagingReceiver : MessagingReceiver() {
unifiedPushHelper.storeCustomOrDefaultGateway(endpoint) {
unifiedPushHelper.getPushGateway()?.let {
coroutineScope.launch {
pushersManager.enqueueRegisterPusher(endpoint, it)
pushersManager.onNewUnifiedPushEndpoint(endpoint, it)
}
}
}

3
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/di/VectorUnifiedPushMessagingReceiverBindings.kt → libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/unifiedpush/VectorUnifiedPushMessagingReceiverBindings.kt

@ -14,11 +14,10 @@ @@ -14,11 +14,10 @@
* limitations under the License.
*/
package io.element.android.libraries.push.impl.di
package io.element.android.libraries.push.impl.unifiedpush
import com.squareup.anvil.annotations.ContributesTo
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.push.impl.VectorUnifiedPushMessagingReceiver
@ContributesTo(AppScope::class)
interface VectorUnifiedPushMessagingReceiverBindings {

40
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/userpushstore/UserPushStore.kt

@ -0,0 +1,40 @@ @@ -0,0 +1,40 @@
/*
* 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.impl.userpushstore
const val NOTIFICATION_METHOD_FIREBASE = "NOTIFICATION_METHOD_FIREBASE"
const val NOTIFICATION_METHOD_UNIFIEDPUSH = "NOTIFICATION_METHOD_UNIFIEDPUSH"
/**
* Store data related to push about a user.
*/
interface UserPushStore {
/**
* NOTIFICATION_METHOD_FIREBASE or NOTIFICATION_METHOD_UNIFIEDPUSH
*/
suspend fun getNotificationMethod(): String
suspend fun setNotificationMethod(value: String)
suspend fun getCurrentRegisteredPushKey(): String?
suspend fun setCurrentRegisteredPushKey(value: String)
suspend fun reset()
}
suspend fun UserPushStore.isFirebase(): Boolean = getNotificationMethod() == NOTIFICATION_METHOD_FIREBASE

63
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/userpushstore/UserPushStoreDataStore.kt

@ -0,0 +1,63 @@ @@ -0,0 +1,63 @@
/*
* 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.impl.userpushstore
import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import kotlinx.coroutines.flow.first
/**
* Store data related to push about a user.
*/
class UserPushStoreDataStore(
private val context: Context,
userId: String,
) : UserPushStore {
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "push_store_$userId")
private val notificationMethod = stringPreferencesKey("notificationMethod")
private val currentPushKey = stringPreferencesKey("currentPushKey")
override suspend fun getNotificationMethod(): String {
return context.dataStore.data.first()[notificationMethod] ?: NOTIFICATION_METHOD_FIREBASE
}
override suspend fun setNotificationMethod(value: String) {
context.dataStore.edit {
it[notificationMethod] = value
}
}
override suspend fun getCurrentRegisteredPushKey(): String? {
return context.dataStore.data.first()[currentPushKey]
}
override suspend fun setCurrentRegisteredPushKey(value: String) {
context.dataStore.edit {
it[currentPushKey] = value
}
}
override suspend fun reset() {
context.dataStore.edit {
it.clear()
}
}
}

32
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/userpushstore/UserPushStoreFactory.kt

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
/*
* 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.impl.userpushstore
import android.content.Context
import io.element.android.libraries.di.ApplicationContext
import javax.inject.Inject
class UserPushStoreFactory @Inject constructor(
@ApplicationContext private val context: Context,
) {
fun create(userId: String): UserPushStore {
return UserPushStoreDataStore(
context = context,
userId = userId
)
}
}

4
libraries/session-storage/api/src/main/kotlin/io/element/android/libraries/sessionstorage/api/SessionStore.kt

@ -26,3 +26,7 @@ interface SessionStore { @@ -26,3 +26,7 @@ interface SessionStore {
suspend fun getLatestSession(): SessionData?
suspend fun removeSession(sessionId: String)
}
fun List<SessionData>.toUserList(): List<String> {
return map { it.userId }
}

Loading…
Cancel
Save