Add support for scheduled message sends.

This commit is contained in:
Clark
2023-01-26 10:37:08 -05:00
committed by Greyson Parrelli
parent df695f7611
commit f3e715e069
59 changed files with 1948 additions and 90 deletions

View File

@@ -29,6 +29,7 @@ import org.signal.core.util.concurrent.SignalExecutors;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.animation.AnimationCompleteListener;
import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
@@ -36,6 +37,7 @@ import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.MessageRecordUtil;
import org.thoughtcrime.securesms.util.Projection;
import org.thoughtcrime.securesms.util.SignalLocalMetrics;
import org.thoughtcrime.securesms.util.ViewUtil;
@@ -315,6 +317,8 @@ public class ConversationItemFooter extends ConstraintLayout {
dateView.setText(R.string.ConversationItem_click_to_approve_unencrypted);
} else if (messageRecord.isRateLimited()) {
dateView.setText(R.string.ConversationItem_send_paused);
} else if (MessageRecordUtil.isScheduled(messageRecord)) {
dateView.setText(DateUtils.getOnlyTimeString(getContext(), locale, ((MediaMmsMessageRecord) messageRecord).getScheduledDate()));
} else {
dateView.setText(DateUtils.getSimpleRelativeTimeSpanString(getContext(), locale, messageRecord.getTimestamp()));
}
@@ -392,7 +396,7 @@ public class ConversationItemFooter extends ConstraintLayout {
previousMessageId = newMessageId;
if (messageRecord.isFailed() || messageRecord.isPendingInsecureSmsFallback()) {
if (messageRecord.isFailed() || messageRecord.isPendingInsecureSmsFallback() || MessageRecordUtil.isScheduled(messageRecord)) {
deliveryStatusView.setNone();
return;
}

View File

@@ -28,6 +28,7 @@ class SendButton(context: Context, attributeSet: AttributeSet?) : AppCompatImage
}
private val listeners: MutableList<SendTypeChangedListener> = CopyOnWriteArrayList()
private var scheduledSendListener: ScheduledSendListener? = null
private var availableSendTypes: List<MessageSendType> = MessageSendType.getAllAvailable(context, false)
private var activeMessageSendType: MessageSendType? = null
@@ -98,6 +99,10 @@ class SendButton(context: Context, attributeSet: AttributeSet?) : AppCompatImage
onSelectionChanged(newType = selectedSendType, isManualSelection = false)
}
fun setScheduledSendListener(listener: ScheduledSendListener?) {
this.scheduledSendListener = listener
}
fun resetAvailableTransports(isMediaMessage: Boolean) {
availableSendTypes = MessageSendType.getAllAvailable(context, isMediaMessage)
activeMessageSendType = null
@@ -150,13 +155,29 @@ class SendButton(context: Context, attributeSet: AttributeSet?) : AppCompatImage
}
}
fun showSendTypeMenu(): Boolean {
return if (availableSendTypes.size == 1) {
if (scheduledSendListener == null && !SignalStore.misc().smsExportPhase.allowSmsFeatures()) {
Snackbar.make(snackbarContainer, R.string.InputPanel__sms_messaging_is_no_longer_supported_in_signal, Snackbar.LENGTH_SHORT).show()
}
false
} else {
showSendTypeContextMenu(false)
true
}
}
override fun onLongClick(v: View): Boolean {
if (!isEnabled) {
return false
}
val scheduleListener = scheduledSendListener
if (availableSendTypes.size == 1) {
return if (!SignalStore.misc().smsExportPhase.allowSmsFeatures()) {
return if (scheduleListener != null) {
scheduleListener.onSendScheduled()
true
} else if (!SignalStore.misc().smsExportPhase.allowSmsFeatures()) {
Snackbar.make(snackbarContainer, R.string.InputPanel__sms_messaging_is_no_longer_supported_in_signal, Snackbar.LENGTH_SHORT).show()
true
} else {
@@ -164,8 +185,14 @@ class SendButton(context: Context, attributeSet: AttributeSet?) : AppCompatImage
}
}
val currentlySelected: MessageSendType = selectedSendType
showSendTypeContextMenu(true)
return true
}
private fun showSendTypeContextMenu(allowScheduling: Boolean) {
val currentlySelected: MessageSendType = selectedSendType
val listener = scheduledSendListener
val items = availableSendTypes
.filterNot { it == currentlySelected }
.map { option ->
@@ -174,17 +201,26 @@ class SendButton(context: Context, attributeSet: AttributeSet?) : AppCompatImage
title = option.getTitle(context),
action = { setSendType(option) }
)
}
}.toMutableList()
if (allowScheduling && listener != null) {
items += ActionItem(
iconRes = R.drawable.ic_calendar_24,
title = context.getString(R.string.conversation_activity__option_schedule_message),
action = { listener.onSendScheduled() }
)
}
SignalContextMenu.Builder((parent as View), popupContainer!!)
.preferredVerticalPosition(SignalContextMenu.VerticalPosition.ABOVE)
.offsetY(ViewUtil.dpToPx(8))
.show(items)
return true
}
interface SendTypeChangedListener {
fun onSendTypeChanged(newType: MessageSendType, manuallySelected: Boolean)
}
interface ScheduledSendListener {
fun onSendScheduled()
}
}