diff --git a/app/src/main/kotlin/com/simplemobiletools/dialer/activities/CallActivity.kt b/app/src/main/kotlin/com/simplemobiletools/dialer/activities/CallActivity.kt index 80d034bd..3148920f 100644 --- a/app/src/main/kotlin/com/simplemobiletools/dialer/activities/CallActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/dialer/activities/CallActivity.kt @@ -23,9 +23,7 @@ import com.simplemobiletools.commons.helpers.isOreoMr1Plus import com.simplemobiletools.commons.helpers.isOreoPlus import com.simplemobiletools.dialer.R import com.simplemobiletools.dialer.extensions.* -import com.simplemobiletools.dialer.helpers.CallContactAvatarHelper -import com.simplemobiletools.dialer.helpers.CallManager -import com.simplemobiletools.dialer.helpers.CallManagerListener +import com.simplemobiletools.dialer.helpers.* import com.simplemobiletools.dialer.models.CallContact import kotlinx.android.synthetic.main.activity_call.* import kotlinx.android.synthetic.main.dialpad.* @@ -57,6 +55,11 @@ class CallActivity : SimpleActivity() { super.onCreate(savedInstanceState) setContentView(R.layout.activity_call) + if (CallManager.call == null) { + finish() + return + } + updateTextColors(call_holder) initButtons() @@ -65,13 +68,13 @@ class CallActivity : SimpleActivity() { addLockScreenFlags() CallManager.addListener(callCallback) + + updateCallContactInfo(CallManager.getPrimaryCall()) } override fun onResume() { super.onResume() - updateCallState(CallManager.getPrimaryCall()) - updateCallOnHoldState(CallManager.getSecondaryCall()) - updateCallContactInfo(CallManager.getPrimaryCall()) + updateState() } override fun onDestroy() { @@ -171,7 +174,10 @@ class CallActivity : SimpleActivity() { dialpad_hashtag_holder.setOnClickListener { dialpadPressed('#') } 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()) } @@ -410,11 +416,23 @@ class CallActivity : SimpleActivity() { if (statusTextId != 0) { call_status_label.text = getString(statusTextId) } + } - val isSingleCallActionsEnabled = (state == Call.STATE_ACTIVE || state == Call.STATE_DISCONNECTED - || state == Call.STATE_DISCONNECTING || state == Call.STATE_HOLDING) - setActionButtonEnabled(call_toggle_hold, isSingleCallActionsEnabled) - setActionButtonEnabled(call_add, isSingleCallActionsEnabled) + 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 + || state == Call.STATE_DISCONNECTING || state == Call.STATE_HOLDING) + setActionButtonEnabled(call_toggle_hold, 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?) { @@ -427,17 +445,23 @@ class CallActivity : SimpleActivity() { } } 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) } private fun updateCallContactInfo(call: Call?) { - CallManager.getCallContact(applicationContext, call) { contact -> - callContact = contact - val avatar = callContactAvatarHelper.getCallContactAvatar(contact) - runOnUiThread { - updateOtherPersonsInfo(avatar) - checkCalledSIMCard() + 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 -> + callContact = contact + val avatar = callContactAvatarHelper.getCallContactAvatar(contact) + runOnUiThread { + updateOtherPersonsInfo(avatar) + checkCalledSIMCard() + } } } } @@ -502,17 +526,12 @@ class CallActivity : SimpleActivity() { private val callCallback = object : CallManagerListener { override fun onStateChanged(call: Call, state: Int) { - updateCallState(call) + updateState() } - override fun onCallPutOnHold(call: Call?) { - updateCallOnHoldState(call) - } - - override fun onCallsChanged(active: Call, onHold: Call?) { - updateCallState(active) - updateCallOnHoldState(onHold) - updateCallContactInfo(active) + override fun onPrimaryCallChanged(call: Call) { + updateCallContactInfo(call) + updateState() } } diff --git a/app/src/main/kotlin/com/simplemobiletools/dialer/helpers/CallManager.kt b/app/src/main/kotlin/com/simplemobiletools/dialer/helpers/CallManager.kt index 4349d195..e8f7c996 100644 --- a/app/src/main/kotlin/com/simplemobiletools/dialer/helpers/CallManager.kt +++ b/app/src/main/kotlin/com/simplemobiletools/dialer/helpers/CallManager.kt @@ -12,6 +12,8 @@ import com.simplemobiletools.commons.helpers.MyContactsContentProvider import com.simplemobiletools.commons.helpers.SimpleContactsHelper import com.simplemobiletools.commons.helpers.ensureBackgroundThread 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 java.util.concurrent.CopyOnWriteArraySet @@ -28,37 +30,73 @@ class CallManager { fun onCallAdded(call: Call) { this.call = call calls.add(call) + for (listener in listeners) { + listener.onPrimaryCallChanged(call) + } call.registerCallback(object : Call.Callback() { override fun onStateChanged(call: Call, state: Int) { Log.d(TAG, "onStateChanged: $call") + updateState() for (listener in listeners) { 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) { + Log.d(TAG, "onConferenceableCallsChanged: $call, conferenceableCalls size=${conferenceableCalls.size}") + updateState() } }) } fun onCallRemoved(call: 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? { @@ -104,14 +142,14 @@ class CallManager { } fun merge() { -// val conferenceableCalls = call!!.conferenceableCalls -// if (conferenceableCalls.isNotEmpty()) { -// call!!.conference(conferenceableCalls.first()) -// } else { -// if (call!!.hasCapability(Call.Details.CAPABILITY_MERGE_CONFERENCE)) { -// call!!.mergeConference() -// } -// } + val conferenceableCalls = call!!.conferenceableCalls + if (conferenceableCalls.isNotEmpty()) { + call!!.conference(conferenceableCalls.first()) + } else { + if (call!!.hasCapability(Call.Details.CAPABILITY_MERGE_CONFERENCE)) { + call!!.mergeConference() + } + } } fun addListener(listener: CallManagerListener) { @@ -203,6 +241,10 @@ class CallManager { interface CallManagerListener { fun onStateChanged(call: Call, state: Int) - fun onCallPutOnHold(call: Call?) - fun onCallsChanged(active: Call, onHold: Call?) + fun onPrimaryCallChanged(call: Call) } + +sealed class PhoneState +object NoCall : PhoneState() +class SingleCall(val call: Call?) : PhoneState() +class TwoCalls(val active: Call, val onHold: Call) : PhoneState() diff --git a/app/src/main/kotlin/com/simplemobiletools/dialer/services/CallService.kt b/app/src/main/kotlin/com/simplemobiletools/dialer/services/CallService.kt index d3912049..0bcddd5d 100644 --- a/app/src/main/kotlin/com/simplemobiletools/dialer/services/CallService.kt +++ b/app/src/main/kotlin/com/simplemobiletools/dialer/services/CallService.kt @@ -46,8 +46,6 @@ class CallService : InCallService() { CallManager.inCallService = null callNotificationManager.cancelNotification() } else { - // TODO if left more than 1 - CallManager.call = CallManager.calls.first() callNotificationManager.setupNotification() startActivity(CallActivity.getStartIntent(this)) } diff --git a/app/src/main/res/drawable/ic_people_vector.xml b/app/src/main/res/drawable/ic_people_vector.xml deleted file mode 100644 index 4910d920..00000000 --- a/app/src/main/res/drawable/ic_people_vector.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - diff --git a/app/src/main/res/layout/activity_call.xml b/app/src/main/res/layout/activity_call.xml index 7d73de8f..bf927509 100644 --- a/app/src/main/res/layout/activity_call.xml +++ b/app/src/main/res/layout/activity_call.xml @@ -118,6 +118,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="@dimen/normal_margin" + android:contentDescription="@null" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" @@ -203,6 +204,7 @@ android:layout_height="@dimen/dialpad_button_size" android:layout_marginTop="@dimen/bigger_margin" android:background="?attr/selectableItemBackgroundBorderless" + android:contentDescription="@string/hold_call" android:padding="@dimen/medium_margin" android:src="@drawable/ic_pause_vector" app:layout_constraintEnd_toStartOf="@id/call_add" @@ -215,6 +217,7 @@ android:layout_height="@dimen/dialpad_button_size" android:layout_marginTop="@dimen/bigger_margin" android:background="?attr/selectableItemBackgroundBorderless" + android:contentDescription="@string/call_add" android:padding="@dimen/medium_margin" android:src="@drawable/ic_add_call_vector" app:layout_constraintEnd_toEndOf="@id/call_manage" @@ -227,6 +230,7 @@ android:layout_height="@dimen/dialpad_button_size" android:layout_marginTop="@dimen/bigger_margin" android:background="?attr/selectableItemBackgroundBorderless" + android:contentDescription="@string/call_manage" android:padding="@dimen/medium_margin" android:src="@drawable/ic_people_vector" android:visibility="gone" @@ -240,6 +244,7 @@ android:layout_height="@dimen/dialpad_button_size" android:layout_marginTop="@dimen/bigger_margin" android:background="?attr/selectableItemBackgroundBorderless" + android:contentDescription="@string/call_swap" android:padding="@dimen/medium_margin" android:src="@drawable/ic_call_swap_vector" app:layout_constraintEnd_toStartOf="@+id/call_merge" @@ -254,6 +259,7 @@ android:layout_height="@dimen/dialpad_button_size" android:layout_marginTop="@dimen/bigger_margin" android:background="?attr/selectableItemBackgroundBorderless" + android:contentDescription="@string/call_merge" android:padding="@dimen/medium_margin" android:src="@drawable/ic_call_merge_vector" app:layout_constraintEnd_toEndOf="parent" diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 928b9370..49689d9a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -51,6 +51,12 @@ Hold call Resume call On Hold + Swap calls + Merge calls + Split call + Add call + Manage calls + Conference Speed dial