mirror of
https://github.com/nextcloud/talk-android
synced 2025-06-19 03:29:28 +01:00
Merge pull request #4674 from nextcloud/issue-4453-4657-improve-main-search
Fixing and improving main search
This commit is contained in:
commit
b7477658ac
@ -66,6 +66,9 @@
|
|||||||
<option name="composableFile" value="true" />
|
<option name="composableFile" value="true" />
|
||||||
<option name="previewFile" value="true" />
|
<option name="previewFile" value="true" />
|
||||||
</inspection_tool>
|
</inspection_tool>
|
||||||
|
<inspection_tool class="PreviewParameterProviderOnFirstParameter" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
|
<option name="composableFile" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
<inspection_tool class="PreviewPickerAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
|
<inspection_tool class="PreviewPickerAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
|
||||||
<option name="composableFile" value="true" />
|
<option name="composableFile" value="true" />
|
||||||
<option name="previewFile" value="true" />
|
<option name="previewFile" value="true" />
|
||||||
|
@ -194,6 +194,7 @@ class ContactItem(
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
const val VIEW_TYPE = FlexibleItemViewType.CONTACT_ITEM
|
||||||
private const val FULLY_OPAQUE: Float = 1.0f
|
private const val FULLY_OPAQUE: Float = 1.0f
|
||||||
private const val SEMI_TRANSPARENT: Float = 0.38f
|
private const val SEMI_TRANSPARENT: Float = 0.38f
|
||||||
}
|
}
|
||||||
|
@ -6,14 +6,13 @@
|
|||||||
*/
|
*/
|
||||||
package com.nextcloud.talk.adapters.items
|
package com.nextcloud.talk.adapters.items
|
||||||
|
|
||||||
class FlexibleItemViewType {
|
object FlexibleItemViewType {
|
||||||
companion object {
|
const val CONVERSATION_ITEM: Int = 1120391230
|
||||||
const val CONVERSATION_ITEM: Int = 1120391230
|
const val LOAD_MORE_RESULTS_ITEM: Int = 1120391231
|
||||||
const val LOAD_MORE_RESULTS_ITEM: Int = 1120391231
|
const val MESSAGE_RESULT_ITEM: Int = 1120391232
|
||||||
const val MESSAGE_RESULT_ITEM: Int = 1120391232
|
const val MESSAGES_TEXT_HEADER_ITEM: Int = 1120391233
|
||||||
const val MESSAGES_TEXT_HEADER_ITEM: Int = 1120391233
|
const val POLL_RESULT_HEADER_ITEM: Int = 1120391234
|
||||||
const val POLL_RESULT_HEADER_ITEM: Int = 1120391234
|
const val POLL_RESULT_VOTER_ITEM: Int = 1120391235
|
||||||
const val POLL_RESULT_VOTER_ITEM: Int = 1120391235
|
const val POLL_RESULT_VOTERS_OVERVIEW_ITEM: Int = 1120391236
|
||||||
const val POLL_RESULT_VOTERS_OVERVIEW_ITEM: Int = 1120391236
|
const val CONTACT_ITEM: Int = 2131558687
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,11 @@ import com.nextcloud.talk.models.json.conversations.RoomOverall
|
|||||||
|
|
||||||
interface ContactsRepository {
|
interface ContactsRepository {
|
||||||
suspend fun getContacts(searchQuery: String?, shareTypes: List<String>): AutocompleteOverall
|
suspend fun getContacts(searchQuery: String?, shareTypes: List<String>): AutocompleteOverall
|
||||||
suspend fun createRoom(roomType: String, sourceType: String, userId: String, conversationName: String?): RoomOverall
|
suspend fun createRoom(
|
||||||
|
roomType: String,
|
||||||
|
sourceType: String?,
|
||||||
|
userId: String,
|
||||||
|
conversationName: String?
|
||||||
|
): RoomOverall
|
||||||
fun getImageUri(avatarId: String, requestBigSize: Boolean): String
|
fun getImageUri(avatarId: String, requestBigSize: Boolean): String
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ class ContactsRepositoryImpl(
|
|||||||
|
|
||||||
override suspend fun createRoom(
|
override suspend fun createRoom(
|
||||||
roomType: String,
|
roomType: String,
|
||||||
sourceType: String,
|
sourceType: String?,
|
||||||
userId: String,
|
userId: String,
|
||||||
conversationName: String?
|
conversationName: String?
|
||||||
): RoomOverall {
|
): RoomOverall {
|
||||||
|
@ -87,7 +87,7 @@ class ContactsViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("Detekt.TooGenericExceptionCaught")
|
@Suppress("Detekt.TooGenericExceptionCaught")
|
||||||
fun createRoom(roomType: String, sourceType: String, userId: String, conversationName: String?) {
|
fun createRoom(roomType: String, sourceType: String?, userId: String, conversationName: String?) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
try {
|
try {
|
||||||
val room = repository.createRoom(
|
val room = repository.createRoom(
|
||||||
|
@ -70,6 +70,7 @@ import com.nextcloud.talk.account.WebViewLoginActivity
|
|||||||
import com.nextcloud.talk.activities.BaseActivity
|
import com.nextcloud.talk.activities.BaseActivity
|
||||||
import com.nextcloud.talk.activities.CallActivity
|
import com.nextcloud.talk.activities.CallActivity
|
||||||
import com.nextcloud.talk.activities.MainActivity
|
import com.nextcloud.talk.activities.MainActivity
|
||||||
|
import com.nextcloud.talk.adapters.items.ContactItem
|
||||||
import com.nextcloud.talk.adapters.items.ConversationItem
|
import com.nextcloud.talk.adapters.items.ConversationItem
|
||||||
import com.nextcloud.talk.adapters.items.GenericTextHeaderItem
|
import com.nextcloud.talk.adapters.items.GenericTextHeaderItem
|
||||||
import com.nextcloud.talk.adapters.items.LoadMoreResultsItem
|
import com.nextcloud.talk.adapters.items.LoadMoreResultsItem
|
||||||
@ -80,6 +81,9 @@ import com.nextcloud.talk.application.NextcloudTalkApplication
|
|||||||
import com.nextcloud.talk.arbitrarystorage.ArbitraryStorageManager
|
import com.nextcloud.talk.arbitrarystorage.ArbitraryStorageManager
|
||||||
import com.nextcloud.talk.chat.ChatActivity
|
import com.nextcloud.talk.chat.ChatActivity
|
||||||
import com.nextcloud.talk.contacts.ContactsActivityCompose
|
import com.nextcloud.talk.contacts.ContactsActivityCompose
|
||||||
|
import com.nextcloud.talk.contacts.ContactsUiState
|
||||||
|
import com.nextcloud.talk.contacts.ContactsViewModel
|
||||||
|
import com.nextcloud.talk.contacts.RoomUiState
|
||||||
import com.nextcloud.talk.conversationlist.viewmodels.ConversationsListViewModel
|
import com.nextcloud.talk.conversationlist.viewmodels.ConversationsListViewModel
|
||||||
import com.nextcloud.talk.data.network.NetworkMonitor
|
import com.nextcloud.talk.data.network.NetworkMonitor
|
||||||
import com.nextcloud.talk.data.user.model.User
|
import com.nextcloud.talk.data.user.model.User
|
||||||
@ -95,6 +99,9 @@ import com.nextcloud.talk.messagesearch.MessageSearchHelper
|
|||||||
import com.nextcloud.talk.messagesearch.MessageSearchHelper.MessageSearchResults
|
import com.nextcloud.talk.messagesearch.MessageSearchHelper.MessageSearchResults
|
||||||
import com.nextcloud.talk.models.domain.ConversationModel
|
import com.nextcloud.talk.models.domain.ConversationModel
|
||||||
import com.nextcloud.talk.models.json.conversations.ConversationEnums
|
import com.nextcloud.talk.models.json.conversations.ConversationEnums
|
||||||
|
import com.nextcloud.talk.models.json.conversations.RoomsOverall
|
||||||
|
import com.nextcloud.talk.models.json.converters.EnumActorTypeConverter
|
||||||
|
import com.nextcloud.talk.models.json.participants.Participant
|
||||||
import com.nextcloud.talk.repositories.unifiedsearch.UnifiedSearchRepository
|
import com.nextcloud.talk.repositories.unifiedsearch.UnifiedSearchRepository
|
||||||
import com.nextcloud.talk.settings.SettingsActivity
|
import com.nextcloud.talk.settings.SettingsActivity
|
||||||
import com.nextcloud.talk.ui.dialog.ChooseAccountDialogFragment
|
import com.nextcloud.talk.ui.dialog.ChooseAccountDialogFragment
|
||||||
@ -178,6 +185,9 @@ class ConversationsListActivity :
|
|||||||
@Inject
|
@Inject
|
||||||
lateinit var networkMonitor: NetworkMonitor
|
lateinit var networkMonitor: NetworkMonitor
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var contactsViewModel: ContactsViewModel
|
||||||
|
|
||||||
lateinit var conversationsListViewModel: ConversationsListViewModel
|
lateinit var conversationsListViewModel: ConversationsListViewModel
|
||||||
|
|
||||||
override val appBarLayoutType: AppBarLayoutType
|
override val appBarLayoutType: AppBarLayoutType
|
||||||
@ -317,6 +327,7 @@ class ConversationsListActivity :
|
|||||||
showSearchOrToolbar()
|
showSearchOrToolbar()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("LongMethod")
|
||||||
private fun initObservers() {
|
private fun initObservers() {
|
||||||
this.lifecycleScope.launch {
|
this.lifecycleScope.launch {
|
||||||
networkMonitor.isOnline.onEach { isOnline ->
|
networkMonitor.isOnline.onEach { isOnline ->
|
||||||
@ -387,6 +398,63 @@ class ConversationsListActivity :
|
|||||||
setConversationList(list)
|
setConversationList(list)
|
||||||
}.collect()
|
}.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lifecycleScope.launch {
|
||||||
|
contactsViewModel.roomViewState.onEach { state ->
|
||||||
|
when (state) {
|
||||||
|
is RoomUiState.Success -> {
|
||||||
|
val conversation = state.conversation
|
||||||
|
val bundle = Bundle()
|
||||||
|
bundle.putString(BundleKeys.KEY_ROOM_TOKEN, conversation?.token)
|
||||||
|
val chatIntent = Intent(context, ChatActivity::class.java)
|
||||||
|
chatIntent.putExtras(bundle)
|
||||||
|
chatIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||||
|
startActivity(chatIntent)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
lifecycleScope.launch {
|
||||||
|
contactsViewModel.contactsViewState.onEach { state ->
|
||||||
|
when (state) {
|
||||||
|
is ContactsUiState.Success -> {
|
||||||
|
if (state.contacts.isNullOrEmpty()) return@onEach
|
||||||
|
|
||||||
|
val userItems: MutableList<AbstractFlexibleItem<*>> = ArrayList()
|
||||||
|
val actorTypeConverter = EnumActorTypeConverter()
|
||||||
|
var genericTextHeaderItem: GenericTextHeaderItem
|
||||||
|
for (autocompleteUser in state.contacts) {
|
||||||
|
val headerTitle = resources!!.getString(R.string.nc_user)
|
||||||
|
if (!callHeaderItems.containsKey(headerTitle)) {
|
||||||
|
genericTextHeaderItem = GenericTextHeaderItem(headerTitle, viewThemeUtils)
|
||||||
|
callHeaderItems[headerTitle] = genericTextHeaderItem
|
||||||
|
}
|
||||||
|
|
||||||
|
val participant = Participant()
|
||||||
|
participant.actorId = autocompleteUser.id
|
||||||
|
participant.actorType = actorTypeConverter.getFromString(autocompleteUser.source)
|
||||||
|
participant.displayName = autocompleteUser.label
|
||||||
|
|
||||||
|
val contactItem = ContactItem(
|
||||||
|
participant,
|
||||||
|
currentUser!!,
|
||||||
|
callHeaderItems[headerTitle],
|
||||||
|
viewThemeUtils
|
||||||
|
)
|
||||||
|
|
||||||
|
userItems.add(contactItem)
|
||||||
|
}
|
||||||
|
|
||||||
|
searchableConversationItems.addAll(userItems)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}.collect()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setConversationList(list: List<ConversationModel>) {
|
private fun setConversationList(list: List<ConversationModel>) {
|
||||||
@ -411,6 +479,9 @@ class ConversationsListActivity :
|
|||||||
intArrayOf(ApiUtils.API_V4, ApiUtils.API_V3, 1)
|
intArrayOf(ApiUtils.API_V4, ApiUtils.API_V3, 1)
|
||||||
)
|
)
|
||||||
fetchOpenConversations(apiVersion)
|
fetchOpenConversations(apiVersion)
|
||||||
|
|
||||||
|
// Get users
|
||||||
|
fetchUsers()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hasFilterEnabled(): Boolean {
|
private fun hasFilterEnabled(): Boolean {
|
||||||
@ -944,40 +1015,45 @@ class ConversationsListActivity :
|
|||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
val openConversationItems: MutableList<AbstractFlexibleItem<*>> = ArrayList()
|
val openConversationItems: MutableList<AbstractFlexibleItem<*>> = ArrayList()
|
||||||
// openConversationsQueryDisposable = ncApi.getOpenConversations(
|
openConversationsQueryDisposable = ncApi.getOpenConversations(
|
||||||
// credentials,
|
credentials,
|
||||||
// ApiUtils.getUrlForOpenConversations(apiVersion, currentUser!!.baseUrl!!)
|
ApiUtils.getUrlForOpenConversations(apiVersion, currentUser!!.baseUrl!!),
|
||||||
// )
|
""
|
||||||
// .subscribeOn(Schedulers.io())
|
)
|
||||||
// .observeOn(AndroidSchedulers.mainThread())
|
.subscribeOn(Schedulers.io())
|
||||||
// .subscribe({ (ocs): RoomsOverall ->
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
// for (conversation in ocs!!.data!!) {
|
.subscribe({ (ocs): RoomsOverall ->
|
||||||
// val headerTitle = resources!!.getString(R.string.openConversations)
|
for (conversation in ocs!!.data!!) {
|
||||||
// var genericTextHeaderItem: GenericTextHeaderItem
|
val headerTitle = resources!!.getString(R.string.openConversations)
|
||||||
// if (!callHeaderItems.containsKey(headerTitle)) {
|
var genericTextHeaderItem: GenericTextHeaderItem
|
||||||
// genericTextHeaderItem = GenericTextHeaderItem(headerTitle, viewThemeUtils)
|
if (!callHeaderItems.containsKey(headerTitle)) {
|
||||||
// callHeaderItems[headerTitle] = genericTextHeaderItem
|
genericTextHeaderItem = GenericTextHeaderItem(headerTitle, viewThemeUtils)
|
||||||
// }
|
callHeaderItems[headerTitle] = genericTextHeaderItem
|
||||||
// val conversationItem = ConversationItem(
|
}
|
||||||
// conversation,
|
val conversationItem = ConversationItem(
|
||||||
// currentUser!!,
|
ConversationModel.mapToConversationModel(conversation, currentUser!!),
|
||||||
// this,
|
currentUser!!,
|
||||||
// callHeaderItems[headerTitle],
|
this,
|
||||||
// viewThemeUtils
|
callHeaderItems[headerTitle],
|
||||||
// )
|
viewThemeUtils
|
||||||
// openConversationItems.add(conversationItem)
|
)
|
||||||
// }
|
openConversationItems.add(conversationItem)
|
||||||
// searchableConversationItems.addAll(openConversationItems)
|
}
|
||||||
// }, { throwable: Throwable ->
|
searchableConversationItems.addAll(openConversationItems)
|
||||||
// Log.e(TAG, "fetchData - getRooms - ERROR", throwable)
|
}, { throwable: Throwable ->
|
||||||
// handleHttpExceptions(throwable)
|
Log.e(TAG, "fetchData - getRooms - ERROR", throwable)
|
||||||
// dispose(openConversationsQueryDisposable)
|
handleHttpExceptions(throwable)
|
||||||
// }) { dispose(openConversationsQueryDisposable) }
|
dispose(openConversationsQueryDisposable)
|
||||||
|
}) { dispose(openConversationsQueryDisposable) }
|
||||||
} else {
|
} else {
|
||||||
Log.d(TAG, "no open conversations fetched because of missing capability")
|
Log.d(TAG, "no open conversations fetched because of missing capability")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun fetchUsers() {
|
||||||
|
contactsViewModel.getContactsFromSearchParams()
|
||||||
|
}
|
||||||
|
|
||||||
private fun handleHttpExceptions(throwable: Throwable) {
|
private fun handleHttpExceptions(throwable: Throwable) {
|
||||||
if (throwable is HttpException) {
|
if (throwable is HttpException) {
|
||||||
when (throwable.code()) {
|
when (throwable.code()) {
|
||||||
@ -1247,6 +1323,16 @@ class ConversationsListActivity :
|
|||||||
ConversationItem.VIEW_TYPE -> {
|
ConversationItem.VIEW_TYPE -> {
|
||||||
handleConversation((Objects.requireNonNull(item) as ConversationItem).model)
|
handleConversation((Objects.requireNonNull(item) as ConversationItem).model)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ContactItem.VIEW_TYPE -> {
|
||||||
|
val contact = item as ContactItem
|
||||||
|
contactsViewModel.createRoom(
|
||||||
|
ROOM_TYPE_ONE_ONE,
|
||||||
|
null,
|
||||||
|
contact.model.actorId!!,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -1923,8 +2009,8 @@ class ConversationsListActivity :
|
|||||||
if (results.hasMore) {
|
if (results.hasMore) {
|
||||||
adapterItems.add(LoadMoreResultsItem)
|
adapterItems.add(LoadMoreResultsItem)
|
||||||
}
|
}
|
||||||
// add unified search result at the end of the list
|
|
||||||
adapter!!.addItems(adapter!!.mainItemCount + adapter!!.scrollableHeaders.size, adapterItems)
|
adapter!!.addItems(0, adapterItems)
|
||||||
binding.recyclerView?.scrollToPosition(0)
|
binding.recyclerView?.scrollToPosition(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1965,7 +2051,7 @@ class ConversationsListActivity :
|
|||||||
const val BOTTOM_SHEET_DELAY: Long = 2500
|
const val BOTTOM_SHEET_DELAY: Long = 2500
|
||||||
private const val KEY_SEARCH_QUERY = "ConversationsListActivity.searchQuery"
|
private const val KEY_SEARCH_QUERY = "ConversationsListActivity.searchQuery"
|
||||||
const val SEARCH_DEBOUNCE_INTERVAL_MS = 300
|
const val SEARCH_DEBOUNCE_INTERVAL_MS = 300
|
||||||
const val SEARCH_MIN_CHARS = 2
|
const val SEARCH_MIN_CHARS = 1
|
||||||
const val HTTP_UNAUTHORIZED = 401
|
const val HTTP_UNAUTHORIZED = 401
|
||||||
const val HTTP_CLIENT_UPGRADE_REQUIRED = 426
|
const val HTTP_CLIENT_UPGRADE_REQUIRED = 426
|
||||||
const val CLIENT_UPGRADE_MARKET_LINK = "market://details?id="
|
const val CLIENT_UPGRADE_MARKET_LINK = "market://details?id="
|
||||||
@ -1977,5 +2063,6 @@ class ConversationsListActivity :
|
|||||||
const val DAYS_FOR_NOTIFICATION_WARNING = 5L
|
const val DAYS_FOR_NOTIFICATION_WARNING = 5L
|
||||||
const val NOTIFICATION_WARNING_DATE_NOT_SET = 0L
|
const val NOTIFICATION_WARNING_DATE_NOT_SET = 0L
|
||||||
const val OFFSET_HEIGHT_DIVIDER: Int = 3
|
const val OFFSET_HEIGHT_DIVIDER: Int = 3
|
||||||
|
const val ROOM_TYPE_ONE_ONE = "1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ class FakeRepositoryError : ContactsRepository {
|
|||||||
@Suppress("Detekt.TooGenericExceptionThrown")
|
@Suppress("Detekt.TooGenericExceptionThrown")
|
||||||
override suspend fun createRoom(
|
override suspend fun createRoom(
|
||||||
roomType: String,
|
roomType: String,
|
||||||
sourceType: String,
|
sourceType: String?,
|
||||||
userId: String,
|
userId: String,
|
||||||
conversationName: String?
|
conversationName: String?
|
||||||
): RoomOverall {
|
): RoomOverall {
|
||||||
|
@ -19,7 +19,7 @@ class FakeRepositorySuccess : ContactsRepository {
|
|||||||
|
|
||||||
override suspend fun createRoom(
|
override suspend fun createRoom(
|
||||||
roomType: String,
|
roomType: String,
|
||||||
sourceType: String,
|
sourceType: String?,
|
||||||
userId: String,
|
userId: String,
|
||||||
conversationName: String?
|
conversationName: String?
|
||||||
): RoomOverall {
|
): RoomOverall {
|
||||||
|
Loading…
Reference in New Issue
Block a user