Add deleting of posts

filtering
Floens 10 years ago
parent 07eeabd482
commit 092909c7aa
  1. 69
      Clover/app/src/main/java/org/floens/chan/core/http/DeleteHttpCall.java
  2. 12
      Clover/app/src/main/java/org/floens/chan/core/http/HttpCall.java
  3. 6
      Clover/app/src/main/java/org/floens/chan/core/http/ReplyHttpCall.java
  4. 2
      Clover/app/src/main/java/org/floens/chan/core/http/ReplyManager.java
  5. 4
      Clover/app/src/main/java/org/floens/chan/core/presenter/ReplyPresenter.java
  6. 48
      Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java
  7. 2
      Clover/app/src/main/java/org/floens/chan/ui/activity/ImagePickActivity.java
  8. 2
      Clover/app/src/main/java/org/floens/chan/ui/controller/PassSettingsController.java
  9. 44
      Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadLayout.java
  10. 30
      Clover/app/src/main/res/layout/dialog_post_delete.xml
  11. 4
      Clover/app/src/main/res/values/strings.xml

@ -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 <http://www.gnu.org/licenses/>.
*/
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;
}
}
}

@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.floens.chan.core.reply; package org.floens.chan.core.http;
import com.squareup.okhttp.Callback; import com.squareup.okhttp.Callback;
import com.squareup.okhttp.Request; 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 abstract void process(Response response, String result) throws IOException;
public void fail(Request request, IOException e) {
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void postUI(boolean successful) { public void postUI(boolean successful) {
if (successful) { if (successful) {
@ -79,7 +76,12 @@ public abstract class HttpCall implements Callback {
@Override @Override
public void onFailure(Request request, IOException e) { 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) { void setCallback(ReplyManager.HttpCallback<? extends HttpCall> callback) {

@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.floens.chan.core.reply; package org.floens.chan.core.http;
import android.text.TextUtils; import android.text.TextUtils;
@ -122,8 +122,4 @@ public class ReplyHttpCall extends HttpCall {
} }
} }
} }
@Override
public void fail(Request request, IOException e) {
}
} }

@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.floens.chan.core.reply; package org.floens.chan.core.http;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;

@ -29,8 +29,8 @@ import org.floens.chan.core.model.Loadable;
import org.floens.chan.core.model.Post; import org.floens.chan.core.model.Post;
import org.floens.chan.core.model.Reply; import org.floens.chan.core.model.Reply;
import org.floens.chan.core.model.SavedReply; import org.floens.chan.core.model.SavedReply;
import org.floens.chan.core.reply.ReplyHttpCall; import org.floens.chan.core.http.ReplyHttpCall;
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.core.settings.ChanSettings;
import org.floens.chan.database.DatabaseManager; import org.floens.chan.database.DatabaseManager;
import org.floens.chan.ui.layout.CaptchaLayout; import org.floens.chan.ui.layout.CaptchaLayout;

@ -24,6 +24,8 @@ import com.android.volley.VolleyError;
import org.floens.chan.Chan; import org.floens.chan.Chan;
import org.floens.chan.R; import org.floens.chan.R;
import org.floens.chan.chan.ChanUrls; 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.ChanLoader;
import org.floens.chan.core.loader.LoaderPool; import org.floens.chan.core.loader.LoaderPool;
import org.floens.chan.core.manager.WatchManager; import org.floens.chan.core.manager.WatchManager;
@ -48,6 +50,8 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale; 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 { 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 = 0;
private static final int POST_OPTION_QUOTE_TEXT = 1; private static final int POST_OPTION_QUOTE_TEXT = 1;
@ -63,6 +67,7 @@ public class ThreadPresenter implements ChanLoader.ChanLoaderCallback, PostAdapt
private WatchManager watchManager; private WatchManager watchManager;
private DatabaseManager databaseManager; private DatabaseManager databaseManager;
private ReplyManager replyManager;
private ThreadPresenterCallback threadPresenterCallback; private ThreadPresenterCallback threadPresenterCallback;
@ -75,6 +80,7 @@ public class ThreadPresenter implements ChanLoader.ChanLoaderCallback, PostAdapt
watchManager = Chan.getWatchManager(); watchManager = Chan.getWatchManager();
databaseManager = Chan.getDatabaseManager(); databaseManager = Chan.getDatabaseManager();
replyManager = Chan.getReplyManager();
} }
public void bindLoadable(Loadable loadable) { public void bindLoadable(Loadable loadable) {
@ -330,7 +336,7 @@ public class ThreadPresenter implements ChanLoader.ChanLoaderCallback, PostAdapt
threadPresenterCallback.highlightPostId(post.id); threadPresenterCallback.highlightPostId(post.id);
break; break;
case POST_OPTION_DELETE: case POST_OPTION_DELETE:
// deletePost(post); TODO requestDeletePost(post);
break; break;
case POST_OPTION_SAVE: case POST_OPTION_SAVE:
databaseManager.saveReply(new SavedReply(post.board, post.no, "foo")); 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<DeleteHttpCall>() {
@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) { private void showPostInfo(Post post) {
String text = ""; String text = "";
@ -512,5 +552,11 @@ public class ThreadPresenter implements ChanLoader.ChanLoaderCallback, PostAdapt
void filterList(String query, List<Post> filter, boolean clearFilter, boolean setEmptyText, boolean hideKeyboard); void filterList(String query, List<Post> filter, boolean clearFilter, boolean setEmptyText, boolean hideKeyboard);
void quote(Post post, boolean withText); void quote(Post post, boolean withText);
void confirmPostDelete(Post post);
void showDeleting();
void hideDeleting(String message);
} }
} }

