mirror of
https://github.com/nextcloud/talk-android
synced 2025-06-20 03:59:35 +01:00
Merge pull request #3830 from nextcloud/bugfix/3315/fixEmptyCallNotificationScreen
Bugfix/3315/fix empty call notification screen
This commit is contained in:
commit
1d2f1bfeb7
@ -28,7 +28,6 @@ import com.nextcloud.talk.account.ServerSelectionActivity
|
||||
import com.nextcloud.talk.account.WebViewLoginActivity
|
||||
import com.nextcloud.talk.api.NcApi
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||
import com.nextcloud.talk.callnotification.CallNotificationActivity
|
||||
import com.nextcloud.talk.chat.ChatActivity
|
||||
import com.nextcloud.talk.conversationlist.ConversationsListActivity
|
||||
import com.nextcloud.talk.data.user.model.User
|
||||
@ -245,19 +244,13 @@ class MainActivity : BaseActivity(), ActionBarProvider {
|
||||
if (user != null && userManager.setUserAsActive(user).blockingGet()) {
|
||||
if (intent.hasExtra(BundleKeys.KEY_REMOTE_TALK_SHARE)) {
|
||||
if (intent.getBooleanExtra(BundleKeys.KEY_REMOTE_TALK_SHARE, false)) {
|
||||
val intent = Intent(this, InvitationsActivity::class.java)
|
||||
startActivity(intent)
|
||||
}
|
||||
} else if (intent.hasExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL)) {
|
||||
if (intent.getBooleanExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL, false)) {
|
||||
val callNotificationIntent = Intent(this, CallNotificationActivity::class.java)
|
||||
intent.extras?.let { callNotificationIntent.putExtras(it) }
|
||||
startActivity(callNotificationIntent)
|
||||
} else {
|
||||
val chatIntent = Intent(context, ChatActivity::class.java)
|
||||
chatIntent.putExtras(intent.extras!!)
|
||||
startActivity(chatIntent)
|
||||
val invitationsIntent = Intent(this, InvitationsActivity::class.java)
|
||||
startActivity(invitationsIntent)
|
||||
}
|
||||
} else {
|
||||
val chatIntent = Intent(context, ChatActivity::class.java)
|
||||
chatIntent.putExtras(intent.extras!!)
|
||||
startActivity(chatIntent)
|
||||
}
|
||||
} else {
|
||||
if (!appPreferences.isDbRoomMigrated) {
|
||||
|
@ -18,34 +18,25 @@ import android.util.Log
|
||||
import android.view.View
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import autodagger.AutoInjector
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.nextcloud.talk.R
|
||||
import com.nextcloud.talk.activities.CallActivity
|
||||
import com.nextcloud.talk.activities.CallBaseActivity
|
||||
import com.nextcloud.talk.api.NcApi
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||
import com.nextcloud.talk.callnotification.viewmodel.CallNotificationViewModel
|
||||
import com.nextcloud.talk.data.user.model.User
|
||||
import com.nextcloud.talk.databinding.CallNotificationActivityBinding
|
||||
import com.nextcloud.talk.extensions.loadUserAvatar
|
||||
import com.nextcloud.talk.models.domain.ConversationModel
|
||||
import com.nextcloud.talk.models.domain.ConversationType
|
||||
import com.nextcloud.talk.models.json.participants.Participant
|
||||
import com.nextcloud.talk.users.UserManager
|
||||
import com.nextcloud.talk.utils.ApiUtils
|
||||
import com.nextcloud.talk.utils.SpreedFeatures
|
||||
import com.nextcloud.talk.utils.ConversationUtils
|
||||
import com.nextcloud.talk.utils.NotificationUtils
|
||||
import com.nextcloud.talk.utils.ParticipantPermissions
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_CALL_VOICE_ONLY
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_CONVERSATION_NAME
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
|
||||
import com.nextcloud.talk.utils.CapabilitiesUtil.hasSpreedFeatureCapability
|
||||
import io.reactivex.disposables.Disposable
|
||||
import okhttp3.Cache
|
||||
import java.io.IOException
|
||||
import javax.inject.Inject
|
||||
@ -64,49 +55,110 @@ class CallNotificationActivity : CallBaseActivity() {
|
||||
@Inject
|
||||
lateinit var userManager: UserManager
|
||||
|
||||
@Inject
|
||||
lateinit var viewModelFactory: ViewModelProvider.Factory
|
||||
|
||||
lateinit var callNotificationViewModel: CallNotificationViewModel
|
||||
|
||||
private val disposablesList: MutableList<Disposable> = ArrayList()
|
||||
private var originalBundle: Bundle? = null
|
||||
private var roomToken: String? = null
|
||||
private var notificationTimestamp: Int? = null
|
||||
private var displayName: String? = null
|
||||
private var callFlag: Int = 0
|
||||
private var isOneToOneCall: Boolean = true
|
||||
private var conversationName: String? = null
|
||||
private var internalUserId: Long = -1
|
||||
|
||||
private var userBeingCalled: User? = null
|
||||
private var credentials: String? = null
|
||||
var currentConversation: ConversationModel? = null
|
||||
private var leavingScreen = false
|
||||
private var handler: Handler? = null
|
||||
private var binding: CallNotificationActivityBinding? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
Log.d(TAG, "onCreate")
|
||||
super.onCreate(savedInstanceState)
|
||||
sharedApplication!!.componentApplication.inject(this)
|
||||
binding = CallNotificationActivityBinding.inflate(layoutInflater)
|
||||
setContentView(binding!!.root)
|
||||
hideNavigationIfNoPipAvailable()
|
||||
val extras = intent.extras
|
||||
roomToken = extras!!.getString(KEY_ROOM_TOKEN, "")
|
||||
notificationTimestamp = extras.getInt(BundleKeys.KEY_NOTIFICATION_TIMESTAMP)
|
||||
|
||||
val internalUserId = extras.getLong(BundleKeys.KEY_INTERNAL_USER_ID)
|
||||
handleExtras()
|
||||
userBeingCalled = userManager.getUserWithId(internalUserId).blockingGet()
|
||||
|
||||
originalBundle = extras
|
||||
credentials = ApiUtils.getCredentials(userBeingCalled!!.username, userBeingCalled!!.token)
|
||||
setupCallTypeDescription()
|
||||
binding!!.conversationNameTextView.text = displayName
|
||||
setupAvatar(isOneToOneCall, conversationName)
|
||||
initClickListeners()
|
||||
setupNotificationCanceledRoutine()
|
||||
}
|
||||
|
||||
callNotificationViewModel = ViewModelProvider(this, viewModelFactory)[CallNotificationViewModel::class.java]
|
||||
private fun handleExtras() {
|
||||
val extras = intent.extras!!
|
||||
roomToken = extras.getString(KEY_ROOM_TOKEN, "")
|
||||
notificationTimestamp = extras.getInt(BundleKeys.KEY_NOTIFICATION_TIMESTAMP)
|
||||
displayName = extras.getString(BundleKeys.KEY_CONVERSATION_DISPLAY_NAME, "")
|
||||
callFlag = extras.getInt(BundleKeys.KEY_CALL_FLAG)
|
||||
isOneToOneCall = extras.getBoolean(BundleKeys.KEY_ROOM_ONE_TO_ONE)
|
||||
conversationName = extras.getString(BundleKeys.KEY_CONVERSATION_NAME, "")
|
||||
internalUserId = extras.getLong(BundleKeys.KEY_INTERNAL_USER_ID)
|
||||
}
|
||||
|
||||
initObservers()
|
||||
|
||||
if (userManager.setUserAsActive(userBeingCalled!!).blockingGet()) {
|
||||
setCallDescriptionText()
|
||||
callNotificationViewModel.getRoom(userBeingCalled!!, roomToken!!)
|
||||
private fun setupAvatar(isOneToOneCall: Boolean, conversationName: String?) {
|
||||
if (isOneToOneCall) {
|
||||
binding!!.avatarImageView.loadUserAvatar(
|
||||
userBeingCalled!!,
|
||||
conversationName!!,
|
||||
true,
|
||||
false
|
||||
)
|
||||
} else {
|
||||
binding!!.avatarImageView.setImageResource(R.drawable.ic_circular_group)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupCallTypeDescription() {
|
||||
val apiVersion = ApiUtils.getConversationApiVersion(
|
||||
userBeingCalled!!,
|
||||
intArrayOf(
|
||||
ApiUtils.API_V4,
|
||||
ApiUtils.API_V3,
|
||||
1
|
||||
)
|
||||
)
|
||||
|
||||
if (apiVersion >= ApiUtils.API_V3) {
|
||||
val hasCallFlags = hasSpreedFeatureCapability(
|
||||
userBeingCalled?.capabilities?.spreedCapability!!,
|
||||
SpreedFeatures.CONVERSATION_CALL_FLAGS
|
||||
)
|
||||
if (hasCallFlags) {
|
||||
if (isInCallWithVideo(callFlag)) {
|
||||
binding!!.incomingCallVoiceOrVideoTextView.text = String.format(
|
||||
resources.getString(R.string.nc_call_video),
|
||||
resources.getString(R.string.nc_app_product_name)
|
||||
)
|
||||
} else {
|
||||
binding!!.incomingCallVoiceOrVideoTextView.text = String.format(
|
||||
resources.getString(R.string.nc_call_voice),
|
||||
resources.getString(R.string.nc_app_product_name)
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val callDescriptionWithoutTypeInfo = String.format(
|
||||
resources.getString(R.string.nc_call_unknown),
|
||||
resources.getString(R.string.nc_app_product_name)
|
||||
)
|
||||
binding!!.incomingCallVoiceOrVideoTextView.text = callDescriptionWithoutTypeInfo
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupNotificationCanceledRoutine() {
|
||||
val notificationHandler = Handler(Looper.getMainLooper())
|
||||
notificationHandler.post(object : Runnable {
|
||||
override fun run() {
|
||||
if (NotificationUtils.isNotificationVisible(context, notificationTimestamp!!.toInt())) {
|
||||
notificationHandler.postDelayed(this, ONE_SECOND)
|
||||
} else {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
if (handler == null) {
|
||||
@ -122,136 +174,26 @@ class CallNotificationActivity : CallBaseActivity() {
|
||||
private fun initClickListeners() {
|
||||
binding!!.callAnswerVoiceOnlyView.setOnClickListener {
|
||||
Log.d(TAG, "accept call (voice only)")
|
||||
originalBundle!!.putBoolean(KEY_CALL_VOICE_ONLY, true)
|
||||
intent.extras!!.putBoolean(KEY_CALL_VOICE_ONLY, true)
|
||||
proceedToCall()
|
||||
}
|
||||
binding!!.callAnswerCameraView.setOnClickListener {
|
||||
Log.d(TAG, "accept call (with video)")
|
||||
originalBundle!!.putBoolean(KEY_CALL_VOICE_ONLY, false)
|
||||
intent.extras!!.putBoolean(KEY_CALL_VOICE_ONLY, false)
|
||||
proceedToCall()
|
||||
}
|
||||
binding!!.hangupButton.setOnClickListener { hangup() }
|
||||
}
|
||||
|
||||
private fun initObservers() {
|
||||
val apiVersion = ApiUtils.getConversationApiVersion(
|
||||
userBeingCalled!!,
|
||||
intArrayOf(
|
||||
ApiUtils.API_V4,
|
||||
ApiUtils.API_V3,
|
||||
1
|
||||
)
|
||||
)
|
||||
|
||||
callNotificationViewModel.getRoomViewState.observe(this) { state ->
|
||||
when (state) {
|
||||
is CallNotificationViewModel.GetRoomSuccessState -> {
|
||||
currentConversation = state.conversationModel
|
||||
|
||||
binding!!.conversationNameTextView.text = currentConversation!!.displayName
|
||||
if (currentConversation!!.type === ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL) {
|
||||
binding!!.avatarImageView.loadUserAvatar(
|
||||
userBeingCalled!!,
|
||||
currentConversation!!.name!!,
|
||||
true,
|
||||
false
|
||||
)
|
||||
} else {
|
||||
binding!!.avatarImageView.setImageResource(R.drawable.ic_circular_group)
|
||||
}
|
||||
|
||||
val notificationHandler = Handler(Looper.getMainLooper())
|
||||
notificationHandler.post(object : Runnable {
|
||||
override fun run() {
|
||||
if (NotificationUtils.isNotificationVisible(context, notificationTimestamp!!.toInt())) {
|
||||
notificationHandler.postDelayed(this, ONE_SECOND)
|
||||
} else {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
showAnswerControls()
|
||||
|
||||
if (apiVersion >= ApiUtils.API_V3) {
|
||||
val hasCallFlags = hasSpreedFeatureCapability(
|
||||
userBeingCalled?.capabilities?.spreedCapability!!,
|
||||
SpreedFeatures.CONVERSATION_CALL_FLAGS
|
||||
)
|
||||
if (hasCallFlags) {
|
||||
if (isInCallWithVideo(currentConversation!!.callFlag)) {
|
||||
binding!!.incomingCallVoiceOrVideoTextView.text = String.format(
|
||||
resources.getString(R.string.nc_call_video),
|
||||
resources.getString(R.string.nc_app_product_name)
|
||||
)
|
||||
} else {
|
||||
binding!!.incomingCallVoiceOrVideoTextView.text = String.format(
|
||||
resources.getString(R.string.nc_call_voice),
|
||||
resources.getString(R.string.nc_app_product_name)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
initClickListeners()
|
||||
}
|
||||
|
||||
is CallNotificationViewModel.GetRoomErrorState -> {
|
||||
Snackbar.make(binding!!.root, R.string.nc_common_error_sorry, Snackbar.LENGTH_LONG).show()
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setCallDescriptionText() {
|
||||
val callDescriptionWithoutTypeInfo = String.format(
|
||||
resources.getString(R.string.nc_call_unknown),
|
||||
resources.getString(R.string.nc_app_product_name)
|
||||
)
|
||||
binding!!.incomingCallVoiceOrVideoTextView.text = callDescriptionWithoutTypeInfo
|
||||
}
|
||||
|
||||
private fun showAnswerControls() {
|
||||
binding!!.callAnswerCameraView.visibility = View.VISIBLE
|
||||
binding!!.callAnswerVoiceOnlyView.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
private fun hangup() {
|
||||
leavingScreen = true
|
||||
dispose()
|
||||
finish()
|
||||
}
|
||||
|
||||
private fun proceedToCall() {
|
||||
if (currentConversation != null) {
|
||||
originalBundle!!.putString(KEY_ROOM_TOKEN, currentConversation!!.token)
|
||||
originalBundle!!.putString(KEY_CONVERSATION_NAME, currentConversation!!.displayName)
|
||||
|
||||
val participantPermission = ParticipantPermissions(
|
||||
userBeingCalled!!.capabilities!!.spreedCapability!!,
|
||||
currentConversation!!
|
||||
)
|
||||
originalBundle!!.putBoolean(
|
||||
BundleKeys.KEY_PARTICIPANT_PERMISSION_CAN_PUBLISH_AUDIO,
|
||||
participantPermission.canPublishAudio()
|
||||
)
|
||||
originalBundle!!.putBoolean(
|
||||
BundleKeys.KEY_PARTICIPANT_PERMISSION_CAN_PUBLISH_VIDEO,
|
||||
participantPermission.canPublishVideo()
|
||||
)
|
||||
originalBundle!!.putBoolean(
|
||||
BundleKeys.KEY_IS_MODERATOR,
|
||||
ConversationUtils.isParticipantOwnerOrModerator(currentConversation!!)
|
||||
)
|
||||
|
||||
val intent = Intent(this, CallActivity::class.java)
|
||||
intent.putExtras(originalBundle!!)
|
||||
startActivity(intent)
|
||||
} else {
|
||||
Log.w(TAG, "conversation was still null when clicked to answer call. User has to click another time.")
|
||||
}
|
||||
val callIntent = Intent(this, CallActivity::class.java)
|
||||
callIntent.putExtras(intent.extras!!)
|
||||
startActivity(callIntent)
|
||||
}
|
||||
|
||||
private fun isInCallWithVideo(callFlag: Int): Boolean {
|
||||
@ -270,18 +212,9 @@ class CallNotificationActivity : CallBaseActivity() {
|
||||
handler!!.removeCallbacksAndMessages(null)
|
||||
handler = null
|
||||
}
|
||||
dispose()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
private fun dispose() {
|
||||
for (disposable in disposablesList) {
|
||||
if (!disposable.isDisposed) {
|
||||
disposable.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean, newConfig: Configuration) {
|
||||
super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig)
|
||||
@ -308,7 +241,7 @@ class CallNotificationActivity : CallBaseActivity() {
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG = "CallNotificationActivity"
|
||||
private val TAG = CallNotificationActivity::class.simpleName
|
||||
const val ONE_SECOND: Long = 1000
|
||||
}
|
||||
}
|
||||
|
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Nextcloud Talk - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2023 Marcel Hibbe <dev@mhibbe.de>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package com.nextcloud.talk.callnotification.viewmodel
|
||||
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.nextcloud.talk.chat.data.ChatRepository
|
||||
import com.nextcloud.talk.data.user.model.User
|
||||
import com.nextcloud.talk.models.domain.ConversationModel
|
||||
import io.reactivex.Observer
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.Disposable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import javax.inject.Inject
|
||||
|
||||
class CallNotificationViewModel @Inject constructor(private val repository: ChatRepository) :
|
||||
ViewModel() {
|
||||
|
||||
sealed interface ViewState
|
||||
|
||||
object GetRoomStartState : ViewState
|
||||
object GetRoomErrorState : ViewState
|
||||
open class GetRoomSuccessState(val conversationModel: ConversationModel) : ViewState
|
||||
|
||||
private val _getRoomViewState: MutableLiveData<ViewState> = MutableLiveData(GetRoomStartState)
|
||||
val getRoomViewState: LiveData<ViewState>
|
||||
get() = _getRoomViewState
|
||||
|
||||
fun getRoom(user: User, token: String) {
|
||||
_getRoomViewState.value = GetRoomStartState
|
||||
repository.getRoom(user, token)
|
||||
.subscribeOn(Schedulers.io())
|
||||
?.observeOn(AndroidSchedulers.mainThread())
|
||||
?.subscribe(GetRoomObserver())
|
||||
}
|
||||
|
||||
inner class GetRoomObserver : Observer<ConversationModel> {
|
||||
override fun onSubscribe(d: Disposable) {
|
||||
// unused atm
|
||||
}
|
||||
|
||||
override fun onNext(conversationModel: ConversationModel) {
|
||||
_getRoomViewState.value = GetRoomSuccessState(conversationModel)
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
Log.e(TAG, "Error when fetching room")
|
||||
_getRoomViewState.value = GetRoomErrorState
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
// unused atm
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = CallNotificationViewModel::class.simpleName
|
||||
}
|
||||
}
|
@ -9,7 +9,6 @@ package com.nextcloud.talk.dagger.modules
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.nextcloud.talk.callnotification.viewmodel.CallNotificationViewModel
|
||||
import com.nextcloud.talk.chat.viewmodels.ChatViewModel
|
||||
import com.nextcloud.talk.conversation.viewmodel.ConversationViewModel
|
||||
import com.nextcloud.talk.conversation.viewmodel.RenameConversationViewModel
|
||||
@ -119,11 +118,6 @@ abstract class ViewModelModule {
|
||||
@ViewModelKey(ChatViewModel::class)
|
||||
abstract fun chatViewModel(viewModel: ChatViewModel): ViewModel
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ViewModelKey(CallNotificationViewModel::class)
|
||||
abstract fun callNotificationViewModel(viewModel: CallNotificationViewModel): ViewModel
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ViewModelKey(ConversationInfoViewModel::class)
|
||||
|
@ -49,9 +49,11 @@ import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||
import com.nextcloud.talk.arbitrarystorage.ArbitraryStorageManager
|
||||
import com.nextcloud.talk.callnotification.CallNotificationActivity
|
||||
import com.nextcloud.talk.chat.data.ChatRepository
|
||||
import com.nextcloud.talk.models.SignatureVerification
|
||||
import com.nextcloud.talk.models.domain.ConversationModel
|
||||
import com.nextcloud.talk.models.domain.ConversationType
|
||||
import com.nextcloud.talk.models.json.chat.ChatUtils.Companion.getParsedMessage
|
||||
import com.nextcloud.talk.models.json.conversations.RoomOverall
|
||||
import com.nextcloud.talk.models.json.notifications.NotificationOverall
|
||||
import com.nextcloud.talk.models.json.participants.Participant
|
||||
import com.nextcloud.talk.models.json.participants.ParticipantsOverall
|
||||
@ -61,7 +63,9 @@ import com.nextcloud.talk.receivers.DirectReplyReceiver
|
||||
import com.nextcloud.talk.receivers.DismissRecordingAvailableReceiver
|
||||
import com.nextcloud.talk.receivers.MarkAsReadReceiver
|
||||
import com.nextcloud.talk.receivers.ShareRecordingToChatReceiver
|
||||
import com.nextcloud.talk.users.UserManager
|
||||
import com.nextcloud.talk.utils.ApiUtils
|
||||
import com.nextcloud.talk.utils.ConversationUtils
|
||||
import com.nextcloud.talk.utils.DoNotDisturbUtils.shouldPlaySound
|
||||
import com.nextcloud.talk.utils.NotificationUtils
|
||||
import com.nextcloud.talk.utils.NotificationUtils.cancelAllNotificationsForAccount
|
||||
@ -70,6 +74,7 @@ import com.nextcloud.talk.utils.NotificationUtils.findNotificationForRoom
|
||||
import com.nextcloud.talk.utils.NotificationUtils.getCallRingtoneUri
|
||||
import com.nextcloud.talk.utils.NotificationUtils.getMessageRingtoneUri
|
||||
import com.nextcloud.talk.utils.NotificationUtils.loadAvatarSync
|
||||
import com.nextcloud.talk.utils.ParticipantPermissions
|
||||
import com.nextcloud.talk.utils.PushUtils
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_DISMISS_RECORDING_URL
|
||||
@ -80,6 +85,7 @@ import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_NOTIFICATION_ID
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_NOTIFICATION_RESTRICT_DELETION
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_NOTIFICATION_TIMESTAMP
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_REMOTE_TALK_SHARE
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_ONE_TO_ONE
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_SHARE_RECORDING_TO_CHAT_URL
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_SYSTEM_NOTIFICATION_ID
|
||||
@ -119,6 +125,12 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
|
||||
@Inject
|
||||
var retrofit: Retrofit? = null
|
||||
|
||||
var chatRepository: ChatRepository? = null
|
||||
@Inject set
|
||||
|
||||
@Inject
|
||||
lateinit var userManager: UserManager
|
||||
|
||||
@JvmField
|
||||
@Inject
|
||||
var okHttpClient: OkHttpClient? = null
|
||||
@ -209,55 +221,107 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
|
||||
}
|
||||
|
||||
private fun handleCallPushMessage() {
|
||||
val fullScreenIntent = Intent(context, CallNotificationActivity::class.java)
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ROOM_TOKEN, pushMessage.id)
|
||||
bundle.putInt(KEY_NOTIFICATION_TIMESTAMP, pushMessage.timestamp.toInt())
|
||||
bundle.putLong(KEY_INTERNAL_USER_ID, signatureVerification.user!!.id!!)
|
||||
bundle.putBoolean(KEY_FROM_NOTIFICATION_START_CALL, true)
|
||||
fullScreenIntent.putExtras(bundle)
|
||||
fullScreenIntent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
val userBeingCalled = userManager.getUserWithId(signatureVerification.user!!.id!!).blockingGet()
|
||||
|
||||
val requestCode = System.currentTimeMillis().toInt()
|
||||
fun prepareCallNotificationScreen(conversation: ConversationModel) {
|
||||
val fullScreenIntent = Intent(context, CallNotificationActivity::class.java)
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ROOM_TOKEN, pushMessage.id)
|
||||
bundle.putInt(KEY_NOTIFICATION_TIMESTAMP, pushMessage.timestamp.toInt())
|
||||
bundle.putLong(KEY_INTERNAL_USER_ID, signatureVerification.user!!.id!!)
|
||||
bundle.putBoolean(KEY_FROM_NOTIFICATION_START_CALL, true)
|
||||
|
||||
val fullScreenPendingIntent = PendingIntent.getActivity(
|
||||
context,
|
||||
requestCode,
|
||||
fullScreenIntent,
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
|
||||
} else {
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
}
|
||||
)
|
||||
val isOneToOneCall = conversation.type === ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL
|
||||
|
||||
val soundUri = getCallRingtoneUri(applicationContext, appPreferences)
|
||||
val notificationChannelId = NotificationUtils.NotificationChannels.NOTIFICATION_CHANNEL_CALLS_V4.name
|
||||
val uri = Uri.parse(signatureVerification.user!!.baseUrl!!)
|
||||
val baseUrl = uri.host
|
||||
bundle.putBoolean(KEY_ROOM_ONE_TO_ONE, isOneToOneCall) // ggf change in Activity? not necessary????
|
||||
bundle.putString(BundleKeys.KEY_CONVERSATION_NAME, conversation.name)
|
||||
bundle.putString(BundleKeys.KEY_CONVERSATION_DISPLAY_NAME, conversation.displayName)
|
||||
bundle.putInt(BundleKeys.KEY_CALL_FLAG, conversation.callFlag)
|
||||
|
||||
val notification =
|
||||
NotificationCompat.Builder(applicationContext, notificationChannelId)
|
||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||
.setCategory(NotificationCompat.CATEGORY_CALL)
|
||||
.setSmallIcon(R.drawable.ic_call_black_24dp)
|
||||
.setSubText(baseUrl)
|
||||
.setShowWhen(true)
|
||||
.setWhen(pushMessage.timestamp)
|
||||
.setContentTitle(EmojiCompat.get().process(pushMessage.subject))
|
||||
// auto cancel is set to false because notification (including sound) should continue while
|
||||
// CallNotificationActivity is active
|
||||
.setAutoCancel(false)
|
||||
.setOngoing(true)
|
||||
.setContentIntent(fullScreenPendingIntent)
|
||||
.setFullScreenIntent(fullScreenPendingIntent, true)
|
||||
.setSound(soundUri)
|
||||
.build()
|
||||
notification.flags = notification.flags or Notification.FLAG_INSISTENT
|
||||
val participantPermission = ParticipantPermissions(
|
||||
userBeingCalled!!.capabilities!!.spreedCapability!!,
|
||||
conversation
|
||||
)
|
||||
bundle.putBoolean(
|
||||
BundleKeys.KEY_PARTICIPANT_PERMISSION_CAN_PUBLISH_AUDIO,
|
||||
participantPermission.canPublishAudio()
|
||||
)
|
||||
bundle.putBoolean(
|
||||
BundleKeys.KEY_PARTICIPANT_PERMISSION_CAN_PUBLISH_VIDEO,
|
||||
participantPermission.canPublishVideo()
|
||||
)
|
||||
bundle.putBoolean(
|
||||
BundleKeys.KEY_IS_MODERATOR,
|
||||
ConversationUtils.isParticipantOwnerOrModerator(conversation)
|
||||
)
|
||||
|
||||
sendNotification(pushMessage.timestamp.toInt(), notification)
|
||||
fullScreenIntent.putExtras(bundle)
|
||||
fullScreenIntent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
|
||||
checkIfCallIsActive(signatureVerification)
|
||||
val requestCode = System.currentTimeMillis().toInt()
|
||||
|
||||
val fullScreenPendingIntent = PendingIntent.getActivity(
|
||||
context,
|
||||
requestCode,
|
||||
fullScreenIntent,
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
|
||||
} else {
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
}
|
||||
)
|
||||
|
||||
val soundUri = getCallRingtoneUri(applicationContext, appPreferences)
|
||||
val notificationChannelId = NotificationUtils.NotificationChannels.NOTIFICATION_CHANNEL_CALLS_V4.name
|
||||
val uri = Uri.parse(signatureVerification.user!!.baseUrl!!)
|
||||
val baseUrl = uri.host
|
||||
|
||||
val notification =
|
||||
NotificationCompat.Builder(applicationContext, notificationChannelId)
|
||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||
.setCategory(NotificationCompat.CATEGORY_CALL)
|
||||
.setSmallIcon(R.drawable.ic_call_black_24dp)
|
||||
.setSubText(baseUrl)
|
||||
.setShowWhen(true)
|
||||
.setWhen(pushMessage.timestamp)
|
||||
.setContentTitle(EmojiCompat.get().process(pushMessage.subject))
|
||||
// auto cancel is set to false because notification (including sound) should continue while
|
||||
// CallNotificationActivity is active
|
||||
.setAutoCancel(false)
|
||||
.setOngoing(true)
|
||||
.setContentIntent(fullScreenPendingIntent)
|
||||
.setFullScreenIntent(fullScreenPendingIntent, true)
|
||||
.setSound(soundUri)
|
||||
.build()
|
||||
notification.flags = notification.flags or Notification.FLAG_INSISTENT
|
||||
|
||||
sendNotification(pushMessage.timestamp.toInt(), notification)
|
||||
|
||||
checkIfCallIsActive(signatureVerification, conversation)
|
||||
}
|
||||
|
||||
chatRepository?.getRoom(userBeingCalled, roomToken = pushMessage.id!!)
|
||||
?.subscribeOn(Schedulers.io())
|
||||
?.observeOn(AndroidSchedulers.mainThread())
|
||||
?.subscribe(object : Observer<ConversationModel> {
|
||||
override fun onSubscribe(d: Disposable) {
|
||||
// unused atm
|
||||
}
|
||||
|
||||
override fun onNext(conversation: ConversationModel) {
|
||||
if (userManager.setUserAsActive(userBeingCalled!!).blockingGet()) {
|
||||
prepareCallNotificationScreen(conversation)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
Log.e(TAG, "Failed to get room", e)
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
// unused atm
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun initNcApiAndCredentials() {
|
||||
@ -819,7 +883,7 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
|
||||
notificationManager.cancel(notificationId)
|
||||
}
|
||||
|
||||
private fun checkIfCallIsActive(signatureVerification: SignatureVerification) {
|
||||
private fun checkIfCallIsActive(signatureVerification: SignatureVerification, conversation: ConversationModel) {
|
||||
Log.d(TAG, "checkIfCallIsActive")
|
||||
var hasParticipantsInCall = true
|
||||
var inCallOnDifferentDevice = false
|
||||
@ -867,7 +931,7 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
|
||||
}
|
||||
|
||||
if (!hasParticipantsInCall) {
|
||||
showMissedCallNotification()
|
||||
showMissedCallNotification(conversation)
|
||||
Log.d(TAG, "no participants in call")
|
||||
removeNotification(pushMessage.timestamp.toInt())
|
||||
}
|
||||
@ -881,7 +945,7 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
|
||||
override fun onError(e: Throwable) {
|
||||
Log.e(TAG, "Error in getPeersForCall", e)
|
||||
if (isCallNotificationVisible) {
|
||||
showMissedCallNotification()
|
||||
showMissedCallNotification(conversation)
|
||||
}
|
||||
removeNotification(pushMessage.timestamp.toInt())
|
||||
}
|
||||
@ -889,7 +953,7 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
|
||||
override fun onComplete() {
|
||||
if (isCallNotificationVisible) {
|
||||
// this state can be reached when call timeout is reached.
|
||||
showMissedCallNotification()
|
||||
showMissedCallNotification(conversation)
|
||||
}
|
||||
|
||||
removeNotification(pushMessage.timestamp.toInt())
|
||||
@ -897,86 +961,50 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
|
||||
})
|
||||
}
|
||||
|
||||
fun showMissedCallNotification() {
|
||||
fun showMissedCallNotification(conversation: ConversationModel) {
|
||||
val isOngoingCallNotificationVisible = NotificationUtils.isNotificationVisible(
|
||||
context,
|
||||
pushMessage.timestamp.toInt()
|
||||
)
|
||||
|
||||
if (isOngoingCallNotificationVisible) {
|
||||
val apiVersion = ApiUtils.getConversationApiVersion(
|
||||
signatureVerification.user!!,
|
||||
intArrayOf(
|
||||
ApiUtils.API_V4,
|
||||
ApiUtils.API_V3,
|
||||
1
|
||||
)
|
||||
val notificationBuilder: NotificationCompat.Builder?
|
||||
|
||||
notificationBuilder = NotificationCompat.Builder(
|
||||
context!!,
|
||||
NotificationUtils.NotificationChannels
|
||||
.NOTIFICATION_CHANNEL_MESSAGES_V4.name
|
||||
)
|
||||
ncApi.getRoom(
|
||||
credentials,
|
||||
ApiUtils.getUrlForRoom(
|
||||
apiVersion,
|
||||
signatureVerification.user?.baseUrl!!,
|
||||
pushMessage.id
|
||||
|
||||
val notification: Notification = notificationBuilder
|
||||
.setContentTitle(
|
||||
String.format(
|
||||
context!!.resources.getString(R.string.nc_missed_call),
|
||||
conversation.displayName
|
||||
)
|
||||
)
|
||||
)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.retry(GET_ROOM_RETRY_COUNT)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Observer<RoomOverall> {
|
||||
override fun onSubscribe(d: Disposable) {
|
||||
// unused atm
|
||||
}
|
||||
.setSmallIcon(R.drawable.ic_baseline_phone_missed_24)
|
||||
.setOngoing(false)
|
||||
.setAutoCancel(true)
|
||||
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||
.setContentIntent(getIntentToOpenConversation())
|
||||
.build()
|
||||
|
||||
override fun onNext(roomOverall: RoomOverall) {
|
||||
val currentConversation = roomOverall.ocs!!.data
|
||||
val notificationBuilder: NotificationCompat.Builder?
|
||||
|
||||
notificationBuilder = NotificationCompat.Builder(
|
||||
context!!,
|
||||
NotificationUtils.NotificationChannels
|
||||
.NOTIFICATION_CHANNEL_MESSAGES_V4.name
|
||||
)
|
||||
|
||||
val notification: Notification = notificationBuilder
|
||||
.setContentTitle(
|
||||
String.format(
|
||||
context!!.resources.getString(R.string.nc_missed_call),
|
||||
currentConversation!!.displayName
|
||||
)
|
||||
)
|
||||
.setSmallIcon(R.drawable.ic_baseline_phone_missed_24)
|
||||
.setOngoing(false)
|
||||
.setAutoCancel(true)
|
||||
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||
.setContentIntent(getIntentToOpenConversation())
|
||||
.build()
|
||||
|
||||
val notificationId: Int = SystemClock.uptimeMillis().toInt()
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
applicationContext,
|
||||
Manifest.permission.POST_NOTIFICATIONS
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
// here to request the missing permissions, and then overriding
|
||||
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
|
||||
// int[] grantResults)
|
||||
// to handle the case where the user grants the permission. See the documentation
|
||||
// for ActivityCompat#requestPermissions for more details.
|
||||
return
|
||||
}
|
||||
notificationManager.notify(notificationId, notification)
|
||||
Log.d(TAG, "'you missed a call' notification was created")
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
Log.e(TAG, "An error occurred while fetching room for the 'missed call' notification", e)
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
// unused atm
|
||||
}
|
||||
})
|
||||
val notificationId: Int = SystemClock.uptimeMillis().toInt()
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
applicationContext,
|
||||
Manifest.permission.POST_NOTIFICATIONS
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
// here to request the missing permissions, and then overriding
|
||||
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
|
||||
// int[] grantResults)
|
||||
// to handle the case where the user grants the permission. See the documentation
|
||||
// for ActivityCompat#requestPermissions for more details.
|
||||
return
|
||||
}
|
||||
notificationManager.notify(notificationId, notification)
|
||||
Log.d(TAG, "'you missed a call' notification was created")
|
||||
}
|
||||
}
|
||||
|
||||
@ -986,7 +1014,6 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ROOM_TOKEN, pushMessage.id)
|
||||
bundle.putLong(KEY_INTERNAL_USER_ID, signatureVerification.user!!.id!!)
|
||||
bundle.putBoolean(KEY_FROM_NOTIFICATION_START_CALL, false)
|
||||
intent.putExtras(bundle)
|
||||
return intent
|
||||
}
|
||||
@ -997,7 +1024,6 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
|
||||
val bundle = Bundle()
|
||||
bundle.putString(KEY_ROOM_TOKEN, pushMessage.id)
|
||||
bundle.putLong(KEY_INTERNAL_USER_ID, signatureVerification.user!!.id!!)
|
||||
bundle.putBoolean(KEY_FROM_NOTIFICATION_START_CALL, false)
|
||||
intent.putExtras(bundle)
|
||||
|
||||
val requestCode = System.currentTimeMillis().toInt()
|
||||
|
@ -35,13 +35,12 @@ import com.nextcloud.talk.upload.chunked.ChunkedFileUploader
|
||||
import com.nextcloud.talk.upload.chunked.OnDataTransferProgressListener
|
||||
import com.nextcloud.talk.upload.normal.FileUploader
|
||||
import com.nextcloud.talk.users.UserManager
|
||||
import com.nextcloud.talk.utils.CapabilitiesUtil
|
||||
import com.nextcloud.talk.utils.FileUtils
|
||||
import com.nextcloud.talk.utils.NotificationUtils
|
||||
import com.nextcloud.talk.utils.RemoteFileUtils
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_FROM_NOTIFICATION_START_CALL
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_INTERNAL_USER_ID
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
|
||||
import com.nextcloud.talk.utils.CapabilitiesUtil
|
||||
import com.nextcloud.talk.utils.permissions.PlatformPermissionUtil
|
||||
import com.nextcloud.talk.utils.preferences.AppPreferences
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
@ -295,7 +294,6 @@ class UploadAndShareFilesWorker(val context: Context, workerParameters: WorkerPa
|
||||
|
||||
bundle.putString(KEY_ROOM_TOKEN, roomToken)
|
||||
bundle.putLong(KEY_INTERNAL_USER_ID, currentUser.id!!)
|
||||
bundle.putBoolean(KEY_FROM_NOTIFICATION_START_CALL, false)
|
||||
|
||||
intent.putExtras(bundle)
|
||||
|
||||
|
@ -39,6 +39,7 @@ object BundleKeys {
|
||||
const val KEY_INVITED_GROUP = "KEY_INVITED_GROUP"
|
||||
const val KEY_INVITED_EMAIL = "KEY_INVITED_EMAIL"
|
||||
const val KEY_CONVERSATION_NAME = "KEY_CONVERSATION_NAME"
|
||||
const val KEY_CONVERSATION_DISPLAY_NAME = "KEY_CONVERSATION_DISPLAY_NAME"
|
||||
const val KEY_RECORDING_STATE = "KEY_RECORDING_STATE"
|
||||
const val KEY_CALL_VOICE_ONLY = "KEY_CALL_VOICE_ONLY"
|
||||
const val KEY_CALL_WITHOUT_NOTIFICATION = "KEY_CALL_WITHOUT_NOTIFICATION"
|
||||
@ -75,4 +76,5 @@ object BundleKeys {
|
||||
const val KEY_PASSWORD = "KEY_PASSWORD"
|
||||
const val KEY_REMOTE_TALK_SHARE = "KEY_REMOTE_TALK_SHARE"
|
||||
const val KEY_CHAT_API_VERSION = "KEY_CHAT_API_VERSION"
|
||||
const val KEY_CALL_FLAG = "KEY_CALL_FLAG"
|
||||
}
|
||||
|
@ -52,8 +52,6 @@
|
||||
android:background="@drawable/shape_oval"
|
||||
android:backgroundTint="@color/nc_darkGreen"
|
||||
android:src="@drawable/ic_videocam_white_24px"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
android:contentDescription="@string/nc_call_button_content_description_answer_video_call" />
|
||||
</LinearLayout>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user