From 6aee7ea863d5c783d3111ec3341ca0b44d4db99a Mon Sep 17 00:00:00 2001 From: Ammar Githam Date: Wed, 20 Jan 2021 02:24:49 +0900 Subject: [PATCH] Allow ending a group chat --- .../directmessages/DirectItemViewHolder.java | 8 +- .../customviews/DirectItemContextMenu.java | 26 +-- .../DirectMessageSettingsFragment.java | 58 ++++++- .../DirectMessageThreadFragment.java | 149 +++--------------- .../DirectMessagesRepository.java | 5 + .../directmessages/DirectThread.java | 13 +- .../viewmodels/AppStateViewModel.java | 3 +- .../viewmodels/DirectSettingsViewModel.java | 19 ++- .../viewmodels/DirectThreadViewModel.java | 8 +- .../webservices/DirectMessagesService.java | 8 + .../fragment_direct_messages_settings.xml | 23 ++- .../fragment_direct_messages_thread.xml | 10 +- app/src/main/res/values/dimens.xml | 1 + app/src/main/res/values/strings.xml | 3 + 14 files changed, 176 insertions(+), 158 deletions(-) diff --git a/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemViewHolder.java b/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemViewHolder.java index 9ce5d14b..739a4a66 100644 --- a/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemViewHolder.java +++ b/app/src/main/java/awais/instagrabber/adapters/viewholder/directmessages/DirectItemViewHolder.java @@ -50,6 +50,7 @@ import awais.instagrabber.utils.ResponseBodyUtils; public abstract class DirectItemViewHolder extends RecyclerView.ViewHolder implements SwipeableViewHolder { private static final String TAG = DirectItemViewHolder.class.getSimpleName(); + // private static final List THREAD_CHANGING_OPTIONS = ImmutableList.of(R.id.unsend); private final LayoutDmBaseBinding binding; private final User currentUser; @@ -532,10 +533,13 @@ public abstract class DirectItemViewHolder extends RecyclerView.ViewHolder imple if (canForward()) { builder.add(new DirectItemContextMenu.MenuItem(R.id.forward, R.string.forward)); } - if (messageDirection == MessageDirection.OUTGOING) { + if (thread.getInputMode() != 1 && messageDirection == MessageDirection.OUTGOING) { builder.add(new DirectItemContextMenu.MenuItem(R.id.unsend, R.string.dms_inbox_unsend)); } - final DirectItemContextMenu menu = new DirectItemContextMenu(itemView.getContext(), allowReaction(), builder.build()); + final boolean showReactions = thread.getInputMode() != 1 && allowReaction(); + final ImmutableList menuItems = builder.build(); + if (!showReactions && menuItems.isEmpty()) return; + final DirectItemContextMenu menu = new DirectItemContextMenu(itemView.getContext(), showReactions, menuItems); menu.setOnDismissListener(() -> setSelected(false)); menu.setOnReactionClickListener(emoji -> callback.onReaction(item, emoji)); menu.setOnOptionSelectListener(itemId -> callback.onOptionSelect(item, itemId)); diff --git a/app/src/main/java/awais/instagrabber/customviews/DirectItemContextMenu.java b/app/src/main/java/awais/instagrabber/customviews/DirectItemContextMenu.java index f125f72a..f615b7fc 100644 --- a/app/src/main/java/awais/instagrabber/customviews/DirectItemContextMenu.java +++ b/app/src/main/java/awais/instagrabber/customviews/DirectItemContextMenu.java @@ -6,6 +6,7 @@ import android.animation.AnimatorSet; import android.animation.TimeInterpolator; import android.animation.ValueAnimator; import android.content.Context; +import android.content.res.Resources; import android.graphics.Point; import android.graphics.Rect; import android.util.TypedValue; @@ -60,11 +61,8 @@ public class DirectItemContextMenu extends PopupWindow { private final int addAdjust; private final boolean hasOptions; private final List options; + private final int widthWithoutReactions; - /* = ImmutableList.of( - new MenuItem(R.id.reply, R.string.reply), - new MenuItem(R.id.unsend, R.string.dms_inbox_unsend) - );*/ private AnimatorSet openCloseAnimator; private Point location; private Point point; @@ -81,13 +79,15 @@ public class DirectItemContextMenu extends PopupWindow { throw new IllegalArgumentException("showReactions is set false and options are empty"); } reactionsManager = ReactionsManager.getInstance(); - emojiSize = context.getResources().getDimensionPixelSize(R.dimen.reaction_picker_emoji_size); - emojiMargin = context.getResources().getDimensionPixelSize(R.dimen.reaction_picker_emoji_margin); + final Resources resources = context.getResources(); + emojiSize = resources.getDimensionPixelSize(R.dimen.reaction_picker_emoji_size); + emojiMargin = resources.getDimensionPixelSize(R.dimen.reaction_picker_emoji_margin); emojiMarginHalf = emojiMargin / 2; - addAdjust = context.getResources().getDimensionPixelSize(R.dimen.reaction_picker_add_padding_adjustment); - dividerHeight = context.getResources().getDimensionPixelSize(R.dimen.horizontal_divider_height); - optionHeight = context.getResources().getDimensionPixelSize(R.dimen.reaction_picker_option_height); - optionPadding = context.getResources().getDimensionPixelSize(R.dimen.dm_message_card_radius); + addAdjust = resources.getDimensionPixelSize(R.dimen.reaction_picker_add_padding_adjustment); + dividerHeight = resources.getDimensionPixelSize(R.dimen.horizontal_divider_height); + optionHeight = resources.getDimensionPixelSize(R.dimen.reaction_picker_option_height); + optionPadding = resources.getDimensionPixelSize(R.dimen.dm_message_card_radius); + widthWithoutReactions = resources.getDimensionPixelSize(R.dimen.dm_item_context_min_width); exitAnimationListener = new AnimatorListenerAdapter() { @Override public void onAnimationEnd(final Animator animation) { @@ -315,6 +315,9 @@ public class DirectItemContextMenu extends PopupWindow { final ConstraintLayout container, @Nullable final View divider) { View prevOptionView = null; + if (!showReactions) { + container.getLayoutParams().width = widthWithoutReactions; + } for (int i = 0; i < options.size(); i++) { final MenuItem menuItem = options.get(i); final AppCompatTextView textView = getTextView(); @@ -324,11 +327,12 @@ public class DirectItemContextMenu extends PopupWindow { if (i == 0) { if (divider != null) { layoutParams.topToBottom = divider.getId(); + ((ConstraintLayout.LayoutParams) divider.getLayoutParams()).bottomToTop = textView.getId(); } else { // if divider is null mean reactions were not added, so connect top to top of parent layoutParams.topToTop = ConstraintLayout.LayoutParams.PARENT_ID; + layoutParams.topMargin = emojiMargin; // material design spec (https://material.io/components/menus#specs) } - ((ConstraintLayout.LayoutParams) divider.getLayoutParams()).bottomToTop = textView.getId(); } else { layoutParams.topToBottom = prevOptionView.getId(); final ConstraintLayout.LayoutParams prevLayoutParams = (ConstraintLayout.LayoutParams) prevOptionView.getLayoutParams(); diff --git a/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageSettingsFragment.java b/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageSettingsFragment.java index e1ab8ff4..7162940a 100644 --- a/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageSettingsFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageSettingsFragment.java @@ -62,6 +62,7 @@ public class DirectMessageSettingsFragment extends Fragment implements ConfirmDi private static final String TAG = DirectMessageSettingsFragment.class.getSimpleName(); private static final int APPROVAL_REQUIRED_REQUEST_CODE = 200; private static final int LEAVE_THREAD_REQUEST_CODE = 201; + private static final int END_THREAD_REQUEST_CODE = 202; private FragmentDirectMessagesSettingsBinding binding; private DirectSettingsViewModel viewModel; @@ -147,6 +148,17 @@ public class DirectMessageSettingsFragment extends Fragment implements ConfirmDi } private void setupObservers() { + viewModel.getInputMode().observe(getViewLifecycleOwner(), inputMode -> { + if (inputMode == null || inputMode == 0) return; + if (inputMode == 1) { + binding.groupSettings.setVisibility(View.GONE); + binding.pendingMembersGroup.setVisibility(View.GONE); + binding.approvalRequired.setVisibility(View.GONE); + binding.approvalRequiredLabel.setVisibility(View.GONE); + binding.muteMessagesLabel.setVisibility(View.GONE); + binding.muteMessages.setVisibility(View.GONE); + } + }); viewModel.getUsers().observe(getViewLifecycleOwner(), users -> { if (usersAdapter == null) return; usersAdapter.submitUsers(users.first, users.second); @@ -230,6 +242,11 @@ public class DirectMessageSettingsFragment extends Fragment implements ConfirmDi private void setupSettings() { binding.groupSettings.setVisibility(viewModel.isGroup() ? View.VISIBLE : View.GONE); + binding.muteMessagesLabel.setOnClickListener(v -> binding.muteMessages.toggle()); + binding.muteMessages.setOnCheckedChangeListener((buttonView, isChecked) -> { + final LiveData> resourceLiveData = isChecked ? viewModel.mute() : viewModel.unmute(); + handleSwitchChangeResource(resourceLiveData, buttonView); + }); if (!viewModel.isGroup()) return; binding.titleEdit.addTextChangedListener(new TextWatcherAdapter() { @Override @@ -274,11 +291,6 @@ public class DirectMessageSettingsFragment extends Fragment implements ConfirmDi .setMultiple(true); navController.navigate(actionGlobalUserSearch); }); - binding.muteMessagesLabel.setOnClickListener(v -> binding.muteMessages.toggle()); - binding.muteMessages.setOnCheckedChangeListener((buttonView, isChecked) -> { - final LiveData> resourceLiveData = isChecked ? viewModel.mute() : viewModel.unmute(); - handleSwitchChangeResource(resourceLiveData, buttonView); - }); binding.muteMentionsLabel.setOnClickListener(v -> binding.muteMentions.toggle()); binding.muteMentions.setOnCheckedChangeListener((buttonView, isChecked) -> { final LiveData> resourceLiveData = isChecked ? viewModel.muteMentions() : viewModel.unmuteMentions(); @@ -296,6 +308,22 @@ public class DirectMessageSettingsFragment extends Fragment implements ConfirmDi ); confirmDialogFragment.show(getChildFragmentManager(), "leave_thread_confirmation_dialog"); }); + if (viewModel.isViewerAdmin()) { + binding.end.setVisibility(View.VISIBLE); + binding.end.setOnClickListener(v -> { + final ConfirmDialogFragment confirmDialogFragment = ConfirmDialogFragment.newInstance( + END_THREAD_REQUEST_CODE, + R.string.dms_action_end_question, + R.string.dms_action_end_description, + R.string.yes, + R.string.no, + -1 + ); + confirmDialogFragment.show(getChildFragmentManager(), "end_thread_confirmation_dialog"); + }); + } else { + binding.end.setVisibility(View.GONE); + } } private void setApprovalRelatedUI() { @@ -476,6 +504,26 @@ public class DirectMessageSettingsFragment extends Fragment implements ConfirmDi break; } }); + return; + } + if (requestCode == END_THREAD_REQUEST_CODE) { + final LiveData> resourceLiveData = viewModel.end(); + resourceLiveData.observe(getViewLifecycleOwner(), resource -> { + if (resource == null) return; + switch (resource.status) { + case SUCCESS: + break; + case ERROR: + binding.end.setEnabled(true); + if (resource.message != null) { + Snackbar.make(binding.getRoot(), resource.message, Snackbar.LENGTH_LONG).show(); + } + break; + case LOADING: + binding.end.setEnabled(false); + break; + } + }); } } diff --git a/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageThreadFragment.java b/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageThreadFragment.java index 9f15a5db..c2d2982f 100644 --- a/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageThreadFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/directmessages/DirectMessageThreadFragment.java @@ -293,6 +293,7 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact backStackSavedStateResultLiveData.postValue(null); }; private final MutableLiveData inputLength = new MutableLiveData<>(0); + private ItemTouchHelper itemTouchHelper; @Override public void onCreate(@Nullable final Bundle savedInstanceState) { @@ -520,135 +521,29 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact viewModel.setReplyToItem(directItemOrHeader.item); } ); - final ItemTouchHelper itemTouchHelper = new ItemTouchHelper(touchHelperCallback); - itemTouchHelper.attachToRecyclerView(binding.chats); - // final MentionClickListener mentionClickListener = (view, text, isHashtag, isLocation) -> searchUsername(text); - // final DialogInterface.OnClickListener onDialogListener = (dialogInterface, which) -> { - // if (which == 0) { - // final DirectItemType itemType = directItemModel.getItemType(); - // switch (itemType) { - // case MEDIA_SHARE: - // case CLIP: - // case FELIX_SHARE: - // final String shortCode = ((DirectItemMediaModel) directItemModel.getMediaModel()).getCode(); - // new PostFetcher(shortCode, feedModel -> { - // final PostViewV2Fragment fragment = PostViewV2Fragment - // .builder(feedModel) - // .build(); - // fragment.show(getChildFragmentManager(), "post_view"); - // }).execute(); - // break; - // case LINK: - // Intent linkIntent = new Intent(Intent.ACTION_VIEW); - // linkIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP); - // linkIntent.setData(Uri.parse(((DirectItemLinkModel) directItemModel.getMediaModel()).getLinkContext().getLinkUrl())); - // startActivity(linkIntent); - // break; - // case TEXT: - // case REEL_SHARE: - // Utils.copyText(context, directItemModel.getText()); - // Toast.makeText(context, R.string.clipboard_copied, Toast.LENGTH_SHORT).show(); - // break; - // case RAVEN_MEDIA: - // case MEDIA: - // downloadItem(context); - // break; - // case STORY_SHARE: - // if (directItemModel.getMediaModel() != null) { - // // StoryModel sm = new StoryModel( - // // directItemModel.getReelShare().getReelId(), - // // directItemModel.getReelShare().getMedia().getVideoUrl(), - // // directItemModel.getReelShare().getMedia().getMediaType(), - // // directItemModel.getTimestamp(), - // // directItemModel.getReelShare().getReelOwnerName(), - // // String.valueOf(directItemModel.getReelShare().getReelOwnerId()), - // // false - // // ); - // // sm.setVideoUrl(directItemModel.getReelShare().getMedia().getVideoUrl()); - // // StoryModel[] sms = {sm}; - // // startActivity(new Intent(getContext(), StoryViewer.class) - // // .putExtra(Constants.EXTRAS_USERNAME, directItemModel.getReelShare().getReelOwnerName()) - // // .putExtra(Constants.EXTRAS_STORIES, sms) - // // ); - // } else if (directItemModel.getText() != null && directItemModel.getText().toString().contains("@")) { - // searchUsername(directItemModel.getText().toString().split("@")[1].split(" ")[0]); - // } - // break; - // case PLACEHOLDER: - // if (directItemModel.getText().toString().contains("@")) - // searchUsername(directItemModel.getText().toString().split("@")[1].split(" ")[0]); - // break; - // default: - // Log.d(TAG, "unsupported type " + itemType); - // } - // } else if (which == 1) { - // sendText(null, directItemModel.getItemId(), directItemModel.isLiked()); - // } else if (which == 2) { - // if (directItemModel == null) { - // Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show(); - // } else if (String.valueOf(directItemModel.getUserId()).equals(myId)) { - // new ThreadAction().execute("delete", directItemModel.getItemId()); - // } else { - // searchUsername(getUser(directItemModel.getUserId()).getUsername()); - // } - // } - // }; - // final View.OnClickListener onClickListener = v -> { - // Object tag = v.getTag(); - // if (tag instanceof ProfileModel) { - // searchUsername(((ProfileModel) tag).getUsername()); - // } else if (tag instanceof DirectItemModel) { - // directItemModel = (DirectItemModel) tag; - // final DirectItemType itemType = directItemModel.getItemType(); - // int firstOption = R.string.dms_inbox_raven_message_unknown; - // String[] dialogList; - // - // switch (itemType) { - // case MEDIA_SHARE: - // case CLIP: - // case FELIX_SHARE: - // firstOption = R.string.view_post; - // break; - // case LINK: - // firstOption = R.string.dms_inbox_open_link; - // break; - // case TEXT: - // case REEL_SHARE: - // firstOption = R.string.dms_inbox_copy_text; - // break; - // case RAVEN_MEDIA: - // case MEDIA: - // firstOption = R.string.dms_inbox_download; - // break; - // case STORY_SHARE: - // if (directItemModel.getMediaModel() != null) { - // firstOption = R.string.show_stories; - // } else if (directItemModel.getText() != null && directItemModel.getText().toString().contains("@")) { - // firstOption = R.string.open_profile; - // } - // break; - // case PLACEHOLDER: - // if (directItemModel.getText().toString().contains("@")) - // firstOption = R.string.open_profile; - // break; - // } - // - // dialogList = new String[]{ - // getString(firstOption), - // getString(directItemModel.isLiked() ? R.string.dms_inbox_unlike : R.string.dms_inbox_like), - // getString(String.valueOf(directItemModel.getUserId()).equals(myId) ? R.string.dms_inbox_unsend : R.string.dms_inbox_author) - // }; - // - // dialogAdapter = new ArrayAdapter<>(context, android.R.layout.simple_list_item_1, dialogList); - // - // new AlertDialog.Builder(context) - // .setAdapter(dialogAdapter, onDialogListener) - // .show(); - // } - // }; + final Integer inputMode = viewModel.getInputMode().getValue(); + if (inputMode != null && inputMode != 1) { + itemTouchHelper = new ItemTouchHelper(touchHelperCallback); + itemTouchHelper.attachToRecyclerView(binding.chats); + } } private void setObservers() { + viewModel.getInputMode().observe(getViewLifecycleOwner(), inputMode -> { + if (inputMode == null || inputMode == 0) return; + if (inputMode == 1) { + binding.emojiToggle.setVisibility(View.GONE); + binding.camera.setVisibility(View.GONE); + binding.gallery.setVisibility(View.GONE); + binding.input.setVisibility(View.GONE); + binding.inputBg.setVisibility(View.GONE); + binding.recordView.setVisibility(View.GONE); + binding.send.setVisibility(View.GONE); + if (itemTouchHelper != null) { + itemTouchHelper.attachToRecyclerView(null); + } + } + }); viewModel.getThreadTitle().observe(getViewLifecycleOwner(), this::setTitle); viewModel.getFetching().observe(getViewLifecycleOwner(), fetching -> { if (fetching) { @@ -882,6 +777,8 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact } private void setupInput() { + final Integer inputMode = viewModel.getInputMode().getValue(); + if (inputMode != null && inputMode == 1) return; final Context context = getContext(); if (context == null) return; tooltip.setText(HOLD_TO_RECORD_AUDIO_LABEL); diff --git a/app/src/main/java/awais/instagrabber/repositories/DirectMessagesRepository.java b/app/src/main/java/awais/instagrabber/repositories/DirectMessagesRepository.java index c2f50bca..21e26ae7 100644 --- a/app/src/main/java/awais/instagrabber/repositories/DirectMessagesRepository.java +++ b/app/src/main/java/awais/instagrabber/repositories/DirectMessagesRepository.java @@ -127,4 +127,9 @@ public interface DirectMessagesRepository { @POST("/api/v1/direct_v2/threads/{threadId}/leave/") Call leave(@Path("threadId") String threadId, @FieldMap final Map form); + + @FormUrlEncoded + @POST("/api/v1/direct_v2/threads/{threadId}/remove_all_users/") + Call end(@Path("threadId") String threadId, + @FieldMap final Map form); } diff --git a/app/src/main/java/awais/instagrabber/repositories/responses/directmessages/DirectThread.java b/app/src/main/java/awais/instagrabber/repositories/responses/directmessages/DirectThread.java index 33d0f109..97d5f763 100644 --- a/app/src/main/java/awais/instagrabber/repositories/responses/directmessages/DirectThread.java +++ b/app/src/main/java/awais/instagrabber/repositories/responses/directmessages/DirectThread.java @@ -42,6 +42,7 @@ public class DirectThread implements Serializable { private final DirectItem lastPermanentItem; private final DirectThreadDirectStory directStory; private boolean approvalRequiredForNewMembers; + private int inputMode; public DirectThread(final String threadId, final String threadV2Id, @@ -74,7 +75,8 @@ public class DirectThread implements Serializable { final boolean isSpam, final DirectItem lastPermanentItem, final DirectThreadDirectStory directStory, - final boolean approvalRequiredForNewMembers) { + final boolean approvalRequiredForNewMembers, + final int inputMode) { this.threadId = threadId; this.threadV2Id = threadV2Id; this.users = users; @@ -107,6 +109,7 @@ public class DirectThread implements Serializable { this.lastPermanentItem = lastPermanentItem; this.directStory = directStory; this.approvalRequiredForNewMembers = approvalRequiredForNewMembers; + this.inputMode = inputMode; } public String getThreadId() { @@ -249,6 +252,14 @@ public class DirectThread implements Serializable { this.approvalRequiredForNewMembers = approvalRequiredForNewMembers; } + public int getInputMode() { + return inputMode; + } + + public void setInputMode(final int inputMode) { + this.inputMode = inputMode; + } + @Nullable public DirectItem getFirstDirectItem() { DirectItem firstItem = null; diff --git a/app/src/main/java/awais/instagrabber/viewmodels/AppStateViewModel.java b/app/src/main/java/awais/instagrabber/viewmodels/AppStateViewModel.java index 134d8170..37158b60 100644 --- a/app/src/main/java/awais/instagrabber/viewmodels/AppStateViewModel.java +++ b/app/src/main/java/awais/instagrabber/viewmodels/AppStateViewModel.java @@ -2,7 +2,6 @@ package awais.instagrabber.viewmodels; import android.app.Application; import android.os.AsyncTask; -import android.util.Log; import androidx.annotation.NonNull; import androidx.lifecycle.AndroidViewModel; @@ -35,7 +34,7 @@ public class AppStateViewModel extends AndroidViewModel { public AppStateViewModel(@NonNull final Application application) { super(application); - Log.d(TAG, "AppStateViewModel: constructor"); + // Log.d(TAG, "AppStateViewModel: constructor"); cookie = settingsHelper.getString(Constants.COOKIE); isLoggedIn = !TextUtils.isEmpty(cookie) && CookieUtils.getUserIdFromCookie(cookie) > 0; if (!isLoggedIn) return; diff --git a/app/src/main/java/awais/instagrabber/viewmodels/DirectSettingsViewModel.java b/app/src/main/java/awais/instagrabber/viewmodels/DirectSettingsViewModel.java index 44be9a72..cdb209e7 100644 --- a/app/src/main/java/awais/instagrabber/viewmodels/DirectSettingsViewModel.java +++ b/app/src/main/java/awais/instagrabber/viewmodels/DirectSettingsViewModel.java @@ -66,6 +66,7 @@ public class DirectSettingsViewModel extends AndroidViewModel { private final MutableLiveData mentionsMuted = new MutableLiveData<>(false); private final MutableLiveData approvalRequiredToJoin = new MutableLiveData<>(false); private final MutableLiveData pendingRequests = new MutableLiveData<>(null); + private final MutableLiveData inputMode = new MutableLiveData<>(null); private final DirectMessagesService directMessagesService; private final long userId; private final Resources resources; @@ -97,6 +98,7 @@ public class DirectSettingsViewModel extends AndroidViewModel { public void setThread(@NonNull final DirectThread thread) { this.thread = thread; + inputMode.postValue(thread.getInputMode()); List users = thread.getUsers(); if (viewer != null) { final ImmutableList.Builder builder = ImmutableList.builder().add(viewer); @@ -113,11 +115,15 @@ public class DirectSettingsViewModel extends AndroidViewModel { muted.postValue(thread.isMuted()); mentionsMuted.postValue(thread.isMentionsMuted()); approvalRequiredToJoin.postValue(thread.isApprovalRequiredForNewMembers()); - if (thread.isGroup() && viewerIsAdmin) { + if (thread.getInputMode() != 1 && thread.isGroup() && viewerIsAdmin) { fetchPendingRequests(); } } + public LiveData getInputMode() { + return inputMode; + } + public boolean isGroup() { if (thread != null) { return thread.isGroup(); @@ -542,8 +548,17 @@ public class DirectSettingsViewModel extends AndroidViewModel { final MutableLiveData> data = new MutableLiveData<>(); data.postValue(Resource.loading(null)); final Call request = directMessagesService.leave(thread.getThreadId()); - handleDetailsChangeRequest(data, request, () -> { + handleDetailsChangeRequest(data, request); + return data; + } + public LiveData> end() { + final MutableLiveData> data = new MutableLiveData<>(); + data.postValue(Resource.loading(null)); + final Call request = directMessagesService.end(thread.getThreadId()); + handleDetailsChangeRequest(data, request, () -> { + thread.setInputMode(1); + inputMode.postValue(1); }); return data; } diff --git a/app/src/main/java/awais/instagrabber/viewmodels/DirectThreadViewModel.java b/app/src/main/java/awais/instagrabber/viewmodels/DirectThreadViewModel.java index 560492f1..11f71ebe 100644 --- a/app/src/main/java/awais/instagrabber/viewmodels/DirectThreadViewModel.java +++ b/app/src/main/java/awais/instagrabber/viewmodels/DirectThreadViewModel.java @@ -84,6 +84,7 @@ public class DirectThreadViewModel extends AndroidViewModel { private final MutableLiveData> leftUsers = new MutableLiveData<>(new ArrayList<>()); private final MutableLiveData replyToItem = new MutableLiveData<>(); private final MutableLiveData pendingRequestsCount = new MutableLiveData<>(null); + private final MutableLiveData inputMode = new MutableLiveData<>(0); private final DirectMessagesService service; private final ContentResolver contentResolver; @@ -335,6 +336,10 @@ public class DirectThreadViewModel extends AndroidViewModel { return pendingRequestsCount; } + public LiveData getInputMode() { + return inputMode; + } + public void fetchChats() { final Boolean isFetching = fetching.getValue(); if ((isFetching != null && isFetching) || !hasOlder) return; @@ -382,6 +387,7 @@ public class DirectThreadViewModel extends AndroidViewModel { private void setupThreadInfo(final DirectThread thread) { if (thread == null) return; + inputMode.postValue(thread.getInputMode()); final List items = thread.getItems() .stream() .filter(directItem -> directItem.getHideInThread() == 0) @@ -400,7 +406,7 @@ public class DirectThreadViewModel extends AndroidViewModel { fetching.postValue(false); final List adminUserIds = thread.getAdminUserIds(); viewerIsAdmin = adminUserIds.contains(viewerId); - if (thread.isGroup() && viewerIsAdmin) { + if (thread.getInputMode() != 1 && thread.isGroup() && viewerIsAdmin) { fetchPendingRequests(); } } diff --git a/app/src/main/java/awais/instagrabber/webservices/DirectMessagesService.java b/app/src/main/java/awais/instagrabber/webservices/DirectMessagesService.java index d0947ab8..984df066 100644 --- a/app/src/main/java/awais/instagrabber/webservices/DirectMessagesService.java +++ b/app/src/main/java/awais/instagrabber/webservices/DirectMessagesService.java @@ -401,4 +401,12 @@ public class DirectMessagesService extends BaseService { ); return repository.leave(threadId, form); } + + public Call end(@NonNull final String threadId) { + final ImmutableMap form = ImmutableMap.of( + "_csrftoken", csrfToken, + "_uuid", deviceUuid + ); + return repository.end(threadId, form); + } } diff --git a/app/src/main/res/layout/fragment_direct_messages_settings.xml b/app/src/main/res/layout/fragment_direct_messages_settings.xml index e254586d..c9fdb5d6 100644 --- a/app/src/main/res/layout/fragment_direct_messages_settings.xml +++ b/app/src/main/res/layout/fragment_direct_messages_settings.xml @@ -146,9 +146,26 @@ android:text="@string/dms_action_leave" android:textAppearance="@style/TextAppearance.MaterialComponents.Body1" android:textColor="@color/red_600" - app:layout_constraintBottom_toTopOf="@id/pending_members_header" + app:layout_constraintBottom_toTopOf="@id/end" app:layout_constraintTop_toBottomOf="@id/approval_required" /> + + + app:layout_constraintTop_toBottomOf="@id/end" /> + app:constraint_referenced_ids="title_edit_input_layout, mute_mentions_label, mute_mentions, leave, end, add_members, approval_required, approval_required_label" /> diff --git a/app/src/main/res/layout/fragment_direct_messages_thread.xml b/app/src/main/res/layout/fragment_direct_messages_thread.xml index d242a1b4..88b3aa31 100644 --- a/app/src/main/res/layout/fragment_direct_messages_thread.xml +++ b/app/src/main/res/layout/fragment_direct_messages_thread.xml @@ -27,7 +27,7 @@ app:layout_constraintEnd_toEndOf="@id/input_bg" app:layout_constraintStart_toStartOf="@id/input_bg" app:layout_constraintTop_toTopOf="@id/reply_info" - tools:visibility="visible" /> + tools:visibility="gone" /> + tools:visibility="gone" /> + tools:visibility="gone" /> + tools:visibility="gone" /> + tools:visibility="gone" /> diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index d41fb190..d2dddd99 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -43,6 +43,7 @@ 8dp 48dp 4dp + 200dp 1dp \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 80e92179..1e8edf4c 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -415,4 +415,7 @@ Added by %s Admin approval required An admin approval will be required to add new members to the group + End chat + End chat? + All members will be removed from the group. They will still be able to view the chat history.