Moved into libsession for ease of access to control message view creation

This commit is contained in:
alansley 2024-08-26 17:11:45 +10:00
parent b908a54a44
commit 3c576053a3
6 changed files with 56 additions and 46 deletions

View File

@ -227,7 +227,6 @@ dependencies {
ksp("com.google.dagger:hilt-compiler:$daggerHiltVersion")
ksp("com.github.bumptech.glide:ksp:$glideVersion")
implementation 'androidx.compose.material3:material3-android:1.2.1'
implementation("com.google.dagger:hilt-android:$daggerHiltVersion")
implementation "androidx.appcompat:appcompat:$appcompatVersion"
implementation 'androidx.recyclerview:recyclerview:1.2.1'

View File

@ -1072,24 +1072,6 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
updateUnreadCountIndicator()
}
// Method that takes a char sequence that contains one or more elements surrounded in bold tags
// like "Hello <b>world</b>" and returns a SpannableString that will display the appropriate
// elements in bold. If there are no such <b> or </b> elements then the original string is returned
// as a SpannableString without any bold highlighting.
private fun makeBoldBetweenTags(input: CharSequence): SpannableString {
val spannable = SpannableString(input)
var startIndex = 0
while (true) {
startIndex = input.indexOf("<b>", startIndex)
if (startIndex == -1) break
val endIndex = input.indexOf("</b>", startIndex + 3)
if (endIndex == -1) break
spannable.setSpan(StyleSpan(Typeface.BOLD),startIndex + 3, endIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
startIndex = endIndex + 4
}
return spannable
}
// Update placeholder / control messages in a conversation
private fun updatePlaceholder() {
val recipient = viewModel.recipient ?: return Log.w("Loki", "recipient was null in placeholder update")
@ -1134,7 +1116,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
binding.placeholderText.isVisible = showPlaceholder
if (showPlaceholder) {
if (!isNoteToSelf) {
binding.placeholderText.text = makeBoldBetweenTags(txtCS)
binding.placeholderText.text = org.session.libsession.utilities.Util.makeBoldBetweenTags(txtCS)
} else {
binding.placeholderText.text = txtCS
}

View File

@ -1,9 +1,13 @@
package org.thoughtcrime.securesms.conversation.v2.utilities
import android.graphics.Rect
import android.graphics.Typeface
import android.text.Layout
import android.text.SpannableString
import android.text.Spanned
import android.text.StaticLayout
import android.text.TextPaint
import android.text.style.StyleSpan
import android.view.MotionEvent
import android.widget.TextView
import androidx.core.text.getSpans

View File

@ -1,6 +1,7 @@
package org.session.libsession.messaging.utilities
import android.content.Context
import android.text.SpannableString
import com.squareup.phrase.Phrase
import org.session.libsession.R
import org.session.libsession.messaging.MessagingModuleConfiguration
@ -23,6 +24,7 @@ import org.session.libsession.utilities.StringSubstitutionConstants.GROUP_NAME_K
import org.session.libsession.utilities.StringSubstitutionConstants.NAME_KEY
import org.session.libsession.utilities.StringSubstitutionConstants.OTHER_NAME_KEY
import org.session.libsession.utilities.StringSubstitutionConstants.TIME_KEY
import org.session.libsession.utilities.Util
object UpdateMessageBuilder {
const val TAG = "libsession"
@ -33,29 +35,34 @@ object UpdateMessageBuilder {
?.displayName(Contact.ContactContext.REGULAR)
?: truncateIdForDisplay(senderId)
fun buildGroupUpdateMessage(context: Context, updateMessageData: UpdateMessageData, senderId: String? = null, isOutgoing: Boolean = false): String {
//@RequiresApi(Build.VERSION_CODES.P)
fun buildGroupUpdateMessage(context: Context, updateMessageData: UpdateMessageData, senderId: String? = null, isOutgoing: Boolean = false): CharSequence {
val updateData = updateMessageData.kind
if (updateData == null || !isOutgoing && senderId == null) return ""
val senderName: String = if (isOutgoing) context.getString(R.string.you) else getSenderName(senderId!!)
return when (updateData) {
// --- Group created or joined ---
is UpdateMessageData.Kind.GroupCreation -> {
if (!isOutgoing) context.getString(R.string.groupInviteYou)
else "" // We no longer add a string like `disappearingMessagesNewGroup` ("You created a new group") and leave the group with its default empty state
if (!isOutgoing) {
Util.makeBoldBetweenTags(SpannableString(context.getString(R.string.groupInviteYou)))
} else {
"" // We no longer add a string like `disappearingMessagesNewGroup` ("You created a new group") and leave the group with its default empty state
}
}
// --- Group name changed ---
is UpdateMessageData.Kind.GroupNameChange -> {
if (isOutgoing) {
Phrase.from(context, R.string.groupNameNew)
val cs = Phrase.from(context, R.string.groupNameNew)
.put(GROUP_NAME_KEY, updateData.name)
.format().toString()
.format()
Util.makeBoldBetweenTags(cs)
}
else {
Phrase.from(context, R.string.groupNameNew)
val cs = Phrase.from(context, R.string.groupNameNew)
.put(GROUP_NAME_KEY, updateData.name)
.format().toString()
.format()
Util.makeBoldBetweenTags(cs)
}
}
@ -74,20 +81,20 @@ object UpdateMessageBuilder {
1 -> {
Phrase.from(context, R.string.groupMemberNew)
.put(NAME_KEY, updateData.updatedMembers.elementAtOrNull(0))
.format().toString()
.format()
}
2 -> {
Phrase.from(context, R.string.groupMemberTwoNew)
.put(NAME_KEY, updateData.updatedMembers.elementAtOrNull(0))
.put(OTHER_NAME_KEY, updateData.updatedMembers.elementAtOrNull(1))
.format().toString()
.format()
}
else -> {
val newMemberCountMinusOne = newMemberCount - 1
Phrase.from(context, R.string.groupMemberMoreNew)
.put(NAME_KEY, updateData.updatedMembers.elementAtOrNull(0))
.put(COUNT_KEY, newMemberCountMinusOne)
.format().toString()
.format()
}
}
}
@ -101,12 +108,10 @@ object UpdateMessageBuilder {
if (isOutgoing) context.getString(R.string.groupMemberYouLeft) // You chose to leave
else Phrase.from(context, R.string.groupRemovedYou) // You were forced to leave
.put(GROUP_NAME_KEY, updateData.groupName)
.format().toString()
.format()
}
else // 2nd case: you are not part of the removed members
{
val members = updateData.updatedMembers.joinToString(", ", transform = ::getSenderName)
// a.) You are the person doing the removing of one or more members
if (isOutgoing) {
when (updateData.updatedMembers.size) {
@ -116,15 +121,15 @@ object UpdateMessageBuilder {
}
1 -> Phrase.from(context, R.string.groupRemoved)
.put(NAME_KEY, getSenderName(updateData.updatedMembers.elementAt(0)))
.format().toString()
.format()
2 -> Phrase.from(context, R.string.groupRemovedTwo)
.put(NAME_KEY, getSenderName(updateData.updatedMembers.elementAt(0)))
.put(OTHER_NAME_KEY, getSenderName(updateData.updatedMembers.elementAt(1)))
.format().toString()
.format()
else -> Phrase.from(context, R.string.groupRemovedMore)
.put(NAME_KEY, getSenderName(updateData.updatedMembers.elementAt(0)))
.put(COUNT_KEY, updateData.updatedMembers.size - 1)
.format().toString()
.format()
}
}
else // b.) Someone else is the person doing the removing of one or more members
@ -140,15 +145,15 @@ object UpdateMessageBuilder {
}
1 -> Phrase.from(context, R.string.groupRemoved)
.put(NAME_KEY, getSenderName(updateData.updatedMembers.elementAt(0)))
.format().toString()
.format()
2 -> Phrase.from(context, R.string.groupRemovedTwo)
.put(NAME_KEY, getSenderName(updateData.updatedMembers.elementAt(0)))
.put(OTHER_NAME_KEY, getSenderName(updateData.updatedMembers.elementAt(1)))
.format().toString()
.format()
else -> Phrase.from(context, R.string.groupRemovedMore)
.put(NAME_KEY, getSenderName(updateData.updatedMembers.elementAt(0)))
.put(COUNT_KEY, updateData.updatedMembers.size - 1)
.format().toString()
.format()
}
}
}
@ -165,15 +170,15 @@ object UpdateMessageBuilder {
}
1 -> Phrase.from(context, R.string.groupMemberLeft)
.put(NAME_KEY, getSenderName(updateData.updatedMembers.elementAt(0)))
.format().toString()
.format()
2 -> Phrase.from(context, R.string.groupMemberLeftTwo)
.put(NAME_KEY, getSenderName(updateData.updatedMembers.elementAt(0)))
.put(OTHER_NAME_KEY, getSenderName(updateData.updatedMembers.elementAt(1)))
.format().toString()
.format()
else -> Phrase.from(context, R.string.groupMemberLeftMore)
.put(NAME_KEY, getSenderName(updateData.updatedMembers.elementAt(0)))
.put(COUNT_KEY, updateData.updatedMembers.size - 1)
.format().toString()
.format()
}
}
}

View File

@ -9,6 +9,7 @@ import android.os.Looper
import android.provider.Telephony
import android.text.Spannable
import android.text.SpannableString
import android.text.Spanned
import android.text.TextUtils
import android.text.style.StyleSpan
import org.session.libsignal.utilities.Log
@ -358,6 +359,25 @@ object Util {
val digitGroups = (Math.log10(sizeBytes.toDouble()) / Math.log10(1024.0)).toInt()
return DecimalFormat("#,##0.#").format(sizeBytes / Math.pow(1024.0, digitGroups.toDouble())) + " " + units[digitGroups]
}
// Method that takes a char sequence that contains one or more elements surrounded in bold tags
// like "Hello <b>world</b>" and returns a SpannableString that will display the appropriate
// elements in bold. If there are no such <b> or </b> elements then the original string is returned
// as a SpannableString without any bold highlighting.
@JvmStatic
fun makeBoldBetweenTags(input: CharSequence): SpannableString {
val spannable = SpannableString(input)
var startIndex = 0
while (true) {
startIndex = input.indexOf("<b>", startIndex)
if (startIndex == -1) break
val endIndex = input.indexOf("</b>", startIndex + 3)
if (endIndex == -1) break
spannable.setSpan(StyleSpan(Typeface.BOLD),startIndex + 3, endIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
startIndex = endIndex + 4
}
return spannable
}
}
fun <T, R> T.runIf(condition: Boolean, block: T.() -> R): R where T: R = if (condition) block() else this