Signed-off-by: Mario Danic <mario@lovelyhq.com>
This commit is contained in:
Mario Danic 2020-02-23 19:15:17 +01:00
parent cf8261fe4c
commit 0e8b0b8db0
No known key found for this signature in database
GPG Key ID: CDE0BBD2738C4CC0
9 changed files with 63 additions and 27 deletions

View File

@ -251,7 +251,7 @@ class MessageNotificationWorker(
var notificationId = decryptedPushMessage.timestamp.toInt()
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.putLong(BundleKeys.KEY_NOTIFICATION_ID, decryptedPushMessage.notificationId!!)
notificationBuilder.extras = notificationInfoBundle

View File

@ -83,8 +83,8 @@ class ConversationsRepositoryImpl(val conversationsDao: ConversationsDao) :
}
}
override suspend fun getConversationForUserWithToken(userId: Long, token: String): Conversation? {
val conversationEntity = conversationsDao.getConversationForUserWithToken(userId, token)
override suspend fun getConversationForUserWithToken(internalUserId: Long, token: String): Conversation? {
val conversationEntity = conversationsDao.getConversationForUserWithToken(internalUserId, token)
if (conversationEntity != null) {
return conversationEntity.toConversation()
}

View File

@ -99,7 +99,7 @@ class NextcloudTalkRepositoryImpl(private val apiService: ApiService) : Nextclou
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))
}

View File

