Merge branch 'contact'
This commit is contained in:
@ -8,6 +8,7 @@ import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.widget.*
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
@ -23,6 +24,7 @@ class ChatsActivity: AppCompatActivity() {
|
||||
private lateinit var plusButton: ImageButton
|
||||
internal lateinit var aor: String
|
||||
internal lateinit var account: Account
|
||||
private lateinit var chatRequest: ActivityResultLauncher<Intent>
|
||||
private var scrollPosition = -1
|
||||
|
||||
private val onBackPressedCallback = object : OnBackPressedCallback(true) {
|
||||
@ -57,7 +59,7 @@ class ChatsActivity: AppCompatActivity() {
|
||||
listView.adapter = clAdapter
|
||||
listView.isLongClickable = true
|
||||
|
||||
val chatRequest =
|
||||
chatRequest =
|
||||
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
if (it.resultCode == RESULT_OK) {
|
||||
clAdapter.clear()
|
||||
@ -135,34 +137,62 @@ class ChatsActivity: AppCompatActivity() {
|
||||
Contact.contactNames()))
|
||||
|
||||
plusButton.setOnClickListener {
|
||||
val uriText = peerUri.text.toString().trim()
|
||||
if (uriText.isNotEmpty()) {
|
||||
var uri = Contact.contactUri(uriText, null)
|
||||
if (uri == null)
|
||||
uri = if (Utils.isTelNumber(uriText))
|
||||
"tel:$uriText"
|
||||
else
|
||||
Utils.uriComplete(uriText, aor)
|
||||
if (!Utils.checkUri(uri)) {
|
||||
Utils.alertView(this, getString(R.string.notice),
|
||||
String.format(getString(R.string.invalid_sip_or_tel_uri), uri))
|
||||
} else {
|
||||
peerUri.text.clear()
|
||||
peerUri.isCursorVisible = false
|
||||
val i = Intent(this@ChatsActivity, ChatActivity::class.java)
|
||||
val b = Bundle()
|
||||
b.putString("aor", aor)
|
||||
b.putString("peer", uri)
|
||||
i.putExtras(b)
|
||||
chatRequest.launch(i)
|
||||
}
|
||||
}
|
||||
makeChat(true)
|
||||
}
|
||||
|
||||
onBackPressedDispatcher.addCallback(this, onBackPressedCallback)
|
||||
|
||||
}
|
||||
|
||||
private fun makeChat(lookForContact: Boolean = true) {
|
||||
var uriText = peerUri.text.toString().trim()
|
||||
if (uriText.isNotEmpty()) {
|
||||
if (lookForContact) {
|
||||
val uris = Contact.contactUris(uriText)
|
||||
if (uris.size == 1)
|
||||
uriText = uris[0]
|
||||
else if (uris.size > 1) {
|
||||
val builder = MaterialAlertDialogBuilder(this, R.style.AlertDialogTheme)
|
||||
with(builder) {
|
||||
setTitle("Choose Destination")
|
||||
setItems(uris.toTypedArray()) { _, which ->
|
||||
peerUri.setText(uris[which])
|
||||
makeChat(false)
|
||||
}
|
||||
setNeutralButton(getString(R.string.cancel)) { _: DialogInterface, _: Int -> }
|
||||
show()
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
if (Utils.isTelNumber(uriText))
|
||||
uriText = "tel:$uriText"
|
||||
val uri = if (Utils.isTelUri(uriText)) {
|
||||
if (account.telProvider == "") {
|
||||
Utils.alertView(this, getString(R.string.notice),
|
||||
String.format(getString(R.string.no_telephony_provider), account.aor))
|
||||
return
|
||||
}
|
||||
Utils.telToSip(uriText, account)
|
||||
} else {
|
||||
Utils.uriComplete(uriText, aor)
|
||||
}
|
||||
if (!Utils.checkUri(uri)) {
|
||||
Utils.alertView(this, getString(R.string.notice),
|
||||
String.format(getString(R.string.invalid_sip_or_tel_uri), uri))
|
||||
} else {
|
||||
peerUri.text.clear()
|
||||
peerUri.isCursorVisible = false
|
||||
val i = Intent(this@ChatsActivity, ChatActivity::class.java)
|
||||
val b = Bundle()
|
||||
b.putString("aor", aor)
|
||||
b.putString("peer", uri)
|
||||
i.putExtras(b)
|
||||
chatRequest.launch(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
MainActivity.activityAor = aor
|
||||
super.onPause()
|
||||
|
||||
@ -51,36 +51,28 @@ sealed class Contact {
|
||||
return uri
|
||||
}
|
||||
|
||||
// Return uri of contact name or null if contact is not found
|
||||
// If Android contact has more than one uri, return latest if given and found
|
||||
fun contactUri(name: String, latest: String?): String? {
|
||||
// Return URIs of contact name
|
||||
fun contactUris(name: String): ArrayList<String> {
|
||||
val uris = ArrayList<String>()
|
||||
for (c in contacts())
|
||||
when (c) {
|
||||
is BaresipContact -> {
|
||||
if (c.name.equals(name, ignoreCase = true))
|
||||
return c.uri.removePrefix("<")
|
||||
.replaceAfter(">", "")
|
||||
.replace(">", "")
|
||||
if (c.name.equals(name, ignoreCase = true)) {
|
||||
uris.add(c.uri.removePrefix("<")
|
||||
.replaceAfter(">", "")
|
||||
.replace(">", ""))
|
||||
return uris
|
||||
}
|
||||
}
|
||||
is AndroidContact -> {
|
||||
if (c.name == name) {
|
||||
return if (c.uris.isNotEmpty()) {
|
||||
var uri = c.uris.first()
|
||||
if (c.uris.size > 1 && latest != null) {
|
||||
for (u in c.uris)
|
||||
if (u == latest) {
|
||||
uri = latest
|
||||
break
|
||||
}
|
||||
}
|
||||
uri
|
||||
} else {
|
||||
null
|
||||
}
|
||||
for (u in c.uris)
|
||||
uris.add(u)
|
||||
return uris
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
return uris
|
||||
}
|
||||
|
||||
fun findContact(uri: String): Contact? {
|
||||
@ -127,7 +119,7 @@ sealed class Contact {
|
||||
// cursor using getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE
|
||||
val projection = arrayOf(ContactsContract.Data.CONTACT_ID, ContactsContract.Data.DISPLAY_NAME,
|
||||
ContactsContract.Data.MIMETYPE, ContactsContract.Data.DATA1,
|
||||
ContactsContract.Data.PHOTO_THUMBNAIL_URI)
|
||||
/* ContactsContract.Data.DATA2 ,*/ ContactsContract.Data.PHOTO_THUMBNAIL_URI)
|
||||
val selection =
|
||||
ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE + "' OR " +
|
||||
ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE + "'"
|
||||
@ -149,8 +141,10 @@ sealed class Contact {
|
||||
contact.name = name
|
||||
if (contact.thumbnailUri == null && thumb != null)
|
||||
contact.thumbnailUri = thumb
|
||||
if (mime == ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
|
||||
contact.uris.add("tel:${data.filterNot{setOf('-', ' ', '(', ')').contains(it)}}")
|
||||
if (mime == ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) {
|
||||
contact.uris.add("tel:${data.filterNot { setOf('-', ' ', '(', ')').contains(it) }}")
|
||||
// contact.types.add(typeToString(cur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE)))
|
||||
}
|
||||
else if (mime == ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE)
|
||||
contact.uris.add("sip:$data")
|
||||
else
|
||||
@ -164,6 +158,16 @@ sealed class Contact {
|
||||
BaresipService.androidContacts.add(value)
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
private fun typeToString(type: Int): String {
|
||||
return when(type) {
|
||||
ContactsContract.CommonDataKinds.Phone.TYPE_HOME -> "Home"
|
||||
ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE -> "Mobile"
|
||||
ContactsContract.CommonDataKinds.Phone.TYPE_WORK -> "Work"
|
||||
else -> "Unknown"
|
||||
}
|
||||
}
|
||||
|
||||
fun restoreBaresipContacts(): Boolean {
|
||||
val content = Utils.getFileContents(BaresipService.filesPath + "/contacts")
|
||||
?: return false
|
||||
@ -235,8 +239,7 @@ sealed class Contact {
|
||||
is BaresipContact ->
|
||||
BaresipService.contactNames.add(c.name)
|
||||
is AndroidContact ->
|
||||
if (c.uris.size == 1)
|
||||
BaresipService.contactNames.add(c.name)
|
||||
BaresipService.contactNames.add(c.name)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1448,33 +1448,31 @@ class MainActivity : AppCompatActivity() {
|
||||
dialog.dismiss()
|
||||
var uriText = transferUri.text.toString().trim()
|
||||
if (uriText.isNotEmpty()) {
|
||||
uriText = Contact.contactUri(uriText, null) ?: uriText
|
||||
if (Utils.isTelNumber(uriText))
|
||||
uriText = "tel:$uriText"
|
||||
val uri = if (Utils.isTelUri(uriText))
|
||||
Utils.telToSip(uriText, ua.account)
|
||||
else
|
||||
Utils.uriComplete(uriText, ua.account.aor)
|
||||
if (!Utils.checkUri(uri)) {
|
||||
Utils.alertView(this@MainActivity, getString(R.string.notice),
|
||||
String.format(getString(R.string.invalid_sip_or_tel_uri), uri))
|
||||
} else {
|
||||
val call = ua.currentCall()
|
||||
if (call != null) {
|
||||
if (attended.isChecked) {
|
||||
if (call.hold()) {
|
||||
call.referTo = uri
|
||||
call(ua, uri, call)
|
||||
}
|
||||
} else {
|
||||
if (!call.transfer(uri)) {
|
||||
Utils.alertView(this@MainActivity, getString(R.string.notice),
|
||||
String.format(getString(R.string.transfer_failed)))
|
||||
}
|
||||
val uris = Contact.contactUris(uriText)
|
||||
if (uris.size > 1) {
|
||||
val destinationBuilder = MaterialAlertDialogBuilder(
|
||||
this@MainActivity,
|
||||
R.style.AlertDialogTheme
|
||||
)
|
||||
with(destinationBuilder) {
|
||||
setTitle(R.string.choose_destination_uri)
|
||||
setItems(uris.toTypedArray()) { _, which ->
|
||||
uriText = uris[which]
|
||||
transfer(
|
||||
ua,
|
||||
if (Utils.isTelNumber(uriText)) "tel:$uriText" else uriText,
|
||||
attended.isChecked
|
||||
)
|
||||
}
|
||||
showCall(ua)
|
||||
setNeutralButton(getString(R.string.cancel)) { _: DialogInterface, _: Int -> }
|
||||
show()
|
||||
}
|
||||
} else {
|
||||
if (uris.size == 1)
|
||||
uriText = uris[0]
|
||||
}
|
||||
transfer(ua, if (Utils.isTelNumber(uriText)) "tel:$uriText" else uriText,
|
||||
attended.isChecked)
|
||||
}
|
||||
}
|
||||
setNeutralButton(android.R.string.cancel) { dialog, _ ->
|
||||
@ -1509,6 +1507,32 @@ class MainActivity : AppCompatActivity() {
|
||||
alertDialog.show()
|
||||
}
|
||||
|
||||
private fun transfer(ua: UserAgent, uriText: String, attended: Boolean) {
|
||||
val uri = if (Utils.isTelUri(uriText))
|
||||
Utils.telToSip(uriText, ua.account)
|
||||
else
|
||||
Utils.uriComplete(uriText, ua.account.aor)
|
||||
if (!Utils.checkUri(uri)) {
|
||||
Utils.alertView(this@MainActivity, getString(R.string.notice),
|
||||
String.format(getString(R.string.invalid_sip_or_tel_uri), uri))
|
||||
} else {
|
||||
val call = ua.currentCall()
|
||||
if (call != null) {
|
||||
if (attended) {
|
||||
if (call.hold()) {
|
||||
call.referTo = uri
|
||||
call(ua, uri, call)
|
||||
}
|
||||
} else {
|
||||
if (!call.transfer(uri)) {
|
||||
Utils.alertView(this@MainActivity, getString(R.string.notice),
|
||||
String.format(getString(R.string.transfer_failed)))
|
||||
}
|
||||
}
|
||||
showCall(ua)
|
||||
}
|
||||
}
|
||||
}
|
||||
private fun askPassword(title: String, ua: UserAgent? = null) {
|
||||
val layout = LayoutInflater.from(this)
|
||||
.inflate(R.layout.password_dialog, findViewById(android.R.id.content),
|
||||
@ -1751,34 +1775,37 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun makeCall() {
|
||||
private fun makeCall(lookForContact: Boolean = true) {
|
||||
callUri.setAdapter(null)
|
||||
val ua = BaresipService.uas[aorSpinner.selectedItemPosition]
|
||||
val aor = ua.account.aor
|
||||
if (Call.calls().isEmpty()) {
|
||||
var uriText = callUri.text.toString().trim()
|
||||
if (uriText.isNotEmpty()) {
|
||||
uriText = Contact.contactUri(uriText, NewCallHistory.aorLatestPeerUri(aor)) ?: uriText
|
||||
if (lookForContact) {
|
||||
val uris = Contact.contactUris(uriText)
|
||||
if (uris.size == 1)
|
||||
uriText = uris[0]
|
||||
else if (uris.size > 1) {
|
||||
val builder = MaterialAlertDialogBuilder(this, R.style.AlertDialogTheme)
|
||||
with(builder) {
|
||||
setTitle(R.string.choose_destination_uri)
|
||||
setItems(uris.toTypedArray()) { _, which ->
|
||||
callUri.setText(uris[which])
|
||||
makeCall(false)
|
||||
}
|
||||
setNeutralButton(getString(R.string.cancel)) { _: DialogInterface, _: Int -> }
|
||||
show()
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
if (Utils.isTelNumber(uriText))
|
||||
uriText = "tel:$uriText"
|
||||
val uri = if (Utils.isTelUri(uriText)) {
|
||||
if (ua.account.telProvider == "") {
|
||||
val telAccounts = Account.telProviderAccounts()
|
||||
if (telAccounts.isEmpty()) {
|
||||
Utils.alertView(this, getString(R.string.notice),
|
||||
getString(R.string.no_telephony_providers))
|
||||
} else {
|
||||
val builder = MaterialAlertDialogBuilder(this, R.style.AlertDialogTheme)
|
||||
with(builder) {
|
||||
setTitle(getString(R.string.choose_telephony_provider_account))
|
||||
setItems(telAccounts) { _, which ->
|
||||
spinToAor("sip:${telAccounts[which]}")
|
||||
makeCall()
|
||||
}
|
||||
setNeutralButton("Cancel") { _: DialogInterface, _: Int -> }
|
||||
show()
|
||||
}
|
||||
}
|
||||
Utils.alertView(this, getString(R.string.notice),
|
||||
String.format(getString(R.string.no_telephony_provider), aor))
|
||||
return
|
||||
}
|
||||
Utils.telToSip(uriText, ua.account)
|
||||
@ -1787,8 +1814,7 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
if (!Utils.checkUri(uri)) {
|
||||
Utils.alertView(this, getString(R.string.notice),
|
||||
String.format(getString(R.string.invalid_sip_or_tel_uri), uri)
|
||||
)
|
||||
String.format(getString(R.string.invalid_sip_or_tel_uri), uri))
|
||||
} else {
|
||||
callUri.isFocusable = false
|
||||
uaAdapter.notifyDataSetChanged()
|
||||
|
||||
@ -479,6 +479,7 @@
|
||||
<string name="blind">Sokeasti</string>
|
||||
<string name="attended">Osallistu</string>
|
||||
<string name="transfer_destination">Siirron kohde</string>
|
||||
<string name="choose_destination_uri">Valitse kohteen URI</string>
|
||||
<string name="transfer">Siirto</string>
|
||||
<string name="transfer_failed">Siirto epäonnistui</string>
|
||||
<string name="dtmf">DTMF</string>
|
||||
|
||||
@ -452,6 +452,7 @@
|
||||
<string name="blind">Blind</string>
|
||||
<string name="attended">Attended</string>
|
||||
<string name="transfer_destination">Transfer destination</string>
|
||||
<string name="choose_destination_uri">Choose destination URI</string>
|
||||
<string name="transfer">Transfer</string>
|
||||
<string name="transfer_failed">Transfer failed</string>
|
||||
<string name="dtmf">DTMF</string>
|
||||
|
||||
Reference in New Issue
Block a user