Merge branch 'contact'

This commit is contained in:
Juha Heinanen
2023-03-07 07:52:13 +02:00
5 changed files with 154 additions and 93 deletions

View File

@ -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()

View File

@ -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)
}
}

View File

@ -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()

View File

@ -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>

View File

@ -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>