Merge branch 'dev' into bluetooth-manager-crash

pull/1164/head
ryanzhao 1 year ago
commit 7a14c3f8be

@ -22,6 +22,7 @@ import androidx.activity.viewModels
import androidx.annotation.DimenRes
import androidx.appcompat.app.AlertDialog
import androidx.core.view.drawToBitmap
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
@ -344,6 +345,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
updateSubtitle()
setUpBlockedBanner()
binding!!.searchBottomBar.setEventListener(this)
updateSendAfterApprovalText()
showOrHideInputIfNeeded()
setUpMessageRequestsBar()
@ -653,7 +655,9 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
setUpMessageRequestsBar()
invalidateOptionsMenu()
updateSubtitle()
updateSendAfterApprovalText()
showOrHideInputIfNeeded()
binding?.toolbarContent?.profilePictureView?.root?.update(threadRecipient)
binding?.toolbarContent?.conversationTitleView?.text = when {
threadRecipient.isLocalNumber -> getString(R.string.note_to_self)
@ -662,6 +666,10 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
}
}
private fun updateSendAfterApprovalText() {
binding?.textSendAfterApproval?.isGone = viewModel.recipient?.hasApprovedMe() ?: true
}
private fun showOrHideInputIfNeeded() {
val recipient = viewModel.recipient
if (recipient != null && recipient.isClosedGroupRecipient) {

@ -203,10 +203,11 @@ public final class ConversationReactionOverlay extends FrameLayout {
boolean isMessageOnLeft) {
contextMenu = new ConversationContextMenu(dropdownAnchor, getMenuActionItems(messageRecord));
float itemX = isMessageOnLeft ? scrubberHorizontalMargin :
float endX = isMessageOnLeft ? scrubberHorizontalMargin :
selectedConversationModel.getBubbleX() - conversationItem.getWidth() + selectedConversationModel.getBubbleWidth();
conversationItem.setX(itemX);
conversationItem.setY(selectedConversationModel.getBubbleY() - statusBarHeight);
float endY = selectedConversationModel.getBubbleY() - statusBarHeight;
conversationItem.setX(endX);
conversationItem.setY(endY);
Bitmap conversationItemSnapshot = selectedConversationModel.getBitmap();
boolean isWideLayout = contextMenu.getMaxWidth() + scrubberWidth < getWidth();
@ -214,8 +215,6 @@ public final class ConversationReactionOverlay extends FrameLayout {
int overlayHeight = getHeight();
int bubbleWidth = selectedConversationModel.getBubbleWidth();
float endX = itemX;
float endY = conversationItem.getY();
float endApparentTop = endY;
float endScale = 1f;
@ -265,9 +264,7 @@ public final class ConversationReactionOverlay extends FrameLayout {
}
} else {
endY = overlayHeight - contextMenu.getMaxHeight() - menuPadding - conversationItemSnapshot.getHeight();
float contextMenuTop = endY + conversationItemSnapshot.getHeight();
reactionBarBackgroundY = getReactionBarOffsetForTouch(selectedConversationModel.getBubbleY(), contextMenuTop, menuPadding, reactionBarOffset, reactionBarHeight, reactionBarTopPadding, endY);
reactionBarBackgroundY = endY - reactionBarHeight - menuPadding;
}
endApparentTop = endY;

@ -126,10 +126,9 @@ open class ThumbnailView: FrameLayout {
buildThumbnailGlideRequest(glide, slide).into(GlideDrawableListeningTarget(binding.thumbnailImage, binding.thumbnailLoadIndicator, result))
}
slide.hasPlaceholder() -> {
buildPlaceholderGlideRequest(glide, slide).into(GlideBitmapListeningTarget(binding.thumbnailImage, binding.thumbnailLoadIndicator, result))
buildPlaceholderGlideRequest(glide, slide).into(GlideBitmapListeningTarget(binding.thumbnailImage, null, result))
}
else -> {
binding.thumbnailLoadIndicator.isVisible = false
glide.clear(binding.thumbnailImage)
result.set(false)
}

@ -65,6 +65,7 @@ import org.thoughtcrime.securesms.database.model.Quote
import org.thoughtcrime.securesms.dependencies.DatabaseComponent.Companion.get
import org.thoughtcrime.securesms.mms.MmsException
import org.thoughtcrime.securesms.mms.SlideDeck
import org.thoughtcrime.securesms.util.asSequence
import java.io.Closeable
import java.io.IOException
import java.security.SecureRandom
@ -91,54 +92,22 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
return 0
}
fun addFailures(messageId: Long, failure: List<NetworkFailure>) {
try {
addToDocument(messageId, NETWORK_FAILURE, failure, NetworkFailureList::class.java)
} catch (e: IOException) {
Log.w(TAG, e)
}
}
fun removeFailure(messageId: Long, failure: NetworkFailure?) {
try {
removeFromDocument(messageId, NETWORK_FAILURE, failure, NetworkFailureList::class.java)
} catch (e: IOException) {
Log.w(TAG, e)
}
}
fun isOutgoingMessage(timestamp: Long): Boolean {
val database = databaseHelper.writableDatabase
var cursor: Cursor? = null
var isOutgoing = false
try {
cursor = database.query(
TABLE_NAME,
arrayOf<String>(ID, THREAD_ID, MESSAGE_BOX, ADDRESS),
DATE_SENT + " = ?",
arrayOf(timestamp.toString()),
null,
null,
null,
null
)
while (cursor.moveToNext()) {
if (MmsSmsColumns.Types.isOutgoingMessageType(
cursor.getLong(
cursor.getColumnIndexOrThrow(
MESSAGE_BOX
)
)
)
) {
isOutgoing = true
}
}
} finally {
cursor?.close()
fun isOutgoingMessage(timestamp: Long): Boolean =
databaseHelper.writableDatabase.query(
TABLE_NAME,
arrayOf(ID, THREAD_ID, MESSAGE_BOX, ADDRESS),
DATE_SENT + " = ?",
arrayOf(timestamp.toString()),
null,
null,
null,
null
).use { cursor ->
cursor.asSequence()
.map { cursor.getColumnIndexOrThrow(MESSAGE_BOX) }
.map(cursor::getLong)
.any { MmsSmsColumns.Types.isOutgoingMessageType(it) }
}
return isOutgoing
}
fun incrementReceiptCount(
messageId: SyncMessageId,
@ -254,15 +223,6 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
}
}
private fun getThreadIdFor(notification: NotificationInd): Long {
val fromString =
if (notification.from != null && notification.from.textString != null) toIsoString(
notification.from.textString
) else ""
val recipient = Recipient.from(context, fromExternal(context, fromString), false)
return get(context).threadDatabase().getOrCreateThreadIdFor(recipient)
}
private fun rawQuery(where: String, arguments: Array<String>?): Cursor {
val database = databaseHelper.readableDatabase
return database.rawQuery(
@ -273,10 +233,6 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
)
}
fun getMessages(idsAsString: String): Cursor {
return rawQuery(idsAsString, null)
}
fun getMessage(messageId: Long): Cursor {
val cursor = rawQuery(RAW_ID_WHERE, arrayOf(messageId.toString()))
setNotifyConverationListeners(cursor, getThreadIdForMessage(messageId))
@ -306,48 +262,30 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
}
}
fun markAsPendingInsecureSmsFallback(messageId: Long) {
val threadId = getThreadIdForMessage(messageId)
private fun markAs(
messageId: Long,
baseType: Long,
threadId: Long = getThreadIdForMessage(messageId)
) {
updateMailboxBitmask(
messageId,
MmsSmsColumns.Types.BASE_TYPE_MASK,
MmsSmsColumns.Types.BASE_PENDING_INSECURE_SMS_FALLBACK,
baseType,
Optional.of(threadId)
)
notifyConversationListeners(threadId)
}
fun markAsSending(messageId: Long) {
val threadId = getThreadIdForMessage(messageId)
updateMailboxBitmask(
messageId,
MmsSmsColumns.Types.BASE_TYPE_MASK,
MmsSmsColumns.Types.BASE_SENDING_TYPE,
Optional.of(threadId)
)
notifyConversationListeners(threadId)
markAs(messageId, MmsSmsColumns.Types.BASE_SENDING_TYPE)
}
fun markAsSentFailed(messageId: Long) {
val threadId = getThreadIdForMessage(messageId)
updateMailboxBitmask(
messageId,
MmsSmsColumns.Types.BASE_TYPE_MASK,
MmsSmsColumns.Types.BASE_SENT_FAILED_TYPE,
Optional.of(threadId)
)
notifyConversationListeners(threadId)
markAs(messageId, MmsSmsColumns.Types.BASE_SENT_FAILED_TYPE)
}
override fun markAsSent(messageId: Long, secure: Boolean) {
val threadId = getThreadIdForMessage(messageId)
updateMailboxBitmask(
messageId,
MmsSmsColumns.Types.BASE_TYPE_MASK,
MmsSmsColumns.Types.BASE_SENT_TYPE or if (secure) MmsSmsColumns.Types.PUSH_MESSAGE_BIT or MmsSmsColumns.Types.SECURE_MESSAGE_BIT else 0,
Optional.of(threadId)
)
notifyConversationListeners(threadId)
markAs(messageId, MmsSmsColumns.Types.BASE_SENT_TYPE or if (secure) MmsSmsColumns.Types.PUSH_MESSAGE_BIT or MmsSmsColumns.Types.SECURE_MESSAGE_BIT else 0)
}
override fun markUnidentified(messageId: Long, unidentified: Boolean) {
@ -371,13 +309,7 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
val mentionChange = if (hasMention) { 1 } else { 0 }
get(context).threadDatabase().decrementUnread(threadId, 1, mentionChange)
}
updateMailboxBitmask(
messageId,
MmsSmsColumns.Types.BASE_TYPE_MASK,
MmsSmsColumns.Types.BASE_DELETED_TYPE,
Optional.of(threadId)
)
notifyConversationListeners(threadId)
markAs(messageId, MmsSmsColumns.Types.BASE_DELETED_TYPE, threadId)
}
override fun markExpireStarted(messageId: Long) {
@ -407,10 +339,6 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
)
}
fun setAllMessagesRead(): List<MarkedMessageInfo> {
return setMessagesRead(READ + " = 0", null)
}
private fun setMessagesRead(where: String, arguments: Array<String>?): List<MarkedMessageInfo> {
val database = databaseHelper.writableDatabase
val result: MutableList<MarkedMessageInfo> = LinkedList()
@ -419,7 +347,7 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
try {
cursor = database.query(
TABLE_NAME,
arrayOf<String>(ID, ADDRESS, DATE_SENT, MESSAGE_BOX, EXPIRES_IN, EXPIRE_STARTED),
arrayOf(ID, ADDRESS, DATE_SENT, MESSAGE_BOX, EXPIRES_IN, EXPIRE_STARTED),
where,
arguments,
null,
@ -1400,25 +1328,16 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
val attachments = get(context).attachmentDatabase().getAttachment(
cursor
)
val contacts: List<Contact?> = getSharedContacts(
cursor, attachments
)
val contactAttachments =
contacts.map { obj: Contact? -> obj!!.avatarAttachment }
.filter { a: Attachment? -> a != null }
.toSet()
val previews: List<LinkPreview?> = getLinkPreviews(
cursor, attachments
)
val previewAttachments =
previews.filter { lp: LinkPreview? -> lp!!.getThumbnail().isPresent }
.map { lp: LinkPreview? -> lp!!.getThumbnail().get() }
.toSet()
val contacts: List<Contact?> = getSharedContacts(cursor, attachments)
val contactAttachments: Set<Attachment?> =
contacts.mapNotNull { it?.avatarAttachment }.toSet()
val previews: List<LinkPreview?> = getLinkPreviews(cursor, attachments)
val previewAttachments: Set<Attachment?> =
previews.mapNotNull { it?.getThumbnail()?.orNull() }.toSet()
val slideDeck = getSlideDeck(
Stream.of(attachments)
.filterNot { o: DatabaseAttachment? -> contactAttachments.contains(o) }
.filterNot { o: DatabaseAttachment? -> previewAttachments.contains(o) }
.toList()
attachments
.filterNot { o: DatabaseAttachment? -> o in contactAttachments }
.filterNot { o: DatabaseAttachment? -> o in previewAttachments }
)
val quote = getQuote(cursor)
val reactions = get(context).reactionDatabase().getReactions(cursor)
@ -1623,4 +1542,4 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
const val CREATE_REACTIONS_LAST_SEEN_COMMAND = "ALTER TABLE $TABLE_NAME ADD COLUMN $REACTIONS_LAST_SEEN INTEGER DEFAULT 0;"
const val CREATE_HAS_MENTION_COMMAND = "ALTER TABLE $TABLE_NAME ADD COLUMN $HAS_MENTION INTEGER DEFAULT 0;"
}
}
}

