Add follow setting button

This commit is contained in:
andrew 2023-12-07 17:50:30 +10:30
parent c60b6d9ba2
commit cf0dbffafd
9 changed files with 58 additions and 26 deletions

View File

@ -105,7 +105,7 @@ class SessionDialogBuilder(val context: Context) {
fun destructiveButton( fun destructiveButton(
@StringRes text: Int, @StringRes text: Int,
@StringRes contentDescription: Int, @StringRes contentDescription: Int = text,
listener: () -> Unit = {} listener: () -> Unit = {}
) = button( ) = button(
text, text,

View File

@ -10,7 +10,13 @@ import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import network.loki.messenger.R import network.loki.messenger.R
import network.loki.messenger.databinding.ViewControlMessageBinding import network.loki.messenger.databinding.ViewControlMessageBinding
import org.session.libsession.messaging.messages.ExpirationConfiguration
import org.session.libsession.utilities.ExpirationUtil.getExpirationDisplayValue
import org.session.libsession.utilities.getExpirationTypeDisplayValue
import org.thoughtcrime.securesms.database.model.MessageRecord import org.thoughtcrime.securesms.database.model.MessageRecord
import org.thoughtcrime.securesms.showSessionDialog
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
class ControlMessageView : LinearLayout { class ControlMessageView : LinearLayout {
@ -31,15 +37,33 @@ class ControlMessageView : LinearLayout {
binding.expirationTimerView.isGone = true binding.expirationTimerView.isGone = true
binding.followSetting.isGone = true binding.followSetting.isGone = true
var messageBody: CharSequence = message.getDisplayBody(context) var messageBody: CharSequence = message.getDisplayBody(context)
binding.root.contentDescription= null binding.root.contentDescription = null
when { when {
message.isExpirationTimerUpdate -> { message.isExpirationTimerUpdate -> {
binding.expirationTimerView.apply { binding.apply {
isVisible = true expirationTimerView.isVisible = true
setExpirationTime(message.expireStarted, message.expiresIn) expirationTimerView.setExpirationTime(message.expireStarted, message.expiresIn)
followSetting.isVisible = ExpirationConfiguration.isNewConfigEnabled && !message.isOutgoing
followSetting.setOnClickListener {
context.showSessionDialog {
val isOff = message.expiresIn == 0L
title(R.string.dialog_disappearing_messages_follow_setting_title)
if (isOff) {
text(R.string.dialog_disappearing_messages_follow_setting_off_body)
} else {
text(
context.getString(
R.string.dialog_disappearing_messages_follow_setting_on_body,
getExpirationDisplayValue(context, message.expiresIn.milliseconds),
context.getExpirationTypeDisplayValue(message.expireStarted == message.timestamp)
)
)
}
destructiveButton(if (isOff) R.string.dialog_disappearing_messages_follow_setting_confirm else R.string.dialog_disappearing_messages_follow_setting_set) { }
cancelButton()
}
}
} }
binding.followSetting.isGone = message.isOutgoing
} }
message.isMediaSavedNotification -> { message.isMediaSavedNotification -> {
binding.iconImageView.apply { binding.iconImageView.apply {

View File

@ -25,6 +25,7 @@ import com.google.android.mms.pdu_alt.PduHeaders
import org.json.JSONArray import org.json.JSONArray
import org.json.JSONException import org.json.JSONException
import org.json.JSONObject import org.json.JSONObject
import org.session.libsession.messaging.messages.ExpirationConfiguration
import org.session.libsession.messaging.messages.signal.IncomingMediaMessage import org.session.libsession.messaging.messages.signal.IncomingMediaMessage
import org.session.libsession.messaging.messages.signal.OutgoingGroupMediaMessage import org.session.libsession.messaging.messages.signal.OutgoingGroupMediaMessage
import org.session.libsession.messaging.messages.signal.OutgoingMediaMessage import org.session.libsession.messaging.messages.signal.OutgoingMediaMessage
@ -1170,7 +1171,7 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
* @param outgoing if true only delete outgoing messages, if false only delete incoming messages, if null delete both. * @param outgoing if true only delete outgoing messages, if false only delete incoming messages, if null delete both.
*/ */
private fun deleteExpirationTimerMessages(threadId: Long, outgoing: Boolean? = null) { private fun deleteExpirationTimerMessages(threadId: Long, outgoing: Boolean? = null) {
val outgoingClause = outgoing?.let { val outgoingClause = outgoing?.takeIf { ExpirationConfiguration.isNewConfigEnabled }?.let {
val comparison = if (it) "IN" else "NOT IN" val comparison = if (it) "IN" else "NOT IN"
" AND $MESSAGE_BOX & ${MmsSmsColumns.Types.BASE_TYPE_MASK} $comparison (${MmsSmsColumns.Types.OUTGOING_MESSAGE_TYPES.joinToString()})" " AND $MESSAGE_BOX & ${MmsSmsColumns.Types.BASE_TYPE_MASK} $comparison (${MmsSmsColumns.Types.OUTGOING_MESSAGE_TYPES.joinToString()})"
} ?: "" } ?: ""

View File

@ -116,7 +116,7 @@ public abstract class MessageRecord extends DisplayRecord {
return new SpannableString(UpdateMessageBuilder.INSTANCE.buildGroupUpdateMessage(context, updateMessageData, getIndividualRecipient().getAddress().serialize(), isOutgoing())); return new SpannableString(UpdateMessageBuilder.INSTANCE.buildGroupUpdateMessage(context, updateMessageData, getIndividualRecipient().getAddress().serialize(), isOutgoing()));
} else if (isExpirationTimerUpdate()) { } else if (isExpirationTimerUpdate()) {
int seconds = (int) (getExpiresIn() / 1000); int seconds = (int) (getExpiresIn() / 1000);
return new SpannableString(UpdateMessageBuilder.INSTANCE.buildExpirationTimerMessage(context, seconds, getIndividualRecipient().getAddress().serialize(), getThreadId(), isOutgoing())); return new SpannableString(UpdateMessageBuilder.INSTANCE.buildExpirationTimerMessage(context, seconds, getIndividualRecipient().getAddress().serialize(), getThreadId(), 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())));
else if (isMediaSavedNotification()) return new SpannableString((UpdateMessageBuilder.INSTANCE.buildDataExtractionMessage(context, DataExtractionNotificationInfoMessage.Kind.MEDIA_SAVED, getIndividualRecipient().getAddress().serialize()))); else if (isMediaSavedNotification()) return new SpannableString((UpdateMessageBuilder.INSTANCE.buildDataExtractionMessage(context, DataExtractionNotificationInfoMessage.Kind.MEDIA_SAVED, getIndividualRecipient().getAddress().serialize())));

View File

@ -906,6 +906,11 @@
<string name="dialog_join_open_group_explanation">Are you sure you want to join the %s open group?</string> <string name="dialog_join_open_group_explanation">Are you sure you want to join the %s open group?</string>
<string name="dialog_open_url_title">Open URL?</string> <string name="dialog_open_url_title">Open URL?</string>
<string name="dialog_open_url_explanation">Are you sure you want to open %s?</string> <string name="dialog_open_url_explanation">Are you sure you want to open %s?</string>
<string name="dialog_disappearing_messages_follow_setting_title">Follow Setting</string>
<string name="dialog_disappearing_messages_follow_setting_off_body">Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?</string>
<string name="dialog_disappearing_messages_follow_setting_on_body">Set your messages to disappear %1$s after they have been %2$s?</string>
<string name="dialog_disappearing_messages_follow_setting_set">Set</string>
<string name="dialog_disappearing_messages_follow_setting_confirm">Confirm</string>
<string name="open">Open</string> <string name="open">Open</string>
<string name="copy_url">Copy URL</string> <string name="copy_url">Copy URL</string>
<string name="dialog_link_preview_title">Enable Link Previews?</string> <string name="dialog_link_preview_title">Enable Link Previews?</string>

View File

@ -56,8 +56,6 @@ data class ExpirationTimerUpdate(var expiryMode: ExpiryMode, var syncTarget: Str
} }
return try { return try {
SignalServiceProtos.Content.newBuilder().apply { SignalServiceProtos.Content.newBuilder().apply {
expirationType
expirationTimer
dataMessage = dataMessageProto.build() dataMessage = dataMessageProto.build()
setExpirationConfigurationIfNeeded(threadID) setExpirationConfigurationIfNeeded(threadID)
}.build() }.build()

View File

@ -151,11 +151,10 @@ object MessageReceiver {
val isUserBlindedSender = sender == openGroupPublicKey?.let { SodiumUtilities.blindedKeyPair(it, MessagingModuleConfiguration.shared.getUserED25519KeyPair()!!) }?.let { SessionId(IdPrefix.BLINDED, it.publicKey.asBytes).hexString } val isUserBlindedSender = sender == openGroupPublicKey?.let { SodiumUtilities.blindedKeyPair(it, MessagingModuleConfiguration.shared.getUserED25519KeyPair()!!) }?.let { SessionId(IdPrefix.BLINDED, it.publicKey.asBytes).hexString }
val isUserSender = sender == userPublicKey val isUserSender = sender == userPublicKey
// Ignore self send if needed
if (!message.isSelfSendValid && (isUserSender || isUserBlindedSender)) {
throw Error.SelfSend
}
if (isUserSender || isUserBlindedSender) { if (isUserSender || isUserBlindedSender) {
// Ignore self send if needed
if (!message.isSelfSendValid) throw Error.SelfSend
message.isSenderSelf = true message.isSenderSelf = true
} }
// Guard against control messages in open groups // Guard against control messages in open groups

View File

@ -12,14 +12,14 @@ import org.session.libsession.messaging.calls.CallMessageType.CALL_OUTGOING
import org.session.libsession.messaging.contacts.Contact import org.session.libsession.messaging.contacts.Contact
import org.session.libsession.messaging.messages.ExpirationConfiguration import org.session.libsession.messaging.messages.ExpirationConfiguration
import org.session.libsession.messaging.sending_receiving.data_extraction.DataExtractionNotificationInfoMessage import org.session.libsession.messaging.sending_receiving.data_extraction.DataExtractionNotificationInfoMessage
import org.session.libsession.utilities.Address
import org.session.libsession.utilities.ExpirationUtil import org.session.libsession.utilities.ExpirationUtil
import org.session.libsession.utilities.getExpirationTypeDisplayValue
import org.session.libsession.utilities.truncateIdForDisplay import org.session.libsession.utilities.truncateIdForDisplay
object UpdateMessageBuilder { object UpdateMessageBuilder {
val storage = MessagingModuleConfiguration.shared.storage val storage = MessagingModuleConfiguration.shared.storage
fun getSenderName(senderId: String) = storage.getContactWithSessionID(senderId) private fun getSenderName(senderId: String) = storage.getContactWithSessionID(senderId)
?.displayName(Contact.ContactContext.REGULAR) ?.displayName(Contact.ContactContext.REGULAR)
?: truncateIdForDisplay(senderId) ?: truncateIdForDisplay(senderId)
@ -76,11 +76,17 @@ object UpdateMessageBuilder {
} }
} }
fun buildExpirationTimerMessage(context: Context, duration: Long, senderId: String? = null, threadId: Long, isOutgoing: Boolean = false): String { fun buildExpirationTimerMessage(
context: Context,
duration: Long,
senderId: String? = null,
threadId: Long,
isOutgoing: Boolean = false,
timestamp: Long,
expireStarted: Long
): String {
if (!isOutgoing && senderId == null) return "" if (!isOutgoing && senderId == null) return ""
val senderName: String = if (!isOutgoing) { val senderName = if (isOutgoing) context.getString(R.string.MessageRecord_you) else getSenderName(senderId!!)
getSenderName(senderId!!)
} else { context.getString(R.string.MessageRecord_you) }
return if (duration <= 0) { return if (duration <= 0) {
if (isOutgoing) { if (isOutgoing) {
if (ExpirationConfiguration.isNewConfigEnabled) { if (ExpirationConfiguration.isNewConfigEnabled) {
@ -98,11 +104,7 @@ object UpdateMessageBuilder {
} else { } else {
val time = ExpirationUtil.getExpirationDisplayValue(context, duration.toInt()) val time = ExpirationUtil.getExpirationDisplayValue(context, duration.toInt())
val config = threadId.let { storage.getExpirationConfiguration(it) } val config = threadId.let { storage.getExpirationConfiguration(it) }
val state = when (config?.expiryMode) { val state = context.getExpirationTypeDisplayValue(timestamp == expireStarted)
is ExpiryMode.AfterSend -> context.getString(R.string.MessageRecord_state_sent)
is ExpiryMode.AfterRead -> context.getString(R.string.MessageRecord_state_read)
else -> ""
}
if (isOutgoing) { if (isOutgoing) {
if (ExpirationConfiguration.isNewConfigEnabled) { if (ExpirationConfiguration.isNewConfigEnabled) {
context.getString(R.string.MessageRecord_you_set_messages_to_disappear_s_after_s, time, state) context.getString(R.string.MessageRecord_you_set_messages_to_disappear_s_after_s, time, state)

View File

@ -1,10 +1,13 @@
package org.session.libsession.utilities package org.session.libsession.utilities
import android.content.Context import android.content.Context
import network.loki.messenger.libsession_util.util.ExpiryMode
import org.session.libsession.R import org.session.libsession.R
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import kotlin.time.Duration import kotlin.time.Duration
fun Context.getExpirationTypeDisplayValue(sent: Boolean) = if (sent) getString(R.string.MessageRecord_state_sent) else getString(R.string.MessageRecord_state_read)
object ExpirationUtil { object ExpirationUtil {
@JvmStatic @JvmStatic
fun getExpirationDisplayValue(context: Context, duration: Duration): String = getExpirationDisplayValue(context, duration.inWholeSeconds.toInt()) fun getExpirationDisplayValue(context: Context, duration: Duration): String = getExpirationDisplayValue(context, duration.inWholeSeconds.toInt())