diff --git a/app/build.gradle b/app/build.gradle
index dd69ffecc8..19357e704a 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -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'
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
index 92aaa44543..989be7880b 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
@@ -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 world" and returns a SpannableString that will display the appropriate
- // elements in bold. If there are no such or 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("", startIndex)
- if (startIndex == -1) break
- val endIndex = input.indexOf("", 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
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/TextUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/TextUtilities.kt
index 7a47b92756..23d81e2513 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/TextUtilities.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/TextUtilities.kt
@@ -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
diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/SaveAttachmentTask.kt b/app/src/main/java/org/thoughtcrime/securesms/util/SaveAttachmentTask.kt
index 89d61e5c22..bd39f5f079 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/util/SaveAttachmentTask.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/util/SaveAttachmentTask.kt
@@ -78,7 +78,7 @@ class SaveAttachmentTask @JvmOverloads constructor(context: Context, count: Int
// for unknown reasons it provides us with an empty filename when saving files.
// TODO: Further investigation into root cause and fix!
if (fileName.isNullOrEmpty()) fileName = generateOutputFileName(contentType, attachment.date)
-
+
fileName = sanitizeOutputFileName(fileName)
val outputUri: Uri = getMediaStoreContentUriForType(contentType)
val mediaUri = createOutputUri(context, outputUri, contentType, fileName)
diff --git a/libsession/src/main/java/org/session/libsession/messaging/utilities/UpdateMessageBuilder.kt b/libsession/src/main/java/org/session/libsession/messaging/utilities/UpdateMessageBuilder.kt
index 85d502f1b5..f20ba1ec16 100644
--- a/libsession/src/main/java/org/session/libsession/messaging/utilities/UpdateMessageBuilder.kt
+++ b/libsession/src/main/java/org/session/libsession/messaging/utilities/UpdateMessageBuilder.kt
@@ -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()
}
}
}
@@ -98,15 +105,13 @@ object UpdateMessageBuilder {
// 1st case: you are part of the removed members
return if (userPublicKey in updateData.updatedMembers) {
- if (isOutgoing) context.getString(R.string.groupMemberYouLeft) // You chose to leave
- else Phrase.from(context, R.string.groupRemovedYou) // You were forced to leave
+ 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()
}
}
}
diff --git a/libsession/src/main/java/org/session/libsession/utilities/Util.kt b/libsession/src/main/java/org/session/libsession/utilities/Util.kt
index ae42d51068..9110066a45 100644
--- a/libsession/src/main/java/org/session/libsession/utilities/Util.kt
+++ b/libsession/src/main/java/org/session/libsession/utilities/Util.kt
@@ -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 world" and returns a SpannableString that will display the appropriate
+ // elements in bold. If there are no such or 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("", startIndex)
+ if (startIndex == -1) break
+ val endIndex = input.indexOf("", 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.runIf(condition: Boolean, block: T.() -> R): R where T: R = if (condition) block() else this