diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.kt index 9490eb58e7..01e716d007 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.kt @@ -32,14 +32,27 @@ open class ConversationActivity : PassphraseRequiredActivity(), ConversationPare override fun onCreate(savedInstanceState: Bundle?, ready: Boolean) { setContentView(R.layout.conversation_parent_fragment_container) - fragment = supportFragmentManager.findFragmentById(R.id.fragment_container) as ConversationParentFragment + if (savedInstanceState == null) { + replaceFragment(intent!!) + } else { + fragment = supportFragmentManager.findFragmentById(R.id.fragment_container) as ConversationParentFragment + } } override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) - finish() - startActivity(intent) + setIntent(intent) + replaceFragment(intent!!) + } + + private fun replaceFragment(intent: Intent) { + fragment = ConversationParentFragment.create(intent) + supportFragmentManager + .beginTransaction() + .replace(R.id.fragment_container, fragment) + .disallowAddToBackStack() + .commitNowAllowingStateLoss() } override fun dispatchTouchEvent(ev: MotionEvent?): Boolean { diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationIntents.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationIntents.java index cf3a841f3f..136169d773 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationIntents.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationIntents.java @@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.conversation; import android.content.Context; import android.content.Intent; import android.net.Uri; +import android.os.Bundle; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -35,6 +36,8 @@ public class ConversationIntents { private static final String EXTRA_FIRST_TIME_IN_SELF_CREATED_GROUP = "first_time_in_group"; private static final String EXTRA_WITH_SEARCH_OPEN = "with_search_open"; private static final String EXTRA_GIFT_BADGE = "gift_badge"; + private static final String INTENT_DATA = "intent_data"; + private static final String INTENT_TYPE = "intent_type"; private ConversationIntents() { } @@ -51,16 +54,35 @@ public class ConversationIntents { return new Builder(context, BubbleConversationActivity.class, recipientId, threadId).build(); } - static boolean isInvalid(@NonNull Intent intent) { - if (isBubbleIntent(intent)) { - return intent.getData().getQueryParameter(EXTRA_RECIPIENT) == null; + static boolean isInvalid(@NonNull Bundle arguments) { + Uri uri = getIntentData(arguments); + if (isBubbleIntentUri(uri)) { + return uri.getQueryParameter(EXTRA_RECIPIENT) == null; } else { - return !intent.hasExtra(EXTRA_RECIPIENT); + return !arguments.containsKey(EXTRA_RECIPIENT); } } - private static boolean isBubbleIntent(@NonNull Intent intent) { - return intent.getData() != null && Objects.equals(intent.getData().getAuthority(), BUBBLE_AUTHORITY); + static @Nullable Uri getIntentData(@NonNull Bundle bundle) { + return bundle.getParcelable(INTENT_DATA); + } + + static @Nullable String getIntentType(@NonNull Bundle bundle) { + return bundle.getString(INTENT_TYPE); + } + + static @NonNull Bundle createParentFragmentArguments(@NonNull Intent intent) { + Bundle bundle = new Bundle(); + + bundle.putAll(intent.getExtras()); + bundle.putParcelable(INTENT_DATA, intent.getData()); + bundle.putString(INTENT_TYPE, intent.getType()); + + return bundle; + } + + private static boolean isBubbleIntentUri(@Nullable Uri uri) { + return uri != null && Objects.equals(uri.getAuthority(), BUBBLE_AUTHORITY); } final static class Args { @@ -76,10 +98,11 @@ public class ConversationIntents { private final boolean withSearchOpen; private final Badge giftBadge; - static Args from(@NonNull Intent intent) { - if (isBubbleIntent(intent)) { - return new Args(RecipientId.from(intent.getData().getQueryParameter(EXTRA_RECIPIENT)), - Long.parseLong(intent.getData().getQueryParameter(EXTRA_THREAD_ID)), + static Args from(@NonNull Bundle arguments) { + Uri intentDataUri = getIntentData(arguments); + if (isBubbleIntentUri(intentDataUri)) { + return new Args(RecipientId.from(intentDataUri.getQueryParameter(EXTRA_RECIPIENT)), + Long.parseLong(intentDataUri.getQueryParameter(EXTRA_THREAD_ID)), null, null, null, @@ -91,17 +114,17 @@ public class ConversationIntents { null); } - return new Args(RecipientId.from(Objects.requireNonNull(intent.getStringExtra(EXTRA_RECIPIENT))), - intent.getLongExtra(EXTRA_THREAD_ID, -1), - intent.getStringExtra(EXTRA_TEXT), - intent.getParcelableArrayListExtra(EXTRA_MEDIA), - intent.getParcelableExtra(EXTRA_STICKER), - intent.getBooleanExtra(EXTRA_BORDERLESS, false), - intent.getIntExtra(EXTRA_DISTRIBUTION_TYPE, ThreadDatabase.DistributionTypes.DEFAULT), - intent.getIntExtra(EXTRA_STARTING_POSITION, -1), - intent.getBooleanExtra(EXTRA_FIRST_TIME_IN_SELF_CREATED_GROUP, false), - intent.getBooleanExtra(EXTRA_WITH_SEARCH_OPEN, false), - intent.getParcelableExtra(EXTRA_GIFT_BADGE)); + return new Args(RecipientId.from(Objects.requireNonNull(arguments.getString(EXTRA_RECIPIENT))), + arguments.getLong(EXTRA_THREAD_ID, -1), + arguments.getString(EXTRA_TEXT), + arguments.getParcelableArrayList(EXTRA_MEDIA), + arguments.getParcelable(EXTRA_STICKER), + arguments.getBoolean(EXTRA_BORDERLESS, false), + arguments.getInt(EXTRA_DISTRIBUTION_TYPE, ThreadDatabase.DistributionTypes.DEFAULT), + arguments.getInt(EXTRA_STARTING_POSITION, -1), + arguments.getBoolean(EXTRA_FIRST_TIME_IN_SELF_CREATED_GROUP, false), + arguments.getBoolean(EXTRA_WITH_SEARCH_OPEN, false), + arguments.getParcelable(EXTRA_GIFT_BADGE)); } private Args(@NonNull RecipientId recipientId, 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 a2c325d418..62ecb0363e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationParentFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationParentFragment.java @@ -369,6 +369,8 @@ public class ConversationParentFragment extends Fragment private static final String STATE_REACT_WITH_ANY_PAGE = "STATE_REACT_WITH_ANY_PAGE"; private static final String STATE_IS_SEARCH_REQUESTED = "STATE_IS_SEARCH_REQUESTED"; + private static final String ARG_INTENT_DATA = "arg.intent.data"; + private static final int REQUEST_CODE_SETTINGS = 1000; private static final int PICK_GALLERY = 1; @@ -460,12 +462,20 @@ public class ConversationParentFragment extends Fragment private final LifecycleDisposable disposables = new LifecycleDisposable(); private final Debouncer optionsMenuDebouncer = new Debouncer(50); - private volatile boolean screenInitialized = false; - private IdentityRecordList identityRecords = new IdentityRecordList(Collections.emptyList()); private Callback callback; private RecentEmojiPageModel recentEmojis; + public static ConversationParentFragment create(Intent intent) { + ConversationParentFragment fragment = new ConversationParentFragment(); + Bundle bundle = new Bundle(); + + bundle.putAll(ConversationIntents.createParentFragmentArguments(intent)); + fragment.setArguments(bundle); + + return fragment; + } + @Override public @NonNull View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.conversation_activity, container, false); @@ -484,7 +494,7 @@ public class ConversationParentFragment extends Fragment } // TODO [alex] LargeScreenSupport -- This check will no longer be valid / necessary - if (ConversationIntents.isInvalid(requireActivity().getIntent())) { + if (ConversationIntents.isInvalid(requireArguments())) { Log.w(TAG, "[onCreate] Missing recipientId!"); // TODO [greyson] Navigation startActivity(MainActivity.clearTop(requireContext())); @@ -499,8 +509,7 @@ public class ConversationParentFragment extends Fragment // TODO [alex] LargeScreenSupport -- Should be removed once we move to multi-pane layout. new FullscreenHelper(requireActivity()).showSystemUI(); - // TODO [alex] LargeScreenSupport -- This will need to be built from requireArguments() - ConversationIntents.Args args = ConversationIntents.Args.from(requireActivity().getIntent()); + ConversationIntents.Args args = ConversationIntents.Args.from(requireArguments()); if (savedInstanceState == null && args.getGiftBadge() != null) { GiftThanksSheet.show(getChildFragmentManager(), args.getRecipientId(), args.getGiftBadge()); } @@ -575,8 +584,6 @@ public class ConversationParentFragment extends Fragment composeText.addTextChangedListener(typingTextWatcher); } composeText.setSelection(composeText.length(), composeText.length()); - - screenInitialized = true; } }); } @@ -600,78 +607,6 @@ public class ConversationParentFragment extends Fragment sendButton.post(() -> sendButton.triggerSelectedChangedEvent()); } - // TODO [alex] LargeScreenSupport -- This needs to be fed a stream of intents - protected void onNewIntent(Intent intent) { - Log.i(TAG, "onNewIntent()"); - - if (requireActivity().isFinishing()) { - Log.w(TAG, "Activity is finishing..."); - return; - } - - if (!screenInitialized) { - Log.w(TAG, "Activity is in the middle of initialization. Restarting."); - requireActivity().finish(); - startActivity(intent); - return; - } - - reactWithAnyEmojiStartPage = -1; - if (!Util.isEmpty(composeText) || attachmentManager.isAttachmentPresent() || inputPanel.hasSaveableContent()) { - saveDraft(); - attachmentManager.clear(glideRequests, false); - inputPanel.clearQuote(); - silentlySetComposeText(""); - } - - if (ConversationIntents.isInvalid(intent)) { - Log.w(TAG, "[onNewIntent] Missing recipientId!"); - // TODO [greyson] Navigation - startActivity(MainActivity.clearTop(requireContext())); - requireActivity().finish(); - return; - } - - requireActivity().setIntent(intent); - - ConversationIntents.Args args = ConversationIntents.Args.from(intent); - // TODO [alex] LargeScreenSupport - Set arguments - isSearchRequested = args.isWithSearchOpen(); - - viewModel.setArgs(args); - setVisibleThread(args.getThreadId()); - - reportShortcutLaunch(viewModel.getArgs().getRecipientId()); - initializeResources(viewModel.getArgs()); - - initializeSecurity(recipient.get().isRegistered(), isDefaultSms).addListener(new AssertedSuccessListener() { - @Override - public void onSuccess(Boolean result) { - if (getContext() != null) { - Log.d(TAG, "Initializing draft from new intent..."); - hasProcessedShareData = false; - initializeDraft(viewModel.getArgs()); - } - } - }); - - if (fragment != null) { - fragment.onNewIntent(); - } - - searchNav.setVisibility(View.GONE); - - if (args.isWithSearchOpen()) { - if (searchViewItem != null && searchViewItem.expandActionView()) { - searchViewModel.onSearchOpened(); - } - } else { - searchViewModel.onSearchClosed(); - viewModel.setSearchQuery(null); - inputPanel.setHideForSearch(false); - } - } - @Override public void onResume() { super.onResume(); @@ -1598,9 +1533,10 @@ public class ConversationParentFragment extends Fragment private void handleManualMmsRequired() { Toast.makeText(requireContext(), R.string.MmsDownloader_error_reading_mms_settings, Toast.LENGTH_LONG).show(); - Bundle extras = requireActivity().getIntent().getExtras(); + Bundle extras = requireArguments(); Intent intent = new Intent(requireContext(), PromptMmsActivity.class); - if (extras != null) intent.putExtras(extras); + + intent.putExtras(extras); startActivity(intent); } @@ -1676,8 +1612,8 @@ public class ConversationParentFragment extends Fragment } final CharSequence draftText = args.getDraftText(); - final Uri draftMedia = requireActivity().getIntent().getData(); - final String draftContentType = requireActivity().getIntent().getType(); + final Uri draftMedia = ConversationIntents.getIntentData(requireArguments()); + final String draftContentType = ConversationIntents.getIntentType(requireArguments()); final MediaType draftMediaType = MediaType.from(draftContentType); final List mediaList = args.getMedia(); final StickerLocator stickerLocator = args.getStickerLocator(); diff --git a/app/src/main/res/layout/conversation_parent_fragment_container.xml b/app/src/main/res/layout/conversation_parent_fragment_container.xml index 63a53d026b..90c9e68422 100644 --- a/app/src/main/res/layout/conversation_parent_fragment_container.xml +++ b/app/src/main/res/layout/conversation_parent_fragment_container.xml @@ -1,6 +1,5 @@ \ No newline at end of file