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