diff --git a/Clover/app/src/main/java/org/floens/chan/core/manager/ThreadManager.java b/Clover/app/src/main/java/org/floens/chan/core/manager/ThreadManager.java index 4c2667ba..42aeb294 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/manager/ThreadManager.java +++ b/Clover/app/src/main/java/org/floens/chan/core/manager/ThreadManager.java @@ -28,7 +28,10 @@ import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.text.TextUtils; +import android.view.Menu; +import android.view.MenuItem; import android.widget.CheckBox; +import android.widget.PopupMenu; import android.widget.Toast; import com.android.volley.VolleyError; @@ -52,7 +55,6 @@ import org.floens.chan.utils.Logger; import org.floens.chan.utils.Utils; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; /** @@ -64,7 +66,7 @@ public class ThreadManager implements Loader.LoaderListener { private static final String TAG = "ThreadManager"; private final Activity activity; - private final ThreadManager.ThreadManagerListener threadManagerListener; + private final ThreadManagerListener threadManagerListener; private final List popupQueue = new ArrayList<>(); private PostRepliesFragment currentPopupFragment; private int highlightedPost = -1; @@ -214,31 +216,31 @@ public class ThreadManager implements Loader.LoaderListener { } } - public void onPostLongClicked(final Post post) { - AlertDialog.Builder builder = new AlertDialog.Builder(activity); + public void showPostOptions(final Post post, PopupMenu popupMenu) { + Menu menu = popupMenu.getMenu(); - List options = new ArrayList<>(Arrays.asList(activity.getResources().getStringArray(R.array.post_options))); + String[] baseOptions = activity.getResources().getStringArray(R.array.post_options); + for (int i = 0; i < baseOptions.length; i++) { + menu.add(Menu.NONE, i, Menu.NONE, baseOptions[i]); + } - final boolean id = !TextUtils.isEmpty(post.id); - if (id) { - options.add(activity.getString(R.string.post_highlight_id)); + if (!TextUtils.isEmpty(post.id)) { + menu.add(Menu.NONE, 5, Menu.NONE, activity.getString(R.string.post_highlight_id)); } // Only add the delete option when the post is a saved reply - final boolean delete = ChanApplication.getDatabaseManager().isSavedReply(post.board, post.no); - if (delete) { - options.add(activity.getString(R.string.delete)); + if (ChanApplication.getDatabaseManager().isSavedReply(post.board, post.no)) { + menu.add(Menu.NONE, 6, Menu.NONE, activity.getString(R.string.delete)); } - final boolean saved = ChanPreferences.getDeveloper(); - if (saved) { - options.add("Make this a saved reply"); + if (ChanPreferences.getDeveloper()) { + menu.add(Menu.NONE, 7, Menu.NONE, "Make this a saved reply"); } - builder.setItems(options.toArray(new String[options.size()]), new DialogInterface.OnClickListener() { + popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override - public void onClick(DialogInterface dialog, int which) { - switch (which) { + public boolean onMenuItemClick(final MenuItem item) { + switch (item.getItemId()) { case 0: // Quick reply openReply(false); // Pass through @@ -254,38 +256,20 @@ public class ThreadManager implements Loader.LoaderListener { case 4: // Copy text copyToClipboard(post.comment.toString()); break; - default: - // all optional, but with this order, starting at 5: - // id - // delete - // saved - - int idIndex = 5; - int deleteIndex = 5; - int savedIndex = 5; - - if (id) { - deleteIndex++; - savedIndex++; - } - - if (delete) { - savedIndex++; - } - - if (id && which == idIndex) { - highlightedId = post.id; - threadManagerListener.onRefreshView(); - } else if (delete && which == deleteIndex) { - deletePost(post); - } else if (saved && which == savedIndex) { - ChanApplication.getDatabaseManager().saveReply(new SavedReply(post.board, post.no, "foo")); - } + case 5: // Id + highlightedId = post.id; + threadManagerListener.onRefreshView(); + break; + case 6: // Delete + deletePost(post); + break; + case 7: // Save reply + ChanApplication.getDatabaseManager().saveReply(new SavedReply(post.board, post.no, "foo")); + break; } + return false; } }); - - builder.create().show(); } public void openReply(boolean startInActivity) { @@ -326,6 +310,7 @@ public class ThreadManager implements Loader.LoaderListener { ClipboardManager clipboard = (ClipboardManager) activity.getSystemService(Context.CLIPBOARD_SERVICE); ClipData clip = ClipData.newPlainText("Post text", comment); clipboard.setPrimaryClip(clip); + Toast.makeText(activity, R.string.post_text_copied_to_clipboard, Toast.LENGTH_SHORT).show(); } private void showPostInfo(Post post) { @@ -369,9 +354,7 @@ public class ThreadManager implements Loader.LoaderListener { } /** - * When the user clicks a post: a. when there's one linkable, open the - * linkable. b. when there's more than one linkable, show the user multiple - * options to select from. + * Show a list of things that can be clicked in a list to the user. * * @param post The post that was clicked. */ @@ -380,24 +363,20 @@ public class ThreadManager implements Loader.LoaderListener { final ArrayList linkables = post.linkables; if (linkables.size() > 0) { - if (linkables.size() == 1) { - handleLinkableSelected(linkables.get(0)); - } else { - String[] keys = new String[linkables.size()]; - for (int i = 0; i < linkables.size(); i++) { - keys[i] = linkables.get(i).key; - } + String[] keys = new String[linkables.size()]; + for (int i = 0; i < linkables.size(); i++) { + keys[i] = linkables.get(i).key; + } - builder.setItems(keys, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - handleLinkableSelected(linkables.get(which)); - } - }); + builder.setItems(keys, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + handleLinkableSelected(linkables.get(which)); + } + }); - AlertDialog dialog = builder.create(); - dialog.show(); - } + AlertDialog dialog = builder.create(); + dialog.show(); } } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/view/PostView.java b/Clover/app/src/main/java/org/floens/chan/ui/view/PostView.java index 9cacec3a..a3839809 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/view/PostView.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/view/PostView.java @@ -38,6 +38,8 @@ import android.view.MotionEvent; import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.PopupMenu; +import android.widget.RelativeLayout; import android.widget.TextView; import com.android.volley.toolbox.NetworkImageView; @@ -49,10 +51,11 @@ import org.floens.chan.core.manager.ThreadManager; import org.floens.chan.core.model.Post; import org.floens.chan.core.model.PostLinkable; import org.floens.chan.utils.IconCache; +import org.floens.chan.utils.ThemeHelper; import org.floens.chan.utils.Time; import org.floens.chan.utils.Utils; -public class PostView extends LinearLayout implements View.OnClickListener, View.OnLongClickListener { +public class PostView extends LinearLayout implements View.OnClickListener { private final static LinearLayout.LayoutParams matchParams = new LinearLayout.LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); private final static LinearLayout.LayoutParams wrapParams = new LinearLayout.LayoutParams( @@ -78,6 +81,7 @@ public class PostView extends LinearLayout implements View.OnClickListener, View private ImageView stickyView; private ImageView closedView; private NetworkImageView countryView; + private ImageView optionsView; private View lastSeen; private int thumbnailBackground; @@ -181,7 +185,6 @@ public class PostView extends LinearLayout implements View.OnClickListener, View } commentView.setOnClickListener(this); - commentView.setOnLongClickListener(this); if (manager.getLoadable().isThreadMode()) { post.setLinkableListener(this); @@ -345,9 +348,12 @@ public class PostView extends LinearLayout implements View.OnClickListener, View int iconHeight = resources.getDimensionPixelSize(R.dimen.post_icon_height); int imageSize = resources.getDimensionPixelSize(R.dimen.thumbnail_size); + RelativeLayout wrapper = new RelativeLayout(context); + wrapper.setLayoutParams(matchParams); + full = new LinearLayout(context); - full.setLayoutParams(matchParams); full.setOrientation(HORIZONTAL); + wrapper.addView(full, matchParams); // Create thumbnail imageView = new CustomNetworkImageView(context); @@ -375,6 +381,8 @@ public class PostView extends LinearLayout implements View.OnClickListener, View LinearLayout header = new LinearLayout(context); header.setOrientation(HORIZONTAL); + // 25 padding to give optionsView some space + header.setPadding(0, 0, Utils.dp(25), 0); titleView = new TextView(context); titleView.setTextSize(14); @@ -424,10 +432,36 @@ public class PostView extends LinearLayout implements View.OnClickListener, View full.addView(right, matchWrapParams); - addView(full, matchParams); + optionsView = new ImageView(context); + optionsView.setImageResource(R.drawable.ic_overflow); + Utils.setPressedDrawable(optionsView); + optionsView.setPadding(Utils.dp(15), Utils.dp(5), Utils.dp(5), Utils.dp(15)); + optionsView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(final View v) { + PopupMenu popupMenu = new PopupMenu(context, v); + manager.showPostOptions(post, popupMenu); + popupMenu.show(); + if (ThemeHelper.getInstance().getTheme().isLightTheme) { + optionsView.setImageResource(R.drawable.ic_overflow_black); + popupMenu.setOnDismissListener(new PopupMenu.OnDismissListener() { + @Override + public void onDismiss(final PopupMenu menu) { + optionsView.setImageResource(R.drawable.ic_overflow); + } + }); + } + } + }); + wrapper.addView(optionsView, wrapParams); + RelativeLayout.LayoutParams optionsParams = (RelativeLayout.LayoutParams) optionsView.getLayoutParams(); + optionsParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); + optionsParams.addRule(RelativeLayout.ALIGN_PARENT_TOP); + optionsView.setLayoutParams(optionsParams); + + addView(wrapper, matchParams); - full.setOnClickListener(this); - full.setOnLongClickListener(this); + wrapper.setOnClickListener(this); } public void setOnClickListeners(View.OnClickListener listener) { @@ -444,13 +478,6 @@ public class PostView extends LinearLayout implements View.OnClickListener, View manager.onPostClicked(post); } - @Override - public boolean onLongClick(View v) { - manager.onPostLongClicked(post); - - return true; - } - private class PostViewMovementMethod extends LinkMovementMethod { @Override public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) { diff --git a/Clover/app/src/main/res/drawable-hdpi/ic_overflow.png b/Clover/app/src/main/res/drawable-hdpi/ic_overflow.png new file mode 100644 index 00000000..175e73f2 Binary files /dev/null and b/Clover/app/src/main/res/drawable-hdpi/ic_overflow.png differ diff --git a/Clover/app/src/main/res/drawable-hdpi/ic_overflow_black.png b/Clover/app/src/main/res/drawable-hdpi/ic_overflow_black.png new file mode 100644 index 00000000..b7f19c72 Binary files /dev/null and b/Clover/app/src/main/res/drawable-hdpi/ic_overflow_black.png differ diff --git a/Clover/app/src/main/res/drawable-mdpi/ic_overflow.png b/Clover/app/src/main/res/drawable-mdpi/ic_overflow.png new file mode 100644 index 00000000..7499b737 Binary files /dev/null and b/Clover/app/src/main/res/drawable-mdpi/ic_overflow.png differ diff --git a/Clover/app/src/main/res/drawable-mdpi/ic_overflow_black.png b/Clover/app/src/main/res/drawable-mdpi/ic_overflow_black.png new file mode 100644 index 00000000..9d573fa0 Binary files /dev/null and b/Clover/app/src/main/res/drawable-mdpi/ic_overflow_black.png differ diff --git a/Clover/app/src/main/res/drawable-xhdpi/ic_overflow.png b/Clover/app/src/main/res/drawable-xhdpi/ic_overflow.png new file mode 100644 index 00000000..e45da5dc Binary files /dev/null and b/Clover/app/src/main/res/drawable-xhdpi/ic_overflow.png differ diff --git a/Clover/app/src/main/res/drawable-xhdpi/ic_overflow_black.png b/Clover/app/src/main/res/drawable-xhdpi/ic_overflow_black.png new file mode 100644 index 00000000..77e5c3d1 Binary files /dev/null and b/Clover/app/src/main/res/drawable-xhdpi/ic_overflow_black.png differ diff --git a/Clover/app/src/main/res/drawable-xxhdpi/ic_overflow.png b/Clover/app/src/main/res/drawable-xxhdpi/ic_overflow.png new file mode 100644 index 00000000..17dc0f29 Binary files /dev/null and b/Clover/app/src/main/res/drawable-xxhdpi/ic_overflow.png differ diff --git a/Clover/app/src/main/res/drawable-xxhdpi/ic_overflow_black.png b/Clover/app/src/main/res/drawable-xxhdpi/ic_overflow_black.png new file mode 100644 index 00000000..61f33d21 Binary files /dev/null and b/Clover/app/src/main/res/drawable-xxhdpi/ic_overflow_black.png differ diff --git a/Clover/app/src/main/res/values/strings.xml b/Clover/app/src/main/res/values/strings.xml index 11797e6f..36b0076f 100644 --- a/Clover/app/src/main/res/values/strings.xml +++ b/Clover/app/src/main/res/values/strings.xml @@ -87,6 +87,7 @@ along with this program. If not, see . Copy text Highlight ID + Text copied to clipboard Reply to Make thread in