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 340abdbf..6d636c78 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 @@ -20,7 +20,6 @@ public class MainApplication extends Application { JSONObject json = PreferenceUtil.getCachedJson(getApplicationContext(), PreferenceUtil.PREF_CACHED_USER_INFO_JSON); ApplicationContext.getInstance().setUserInfo(getApplicationContext(), json); - // TODO google docs app: right drawer with all actions, with acls, with deep metadatas // TODO Provide documents to intent action get content super.onCreate(); @@ -28,6 +27,7 @@ public class MainApplication extends Application { @Override public void onLowMemory() { + super.onLowMemory(); BitmapAjaxCallback.clearCache(); } } diff --git a/docs-android/app/src/main/java/com/sismics/docs/activity/DocumentViewActivity.java b/docs-android/app/src/main/java/com/sismics/docs/activity/DocumentViewActivity.java index 5076978c..d6bc8f12 100644 --- a/docs-android/app/src/main/java/com/sismics/docs/activity/DocumentViewActivity.java +++ b/docs-android/app/src/main/java/com/sismics/docs/activity/DocumentViewActivity.java @@ -19,10 +19,12 @@ import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.text.TextUtils; import android.text.format.DateFormat; +import android.view.ContextMenu; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; +import android.widget.AdapterView; import android.widget.Button; import android.widget.EditText; import android.widget.ImageButton; @@ -35,6 +37,8 @@ import com.sismics.docs.R; import com.sismics.docs.adapter.AclListAdapter; import com.sismics.docs.adapter.CommentListAdapter; import com.sismics.docs.adapter.FilePagerAdapter; +import com.sismics.docs.event.CommentAddEvent; +import com.sismics.docs.event.CommentDeleteEvent; import com.sismics.docs.event.DocumentDeleteEvent; import com.sismics.docs.event.DocumentEditEvent; import com.sismics.docs.event.DocumentFullscreenEvent; @@ -87,6 +91,11 @@ public class DocumentViewActivity extends AppCompatActivity { */ private FilePagerAdapter filePagerAdapter; + /** + * Comment list adapter. + */ + private CommentListAdapter commentListAdapter; + /** * Document displayed. */ @@ -245,8 +254,7 @@ public class DocumentViewActivity extends AppCompatActivity { } }); - // TODO Delete comment button - + // Button add a comment ImageButton imageButton = (ImageButton) findViewById(R.id.addCommentBtn); imageButton.setOnClickListener(new View.OnClickListener() { @Override @@ -264,10 +272,8 @@ public class DocumentViewActivity extends AppCompatActivity { commentEditText.getText().toString(), new JsonHttpResponseHandler() { public void onSuccess(int statusCode, Header[] headers, JSONObject response) { - // TODO Send a new comment event and update the adapter properly - // if there is no adapter yet (comments not loaded), do nothing + EventBus.getDefault().post(new CommentAddEvent(response)); commentEditText.setText(""); - updateComments(); } @Override @@ -556,6 +562,36 @@ public class DocumentViewActivity extends AppCompatActivity { } } + /** + * A comment add event has been fired. + * + * @param event Comment add event + */ + public void onEventMainThread(CommentAddEvent event) { + if (commentListAdapter == null) return; + TextView emptyView = (TextView) findViewById(R.id.commentEmptyView); + ListView listView = (ListView) findViewById(R.id.commentListView); + emptyView.setVisibility(View.GONE); + listView.setVisibility(View.VISIBLE); + commentListAdapter.add(event.getComment()); + } + + /** + * A comment delete event has been fired. + * + * @param event Comment add event + */ + public void onEventMainThread(CommentDeleteEvent event) { + if (commentListAdapter == null) return; + TextView emptyView = (TextView) findViewById(R.id.commentEmptyView); + ListView listView = (ListView) findViewById(R.id.commentListView); + commentListAdapter.remove(event.getCommentId()); + if (commentListAdapter.getCount() == 0) { + emptyView.setVisibility(View.VISIBLE); + listView.setVisibility(View.GONE); + } + } + @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (document == null) return; @@ -621,6 +657,51 @@ public class DocumentViewActivity extends AppCompatActivity { }); } + @Override + public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) { + switch (view.getId()) { + case R.id.commentListView: + if (commentListAdapter == null || document == null) return; + AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; + JSONObject comment = commentListAdapter.getItem(info.position); + boolean writable = document.optBoolean("writable"); + String creator = comment.optString("creator"); + String username = ApplicationContext.getInstance().getUserInfo().optString("username"); + if (writable || creator.equals(username)) { + menu.add(Menu.NONE, 0, 0, getString(R.string.comment_delete)); + } + } + } + + @Override + public boolean onContextItemSelected(MenuItem item) { + // Use real ids if more than one item someday + if (item.getItemId() == 0) { + // Delete a comment + AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo(); + if (commentListAdapter == null) return false; + JSONObject comment = commentListAdapter.getItem(info.position); + final String commentId = comment.optString("id"); + Toast.makeText(DocumentViewActivity.this, R.string.deleting_comment, Toast.LENGTH_LONG).show(); + + CommentResource.remove(DocumentViewActivity.this, commentId, new JsonHttpResponseHandler() { + @Override + public void onSuccess(int statusCode, Header[] headers, JSONObject response) { + EventBus.getDefault().post(new CommentDeleteEvent(commentId)); + } + + @Override + public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) { + Toast.makeText(DocumentViewActivity.this, R.string.error_deleting_comment, Toast.LENGTH_LONG).show(); + } + }); + + return true; + } + + return false; + } + /** * Refresh comments list. */ @@ -633,12 +714,14 @@ public class DocumentViewActivity extends AppCompatActivity { progressBar.setVisibility(View.VISIBLE); emptyView.setVisibility(View.GONE); listView.setVisibility(View.GONE); + registerForContextMenu(listView); CommentResource.list(this, document.optString("id"), new JsonHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, JSONObject response) { JSONArray comments = response.optJSONArray("comments"); - listView.setAdapter(new CommentListAdapter(comments)); + commentListAdapter = new CommentListAdapter(comments); + listView.setAdapter(commentListAdapter); listView.setVisibility(View.VISIBLE); progressBar.setVisibility(View.GONE); if (comments.length() == 0) { diff --git a/docs-android/app/src/main/java/com/sismics/docs/adapter/CommentListAdapter.java b/docs-android/app/src/main/java/com/sismics/docs/adapter/CommentListAdapter.java index 7ef0384d..3a11585c 100644 --- a/docs-android/app/src/main/java/com/sismics/docs/adapter/CommentListAdapter.java +++ b/docs-android/app/src/main/java/com/sismics/docs/adapter/CommentListAdapter.java @@ -99,4 +99,29 @@ public class CommentListAdapter extends BaseAdapter { return view; } + + /** + * Add a new comment. + * + * @param comment Comment + */ + public void add(JSONObject comment) { + commentList.add(comment); + notifyDataSetChanged(); + } + + /** + * Remove a comment. + * + * @param commentId Comment ID + */ + public void remove(String commentId) { + for (JSONObject comment : commentList) { + if (comment.optString("id").equals(commentId)) { + commentList.remove(comment); + notifyDataSetChanged(); + return; + } + } + } } diff --git a/docs-android/app/src/main/java/com/sismics/docs/event/CommentAddEvent.java b/docs-android/app/src/main/java/com/sismics/docs/event/CommentAddEvent.java new file mode 100644 index 00000000..374fda6d --- /dev/null +++ b/docs-android/app/src/main/java/com/sismics/docs/event/CommentAddEvent.java @@ -0,0 +1,33 @@ +package com.sismics.docs.event; + +import org.json.JSONObject; + +/** + * Comment add event. + * + * @author bgamard. + */ +public class CommentAddEvent { + /** + * Comment. + */ + private JSONObject comment; + + /** + * Create a comment add event. + * + * @param comment Comment + */ + public CommentAddEvent(JSONObject comment) { + this.comment = comment; + } + + /** + * Getter of comment. + * + * @return comment + */ + public JSONObject getComment() { + return comment; + } +} diff --git a/docs-android/app/src/main/java/com/sismics/docs/event/CommentDeleteEvent.java b/docs-android/app/src/main/java/com/sismics/docs/event/CommentDeleteEvent.java new file mode 100644 index 00000000..4d25863d --- /dev/null +++ b/docs-android/app/src/main/java/com/sismics/docs/event/CommentDeleteEvent.java @@ -0,0 +1,31 @@ +package com.sismics.docs.event; + +/** + * Comment delete event. + * + * @author bgamard. + */ +public class CommentDeleteEvent { + /** + * Comment ID. + */ + private String commentId; + + /** + * Create a comment add event. + * + * @param commentId Comment ID + */ + public CommentDeleteEvent(String commentId) { + this.commentId = commentId; + } + + /** + * Getter of commentId. + * + * @return commentId + */ + public String getCommentId() { + return commentId; + } +} diff --git a/docs-android/app/src/main/java/com/sismics/docs/resource/CommentResource.java b/docs-android/app/src/main/java/com/sismics/docs/resource/CommentResource.java index ca330ee1..6e545956 100644 --- a/docs-android/app/src/main/java/com/sismics/docs/resource/CommentResource.java +++ b/docs-android/app/src/main/java/com/sismics/docs/resource/CommentResource.java @@ -42,6 +42,19 @@ public class CommentResource extends BaseResource { client.put(getApiUrl(context) + "/comment", params, responseHandler); } + /** + * DELETE /comment/id. + * + * @param context Context + * @param commentId Comment ID + * @param responseHandler Callback + */ + public static void remove(Context context, String commentId, JsonHttpResponseHandler responseHandler) { + init(context); + + client.delete(getApiUrl(context) + "/comment/" + commentId, responseHandler); + } + /** * Cancel pending requests. * diff --git a/docs-android/app/src/main/res/layout/document_view_activity.xml b/docs-android/app/src/main/res/layout/document_view_activity.xml index b437c238..a0609e89 100644 --- a/docs-android/app/src/main/res/layout/document_view_activity.xml +++ b/docs-android/app/src/main/res/layout/document_view_activity.xml @@ -75,6 +75,7 @@ android:layout_height="0dp" android:choiceMode="singleChoice" android:divider="@android:color/transparent" + android:transcriptMode="normal" android:dividerHeight="0dp"/> Send Add a comment Error adding a comment - Adding a comment... + Adding a comment + Delete comment + Deleting comment + Error deleting comment