create conference

This commit is contained in:
Mysochenko Yuriy
2022-05-16 19:58:09 +03:00
parent bc1dbb234d
commit 7b24561c55
6 changed files with 129 additions and 70 deletions

View File

@ -23,9 +23,7 @@ import com.simplemobiletools.commons.helpers.isOreoMr1Plus
import com.simplemobiletools.commons.helpers.isOreoPlus import com.simplemobiletools.commons.helpers.isOreoPlus
import com.simplemobiletools.dialer.R import com.simplemobiletools.dialer.R
import com.simplemobiletools.dialer.extensions.* import com.simplemobiletools.dialer.extensions.*
import com.simplemobiletools.dialer.helpers.CallContactAvatarHelper import com.simplemobiletools.dialer.helpers.*
import com.simplemobiletools.dialer.helpers.CallManager
import com.simplemobiletools.dialer.helpers.CallManagerListener
import com.simplemobiletools.dialer.models.CallContact import com.simplemobiletools.dialer.models.CallContact
import kotlinx.android.synthetic.main.activity_call.* import kotlinx.android.synthetic.main.activity_call.*
import kotlinx.android.synthetic.main.dialpad.* import kotlinx.android.synthetic.main.dialpad.*
@ -57,6 +55,11 @@ class CallActivity : SimpleActivity() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_call) setContentView(R.layout.activity_call)
if (CallManager.call == null) {
finish()
return
}
updateTextColors(call_holder) updateTextColors(call_holder)
initButtons() initButtons()
@ -65,13 +68,13 @@ class CallActivity : SimpleActivity() {
addLockScreenFlags() addLockScreenFlags()
CallManager.addListener(callCallback) CallManager.addListener(callCallback)
updateCallContactInfo(CallManager.getPrimaryCall())
} }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
updateCallState(CallManager.getPrimaryCall()) updateState()
updateCallOnHoldState(CallManager.getSecondaryCall())
updateCallContactInfo(CallManager.getPrimaryCall())
} }
override fun onDestroy() { override fun onDestroy() {
@ -171,7 +174,10 @@ class CallActivity : SimpleActivity() {
dialpad_hashtag_holder.setOnClickListener { dialpadPressed('#') } dialpad_hashtag_holder.setOnClickListener { dialpadPressed('#') }
dialpad_wrapper.setBackgroundColor(getProperBackgroundColor()) dialpad_wrapper.setBackgroundColor(getProperBackgroundColor())
arrayOf(call_toggle_microphone, call_toggle_speaker, call_dialpad, dialpad_close, call_sim_image).forEach { arrayOf(
call_toggle_microphone, call_toggle_speaker, call_dialpad, dialpad_close,
call_sim_image, call_toggle_hold, call_add, call_swap, call_merge, call_manage
).forEach {
it.applyColorFilter(getProperTextColor()) it.applyColorFilter(getProperTextColor())
} }
@ -410,11 +416,23 @@ class CallActivity : SimpleActivity() {
if (statusTextId != 0) { if (statusTextId != 0) {
call_status_label.text = getString(statusTextId) call_status_label.text = getString(statusTextId)
} }
}
private fun updateState() {
val phoneState = CallManager.getPhoneState()
if (phoneState is SingleCall) {
updateCallState(phoneState.call)
updateCallOnHoldState(null)
val state = phoneState.call.getStateCompat()
val isSingleCallActionsEnabled = (state == Call.STATE_ACTIVE || state == Call.STATE_DISCONNECTED val isSingleCallActionsEnabled = (state == Call.STATE_ACTIVE || state == Call.STATE_DISCONNECTED
|| state == Call.STATE_DISCONNECTING || state == Call.STATE_HOLDING) || state == Call.STATE_DISCONNECTING || state == Call.STATE_HOLDING)
setActionButtonEnabled(call_toggle_hold, isSingleCallActionsEnabled) setActionButtonEnabled(call_toggle_hold, isSingleCallActionsEnabled)
setActionButtonEnabled(call_add, isSingleCallActionsEnabled) setActionButtonEnabled(call_add, isSingleCallActionsEnabled)
call_manage.beVisibleIf(phoneState.call.isConference())
} else if (phoneState is TwoCalls) {
updateCallState(phoneState.active)
updateCallOnHoldState(phoneState.onHold)
}
} }
private fun updateCallOnHoldState(call: Call?) { private fun updateCallOnHoldState(call: Call?) {
@ -427,11 +445,16 @@ class CallActivity : SimpleActivity() {
} }
} }
on_hold_status_holder.beVisibleIf(hasCallOnHold) on_hold_status_holder.beVisibleIf(hasCallOnHold)
controls_single_call.beVisibleIf(!hasCallOnHold) // TODO and not conference controls_single_call.beVisibleIf(!hasCallOnHold)
controls_two_calls.beVisibleIf(hasCallOnHold) controls_two_calls.beVisibleIf(hasCallOnHold)
} }
private fun updateCallContactInfo(call: Call?) { private fun updateCallContactInfo(call: Call?) {
if (call.isConference()) {
caller_avatar.setImageDrawable(null)
caller_number.text = null
caller_name_label.text = getString(R.string.conference)
} else {
CallManager.getCallContact(applicationContext, call) { contact -> CallManager.getCallContact(applicationContext, call) { contact ->
callContact = contact callContact = contact
val avatar = callContactAvatarHelper.getCallContactAvatar(contact) val avatar = callContactAvatarHelper.getCallContactAvatar(contact)
@ -441,6 +464,7 @@ class CallActivity : SimpleActivity() {
} }
} }
} }
}
private fun acceptCall() { private fun acceptCall() {
CallManager.accept() CallManager.accept()
@ -502,17 +526,12 @@ class CallActivity : SimpleActivity() {
private val callCallback = object : CallManagerListener { private val callCallback = object : CallManagerListener {
override fun onStateChanged(call: Call, state: Int) { override fun onStateChanged(call: Call, state: Int) {
updateCallState(call) updateState()
} }
override fun onCallPutOnHold(call: Call?) { override fun onPrimaryCallChanged(call: Call) {
updateCallOnHoldState(call) updateCallContactInfo(call)
} updateState()
override fun onCallsChanged(active: Call, onHold: Call?) {
updateCallState(active)
updateCallOnHoldState(onHold)
updateCallContactInfo(active)
} }
} }

View File

@ -12,6 +12,8 @@ import com.simplemobiletools.commons.helpers.MyContactsContentProvider
import com.simplemobiletools.commons.helpers.SimpleContactsHelper import com.simplemobiletools.commons.helpers.SimpleContactsHelper
import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.dialer.extensions.getStateCompat import com.simplemobiletools.dialer.extensions.getStateCompat
import com.simplemobiletools.dialer.extensions.hasCapability
import com.simplemobiletools.dialer.extensions.isConference
import com.simplemobiletools.dialer.models.CallContact import com.simplemobiletools.dialer.models.CallContact
import java.util.concurrent.CopyOnWriteArraySet import java.util.concurrent.CopyOnWriteArraySet
@ -28,37 +30,73 @@ class CallManager {
fun onCallAdded(call: Call) { fun onCallAdded(call: Call) {
this.call = call this.call = call
calls.add(call) calls.add(call)
for (listener in listeners) {
listener.onPrimaryCallChanged(call)
}
call.registerCallback(object : Call.Callback() { call.registerCallback(object : Call.Callback() {
override fun onStateChanged(call: Call, state: Int) { override fun onStateChanged(call: Call, state: Int) {
Log.d(TAG, "onStateChanged: $call") Log.d(TAG, "onStateChanged: $call")
updateState()
for (listener in listeners) { for (listener in listeners) {
listener.onStateChanged(call, state) listener.onStateChanged(call, state)
} }
if (state == Call.STATE_HOLDING && calls.size > 1) {
for (listener in listeners) {
listener.onCallPutOnHold(call)
}
}
if (state == Call.STATE_ACTIVE && calls.size == 1) {
for (listener in listeners) {
listener.onCallPutOnHold(null)
}
}
if ((state == Call.STATE_CONNECTING || state == Call.STATE_DIALING || state == Call.STATE_ACTIVE) && calls.size > 1) {
if (CallManager.call != call) {
CallManager.call = call
Log.d(TAG, "onCallsChanged")
for (listener in listeners) {
listener.onCallsChanged(call, getSecondaryCall())
}
}
} }
override fun onConferenceableCallsChanged(call: Call, conferenceableCalls: MutableList<Call>) {
Log.d(TAG, "onConferenceableCallsChanged: $call, conferenceableCalls size=${conferenceableCalls.size}")
updateState()
} }
}) })
} }
fun onCallRemoved(call: Call) { fun onCallRemoved(call: Call) {
calls.remove(call) calls.remove(call)
updateState()
}
fun getPhoneState(): PhoneState {
return when (calls.size) {
0 -> {
NoCall
}
1 -> {
SingleCall(calls.first())
}
2 -> {
val active = calls.find { it.getStateCompat() == Call.STATE_ACTIVE }
val newCall = calls.find { it.getStateCompat() == Call.STATE_CONNECTING || it.getStateCompat() == Call.STATE_DIALING }
val onHold = calls.find { it.getStateCompat() == Call.STATE_HOLDING }
if (active != null && newCall != null) {
TwoCalls(newCall, active)
} else if(newCall != null && onHold != null) {
TwoCalls(newCall, onHold)
} else if(active != null && onHold != null) {
TwoCalls(active, onHold)
} else {
TwoCalls(calls[0], calls[1])
}
}
else -> {
SingleCall(calls.find { it.isConference() }!!)
// TODO handle the call on hold (outside the conference)
}
}
}
private fun updateState() {
val primaryCall = when (val phoneState = getPhoneState()) {
is NoCall -> null
is SingleCall -> phoneState.call
is TwoCalls -> phoneState.active
}
if (primaryCall == null) {
call = null
} else if (primaryCall != call) {
call = primaryCall
for (listener in listeners) {
listener.onPrimaryCallChanged(primaryCall)
}
}
} }
fun getPrimaryCall(): Call? { fun getPrimaryCall(): Call? {
@ -104,14 +142,14 @@ class CallManager {
} }
fun merge() { fun merge() {
// val conferenceableCalls = call!!.conferenceableCalls val conferenceableCalls = call!!.conferenceableCalls
// if (conferenceableCalls.isNotEmpty()) { if (conferenceableCalls.isNotEmpty()) {
// call!!.conference(conferenceableCalls.first()) call!!.conference(conferenceableCalls.first())
// } else { } else {
// if (call!!.hasCapability(Call.Details.CAPABILITY_MERGE_CONFERENCE)) { if (call!!.hasCapability(Call.Details.CAPABILITY_MERGE_CONFERENCE)) {
// call!!.mergeConference() call!!.mergeConference()
// } }
// } }
} }
fun addListener(listener: CallManagerListener) { fun addListener(listener: CallManagerListener) {
@ -203,6 +241,10 @@ class CallManager {
interface CallManagerListener { interface CallManagerListener {
fun onStateChanged(call: Call, state: Int) fun onStateChanged(call: Call, state: Int)
fun onCallPutOnHold(call: Call?) fun onPrimaryCallChanged(call: Call)
fun onCallsChanged(active: Call, onHold: Call?)
} }
sealed class PhoneState
object NoCall : PhoneState()
class SingleCall(val call: Call?) : PhoneState()
class TwoCalls(val active: Call, val onHold: Call) : PhoneState()

View File

@ -46,8 +46,6 @@ class CallService : InCallService() {
CallManager.inCallService = null CallManager.inCallService = null
callNotificationManager.cancelNotification() callNotificationManager.cancelNotification()
} else { } else {
// TODO if left more than 1
CallManager.call = CallManager.calls.first()
callNotificationManager.setupNotification() callNotificationManager.setupNotification()
startActivity(CallActivity.getStartIntent(this)) startActivity(CallActivity.getStartIntent(this))
} }

View File

@ -1,12 +0,0 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white"
android:fillType="evenOdd" android:pathData="M16.67,13.13C18.04,14.06 19,15.32 19,17v3h4v-3C23,14.82 19.43,13.53 16.67,13.13z"/>
<path android:fillColor="@android:color/white"
android:fillType="evenOdd" android:pathData="M9,8m-4,0a4,4 0,1 1,8 0a4,4 0,1 1,-8 0"/>
<path android:fillColor="@android:color/white"
android:fillType="evenOdd" android:pathData="M15,12c2.21,0 4,-1.79 4,-4c0,-2.21 -1.79,-4 -4,-4c-0.47,0 -0.91,0.1 -1.33,0.24C14.5,5.27 15,6.58 15,8s-0.5,2.73 -1.33,3.76C14.09,11.9 14.53,12 15,12z"/>
<path android:fillColor="@android:color/white"
android:fillType="evenOdd" android:pathData="M9,13c-2.67,0 -8,1.34 -8,4v3h16v-3C17,14.34 11.67,13 9,13z"/>
</vector>

View File

@ -118,6 +118,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="@dimen/normal_margin" android:layout_margin="@dimen/normal_margin"
android:contentDescription="@null"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
@ -203,6 +204,7 @@
android:layout_height="@dimen/dialpad_button_size" android:layout_height="@dimen/dialpad_button_size"
android:layout_marginTop="@dimen/bigger_margin" android:layout_marginTop="@dimen/bigger_margin"
android:background="?attr/selectableItemBackgroundBorderless" android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/hold_call"
android:padding="@dimen/medium_margin" android:padding="@dimen/medium_margin"
android:src="@drawable/ic_pause_vector" android:src="@drawable/ic_pause_vector"
app:layout_constraintEnd_toStartOf="@id/call_add" app:layout_constraintEnd_toStartOf="@id/call_add"
@ -215,6 +217,7 @@
android:layout_height="@dimen/dialpad_button_size" android:layout_height="@dimen/dialpad_button_size"
android:layout_marginTop="@dimen/bigger_margin" android:layout_marginTop="@dimen/bigger_margin"
android:background="?attr/selectableItemBackgroundBorderless" android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/call_add"
android:padding="@dimen/medium_margin" android:padding="@dimen/medium_margin"
android:src="@drawable/ic_add_call_vector" android:src="@drawable/ic_add_call_vector"
app:layout_constraintEnd_toEndOf="@id/call_manage" app:layout_constraintEnd_toEndOf="@id/call_manage"
@ -227,6 +230,7 @@
android:layout_height="@dimen/dialpad_button_size" android:layout_height="@dimen/dialpad_button_size"
android:layout_marginTop="@dimen/bigger_margin" android:layout_marginTop="@dimen/bigger_margin"
android:background="?attr/selectableItemBackgroundBorderless" android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/call_manage"
android:padding="@dimen/medium_margin" android:padding="@dimen/medium_margin"
android:src="@drawable/ic_people_vector" android:src="@drawable/ic_people_vector"
android:visibility="gone" android:visibility="gone"
@ -240,6 +244,7 @@
android:layout_height="@dimen/dialpad_button_size" android:layout_height="@dimen/dialpad_button_size"
android:layout_marginTop="@dimen/bigger_margin" android:layout_marginTop="@dimen/bigger_margin"
android:background="?attr/selectableItemBackgroundBorderless" android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/call_swap"
android:padding="@dimen/medium_margin" android:padding="@dimen/medium_margin"
android:src="@drawable/ic_call_swap_vector" android:src="@drawable/ic_call_swap_vector"
app:layout_constraintEnd_toStartOf="@+id/call_merge" app:layout_constraintEnd_toStartOf="@+id/call_merge"
@ -254,6 +259,7 @@
android:layout_height="@dimen/dialpad_button_size" android:layout_height="@dimen/dialpad_button_size"
android:layout_marginTop="@dimen/bigger_margin" android:layout_marginTop="@dimen/bigger_margin"
android:background="?attr/selectableItemBackgroundBorderless" android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/call_merge"
android:padding="@dimen/medium_margin" android:padding="@dimen/medium_margin"
android:src="@drawable/ic_call_merge_vector" android:src="@drawable/ic_call_merge_vector"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"

View File

@ -51,6 +51,12 @@
<string name="hold_call">Hold call</string> <string name="hold_call">Hold call</string>
<string name="resume_call">Resume call</string> <string name="resume_call">Resume call</string>
<string name="call_on_hold">On Hold</string> <string name="call_on_hold">On Hold</string>
<string name="call_swap">Swap calls</string>
<string name="call_merge">Merge calls</string>
<string name="call_split">Split call</string>
<string name="call_add">Add call</string>
<string name="call_manage">Manage calls</string>
<string name="conference">Conference</string>
<!-- Speed dial --> <!-- Speed dial -->
<string name="speed_dial">Speed dial</string> <string name="speed_dial">Speed dial</string>