diff --git a/docs-android/app/app.iml b/docs-android/app/app.iml
index 3aac58b8..7821ca38 100644
--- a/docs-android/app/app.iml
+++ b/docs-android/app/app.iml
@@ -102,6 +102,7 @@
+
diff --git a/docs-android/app/build.gradle b/docs-android/app/build.gradle
index c48d012a..7a40c4ba 100644
--- a/docs-android/app/build.gradle
+++ b/docs-android/app/build.gradle
@@ -35,4 +35,5 @@ dependencies {
compile 'com.android.support:recyclerview-v7:21.0.0'
compile 'com.loopj.android:android-async-http:1.4.6'
compile 'it.sephiroth.android.library.imagezoom:imagezoom:1.0.5'
+ compile 'de.greenrobot:eventbus:2.4.0'
}
diff --git a/docs-android/app/src/main/AndroidManifest.xml b/docs-android/app/src/main/AndroidManifest.xml
index 2f0116b7..6719ebd1 100644
--- a/docs-android/app/src/main/AndroidManifest.xml
+++ b/docs-android/app/src/main/AndroidManifest.xml
@@ -27,12 +27,19 @@
android:label="@string/app_name"
android:logo="@drawable/ic_launcher"
android:launchMode="singleTop">
+
+
+
+
+
diff --git a/docs-android/app/src/main/java/com/sismics/docs/MainApplication.java b/docs-android/app/src/main/java/com/sismics/docs/MainApplication.java
index 9e354e37..88924c12 100644
--- a/docs-android/app/src/main/java/com/sismics/docs/MainApplication.java
+++ b/docs-android/app/src/main/java/com/sismics/docs/MainApplication.java
@@ -23,7 +23,6 @@ public class MainApplication extends Application {
// TODO Fullscreen preview
// TODO Sharing
// TODO Error feedback
- // TODO Searching
// TODO Printing
super.onCreate();
diff --git a/docs-android/app/src/main/java/com/sismics/docs/activity/MainActivity.java b/docs-android/app/src/main/java/com/sismics/docs/activity/MainActivity.java
index 5a91da98..ade0539f 100644
--- a/docs-android/app/src/main/java/com/sismics/docs/activity/MainActivity.java
+++ b/docs-android/app/src/main/java/com/sismics/docs/activity/MainActivity.java
@@ -1,18 +1,28 @@
package com.sismics.docs.activity;
+import android.app.SearchManager;
+import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
+import android.provider.SearchRecentSuggestions;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBarDrawerToggle;
+import android.support.v7.widget.SearchView;
+import android.view.Menu;
+import android.view.MenuInflater;
import android.view.MenuItem;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ListView;
+import android.widget.TextView;
import com.sismics.docs.R;
+import com.sismics.docs.event.SearchEvent;
import com.sismics.docs.model.application.ApplicationContext;
+import com.sismics.docs.provider.RecentSuggestionsProvider;
+
+import org.json.JSONObject;
+
+import de.greenrobot.event.EventBus;
/**
* Main activity.
@@ -21,8 +31,8 @@ import com.sismics.docs.model.application.ApplicationContext;
*/
public class MainActivity extends ActionBarActivity {
- private ListView drawerList;
private ActionBarDrawerToggle drawerToggle;
+ private MenuItem searchItem;
@Override
protected void onCreate(final Bundle args) {
@@ -38,30 +48,27 @@ public class MainActivity extends ActionBarActivity {
// Setup the activity
setContentView(R.layout.main_activity);
- // Cache view references
+ // Enable ActionBar app icon to behave as action to toggle nav drawer
DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
- drawerList = (ListView) findViewById(R.id.drawer_list);
-
- // Drawer item click listener
- drawerList.setOnItemClickListener(new ListView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView> parent, View view, int position, long id) {
- }
- });
-
- if (drawerLayout != null) {
- // Enable ActionBar app icon to behave as action to toggle nav drawer
- if (getSupportActionBar() != null) {
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
- getSupportActionBar().setHomeButtonEnabled(true);
- }
-
- // ActionBarDrawerToggle ties together the the proper interactions
- // between the sliding drawer and the action bar app icon
- drawerToggle = new ActionBarDrawerToggle(this, drawerLayout,
- R.string.drawer_open, R.string.drawer_close);
- drawerLayout.setDrawerListener(drawerToggle);
+ if (getSupportActionBar() != null) {
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setHomeButtonEnabled(true);
}
+
+ // ActionBarDrawerToggle ties together the the proper interactions
+ // between the sliding drawer and the action bar app icon
+ drawerToggle = new ActionBarDrawerToggle(this, drawerLayout,
+ R.string.drawer_open, R.string.drawer_close);
+ drawerLayout.setDrawerListener(drawerToggle);
+
+ // Fill the drawer user info
+ JSONObject userInfo = ApplicationContext.getInstance().getUserInfo();
+ TextView usernameTextView = (TextView) findViewById(R.id.usernameTextView);
+ usernameTextView.setText(userInfo.optString("username"));
+ TextView emailTextView = (TextView) findViewById(R.id.emailTextView);
+ emailTextView.setText(userInfo.optString("email"));
+
+ handleIntent(getIntent());
}
@Override
@@ -70,7 +77,7 @@ public class MainActivity extends ActionBarActivity {
case android.R.id.home:
// The action bar home/up action should open or close the drawer.
// ActionBarDrawerToggle will take care of this.
- if (drawerToggle != null && drawerToggle.onOptionsItemSelected(item)) {
+ if (drawerToggle.onOptionsItemSelected(item)) {
return true;
}
return true;
@@ -83,24 +90,69 @@ public class MainActivity extends ActionBarActivity {
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
- if (drawerToggle != null) {
- // Sync the toggle state after onRestoreInstanceState has occurred.
- drawerToggle.syncState();
- }
+ // Sync the toggle state after onRestoreInstanceState has occurred.
+ drawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- if (drawerToggle != null) {
- // Pass any configuration change to the drawer toggle
- drawerToggle.onConfigurationChanged(newConfig);
- }
+ // Pass any configuration change to the drawer toggle
+ drawerToggle.onConfigurationChanged(newConfig);
}
+
@Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- outState.putInt("drawerItemSelected", drawerList.getCheckedItemPosition());
+ public boolean onCreateOptionsMenu(Menu menu) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.main_activity, menu);
+
+ // Get the SearchView and set the searchable configuration
+ SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
+ searchItem = menu.findItem(R.id.action_search);
+ SearchView searchView = (SearchView) searchItem.getActionView();
+ searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
+
+ searchView.setOnCloseListener(new SearchView.OnCloseListener() {
+ @Override
+ public boolean onClose() {
+ EventBus.getDefault().post(new SearchEvent(null));
+ return false;
+ }
+ });
+
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ @Override
+ protected void onNewIntent(Intent intent) {
+ setIntent(intent);
+ handleIntent(intent);
+ }
+
+ /**
+ * Handle the incoming intent.
+ *
+ * @param intent Intent
+ */
+ private void handleIntent(Intent intent) {
+ // Intent is consumed
+ setIntent(null);
+
+ if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
+ // Perform a search query
+ String query = intent.getStringExtra(SearchManager.QUERY);
+
+ // Collapse the SearchView
+ if (searchItem != null) {
+ searchItem.collapseActionView();
+ }
+
+ // Save the query
+ SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this, RecentSuggestionsProvider.AUTHORITY, RecentSuggestionsProvider.MODE);
+ suggestions.saveRecentQuery(query, null);
+
+ EventBus.getDefault().post(new SearchEvent(query));
+ }
}
}
\ No newline at end of file
diff --git a/docs-android/app/src/main/java/com/sismics/docs/adapter/DocListAdapter.java b/docs-android/app/src/main/java/com/sismics/docs/adapter/DocListAdapter.java
index cc4aa19c..9da23c57 100644
--- a/docs-android/app/src/main/java/com/sismics/docs/adapter/DocListAdapter.java
+++ b/docs-android/app/src/main/java/com/sismics/docs/adapter/DocListAdapter.java
@@ -88,14 +88,21 @@ public class DocListAdapter extends RecyclerView.Adapter previousTotal) {
@@ -80,26 +87,54 @@ public class DocListFragment extends Fragment {
}
}
if (!loading && totalItemCount - visibleItemCount <= firstVisibleItem + 3) {
- loadDocuments();
+ loadDocuments(false);
loading = true;
}
}
});
// Grab the documents
- loadDocuments();
+ loadDocuments(true);
+ EventBus.getDefault().register(this);
return view;
}
+ @Override
+ public void onDestroyView() {
+ EventBus.getDefault().unregister(this);
+ super.onDestroyView();
+ }
+
+ /**
+ * A search event has been fired.
+ *
+ * @param event Search event
+ */
+ public void onEvent(SearchEvent event) {
+ query = event.getQuery();
+ loadDocuments(true);
+ }
+
/**
* Refresh the document list.
+ *
+ * @param reset If true, reload the documents
*/
- private void loadDocuments() {
- DocumentResource.list(getActivity(), adapter.getItemCount(), new JsonHttpResponseHandler() {
+ private void loadDocuments(final boolean reset) {
+ if (reset) {
+ loading = true;
+ previousTotal = 0;
+ adapter.clearDocuments();
+ if (getView() != null) {
+ getView().findViewById(R.id.progressBar).setVisibility(View.VISIBLE);
+ }
+ }
+
+ DocumentResource.list(getActivity(), reset ? 0 : adapter.getItemCount(), query, new JsonHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
- adapter.addDocuments(response.optJSONArray("documents"), false);
+ adapter.addDocuments(response.optJSONArray("documents"));
if (getView() != null) {
getView().findViewById(R.id.progressBar).setVisibility(View.GONE);
}
diff --git a/docs-android/app/src/main/java/com/sismics/docs/provider/RecentSuggestionsProvider.java b/docs-android/app/src/main/java/com/sismics/docs/provider/RecentSuggestionsProvider.java
new file mode 100644
index 00000000..94f4839a
--- /dev/null
+++ b/docs-android/app/src/main/java/com/sismics/docs/provider/RecentSuggestionsProvider.java
@@ -0,0 +1,17 @@
+package com.sismics.docs.provider;
+
+import android.content.SearchRecentSuggestionsProvider;
+
+/**
+ * Search recent suggestions provider.
+ *
+ * @author bgamard.
+ */
+public class RecentSuggestionsProvider extends SearchRecentSuggestionsProvider {
+ public final static String AUTHORITY = "com.sismics.docs.provider.RecentSuggestionsProvider";
+ public final static int MODE = DATABASE_MODE_QUERIES;
+
+ public RecentSuggestionsProvider() {
+ setupSuggestions(AUTHORITY, MODE);
+ }
+}
diff --git a/docs-android/app/src/main/java/com/sismics/docs/resource/DocumentResource.java b/docs-android/app/src/main/java/com/sismics/docs/resource/DocumentResource.java
index a8d575db..c9121882 100644
--- a/docs-android/app/src/main/java/com/sismics/docs/resource/DocumentResource.java
+++ b/docs-android/app/src/main/java/com/sismics/docs/resource/DocumentResource.java
@@ -15,9 +15,11 @@ public class DocumentResource extends BaseResource {
* GET /document/list.
*
* @param context Context
+ * @param offset Offset
+ * @param query Search query
* @param responseHandler Callback
*/
- public static void list(Context context, int offset, JsonHttpResponseHandler responseHandler) {
+ public static void list(Context context, int offset, String query, JsonHttpResponseHandler responseHandler) {
init(context);
RequestParams params = new RequestParams();
@@ -25,6 +27,7 @@ public class DocumentResource extends BaseResource {
params.put("offset", offset);
params.put("sort_column", 3);
params.put("asc", false);
+ params.put("search", query);
client.get(getApiUrl(context) + "/document/list", params, responseHandler);
}
}
diff --git a/docs-android/app/src/main/res/drawable-xhdpi/ic_launcher.png b/docs-android/app/src/main/res/drawable-xhdpi/ic_launcher.png
index 71c6d760..1d2a2d4f 100644
Binary files a/docs-android/app/src/main/res/drawable-xhdpi/ic_launcher.png and b/docs-android/app/src/main/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/docs-android/app/src/main/res/drawable-xxhdpi/ic_launcher.png b/docs-android/app/src/main/res/drawable-xxhdpi/ic_launcher.png
index 4df18946..a4de9a1a 100644
Binary files a/docs-android/app/src/main/res/drawable-xxhdpi/ic_launcher.png and b/docs-android/app/src/main/res/drawable-xxhdpi/ic_launcher.png differ
diff --git a/docs-android/app/src/main/res/layout/main_activity.xml b/docs-android/app/src/main/res/layout/main_activity.xml
index c38cd8af..d8fc692b 100644
--- a/docs-android/app/src/main/res/layout/main_activity.xml
+++ b/docs-android/app/src/main/res/layout/main_activity.xml
@@ -18,12 +18,40 @@
android:layout_height="match_parent"
android:layout_gravity="start"
android:gravity="center"
- android:orientation="vertical">
+ android:orientation="vertical"
+ android:background="#fff"
+ android:elevation="5dp">
+
+
+
+
+
+
+
+
diff --git a/docs-android/app/src/main/res/menu/main_activity.xml b/docs-android/app/src/main/res/menu/main_activity.xml
new file mode 100644
index 00000000..a635ec73
--- /dev/null
+++ b/docs-android/app/src/main/res/menu/main_activity.xml
@@ -0,0 +1,8 @@
+
+
\ No newline at end of file
diff --git a/docs-android/app/src/main/res/values/strings.xml b/docs-android/app/src/main/res/values/strings.xml
index 8551a5d0..87ff6bd2 100644
--- a/docs-android/app/src/main/res/values/strings.xml
+++ b/docs-android/app/src/main/res/values/strings.xml
@@ -30,5 +30,6 @@
Downloading file number %1s
Download all files
Downloading document
+ Search documents
diff --git a/docs-android/app/src/main/res/xml/searchable.xml b/docs-android/app/src/main/res/xml/searchable.xml
new file mode 100644
index 00000000..4635951c
--- /dev/null
+++ b/docs-android/app/src/main/res/xml/searchable.xml
@@ -0,0 +1,7 @@
+
+
+
\ No newline at end of file