diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index ed1e13d..5120c6c 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -39,6 +39,11 @@
android:name=".ui.activities.SearchUserActivity"
android:label="@string/activity_searchuser_title" />
+
+
+
-
+
-
\ No newline at end of file
diff --git a/app/src/main/java/org/communiquons/android/comunic/client/data/enums/KindSearchResult.java b/app/src/main/java/org/communiquons/android/comunic/client/data/enums/KindSearchResult.java
new file mode 100644
index 0000000..c048889
--- /dev/null
+++ b/app/src/main/java/org/communiquons/android/comunic/client/data/enums/KindSearchResult.java
@@ -0,0 +1,12 @@
+package org.communiquons.android.comunic.client.data.enums;
+
+/**
+ * Different kinds of search result
+ *
+ * @author Pierre HUBERT
+ */
+public enum KindSearchResult {
+ USER,
+ GROUP,
+ UNKNOWN
+}
diff --git a/app/src/main/java/org/communiquons/android/comunic/client/data/helpers/SearchHelper.java b/app/src/main/java/org/communiquons/android/comunic/client/data/helpers/SearchHelper.java
new file mode 100644
index 0000000..a76efd1
--- /dev/null
+++ b/app/src/main/java/org/communiquons/android/comunic/client/data/helpers/SearchHelper.java
@@ -0,0 +1,182 @@
+package org.communiquons.android.comunic.client.data.helpers;
+
+import android.content.Context;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.util.ArrayMap;
+
+import org.communiquons.android.comunic.client.data.enums.KindSearchResult;
+import org.communiquons.android.comunic.client.data.models.APIRequest;
+import org.communiquons.android.comunic.client.data.models.APIResponse;
+import org.communiquons.android.comunic.client.data.models.GroupInfo;
+import org.communiquons.android.comunic.client.data.models.SearchResult;
+import org.communiquons.android.comunic.client.data.models.SearchResultWithInfo;
+import org.communiquons.android.comunic.client.data.models.UserInfo;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+
+/**
+ * Search helper
+ *
+ * This helper is used to search users and groups
+ *
+ * @author Pierre HUBERT
+ */
+public class SearchHelper extends BaseHelper {
+
+ public SearchHelper(Context context) {
+ super(context);
+ }
+
+ /**
+ * Perform a global search in the database
+ *
+ * @param query The query to search for
+ * @return The list of results / null in case of failure
+ */
+ @Nullable
+ public ArrayList global(String query) {
+
+ //Prepare request
+ APIRequest request = new APIRequest(getContext(), "search/global");
+ request.addString("query", query);
+
+ //Execute request
+ try {
+ APIResponse response = request.exec();
+
+ if(response.getResponse_code() != 200)
+ return null;
+
+ //Get JSON data
+ JSONArray data = response.getJSONArray();
+ if(data == null)
+ return null;
+
+ //Parse and return results
+ ArrayList results = new ArrayList<>();
+ for(int i = 0; i < data.length(); i++)
+ results.add(JSONObjectToSearchResult(data.getJSONObject(i)));
+ return results;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+
+ }
+
+
+ /**
+ * Fill search result with information for users, groups...
+ *
+ * @param list The list of results to process
+ * @return Information for groups, users / null in case of failure
+ */
+ @Nullable
+ public ArrayList fillResults(@NonNull ArrayList list){
+
+ ArrayList listWithInfo = new ArrayList<>();
+
+ //Extract the ids of the users and the groups to get
+ ArrayList usersID = new ArrayList<>();
+ ArrayList groupsID = new ArrayList<>();
+
+ for(SearchResult result : list){
+ if(result.getKind() == KindSearchResult.USER)
+ usersID.add(result.getId());
+
+ else if(result.getKind() == KindSearchResult.GROUP)
+ groupsID.add(result.getId());
+
+ SearchResultWithInfo resultWithInfo = new SearchResultWithInfo();
+ result.copyTo(resultWithInfo);
+ listWithInfo.add(resultWithInfo);
+ }
+
+ //Get information about users (if any)
+ if(usersID.size() > 0){
+
+ ArrayMap usersInfo = new GetUsersHelper(getContext())
+ .getMultiple(usersID);
+
+ if(usersInfo == null)
+ return null;
+
+ //Process the list of result to apply information
+ for(SearchResultWithInfo result : listWithInfo){
+
+ //Skip non related entries
+ if(result.getKind() != KindSearchResult.USER)
+ continue;
+
+ result.setUserInfo(usersInfo.get(result.getId()));
+ }
+
+ }
+
+ //Get information about groups (if any)
+ if(groupsID.size() > 0){
+
+ ArrayMap groupsInfo = new GroupsHelper(getContext())
+ .getInfoMultiple(groupsID);
+
+ if(groupsInfo == null)
+ return null;
+
+ //Process the list of result to apply information
+ for(SearchResultWithInfo result : listWithInfo){
+
+ //Skip non related entries
+ if(result.getKind() != KindSearchResult.GROUP)
+ continue;
+
+ result.setGroupInfo(groupsInfo.get(result.getId()));
+ }
+
+ }
+
+
+ return listWithInfo;
+ }
+
+ /**
+ * Turn a string into a search kind result
+ *
+ * @param string The string to convert
+ * @return Matching search result
+ */
+ private static KindSearchResult StringToKindSearchResult(String string){
+ switch (string){
+
+ case "user":
+ return KindSearchResult.USER;
+
+ case "group":
+ return KindSearchResult.GROUP;
+
+ default:
+ return KindSearchResult.UNKNOWN;
+ }
+ }
+
+
+ /**
+ * Turn a JSONObject into a SearchResult object
+ *
+ * @param object The object to convert
+ * @return Generated SearchResult object
+ * @throws JSONException This exception is thrown in case of failure
+ */
+ private static SearchResult JSONObjectToSearchResult(JSONObject object) throws JSONException {
+ SearchResult result = new SearchResult();
+
+ result.setId(object.getInt("id"));
+ result.setKind(StringToKindSearchResult(object.getString("kind")));
+
+ return result;
+ }
+}
diff --git a/app/src/main/java/org/communiquons/android/comunic/client/data/models/APIRequest.java b/app/src/main/java/org/communiquons/android/comunic/client/data/models/APIRequest.java
index 672e599..08104be 100644
--- a/app/src/main/java/org/communiquons/android/comunic/client/data/models/APIRequest.java
+++ b/app/src/main/java/org/communiquons/android/comunic/client/data/models/APIRequest.java
@@ -2,6 +2,8 @@ package org.communiquons.android.comunic.client.data.models;
import android.content.Context;
+import org.communiquons.android.comunic.client.data.helpers.APIRequestHelper;
+
import java.util.ArrayList;
/**
@@ -99,17 +101,17 @@ public class APIRequest {
public String get_parameters_encoded(){
//Return string
- String result = "";
+ StringBuilder result = new StringBuilder();
//Process loop
for(int i = 0; i < parameters.size(); i++){
//Make sure to separate parameters
- result += (i > 0 ? "&" : "");
- result += parameters.get(i).get_encoded();
+ result.append(i > 0 ? "&" : "");
+ result.append(parameters.get(i).get_encoded());
}
- return result;
+ return result.toString();
}
/**
@@ -147,4 +149,16 @@ public class APIRequest {
public boolean isTryContinueOnError() {
return tryContinueOnError;
}
+
+ /**
+ * Execute the request
+ *
+ * This is a convenience method
+ *
+ * @return The result of the operation
+ * @throws Exception In case of failure
+ */
+ public APIResponse exec() throws Exception {
+ return new APIRequestHelper().exec(this);
+ }
}
diff --git a/app/src/main/java/org/communiquons/android/comunic/client/data/models/SearchResult.java b/app/src/main/java/org/communiquons/android/comunic/client/data/models/SearchResult.java
new file mode 100644
index 0000000..9e7fbac
--- /dev/null
+++ b/app/src/main/java/org/communiquons/android/comunic/client/data/models/SearchResult.java
@@ -0,0 +1,46 @@
+package org.communiquons.android.comunic.client.data.models;
+
+import org.communiquons.android.comunic.client.data.enums.KindSearchResult;
+
+/**
+ * Single search result
+ *
+ * @author Pierre HUBERT
+ */
+public class SearchResult {
+
+ //Private fields
+ private int id;
+ private KindSearchResult kind;
+
+ /**
+ * Base constructor
+ */
+ public SearchResult(){}
+
+ /**
+ * Copy the values of the current object to a new object
+ *
+ * @param dst Destination object
+ */
+ public void copyTo(SearchResult dst){
+ dst.setId(getId());
+ dst.setKind(getKind());
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public KindSearchResult getKind() {
+ return kind;
+ }
+
+ public void setKind(KindSearchResult kind) {
+ this.kind = kind;
+ }
+}
diff --git a/app/src/main/java/org/communiquons/android/comunic/client/data/models/SearchResultWithInfo.java b/app/src/main/java/org/communiquons/android/comunic/client/data/models/SearchResultWithInfo.java
new file mode 100644
index 0000000..6918226
--- /dev/null
+++ b/app/src/main/java/org/communiquons/android/comunic/client/data/models/SearchResultWithInfo.java
@@ -0,0 +1,28 @@
+package org.communiquons.android.comunic.client.data.models;
+
+/**
+ * This object handles a search result and all the information associated with it
+ *
+ * @author Pierre HUBERT
+ */
+public class SearchResultWithInfo extends SearchResult {
+
+ private GroupInfo groupInfo;
+ private UserInfo userInfo;
+
+ public GroupInfo getGroupInfo() {
+ return groupInfo;
+ }
+
+ public void setGroupInfo(GroupInfo groupInfo) {
+ this.groupInfo = groupInfo;
+ }
+
+ public UserInfo getUserInfo() {
+ return userInfo;
+ }
+
+ public void setUserInfo(UserInfo userInfo) {
+ this.userInfo = userInfo;
+ }
+}
diff --git a/app/src/main/java/org/communiquons/android/comunic/client/ui/Constants.java b/app/src/main/java/org/communiquons/android/comunic/client/ui/Constants.java
index 9f09fde..80f9a1e 100644
--- a/app/src/main/java/org/communiquons/android/comunic/client/ui/Constants.java
+++ b/app/src/main/java/org/communiquons/android/comunic/client/ui/Constants.java
@@ -28,14 +28,36 @@ public final class Constants {
public static final int POST_CREATE_FORM_PICK_PHOTO = 2;
/**
- * Intent code : search a user
+ * Main Activity : search a user
*/
public static final int MAIN_ACTIVITY_SEARCH_USER_INTENT = 3;
+ /**
+ * Main Activity : make a global search
+ */
+ public static final int MAIN_ACTIVITY_GLOBAL_SEARCH_INTENT = 4;
+
/**
* Pick image to update account image
*/
- public static final int ACCOUNT_IMAGE_SETTINGS_PICK_NEW_INTENT = 4;
+ public static final int ACCOUNT_IMAGE_SETTINGS_PICK_NEW_INTENT = 5;
}
+
+ /**
+ * Intents results
+ */
+ public final class IntentResults {
+
+ /**
+ * Search user result
+ */
+ public static final String SEARCH_USER_RESULT = "org.communiquons.android.searchUser.RESULT";
+
+ /**
+ * Global search result
+ */
+ public static final String SEARCH_GLOBAL_RESULT = "org.communiquons.android.globalSearch.RESULT";
+
+ }
}
diff --git a/app/src/main/java/org/communiquons/android/comunic/client/ui/activities/BaseActivity.java b/app/src/main/java/org/communiquons/android/comunic/client/ui/activities/BaseActivity.java
index 51db929..1f38cf9 100644
--- a/app/src/main/java/org/communiquons/android/comunic/client/ui/activities/BaseActivity.java
+++ b/app/src/main/java/org/communiquons/android/comunic/client/ui/activities/BaseActivity.java
@@ -1,9 +1,13 @@
package org.communiquons.android.comunic.client.ui.activities;
+import android.os.Bundle;
+import android.support.annotation.CallSuper;
import android.support.annotation.NonNull;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
+import org.communiquons.android.comunic.client.ui.asynctasks.SafeAsyncTasksManager;
+
/**
* Base application activity
*
@@ -11,10 +15,40 @@ import android.support.v7.app.AppCompatActivity;
*/
public abstract class BaseActivity extends AppCompatActivity {
+ /**
+ * Tasks manager
+ */
+ private SafeAsyncTasksManager mSafeAsyncTasksManager = null;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ //Initialize task manager
+ mSafeAsyncTasksManager = new SafeAsyncTasksManager();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+
+ //Unset all task
+ mSafeAsyncTasksManager.unsetAllTasks();
+ }
+
@NonNull
@Override
public ActionBar getSupportActionBar() {
assert super.getSupportActionBar() != null;
return super.getSupportActionBar();
}
+
+ /**
+ * Get tasks manager associated with this activity
+ *
+ * @return Task manager associated to this activity
+ */
+ public SafeAsyncTasksManager getTasksManager() {
+ return mSafeAsyncTasksManager;
+ }
}
diff --git a/app/src/main/java/org/communiquons/android/comunic/client/ui/activities/MainActivity.java b/app/src/main/java/org/communiquons/android/comunic/client/ui/activities/MainActivity.java
index 0ab4e6b..ac3d045 100644
--- a/app/src/main/java/org/communiquons/android/comunic/client/ui/activities/MainActivity.java
+++ b/app/src/main/java/org/communiquons/android/comunic/client/ui/activities/MainActivity.java
@@ -7,6 +7,7 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
+import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
@@ -49,14 +50,16 @@ import org.communiquons.android.comunic.client.ui.fragments.groups.GroupPageMain
import org.communiquons.android.comunic.client.ui.fragments.groups.UserGroupsFragment;
import org.communiquons.android.comunic.client.ui.fragments.userpage.UserAccessDeniedFragment;
import org.communiquons.android.comunic.client.ui.fragments.userpage.UserPageFragment;
-import org.communiquons.android.comunic.client.ui.listeners.OnOpenGroupListener;
-import org.communiquons.android.comunic.client.ui.listeners.onOpenUsersPageListener;
+import org.communiquons.android.comunic.client.ui.listeners.OnOpenPageListener;
import org.communiquons.android.comunic.client.ui.listeners.onPostOpenListener;
import org.communiquons.android.comunic.client.ui.listeners.openConversationListener;
import org.communiquons.android.comunic.client.ui.listeners.updateConversationListener;
import org.communiquons.android.comunic.client.ui.utils.UiUtils;
import org.communiquons.android.comunic.client.ui.views.NavigationBar;
+import java.util.Objects;
+
+import static org.communiquons.android.comunic.client.ui.Constants.IntentRequestCode.MAIN_ACTIVITY_GLOBAL_SEARCH_INTENT;
import static org.communiquons.android.comunic.client.ui.Constants.IntentRequestCode.MAIN_ACTIVITY_SEARCH_USER_INTENT;
@@ -66,8 +69,8 @@ import static org.communiquons.android.comunic.client.ui.Constants.IntentRequest
* @author Pierre HUBERT
*/
public class MainActivity extends BaseActivity implements
- openConversationListener, updateConversationListener, onOpenUsersPageListener,
- onPostOpenListener, NavigationBar.OnNavigationItemSelectedListener, OnOpenGroupListener {
+ openConversationListener, updateConversationListener, OnOpenPageListener,
+ onPostOpenListener, NavigationBar.OnNavigationItemSelectedListener {
/**
* Debug tag
@@ -245,9 +248,9 @@ public class MainActivity extends BaseActivity implements
return true;
}
- //To search a user
- if (id == R.id.action_search_user) {
- searchUser();
+ //To perform a wider search
+ if(id == R.id.action_search) {
+ searchGlobal();
return true;
}
@@ -387,9 +390,28 @@ public class MainActivity extends BaseActivity implements
switch (requestCode) {
+ //User search
case MAIN_ACTIVITY_SEARCH_USER_INTENT:
assert data.getData() != null;
- openUserPage(Integer.decode(data.getData().getQueryParameter("userID")));
+ openUserPage(Integer.decode(
+ Objects.requireNonNull(
+ data.getData().getQueryParameter("userID"))));
+ break;
+
+
+ //Global search result
+ case MAIN_ACTIVITY_GLOBAL_SEARCH_INTENT:
+ assert data.getData() != null;
+
+ //Open user page or group accordingly to the choice of the user
+ Uri result = data.getData();
+ String type = result.getQueryParameter(SearchActivity.INTENT_ARG_RESULT_TYPE);
+ int id = Integer.decode(Objects.requireNonNull(result.getQueryParameter(SearchActivity.INTENT_ARG_RESULT_ID)));
+ if(Objects.equals(type, SearchActivity.INTENT_RESULT_USER))
+ openUserPage(id);
+ else
+ onOpenGroup(id);
+
break;
}
@@ -759,6 +781,17 @@ public class MainActivity extends BaseActivity implements
}
+ /**
+ * Perform a global search
+ */
+ private void searchGlobal(){
+
+ //Make intent
+ Intent intent = new Intent(this, SearchActivity.class);
+ startActivityForResult(intent, MAIN_ACTIVITY_GLOBAL_SEARCH_INTENT);
+
+ }
+
/**
* Open group page
*
diff --git a/app/src/main/java/org/communiquons/android/comunic/client/ui/activities/SearchActivity.java b/app/src/main/java/org/communiquons/android/comunic/client/ui/activities/SearchActivity.java
new file mode 100644
index 0000000..d8dc470
--- /dev/null
+++ b/app/src/main/java/org/communiquons/android/comunic/client/ui/activities/SearchActivity.java
@@ -0,0 +1,178 @@
+package org.communiquons.android.comunic.client.ui.activities;
+
+import android.content.Intent;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.view.MenuItem;
+import android.widget.EditText;
+import android.widget.Toast;
+
+import org.communiquons.android.comunic.client.R;
+import org.communiquons.android.comunic.client.data.models.SearchResultWithInfo;
+import org.communiquons.android.comunic.client.ui.Constants;
+import org.communiquons.android.comunic.client.ui.adapters.SearchResultsAdapter;
+import org.communiquons.android.comunic.client.ui.asynctasks.GlobalSearchTask;
+import org.communiquons.android.comunic.client.ui.asynctasks.SafeAsyncTask;
+import org.communiquons.android.comunic.client.ui.listeners.OnOpenPageListener;
+
+import java.util.ArrayList;
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * Search activity
+ *
+ * This activity can be used to search both users and groups
+ *
+ * @author Pierre HUBERT
+ */
+public class SearchActivity extends BaseActivity implements TextWatcher, OnOpenPageListener {
+
+ /**
+ * Debug tag
+ */
+ private static final String TAG = SearchActivity.class.getSimpleName();
+
+
+ /**
+ * Results type
+ */
+ public static final String INTENT_ARG_RESULT_ID = "id";
+ public static final String INTENT_ARG_RESULT_TYPE = "type";
+ public static final String INTENT_RESULT_USER = "user";
+ public static final String INTENT_RESULT_GROUP = "group";
+
+
+ /**
+ * Adapters
+ */
+ private SearchResultsAdapter mAdapter;
+
+
+ /**
+ * Views
+ */
+ private RecyclerView mRecyclerView;
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_search);
+
+ //Add go back button
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+
+ ((EditText)findViewById(R.id.searchInput)).addTextChangedListener(this);
+
+ //Initialize recycler view
+ mRecyclerView = findViewById(R.id.resultsRecyclerView);
+ mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
+ mAdapter = new SearchResultsAdapter(this ,this);
+ mRecyclerView.setAdapter(mAdapter);
+
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+
+
+ switch (item.getItemId()){
+
+ //Check if we have to finish activity
+ case android.R.id.home:
+ finish();
+ return true;
+
+ }
+
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+
+ //Check if user did not type at least three characters
+ if(s.length() < 3)
+ return; //We ignore small researches
+
+ //Perform the search
+ getTasksManager().unsetSpecificTasks(GlobalSearchTask.class);
+ GlobalSearchTask task = new GlobalSearchTask(this);
+
+ task.setOnPostExecuteListener(new SafeAsyncTask.OnPostExecuteListener>() {
+ @Override
+ public void OnPostExecute(@Nullable ArrayList searchResultWithInfoList) {
+ onGotNewList(searchResultWithInfoList);
+ }
+ });
+
+ task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ""+s);
+ getTasksManager().addTask(task);
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+
+ }
+
+ private void onGotNewList(@Nullable ArrayList list){
+
+ //First, check for errors
+ if(list == null){
+ Toast.makeText(this, R.string.err_get_search_results, Toast.LENGTH_SHORT).show();
+ return;
+ }
+
+ //Apply search results
+ mAdapter.setList(list);
+ }
+
+ @Override
+ public void onOpenGroup(int groupID) {
+ sendResult(groupID, INTENT_RESULT_GROUP);
+ }
+
+ @Override
+ public void onOpenGroupAccessDenied(int groupID) {
+ onOpenGroup(groupID);
+ }
+
+ @Override
+ public void openUserPage(int userID) {
+ sendResult(userID, INTENT_RESULT_USER);
+ }
+
+ @Override
+ public void openUserAccessDeniedPage(int userID) {
+ openUserPage(userID);
+ }
+
+ /**
+ * This method is called once the user has made a selection
+ *
+ * @param id The id of the element chosen by the user
+ * @param type The type of the element chosen by the user
+ */
+ private void sendResult(int id, String type){
+
+ //Send result and terminates activity
+ Intent intent = new Intent(Constants.IntentResults.SEARCH_GLOBAL_RESULT);
+ intent.setData(Uri.parse("?" + INTENT_ARG_RESULT_TYPE+"="+type+"&"+INTENT_ARG_RESULT_ID+"="+id));
+ setResult(RESULT_OK, intent);
+ finish();
+
+ }
+}
diff --git a/app/src/main/java/org/communiquons/android/comunic/client/ui/activities/SearchUserActivity.java b/app/src/main/java/org/communiquons/android/comunic/client/ui/activities/SearchUserActivity.java
index 37ce966..7f5474c 100644
--- a/app/src/main/java/org/communiquons/android/comunic/client/ui/activities/SearchUserActivity.java
+++ b/app/src/main/java/org/communiquons/android/comunic/client/ui/activities/SearchUserActivity.java
@@ -18,6 +18,7 @@ import android.widget.Toast;
import org.communiquons.android.comunic.client.R;
import org.communiquons.android.comunic.client.data.helpers.DatabaseHelper;
import org.communiquons.android.comunic.client.data.helpers.GetUsersHelper;
+import org.communiquons.android.comunic.client.ui.Constants;
import org.communiquons.android.comunic.client.ui.adapters.UsersBasicAdapter;
import org.communiquons.android.comunic.client.data.models.UserInfo;
@@ -81,7 +82,7 @@ public class SearchUserActivity extends AppCompatActivity
*/
private void onGotUserID(int userID){
- Intent data = new Intent("org.communiquons.android.RESULT");
+ Intent data = new Intent(Constants.IntentResults.SEARCH_USER_RESULT);
data.setData(Uri.parse("?userID=" + userID));
setResult(RESULT_OK, data);
finish();
diff --git a/app/src/main/java/org/communiquons/android/comunic/client/ui/adapters/GroupsListAdapter.java b/app/src/main/java/org/communiquons/android/comunic/client/ui/adapters/GroupsListAdapter.java
index de2dfa2..dfefbab 100644
--- a/app/src/main/java/org/communiquons/android/comunic/client/ui/adapters/GroupsListAdapter.java
+++ b/app/src/main/java/org/communiquons/android/comunic/client/ui/adapters/GroupsListAdapter.java
@@ -6,13 +6,11 @@ import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.TextView;
import org.communiquons.android.comunic.client.R;
import org.communiquons.android.comunic.client.data.models.GroupInfo;
import org.communiquons.android.comunic.client.ui.listeners.OnGroupActionListener;
-import org.communiquons.android.comunic.client.ui.views.GroupImageView;
-import org.communiquons.android.comunic.client.ui.views.GroupMembershipStatusView;
+import org.communiquons.android.comunic.client.ui.viewholders.GroupViewHolder;
import java.util.ArrayList;
@@ -62,55 +60,12 @@ public class GroupsListAdapter extends BaseRecyclerViewAdapter {
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(getContext()).inflate(
R.layout.viewholder_group, viewGroup, false);
- return new GroupHolder(view);
+ return new GroupViewHolder(view, mOnGroupActionListener);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
- ((GroupHolder)viewHolder).bind(i);
+ ((GroupViewHolder)viewHolder).bind(mList.get(i));
}
-
- /**
- * Single group holder class
- */
- private class GroupHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
-
-
- private GroupInfo mGroupInfo;
-
-
- private GroupImageView mGroupImageView;
- private TextView mGroupName;
- private GroupMembershipStatusView mGroupMembershipStatus;
-
- GroupHolder(@NonNull View itemView) {
- super(itemView);
-
- itemView.setOnClickListener(this);
-
- mGroupImageView = itemView.findViewById(R.id.groupImage);
- mGroupName = itemView.findViewById(R.id.groupName);
- mGroupMembershipStatus = itemView.findViewById(R.id.groupMembershipStatusView);
-
- mGroupMembershipStatus.setOnGroupMembershipUpdateListener(mOnGroupActionListener);
- }
-
- GroupInfo getGroup(int pos){
- return mList.get(pos);
- }
-
- void bind(int pos){
- mGroupInfo = getGroup(pos);
- mGroupImageView.setGroup(mGroupInfo);
- mGroupName.setText(mGroupInfo.getDisplayName());
- mGroupMembershipStatus.setGroup(mGroupInfo);
- }
-
- @Override
- public void onClick(View v) {
- if(v.equals(itemView))
- mOnGroupActionListener.onOpenGroup(mGroupInfo.getId());
- }
- }
}
diff --git a/app/src/main/java/org/communiquons/android/comunic/client/ui/adapters/SearchResultsAdapter.java b/app/src/main/java/org/communiquons/android/comunic/client/ui/adapters/SearchResultsAdapter.java
new file mode 100644
index 0000000..22d7496
--- /dev/null
+++ b/app/src/main/java/org/communiquons/android/comunic/client/ui/adapters/SearchResultsAdapter.java
@@ -0,0 +1,112 @@
+package org.communiquons.android.comunic.client.ui.adapters;
+
+import android.content.Context;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+
+import org.communiquons.android.comunic.client.R;
+import org.communiquons.android.comunic.client.data.enums.KindSearchResult;
+import org.communiquons.android.comunic.client.data.models.SearchResultWithInfo;
+import org.communiquons.android.comunic.client.ui.listeners.OnOpenPageListener;
+import org.communiquons.android.comunic.client.ui.viewholders.GroupViewHolder;
+import org.communiquons.android.comunic.client.ui.viewholders.UserViewHolder;
+
+import java.util.ArrayList;
+
+/**
+ * Search results adapter
+ *
+ * @author Pierre HUBERT
+ */
+public class SearchResultsAdapter extends BaseRecyclerViewAdapter {
+
+ /**
+ * The list of results to the search
+ */
+ private ArrayList mList;
+
+ /**
+ * Open listener
+ */
+ private OnOpenPageListener openPageListener;
+
+ /**
+ * Get view types
+ */
+ private final int VIEW_TYPE_USER = 0;
+ private final int VIEW_TYPE_GROUP = 1;
+
+ public SearchResultsAdapter(Context context, @Nullable OnOpenPageListener openPageListener) {
+ super(context);
+
+ this.mList = new ArrayList<>();
+ this.openPageListener = openPageListener;
+ }
+
+ /**
+ * Set (update) the list of search results
+ *
+ * @param list New list to apply
+ */
+ public void setList(ArrayList list){
+ this.mList = list;
+ notifyDataSetChanged();
+ }
+
+ @Override
+ public int getItemCount() {
+ return mList.size();
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ return mList.get(position).getKind() == KindSearchResult.USER ?
+ VIEW_TYPE_USER : VIEW_TYPE_GROUP;
+ }
+
+ @NonNull
+ @Override
+ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int type) {
+
+ RecyclerView.ViewHolder viewHolder;
+
+ if(type == VIEW_TYPE_USER){
+ viewHolder = new UserViewHolder(LayoutInflater
+ .from(getContext())
+ .inflate(R.layout.viewholder_user, viewGroup, false)
+ , openPageListener);
+ }
+
+ else if(type == VIEW_TYPE_GROUP){
+ viewHolder = new GroupViewHolder(LayoutInflater
+ .from(getContext())
+ .inflate(R.layout.viewholder_group, viewGroup, false)
+ , openPageListener);
+ }
+
+ else
+ throw new RuntimeException("Intend to display a none supported kind of result!");
+
+
+ return viewHolder;
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
+
+ SearchResultWithInfo searchResultWithInfo = mList.get(i);
+
+ if(searchResultWithInfo.getKind() == KindSearchResult.USER){
+ ((UserViewHolder)viewHolder).bind(searchResultWithInfo.getUserInfo());
+ }
+
+ if(searchResultWithInfo.getKind() == KindSearchResult.GROUP){
+ ((GroupViewHolder)viewHolder).bind(searchResultWithInfo.getGroupInfo());
+ }
+ }
+
+
+}
diff --git a/app/src/main/java/org/communiquons/android/comunic/client/ui/adapters/UsersBasicAdapter.java b/app/src/main/java/org/communiquons/android/comunic/client/ui/adapters/UsersBasicAdapter.java
index 2050b1d..69c00c6 100644
--- a/app/src/main/java/org/communiquons/android/comunic/client/ui/adapters/UsersBasicAdapter.java
+++ b/app/src/main/java/org/communiquons/android/comunic/client/ui/adapters/UsersBasicAdapter.java
@@ -59,6 +59,7 @@ public class UsersBasicAdapter extends ArrayAdapter {
account_image.setUser(userInfos);
}
+
return convertView;
}
}
diff --git a/app/src/main/java/org/communiquons/android/comunic/client/ui/asynctasks/GlobalSearchTask.java b/app/src/main/java/org/communiquons/android/comunic/client/ui/asynctasks/GlobalSearchTask.java
new file mode 100644
index 0000000..5254c5f
--- /dev/null
+++ b/app/src/main/java/org/communiquons/android/comunic/client/ui/asynctasks/GlobalSearchTask.java
@@ -0,0 +1,32 @@
+package org.communiquons.android.comunic.client.ui.asynctasks;
+
+import android.content.Context;
+import android.support.annotation.Nullable;
+
+import org.communiquons.android.comunic.client.data.helpers.SearchHelper;
+import org.communiquons.android.comunic.client.data.models.SearchResult;
+import org.communiquons.android.comunic.client.data.models.SearchResultWithInfo;
+
+import java.util.ArrayList;
+
+public class GlobalSearchTask extends SafeAsyncTask> {
+
+ public GlobalSearchTask(Context context) {
+ super(context);
+ }
+
+ @Override
+ @Nullable
+ protected ArrayList doInBackground(String... strings) {
+
+ SearchHelper helper = new SearchHelper(getContext());
+
+ //First, perform the search itself
+ ArrayList list = helper.global(strings[0]);
+ if(list == null)
+ return null;
+
+ //Then get information about related users and groups
+ return helper.fillResults(list);
+ }
+}
diff --git a/app/src/main/java/org/communiquons/android/comunic/client/ui/listeners/OnOpenPageListener.java b/app/src/main/java/org/communiquons/android/comunic/client/ui/listeners/OnOpenPageListener.java
new file mode 100644
index 0000000..6c66d5e
--- /dev/null
+++ b/app/src/main/java/org/communiquons/android/comunic/client/ui/listeners/OnOpenPageListener.java
@@ -0,0 +1,9 @@
+package org.communiquons.android.comunic.client.ui.listeners;
+
+/**
+ * Implement this interface on activities that can open group and user pages
+ *
+ * @author Pierre HUBERT
+ */
+public interface OnOpenPageListener extends OnOpenGroupListener, onOpenUsersPageListener {
+}
diff --git a/app/src/main/java/org/communiquons/android/comunic/client/ui/viewholders/GroupViewHolder.java b/app/src/main/java/org/communiquons/android/comunic/client/ui/viewholders/GroupViewHolder.java
new file mode 100644
index 0000000..a90ddc6
--- /dev/null
+++ b/app/src/main/java/org/communiquons/android/comunic/client/ui/viewholders/GroupViewHolder.java
@@ -0,0 +1,73 @@
+package org.communiquons.android.comunic.client.ui.viewholders;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+import android.widget.TextView;
+
+import org.communiquons.android.comunic.client.R;
+import org.communiquons.android.comunic.client.data.models.GroupInfo;
+import org.communiquons.android.comunic.client.ui.listeners.OnGroupActionListener;
+import org.communiquons.android.comunic.client.ui.listeners.OnOpenGroupListener;
+import org.communiquons.android.comunic.client.ui.views.GroupImageView;
+import org.communiquons.android.comunic.client.ui.views.GroupMembershipStatusView;
+
+/**
+ * Single group holder class
+ *
+ * @author Pierre HUBERT
+ */
+public class GroupViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
+
+
+ private GroupInfo mGroupInfo;
+
+ private OnOpenGroupListener mOnOpenGroupListener;
+
+ private GroupImageView mGroupImageView;
+ private TextView mGroupName;
+ private GroupMembershipStatusView mGroupMembershipStatus;
+
+
+ public GroupViewHolder(@NonNull View itemView, @Nullable OnOpenGroupListener openGroupListener){
+ this(itemView, null);
+ mOnOpenGroupListener = openGroupListener;
+ }
+
+ public GroupViewHolder(@NonNull View itemView, @Nullable OnGroupActionListener actionListener) {
+ super(itemView);
+
+ itemView.setOnClickListener(this);
+
+ mGroupImageView = itemView.findViewById(R.id.groupImage);
+ mGroupName = itemView.findViewById(R.id.groupName);
+ mGroupMembershipStatus = itemView.findViewById(R.id.groupMembershipStatusView);
+
+ if(actionListener != null) {
+ mGroupMembershipStatus.setOnGroupMembershipUpdateListener(actionListener);
+ mOnOpenGroupListener = actionListener;
+ }
+ else
+ mGroupMembershipStatus.setVisibility(View.GONE);
+ }
+
+
+ /**
+ * Bind (apply) a new group to the view
+ *
+ * @param group The group to apply to the view
+ */
+ public void bind(GroupInfo group){
+ mGroupInfo = group;
+ mGroupImageView.setGroup(mGroupInfo);
+ mGroupName.setText(mGroupInfo.getDisplayName());
+ mGroupMembershipStatus.setGroup(mGroupInfo);
+ }
+
+ @Override
+ public void onClick(View v) {
+ if(v.equals(itemView) && mOnOpenGroupListener != null)
+ mOnOpenGroupListener.onOpenGroup(mGroupInfo.getId());
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/communiquons/android/comunic/client/ui/viewholders/UserViewHolder.java b/app/src/main/java/org/communiquons/android/comunic/client/ui/viewholders/UserViewHolder.java
new file mode 100644
index 0000000..eac706f
--- /dev/null
+++ b/app/src/main/java/org/communiquons/android/comunic/client/ui/viewholders/UserViewHolder.java
@@ -0,0 +1,56 @@
+package org.communiquons.android.comunic.client.ui.viewholders;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+import android.widget.TextView;
+
+import org.communiquons.android.comunic.client.R;
+import org.communiquons.android.comunic.client.data.models.UserInfo;
+import org.communiquons.android.comunic.client.ui.listeners.onOpenUsersPageListener;
+import org.communiquons.android.comunic.client.ui.views.WebUserAccountImage;
+
+/**
+ * User view holder
+ *
+ * Handles displaying of a single user
+ *
+ * @author Pierre HUBERT
+ */
+public class UserViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
+
+ //Private fields
+ private onOpenUsersPageListener mListener;
+ private WebUserAccountImage mUserAccountImage;
+ private TextView mUserName;
+ private UserInfo mUserInfo;
+
+ public UserViewHolder(@NonNull View itemView, @Nullable onOpenUsersPageListener listener) {
+ super(itemView);
+
+ mUserAccountImage = itemView.findViewById(R.id.user_account_image);
+ mUserName = itemView.findViewById(R.id.user_name);
+
+ this.mListener = listener;
+ itemView.setOnClickListener(this);
+ }
+
+
+ /**
+ * Apply a new user to this view
+ *
+ * @param userInfo Information about the user to apply
+ */
+ public void bind(UserInfo userInfo){
+ this.mUserInfo = userInfo;
+ mUserAccountImage.setUser(userInfo);
+ mUserName.setText(userInfo.getDisplayFullName());
+ }
+
+ @Override
+ public void onClick(View v) {
+ if(mListener != null && v.equals(itemView))
+ mListener.openUserPage(mUserInfo.getId());
+ }
+}
diff --git a/app/src/main/res/layout/activity_search.xml b/app/src/main/res/layout/activity_search.xml
new file mode 100644
index 0000000..12ad53b
--- /dev/null
+++ b/app/src/main/res/layout/activity_search.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/viewholder_user.xml b/app/src/main/res/layout/viewholder_user.xml
new file mode 100644
index 0000000..9c8c68e
--- /dev/null
+++ b/app/src/main/res/layout/viewholder_user.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/main_menu.xml b/app/src/main/res/menu/main_menu.xml
index 5a0abcb..ef4167b 100644
--- a/app/src/main/res/menu/main_menu.xml
+++ b/app/src/main/res/menu/main_menu.xml
@@ -9,8 +9,8 @@
+ android:id="@+id/action_search"
+ android:title="@string/main_menu_search" />
- Annuler
Quitter
Une erreur a survenue lors de la mise à jour de votre appartenance au groupe !
+ Rechercher
+ Recherche
+ Rechercher un utilisateur, un groupe…
+ Une erreur a survenue lors de la récupération du résultat de votre recherche !
+ Accès au groupe refusé.
+ Impossible de récupérer les informations sur le groupe !
+ Accès sur invitation
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 847868f..cab995c 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -314,4 +314,8 @@
Could not get group information!
Access to the group denied.
Invitation only
+ Search
+ Search
+ Search a user, a group…
+ Could not get results of your search!