feat: updating call layout

This commit is contained in:
jubb 2021-11-12 17:07:39 +11:00
parent 3d0e5541d0
commit b6c53b4964
12 changed files with 173 additions and 45 deletions

View File

@ -54,7 +54,6 @@
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" tools:node="remove"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.CALL_PHONE" />
<queries>
<intent>

View File

@ -5,11 +5,14 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.graphics.drawable.ColorDrawable
import android.media.AudioManager
import android.os.Bundle
import android.view.MenuItem
import android.view.View
import android.view.WindowManager
import androidx.activity.viewModels
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import com.bumptech.glide.load.engine.DiskCacheStrategy
@ -65,6 +68,14 @@ class WebRtcCallActivity: PassphraseRequiredActionBarActivity() {
return super.onOptionsItemSelected(item)
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
if (intent?.action == ACTION_ANSWER) {
val answerIntent = WebRtcCallService.acceptCallIntent(this)
ContextCompat.startForegroundService(this,answerIntent)
}
}
override fun onCreate(savedInstanceState: Bundle?, ready: Boolean) {
super.onCreate(savedInstanceState, ready)
window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED)
@ -82,9 +93,18 @@ class WebRtcCallActivity: PassphraseRequiredActionBarActivity() {
.execute()
if (intent.action == ACTION_ANSWER) {
// answer via ViewModel
val answerIntent = WebRtcCallService.acceptCallIntent(this)
startService(answerIntent)
ContextCompat.startForegroundService(this,answerIntent)
}
acceptCallButton.setOnClickListener {
val answerIntent = WebRtcCallService.acceptCallIntent(this)
ContextCompat.startForegroundService(this,answerIntent)
}
declineCallButton.setOnClickListener {
val declineIntent = WebRtcCallService.hangupIntent(this)
startService(declineIntent)
}
registerReceiver(object: BroadcastReceiver() {
@ -128,7 +148,20 @@ class WebRtcCallActivity: PassphraseRequiredActionBarActivity() {
launch {
viewModel.callState.collect { state ->
remote_loading_view.isVisible = state != CALL_CONNECTED
when (state) {
CALL_RINGING -> {
}
CALL_OUTGOING -> {
}
CALL_CONNECTED -> {
}
}
controlGroup.isVisible = state in listOf(CALL_CONNECTED, CALL_OUTGOING, CALL_INCOMING)
remote_loading_view.isVisible = state !in listOf(CALL_CONNECTED, CALL_RINGING)
incomingControlGroup.isVisible = state == CALL_RINGING
}
}
@ -165,9 +198,10 @@ class WebRtcCallActivity: PassphraseRequiredActionBarActivity() {
}
local_renderer.isVisible = isEnabled
enableCameraButton.setImageResource(
if (isEnabled) R.drawable.ic_baseline_videocam_off_24
else R.drawable.ic_baseline_videocam_24
if (isEnabled) R.drawable.ic_outline_videocam_off_24
else R.drawable.ic_outline_videocam_24
)
enableCameraButton.styleEnabled(isEnabled)
}
}
@ -184,7 +218,15 @@ class WebRtcCallActivity: PassphraseRequiredActionBarActivity() {
}
}
fun getUserDisplayName(publicKey: String): String {
fun View.styleEnabled(isEnabled: Boolean) {
if (isEnabled) {
setBackgroundResource(R.drawable.call_controls_selected)
} else {
setBackgroundResource(R.drawable.call_controls_unselected)
}
}
private fun getUserDisplayName(publicKey: String): String {
val contact = DatabaseComponent.get(this).sessionContactDatabase().getContactWithSessionID(publicKey)
return contact?.displayName(Contact.ContactContext.REGULAR) ?: publicKey
}

View File

@ -337,23 +337,23 @@ class WebRtcCallService: Service(), PeerConnection.Observer {
val recipient = callManager.recipient ?: return
val timestamp = callManager.pendingOfferTime
setCallInProgressNotification(TYPE_INCOMING_CONNECTING, recipient)
intent.putExtra(EXTRA_CALL_ID, callId)
intent.putExtra(EXTRA_RECIPIENT_ADDRESS, recipient.address)
intent.putExtra(EXTRA_REMOTE_DESCRIPTION, pending)
intent.putExtra(EXTRA_TIMESTAMP, timestamp)
callManager.postConnectionEvent(STATE_ANSWERING)
callManager.postViewModelState(CallViewModel.State.CALL_INCOMING)
if (isIncomingMessageExpired(intent)) {
insertMissedCall(recipient, true)
terminate()
return
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
setCallInProgressNotification(TYPE_INCOMING_CONNECTING, recipient)
}
timeoutExecutor.schedule(TimeoutRunnable(callId, this), 5, TimeUnit.MINUTES)
timeoutExecutor.schedule(TimeoutRunnable(callId, this), 2, TimeUnit.MINUTES)
callManager.initializeAudioForCall()
callManager.initializeVideo(this)
@ -370,7 +370,6 @@ class WebRtcCallService: Service(), PeerConnection.Observer {
terminate()
}
}
callManager.postViewModelState(CallViewModel.State.CALL_INCOMING)
lockManager.updatePhoneState(LockManager.PhoneState.PROCESSING)
} catch (e: Exception) {
Log.e(TAG,e)

View File

@ -46,6 +46,7 @@ class CallNotificationBuilder {
}
TYPE_INCOMING_RINGING -> {
builder.setContentText(context.getString(R.string.NotificationBarManager__incoming_signal_call))
.setCategory(NotificationCompat.CATEGORY_CALL)
builder.addAction(getServiceNotificationAction(
context,
WebRtcCallService.ACTION_DENY_CALL,

View File

@ -1,5 +1,6 @@
package org.thoughtcrime.securesms.webrtc.audio
import android.Manifest
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothHeadset
@ -32,8 +33,6 @@ class SignalBluetoothManager(
}
private set
private fun hasPermission() = false
private var bluetoothAdapter: BluetoothAdapter? = null
private var bluetoothDevice: BluetoothDevice? = null
private var bluetoothHeadset: BluetoothHeadset? = null
@ -92,7 +91,7 @@ class SignalBluetoothManager(
Log.d(TAG, "stop(): state: $state")
if (bluetoothAdapter == null || !hasPermission()) {
if (bluetoothAdapter == null) {
return
}
@ -125,7 +124,6 @@ class SignalBluetoothManager(
fun startScoAudio(): Boolean {
handler.assertHandlerThread()
if (!hasPermission()) return false
Log.i(TAG, "startScoAudio(): $state attempts: $scoConnectionAttempts")
@ -150,7 +148,6 @@ class SignalBluetoothManager(
fun stopScoAudio() {
handler.assertHandlerThread()
if (!hasPermission()) return
Log.i(TAG, "stopScoAudio(): $state")
@ -166,7 +163,6 @@ class SignalBluetoothManager(
fun updateDevice() {
handler.assertHandlerThread()
if (!hasPermission()) return
Log.d(TAG, "updateDevice(): state: $state")
@ -200,7 +196,6 @@ class SignalBluetoothManager(
private fun onBluetoothTimeout() {
Log.i(TAG, "onBluetoothTimeout: state: $state bluetoothHeadset: $bluetoothHeadset")
if (!hasPermission()) return
if (state == State.UNINITIALIZED || bluetoothHeadset == null || state != State.CONNECTING) {
return

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="oval"
xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/unimportant"/>
</shape>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="oval"
xmlns:android="http://schemas.android.com/apk/res/android">
<stroke android:color="@color/unimportant" android:width="@dimen/small_spacing"/>
</shape>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M15,8v8H5V8h10m1,-2H4c-0.55,0 -1,0.45 -1,1v10c0,0.55 0.45,1 1,1h12c0.55,0 1,-0.45 1,-1v-3.5l4,4v-11l-4,4V7c0,-0.55 -0.45,-1 -1,-1z"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M9.56,8l-2,-2 -4.15,-4.14L2,3.27 4.73,6L4,6c-0.55,0 -1,0.45 -1,1v10c0,0.55 0.45,1 1,1h12c0.21,0 0.39,-0.08 0.55,-0.18L19.73,21l1.41,-1.41 -8.86,-8.86L9.56,8zM5,16L5,8h1.73l8,8L5,16zM15,8v2.61l6,6L21,6.5l-4,4L17,7c0,-0.55 -0.45,-1 -1,-1h-5.61l2,2L15,8z"/>
</vector>

View File

@ -7,29 +7,39 @@
xmlns:tools="http://schemas.android.com/tools">
<FrameLayout
android:id="@+id/remote_parent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/remote_renderer"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<com.github.ybq.android.spinkit.SpinKitView
android:id="@+id/remote_loading_view"
style="@style/SpinKitView.Large.ThreeBounce"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:SpinKit_Color="@color/text"
android:layout_gravity="center"
tools:visibility="visible"
android:visibility="gone" />
<com.makeramen.roundedimageview.RoundedImageView
android:id="@+id/remote_recipient"
android:layout_gravity="center"
android:layout_width="@dimen/extra_large_profile_picture_size"
android:layout_height="@dimen/extra_large_profile_picture_size"/>
app:layout_constraintTop_toTopOf="parent" />
</FrameLayout>
<com.makeramen.roundedimageview.RoundedImageView
android:id="@+id/remote_recipient"
app:layout_constraintStart_toStartOf="@id/remote_parent"
app:layout_constraintEnd_toEndOf="@id/remote_parent"
app:layout_constraintTop_toTopOf="@id/remote_parent"
app:layout_constraintBottom_toBottomOf="@id/remote_parent"
android:layout_width="@dimen/extra_large_profile_picture_size"
android:layout_height="@dimen/extra_large_profile_picture_size"/>
<com.github.ybq.android.spinkit.SpinKitView
android:id="@+id/remote_loading_view"
style="@style/SpinKitView.ThreeBounce"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:foregroundGravity="center"
android:visibility="gone"
app:SpinKit_Color="@color/text"
app:layout_constraintEnd_toEndOf="@+id/remote_recipient"
app:layout_constraintStart_toStartOf="@+id/remote_recipient"
app:layout_constraintTop_toBottomOf="@id/remote_recipient"
tools:visibility="visible" />
<FrameLayout
app:layout_constraintEnd_toEndOf="parent"
@ -59,7 +69,7 @@
android:id="@+id/endCallButton"
android:background="@drawable/circle_tintable"
android:src="@drawable/ic_baseline_call_end_24"
android:padding="@dimen/small_spacing"
android:padding="@dimen/medium_spacing"
app:tint="@color/core_white"
android:backgroundTint="@color/destructive"
android:layout_width="@dimen/large_button_height"
@ -74,12 +84,12 @@
android:id="@+id/switchCameraButton"
android:background="@drawable/circle_tintable"
android:src="@drawable/ic_baseline_flip_camera_android_24"
android:padding="@dimen/small_spacing"
android:padding="@dimen/medium_spacing"
app:tint="@color/unimportant"
android:backgroundTint="@color/unimportant_button_background"
android:layout_width="@dimen/large_button_height"
android:layout_height="@dimen/large_button_height"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="@+id/endCallButton"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginBottom="@dimen/large_spacing"
@ -90,44 +100,87 @@
android:id="@+id/enableCameraButton"
android:background="@drawable/circle_tintable"
android:src="@drawable/ic_baseline_videocam_24"
android:padding="@dimen/small_spacing"
android:padding="@dimen/medium_spacing"
app:tint="@color/unimportant"
android:backgroundTint="@color/unimportant_button_background"
android:layout_width="@dimen/large_button_height"
android:layout_height="@dimen/large_button_height"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="@+id/endCallButton"
app:layout_constraintStart_toEndOf="@id/switchCameraButton"
app:layout_constraintEnd_toStartOf="@id/endCallButton"
app:layout_constraintEnd_toStartOf="@id/microphoneButton"
android:layout_marginBottom="@dimen/large_spacing"
/>
<ImageView
android:id="@+id/microphoneButton"
android:layout_width="@dimen/large_button_height"
android:layout_height="@dimen/large_button_height"
android:padding="@dimen/small_spacing"
android:padding="@dimen/medium_spacing"
android:src="@drawable/ic_microphone"
app:tint="@color/unimportant"
android:layout_marginBottom="@dimen/large_spacing"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="@+id/endCallButton"
android:backgroundTint="@color/unimportant_button_background"
android:background="@drawable/circle_tintable"
app:layout_constraintEnd_toStartOf="@id/speakerPhoneButton"
app:layout_constraintStart_toEndOf="@id/endCallButton"/>
app:layout_constraintStart_toEndOf="@id/enableCameraButton"/>
<ImageView
android:id="@+id/speakerPhoneButton"
android:background="@drawable/circle_tintable"
android:src="@drawable/ic_audio_light"
android:padding="@dimen/small_spacing"
android:padding="@dimen/medium_spacing"
app:tint="@color/unimportant"
android:backgroundTint="@color/unimportant_button_background"
android:layout_width="@dimen/large_button_height"
android:layout_height="@dimen/large_button_height"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="@+id/endCallButton"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginBottom="@dimen/large_spacing"
app:layout_constraintHorizontal_bias="0.9"
/>
<TextView
android:textAllCaps="true"
style="@style/Widget.Session.Button.Common.ProminentOutline"
android:text="@string/accept_call"
android:layout_marginBottom="@dimen/large_spacing"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintHorizontal_bias="0.85"
android:padding="@dimen/medium_spacing"
android:gravity="center"
android:id="@+id/acceptCallButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:textAllCaps="true"
style="@style/Widget.Session.Button.Common.UnimportantDestructive"
android:text="@string/decline_call"
android:layout_marginBottom="@dimen/large_spacing"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintHorizontal_bias="0.15"
android:padding="@dimen/medium_spacing"
android:id="@+id/declineCallButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<androidx.constraintlayout.widget.Group
android:id="@+id/controlGroup"
android:layout_width="0dp"
android:layout_height="0dp"
app:constraint_referenced_ids="enableCameraButton,endCallButton,switchCameraButton,speakerPhoneButton,microphoneButton"
/>
<androidx.constraintlayout.widget.Group
android:layout_width="0dp"
android:layout_height="0dp"
android:id="@+id/incomingControlGroup"
app:constraint_referenced_ids="acceptCallButton,declineCallButton"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -911,5 +911,7 @@
<string name="NotificationBarManager__cancel_call">Cancel call</string>
<string name="NotificationBarManager__establishing_signal_call">Establishing call</string>
<string name="NotificationBarManager__end_call">End call</string>
<string name="accept_call">Accept Call</string>
<string name="decline_call">Decline call</string>
</resources>

View File

@ -95,6 +95,13 @@
<item name="android:drawableTint" tools:ignore="NewApi">?android:textColorPrimary</item>
</style>
<style name="Widget.Session.Button.Common.UnimportantDestructive">
<item name="android:background">@drawable/unimportant_outline_button_medium_background</item>
<item name="android:textColor">@color/destructive</item>
<item name="android:backgroundTint" tools:ignore="NewApi">@color/destructive</item>
<item name="android:drawableTint" tools:ignore="NewApi">@color/destructive</item>
</style>
<style name="Widget.Session.Button.Dialog" parent="">
<item name="android:textAllCaps">false</item>
<item name="android:textSize">@dimen/small_font_size</item>