diff --git a/jni/dc_wrapper.c b/jni/dc_wrapper.c index a358e8ddd..7e2dfc89c 100644 --- a/jni/dc_wrapper.c +++ b/jni/dc_wrapper.c @@ -691,6 +691,13 @@ JNIEXPORT void Java_com_b44t_messenger_DcContext_forwardMsgs(JNIEnv *env, jobjec free(msg_ids_ptr); } +JNIEXPORT void Java_com_b44t_messenger_DcContext_saveMsgs(JNIEnv *env, jobject obj, jintArray msg_ids) +{ + int msg_ids_cnt = 0; + uint32_t* msg_ids_ptr = jintArray2uint32Pointer(env, msg_ids, &msg_ids_cnt); + dc_save_msgs(get_dc_context(env, obj), msg_ids_ptr, msg_ids_cnt); + free(msg_ids_ptr); +} JNIEXPORT jboolean Java_com_b44t_messenger_DcContext_resendMsgs(JNIEnv *env, jobject obj, jintArray msg_ids) { diff --git a/src/main/java/com/b44t/messenger/DcContext.java b/src/main/java/com/b44t/messenger/DcContext.java index 0f9ae87c7..9cb5de759 100644 --- a/src/main/java/com/b44t/messenger/DcContext.java +++ b/src/main/java/com/b44t/messenger/DcContext.java @@ -193,6 +193,7 @@ public class DcContext { public native int estimateDeletionCount(boolean from_server, long seconds); public native void deleteMsgs (int msg_ids[]); public native void forwardMsgs (int msg_ids[], int chat_id); + public native void saveMsgs (int msg_ids[]); public native boolean resendMsgs (int msg_ids[]); public native int sendMsg (int chat_id, DcMsg msg); public native int sendTextMsg (int chat_id, String text); diff --git a/src/main/java/com/b44t/messenger/DcMsg.java b/src/main/java/com/b44t/messenger/DcMsg.java index 46a7f8641..11c3c731f 100644 --- a/src/main/java/com/b44t/messenger/DcMsg.java +++ b/src/main/java/com/b44t/messenger/DcMsg.java @@ -189,6 +189,7 @@ public class DcMsg { public native int getSavedMsgId (); public boolean canSave() { + // saving info-messages out of context results in confusion, see https://github.com/deltachat/deltachat-ios/issues/2567 return !isInfo(); } diff --git a/src/main/java/org/thoughtcrime/securesms/ConversationFragment.java b/src/main/java/org/thoughtcrime/securesms/ConversationFragment.java index 72bb7d713..854909130 100644 --- a/src/main/java/org/thoughtcrime/securesms/ConversationFragment.java +++ b/src/main/java/org/thoughtcrime/securesms/ConversationFragment.java @@ -326,6 +326,7 @@ public class ConversationFragment extends MessageSelectorFragment menu.findItem(R.id.menu_context_reply).setVisible(false); menu.findItem(R.id.menu_context_reply_privately).setVisible(false); menu.findItem(R.id.menu_add_to_home_screen).setVisible(false); + menu.findItem(R.id.toggle_save).setVisible(false); } else { DcMsg messageRecord = messageRecords.iterator().next(); DcChat chat = getListAdapter().getChat(); @@ -336,6 +337,10 @@ public class ConversationFragment extends MessageSelectorFragment boolean showReplyPrivately = chat.isMultiUser() && !messageRecord.isOutgoing() && canReply; menu.findItem(R.id.menu_context_reply_privately).setVisible(showReplyPrivately); menu.findItem(R.id.menu_add_to_home_screen).setVisible(messageRecord.getType() == DcMsg.DC_MSG_WEBXDC); + + boolean showSavedIcon = messageRecord.isSaved() || chat.isSelfTalk(); + menu.findItem(R.id.toggle_save).setVisible(messageRecord.canSave()); + menu.findItem(R.id.toggle_save).setIcon(showSavedIcon ? R.drawable.baseline_star_24 : R.drawable.baseline_star_outline_24); } // if one of the selected items cannot be saved, disable saving. @@ -478,6 +483,21 @@ public class ConversationFragment extends MessageSelectorFragment } } + private void handleToggleSave(final Set messageRecords) { + DcMsg msg = getSelectedMessageRecord(messageRecords); + if (getListAdapter().getChat().isSelfTalk()) { + if (msg.getOriginalMsgId() != 0) { + dcContext.deleteMsgs(new int[]{msg.getId()}); + } else { + handleDeleteMessages((int) chatId, messageRecords); + } + } else if (msg.getSavedMsgId() != 0) { + dcContext.deleteMsgs(new int[]{msg.getSavedMsgId()}); + } else { + dcContext.saveMsgs(new int[]{msg.getId()}); + } + } + private void reloadList() { reloadList(false); } @@ -953,6 +973,10 @@ public class ConversationFragment extends MessageSelectorFragment case R.id.menu_context_reply_privately: handleReplyMessagePrivately(getSelectedMessageRecord(getListAdapter().getSelectedItems())); return true; + case R.id.toggle_save: + handleToggleSave(getListAdapter().getSelectedItems()); + actionMode.finish(); + return true; case R.id.menu_resend: handleResendMessage(getListAdapter().getSelectedItems()); return true; diff --git a/src/main/java/org/thoughtcrime/securesms/util/views/ConversationAdaptiveActionsToolbar.java b/src/main/java/org/thoughtcrime/securesms/util/views/ConversationAdaptiveActionsToolbar.java index f61d39bf3..6bed8a248 100644 --- a/src/main/java/org/thoughtcrime/securesms/util/views/ConversationAdaptiveActionsToolbar.java +++ b/src/main/java/org/thoughtcrime/securesms/util/views/ConversationAdaptiveActionsToolbar.java @@ -27,6 +27,7 @@ public class ConversationAdaptiveActionsToolbar extends Toolbar { private static final int ID_NEVER_SHOW_AS_ACTION_2 = R.id.menu_add_to_home_screen; private static final int ID_NEVER_SHOW_AS_ACTION_3 = R.id.menu_context_save_attachment; private static final int ID_NEVER_SHOW_AS_ACTION_4 = R.id.menu_resend; + private static final int ID_NEVER_SHOW_AS_ACTION_5 = R.id.menu_context_details; private static final int ID_ALWAYS_SHOW_AS_ACTION = R.id.menu_context_forward; private final int maxShown; @@ -83,7 +84,8 @@ public class ConversationAdaptiveActionsToolbar extends Toolbar { boolean neverShowAsAction = item.getItemId() == ID_NEVER_SHOW_AS_ACTION_1 || item.getItemId() == ID_NEVER_SHOW_AS_ACTION_2 || item.getItemId() == ID_NEVER_SHOW_AS_ACTION_3 - || item.getItemId() == ID_NEVER_SHOW_AS_ACTION_4; + || item.getItemId() == ID_NEVER_SHOW_AS_ACTION_4 + || item.getItemId() == ID_NEVER_SHOW_AS_ACTION_5; boolean alwaysShowAsAction = item.getItemId() == ID_ALWAYS_SHOW_AS_ACTION; if (alwaysShowAsAction) continue; diff --git a/src/main/res/drawable/baseline_star_24.xml b/src/main/res/drawable/baseline_star_24.xml new file mode 100644 index 000000000..90fac96dc --- /dev/null +++ b/src/main/res/drawable/baseline_star_24.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/res/drawable/baseline_star_outline_24.xml b/src/main/res/drawable/baseline_star_outline_24.xml new file mode 100644 index 000000000..c6f3cc3d4 --- /dev/null +++ b/src/main/res/drawable/baseline_star_outline_24.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/res/menu/conversation_context.xml b/src/main/res/menu/conversation_context.xml index 7be2b04a7..0dca33e34 100644 --- a/src/main/res/menu/conversation_context.xml +++ b/src/main/res/menu/conversation_context.xml @@ -5,10 +5,15 @@ android:icon="?menu_reply_icon" app:showAsAction="always" /> - + + + app:showAsAction="never" />