mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-27 12:05:22 +00:00
Fix Search
This commit is contained in:
parent
ca66d115a3
commit
a4ee521ee0
@ -8,30 +8,9 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.provider.Telephony.Mms.Addr
|
||||
import android.widget.Toast
|
||||
import androidx.activity.viewModels
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.requiredWidth
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.view.isInvisible
|
||||
import androidx.core.view.isVisible
|
||||
@ -56,11 +35,9 @@ import org.session.libsession.messaging.jobs.JobQueue
|
||||
import org.session.libsession.messaging.sending_receiving.MessageSender
|
||||
import org.session.libsession.snode.SnodeAPI
|
||||
import org.session.libsession.utilities.Address
|
||||
import org.session.libsession.utilities.AppTextSecurePreferences
|
||||
import org.session.libsession.utilities.GroupUtil
|
||||
import org.session.libsession.utilities.ProfilePictureModifiedEvent
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsession.utilities.groupByNotNull
|
||||
import org.session.libsession.utilities.recipients.Recipient
|
||||
import org.session.libsignal.utilities.Log
|
||||
import org.session.libsignal.utilities.ThreadUtils
|
||||
@ -87,25 +64,12 @@ import org.thoughtcrime.securesms.messagerequests.MessageRequestsActivity
|
||||
import org.thoughtcrime.securesms.mms.GlideApp
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||
import org.thoughtcrime.securesms.notifications.PushRegistry
|
||||
import org.thoughtcrime.securesms.recoverypassword.RecoveryPasswordActivity
|
||||
import org.thoughtcrime.securesms.permissions.Permissions
|
||||
import org.thoughtcrime.securesms.preferences.SettingsActivity
|
||||
import org.thoughtcrime.securesms.recoverypassword.RecoveryPasswordActivity
|
||||
import org.thoughtcrime.securesms.showMuteDialog
|
||||
import org.thoughtcrime.securesms.showSessionDialog
|
||||
import org.thoughtcrime.securesms.ui.Divider
|
||||
import org.thoughtcrime.securesms.ui.LocalDimensions
|
||||
import org.thoughtcrime.securesms.ui.color.LocalColors
|
||||
import org.thoughtcrime.securesms.ui.color.Colors
|
||||
import org.thoughtcrime.securesms.ui.PreviewTheme
|
||||
import org.thoughtcrime.securesms.ui.SessionColorsParameterProvider
|
||||
import org.thoughtcrime.securesms.ui.SessionShieldIcon
|
||||
import org.thoughtcrime.securesms.ui.base
|
||||
import org.thoughtcrime.securesms.ui.components.SlimOutlineButton
|
||||
import org.thoughtcrime.securesms.ui.contentDescription
|
||||
import org.thoughtcrime.securesms.ui.h4
|
||||
import org.thoughtcrime.securesms.ui.h8
|
||||
import org.thoughtcrime.securesms.ui.setThemedContent
|
||||
import org.thoughtcrime.securesms.ui.small
|
||||
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
||||
import org.thoughtcrime.securesms.util.IP2Country
|
||||
import org.thoughtcrime.securesms.util.disableClipping
|
||||
@ -147,41 +111,27 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
||||
|
||||
private val globalSearchAdapter = GlobalSearchAdapter { model ->
|
||||
when (model) {
|
||||
is GlobalSearchAdapter.Model.Message -> {
|
||||
val threadId = model.messageResult.threadId
|
||||
val timestamp = model.messageResult.sentTimestampMs
|
||||
val author = model.messageResult.messageRecipient.address
|
||||
|
||||
val intent = Intent(this, ConversationActivityV2::class.java)
|
||||
intent.putExtra(ConversationActivityV2.THREAD_ID, threadId)
|
||||
intent.putExtra(ConversationActivityV2.SCROLL_MESSAGE_ID, timestamp)
|
||||
intent.putExtra(ConversationActivityV2.SCROLL_MESSAGE_AUTHOR, author)
|
||||
push(intent)
|
||||
}
|
||||
is GlobalSearchAdapter.Model.SavedMessages -> {
|
||||
val intent = Intent(this, ConversationActivityV2::class.java)
|
||||
intent.putExtra(ConversationActivityV2.ADDRESS, Address.fromSerialized(model.currentUserPublicKey))
|
||||
push(intent)
|
||||
}
|
||||
is GlobalSearchAdapter.Model.Contact -> {
|
||||
val address = model.contact.accountID
|
||||
|
||||
val intent = Intent(this, ConversationActivityV2::class.java)
|
||||
intent.putExtra(ConversationActivityV2.ADDRESS, Address.fromSerialized(address))
|
||||
push(intent)
|
||||
}
|
||||
is GlobalSearchAdapter.Model.GroupConversation -> {
|
||||
val groupAddress = Address.fromSerialized(model.groupRecord.encodedId)
|
||||
val threadId = threadDb.getThreadIdIfExistsFor(Recipient.from(this, groupAddress, false))
|
||||
if (threadId >= 0) {
|
||||
val intent = Intent(this, ConversationActivityV2::class.java)
|
||||
intent.putExtra(ConversationActivityV2.THREAD_ID, threadId)
|
||||
push(intent)
|
||||
is GlobalSearchAdapter.Model.Message -> push<ConversationActivityV2> {
|
||||
model.messageResult.run {
|
||||
putExtra(ConversationActivityV2.THREAD_ID, threadId)
|
||||
putExtra(ConversationActivityV2.SCROLL_MESSAGE_ID, sentTimestampMs)
|
||||
putExtra(ConversationActivityV2.SCROLL_MESSAGE_AUTHOR, messageRecipient.address)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
Log.d("Loki", "callback with model: $model")
|
||||
is GlobalSearchAdapter.Model.SavedMessages -> push<ConversationActivityV2> {
|
||||
putExtra(ConversationActivityV2.ADDRESS, Address.fromSerialized(model.currentUserPublicKey))
|
||||
}
|
||||
is GlobalSearchAdapter.Model.Contact -> push<ConversationActivityV2> {
|
||||
putExtra(ConversationActivityV2.ADDRESS, model.contact.accountID.let(Address::fromSerialized))
|
||||
}
|
||||
is GlobalSearchAdapter.Model.GroupConversation -> model.groupRecord.encodedId
|
||||
.let { Recipient.from(this, Address.fromSerialized(it), false) }
|
||||
.let(threadDb::getThreadIdIfExistsFor)
|
||||
.takeIf { it >= 0 }
|
||||
?.let {
|
||||
push<ConversationActivityV2> { putExtra(ConversationActivityV2.THREAD_ID, it) }
|
||||
}
|
||||
else -> Log.d("Loki", "callback with model: $model")
|
||||
}
|
||||
}
|
||||
|
||||
@ -321,24 +271,14 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
||||
.flatMap { (key, contacts) ->
|
||||
listOf(
|
||||
GlobalSearchAdapter.Model.SubHeader(key)
|
||||
) + contacts.sortedBy { it.name ?: it.value.accountID }.map { it.value }.map(GlobalSearchAdapter.Model::Contact)
|
||||
) + contacts.sortedBy { it.name ?: it.value.accountID }.map { it.value }.map { GlobalSearchAdapter.Model.Contact(it, it.accountID == publicKey) }
|
||||
}
|
||||
} else {
|
||||
val currentUserPublicKey = publicKey
|
||||
val contactAndGroupList = result.contacts.map(GlobalSearchAdapter.Model::Contact) +
|
||||
val contactAndGroupList = result.contacts.map { GlobalSearchAdapter.Model.Contact(it, it.accountID == publicKey) } +
|
||||
result.threads.map(GlobalSearchAdapter.Model::GroupConversation)
|
||||
|
||||
val contactResults = contactAndGroupList.toMutableList()
|
||||
|
||||
if (contactResults.isEmpty()) {
|
||||
contactResults.add(GlobalSearchAdapter.Model.SavedMessages(currentUserPublicKey))
|
||||
}
|
||||
|
||||
val userIndex = contactResults.indexOfFirst { it is GlobalSearchAdapter.Model.Contact && it.contact.accountID == currentUserPublicKey }
|
||||
if (userIndex >= 0) {
|
||||
contactResults[userIndex] = GlobalSearchAdapter.Model.SavedMessages(currentUserPublicKey)
|
||||
}
|
||||
|
||||
if (contactResults.isNotEmpty()) {
|
||||
contactResults.add(0, GlobalSearchAdapter.Model.Header(R.string.conversations))
|
||||
}
|
||||
@ -348,7 +288,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
||||
.associateWith { mmsSmsDatabase.getUnreadCount(it) }
|
||||
|
||||
val messageResults: MutableList<GlobalSearchAdapter.Model> = result.messages
|
||||
.map { GlobalSearchAdapter.Model.Message(it, unreadThreadMap[it.threadId] ?: 0) }
|
||||
.map { GlobalSearchAdapter.Model.Message(it, unreadThreadMap[it.threadId] ?: 0, it.conversationRecipient.isLocalNumber) }
|
||||
.toMutableList()
|
||||
|
||||
if (messageResults.isNotEmpty()) {
|
||||
|
@ -17,7 +17,7 @@ import org.thoughtcrime.securesms.ui.GetString
|
||||
import java.security.InvalidParameterException
|
||||
import org.session.libsession.messaging.contacts.Contact as ContactModel
|
||||
|
||||
class GlobalSearchAdapter (private val modelCallback: (Model)->Unit): RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
class GlobalSearchAdapter(private val modelCallback: (Model)->Unit): RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
|
||||
companion object {
|
||||
const val HEADER_VIEW_TYPE = 0
|
||||
@ -122,15 +122,8 @@ class GlobalSearchAdapter (private val modelCallback: (Model)->Unit): RecyclerVi
|
||||
}
|
||||
binding.root.setOnClickListener { modelCallback(model) }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
data class MessageModel(
|
||||
val threadRecipient: Recipient,
|
||||
val messageRecipient: Recipient,
|
||||
val messageSnippet: String
|
||||
)
|
||||
|
||||
sealed class Model {
|
||||
data class Header(val title: GetString): Model() {
|
||||
constructor(@StringRes title: Int): this(GetString(title))
|
||||
@ -141,8 +134,8 @@ class GlobalSearchAdapter (private val modelCallback: (Model)->Unit): RecyclerVi
|
||||
constructor(title: String): this(GetString(title))
|
||||
}
|
||||
data class SavedMessages(val currentUserPublicKey: String): Model()
|
||||
data class Contact(val contact: ContactModel): Model()
|
||||
data class Contact(val contact: ContactModel, val isSelf: Boolean): Model()
|
||||
data class GroupConversation(val groupRecord: GroupRecord): Model()
|
||||
data class Message(val messageResult: MessageResult, val unread: Int): Model()
|
||||
data class Message(val messageResult: MessageResult, val unread: Int, val isSelf: Boolean): Model()
|
||||
}
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ fun ContentView.bindQuery(query: String, model: GlobalSearchAdapter.Model) {
|
||||
))
|
||||
binding.searchResultSubtitle.text = textSpannable
|
||||
binding.searchResultSubtitle.isVisible = true
|
||||
binding.searchResultTitle.text = model.messageResult.conversationRecipient.toShortString()
|
||||
binding.searchResultTitle.text = model.messageResult.conversationRecipient.getSearchName()
|
||||
}
|
||||
is GroupConversation -> {
|
||||
binding.searchResultTitle.text = getHighlight(
|
||||
@ -74,8 +74,7 @@ fun ContentView.bindQuery(query: String, model: GlobalSearchAdapter.Model) {
|
||||
)
|
||||
|
||||
val membersString = model.groupRecord.members.joinToString { address ->
|
||||
val recipient = Recipient.from(binding.root.context, address, false)
|
||||
recipient.name ?: "${address.serialize().take(4)}...${address.serialize().takeLast(4)}"
|
||||
Recipient.from(binding.root.context, address, false).getSearchName()
|
||||
}
|
||||
binding.searchResultSubtitle.text = getHighlight(query, membersString)
|
||||
}
|
||||
@ -106,16 +105,16 @@ fun ContentView.bindModel(query: String?, model: GroupConversation) {
|
||||
}
|
||||
}
|
||||
|
||||
fun ContentView.bindModel(query: String?, model: ContactModel) {
|
||||
binding.searchResultProfilePicture.isVisible = true
|
||||
binding.searchResultSubtitle.isVisible = false
|
||||
binding.searchResultTimestamp.isVisible = false
|
||||
binding.searchResultSubtitle.text = null
|
||||
val recipient =
|
||||
Recipient.from(binding.root.context, Address.fromSerialized(model.contact.accountID), false)
|
||||
binding.searchResultProfilePicture.update(recipient)
|
||||
val nameString = model.contact.getSearchName()
|
||||
binding.searchResultTitle.text = getHighlight(query, nameString)
|
||||
fun ContentView.bindModel(query: String?, model: ContactModel) = binding.run {
|
||||
searchResultProfilePicture.isVisible = true
|
||||
searchResultSubtitle.isVisible = false
|
||||
searchResultTimestamp.isVisible = false
|
||||
searchResultSubtitle.text = null
|
||||
val recipient = Recipient.from(root.context, Address.fromSerialized(model.contact.accountID), false)
|
||||
searchResultProfilePicture.update(recipient)
|
||||
val nameString = if (model.isSelf) root.context.getString(R.string.note_to_self)
|
||||
else model.contact.getSearchName()
|
||||
searchResultTitle.text = getHighlight(query, nameString)
|
||||
}
|
||||
|
||||
fun ContentView.bindModel(model: SavedMessages) {
|
||||
@ -126,32 +125,39 @@ fun ContentView.bindModel(model: SavedMessages) {
|
||||
binding.searchResultProfilePicture.isVisible = true
|
||||
}
|
||||
|
||||
fun ContentView.bindModel(query: String?, model: Message) {
|
||||
binding.searchResultProfilePicture.isVisible = true
|
||||
binding.searchResultTimestamp.isVisible = true
|
||||
fun ContentView.bindModel(query: String?, model: Message) = binding.apply {
|
||||
searchResultProfilePicture.isVisible = true
|
||||
searchResultTimestamp.isVisible = true
|
||||
// val hasUnreads = model.unread > 0
|
||||
// binding.unreadCountIndicator.isVisible = hasUnreads
|
||||
// unreadCountIndicator.isVisible = hasUnreads
|
||||
// if (hasUnreads) {
|
||||
// binding.unreadCountTextView.text = model.unread.toString()
|
||||
// unreadCountTextView.text = model.unread.toString()
|
||||
// }
|
||||
binding.searchResultTimestamp.text = DateUtils.getDisplayFormattedTimeSpanString(binding.root.context, Locale.getDefault(), model.messageResult.sentTimestampMs)
|
||||
binding.searchResultProfilePicture.update(model.messageResult.conversationRecipient)
|
||||
searchResultTimestamp.text = DateUtils.getDisplayFormattedTimeSpanString(root.context, Locale.getDefault(), model.messageResult.sentTimestampMs)
|
||||
searchResultProfilePicture.update(model.messageResult.conversationRecipient)
|
||||
val textSpannable = SpannableStringBuilder()
|
||||
if (model.messageResult.conversationRecipient != model.messageResult.messageRecipient) {
|
||||
// group chat, bind
|
||||
val text = "${model.messageResult.messageRecipient.getSearchName()}: "
|
||||
val text = "${model.messageResult.messageRecipient.toShortString()}: "
|
||||
textSpannable.append(text)
|
||||
}
|
||||
textSpannable.append(getHighlight(
|
||||
query,
|
||||
model.messageResult.bodySnippet
|
||||
))
|
||||
binding.searchResultSubtitle.text = textSpannable
|
||||
binding.searchResultTitle.text = model.messageResult.conversationRecipient.toShortString()
|
||||
binding.searchResultSubtitle.isVisible = true
|
||||
searchResultSubtitle.text = textSpannable
|
||||
searchResultTitle.text = if (model.isSelf) root.context.getString(R.string.note_to_self)
|
||||
else model.messageResult.conversationRecipient.getSearchName()
|
||||
searchResultSubtitle.isVisible = true
|
||||
}
|
||||
|
||||
fun Recipient.getSearchName(): String = name ?: address.serialize().let(::truncateIdForDisplay)
|
||||
fun Recipient.getSearchName(): String =
|
||||
name?.takeIf { it.isNotEmpty() && !it.looksLikeAccountId }
|
||||
?: address.serialize().let(::truncateIdForDisplay)
|
||||
|
||||
fun Contact.getSearchName(): String = nickname?.takeIf { it.isNotEmpty() }
|
||||
?: name?.takeIf { it.isNotEmpty() } ?: truncateIdForDisplay(accountID)
|
||||
fun Contact.getSearchName(): String =
|
||||
nickname?.takeIf { it.isNotEmpty() && !it.looksLikeAccountId }
|
||||
?: name?.takeIf { it.isNotEmpty() && !it.looksLikeAccountId }
|
||||
?: truncateIdForDisplay(accountID)
|
||||
|
||||
private val String.looksLikeAccountId: Boolean get() = length > 60 && all { it.isDigit() || it.isLetter() }
|
||||
|
@ -57,10 +57,12 @@ class PickDisplayNameActivity : BaseActionBarActivity() {
|
||||
viewModel.states.collectAsState().value,
|
||||
viewModel::onChange,
|
||||
viewModel::onContinue,
|
||||
viewModel::dismissDialog
|
||||
) { viewModel.dismissDialog(); finish() }
|
||||
viewModel::dismissDialog,
|
||||
quit = { viewModel.dismissDialog(); finish() }
|
||||
)
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun onBackPressed() {
|
||||
if (viewModel.onBackPressed()) return
|
||||
|
||||
|
@ -108,5 +108,5 @@ data class ThemeState (
|
||||
)
|
||||
|
||||
inline fun <reified T: Activity> Activity.show() = Intent(this, T::class.java).also(::startActivity).let { overridePendingTransition(R.anim.slide_from_bottom, R.anim.fade_scale_out) }
|
||||
inline fun <reified T: Activity> Activity.push() = Intent(this, T::class.java).also(::startActivity).let { overridePendingTransition(R.anim.slide_from_right, R.anim.fade_scale_out) }
|
||||
inline fun <reified T: Activity> Activity.push(modify: Intent.() -> Unit = {}) = Intent(this, T::class.java).also(modify).also(::startActivity).let { overridePendingTransition(R.anim.slide_from_right, R.anim.fade_scale_out) }
|
||||
inline fun <reified T: Activity> Context.start(modify: Intent.() -> Unit = {}) = Intent(this, T::class.java).also(modify).apply { addFlags(FLAG_ACTIVITY_SINGLE_TOP) }.let(::startActivity)
|
||||
|
@ -1,4 +1,4 @@
|
||||
package org.session.libsession.utilities
|
||||
|
||||
fun truncateIdForDisplay(id: String): String =
|
||||
id.takeIf { it.length > 8 }?.apply{ "${take(4)}…${takeLast(4)}" } ?: id
|
||||
id.takeIf { it.length > 8 }?.run{ "${take(4)}…${takeLast(4)}" } ?: id
|
||||
|
Loading…
Reference in New Issue
Block a user