@ -51,7 +51,7 @@ val UseCasesModule = module {
single { createCreateConversationUseCase(get(), get()) }
single { createAddParticipantToConversationUseCase(get(), get()) }
single { setConversationPasswordUseCase(get(), get()) }
factory { getPeersForCallUseCase(get(), get()) }
factory { getParticipantsForCallUseCase(get(), get()) }
factory { getNotificationUseCase(get(), get()) }
factory { createChatViewModelFactory(get(), get(), get(), get(), get(), get()) }
}
@ -61,9 +61,9 @@ fun getNotificationUseCase(nextcloudTalkRepository: NextcloudTalkRepository,
return GetNotificationUseCase(nextcloudTalkRepository, apiErrorHandler)
}
fun getPeersForCallUseCase(nextcloudTalkRepository: NextcloudTalkRepository,
apiErrorHandler: ApiErrorHandler): GetPeersForCallUseCase {
return GetPeersForCallUseCase(nextcloudTalkRepository, apiErrorHandler)
fun getParticipantsForCallUseCase(nextcloudTalkRepository: NextcloudTalkRepository,
apiErrorHandler: ApiErrorHandler): GetParticipantsForCallUseCase {
return GetParticipantsForCallUseCase(nextcloudTalkRepository, apiErrorHandler)
}

View File

@ -28,7 +28,7 @@ import com.nextcloud.talk.models.json.conversations.Conversation
interface ConversationsRepository {
fun getConversationsForUser(userId: Long, filter: CharSequence?): 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 saveConversationsForUser(
userId: Long,

View File

@ -37,7 +37,7 @@ import com.nextcloud.talk.newarch.local.models.UserNgEntity
interface NextcloudTalkRepository {
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 addParticipantToConversation(user: UserNgEntity, conversationToken: String, participantId: String, source: String): AddParticipantOverall
suspend fun createConversationForUser(user: UserNgEntity, conversationType: Int, invite: String?, source: String?, conversationName: String?): ConversationOverall

View File

@ -28,12 +28,12 @@ import com.nextcloud.talk.newarch.domain.repository.online.NextcloudTalkReposito
import com.nextcloud.talk.newarch.domain.usecases.base.UseCase
import org.koin.core.parameter.DefinitionParameters
class GetPeersForCallUseCase constructor(
class GetParticipantsForCallUseCase constructor(
private val nextcloudTalkRepository: NextcloudTalkRepository,
apiErrorHandler: ApiErrorHandler?
) : UseCase<ParticipantsOverall, Any?>(apiErrorHandler) {
override suspend fun run(params: Any?): ParticipantsOverall {
val definitionParameters = params as DefinitionParameters
return nextcloudTalkRepository.getPeersForCall(definitionParameters[0], definitionParameters[1])
return nextcloudTalkRepository.getParticipantsForCall(definitionParameters[0], definitionParameters[1])
}
}

View File

@ -80,8 +80,8 @@ abstract class ConversationsDao {
timestamp: Long
)
@Query("SELECT * FROM conversations where id = :userId AND token = :token")
abstract suspend fun getConversationForUserWithToken(userId: Long, token: String): ConversationEntity?
@Query("SELECT * FROM conversations where id = :internalUserId AND token = :token")
abstract suspend fun getConversationForUserWithToken(internalUserId: Long, token: String): ConversationEntity?
@Transaction
open suspend fun updateConversationsForUser(

View File

@ -10,6 +10,7 @@ import android.media.AudioAttributes
import android.media.AudioManager
import android.net.Uri
import android.os.Bundle
import android.os.Handler
import android.os.IBinder
import android.util.Base64
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.json.conversations.Conversation
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.newarch.data.model.ErrorModel
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.UsersRepository
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.local.models.UserNgEntity
import com.nextcloud.talk.newarch.utils.ComponentsWithEmptyCookieJar
@ -57,8 +62,10 @@ import retrofit2.Retrofit
import java.security.InvalidKeyException
import java.security.NoSuchAlgorithmException
import java.security.PrivateKey
import java.util.*
import javax.crypto.Cipher
import javax.crypto.NoSuchPaddingException
import kotlin.concurrent.timerTask
import kotlin.coroutines.CoroutineContext
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))
} else if (it.action == BundleKeys.KEY_REJECT_INCOMING_CALL || it.action == BundleKeys.DISMISS_CALL_NOTIFICATION) {
if (it.getStringExtra(BundleKeys.KEY_ACTIVE_NOTIFICATION) == activeNotification) {
stopForeground(true)
if (it.action != BundleKeys.DISMISS_CALL_NOTIFICATION) {
eventBus.post(CallEvent())
} else {
// do nothing
}
endIncomingConversation(it.action != BundleKeys.DISMISS_CALL_NOTIFICATION)
} else {
// do nothing? :D
}
@ -184,7 +186,6 @@ class CallService : Service(), KoinComponent, CoroutineScope {
.setAutoCancel(true)
.setOngoing(true)
.addAction(R.drawable.ic_call_end_white_24px, resources.getString(R.string.reject_call), rejectCallPendingIntent)
//.setTimeoutAfter(45000L)
.setContentIntent(fullScreenPendingIntent)
.setFullScreenIntent(fullScreenPendingIntent, true)
.setSound(NotificationUtils.getCallSoundUri(applicationContext, appPreferences), AudioManager.STREAM_RING)
@ -193,20 +194,18 @@ class CallService : Service(), KoinComponent, CoroutineScope {
notificationBuilder.setVibrate(vibrationEffect)
}
//checkIfCallIsActive(signatureVerification, decryptedPushMessage)
if (conversation.type == Conversation.ConversationType.ONE_TO_ONE_CONVERSATION) {
val target = object : Target {
override fun onSuccess(result: Drawable) {
super.onSuccess(result)
largeIcon = result.toBitmap()
notificationBuilder.setLargeIcon(largeIcon)
showNotification(notificationBuilder, signatureVerification.userEntity!!, decryptedPushMessage.notificationId!!, generatedActiveNotificationId)
showNotification(notificationBuilder, signatureVerification.userEntity!!, conversation.token!!, decryptedPushMessage.notificationId!!, generatedActiveNotificationId)
}
override fun onError(error: Drawable?) {
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)
} 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? {
var conversation = conversationsRepository.getConversationForUserWithToken(user.id, conversationToken)
if (conversation == null) {
@ -275,13 +309,15 @@ class CallService : Service(), KoinComponent, CoroutineScope {
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
val notification = builder.build()
notification.extras.putLong(BundleKeys.KEY_INTERNAL_USER_ID, user.id)
notification.extras.putLong(BundleKeys.KEY_NOTIFICATION_ID, internalNotificationId)
notification.flags = notification.flags or Notification.FLAG_INSISTENT
startForeground(generatedNotificationId.hashCode(), notification)
checkIsConversationActive(user, conversationToken, generatedNotificationId)
}
override fun onBind(intent: Intent?): IBinder? {