From 092909c7aa3f40ffc8ab9ad59f4fcc43f188b0cb Mon Sep 17 00:00:00 2001 From: Floens Date: Wed, 20 May 2015 00:55:03 +0200 Subject: [PATCH] Add deleting of posts --- .../floens/chan/core/http/DeleteHttpCall.java | 69 +++++++++++++++++++ .../chan/core/{reply => http}/HttpCall.java | 12 ++-- .../core/{reply => http}/ReplyHttpCall.java | 6 +- .../core/{reply => http}/ReplyManager.java | 2 +- .../chan/core/presenter/ReplyPresenter.java | 4 +- .../chan/core/presenter/ThreadPresenter.java | 48 ++++++++++++- .../chan/ui/activity/ImagePickActivity.java | 2 +- .../ui/controller/PassSettingsController.java | 2 +- .../floens/chan/ui/layout/ThreadLayout.java | 44 ++++++++++++ .../main/res/layout/dialog_post_delete.xml | 30 ++++++++ Clover/app/src/main/res/values/strings.xml | 4 +- 11 files changed, 206 insertions(+), 17 deletions(-) create mode 100644 Clover/app/src/main/java/org/floens/chan/core/http/DeleteHttpCall.java rename Clover/app/src/main/java/org/floens/chan/core/{reply => http}/HttpCall.java (92%) rename Clover/app/src/main/java/org/floens/chan/core/{reply => http}/ReplyHttpCall.java (97%) rename Clover/app/src/main/java/org/floens/chan/core/{reply => http}/ReplyManager.java (99%) create mode 100644 Clover/app/src/main/res/layout/dialog_post_delete.xml 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 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.