Fix up various other elements of notifications

Signed-off-by: Mario Danic <mario@lovelyhq.com>
This commit is contained in:
Mario Danic 2020-02-23 18:08:51 +01:00
parent 5819ca7a79
commit cf8261fe4c
No known key found for this signature in database
GPG Key ID: CDE0BBD2738C4CC0
6 changed files with 49 additions and 221 deletions

View File

@ -67,12 +67,6 @@ class MagicCallActivity : BaseActivity() {
if (!router!!.hasRootController()) { if (!router!!.hasRootController()) {
if (intent.action == BundleKeys.KEY_OPEN_INCOMING_CALL) { if (intent.action == BundleKeys.KEY_OPEN_INCOMING_CALL) {
val hideIncomingCallNotificationIntent = Intent(applicationContext, CallService::class.java)
hideIncomingCallNotificationIntent.action = BundleKeys.KEY_SHOW_INCOMING_CALL
hideIncomingCallNotificationIntent.putExtra(BundleKeys.KEY_NOTIFICATION_ID, intent.getLongExtra(BundleKeys.KEY_NOTIFICATION_ID, -1))
//applicationContext?.startService(hideIncomingCallNotificationIntent)
router!!.setRoot( router!!.setRoot(
RouterTransaction.with(CallNotificationController(intent.extras!!)) RouterTransaction.with(CallNotificationController(intent.extras!!))
.pushChangeHandler(HorizontalChangeHandler()) .pushChangeHandler(HorizontalChangeHandler())

View File

@ -21,6 +21,7 @@
package com.nextcloud.talk.controllers package com.nextcloud.talk.controllers
import android.annotation.SuppressLint import android.annotation.SuppressLint
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
@ -49,12 +50,14 @@ import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
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.CallEvent
import com.nextcloud.talk.events.ConfigurationChangeEvent import com.nextcloud.talk.events.ConfigurationChangeEvent
import com.nextcloud.talk.models.json.conversations.Conversation import com.nextcloud.talk.models.json.conversations.Conversation
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.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
@ -71,11 +74,11 @@ 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 org.parceler.Parcels
class CallNotificationController(private val originalBundle: Bundle) : BaseController() { class CallNotificationController(private val originalBundle: Bundle) : BaseController() {
val ncApi: NcApi by inject() val ncApi: NcApi by inject()
val arbitraryStorageUtils: ArbitraryStorageUtils by inject()
@JvmField @JvmField
@BindView(R.id.conversationNameTextView) @BindView(R.id.conversationNameTextView)
@ -100,23 +103,9 @@ class CallNotificationController(private val originalBundle: Bundle) : BaseContr
@JvmField @JvmField
@BindView(R.id.incomingTextRelativeLayout) @BindView(R.id.incomingTextRelativeLayout)
var incomingTextRelativeLayout: RelativeLayout? = null var incomingTextRelativeLayout: RelativeLayout? = null
private val conversationToken: String private val conversation: Conversation = Parcels.unwrap(originalBundle.getParcelable(BundleKeys.KEY_CONVERSATION))
private val userBeingCalled: UserNgEntity? private val userBeingCalled: UserNgEntity = originalBundle.getParcelable(BundleKeys.KEY_USER_ENTITY)!!
private val credentials: String? private val activeNotification: String = originalBundle.getString(BundleKeys.KEY_ACTIVE_NOTIFICATION)!!
private val notificationId: Long?
private var currentConversation: Conversation? = null
private var mediaPlayer: MediaPlayer? = null
private var leavingScreen = false
private var vibrator: Vibrator? = null
private var handler: Handler? = null
init {
this.conversationToken = originalBundle.getString(BundleKeys.KEY_CONVERSATION_TOKEN)!!
this.userBeingCalled = originalBundle.getParcelable(BundleKeys.KEY_USER_ENTITY)!!
this.notificationId = originalBundle.getLong(BundleKeys.KEY_NOTIFICATION_ID)
credentials = userBeingCalled.getCredentials()
}
override fun inflateView( override fun inflateView(
inflater: LayoutInflater, inflater: LayoutInflater,
@ -135,18 +124,16 @@ class CallNotificationController(private val originalBundle: Bundle) : BaseContr
eventBus.register(this) eventBus.register(this)
} }
private fun showAnswerControls() { private fun dismissIncomingCallNotification() {
callAnswerCameraView!!.visibility = View.VISIBLE val hideIncomingCallNotificationIntent = Intent(applicationContext, CallService::class.java)
callAnswerVoiceOnlyView!!.visibility = View.VISIBLE hideIncomingCallNotificationIntent.action = BundleKeys.DISMISS_CALL_NOTIFICATION
hideIncomingCallNotificationIntent.putExtra(BundleKeys.KEY_ACTIVE_NOTIFICATION, activeNotification)
applicationContext?.startService(hideIncomingCallNotificationIntent)
} }
@OnClick(R.id.callControlHangupView) @OnClick(R.id.callControlHangupView)
internal fun hangup() { internal fun hangup() {
leavingScreen = true dismissIncomingCallNotification()
activity?.finish()
if (activity != null) {
activity!!.finish()
}
} }
@OnClick(R.id.callAnswerCameraView) @OnClick(R.id.callAnswerCameraView)
@ -162,11 +149,8 @@ class CallNotificationController(private val originalBundle: Bundle) : BaseContr
} }
private fun proceedToCall() { private fun proceedToCall() {
originalBundle.putString( dismissIncomingCallNotification()
BundleKeys.KEY_CONVERSATION_TOKEN, originalBundle.putString(BundleKeys.KEY_CONVERSATION_TOKEN, conversation.token)
currentConversation!!.token
)
router.replaceTopController( router.replaceTopController(
RouterTransaction.with(CallController(originalBundle)) RouterTransaction.with(CallController(originalBundle))
.popChangeHandler(HorizontalChangeHandler()) .popChangeHandler(HorizontalChangeHandler())
@ -174,162 +158,18 @@ class CallNotificationController(private val originalBundle: Bundle) : BaseContr
) )
} }
private fun checkIfAnyParticipantsRemainInRoom() {
ncApi.getPeersForCall(
credentials, ApiUtils.getUrlForParticipants(
userBeingCalled!!.baseUrl,
currentConversation!!.token
)
)
.subscribeOn(Schedulers.io())
.takeWhile { observable -> !leavingScreen }
.retry(3)
.`as`(AutoDispose.autoDisposable(scopeProvider))
.subscribe(object : Observer<ParticipantsOverall> {
override fun onSubscribe(d: Disposable) {}
override fun onNext(participantsOverall: ParticipantsOverall) {
var hasParticipantsInCall = false
var inCallOnDifferentDevice = false
val participantList = participantsOverall.ocs.data
for (participant in participantList) {
if (participant.participantFlags != Participant.ParticipantFlags.NOT_IN_CALL) {
hasParticipantsInCall = true
if (participant.userId == userBeingCalled.userId) {
inCallOnDifferentDevice = true
break
}
}
}
if (!hasParticipantsInCall || inCallOnDifferentDevice) {
if (activity != null) {
activity!!.runOnUiThread { hangup() }
}
}
}
override fun onError(e: Throwable) {
}
override fun onComplete() {
if (!leavingScreen) {
checkIfAnyParticipantsRemainInRoom()
}
}
})
}
private fun runAllThings() {
/*if (conversationNameTextView != null) {
conversationNameTextView!!.text = currentConversation!!.displayName
}
loadAvatar()
checkIfAnyParticipantsRemainInRoom()
showAnswerControls()*/
}
@SuppressLint("LongLogTag") @SuppressLint("LongLogTag")
override fun onViewBound(view: View) { override fun onViewBound(view: View) {
super.onViewBound(view) super.onViewBound(view)
conversationNameTextView?.text = conversation.displayName
if (handler == null) { loadAvatar()
handler = Handler() callAnswerCameraView?.visibility = View.VISIBLE
callAnswerVoiceOnlyView?.visibility = View.VISIBLE
} }
runAllThings() @Subscribe(threadMode = ThreadMode.MAIN)
fun onMessageEvent(callEvent: CallEvent) {
/*var importantConversation = false activity?.finish()
val arbitraryStorageEntity: ArbitraryStorageEntity? = arbitraryStorageUtils.getStorageSetting(
userBeingCalled!!.id!!,
"important_conversation",
currentConversation!!.token
)
if (arbitraryStorageEntity != null) {
importantConversation = arbitraryStorageEntity.value!!.toBoolean()
}
if (DoNotDisturbUtils.shouldPlaySound(importantConversation)) {
val callRingtonePreferenceString = appPreferences.callRingtoneUri
var ringtoneUri: Uri?
if (TextUtils.isEmpty(callRingtonePreferenceString)) {
// play default sound
ringtoneUri = Uri.parse(
"android.resource://" + applicationContext!!.packageName +
"/raw/librem_by_feandesign_call"
)
} else {
ringtoneUri = try {
val ringtoneSettings =
LoganSquare.parse(callRingtonePreferenceString, RingtoneSettings::class.java)
ringtoneSettings.ringtoneUri
} catch (e: IOException) {
Log.e(TAG, "Failed to parse ringtone settings")
Uri.parse(
"android.resource://" + applicationContext!!.packageName +
"/raw/librem_by_feandesign_call"
)
}
}
if (ringtoneUri != null && activity != null) {
mediaPlayer = MediaPlayer()
try {
mediaPlayer!!.setDataSource(activity!!, ringtoneUri)
mediaPlayer!!.isLooping = true
val audioAttributes = AudioAttributes.Builder()
.setContentType(
AudioAttributes
.CONTENT_TYPE_SONIFICATION
)
.setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
.build()
mediaPlayer!!.setAudioAttributes(audioAttributes)
mediaPlayer!!.setOnPreparedListener { mp -> mediaPlayer!!.start() }
mediaPlayer!!.prepareAsync()
} catch (e: IOException) {
Log.e(TAG, "Failed to set data source")
}
}
}
if (DoNotDisturbUtils.shouldVibrate(appPreferences.shouldVibrateSetting)) {
vibrator = applicationContext!!.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
if (vibrator != null) {
val vibratePattern = longArrayOf(0, 400, 800, 600, 800, 800, 800, 1000)
val amplitudes = intArrayOf(0, 255, 0, 255, 0, 255, 0, 255)
val vibrationEffect: VibrationEffect
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (vibrator!!.hasAmplitudeControl()) {
vibrationEffect = VibrationEffect.createWaveform(vibratePattern, amplitudes, -1)
vibrator!!.vibrate(vibrationEffect)
} else {
vibrationEffect = VibrationEffect.createWaveform(vibratePattern, -1)
vibrator!!.vibrate(vibrationEffect)
}
} else {
vibrator!!.vibrate(vibratePattern, -1)
}
}
handler!!.postDelayed({
if (vibrator != null) {
vibrator!!.cancel()
}
}, 10000)
}*/
} }
@Subscribe(threadMode = ThreadMode.MAIN) @Subscribe(threadMode = ThreadMode.MAIN)
@ -344,7 +184,7 @@ class CallNotificationController(private val originalBundle: Bundle) : BaseContr
} }
private fun loadAvatar() { private fun loadAvatar() {
when (currentConversation!!.type) { when (conversation.type) {
Conversation.ConversationType.ONE_TO_ONE_CONVERSATION -> { Conversation.ConversationType.ONE_TO_ONE_CONVERSATION -> {
avatarImageView!!.visibility = View.VISIBLE avatarImageView!!.visibility = View.VISIBLE
@ -352,8 +192,8 @@ class CallNotificationController(private val originalBundle: Bundle) : BaseContr
resources?.getDrawable(R.drawable.incoming_gradient) resources?.getDrawable(R.drawable.incoming_gradient)
avatarImageView?.load( avatarImageView?.load(
ApiUtils.getUrlForAvatarWithName( ApiUtils.getUrlForAvatarWithName(
userBeingCalled!!.baseUrl, userBeingCalled.baseUrl,
currentConversation!!.name, R.dimen.avatar_size_very_big conversation.name, R.dimen.avatar_size_very_big
) )
) { ) {
addHeader("Authorization", userBeingCalled.getCredentials()) addHeader("Authorization", userBeingCalled.getCredentials())
@ -415,30 +255,8 @@ class CallNotificationController(private val originalBundle: Bundle) : BaseContr
} }
} }
private fun endMediaAndVibratorNotifications() {
if (mediaPlayer != null) {
if (mediaPlayer!!.isPlaying) {
mediaPlayer!!.stop()
}
mediaPlayer!!.release()
mediaPlayer = null
}
if (vibrator != null) {
vibrator!!.cancel()
}
}
public override fun onDestroy() { public override fun onDestroy() {
AvatarStatusCodeHolder.getInstance() AvatarStatusCodeHolder.getInstance().statusCode = 0
.statusCode = 0
leavingScreen = true
if (handler != null) {
handler!!.removeCallbacksAndMessages(null)
handler = null
}
endMediaAndVibratorNotifications()
super.onDestroy() super.onDestroy()
} }

View File

@ -0,0 +1,6 @@
package com.nextcloud.talk.events
import kotlinx.serialization.Serializable
@Serializable
class CallEvent

View File

@ -25,6 +25,7 @@ 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.events.CallEvent
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.Conversation
@ -47,9 +48,11 @@ import com.nextcloud.talk.utils.bundle.BundleKeys
import com.nextcloud.talk.utils.preferences.AppPreferences import com.nextcloud.talk.utils.preferences.AppPreferences
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import org.greenrobot.eventbus.EventBus
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 org.koin.core.parameter.parametersOf
import org.parceler.Parcels
import retrofit2.Retrofit import retrofit2.Retrofit
import java.security.InvalidKeyException import java.security.InvalidKeyException
import java.security.NoSuchAlgorithmException import java.security.NoSuchAlgorithmException
@ -70,6 +73,7 @@ class CallService : Service(), KoinComponent, CoroutineScope {
val retrofit: Retrofit by inject() val retrofit: Retrofit by inject()
val componentsWithEmptyCookieJar: ComponentsWithEmptyCookieJar by inject() val componentsWithEmptyCookieJar: ComponentsWithEmptyCookieJar by inject()
val apiErrorHandler: ApiErrorHandler by inject() val apiErrorHandler: ApiErrorHandler by inject()
val eventBus: EventBus by inject()
private var activeNotification = "" private var activeNotification = ""
@ -77,9 +81,14 @@ class CallService : Service(), KoinComponent, CoroutineScope {
intent?.let { intent?.let {
if (it.action == BundleKeys.KEY_INCOMING_PUSH_MESSSAGE) { if (it.action == BundleKeys.KEY_INCOMING_PUSH_MESSSAGE) {
decryptMessage(it.getStringExtra(BundleKeys.KEY_ENCRYPTED_SUBJECT), it.getStringExtra(BundleKeys.KEY_ENCRYPTED_SIGNATURE)) decryptMessage(it.getStringExtra(BundleKeys.KEY_ENCRYPTED_SUBJECT), it.getStringExtra(BundleKeys.KEY_ENCRYPTED_SIGNATURE))
} else if (it.action == BundleKeys.KEY_REJECT_INCOMING_CALL || it.action == BundleKeys.KEY_SHOW_INCOMING_CALL) { } else if (it.action == BundleKeys.KEY_REJECT_INCOMING_CALL || it.action == BundleKeys.DISMISS_CALL_NOTIFICATION) {
if (it.getStringExtra(BundleKeys.KEY_ACTIVE_NOTIFICATION) == activeNotification) { if (it.getStringExtra(BundleKeys.KEY_ACTIVE_NOTIFICATION) == activeNotification) {
stopForeground(true) stopForeground(true)
if (it.action != BundleKeys.DISMISS_CALL_NOTIFICATION) {
eventBus.post(CallEvent())
} else {
// do nothing
}
} else { } else {
// do nothing? :D // do nothing? :D
} }
@ -124,7 +133,7 @@ class CallService : Service(), KoinComponent, CoroutineScope {
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.putParcelable(BundleKeys.KEY_CONVERSATION, Parcels.wrap(conversation))
bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, signatureVerification.userEntity) bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, signatureVerification.userEntity)
bundle.putString(BundleKeys.KEY_ACTIVE_NOTIFICATION, generatedActiveNotificationId) bundle.putString(BundleKeys.KEY_ACTIVE_NOTIFICATION, generatedActiveNotificationId)
fullScreenIntent.putExtras(bundle) fullScreenIntent.putExtras(bundle)

View File

@ -64,9 +64,10 @@ object BundleKeys {
val KEY_ENCRYPTED_SUBJECT = "KEY_ENCRYPTED_SUBJECT" val KEY_ENCRYPTED_SUBJECT = "KEY_ENCRYPTED_SUBJECT"
val KEY_ENCRYPTED_SIGNATURE = "KEY_ENCRYPTED_SIGNATURE" val KEY_ENCRYPTED_SIGNATURE = "KEY_ENCRYPTED_SIGNATURE"
val KEY_CONVERSATION = "KEY_CONVERSATION"
val KEY_REJECT_INCOMING_CALL = "KEY_REJECT_INCOMING_CALL" val KEY_REJECT_INCOMING_CALL = "KEY_REJECT_INCOMING_CALL"
val KEY_SHOW_INCOMING_CALL = "KEY_SHOW_INCOMING_CALL" val KEY_SHOW_INCOMING_CALL = "KEY_SHOW_INCOMING_CALL"
val DISMISS_CALL_NOTIFICATION: String = "KEY_DISMISS_CALL_NOTIFICATION"
val KEY_INCOMING_PUSH_MESSSAGE = "KEY_INCOMING_PUSH_MESSAGE" val KEY_INCOMING_PUSH_MESSSAGE = "KEY_INCOMING_PUSH_MESSAGE"
val KEY_DECRYPTED_PUSH_MESSAGE = "KEY_DECRYPTED_PUSH_MESSAGE" val KEY_DECRYPTED_PUSH_MESSAGE = "KEY_DECRYPTED_PUSH_MESSAGE"
val KEY_SIGNATURE_VERIFICATION = "KEY_SIGNATURE_VERIFICATION" val KEY_SIGNATURE_VERIFICATION = "KEY_SIGNATURE_VERIFICATION"

View File

@ -46,7 +46,7 @@
android:layout_margin="24dp" android:layout_margin="24dp"
android:visibility="gone" android:visibility="gone"
android:scaleType="centerInside" android:scaleType="centerInside"
android:background="@color/nc_darkGreen" android:background="@drawable/primary_color_circle"
android:src="@drawable/ic_call_white_24dp" /> android:src="@drawable/ic_call_white_24dp" />
<ImageView <ImageView
@ -65,7 +65,7 @@
android:layout_margin="24dp" android:layout_margin="24dp"
android:visibility="gone" android:visibility="gone"
android:scaleType="centerInside" android:scaleType="centerInside"
android:background="@color/nc_darkGreen" android:background="@drawable/primary_color_circle"
android:src="@drawable/ic_videocam_white_24px" /> android:src="@drawable/ic_videocam_white_24px" />
</LinearLayout> </LinearLayout>