diff --git a/app/build.gradle b/app/build.gradle index f68e79ae..88183be2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -7,8 +7,8 @@ android { applicationId = 'com.tutpro.baresip' minSdkVersion 21 targetSdkVersion 27 - versionCode = 32 - versionName = '3.2.3' + versionCode = 33 + versionName = '4.0.0' externalNativeBuild { cmake { cFlags '-DHAVE_INTTYPES_H' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 9bf1d32b..6c5cc781 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -47,76 +47,49 @@ android:name=".AccountsActivity" android:label="Accounts" android:parentActivityName=".MainActivity"> - - + android:parentActivityName=".AccountsActivity"> - + android:windowSoftInputMode="adjustPan" + android:parentActivityName=".MainActivity" > - + android:parentActivityName=".ContactsActivity" > - + android:parentActivityName=".MainActivity" > - + android:parentActivityName=".MainActivity" > - + android:name=".ChatsActivity" + android:label="Chat History" + android:parentActivityName=".MainActivity" > - + android:name=".ChatActivity" + android:label="Messages of a Chat" + android:parentActivityName=".ChatsActivity" > - () - var posAtAccounts = ArrayList() fun generateAccounts() { accounts.clear() - posAtAccounts.clear() - var i = 0; - for (ua in MainActivity.uas) { + for (ua in MainActivity.uas) accounts.add(AccountRow(ua.account.aor.replace("sip:", ""), R.drawable.action_remove)) - posAtAccounts.add(i) - i++ - } } fun saveAccounts() { diff --git a/app/src/main/kotlin/com/tutpro/baresip/CallsActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/CallsActivity.kt index 0987b211..6d5ef681 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/CallsActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/CallsActivity.kt @@ -40,7 +40,7 @@ class CallsActivity : AppCompatActivity() { val adapter = CallListAdapter(this, uaHistory) listview.adapter = adapter listview.onItemClickListener = AdapterView.OnItemClickListener { _, _, pos, _ -> - val i = Intent(this@CallsActivity, MessageActivity::class.java) + val i = Intent(this@CallsActivity, ChatActivity::class.java) val b = Bundle() b.putString("aor", aor) b.putString("peer", uaHistory[pos].peerURI) diff --git a/app/src/main/kotlin/com/tutpro/baresip/ChatActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/ChatActivity.kt new file mode 100644 index 00000000..94696470 --- /dev/null +++ b/app/src/main/kotlin/com/tutpro/baresip/ChatActivity.kt @@ -0,0 +1,205 @@ +package com.tutpro.baresip + +import android.app.Activity +import android.content.* +import android.os.Bundle +import android.support.v4.content.LocalBroadcastManager +import android.support.v7.app.AlertDialog +import android.support.v7.app.AppCompatActivity +import android.util.Log +import android.view.Menu +import android.view.MenuItem +import android.view.View +import android.view.WindowManager +import android.view.inputmethod.InputMethodManager +import android.widget.* + +class ChatActivity : AppCompatActivity() { + + internal lateinit var chatMessages: ArrayList + internal lateinit var mlAdapter: MessageListAdapter + internal lateinit var newMessage: EditText + internal lateinit var sendButton: ImageButton + internal lateinit var imm: InputMethodManager + internal lateinit var aor: String + internal lateinit var peerUri: String + internal lateinit var ua: UserAgent + internal lateinit var messageResponseReceiver: BroadcastReceiver + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + setContentView(R.layout.activity_chat) + + aor = intent.extras.getString("aor") + peerUri = intent.extras.getString("peer") + val reply = intent.extras.getBoolean("reply") + + val userAgent = Account.findUa(aor) + if (userAgent == null) { + Log.e("Baresip", "MessageActivity did not find ua of $aor") + val i = Intent() + setResult(Activity.RESULT_CANCELED, i) + finish() + } else { + ua = userAgent + } + + imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + this@ChatActivity.window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN) + + var chatPeer = ContactsActivity.contactName(peerUri) + if (chatPeer.startsWith("sip:")) { + if (Utils.checkTelNo(Utils.uriUserPart(peerUri))) + chatPeer = Utils.uriUserPart(peerUri) + else + chatPeer = chatPeer.substring(4) + } + setTitle("Chat with $chatPeer") + + chatMessages = uaPeerMessages(aor, peerUri) + + val listView = findViewById(R.id.messages) as ListView + mlAdapter = MessageListAdapter(this, chatMessages) + listView.adapter = mlAdapter + listView.isLongClickable = true + val footerView = View(applicationContext) + listView.addFooterView(footerView) + listView.smoothScrollToPosition(mlAdapter.count) + + listView.onItemLongClickListener = AdapterView.OnItemLongClickListener { _, _, pos, _ -> + val dialogClickListener = DialogInterface.OnClickListener { _, which -> + when (which) { + DialogInterface.BUTTON_NEUTRAL -> { + val i = Intent(this, ContactActivity::class.java) + val b = Bundle() + b.putBoolean("new", true) + b.putString("uri", peerUri) + i.putExtras(b) + startActivityForResult(i, MainActivity.CONTACT_CODE) + } + DialogInterface.BUTTON_NEGATIVE -> { + MainActivity.messages.remove(chatMessages[pos]) + chatMessages.removeAt(pos) + mlAdapter.notifyDataSetChanged() + if (chatMessages.size == 0) { + listView.removeFooterView(footerView) + } + } + DialogInterface.BUTTON_POSITIVE -> { + } + } + } + val builder = AlertDialog.Builder(this@ChatActivity, R.style.Theme_AppCompat) + if (chatPeer.contains("@") || Utils.checkTelNo(chatPeer)) + builder.setMessage("Do you want to delete message or add peer $chatPeer to contacts?") + .setPositiveButton("Cancel", dialogClickListener) + .setNegativeButton("Delete Message", dialogClickListener) + .setNeutralButton("Add Contact", dialogClickListener) + .show() + else + builder.setMessage("Do you want to delete message?") + .setPositiveButton("Cancel", dialogClickListener) + .setNegativeButton("Delete Message", dialogClickListener) + .show() + true + } + + newMessage = findViewById(R.id.text) as EditText + if (reply) newMessage.requestFocus() + + sendButton = findViewById(R.id.sendButton) as ImageButton + sendButton.setOnClickListener { + val msgText = newMessage.text.toString() + if (msgText.length > 0) { + imm.hideSoftInputFromWindow(newMessage.windowToken, 0) + val time = System.currentTimeMillis() + val msg = Message(aor, peerUri, R.drawable.arrow_up_yellow, msgText, time,true) + MainActivity.messages.add(msg) + chatMessages.add(msg) + mlAdapter.notifyDataSetChanged() + if (message_send(ua!!.uap, peerUri, msgText, time.toString()) != 0) + Toast.makeText(getApplicationContext(), "Sending of message failed!", + Toast.LENGTH_SHORT).show() + else + newMessage.text.clear() + } + } + + messageResponseReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + handleMessageResponse(intent.getIntExtra("response code", 0), + intent.getStringExtra("time")) + } + } + LocalBroadcastManager.getInstance(this).registerReceiver(messageResponseReceiver, + IntentFilter("message response")) + + } + + override fun onCreateOptionsMenu(menu: Menu): Boolean { + menuInflater.inflate(R.menu.call_icon, menu) + return true + } + + override fun onPause() { + ChatsActivity.saveMessages() + super.onPause() + } + + override fun onDestroy() { + LocalBroadcastManager.getInstance(this).unregisterReceiver(messageResponseReceiver) + super.onDestroy() + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + when (item.itemId) { + android.R.id.home -> { + for (m in chatMessages) if (m.new) m.new = false + imm.hideSoftInputFromWindow(newMessage.windowToken, 0) + val i = Intent() + setResult(Activity.RESULT_OK, i) + } + R.id.callIcon -> { + val intent = Intent(this, MainActivity::class.java) + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or + Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP) + intent.putExtra("action", "call") + intent.putExtra("uap", ua.uap) + intent.putExtra("peer", ContactsActivity.contactName(peerUri)) + startActivity(intent) + } + } + finish() + return true + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) { + if ((requestCode == MainActivity.CONTACT_CODE) && (resultCode == Activity.RESULT_OK)) { + setTitle("Chat with ${data.getStringExtra("name")}") + } + } + + private fun uaPeerMessages(aor: String, peerUri: String): ArrayList { + val res = ArrayList() + for (m in MainActivity.messages) + if ((m.aor == aor) && (m.peerUri == peerUri)) res.add(m) + return res + } + + private fun handleMessageResponse(responseCode: Int, time: String) { + val timeStamp = time.toLong() + for (m in chatMessages.reversed()) + if (m.timeStamp == timeStamp) { + if (responseCode < 300) + m.direction = R.drawable.arrow_up_green + else + m.direction = R.drawable.arrow_up_red + mlAdapter.notifyDataSetChanged() + return + } + } + + external fun message_send(uap: String, peer_uri: String, message: String, time: String): Int + +} diff --git a/app/src/main/kotlin/com/tutpro/baresip/ChatListAdapter.kt b/app/src/main/kotlin/com/tutpro/baresip/ChatListAdapter.kt new file mode 100644 index 00000000..38c1645e --- /dev/null +++ b/app/src/main/kotlin/com/tutpro/baresip/ChatListAdapter.kt @@ -0,0 +1,53 @@ +package com.tutpro.baresip + +import android.content.Context +import android.graphics.Typeface +import android.text.format.DateUtils.isToday +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ArrayAdapter +import android.widget.ImageView +import android.widget.TextView + +import java.text.SimpleDateFormat +import java.util.* + +class ChatListAdapter(private val cxt: Context, private var rows: ArrayList) : + ArrayAdapter(cxt, R.layout.message, rows) { + + override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { + val message = rows[position] + val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater + val messageView = inflater.inflate(R.layout.message, parent, false) + val directionView = messageView.findViewById(R.id.direction) as ImageView + directionView.setImageResource(message.direction) + val peerView = messageView.findViewById(R.id.peer) as TextView + val contactName = ContactsActivity.contactName(message.peerUri) + if (contactName.startsWith("sip:") && + (Utils.uriHostPart(message.peerUri) == Utils.uriHostPart(message.aor))) + peerView.text = Utils.uriUserPart(message.peerUri) + else + peerView.text = contactName + val timeView = messageView.findViewById(R.id.time) as TextView + val time: String + val cal = GregorianCalendar() + cal.timeInMillis = message.timeStamp + if (isToday(message.timeStamp)) { + val fmt = SimpleDateFormat("HH:mm") + time = fmt.format(cal.time) + } else { + val fmt = SimpleDateFormat("dd.MM") + time = fmt.format(cal.time) + } + timeView.text = time + val textView = messageView.findViewById(R.id.text) as TextView + textView.text = message.message + if (message.new) { + textView.setTypeface(null, Typeface.BOLD) + message.new = false + } + return messageView + } + +} diff --git a/app/src/main/kotlin/com/tutpro/baresip/MessagesActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/ChatsActivity.kt similarity index 56% rename from app/src/main/kotlin/com/tutpro/baresip/MessagesActivity.kt rename to app/src/main/kotlin/com/tutpro/baresip/ChatsActivity.kt index 3116c3f5..4b60773d 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/MessagesActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/ChatsActivity.kt @@ -3,14 +3,11 @@ package com.tutpro.baresip import android.app.Activity import android.content.* import android.os.Bundle -import android.support.v4.content.LocalBroadcastManager import android.support.v7.app.AlertDialog import android.support.v7.app.AppCompatActivity import android.util.Log import android.view.MenuItem -import android.widget.AdapterView -import android.widget.ImageButton -import android.widget.ListView +import android.widget.* import java.io.File import java.io.FileInputStream @@ -20,32 +17,34 @@ import java.io.ObjectInputStream import java.io.ObjectOutputStream import java.util.* -class MessagesActivity: AppCompatActivity() { +class ChatsActivity: AppCompatActivity() { + internal lateinit var uaMessages: ArrayList internal lateinit var aor: String - internal lateinit var mlAdapter: MessageListAdapter + internal lateinit var listView: ListView + internal lateinit var clAdapter: ChatListAdapter + internal lateinit var peerUri: AutoCompleteTextView internal lateinit var plusButton: ImageButton - internal lateinit var serviceEventReceiver: BroadcastReceiver public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.activity_messages) + setContentView(R.layout.activity_chats) - val listView = findViewById(R.id.messages) as ListView + listView = findViewById(R.id.chats) as ListView plusButton = findViewById(R.id.plusButton) as ImageButton aor = intent.extras.getString("aor") uaMessages = uaMessages(aor) - mlAdapter = MessageListAdapter(this, uaMessages) - listView.adapter = mlAdapter + clAdapter = ChatListAdapter(this, uaMessages) + listView.adapter = clAdapter listView.isLongClickable = true listView.onItemClickListener = AdapterView.OnItemClickListener { _, _, pos, _ -> - val i = Intent(this@MessagesActivity, MessageActivity::class.java) + val i = Intent(this, ChatActivity::class.java) val b = Bundle() b.putString("aor", aor) - b.putString("peer", uaMessages[pos].peerURI) + b.putString("peer", uaMessages[pos].peerUri) i.putExtras(b) startActivityForResult(i, MainActivity.MESSAGE_CODE) } @@ -57,55 +56,77 @@ class MessagesActivity: AppCompatActivity() { val i = Intent(this, ContactActivity::class.java) val b = Bundle() b.putBoolean("new", true) - b.putString("uri", uaMessages[pos].peerURI) + b.putString("uri", uaMessages[pos].peerUri) i.putExtras(b) startActivityForResult(i, MainActivity.CONTACT_CODE) } DialogInterface.BUTTON_NEGATIVE -> { - MainActivity.messages.remove(uaMessages[pos]) - saveMessages() - uaMessages.removeAt(pos) - if (uaMessages.size == 0) { - val i = Intent() - setResult(Activity.RESULT_CANCELED, i) - finish() - } - mlAdapter.notifyDataSetChanged() + val peerUri = uaMessages[pos].peerUri + val msgs = ArrayList() + for (m in MainActivity.messages) + if ((m.aor != aor) || (m.peerUri != peerUri)) + msgs.add(m) + else + clAdapter.remove(m) + clAdapter.notifyDataSetChanged() + MainActivity.messages = msgs + uaMessages = uaMessages(aor) } DialogInterface.BUTTON_POSITIVE -> { } } } - val builder = AlertDialog.Builder(this@MessagesActivity, - R.style.Theme_AppCompat) - if (ContactsActivity.contactName(uaMessages[pos].peerURI).startsWith("sip:")) - builder.setMessage("Do you want to add ${uaMessages[pos].peerURI} to contacs or " + - "delete message from history?") + val builder = AlertDialog.Builder(this@ChatsActivity, R.style.Theme_AppCompat) + val peer = ContactsActivity.contactName(uaMessages[pos].peerUri) + if (peer.startsWith("sip:")) + builder.setMessage("Do you want to delete chat with $peer or add peer to contacts?") .setPositiveButton("Cancel", dialogClickListener) - .setNegativeButton("Delete Message", dialogClickListener) + .setNegativeButton("Delete Chat", dialogClickListener) .setNeutralButton("Add Contact", dialogClickListener) .show() else - builder.setMessage("Do you want to delete message from history?") + builder.setMessage("Do you want to delete chat with $peer?") .setPositiveButton("Cancel", dialogClickListener) - .setNegativeButton("Delete Message", dialogClickListener) + .setNegativeButton("Delete Chat", dialogClickListener) .show() true } + peerUri = findViewById(R.id.peerUri) as AutoCompleteTextView + peerUri.threshold = 2 + peerUri.setAdapter(ArrayAdapter(this, android.R.layout.select_dialog_item, + ContactsActivity.contacts.map{Contact -> Contact.name})) + plusButton.setOnClickListener { - val i = Intent(this@MessagesActivity, MessageActivity::class.java) - val b = Bundle() - b.putString("aor", aor) - b.putString("peer", "") - i.putExtras(b) - startActivityForResult(i, MainActivity.MESSAGE_CODE) + val uriText = peerUri.text.toString().trim() + if (uriText.length > 0) { + var uri = ContactsActivity.findContactURI(uriText) + if (!uri.startsWith("sip:")) { + uri = "sip:$uri" + if (!uri.contains("@")) { + val host = aor.substring(aor.indexOf("@") + 1) + uri = "$uri@$host" + } + } + if (!Utils.checkSipUri(uri)) { + Utils.alertView(this, "Notice", "Invalid SIP 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) + startActivityForResult(i, MainActivity.MESSAGE_CODE) + } + } } val peer = intent.extras.getString("peer") - if (peer != null) { - val i = Intent(this@MessagesActivity, MessageActivity::class.java) + if (peer != "") { + val i = Intent(this, ChatActivity::class.java) val b = Bundle() b.putString("aor", aor) b.putString("peer", peer) @@ -113,22 +134,17 @@ class MessagesActivity: AppCompatActivity() { startActivityForResult(i, MainActivity.MESSAGE_CODE) } - serviceEventReceiver = object : BroadcastReceiver() { - override fun onReceive(context: Context, intent: Intent) { - handleMessageResponse(intent.getIntExtra("response code", 0), - intent.getStringExtra("time")) - } - } - LocalBroadcastManager.getInstance(this).registerReceiver(serviceEventReceiver, - IntentFilter("message response")) + } + override fun onPause() { + saveMessages() + super.onPause() } override fun onOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { android.R.id.home -> { - Log.d("Baresip", "Back array was pressed at Messages") - saveMessages() + Log.d("Baresip", "Back array was pressed at Chats") val i = Intent() setResult(Activity.RESULT_CANCELED, i) finish() @@ -138,46 +154,32 @@ class MessagesActivity: AppCompatActivity() { } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - Log.d("Baresip", "onActivityResult at Messages") - when (requestCode) { - MainActivity.MESSAGE_CODE -> { - if (resultCode == RESULT_OK) { - mlAdapter.notifyDataSetChanged() - } - } + Log.d("Baresip", "onActivityResult $requestCode $resultCode") + if ((requestCode == MainActivity.MESSAGE_CODE) && (resultCode == Activity.RESULT_OK)) { + clAdapter.clear() + uaMessages = uaMessages(aor) + clAdapter = ChatListAdapter(this, uaMessages) + listView.adapter = clAdapter } } - private fun handleMessageResponse(responseCode: Int, time: String) { - if (responseCode < 300) - updateMessageDirection(time.toLong(), R.drawable.arrow_up_green) - else - updateMessageDirection(time.toLong(), R.drawable.arrow_up_red) - mlAdapter.notifyDataSetChanged() - } - - fun updateMessageDirection(timeStamp: Long, direction: Int) { - for (m in uaMessages.reversed()) - if (m.timeStamp == timeStamp) { - m.direction = direction - return - } - } - private fun uaMessages(aor: String) : ArrayList { val res = ArrayList() for (m in MainActivity.messages.reversed()) { - if (m.aor == aor) { - res.add(m) - } + if (m.aor != aor) continue + var found = false + for (r in res) + if (r.peerUri == m.peerUri) { + found = true + break + } + if (!found) res.add(m) } return res } companion object { - var uaMessages = ArrayList() - fun archiveUaMessage(aor: String, time: Long) { for (i in MainActivity.messages.indices.reversed()) if ((MainActivity.messages[i].aor == aor) && @@ -198,18 +200,6 @@ class MessagesActivity: AppCompatActivity() { } } - fun addMessage(message: Message) { - if ((MainActivity.messages.filter{it.aor == message.aor}).size >= - MainActivity.MESSAGE_HISTORY_SIZE) - for (i in MainActivity.messages.indices) - if (MainActivity.messages[i].aor == message.aor) { - MainActivity.messages.removeAt(i) - break - } - MainActivity.messages.add(message) - saveMessages() - } - fun saveMessages() { val file = File(MainActivity.filesPath, "messages") try { diff --git a/app/src/main/kotlin/com/tutpro/baresip/ContactActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/ContactActivity.kt index 6377dfbc..d1dd50c4 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/ContactActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/ContactActivity.kt @@ -1,5 +1,6 @@ package com.tutpro.baresip +import android.app.Activity import android.content.Intent import android.os.Bundle import android.support.v7.app.AppCompatActivity @@ -87,14 +88,15 @@ class ContactActivity : AppCompatActivity() { ContactsActivity.contacts.sortBy { Contact -> Contact.name } ContactsActivity.saveContacts() - setResult(RESULT_OK, i) + i.putExtra("name", newName) + setResult(Activity.RESULT_OK, i) finish() return true } else if (item.itemId == android.R.id.home) { Log.d("Baresip", "Back array was pressed at Contact") - setResult(RESULT_CANCELED, i) + setResult(Activity.RESULT_CANCELED, i) finish() return true diff --git a/app/src/main/kotlin/com/tutpro/baresip/ContactListAdapter.kt b/app/src/main/kotlin/com/tutpro/baresip/ContactListAdapter.kt index 5976ae23..d50300b8 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/ContactListAdapter.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/ContactListAdapter.kt @@ -31,7 +31,7 @@ class ContactListAdapter(private val cxt: Context, private val rows: ArrayList - val i = Intent(cxt, MessageActivity::class.java) + val i = Intent(cxt, ChatActivity::class.java) val b = Bundle() b.putString("aor", aor) b.putString("peer", ContactsActivity.contacts[position].uri) diff --git a/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt index daff4611..548c3464 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt @@ -324,12 +324,13 @@ class MainActivity : AppCompatActivity() { startActivityForResult(i, CONTACTS_CODE) } - MessagesActivity.restoreMessages(applicationContext.filesDir.path) + ChatsActivity.restoreMessages(applicationContext.filesDir.path) messagesButton.setOnClickListener { if (aorSpinner.selectedItemPosition >= 0) { - val i = Intent(this@MainActivity, MessagesActivity::class.java) + val i = Intent(this@MainActivity, ChatsActivity::class.java) val b = Bundle() b.putString("aor", uas[aorSpinner.selectedItemPosition].account.aor) + b.putString("peer", "") i.putExtras(b) startActivityForResult(i, MESSAGES_CODE) } @@ -642,20 +643,22 @@ class MainActivity : AppCompatActivity() { } } "message" -> { - val peer_uri = params[1] - val msg = params[2] + val peerUri = params[1] + val msgText = params[2] val time = params[3] - val new_message = Message(aor, peer_uri, R.drawable.arrow_down_green, msg, + val newMsg = Message(aor, peerUri, R.drawable.arrow_down_green, msgText, time.toLong(), true) - Log.d("Baresip", "Incoming message $aor/$peer_uri/$msg") - MessagesActivity.addMessage(new_message) + Log.d("Baresip", "Incoming message $aor/$peerUri/$msgText") + messages.add(newMsg) + ChatsActivity.saveMessages() if (Utils.isVisible()) { if (ua != uas[aorSpinner.selectedItemPosition]) aorSpinner.setSelection(account_index) - val i = Intent(applicationContext, MessagesActivity::class.java) + val i = Intent(applicationContext, ChatsActivity::class.java) i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) val b = Bundle() b.putString("aor", ua.account.aor) + b.putString("peer", peerUri) i.putExtras(b) startActivity(i) } @@ -670,7 +673,8 @@ class MainActivity : AppCompatActivity() { break } } - if (ua == uas[aorSpinner.selectedItemPosition]) + if ((aorSpinner.selectedItemPosition >= 0) && + (ua == uas[aorSpinner.selectedItemPosition])) if (acc.vmNew > 0) voicemailButton.setImageResource(R.drawable.voicemail_new) else @@ -735,7 +739,7 @@ class MainActivity : AppCompatActivity() { val aor = ua.account.aor when (action) { "reply" -> { - val i = Intent(this@MainActivity, MessagesActivity::class.java) + val i = Intent(this@MainActivity, ChatActivity::class.java) val b = Bundle() if (ua != uas[aorSpinner.selectedItemPosition]) { for (account_index in uas.indices) { @@ -749,15 +753,15 @@ class MainActivity : AppCompatActivity() { b.putString("peer", intent.getStringExtra("peer")) b.putBoolean("reply", true) i.putExtras(b) - startActivityForResult(i, MESSAGES_CODE) + startActivityForResult(i, MESSAGE_CODE) } "archive" -> { - MessagesActivity.archiveUaMessage(ua.account.aor, + ChatsActivity.archiveUaMessage(ua.account.aor, intent.getStringExtra("time").toLong()) moveTaskToBack(true) } "delete" -> { - MessagesActivity.deleteUaMessage(ua.account.aor, + ChatsActivity.deleteUaMessage(ua.account.aor, intent.getStringExtra("time").toLong()) moveTaskToBack(true) } diff --git a/app/src/main/kotlin/com/tutpro/baresip/Message.kt b/app/src/main/kotlin/com/tutpro/baresip/Message.kt index 3128ba23..67844fb2 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Message.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Message.kt @@ -2,6 +2,6 @@ package com.tutpro.baresip import java.io.Serializable -class Message(val aor: String, val peerURI: String, var direction: Int, val message: String, +class Message(val aor: String, val peerUri: String, var direction: Int, val message: String, val timeStamp: Long, var new: Boolean): Serializable { } diff --git a/app/src/main/kotlin/com/tutpro/baresip/MessageActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/MessageActivity.kt deleted file mode 100644 index 28123be8..00000000 --- a/app/src/main/kotlin/com/tutpro/baresip/MessageActivity.kt +++ /dev/null @@ -1,116 +0,0 @@ -package com.tutpro.baresip - -import android.app.Activity -import android.content.Context -import android.content.Intent -import android.os.Bundle -import android.support.v7.app.AppCompatActivity -import android.util.Log -import android.view.MenuItem -import android.view.inputmethod.InputMethodManager -import android.widget.* - -class MessageActivity : AppCompatActivity() { - - internal lateinit var receiver: AutoCompleteTextView - internal lateinit var message: EditText - internal lateinit var sendButton: ImageButton - internal lateinit var callButton: ImageButton - internal lateinit var imm: InputMethodManager - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - setContentView(R.layout.activity_message) - - val aor = intent.extras.getString("aor") - val peerURI = intent.extras.getString("peer") - Log.d("Baresip", "peerURI is $peerURI") - - val ua = Account.findUa(aor) - if (ua == null) { - Log.e("Baresip", "MessageActivity did not find ua of $aor") - val i = Intent() - setResult(Activity.RESULT_CANCELED, i) - finish() - } - - val title = findViewById(R.id.messageToTitle) as TextView - message = findViewById(R.id.text) as EditText - receiver = findViewById(R.id.receiver) as AutoCompleteTextView - - imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager - title.text = "Message or call to ..." - if (peerURI == "") { - receiver.threshold = 2 - receiver.setAdapter(ArrayAdapter(this, android.R.layout.select_dialog_item, - ContactsActivity.contacts.map { Contact -> Contact.name })) - receiver.requestFocus() - } else { - receiver.setText(ContactsActivity.contactName(peerURI), false) - message.requestFocus() - } - - sendButton = findViewById(R.id.sendButton) as ImageButton - sendButton.setOnClickListener { - val receiverText = receiver.text.toString() - val msg = message.text.toString() - if (receiverText.length > 0) { - var uri = ContactsActivity.findContactURI(receiverText) - if (!uri.startsWith("sip:")) uri = "sip:$uri" - if (!uri.contains("@")) { - val host = aor.substring(aor.indexOf("@") + 1) - uri = "$uri@$host" - } - if (msg.length > 0) { - imm.hideSoftInputFromWindow(receiver.getWindowToken(), 0) - imm.hideSoftInputFromWindow(message.getWindowToken(), 0) - val time = System.currentTimeMillis() - val res = message_send(ua!!.uap, uri, msg, time.toString()) - if (res != 0) { - Toast.makeText(getApplicationContext(), "Sending of message failed!", - Toast.LENGTH_SHORT).show() - } else { - val new_message = Message(aor, uri, R.drawable.arrow_up_yellow, msg, time, - false) - MessagesActivity.addMessage(new_message) - MessagesActivity.uaMessages.add(0, new_message) - val i = Intent() - setResult(Activity.RESULT_OK, i) - finish() - } - } - } - } - - callButton = findViewById(R.id.callButton) as ImageButton - callButton.setOnClickListener { - imm.hideSoftInputFromWindow(receiver.getWindowToken(), 0) - imm.hideSoftInputFromWindow(message.getWindowToken(), 0) - val callIntent = Intent(this, MainActivity::class.java) - callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or - Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP) - callIntent.putExtra("action", "call") - callIntent.putExtra("uap", ua!!.uap) - callIntent.putExtra("peer", ContactsActivity.contactName(peerURI)) - startActivity(callIntent) - } - - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - when (item.itemId) { - android.R.id.home -> { - imm.hideSoftInputFromWindow(receiver.getWindowToken(), 0) - imm.hideSoftInputFromWindow(message.getWindowToken(), 0) - val i = Intent() - setResult(Activity.RESULT_CANCELED, i) - finish() - } - } - return true - } - - external fun message_send(uap: String, peer_uri: String, message: String, time: String) : Int - -} diff --git a/app/src/main/kotlin/com/tutpro/baresip/MessageListAdapter.kt b/app/src/main/kotlin/com/tutpro/baresip/MessageListAdapter.kt index b82eee9c..ec94d508 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/MessageListAdapter.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/MessageListAdapter.kt @@ -22,13 +22,6 @@ class MessageListAdapter(private val cxt: Context, private val rows: ArrayList @@ -97,7 +97,7 @@ android:layout_height="wrap_content" android:hint="SIP URI of another Proxy Server" android:textSize="18sp" - android:inputType="textUri" + android:inputType="textEmailAddress" android:layout_width="fill_parent"> diff --git a/app/src/main/res/layout/activity_accounts.xml b/app/src/main/res/layout/activity_accounts.xml index ae3af852..4194aa86 100644 --- a/app/src/main/res/layout/activity_accounts.xml +++ b/app/src/main/res/layout/activity_accounts.xml @@ -27,6 +27,7 @@ android:textSize="20sp" android:layout_alignParentStart="true" android:layout_marginStart="0dp" + android:layout_toLeftOf="@+id/addAccount" android:inputType="textEmailAddress" android:hint="SIP URI user@domain" > diff --git a/app/src/main/res/layout/activity_chat.xml b/app/src/main/res/layout/activity_chat.xml new file mode 100644 index 00000000..754aa7a7 --- /dev/null +++ b/app/src/main/res/layout/activity_chat.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_messages.xml b/app/src/main/res/layout/activity_chats.xml similarity index 57% rename from app/src/main/res/layout/activity_messages.xml rename to app/src/main/res/layout/activity_chats.xml index 51aec5bb..3daf6591 100644 --- a/app/src/main/res/layout/activity_messages.xml +++ b/app/src/main/res/layout/activity_chats.xml @@ -7,12 +7,27 @@ android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" - tools:context=".MessagesActivity"> + tools:context=".ChatsActivity" > + android:layout_height="fill_parent" > + + + + - - diff --git a/app/src/main/res/layout/activity_message.xml b/app/src/main/res/layout/activity_message.xml deleted file mode 100644 index 57478e2a..00000000 --- a/app/src/main/res/layout/activity_message.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/menu/call_icon.xml b/app/src/main/res/menu/call_icon.xml new file mode 100644 index 00000000..3eb7ade4 --- /dev/null +++ b/app/src/main/res/menu/call_icon.xml @@ -0,0 +1,12 @@ + + + + + +