mirror of
https://github.com/nextcloud/talk-android
synced 2025-06-22 21:19:31 +01:00
parent
cf8261fe4c
commit
0e8b0b8db0
@ -251,7 +251,7 @@ class MessageNotificationWorker(
|
|||||||
var notificationId = decryptedPushMessage.timestamp.toInt()
|
var notificationId = decryptedPushMessage.timestamp.toInt()
|
||||||
|
|
||||||
val notificationInfoBundle = Bundle()
|
val notificationInfoBundle = Bundle()
|
||||||
notificationInfoBundle.putLong(BundleKeys.KEY_INTERNAL_USER_ID, signatureVerification.userEntity!!.id!!)
|
notificationInfoBundle.putLong(BundleKeys.KEY_INTERNAL_USER_ID, signatureVerification.userEntity!!.id)
|
||||||
notificationInfoBundle.putString(BundleKeys.KEY_CONVERSATION_TOKEN, decryptedPushMessage.id)
|
notificationInfoBundle.putString(BundleKeys.KEY_CONVERSATION_TOKEN, decryptedPushMessage.id)
|
||||||
notificationInfoBundle.putLong(BundleKeys.KEY_NOTIFICATION_ID, decryptedPushMessage.notificationId!!)
|
notificationInfoBundle.putLong(BundleKeys.KEY_NOTIFICATION_ID, decryptedPushMessage.notificationId!!)
|
||||||
notificationBuilder.extras = notificationInfoBundle
|
notificationBuilder.extras = notificationInfoBundle
|
||||||
|
@ -83,8 +83,8 @@ class ConversationsRepositoryImpl(val conversationsDao: ConversationsDao) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getConversationForUserWithToken(userId: Long, token: String): Conversation? {
|
override suspend fun getConversationForUserWithToken(internalUserId: Long, token: String): Conversation? {
|
||||||
val conversationEntity = conversationsDao.getConversationForUserWithToken(userId, token)
|
val conversationEntity = conversationsDao.getConversationForUserWithToken(internalUserId, token)
|
||||||
if (conversationEntity != null) {
|
if (conversationEntity != null) {
|
||||||
return conversationEntity.toConversation()
|
return conversationEntity.toConversation()
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ class NextcloudTalkRepositoryImpl(private val apiService: ApiService) : Nextclou
|
|||||||
return apiService.getNotification(user.getCredentials(), ApiUtils.getUrlForNotificationWithId(user.baseUrl, notificationId))
|
return apiService.getNotification(user.getCredentials(), ApiUtils.getUrlForNotificationWithId(user.baseUrl, notificationId))
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getPeersForCall(user: UserNgEntity, conversationToken: String): ParticipantsOverall {
|
override suspend fun getParticipantsForCall(user: UserNgEntity, conversationToken: String): ParticipantsOverall {
|
||||||
return apiService.getPeersForCall(user.getCredentials(), ApiUtils.getUrlForCall(user.baseUrl, conversationToken))
|
return apiService.getPeersForCall(user.getCredentials(), ApiUtils.getUrlForCall(user.baseUrl, conversationToken))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ val UseCasesModule = module {
|
|||||||
single { createCreateConversationUseCase(get(), get()) }
|
single { createCreateConversationUseCase(get(), get()) }
|
||||||
single { createAddParticipantToConversationUseCase(get(), get()) }
|
single { createAddParticipantToConversationUseCase(get(), get()) }
|
||||||
single { setConversationPasswordUseCase(get(), get()) }
|
single { setConversationPasswordUseCase(get(), get()) }
|
||||||
factory { getPeersForCallUseCase(get(), get()) }
|
factory { getParticipantsForCallUseCase(get(), get()) }
|
||||||
factory { getNotificationUseCase(get(), get()) }
|
factory { getNotificationUseCase(get(), get()) }
|
||||||
factory { createChatViewModelFactory(get(), get(), get(), get(), get(), get()) }
|
factory { createChatViewModelFactory(get(), get(), get(), get(), get(), get()) }
|
||||||
}
|
}
|
||||||
@ -61,9 +61,9 @@ fun getNotificationUseCase(nextcloudTalkRepository: NextcloudTalkRepository,
|
|||||||
return GetNotificationUseCase(nextcloudTalkRepository, apiErrorHandler)
|
return GetNotificationUseCase(nextcloudTalkRepository, apiErrorHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getPeersForCallUseCase(nextcloudTalkRepository: NextcloudTalkRepository,
|
fun getParticipantsForCallUseCase(nextcloudTalkRepository: NextcloudTalkRepository,
|
||||||
apiErrorHandler: ApiErrorHandler): GetPeersForCallUseCase {
|
apiErrorHandler: ApiErrorHandler): GetParticipantsForCallUseCase {
|
||||||
return GetPeersForCallUseCase(nextcloudTalkRepository, apiErrorHandler)
|
return GetParticipantsForCallUseCase(nextcloudTalkRepository, apiErrorHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ import com.nextcloud.talk.models.json.conversations.Conversation
|
|||||||
interface ConversationsRepository {
|
interface ConversationsRepository {
|
||||||
fun getConversationsForUser(userId: Long, filter: CharSequence?): LiveData<List<Conversation>>
|
fun getConversationsForUser(userId: Long, filter: CharSequence?): LiveData<List<Conversation>>
|
||||||
fun getShortcutTargetConversations(userId: Long): LiveData<List<Conversation>>
|
fun getShortcutTargetConversations(userId: Long): LiveData<List<Conversation>>
|
||||||
suspend fun getConversationForUserWithToken(userId: Long, token: String): Conversation?
|
suspend fun getConversationForUserWithToken(internalUserId: Long, token: String): Conversation?
|
||||||
suspend fun clearConversationsForUser(userId: Long)
|
suspend fun clearConversationsForUser(userId: Long)
|
||||||
suspend fun saveConversationsForUser(
|
suspend fun saveConversationsForUser(
|
||||||
userId: Long,
|
userId: Long,
|
||||||
|
@ -37,7 +37,7 @@ import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
|||||||
|
|
||||||
interface NextcloudTalkRepository {
|
interface NextcloudTalkRepository {
|
||||||
suspend fun getNotificationForUser(user: UserNgEntity, notificationId: String): NotificationOverall
|
suspend fun getNotificationForUser(user: UserNgEntity, notificationId: String): NotificationOverall
|
||||||
suspend fun getPeersForCall(user: UserNgEntity, conversationToken: String): ParticipantsOverall
|
suspend fun getParticipantsForCall(user: UserNgEntity, conversationToken: String): ParticipantsOverall
|
||||||
suspend fun setPasswordForConversation(user: UserNgEntity, conversationToken: String, password: String): GenericOverall
|
suspend fun setPasswordForConversation(user: UserNgEntity, conversationToken: String, password: String): GenericOverall
|
||||||
suspend fun addParticipantToConversation(user: UserNgEntity, conversationToken: String, participantId: String, source: String): AddParticipantOverall
|
suspend fun addParticipantToConversation(user: UserNgEntity, conversationToken: String, participantId: String, source: String): AddParticipantOverall
|
||||||
suspend fun createConversationForUser(user: UserNgEntity, conversationType: Int, invite: String?, source: String?, conversationName: String?): ConversationOverall
|
suspend fun createConversationForUser(user: UserNgEntity, conversationType: Int, invite: String?, source: String?, conversationName: String?): ConversationOverall
|
||||||
|
@ -28,12 +28,12 @@ import com.nextcloud.talk.newarch.domain.repository.online.NextcloudTalkReposito
|
|||||||
import com.nextcloud.talk.newarch.domain.usecases.base.UseCase
|
import com.nextcloud.talk.newarch.domain.usecases.base.UseCase
|
||||||
import org.koin.core.parameter.DefinitionParameters
|
import org.koin.core.parameter.DefinitionParameters
|
||||||
|
|
||||||
class GetPeersForCallUseCase constructor(
|
class GetParticipantsForCallUseCase constructor(
|
||||||
private val nextcloudTalkRepository: NextcloudTalkRepository,
|
private val nextcloudTalkRepository: NextcloudTalkRepository,
|
||||||
apiErrorHandler: ApiErrorHandler?
|
apiErrorHandler: ApiErrorHandler?
|
||||||
) : UseCase<ParticipantsOverall, Any?>(apiErrorHandler) {
|
) : UseCase<ParticipantsOverall, Any?>(apiErrorHandler) {
|
||||||
override suspend fun run(params: Any?): ParticipantsOverall {
|
override suspend fun run(params: Any?): ParticipantsOverall {
|
||||||
val definitionParameters = params as DefinitionParameters
|
val definitionParameters = params as DefinitionParameters
|
||||||
return nextcloudTalkRepository.getPeersForCall(definitionParameters[0], definitionParameters[1])
|
return nextcloudTalkRepository.getParticipantsForCall(definitionParameters[0], definitionParameters[1])
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -80,8 +80,8 @@ abstract class ConversationsDao {
|
|||||||
timestamp: Long
|
timestamp: Long
|
||||||
)
|
)
|
||||||
|
|
||||||
@Query("SELECT * FROM conversations where id = :userId AND token = :token")
|
@Query("SELECT * FROM conversations where id = :internalUserId AND token = :token")
|
||||||
abstract suspend fun getConversationForUserWithToken(userId: Long, token: String): ConversationEntity?
|
abstract suspend fun getConversationForUserWithToken(internalUserId: Long, token: String): ConversationEntity?
|
||||||
|
|
||||||
@Transaction
|
@Transaction
|
||||||
open suspend fun updateConversationsForUser(
|
open suspend fun updateConversationsForUser(
|
||||||
|
@ -10,6 +10,7 @@ import android.media.AudioAttributes
|
|||||||
import android.media.AudioManager
|
import android.media.AudioManager
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.Handler
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
import android.util.Base64
|
import android.util.Base64
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
@ -30,12 +31,16 @@ import com.nextcloud.talk.jobs.MessageNotificationWorker
|
|||||||
import com.nextcloud.talk.models.SignatureVerification
|
import com.nextcloud.talk.models.SignatureVerification
|
||||||
import com.nextcloud.talk.models.json.conversations.Conversation
|
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||||
import com.nextcloud.talk.models.json.conversations.ConversationOverall
|
import com.nextcloud.talk.models.json.conversations.ConversationOverall
|
||||||
|
import com.nextcloud.talk.models.json.participants.Participant
|
||||||
|
import com.nextcloud.talk.models.json.participants.ParticipantsOverall
|
||||||
import com.nextcloud.talk.models.json.push.DecryptedPushMessage
|
import com.nextcloud.talk.models.json.push.DecryptedPushMessage
|
||||||
import com.nextcloud.talk.newarch.data.model.ErrorModel
|
import com.nextcloud.talk.newarch.data.model.ErrorModel
|
||||||
import com.nextcloud.talk.newarch.data.source.remote.ApiErrorHandler
|
import com.nextcloud.talk.newarch.data.source.remote.ApiErrorHandler
|
||||||
import com.nextcloud.talk.newarch.domain.repository.offline.ConversationsRepository
|
import com.nextcloud.talk.newarch.domain.repository.offline.ConversationsRepository
|
||||||
import com.nextcloud.talk.newarch.domain.repository.offline.UsersRepository
|
import com.nextcloud.talk.newarch.domain.repository.offline.UsersRepository
|
||||||
import com.nextcloud.talk.newarch.domain.usecases.GetConversationUseCase
|
import com.nextcloud.talk.newarch.domain.usecases.GetConversationUseCase
|
||||||
|
import com.nextcloud.talk.newarch.domain.usecases.GetParticipantsForCallUseCase
|
||||||
|
import com.nextcloud.talk.newarch.domain.usecases.base.UseCase
|
||||||
import com.nextcloud.talk.newarch.domain.usecases.base.UseCaseResponse
|
import com.nextcloud.talk.newarch.domain.usecases.base.UseCaseResponse
|
||||||
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
||||||
import com.nextcloud.talk.newarch.utils.ComponentsWithEmptyCookieJar
|
import com.nextcloud.talk.newarch.utils.ComponentsWithEmptyCookieJar
|
||||||
@ -57,8 +62,10 @@ import retrofit2.Retrofit
|
|||||||
import java.security.InvalidKeyException
|
import java.security.InvalidKeyException
|
||||||
import java.security.NoSuchAlgorithmException
|
import java.security.NoSuchAlgorithmException
|
||||||
import java.security.PrivateKey
|
import java.security.PrivateKey
|
||||||
|
import java.util.*
|
||||||
import javax.crypto.Cipher
|
import javax.crypto.Cipher
|
||||||
import javax.crypto.NoSuchPaddingException
|
import javax.crypto.NoSuchPaddingException
|
||||||
|
import kotlin.concurrent.timerTask
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
class CallService : Service(), KoinComponent, CoroutineScope {
|
class CallService : Service(), KoinComponent, CoroutineScope {
|
||||||
@ -83,12 +90,7 @@ class CallService : Service(), KoinComponent, CoroutineScope {
|
|||||||
decryptMessage(it.getStringExtra(BundleKeys.KEY_ENCRYPTED_SUBJECT), it.getStringExtra(BundleKeys.KEY_ENCRYPTED_SIGNATURE))
|
decryptMessage(it.getStringExtra(BundleKeys.KEY_ENCRYPTED_SUBJECT), it.getStringExtra(BundleKeys.KEY_ENCRYPTED_SIGNATURE))
|
||||||
} else if (it.action == BundleKeys.KEY_REJECT_INCOMING_CALL || it.action == BundleKeys.DISMISS_CALL_NOTIFICATION) {
|
} else if (it.action == BundleKeys.KEY_REJECT_INCOMING_CALL || it.action == BundleKeys.DISMISS_CALL_NOTIFICATION) {
|
||||||
if (it.getStringExtra(BundleKeys.KEY_ACTIVE_NOTIFICATION) == activeNotification) {
|
if (it.getStringExtra(BundleKeys.KEY_ACTIVE_NOTIFICATION) == activeNotification) {
|
||||||
stopForeground(true)
|
endIncomingConversation(it.action != BundleKeys.DISMISS_CALL_NOTIFICATION)
|
||||||
if (it.action != BundleKeys.DISMISS_CALL_NOTIFICATION) {
|
|
||||||
eventBus.post(CallEvent())
|
|
||||||
} else {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// do nothing? :D
|
// do nothing? :D
|
||||||
}
|
}
|
||||||
@ -184,7 +186,6 @@ class CallService : Service(), KoinComponent, CoroutineScope {
|
|||||||
.setAutoCancel(true)
|
.setAutoCancel(true)
|
||||||
.setOngoing(true)
|
.setOngoing(true)
|
||||||
.addAction(R.drawable.ic_call_end_white_24px, resources.getString(R.string.reject_call), rejectCallPendingIntent)
|
.addAction(R.drawable.ic_call_end_white_24px, resources.getString(R.string.reject_call), rejectCallPendingIntent)
|
||||||
//.setTimeoutAfter(45000L)
|
|
||||||
.setContentIntent(fullScreenPendingIntent)
|
.setContentIntent(fullScreenPendingIntent)
|
||||||
.setFullScreenIntent(fullScreenPendingIntent, true)
|
.setFullScreenIntent(fullScreenPendingIntent, true)
|
||||||
.setSound(NotificationUtils.getCallSoundUri(applicationContext, appPreferences), AudioManager.STREAM_RING)
|
.setSound(NotificationUtils.getCallSoundUri(applicationContext, appPreferences), AudioManager.STREAM_RING)
|
||||||
@ -193,20 +194,18 @@ class CallService : Service(), KoinComponent, CoroutineScope {
|
|||||||
notificationBuilder.setVibrate(vibrationEffect)
|
notificationBuilder.setVibrate(vibrationEffect)
|
||||||
}
|
}
|
||||||
|
|
||||||
//checkIfCallIsActive(signatureVerification, decryptedPushMessage)
|
|
||||||
|
|
||||||
if (conversation.type == Conversation.ConversationType.ONE_TO_ONE_CONVERSATION) {
|
if (conversation.type == Conversation.ConversationType.ONE_TO_ONE_CONVERSATION) {
|
||||||
val target = object : Target {
|
val target = object : Target {
|
||||||
override fun onSuccess(result: Drawable) {
|
override fun onSuccess(result: Drawable) {
|
||||||
super.onSuccess(result)
|
super.onSuccess(result)
|
||||||
largeIcon = result.toBitmap()
|
largeIcon = result.toBitmap()
|
||||||
notificationBuilder.setLargeIcon(largeIcon)
|
notificationBuilder.setLargeIcon(largeIcon)
|
||||||
showNotification(notificationBuilder, signatureVerification.userEntity!!, decryptedPushMessage.notificationId!!, generatedActiveNotificationId)
|
showNotification(notificationBuilder, signatureVerification.userEntity!!, conversation.token!!, decryptedPushMessage.notificationId!!, generatedActiveNotificationId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(error: Drawable?) {
|
override fun onError(error: Drawable?) {
|
||||||
super.onError(error)
|
super.onError(error)
|
||||||
showNotification(notificationBuilder, signatureVerification.userEntity!!, decryptedPushMessage.notificationId!!, generatedActiveNotificationId)
|
showNotification(notificationBuilder, signatureVerification.userEntity!!, conversation.token!!, decryptedPushMessage.notificationId!!, generatedActiveNotificationId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,7 +218,7 @@ class CallService : Service(), KoinComponent, CoroutineScope {
|
|||||||
|
|
||||||
imageLoader.load(request)
|
imageLoader.load(request)
|
||||||
} else {
|
} else {
|
||||||
showNotification(notificationBuilder, signatureVerification.userEntity!!, decryptedPushMessage.notificationId!!, generatedActiveNotificationId)
|
showNotification(notificationBuilder, signatureVerification.userEntity!!, conversation.token!!, decryptedPushMessage.notificationId!!, generatedActiveNotificationId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -253,6 +252,41 @@ class CallService : Service(), KoinComponent, CoroutineScope {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun checkIsConversationActive(user: UserNgEntity, conversationToken: String, activeNotificationArgument: String) {
|
||||||
|
if (activeNotificationArgument == activeNotification) {
|
||||||
|
val getParticipantsForCallUseCase = GetParticipantsForCallUseCase(componentsWithEmptyCookieJar.getRepository(), apiErrorHandler)
|
||||||
|
getParticipantsForCallUseCase.invoke(this, parametersOf(user, conversationToken), object : UseCaseResponse<ParticipantsOverall> {
|
||||||
|
override suspend fun onSuccess(result: ParticipantsOverall) {
|
||||||
|
val participants = result.ocs.data
|
||||||
|
if (participants.size > 0 && activeNotificationArgument == activeNotification) {
|
||||||
|
val activeParticipants = participants.filter { it.participantFlags != Participant.ParticipantFlags.NOT_IN_CALL }
|
||||||
|
val activeOnAnotherDevice = activeParticipants.filter { it.userId == user.userId }
|
||||||
|
if (activeParticipants.isNotEmpty() && activeOnAnotherDevice.isEmpty()) {
|
||||||
|
delay(5000)
|
||||||
|
checkIsConversationActive(user, conversationToken, activeNotificationArgument)
|
||||||
|
} else {
|
||||||
|
endIncomingConversation(true)
|
||||||
|
}
|
||||||
|
} else if (activeNotificationArgument == activeNotification) {
|
||||||
|
endIncomingConversation(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun onError(errorModel: ErrorModel?) {
|
||||||
|
endIncomingConversation(true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun endIncomingConversation(triggerEventBus : Boolean) {
|
||||||
|
activeNotification = ""
|
||||||
|
stopForeground(true)
|
||||||
|
if (triggerEventBus) {
|
||||||
|
eventBus.post(CallEvent())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private suspend fun getConversationForTokenAndUser(user: UserNgEntity, conversationToken: String): Conversation? {
|
private suspend fun getConversationForTokenAndUser(user: UserNgEntity, conversationToken: String): Conversation? {
|
||||||
var conversation = conversationsRepository.getConversationForUserWithToken(user.id, conversationToken)
|
var conversation = conversationsRepository.getConversationForUserWithToken(user.id, conversationToken)
|
||||||
if (conversation == null) {
|
if (conversation == null) {
|
||||||
@ -275,13 +309,15 @@ class CallService : Service(), KoinComponent, CoroutineScope {
|
|||||||
return conversation
|
return conversation
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showNotification(builder: NotificationCompat.Builder, user: UserNgEntity, internalNotificationId: Long, generatedNotificationId: String) {
|
private fun showNotification(builder: NotificationCompat.Builder, user: UserNgEntity, conversationToken: String, internalNotificationId: Long, generatedNotificationId: String) {
|
||||||
|
endIncomingConversation(true)
|
||||||
activeNotification = generatedNotificationId
|
activeNotification = generatedNotificationId
|
||||||
val notification = builder.build()
|
val notification = builder.build()
|
||||||
notification.extras.putLong(BundleKeys.KEY_INTERNAL_USER_ID, user.id)
|
notification.extras.putLong(BundleKeys.KEY_INTERNAL_USER_ID, user.id)
|
||||||
notification.extras.putLong(BundleKeys.KEY_NOTIFICATION_ID, internalNotificationId)
|
notification.extras.putLong(BundleKeys.KEY_NOTIFICATION_ID, internalNotificationId)
|
||||||
notification.flags = notification.flags or Notification.FLAG_INSISTENT
|
notification.flags = notification.flags or Notification.FLAG_INSISTENT
|
||||||
startForeground(generatedNotificationId.hashCode(), notification)
|
startForeground(generatedNotificationId.hashCode(), notification)
|
||||||
|
checkIsConversationActive(user, conversationToken, generatedNotificationId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBind(intent: Intent?): IBinder? {
|
override fun onBind(intent: Intent?): IBinder? {
|
||||||
|
Loading…
Reference in New Issue
Block a user