mirror of
https://github.com/KokaKiwi/BarInsta
synced 2026-03-05 20:11:36 +00:00
Add search back!
This commit is contained in:
parent
48b76c231a
commit
89bb79a8fc
11 changed files with 343 additions and 78 deletions
|
|
@ -1,15 +1,24 @@
|
|||
package awais.instagrabber.activities;
|
||||
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.database.MatrixCursor;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.provider.BaseColumns;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.AutoCompleteTextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.SearchView;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.navigation.NavBackStackEntry;
|
||||
import androidx.navigation.NavController;
|
||||
import androidx.navigation.ui.NavigationUI;
|
||||
|
||||
|
|
@ -19,11 +28,17 @@ import com.google.android.material.appbar.CollapsingToolbarLayout;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.List;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.adapters.SuggestionsAdapter;
|
||||
import awais.instagrabber.asyncs.SuggestionsFetcher;
|
||||
import awais.instagrabber.customviews.helpers.CustomHideBottomViewOnScrollBehavior;
|
||||
import awais.instagrabber.databinding.ActivityMainBinding;
|
||||
import awais.instagrabber.interfaces.FetchListener;
|
||||
import awais.instagrabber.models.SuggestionModel;
|
||||
import awais.instagrabber.models.enums.SuggestionType;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
|
||||
|
|
@ -55,6 +70,12 @@ public class MainActivity extends BaseLanguageActivity {
|
|||
private static final List<Integer> REMOVE_COLLAPSING_TOOLBAR_SCROLL_DESTINATIONS = Collections.singletonList(R.id.commentsViewerFragment);
|
||||
private ActivityMainBinding binding;
|
||||
private LiveData<NavController> currentNavControllerLiveData;
|
||||
private MenuItem searchMenuItem;
|
||||
private SuggestionsAdapter suggestionAdapter;
|
||||
private AutoCompleteTextView searchAutoComplete;
|
||||
private SearchView searchView;
|
||||
private boolean showSearch = true;
|
||||
private Handler suggestionsFetchHandler;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
|
|
@ -63,15 +84,39 @@ public class MainActivity extends BaseLanguageActivity {
|
|||
final String cookie = settingsHelper.getString(Constants.COOKIE);
|
||||
Utils.setupCookies(cookie);
|
||||
setContentView(binding.getRoot());
|
||||
|
||||
final Toolbar toolbar = binding.toolbar;
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
setupBottomNavigationBar();
|
||||
}
|
||||
|
||||
setupScrollingListener();
|
||||
setupSuggestions();
|
||||
}
|
||||
|
||||
private void setupSuggestions() {
|
||||
suggestionsFetchHandler = new Handler();
|
||||
suggestionAdapter = new SuggestionsAdapter(this, (type, query) -> {
|
||||
if (searchMenuItem != null) searchMenuItem.collapseActionView();
|
||||
if (searchView != null && !searchView.isIconified()) searchView.setIconified(true);
|
||||
if (currentNavControllerLiveData != null && currentNavControllerLiveData.getValue() != null) {
|
||||
final NavController navController = currentNavControllerLiveData.getValue();
|
||||
final Bundle bundle = new Bundle();
|
||||
switch (type) {
|
||||
case TYPE_LOCATION:
|
||||
bundle.putString("locationId", query);
|
||||
navController.navigate(R.id.action_global_locationFragment, bundle);
|
||||
break;
|
||||
case TYPE_HASHTAG:
|
||||
bundle.putString("hashtag", query);
|
||||
navController.navigate(R.id.action_global_hashTagFragment, bundle);
|
||||
break;
|
||||
case TYPE_USER:
|
||||
bundle.putString("username", query);
|
||||
navController.navigate(R.id.action_global_profileFragment, bundle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupScrollingListener() {
|
||||
|
|
@ -83,11 +128,132 @@ public class MainActivity extends BaseLanguageActivity {
|
|||
@Override
|
||||
public boolean onCreateOptionsMenu(final Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.main_menu, menu);
|
||||
searchMenuItem = menu.findItem(R.id.search);
|
||||
if (!showSearch) {
|
||||
searchMenuItem.setVisible(false);
|
||||
return true;
|
||||
}
|
||||
return setupSearchView();
|
||||
}
|
||||
|
||||
private boolean setupSearchView() {
|
||||
final View actionView = searchMenuItem.getActionView();
|
||||
if (!(actionView instanceof SearchView)) return false;
|
||||
searchView = (SearchView) actionView;
|
||||
searchView.setSuggestionsAdapter(suggestionAdapter);
|
||||
searchView.setMaxWidth(Integer.MAX_VALUE);
|
||||
final View searchText = searchView.findViewById(R.id.search_src_text);
|
||||
if (searchText instanceof AutoCompleteTextView) {
|
||||
searchAutoComplete = (AutoCompleteTextView) searchText;
|
||||
searchAutoComplete.setTextColor(getResources().getColor(android.R.color.white));
|
||||
}
|
||||
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
||||
private boolean searchUser;
|
||||
private boolean searchHash;
|
||||
private AsyncTask<?, ?, ?> prevSuggestionAsync;
|
||||
private final String[] COLUMNS = {
|
||||
BaseColumns._ID,
|
||||
Constants.EXTRAS_USERNAME,
|
||||
Constants.EXTRAS_NAME,
|
||||
Constants.EXTRAS_TYPE,
|
||||
"pfp",
|
||||
"verified"
|
||||
};
|
||||
private String currentSearchQuery;
|
||||
|
||||
private final FetchListener<SuggestionModel[]> fetchListener = new FetchListener<SuggestionModel[]>() {
|
||||
@Override
|
||||
public void doBefore() {
|
||||
suggestionAdapter.changeCursor(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResult(final SuggestionModel[] result) {
|
||||
final MatrixCursor cursor;
|
||||
if (result == null) cursor = null;
|
||||
else {
|
||||
cursor = new MatrixCursor(COLUMNS, 0);
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
final SuggestionModel suggestionModel = result[i];
|
||||
if (suggestionModel != null) {
|
||||
final SuggestionType suggestionType = suggestionModel.getSuggestionType();
|
||||
final Object[] objects = {
|
||||
i,
|
||||
suggestionType == SuggestionType.TYPE_LOCATION ? suggestionModel.getName() : suggestionModel.getUsername(),
|
||||
suggestionType == SuggestionType.TYPE_LOCATION ? suggestionModel.getUsername() : suggestionModel.getName(),
|
||||
suggestionType,
|
||||
suggestionModel.getProfilePic(),
|
||||
suggestionModel.isVerified()};
|
||||
if (!searchHash && !searchUser) cursor.addRow(objects);
|
||||
else {
|
||||
final boolean isCurrHash = suggestionType == SuggestionType.TYPE_HASHTAG;
|
||||
if (searchHash && isCurrHash || !searchHash && !isCurrHash)
|
||||
cursor.addRow(objects);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
suggestionAdapter.changeCursor(cursor);
|
||||
}
|
||||
};
|
||||
|
||||
private final Runnable runnable = () -> {
|
||||
cancelSuggestionsAsync();
|
||||
if (Utils.isEmpty(currentSearchQuery)) {
|
||||
suggestionAdapter.changeCursor(null);
|
||||
return;
|
||||
}
|
||||
searchUser = currentSearchQuery.charAt(0) == '@';
|
||||
searchHash = currentSearchQuery.charAt(0) == '#';
|
||||
if (currentSearchQuery.length() == 1 && (searchHash || searchUser)) {
|
||||
if (searchAutoComplete != null) {
|
||||
searchAutoComplete.setThreshold(2);
|
||||
}
|
||||
} else {
|
||||
if (searchAutoComplete != null) {
|
||||
searchAutoComplete.setThreshold(1);
|
||||
}
|
||||
prevSuggestionAsync = new SuggestionsFetcher(fetchListener).executeOnExecutor(
|
||||
AsyncTask.THREAD_POOL_EXECUTOR,
|
||||
searchUser || searchHash ? currentSearchQuery.substring(1)
|
||||
: currentSearchQuery);
|
||||
}
|
||||
};
|
||||
|
||||
private void cancelSuggestionsAsync() {
|
||||
if (prevSuggestionAsync != null)
|
||||
try {
|
||||
prevSuggestionAsync.cancel(true);
|
||||
} catch (final Exception ignored) {}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onQueryTextSubmit(final String query) {
|
||||
return onQueryTextChange(query);
|
||||
// menu.findItem(R.id.action_about).setVisible(true);
|
||||
// menu.findItem(R.id.action_settings).setVisible(true);
|
||||
// closeAnyOpenDrawer();
|
||||
// addToStack();
|
||||
// userQuery = (query.contains("@") || query.contains("#")) ? query : ("@" + query);
|
||||
// searchAction.collapseActionView();
|
||||
// searchView.setIconified(true);
|
||||
// searchView.setIconified(true);
|
||||
// mainHelper.onRefresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onQueryTextChange(final String query) {
|
||||
suggestionsFetchHandler.removeCallbacks(runnable);
|
||||
currentSearchQuery = query;
|
||||
suggestionsFetchHandler.postDelayed(runnable, 800);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
private void setupBottomNavigationBar() {
|
||||
final List<Integer> navList = new ArrayList<>(Arrays.asList(
|
||||
final List<Integer> mainNavList = new ArrayList<>(Arrays.asList(
|
||||
R.navigation.direct_messages_nav_graph,
|
||||
R.navigation.feed_nav_graph,
|
||||
R.navigation.profile_nav_graph,
|
||||
|
|
@ -96,7 +262,7 @@ public class MainActivity extends BaseLanguageActivity {
|
|||
));
|
||||
final LiveData<NavController> navControllerLiveData = setupWithNavController(
|
||||
binding.bottomNavView,
|
||||
navList,
|
||||
mainNavList,
|
||||
getSupportFragmentManager(),
|
||||
R.id.main_nav_host,
|
||||
getIntent(),
|
||||
|
|
@ -108,8 +274,11 @@ public class MainActivity extends BaseLanguageActivity {
|
|||
private void setupNavigation(final NavController navController) {
|
||||
NavigationUI.setupWithNavController(binding.toolbar, navController);
|
||||
navController.addOnDestinationChangedListener((controller, destination, arguments) -> {
|
||||
// below is a hack to check if we are at the end of the current stack, to setup the search view
|
||||
binding.appBarLayout.setExpanded(true, true);
|
||||
final int destinationId = destination.getId();
|
||||
@SuppressLint("RestrictedApi") final Deque<NavBackStackEntry> backStack = navController.getBackStack();
|
||||
setupMenu(backStack.size(), destinationId);
|
||||
binding.bottomNavView.setVisibility(SHOW_BOTTOM_VIEW_DESTINATIONS.contains(destinationId) ? View.VISIBLE : View.GONE);
|
||||
if (KEEP_SCROLL_BEHAVIOUR_DESTINATIONS.contains(destinationId)) {
|
||||
setScrollingBehaviour();
|
||||
|
|
@ -124,6 +293,17 @@ public class MainActivity extends BaseLanguageActivity {
|
|||
});
|
||||
}
|
||||
|
||||
private void setupMenu(final int backStackSize, final int destinationId) {
|
||||
if (searchMenuItem == null) return;
|
||||
if (backStackSize == 2 && destinationId != R.id.morePreferencesFragment) {
|
||||
showSearch = true;
|
||||
searchMenuItem.setVisible(true);
|
||||
return;
|
||||
}
|
||||
showSearch = false;
|
||||
searchMenuItem.setVisible(false);
|
||||
}
|
||||
|
||||
private void setScrollingBehaviour() {
|
||||
final CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) binding.mainNavHost.getLayoutParams();
|
||||
layoutParams.setBehavior(new AppBarLayout.ScrollingViewBehavior());
|
||||
|
|
|
|||
|
|
@ -2,60 +2,87 @@ package awais.instagrabber.adapters;
|
|||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.cursoradapter.widget.CursorAdapter;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.RequestManager;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
|
||||
import awais.instagrabber.R;
|
||||
import awais.instagrabber.databinding.ItemSuggestionBinding;
|
||||
import awais.instagrabber.models.enums.SuggestionType;
|
||||
|
||||
public final class SuggestionsAdapter extends CursorAdapter {
|
||||
private final LayoutInflater layoutInflater;
|
||||
private final View.OnClickListener onClickListener;
|
||||
private final RequestManager glideRequestManager;
|
||||
private static final String TAG = "SuggestionsAdapter";
|
||||
|
||||
public SuggestionsAdapter(final Context context, final View.OnClickListener onClickListener) {
|
||||
private final OnSuggestionClickListener onSuggestionClickListener;
|
||||
|
||||
public SuggestionsAdapter(final Context context,
|
||||
final OnSuggestionClickListener onSuggestionClickListener) {
|
||||
super(context, null, FLAG_REGISTER_CONTENT_OBSERVER);
|
||||
this.glideRequestManager = Glide.with(context);
|
||||
this.layoutInflater = LayoutInflater.from(context);
|
||||
this.onClickListener = onClickListener;
|
||||
this.onSuggestionClickListener = onSuggestionClickListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View newView(final Context context, final Cursor cursor, final ViewGroup parent) {
|
||||
return layoutInflater.inflate(R.layout.item_suggestion, parent, false);
|
||||
final LayoutInflater layoutInflater = LayoutInflater.from(context);
|
||||
final ItemSuggestionBinding binding = ItemSuggestionBinding.inflate(layoutInflater, parent, false);
|
||||
return binding.getRoot();
|
||||
// return layoutInflater.inflate(R.layout.item_suggestion, parent, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(@NonNull final View view, final Context context, @NonNull final Cursor cursor) {
|
||||
// i, username, fullname, type, picUrl, verified
|
||||
// 0, 1 , 2 , 3 , 4 , 5
|
||||
|
||||
final String fullname = cursor.getString(2);
|
||||
final String fullName = cursor.getString(2);
|
||||
String username = cursor.getString(1);
|
||||
final String picUrl = cursor.getString(4);
|
||||
final boolean verified = cursor.getString(5).charAt(0) == 't';
|
||||
|
||||
if ("TYPE_HASHTAG".equals(cursor.getString(3))) username = '#' + username;
|
||||
else if ("TYPE_USER".equals(cursor.getString(3))) username = '@' + username;
|
||||
final String type = cursor.getString(3);
|
||||
SuggestionType suggestionType = null;
|
||||
try {
|
||||
suggestionType = SuggestionType.valueOf(type);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.e(TAG, "Unknown suggestion type: " + type, e);
|
||||
}
|
||||
if (suggestionType == null) return;
|
||||
final String query;
|
||||
switch (suggestionType) {
|
||||
case TYPE_USER:
|
||||
username = '@' + username;
|
||||
query = username;
|
||||
break;
|
||||
case TYPE_HASHTAG:
|
||||
username = '#' + username;
|
||||
query = username;
|
||||
break;
|
||||
case TYPE_LOCATION:
|
||||
query = fullName;
|
||||
break;
|
||||
default:
|
||||
return; // will never come here
|
||||
}
|
||||
|
||||
view.setOnClickListener(onClickListener);
|
||||
view.setTag("TYPE_LOCATION".equals(cursor.getString(3)) ? fullname : username);
|
||||
if (onSuggestionClickListener != null) {
|
||||
final SuggestionType finalSuggestionType = suggestionType;
|
||||
view.setOnClickListener(v -> onSuggestionClickListener.onSuggestionClick(finalSuggestionType, query));
|
||||
}
|
||||
final ItemSuggestionBinding binding = ItemSuggestionBinding.bind(view);
|
||||
binding.isVerified.setVisibility(verified ? View.VISIBLE : View.GONE);
|
||||
binding.tvUsername.setText(username);
|
||||
if (suggestionType.equals(SuggestionType.TYPE_LOCATION)) {
|
||||
binding.tvFullName.setVisibility(View.GONE);
|
||||
} else {
|
||||
binding.tvFullName.setVisibility(View.VISIBLE);
|
||||
binding.tvFullName.setText(fullName);
|
||||
}
|
||||
binding.ivProfilePic.setImageURI(picUrl);
|
||||
}
|
||||
|
||||
view.findViewById(R.id.isVerified).setVisibility(verified ? View.VISIBLE : View.GONE);
|
||||
|
||||
((TextView) view.findViewById(R.id.tvUsername)).setText(username);
|
||||
((TextView) view.findViewById(R.id.tvFullName)).setText(fullname);
|
||||
|
||||
glideRequestManager.applyDefaultRequestOptions(new RequestOptions().skipMemoryCache(true))
|
||||
.load(picUrl == null ? R.drawable.ic_location : picUrl).into((ImageView) view.findViewById(R.id.ivProfilePic));
|
||||
public interface OnSuggestionClickListener {
|
||||
void onSuggestionClick(final SuggestionType type, final String query);
|
||||
}
|
||||
}
|
||||
|
|
@ -75,9 +75,9 @@ public final class SuggestionsFetcher extends AsyncTask<String, String, Suggesti
|
|||
|
||||
// name
|
||||
suggestionModels.add(new SuggestionModel(false,
|
||||
place.getJSONObject("location").getString("pk")+"/"+place.getString("slug"),
|
||||
place.getJSONObject("location").getString("pk"), // +"/"+place.getString("slug"),
|
||||
place.getString("title"),
|
||||
place.optString("profile_pic_url", null),
|
||||
place.optString("profile_pic_url"),
|
||||
SuggestionType.TYPE_LOCATION,
|
||||
placesArrayJSONObject.optInt("position", suggestionModels.size() - 1)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ public class NavigationExtensions {
|
|||
}
|
||||
return false;
|
||||
});
|
||||
setupItemReselected(bottomNavigationView, graphIdToTagMap, fragmentManager);
|
||||
// setupItemReselected(bottomNavigationView, graphIdToTagMap, fragmentManager);
|
||||
setupDeepLinks(bottomNavigationView, navGraphIds, fragmentManager, containerId, intent);
|
||||
final int finalFirstFragmentGraphId = firstFragmentGraphId;
|
||||
fragmentManager.addOnBackStackChangedListener(() -> {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue