Add basic story search support.

This commit is contained in:
Alex Hart 2022-09-26 12:45:01 -03:00 committed by Cody Henthorne
parent 1049f8bd2f
commit e8c10cd550
6 changed files with 63 additions and 15 deletions

View file

@ -120,6 +120,7 @@ import org.thoughtcrime.securesms.jobs.ServiceOutageDetectionJob;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.lock.v2.CreateKbsPinActivity;
import org.thoughtcrime.securesms.main.Material3OnScrollHelperBinder;
import org.thoughtcrime.securesms.main.SearchBinder;
import org.thoughtcrime.securesms.mediasend.v2.MediaSelectionActivity;
import org.thoughtcrime.securesms.megaphone.Megaphone;
import org.thoughtcrime.securesms.megaphone.MegaphoneActionController;
@ -299,7 +300,6 @@ public class ConversationListFragment extends MainFragment implements ActionMode
initializeViewModel();
initializeListAdapters();
initializeTypingObserver();
initializeSearchListener();
initializeVoiceNotePlayer();
RatingManager.showRatingDialogIfNecessary(requireContext());
@ -362,6 +362,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode
public void onResume() {
super.onResume();
initializeSearchListener();
updateReminders();
EventBus.getDefault().register(this);
itemAnimator.disable();
@ -434,6 +435,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode
public void onPause() {
super.onPause();
requireCallback().getSearchAction().setOnClickListener(null);
fab.stopPulse();
cameraFab.stopPulse();
EventBus.getDefault().unregister(this);
@ -617,8 +619,6 @@ public class ConversationListFragment extends MainFragment implements ActionMode
requireCallback().getSearchAction().setOnClickListener(v -> {
fadeOutButtonsAndMegaphone(250);
requireCallback().onSearchOpened();
requireCallback().getSearchToolbar().get().display(requireCallback().getSearchAction().getX() + (requireCallback().getSearchAction().getWidth() / 2.0f),
requireCallback().getSearchAction().getY() + (requireCallback().getSearchAction().getHeight() / 2.0f));
requireCallback().getSearchToolbar().get().setListener(new Material3SearchToolbar.Listener() {
@Override
@ -1670,13 +1670,9 @@ public class ConversationListFragment extends MainFragment implements ActionMode
}
}
public interface Callback extends Material3OnScrollHelperBinder {
public interface Callback extends Material3OnScrollHelperBinder, SearchBinder {
@NonNull Toolbar getToolbar();
@NonNull ImageView getSearchAction();
@NonNull Stub<Material3SearchToolbar> getSearchToolbar();
@NonNull View getUnreadPaymentsDot();
@NonNull Stub<Toolbar> getBasicToolbar();
@ -1685,10 +1681,6 @@ public class ConversationListFragment extends MainFragment implements ActionMode
void updateProxyStatus(@NonNull WebSocketConnectionState state);
void onSearchOpened();
void onSearchClosed();
void onMultiSelectStarted();
void onMultiSelectFinished();

View file

@ -172,7 +172,7 @@ class MainActivityListHostFragment : Fragment(R.layout.main_activity_list_host_f
private fun presentToolbarForStoriesLandingFragment() {
_toolbar.visible = true
_searchAction.visible = false
_searchAction.visible = true
if (_basicToolbar.resolved()) {
_basicToolbar.get().visible = false
}
@ -213,6 +213,7 @@ class MainActivityListHostFragment : Fragment(R.layout.main_activity_list_host_f
override fun onSearchOpened() {
conversationListTabsViewModel.onSearchOpened()
_searchToolbar.get().clearText()
_searchToolbar.get().display(_searchAction.x + (_searchAction.width / 2.0f), _searchAction.y + (_searchAction.height / 2.0f))
}
override fun onSearchClosed() {

View file

@ -0,0 +1,15 @@
package org.thoughtcrime.securesms.main
import android.widget.ImageView
import org.thoughtcrime.securesms.components.Material3SearchToolbar
import org.thoughtcrime.securesms.util.views.Stub
interface SearchBinder {
fun getSearchAction(): ImageView
fun getSearchToolbar(): Stub<Material3SearchToolbar>
fun onSearchOpened()
fun onSearchClosed()
}

View file

@ -23,6 +23,7 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.kotlin.subscribeBy
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.Material3SearchToolbar
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
@ -33,6 +34,7 @@ import org.thoughtcrime.securesms.conversation.mutiselect.forward.MultiselectFor
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
import org.thoughtcrime.securesms.main.Material3OnScrollHelperBinder
import org.thoughtcrime.securesms.main.SearchBinder
import org.thoughtcrime.securesms.mediasend.v2.MediaSelectionActivity
import org.thoughtcrime.securesms.permissions.Permissions
import org.thoughtcrime.securesms.safety.SafetyNumberBottomSheet
@ -88,6 +90,30 @@ class StoriesLandingFragment : DSLSettingsFragment(layoutId = R.layout.stories_l
override fun onResume() {
super.onResume()
viewModel.isTransitioningToAnotherScreen = false
initializeSearchAction()
}
override fun onPause() {
super.onPause()
requireListener<SearchBinder>().getSearchAction().setOnClickListener(null)
}
private fun initializeSearchAction() {
val searchBinder = requireListener<SearchBinder>()
searchBinder.getSearchAction().setOnClickListener {
searchBinder.onSearchOpened()
searchBinder.getSearchToolbar().get().listener = object : Material3SearchToolbar.Listener {
override fun onSearchTextChange(text: String) {
viewModel.setSearchQuery(text.trim())
}
override fun onSearchClosed() {
viewModel.setSearchQuery("")
searchBinder.onSearchClosed()
}
}
}
}
override fun bindAdapter(adapter: MappingAdapter) {
@ -160,7 +186,16 @@ class StoriesLandingFragment : DSLSettingsFragment(layoutId = R.layout.stories_l
private fun getConfiguration(state: StoriesLandingState): DSLConfiguration {
return configure {
val (stories, hidden) = state.storiesLandingItems.map {
val (stories, hidden) = state.storiesLandingItems.filter {
if (state.searchQuery.isNotEmpty()) {
val storyRecipientName = it.storyRecipient.getDisplayName(requireContext())
val individualRecipientName = it.individualRecipient.getDisplayName(requireContext())
storyRecipientName.contains(state.searchQuery, ignoreCase = true) || individualRecipientName.contains(state.searchQuery, ignoreCase = true)
} else {
true
}
}.map {
createStoryLandingItem(it)
}.partition {
!it.data.isHidden

View file

@ -4,7 +4,8 @@ data class StoriesLandingState(
val storiesLandingItems: List<StoriesLandingItemData> = emptyList(),
val displayMyStoryItem: Boolean = false,
val isHiddenContentVisible: Boolean = false,
val loadingState: LoadingState = LoadingState.INIT
val loadingState: LoadingState = LoadingState.INIT,
val searchQuery: String = ""
) {
enum class LoadingState {
INIT,

View file

@ -54,6 +54,10 @@ class StoriesLandingViewModel(private val storiesLandingRepository: StoriesLandi
.map { it.storyRecipient.id }
}
fun setSearchQuery(query: String) {
store.update { it.copy(searchQuery = query) }
}
class Factory(private val storiesLandingRepository: StoriesLandingRepository) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return modelClass.cast(StoriesLandingViewModel(storiesLandingRepository)) as T