From c77a2b15bfa884e32cdc7d91ba399e331bd1ddad Mon Sep 17 00:00:00 2001 From: Evgenii Kozlov Date: Thu, 17 Apr 2025 20:17:28 +0200 Subject: [PATCH] DROID-3586 Widgets | Fix | Enhance search behavior to include suggested types and system widgets when selecting a source for widget (#2339) --- .../ui/widgets/SelectWidgetSourceFragment.kt | 4 +- .../features/navigation/PageLinksAdapter.kt | 32 ++++++- .../widgets/SelectWidgetSourceViewModel.kt | 91 ++++++++++++------- 3 files changed, 90 insertions(+), 37 deletions(-) diff --git a/app/src/main/java/com/anytypeio/anytype/ui/widgets/SelectWidgetSourceFragment.kt b/app/src/main/java/com/anytypeio/anytype/ui/widgets/SelectWidgetSourceFragment.kt index 3f5d16a257..4d997461db 100644 --- a/app/src/main/java/com/anytypeio/anytype/ui/widgets/SelectWidgetSourceFragment.kt +++ b/app/src/main/java/com/anytypeio/anytype/ui/widgets/SelectWidgetSourceFragment.kt @@ -148,7 +148,9 @@ class SelectWidgetSourceFragment : BaseBottomSheetTextInputFragment { diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/navigation/PageLinksAdapter.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/navigation/PageLinksAdapter.kt index df4ae01520..2fe71aaa3c 100644 --- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/navigation/PageLinksAdapter.kt +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/navigation/PageLinksAdapter.kt @@ -189,12 +189,40 @@ class ObjectItemViewHolder(view: View) : ObjectViewHolder(view) { override fun areItemsTheSame( oldItem: DefaultSearchItem, newItem: DefaultSearchItem - ): Boolean = (oldItem as? DefaultObjectView)?.id == (newItem as? DefaultObjectView)?.id + ): Boolean { + return when { + oldItem is DefaultObjectView && newItem is DefaultObjectView -> { + oldItem.id == newItem.id + } + oldItem is SuggestWidgetObjectType && newItem is SuggestWidgetObjectType -> { + oldItem.id == newItem.id + } + oldItem is BundledWidgetSourceView && newItem is BundledWidgetSourceView -> { + oldItem.id == newItem.id + } + else -> { + oldItem == newItem + } + } + } override fun areContentsTheSame( oldItem: DefaultSearchItem, newItem: DefaultSearchItem - ): Boolean = (oldItem as? DefaultObjectView) == (newItem as? DefaultObjectView) + ): Boolean { + return when { + oldItem is DefaultObjectView && newItem is DefaultObjectView -> { + oldItem == newItem + } + oldItem is SuggestWidgetObjectType && newItem is SuggestWidgetObjectType -> { + oldItem == newItem + } + oldItem is BundledWidgetSourceView && newItem is BundledWidgetSourceView -> { + oldItem == newItem + } + else -> false + } + } } } diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/widgets/SelectWidgetSourceViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/widgets/SelectWidgetSourceViewModel.kt index 53e685dd50..9e7203f904 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/widgets/SelectWidgetSourceViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/widgets/SelectWidgetSourceViewModel.kt @@ -9,7 +9,6 @@ import com.anytypeio.anytype.core_models.DVFilter import com.anytypeio.anytype.core_models.DVFilterCondition import com.anytypeio.anytype.core_models.Id import com.anytypeio.anytype.core_models.ObjectType -import com.anytypeio.anytype.core_models.ObjectWrapper import com.anytypeio.anytype.core_models.Relations import com.anytypeio.anytype.core_models.widgets.BundledWidgetSourceIds import com.anytypeio.anytype.domain.base.Resultat @@ -26,6 +25,7 @@ import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate import com.anytypeio.anytype.presentation.extension.sendChangeWidgetSourceEvent import com.anytypeio.anytype.presentation.mapper.objectIcon import com.anytypeio.anytype.presentation.navigation.DefaultObjectView +import com.anytypeio.anytype.presentation.navigation.DefaultSearchItem import com.anytypeio.anytype.presentation.search.ObjectSearchConstants import com.anytypeio.anytype.presentation.search.ObjectSearchSection import com.anytypeio.anytype.presentation.search.ObjectSearchView @@ -37,7 +37,6 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.filterIsInstance -import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.take import kotlinx.coroutines.launch import timber.log.Timber @@ -74,48 +73,29 @@ class SelectWidgetSourceViewModel( .asFlow(), suggested.filterIsInstance() ) { state, suggested -> - - when(state) { is ObjectSearchView.Success -> { state.copy( objects = buildList { - - // System widgets - - if (suggested.suggestedSystemSources.isNotEmpty()) { - add(ObjectSearchSection.SelectWidgetSource.System) - with(suggested.suggestedSystemSources) { - if (contains(BundledWidgetSourceIds.FAVORITE)) { - add(BundledWidgetSourceView.Favorites) - } - if (contains(BundledWidgetSourceIds.ALL_OBJECTS)) { - add(BundledWidgetSourceView.AllObjects) - } - if (contains(BundledWidgetSourceIds.RECENT)) { - add(BundledWidgetSourceView.Recent) - } - if (contains(BundledWidgetSourceIds.RECENT_LOCAL)) { - add(BundledWidgetSourceView.RecentLocal) - } - if (contains(BundledWidgetSourceIds.BIN)) { - add(BundledWidgetSourceView.Bin) - } - } - } - - // Suggested widgets (aka object type widgets) - if (suggested.suggestedObjectTypes.isNotEmpty()) { - add(ObjectSearchSection.SelectWidgetSource.Suggested) - addAll(suggested.suggestedObjectTypes) - } - + val query = userInput.value + addAll(resolveSuggestedResults(suggested, query)) // Widgets from existing objects add(ObjectSearchSection.SelectWidgetSource.FromMyObjects) addAll(state.objects) } ) } + is ObjectSearchView.NoResults -> { + val query = state.searchText + val result = buildList { + addAll(resolveSuggestedResults(suggested, query)) + } + if (result.isNotEmpty()) { + ObjectSearchView.Success(result) + } else { + state + } + } else -> state } } @@ -131,6 +111,49 @@ class SelectWidgetSourceViewModel( } } + private fun resolveSuggestedResults( + suggested: SuggestedWidgetsState.Default, + query: String + ) = buildList { + + // Adding system widgets if matched by query + + val filteredSuggestedSystemSources = suggested.suggestedSystemSources.filter { source -> + source.contains(query, ignoreCase = true) + } + if (filteredSuggestedSystemSources.isNotEmpty()) { + add(ObjectSearchSection.SelectWidgetSource.System) + with(filteredSuggestedSystemSources) { + if (contains(BundledWidgetSourceIds.FAVORITE)) { + add(BundledWidgetSourceView.Favorites) + } + if (contains(BundledWidgetSourceIds.ALL_OBJECTS)) { + add(BundledWidgetSourceView.AllObjects) + } + if (contains(BundledWidgetSourceIds.RECENT)) { + add(BundledWidgetSourceView.Recent) + } + if (contains(BundledWidgetSourceIds.RECENT_LOCAL)) { + add(BundledWidgetSourceView.RecentLocal) + } + if (contains(BundledWidgetSourceIds.BIN)) { + add(BundledWidgetSourceView.Bin) + } + } + } + + // Adding object type widgets (aka object type widgets) if matched by query + + val filteredSuggestedObjectTypes = suggested.suggestedObjectTypes.filter { type -> + type.name.contains(query, ignoreCase = true) + } + + if (filteredSuggestedObjectTypes.isNotEmpty()) { + add(ObjectSearchSection.SelectWidgetSource.Suggested) + addAll(filteredSuggestedObjectTypes) + } + } + override fun resolveViews(result: Resultat>) { viewModelScope.launch { result.fold(