Recreate fragment whenever we handle onNewIntent instead of restarting whole activity.

This commit is contained in:
Alex Hart 2022-07-19 12:49:28 -03:00 committed by Cody Henthorne
parent 88b895f5ea
commit 8767f775e9
4 changed files with 79 additions and 108 deletions

View file

@ -32,14 +32,27 @@ open class ConversationActivity : PassphraseRequiredActivity(), ConversationPare
override fun onCreate(savedInstanceState: Bundle?, ready: Boolean) {
setContentView(R.layout.conversation_parent_fragment_container)
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 {

View file

@ -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,

View file

@ -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<Boolean>() {
@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<Media> mediaList = args.getMedia();
final StickerLocator stickerLocator = args.getStickerLocator();

View file

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container"
android:name="org.thoughtcrime.securesms.conversation.ConversationParentFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />