mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-28 20:45:17 +00:00
Renamed group terminology
This commit is contained in:
parent
122838d9ae
commit
e89cbdf029
@ -440,7 +440,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void sendMediaSavedNotificationIfNeeded() {
|
private void sendMediaSavedNotificationIfNeeded() {
|
||||||
if (conversationRecipient.isGroupRecipient()) return;
|
if (conversationRecipient.isGroupOrCommunityRecipient()) return;
|
||||||
DataExtractionNotification message = new DataExtractionNotification(new DataExtractionNotification.Kind.MediaSaved(SnodeAPI.getNowWithOffset()));
|
DataExtractionNotification message = new DataExtractionNotification(new DataExtractionNotification.Kind.MediaSaved(SnodeAPI.getNowWithOffset()));
|
||||||
MessageSender.send(message, conversationRecipient.getAddress());
|
MessageSender.send(message, conversationRecipient.getAddress());
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ class ProfilePictureView @JvmOverloads constructor(
|
|||||||
|
|
||||||
fun update(recipient: Recipient) {
|
fun update(recipient: Recipient) {
|
||||||
this.recipient = recipient
|
this.recipient = recipient
|
||||||
recipient.run { update(address, isLegacyClosedGroupRecipient, isOpenGroupInboxRecipient) }
|
recipient.run { update(address, isLegacyGroupRecipient, isCommunityInboxRecipient) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun update(
|
fun update(
|
||||||
|
@ -298,7 +298,7 @@ class ConfigToDatabaseSync @Inject constructor(
|
|||||||
buildMap(reader.count) {
|
buildMap(reader.count) {
|
||||||
var current = reader.next
|
var current = reader.next
|
||||||
while (current != null) {
|
while (current != null) {
|
||||||
if (current.recipient?.isClosedGroupV2Recipient == true) {
|
if (current.recipient?.isGroupV2Recipient == true) {
|
||||||
put(AccountId(current.recipient.address.serialize()), current.threadId)
|
put(AccountId(current.recipient.address.serialize()), current.threadId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ class ContactSelectionListLoader(context: Context, val mode: Int, val filter: St
|
|||||||
}
|
}
|
||||||
val list = mutableListOf<ContactSelectionListItem>()
|
val list = mutableListOf<ContactSelectionListItem>()
|
||||||
if (isFlagSet(DisplayMode.FLAG_CLOSED_GROUPS)) {
|
if (isFlagSet(DisplayMode.FLAG_CLOSED_GROUPS)) {
|
||||||
list.addAll(getClosedGroups(contacts))
|
list.addAll(getGroups(contacts))
|
||||||
}
|
}
|
||||||
if (isFlagSet(DisplayMode.FLAG_OPEN_GROUPS)) {
|
if (isFlagSet(DisplayMode.FLAG_OPEN_GROUPS)) {
|
||||||
list.addAll(getCommunities(contacts))
|
list.addAll(getCommunities(contacts))
|
||||||
@ -46,14 +46,12 @@ class ContactSelectionListLoader(context: Context, val mode: Int, val filter: St
|
|||||||
|
|
||||||
private fun getContacts(contacts: List<Recipient>): List<ContactSelectionListItem> {
|
private fun getContacts(contacts: List<Recipient>): List<ContactSelectionListItem> {
|
||||||
return getItems(contacts, context.getString(R.string.contactContacts)) {
|
return getItems(contacts, context.getString(R.string.contactContacts)) {
|
||||||
!it.isGroupRecipient
|
!it.isGroupOrCommunityRecipient
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getClosedGroups(contacts: List<Recipient>): List<ContactSelectionListItem> {
|
private fun getGroups(contacts: List<Recipient>): List<ContactSelectionListItem> {
|
||||||
return getItems(contacts, context.getString(R.string.conversationsGroups)) {
|
return getItems(contacts, context.getString(R.string.conversationsGroups)) { it.address.isGroup }
|
||||||
it.address.isLegacyClosedGroup || it.address.isClosedGroupV2
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getCommunities(contacts: List<Recipient>): List<ContactSelectionListItem> {
|
private fun getCommunities(contacts: List<Recipient>): List<ContactSelectionListItem> {
|
||||||
|
@ -9,7 +9,7 @@ class SelectContactsLoader(context: Context, private val usersToExclude: Set<Str
|
|||||||
override fun loadInBackground(): List<String> {
|
override fun loadInBackground(): List<String> {
|
||||||
val contacts = ContactUtilities.getAllContacts(context)
|
val contacts = ContactUtilities.getAllContacts(context)
|
||||||
return contacts.filter {
|
return contacts.filter {
|
||||||
!it.isGroupRecipient && !usersToExclude.contains(it.address.toString()) && it.hasApprovedMe()
|
!it.isGroupOrCommunityRecipient && !usersToExclude.contains(it.address.toString()) && it.hasApprovedMe()
|
||||||
}.map {
|
}.map {
|
||||||
it.address.toString()
|
it.address.toString()
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ class UserView : LinearLayout {
|
|||||||
val address = user.address.serialize()
|
val address = user.address.serialize()
|
||||||
binding.profilePictureView.update(user)
|
binding.profilePictureView.update(user)
|
||||||
binding.actionIndicatorImageView.setImageResource(R.drawable.ic_baseline_edit_24)
|
binding.actionIndicatorImageView.setImageResource(R.drawable.ic_baseline_edit_24)
|
||||||
binding.nameTextView.text = if (user.isGroupRecipient) user.name else getUserDisplayName(address)
|
binding.nameTextView.text = if (user.isGroupOrCommunityRecipient) user.name else getUserDisplayName(address)
|
||||||
when (actionIndicator) {
|
when (actionIndicator) {
|
||||||
ActionIndicator.None -> {
|
ActionIndicator.None -> {
|
||||||
binding.actionIndicatorImageView.visibility = View.GONE
|
binding.actionIndicatorImageView.visibility = View.GONE
|
||||||
|
@ -12,7 +12,6 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback
|
import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback
|
||||||
import com.google.android.material.tabs.TabLayoutMediator
|
import com.google.android.material.tabs.TabLayoutMediator
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlin.time.Duration.Companion.milliseconds
|
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import network.loki.messenger.databinding.ViewConversationActionBarBinding
|
import network.loki.messenger.databinding.ViewConversationActionBarBinding
|
||||||
import network.loki.messenger.databinding.ViewConversationSettingBinding
|
import network.loki.messenger.databinding.ViewConversationSettingBinding
|
||||||
@ -81,7 +80,7 @@ class ConversationActionBarView @JvmOverloads constructor(
|
|||||||
) {
|
) {
|
||||||
this.delegate = delegate
|
this.delegate = delegate
|
||||||
binding.profilePictureView.layoutParams = resources.getDimensionPixelSize(
|
binding.profilePictureView.layoutParams = resources.getDimensionPixelSize(
|
||||||
if (recipient.isClosedGroupV2Recipient) R.dimen.medium_profile_picture_size else R.dimen.small_profile_picture_size
|
if (recipient.isGroupV2Recipient) R.dimen.medium_profile_picture_size else R.dimen.small_profile_picture_size
|
||||||
).let { LayoutParams(it, it) }
|
).let { LayoutParams(it, it) }
|
||||||
update(recipient, openGroup, config)
|
update(recipient, openGroup, config)
|
||||||
}
|
}
|
||||||
@ -134,12 +133,12 @@ class ConversationActionBarView @JvmOverloads constructor(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recipient.isGroupRecipient) {
|
if (recipient.isGroupOrCommunityRecipient) {
|
||||||
val title = if (recipient.isCommunityRecipient) {
|
val title = if (recipient.isCommunityRecipient) {
|
||||||
val userCount = openGroup?.let { lokiApiDb.getUserCount(it.room, it.server) } ?: 0
|
val userCount = openGroup?.let { lokiApiDb.getUserCount(it.room, it.server) } ?: 0
|
||||||
resources.getQuantityString(R.plurals.membersActive, userCount, userCount)
|
resources.getQuantityString(R.plurals.membersActive, userCount, userCount)
|
||||||
} else {
|
} else {
|
||||||
val userCount = if (recipient.isClosedGroupV2Recipient) {
|
val userCount = if (recipient.isGroupV2Recipient) {
|
||||||
storage.getMembers(recipient.address.serialize()).size
|
storage.getMembers(recipient.address.serialize()).size
|
||||||
} else { // legacy closed groups
|
} else { // legacy closed groups
|
||||||
groupDb.getGroupMemberAddresses(recipient.address.toGroupString(), true).size
|
groupDb.getGroupMemberAddresses(recipient.address.toGroupString(), true).size
|
||||||
|
@ -58,7 +58,7 @@ class DisappearingMessages @Inject constructor(
|
|||||||
text = if (message.expiresIn == 0L) R.string.confirm else R.string.set,
|
text = if (message.expiresIn == 0L) R.string.confirm else R.string.set,
|
||||||
contentDescriptionRes = if (message.expiresIn == 0L) R.string.AccessibilityId_confirm else R.string.AccessibilityId_setButton
|
contentDescriptionRes = if (message.expiresIn == 0L) R.string.AccessibilityId_confirm else R.string.AccessibilityId_setButton
|
||||||
) {
|
) {
|
||||||
set(message.threadId, message.recipient.address, message.expiryMode, message.recipient.isClosedGroupV2Recipient)
|
set(message.threadId, message.recipient.address, message.expiryMode, message.recipient.isGroupV2Recipient)
|
||||||
}
|
}
|
||||||
cancelButton()
|
cancelButton()
|
||||||
}
|
}
|
||||||
|
@ -60,25 +60,25 @@ class DisappearingMessagesViewModel(
|
|||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
val expiryMode = storage.getExpirationConfiguration(threadId)?.expiryMode ?: ExpiryMode.NONE
|
val expiryMode = storage.getExpirationConfiguration(threadId)?.expiryMode ?: ExpiryMode.NONE
|
||||||
val recipient = threadDb.getRecipientForThreadId(threadId)?: return@launch
|
val recipient = threadDb.getRecipientForThreadId(threadId)?: return@launch
|
||||||
val groupRecord = recipient.takeIf { it.isLegacyClosedGroupRecipient || it.isClosedGroupV2Recipient }
|
val groupRecord = recipient.takeIf { it.isLegacyGroupRecipient || it.isGroupV2Recipient }
|
||||||
?.run { groupDb.getGroup(address.toGroupString()).orNull() }
|
?.run { groupDb.getGroup(address.toGroupString()).orNull() }
|
||||||
|
|
||||||
val isAdmin = when {
|
val isAdmin = when {
|
||||||
recipient.isClosedGroupV2Recipient -> {
|
recipient.isGroupV2Recipient -> {
|
||||||
// Handle the new closed group functionality
|
// Handle the new closed group functionality
|
||||||
storage.getMembers(recipient.address.serialize()).any { it.sessionId == textSecurePreferences.getLocalNumber() && it.admin }
|
storage.getMembers(recipient.address.serialize()).any { it.sessionId == textSecurePreferences.getLocalNumber() && it.admin }
|
||||||
}
|
}
|
||||||
recipient.isLegacyClosedGroupRecipient -> {
|
recipient.isLegacyGroupRecipient -> {
|
||||||
// Handle as legacy group
|
// Handle as legacy group
|
||||||
groupRecord?.admins?.any{ it.serialize() == textSecurePreferences.getLocalNumber() } == true
|
groupRecord?.admins?.any{ it.serialize() == textSecurePreferences.getLocalNumber() } == true
|
||||||
}
|
}
|
||||||
else -> !recipient.isGroupRecipient
|
else -> !recipient.isGroupOrCommunityRecipient
|
||||||
}
|
}
|
||||||
|
|
||||||
_state.update {
|
_state.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
address = recipient.address,
|
address = recipient.address,
|
||||||
isGroup = recipient.isGroupRecipient,
|
isGroup = recipient.isGroupOrCommunityRecipient,
|
||||||
isNoteToSelf = recipient.address.serialize() == textSecurePreferences.getLocalNumber(),
|
isNoteToSelf = recipient.address.serialize() == textSecurePreferences.getLocalNumber(),
|
||||||
isSelfAdmin = isAdmin,
|
isSelfAdmin = isAdmin,
|
||||||
expiryMode = expiryMode,
|
expiryMode = expiryMode,
|
||||||
|
@ -37,7 +37,6 @@ import androidx.compose.runtime.collectAsState
|
|||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.platform.ViewCompositionStrategy
|
import androidx.compose.ui.platform.ViewCompositionStrategy
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.isGone
|
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
@ -57,17 +56,13 @@ import dagger.hilt.android.AndroidEntryPoint
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.channels.BufferOverflow
|
import kotlinx.coroutines.channels.BufferOverflow
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
import kotlinx.coroutines.flow.collect
|
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.flow.filter
|
import kotlinx.coroutines.flow.filter
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.mapNotNull
|
import kotlinx.coroutines.flow.mapNotNull
|
||||||
import kotlinx.coroutines.flow.onCompletion
|
|
||||||
import kotlinx.coroutines.flow.receiveAsFlow
|
import kotlinx.coroutines.flow.receiveAsFlow
|
||||||
import kotlinx.coroutines.flow.takeWhile
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
@ -168,8 +163,6 @@ import org.thoughtcrime.securesms.dependencies.ConfigFactory
|
|||||||
import org.thoughtcrime.securesms.giph.ui.GiphyActivity
|
import org.thoughtcrime.securesms.giph.ui.GiphyActivity
|
||||||
import org.thoughtcrime.securesms.groups.OpenGroupManager
|
import org.thoughtcrime.securesms.groups.OpenGroupManager
|
||||||
import org.thoughtcrime.securesms.home.search.getSearchName
|
import org.thoughtcrime.securesms.home.search.getSearchName
|
||||||
import org.thoughtcrime.securesms.home.HomeActivity
|
|
||||||
import org.thoughtcrime.securesms.home.startHomeActivity
|
|
||||||
import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository
|
import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository
|
||||||
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil
|
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil
|
||||||
import org.thoughtcrime.securesms.linkpreview.LinkPreviewViewModel
|
import org.thoughtcrime.securesms.linkpreview.LinkPreviewViewModel
|
||||||
@ -188,7 +181,6 @@ import org.thoughtcrime.securesms.reactions.ReactionsDialogFragment
|
|||||||
import org.thoughtcrime.securesms.reactions.any.ReactWithAnyEmojiDialogFragment
|
import org.thoughtcrime.securesms.reactions.any.ReactWithAnyEmojiDialogFragment
|
||||||
import org.thoughtcrime.securesms.showSessionDialog
|
import org.thoughtcrime.securesms.showSessionDialog
|
||||||
import org.thoughtcrime.securesms.util.ActivityDispatcher
|
import org.thoughtcrime.securesms.util.ActivityDispatcher
|
||||||
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
|
||||||
import org.thoughtcrime.securesms.util.DateUtils
|
import org.thoughtcrime.securesms.util.DateUtils
|
||||||
import org.thoughtcrime.securesms.util.MediaUtil
|
import org.thoughtcrime.securesms.util.MediaUtil
|
||||||
import org.thoughtcrime.securesms.util.NetworkUtils
|
import org.thoughtcrime.securesms.util.NetworkUtils
|
||||||
@ -815,7 +807,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
|
|
||||||
// called from onCreate
|
// called from onCreate
|
||||||
private fun setUpBlockedBanner() {
|
private fun setUpBlockedBanner() {
|
||||||
val recipient = viewModel.recipient?.takeUnless { it.isGroupRecipient } ?: return
|
val recipient = viewModel.recipient?.takeUnless { it.isGroupOrCommunityRecipient } ?: return
|
||||||
binding.blockedBannerTextView.text = applicationContext.getString(R.string.blockBlockedDescription)
|
binding.blockedBannerTextView.text = applicationContext.getString(R.string.blockBlockedDescription)
|
||||||
binding.blockedBanner.isVisible = recipient.isBlocked
|
binding.blockedBanner.isVisible = recipient.isBlocked
|
||||||
binding.blockedBanner.setOnClickListener { viewModel.unblock() }
|
binding.blockedBanner.setOnClickListener { viewModel.unblock() }
|
||||||
@ -838,7 +830,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setUpLegacyGroupBanner() {
|
private fun setUpLegacyGroupBanner() {
|
||||||
val shouldDisplayBanner = viewModel.recipient?.isLegacyClosedGroupRecipient ?: return
|
val shouldDisplayBanner = viewModel.recipient?.isLegacyGroupRecipient ?: return
|
||||||
|
|
||||||
with(binding) {
|
with(binding) {
|
||||||
outdatedGroupBanner.isVisible = shouldDisplayBanner
|
outdatedGroupBanner.isVisible = shouldDisplayBanner
|
||||||
@ -1190,7 +1182,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 10n1 and groups
|
// 10n1 and groups
|
||||||
recipient.is1on1 || recipient.isGroupRecipient -> {
|
recipient.is1on1 || recipient.isGroupOrCommunityRecipient -> {
|
||||||
Phrase.from(applicationContext, R.string.groupNoMessages)
|
Phrase.from(applicationContext, R.string.groupNoMessages)
|
||||||
.put(GROUP_NAME_KEY, recipient.toShortString())
|
.put(GROUP_NAME_KEY, recipient.toShortString())
|
||||||
.format()
|
.format()
|
||||||
@ -1241,7 +1233,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
val recipient = viewModel.recipient ?: return Log.w("Loki", "Recipient was null for block action")
|
val recipient = viewModel.recipient ?: return Log.w("Loki", "Recipient was null for block action")
|
||||||
val invitingAdmin = viewModel.invitingAdmin
|
val invitingAdmin = viewModel.invitingAdmin
|
||||||
|
|
||||||
val name = if (recipient.isClosedGroupV2Recipient && invitingAdmin != null) {
|
val name = if (recipient.isGroupV2Recipient && invitingAdmin != null) {
|
||||||
invitingAdmin.getSearchName()
|
invitingAdmin.getSearchName()
|
||||||
} else {
|
} else {
|
||||||
recipient.toShortString()
|
recipient.toShortString()
|
||||||
@ -1291,7 +1283,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
|
|
||||||
// TODO: don't need to allow new closed group check here, removed in new disappearing messages
|
// TODO: don't need to allow new closed group check here, removed in new disappearing messages
|
||||||
override fun showDisappearingMessages(thread: Recipient) {
|
override fun showDisappearingMessages(thread: Recipient) {
|
||||||
if (thread.isLegacyClosedGroupRecipient) {
|
if (thread.isLegacyGroupRecipient) {
|
||||||
groupDb.getGroup(thread.address.toGroupString()).orNull()?.run { if (!isActive) return }
|
groupDb.getGroup(thread.address.toGroupString()).orNull()?.run { if (!isActive) return }
|
||||||
}
|
}
|
||||||
Intent(this, DisappearingMessagesActivity::class.java)
|
Intent(this, DisappearingMessagesActivity::class.java)
|
||||||
@ -1719,7 +1711,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onReactionLongClicked(messageId: MessageId, emoji: String?) {
|
override fun onReactionLongClicked(messageId: MessageId, emoji: String?) {
|
||||||
if (viewModel.recipient?.isGroupRecipient == true) {
|
if (viewModel.recipient?.isGroupOrCommunityRecipient == true) {
|
||||||
val isUserModerator = viewModel.openGroup?.let { openGroup ->
|
val isUserModerator = viewModel.openGroup?.let { openGroup ->
|
||||||
val userPublicKey = textSecurePreferences.getLocalNumber() ?: return@let false
|
val userPublicKey = textSecurePreferences.getLocalNumber() ?: return@let false
|
||||||
OpenGroupManager.isUserModerator(this, openGroup.id, userPublicKey, viewModel.blindedPublicKey)
|
OpenGroupManager.isUserModerator(this, openGroup.id, userPublicKey, viewModel.blindedPublicKey)
|
||||||
@ -2339,7 +2331,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
|
|
||||||
private fun sendScreenshotNotification() {
|
private fun sendScreenshotNotification() {
|
||||||
val recipient = viewModel.recipient ?: return
|
val recipient = viewModel.recipient ?: return
|
||||||
if (recipient.isGroupRecipient) return
|
if (recipient.isGroupOrCommunityRecipient) return
|
||||||
val kind = DataExtractionNotification.Kind.Screenshot()
|
val kind = DataExtractionNotification.Kind.Screenshot()
|
||||||
val message = DataExtractionNotification(kind)
|
val message = DataExtractionNotification(kind)
|
||||||
MessageSender.send(message, recipient.address)
|
MessageSender.send(message, recipient.address)
|
||||||
@ -2347,7 +2339,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
|
|
||||||
private fun sendMediaSavedNotification() {
|
private fun sendMediaSavedNotification() {
|
||||||
val recipient = viewModel.recipient ?: return
|
val recipient = viewModel.recipient ?: return
|
||||||
if (recipient.isGroupRecipient) { return }
|
if (recipient.isGroupOrCommunityRecipient) { return }
|
||||||
val timestamp = SnodeAPI.nowWithOffset
|
val timestamp = SnodeAPI.nowWithOffset
|
||||||
val kind = DataExtractionNotification.Kind.MediaSaved(timestamp)
|
val kind = DataExtractionNotification.Kind.MediaSaved(timestamp)
|
||||||
val message = DataExtractionNotification(kind)
|
val message = DataExtractionNotification(kind)
|
||||||
|
@ -123,8 +123,8 @@ class ConversationViewModel(
|
|||||||
val blindedRecipient: Recipient?
|
val blindedRecipient: Recipient?
|
||||||
get() = _recipient.value?.let { recipient ->
|
get() = _recipient.value?.let { recipient ->
|
||||||
when {
|
when {
|
||||||
recipient.isOpenGroupOutboxRecipient -> recipient
|
recipient.isCommunityOutboxRecipient -> recipient
|
||||||
recipient.isOpenGroupInboxRecipient -> repository.maybeGetBlindedRecipient(recipient)
|
recipient.isCommunityInboxRecipient -> repository.maybeGetBlindedRecipient(recipient)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,7 +137,7 @@ class ConversationViewModel(
|
|||||||
val invitingAdmin: Recipient?
|
val invitingAdmin: Recipient?
|
||||||
get() {
|
get() {
|
||||||
val recipient = recipient ?: return null
|
val recipient = recipient ?: return null
|
||||||
if (!recipient.isClosedGroupV2Recipient) return null
|
if (!recipient.isGroupV2Recipient) return null
|
||||||
|
|
||||||
return repository.getInvitingAdmin(threadId)
|
return repository.getInvitingAdmin(threadId)
|
||||||
}
|
}
|
||||||
@ -151,14 +151,14 @@ class ConversationViewModel(
|
|||||||
private val closedGroupMembers: List<GroupMember>
|
private val closedGroupMembers: List<GroupMember>
|
||||||
get() {
|
get() {
|
||||||
val recipient = recipient ?: return emptyList()
|
val recipient = recipient ?: return emptyList()
|
||||||
if (!recipient.isClosedGroupV2Recipient) return emptyList()
|
if (!recipient.isGroupV2Recipient) return emptyList()
|
||||||
return storage.getMembers(recipient.address.serialize())
|
return storage.getMembers(recipient.address.serialize())
|
||||||
}
|
}
|
||||||
|
|
||||||
val isClosedGroupAdmin: Boolean
|
val isClosedGroupAdmin: Boolean
|
||||||
get() {
|
get() {
|
||||||
val recipient = recipient ?: return false
|
val recipient = recipient ?: return false
|
||||||
return !recipient.isClosedGroupV2Recipient ||
|
return !recipient.isGroupV2Recipient ||
|
||||||
(closedGroupMembers.firstOrNull { it.sessionId == storage.getUserPublicKey() }?.admin ?: false)
|
(closedGroupMembers.firstOrNull { it.sessionId == storage.getUserPublicKey() }?.admin ?: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,7 +174,7 @@ class ConversationViewModel(
|
|||||||
val isMessageRequestThread : Boolean
|
val isMessageRequestThread : Boolean
|
||||||
get() {
|
get() {
|
||||||
val recipient = recipient ?: return false
|
val recipient = recipient ?: return false
|
||||||
return !recipient.isLocalNumber && !recipient.isLegacyClosedGroupRecipient && !recipient.isCommunityRecipient && !recipient.isApproved
|
return !recipient.isLocalNumber && !recipient.isLegacyGroupRecipient && !recipient.isCommunityRecipient && !recipient.isApproved
|
||||||
}
|
}
|
||||||
|
|
||||||
val canReactToMessages: Boolean
|
val canReactToMessages: Boolean
|
||||||
@ -230,8 +230,8 @@ class ConversationViewModel(
|
|||||||
*/
|
*/
|
||||||
private fun shouldShowInput(recipient: Recipient?): Boolean {
|
private fun shouldShowInput(recipient: Recipient?): Boolean {
|
||||||
return when {
|
return when {
|
||||||
recipient?.isClosedGroupV2Recipient == true -> !repository.isGroupReadOnly(recipient)
|
recipient?.isGroupV2Recipient == true -> !repository.isGroupReadOnly(recipient)
|
||||||
recipient?.isLegacyClosedGroupRecipient == true -> {
|
recipient?.isLegacyGroupRecipient == true -> {
|
||||||
groupDb.getGroup(recipient.address.toGroupString()).orNull()?.isActive == true
|
groupDb.getGroup(recipient.address.toGroupString()).orNull()?.isActive == true
|
||||||
}
|
}
|
||||||
openGroup != null -> openGroup?.canWrite == true
|
openGroup != null -> openGroup?.canWrite == true
|
||||||
@ -253,7 +253,7 @@ class ConversationViewModel(
|
|||||||
(!recipient.isApproved && !recipient.isLocalNumber) &&
|
(!recipient.isApproved && !recipient.isLocalNumber) &&
|
||||||
|
|
||||||
// Req 4: the type of conversation supports message request
|
// Req 4: the type of conversation supports message request
|
||||||
(recipient.is1on1 || recipient.isClosedGroupV2Recipient) &&
|
(recipient.is1on1 || recipient.isGroupV2Recipient) &&
|
||||||
|
|
||||||
// Req 2: we haven't sent a message to them before
|
// Req 2: we haven't sent a message to them before
|
||||||
!threadDb.getLastSeenAndHasSent(threadId).second() &&
|
!threadDb.getLastSeenAndHasSent(threadId).second() &&
|
||||||
@ -263,14 +263,14 @@ class ConversationViewModel(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
return MessageRequestUiState.Visible(
|
return MessageRequestUiState.Visible(
|
||||||
acceptButtonText = if (recipient.isGroupRecipient) {
|
acceptButtonText = if (recipient.isGroupOrCommunityRecipient) {
|
||||||
R.string.messageRequestGroupInviteDescription
|
R.string.messageRequestGroupInviteDescription
|
||||||
} else {
|
} else {
|
||||||
R.string.messageRequestsAcceptDescription
|
R.string.messageRequestsAcceptDescription
|
||||||
},
|
},
|
||||||
// You can block a 1to1 conversation, or a normal groups v2 conversation
|
// You can block a 1to1 conversation, or a normal groups v2 conversation
|
||||||
showBlockButton = recipient.is1on1 || recipient.isClosedGroupV2Recipient,
|
showBlockButton = recipient.is1on1 || recipient.isGroupV2Recipient,
|
||||||
declineButtonText = if (recipient.isClosedGroupV2Recipient) {
|
declineButtonText = if (recipient.isGroupV2Recipient) {
|
||||||
R.string.delete
|
R.string.delete
|
||||||
} else {
|
} else {
|
||||||
R.string.decline
|
R.string.decline
|
||||||
@ -311,7 +311,7 @@ class ConversationViewModel(
|
|||||||
fun block() {
|
fun block() {
|
||||||
// inviting admin will be true if this request is a closed group message request
|
// inviting admin will be true if this request is a closed group message request
|
||||||
val recipient = invitingAdmin ?: recipient ?: return Log.w("Loki", "Recipient was null for block action")
|
val recipient = invitingAdmin ?: recipient ?: return Log.w("Loki", "Recipient was null for block action")
|
||||||
if (recipient.isContactRecipient || recipient.isClosedGroupV2Recipient) {
|
if (recipient.isContactRecipient || recipient.isGroupV2Recipient) {
|
||||||
repository.setBlocked(threadId, recipient, true)
|
repository.setBlocked(threadId, recipient, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@ import network.loki.messenger.databinding.FragmentDeleteMessageBottomSheetBindin
|
|||||||
import org.session.libsession.messaging.contacts.Contact
|
import org.session.libsession.messaging.contacts.Contact
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.database.SessionContactDatabase
|
import org.thoughtcrime.securesms.database.SessionContactDatabase
|
||||||
import org.thoughtcrime.securesms.util.UiModeUtilities
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
@ -59,11 +58,11 @@ class DeleteOptionsBottomSheet : BottomSheetDialogFragment(), View.OnClickListen
|
|||||||
if (recipient.isLocalNumber) {
|
if (recipient.isLocalNumber) {
|
||||||
binding.deleteForEveryoneTextView.text =
|
binding.deleteForEveryoneTextView.text =
|
||||||
getString(R.string.clearMessagesForMe)
|
getString(R.string.clearMessagesForMe)
|
||||||
} else if (!recipient.isGroupRecipient && !contact.isNullOrEmpty()) {
|
} else if (!recipient.isGroupOrCommunityRecipient && !contact.isNullOrEmpty()) {
|
||||||
binding.deleteForEveryoneTextView.text =
|
binding.deleteForEveryoneTextView.text =
|
||||||
resources.getString(R.string.clearMessagesForEveryone)
|
resources.getString(R.string.clearMessagesForEveryone)
|
||||||
}
|
}
|
||||||
binding.deleteForEveryoneTextView.isVisible = !recipient.isLegacyClosedGroupRecipient
|
binding.deleteForEveryoneTextView.isVisible = !recipient.isLegacyGroupRecipient
|
||||||
binding.deleteForMeTextView.setOnClickListener(this)
|
binding.deleteForMeTextView.setOnClickListener(this)
|
||||||
binding.deleteForEveryoneTextView.setOnClickListener(this)
|
binding.deleteForEveryoneTextView.setOnClickListener(this)
|
||||||
binding.cancelTextView.setOnClickListener(this)
|
binding.cancelTextView.setOnClickListener(this)
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
package org.thoughtcrime.securesms.conversation.v2.dialogs
|
package org.thoughtcrime.securesms.conversation.v2.dialogs
|
||||||
|
|
||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
import android.graphics.Typeface
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.Spannable
|
|
||||||
import android.text.SpannableStringBuilder
|
|
||||||
import android.text.style.StyleSpan
|
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import com.squareup.phrase.Phrase
|
import com.squareup.phrase.Phrase
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
@ -39,8 +35,8 @@ class AutoDownloadDialog(private val threadRecipient: Recipient,
|
|||||||
|
|
||||||
val displayName = when {
|
val displayName = when {
|
||||||
threadRecipient.isCommunityRecipient -> storage.getOpenGroup(threadId)?.name ?: "UNKNOWN"
|
threadRecipient.isCommunityRecipient -> storage.getOpenGroup(threadId)?.name ?: "UNKNOWN"
|
||||||
threadRecipient.isLegacyClosedGroupRecipient -> storage.getGroup(threadRecipient.address.toGroupString())?.title ?: "UNKNOWN"
|
threadRecipient.isLegacyGroupRecipient -> storage.getGroup(threadRecipient.address.toGroupString())?.title ?: "UNKNOWN"
|
||||||
threadRecipient.isClosedGroupV2Recipient -> threadRecipient.name ?: "UNKNOWN"
|
threadRecipient.isGroupV2Recipient -> threadRecipient.name ?: "UNKNOWN"
|
||||||
else -> storage.getContactWithAccountID(threadRecipient.address.serialize())?.displayName(Contact.ContactContext.REGULAR) ?: "UNKNOWN"
|
else -> storage.getContactWithAccountID(threadRecipient.address.serialize())?.displayName(Contact.ContactContext.REGULAR) ?: "UNKNOWN"
|
||||||
}
|
}
|
||||||
title(getString(R.string.attachmentsAutoDownloadModalTitle))
|
title(getString(R.string.attachmentsAutoDownloadModalTitle))
|
||||||
|
@ -85,11 +85,11 @@ class MentionViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val memberIDs = when {
|
val memberIDs = when {
|
||||||
recipient.isLegacyClosedGroupRecipient -> {
|
recipient.isLegacyGroupRecipient -> {
|
||||||
groupDatabase.getGroupMemberAddresses(recipient.address.toGroupString(), false)
|
groupDatabase.getGroupMemberAddresses(recipient.address.toGroupString(), false)
|
||||||
.map { it.serialize() }
|
.map { it.serialize() }
|
||||||
}
|
}
|
||||||
recipient.isClosedGroupV2Recipient -> {
|
recipient.isGroupV2Recipient -> {
|
||||||
storage.getMembers(recipient.address.serialize()).map { it.sessionId }
|
storage.getMembers(recipient.address.serialize()).map { it.sessionId }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@ import org.session.libsession.messaging.utilities.SodiumUtilities
|
|||||||
import org.session.libsession.utilities.TextSecurePreferences
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
import org.session.libsignal.utilities.IdPrefix
|
import org.session.libsignal.utilities.IdPrefix
|
||||||
import org.session.libsignal.utilities.AccountId
|
import org.session.libsignal.utilities.AccountId
|
||||||
import org.session.libsignal.utilities.Log
|
|
||||||
import org.thoughtcrime.securesms.conversation.v2.ConversationAdapter
|
import org.thoughtcrime.securesms.conversation.v2.ConversationAdapter
|
||||||
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord
|
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord
|
||||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||||
@ -64,7 +63,7 @@ class ConversationActionModeCallback(private val adapter: ConversationAdapter, p
|
|||||||
menu.findItem(R.id.menu_context_copy).isVisible = !containsControlMessage && hasText
|
menu.findItem(R.id.menu_context_copy).isVisible = !containsControlMessage && hasText
|
||||||
// Copy Account ID
|
// Copy Account ID
|
||||||
menu.findItem(R.id.menu_context_copy_public_key).isVisible =
|
menu.findItem(R.id.menu_context_copy_public_key).isVisible =
|
||||||
(thread.isGroupRecipient && !thread.isCommunityRecipient && selectedItems.size == 1 && firstMessage.individualRecipient.address.toString() != userPublicKey)
|
(thread.isGroupOrCommunityRecipient && !thread.isCommunityRecipient && selectedItems.size == 1 && firstMessage.individualRecipient.address.toString() != userPublicKey)
|
||||||
// Message detail
|
// Message detail
|
||||||
menu.findItem(R.id.menu_message_details).isVisible = selectedItems.size == 1
|
menu.findItem(R.id.menu_message_details).isVisible = selectedItems.size == 1
|
||||||
// Resend
|
// Resend
|
||||||
|
@ -44,7 +44,6 @@ import org.thoughtcrime.securesms.calls.WebRtcCallActivity
|
|||||||
import org.thoughtcrime.securesms.contacts.SelectContactsActivity
|
import org.thoughtcrime.securesms.contacts.SelectContactsActivity
|
||||||
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
|
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
|
||||||
import org.thoughtcrime.securesms.conversation.v2.utilities.NotificationUtils
|
import org.thoughtcrime.securesms.conversation.v2.utilities.NotificationUtils
|
||||||
import org.thoughtcrime.securesms.database.Storage
|
|
||||||
import org.thoughtcrime.securesms.dependencies.ConfigFactory
|
import org.thoughtcrime.securesms.dependencies.ConfigFactory
|
||||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
||||||
import org.thoughtcrime.securesms.groups.EditGroupActivity
|
import org.thoughtcrime.securesms.groups.EditGroupActivity
|
||||||
@ -75,7 +74,7 @@ object ConversationMenuHelper {
|
|||||||
// Base menu (options that should always be present)
|
// Base menu (options that should always be present)
|
||||||
inflater.inflate(R.menu.menu_conversation, menu)
|
inflater.inflate(R.menu.menu_conversation, menu)
|
||||||
// Expiring messages
|
// Expiring messages
|
||||||
if (!isCommunity && (thread.hasApprovedMe() || thread.isLegacyClosedGroupRecipient || thread.isLocalNumber)) {
|
if (!isCommunity && (thread.hasApprovedMe() || thread.isLegacyGroupRecipient || thread.isLocalNumber)) {
|
||||||
inflater.inflate(R.menu.menu_conversation_expiration, menu)
|
inflater.inflate(R.menu.menu_conversation_expiration, menu)
|
||||||
}
|
}
|
||||||
// One-on-one chat menu allows copying the account id
|
// One-on-one chat menu allows copying the account id
|
||||||
@ -91,12 +90,12 @@ object ConversationMenuHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// (Legacy) Closed group menu (options that should only be present in closed groups)
|
// (Legacy) Closed group menu (options that should only be present in closed groups)
|
||||||
if (thread.isLegacyClosedGroupRecipient) {
|
if (thread.isLegacyGroupRecipient) {
|
||||||
inflater.inflate(R.menu.menu_conversation_legacy_group, menu)
|
inflater.inflate(R.menu.menu_conversation_legacy_group, menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Groups v2 menu
|
// Groups v2 menu
|
||||||
if (thread.isClosedGroupV2Recipient) {
|
if (thread.isGroupV2Recipient) {
|
||||||
val hasAdminKey = configFactory.withUserConfigs { it.userGroups.getClosedGroup(thread.address.serialize())?.hasAdminKey() }
|
val hasAdminKey = configFactory.withUserConfigs { it.userGroups.getClosedGroup(thread.address.serialize())?.hasAdminKey() }
|
||||||
if (hasAdminKey == true) {
|
if (hasAdminKey == true) {
|
||||||
inflater.inflate(R.menu.menu_conversation_groups_v2_admin, menu)
|
inflater.inflate(R.menu.menu_conversation_groups_v2_admin, menu)
|
||||||
@ -116,7 +115,7 @@ object ConversationMenuHelper {
|
|||||||
inflater.inflate(R.menu.menu_conversation_unmuted, menu)
|
inflater.inflate(R.menu.menu_conversation_unmuted, menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thread.isGroupRecipient && !thread.isMuted) {
|
if (thread.isGroupOrCommunityRecipient && !thread.isMuted) {
|
||||||
inflater.inflate(R.menu.menu_conversation_notification_settings, menu)
|
inflater.inflate(R.menu.menu_conversation_notification_settings, menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,7 +259,7 @@ object ConversationMenuHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (icon == null) {
|
if (icon == null) {
|
||||||
icon = IconCompat.createWithResource(context, if (thread.isGroupRecipient) R.mipmap.ic_group_shortcut else R.mipmap.ic_person_shortcut)
|
icon = IconCompat.createWithResource(context, if (thread.isGroupOrCommunityRecipient) R.mipmap.ic_group_shortcut else R.mipmap.ic_person_shortcut)
|
||||||
}
|
}
|
||||||
return icon
|
return icon
|
||||||
}
|
}
|
||||||
@ -319,11 +318,11 @@ object ConversationMenuHelper {
|
|||||||
|
|
||||||
private fun editClosedGroup(context: Context, thread: Recipient) {
|
private fun editClosedGroup(context: Context, thread: Recipient) {
|
||||||
when {
|
when {
|
||||||
thread.isClosedGroupV2Recipient -> {
|
thread.isGroupV2Recipient -> {
|
||||||
context.startActivity(EditGroupActivity.createIntent(context, thread.address.serialize()))
|
context.startActivity(EditGroupActivity.createIntent(context, thread.address.serialize()))
|
||||||
}
|
}
|
||||||
|
|
||||||
thread.isLegacyClosedGroupRecipient -> {
|
thread.isLegacyGroupRecipient -> {
|
||||||
val intent = Intent(context, EditLegacyGroupActivity::class.java)
|
val intent = Intent(context, EditLegacyGroupActivity::class.java)
|
||||||
val groupID: String = thread.address.toGroupString()
|
val groupID: String = thread.address.toGroupString()
|
||||||
intent.putExtra(groupIDKey, groupID)
|
intent.putExtra(groupIDKey, groupID)
|
||||||
@ -341,7 +340,7 @@ object ConversationMenuHelper {
|
|||||||
groupManager: GroupManagerV2,
|
groupManager: GroupManagerV2,
|
||||||
): ReceiveChannel<Unit>? {
|
): ReceiveChannel<Unit>? {
|
||||||
when {
|
when {
|
||||||
thread.isLegacyClosedGroupRecipient -> {
|
thread.isLegacyGroupRecipient -> {
|
||||||
val group = DatabaseComponent.get(context).groupDatabase().getGroup(thread.address.toGroupString()).orNull()
|
val group = DatabaseComponent.get(context).groupDatabase().getGroup(thread.address.toGroupString()).orNull()
|
||||||
val admins = group.admins
|
val admins = group.admins
|
||||||
val accountID = TextSecurePreferences.getLocalNumber(context)
|
val accountID = TextSecurePreferences.getLocalNumber(context)
|
||||||
@ -364,7 +363,7 @@ object ConversationMenuHelper {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
thread.isClosedGroupV2Recipient -> {
|
thread.isGroupV2Recipient -> {
|
||||||
val accountId = AccountId(thread.address.serialize())
|
val accountId = AccountId(thread.address.serialize())
|
||||||
val group = configFactory.withUserConfigs { it.userGroups.getClosedGroup(accountId.hexString) } ?: return null
|
val group = configFactory.withUserConfigs { it.userGroups.getClosedGroup(accountId.hexString) } ?: return null
|
||||||
val name = configFactory.withGroupConfigs(accountId) {
|
val name = configFactory.withGroupConfigs(accountId) {
|
||||||
|
@ -4,7 +4,6 @@ import android.Manifest
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.util.Log
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
@ -12,7 +11,6 @@ import androidx.core.content.res.ResourcesCompat
|
|||||||
import androidx.core.view.isGone
|
import androidx.core.view.isGone
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.squareup.phrase.Phrase
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import network.loki.messenger.databinding.ViewControlMessageBinding
|
import network.loki.messenger.databinding.ViewControlMessageBinding
|
||||||
@ -78,7 +76,7 @@ class ControlMessageView : LinearLayout {
|
|||||||
|
|
||||||
val threadRecipient = DatabaseComponent.get(context).threadDatabase().getRecipientForThreadId(message.threadId)
|
val threadRecipient = DatabaseComponent.get(context).threadDatabase().getRecipientForThreadId(message.threadId)
|
||||||
|
|
||||||
if (threadRecipient?.isClosedGroupV2Recipient == true) {
|
if (threadRecipient?.isGroupV2Recipient == true) {
|
||||||
expirationTimerView.setTimerIcon()
|
expirationTimerView.setTimerIcon()
|
||||||
} else {
|
} else {
|
||||||
expirationTimerView.setExpirationTime(message.expireStarted, message.expiresIn)
|
expirationTimerView.setExpirationTime(message.expireStarted, message.expiresIn)
|
||||||
@ -87,7 +85,7 @@ class ControlMessageView : LinearLayout {
|
|||||||
followSetting.isVisible = ExpirationConfiguration.isNewConfigEnabled
|
followSetting.isVisible = ExpirationConfiguration.isNewConfigEnabled
|
||||||
&& !message.isOutgoing
|
&& !message.isOutgoing
|
||||||
&& message.expiryMode != (MessagingModuleConfiguration.shared.storage.getExpirationConfiguration(message.threadId)?.expiryMode ?: ExpiryMode.NONE)
|
&& message.expiryMode != (MessagingModuleConfiguration.shared.storage.getExpirationConfiguration(message.threadId)?.expiryMode ?: ExpiryMode.NONE)
|
||||||
&& threadRecipient?.isGroupRecipient != true
|
&& threadRecipient?.isGroupOrCommunityRecipient != true
|
||||||
|
|
||||||
if (followSetting.isVisible) {
|
if (followSetting.isVisible) {
|
||||||
binding.controlContentView.setOnClickListener { disappearingMessages.showFollowSettingDialog(context, message) }
|
binding.controlContentView.setOnClickListener { disappearingMessages.showFollowSettingDialog(context, message) }
|
||||||
|
@ -16,7 +16,6 @@ import android.view.MotionEvent
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import android.widget.LinearLayout
|
|
||||||
import androidx.annotation.ColorInt
|
import androidx.annotation.ColorInt
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
@ -61,7 +60,6 @@ import org.thoughtcrime.securesms.groups.OpenGroupManager
|
|||||||
import org.thoughtcrime.securesms.home.UserDetailsBottomSheet
|
import org.thoughtcrime.securesms.home.UserDetailsBottomSheet
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.bumptech.glide.RequestManager
|
import com.bumptech.glide.RequestManager
|
||||||
import org.session.libsignal.utilities.Log
|
|
||||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
||||||
import org.thoughtcrime.securesms.util.DateUtils
|
import org.thoughtcrime.securesms.util.DateUtils
|
||||||
import org.thoughtcrime.securesms.util.disableClipping
|
import org.thoughtcrime.securesms.util.disableClipping
|
||||||
@ -155,14 +153,14 @@ class VisibleMessageView : FrameLayout {
|
|||||||
replyDisabled = message.isOpenGroupInvitation
|
replyDisabled = message.isOpenGroupInvitation
|
||||||
val threadID = message.threadId
|
val threadID = message.threadId
|
||||||
val thread = threadDb.getRecipientForThreadId(threadID) ?: return
|
val thread = threadDb.getRecipientForThreadId(threadID) ?: return
|
||||||
val isGroupThread = thread.isGroupRecipient
|
val isGroupThread = thread.isGroupOrCommunityRecipient
|
||||||
val isStartOfMessageCluster = isStartOfMessageCluster(message, previous, isGroupThread)
|
val isStartOfMessageCluster = isStartOfMessageCluster(message, previous, isGroupThread)
|
||||||
val isEndOfMessageCluster = isEndOfMessageCluster(message, next, isGroupThread)
|
val isEndOfMessageCluster = isEndOfMessageCluster(message, next, isGroupThread)
|
||||||
// Show profile picture and sender name if this is a group thread AND the message is incoming
|
// Show profile picture and sender name if this is a group thread AND the message is incoming
|
||||||
binding.moderatorIconImageView.isVisible = false
|
binding.moderatorIconImageView.isVisible = false
|
||||||
binding.profilePictureView.visibility = when {
|
binding.profilePictureView.visibility = when {
|
||||||
thread.isGroupRecipient && !message.isOutgoing && isEndOfMessageCluster -> View.VISIBLE
|
thread.isGroupOrCommunityRecipient && !message.isOutgoing && isEndOfMessageCluster -> View.VISIBLE
|
||||||
thread.isGroupRecipient -> View.INVISIBLE
|
thread.isGroupOrCommunityRecipient -> View.INVISIBLE
|
||||||
else -> View.GONE
|
else -> View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ object ResendMessageUtilities {
|
|||||||
message.text = messageRecord.body
|
message.text = messageRecord.body
|
||||||
}
|
}
|
||||||
message.sentTimestamp = messageRecord.timestamp
|
message.sentTimestamp = messageRecord.timestamp
|
||||||
if (recipient.isGroupRecipient) {
|
if (recipient.isGroupOrCommunityRecipient) {
|
||||||
message.groupPublicKey = recipient.address.toGroupString()
|
message.groupPublicKey = recipient.address.toGroupString()
|
||||||
} else {
|
} else {
|
||||||
message.recipient = messageRecord.recipient.address.serialize()
|
message.recipient = messageRecord.recipient.address.serialize()
|
||||||
|
@ -162,7 +162,7 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
|
|||||||
val ourAddress = messageId.address
|
val ourAddress = messageId.address
|
||||||
val columnName =
|
val columnName =
|
||||||
if (deliveryReceipt) DELIVERY_RECEIPT_COUNT else READ_RECEIPT_COUNT
|
if (deliveryReceipt) DELIVERY_RECEIPT_COUNT else READ_RECEIPT_COUNT
|
||||||
if (ourAddress.equals(theirAddress) || theirAddress.isGroup) {
|
if (ourAddress.equals(theirAddress) || theirAddress.isGroupOrCommunity) {
|
||||||
val id = cursor.getLong(cursor.getColumnIndexOrThrow(ID))
|
val id = cursor.getLong(cursor.getColumnIndexOrThrow(ID))
|
||||||
val threadId = cursor.getLong(cursor.getColumnIndexOrThrow(THREAD_ID))
|
val threadId = cursor.getLong(cursor.getColumnIndexOrThrow(THREAD_ID))
|
||||||
val status =
|
val status =
|
||||||
@ -779,7 +779,7 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
|
|||||||
contentValues,
|
contentValues,
|
||||||
insertListener,
|
insertListener,
|
||||||
)
|
)
|
||||||
if (message.recipient.address.isGroup) {
|
if (message.recipient.address.isGroupOrCommunity) {
|
||||||
val members = get(context).groupDatabase()
|
val members = get(context).groupDatabase()
|
||||||
.getGroupMembers(message.recipient.address.toGroupString(), false)
|
.getGroupMembers(message.recipient.address.toGroupString(), false)
|
||||||
val receiptDatabase = get(context).groupReceiptDatabase()
|
val receiptDatabase = get(context).groupReceiptDatabase()
|
||||||
|
@ -67,7 +67,6 @@ import org.session.libsession.utilities.recipients.Recipient
|
|||||||
import org.session.libsession.utilities.recipients.Recipient.DisappearingState
|
import org.session.libsession.utilities.recipients.Recipient.DisappearingState
|
||||||
import org.session.libsession.utilities.recipients.MessageType
|
import org.session.libsession.utilities.recipients.MessageType
|
||||||
import org.session.libsession.utilities.recipients.getType
|
import org.session.libsession.utilities.recipients.getType
|
||||||
import org.session.libsignal.crypto.ecc.DjbECPrivateKey
|
|
||||||
import org.session.libsignal.crypto.ecc.DjbECPublicKey
|
import org.session.libsignal.crypto.ecc.DjbECPublicKey
|
||||||
import org.session.libsignal.crypto.ecc.ECKeyPair
|
import org.session.libsignal.crypto.ecc.ECKeyPair
|
||||||
import org.session.libsignal.messages.SignalServiceAttachmentPointer
|
import org.session.libsignal.messages.SignalServiceAttachmentPointer
|
||||||
@ -134,73 +133,73 @@ open class Storage @Inject constructor(
|
|||||||
val localUserAddress = getUserPublicKey() ?: return
|
val localUserAddress = getUserPublicKey() ?: return
|
||||||
if (!getRecipientApproved(address) && localUserAddress != address.serialize()) return // don't store unapproved / message requests
|
if (!getRecipientApproved(address) && localUserAddress != address.serialize()) return // don't store unapproved / message requests
|
||||||
|
|
||||||
if (address.isGroup) {
|
when {
|
||||||
when {
|
address.isLegacyGroup -> {
|
||||||
address.isLegacyClosedGroup -> {
|
val accountId = GroupUtil.doubleDecodeGroupId(address.serialize())
|
||||||
val accountId = GroupUtil.doubleDecodeGroupId(address.serialize())
|
val closedGroup = getGroup(address.toGroupString())
|
||||||
val closedGroup = getGroup(address.toGroupString())
|
if (closedGroup != null && closedGroup.isActive) {
|
||||||
if (closedGroup != null && closedGroup.isActive) {
|
|
||||||
configFactory.withMutableUserConfigs { configs ->
|
|
||||||
val legacyGroup = configs.userGroups.getOrConstructLegacyGroupInfo(accountId)
|
|
||||||
configs.userGroups.set(legacyGroup)
|
|
||||||
val newVolatileParams = configs.convoInfoVolatile.getOrConstructLegacyGroup(accountId).copy(
|
|
||||||
lastRead = clock.currentTimeMills(),
|
|
||||||
)
|
|
||||||
configs.convoInfoVolatile.set(newVolatileParams)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
address.isClosedGroupV2 -> {
|
|
||||||
configFactory.withMutableUserConfigs { configs ->
|
configFactory.withMutableUserConfigs { configs ->
|
||||||
val accountId = address.serialize()
|
val legacyGroup = configs.userGroups.getOrConstructLegacyGroupInfo(accountId)
|
||||||
configs.userGroups.getClosedGroup(accountId)
|
configs.userGroups.set(legacyGroup)
|
||||||
?: return@withMutableUserConfigs Log.d("Closed group doesn't exist locally", NullPointerException())
|
val newVolatileParams = configs.convoInfoVolatile.getOrConstructLegacyGroup(accountId).copy(
|
||||||
|
lastRead = clock.currentTimeMills(),
|
||||||
configs.convoInfoVolatile.getOrConstructClosedGroup(accountId)
|
)
|
||||||
|
configs.convoInfoVolatile.set(newVolatileParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
address.isCommunity -> {
|
|
||||||
// these should be added on the group join / group info fetch
|
|
||||||
Log.w("Loki", "Thread created called for open group address, not adding any extra information")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (address.isContact) {
|
address.isGroupV2 -> {
|
||||||
// non-standard contact prefixes: 15, 00 etc shouldn't be stored in config
|
|
||||||
if (AccountId(address.serialize()).prefix != IdPrefix.STANDARD) return
|
|
||||||
// don't update our own address into the contacts DB
|
|
||||||
if (getUserPublicKey() != address.serialize()) {
|
|
||||||
configFactory.withMutableUserConfigs { configs ->
|
configFactory.withMutableUserConfigs { configs ->
|
||||||
configs.contacts.upsertContact(address.serialize()) {
|
val accountId = address.serialize()
|
||||||
priority = PRIORITY_VISIBLE
|
configs.userGroups.getClosedGroup(accountId)
|
||||||
|
?: return@withMutableUserConfigs Log.d("Closed group doesn't exist locally", NullPointerException())
|
||||||
|
|
||||||
|
configs.convoInfoVolatile.getOrConstructClosedGroup(accountId)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
address.isCommunity -> {
|
||||||
|
// these should be added on the group join / group info fetch
|
||||||
|
Log.w("Loki", "Thread created called for open group address, not adding any extra information")
|
||||||
|
}
|
||||||
|
|
||||||
|
address.isContact -> {
|
||||||
|
// non-standard contact prefixes: 15, 00 etc shouldn't be stored in config
|
||||||
|
if (AccountId(address.serialize()).prefix != IdPrefix.STANDARD) return
|
||||||
|
// don't update our own address into the contacts DB
|
||||||
|
if (getUserPublicKey() != address.serialize()) {
|
||||||
|
configFactory.withMutableUserConfigs { configs ->
|
||||||
|
configs.contacts.upsertContact(address.serialize()) {
|
||||||
|
priority = PRIORITY_VISIBLE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
configFactory.withMutableUserConfigs { configs ->
|
||||||
|
configs.userProfile.setNtsPriority(PRIORITY_VISIBLE)
|
||||||
|
}
|
||||||
|
|
||||||
|
threadDatabase.setHasSent(threadId, true)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
configFactory.withMutableUserConfigs { configs ->
|
configFactory.withMutableUserConfigs { configs ->
|
||||||
configs.userProfile.setNtsPriority(PRIORITY_VISIBLE)
|
configs.convoInfoVolatile.getOrConstructOneToOne(address.serialize())
|
||||||
}
|
}
|
||||||
|
|
||||||
threadDatabase.setHasSent(threadId, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
configFactory.withMutableUserConfigs { configs ->
|
|
||||||
configs.convoInfoVolatile.getOrConstructOneToOne(address.serialize())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun threadDeleted(address: Address, threadId: Long) {
|
override fun threadDeleted(address: Address, threadId: Long) {
|
||||||
configFactory.withMutableUserConfigs { configs ->
|
configFactory.withMutableUserConfigs { configs ->
|
||||||
if (address.isGroup) {
|
if (address.isGroupOrCommunity) {
|
||||||
if (address.isLegacyClosedGroup) {
|
if (address.isLegacyGroup) {
|
||||||
val accountId = GroupUtil.doubleDecodeGroupId(address.serialize())
|
val accountId = GroupUtil.doubleDecodeGroupId(address.serialize())
|
||||||
configs.convoInfoVolatile.eraseLegacyClosedGroup(accountId)
|
configs.convoInfoVolatile.eraseLegacyClosedGroup(accountId)
|
||||||
configs.userGroups.eraseLegacyGroup(accountId)
|
configs.userGroups.eraseLegacyGroup(accountId)
|
||||||
} else if (address.isCommunity) {
|
} else if (address.isCommunity) {
|
||||||
// these should be removed in the group leave / handling new configs
|
// these should be removed in the group leave / handling new configs
|
||||||
Log.w("Loki", "Thread delete called for open group address, expecting to be handled elsewhere")
|
Log.w("Loki", "Thread delete called for open group address, expecting to be handled elsewhere")
|
||||||
} else if (address.isClosedGroupV2) {
|
} else if (address.isGroupV2) {
|
||||||
Log.w("Loki", "Thread delete called for closed group address, expecting to be handled elsewhere")
|
Log.w("Loki", "Thread delete called for closed group address, expecting to be handled elsewhere")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -327,17 +326,17 @@ open class Storage @Inject constructor(
|
|||||||
getRecipientForThread(threadId)?.let { recipient ->
|
getRecipientForThread(threadId)?.let { recipient ->
|
||||||
val currentLastRead = threadDb.getLastSeenAndHasSent(threadId).first()
|
val currentLastRead = threadDb.getLastSeenAndHasSent(threadId).first()
|
||||||
// don't set the last read in the volatile if we didn't set it in the DB
|
// don't set the last read in the volatile if we didn't set it in the DB
|
||||||
if (!threadDb.markAllAsRead(threadId, recipient.isGroupRecipient, lastSeenTime, force) && !force) return
|
if (!threadDb.markAllAsRead(threadId, recipient.isGroupOrCommunityRecipient, lastSeenTime, force) && !force) return
|
||||||
|
|
||||||
// don't process configs for inbox recipients
|
// don't process configs for inbox recipients
|
||||||
if (recipient.isOpenGroupInboxRecipient) return
|
if (recipient.isCommunityInboxRecipient) return
|
||||||
|
|
||||||
configFactory.withMutableUserConfigs { configs ->
|
configFactory.withMutableUserConfigs { configs ->
|
||||||
val config = configs.convoInfoVolatile
|
val config = configs.convoInfoVolatile
|
||||||
val convo = when {
|
val convo = when {
|
||||||
// recipient closed group
|
// recipient closed group
|
||||||
recipient.isLegacyClosedGroupRecipient -> config.getOrConstructLegacyGroup(GroupUtil.doubleDecodeGroupId(recipient.address.serialize()))
|
recipient.isLegacyGroupRecipient -> config.getOrConstructLegacyGroup(GroupUtil.doubleDecodeGroupId(recipient.address.serialize()))
|
||||||
recipient.isClosedGroupV2Recipient -> config.getOrConstructClosedGroup(recipient.address.serialize())
|
recipient.isGroupV2Recipient -> config.getOrConstructClosedGroup(recipient.address.serialize())
|
||||||
// recipient is open group
|
// recipient is open group
|
||||||
recipient.isCommunityRecipient -> {
|
recipient.isCommunityRecipient -> {
|
||||||
val openGroupJoinUrl = getOpenGroup(threadId)?.joinURL ?: return@withMutableUserConfigs
|
val openGroupJoinUrl = getOpenGroup(threadId)?.joinURL ?: return@withMutableUserConfigs
|
||||||
@ -409,7 +408,7 @@ open class Storage @Inject constructor(
|
|||||||
senderAddress
|
senderAddress
|
||||||
}
|
}
|
||||||
val targetRecipient = Recipient.from(context, targetAddress, false)
|
val targetRecipient = Recipient.from(context, targetAddress, false)
|
||||||
if (!targetRecipient.isGroupRecipient) {
|
if (!targetRecipient.isGroupOrCommunityRecipient) {
|
||||||
if (isUserSender || isUserBlindedSender) {
|
if (isUserSender || isUserBlindedSender) {
|
||||||
setRecipientApproved(targetRecipient, true)
|
setRecipientApproved(targetRecipient, true)
|
||||||
} else {
|
} else {
|
||||||
@ -1390,9 +1389,9 @@ open class Storage @Inject constructor(
|
|||||||
configs.contacts.upsertContact(threadRecipient.address.serialize()) {
|
configs.contacts.upsertContact(threadRecipient.address.serialize()) {
|
||||||
priority = if (isPinned) PRIORITY_PINNED else PRIORITY_VISIBLE
|
priority = if (isPinned) PRIORITY_PINNED else PRIORITY_VISIBLE
|
||||||
}
|
}
|
||||||
} else if (threadRecipient.isGroupRecipient) {
|
} else if (threadRecipient.isGroupOrCommunityRecipient) {
|
||||||
when {
|
when {
|
||||||
threadRecipient.isLegacyClosedGroupRecipient -> {
|
threadRecipient.isLegacyGroupRecipient -> {
|
||||||
threadRecipient.address.serialize()
|
threadRecipient.address.serialize()
|
||||||
.let(GroupUtil::doubleDecodeGroupId)
|
.let(GroupUtil::doubleDecodeGroupId)
|
||||||
.let(configs.userGroups::getOrConstructLegacyGroupInfo)
|
.let(configs.userGroups::getOrConstructLegacyGroupInfo)
|
||||||
@ -1400,7 +1399,7 @@ open class Storage @Inject constructor(
|
|||||||
.let(configs.userGroups::set)
|
.let(configs.userGroups::set)
|
||||||
}
|
}
|
||||||
|
|
||||||
threadRecipient.isClosedGroupV2Recipient -> {
|
threadRecipient.isGroupV2Recipient -> {
|
||||||
val newGroupInfo = configs.userGroups
|
val newGroupInfo = configs.userGroups
|
||||||
.getOrConstructClosedGroup(threadRecipient.address.serialize())
|
.getOrConstructClosedGroup(threadRecipient.address.serialize())
|
||||||
.copy(priority = if (isPinned) PRIORITY_PINNED else PRIORITY_VISIBLE)
|
.copy(priority = if (isPinned) PRIORITY_PINNED else PRIORITY_VISIBLE)
|
||||||
@ -1586,8 +1585,8 @@ open class Storage @Inject constructor(
|
|||||||
val recipient = reader.current.recipient
|
val recipient = reader.current.recipient
|
||||||
val address = recipient.address.serialize()
|
val address = recipient.address.serialize()
|
||||||
val blindedId = when {
|
val blindedId = when {
|
||||||
recipient.isGroupRecipient -> null
|
recipient.isGroupOrCommunityRecipient -> null
|
||||||
recipient.isOpenGroupInboxRecipient -> GroupUtil.getDecodedOpenGroupInboxAccountId(address)
|
recipient.isCommunityInboxRecipient -> GroupUtil.getDecodedOpenGroupInboxAccountId(address)
|
||||||
else -> address.takeIf { AccountId(it).prefix == IdPrefix.BLINDED }
|
else -> address.takeIf { AccountId(it).prefix == IdPrefix.BLINDED }
|
||||||
} ?: continue
|
} ?: continue
|
||||||
mappingDb.getBlindedIdMapping(blindedId).firstOrNull()?.let {
|
mappingDb.getBlindedIdMapping(blindedId).firstOrNull()?.let {
|
||||||
@ -1668,7 +1667,7 @@ open class Storage @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getRecipientApproved(address: Address): Boolean {
|
override fun getRecipientApproved(address: Address): Boolean {
|
||||||
return address.isClosedGroupV2 || recipientDatabase.getApproved(address)
|
return address.isGroupV2 || recipientDatabase.getApproved(address)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setRecipientApproved(recipient: Recipient, approved: Boolean) {
|
override fun setRecipientApproved(recipient: Recipient, approved: Boolean) {
|
||||||
@ -1864,14 +1863,14 @@ open class Storage @Inject constructor(
|
|||||||
recipient.address.serialize().takeIf { it.startsWith(IdPrefix.STANDARD.value) }
|
recipient.address.serialize().takeIf { it.startsWith(IdPrefix.STANDARD.value) }
|
||||||
?.let { configFactory.withUserConfigs { configs -> configs.contacts.get(it)?.expiryMode } }
|
?.let { configFactory.withUserConfigs { configs -> configs.contacts.get(it)?.expiryMode } }
|
||||||
}
|
}
|
||||||
recipient.isClosedGroupV2Recipient -> {
|
recipient.isGroupV2Recipient -> {
|
||||||
configFactory.withGroupConfigs(AccountId(recipient.address.serialize())) { configs ->
|
configFactory.withGroupConfigs(AccountId(recipient.address.serialize())) { configs ->
|
||||||
configs.groupInfo.getExpiryTimer()
|
configs.groupInfo.getExpiryTimer()
|
||||||
}.let {
|
}.let {
|
||||||
if (it == 0L) ExpiryMode.NONE else ExpiryMode.AfterSend(it)
|
if (it == 0L) ExpiryMode.NONE else ExpiryMode.AfterSend(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
recipient.isLegacyClosedGroupRecipient -> {
|
recipient.isLegacyGroupRecipient -> {
|
||||||
// read it from group config if exists
|
// read it from group config if exists
|
||||||
GroupUtil.doubleDecodeGroupId(recipient.address.serialize())
|
GroupUtil.doubleDecodeGroupId(recipient.address.serialize())
|
||||||
.let { id -> configFactory.withUserConfigs { it.userGroups.getLegacyGroupInfo(id) } }
|
.let { id -> configFactory.withUserConfigs { it.userGroups.getLegacyGroupInfo(id) } }
|
||||||
@ -1899,7 +1898,7 @@ open class Storage @Inject constructor(
|
|||||||
lokiAPIDatabase.setLastLegacySenderAddress(recipient.address.serialize(), null)
|
lokiAPIDatabase.setLastLegacySenderAddress(recipient.address.serialize(), null)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recipient.isLegacyClosedGroupRecipient) {
|
if (recipient.isLegacyGroupRecipient) {
|
||||||
val groupPublicKey = GroupUtil.addressToGroupAccountId(recipient.address)
|
val groupPublicKey = GroupUtil.addressToGroupAccountId(recipient.address)
|
||||||
|
|
||||||
configFactory.withMutableUserConfigs {
|
configFactory.withMutableUserConfigs {
|
||||||
@ -1907,7 +1906,7 @@ open class Storage @Inject constructor(
|
|||||||
?.copy(disappearingTimer = expiryMode.expirySeconds) ?: return@withMutableUserConfigs
|
?.copy(disappearingTimer = expiryMode.expirySeconds) ?: return@withMutableUserConfigs
|
||||||
it.userGroups.set(groupInfo)
|
it.userGroups.set(groupInfo)
|
||||||
}
|
}
|
||||||
} else if (recipient.isClosedGroupV2Recipient) {
|
} else if (recipient.isGroupV2Recipient) {
|
||||||
val groupSessionId = AccountId(recipient.address.serialize())
|
val groupSessionId = AccountId(recipient.address.serialize())
|
||||||
configFactory.withMutableGroupConfigs(groupSessionId) { configs ->
|
configFactory.withMutableGroupConfigs(groupSessionId) { configs ->
|
||||||
configs.groupInfo.setExpiryTimer(expiryMode.expirySeconds)
|
configs.groupInfo.setExpiryTimer(expiryMode.expirySeconds)
|
||||||
|
@ -665,7 +665,7 @@ public class ThreadDatabase extends Database {
|
|||||||
threadId = cursor.getLong(cursor.getColumnIndexOrThrow(ID));
|
threadId = cursor.getLong(cursor.getColumnIndexOrThrow(ID));
|
||||||
} else {
|
} else {
|
||||||
DatabaseComponent.get(context).recipientDatabase().setProfileSharing(recipient, true);
|
DatabaseComponent.get(context).recipientDatabase().setProfileSharing(recipient, true);
|
||||||
threadId = createThreadForRecipient(recipient.getAddress(), recipient.isGroupRecipient(), distributionType);
|
threadId = createThreadForRecipient(recipient.getAddress(), recipient.isGroupOrCommunityRecipient(), distributionType);
|
||||||
created = true;
|
created = true;
|
||||||
}
|
}
|
||||||
if (created && updateListener != null) {
|
if (created && updateListener != null) {
|
||||||
|
@ -131,7 +131,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||||||
);
|
);
|
||||||
} else if (isExpirationTimerUpdate()) {
|
} else if (isExpirationTimerUpdate()) {
|
||||||
int seconds = (int) (getExpiresIn() / 1000);
|
int seconds = (int) (getExpiresIn() / 1000);
|
||||||
boolean isGroup = DatabaseComponent.get(context).threadDatabase().getRecipientForThreadId(getThreadId()).isGroupRecipient();
|
boolean isGroup = DatabaseComponent.get(context).threadDatabase().getRecipientForThreadId(getThreadId()).isGroupOrCommunityRecipient();
|
||||||
return new SpannableString(UpdateMessageBuilder.INSTANCE.buildExpirationTimerMessage(context, seconds, isGroup, getIndividualRecipient().getAddress().serialize(), isOutgoing(), getTimestamp(), expireStarted));
|
return new SpannableString(UpdateMessageBuilder.INSTANCE.buildExpirationTimerMessage(context, seconds, isGroup, getIndividualRecipient().getAddress().serialize(), isOutgoing(), getTimestamp(), expireStarted));
|
||||||
} else if (isDataExtractionNotification()) {
|
} else if (isDataExtractionNotification()) {
|
||||||
if (isScreenshotNotification()) return new SpannableString((UpdateMessageBuilder.INSTANCE.buildDataExtractionMessage(context, DataExtractionNotificationInfoMessage.Kind.SCREENSHOT, getIndividualRecipient().getAddress().serialize())));
|
if (isScreenshotNotification()) return new SpannableString((UpdateMessageBuilder.INSTANCE.buildDataExtractionMessage(context, DataExtractionNotificationInfoMessage.Kind.SCREENSHOT, getIndividualRecipient().getAddress().serialize())));
|
||||||
|
@ -545,18 +545,18 @@ private fun MutableConversationVolatileConfig.initFrom(storage: StorageProtocol,
|
|||||||
val (base, room, pubKey) = BaseCommunityInfo.parseFullUrl(openGroup.joinURL) ?: continue
|
val (base, room, pubKey) = BaseCommunityInfo.parseFullUrl(openGroup.joinURL) ?: continue
|
||||||
getOrConstructCommunity(base, room, pubKey)
|
getOrConstructCommunity(base, room, pubKey)
|
||||||
}
|
}
|
||||||
recipient.isClosedGroupV2Recipient -> {
|
recipient.isGroupV2Recipient -> {
|
||||||
// It's probably safe to assume there will never be a case where new closed groups will ever be there before a dump is created...
|
// It's probably safe to assume there will never be a case where new closed groups will ever be there before a dump is created...
|
||||||
// but just in case...
|
// but just in case...
|
||||||
getOrConstructClosedGroup(recipient.address.serialize())
|
getOrConstructClosedGroup(recipient.address.serialize())
|
||||||
}
|
}
|
||||||
recipient.isLegacyClosedGroupRecipient -> {
|
recipient.isLegacyGroupRecipient -> {
|
||||||
val groupPublicKey = GroupUtil.doubleDecodeGroupId(recipient.address.serialize())
|
val groupPublicKey = GroupUtil.doubleDecodeGroupId(recipient.address.serialize())
|
||||||
getOrConstructLegacyGroup(groupPublicKey)
|
getOrConstructLegacyGroup(groupPublicKey)
|
||||||
}
|
}
|
||||||
recipient.isContactRecipient -> {
|
recipient.isContactRecipient -> {
|
||||||
if (recipient.isLocalNumber) null // this is handled by the user profile NTS data
|
if (recipient.isLocalNumber) null // this is handled by the user profile NTS data
|
||||||
else if (recipient.isOpenGroupInboxRecipient) null // specifically exclude
|
else if (recipient.isCommunityInboxRecipient) null // specifically exclude
|
||||||
else if (!recipient.address.serialize().startsWith(IdPrefix.STANDARD.value)) null
|
else if (!recipient.address.serialize().startsWith(IdPrefix.STANDARD.value)) null
|
||||||
else getOrConstructOneToOne(recipient.address.serialize())
|
else getOrConstructOneToOne(recipient.address.serialize())
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ class ConversationOptionsBottomSheet(private val parentContext: Context) : Botto
|
|||||||
if (!this::thread.isInitialized) { return dismiss() }
|
if (!this::thread.isInitialized) { return dismiss() }
|
||||||
val recipient = thread.recipient
|
val recipient = thread.recipient
|
||||||
val isCurrentUserInGroup = group?.members?.map { it.toString() }?.contains(publicKey) ?: false
|
val isCurrentUserInGroup = group?.members?.map { it.toString() }?.contains(publicKey) ?: false
|
||||||
if (!recipient.isGroupRecipient && !recipient.isLocalNumber) {
|
if (!recipient.isGroupOrCommunityRecipient && !recipient.isLocalNumber) {
|
||||||
binding.detailsTextView.visibility = View.VISIBLE
|
binding.detailsTextView.visibility = View.VISIBLE
|
||||||
binding.unblockTextView.visibility = if (recipient.isBlocked) View.VISIBLE else View.GONE
|
binding.unblockTextView.visibility = if (recipient.isBlocked) View.VISIBLE else View.GONE
|
||||||
binding.blockTextView.visibility = if (recipient.isBlocked) View.GONE else View.VISIBLE
|
binding.blockTextView.visibility = if (recipient.isBlocked) View.GONE else View.VISIBLE
|
||||||
@ -78,7 +78,7 @@ class ConversationOptionsBottomSheet(private val parentContext: Context) : Botto
|
|||||||
} else {
|
} else {
|
||||||
binding.detailsTextView.visibility = View.GONE
|
binding.detailsTextView.visibility = View.GONE
|
||||||
}
|
}
|
||||||
binding.copyConversationId.visibility = if (!recipient.isGroupRecipient && !recipient.isLocalNumber) View.VISIBLE else View.GONE
|
binding.copyConversationId.visibility = if (!recipient.isGroupOrCommunityRecipient && !recipient.isLocalNumber) View.VISIBLE else View.GONE
|
||||||
binding.copyConversationId.setOnClickListener(this)
|
binding.copyConversationId.setOnClickListener(this)
|
||||||
binding.copyCommunityUrl.visibility = if (recipient.isCommunityRecipient) View.VISIBLE else View.GONE
|
binding.copyCommunityUrl.visibility = if (recipient.isCommunityRecipient) View.VISIBLE else View.GONE
|
||||||
binding.copyCommunityUrl.setOnClickListener(this)
|
binding.copyCommunityUrl.setOnClickListener(this)
|
||||||
@ -86,18 +86,18 @@ class ConversationOptionsBottomSheet(private val parentContext: Context) : Botto
|
|||||||
binding.muteNotificationsTextView.isVisible = !recipient.isMuted && !recipient.isLocalNumber
|
binding.muteNotificationsTextView.isVisible = !recipient.isMuted && !recipient.isLocalNumber
|
||||||
binding.unMuteNotificationsTextView.setOnClickListener(this)
|
binding.unMuteNotificationsTextView.setOnClickListener(this)
|
||||||
binding.muteNotificationsTextView.setOnClickListener(this)
|
binding.muteNotificationsTextView.setOnClickListener(this)
|
||||||
binding.notificationsTextView.isVisible = recipient.isGroupRecipient && !recipient.isMuted
|
binding.notificationsTextView.isVisible = recipient.isGroupOrCommunityRecipient && !recipient.isMuted
|
||||||
binding.notificationsTextView.setOnClickListener(this)
|
binding.notificationsTextView.setOnClickListener(this)
|
||||||
|
|
||||||
// delete
|
// delete
|
||||||
binding.deleteTextView.apply {
|
binding.deleteTextView.apply {
|
||||||
isVisible = recipient.isContactRecipient || (recipient.isGroupRecipient && !isCurrentUserInGroup)
|
isVisible = recipient.isContactRecipient || (recipient.isGroupOrCommunityRecipient && !isCurrentUserInGroup)
|
||||||
setOnClickListener(this@ConversationOptionsBottomSheet)
|
setOnClickListener(this@ConversationOptionsBottomSheet)
|
||||||
|
|
||||||
// the text and content description will change depending on the type
|
// the text and content description will change depending on the type
|
||||||
when{
|
when{
|
||||||
// groups and communities
|
// groups and communities
|
||||||
recipient.isGroupRecipient -> {
|
recipient.isGroupOrCommunityRecipient -> {
|
||||||
text = context.getString(R.string.leave)
|
text = context.getString(R.string.leave)
|
||||||
contentDescription = context.getString(R.string.AccessibilityId_leave)
|
contentDescription = context.getString(R.string.AccessibilityId_leave)
|
||||||
}
|
}
|
||||||
@ -115,7 +115,7 @@ class ConversationOptionsBottomSheet(private val parentContext: Context) : Botto
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.leaveTextView.isVisible = recipient.isGroupRecipient && isCurrentUserInGroup
|
binding.leaveTextView.isVisible = recipient.isGroupOrCommunityRecipient && isCurrentUserInGroup
|
||||||
binding.leaveTextView.setOnClickListener(this)
|
binding.leaveTextView.setOnClickListener(this)
|
||||||
|
|
||||||
binding.markAllAsReadTextView.isVisible = thread.unreadCount > 0 ||
|
binding.markAllAsReadTextView.isVisible = thread.unreadCount > 0 ||
|
||||||
|
@ -99,7 +99,7 @@ class ConversationView : LinearLayout {
|
|||||||
binding.unreadCountIndicator.isVisible = (unreadCount != 0 && !thread.isRead)
|
binding.unreadCountIndicator.isVisible = (unreadCount != 0 && !thread.isRead)
|
||||||
|| (configFactory.withUserConfigs { it.convoInfoVolatile.getConversationUnread(thread) })
|
|| (configFactory.withUserConfigs { it.convoInfoVolatile.getConversationUnread(thread) })
|
||||||
binding.unreadMentionTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, textSize)
|
binding.unreadMentionTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, textSize)
|
||||||
binding.unreadMentionIndicator.isVisible = (thread.unreadMentionCount != 0 && thread.recipient.address.isGroup)
|
binding.unreadMentionIndicator.isVisible = (thread.unreadMentionCount != 0 && thread.recipient.address.isGroupOrCommunity)
|
||||||
val senderDisplayName = getTitle(thread.recipient)
|
val senderDisplayName = getTitle(thread.recipient)
|
||||||
?: thread.recipient.address.toString()
|
?: thread.recipient.address.toString()
|
||||||
binding.conversationViewDisplayNameTextView.text = senderDisplayName
|
binding.conversationViewDisplayNameTextView.text = senderDisplayName
|
||||||
|
@ -442,7 +442,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
|||||||
}
|
}
|
||||||
bottomSheet.onCopyConversationId = onCopyConversationId@{
|
bottomSheet.onCopyConversationId = onCopyConversationId@{
|
||||||
bottomSheet.dismiss()
|
bottomSheet.dismiss()
|
||||||
if (!thread.recipient.isGroupRecipient && !thread.recipient.isLocalNumber) {
|
if (!thread.recipient.isGroupOrCommunityRecipient && !thread.recipient.isLocalNumber) {
|
||||||
val clip = ClipData.newPlainText("Account ID", thread.recipient.address.toString())
|
val clip = ClipData.newPlainText("Account ID", thread.recipient.address.toString())
|
||||||
val manager = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
|
val manager = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
|
||||||
manager.setPrimaryClip(clip)
|
manager.setPrimaryClip(clip)
|
||||||
@ -583,7 +583,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
|||||||
val threadID = thread.threadId
|
val threadID = thread.threadId
|
||||||
val recipient = thread.recipient
|
val recipient = thread.recipient
|
||||||
|
|
||||||
if (recipient.isClosedGroupV2Recipient || recipient.isLegacyClosedGroupRecipient) {
|
if (recipient.isGroupV2Recipient || recipient.isLegacyGroupRecipient) {
|
||||||
ConversationMenuHelper.leaveClosedGroup(
|
ConversationMenuHelper.leaveClosedGroup(
|
||||||
context = this,
|
context = this,
|
||||||
thread = recipient,
|
thread = recipient,
|
||||||
@ -601,7 +601,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
|||||||
var positiveButtonId: Int = R.string.yes
|
var positiveButtonId: Int = R.string.yes
|
||||||
var negativeButtonId: Int = R.string.no
|
var negativeButtonId: Int = R.string.no
|
||||||
|
|
||||||
if (recipient.isGroupRecipient) {
|
if (recipient.isGroupOrCommunityRecipient) {
|
||||||
val group = groupDatabase.getGroup(recipient.address.toString()).orNull()
|
val group = groupDatabase.getGroup(recipient.address.toString()).orNull()
|
||||||
|
|
||||||
// If you are an admin of this group you can delete it
|
// If you are an admin of this group you can delete it
|
||||||
@ -666,7 +666,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
|||||||
ApplicationContext.getInstance(context).messageNotifier.updateNotification(context)
|
ApplicationContext.getInstance(context).messageNotifier.updateNotification(context)
|
||||||
|
|
||||||
// Notify the user
|
// Notify the user
|
||||||
val toastMessage = if (recipient.isGroupRecipient) R.string.groupMemberYouLeft else R.string.conversationsDeleted
|
val toastMessage = if (recipient.isGroupOrCommunityRecipient) R.string.groupMemberYouLeft else R.string.conversationsDeleted
|
||||||
Toast.makeText(context, toastMessage, Toast.LENGTH_LONG).show()
|
Toast.makeText(context, toastMessage, Toast.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ class UserDetailsBottomSheet: BottomSheetDialogFragment() {
|
|||||||
profilePictureView.update(recipient)
|
profilePictureView.update(recipient)
|
||||||
nameTextViewContainer.visibility = View.VISIBLE
|
nameTextViewContainer.visibility = View.VISIBLE
|
||||||
nameTextViewContainer.setOnClickListener {
|
nameTextViewContainer.setOnClickListener {
|
||||||
if (recipient.isOpenGroupInboxRecipient || recipient.isOpenGroupOutboxRecipient) return@setOnClickListener
|
if (recipient.isCommunityInboxRecipient || recipient.isCommunityOutboxRecipient) return@setOnClickListener
|
||||||
nameTextViewContainer.visibility = View.INVISIBLE
|
nameTextViewContainer.visibility = View.INVISIBLE
|
||||||
nameEditTextContainer.visibility = View.VISIBLE
|
nameEditTextContainer.visibility = View.VISIBLE
|
||||||
nicknameEditText.text = null
|
nicknameEditText.text = null
|
||||||
@ -87,12 +87,12 @@ class UserDetailsBottomSheet: BottomSheetDialogFragment() {
|
|||||||
nameTextView.text = recipient.name ?: publicKey // Uses the Contact API internally
|
nameTextView.text = recipient.name ?: publicKey // Uses the Contact API internally
|
||||||
|
|
||||||
nameEditIcon.isVisible = threadRecipient.isContactRecipient
|
nameEditIcon.isVisible = threadRecipient.isContactRecipient
|
||||||
&& !threadRecipient.isOpenGroupInboxRecipient
|
&& !threadRecipient.isCommunityInboxRecipient
|
||||||
&& !threadRecipient.isOpenGroupOutboxRecipient
|
&& !threadRecipient.isCommunityOutboxRecipient
|
||||||
|
|
||||||
publicKeyTextView.isVisible = !threadRecipient.isCommunityRecipient
|
publicKeyTextView.isVisible = !threadRecipient.isCommunityRecipient
|
||||||
&& !threadRecipient.isOpenGroupInboxRecipient
|
&& !threadRecipient.isCommunityInboxRecipient
|
||||||
&& !threadRecipient.isOpenGroupOutboxRecipient
|
&& !threadRecipient.isCommunityOutboxRecipient
|
||||||
messageButton.isVisible = !threadRecipient.isCommunityRecipient || IdPrefix.fromValue(publicKey)?.isBlinded() == true
|
messageButton.isVisible = !threadRecipient.isCommunityRecipient || IdPrefix.fromValue(publicKey)?.isBlinded() == true
|
||||||
publicKeyTextView.text = publicKey
|
publicKeyTextView.text = publicKey
|
||||||
publicKeyTextView.setOnLongClickListener {
|
publicKeyTextView.setOnLongClickListener {
|
||||||
|
@ -282,7 +282,7 @@ class MediaOverviewViewModel(
|
|||||||
// in groups/communities)
|
// in groups/communities)
|
||||||
if (selectedMedia.any { !it.mediaRecord.isOutgoing } &&
|
if (selectedMedia.any { !it.mediaRecord.isOutgoing } &&
|
||||||
successCount > 0 &&
|
successCount > 0 &&
|
||||||
!address.isGroup) {
|
!address.isGroupOrCommunity) {
|
||||||
withContext(Dispatchers.Default) {
|
withContext(Dispatchers.Default) {
|
||||||
val timestamp = SnodeAPI.nowWithOffset
|
val timestamp = SnodeAPI.nowWithOffset
|
||||||
val kind = DataExtractionNotification.Kind.MediaSaved(timestamp)
|
val kind = DataExtractionNotification.Kind.MediaSaved(timestamp)
|
||||||
|
@ -32,7 +32,7 @@ class MessageRequestsAdapter(
|
|||||||
view.setOnClickListener { view.thread?.let { listener.onConversationClick(it) } }
|
view.setOnClickListener { view.thread?.let { listener.onConversationClick(it) } }
|
||||||
view.setOnLongClickListener {
|
view.setOnLongClickListener {
|
||||||
view.thread?.let { thread ->
|
view.thread?.let { thread ->
|
||||||
showPopupMenu(view, thread.recipient.isGroupRecipient, thread.invitingAdminId)
|
showPopupMenu(view, thread.recipient.isGroupOrCommunityRecipient, thread.invitingAdminId)
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
@ -52,7 +52,7 @@ class MessageRequestsAdapter(
|
|||||||
private fun showPopupMenu(view: MessageRequestView, groupRecipient: Boolean, invitingAdmin: String?) {
|
private fun showPopupMenu(view: MessageRequestView, groupRecipient: Boolean, invitingAdmin: String?) {
|
||||||
val popupMenu = PopupMenu(ContextThemeWrapper(context, R.style.PopupMenu_MessageRequests), view)
|
val popupMenu = PopupMenu(ContextThemeWrapper(context, R.style.PopupMenu_MessageRequests), view)
|
||||||
// still show the block option if we have an inviting admin for the group
|
// still show the block option if we have an inviting admin for the group
|
||||||
if ((groupRecipient && invitingAdmin == null) || view.thread!!.recipient.isOpenGroupInboxRecipient) {
|
if ((groupRecipient && invitingAdmin == null) || view.thread!!.recipient.isCommunityInboxRecipient) {
|
||||||
popupMenu.menuInflater.inflate(R.menu.menu_group_request, popupMenu.menu)
|
popupMenu.menuInflater.inflate(R.menu.menu_group_request, popupMenu.menu)
|
||||||
} else {
|
} else {
|
||||||
popupMenu.menuInflater.inflate(R.menu.menu_message_request, popupMenu.menu)
|
popupMenu.menuInflater.inflate(R.menu.menu_message_request, popupMenu.menu)
|
||||||
|
@ -93,7 +93,7 @@ public class AndroidAutoReplyReceiver extends BroadcastReceiver {
|
|||||||
long expiresInMillis = expiryMode == null ? 0 : expiryMode.getExpiryMillis();
|
long expiresInMillis = expiryMode == null ? 0 : expiryMode.getExpiryMillis();
|
||||||
long expireStartedAt = expiryMode instanceof ExpiryMode.AfterSend ? message.getSentTimestamp() : 0L;
|
long expireStartedAt = expiryMode instanceof ExpiryMode.AfterSend ? message.getSentTimestamp() : 0L;
|
||||||
|
|
||||||
if (recipient.isGroupRecipient()) {
|
if (recipient.isGroupOrCommunityRecipient()) {
|
||||||
Log.w("AndroidAutoReplyReceiver", "GroupRecipient, Sending media message");
|
Log.w("AndroidAutoReplyReceiver", "GroupRecipient, Sending media message");
|
||||||
OutgoingMediaMessage reply = OutgoingMediaMessage.from(message, recipient, Collections.emptyList(), null, null, expiresInMillis, 0);
|
OutgoingMediaMessage reply = OutgoingMediaMessage.from(message, recipient, Collections.emptyList(), null, null, expiresInMillis, 0);
|
||||||
try {
|
try {
|
||||||
|
@ -28,8 +28,6 @@ import android.database.Cursor
|
|||||||
import android.os.AsyncTask
|
import android.os.AsyncTask
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.camera.core.impl.utils.ContextUtil.getApplicationContext
|
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
@ -69,8 +67,6 @@ import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
|||||||
import org.thoughtcrime.securesms.database.model.ReactionRecord
|
import org.thoughtcrime.securesms.database.model.ReactionRecord
|
||||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent.Companion.get
|
import org.thoughtcrime.securesms.dependencies.DatabaseComponent.Companion.get
|
||||||
import org.thoughtcrime.securesms.mms.SlideDeck
|
import org.thoughtcrime.securesms.mms.SlideDeck
|
||||||
import org.thoughtcrime.securesms.permissions.Permissions
|
|
||||||
import org.thoughtcrime.securesms.preferences.ShareLogsDialog
|
|
||||||
import org.thoughtcrime.securesms.service.KeyCachingService
|
import org.thoughtcrime.securesms.service.KeyCachingService
|
||||||
import org.thoughtcrime.securesms.util.SessionMetaProtocol.canUserReplyToNotification
|
import org.thoughtcrime.securesms.util.SessionMetaProtocol.canUserReplyToNotification
|
||||||
import org.thoughtcrime.securesms.util.SpanUtil
|
import org.thoughtcrime.securesms.util.SpanUtil
|
||||||
@ -171,7 +167,7 @@ class DefaultMessageNotifier : MessageNotifier {
|
|||||||
val threads = get(context).threadDatabase()
|
val threads = get(context).threadDatabase()
|
||||||
val recipient = threads.getRecipientForThreadId(threadId)
|
val recipient = threads.getRecipientForThreadId(threadId)
|
||||||
|
|
||||||
if (recipient != null && !recipient.isGroupRecipient && threads.getMessageCount(threadId) == 1 &&
|
if (recipient != null && !recipient.isGroupOrCommunityRecipient && threads.getMessageCount(threadId) == 1 &&
|
||||||
!(recipient.isApproved || threads.getLastSeenAndHasSent(threadId).second())
|
!(recipient.isApproved || threads.getLastSeenAndHasSent(threadId).second())
|
||||||
) {
|
) {
|
||||||
removeHasHiddenMessageRequests(context)
|
removeHasHiddenMessageRequests(context)
|
||||||
@ -485,7 +481,7 @@ class DefaultMessageNotifier : MessageNotifier {
|
|||||||
|
|
||||||
if (threadId != -1L) {
|
if (threadId != -1L) {
|
||||||
threadRecipients = threadDatabase.getRecipientForThreadId(threadId)
|
threadRecipients = threadDatabase.getRecipientForThreadId(threadId)
|
||||||
messageRequest = threadRecipients != null && !threadRecipients.isGroupRecipient &&
|
messageRequest = threadRecipients != null && !threadRecipients.isGroupOrCommunityRecipient &&
|
||||||
!threadRecipients.isApproved && !threadDatabase.getLastSeenAndHasSent(threadId).second()
|
!threadRecipients.isApproved && !threadDatabase.getLastSeenAndHasSent(threadId).second()
|
||||||
if (messageRequest && (threadDatabase.getMessageCount(threadId) > 1 || !hasHiddenMessageRequests(context))) {
|
if (messageRequest && (threadDatabase.getMessageCount(threadId) > 1 || !hasHiddenMessageRequests(context))) {
|
||||||
continue
|
continue
|
||||||
@ -558,7 +554,7 @@ class DefaultMessageNotifier : MessageNotifier {
|
|||||||
.findLast()
|
.findLast()
|
||||||
|
|
||||||
if (lastReact.isPresent) {
|
if (lastReact.isPresent) {
|
||||||
if (threadRecipients != null && !threadRecipients.isGroupRecipient) {
|
if (threadRecipients != null && !threadRecipients.isGroupOrCommunityRecipient) {
|
||||||
val reaction = lastReact.get()
|
val reaction = lastReact.get()
|
||||||
val reactor = Recipient.from(context, fromSerialized(reaction.author), false)
|
val reactor = Recipient.from(context, fromSerialized(reaction.author), false)
|
||||||
val emoji = Phrase.from(context, R.string.emojiReactsNotification).put(EMOJI_KEY, reaction.emoji).format().toString()
|
val emoji = Phrase.from(context, R.string.emojiReactsNotification).put(EMOJI_KEY, reaction.emoji).format().toString()
|
||||||
|
@ -73,7 +73,7 @@ class MarkReadReceiver : BroadcastReceiver() {
|
|||||||
.filter { it.expiryType == ExpiryType.AFTER_READ }
|
.filter { it.expiryType == ExpiryType.AFTER_READ }
|
||||||
.map { it.syncMessageId }
|
.map { it.syncMessageId }
|
||||||
.filter { mmsSmsDatabase.getMessageForTimestamp(it.timetamp)?.run {
|
.filter { mmsSmsDatabase.getMessageForTimestamp(it.timetamp)?.run {
|
||||||
isExpirationTimerUpdate && threadDb.getRecipientForThreadId(threadId)?.isGroupRecipient == true } == false
|
isExpirationTimerUpdate && threadDb.getRecipientForThreadId(threadId)?.isGroupOrCommunityRecipient == true } == false
|
||||||
}
|
}
|
||||||
.forEach { messageExpirationManager.startDisappearAfterRead(it.timetamp, it.address.serialize()) }
|
.forEach { messageExpirationManager.startDisappearAfterRead(it.timetamp, it.address.serialize()) }
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ class MultipleRecipientNotificationBuilder(context: Context, privacy: Notificati
|
|||||||
|
|
||||||
fun setMostRecentSender(recipient: Recipient, threadRecipient: Recipient) {
|
fun setMostRecentSender(recipient: Recipient, threadRecipient: Recipient) {
|
||||||
var displayName = recipient.toShortString()
|
var displayName = recipient.toShortString()
|
||||||
if (threadRecipient.isGroupRecipient) {
|
if (threadRecipient.isGroupOrCommunityRecipient) {
|
||||||
displayName = getGroupDisplayName(recipient, threadRecipient.isCommunityRecipient)
|
displayName = getGroupDisplayName(recipient, threadRecipient.isCommunityRecipient)
|
||||||
}
|
}
|
||||||
if (privacy.isDisplayContact) {
|
if (privacy.isDisplayContact) {
|
||||||
@ -69,7 +69,7 @@ class MultipleRecipientNotificationBuilder(context: Context, privacy: Notificati
|
|||||||
|
|
||||||
fun addMessageBody(sender: Recipient, threadRecipient: Recipient, body: CharSequence?) {
|
fun addMessageBody(sender: Recipient, threadRecipient: Recipient, body: CharSequence?) {
|
||||||
var displayName = sender.toShortString()
|
var displayName = sender.toShortString()
|
||||||
if (threadRecipient.isGroupRecipient) {
|
if (threadRecipient.isGroupOrCommunityRecipient) {
|
||||||
displayName = getGroupDisplayName(sender, threadRecipient.isCommunityRecipient)
|
displayName = getGroupDisplayName(sender, threadRecipient.isCommunityRecipient)
|
||||||
}
|
}
|
||||||
if (privacy.isDisplayMessage) {
|
if (privacy.isDisplayMessage) {
|
||||||
|
@ -11,7 +11,7 @@ public enum ReplyMethod {
|
|||||||
SecureMessage;
|
SecureMessage;
|
||||||
|
|
||||||
public static @NonNull ReplyMethod forRecipient(Context context, Recipient recipient) {
|
public static @NonNull ReplyMethod forRecipient(Context context, Recipient recipient) {
|
||||||
if (recipient.isGroupRecipient()) {
|
if (recipient.isGroupOrCommunityRecipient()) {
|
||||||
return ReplyMethod.GroupMessage;
|
return ReplyMethod.GroupMessage;
|
||||||
}
|
}
|
||||||
return ReplyMethod.SecureMessage;
|
return ReplyMethod.SecureMessage;
|
||||||
|
@ -29,7 +29,6 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
|||||||
import org.session.libsession.avatars.ContactPhoto;
|
import org.session.libsession.avatars.ContactPhoto;
|
||||||
import org.session.libsession.messaging.contacts.Contact;
|
import org.session.libsession.messaging.contacts.Contact;
|
||||||
import org.session.libsession.utilities.NotificationPrivacyPreference;
|
import org.session.libsession.utilities.NotificationPrivacyPreference;
|
||||||
import org.session.libsession.utilities.TextSecurePreferences;
|
|
||||||
import org.session.libsession.utilities.Util;
|
import org.session.libsession.utilities.Util;
|
||||||
import org.session.libsession.utilities.recipients.Recipient;
|
import org.session.libsession.utilities.recipients.Recipient;
|
||||||
import org.session.libsignal.utilities.Log;
|
import org.session.libsignal.utilities.Log;
|
||||||
@ -119,7 +118,7 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil
|
|||||||
{
|
{
|
||||||
SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
|
SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
|
||||||
|
|
||||||
if (privacy.isDisplayContact() && threadRecipient.isGroupRecipient()) {
|
if (privacy.isDisplayContact() && threadRecipient.isGroupOrCommunityRecipient()) {
|
||||||
String displayName = getGroupDisplayName(individualRecipient, threadRecipient.isCommunityRecipient());
|
String displayName = getGroupDisplayName(individualRecipient, threadRecipient.isCommunityRecipient());
|
||||||
stringBuilder.append(Util.getBoldedString(displayName + ": "));
|
stringBuilder.append(Util.getBoldedString(displayName + ": "));
|
||||||
}
|
}
|
||||||
@ -207,7 +206,7 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil
|
|||||||
{
|
{
|
||||||
SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
|
SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
|
||||||
|
|
||||||
if (privacy.isDisplayContact() && threadRecipient.isGroupRecipient()) {
|
if (privacy.isDisplayContact() && threadRecipient.isGroupOrCommunityRecipient()) {
|
||||||
String displayName = getGroupDisplayName(individualRecipient, threadRecipient.isCommunityRecipient());
|
String displayName = getGroupDisplayName(individualRecipient, threadRecipient.isCommunityRecipient());
|
||||||
stringBuilder.append(Util.getBoldedString(displayName + ": "));
|
stringBuilder.append(Util.getBoldedString(displayName + ": "));
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,6 @@ import org.session.libsession.snode.utilities.await
|
|||||||
import org.session.libsession.utilities.Address
|
import org.session.libsession.utilities.Address
|
||||||
import org.session.libsession.utilities.GroupUtil
|
import org.session.libsession.utilities.GroupUtil
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
import org.session.libsession.utilities.getClosedGroup
|
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.session.libsignal.utilities.AccountId
|
import org.session.libsignal.utilities.AccountId
|
||||||
import org.thoughtcrime.securesms.database.DatabaseContentProviders
|
import org.thoughtcrime.securesms.database.DatabaseContentProviders
|
||||||
@ -113,7 +112,7 @@ class DefaultConversationRepository @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun maybeGetBlindedRecipient(recipient: Recipient): Recipient? {
|
override fun maybeGetBlindedRecipient(recipient: Recipient): Recipient? {
|
||||||
if (!recipient.isOpenGroupInboxRecipient) return null
|
if (!recipient.isCommunityInboxRecipient) return null
|
||||||
return Recipient.from(
|
return Recipient.from(
|
||||||
context,
|
context,
|
||||||
Address.fromSerialized(GroupUtil.getDecodedOpenGroupInboxAccountId(recipient.address.serialize())),
|
Address.fromSerialized(GroupUtil.getDecodedOpenGroupInboxAccountId(recipient.address.serialize())),
|
||||||
@ -173,7 +172,7 @@ class DefaultConversationRepository @Inject constructor(
|
|||||||
|
|
||||||
override fun isGroupReadOnly(recipient: Recipient): Boolean {
|
override fun isGroupReadOnly(recipient: Recipient): Boolean {
|
||||||
// We only care about group v2 recipient
|
// We only care about group v2 recipient
|
||||||
if (!recipient.isClosedGroupV2Recipient) {
|
if (!recipient.isGroupV2Recipient) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,7 +303,7 @@ class DefaultConversationRepository @Inject constructor(
|
|||||||
recipient: Recipient,
|
recipient: Recipient,
|
||||||
messages: Set<MessageRecord>
|
messages: Set<MessageRecord>
|
||||||
) {
|
) {
|
||||||
if (recipient.isLegacyClosedGroupRecipient) {
|
if (recipient.isLegacyGroupRecipient) {
|
||||||
val publicKey = recipient.address
|
val publicKey = recipient.address
|
||||||
|
|
||||||
messages.forEach { message ->
|
messages.forEach { message ->
|
||||||
@ -343,7 +342,7 @@ class DefaultConversationRepository @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun shouldSendUnsendRequest(recipient: Recipient): Boolean {
|
private fun shouldSendUnsendRequest(recipient: Recipient): Boolean {
|
||||||
return recipient.is1on1 || recipient.isLegacyClosedGroupRecipient
|
return recipient.is1on1 || recipient.isLegacyGroupRecipient
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildUnsendRequest(message: MessageRecord): UnsendRequest {
|
private fun buildUnsendRequest(message: MessageRecord): UnsendRequest {
|
||||||
@ -383,7 +382,7 @@ class DefaultConversationRepository @Inject constructor(
|
|||||||
while (reader.next != null) {
|
while (reader.next != null) {
|
||||||
deleteMessageRequest(reader.current)
|
deleteMessageRequest(reader.current)
|
||||||
val recipient = reader.current.recipient
|
val recipient = reader.current.recipient
|
||||||
if (block && !recipient.isClosedGroupV2Recipient) {
|
if (block && !recipient.isGroupV2Recipient) {
|
||||||
setBlocked(reader.current.threadId, recipient, true)
|
setBlocked(reader.current.threadId, recipient, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -394,7 +393,7 @@ class DefaultConversationRepository @Inject constructor(
|
|||||||
override suspend fun acceptMessageRequest(threadId: Long, recipient: Recipient) = runCatching {
|
override suspend fun acceptMessageRequest(threadId: Long, recipient: Recipient) = runCatching {
|
||||||
withContext(Dispatchers.Default) {
|
withContext(Dispatchers.Default) {
|
||||||
storage.setRecipientApproved(recipient, true)
|
storage.setRecipientApproved(recipient, true)
|
||||||
if (recipient.isClosedGroupV2Recipient) {
|
if (recipient.isGroupV2Recipient) {
|
||||||
groupManager.respondToInvitation(
|
groupManager.respondToInvitation(
|
||||||
AccountId(recipient.address.serialize()),
|
AccountId(recipient.address.serialize()),
|
||||||
approved = true
|
approved = true
|
||||||
@ -418,7 +417,7 @@ class DefaultConversationRepository @Inject constructor(
|
|||||||
override suspend fun declineMessageRequest(threadId: Long, recipient: Recipient): Result<Unit> = runCatching {
|
override suspend fun declineMessageRequest(threadId: Long, recipient: Recipient): Result<Unit> = runCatching {
|
||||||
withContext(Dispatchers.Default) {
|
withContext(Dispatchers.Default) {
|
||||||
sessionJobDb.cancelPendingMessageSendJobs(threadId)
|
sessionJobDb.cancelPendingMessageSendJobs(threadId)
|
||||||
if (recipient.isClosedGroupV2Recipient) {
|
if (recipient.isGroupV2Recipient) {
|
||||||
groupManager.respondToInvitation(
|
groupManager.respondToInvitation(
|
||||||
AccountId(recipient.address.serialize()),
|
AccountId(recipient.address.serialize()),
|
||||||
approved = false
|
approved = false
|
||||||
|
@ -40,7 +40,7 @@ object SessionMetaProtocol {
|
|||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun shouldSendDeliveryReceipt(message: SignalServiceDataMessage, address: Address): Boolean {
|
fun shouldSendDeliveryReceipt(message: SignalServiceDataMessage, address: Address): Boolean {
|
||||||
if (address.isGroup) { return false }
|
if (address.isGroupOrCommunity) { return false }
|
||||||
val hasBody = message.body.isPresent && message.body.get().isNotEmpty()
|
val hasBody = message.body.isPresent && message.body.get().isNotEmpty()
|
||||||
val hasAttachment = message.attachments.isPresent && message.attachments.get().isNotEmpty()
|
val hasAttachment = message.attachments.isPresent && message.attachments.get().isNotEmpty()
|
||||||
val hasLinkPreview = message.previews.isPresent && message.previews.get().isNotEmpty()
|
val hasLinkPreview = message.previews.isPresent && message.previews.get().isNotEmpty()
|
||||||
@ -49,11 +49,11 @@ object SessionMetaProtocol {
|
|||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun shouldSendReadReceipt(recipient: Recipient): Boolean {
|
fun shouldSendReadReceipt(recipient: Recipient): Boolean {
|
||||||
return !recipient.isGroupRecipient && recipient.isApproved && !recipient.isBlocked
|
return !recipient.isGroupOrCommunityRecipient && recipient.isApproved && !recipient.isBlocked
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun shouldSendTypingIndicator(recipient: Recipient): Boolean {
|
fun shouldSendTypingIndicator(recipient: Recipient): Boolean {
|
||||||
return !recipient.isGroupRecipient && recipient.isApproved && !recipient.isBlocked
|
return !recipient.isGroupOrCommunityRecipient && recipient.isApproved && !recipient.isBlocked
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,5 @@
|
|||||||
package org.thoughtcrime.securesms.util
|
package org.thoughtcrime.securesms.util
|
||||||
|
|
||||||
import network.loki.messenger.libsession_util.ConversationVolatileConfig
|
|
||||||
import network.loki.messenger.libsession_util.ReadableConversationVolatileConfig
|
import network.loki.messenger.libsession_util.ReadableConversationVolatileConfig
|
||||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||||
import org.session.libsession.utilities.GroupUtil
|
import org.session.libsession.utilities.GroupUtil
|
||||||
@ -10,12 +9,12 @@ import org.thoughtcrime.securesms.database.model.ThreadRecord
|
|||||||
fun ReadableConversationVolatileConfig.getConversationUnread(thread: ThreadRecord): Boolean {
|
fun ReadableConversationVolatileConfig.getConversationUnread(thread: ThreadRecord): Boolean {
|
||||||
val recipient = thread.recipient
|
val recipient = thread.recipient
|
||||||
if (recipient.isContactRecipient
|
if (recipient.isContactRecipient
|
||||||
&& recipient.isOpenGroupInboxRecipient
|
&& recipient.isCommunityInboxRecipient
|
||||||
&& recipient.address.serialize().startsWith(IdPrefix.STANDARD.value)) {
|
&& recipient.address.serialize().startsWith(IdPrefix.STANDARD.value)) {
|
||||||
return getOneToOne(recipient.address.serialize())?.unread == true
|
return getOneToOne(recipient.address.serialize())?.unread == true
|
||||||
} else if (recipient.isClosedGroupV2Recipient) {
|
} else if (recipient.isGroupV2Recipient) {
|
||||||
return getClosedGroup(recipient.address.serialize())?.unread == true
|
return getClosedGroup(recipient.address.serialize())?.unread == true
|
||||||
} else if (recipient.isLegacyClosedGroupRecipient) {
|
} else if (recipient.isLegacyGroupRecipient) {
|
||||||
return getLegacyClosedGroup(GroupUtil.doubleDecodeGroupId(recipient.address.toGroupString()))?.unread == true
|
return getLegacyClosedGroup(GroupUtil.doubleDecodeGroupId(recipient.address.toGroupString()))?.unread == true
|
||||||
} else if (recipient.isCommunityRecipient) {
|
} else if (recipient.isCommunityRecipient) {
|
||||||
val openGroup = MessagingModuleConfiguration.shared.storage.getOpenGroup(thread.threadId) ?: return false
|
val openGroup = MessagingModuleConfiguration.shared.storage.getOpenGroup(thread.threadId) ?: return false
|
||||||
|
@ -443,8 +443,8 @@ class DisappearingMessagesViewModelTest {
|
|||||||
mockStuff(mode)
|
mockStuff(mode)
|
||||||
|
|
||||||
whenever(recipient.address).thenReturn(GROUP_ADDRESS)
|
whenever(recipient.address).thenReturn(GROUP_ADDRESS)
|
||||||
whenever(recipient.isGroupRecipient).thenReturn(true)
|
whenever(recipient.isGroupOrCommunityRecipient).thenReturn(true)
|
||||||
whenever(recipient.isLegacyClosedGroupRecipient).thenReturn(true)
|
whenever(recipient.isLegacyGroupRecipient).thenReturn(true)
|
||||||
whenever(groupDb.getGroup(any<String>())).thenReturn(Optional.of(groupRecord))
|
whenever(groupDb.getGroup(any<String>())).thenReturn(Optional.of(groupRecord))
|
||||||
whenever(groupRecord.admins).thenReturn(
|
whenever(groupRecord.admins).thenReturn(
|
||||||
buildList {
|
buildList {
|
||||||
|
@ -4,7 +4,6 @@ import android.app.Application
|
|||||||
import com.goterl.lazysodium.utils.KeyPair
|
import com.goterl.lazysodium.utils.KeyPair
|
||||||
import kotlinx.coroutines.flow.emptyFlow
|
import kotlinx.coroutines.flow.emptyFlow
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import org.hamcrest.CoreMatchers.endsWith
|
|
||||||
import org.hamcrest.CoreMatchers.equalTo
|
import org.hamcrest.CoreMatchers.equalTo
|
||||||
import org.hamcrest.CoreMatchers.notNullValue
|
import org.hamcrest.CoreMatchers.notNullValue
|
||||||
import org.hamcrest.CoreMatchers.nullValue
|
import org.hamcrest.CoreMatchers.nullValue
|
||||||
@ -166,8 +165,8 @@ class ConversationViewModelTest: BaseViewModelTest() {
|
|||||||
@Test
|
@Test
|
||||||
fun `open group recipient should have no blinded recipient`() {
|
fun `open group recipient should have no blinded recipient`() {
|
||||||
whenever(recipient.isCommunityRecipient).thenReturn(true)
|
whenever(recipient.isCommunityRecipient).thenReturn(true)
|
||||||
whenever(recipient.isOpenGroupOutboxRecipient).thenReturn(false)
|
whenever(recipient.isCommunityOutboxRecipient).thenReturn(false)
|
||||||
whenever(recipient.isOpenGroupInboxRecipient).thenReturn(false)
|
whenever(recipient.isCommunityInboxRecipient).thenReturn(false)
|
||||||
assertThat(viewModel.blindedRecipient, nullValue())
|
assertThat(viewModel.blindedRecipient, nullValue())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,7 +179,7 @@ class ConversationViewModelTest: BaseViewModelTest() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `contact recipient should hide input bar if not accepting requests`() {
|
fun `contact recipient should hide input bar if not accepting requests`() {
|
||||||
whenever(recipient.isOpenGroupInboxRecipient).thenReturn(true)
|
whenever(recipient.isCommunityInboxRecipient).thenReturn(true)
|
||||||
val blinded = mock<Recipient> {
|
val blinded = mock<Recipient> {
|
||||||
whenever(it.blocksCommunityMessageRequests).thenReturn(true)
|
whenever(it.blocksCommunityMessageRequests).thenReturn(true)
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ class MentionViewModelTest {
|
|||||||
threadDatabase = mock {
|
threadDatabase = mock {
|
||||||
on { getRecipientForThreadId(threadID) } doAnswer {
|
on { getRecipientForThreadId(threadID) } doAnswer {
|
||||||
mock<Recipient> {
|
mock<Recipient> {
|
||||||
on { isClosedGroupV2Recipient } doReturn false
|
on { isGroupV2Recipient } doReturn false
|
||||||
on { isCommunityRecipient } doReturn true
|
on { isCommunityRecipient } doReturn true
|
||||||
on { isContactRecipient } doReturn false
|
on { isContactRecipient } doReturn false
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ sealed class Destination {
|
|||||||
address.isContact -> {
|
address.isContact -> {
|
||||||
Contact(address.contactIdentifier())
|
Contact(address.contactIdentifier())
|
||||||
}
|
}
|
||||||
address.isLegacyClosedGroup -> {
|
address.isLegacyGroup -> {
|
||||||
val groupID = address.toGroupString()
|
val groupID = address.toGroupString()
|
||||||
val groupPublicKey = GroupUtil.doubleDecodeGroupID(groupID).toHexString()
|
val groupPublicKey = GroupUtil.doubleDecodeGroupID(groupID).toHexString()
|
||||||
LegacyClosedGroup(groupPublicKey)
|
LegacyClosedGroup(groupPublicKey)
|
||||||
@ -61,7 +61,7 @@ sealed class Destination {
|
|||||||
groupInboxId.last()
|
groupInboxId.last()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
address.isClosedGroupV2 -> {
|
address.isGroupV2 -> {
|
||||||
ClosedGroup(address.serialize())
|
ClosedGroup(address.serialize())
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
|
@ -407,7 +407,7 @@ fun MessageReceiver.handleVisibleMessage(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
// Handle group invite response if new closed group
|
// Handle group invite response if new closed group
|
||||||
if (threadRecipient?.isClosedGroupV2Recipient == true) {
|
if (threadRecipient?.isGroupV2Recipient == true) {
|
||||||
GlobalScope.launch {
|
GlobalScope.launch {
|
||||||
try {
|
try {
|
||||||
MessagingModuleConfiguration.shared.groupManagerV2
|
MessagingModuleConfiguration.shared.groupManagerV2
|
||||||
@ -464,7 +464,7 @@ fun MessageReceiver.handleVisibleMessage(
|
|||||||
// Cancel any typing indicators if needed
|
// Cancel any typing indicators if needed
|
||||||
cancelTypingIndicatorsIfNeeded(message.sender!!)
|
cancelTypingIndicatorsIfNeeded(message.sender!!)
|
||||||
// Parse reaction if needed
|
// Parse reaction if needed
|
||||||
val threadIsGroup = threadRecipient?.isGroupRecipient == true
|
val threadIsGroup = threadRecipient?.isGroupOrCommunityRecipient == true
|
||||||
message.reaction?.let { reaction ->
|
message.reaction?.let { reaction ->
|
||||||
if (reaction.react == true) {
|
if (reaction.react == true) {
|
||||||
reaction.serverId = message.openGroupServerMessageID?.toString() ?: message.serverHash.orEmpty()
|
reaction.serverId = message.openGroupServerMessageID?.toString() ?: message.serverHash.orEmpty()
|
||||||
|
@ -18,11 +18,9 @@ class Address private constructor(address: String) : Parcelable, Comparable<Addr
|
|||||||
|
|
||||||
constructor(`in`: Parcel) : this(`in`.readString()!!) {}
|
constructor(`in`: Parcel) : this(`in`.readString()!!) {}
|
||||||
|
|
||||||
val isGroup: Boolean
|
val isLegacyGroup: Boolean
|
||||||
get() = GroupUtil.isEncodedGroup(address) || address.startsWith(IdPrefix.GROUP.value)
|
|
||||||
val isLegacyClosedGroup: Boolean
|
|
||||||
get() = GroupUtil.isLegacyClosedGroup(address)
|
get() = GroupUtil.isLegacyClosedGroup(address)
|
||||||
val isClosedGroupV2: Boolean
|
val isGroupV2: Boolean
|
||||||
get() = address.startsWith(IdPrefix.GROUP.value)
|
get() = address.startsWith(IdPrefix.GROUP.value)
|
||||||
val isCommunity: Boolean
|
val isCommunity: Boolean
|
||||||
get() = GroupUtil.isCommunity(address)
|
get() = GroupUtil.isCommunity(address)
|
||||||
@ -30,19 +28,23 @@ class Address private constructor(address: String) : Parcelable, Comparable<Addr
|
|||||||
get() = GroupUtil.isCommunityInbox(address)
|
get() = GroupUtil.isCommunityInbox(address)
|
||||||
val isCommunityOutbox: Boolean
|
val isCommunityOutbox: Boolean
|
||||||
get() = address.startsWith(IdPrefix.BLINDED.value) || address.startsWith(IdPrefix.BLINDEDV2.value)
|
get() = address.startsWith(IdPrefix.BLINDED.value) || address.startsWith(IdPrefix.BLINDEDV2.value)
|
||||||
|
val isGroupOrCommunity: Boolean
|
||||||
|
get() = isGroup || isCommunity
|
||||||
|
val isGroup: Boolean
|
||||||
|
get() = isLegacyGroup || isGroupV2
|
||||||
val isContact: Boolean
|
val isContact: Boolean
|
||||||
get() = !(isGroup || isCommunityInbox)
|
get() = !(isGroupOrCommunity || isCommunityInbox)
|
||||||
|
|
||||||
fun contactIdentifier(): String {
|
fun contactIdentifier(): String {
|
||||||
if (!isContact && !isCommunity) {
|
if (!isContact && !isCommunity) {
|
||||||
if (isGroup) throw AssertionError("Not e164, is group")
|
if (isGroupOrCommunity) throw AssertionError("Not e164, is group")
|
||||||
throw AssertionError("Not e164, unknown")
|
throw AssertionError("Not e164, unknown")
|
||||||
}
|
}
|
||||||
return address
|
return address
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toGroupString(): String {
|
fun toGroupString(): String {
|
||||||
if (!isGroup) throw AssertionError("Not group")
|
if (!isGroupOrCommunity) throw AssertionError("Not group")
|
||||||
return address
|
return address
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,9 +24,9 @@ class GroupRecord(
|
|||||||
val isOpenGroup: Boolean
|
val isOpenGroup: Boolean
|
||||||
get() = Address.fromSerialized(encodedId).isCommunity
|
get() = Address.fromSerialized(encodedId).isCommunity
|
||||||
val isLegacyClosedGroup: Boolean
|
val isLegacyClosedGroup: Boolean
|
||||||
get() = Address.fromSerialized(encodedId).isLegacyClosedGroup
|
get() = Address.fromSerialized(encodedId).isLegacyGroup
|
||||||
val isClosedGroupV2: Boolean
|
val isClosedGroupV2: Boolean
|
||||||
get() = Address.fromSerialized(encodedId).isClosedGroupV2
|
get() = Address.fromSerialized(encodedId).isGroupV2
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (!TextUtils.isEmpty(members)) {
|
if (!TextUtils.isEmpty(members)) {
|
||||||
|
@ -8,7 +8,7 @@ fun Recipient.getType(): MessageType =
|
|||||||
when{
|
when{
|
||||||
isCommunityRecipient -> MessageType.COMMUNITY
|
isCommunityRecipient -> MessageType.COMMUNITY
|
||||||
isLocalNumber -> MessageType.NOTE_TO_SELF
|
isLocalNumber -> MessageType.NOTE_TO_SELF
|
||||||
isLegacyClosedGroupRecipient -> MessageType.LEGACY_GROUP
|
isLegacyGroupRecipient -> MessageType.LEGACY_GROUP
|
||||||
isClosedGroupV2Recipient -> MessageType.GROUPS_V2
|
isGroupV2Recipient -> MessageType.GROUPS_V2
|
||||||
else -> MessageType.ONE_ON_ONE
|
else -> MessageType.ONE_ON_ONE
|
||||||
}
|
}
|
@ -17,12 +17,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.session.libsession.utilities.recipients;
|
package org.session.libsession.utilities.recipients;
|
||||||
|
|
||||||
import static org.session.libsession.utilities.IdUtilKt.truncateIdForDisplay;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
@ -326,7 +323,7 @@ public class Recipient implements RecipientModifiedListener {
|
|||||||
public synchronized @Nullable String getName() {
|
public synchronized @Nullable String getName() {
|
||||||
StorageProtocol storage = MessagingModuleConfiguration.getShared().getStorage();
|
StorageProtocol storage = MessagingModuleConfiguration.getShared().getStorage();
|
||||||
String accountID = this.address.toString();
|
String accountID = this.address.toString();
|
||||||
if (isGroupRecipient()) {
|
if (isGroupOrCommunityRecipient()) {
|
||||||
if (this.name == null) {
|
if (this.name == null) {
|
||||||
List<String> names = new LinkedList<>();
|
List<String> names = new LinkedList<>();
|
||||||
for (Recipient recipient : participants) {
|
for (Recipient recipient : participants) {
|
||||||
@ -336,7 +333,7 @@ public class Recipient implements RecipientModifiedListener {
|
|||||||
} else {
|
} else {
|
||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
} else if (isOpenGroupInboxRecipient()){
|
} else if (isCommunityInboxRecipient()){
|
||||||
String inboxID = GroupUtil.getDecodedOpenGroupInboxAccountId(accountID);
|
String inboxID = GroupUtil.getDecodedOpenGroupInboxAccountId(accountID);
|
||||||
Contact contact = storage.getContactWithAccountID(inboxID);
|
Contact contact = storage.getContactWithAccountID(inboxID);
|
||||||
if (contact == null) return accountID;
|
if (contact == null) return accountID;
|
||||||
@ -374,7 +371,7 @@ public class Recipient implements RecipientModifiedListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public synchronized @NonNull MaterialColor getColor() {
|
public synchronized @NonNull MaterialColor getColor() {
|
||||||
if (isGroupRecipient()) return MaterialColor.GROUP;
|
if (isGroupOrCommunityRecipient()) return MaterialColor.GROUP;
|
||||||
else if (color != null) return color;
|
else if (color != null) return color;
|
||||||
else if (name != null) return ContactColors.generateFor(name);
|
else if (name != null) return ContactColors.generateFor(name);
|
||||||
else return ContactColors.UNKNOWN_COLOR;
|
else return ContactColors.UNKNOWN_COLOR;
|
||||||
@ -458,8 +455,8 @@ public class Recipient implements RecipientModifiedListener {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isGroupRecipient() {
|
public boolean isGroupOrCommunityRecipient() {
|
||||||
return address.isGroup();
|
return address.isGroupOrCommunity();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isContactRecipient() {
|
public boolean isContactRecipient() {
|
||||||
@ -471,26 +468,26 @@ public class Recipient implements RecipientModifiedListener {
|
|||||||
return address.isCommunity();
|
return address.isCommunity();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOpenGroupOutboxRecipient() {
|
public boolean isCommunityOutboxRecipient() {
|
||||||
return address.isCommunityOutbox();
|
return address.isCommunityOutbox();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOpenGroupInboxRecipient() {
|
public boolean isCommunityInboxRecipient() {
|
||||||
return address.isCommunityInbox();
|
return address.isCommunityInbox();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLegacyClosedGroupRecipient() {
|
public boolean isLegacyGroupRecipient() {
|
||||||
return address.isLegacyClosedGroup();
|
return address.isLegacyGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isClosedGroupV2Recipient() {
|
public boolean isGroupV2Recipient() {
|
||||||
return address.isClosedGroupV2();
|
return address.isGroupV2();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public boolean isPushGroupRecipient() {
|
public boolean isPushGroupRecipient() {
|
||||||
return address.isGroup();
|
return address.isGroupOrCommunity();
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NonNull synchronized List<Recipient> getParticipants() {
|
public @NonNull synchronized List<Recipient> getParticipants() {
|
||||||
@ -538,7 +535,7 @@ public class Recipient implements RecipientModifiedListener {
|
|||||||
|
|
||||||
public synchronized @Nullable ContactPhoto getContactPhoto() {
|
public synchronized @Nullable ContactPhoto getContactPhoto() {
|
||||||
if (isLocalNumber) return new ProfileContactPhoto(address, String.valueOf(TextSecurePreferences.getProfileAvatarId(context)));
|
if (isLocalNumber) return new ProfileContactPhoto(address, String.valueOf(TextSecurePreferences.getProfileAvatarId(context)));
|
||||||
else if (isGroupRecipient() && groupAvatarId != null) return new GroupRecordContactPhoto(address, groupAvatarId);
|
else if (isGroupOrCommunityRecipient() && groupAvatarId != null) return new GroupRecordContactPhoto(address, groupAvatarId);
|
||||||
else if (systemContactPhoto != null) return new SystemContactPhoto(address, systemContactPhoto, 0);
|
else if (systemContactPhoto != null) return new SystemContactPhoto(address, systemContactPhoto, 0);
|
||||||
else if (profileAvatar != null) return new ProfileContactPhoto(address, profileAvatar);
|
else if (profileAvatar != null) return new ProfileContactPhoto(address, profileAvatar);
|
||||||
else return null;
|
else return null;
|
||||||
@ -813,7 +810,7 @@ public class Recipient implements RecipientModifiedListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public synchronized boolean showCallMenu() {
|
public synchronized boolean showCallMenu() {
|
||||||
return !isGroupRecipient() && hasApprovedMe();
|
return !isGroupOrCommunityRecipient() && hasApprovedMe();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -84,9 +84,9 @@ class RecipientProvider {
|
|||||||
@NonNull Optional<RecipientSettings> settings,
|
@NonNull Optional<RecipientSettings> settings,
|
||||||
@NonNull Optional<GroupRecord> groupRecord)
|
@NonNull Optional<GroupRecord> groupRecord)
|
||||||
{
|
{
|
||||||
if (address.isGroup() && settings.isPresent() && groupRecord.isPresent()) {
|
if (address.isGroupOrCommunity() && settings.isPresent() && groupRecord.isPresent()) {
|
||||||
return Optional.of(getGroupRecipientDetails(context, address, groupRecord, settings, true));
|
return Optional.of(getGroupRecipientDetails(context, address, groupRecord, settings, true));
|
||||||
} else if (!address.isGroup() && settings.isPresent()) {
|
} else if (!address.isGroupOrCommunity() && settings.isPresent()) {
|
||||||
boolean isLocalNumber = address.serialize().equals(TextSecurePreferences.getLocalNumber(context));
|
boolean isLocalNumber = address.serialize().equals(TextSecurePreferences.getLocalNumber(context));
|
||||||
return Optional.of(new RecipientDetails(null, null, !TextUtils.isEmpty(settings.get().getSystemDisplayName()), isLocalNumber, settings.get(), null));
|
return Optional.of(new RecipientDetails(null, null, !TextUtils.isEmpty(settings.get().getSystemDisplayName()), isLocalNumber, settings.get(), null));
|
||||||
}
|
}
|
||||||
@ -104,7 +104,7 @@ class RecipientProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private @NonNull RecipientDetails getRecipientDetailsSync(Context context, @NonNull Address address, Optional<RecipientSettings> settings, Optional<GroupRecord> groupRecord, boolean nestedAsynchronous) {
|
private @NonNull RecipientDetails getRecipientDetailsSync(Context context, @NonNull Address address, Optional<RecipientSettings> settings, Optional<GroupRecord> groupRecord, boolean nestedAsynchronous) {
|
||||||
if (address.isGroup() && !address.isClosedGroupV2()) return getGroupRecipientDetails(context, address, groupRecord, settings, nestedAsynchronous);
|
if (address.isGroupOrCommunity() && !address.isGroupV2()) return getGroupRecipientDetails(context, address, groupRecord, settings, nestedAsynchronous);
|
||||||
else return getIndividualRecipientDetails(context, address, settings);
|
else return getIndividualRecipientDetails(context, address, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user