mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-17 11:28:06 +00:00
Added countdowns in chat bubbles for ephemeral messages
This commit is contained in:
parent
6ecc0839ea
commit
01d721d477
6 changed files with 125 additions and 0 deletions
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
package org.linphone.ui.main.chat.model
|
||||
|
||||
import android.os.CountDownTimer
|
||||
import android.text.Spannable
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.Spanned
|
||||
|
|
@ -108,6 +109,10 @@ class MessageModel @WorkerThread constructor(
|
|||
|
||||
val statusIcon = MutableLiveData<Int>()
|
||||
|
||||
val isEphemeral = MutableLiveData<Boolean>()
|
||||
|
||||
val ephemeralLifetime = MutableLiveData<String>()
|
||||
|
||||
val text = MutableLiveData<Spannable>()
|
||||
|
||||
val reactions = MutableLiveData<String>()
|
||||
|
|
@ -169,6 +174,8 @@ class MessageModel @WorkerThread constructor(
|
|||
}
|
||||
// End of voice record related fields
|
||||
|
||||
private lateinit var countDownTimer: CountDownTimer
|
||||
|
||||
private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
|
||||
|
||||
private var transferringFileModel: FileModel? = null
|
||||
|
|
@ -234,12 +241,20 @@ class MessageModel @WorkerThread constructor(
|
|||
}
|
||||
model?.transferProgress?.postValue(percent)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun onEphemeralMessageTimerStarted(message: ChatMessage) {
|
||||
Log.d("$TAG Ephemeral timer started")
|
||||
updateEphemeralTimer()
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
groupedWithNextMessage.postValue(isGroupedWithNextOne)
|
||||
groupedWithPreviousMessage.postValue(isGroupedWithPreviousOne)
|
||||
isPlayingVoiceRecord.postValue(false)
|
||||
isEphemeral.postValue(chatMessage.isEphemeral)
|
||||
updateEphemeralTimer()
|
||||
|
||||
chatMessage.addListener(chatMessageListener)
|
||||
statusIcon.postValue(LinphoneUtils.getChatIconResId(chatMessage.state))
|
||||
|
|
@ -813,4 +828,33 @@ class MessageModel @WorkerThread constructor(
|
|||
|
||||
return ""
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun updateEphemeralTimer() {
|
||||
if (chatMessage.isEphemeral) {
|
||||
if (chatMessage.ephemeralExpireTime == 0L) {
|
||||
// This means the message hasn't been read by all participants yet, so the countdown hasn't started
|
||||
// In this case we simply display the configured value for lifetime
|
||||
ephemeralLifetime.postValue(
|
||||
TimestampUtils.formatLifetime(chatMessage.ephemeralLifetime)
|
||||
)
|
||||
} else {
|
||||
// Countdown has started, display remaining time
|
||||
val remaining = chatMessage.ephemeralExpireTime - (System.currentTimeMillis() / 1000)
|
||||
ephemeralLifetime.postValue(TimestampUtils.formatLifetime(remaining))
|
||||
if (!::countDownTimer.isInitialized) {
|
||||
countDownTimer = object : CountDownTimer(remaining * 1000, 1000) {
|
||||
override fun onFinish() {}
|
||||
|
||||
override fun onTick(millisUntilFinished: Long) {
|
||||
ephemeralLifetime.postValue(
|
||||
TimestampUtils.formatLifetime(millisUntilFinished / 1000)
|
||||
)
|
||||
}
|
||||
}
|
||||
countDownTimer.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import java.util.Calendar
|
|||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.R
|
||||
|
||||
class TimestampUtils {
|
||||
companion object {
|
||||
|
|
@ -217,6 +218,32 @@ class TimestampUtils {
|
|||
.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
fun formatLifetime(seconds: Long): String {
|
||||
val days = seconds / 86400
|
||||
val hours = seconds / 3600
|
||||
return when {
|
||||
days >= 1L -> AppUtils.getStringWithPlural(
|
||||
R.plurals.days,
|
||||
days.toInt(),
|
||||
"$days"
|
||||
)
|
||||
hours >= 1L -> {
|
||||
String.format(
|
||||
"%02d:%02d:%02d",
|
||||
seconds / 3600,
|
||||
(seconds % 3600) / 60,
|
||||
(seconds % 60)
|
||||
)
|
||||
}
|
||||
else -> String.format(
|
||||
"%02d:%02d",
|
||||
(seconds % 3600) / 60,
|
||||
(seconds % 60)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
private fun isSameDay(
|
||||
cal1: Calendar,
|
||||
|
|
|
|||
|
|
@ -247,6 +247,29 @@
|
|||
android:visibility="@{model.isFromGroup ? View.VISIBLE : View.GONE}"
|
||||
app:tint="?attr/color_main1_500" />
|
||||
|
||||
<ImageView
|
||||
style="@style/default_text_style_300"
|
||||
android:id="@+id/countdown_clock"
|
||||
android:layout_width="@dimen/small_icon_size"
|
||||
android:layout_height="@dimen/small_icon_size"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_marginTop="2dp"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/clock_countdown"
|
||||
app:tint="?attr/color_main2_600"
|
||||
android:visibility="@{model.isEphemeral ? View.VISIBLE : View.GONE, default=gone}" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/default_text_style_300"
|
||||
android:id="@+id/ephemeral_timer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="2dp"
|
||||
android:textAlignment="textEnd"
|
||||
android:text="@{model.ephemeralLifetime, default=`00:00`}"
|
||||
android:textSize="12sp"
|
||||
android:visibility="@{model.isEphemeral ? View.VISIBLE : View.GONE, default=gone}"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
|||
|
|
@ -198,6 +198,28 @@
|
|||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/default_text_style_300"
|
||||
android:id="@+id/ephemeral_timer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{model.ephemeralLifetime, default=`00:00`}"
|
||||
android:textSize="12sp"
|
||||
android:visibility="@{model.isEphemeral ? View.VISIBLE : View.GONE, default=gone}"/>
|
||||
|
||||
<ImageView
|
||||
style="@style/default_text_style_300"
|
||||
android:id="@+id/countdown_clock"
|
||||
android:layout_width="@dimen/small_icon_size"
|
||||
android:layout_height="@dimen/small_icon_size"
|
||||
android:layout_gravity="center_vertical|start"
|
||||
android:layout_marginStart="2dp"
|
||||
android:layout_marginTop="2dp"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/clock_countdown"
|
||||
app:tint="?attr/color_main2_600"
|
||||
android:visibility="@{model.isEphemeral ? View.VISIBLE : View.GONE, default=gone}" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/default_text_style_300"
|
||||
android:id="@+id/date_time"
|
||||
|
|
@ -205,6 +227,7 @@
|
|||
android:onLongClick="@{onLongClickListener}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5dp"
|
||||
android:text="@{model.time, default=`13:40`}"
|
||||
android:textSize="12sp" />
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,10 @@
|
|||
<string name="start">Commencer</string>
|
||||
<string name="today">Aujourd\'hui</string>
|
||||
<string name="yesterday">Hier</string>
|
||||
<plurals name="days" tools:ignore="MissingQuantity">
|
||||
<item quantity="one">%s jour</item>
|
||||
<item quantity="other">%s jours</item>
|
||||
</plurals>
|
||||
|
||||
<plurals name="selection_count_label" tools:ignore="MissingQuantity">
|
||||
<item quantity="one">%s selectionné</item>
|
||||
|
|
|
|||
|
|
@ -53,6 +53,10 @@
|
|||
<string name="start">Start</string>
|
||||
<string name="today">Today</string>
|
||||
<string name="yesterday">Yesterday</string>
|
||||
<plurals name="days">
|
||||
<item quantity="one">%s day</item>
|
||||
<item quantity="other">%s days</item>
|
||||
</plurals>
|
||||
|
||||
<plurals name="selection_count_label">
|
||||
<item quantity="one">%s selected</item>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue