From 5b4d74b7fe878e721fa3a4e5a94e1b69827b6eea Mon Sep 17 00:00:00 2001 From: Cody Henthorne Date: Sat, 6 Jun 2020 19:26:21 -0400 Subject: [PATCH] Move group resolution for conversations to background LiveData. --- .../conversation/ConversationActivity.java | 48 ++++++----- .../ConversationGroupViewModel.java | 81 +++++++++++++++++++ 2 files changed, 111 insertions(+), 18 deletions(-) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationGroupViewModel.java diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java index ab909a36da6..88107ad6948 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java @@ -126,6 +126,7 @@ import org.thoughtcrime.securesms.contactshare.ContactShareEditActivity; import org.thoughtcrime.securesms.contactshare.ContactUtil; import org.thoughtcrime.securesms.contactshare.SimpleTextWatcher; +import org.thoughtcrime.securesms.conversation.ConversationGroupViewModel.GroupActiveState; import org.thoughtcrime.securesms.conversationlist.model.MessageResult; import org.thoughtcrime.securesms.crypto.SecurityEvent; import org.thoughtcrime.securesms.database.DatabaseFactory; @@ -339,6 +340,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity private ConversationStickerViewModel stickerViewModel; private ConversationViewModel viewModel; private InviteReminderModel inviteReminderModel; + private ConversationGroupViewModel groupViewModel; private LiveRecipient recipient; private long threadId; @@ -406,6 +408,8 @@ protected void onCreate(Bundle state, boolean ready) { initializeSearchObserver(); initializeStickerObserver(); initializeViewModel(); + initializeGroupViewModel(); + initializeEnabledCheck(); initializeSecurity(recipient.get().isRegistered(), isDefaultSms).addListener(new AssertedSuccessListener() { @Override public void onSuccess(Boolean result) { @@ -485,7 +489,6 @@ protected void onResume() { dynamicLanguage.onResume(this); EventBus.getDefault().register(this); - initializeEnabledCheck(); initializeMmsEnabledCheck(); initializeIdentityRecords(); composeText.setTransport(sendButton.getSelectedTransport()); @@ -704,8 +707,12 @@ public boolean onPrepareOptionsMenu(Menu menu) { MenuInflater inflater = this.getMenuInflater(); menu.clear(); + GroupActiveState groupActiveState = groupViewModel.getGroupActiveState().getValue(); + boolean isActiveGroup = groupActiveState != null && groupActiveState.isActiveGroup(); + boolean isActiveV2Group = groupActiveState != null && groupActiveState.isActiveV2Group(); + if (isInMessageRequest()) { - if (isActiveGroup()) { + if (isActiveGroup) { inflater.inflate(R.menu.conversation_message_requests_group, menu); } @@ -741,9 +748,9 @@ public boolean onPrepareOptionsMenu(Menu menu) { } else { menu.findItem(R.id.menu_distribution_conversation).setChecked(true); } - } else if (isActiveV2Group() || isActiveGroup() && FeatureFlags.newGroupUI()) { + } else if (isActiveV2Group || isActiveGroup && FeatureFlags.newGroupUI()) { inflater.inflate(R.menu.conversation_push_group_v2_options, menu); - } else if (isActiveGroup()) { + } else if (isActiveGroup) { inflater.inflate(R.menu.conversation_push_group_options, menu); } } @@ -789,10 +796,10 @@ public boolean onPrepareOptionsMenu(Menu menu) { hideMenuItem(menu, R.id.menu_mute_notifications); } - if (isActiveV2Group()) { + if (isActiveV2Group) { hideMenuItem(menu, R.id.menu_mute_notifications); hideMenuItem(menu, R.id.menu_conversation_settings); - } else if (isActiveGroup()) { + } else if (isActiveGroup) { hideMenuItem(menu, R.id.menu_conversation_settings); } @@ -1187,7 +1194,7 @@ private void handleLeavePushGroup() { LeaveGroupDialog.handleLeavePushGroup(ConversationActivity.this, getLifecycle(), getRecipient().requireGroupId().requirePush(), - this::initializeEnabledCheck); + null); } private void handleEditPushGroupV1() { @@ -1417,10 +1424,12 @@ private ListenableFuture initializeDraft() { } private void initializeEnabledCheck() { - boolean enabled = !(isPushGroupConversation() && !isActiveGroup()); - inputPanel.setEnabled(enabled); - sendButton.setEnabled(enabled); - attachButton.setEnabled(enabled); + groupViewModel.getGroupActiveState().observe(this, state -> { + boolean enabled = state == null || !(isPushGroupConversation() && !state.isActiveGroup()); + inputPanel.setEnabled(enabled); + sendButton.setEnabled(enabled); + attachButton.setEnabled(enabled); + }); } private ListenableFuture initializeDraftFromDatabase() { @@ -1851,6 +1860,12 @@ private void initializeViewModel() { this.viewModel = ViewModelProviders.of(this, new ConversationViewModel.Factory()).get(ConversationViewModel.class); } + private void initializeGroupViewModel() { + groupViewModel = ViewModelProviders.of(this, new ConversationGroupViewModel.Factory()).get(ConversationGroupViewModel.class); + recipient.observe(this, groupViewModel::onRecipientChange); + groupViewModel.getGroupActiveState().observe(this, unused -> invalidateOptionsMenu()); + } + private void showStickerIntroductionTooltip() { TextSecurePreferences.setMediaKeyboardMode(this, MediaKeyboardMode.STICKER); inputPanel.setMediaKeyboardToggleMode(true); @@ -1948,6 +1963,10 @@ private void onRecipientChanged(@NonNull Recipient recipient) { if (searchViewItem == null || !searchViewItem.isActionViewExpanded()) { invalidateOptionsMenu(); } + + if (groupViewModel != null) { + groupViewModel.onRecipientChange(recipient); + } } @Subscribe(threadMode = ThreadMode.MAIN) @@ -2205,13 +2224,6 @@ private boolean isActiveGroup() { return record.isPresent() && record.get().isActive(); } - private boolean isActiveV2Group() { - if (!isGroupConversation()) return false; - - Optional record = DatabaseFactory.getGroupDatabase(this).getGroup(getRecipient().getId()); - return record.isPresent() && record.get().isActive() && record.get().isV2Group(); - } - @SuppressWarnings("SimplifiableIfStatement") private boolean isSelfConversation() { if (!TextSecurePreferences.isPushRegistered(this)) return false; diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationGroupViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationGroupViewModel.java new file mode 100644 index 00000000000..8f5f185aaa6 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationGroupViewModel.java @@ -0,0 +1,81 @@ +package org.thoughtcrime.securesms.conversation; + +import android.app.Application; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.Transformations; +import androidx.lifecycle.ViewModel; +import androidx.lifecycle.ViewModelProvider; + +import org.thoughtcrime.securesms.database.DatabaseFactory; +import org.thoughtcrime.securesms.database.GroupDatabase; +import org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord; +import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; +import org.thoughtcrime.securesms.recipients.Recipient; +import org.thoughtcrime.securesms.util.livedata.LiveDataUtil; + +class ConversationGroupViewModel extends ViewModel { + + private final MutableLiveData liveRecipient; + private final LiveData groupActiveState; + + private ConversationGroupViewModel() { + liveRecipient = new MutableLiveData<>(); + LiveData groupRecord = LiveDataUtil.mapAsync(liveRecipient, this::getGroupRecordForRecipient); + groupActiveState = Transformations.distinctUntilChanged(Transformations.map(groupRecord, this::mapToGroupActiveState)); + } + + void onRecipientChange(Recipient recipient) { + liveRecipient.setValue(recipient); + } + + LiveData getGroupActiveState() { + return groupActiveState; + } + + private GroupRecord getGroupRecordForRecipient(Recipient recipient) { + if (recipient != null && recipient.isGroup()) { + Application context = ApplicationDependencies.getApplication(); + GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context); + return groupDatabase.getGroup(recipient.getId()).orNull(); + } else { + return null; + } + } + + private GroupActiveState mapToGroupActiveState(@Nullable GroupRecord record) { + if (record == null) { + return null; + } + return new GroupActiveState(record.isActive(), record.isV2Group()); + } + + static final class GroupActiveState { + private final boolean isActive; + private final boolean isActiveV2; + + public GroupActiveState(boolean isActive, boolean isV2) { + this.isActive = isActive; + this.isActiveV2 = isActive && isV2; + } + + public boolean isActiveGroup() { + return isActive; + } + + public boolean isActiveV2Group() { + return isActiveV2; + } + } + + static class Factory extends ViewModelProvider.NewInstanceFactory { + @Override + public @NonNull T create(@NonNull Class modelClass) { + //noinspection ConstantConditions + return modelClass.cast(new ConversationGroupViewModel()); + } + } +}