Add basic story search support.

fork-5.53.8
Alex Hart 2022-09-26 12:45:01 -03:00 zatwierdzone przez Cody Henthorne
rodzic 1049f8bd2f
commit e8c10cd550
6 zmienionych plików z 63 dodań i 15 usunięć

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

@ -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()
}

Wyświetl plik

@ -23,6 +23,7 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Single import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.kotlin.subscribeBy import io.reactivex.rxjava3.kotlin.subscribeBy
import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.Material3SearchToolbar
import org.thoughtcrime.securesms.components.settings.DSLConfiguration import org.thoughtcrime.securesms.components.settings.DSLConfiguration
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
import org.thoughtcrime.securesms.components.settings.DSLSettingsText 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.MediaMmsMessageRecord
import org.thoughtcrime.securesms.database.model.MmsMessageRecord import org.thoughtcrime.securesms.database.model.MmsMessageRecord
import org.thoughtcrime.securesms.main.Material3OnScrollHelperBinder import org.thoughtcrime.securesms.main.Material3OnScrollHelperBinder
import org.thoughtcrime.securesms.main.SearchBinder
import org.thoughtcrime.securesms.mediasend.v2.MediaSelectionActivity import org.thoughtcrime.securesms.mediasend.v2.MediaSelectionActivity
import org.thoughtcrime.securesms.permissions.Permissions import org.thoughtcrime.securesms.permissions.Permissions
import org.thoughtcrime.securesms.safety.SafetyNumberBottomSheet import org.thoughtcrime.securesms.safety.SafetyNumberBottomSheet
@ -88,6 +90,30 @@ class StoriesLandingFragment : DSLSettingsFragment(layoutId = R.layout.stories_l
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
viewModel.isTransitioningToAnotherScreen = false 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) { override fun bindAdapter(adapter: MappingAdapter) {
@ -160,7 +186,16 @@ class StoriesLandingFragment : DSLSettingsFragment(layoutId = R.layout.stories_l
private fun getConfiguration(state: StoriesLandingState): DSLConfiguration { private fun getConfiguration(state: StoriesLandingState): DSLConfiguration {
return configure { 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) createStoryLandingItem(it)
}.partition { }.partition {
!it.data.isHidden !it.data.isHidden

Wyświetl plik

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

Wyświetl plik

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