mirror of
https://github.com/nextcloud/talk-android
synced 2025-07-21 11:45:03 +01:00
Dismiss notification via action
Signed-off-by: Mario Danic <mario@lovelyhq.com>
This commit is contained in:
parent
8252240b3b
commit
aff8595224
@ -71,7 +71,7 @@ class MagicCallActivity : BaseActivity() {
|
|||||||
val hideIncomingCallNotificationIntent = Intent(applicationContext, CallService::class.java)
|
val hideIncomingCallNotificationIntent = Intent(applicationContext, CallService::class.java)
|
||||||
hideIncomingCallNotificationIntent.action = BundleKeys.KEY_SHOW_INCOMING_CALL
|
hideIncomingCallNotificationIntent.action = BundleKeys.KEY_SHOW_INCOMING_CALL
|
||||||
hideIncomingCallNotificationIntent.putExtra(BundleKeys.KEY_NOTIFICATION_ID, intent.getLongExtra(BundleKeys.KEY_NOTIFICATION_ID, -1))
|
hideIncomingCallNotificationIntent.putExtra(BundleKeys.KEY_NOTIFICATION_ID, intent.getLongExtra(BundleKeys.KEY_NOTIFICATION_ID, -1))
|
||||||
applicationContext?.startService(hideIncomingCallNotificationIntent)
|
//applicationContext?.startService(hideIncomingCallNotificationIntent)
|
||||||
|
|
||||||
router!!.setRoot(
|
router!!.setRoot(
|
||||||
RouterTransaction.with(CallNotificationController(intent.extras!!))
|
RouterTransaction.with(CallNotificationController(intent.extras!!))
|
||||||
|
@ -21,18 +21,14 @@
|
|||||||
package com.nextcloud.talk.controllers
|
package com.nextcloud.talk.controllers
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.drawable.BitmapDrawable
|
import android.graphics.drawable.BitmapDrawable
|
||||||
import android.graphics.drawable.ColorDrawable
|
import android.graphics.drawable.ColorDrawable
|
||||||
import android.media.AudioAttributes
|
|
||||||
import android.media.MediaPlayer
|
import android.media.MediaPlayer
|
||||||
import android.net.Uri
|
import android.os.Bundle
|
||||||
import android.os.*
|
import android.os.Handler
|
||||||
import android.text.TextUtils
|
import android.os.Vibrator
|
||||||
import android.util.Log
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@ -40,7 +36,6 @@ import android.widget.ImageView
|
|||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
import androidx.core.content.ContextCompat
|
|
||||||
import butterknife.BindView
|
import butterknife.BindView
|
||||||
import butterknife.OnClick
|
import butterknife.OnClick
|
||||||
import coil.api.load
|
import coil.api.load
|
||||||
@ -51,28 +46,21 @@ import coil.transform.BlurTransformation
|
|||||||
import coil.transform.CircleCropTransformation
|
import coil.transform.CircleCropTransformation
|
||||||
import com.bluelinelabs.conductor.RouterTransaction
|
import com.bluelinelabs.conductor.RouterTransaction
|
||||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
||||||
import com.bluelinelabs.logansquare.LoganSquare
|
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.api.NcApi
|
import com.nextcloud.talk.api.NcApi
|
||||||
import com.nextcloud.talk.controllers.base.BaseController
|
import com.nextcloud.talk.controllers.base.BaseController
|
||||||
import com.nextcloud.talk.events.ConfigurationChangeEvent
|
import com.nextcloud.talk.events.ConfigurationChangeEvent
|
||||||
import com.nextcloud.talk.models.RingtoneSettings
|
|
||||||
import com.nextcloud.talk.models.database.ArbitraryStorageEntity
|
|
||||||
import com.nextcloud.talk.models.json.conversations.Conversation
|
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||||
import com.nextcloud.talk.models.json.conversations.RoomsOverall
|
|
||||||
import com.nextcloud.talk.models.json.participants.Participant
|
import com.nextcloud.talk.models.json.participants.Participant
|
||||||
import com.nextcloud.talk.models.json.participants.ParticipantsOverall
|
import com.nextcloud.talk.models.json.participants.ParticipantsOverall
|
||||||
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
||||||
import com.nextcloud.talk.newarch.local.models.getCredentials
|
import com.nextcloud.talk.newarch.local.models.getCredentials
|
||||||
import com.nextcloud.talk.newarch.services.CallService
|
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
import com.nextcloud.talk.utils.DoNotDisturbUtils
|
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys
|
import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||||
import com.nextcloud.talk.utils.database.arbitrarystorage.ArbitraryStorageUtils
|
import com.nextcloud.talk.utils.database.arbitrarystorage.ArbitraryStorageUtils
|
||||||
import com.nextcloud.talk.utils.singletons.AvatarStatusCodeHolder
|
import com.nextcloud.talk.utils.singletons.AvatarStatusCodeHolder
|
||||||
import com.uber.autodispose.AutoDispose
|
import com.uber.autodispose.AutoDispose
|
||||||
import io.reactivex.Observer
|
import io.reactivex.Observer
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
|
||||||
import io.reactivex.disposables.Disposable
|
import io.reactivex.disposables.Disposable
|
||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.schedulers.Schedulers
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@ -83,7 +71,6 @@ import org.greenrobot.eventbus.Subscribe
|
|||||||
import org.greenrobot.eventbus.ThreadMode
|
import org.greenrobot.eventbus.ThreadMode
|
||||||
import org.koin.android.ext.android.inject
|
import org.koin.android.ext.android.inject
|
||||||
import org.michaelevans.colorart.library.ColorArt
|
import org.michaelevans.colorart.library.ColorArt
|
||||||
import java.io.IOException
|
|
||||||
|
|
||||||
class CallNotificationController(private val originalBundle: Bundle) : BaseController() {
|
class CallNotificationController(private val originalBundle: Bundle) : BaseController() {
|
||||||
|
|
||||||
@ -116,6 +103,7 @@ class CallNotificationController(private val originalBundle: Bundle) : BaseContr
|
|||||||
private val conversationToken: String
|
private val conversationToken: String
|
||||||
private val userBeingCalled: UserNgEntity?
|
private val userBeingCalled: UserNgEntity?
|
||||||
private val credentials: String?
|
private val credentials: String?
|
||||||
|
private val notificationId: Long?
|
||||||
private var currentConversation: Conversation? = null
|
private var currentConversation: Conversation? = null
|
||||||
private var mediaPlayer: MediaPlayer? = null
|
private var mediaPlayer: MediaPlayer? = null
|
||||||
private var leavingScreen = false
|
private var leavingScreen = false
|
||||||
@ -125,6 +113,7 @@ class CallNotificationController(private val originalBundle: Bundle) : BaseContr
|
|||||||
init {
|
init {
|
||||||
this.conversationToken = originalBundle.getString(BundleKeys.KEY_CONVERSATION_TOKEN)!!
|
this.conversationToken = originalBundle.getString(BundleKeys.KEY_CONVERSATION_TOKEN)!!
|
||||||
this.userBeingCalled = originalBundle.getParcelable(BundleKeys.KEY_USER_ENTITY)!!
|
this.userBeingCalled = originalBundle.getParcelable(BundleKeys.KEY_USER_ENTITY)!!
|
||||||
|
this.notificationId = originalBundle.getLong(BundleKeys.KEY_NOTIFICATION_ID)
|
||||||
credentials = userBeingCalled.getCredentials()
|
credentials = userBeingCalled.getCredentials()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,43 +222,14 @@ class CallNotificationController(private val originalBundle: Bundle) : BaseContr
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleFromNotification() {
|
|
||||||
ncApi.getRooms(credentials, ApiUtils.getUrlForRoomEndpoint(userBeingCalled!!.baseUrl))
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.retry(3)
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.`as`(AutoDispose.autoDisposable(scopeProvider))
|
|
||||||
.subscribe(object : Observer<RoomsOverall> {
|
|
||||||
override fun onSubscribe(d: Disposable) {}
|
|
||||||
|
|
||||||
override fun onNext(roomsOverall: RoomsOverall) {
|
|
||||||
for (conversation in roomsOverall.ocs.data) {
|
|
||||||
if (roomId == conversation.conversationId) {
|
|
||||||
currentConversation = conversation
|
|
||||||
runAllThings()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onComplete() {
|
|
||||||
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun runAllThings() {
|
private fun runAllThings() {
|
||||||
if (conversationNameTextView != null) {
|
/*if (conversationNameTextView != null) {
|
||||||
conversationNameTextView!!.text = currentConversation!!.displayName
|
conversationNameTextView!!.text = currentConversation!!.displayName
|
||||||
}
|
}
|
||||||
|
|
||||||
loadAvatar()
|
loadAvatar()
|
||||||
checkIfAnyParticipantsRemainInRoom()
|
checkIfAnyParticipantsRemainInRoom()
|
||||||
showAnswerControls()
|
showAnswerControls()*/
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("LongLogTag")
|
@SuppressLint("LongLogTag")
|
||||||
|
@ -55,7 +55,7 @@ import com.nextcloud.talk.newarch.domain.usecases.GetNotificationUseCase
|
|||||||
import com.nextcloud.talk.newarch.domain.usecases.base.UseCaseResponse
|
import com.nextcloud.talk.newarch.domain.usecases.base.UseCaseResponse
|
||||||
import com.nextcloud.talk.newarch.utils.Images
|
import com.nextcloud.talk.newarch.utils.Images
|
||||||
import com.nextcloud.talk.newarch.utils.MagicJson
|
import com.nextcloud.talk.newarch.utils.MagicJson
|
||||||
import com.nextcloud.talk.newarch.utils.NextcloudRepositoryWithNoCookies
|
import com.nextcloud.talk.newarch.utils.ComponentsWithEmptyCookieJar
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
import com.nextcloud.talk.utils.NotificationUtils
|
import com.nextcloud.talk.utils.NotificationUtils
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys
|
import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||||
@ -73,7 +73,7 @@ class MessageNotificationWorker(
|
|||||||
workerParams: WorkerParameters
|
workerParams: WorkerParameters
|
||||||
) : CoroutineWorker(context, workerParams), KoinComponent {
|
) : CoroutineWorker(context, workerParams), KoinComponent {
|
||||||
val appPreferences: AppPreferences by inject()
|
val appPreferences: AppPreferences by inject()
|
||||||
private val nextcloudRepositoryWithNoCookies: NextcloudRepositoryWithNoCookies by inject()
|
private val componentsWithEmptyCookieJar: ComponentsWithEmptyCookieJar by inject()
|
||||||
private val apiErrorHandler: ApiErrorHandler by inject()
|
private val apiErrorHandler: ApiErrorHandler by inject()
|
||||||
|
|
||||||
override suspend fun doWork(): Result = coroutineScope {
|
override suspend fun doWork(): Result = coroutineScope {
|
||||||
@ -107,7 +107,7 @@ class MessageNotificationWorker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun showNotificationWithObjectData(coroutineScope: CoroutineScope, decryptedPushMessage: DecryptedPushMessage, signatureVerification: SignatureVerification, intent: Intent) {
|
private fun showNotificationWithObjectData(coroutineScope: CoroutineScope, decryptedPushMessage: DecryptedPushMessage, signatureVerification: SignatureVerification, intent: Intent) {
|
||||||
val nextcloudTalkRepository = nextcloudRepositoryWithNoCookies.getRepository()
|
val nextcloudTalkRepository = componentsWithEmptyCookieJar.getRepository()
|
||||||
val getNotificationUseCase = GetNotificationUseCase(nextcloudTalkRepository, apiErrorHandler)
|
val getNotificationUseCase = GetNotificationUseCase(nextcloudTalkRepository, apiErrorHandler)
|
||||||
getNotificationUseCase.invoke(coroutineScope, parametersOf(signatureVerification.userEntity, decryptedPushMessage.notificationId.toString()), object : UseCaseResponse<NotificationOverall> {
|
getNotificationUseCase.invoke(coroutineScope, parametersOf(signatureVerification.userEntity, decryptedPushMessage.notificationId.toString()), object : UseCaseResponse<NotificationOverall> {
|
||||||
override suspend fun onSuccess(result: NotificationOverall) {
|
override suspend fun onSuccess(result: NotificationOverall) {
|
||||||
@ -193,7 +193,6 @@ class MessageNotificationWorker(
|
|||||||
else -> {
|
else -> {
|
||||||
// one to one and unknown
|
// one to one and unknown
|
||||||
BitmapFactory.decodeResource(applicationContext.resources, R.drawable.ic_chat_black_24dp)
|
BitmapFactory.decodeResource(applicationContext.resources, R.drawable.ic_chat_black_24dp)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +99,8 @@ class ConversationsRepositoryImpl(val conversationsDao: ConversationsDao) :
|
|||||||
|
|
||||||
override suspend fun saveConversationsForUser(
|
override suspend fun saveConversationsForUser(
|
||||||
userId: Long,
|
userId: Long,
|
||||||
conversations: List<Conversation>
|
conversations: List<Conversation>,
|
||||||
|
deleteOutdated: Boolean
|
||||||
): List<Long> {
|
): List<Long> {
|
||||||
val map = conversations.map {
|
val map = conversations.map {
|
||||||
it.toConversationEntity()
|
it.toConversationEntity()
|
||||||
@ -108,7 +109,8 @@ class ConversationsRepositoryImpl(val conversationsDao: ConversationsDao) :
|
|||||||
return conversationsDao
|
return conversationsDao
|
||||||
.updateConversationsForUser(
|
.updateConversationsForUser(
|
||||||
userId,
|
userId,
|
||||||
map.toTypedArray()
|
map.toTypedArray(),
|
||||||
|
deleteOutdated
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ class NextcloudTalkRepositoryImpl(private val apiService: ApiService) : Nextclou
|
|||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getConversationForUser(user: UserNgEntity, conversationToken: String): ConversationOverall {
|
override suspend fun getConversationForUser(user: UserNgEntity, conversationToken: String): ConversationOverall {
|
||||||
return apiService.getConversation(user.getCredentials(), conversationToken)
|
return apiService.getConversation(user.getCredentials(), ApiUtils.getRoom(user.baseUrl, conversationToken))
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun joinConversationForUser(user: UserNgEntity, conversationToken: String, conversationPassword: String?): ConversationOverall {
|
override suspend fun joinConversationForUser(user: UserNgEntity, conversationToken: String, conversationPassword: String?): ConversationOverall {
|
||||||
|
@ -46,7 +46,7 @@ import com.nextcloud.talk.newarch.domain.repository.online.NextcloudTalkReposito
|
|||||||
import com.nextcloud.talk.newarch.utils.NetworkUtils
|
import com.nextcloud.talk.newarch.utils.NetworkUtils
|
||||||
import com.nextcloud.talk.newarch.utils.NetworkUtils.GetProxyRunnable
|
import com.nextcloud.talk.newarch.utils.NetworkUtils.GetProxyRunnable
|
||||||
import com.nextcloud.talk.newarch.utils.NetworkUtils.MagicAuthenticator
|
import com.nextcloud.talk.newarch.utils.NetworkUtils.MagicAuthenticator
|
||||||
import com.nextcloud.talk.newarch.utils.NextcloudRepositoryWithNoCookies
|
import com.nextcloud.talk.newarch.utils.ComponentsWithEmptyCookieJar
|
||||||
import com.nextcloud.talk.utils.LoggingUtils
|
import com.nextcloud.talk.utils.LoggingUtils
|
||||||
import com.nextcloud.talk.utils.preferences.AppPreferences
|
import com.nextcloud.talk.utils.preferences.AppPreferences
|
||||||
import com.nextcloud.talk.utils.singletons.AvatarStatusCodeHolder
|
import com.nextcloud.talk.utils.singletons.AvatarStatusCodeHolder
|
||||||
@ -88,13 +88,13 @@ val NetworkModule = module {
|
|||||||
single { createOkHttpClient(androidContext(), get(), get(), get(), get(), get(), get(), get()) }
|
single { createOkHttpClient(androidContext(), get(), get(), get(), get(), get(), get(), get()) }
|
||||||
factory { createApiErrorHandler() }
|
factory { createApiErrorHandler() }
|
||||||
single { createNextcloudTalkRepository(get()) }
|
single { createNextcloudTalkRepository(get()) }
|
||||||
single { createNexcloudRepositoryWithNoCookies(get(), get()) }
|
single { createComponentsWithEmptyCookieJar(get(), get(), androidApplication()) }
|
||||||
single { createImageLoader(androidApplication(), get()) }
|
single { createImageLoader(androidApplication(), get()) }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createNexcloudRepositoryWithNoCookies(okHttpClient: OkHttpClient, retrofit: Retrofit): NextcloudRepositoryWithNoCookies {
|
fun createComponentsWithEmptyCookieJar(okHttpClient: OkHttpClient, retrofit: Retrofit, androidApplication: Application): ComponentsWithEmptyCookieJar {
|
||||||
return NextcloudRepositoryWithNoCookies(okHttpClient, retrofit)
|
return ComponentsWithEmptyCookieJar(okHttpClient, retrofit, androidApplication)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createCookieManager(): CookieManager {
|
fun createCookieManager(): CookieManager {
|
||||||
|
@ -28,12 +28,12 @@ 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(userId: Long, token: String): Conversation?
|
||||||
suspend fun clearConversationsForUser(userId: Long)
|
suspend fun clearConversationsForUser(userId: Long)
|
||||||
suspend fun saveConversationsForUser(
|
suspend fun saveConversationsForUser(
|
||||||
userId: Long,
|
userId: Long,
|
||||||
conversations: List<Conversation>
|
conversations: List<Conversation>,
|
||||||
|
deleteOutdated: Boolean
|
||||||
): List<Long>
|
): List<Long>
|
||||||
|
|
||||||
suspend fun setChangingValueForConversation(
|
suspend fun setChangingValueForConversation(
|
||||||
|
@ -203,7 +203,7 @@ class ConversationsListViewModel constructor(
|
|||||||
|
|
||||||
conversationsRepository.saveConversationsForUser(
|
conversationsRepository.saveConversationsForUser(
|
||||||
internalUserId,
|
internalUserId,
|
||||||
mutableList)
|
mutableList, true)
|
||||||
messageData = ""
|
messageData = ""
|
||||||
conversationsLoadingLock.unlock()
|
conversationsLoadingLock.unlock()
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,8 @@ abstract class ConversationsDao {
|
|||||||
@Transaction
|
@Transaction
|
||||||
open suspend fun updateConversationsForUser(
|
open suspend fun updateConversationsForUser(
|
||||||
userId: Long,
|
userId: Long,
|
||||||
newConversations: Array<ConversationEntity>
|
newConversations: Array<ConversationEntity>,
|
||||||
|
deleteOutdated: Boolean
|
||||||
): List<Long> {
|
): List<Long> {
|
||||||
val timestamp = System.currentTimeMillis()
|
val timestamp = System.currentTimeMillis()
|
||||||
|
|
||||||
@ -96,7 +97,9 @@ abstract class ConversationsDao {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val list = saveConversationsWithInsert(*conversationsWithTimestampApplied.toTypedArray())
|
val list = saveConversationsWithInsert(*conversationsWithTimestampApplied.toTypedArray())
|
||||||
|
if (deleteOutdated) {
|
||||||
deleteConversationsForUserWithTimestamp(userId, timestamp)
|
deleteConversationsForUserWithTimestamp(userId, timestamp)
|
||||||
|
}
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ import android.app.Notification
|
|||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.app.Service
|
import android.app.Service
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.graphics.BitmapFactory
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
import android.media.AudioAttributes
|
import android.media.AudioAttributes
|
||||||
import android.media.AudioManager
|
import android.media.AudioManager
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
@ -13,32 +15,47 @@ import android.util.Base64
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
|
import androidx.core.graphics.drawable.toBitmap
|
||||||
import androidx.emoji.text.EmojiCompat
|
import androidx.emoji.text.EmojiCompat
|
||||||
import androidx.work.Data
|
import androidx.work.Data
|
||||||
import androidx.work.OneTimeWorkRequest
|
import androidx.work.OneTimeWorkRequest
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
|
import coil.target.Target
|
||||||
|
import coil.transform.CircleCropTransformation
|
||||||
import com.bluelinelabs.logansquare.LoganSquare
|
import com.bluelinelabs.logansquare.LoganSquare
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.activities.MagicCallActivity
|
import com.nextcloud.talk.activities.MagicCallActivity
|
||||||
import com.nextcloud.talk.jobs.MessageNotificationWorker
|
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.ConversationOverall
|
||||||
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.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.repository.offline.UsersRepository
|
||||||
|
import com.nextcloud.talk.newarch.domain.usecases.GetConversationUseCase
|
||||||
|
import com.nextcloud.talk.newarch.domain.usecases.base.UseCaseResponse
|
||||||
|
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
||||||
|
import com.nextcloud.talk.newarch.utils.ComponentsWithEmptyCookieJar
|
||||||
|
import com.nextcloud.talk.newarch.utils.Images
|
||||||
import com.nextcloud.talk.newarch.utils.MagicJson
|
import com.nextcloud.talk.newarch.utils.MagicJson
|
||||||
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
import com.nextcloud.talk.utils.NotificationUtils
|
import com.nextcloud.talk.utils.NotificationUtils
|
||||||
import com.nextcloud.talk.utils.PushUtils
|
import com.nextcloud.talk.utils.PushUtils
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys
|
import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||||
import com.nextcloud.talk.utils.preferences.AppPreferences
|
import com.nextcloud.talk.utils.preferences.AppPreferences
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlinx.serialization.toUtf8Bytes
|
||||||
import org.koin.core.KoinComponent
|
import org.koin.core.KoinComponent
|
||||||
import org.koin.core.inject
|
import org.koin.core.inject
|
||||||
|
import org.koin.core.parameter.parametersOf
|
||||||
|
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.zip.CRC32
|
||||||
import javax.crypto.Cipher
|
import javax.crypto.Cipher
|
||||||
import javax.crypto.NoSuchPaddingException
|
import javax.crypto.NoSuchPaddingException
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
@ -51,15 +68,19 @@ class CallService : Service(), KoinComponent, CoroutineScope {
|
|||||||
|
|
||||||
val appPreferences: AppPreferences by inject()
|
val appPreferences: AppPreferences by inject()
|
||||||
val usersRepository: UsersRepository by inject()
|
val usersRepository: UsersRepository by inject()
|
||||||
|
val conversationsRepository: ConversationsRepository by inject()
|
||||||
|
val retrofit: Retrofit by inject()
|
||||||
|
val componentsWithEmptyCookieJar: ComponentsWithEmptyCookieJar by inject()
|
||||||
|
val apiErrorHandler: ApiErrorHandler by inject()
|
||||||
|
|
||||||
var currentlyActiveNotificationId = 0L
|
private var activeNotification = ""
|
||||||
|
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
intent?.let {
|
intent?.let {
|
||||||
if (intent.action == BundleKeys.KEY_INCOMING_PUSH_MESSSAGE) {
|
if (it.action == BundleKeys.KEY_INCOMING_PUSH_MESSSAGE) {
|
||||||
decryptMessage(intent.getStringExtra(BundleKeys.KEY_ENCRYPTED_SUBJECT), intent.getStringExtra(BundleKeys.KEY_ENCRYPTED_SIGNATURE))
|
decryptMessage(it.getStringExtra(BundleKeys.KEY_ENCRYPTED_SUBJECT), it.getStringExtra(BundleKeys.KEY_ENCRYPTED_SIGNATURE))
|
||||||
} else if (intent.action == BundleKeys.KEY_REJECT_INCOMING_CALL || intent.action == BundleKeys.KEY_SHOW_INCOMING_CALL) {
|
} else if (it.action == BundleKeys.KEY_REJECT_INCOMING_CALL || it.action == BundleKeys.KEY_SHOW_INCOMING_CALL) {
|
||||||
if (intent.getLongExtra(BundleKeys.KEY_NOTIFICATION_ID, -1L) == currentlyActiveNotificationId) {
|
if (it.getStringExtra(BundleKeys.KEY_ACTIVE_NOTIFICATION) == activeNotification) {
|
||||||
stopForeground(true)
|
stopForeground(true)
|
||||||
} else {
|
} else {
|
||||||
// do nothing? :D
|
// do nothing? :D
|
||||||
@ -89,6 +110,8 @@ class CallService : Service(), KoinComponent, CoroutineScope {
|
|||||||
cipher.init(Cipher.DECRYPT_MODE, privateKey)
|
cipher.init(Cipher.DECRYPT_MODE, privateKey)
|
||||||
val decryptedSubject = cipher.doFinal(base64DecodedSubject)
|
val decryptedSubject = cipher.doFinal(base64DecodedSubject)
|
||||||
decryptedPushMessage = LoganSquare.parse(String(decryptedSubject), DecryptedPushMessage::class.java)
|
decryptedPushMessage = LoganSquare.parse(String(decryptedSubject), DecryptedPushMessage::class.java)
|
||||||
|
val conversation = getConversationForTokenAndUser(signatureVerification.userEntity!!, decryptedPushMessage.id!!)
|
||||||
|
|
||||||
decryptedPushMessage.apply {
|
decryptedPushMessage.apply {
|
||||||
when {
|
when {
|
||||||
delete -> {
|
delete -> {
|
||||||
@ -98,14 +121,14 @@ class CallService : Service(), KoinComponent, CoroutineScope {
|
|||||||
NotificationUtils.cancelAllNotificationsForAccount(applicationContext, signatureVerification.userEntity!!)
|
NotificationUtils.cancelAllNotificationsForAccount(applicationContext, signatureVerification.userEntity!!)
|
||||||
}
|
}
|
||||||
type == "call" -> {
|
type == "call" -> {
|
||||||
val timestamp = System.currentTimeMillis()
|
if (conversation != null) {
|
||||||
|
val generatedActiveNotificationId = signatureVerification.userEntity!!.id.toString() + "@" + decryptedPushMessage.notificationId!!.toString()
|
||||||
val fullScreenIntent = Intent(applicationContext, MagicCallActivity::class.java)
|
val fullScreenIntent = Intent(applicationContext, MagicCallActivity::class.java)
|
||||||
fullScreenIntent.action = BundleKeys.KEY_OPEN_INCOMING_CALL
|
fullScreenIntent.action = BundleKeys.KEY_OPEN_INCOMING_CALL
|
||||||
val bundle = Bundle()
|
val bundle = Bundle()
|
||||||
bundle.putString(BundleKeys.KEY_CONVERSATION_TOKEN, decryptedPushMessage.id)
|
bundle.putString(BundleKeys.KEY_CONVERSATION_TOKEN, decryptedPushMessage.id)
|
||||||
bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, signatureVerification.userEntity)
|
bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, signatureVerification.userEntity)
|
||||||
bundle.putLong(BundleKeys.KEY_NOTIFICATION_ID, timestamp)
|
bundle.putString(BundleKeys.KEY_ACTIVE_NOTIFICATION, generatedActiveNotificationId)
|
||||||
fullScreenIntent.putExtras(bundle)
|
fullScreenIntent.putExtras(bundle)
|
||||||
|
|
||||||
fullScreenIntent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_NEW_TASK
|
fullScreenIntent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
@ -125,22 +148,37 @@ class CallService : Service(), KoinComponent, CoroutineScope {
|
|||||||
|
|
||||||
val userBaseUrl = Uri.parse(signatureVerification.userEntity!!.baseUrl).toString()
|
val userBaseUrl = Uri.parse(signatureVerification.userEntity!!.baseUrl).toString()
|
||||||
|
|
||||||
|
var largeIcon = when (conversation.type) {
|
||||||
|
Conversation.ConversationType.PUBLIC_CONVERSATION -> {
|
||||||
|
BitmapFactory.decodeResource(applicationContext.resources, R.drawable.ic_link_black_24px)
|
||||||
|
}
|
||||||
|
Conversation.ConversationType.GROUP_CONVERSATION -> {
|
||||||
|
BitmapFactory.decodeResource(applicationContext.resources, R.drawable.ic_people_group_black_24px)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
// one to one and unknown
|
||||||
|
BitmapFactory.decodeResource(applicationContext.resources, R.drawable.ic_user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val rejectCallIntent = Intent(this@CallService, CallService::class.java)
|
val rejectCallIntent = Intent(this@CallService, CallService::class.java)
|
||||||
rejectCallIntent.action = BundleKeys.KEY_REJECT_INCOMING_CALL
|
rejectCallIntent.action = BundleKeys.KEY_REJECT_INCOMING_CALL
|
||||||
rejectCallIntent.putExtra(BundleKeys.KEY_NOTIFICATION_ID, timestamp)
|
rejectCallIntent.putExtra(BundleKeys.KEY_ACTIVE_NOTIFICATION, generatedActiveNotificationId)
|
||||||
val rejectCallPendingIntent = PendingIntent.getService(this@CallService, 0, rejectCallIntent, 0)
|
val rejectCallPendingIntent = PendingIntent.getService(this@CallService, 0, rejectCallIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
val notificationBuilder = NotificationCompat.Builder(this@CallService, notificationChannelId)
|
val notificationBuilder = NotificationCompat.Builder(this@CallService, notificationChannelId)
|
||||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||||
.setCategory(NotificationCompat.CATEGORY_CALL)
|
.setCategory(NotificationCompat.CATEGORY_CALL)
|
||||||
.setSmallIcon(R.drawable.ic_call_black_24dp)
|
.setSmallIcon(R.drawable.ic_call_black_24dp)
|
||||||
|
.setLargeIcon(largeIcon)
|
||||||
.setSubText(userBaseUrl)
|
.setSubText(userBaseUrl)
|
||||||
.setShowWhen(true)
|
.setShowWhen(true)
|
||||||
.setWhen(timestamp)
|
.setWhen(System.currentTimeMillis())
|
||||||
.setContentTitle(EmojiCompat.get().process(decryptedPushMessage.subject.toString()))
|
.setContentTitle(EmojiCompat.get().process(decryptedPushMessage.subject.toString()))
|
||||||
.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)
|
//.setTimeoutAfter(45000L)
|
||||||
|
.setContentIntent(fullScreenPendingIntent)
|
||||||
.setFullScreenIntent(fullScreenPendingIntent, true)
|
.setFullScreenIntent(fullScreenPendingIntent, true)
|
||||||
.setSound(NotificationUtils.getCallSoundUri(applicationContext, appPreferences), AudioManager.STREAM_RING)
|
.setSound(NotificationUtils.getCallSoundUri(applicationContext, appPreferences), AudioManager.STREAM_RING)
|
||||||
|
|
||||||
@ -148,13 +186,38 @@ class CallService : Service(), KoinComponent, CoroutineScope {
|
|||||||
notificationBuilder.setVibrate(vibrationEffect)
|
notificationBuilder.setVibrate(vibrationEffect)
|
||||||
}
|
}
|
||||||
|
|
||||||
val notification = notificationBuilder.build()
|
|
||||||
notification.flags = notification.flags or Notification.FLAG_INSISTENT
|
|
||||||
//checkIfCallIsActive(signatureVerification, decryptedPushMessage)
|
//checkIfCallIsActive(signatureVerification, decryptedPushMessage)
|
||||||
currentlyActiveNotificationId = timestamp
|
|
||||||
startForeground(timestamp.toInt(), notification)
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(error: Drawable?) {
|
||||||
|
super.onError(error)
|
||||||
|
showNotification(notificationBuilder, signatureVerification.userEntity!!, decryptedPushMessage.notificationId!!, generatedActiveNotificationId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val avatarUrl = ApiUtils.getUrlForAvatarWithName(signatureVerification.userEntity!!.baseUrl, conversation.name, R.dimen.avatar_size)
|
||||||
|
val imageLoader = componentsWithEmptyCookieJar.getImageLoader()
|
||||||
|
|
||||||
|
val request = Images().getRequestForUrl(
|
||||||
|
imageLoader, applicationContext, avatarUrl, signatureVerification.userEntity,
|
||||||
|
target, null, CircleCropTransformation())
|
||||||
|
|
||||||
|
imageLoader.load(request)
|
||||||
|
} else {
|
||||||
|
showNotification(notificationBuilder, signatureVerification.userEntity!!, decryptedPushMessage.notificationId!!, generatedActiveNotificationId)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
|
if (conversation != null) {
|
||||||
val json = Json(MagicJson.customJsonConfiguration)
|
val json = Json(MagicJson.customJsonConfiguration)
|
||||||
|
|
||||||
val messageData = Data.Builder()
|
val messageData = Data.Builder()
|
||||||
@ -166,6 +229,7 @@ class CallService : Service(), KoinComponent, CoroutineScope {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// do absolutely nothing
|
// do absolutely nothing
|
||||||
}
|
}
|
||||||
@ -182,6 +246,37 @@ class CallService : Service(), KoinComponent, CoroutineScope {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun getConversationForTokenAndUser(user: UserNgEntity, conversationToken: String): Conversation? {
|
||||||
|
var conversation = conversationsRepository.getConversationForUserWithToken(user.id, conversationToken)
|
||||||
|
if (conversation == null) {
|
||||||
|
val getConversationUseCase = GetConversationUseCase(componentsWithEmptyCookieJar.getRepository(), apiErrorHandler)
|
||||||
|
runBlocking {
|
||||||
|
getConversationUseCase.invoke(this, parametersOf(user, conversationToken), object : UseCaseResponse<ConversationOverall> {
|
||||||
|
override suspend fun onSuccess(result: ConversationOverall) {
|
||||||
|
val internalConversation = result.ocs.data
|
||||||
|
conversationsRepository.saveConversationsForUser(user.id, listOf(internalConversation), false)
|
||||||
|
conversation = result.ocs.data
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun onError(errorModel: ErrorModel?) {
|
||||||
|
conversation = null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return conversation
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showNotification(builder: NotificationCompat.Builder, user: UserNgEntity, internalNotificationId: Long, generatedNotificationId: String) {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onBind(intent: Intent?): IBinder? {
|
override fun onBind(intent: Intent?): IBinder? {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ class GlobalService constructor(usersRepository: UsersRepository,
|
|||||||
object : UseCaseResponse<ConversationOverall> {
|
object : UseCaseResponse<ConversationOverall> {
|
||||||
override suspend fun onSuccess(result: ConversationOverall) {
|
override suspend fun onSuccess(result: ConversationOverall) {
|
||||||
currentUser?.let {
|
currentUser?.let {
|
||||||
conversationsRepository.saveConversationsForUser(it.id, listOf(result.ocs.data))
|
conversationsRepository.saveConversationsForUser(it.id, listOf(result.ocs.data), false)
|
||||||
globalServiceInterface.gotConversationInfoForUser(it, result.ocs.data, GlobalServiceInterface.OperationStatus.STATUS_OK)
|
globalServiceInterface.gotConversationInfoForUser(it, result.ocs.data, GlobalServiceInterface.OperationStatus.STATUS_OK)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,7 +94,7 @@ class GlobalService constructor(usersRepository: UsersRepository,
|
|||||||
object : UseCaseResponse<ConversationOverall> {
|
object : UseCaseResponse<ConversationOverall> {
|
||||||
override suspend fun onSuccess(result: ConversationOverall) {
|
override suspend fun onSuccess(result: ConversationOverall) {
|
||||||
currentUser?.let {
|
currentUser?.let {
|
||||||
conversationsRepository.saveConversationsForUser(it.id, listOf(result.ocs.data))
|
conversationsRepository.saveConversationsForUser(it.id, listOf(result.ocs.data), false)
|
||||||
currentConversation = conversationsRepository.getConversationForUserWithToken(it.id, result.ocs!!.data!!.token!!)
|
currentConversation = conversationsRepository.getConversationForUserWithToken(it.id, result.ocs!!.data!!.token!!)
|
||||||
globalServiceInterface.joinedConversationForUser(it, currentConversation, GlobalServiceInterface.OperationStatus.STATUS_OK)
|
globalServiceInterface.joinedConversationForUser(it, currentConversation, GlobalServiceInterface.OperationStatus.STATUS_OK)
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,12 @@
|
|||||||
|
|
||||||
package com.nextcloud.talk.newarch.utils
|
package com.nextcloud.talk.newarch.utils
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import android.os.Build
|
||||||
|
import coil.ImageLoader
|
||||||
|
import coil.decode.GifDecoder
|
||||||
|
import coil.decode.ImageDecoderDecoder
|
||||||
|
import coil.decode.SvgDecoder
|
||||||
import com.nextcloud.talk.newarch.data.repository.online.NextcloudTalkRepositoryImpl
|
import com.nextcloud.talk.newarch.data.repository.online.NextcloudTalkRepositoryImpl
|
||||||
import com.nextcloud.talk.newarch.data.source.remote.ApiService
|
import com.nextcloud.talk.newarch.data.source.remote.ApiService
|
||||||
import com.nextcloud.talk.newarch.domain.repository.online.NextcloudTalkRepository
|
import com.nextcloud.talk.newarch.domain.repository.online.NextcloudTalkRepository
|
||||||
@ -31,14 +37,35 @@ import org.koin.core.KoinComponent
|
|||||||
import retrofit2.Retrofit
|
import retrofit2.Retrofit
|
||||||
import java.net.CookieManager
|
import java.net.CookieManager
|
||||||
|
|
||||||
class NextcloudRepositoryWithNoCookies(
|
class ComponentsWithEmptyCookieJar(
|
||||||
private val okHttpClient: OkHttpClient,
|
private val okHttpClient: OkHttpClient,
|
||||||
private val retrofit: Retrofit
|
private val retrofit: Retrofit,
|
||||||
|
private val androidApplication: Application
|
||||||
) : KoinComponent {
|
) : KoinComponent {
|
||||||
fun getRepository(): NextcloudTalkRepository {
|
fun getRepository(): NextcloudTalkRepository {
|
||||||
return NextcloudTalkRepositoryImpl(retrofit.newBuilder().client(
|
return NextcloudTalkRepositoryImpl(retrofit.newBuilder().client(getOkHttpClient())
|
||||||
okHttpClient.newBuilder().cookieJar(JavaNetCookieJar(CookieManager())).build())
|
|
||||||
.build().create(ApiService::class.java))
|
.build().create(ApiService::class.java))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getOkHttpClient(): OkHttpClient {
|
||||||
|
return okHttpClient.newBuilder().cookieJar(JavaNetCookieJar(CookieManager())).build()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getImageLoader(): ImageLoader {
|
||||||
|
return ImageLoader(androidApplication) {
|
||||||
|
availableMemoryPercentage(0.5)
|
||||||
|
bitmapPoolPercentage(0.5)
|
||||||
|
crossfade(false)
|
||||||
|
okHttpClient(getOkHttpClient())
|
||||||
|
componentRegistry {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||||
|
add(ImageDecoderDecoder())
|
||||||
|
} else {
|
||||||
|
add(GifDecoder())
|
||||||
|
}
|
||||||
|
add(SvgDecoder(androidApplication))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
@ -187,8 +187,7 @@ object NotificationUtils {
|
|||||||
|
|
||||||
if (notification != null && !notification.extras.isEmpty) {
|
if (notification != null && !notification.extras.isEmpty) {
|
||||||
if (conversationUser.id == notification.extras.getLong(
|
if (conversationUser.id == notification.extras.getLong(
|
||||||
BundleKeys.KEY_INTERNAL_USER_ID
|
BundleKeys.KEY_INTERNAL_USER_ID) && notificationId == notification.extras.getLong(BundleKeys.KEY_NOTIFICATION_ID)
|
||||||
) && notificationId == notification.extras.getLong(BundleKeys.KEY_NOTIFICATION_ID)
|
|
||||||
) {
|
) {
|
||||||
notificationManager.cancel(statusBarNotification.id)
|
notificationManager.cancel(statusBarNotification.id)
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,7 @@ object BundleKeys {
|
|||||||
val KEY_ACCOUNT = "KEY_ACCOUNT"
|
val KEY_ACCOUNT = "KEY_ACCOUNT"
|
||||||
val KEY_FILE_ID = "KEY_FILE_ID"
|
val KEY_FILE_ID = "KEY_FILE_ID"
|
||||||
val KEY_NOTIFICATION_ID = "KEY_NOTIFICATION_ID"
|
val KEY_NOTIFICATION_ID = "KEY_NOTIFICATION_ID"
|
||||||
|
val KEY_ACTIVE_NOTIFICATION = "KEY_ACTIVE_NOTIFICATION"
|
||||||
val KEY_CONVERSATION_ID = "KEY_CONVERSATION_ID"
|
val KEY_CONVERSATION_ID = "KEY_CONVERSATION_ID"
|
||||||
|
|
||||||
val KEY_ENCRYPTED_SUBJECT = "KEY_ENCRYPTED_SUBJECT"
|
val KEY_ENCRYPTED_SUBJECT = "KEY_ENCRYPTED_SUBJECT"
|
||||||
|
Loading…
Reference in New Issue
Block a user