diff options
author | ByteHamster <ByteHamster@users.noreply.github.com> | 2024-03-31 18:40:15 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-31 18:40:15 +0200 |
commit | edb440a5a9a05e24c344a71b272b9238217e9c55 (patch) | |
tree | 13623ca7d0dac052ac35d693aac940d0727c87f9 /app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java | |
parent | 4e47691e70e85736c7eeb30ce02c73176e565a86 (diff) | |
download | AntennaPod-edb440a5a9a05e24c344a71b272b9238217e9c55.zip |
Restructure related UI classes together (#7044)
Diffstat (limited to 'app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java')
-rw-r--r-- | app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java | 460 |
1 files changed, 0 insertions, 460 deletions
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java deleted file mode 100644 index 73fce9f1f..000000000 --- a/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java +++ /dev/null @@ -1,460 +0,0 @@ -package de.danoeh.antennapod.fragment; - - -import android.content.Context; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.util.Log; -import android.util.Pair; -import android.view.ContextMenu; -import android.view.LayoutInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.view.inputmethod.InputMethodManager; -import android.widget.ProgressBar; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.appcompat.widget.SearchView; -import com.google.android.material.appbar.MaterialToolbar; -import androidx.fragment.app.Fragment; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import com.google.android.material.chip.Chip; -import com.google.android.material.snackbar.Snackbar; -import com.leinardi.android.speeddial.SpeedDialView; - -import de.danoeh.antennapod.R; -import de.danoeh.antennapod.activity.MainActivity; -import de.danoeh.antennapod.adapter.EpisodeItemListAdapter; -import de.danoeh.antennapod.adapter.HorizontalFeedListAdapter; -import de.danoeh.antennapod.core.menuhandler.MenuItemUtils; -import de.danoeh.antennapod.databinding.MultiSelectSpeedDialBinding; -import de.danoeh.antennapod.event.EpisodeDownloadEvent; -import de.danoeh.antennapod.event.FeedItemEvent; -import de.danoeh.antennapod.event.playback.PlaybackPositionEvent; -import de.danoeh.antennapod.event.PlayerStatusEvent; -import de.danoeh.antennapod.event.UnreadItemsUpdateEvent; -import de.danoeh.antennapod.fragment.actions.EpisodeMultiSelectActionHandler; -import de.danoeh.antennapod.model.feed.Feed; -import de.danoeh.antennapod.model.feed.FeedItem; -import de.danoeh.antennapod.core.util.FeedItemUtil; -import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler; -import de.danoeh.antennapod.net.discovery.CombinedSearcher; -import de.danoeh.antennapod.storage.database.DBReader; -import de.danoeh.antennapod.ui.appstartintent.OnlineFeedviewActivityStarter; -import de.danoeh.antennapod.ui.discovery.OnlineSearchFragment; -import de.danoeh.antennapod.view.EmptyViewHandler; -import de.danoeh.antennapod.view.EpisodeItemListRecyclerView; -import de.danoeh.antennapod.view.LiftOnScrollListener; -import de.danoeh.antennapod.view.viewholder.EpisodeItemViewHolder; -import io.reactivex.Observable; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.disposables.Disposable; -import io.reactivex.schedulers.Schedulers; -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; -import org.greenrobot.eventbus.ThreadMode; - -import java.util.Collections; -import java.util.List; -import de.danoeh.antennapod.menuhandler.FeedMenuHandler; -import de.danoeh.antennapod.event.FeedListUpdateEvent; - - -/** - * Performs a search operation on all feeds or one specific feed and displays the search result. - */ -public class SearchFragment extends Fragment implements EpisodeItemListAdapter.OnSelectModeListener { - private static final String TAG = "SearchFragment"; - private static final String ARG_QUERY = "query"; - private static final String ARG_FEED = "feed"; - private static final String ARG_FEED_NAME = "feedName"; - private static final int SEARCH_DEBOUNCE_INTERVAL = 1500; - - private EpisodeItemListAdapter adapter; - private HorizontalFeedListAdapter adapterFeeds; - private Disposable disposable; - private ProgressBar progressBar; - private EmptyViewHandler emptyViewHandler; - private EpisodeItemListRecyclerView recyclerView; - private List<FeedItem> results; - private Chip chip; - private SearchView searchView; - private Handler automaticSearchDebouncer; - private long lastQueryChange = 0; - private MultiSelectSpeedDialBinding speedDialBinding; - private boolean isOtherViewInFoucus = false; - - - /** - * Create a new SearchFragment that searches all feeds. - */ - public static SearchFragment newInstance() { - SearchFragment fragment = new SearchFragment(); - Bundle args = new Bundle(); - args.putLong(ARG_FEED, 0); - fragment.setArguments(args); - return fragment; - } - - /** - * Create a new SearchFragment that searches all feeds with pre-defined query. - */ - public static SearchFragment newInstance(String query) { - SearchFragment fragment = newInstance(); - fragment.getArguments().putString(ARG_QUERY, query); - return fragment; - } - - /** - * Create a new SearchFragment that searches one specific feed. - */ - public static SearchFragment newInstance(long feed, String feedTitle) { - SearchFragment fragment = newInstance(); - fragment.getArguments().putLong(ARG_FEED, feed); - fragment.getArguments().putString(ARG_FEED_NAME, feedTitle); - return fragment; - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - automaticSearchDebouncer = new Handler(Looper.getMainLooper()); - } - - @Override - public void onStop() { - super.onStop(); - if (disposable != null) { - disposable.dispose(); - } - } - - @Nullable - @Override - public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { - View layout = inflater.inflate(R.layout.search_fragment, container, false); - setupToolbar(layout.findViewById(R.id.toolbar)); - speedDialBinding = MultiSelectSpeedDialBinding.bind(layout); - progressBar = layout.findViewById(R.id.progressBar); - recyclerView = layout.findViewById(R.id.recyclerView); - recyclerView.setRecycledViewPool(((MainActivity) getActivity()).getRecycledViewPool()); - registerForContextMenu(recyclerView); - adapter = new EpisodeItemListAdapter((MainActivity) getActivity()) { - @Override - public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { - super.onCreateContextMenu(menu, v, menuInfo); - if (!inActionMode()) { - menu.findItem(R.id.multi_select).setVisible(true); - } - MenuItemUtils.setOnClickListeners(menu, SearchFragment.this::onContextItemSelected); - } - }; - adapter.setOnSelectModeListener(this); - recyclerView.setAdapter(adapter); - recyclerView.addOnScrollListener(new LiftOnScrollListener(layout.findViewById(R.id.appbar))); - - RecyclerView recyclerViewFeeds = layout.findViewById(R.id.recyclerViewFeeds); - LinearLayoutManager layoutManagerFeeds = new LinearLayoutManager(getActivity()); - layoutManagerFeeds.setOrientation(RecyclerView.HORIZONTAL); - recyclerViewFeeds.setLayoutManager(layoutManagerFeeds); - adapterFeeds = new HorizontalFeedListAdapter((MainActivity) getActivity()) { - @Override - public void onCreateContextMenu(ContextMenu contextMenu, View view, - ContextMenu.ContextMenuInfo contextMenuInfo) { - super.onCreateContextMenu(contextMenu, view, contextMenuInfo); - MenuItemUtils.setOnClickListeners(contextMenu, SearchFragment.this::onContextItemSelected); - } - }; - recyclerViewFeeds.setAdapter(adapterFeeds); - - emptyViewHandler = new EmptyViewHandler(getContext()); - emptyViewHandler.attachToRecyclerView(recyclerView); - emptyViewHandler.setIcon(R.drawable.ic_search); - emptyViewHandler.setTitle(R.string.search_status_no_results); - emptyViewHandler.setMessage(R.string.type_to_search); - EventBus.getDefault().register(this); - - chip = layout.findViewById(R.id.feed_title_chip); - chip.setOnCloseIconClickListener(v -> { - getArguments().putLong(ARG_FEED, 0); - searchWithProgressBar(); - }); - chip.setVisibility((getArguments().getLong(ARG_FEED, 0) == 0) ? View.GONE : View.VISIBLE); - chip.setText(getArguments().getString(ARG_FEED_NAME, "")); - if (getArguments().getString(ARG_QUERY, null) != null) { - search(); - } - searchView.setOnQueryTextFocusChangeListener((view, hasFocus) -> { - if (hasFocus && !isOtherViewInFoucus) { - showInputMethod(view.findFocus()); - } - }); - recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { - @Override - public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { - super.onScrollStateChanged(recyclerView, newState); - if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { - InputMethodManager imm = (InputMethodManager) - getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); - imm.hideSoftInputFromWindow(recyclerView.getWindowToken(), 0); - } - } - }); - speedDialBinding.fabSD.setOverlayLayout(speedDialBinding.fabSDOverlay); - speedDialBinding.fabSD.inflate(R.menu.episodes_apply_action_speeddial); - speedDialBinding.fabSD.setOnChangeListener(new SpeedDialView.OnChangeListener() { - @Override - public boolean onMainActionSelected() { - return false; - } - - @Override - public void onToggleChanged(boolean open) { - if (open && adapter.getSelectedCount() == 0) { - ((MainActivity) getActivity()) - .showSnackbarAbovePlayer(R.string.no_items_selected, Snackbar.LENGTH_SHORT); - speedDialBinding.fabSD.close(); - } - } - }); - speedDialBinding.fabSD.setOnActionSelectedListener(actionItem -> { - new EpisodeMultiSelectActionHandler((MainActivity) getActivity(), actionItem.getId()) - .handleAction(adapter.getSelectedItems()); - adapter.endSelectMode(); - return true; - }); - - return layout; - } - - @Override - public void onDestroyView() { - super.onDestroyView(); - EventBus.getDefault().unregister(this); - } - - private void setupToolbar(MaterialToolbar toolbar) { - toolbar.setTitle(R.string.search_label); - toolbar.setNavigationOnClickListener(v -> getParentFragmentManager().popBackStack()); - toolbar.inflateMenu(R.menu.search); - - MenuItem item = toolbar.getMenu().findItem(R.id.action_search); - item.expandActionView(); - searchView = (SearchView) item.getActionView(); - searchView.setQueryHint(getString(R.string.search_label)); - searchView.setQuery(getArguments().getString(ARG_QUERY), true); - searchView.requestFocus(); - searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { - @Override - public boolean onQueryTextSubmit(String s) { - searchView.clearFocus(); - searchWithProgressBar(); - return true; - } - - @Override - public boolean onQueryTextChange(String s) { - automaticSearchDebouncer.removeCallbacksAndMessages(null); - if (s.isEmpty() || s.endsWith(" ") || (lastQueryChange != 0 - && System.currentTimeMillis() > lastQueryChange + SEARCH_DEBOUNCE_INTERVAL)) { - search(); - } else { - automaticSearchDebouncer.postDelayed(() -> { - search(); - lastQueryChange = 0; // Don't search instantly with first symbol after some pause - }, SEARCH_DEBOUNCE_INTERVAL / 2); - } - lastQueryChange = System.currentTimeMillis(); - return false; - } - }); - item.setOnActionExpandListener(new MenuItem.OnActionExpandListener() { - @Override - public boolean onMenuItemActionExpand(MenuItem item) { - return true; - } - - @Override - public boolean onMenuItemActionCollapse(MenuItem item) { - getParentFragmentManager().popBackStack(); - return true; - } - }); - } - - @Override - public boolean onContextItemSelected(@NonNull MenuItem item) { - Feed selectedFeedItem = adapterFeeds.getLongPressedItem(); - if (selectedFeedItem != null - && FeedMenuHandler.onMenuItemClicked(this, item.getItemId(), selectedFeedItem, () -> { })) { - return true; - } - FeedItem selectedItem = adapter.getLongPressedItem(); - if (selectedItem != null) { - if (adapter.onContextItemSelected(item)) { - return true; - } - if (FeedItemMenuHandler.onMenuItemClicked(this, item.getItemId(), selectedItem)) { - return true; - } - } - return super.onContextItemSelected(item); - } - - @Subscribe(threadMode = ThreadMode.MAIN) - public void onFeedListChanged(FeedListUpdateEvent event) { - search(); - } - - @Subscribe(threadMode = ThreadMode.MAIN) - public void onUnreadItemsChanged(UnreadItemsUpdateEvent event) { - search(); - } - - @Subscribe(threadMode = ThreadMode.MAIN) - public void onEventMainThread(FeedItemEvent event) { - Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]"); - if (results == null) { - return; - } else if (adapter == null) { - search(); - return; - } - for (int i = 0, size = event.items.size(); i < size; i++) { - FeedItem item = event.items.get(i); - int pos = FeedItemUtil.indexOfItemWithId(results, item.getId()); - if (pos >= 0) { - results.remove(pos); - results.add(pos, item); - adapter.notifyItemChangedCompat(pos); - } - } - } - - @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) - public void onEventMainThread(EpisodeDownloadEvent event) { - if (results == null) { - return; - } - for (String downloadUrl : event.getUrls()) { - int pos = FeedItemUtil.indexOfItemWithDownloadUrl(results, downloadUrl); - if (pos >= 0) { - adapter.notifyItemChangedCompat(pos); - } - } - } - - @Subscribe(threadMode = ThreadMode.MAIN) - public void onEventMainThread(PlaybackPositionEvent event) { - if (adapter != null) { - for (int i = 0; i < adapter.getItemCount(); i++) { - EpisodeItemViewHolder holder = (EpisodeItemViewHolder) recyclerView.findViewHolderForAdapterPosition(i); - if (holder != null && holder.isCurrentlyPlayingItem()) { - holder.notifyPlaybackPositionUpdated(event); - break; - } - } - } - } - - @Subscribe(threadMode = ThreadMode.MAIN) - public void onPlayerStatusChanged(PlayerStatusEvent event) { - search(); - } - - private void searchWithProgressBar() { - progressBar.setVisibility(View.VISIBLE); - emptyViewHandler.hide(); - search(); - } - - private void search() { - if (disposable != null) { - disposable.dispose(); - } - adapterFeeds.setEndButton(R.string.search_online, this::searchOnline); - chip.setVisibility((getArguments().getLong(ARG_FEED, 0) == 0) ? View.GONE : View.VISIBLE); - disposable = Observable.fromCallable(this::performSearch) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(results -> { - progressBar.setVisibility(View.GONE); - this.results = results.first; - adapter.updateItems(results.first); - if (getArguments().getLong(ARG_FEED, 0) == 0) { - adapterFeeds.updateData(results.second); - } else { - adapterFeeds.updateData(Collections.emptyList()); - } - - if (searchView.getQuery().toString().isEmpty()) { - emptyViewHandler.setMessage(R.string.type_to_search); - } else { - emptyViewHandler.setMessage(getString(R.string.no_results_for_query, searchView.getQuery())); - } - }, error -> Log.e(TAG, Log.getStackTraceString(error))); - } - - @NonNull - private Pair<List<FeedItem>, List<Feed>> performSearch() { - String query = searchView.getQuery().toString(); - if (query.isEmpty()) { - return new Pair<>(Collections.emptyList(), Collections.emptyList()); - } - long feed = getArguments().getLong(ARG_FEED); - List<FeedItem> items = DBReader.searchFeedItems(feed, query); - List<Feed> feeds = DBReader.searchFeeds(query); - return new Pair<>(items, feeds); - } - - private void showInputMethod(View view) { - InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); - if (imm != null) { - imm.showSoftInput(view, 0); - } - } - - private void searchOnline() { - searchView.clearFocus(); - InputMethodManager in = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); - in.hideSoftInputFromWindow(searchView.getWindowToken(), 0); - String query = searchView.getQuery().toString(); - if (query.matches("http[s]?://.*")) { - startActivity(new OnlineFeedviewActivityStarter(getContext(), query).getIntent()); - return; - } - ((MainActivity) getActivity()).loadChildFragment( - OnlineSearchFragment.newInstance(CombinedSearcher.class, query)); - } - - @Override - public void onStartSelectMode() { - searchViewFocusOff(); - speedDialBinding.fabSD.removeActionItemById(R.id.remove_from_inbox_batch); - speedDialBinding.fabSD.removeActionItemById(R.id.remove_from_queue_batch); - speedDialBinding.fabSD.removeActionItemById(R.id.delete_batch); - speedDialBinding.fabSD.setVisibility(View.VISIBLE); - } - - @Override - public void onEndSelectMode() { - speedDialBinding.fabSD.close(); - speedDialBinding.fabSD.setVisibility(View.GONE); - searchViewFocusOn(); - } - - private void searchViewFocusOff() { - isOtherViewInFoucus = true; - searchView.clearFocus(); - } - - private void searchViewFocusOn() { - isOtherViewInFoucus = false; - searchView.requestFocus(); - } -} |