diff --git a/Clover/app/src/main/java/org/floens/chan/core/http/DeleteHttpCall.java b/Clover/app/src/main/java/org/floens/chan/core/http/DeleteHttpCall.java
new file mode 100644
index 00000000..dd606a48
--- /dev/null
+++ b/Clover/app/src/main/java/org/floens/chan/core/http/DeleteHttpCall.java
@@ -0,0 +1,69 @@
+/*
+ * Clover - 4chan browser https://github.com/Floens/Clover/
+ * Copyright (C) 2014 Floens
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.floens.chan.core.http;
+
+import com.squareup.okhttp.FormEncodingBuilder;
+import com.squareup.okhttp.Request;
+import com.squareup.okhttp.Response;
+
+import org.floens.chan.chan.ChanUrls;
+import org.floens.chan.core.model.SavedReply;
+import org.jsoup.Jsoup;
+
+import java.io.IOException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class DeleteHttpCall extends HttpCall {
+ private static final Pattern ERROR_MESSAGE = Pattern.compile("\"errmsg\"[^>]*>(.*?)<\\/span");
+
+ public boolean deleted;
+ public String errorMessage;
+
+ private final SavedReply reply;
+ private final boolean onlyImageDelete;
+
+ public DeleteHttpCall(final SavedReply reply, boolean onlyImageDelete) {
+ this.reply = reply;
+ this.onlyImageDelete = onlyImageDelete;
+ }
+
+ @Override
+ public void setup(Request.Builder requestBuilder) {
+ FormEncodingBuilder formBuilder = new FormEncodingBuilder();
+ formBuilder.add(Integer.toString(reply.no), "delete");
+ if (onlyImageDelete) {
+ formBuilder.add("onlyimgdel", "on");
+ }
+ formBuilder.add("mode", "usrdel");
+ formBuilder.add("pwd", reply.password);
+
+ requestBuilder.url(ChanUrls.getDeleteUrl(reply.board));
+ requestBuilder.post(formBuilder.build());
+ }
+
+ @Override
+ public void process(Response response, String result) throws IOException {
+ Matcher errorMessageMatcher = ERROR_MESSAGE.matcher(result);
+ if (errorMessageMatcher.find()) {
+ errorMessage = Jsoup.parse(errorMessageMatcher.group(1)).body().ownText();
+ } else {
+ deleted = true;
+ }
+ }
+}
diff --git a/Clover/app/src/main/java/org/floens/chan/core/reply/HttpCall.java b/Clover/app/src/main/java/org/floens/chan/core/http/HttpCall.java
similarity index 92%
rename from Clover/app/src/main/java/org/floens/chan/core/reply/HttpCall.java
rename to Clover/app/src/main/java/org/floens/chan/core/http/HttpCall.java
index c3d67922..c9cc8481 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/reply/HttpCall.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/http/HttpCall.java
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-package org.floens.chan.core.reply;
+package org.floens.chan.core.http;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.Request;
@@ -41,9 +41,6 @@ public abstract class HttpCall implements Callback {
public abstract void process(Response response, String result) throws IOException;
- public void fail(Request request, IOException e) {
- }
-
@SuppressWarnings("unchecked")
public void postUI(boolean successful) {
if (successful) {
@@ -79,7 +76,12 @@ public abstract class HttpCall implements Callback {
@Override
public void onFailure(Request request, IOException e) {
- fail(request, e);
+ AndroidUtils.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ postUI(false);
+ }
+ });
}
void setCallback(ReplyManager.HttpCallback extends HttpCall> callback) {
diff --git a/Clover/app/src/main/java/org/floens/chan/core/reply/ReplyHttpCall.java b/Clover/app/src/main/java/org/floens/chan/core/http/ReplyHttpCall.java
similarity index 97%
rename from Clover/app/src/main/java/org/floens/chan/core/reply/ReplyHttpCall.java
rename to Clover/app/src/main/java/org/floens/chan/core/http/ReplyHttpCall.java
index 8fc369ee..21f7fa8f 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/reply/ReplyHttpCall.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/http/ReplyHttpCall.java
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-package org.floens.chan.core.reply;
+package org.floens.chan.core.http;
import android.text.TextUtils;
@@ -122,8 +122,4 @@ public class ReplyHttpCall extends HttpCall {
}
}
}
-
- @Override
- public void fail(Request request, IOException e) {
- }
}
diff --git a/Clover/app/src/main/java/org/floens/chan/core/reply/ReplyManager.java b/Clover/app/src/main/java/org/floens/chan/core/http/ReplyManager.java
similarity index 99%
rename from Clover/app/src/main/java/org/floens/chan/core/reply/ReplyManager.java
rename to Clover/app/src/main/java/org/floens/chan/core/http/ReplyManager.java
index 7468d996..f35f430c 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/reply/ReplyManager.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/http/ReplyManager.java
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-package org.floens.chan.core.reply;
+package org.floens.chan.core.http;
import android.content.Context;
import android.content.Intent;
diff --git a/Clover/app/src/main/java/org/floens/chan/core/presenter/ReplyPresenter.java b/Clover/app/src/main/java/org/floens/chan/core/presenter/ReplyPresenter.java
index 9756ebb6..be66535d 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/presenter/ReplyPresenter.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/presenter/ReplyPresenter.java
@@ -29,8 +29,8 @@ import org.floens.chan.core.model.Loadable;
import org.floens.chan.core.model.Post;
import org.floens.chan.core.model.Reply;
import org.floens.chan.core.model.SavedReply;
-import org.floens.chan.core.reply.ReplyHttpCall;
-import org.floens.chan.core.reply.ReplyManager;
+import org.floens.chan.core.http.ReplyHttpCall;
+import org.floens.chan.core.http.ReplyManager;
import org.floens.chan.core.settings.ChanSettings;
import org.floens.chan.database.DatabaseManager;
import org.floens.chan.ui.layout.CaptchaLayout;
diff --git a/Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java b/Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java
index 09e7f93f..e82e866f 100644
--- a/Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java
+++ b/Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java
@@ -24,6 +24,8 @@ import com.android.volley.VolleyError;
import org.floens.chan.Chan;
import org.floens.chan.R;
import org.floens.chan.chan.ChanUrls;
+import org.floens.chan.core.http.DeleteHttpCall;
+import org.floens.chan.core.http.ReplyManager;
import org.floens.chan.core.loader.ChanLoader;
import org.floens.chan.core.loader.LoaderPool;
import org.floens.chan.core.manager.WatchManager;
@@ -48,6 +50,8 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
+import static org.floens.chan.utils.AndroidUtils.getString;
+
public class ThreadPresenter implements ChanLoader.ChanLoaderCallback, PostAdapter.PostAdapterCallback, PostCell.PostCellCallback, ThreadStatusCell.Callback, ThreadListLayout.ThreadListLayoutCallback {
private static final int POST_OPTION_QUOTE = 0;
private static final int POST_OPTION_QUOTE_TEXT = 1;
@@ -63,6 +67,7 @@ public class ThreadPresenter implements ChanLoader.ChanLoaderCallback, PostAdapt
private WatchManager watchManager;
private DatabaseManager databaseManager;
+ private ReplyManager replyManager;
private ThreadPresenterCallback threadPresenterCallback;
@@ -75,6 +80,7 @@ public class ThreadPresenter implements ChanLoader.ChanLoaderCallback, PostAdapt
watchManager = Chan.getWatchManager();
databaseManager = Chan.getDatabaseManager();
+ replyManager = Chan.getReplyManager();
}
public void bindLoadable(Loadable loadable) {
@@ -330,7 +336,7 @@ public class ThreadPresenter implements ChanLoader.ChanLoaderCallback, PostAdapt
threadPresenterCallback.highlightPostId(post.id);
break;
case POST_OPTION_DELETE:
-// deletePost(post); TODO
+ requestDeletePost(post);
break;
case POST_OPTION_SAVE:
databaseManager.saveReply(new SavedReply(post.board, post.no, "foo"));
@@ -413,6 +419,40 @@ public class ThreadPresenter implements ChanLoader.ChanLoaderCallback, PostAdapt
}
}
+ public void deletePostConfirmed(Post post, boolean onlyImageDelete) {
+ threadPresenterCallback.showDeleting();
+
+ SavedReply reply = databaseManager.getSavedReply(post.board, post.no);
+ if (reply != null) {
+ replyManager.makeHttpCall(new DeleteHttpCall(reply, onlyImageDelete), new ReplyManager.HttpCallback() {
+ @Override
+ public void onHttpSuccess(DeleteHttpCall httpPost) {
+ String message;
+ if (httpPost.deleted) {
+ message = getString(R.string.delete_success);
+ } else if (!TextUtils.isEmpty(httpPost.errorMessage)) {
+ message = httpPost.errorMessage;
+ } else {
+ message = getString(R.string.delete_error);
+ }
+ threadPresenterCallback.hideDeleting(message);
+ }
+
+ @Override
+ public void onHttpFail(DeleteHttpCall httpPost) {
+ threadPresenterCallback.hideDeleting(getString(R.string.delete_error));
+ }
+ });
+ }
+ }
+
+ private void requestDeletePost(Post post) {
+ SavedReply reply = databaseManager.getSavedReply(post.board, post.no);
+ if (reply != null) {
+ threadPresenterCallback.confirmPostDelete(post);
+ }
+ }
+
private void showPostInfo(Post post) {
String text = "";
@@ -512,5 +552,11 @@ public class ThreadPresenter implements ChanLoader.ChanLoaderCallback, PostAdapt
void filterList(String query, List filter, boolean clearFilter, boolean setEmptyText, boolean hideKeyboard);
void quote(Post post, boolean withText);
+
+ void confirmPostDelete(Post post);
+
+ void showDeleting();
+
+ void hideDeleting(String message);
}
}
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/activity/ImagePickActivity.java b/Clover/app/src/main/java/org/floens/chan/ui/activity/ImagePickActivity.java
index 055eaf1a..bdabaabe 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/activity/ImagePickActivity.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/activity/ImagePickActivity.java
@@ -26,7 +26,7 @@ import android.os.ParcelFileDescriptor;
import android.provider.OpenableColumns;
import org.floens.chan.Chan;
-import org.floens.chan.core.reply.ReplyManager;
+import org.floens.chan.core.http.ReplyManager;
import org.floens.chan.utils.IOUtils;
import org.floens.chan.utils.Logger;
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/PassSettingsController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/PassSettingsController.java
index 6ffcec71..f2256a8f 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/controller/PassSettingsController.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/PassSettingsController.java
@@ -32,7 +32,7 @@ import android.widget.TextView;
import org.floens.chan.Chan;
import org.floens.chan.R;
import org.floens.chan.controller.Controller;
-import org.floens.chan.core.reply.ReplyManager;
+import org.floens.chan.core.http.ReplyManager;
import org.floens.chan.core.settings.ChanSettings;
import org.floens.chan.ui.view.CrossfadeView;
import org.floens.chan.utils.AndroidUtils;
diff --git a/Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadLayout.java b/Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadLayout.java
index 4ebd5dde..7f760a8f 100644
--- a/Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadLayout.java
+++ b/Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadLayout.java
@@ -17,8 +17,10 @@
*/
package org.floens.chan.ui.layout;
+import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
+import android.app.ProgressDialog;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
@@ -27,6 +29,7 @@ import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
+import android.widget.CheckBox;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
@@ -54,6 +57,8 @@ import java.util.List;
import javax.net.ssl.SSLException;
+import static org.floens.chan.utils.AndroidUtils.getString;
+
/**
* Wrapper around ThreadListLayout, so that it cleanly manages between loadbar and listview.
*/
@@ -74,6 +79,7 @@ public class ThreadLayout extends LoadView implements ThreadPresenter.ThreadPres
private Button errorRetryButton;
private PostPopupHelper postPopupHelper;
private Visible visible;
+ private ProgressDialog deletingDialog;
public ThreadLayout(Context context) {
super(context);
@@ -270,6 +276,44 @@ public class ThreadLayout extends LoadView implements ThreadPresenter.ThreadPres
threadListLayout.getReplyPresenter().quote(post, withText);
}
+ @Override
+ public void confirmPostDelete(final Post post) {
+ @SuppressLint("InflateParams")
+ final View view = LayoutInflater.from(getContext()).inflate(R.layout.dialog_post_delete, null);
+ new AlertDialog.Builder(getContext())
+ .setTitle(R.string.delete_confirm)
+ .setView(view)
+ .setNegativeButton(R.string.cancel, null)
+ .setPositiveButton(R.string.delete, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ CheckBox checkBox = (CheckBox) view.findViewById(R.id.image_only);
+ presenter.deletePostConfirmed(post, checkBox.isChecked());
+ }
+ })
+ .show();
+ }
+
+ @Override
+ public void showDeleting() {
+ if (deletingDialog == null) {
+ deletingDialog = ProgressDialog.show(getContext(), null, getString(R.string.delete_wait));
+ }
+ }
+
+ @Override
+ public void hideDeleting(String message) {
+ if (deletingDialog != null) {
+ deletingDialog.dismiss();
+ deletingDialog = null;
+
+ new AlertDialog.Builder(getContext())
+ .setMessage(message)
+ .setPositiveButton(R.string.ok, null)
+ .show();
+ }
+ }
+
public ThumbnailView getThumbnail(PostImage postImage) {
if (postPopupHelper.isOpen()) {
return postPopupHelper.getThumbnail(postImage);
diff --git a/Clover/app/src/main/res/layout/dialog_post_delete.xml b/Clover/app/src/main/res/layout/dialog_post_delete.xml
new file mode 100644
index 00000000..0ef6ecbd
--- /dev/null
+++ b/Clover/app/src/main/res/layout/dialog_post_delete.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
diff --git a/Clover/app/src/main/res/values/strings.xml b/Clover/app/src/main/res/values/strings.xml
index c71c87a9..3445e491 100644
--- a/Clover/app/src/main/res/values/strings.xml
+++ b/Clover/app/src/main/res/values/strings.xml
@@ -24,6 +24,7 @@ along with this program. If not, see .
Back
OK
Exit
+ Delete
- %d minute
@@ -112,6 +113,7 @@ along with this program. If not, see .
Share
Copy text
Report
+ Delete
Name
Options
@@ -128,11 +130,11 @@ along with this program. If not, see .
Error posting
Post successful
- Delete
Delete your post?
Deleting post…
Post deleted
Only delete the image
+ Error deleting post
WebM video error
The WebM video failed to play. This might be a problem with the hardware of your phone.\n\nYou can install an external media player that has a software decoder and enable \"Open videos external\" in the settings so that the video opens externally in a software decoding app.