diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5ed1462e..aa95a673 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -109,6 +109,12 @@
android:label="@string/call_history"
android:parentActivityName=".MainActivity" >
+
+
{
+ onBackPressed()
+ return true
+ }
+ }
+
+ return super.onOptionsItemSelected(item)
+ }
+
+ override fun onBackPressed() {
+ BaresipService.activities.remove("call_details,$aor,$peer,$position")
+ finish()
+ super.onBackPressed()
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/kotlin/com/tutpro/baresip/CallDetailsAdapter.kt b/app/src/main/kotlin/com/tutpro/baresip/CallDetailsAdapter.kt
new file mode 100644
index 00000000..37908f10
--- /dev/null
+++ b/app/src/main/kotlin/com/tutpro/baresip/CallDetailsAdapter.kt
@@ -0,0 +1,77 @@
+package com.tutpro.baresip
+
+import android.content.Context
+import android.text.format.DateUtils
+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.DateFormat
+
+import java.util.*
+
+class CallDetailsAdapter(private val ctx: Context, private val rows: ArrayList) :
+ ArrayAdapter(ctx, R.layout.call_detail_row, rows) {
+
+ private val layoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
+
+ private class ViewHolder(view: View?) {
+ val directionView = view?.findViewById(R.id.direction) as ImageView
+ val timeView = view?.findViewById(R.id.time) as TextView
+ val durationView = view?.findViewById(R.id.duration) as TextView
+ }
+
+ override fun getView(position: Int, view: View?, parent: ViewGroup): View {
+
+ val viewHolder: ViewHolder
+ val rowView: View
+
+ if (view == null) {
+ rowView = layoutInflater.inflate(R.layout.call_detail_row, parent, false)
+ viewHolder = ViewHolder(rowView)
+ rowView.tag = viewHolder
+ } else {
+ rowView = view
+ viewHolder = rowView.tag as ViewHolder
+ }
+
+ val direction = rows[position].direction
+ viewHolder.directionView.setImageResource(direction)
+
+ val startTime = rows[position].startTime
+ val stopTime = rows[position].stopTime
+
+ val stopText = if (DateUtils.isToday(stopTime.timeInMillis)) {
+ val fmt = DateFormat.getTimeInstance(DateFormat.LONG)
+ ctx.getString(R.string.today) + " " + fmt.format(stopTime.time)
+ } else {
+ val fmt = DateFormat.getDateTimeInstance()
+ fmt.format(stopTime.time)
+ }
+ if (startTime == GregorianCalendar(0, 0, 0)) {
+ viewHolder.timeView.text = stopText
+ viewHolder.durationView.text = "?"
+ } else {
+ if (startTime == null) {
+ viewHolder.timeView.text = stopText
+ viewHolder.durationView.text = ""
+ } else {
+ val startText = if (DateUtils.isToday(startTime.timeInMillis)) {
+ val fmt = DateFormat.getTimeInstance(DateFormat.LONG)
+ ctx.getString(R.string.today) + " " + fmt.format(startTime.time)
+ } else {
+ val fmt = DateFormat.getDateTimeInstance()
+ fmt.format(startTime.time)
+ }
+ viewHolder.timeView.text = startText
+ val duration = (stopTime.time.time - startTime.time.time) / 1000
+ viewHolder.durationView.text = DateUtils.formatElapsedTime(duration)
+ }
+ }
+
+ return rowView
+ }
+
+}
diff --git a/app/src/main/kotlin/com/tutpro/baresip/CallListAdapter.kt b/app/src/main/kotlin/com/tutpro/baresip/CallListAdapter.kt
index ba0d5d4e..ead9b732 100644
--- a/app/src/main/kotlin/com/tutpro/baresip/CallListAdapter.kt
+++ b/app/src/main/kotlin/com/tutpro/baresip/CallListAdapter.kt
@@ -1,6 +1,8 @@
package com.tutpro.baresip
import android.content.Context
+import android.content.Intent
+import android.os.Bundle
import androidx.cardview.widget.CardView
import android.view.LayoutInflater
import android.view.View
@@ -12,15 +14,15 @@ import android.widget.TextView
import java.util.*
-class CallListAdapter(private val cxt: Context, private val rows: ArrayList) :
- ArrayAdapter(cxt, R.layout.call_row, rows) {
+class CallListAdapter(private val ctx: Context, private val aor: String, private val rows: ArrayList) :
+ ArrayAdapter(ctx, R.layout.call_row, rows) {
- private val layoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
+ private val layoutInflater = LayoutInflater.from(context)
private class ViewHolder(view: View?) {
val textAvatarView = view?.findViewById(R.id.TextAvatar) as TextView
val cardAvatarView = view?.findViewById(R.id.CardAvatar) as CardView
- val cardImageAvatarView = view?.findViewById(R.id.CardImageAvatar) as ImageView
+ val imageAvatarView = view?.findViewById(R.id.ImageAvatar) as ImageView
val directionsView = view?.findViewById(R.id.directions) as LinearLayout
val etcView = view?.findViewById(R.id.etc) as TextView
val peerURIView = view?.findViewById(R.id.peer_uri) as TextView
@@ -42,18 +44,22 @@ class CallListAdapter(private val cxt: Context, private val rows: ArrayList 3) {
viewHolder.etcView.text = "..."
break
}
- val dirView = ImageView(cxt)
+ val dirView = ImageView(ctx)
val params = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT)
dirView.layoutParams = params
dirView.setPadding(0, 5, 0, 0)
- dirView.setImageResource(d)
+ dirView.setImageResource(d.direction)
viewHolder.directionsView.addView(dirView)
count++
}
@@ -84,7 +90,17 @@ class CallListAdapter(private val cxt: Context, private val rows: ArrayList()
- val indexes = ArrayList()
+class CallRow(val aor: String, val peerUri: String, val direction: Int,
+ startTime: GregorianCalendar?, val stopTime: GregorianCalendar) {
+
+ class Details(val direction: Int, val startTime: GregorianCalendar?, val stopTime: GregorianCalendar)
+
+ val details = ArrayList()
init {
- directions.add(direction)
- indexes.add(index)
+ details.add(Details(direction, startTime, stopTime))
}
}
diff --git a/app/src/main/kotlin/com/tutpro/baresip/CallsActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/CallsActivity.kt
index ef9af8a5..1216c559 100644
--- a/app/src/main/kotlin/com/tutpro/baresip/CallsActivity.kt
+++ b/app/src/main/kotlin/com/tutpro/baresip/CallsActivity.kt
@@ -7,7 +7,6 @@ import android.os.Bundle
import android.os.SystemClock
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
-import android.text.format.DateUtils.isToday
import android.view.Menu
import android.view.MenuItem
import android.view.View
@@ -16,7 +15,6 @@ import android.widget.TextView
import androidx.activity.result.contract.ActivityResultContracts
import com.tutpro.baresip.databinding.ActivityCallsBinding
-import java.text.DateFormat
import java.util.*
class CallsActivity : AppCompatActivity() {
@@ -46,7 +44,7 @@ class CallsActivity : AppCompatActivity() {
val listView = binding.calls
aorGenerateHistory(aor)
- clAdapter = CallListAdapter(this, uaHistory)
+ clAdapter = CallListAdapter(this, aor, uaHistory)
listView.adapter = clAdapter
listView.isLongClickable = true
@@ -117,7 +115,7 @@ class CallsActivity : AppCompatActivity() {
}
}
}
- val callText: String = if (uaHistory[pos].directions.size > 1)
+ val callText: String = if (uaHistory[pos].details.size > 1)
getString(R.string.calls_calls)
else
getString(R.string.calls_call)
@@ -236,33 +234,19 @@ class CallsActivity : AppCompatActivity() {
R.drawable.arrow_up_green
else
R.drawable.arrow_up_red
- if (uaHistory.isNotEmpty() && (uaHistory.last().peerUri == h.peerUri)) {
- uaHistory.last().directions.add(direction)
- uaHistory.last().indexes.add(i)
- } else {
- val time = if (isToday(h.stopTime.timeInMillis)) {
- val fmt = DateFormat.getTimeInstance(DateFormat.SHORT)
- getString(R.string.today) + "\n" + fmt.format(h.stopTime.time)
- } else {
- val month = h.stopTime.getDisplayName(Calendar.MONTH, Calendar.SHORT, Locale.getDefault())
- val day = h.stopTime.get(Calendar.DAY_OF_MONTH)
- val currentYear = Calendar.getInstance().get(Calendar.YEAR)
- if (h.stopTime.get(Calendar.YEAR) == currentYear) {
- val fmt = DateFormat.getTimeInstance(DateFormat.SHORT)
- "$month $day" + "\n" + fmt.format(h.stopTime.time)
- } else {
- "$month $day" + "\n" + h.stopTime.get(Calendar.YEAR)
- }
- }
- uaHistory.add(CallRow(h.aor, h.peerUri, direction, time, i))
- }
+ if (uaHistory.isNotEmpty() && (uaHistory.last().peerUri == h.peerUri))
+ uaHistory.last().details.add(CallRow.Details(direction, h.startTime, h.stopTime))
+ else
+ uaHistory.add(CallRow(h.aor, h.peerUri, direction, h.startTime, h.stopTime))
}
}
}
private fun removeUaHistoryAt(i: Int) {
- for (index in uaHistory[i].indexes)
- BaresipService.callHistory.removeAt(index)
+ for (details in uaHistory[i].details)
+ BaresipService.callHistory.removeAll {
+ it.startTime == details.startTime && it.stopTime == details.stopTime
+ }
uaHistory.removeAt(i)
}
diff --git a/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt
index 1c334aeb..abf03fe2 100644
--- a/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt
+++ b/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt
@@ -88,6 +88,7 @@ class MainActivity : AppCompatActivity() {
private lateinit var restoreRequest: ActivityResultLauncher
private lateinit var contactsRequest: ActivityResultLauncher
private lateinit var callsRequest: ActivityResultLauncher
+ private lateinit var callDetailsRequest: ActivityResultLauncher
private var downloadsInputStream: FileInputStream? = null
private var downloadsOutputStream: FileOutputStream? = null
@@ -1920,6 +1921,15 @@ class MainActivity : AppCompatActivity() {
i.putExtras(b)
callsRequest.launch(i)
}
+ "call_details" -> {
+ val i = Intent(this, CallDetailsActivity::class.java)
+ val b = Bundle()
+ b.putString("aor", activity[1])
+ b.putString("peer", activity[2])
+ b.putInt("position", activity[3].toInt())
+ i.putExtras(b)
+ callsRequest.launch(i)
+ }
}
return
}
diff --git a/app/src/main/kotlin/com/tutpro/baresip/Utils.kt b/app/src/main/kotlin/com/tutpro/baresip/Utils.kt
index 1a657b8c..01d99401 100644
--- a/app/src/main/kotlin/com/tutpro/baresip/Utils.kt
+++ b/app/src/main/kotlin/com/tutpro/baresip/Utils.kt
@@ -18,13 +18,13 @@ import android.provider.MediaStore
import android.provider.OpenableColumns
import android.text.Editable
import android.text.TextWatcher
+import android.text.format.DateUtils
import android.view.View
import android.view.WindowManager
import android.widget.TextView
import androidx.activity.result.ActivityResultLauncher
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AlertDialog
-import androidx.appcompat.app.AppCompatDelegate
import androidx.core.content.ContextCompat
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.ProcessLifecycleOwner
@@ -39,6 +39,7 @@ import java.util.zip.ZipOutputStream
import java.net.InetAddress
import java.net.NetworkInterface
import java.net.SocketException
+import java.text.DateFormat
import javax.crypto.Cipher
import javax.crypto.SecretKeyFactory
import javax.crypto.spec.IvParameterSpec
@@ -694,4 +695,20 @@ object Utils {
}
}
+ fun relativeTime(ctx: Context, time: GregorianCalendar): String {
+ return if (DateUtils.isToday(time.timeInMillis)) {
+ val fmt = DateFormat.getTimeInstance(DateFormat.SHORT)
+ ctx.getString(R.string.today) + "\n" + fmt.format(time.time)
+ } else {
+ val month = time.getDisplayName(Calendar.MONTH, Calendar.SHORT, Locale.getDefault())
+ val day = time.get(Calendar.DAY_OF_MONTH)
+ val currentYear = Calendar.getInstance().get(Calendar.YEAR)
+ if (time.get(Calendar.YEAR) == currentYear) {
+ val fmt = DateFormat.getTimeInstance(DateFormat.SHORT)
+ "$month $day" + "\n" + fmt.format(time.time)
+ } else {
+ "$month $day" + "\n" + time.get(Calendar.YEAR)
+ }
+ }
+ }
}
diff --git a/app/src/main/res/layout/activity_call_details.xml b/app/src/main/res/layout/activity_call_details.xml
new file mode 100644
index 00000000..ec0f78a8
--- /dev/null
+++ b/app/src/main/res/layout/activity_call_details.xml
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_calls.xml b/app/src/main/res/layout/activity_calls.xml
index a9324f85..a26291c5 100644
--- a/app/src/main/res/layout/activity_calls.xml
+++ b/app/src/main/res/layout/activity_calls.xml
@@ -14,6 +14,7 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
+ android:textSize="16sp"
android:gravity="center_horizontal" >
diff --git a/app/src/main/res/layout/call_detail_row.xml b/app/src/main/res/layout/call_detail_row.xml
new file mode 100644
index 00000000..9233ac38
--- /dev/null
+++ b/app/src/main/res/layout/call_detail_row.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/call_row.xml b/app/src/main/res/layout/call_row.xml
index 7d57db56..afb2dab8 100644
--- a/app/src/main/res/layout/call_row.xml
+++ b/app/src/main/res/layout/call_row.xml
@@ -1,13 +1,9 @@
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
Soita
puhelut
puhelun
+ Suunta
+ Pääri
+ Aika
+ Kesto
Haluatko soittaa tai lähettää viestin kohteeseen
\'%1$s\'?
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 90a3da51..b69de576 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -215,9 +215,14 @@
Tap to start application
Call History
+ Call Details
Call
calls
call
+ Peer
+ Direction
+ Time
+ Duration
Do you want to call or send message to \'%1$s\'?
Do you want to add \'%1$s\' to contacts or delete
%2$s from call history?