| 
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.conversation.v2
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import android.content.Context
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import android.content.Intent
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import android.database.Cursor
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import android.net.Uri
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import android.util.SparseArray
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import android.util.SparseBooleanArray
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import android.view.MotionEvent
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -30,6 +31,9 @@ import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.thoughtcrime.securesms.database.model.MessageRecord
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.thoughtcrime.securesms.dependencies.DatabaseComponent
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import com.bumptech.glide.RequestManager
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import com.squareup.phrase.Phrase
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.session.libsession.utilities.StringSubstitutionConstants.APP_NAME_KEY
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.thoughtcrime.securesms.MissingMicrophonePermissionDialog
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.thoughtcrime.securesms.preferences.PrivacySettingsActivity
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.thoughtcrime.securesms.showSessionDialog
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import org.thoughtcrime.securesms.ui.getSubbedCharSequence
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -121,7 +125,11 @@ class ConversationAdapter(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                val senderId = message.individualRecipient.address.serialize()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                val senderIdHash = senderId.hashCode()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                updateQueue.trySend(senderId)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                if (contactCache[senderIdHash] == null && !contactLoadedCache.getOrDefault(senderIdHash, false)) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                if (contactCache[senderIdHash] == null && !contactLoadedCache.getOrDefault(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        senderIdHash,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        false
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    )
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                ) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    getSenderInfo(senderId)?.let { contact ->
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        contactCache[senderIdHash] = contact
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    }
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -129,49 +137,77 @@ class ConversationAdapter(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                val contact = contactCache[senderIdHash]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                visibleMessageView.bind(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        message,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        messageBefore,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        getMessageAfter(position, cursor),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        glide,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        searchQuery,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        contact,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        senderId,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        lastSeen.get(),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        visibleMessageViewDelegate,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        onAttachmentNeedsDownload,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        lastSentMessageId
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    message,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    messageBefore,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    getMessageAfter(position, cursor),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    glide,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    searchQuery,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    contact,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    senderId,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    lastSeen.get(),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    visibleMessageViewDelegate,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    onAttachmentNeedsDownload,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    lastSentMessageId
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                )
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                if (!message.isDeleted) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    visibleMessageView.onPress = { event -> onItemPress(message, viewHolder.adapterPosition, visibleMessageView, event) }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    visibleMessageView.onSwipeToReply = { onItemSwipeToReply(message, viewHolder.adapterPosition) }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    visibleMessageView.onLongPress = { onItemLongPress(message, viewHolder.adapterPosition, visibleMessageView) }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    visibleMessageView.onPress = { event ->
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        onItemPress(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            message,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            viewHolder.adapterPosition,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            visibleMessageView,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            event
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        )
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    visibleMessageView.onSwipeToReply =
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        { onItemSwipeToReply(message, viewHolder.adapterPosition) }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    visibleMessageView.onLongPress =
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        { onItemLongPress(message, viewHolder.adapterPosition, visibleMessageView) }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    visibleMessageView.onPress = null
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    visibleMessageView.onSwipeToReply = null
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    visibleMessageView.onLongPress = null
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            is ControlMessageViewHolder -> {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                viewHolder.view.bind(message, messageBefore)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                if (message.isCallLog && message.isFirstMissedCall) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    viewHolder.view.setOnClickListener {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        context.showSessionDialog {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            val titleTxt = context.getSubbedString(R.string.callsMissedCallFrom, NAME_KEY to message.individualRecipient.name!!)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            title(titleTxt)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            val bodyTxt = context.getSubbedCharSequence(R.string.callsYouMissedCallPermissions, NAME_KEY to message.individualRecipient.name!!)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            text(bodyTxt)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            button(R.string.sessionSettings) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                Intent(context, PrivacySettingsActivity::class.java)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                    .let(context::startActivity)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                when {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    // Click behaviour for first missed call control message
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    //todo this behaviour is different than iOS where the control message is always clickable when the call toggle is disabled in the privacy page
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    message.isCallLog && message.isFirstMissedCall -> {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        viewHolder.view.setOnClickListener {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            context.showSessionDialog {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                val titleTxt = context.getSubbedString(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                    R.string.callsMissedCallFrom,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                    NAME_KEY to message.individualRecipient.name!!
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                )
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                title(titleTxt)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                val bodyTxt = context.getSubbedCharSequence(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                    R.string.callsYouMissedCallPermissions,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                    NAME_KEY to message.individualRecipient.name!!
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                )
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                text(bodyTxt)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                button(R.string.sessionSettings) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                    Intent(context, PrivacySettingsActivity::class.java)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                        .let(context::startActivity)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                cancelButton()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            cancelButton()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    viewHolder.view.setOnClickListener(null)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    // Click behaviour for missed calls due to missing permission
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    message.isCallLog && message.isMissedPermissionCall -> {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        viewHolder.view.setOnClickListener {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            MissingMicrophonePermissionDialog.show(context)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    // non clickable in other cases
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    else -> viewHolder.view.setOnClickListener(null)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
				
			
			 | 
			 | 
			
				
 
 |