From 1d6b62d8ca6f3c3bd28175fa454d1da02b88b8d4 Mon Sep 17 00:00:00 2001 From: Alex Hart Date: Fri, 22 Jul 2022 10:47:40 -0300 Subject: [PATCH] Stop storing state in ConversationParentFragment. --- .../ConversationParentFragment.java | 84 +++++++++---------- .../conversation/ConversationViewModel.java | 8 ++ 2 files changed, 48 insertions(+), 44 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationParentFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationParentFragment.java index 8181b6a1a..f53c8036b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationParentFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationParentFragment.java @@ -453,10 +453,7 @@ public class ConversationParentFragment extends Fragment private LiveRecipient recipient; private long threadId; private int distributionType; - private boolean isSecureText; - private boolean isDefaultSms; private int reactWithAnyEmojiStartPage = -1; - private boolean isSecurityInitialized = false; private boolean isSearchRequested = false; private boolean hasProcessedShareData = false; @@ -503,7 +500,6 @@ public class ConversationParentFragment extends Fragment return; } - isDefaultSms = Util.isDefaultSmsProvider(requireContext()); voiceNoteMediaController = new VoiceNoteMediaController(requireActivity()); voiceRecorderWakeLock = new VoiceRecorderWakeLock(requireActivity()); @@ -549,12 +545,10 @@ public class ConversationParentFragment extends Fragment initializePendingRequestsBanner(); initializeGroupV1MigrationsBanners(); - Flowable observableSecurityInfo = viewModel.getConversationState() - .map(ConversationState::getSecurityInfo) - .filter(ConversationSecurityInfo::isInitialized); + Flowable observableSecurityInfo = viewModel.getConversationSecurityInfo(args.getRecipientId()); - disposables.add(observableSecurityInfo.subscribe(securityInfo -> handleSecurityChange(securityInfo.isPushAvailable(), securityInfo.isDefaultSmsApplication()))); - disposables.add(viewModel.getConversationSecurityInfo(args.getRecipientId()).firstOrError().subscribe(unused -> onInitialSecurityConfigurationLoaded())); + disposables.add(observableSecurityInfo.subscribe(this::handleSecurityChange)); + disposables.add(observableSecurityInfo.firstOrError().subscribe(unused -> onInitialSecurityConfigurationLoaded())); initializeInsightObserver(); initializeActionBar(); @@ -591,7 +585,7 @@ public class ConversationParentFragment extends Fragment Recipient recipientSnapshot = recipient.get(); titleView.setTitle(glideRequests, recipientSnapshot); - setBlockedUserState(recipientSnapshot, isSecureText, isDefaultSms); + setBlockedUserState(recipientSnapshot, viewModel.getConversationStateSnapshot().getSecurityInfo()); calculateCharactersRemaining(); if (recipientSnapshot.getGroupId().isPresent() && recipientSnapshot.getGroupId().get().isV2() && !recipientSnapshot.isBlocked()) { @@ -690,7 +684,7 @@ public class ConversationParentFragment extends Fragment setMedia(data.getData(), MediaType.AUDIO); break; case PICK_CONTACT: - if (isSecureText && !isSmsForced()) { + if (viewModel.isPushAvailable() && !isSmsForced()) { openContactShareEditor(data.getData()); } else { addAttachmentContactInfo(data.getData()); @@ -705,7 +699,7 @@ public class ConversationParentFragment extends Fragment onRecipientChanged(recipientSnapshot); titleView.setTitle(glideRequests, recipientSnapshot); NotificationChannels.updateContactChannelName(requireContext(), recipientSnapshot); - setBlockedUserState(recipientSnapshot, isSecureText, isDefaultSms); + setBlockedUserState(recipientSnapshot, viewModel.getConversationStateSnapshot().getSecurityInfo()); invalidateOptionsMenu(); break; case TAKE_PHOTO: @@ -914,7 +908,7 @@ public class ConversationParentFragment extends Fragment super.onCreateOptionsMenu(menu, inflater); } - if (isSecureText) { + if (viewModel.isPushAvailable()) { if (recipient.get().getExpiresInSeconds() > 0) { if (!isInActiveGroup) { inflater.inflate(R.menu.conversation_expiring_on, menu); @@ -929,7 +923,7 @@ public class ConversationParentFragment extends Fragment } if (isSingleConversation()) { - if (isSecureText) inflater.inflate(R.menu.conversation_callable_secure, menu); + if (viewModel.isPushAvailable()) inflater.inflate(R.menu.conversation_callable_secure, menu); else if (!recipient.get().isReleaseNotes()) inflater.inflate(R.menu.conversation_callable_insecure, menu); } else if (isGroupConversation()) { if (isActiveV2Group && Build.VERSION.SDK_INT > 19) { @@ -960,7 +954,7 @@ public class ConversationParentFragment extends Fragment hideMenuItem(menu, R.id.menu_conversation_settings); } - if (isSingleConversation() && !isSecureText && !recipient.get().isReleaseNotes()) { + if (isSingleConversation() && !viewModel.isPushAvailable() && !recipient.get().isReleaseNotes()) { inflater.inflate(R.menu.conversation_insecure, menu); } @@ -972,7 +966,7 @@ public class ConversationParentFragment extends Fragment } if (recipient != null && recipient.get().isSelf()) { - if (isSecureText) { + if (viewModel.isPushAvailable()) { hideMenuItem(menu, R.id.menu_call_secure); hideMenuItem(menu, R.id.menu_video_secure); } else { @@ -983,7 +977,7 @@ public class ConversationParentFragment extends Fragment } if (recipient != null && recipient.get().isBlocked()) { - if (isSecureText) { + if (viewModel.isPushAvailable()) { hideMenuItem(menu, R.id.menu_call_secure); hideMenuItem(menu, R.id.menu_video_secure); hideMenuItem(menu, R.id.menu_expiring_messages); @@ -1068,7 +1062,7 @@ public class ConversationParentFragment extends Fragment searchNav.setVisibility(View.GONE); inputPanel.setHideForSearch(false); viewModel.setSearchQuery(null); - setBlockedUserState(recipient.get(), isSecureText, isDefaultSms); + setBlockedUserState(recipient.get(), viewModel.getConversationStateSnapshot().getSecurityInfo()); invalidateOptionsMenu(); return true; } @@ -1306,7 +1300,7 @@ public class ConversationParentFragment extends Fragment private void handleInviteLink() { String inviteText = getString(R.string.ConversationActivity_lets_switch_to_signal, getString(R.string.install_url)); - if (isDefaultSms) { + if (viewModel.isDefaultSmsApplication()) { composeText.appendInvite(inviteText); } else { Intent intent = new Intent(Intent.ACTION_SENDTO); @@ -1496,7 +1490,7 @@ public class ConversationParentFragment extends Fragment } private void handleAddAttachment() { - if (viewModel.getConversationStateSnapshot().isMmsEnabled() || isSecureText) { + if (viewModel.getConversationStateSnapshot().isMmsEnabled() || viewModel.isPushAvailable()) { viewModel.getRecentMedia().removeObservers(this); if (attachmentKeyboardStub.resolved() && container.isInputOpen() && container.getCurrentInput() == attachmentKeyboardStub.get()) { @@ -1570,14 +1564,11 @@ public class ConversationParentFragment extends Fragment @Override public void onCanceled() { } - private void handleSecurityChange(boolean isSecureText, boolean isDefaultSms) { - Log.i(TAG, "handleSecurityChange(" + isSecureText + ", " + isDefaultSms + ")"); + private void handleSecurityChange(@NonNull ConversationSecurityInfo conversationSecurityInfo) { + Log.i(TAG, "handleSecurityChange(" + conversationSecurityInfo + ")"); - this.isSecureText = isSecureText; - this.isDefaultSms = isDefaultSms; - this.isSecurityInitialized = true; - - boolean isMediaMessage = recipient.get().isMmsGroup() || attachmentManager.isAttachmentPresent(); + boolean isPushAvailable = conversationSecurityInfo.isPushAvailable(); + boolean isMediaMessage = recipient.get().isMmsGroup() || attachmentManager.isAttachmentPresent(); sendButton.resetAvailableTransports(isMediaMessage); @@ -1588,14 +1579,14 @@ public class ConversationParentFragment extends Fragment smsEnabled = false; } - if (!isSecureText && !isPushGroupConversation() && !recipient.get().isServiceIdOnly() && !recipient.get().isReleaseNotes() && smsEnabled) { + if (!isPushAvailable && !isPushGroupConversation() && !recipient.get().isServiceIdOnly() && !recipient.get().isReleaseNotes() && smsEnabled) { sendButton.disableTransportType(MessageSendType.TransportType.SIGNAL); } if (!recipient.get().isPushGroup() && recipient.get().isForceSmsSelection() && smsEnabled) { sendButton.setDefaultTransport(MessageSendType.TransportType.SMS); } else { - if (isSecureText || isPushGroupConversation() || recipient.get().isServiceIdOnly() || recipient.get().isReleaseNotes() || !smsEnabled) { + if (isPushAvailable || isPushGroupConversation() || recipient.get().isServiceIdOnly() || recipient.get().isReleaseNotes() || !smsEnabled) { sendButton.setDefaultTransport(MessageSendType.TransportType.SIGNAL); } else { sendButton.setDefaultTransport(MessageSendType.TransportType.SMS); @@ -1604,7 +1595,7 @@ public class ConversationParentFragment extends Fragment calculateCharactersRemaining(); invalidateOptionsMenu(); - setBlockedUserState(recipient.get(), isSecureText, isDefaultSms); + setBlockedUserState(recipient.get(), conversationSecurityInfo); onSecurityUpdated(); } @@ -1885,7 +1876,7 @@ public class ConversationParentFragment extends Fragment reminderView.get().showReminder(new ServiceOutageReminder(context)); } else if (SignalStore.account().isRegistered() && TextSecurePreferences.isShowInviteReminders(context) && - !isSecureText && + !viewModel.isPushAvailable() && inviteReminder.isPresent() && !recipient.get().isGroup()) { reminderView.get().setOnActionClickListener(this::handleReminderAction); @@ -1995,7 +1986,7 @@ public class ConversationParentFragment extends Fragment unverifiedBannerView.get().hide(); } - titleView.setVerified(isSecureText && identityRecords.isVerified() && !recipient.get().isSelf()); + titleView.setVerified(viewModel.isPushAvailable() && identityRecords.isVerified() && !recipient.get().isSelf()); future.set(true); } @@ -2508,7 +2499,7 @@ public class ConversationParentFragment extends Fragment } private void initializeProfiles() { - if (!isSecureText) { + if (!viewModel.isPushAvailable()) { Log.i(TAG, "SMS contact, no profile fetch needed."); return; } @@ -2529,7 +2520,7 @@ public class ConversationParentFragment extends Fragment Log.i(TAG, "onModified(" + recipient.getId() + ") " + recipient.getRegistered()); titleView.setTitle(glideRequests, recipient); titleView.setVerified(identityRecords.isVerified() && !recipient.isSelf()); - setBlockedUserState(recipient, isSecureText, isDefaultSms); + setBlockedUserState(recipient, viewModel.getConversationStateSnapshot().getSecurityInfo()); updateReminders(); updateDefaultSubscriptionId(recipient.getDefaultSubscriptionId()); updatePaymentsAvailable(); @@ -2618,7 +2609,7 @@ public class ConversationParentFragment extends Fragment return new SettableFuture<>(false); } - if (MediaType.VCARD.equals(mediaType) && isSecureText) { + if (MediaType.VCARD.equals(mediaType) && viewModel.isPushAvailable()) { openContactShareEditor(uri); return new SettableFuture<>(false); } else if (MediaType.IMAGE.equals(mediaType) || MediaType.GIF.equals(mediaType) || MediaType.VIDEO.equals(mediaType)) { @@ -2768,13 +2759,18 @@ public class ConversationParentFragment extends Fragment return future; } - private void setBlockedUserState(Recipient recipient, boolean isSecureText, boolean isDefaultSms) { - if (!isSecureText && isPushGroupConversation()) { + private void setBlockedUserState(Recipient recipient, @NonNull ConversationSecurityInfo conversationSecurityInfo) { + if (!conversationSecurityInfo.isInitialized()) { + Log.i(TAG, "Ignoring blocked state update for uninitialized security info."); + return; + } + + if (!conversationSecurityInfo.isPushAvailable() && isPushGroupConversation()) { unblockButton.setVisibility(View.GONE); inputPanel.setHideForBlockedState(true); makeDefaultSmsButton.setVisibility(View.GONE); registerButton.setVisibility(View.VISIBLE); - } else if (!isSecureText && !isDefaultSms && recipient.hasSmsAddress()) { + } else if (!conversationSecurityInfo.isPushAvailable() && !conversationSecurityInfo.isDefaultSmsApplication() && recipient.hasSmsAddress()) { unblockButton.setVisibility(View.GONE); inputPanel.setHideForBlockedState(true); makeDefaultSmsButton.setVisibility(View.VISIBLE); @@ -3046,7 +3042,7 @@ public class ConversationParentFragment extends Fragment final boolean clearComposeBox, final @Nullable String metricId) { - if (!isDefaultSms && sendType.usesSmsTransport() && recipient.get().hasSmsAddress()) { + if (!viewModel.isDefaultSmsApplication() && sendType.usesSmsTransport() && recipient.get().hasSmsAddress()) { showDefaultSmsPrompt(); return new SettableFuture<>(null); } @@ -3106,7 +3102,7 @@ public class ConversationParentFragment extends Fragment private void sendTextMessage(@NonNull MessageSendType sendType, final long expiresIn, final boolean initiating, final @Nullable String metricId) throws InvalidMessageException { - if (!isDefaultSms && sendType.usesSmsTransport() && recipient.get().hasSmsAddress()) { + if (!viewModel.isDefaultSmsApplication() && sendType.usesSmsTransport() && recipient.get().hasSmsAddress()) { showDefaultSmsPrompt(); return; } @@ -3189,7 +3185,7 @@ public class ConversationParentFragment extends Fragment } private void updateLinkPreviewState() { - if (SignalStore.settings().isLinkPreviewsEnabled() && isSecureText && !sendButton.getSelectedSendType().usesSmsTransport() && !attachmentManager.isAttachmentPresent() && getContext() != null) { + if (SignalStore.settings().isLinkPreviewsEnabled() && viewModel.isPushAvailable() && !sendButton.getSelectedSendType().usesSmsTransport() && !attachmentManager.isAttachmentPresent() && getContext() != null) { linkPreviewViewModel.onEnabled(); linkPreviewViewModel.onTextChanged(requireContext(), composeText.getTextTrimmed().toString(), composeText.getSelectionStart(), composeText.getSelectionEnd()); } else { @@ -3464,7 +3460,7 @@ public class ConversationParentFragment extends Fragment @Override public boolean isMms() { - return !isSecureText; + return !viewModel.isPushAvailable(); } @Override @@ -3651,7 +3647,7 @@ public class ConversationParentFragment extends Fragment @Override public void onTextChanged(String text) { - if (enabled && threadId > 0 && isSecureText && !isSmsForced() && !recipient.get().isBlocked() && !recipient.get().isSelf()) { + if (enabled && threadId > 0 && viewModel.isPushAvailable() && !isSmsForced() && !recipient.get().isBlocked() && !recipient.get().isSelf()) { TypingStatusSender typingStatusSender = ApplicationDependencies.getTypingStatusSender(); if (text.length() == 0) { @@ -3974,7 +3970,7 @@ public class ConversationParentFragment extends Fragment @Override public void onAttachmentChanged() { - handleSecurityChange(isSecureText, isDefaultSms); + handleSecurityChange(viewModel.getConversationStateSnapshot().getSecurityInfo()); updateToggleButtonState(); updateLinkPreviewState(); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationViewModel.java index 3e4fc9c33..6f1118423 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationViewModel.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationViewModel.java @@ -329,6 +329,14 @@ public class ConversationViewModel extends ViewModel { conversationStateTick.onNext(Unit.INSTANCE); } + boolean isDefaultSmsApplication() { + return conversationStateStore.getState().getSecurityInfo().isDefaultSmsApplication(); + } + + boolean isPushAvailable() { + return conversationStateStore.getState().getSecurityInfo().isPushAvailable(); + } + @NonNull ConversationState getConversationStateSnapshot() { return conversationStateStore.getState(); }