@ -0,0 +1,6 @@
package org.thoughtcrime.securesms.util
import android.database.Cursor
fun Cursor.asSequence(): Sequence<Cursor> =
generateSequence { if (moveToNext()) this else null }

@ -35,7 +35,7 @@
android:layout_width="match_parent"
android:layout_height="36dp"
android:visibility="gone"
android:layout_above="@+id/messageRequestBar"
android:layout_above="@+id/textSendAfterApproval"
/>
<org.thoughtcrime.securesms.conversation.v2.input_bar.InputBar
@ -118,6 +118,18 @@
</LinearLayout>
<TextView
android:id="@+id/textSendAfterApproval"
android:text="@string/ConversationActivity_send_after_approval"
android:visibility="gone"
android:textAlignment="center"
android:textColor="@color/classic_light_2"
android:padding="22dp"
android:textSize="12sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@id/messageRequestBar"/>
<RelativeLayout
android:id="@+id/scrollToBottomButton"
android:visibility="gone"

@ -227,6 +227,7 @@
<string name="ConversationActivity_search_position">%1$d of %2$d</string>
<string name="ConversationActivity_call_title">Call Permissions Required</string>
<string name="ConversationActivity_call_prompt">You can enable the \'Voice and video calls\' permission in the Privacy Settings.</string>
<string name="ConversationActivity_send_after_approval">You will be able to send voice messages and attachments once the recipient has approved this message request</string>
<!-- ConversationFragment -->
<plurals name="ConversationFragment_delete_selected_messages">
<item quantity="one">Delete selected message?</item>

Loading…
Cancel
Save