@ -26,7 +26,7 @@ import android.os.ParcelFileDescriptor;
import android.provider.OpenableColumns; import android.provider.OpenableColumns;
import org.floens.chan.Chan; 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.IOUtils;
import org.floens.chan.utils.Logger; import org.floens.chan.utils.Logger;

@ -32,7 +32,7 @@ import android.widget.TextView;
import org.floens.chan.Chan; import org.floens.chan.Chan;
import org.floens.chan.R; import org.floens.chan.R;
import org.floens.chan.controller.Controller; 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.core.settings.ChanSettings;
import org.floens.chan.ui.view.CrossfadeView; import org.floens.chan.ui.view.CrossfadeView;
import org.floens.chan.utils.AndroidUtils; import org.floens.chan.utils.AndroidUtils;

@ -17,8 +17,10 @@
*/ */
package org.floens.chan.ui.layout; package org.floens.chan.ui.layout;
import android.annotation.SuppressLint;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.ClipData; import android.content.ClipData;
import android.content.ClipboardManager; import android.content.ClipboardManager;
import android.content.Context; import android.content.Context;
@ -27,6 +29,7 @@ import android.util.AttributeSet;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.Button; import android.widget.Button;
import android.widget.CheckBox;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
@ -54,6 +57,8 @@ import java.util.List;
import javax.net.ssl.SSLException; 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. * 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 Button errorRetryButton;
private PostPopupHelper postPopupHelper; private PostPopupHelper postPopupHelper;
private Visible visible; private Visible visible;
private ProgressDialog deletingDialog;
public ThreadLayout(Context context) { public ThreadLayout(Context context) {
super(context); super(context);
@ -270,6 +276,44 @@ public class ThreadLayout extends LoadView implements ThreadPresenter.ThreadPres
threadListLayout.getReplyPresenter().quote(post, withText); 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) { public ThumbnailView getThumbnail(PostImage postImage) {
if (postPopupHelper.isOpen()) { if (postPopupHelper.isOpen()) {
return postPopupHelper.getThumbnail(postImage); return postPopupHelper.getThumbnail(postImage);

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?><!--
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 <http://www.gnu.org/licenses/>.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<CheckBox
android:id="@+id/image_only"
android:text="@string/delete_image_only"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>

@ -24,6 +24,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<string name="back">Back</string> <string name="back">Back</string>
<string name="ok">OK</string> <string name="ok">OK</string>
<string name="exit">Exit</string> <string name="exit">Exit</string>
<string name="delete">Delete</string>
<plurals name="minutes"> <plurals name="minutes">
<item quantity="one">%d minute</item> <item quantity="one">%d minute</item>
@ -112,6 +113,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<string name="post_share">Share</string> <string name="post_share">Share</string>
<string name="post_copy_text">Copy text</string> <string name="post_copy_text">Copy text</string>
<string name="post_report">Report</string> <string name="post_report">Report</string>
<string name="post_delete">Delete</string>
<string name="reply_name">Name</string> <string name="reply_name">Name</string>
<string name="reply_options">Options</string> <string name="reply_options">Options</string>
@ -128,11 +130,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<string name="reply_error">Error posting</string> <string name="reply_error">Error posting</string>
<string name="reply_success">Post successful</string> <string name="reply_success">Post successful</string>
<string name="delete">Delete</string>
<string name="delete_confirm">Delete your post?</string> <string name="delete_confirm">Delete your post?</string>
<string name="delete_wait">Deleting post&#8230;</string> <string name="delete_wait">Deleting post&#8230;</string>
<string name="delete_success">Post deleted</string> <string name="delete_success">Post deleted</string>
<string name="delete_image_only">Only delete the image</string> <string name="delete_image_only">Only delete the image</string>
<string name="delete_error">Error deleting post</string>
<string name="video_playback_warning_title">WebM video error</string> <string name="video_playback_warning_title">WebM video error</string>
<string name="video_playback_warning">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.</string> <string name="video_playback_warning">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.</string>

Loading…
Cancel
Save