Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Search users feature #105

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package me.grishka.houseclub.api.methods;

import java.util.List;

import me.grishka.houseclub.api.ClubhouseAPIRequest;
import me.grishka.houseclub.api.model.SearchUser;

public class SearchPeople extends ClubhouseAPIRequest<SearchPeople.Resp> {

public SearchPeople(String query) {
super("POST", "search_users", Resp.class);
requestBody = new Body(query);
}

private static class Body {
public boolean cofollowsOnly;
public boolean followingOnly;
public boolean followersOnly;
public String query;

public Body(String query) {
this.query = query;
}
}

public static class Resp {
public List<SearchUser> users;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package me.grishka.houseclub.api.model;

public class SearchUser {
public int userId;
public String name;
public String photoUrl;
public String bio;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package me.grishka.houseclub.fragments;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.SearchView;
import android.widget.TextView;

import androidx.recyclerview.widget.RecyclerView;

import me.grishka.appkit.fragments.LoaderFragment;
import me.grishka.houseclub.R;

abstract class BaseSearchFragment extends LoaderFragment {

public static final String KEY_SEARCH_TYPE = "key_search_type";
private static final long DELAY = 200;

private RecyclerView recyclerView;
private TextView errorTextView;
private String errorMessage;

protected String searchQuery;
private SearchView searchView;
private SearchView.OnQueryTextListener onQueryTextListener;
private long timestamp = System.currentTimeMillis();

protected abstract <VH extends RecyclerView.ViewHolder> RecyclerView.Adapter<VH> getRecyclerAdapter();

@Override
public View onCreateContentView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_search, container, false);
}

@Override
public void loadData() {
dataLoading = true;
doLoadData();
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);

view.findViewById(R.id.toolbar).setVisibility(View.GONE);
showContent();

searchView = view.findViewById(R.id.searchView);

int searchTypeOrdinal = getArguments().getInt(KEY_SEARCH_TYPE);
SearchType searchType = SearchType.values()[searchTypeOrdinal];

String hint;
if (searchType == SearchType.PEOPLE) {
hint = view.getContext().getString(R.string.search_people_hint);
} else {
hint = view.getContext().getString(R.string.search_clubs_hint);
}

if (searchType == SearchType.PEOPLE) {
errorMessage = view.getContext().getString(R.string.search_error_no_users);
} else {
errorMessage = view.getContext().getString(R.string.search_error_no_clubs);
}

searchView.setQueryHint(hint);
onQueryTextListener = new OnSearchQueryTextListener();


recyclerView = view.findViewById(R.id.rvSearch);
recyclerView.setAdapter(getRecyclerAdapter());

errorTextView = view.findViewById(R.id.tvSearchError);

view.findViewById(R.id.tvSearchCancel).setOnClickListener(v -> getActivity().onBackPressed());
}

@Override
public void onResume() {
super.onResume();

searchView.setOnQueryTextListener(onQueryTextListener);
}

@Override
public void onPause() {
super.onPause();

searchView.setOnQueryTextListener(null);
}

protected void onUsersNotFound() {
if (errorTextView != null && errorMessage != null && errorTextView.getVisibility() != View.VISIBLE) {
recyclerView.setVisibility(View.GONE);
errorTextView.setVisibility(View.VISIBLE);
errorTextView.setText(errorMessage);
}
}

protected void onUsersFound() {
if (recyclerView != null && recyclerView.getVisibility() != View.VISIBLE) {
errorTextView.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
}
}

private void onQueryChanged(String query) {
long currentTimeStamp = System.currentTimeMillis();
if (currentTimeStamp - timestamp < DELAY) {
timestamp = currentTimeStamp;
return;
}

if (query == null || query.length() <= 2) {
timestamp = currentTimeStamp;
return;
}
timestamp = currentTimeStamp;
searchQuery = query;
loadData();
}

private class OnSearchQueryTextListener implements SearchView.OnQueryTextListener {
@Override
public boolean onQueryTextSubmit(String query) {
onQueryChanged(query);
return false;
}

@Override
public boolean onQueryTextChange(String newText) {
onQueryChanged(newText);
return false;
}
}

public enum SearchType {
PEOPLE,
CLUBS
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
package me.grishka.houseclub.fragments;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Outline;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
Expand All @@ -20,8 +17,6 @@
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import androidx.annotation.NonNull;
Expand All @@ -35,7 +30,6 @@
import me.grishka.appkit.utils.V;
import me.grishka.houseclub.MainActivity;
import me.grishka.houseclub.R;
import me.grishka.houseclub.VoiceService;
import me.grishka.houseclub.api.ClubhouseSession;
import me.grishka.houseclub.api.methods.GetChannels;
import me.grishka.houseclub.api.model.Channel;
Expand Down Expand Up @@ -113,15 +107,23 @@ public boolean wantsLightStatusBar(){

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
menu.add("").setIcon(R.drawable.ic_baseline_person_24).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
inflater.inflate(R.menu.menu_home, menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item){
Bundle args=new Bundle();
args.putInt("id", Integer.parseInt(ClubhouseSession.userID));
Nav.go(getActivity(), ProfileFragment.class, args);
return true;
if (item.getItemId() == R.id.homeMenuProfile) {
Bundle args=new Bundle();
args.putInt("id", Integer.parseInt(ClubhouseSession.userID));
Nav.go(getActivity(), ProfileFragment.class, args);
return true;
} else if (item.getItemId() == R.id.homeMenuSearchPeople) {
Bundle args = new Bundle();
args.putInt(BaseSearchFragment.KEY_SEARCH_TYPE, BaseSearchFragment.SearchType.PEOPLE.ordinal());
Nav.go(getActivity(), SearchPeopleFragment.class, args);
return true;
}
return false;
}

private class ChannelAdapter extends RecyclerView.Adapter<ChannelViewHolder> implements ImageLoaderRecyclerAdapter{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package me.grishka.houseclub.fragments;

import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
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.recyclerview.widget.RecyclerView;

import java.util.ArrayList;
import java.util.List;

import me.grishka.appkit.Nav;
import me.grishka.appkit.api.SimpleCallback;
import me.grishka.appkit.imageloader.ViewImageLoader;
import me.grishka.houseclub.R;
import me.grishka.houseclub.api.methods.SearchPeople;
import me.grishka.houseclub.api.model.SearchUser;

public class SearchPeopleFragment extends BaseSearchFragment {

private SearchPeopleRecyclerAdapter adapter;

@SuppressWarnings("unchecked")
@Override
protected <VH extends RecyclerView.ViewHolder> RecyclerView.Adapter<VH> getRecyclerAdapter() {
if (adapter == null) {
adapter = new SearchPeopleRecyclerAdapter();
}
return (RecyclerView.Adapter<VH>) adapter;
}

@Override
protected void doLoadData() {
String query = searchQuery;
if (query == null) {
return;
}

if (currentRequest != null) {
currentRequest.cancel();
}

currentRequest = new SearchPeople(query)
.setCallback(new SimpleCallback<SearchPeople.Resp>(this) {
@Override
public void onSuccess(SearchPeople.Resp result) {
dataLoaded();
if (adapter != null && result.users != null && !result.users.isEmpty()) {
onUsersFound();
adapter.updateUsers(result.users);
} else {
onUsersNotFound();
}
}
})
.exec();
}

@Override
public void onRefresh() {
}

private class SearchPeopleRecyclerAdapter extends RecyclerView.Adapter<SearchPeopleRecyclerAdapter.UserViewHolder> {

private final List<SearchUser> userList = new ArrayList<>();

@NonNull
@Override
public UserViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_search_user, parent, false);
return new UserViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull UserViewHolder holder, int position) {
SearchUser user = userList.get(position);
holder.itemView.setOnClickListener(v -> {
Bundle args = new Bundle();
args.putInt("id", user.userId);
Nav.go(getActivity(), ProfileFragment.class, args);
});
holder.bind(user);
}

@Override
public int getItemCount() {
return userList.size();
}

public void updateUsers(List<SearchUser> users) {
userList.clear();
userList.addAll(users);
notifyDataSetChanged();
}

private class UserViewHolder extends RecyclerView.ViewHolder {
private final TextView userNameView, userBioView;
private final ImageView userPhotoView;

UserViewHolder(View view) {
super(view);

userNameView = view.findViewById(R.id.tvUsername);
userBioView = view.findViewById(R.id.tvUserBio);
userPhotoView = view.findViewById(R.id.ivUserPhoto);
}

void bind(SearchUser user) {
userNameView.setText(user.name);
userBioView.setText(user.bio);

ColorDrawable placeholder = new ColorDrawable(0xFF808080);

ViewImageLoader.load(userPhotoView, placeholder, user.photoUrl);
}
}
}
}
15 changes: 15 additions & 0 deletions Houseclub/src/main/res/drawable/ic_search_people.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="512.01"
android:viewportHeight="512.01">
<path
android:fillColor="#FF000000"
android:pathData="M361.993,135c0,-24.813 -20.187,-45 -45,-45s-45,20.187 -45,45s20.187,45 45,45S361.993,159.813 361.993,135zM316.993,150c-8.271,0 -15,-6.729 -15,-15s6.729,-15 15,-15s15,6.729 15,15S325.264,150 316.993,150z" />
<path
android:fillColor="#FF000000"
android:pathData="M316.993,180c-41.355,0 -75,33.645 -75,75v30c0,8.284 6.716,15 15,15h120c8.284,0 15,-6.716 15,-15v-30C391.993,213.645 358.348,180 316.993,180zM361.993,270h-90v-15c0,-24.813 20.187,-45 45,-45s45,20.187 45,45V270z" />
<path
android:fillColor="#FF000000"
android:pathData="M316.993,0c-107.523,0 -195,87.477 -195,195c0,37.494 10.647,72.544 29.062,102.304L13.176,435.183c-17.544,17.544 -17.544,46.091 0,63.635c17.589,17.59 46.044,17.592 63.635,0l137.879,-137.879C244.449,379.353 279.499,390 316.993,390c107.523,0 195,-87.477 195,-195S424.517,0 316.993,0zM55.598,477.604c-5.866,5.865 -15.342,5.866 -21.209,0c-5.847,-5.847 -5.847,-15.362 0,-21.209l81.394,-81.394l21.209,21.209L55.598,477.604zM158.204,374.998l-21.209,-21.209l31.984,-31.983c6.519,7.598 13.611,14.69 21.209,21.209L158.204,374.998zM316.993,360c-90.981,0 -165,-74.019 -165,-165s74.019,-165 165,-165s165,74.019 165,165S407.975,360 316.993,360z" />
</vector>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

<solid android:color="@color/search_view_background" />
<corners android:radius="10dp" />

</shape>
Loading