Browse Source

Handle quick reply from notification (still disabled)

pull/2967/head
Benoit Marty 4 months ago committed by Benoit Marty
parent
commit
7c559363a4
  1. 2
      libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/ThreadId.kt
  2. 179
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiver.kt

2
libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/ThreadId.kt

@ -33,3 +33,5 @@ value class ThreadId(val value: String) : Serializable {
override fun toString(): String = value override fun toString(): String = value
} }
fun ThreadId.asEventId(): EventId = EventId(value)

179
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBroadcastReceiver.kt

@ -19,6 +19,7 @@ package io.element.android.libraries.push.impl.notifications
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import androidx.core.app.RemoteInput
import io.element.android.features.preferences.api.store.SessionPreferencesStoreFactory import io.element.android.features.preferences.api.store.SessionPreferencesStoreFactory
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
@ -26,11 +27,19 @@ import io.element.android.libraries.matrix.api.MatrixClientProvider
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
import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.core.ThreadId
import io.element.android.libraries.matrix.api.core.asEventId
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.timeline.ReceiptType import io.element.android.libraries.matrix.api.timeline.ReceiptType
import io.element.android.libraries.push.impl.R
import io.element.android.libraries.push.impl.notifications.model.NotifiableMessageEvent
import io.element.android.libraries.push.impl.push.OnNotifiableEventReceived
import io.element.android.services.toolbox.api.systemclock.SystemClock
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import timber.log.Timber import timber.log.Timber
import java.util.UUID
import javax.inject.Inject import javax.inject.Inject
private val loggerTag = LoggerTag("NotificationBroadcastReceiver", LoggerTag.NotificationLoggerTag) private val loggerTag = LoggerTag("NotificationBroadcastReceiver", LoggerTag.NotificationLoggerTag)
@ -44,19 +53,23 @@ class NotificationBroadcastReceiver : BroadcastReceiver() {
@Inject lateinit var sessionPreferencesStore: SessionPreferencesStoreFactory @Inject lateinit var sessionPreferencesStore: SessionPreferencesStoreFactory
@Inject lateinit var defaultNotificationDrawerManager: DefaultNotificationDrawerManager @Inject lateinit var defaultNotificationDrawerManager: DefaultNotificationDrawerManager
@Inject lateinit var actionIds: NotificationActionIds @Inject lateinit var actionIds: NotificationActionIds
@Inject lateinit var systemClock: SystemClock
@Inject lateinit var onNotifiableEventReceived: OnNotifiableEventReceived
override fun onReceive(context: Context?, intent: Intent?) { override fun onReceive(context: Context?, intent: Intent?) {
if (intent == null || context == null) return if (intent == null || context == null) return
val sessionId = intent.extras?.getString(KEY_SESSION_ID)?.let(::SessionId) ?: return val sessionId = intent.extras?.getString(KEY_SESSION_ID)?.let(::SessionId) ?: return
val roomId = intent.getStringExtra(KEY_ROOM_ID)?.let(::RoomId) val roomId = intent.getStringExtra(KEY_ROOM_ID)?.let(::RoomId)
val threadId = intent.getStringExtra(KEY_THREAD_ID)?.let(::ThreadId)
val eventId = intent.getStringExtra(KEY_EVENT_ID)?.let(::EventId) val eventId = intent.getStringExtra(KEY_EVENT_ID)?.let(::EventId)
context.bindings<NotificationBroadcastReceiverBindings>().inject(this) context.bindings<NotificationBroadcastReceiverBindings>().inject(this)
Timber.tag(loggerTag.value).d("onReceive: ${intent.action} ${intent.data} for: ${roomId?.value}/${eventId?.value}") Timber.tag(loggerTag.value).d("onReceive: ${intent.action} ${intent.data} for: ${roomId?.value}/${eventId?.value}")
when (intent.action) { when (intent.action) {
actionIds.smartReply -> actionIds.smartReply -> if (roomId != null) {
handleSmartReply(intent, context) handleSmartReply(sessionId, roomId, threadId, intent, context)
}
actionIds.dismissRoom -> if (roomId != null) { actionIds.dismissRoom -> if (roomId != null) {
defaultNotificationDrawerManager.clearMessagesForRoom(sessionId, roomId) defaultNotificationDrawerManager.clearMessagesForRoom(sessionId, roomId)
} }
@ -104,113 +117,84 @@ class NotificationBroadcastReceiver : BroadcastReceiver() {
client.getRoom(roomId)?.markAsRead(receiptType = receiptType) client.getRoom(roomId)?.markAsRead(receiptType = receiptType)
} }
@Suppress("UNUSED_PARAMETER") private fun handleSmartReply(
private fun handleSmartReply(intent: Intent, context: Context) { sessionId: SessionId,
/* roomId: RoomId,
threadId: ThreadId?,
intent: Intent,
context: Context
) = appCoroutineScope.launch {
val message = getReplyMessage(intent) val message = getReplyMessage(intent)
val sessionId = intent.getStringExtra(KEY_SESSION_ID)?.let(::SessionId)
val roomId = intent.getStringExtra(KEY_ROOM_ID)?.let(::RoomId)
val threadId = intent.getStringExtra(KEY_THREAD_ID)?.let(::ThreadId)
if (message.isNullOrBlank() || roomId == null) { if (message.isNullOrBlank()) {
// ignore this event // ignore this event
// Can this happen? should we update notification? // Can this happen? should we update notification?
return return@launch
} }
activeSessionHolder.getActiveSession().let { session -> val client = matrixClientProvider.getOrRestore(sessionId).getOrNull() ?: return@launch
session.getRoom(roomId)?.let { room -> client.getRoom(roomId)?.let { room ->
sendMatrixEvent(message, threadId, session, room, context) sendMatrixEvent(
} sessionId = sessionId,
} roomId = roomId,
*/ threadId = threadId,
} room = room,
message = message,
/* context = context,
private fun sendMatrixEvent(message: String, threadId: String?, session: Session, room: Room, context: Context?) {
if (threadId != null) {
room.relationService().replyInThread(
rootThreadEventId = threadId,
replyInThreadText = message,
) )
} else {
room.sendService().sendTextMessage(message)
} }
}
private suspend fun sendMatrixEvent(
sessionId: SessionId,
roomId: RoomId,
threadId: ThreadId?,
room: MatrixRoom,
message: String,
context: Context,
) {
// Create a new event to be displayed in the notification drawer, right now // Create a new event to be displayed in the notification drawer, right now
val notifiableMessageEvent = NotifiableMessageEvent( val notifiableMessageEvent = NotifiableMessageEvent(
// Generate a Fake event id sessionId = sessionId,
eventId = UUID.randomUUID().toString(), roomId = roomId,
editedEventId = null, // Generate a Fake event id
noisy = false, eventId = EventId("\$" + UUID.randomUUID().toString()),
timestamp = clock.epochMillis(), editedEventId = null,
senderName = session.roomService().getRoomMember(session.myUserId, room.roomId)?.displayName canBeReplaced = false,
?: context?.getString(R.string.notification_sender_me), senderId = sessionId,
senderId = session.myUserId, noisy = false,
body = message, timestamp = systemClock.epochMillis(),
imageUriString = null, senderDisambiguatedDisplayName = room.getUpdatedMember(sessionId).getOrNull()?.disambiguatedDisplayName
roomId = room.roomId, ?: context.getString(R.string.notification_sender_me),
threadId = threadId, body = message,
roomName = room.roomSummary()?.displayName ?: room.roomId, imageUriString = null,
roomIsDirect = room.roomSummary()?.isDirect == true, threadId = threadId,
outGoingMessage = true, roomName = room.displayName,
canBeReplaced = false roomIsDirect = room.isDirect,
outGoingMessage = true,
) )
onNotifiableEventReceived.onNotifiableEventReceived(notifiableMessageEvent)
notificationDrawerManager.updateEvents { it.onNotifiableEventReceived(notifiableMessageEvent) } if (threadId != null) {
room.liveTimeline.replyMessage(
/* eventId = threadId.asEventId(),
// TODO Error cannot be managed the same way than in Riot body = message,
htmlBody = null,
val event = Event(mxMessage, session.credentials.userId, roomId) mentions = emptyList()
room.storeOutgoingEvent(event) )
room.sendEvent(event, object : MatrixCallback<Void?> { } else {
override fun onSuccess(info: Void?) { room.liveTimeline.sendMessage(
Timber.v("Send message : onSuccess ") body = message,
} htmlBody = null,
mentions = emptyList()
override fun onNetworkError(e: Exception) { )
Timber.e(e, "Send message : onNetworkError") }.onFailure {
onSmartReplyFailed(e.localizedMessage) Timber.e(it, "Failed to send smart reply message")
} onNotifiableEventReceived.onNotifiableEventReceived(
notifiableMessageEvent.copy(
override fun onMatrixError(e: MatrixError) { outGoingMessageFailed = true
Timber.v("Send message : onMatrixError " + e.message) )
if (e is MXCryptoError) { )
Toast.makeText(context, e.detailedErrorDescription, Toast.LENGTH_SHORT).show() }
onSmartReplyFailed(e.detailedErrorDescription)
} else {
Toast.makeText(context, e.localizedMessage, Toast.LENGTH_SHORT).show()
onSmartReplyFailed(e.localizedMessage)
}
}
override fun onUnexpectedError(e: Exception) {
Timber.e(e, "Send message : onUnexpectedError " + e.message)
onSmartReplyFailed(e.message)
}
fun onSmartReplyFailed(reason: String?) {
val notifiableMessageEvent = NotifiableMessageEvent(
event.eventId,
false,
clock.epochMillis(),
session.myUser?.displayname
?: context?.getString(R.string.notification_sender_me),
session.myUserId,
message,
roomId,
room.getRoomDisplayName(context),
room.isDirect)
notifiableMessageEvent.outGoingMessage = true
notifiableMessageEvent.outGoingMessageFailed = true
VectorApp.getInstance().notificationDrawerManager.onNotifiableEventReceived(notifiableMessageEvent)
VectorApp.getInstance().notificationDrawerManager.refreshNotificationDrawer(null)
}
})
*/
} }
private fun getReplyMessage(intent: Intent?): String? { private fun getReplyMessage(intent: Intent?): String? {
@ -222,7 +206,6 @@ class NotificationBroadcastReceiver : BroadcastReceiver() {
} }
return null return null
} }
*/
companion object { companion object {
const val KEY_SESSION_ID = "sessionID" const val KEY_SESSION_ID = "sessionID"

Loading…
Cancel
Save