mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-27 12:05:22 +00:00
refactor: use simpler way to generate closed group profile pictures, limit the getConversation call in MentionManagerUtilities.kt to 200 to improve link-through performance to v2 conversation activity. fix notify type not being preloaded into settings
This commit is contained in:
parent
dd01b2968f
commit
9b48d5d203
@ -142,7 +142,7 @@ dependencies {
|
|||||||
testImplementation 'org.robolectric:shadows-multidex:4.2'
|
testImplementation 'org.robolectric:shadows-multidex:4.2'
|
||||||
}
|
}
|
||||||
|
|
||||||
def canonicalVersionCode = 214
|
def canonicalVersionCode = 215
|
||||||
def canonicalVersionName = "1.11.7"
|
def canonicalVersionName = "1.11.7"
|
||||||
|
|
||||||
def postFixSize = 10
|
def postFixSize = 10
|
||||||
|
@ -53,17 +53,15 @@ class ProfilePictureView : RelativeLayout {
|
|||||||
return recipient.isOpenGroupRecipient && recipient.groupAvatarId != null
|
return recipient.isOpenGroupRecipient && recipient.groupAvatarId != null
|
||||||
}
|
}
|
||||||
if (recipient.isGroupRecipient && !isOpenGroupWithProfilePicture(recipient)) {
|
if (recipient.isGroupRecipient && !isOpenGroupWithProfilePicture(recipient)) {
|
||||||
val users = MentionsManager.userPublicKeyCache[threadID]?.toMutableList() ?: mutableListOf()
|
val members = DatabaseFactory.getGroupDatabase(context)
|
||||||
users.remove(TextSecurePreferences.getLocalNumber(context))
|
.getGroupMemberAddresses(recipient.address.toGroupString(), true)
|
||||||
val randomUsers = users.sorted().toMutableList() // Sort to provide a level of stability
|
.sorted()
|
||||||
if (users.count() == 1) {
|
.take(2)
|
||||||
val userPublicKey = TextSecurePreferences.getLocalNumber(context)!!
|
.toMutableList()
|
||||||
randomUsers.add(0, userPublicKey) // Ensure the current user is at the back visually
|
val pk = members.getOrNull(0)?.serialize() ?: ""
|
||||||
}
|
|
||||||
val pk = randomUsers.getOrNull(0) ?: ""
|
|
||||||
publicKey = pk
|
publicKey = pk
|
||||||
displayName = getUserDisplayName(pk)
|
displayName = getUserDisplayName(pk)
|
||||||
val apk = randomUsers.getOrNull(1) ?: ""
|
val apk = members.getOrNull(1)?.serialize() ?: ""
|
||||||
additionalPublicKey = apk
|
additionalPublicKey = apk
|
||||||
additionalDisplayName = getUserDisplayName(apk)
|
additionalDisplayName = getUserDisplayName(apk)
|
||||||
} else {
|
} else {
|
||||||
|
@ -13,13 +13,13 @@ object MentionManagerUtilities {
|
|||||||
if (MentionsManager.userPublicKeyCache[threadID] != null) return
|
if (MentionsManager.userPublicKeyCache[threadID] != null) return
|
||||||
|
|
||||||
val result = mutableSetOf<String>()
|
val result = mutableSetOf<String>()
|
||||||
val recipient = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadID)
|
val recipient = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadID) ?: return
|
||||||
if (recipient != null && recipient.address.isClosedGroup) {
|
if (recipient.address.isClosedGroup) {
|
||||||
val members = DatabaseFactory.getGroupDatabase(context).getGroupMembers(recipient.address.toGroupString(), false).map { it.address.serialize() }
|
val members = DatabaseFactory.getGroupDatabase(context).getGroupMembers(recipient.address.toGroupString(), false).map { it.address.serialize() }
|
||||||
result.addAll(members)
|
result.addAll(members)
|
||||||
} else {
|
} else {
|
||||||
val messageDatabase = DatabaseFactory.getMmsSmsDatabase(context)
|
val messageDatabase = DatabaseFactory.getMmsSmsDatabase(context)
|
||||||
val reader = messageDatabase.readerFor(messageDatabase.getConversation(threadID))
|
val reader = messageDatabase.readerFor(messageDatabase.getConversation(threadID, 0, 200))
|
||||||
var record: MessageRecord? = reader.next
|
var record: MessageRecord? = reader.next
|
||||||
while (record != null) {
|
while (record != null) {
|
||||||
result.add(record.individualRecipient.address.serialize())
|
result.add(record.individualRecipient.address.serialize())
|
||||||
|
@ -14,6 +14,7 @@ import com.annimon.stream.Stream;
|
|||||||
|
|
||||||
import net.sqlcipher.database.SQLiteDatabase;
|
import net.sqlcipher.database.SQLiteDatabase;
|
||||||
|
|
||||||
|
import org.session.libsession.utilities.TextSecurePreferences;
|
||||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
|
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
|
||||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||||
|
|
||||||
@ -155,6 +156,20 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt
|
|||||||
return recipients;
|
return recipients;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public @NonNull List<Address> getGroupMemberAddresses(String groupId, boolean includeSelf) {
|
||||||
|
List<Address> members = getCurrentMembers(groupId, false);
|
||||||
|
if (!includeSelf) {
|
||||||
|
String ownNumber = TextSecurePreferences.getLocalNumber(context);
|
||||||
|
if (ownNumber == null) return members;
|
||||||
|
Address ownAddress = Address.fromSerialized(ownNumber);
|
||||||
|
int indexOfSelf = members.indexOf(ownAddress);
|
||||||
|
if (indexOfSelf >= 0) {
|
||||||
|
members.remove(indexOfSelf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return members;
|
||||||
|
}
|
||||||
|
|
||||||
public @NonNull List<Recipient> getGroupZombieMembers(String groupId) {
|
public @NonNull List<Recipient> getGroupZombieMembers(String groupId) {
|
||||||
List<Address> members = getCurrentZombieMembers(groupId);
|
List<Address> members = getCurrentZombieMembers(groupId);
|
||||||
List<Recipient> recipients = new LinkedList<>();
|
List<Recipient> recipients = new LinkedList<>();
|
||||||
|
@ -651,7 +651,7 @@ public class ThreadDatabase extends Database {
|
|||||||
groupRecord = Optional.absent();
|
groupRecord = Optional.absent();
|
||||||
}
|
}
|
||||||
|
|
||||||
Recipient recipient = Recipient.from(context, address, settings, groupRecord, false);
|
Recipient recipient = Recipient.from(context, address, settings, groupRecord, true);
|
||||||
String body = cursor.getString(cursor.getColumnIndexOrThrow(ThreadDatabase.SNIPPET));
|
String body = cursor.getString(cursor.getColumnIndexOrThrow(ThreadDatabase.SNIPPET));
|
||||||
long date = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.DATE));
|
long date = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.DATE));
|
||||||
long count = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.MESSAGE_COUNT));
|
long count = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.MESSAGE_COUNT));
|
||||||
|
@ -12,11 +12,8 @@ import androidx.core.content.ContextCompat
|
|||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import kotlinx.android.synthetic.main.view_conversation.view.*
|
import kotlinx.android.synthetic.main.view_conversation.view.*
|
||||||
import kotlinx.android.synthetic.main.view_profile_picture.view.*
|
|
||||||
import kotlinx.coroutines.*
|
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionManagerUtilities.populateUserPublicKeyCacheIfNeeded
|
|
||||||
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionUtilities.highlightMentions
|
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionUtilities.highlightMentions
|
||||||
import org.thoughtcrime.securesms.database.RecipientDatabase
|
import org.thoughtcrime.securesms.database.RecipientDatabase
|
||||||
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
||||||
@ -42,63 +39,58 @@ class ConversationView : LinearLayout {
|
|||||||
// region Updating
|
// region Updating
|
||||||
fun bind(thread: ThreadRecord, isTyping: Boolean, glide: GlideRequests) {
|
fun bind(thread: ThreadRecord, isTyping: Boolean, glide: GlideRequests) {
|
||||||
this.thread = thread
|
this.thread = thread
|
||||||
profilePictureView.glide = glide
|
val unreadCount = thread.unreadCount
|
||||||
|
if (thread.recipient.isBlocked) {
|
||||||
|
accentView.setBackgroundResource(R.color.destructive)
|
||||||
|
accentView.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
accentView.setBackgroundResource(R.color.accent)
|
||||||
|
accentView.visibility = if (unreadCount > 0) View.VISIBLE else View.INVISIBLE
|
||||||
|
}
|
||||||
|
val formattedUnreadCount = if (unreadCount < 100) unreadCount.toString() else "99+"
|
||||||
|
unreadCountTextView.text = formattedUnreadCount
|
||||||
|
val textSize = if (unreadCount < 100) 12.0f else 9.0f
|
||||||
|
unreadCountTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, textSize)
|
||||||
|
unreadCountTextView.setTypeface(Typeface.DEFAULT, if (unreadCount < 100) Typeface.BOLD else Typeface.NORMAL)
|
||||||
|
unreadCountIndicator.isVisible = (unreadCount != 0)
|
||||||
|
val senderDisplayName = getUserDisplayName(thread.recipient)
|
||||||
|
?: thread.recipient.address.toString()
|
||||||
|
conversationViewDisplayNameTextView.text = senderDisplayName
|
||||||
|
timestampTextView.text = DateUtils.getDisplayFormattedTimeSpanString(context, Locale.getDefault(), thread.date)
|
||||||
|
val recipient = thread.recipient
|
||||||
|
muteIndicatorImageView.isVisible = recipient.isMuted || recipient.notifyType != RecipientDatabase.NOTIFY_TYPE_ALL
|
||||||
|
val drawableRes = if (recipient.isMuted || recipient.notifyType == RecipientDatabase.NOTIFY_TYPE_NONE) {
|
||||||
|
R.drawable.ic_outline_notifications_off_24
|
||||||
|
} else {
|
||||||
|
R.drawable.ic_notifications_mentions
|
||||||
|
}
|
||||||
|
muteIndicatorImageView.setImageResource(drawableRes)
|
||||||
|
val rawSnippet = thread.getDisplayBody(context)
|
||||||
|
val snippet = highlightMentions(rawSnippet, thread.threadId, context)
|
||||||
|
snippetTextView.text = snippet
|
||||||
|
snippetTextView.typeface = if (unreadCount > 0) Typeface.DEFAULT_BOLD else Typeface.DEFAULT
|
||||||
|
snippetTextView.visibility = if (isTyping) View.GONE else View.VISIBLE
|
||||||
|
if (isTyping) {
|
||||||
|
typingIndicatorView.startAnimation()
|
||||||
|
} else {
|
||||||
|
typingIndicatorView.stopAnimation()
|
||||||
|
}
|
||||||
|
typingIndicatorView.visibility = if (isTyping) View.VISIBLE else View.GONE
|
||||||
|
statusIndicatorImageView.visibility = View.VISIBLE
|
||||||
|
when {
|
||||||
|
!thread.isOutgoing -> statusIndicatorImageView.visibility = View.GONE
|
||||||
|
thread.isFailed -> {
|
||||||
|
val drawable = ContextCompat.getDrawable(context, R.drawable.ic_error)?.mutate()
|
||||||
|
drawable?.setTint(ContextCompat.getColor(context, R.color.destructive))
|
||||||
|
statusIndicatorImageView.setImageDrawable(drawable)
|
||||||
|
}
|
||||||
|
thread.isPending -> statusIndicatorImageView.setImageResource(R.drawable.ic_circle_dot_dot_dot)
|
||||||
|
thread.isRead -> statusIndicatorImageView.setImageResource(R.drawable.ic_filled_circle_check)
|
||||||
|
else -> statusIndicatorImageView.setImageResource(R.drawable.ic_circle_check)
|
||||||
|
}
|
||||||
post {
|
post {
|
||||||
val unreadCount = thread.unreadCount
|
profilePictureView.glide = glide
|
||||||
if (thread.recipient.isBlocked) {
|
profilePictureView.update(thread.recipient, thread.threadId)
|
||||||
accentView.setBackgroundResource(R.color.destructive)
|
|
||||||
accentView.visibility = View.VISIBLE
|
|
||||||
} else {
|
|
||||||
accentView.setBackgroundResource(R.color.accent)
|
|
||||||
accentView.visibility = if (unreadCount > 0) View.VISIBLE else View.INVISIBLE
|
|
||||||
}
|
|
||||||
val formattedUnreadCount = if (unreadCount < 100) unreadCount.toString() else "99+"
|
|
||||||
unreadCountTextView.text = formattedUnreadCount
|
|
||||||
val textSize = if (unreadCount < 100) 12.0f else 9.0f
|
|
||||||
unreadCountTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, textSize)
|
|
||||||
unreadCountTextView.setTypeface(Typeface.DEFAULT, if (unreadCount < 100) Typeface.BOLD else Typeface.NORMAL)
|
|
||||||
unreadCountIndicator.isVisible = (unreadCount != 0)
|
|
||||||
val senderDisplayName = getUserDisplayName(thread.recipient)
|
|
||||||
?: thread.recipient.address.toString()
|
|
||||||
conversationViewDisplayNameTextView.text = senderDisplayName
|
|
||||||
timestampTextView.text = DateUtils.getDisplayFormattedTimeSpanString(context, Locale.getDefault(), thread.date)
|
|
||||||
val recipient = thread.recipient
|
|
||||||
muteIndicatorImageView.isVisible = recipient.isMuted || recipient.notifyType != RecipientDatabase.NOTIFY_TYPE_ALL
|
|
||||||
val drawableRes = if (recipient.isMuted || recipient.notifyType == RecipientDatabase.NOTIFY_TYPE_NONE) {
|
|
||||||
R.drawable.ic_outline_notifications_off_24
|
|
||||||
} else {
|
|
||||||
R.drawable.ic_notifications_mentions
|
|
||||||
}
|
|
||||||
muteIndicatorImageView.setImageResource(drawableRes)
|
|
||||||
val rawSnippet = thread.getDisplayBody(context)
|
|
||||||
val snippet = highlightMentions(rawSnippet, thread.threadId, context)
|
|
||||||
snippetTextView.text = snippet
|
|
||||||
snippetTextView.typeface = if (unreadCount > 0) Typeface.DEFAULT_BOLD else Typeface.DEFAULT
|
|
||||||
snippetTextView.visibility = if (isTyping) View.GONE else View.VISIBLE
|
|
||||||
if (isTyping) {
|
|
||||||
typingIndicatorView.startAnimation()
|
|
||||||
} else {
|
|
||||||
typingIndicatorView.stopAnimation()
|
|
||||||
}
|
|
||||||
typingIndicatorView.visibility = if (isTyping) View.VISIBLE else View.GONE
|
|
||||||
statusIndicatorImageView.visibility = View.VISIBLE
|
|
||||||
when {
|
|
||||||
!thread.isOutgoing -> statusIndicatorImageView.visibility = View.GONE
|
|
||||||
thread.isFailed -> {
|
|
||||||
val drawable = ContextCompat.getDrawable(context, R.drawable.ic_error)?.mutate()
|
|
||||||
drawable?.setTint(ContextCompat.getColor(context, R.color.destructive))
|
|
||||||
statusIndicatorImageView.setImageDrawable(drawable)
|
|
||||||
}
|
|
||||||
thread.isPending -> statusIndicatorImageView.setImageResource(R.drawable.ic_circle_dot_dot_dot)
|
|
||||||
thread.isRead -> statusIndicatorImageView.setImageResource(R.drawable.ic_filled_circle_check)
|
|
||||||
else -> statusIndicatorImageView.setImageResource(R.drawable.ic_circle_check)
|
|
||||||
}
|
|
||||||
GlobalScope.launch(Dispatchers.IO) {
|
|
||||||
populateUserPublicKeyCacheIfNeeded(thread.threadId, context) // FIXME: This is a bad place to do this
|
|
||||||
withContext(Dispatchers.Main) {
|
|
||||||
profilePictureView.update(thread.recipient, thread.threadId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,6 +153,7 @@ public class Recipient implements RecipientModifiedListener {
|
|||||||
this.profileSharing = stale.profileSharing;
|
this.profileSharing = stale.profileSharing;
|
||||||
this.unidentifiedAccessMode = stale.unidentifiedAccessMode;
|
this.unidentifiedAccessMode = stale.unidentifiedAccessMode;
|
||||||
this.forceSmsSelection = stale.forceSmsSelection;
|
this.forceSmsSelection = stale.forceSmsSelection;
|
||||||
|
this.notifyType = stale.notifyType;
|
||||||
|
|
||||||
this.participants.clear();
|
this.participants.clear();
|
||||||
this.participants.addAll(stale.participants);
|
this.participants.addAll(stale.participants);
|
||||||
@ -180,6 +181,7 @@ public class Recipient implements RecipientModifiedListener {
|
|||||||
this.profileSharing = details.get().profileSharing;
|
this.profileSharing = details.get().profileSharing;
|
||||||
this.unidentifiedAccessMode = details.get().unidentifiedAccessMode;
|
this.unidentifiedAccessMode = details.get().unidentifiedAccessMode;
|
||||||
this.forceSmsSelection = details.get().forceSmsSelection;
|
this.forceSmsSelection = details.get().forceSmsSelection;
|
||||||
|
this.notifyType = details.get().notifyType;
|
||||||
|
|
||||||
this.participants.clear();
|
this.participants.clear();
|
||||||
this.participants.addAll(details.get().participants);
|
this.participants.addAll(details.get().participants);
|
||||||
|
Loading…
Reference in New Issue
Block a user