mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-21 15:05:19 +00:00
Moved into libsession for ease of access to control message view creation
This commit is contained in:
parent
b908a54a44
commit
3c576053a3
@ -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'
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user