mirror of
https://github.com/oxen-io/session-android.git
synced 2025-04-03 21:25:39 +00:00
Cleanup
This commit is contained in:
parent
2e50dc08bb
commit
398b5bf7b4
@ -43,17 +43,14 @@ class ContextMenuList(recyclerView: RecyclerView, onItemClick: () -> Unit) {
|
|||||||
mappingAdapter.submitList(items.toAdapterItems())
|
mappingAdapter.submitList(items.toAdapterItems())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun List<ActionItem>.toAdapterItems(): List<DisplayItem> {
|
private fun List<ActionItem>.toAdapterItems(): List<DisplayItem> =
|
||||||
return this.mapIndexed { index, item ->
|
mapIndexed { index, item ->
|
||||||
val displayType: DisplayType = when {
|
when {
|
||||||
this.size == 1 -> DisplayType.ONLY
|
size == 1 -> DisplayType.ONLY
|
||||||
index == 0 -> DisplayType.TOP
|
index == 0 -> DisplayType.TOP
|
||||||
index == this.size - 1 -> DisplayType.BOTTOM
|
index == size - 1 -> DisplayType.BOTTOM
|
||||||
else -> DisplayType.MIDDLE
|
else -> DisplayType.MIDDLE
|
||||||
}
|
}.let { DisplayItem(item, it) }
|
||||||
|
|
||||||
DisplayItem(item, displayType)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class DisplayItem(
|
private data class DisplayItem(
|
||||||
@ -94,9 +91,7 @@ class ContextMenuList(recyclerView: RecyclerView, onItemClick: () -> Unit) {
|
|||||||
color?.let(title::setTextColor)
|
color?.let(title::setTextColor)
|
||||||
color?.let(subtitle::setTextColor)
|
color?.let(subtitle::setTextColor)
|
||||||
subtitle.isGone = true
|
subtitle.isGone = true
|
||||||
item.subtitle?.let {
|
item.subtitle?.let { startSubtitleJob(subtitle, it) }
|
||||||
startSubtitleJob(subtitle, it)
|
|
||||||
}
|
|
||||||
itemView.setOnClickListener {
|
itemView.setOnClickListener {
|
||||||
item.action.run()
|
item.action.run()
|
||||||
onItemClick()
|
onItemClick()
|
||||||
|
@ -5,9 +5,7 @@ import android.util.AttributeSet
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import androidx.annotation.DimenRes
|
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.view.marginEnd
|
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.ListAdapter
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
@ -21,6 +19,7 @@ import network.loki.messenger.libsession_util.util.ExpiryMode
|
|||||||
import org.session.libsession.messaging.messages.ExpirationConfiguration
|
import org.session.libsession.messaging.messages.ExpirationConfiguration
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroup
|
import org.session.libsession.messaging.open_groups.OpenGroup
|
||||||
import org.session.libsession.utilities.ExpirationUtil
|
import org.session.libsession.utilities.ExpirationUtil
|
||||||
|
import org.session.libsession.utilities.modifyLayoutParams
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionManagerUtilities
|
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionManagerUtilities
|
||||||
import org.thoughtcrime.securesms.database.GroupDatabase
|
import org.thoughtcrime.securesms.database.GroupDatabase
|
||||||
@ -28,12 +27,14 @@ import org.thoughtcrime.securesms.database.LokiAPIDatabase
|
|||||||
import org.thoughtcrime.securesms.util.DateUtils
|
import org.thoughtcrime.securesms.util.DateUtils
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.math.roundToInt
|
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class ConversationActionBarView : LinearLayout {
|
class ConversationActionBarView @JvmOverloads constructor(
|
||||||
|
context: Context,
|
||||||
private lateinit var binding: ViewConversationActionBarBinding
|
attrs: AttributeSet? = null,
|
||||||
|
defStyleAttr: Int = 0
|
||||||
|
) : LinearLayout(context, attrs, defStyleAttr) {
|
||||||
|
private val binding = ViewConversationActionBarBinding.inflate(LayoutInflater.from(context), this, true)
|
||||||
|
|
||||||
@Inject lateinit var lokiApiDb: LokiAPIDatabase
|
@Inject lateinit var lokiApiDb: LokiAPIDatabase
|
||||||
@Inject lateinit var groupDb: GroupDatabase
|
@Inject lateinit var groupDb: GroupDatabase
|
||||||
@ -46,12 +47,7 @@ class ConversationActionBarView : LinearLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(context: Context) : super(context) { initialize() }
|
init {
|
||||||
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { initialize() }
|
|
||||||
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { initialize() }
|
|
||||||
|
|
||||||
private fun initialize() {
|
|
||||||
binding = ViewConversationActionBarBinding.inflate(LayoutInflater.from(context), this, true)
|
|
||||||
var previousState: Int
|
var previousState: Int
|
||||||
var currentState = 0
|
var currentState = 0
|
||||||
binding.settingsPager.registerOnPageChangeCallback(object : OnPageChangeCallback() {
|
binding.settingsPager.registerOnPageChangeCallback(object : OnPageChangeCallback() {
|
||||||
@ -68,8 +64,7 @@ class ConversationActionBarView : LinearLayout {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
binding.settingsPager.adapter = settingsAdapter
|
binding.settingsPager.adapter = settingsAdapter
|
||||||
val mediator = TabLayoutMediator(binding.settingsTabLayout, binding.settingsPager) { _, _ -> }
|
TabLayoutMediator(binding.settingsTabLayout, binding.settingsPager) { _, _ -> }.attach()
|
||||||
mediator.attach()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun bind(
|
fun bind(
|
||||||
@ -80,42 +75,32 @@ class ConversationActionBarView : LinearLayout {
|
|||||||
openGroup: OpenGroup? = null
|
openGroup: OpenGroup? = null
|
||||||
) {
|
) {
|
||||||
this.delegate = delegate
|
this.delegate = delegate
|
||||||
@DimenRes val sizeID: Int = if (recipient.isClosedGroupRecipient) {
|
binding.profilePictureView.layoutParams = resources.getDimensionPixelSize(
|
||||||
R.dimen.medium_profile_picture_size
|
if (recipient.isClosedGroupRecipient) R.dimen.medium_profile_picture_size else R.dimen.small_profile_picture_size
|
||||||
} else {
|
).let { LayoutParams(it, it) }
|
||||||
R.dimen.small_profile_picture_size
|
|
||||||
}
|
|
||||||
val size = resources.getDimension(sizeID).roundToInt()
|
|
||||||
binding.profilePictureView.layoutParams = LayoutParams(size, size)
|
|
||||||
MentionManagerUtilities.populateUserPublicKeyCacheIfNeeded(threadId, context)
|
MentionManagerUtilities.populateUserPublicKeyCacheIfNeeded(threadId, context)
|
||||||
update(recipient, openGroup, config)
|
update(recipient, openGroup, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun update(recipient: Recipient, openGroup: OpenGroup? = null, config: ExpirationConfiguration? = null) {
|
fun update(recipient: Recipient, openGroup: OpenGroup? = null, config: ExpirationConfiguration? = null) {
|
||||||
binding.profilePictureView.update(recipient)
|
binding.profilePictureView.update(recipient)
|
||||||
binding.conversationTitleView.text = when {
|
binding.conversationTitleView.text = recipient.takeUnless { it.isLocalNumber }?.toShortString() ?: context.getString(R.string.note_to_self)
|
||||||
recipient.isLocalNumber -> context.getString(R.string.note_to_self)
|
|
||||||
else -> recipient.toShortString()
|
|
||||||
}
|
|
||||||
updateSubtitle(recipient, openGroup, config)
|
updateSubtitle(recipient, openGroup, config)
|
||||||
|
|
||||||
binding.conversationTitleContainer.apply {
|
binding.conversationTitleContainer.modifyLayoutParams<MarginLayoutParams> {
|
||||||
layoutParams = (layoutParams as MarginLayoutParams).apply {
|
|
||||||
marginEnd = if (recipient.showCallMenu()) 0 else binding.profilePictureView.width
|
marginEnd = if (recipient.showCallMenu()) 0 else binding.profilePictureView.width
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun updateSubtitle(recipient: Recipient, openGroup: OpenGroup? = null, config: ExpirationConfiguration? = null) {
|
fun updateSubtitle(recipient: Recipient, openGroup: OpenGroup? = null, config: ExpirationConfiguration? = null) {
|
||||||
val settings = mutableListOf<ConversationSetting>()
|
val settings = mutableListOf<ConversationSetting>()
|
||||||
if (config?.isEnabled == true) {
|
if (config?.isEnabled == true) {
|
||||||
val prefix = if (config.expiryMode is ExpiryMode.AfterRead) {
|
val prefix = when (config.expiryMode) {
|
||||||
context.getString(R.string.expiration_type_disappear_after_read)
|
is ExpiryMode.AfterRead -> R.string.expiration_type_disappear_after_read
|
||||||
} else {
|
else -> R.string.expiration_type_disappear_after_send
|
||||||
context.getString(R.string.expiration_type_disappear_after_send)
|
}.let(context::getString)
|
||||||
}
|
|
||||||
settings += ConversationSetting(
|
settings += ConversationSetting(
|
||||||
"$prefix - ${ExpirationUtil.getExpirationAbbreviatedDisplayValue(context, config.expiryMode.expirySeconds)}" ,
|
"$prefix - ${ExpirationUtil.getExpirationAbbreviatedDisplayValue(context, config.expiryMode.expirySeconds)}",
|
||||||
ConversationSettingType.EXPIRATION,
|
ConversationSettingType.EXPIRATION,
|
||||||
R.drawable.ic_timer,
|
R.drawable.ic_timer,
|
||||||
resources.getString(R.string.AccessibilityId_disappearing_messages_type_and_time)
|
resources.getString(R.string.AccessibilityId_disappearing_messages_type_and_time)
|
||||||
@ -123,11 +108,9 @@ class ConversationActionBarView : LinearLayout {
|
|||||||
}
|
}
|
||||||
if (recipient.isMuted) {
|
if (recipient.isMuted) {
|
||||||
settings += ConversationSetting(
|
settings += ConversationSetting(
|
||||||
if (recipient.mutedUntil != Long.MAX_VALUE) {
|
recipient.mutedUntil.takeUnless { it == Long.MAX_VALUE }
|
||||||
context.getString(R.string.ConversationActivity_muted_until_date, DateUtils.getFormattedDateTime(recipient.mutedUntil, "EEE, MMM d, yyyy HH:mm", Locale.getDefault()))
|
?.let { context.getString(R.string.ConversationActivity_muted_until_date, DateUtils.getFormattedDateTime(it, "EEE, MMM d, yyyy HH:mm", Locale.getDefault())) }
|
||||||
} else {
|
?: context.getString(R.string.ConversationActivity_muted_forever),
|
||||||
context.getString(R.string.ConversationActivity_muted_forever)
|
|
||||||
},
|
|
||||||
ConversationSettingType.NOTIFICATION,
|
ConversationSettingType.NOTIFICATION,
|
||||||
R.drawable.ic_outline_notifications_off_24
|
R.drawable.ic_outline_notifications_off_24
|
||||||
)
|
)
|
||||||
@ -174,23 +157,15 @@ class ConversationActionBarView : LinearLayout {
|
|||||||
binding.leftArrowImageView.isVisible = itemCount > 1
|
binding.leftArrowImageView.isVisible = itemCount > 1
|
||||||
binding.rightArrowImageView.isVisible = itemCount > 1
|
binding.rightArrowImageView.isVisible = itemCount > 1
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class SettingsDiffer: DiffUtil.ItemCallback<ConversationSetting>() {
|
class SettingsDiffer: DiffUtil.ItemCallback<ConversationSetting>() {
|
||||||
override fun areItemsTheSame(oldItem: ConversationSetting, newItem: ConversationSetting): Boolean {
|
override fun areItemsTheSame(oldItem: ConversationSetting, newItem: ConversationSetting): Boolean = oldItem.settingType === newItem.settingType
|
||||||
return oldItem.settingType === newItem.settingType
|
override fun areContentsTheSame(oldItem: ConversationSetting, newItem: ConversationSetting): Boolean = oldItem == newItem
|
||||||
}
|
|
||||||
override fun areContentsTheSame(oldItem: ConversationSetting, newItem: ConversationSetting): Boolean {
|
|
||||||
return oldItem == newItem
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun interface ConversationActionBarDelegate {
|
fun interface ConversationActionBarDelegate {
|
||||||
fun onDisappearingMessagesClicked()
|
fun onDisappearingMessagesClicked()
|
||||||
}
|
}
|
||||||
|
@ -45,10 +45,9 @@ class DisappearingMessages @Inject constructor(
|
|||||||
|
|
||||||
fun showFollowSettingDialog(context: Context, message: MessageRecord) = context.showSessionDialog {
|
fun showFollowSettingDialog(context: Context, message: MessageRecord) = context.showSessionDialog {
|
||||||
title(R.string.dialog_disappearing_messages_follow_setting_title)
|
title(R.string.dialog_disappearing_messages_follow_setting_title)
|
||||||
if (message.expiresIn == 0L) {
|
text(if (message.expiresIn == 0L) {
|
||||||
text(R.string.dialog_disappearing_messages_follow_setting_off_body)
|
context.getString(R.string.dialog_disappearing_messages_follow_setting_off_body)
|
||||||
} else {
|
} else {
|
||||||
text(
|
|
||||||
context.getString(
|
context.getString(
|
||||||
R.string.dialog_disappearing_messages_follow_setting_on_body,
|
R.string.dialog_disappearing_messages_follow_setting_on_body,
|
||||||
ExpirationUtil.getExpirationDisplayValue(
|
ExpirationUtil.getExpirationDisplayValue(
|
||||||
@ -57,8 +56,7 @@ class DisappearingMessages @Inject constructor(
|
|||||||
),
|
),
|
||||||
context.getExpirationTypeDisplayValue(message.isNotDisappearAfterRead)
|
context.getExpirationTypeDisplayValue(message.isNotDisappearAfterRead)
|
||||||
)
|
)
|
||||||
)
|
})
|
||||||
}
|
|
||||||
destructiveButton(
|
destructiveButton(
|
||||||
text = if (message.expiresIn == 0L) R.string.dialog_disappearing_messages_follow_setting_confirm else R.string.dialog_disappearing_messages_follow_setting_set,
|
text = if (message.expiresIn == 0L) R.string.dialog_disappearing_messages_follow_setting_confirm else R.string.dialog_disappearing_messages_follow_setting_set,
|
||||||
contentDescription = if (message.expiresIn == 0L) R.string.AccessibilityId_confirm else R.string.AccessibilityId_set_button
|
contentDescription = if (message.expiresIn == 0L) R.string.AccessibilityId_confirm else R.string.AccessibilityId_set_button
|
||||||
|
@ -60,8 +60,8 @@ class DisappearingMessagesActivity: PassphraseRequiredActionBarActivity() {
|
|||||||
|
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||||
viewModel.state.collect { state ->
|
viewModel.state.collect {
|
||||||
supportActionBar?.subtitle = state.subtitle(this@DisappearingMessagesActivity)
|
supportActionBar?.subtitle = it.subtitle(this@DisappearingMessagesActivity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,8 +63,8 @@ class DisappearingMessagesViewModel(
|
|||||||
val groupRecord = recipient?.takeIf { it.isClosedGroupRecipient }
|
val groupRecord = recipient?.takeIf { it.isClosedGroupRecipient }
|
||||||
?.run { groupDb.getGroup(address.toGroupString()).orNull() }
|
?.run { groupDb.getGroup(address.toGroupString()).orNull() }
|
||||||
|
|
||||||
_state.update { state ->
|
_state.update {
|
||||||
state.copy(
|
it.copy(
|
||||||
address = recipient?.address,
|
address = recipient?.address,
|
||||||
isGroup = groupRecord != null,
|
isGroup = groupRecord != null,
|
||||||
isNoteToSelf = recipient?.address?.serialize() == textSecurePreferences.getLocalNumber(),
|
isNoteToSelf = recipient?.address?.serialize() == textSecurePreferences.getLocalNumber(),
|
||||||
|
@ -470,7 +470,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
storage.markConversationAsRead(viewModel.threadId, it)
|
storage.markConversationAsRead(viewModel.threadId, it)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.d(TAG, "bufferedLastSeenChannel collectLatest", e)
|
Log.e(TAG, "bufferedLastSeenChannel collectLatest", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -486,8 +486,9 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
true,
|
true,
|
||||||
screenshotObserver
|
screenshotObserver
|
||||||
)
|
)
|
||||||
val recipient = viewModel.recipient ?: return
|
viewModel.run {
|
||||||
binding?.toolbarContent?.update(recipient, viewModel.openGroup, viewModel.expirationConfiguration)
|
binding?.toolbarContent?.update(recipient ?: return, openGroup, expirationConfiguration)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
@ -504,8 +505,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun dispatchIntent(body: (Context) -> Intent?) {
|
override fun dispatchIntent(body: (Context) -> Intent?) {
|
||||||
val intent = body(this) ?: return
|
body(this)?.let { push(it, false) }
|
||||||
push(intent, false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showDialog(dialogFragment: DialogFragment, tag: String?) {
|
override fun showDialog(dialogFragment: DialogFragment, tag: String?) {
|
||||||
@ -684,21 +684,18 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getLatestOpenGroupInfoIfNeeded() {
|
private fun getLatestOpenGroupInfoIfNeeded() {
|
||||||
viewModel.openGroup?.let { openGroup ->
|
val openGroup = viewModel.openGroup ?: return
|
||||||
OpenGroupApi.getMemberCount(openGroup.room, openGroup.server).successUi {
|
OpenGroupApi.getMemberCount(openGroup.room, openGroup.server) successUi {
|
||||||
binding?.toolbarContent?.updateSubtitle(viewModel.recipient!!, openGroup, viewModel.expirationConfiguration)
|
binding?.toolbarContent?.updateSubtitle(viewModel.recipient!!, openGroup, viewModel.expirationConfiguration)
|
||||||
maybeUpdateToolbar(viewModel.recipient!!)
|
maybeUpdateToolbar(viewModel.recipient!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// called from onCreate
|
// called from onCreate
|
||||||
private fun setUpBlockedBanner() {
|
private fun setUpBlockedBanner() {
|
||||||
val recipient = viewModel.recipient ?: return
|
val recipient = viewModel.recipient?.takeUnless { it.isGroupRecipient } ?: return
|
||||||
if (recipient.isGroupRecipient) { return }
|
|
||||||
val sessionID = recipient.address.toString()
|
val sessionID = recipient.address.toString()
|
||||||
val contact = sessionContactDb.getContactWithSessionID(sessionID)
|
val name = sessionContactDb.getContactWithSessionID(sessionID)?.displayName(Contact.ContactContext.REGULAR) ?: sessionID
|
||||||
val name = contact?.displayName(Contact.ContactContext.REGULAR) ?: sessionID
|
|
||||||
binding?.blockedBannerTextView?.text = resources.getString(R.string.activity_conversation_blocked_banner_text, name)
|
binding?.blockedBannerTextView?.text = resources.getString(R.string.activity_conversation_blocked_banner_text, name)
|
||||||
binding?.blockedBanner?.isVisible = recipient.isBlocked
|
binding?.blockedBanner?.isVisible = recipient.isBlocked
|
||||||
binding?.blockedBanner?.setOnClickListener { viewModel.unblock() }
|
binding?.blockedBanner?.setOnClickListener { viewModel.unblock() }
|
||||||
@ -790,7 +787,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
this
|
this
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
viewModel.recipient?.let { maybeUpdateToolbar(it) }
|
maybeUpdateToolbar(recipient)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -829,14 +826,9 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun showOrHideInputIfNeeded() {
|
private fun showOrHideInputIfNeeded() {
|
||||||
val recipient = viewModel.recipient
|
binding?.inputBar?.showInput = viewModel.recipient?.takeIf { it.isClosedGroupRecipient }
|
||||||
if (recipient != null && recipient.isClosedGroupRecipient) {
|
?.run { address.toGroupString().let(groupDb::getGroup).orNull()?.isActive == true }
|
||||||
val group = groupDb.getGroup(recipient.address.toGroupString()).orNull()
|
?: true
|
||||||
val isActive = (group?.isActive == true)
|
|
||||||
binding?.inputBar?.showInput = isActive
|
|
||||||
} else {
|
|
||||||
binding?.inputBar?.showInput = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setUpMessageRequestsBar() {
|
private fun setUpMessageRequestsBar() {
|
||||||
|
@ -27,6 +27,7 @@ import org.session.libsession.messaging.sending_receiving.attachments.Attachment
|
|||||||
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
|
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
|
||||||
import org.session.libsession.utilities.ThemeUtil
|
import org.session.libsession.utilities.ThemeUtil
|
||||||
import org.session.libsession.utilities.getColorFromAttr
|
import org.session.libsession.utilities.getColorFromAttr
|
||||||
|
import org.session.libsession.utilities.modifyLayoutParams
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
|
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
|
||||||
import org.thoughtcrime.securesms.conversation.v2.ModalUrlBottomSheet
|
import org.thoughtcrime.securesms.conversation.v2.ModalUrlBottomSheet
|
||||||
@ -198,9 +199,9 @@ class VisibleMessageContentView : ConstraintLayout {
|
|||||||
isStart = isStartOfMessageCluster,
|
isStart = isStartOfMessageCluster,
|
||||||
isEnd = isEndOfMessageCluster
|
isEnd = isEndOfMessageCluster
|
||||||
)
|
)
|
||||||
val layoutParams = binding.albumThumbnailView.root.layoutParams as ConstraintLayout.LayoutParams
|
binding.albumThumbnailView.root.modifyLayoutParams<ConstraintLayout.LayoutParams> {
|
||||||
layoutParams.horizontalBias = if (message.isOutgoing) 1f else 0f
|
horizontalBias = if (message.isOutgoing) 1f else 0f
|
||||||
binding.albumThumbnailView.root.layoutParams = layoutParams
|
}
|
||||||
onContentClick.add { event ->
|
onContentClick.add { event ->
|
||||||
binding.albumThumbnailView.root.calculateHitObject(event, message, thread, onAttachmentNeedsDownload)
|
binding.albumThumbnailView.root.calculateHitObject(event, message, thread, onAttachmentNeedsDownload)
|
||||||
}
|
}
|
||||||
@ -233,9 +234,9 @@ class VisibleMessageContentView : ConstraintLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val layoutParams = binding.contentParent.layoutParams as ConstraintLayout.LayoutParams
|
binding.contentParent.modifyLayoutParams<ConstraintLayout.LayoutParams> {
|
||||||
layoutParams.horizontalBias = if (message.isOutgoing) 1f else 0f
|
horizontalBias = if (message.isOutgoing) 1f else 0f
|
||||||
binding.contentParent.layoutParams = layoutParams
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val onContentClick: MutableList<((event: MotionEvent) -> Unit)> = mutableListOf()
|
private val onContentClick: MutableList<((event: MotionEvent) -> Unit)> = mutableListOf()
|
||||||
@ -306,17 +307,9 @@ class VisibleMessageContentView : ConstraintLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ColorInt
|
@ColorInt
|
||||||
fun getTextColor(context: Context, message: MessageRecord): Int {
|
fun getTextColor(context: Context, message: MessageRecord): Int = context.getColorFromAttr(
|
||||||
val colorAttribute = if (message.isOutgoing) {
|
if (message.isOutgoing) R.attr.message_sent_text_color else R.attr.message_received_text_color
|
||||||
// sent
|
)
|
||||||
R.attr.message_sent_text_color
|
|
||||||
} else {
|
|
||||||
// received
|
|
||||||
R.attr.message_received_text_color
|
|
||||||
}
|
|
||||||
return context.getColorFromAttr(colorAttribute)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ import org.session.libsession.snode.SnodeAPI
|
|||||||
import org.session.libsession.utilities.Address
|
import org.session.libsession.utilities.Address
|
||||||
import org.session.libsession.utilities.ViewUtil
|
import org.session.libsession.utilities.ViewUtil
|
||||||
import org.session.libsession.utilities.getColorFromAttr
|
import org.session.libsession.utilities.getColorFromAttr
|
||||||
|
import org.session.libsession.utilities.modifyLayoutParams
|
||||||
import org.session.libsignal.utilities.IdPrefix
|
import org.session.libsignal.utilities.IdPrefix
|
||||||
import org.session.libsignal.utilities.ThreadUtils
|
import org.session.libsignal.utilities.ThreadUtils
|
||||||
import org.thoughtcrime.securesms.ApplicationContext
|
import org.thoughtcrime.securesms.ApplicationContext
|
||||||
@ -243,14 +244,12 @@ class VisibleMessageView : LinearLayout {
|
|||||||
private fun showStatusMessage(message: MessageRecord) {
|
private fun showStatusMessage(message: MessageRecord) {
|
||||||
val disappearing = message.expiresIn > 0
|
val disappearing = message.expiresIn > 0
|
||||||
|
|
||||||
binding.messageInnerLayout.apply {
|
binding.messageInnerLayout.modifyLayoutParams<FrameLayout.LayoutParams> {
|
||||||
layoutParams = (layoutParams as FrameLayout.LayoutParams)
|
gravity = if (message.isOutgoing) Gravity.END else Gravity.START
|
||||||
.apply { gravity = if (message.isOutgoing) Gravity.END else Gravity.START }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.statusContainer.apply {
|
binding.statusContainer.modifyLayoutParams<ConstraintLayout.LayoutParams> {
|
||||||
layoutParams = (layoutParams as ConstraintLayout.LayoutParams)
|
horizontalBias = if (message.isOutgoing) 1f else 0f
|
||||||
.apply { horizontalBias = if (message.isOutgoing) 1f else 0f }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.expirationTimerView.isGone = true
|
binding.expirationTimerView.isGone = true
|
||||||
@ -356,7 +355,7 @@ class VisibleMessageView : LinearLayout {
|
|||||||
swipeToReplyIconRect.right = right
|
swipeToReplyIconRect.right = right
|
||||||
swipeToReplyIconRect.bottom = bottom
|
swipeToReplyIconRect.bottom = bottom
|
||||||
|
|
||||||
if (translationX < 0 /*&& !binding.expirationTimerView.isVisible*/) {
|
if (translationX < 0 && !binding.expirationTimerView.isVisible) {
|
||||||
val threshold = swipeToReplyThreshold
|
val threshold = swipeToReplyThreshold
|
||||||
swipeToReplyIcon.bounds = swipeToReplyIconRect
|
swipeToReplyIcon.bounds = swipeToReplyIconRect
|
||||||
swipeToReplyIcon.alpha = (255.0f * (min(abs(translationX), threshold) / threshold)).roundToInt()
|
swipeToReplyIcon.alpha = (255.0f * (min(abs(translationX), threshold) / threshold)).roundToInt()
|
||||||
|
@ -425,12 +425,10 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
|||||||
database.endTransaction()
|
database.endTransaction()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getLastLegacySenderAddress(threadRecipientAddress: String): String? {
|
override fun getLastLegacySenderAddress(threadRecipientAddress: String): String? =
|
||||||
val database = databaseHelper.readableDatabase
|
databaseHelper.readableDatabase.get(LAST_LEGACY_MESSAGE_TABLE, LEGACY_THREAD_RECIPIENT_QUERY, wrap(threadRecipientAddress)) { cursor ->
|
||||||
return database.get(LAST_LEGACY_MESSAGE_TABLE, LEGACY_THREAD_RECIPIENT_QUERY, wrap(threadRecipientAddress)) { cursor ->
|
|
||||||
cursor.getString(LAST_LEGACY_SENDER_RECIPIENT)
|
cursor.getString(LAST_LEGACY_SENDER_RECIPIENT)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun setLastLegacySenderAddress(
|
override fun setLastLegacySenderAddress(
|
||||||
threadRecipientAddress: String,
|
threadRecipientAddress: String,
|
||||||
|
@ -305,8 +305,6 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun markExpireStarted(messageId: Long, startedTimestamp: Long) {
|
override fun markExpireStarted(messageId: Long, startedTimestamp: Long) {
|
||||||
Log.d(TAG, "markExpireStarted() called with: messageId = $messageId, startedTimestamp = $startedTimestamp")
|
|
||||||
|
|
||||||
val contentValues = ContentValues()
|
val contentValues = ContentValues()
|
||||||
contentValues.put(EXPIRE_STARTED, startedTimestamp)
|
contentValues.put(EXPIRE_STARTED, startedTimestamp)
|
||||||
val db = databaseHelper.writableDatabase
|
val db = databaseHelper.writableDatabase
|
||||||
@ -886,8 +884,6 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun deleteMessage(messageId: Long): Boolean {
|
override fun deleteMessage(messageId: Long): Boolean {
|
||||||
Log.d(TAG, "deleteMessage() called with: messageId = $messageId")
|
|
||||||
|
|
||||||
val threadId = getThreadIdForMessage(messageId)
|
val threadId = getThreadIdForMessage(messageId)
|
||||||
val attachmentDatabase = get(context).attachmentDatabase()
|
val attachmentDatabase = get(context).attachmentDatabase()
|
||||||
queue(Runnable { attachmentDatabase.deleteAttachmentsForMessage(messageId) })
|
queue(Runnable { attachmentDatabase.deleteAttachmentsForMessage(messageId) })
|
||||||
@ -1405,8 +1401,6 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
|
|
||||||
private val TAG = MmsDatabase::class.java.simpleName
|
private val TAG = MmsDatabase::class.java.simpleName
|
||||||
const val TABLE_NAME: String = "mms"
|
const val TABLE_NAME: String = "mms"
|
||||||
const val DATE_SENT: String = "date"
|
const val DATE_SENT: String = "date"
|
||||||
|
@ -14,6 +14,7 @@ import network.loki.messenger.libsession_util.util.Conversation
|
|||||||
import network.loki.messenger.libsession_util.util.ExpiryMode
|
import network.loki.messenger.libsession_util.util.ExpiryMode
|
||||||
import network.loki.messenger.libsession_util.util.GroupInfo
|
import network.loki.messenger.libsession_util.util.GroupInfo
|
||||||
import network.loki.messenger.libsession_util.util.UserPic
|
import network.loki.messenger.libsession_util.util.UserPic
|
||||||
|
import network.loki.messenger.libsession_util.util.afterSend
|
||||||
import org.session.libsession.avatars.AvatarHelper
|
import org.session.libsession.avatars.AvatarHelper
|
||||||
import org.session.libsession.database.StorageProtocol
|
import org.session.libsession.database.StorageProtocol
|
||||||
import org.session.libsession.messaging.BlindedIdMapping
|
import org.session.libsession.messaging.BlindedIdMapping
|
||||||
@ -498,18 +499,13 @@ open class Storage(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set or reset the shared library to use latest expiration config
|
// Set or reset the shared library to use latest expiration config
|
||||||
getThreadId(recipient)?.let { ourThread ->
|
getThreadId(recipient)?.let {
|
||||||
val currentExpiration = getExpirationConfiguration(ourThread)
|
setExpirationConfiguration(
|
||||||
if (currentExpiration != null && currentExpiration.updatedTimestampMs > messageTimestamp) {
|
getExpirationConfiguration(it)?.takeIf { it.updatedTimestampMs > messageTimestamp } ?: ExpirationConfiguration(it, userProfile.getNtsExpiry(), messageTimestamp)
|
||||||
setExpirationConfiguration(currentExpiration)
|
)
|
||||||
} else {
|
|
||||||
val expiration = ExpirationConfiguration(ourThread, userProfile.getNtsExpiry(), messageTimestamp)
|
|
||||||
setExpirationConfiguration(expiration)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateContacts(contacts: Contacts, messageTimestamp: Long) {
|
private fun updateContacts(contacts: Contacts, messageTimestamp: Long) {
|
||||||
val extracted = contacts.all().toList()
|
val extracted = contacts.all().toList()
|
||||||
addLibSessionContacts(extracted, messageTimestamp)
|
addLibSessionContacts(extracted, messageTimestamp)
|
||||||
@ -635,20 +631,11 @@ open class Storage(
|
|||||||
// Start polling
|
// Start polling
|
||||||
ClosedGroupPollerV2.shared.startPolling(group.sessionId)
|
ClosedGroupPollerV2.shared.startPolling(group.sessionId)
|
||||||
}
|
}
|
||||||
getThreadId(Address.fromSerialized(groupId))?.let { conversationThreadId ->
|
getThreadId(Address.fromSerialized(groupId))?.let {
|
||||||
|
setExpirationConfiguration(
|
||||||
val currentExpiration = getExpirationConfiguration(conversationThreadId)
|
getExpirationConfiguration(it)?.takeIf { it.updatedTimestampMs > messageTimestamp }
|
||||||
if (currentExpiration != null && currentExpiration.updatedTimestampMs > messageTimestamp) {
|
?: ExpirationConfiguration(it, afterSend(group.disappearingTimer), messageTimestamp)
|
||||||
setExpirationConfiguration(currentExpiration)
|
|
||||||
} else {
|
|
||||||
val mode =
|
|
||||||
if (group.disappearingTimer == 0L) ExpiryMode.NONE
|
|
||||||
else ExpiryMode.AfterSend(group.disappearingTimer)
|
|
||||||
val newConfig = ExpirationConfiguration(
|
|
||||||
conversationThreadId, mode, messageTimestamp
|
|
||||||
)
|
)
|
||||||
setExpirationConfiguration(newConfig)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1213,18 +1200,11 @@ open class Storage(
|
|||||||
setPinned(conversationThreadId, contact.priority == PRIORITY_PINNED)
|
setPinned(conversationThreadId, contact.priority == PRIORITY_PINNED)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getThreadId(recipient)?.let { conversationThreadId ->
|
getThreadId(recipient)?.let {
|
||||||
val currentExpiration = getExpirationConfiguration(conversationThreadId)
|
setExpirationConfiguration(
|
||||||
if (currentExpiration != null && currentExpiration.updatedTimestampMs > timestamp) {
|
getExpirationConfiguration(it)?.takeIf { it.updatedTimestampMs > timestamp }
|
||||||
setExpirationConfiguration(currentExpiration)
|
?: ExpirationConfiguration(it, contact.expiryMode, timestamp)
|
||||||
} else {
|
|
||||||
val expiration = ExpirationConfiguration(
|
|
||||||
conversationThreadId,
|
|
||||||
contact.expiryMode,
|
|
||||||
timestamp
|
|
||||||
)
|
)
|
||||||
setExpirationConfiguration(expiration)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
setRecipientHash(recipient, contact.hashCode().toString())
|
setRecipientHash(recipient, contact.hashCode().toString())
|
||||||
}
|
}
|
||||||
@ -1347,19 +1327,18 @@ open class Storage(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun deleteConversation(threadID: Long) {
|
override fun deleteConversation(threadID: Long) {
|
||||||
val recipient = getRecipientForThread(threadID)
|
|
||||||
val threadDB = DatabaseComponent.get(context).threadDatabase()
|
val threadDB = DatabaseComponent.get(context).threadDatabase()
|
||||||
val groupDB = DatabaseComponent.get(context).groupDatabase()
|
val groupDB = DatabaseComponent.get(context).groupDatabase()
|
||||||
threadDB.deleteConversation(threadID)
|
threadDB.deleteConversation(threadID)
|
||||||
if (recipient != null) {
|
val recipient = getRecipientForThread(threadID) ?: return
|
||||||
if (recipient.isContactRecipient) {
|
when {
|
||||||
|
recipient.isContactRecipient -> {
|
||||||
if (recipient.isLocalNumber) return
|
if (recipient.isLocalNumber) return
|
||||||
val contacts = configFactory.contacts ?: return
|
val contacts = configFactory.contacts ?: return
|
||||||
contacts.upsertContact(recipient.address.serialize()) {
|
contacts.upsertContact(recipient.address.serialize()) { priority = PRIORITY_HIDDEN }
|
||||||
this.priority = PRIORITY_HIDDEN
|
|
||||||
}
|
|
||||||
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(context)
|
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(context)
|
||||||
} else if (recipient.isClosedGroupRecipient) {
|
}
|
||||||
|
recipient.isClosedGroupRecipient -> {
|
||||||
// TODO: handle closed group
|
// TODO: handle closed group
|
||||||
val volatile = configFactory.convoVolatile ?: return
|
val volatile = configFactory.convoVolatile ?: return
|
||||||
val groups = configFactory.userGroups ?: return
|
val groups = configFactory.userGroups ?: return
|
||||||
|
@ -28,10 +28,8 @@ class MarkReadReceiver : BroadcastReceiver() {
|
|||||||
@SuppressLint("StaticFieldLeak")
|
@SuppressLint("StaticFieldLeak")
|
||||||
override fun onReceive(context: Context, intent: Intent) {
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
if (CLEAR_ACTION != intent.action) return
|
if (CLEAR_ACTION != intent.action) return
|
||||||
val threadIds = intent.getLongArrayExtra(THREAD_IDS_EXTRA)
|
val threadIds = intent.getLongArrayExtra(THREAD_IDS_EXTRA) ?: return
|
||||||
if (threadIds != null) {
|
NotificationManagerCompat.from(context).cancel(intent.getIntExtra(NOTIFICATION_ID_EXTRA, -1))
|
||||||
NotificationManagerCompat.from(context)
|
|
||||||
.cancel(intent.getIntExtra(NOTIFICATION_ID_EXTRA, -1))
|
|
||||||
object : AsyncTask<Void?, Void?, Void?>() {
|
object : AsyncTask<Void?, Void?, Void?>() {
|
||||||
override fun doInBackground(vararg params: Void?): Void? {
|
override fun doInBackground(vararg params: Void?): Void? {
|
||||||
val currentTime = nowWithOffset
|
val currentTime = nowWithOffset
|
||||||
@ -43,7 +41,6 @@ class MarkReadReceiver : BroadcastReceiver() {
|
|||||||
}
|
}
|
||||||
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)
|
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val TAG = MarkReadReceiver::class.java.simpleName
|
private val TAG = MarkReadReceiver::class.java.simpleName
|
||||||
@ -111,7 +108,8 @@ class MarkReadReceiver : BroadcastReceiver() {
|
|||||||
context: Context,
|
context: Context,
|
||||||
markedReadMessages: List<MarkedMessageInfo>
|
markedReadMessages: List<MarkedMessageInfo>
|
||||||
) {
|
) {
|
||||||
if (isReadReceiptsEnabled(context)) {
|
if (!isReadReceiptsEnabled(context)) return
|
||||||
|
|
||||||
markedReadMessages.map { it.syncMessageId }
|
markedReadMessages.map { it.syncMessageId }
|
||||||
.filter { shouldSendReadReceipt(Recipient.from(context, it.address, false)) }
|
.filter { shouldSendReadReceipt(Recipient.from(context, it.address, false)) }
|
||||||
.groupBy { it.address }
|
.groupBy { it.address }
|
||||||
@ -122,7 +120,6 @@ class MarkReadReceiver : BroadcastReceiver() {
|
|||||||
.let { send(it, address) }
|
.let { send(it, address) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun fetchUpdatedExpiriesAndScheduleDeletion(
|
private fun fetchUpdatedExpiriesAndScheduleDeletion(
|
||||||
context: Context,
|
context: Context,
|
||||||
|
@ -154,7 +154,7 @@ class DefaultConversationRepository @Inject constructor(
|
|||||||
openGroupInvitation.url = openGroup.joinURL
|
openGroupInvitation.url = openGroup.joinURL
|
||||||
message.openGroupInvitation = openGroupInvitation
|
message.openGroupInvitation = openGroupInvitation
|
||||||
val expirationConfig = storage.getExpirationConfiguration(threadId)
|
val expirationConfig = storage.getExpirationConfiguration(threadId)
|
||||||
val expiresInMillis = (expirationConfig?.expiryMode?.expiryMillis ?: 0)
|
val expiresInMillis = expirationConfig?.expiryMode?.expiryMillis ?: 0
|
||||||
val expireStartedAt = if (expirationConfig?.expiryMode is ExpiryMode.AfterSend) message.sentTimestamp!! else 0
|
val expireStartedAt = if (expirationConfig?.expiryMode is ExpiryMode.AfterSend) message.sentTimestamp!! else 0
|
||||||
val outgoingTextMessage = OutgoingTextMessage.fromOpenGroupInvitation(
|
val outgoingTextMessage = OutgoingTextMessage.fromOpenGroupInvitation(
|
||||||
openGroupInvitation,
|
openGroupInvitation,
|
||||||
@ -225,14 +225,10 @@ class DefaultConversationRepository @Inject constructor(
|
|||||||
override fun buildUnsendRequest(recipient: Recipient, message: MessageRecord): UnsendRequest? {
|
override fun buildUnsendRequest(recipient: Recipient, message: MessageRecord): UnsendRequest? {
|
||||||
if (recipient.isOpenGroupRecipient) return null
|
if (recipient.isOpenGroupRecipient) return null
|
||||||
messageDataProvider.getServerHashForMessage(message.id, message.isMms) ?: return null
|
messageDataProvider.getServerHashForMessage(message.id, message.isMms) ?: return null
|
||||||
return UnsendRequest().apply {
|
return UnsendRequest(
|
||||||
author = if (message.isOutgoing) {
|
author = message.takeUnless { it.isOutgoing }?.run { individualRecipient.address.contactIdentifier() } ?: textSecurePreferences.getLocalNumber(),
|
||||||
textSecurePreferences.getLocalNumber()
|
|
||||||
} else {
|
|
||||||
message.individualRecipient.address.contactIdentifier()
|
|
||||||
}
|
|
||||||
timestamp = message.timestamp
|
timestamp = message.timestamp
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun deleteMessageWithoutUnsendRequest(
|
override suspend fun deleteMessageWithoutUnsendRequest(
|
||||||
|
@ -48,8 +48,6 @@ class ExpiringMessageManager(context: Context) : MessageExpirationManagerProtoco
|
|||||||
private fun getDatabase(mms: Boolean) = if (mms) mmsDatabase else smsDatabase
|
private fun getDatabase(mms: Boolean) = if (mms) mmsDatabase else smsDatabase
|
||||||
|
|
||||||
fun scheduleDeletion(id: Long, mms: Boolean, startedAtTimestamp: Long, expiresInMillis: Long) {
|
fun scheduleDeletion(id: Long, mms: Boolean, startedAtTimestamp: Long, expiresInMillis: Long) {
|
||||||
Log.d(TAG, "scheduleDeletion() called with: id = $id, mms = $mms, startedAtTimestamp = $startedAtTimestamp, expiresInMillis = $expiresInMillis")
|
|
||||||
|
|
||||||
if (startedAtTimestamp <= 0) return
|
if (startedAtTimestamp <= 0) return
|
||||||
|
|
||||||
val expiresAtMillis = startedAtTimestamp + expiresInMillis
|
val expiresAtMillis = startedAtTimestamp + expiresInMillis
|
||||||
@ -67,7 +65,6 @@ class ExpiringMessageManager(context: Context) : MessageExpirationManagerProtoco
|
|||||||
message: ExpirationTimerUpdate,
|
message: ExpirationTimerUpdate,
|
||||||
expireStartedAt: Long
|
expireStartedAt: Long
|
||||||
) {
|
) {
|
||||||
Log.d(TAG, "insertIncomingExpirationTimerMessage() called with: message = $message, expireStartedAt = $expireStartedAt")
|
|
||||||
val senderPublicKey = message.sender
|
val senderPublicKey = message.sender
|
||||||
val sentTimestamp = message.sentTimestamp
|
val sentTimestamp = message.sentTimestamp
|
||||||
val groupId = message.groupPublicKey
|
val groupId = message.groupPublicKey
|
||||||
@ -118,7 +115,6 @@ class ExpiringMessageManager(context: Context) : MessageExpirationManagerProtoco
|
|||||||
message: ExpirationTimerUpdate,
|
message: ExpirationTimerUpdate,
|
||||||
expireStartedAt: Long
|
expireStartedAt: Long
|
||||||
) {
|
) {
|
||||||
Log.d(TAG, "insertOutgoingExpirationTimerMessage() called with: message = $message, expireStartedAt = $expireStartedAt")
|
|
||||||
val sentTimestamp = message.sentTimestamp
|
val sentTimestamp = message.sentTimestamp
|
||||||
val groupId = message.groupPublicKey
|
val groupId = message.groupPublicKey
|
||||||
val duration = message.expiryMode.expiryMillis
|
val duration = message.expiryMode.expiryMillis
|
||||||
@ -152,7 +148,6 @@ class ExpiringMessageManager(context: Context) : MessageExpirationManagerProtoco
|
|||||||
|
|
||||||
override fun insertExpirationTimerMessage(message: ExpirationTimerUpdate) {
|
override fun insertExpirationTimerMessage(message: ExpirationTimerUpdate) {
|
||||||
val expiryMode: ExpiryMode = message.expiryMode
|
val expiryMode: ExpiryMode = message.expiryMode
|
||||||
Log.d(TAG, "setExpirationTimer() called with: message = $message, expiryMode = $expiryMode")
|
|
||||||
|
|
||||||
val userPublicKey = getLocalNumber(context)
|
val userPublicKey = getLocalNumber(context)
|
||||||
val senderPublicKey = message.sender
|
val senderPublicKey = message.sender
|
||||||
@ -171,12 +166,10 @@ class ExpiringMessageManager(context: Context) : MessageExpirationManagerProtoco
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun startAnyExpiration(timestamp: Long, author: String, expireStartedAt: Long) {
|
override fun startAnyExpiration(timestamp: Long, author: String, expireStartedAt: Long) {
|
||||||
Log.d(TAG, "startAnyExpiration() called with: timestamp = $timestamp, author = $author, expireStartedAt = $expireStartedAt")
|
|
||||||
|
|
||||||
mmsSmsDatabase.getMessageFor(timestamp, author)?.run {
|
mmsSmsDatabase.getMessageFor(timestamp, author)?.run {
|
||||||
getDatabase(isMms()).markExpireStarted(getId(), expireStartedAt)
|
getDatabase(isMms()).markExpireStarted(getId(), expireStartedAt)
|
||||||
scheduleDeletion(getId(), isMms(), expireStartedAt, expiresIn)
|
scheduleDeletion(getId(), isMms(), expireStartedAt, expiresIn)
|
||||||
} ?: Log.e(TAG, "no message record!!!")
|
} ?: Log.e(TAG, "no message record!")
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class LoadTask : Runnable {
|
private inner class LoadTask : Runnable {
|
||||||
|
@ -14,3 +14,5 @@ sealed class ExpiryMode(val expirySeconds: Long) {
|
|||||||
|
|
||||||
fun coerceSendToRead(coerce: Boolean = true) = if (coerce && this is AfterSend) AfterRead(expirySeconds) else this
|
fun coerceSendToRead(coerce: Boolean = true) = if (coerce && this is AfterSend) AfterRead(expirySeconds) else this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun afterSend(seconds: Long) = seconds.takeIf { it > 0 }?.let(ExpiryMode::AfterSend) ?: ExpiryMode.NONE
|
@ -144,7 +144,6 @@ class BatchMessageReceiveJob(
|
|||||||
runBlocking(Dispatchers.IO) {
|
runBlocking(Dispatchers.IO) {
|
||||||
|
|
||||||
fun processMessages(threadId: Long, messages: List<ParsedMessage>) = async {
|
fun processMessages(threadId: Long, messages: List<ParsedMessage>) = async {
|
||||||
Log.d(TAG, "processMessages() threadId = $threadId, messages = $messages")
|
|
||||||
// The LinkedHashMap should preserve insertion order
|
// The LinkedHashMap should preserve insertion order
|
||||||
val messageIds = linkedMapOf<Long, Pair<Boolean, Boolean>>()
|
val messageIds = linkedMapOf<Long, Pair<Boolean, Boolean>>()
|
||||||
val myLastSeen = storage.getLastSeen(threadId)
|
val myLastSeen = storage.getLastSeen(threadId)
|
||||||
|
@ -6,7 +6,6 @@ import org.session.libsession.database.StorageProtocol
|
|||||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||||
import org.session.libsession.messaging.messages.control.ExpirationTimerUpdate
|
import org.session.libsession.messaging.messages.control.ExpirationTimerUpdate
|
||||||
import org.session.libsession.messaging.messages.visible.VisibleMessage
|
import org.session.libsession.messaging.messages.visible.VisibleMessage
|
||||||
import org.session.libsession.utilities.Address
|
|
||||||
import org.session.libsession.utilities.GroupUtil
|
import org.session.libsession.utilities.GroupUtil
|
||||||
import org.session.libsignal.protos.SignalServiceProtos
|
import org.session.libsignal.protos.SignalServiceProtos
|
||||||
import org.session.libsignal.protos.SignalServiceProtos.Content.ExpirationType
|
import org.session.libsignal.protos.SignalServiceProtos.Content.ExpirationType
|
||||||
@ -43,13 +42,11 @@ abstract class Message {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun isValid(): Boolean {
|
open fun isValid(): Boolean =
|
||||||
val sentTimestamp = sentTimestamp
|
sentTimestamp?.let { it > 0 } == true
|
||||||
if (sentTimestamp != null && sentTimestamp <= 0) { return false }
|
&& receivedTimestamp?.let { it > 0 } == true
|
||||||
val receivedTimestamp = receivedTimestamp
|
&& sender != null
|
||||||
if (receivedTimestamp != null && receivedTimestamp <= 0) { return false }
|
&& recipient != null
|
||||||
return sender != null && recipient != null
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract fun toProto(): SignalServiceProtos.Content?
|
abstract fun toProto(): SignalServiceProtos.Content?
|
||||||
|
|
||||||
@ -60,18 +57,17 @@ abstract class Message {
|
|||||||
}.build()
|
}.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun SignalServiceProtos.Content.Builder.applyExpiryMode(): SignalServiceProtos.Content.Builder {
|
fun SignalServiceProtos.Content.Builder.applyExpiryMode() = apply {
|
||||||
expirationTimer = expiryMode.expirySeconds.toInt()
|
expirationTimer = expiryMode.expirySeconds.toInt()
|
||||||
expirationType = when (expiryMode) {
|
expirationType = when (expiryMode) {
|
||||||
is ExpiryMode.AfterSend -> ExpirationType.DELETE_AFTER_SEND
|
is ExpiryMode.AfterSend -> ExpirationType.DELETE_AFTER_SEND
|
||||||
is ExpiryMode.AfterRead -> ExpirationType.DELETE_AFTER_READ
|
is ExpiryMode.AfterRead -> ExpirationType.DELETE_AFTER_READ
|
||||||
else -> ExpirationType.UNKNOWN
|
else -> ExpirationType.UNKNOWN
|
||||||
}
|
}
|
||||||
return this
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified M: Message> M.copyExpiration(proto: SignalServiceProtos.Content): M {
|
inline fun <reified M: Message> M.copyExpiration(proto: SignalServiceProtos.Content): M = apply {
|
||||||
(proto.takeIf { it.hasExpirationTimer() }?.expirationTimer ?: proto.dataMessage?.expireTimer)?.let { duration ->
|
(proto.takeIf { it.hasExpirationTimer() }?.expirationTimer ?: proto.dataMessage?.expireTimer)?.let { duration ->
|
||||||
expiryMode = when (proto.expirationType.takeIf { duration > 0 }) {
|
expiryMode = when (proto.expirationType.takeIf { duration > 0 }) {
|
||||||
ExpirationType.DELETE_AFTER_SEND -> ExpiryMode.AfterSend(duration.toLong())
|
ExpirationType.DELETE_AFTER_SEND -> ExpiryMode.AfterSend(duration.toLong())
|
||||||
@ -79,9 +75,8 @@ inline fun <reified M: Message> M.copyExpiration(proto: SignalServiceProtos.Cont
|
|||||||
else -> ExpiryMode.NONE
|
else -> ExpiryMode.NONE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun SignalServiceProtos.Content.expiryMode(): ExpiryMode =
|
fun SignalServiceProtos.Content.expiryMode(): ExpiryMode =
|
||||||
(takeIf { it.hasExpirationTimer() }?.expirationTimer ?: dataMessage?.expireTimer)?.let { duration ->
|
(takeIf { it.hasExpirationTimer() }?.expirationTimer ?: dataMessage?.expireTimer)?.let { duration ->
|
||||||
when (expirationType.takeIf { duration > 0 }) {
|
when (expirationType.takeIf { duration > 0 }) {
|
||||||
@ -94,8 +89,7 @@ fun SignalServiceProtos.Content.expiryMode(): ExpiryMode =
|
|||||||
/**
|
/**
|
||||||
* Apply ExpiryMode from the current setting.
|
* Apply ExpiryMode from the current setting.
|
||||||
*/
|
*/
|
||||||
inline fun <reified M: Message> M.applyExpiryMode(thread: Long): M {
|
inline fun <reified M: Message> M.applyExpiryMode(thread: Long): M = apply {
|
||||||
val storage = MessagingModuleConfiguration.shared.storage
|
val storage = MessagingModuleConfiguration.shared.storage
|
||||||
expiryMode = storage.getExpirationConfiguration(thread)?.expiryMode?.coerceSendToRead(coerceDisappearAfterSendToRead) ?: ExpiryMode.NONE
|
expiryMode = storage.getExpirationConfiguration(thread)?.expiryMode?.coerceSendToRead(coerceDisappearAfterSendToRead) ?: ExpiryMode.NONE
|
||||||
return this
|
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,7 @@ import org.session.libsession.messaging.messages.copyExpiration
|
|||||||
import org.session.libsignal.protos.SignalServiceProtos
|
import org.session.libsignal.protos.SignalServiceProtos
|
||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
|
|
||||||
class UnsendRequest(): ControlMessage() {
|
class UnsendRequest(var timestamp: Long? = null, var author: String? = null): ControlMessage() {
|
||||||
var timestamp: Long? = null
|
|
||||||
var author: String? = null
|
|
||||||
|
|
||||||
override val isSelfSendValid: Boolean = true
|
override val isSelfSendValid: Boolean = true
|
||||||
|
|
||||||
@ -20,18 +18,8 @@ class UnsendRequest(): ControlMessage() {
|
|||||||
companion object {
|
companion object {
|
||||||
const val TAG = "UnsendRequest"
|
const val TAG = "UnsendRequest"
|
||||||
|
|
||||||
fun fromProto(proto: SignalServiceProtos.Content): UnsendRequest? {
|
fun fromProto(proto: SignalServiceProtos.Content): UnsendRequest? =
|
||||||
val unsendRequestProto = if (proto.hasUnsendRequest()) proto.unsendRequest else return null
|
proto.takeIf { it.hasUnsendRequest() }?.unsendRequest?.run { UnsendRequest(timestamp, author) }?.copyExpiration(proto)
|
||||||
val timestamp = unsendRequestProto.timestamp
|
|
||||||
val author = unsendRequestProto.author
|
|
||||||
return UnsendRequest(timestamp, author)
|
|
||||||
.copyExpiration(proto)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(timestamp: Long, author: String) : this() {
|
|
||||||
this.timestamp = timestamp
|
|
||||||
this.author = author
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toProto(): SignalServiceProtos.Content? {
|
override fun toProto(): SignalServiceProtos.Content? {
|
||||||
|
@ -108,27 +108,23 @@ object GroupUtil {
|
|||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@Throws(IOException::class)
|
@Throws(IOException::class)
|
||||||
fun doubleDecodeGroupId(groupID: String): String {
|
fun doubleDecodeGroupId(groupID: String): String =
|
||||||
return Hex.toStringCondensed(getDecodedGroupIDAsData(getDecodedGroupID(groupID)))
|
Hex.toStringCondensed(getDecodedGroupIDAsData(getDecodedGroupID(groupID)))
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun addressToGroupSessionId(address: Address): String {
|
fun addressToGroupSessionId(address: Address): String =
|
||||||
return doubleDecodeGroupId(address.toGroupString())
|
doubleDecodeGroupId(address.toGroupString())
|
||||||
}
|
|
||||||
|
|
||||||
fun createConfigMemberMap(
|
fun createConfigMemberMap(
|
||||||
members: Collection<String>,
|
members: Collection<String>,
|
||||||
admins: Collection<String>
|
admins: Collection<String>
|
||||||
): Map<String, Boolean> {
|
): Map<String, Boolean> {
|
||||||
// Start with admins
|
// Start with admins
|
||||||
val memberMap = admins.associate {
|
val memberMap = admins.associateWith { true }.toMutableMap()
|
||||||
it to true
|
|
||||||
}.toMutableMap()
|
|
||||||
|
|
||||||
// Add the remaining members (there may be duplicates, so only add ones that aren't already in there from admins)
|
// Add the remaining members (there may be duplicates, so only add ones that aren't already in there from admins)
|
||||||
for (member in members) {
|
for (member in members) {
|
||||||
if (!memberMap.contains(member)) {
|
if (member !in memberMap) {
|
||||||
memberMap[member] = false
|
memberMap[member] = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,8 +46,6 @@ class SSKEnvironment(
|
|||||||
fun startAnyExpiration(timestamp: Long, author: String, expireStartedAt: Long)
|
fun startAnyExpiration(timestamp: Long, author: String, expireStartedAt: Long)
|
||||||
|
|
||||||
fun maybeStartExpiration(message: Message, startDisappearAfterRead: Boolean = false) {
|
fun maybeStartExpiration(message: Message, startDisappearAfterRead: Boolean = false) {
|
||||||
Log.d("MessageExpirationManagerProtocol", "maybeStartExpiration() called with: message = $message, startDisappearAfterRead = $startDisappearAfterRead")
|
|
||||||
|
|
||||||
if (message is ExpirationTimerUpdate && message.isGroup) return
|
if (message is ExpirationTimerUpdate && message.isGroup) return
|
||||||
|
|
||||||
maybeStartExpiration(
|
maybeStartExpiration(
|
||||||
@ -59,8 +57,6 @@ class SSKEnvironment(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun startDisappearAfterRead(timestamp: Long, sender: String) {
|
fun startDisappearAfterRead(timestamp: Long, sender: String) {
|
||||||
Log.d("MessageExpirationManagerProtocol", "startDisappearAfterRead() called with: timestamp = $timestamp, sender = $sender")
|
|
||||||
|
|
||||||
startAnyExpiration(
|
startAnyExpiration(
|
||||||
timestamp,
|
timestamp,
|
||||||
sender,
|
sender,
|
||||||
@ -69,8 +65,6 @@ class SSKEnvironment(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun maybeStartExpiration(timestamp: Long, sender: String, mode: ExpiryMode, startDisappearAfterRead: Boolean = false) {
|
fun maybeStartExpiration(timestamp: Long, sender: String, mode: ExpiryMode, startDisappearAfterRead: Boolean = false) {
|
||||||
Log.d("MessageExpirationManagerProtocol", "maybeStartExpiration() called with: timestamp = $timestamp, sender = $sender, mode = $mode, startDisappearAfterRead = $startDisappearAfterRead")
|
|
||||||
|
|
||||||
val expireStartedAt = when (mode) {
|
val expireStartedAt = when (mode) {
|
||||||
is ExpiryMode.AfterSend -> timestamp
|
is ExpiryMode.AfterSend -> timestamp
|
||||||
is ExpiryMode.AfterRead -> if (startDisappearAfterRead) nowWithOffset.coerceAtLeast(timestamp + 1) else return
|
is ExpiryMode.AfterRead -> if (startDisappearAfterRead) nowWithOffset.coerceAtLeast(timestamp + 1) else return
|
||||||
|
@ -2,6 +2,8 @@ package org.session.libsession.utilities
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
import androidx.annotation.AttrRes
|
import androidx.annotation.AttrRes
|
||||||
import androidx.annotation.ColorInt
|
import androidx.annotation.ColorInt
|
||||||
|
|
||||||
@ -14,3 +16,7 @@ fun Context.getColorFromAttr(
|
|||||||
theme.resolveAttribute(attrColor, typedValue, resolveRefs)
|
theme.resolveAttribute(attrColor, typedValue, resolveRefs)
|
||||||
return typedValue.data
|
return typedValue.data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline fun <reified LP: ViewGroup.LayoutParams> View.modifyLayoutParams(function: LP.() -> Unit) {
|
||||||
|
layoutParams = (layoutParams as LP).apply { function() }
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user