feat: add a first call missed control message and info popup with link to privacy settings
This commit is contained in:
parent
e7b0707377
commit
34863c5cab
|
@ -1,10 +1,13 @@
|
|||
package org.thoughtcrime.securesms.conversation.v2
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.database.Cursor
|
||||
import android.view.MotionEvent
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
||||
import network.loki.messenger.R
|
||||
import org.thoughtcrime.securesms.conversation.v2.messages.ControlMessageView
|
||||
import org.thoughtcrime.securesms.conversation.v2.messages.VisibleMessageContentViewDelegate
|
||||
import org.thoughtcrime.securesms.conversation.v2.messages.VisibleMessageView
|
||||
|
@ -12,6 +15,7 @@ import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter
|
|||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||
import org.thoughtcrime.securesms.preferences.PrivacySettingsActivity
|
||||
|
||||
class ConversationAdapter(context: Context, cursor: Cursor, private val onItemPress: (MessageRecord, Int, VisibleMessageView, MotionEvent) -> Unit,
|
||||
private val onItemSwipeToReply: (MessageRecord, Int) -> Unit, private val onItemLongPress: (MessageRecord, Int) -> Unit,
|
||||
|
@ -76,7 +80,26 @@ class ConversationAdapter(context: Context, cursor: Cursor, private val onItemPr
|
|||
}
|
||||
view.contentViewDelegate = visibleMessageContentViewDelegate
|
||||
}
|
||||
is ControlMessageViewHolder -> viewHolder.view.bind(message, messageBefore)
|
||||
is ControlMessageViewHolder -> {
|
||||
viewHolder.view.bind(message, messageBefore)
|
||||
if (message.isCallLog && message.isFirstMissedCall) {
|
||||
viewHolder.view.setOnClickListener {
|
||||
AlertDialog.Builder(context)
|
||||
.setTitle(R.string.CallNotificationBuilder_first_call_title)
|
||||
.setMessage(R.string.CallNotificationBuilder_first_call_message)
|
||||
.setPositiveButton(R.string.activity_settings_title) { _, _ ->
|
||||
val intent = Intent(context, PrivacySettingsActivity::class.java)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
.setNeutralButton(R.string.cancel) { d, _ ->
|
||||
d.dismiss()
|
||||
}
|
||||
.show()
|
||||
}
|
||||
} else {
|
||||
viewHolder.view.setOnClickListener(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
package org.thoughtcrime.securesms.conversation.v2.messages
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.LinearLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import network.loki.messenger.R
|
||||
|
@ -53,6 +51,7 @@ class ControlMessageView : LinearLayout {
|
|||
val drawable = when {
|
||||
message.isIncomingCall -> R.drawable.ic_incoming_call
|
||||
message.isOutgoingCall -> R.drawable.ic_outgoing_call
|
||||
message.isFirstMissedCall -> R.drawable.ic_info_outline_light
|
||||
else -> R.drawable.ic_missed_call
|
||||
}
|
||||
binding.iconImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, drawable, context.theme))
|
||||
|
|
|
@ -32,6 +32,7 @@ public interface MmsSmsColumns {
|
|||
protected static final long OUTGOING_CALL_TYPE = 2;
|
||||
protected static final long MISSED_CALL_TYPE = 3;
|
||||
protected static final long JOINED_TYPE = 4;
|
||||
protected static final long FIRST_MISSED_CALL_TYPE = 5;
|
||||
|
||||
protected static final long BASE_INBOX_TYPE = 20;
|
||||
protected static final long BASE_OUTBOX_TYPE = 21;
|
||||
|
@ -208,7 +209,7 @@ public interface MmsSmsColumns {
|
|||
|
||||
public static boolean isCallLog(long type) {
|
||||
long baseType = type & BASE_TYPE_MASK;
|
||||
return baseType == INCOMING_CALL_TYPE || baseType == OUTGOING_CALL_TYPE || baseType == MISSED_CALL_TYPE;
|
||||
return baseType == INCOMING_CALL_TYPE || baseType == OUTGOING_CALL_TYPE || baseType == MISSED_CALL_TYPE || baseType == FIRST_MISSED_CALL_TYPE;
|
||||
}
|
||||
|
||||
public static boolean isExpirationTimerUpdate(long type) {
|
||||
|
@ -239,6 +240,11 @@ public interface MmsSmsColumns {
|
|||
return (type & BASE_TYPE_MASK) == MISSED_CALL_TYPE;
|
||||
}
|
||||
|
||||
public static boolean isFirstMissedCall(long type) {
|
||||
return (type & BASE_TYPE_MASK) == FIRST_MISSED_CALL_TYPE;
|
||||
}
|
||||
|
||||
|
||||
public static boolean isGroupUpdate(long type) {
|
||||
return (type & GROUP_UPDATE_BIT) != 0;
|
||||
}
|
||||
|
|
|
@ -386,6 +386,9 @@ public class SmsDatabase extends MessagingDatabase {
|
|||
case CALL_MISSED:
|
||||
type |= Types.MISSED_CALL_TYPE;
|
||||
break;
|
||||
case CALL_FIRST_MISSED:
|
||||
type |= Types.FIRST_MISSED_CALL_TYPE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -117,6 +117,9 @@ public abstract class DisplayRecord {
|
|||
public boolean isMissedCall() {
|
||||
return SmsDatabase.Types.isMissedCall(type);
|
||||
}
|
||||
public boolean isFirstMissedCall() {
|
||||
return SmsDatabase.Types.isFirstMissedCall(type);
|
||||
}
|
||||
public boolean isDeleted() { return MmsSmsColumns.Types.isDeletedMessage(type); }
|
||||
public boolean isMessageRequestResponse() { return MmsSmsColumns.Types.isMessageRequestResponse(type); }
|
||||
|
||||
|
|
|
@ -114,7 +114,16 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||
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 (isCallLog()) {
|
||||
CallMessageType callType = isIncomingCall() ? CallMessageType.CALL_INCOMING : isOutgoingCall() ? CallMessageType.CALL_OUTGOING : CallMessageType.CALL_MISSED;
|
||||
CallMessageType callType;
|
||||
if (isIncomingCall()) {
|
||||
callType = CallMessageType.CALL_INCOMING;
|
||||
} else if (isOutgoingCall()) {
|
||||
callType = CallMessageType.CALL_OUTGOING;
|
||||
} else if (isMissedCall()) {
|
||||
callType = CallMessageType.CALL_MISSED;
|
||||
} else {
|
||||
callType = CallMessageType.CALL_FIRST_MISSED;
|
||||
}
|
||||
return new SpannableString(UpdateMessageBuilder.INSTANCE.buildCallMessage(context, callType, getIndividualRecipient().getAddress().serialize()));
|
||||
}
|
||||
|
||||
|
|
|
@ -47,8 +47,10 @@ class CallMessageProcessor(private val context: Context, private val textSecureP
|
|||
// first time call notification encountered
|
||||
val notification = CallNotificationBuilder.getFirstCallNotification(context)
|
||||
context.getSystemService(NotificationManager::class.java).notify(CallNotificationBuilder.WEBRTC_NOTIFICATION, notification)
|
||||
}
|
||||
insertMissedCall(sender, sentTimestamp, isFirstCall = true)
|
||||
} else {
|
||||
insertMissedCall(sender, sentTimestamp)
|
||||
}
|
||||
continue
|
||||
}
|
||||
when (nextMessage.type) {
|
||||
|
@ -63,11 +65,15 @@ class CallMessageProcessor(private val context: Context, private val textSecureP
|
|||
}
|
||||
}
|
||||
|
||||
private fun insertMissedCall(sender: String, sentTimestamp: Long) {
|
||||
private fun insertMissedCall(sender: String, sentTimestamp: Long, isFirstCall: Boolean = false) {
|
||||
val currentUserPublicKey = storage.getUserPublicKey()
|
||||
if (sender == currentUserPublicKey) return // don't insert a "missed" due to call notifications disabled if it's our own sender
|
||||
if (isFirstCall) {
|
||||
storage.insertCallMessage(sender, CallMessageType.CALL_FIRST_MISSED, sentTimestamp)
|
||||
} else {
|
||||
storage.insertCallMessage(sender, CallMessageType.CALL_MISSED, sentTimestamp)
|
||||
}
|
||||
}
|
||||
|
||||
private fun incomingHangup(callMessage: CallMessage) {
|
||||
val callId = callMessage.callId ?: return
|
||||
|
|
|
@ -3,5 +3,6 @@ package org.session.libsession.messaging.calls
|
|||
enum class CallMessageType {
|
||||
CALL_MISSED,
|
||||
CALL_INCOMING,
|
||||
CALL_OUTGOING
|
||||
CALL_OUTGOING,
|
||||
CALL_FIRST_MISSED,
|
||||
}
|
|
@ -114,6 +114,8 @@ object UpdateMessageBuilder {
|
|||
context.getString(R.string.MessageRecord_s_called_you, senderName)
|
||||
CallMessageType.CALL_OUTGOING ->
|
||||
context.getString(R.string.MessageRecord_called_s, senderName)
|
||||
CallMessageType.CALL_FIRST_MISSED ->
|
||||
context.getString(R.string.MessageRecord_missed_call_from, senderName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue