Recreate fragment whenever we handle onNewIntent instead of restarting whole activity.
This commit is contained in:
parent
88b895f5ea
commit
8767f775e9
4 changed files with 79 additions and 108 deletions
|
@ -32,14 +32,27 @@ open class ConversationActivity : PassphraseRequiredActivity(), ConversationPare
|
||||||
override fun onCreate(savedInstanceState: Bundle?, ready: Boolean) {
|
override fun onCreate(savedInstanceState: Bundle?, ready: Boolean) {
|
||||||
setContentView(R.layout.conversation_parent_fragment_container)
|
setContentView(R.layout.conversation_parent_fragment_container)
|
||||||
|
|
||||||
|
if (savedInstanceState == null) {
|
||||||
|
replaceFragment(intent!!)
|
||||||
|
} else {
|
||||||
fragment = supportFragmentManager.findFragmentById(R.id.fragment_container) as ConversationParentFragment
|
fragment = supportFragmentManager.findFragmentById(R.id.fragment_container) as ConversationParentFragment
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onNewIntent(intent: Intent?) {
|
override fun onNewIntent(intent: Intent?) {
|
||||||
super.onNewIntent(intent)
|
super.onNewIntent(intent)
|
||||||
|
|
||||||
finish()
|
setIntent(intent)
|
||||||
startActivity(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 {
|
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
|
||||||
|
|
|
@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.conversation;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
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_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_WITH_SEARCH_OPEN = "with_search_open";
|
||||||
private static final String EXTRA_GIFT_BADGE = "gift_badge";
|
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() {
|
private ConversationIntents() {
|
||||||
}
|
}
|
||||||
|
@ -51,16 +54,35 @@ public class ConversationIntents {
|
||||||
return new Builder(context, BubbleConversationActivity.class, recipientId, threadId).build();
|
return new Builder(context, BubbleConversationActivity.class, recipientId, threadId).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean isInvalid(@NonNull Intent intent) {
|
static boolean isInvalid(@NonNull Bundle arguments) {
|
||||||
if (isBubbleIntent(intent)) {
|
Uri uri = getIntentData(arguments);
|
||||||
return intent.getData().getQueryParameter(EXTRA_RECIPIENT) == null;
|
if (isBubbleIntentUri(uri)) {
|
||||||
|
return uri.getQueryParameter(EXTRA_RECIPIENT) == null;
|
||||||
} else {
|
} else {
|
||||||
return !intent.hasExtra(EXTRA_RECIPIENT);
|
return !arguments.containsKey(EXTRA_RECIPIENT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isBubbleIntent(@NonNull Intent intent) {
|
static @Nullable Uri getIntentData(@NonNull Bundle bundle) {
|
||||||
return intent.getData() != null && Objects.equals(intent.getData().getAuthority(), BUBBLE_AUTHORITY);
|
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 {
|
final static class Args {
|
||||||
|
@ -76,10 +98,11 @@ public class ConversationIntents {
|
||||||
private final boolean withSearchOpen;
|
private final boolean withSearchOpen;
|
||||||
private final Badge giftBadge;
|
private final Badge giftBadge;
|
||||||
|
|
||||||
static Args from(@NonNull Intent intent) {
|
static Args from(@NonNull Bundle arguments) {
|
||||||
if (isBubbleIntent(intent)) {
|
Uri intentDataUri = getIntentData(arguments);
|
||||||
return new Args(RecipientId.from(intent.getData().getQueryParameter(EXTRA_RECIPIENT)),
|
if (isBubbleIntentUri(intentDataUri)) {
|
||||||
Long.parseLong(intent.getData().getQueryParameter(EXTRA_THREAD_ID)),
|
return new Args(RecipientId.from(intentDataUri.getQueryParameter(EXTRA_RECIPIENT)),
|
||||||
|
Long.parseLong(intentDataUri.getQueryParameter(EXTRA_THREAD_ID)),
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
|
@ -91,17 +114,17 @@ public class ConversationIntents {
|
||||||
null);
|
null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Args(RecipientId.from(Objects.requireNonNull(intent.getStringExtra(EXTRA_RECIPIENT))),
|
return new Args(RecipientId.from(Objects.requireNonNull(arguments.getString(EXTRA_RECIPIENT))),
|
||||||
intent.getLongExtra(EXTRA_THREAD_ID, -1),
|
arguments.getLong(EXTRA_THREAD_ID, -1),
|
||||||
intent.getStringExtra(EXTRA_TEXT),
|
arguments.getString(EXTRA_TEXT),
|
||||||
intent.getParcelableArrayListExtra(EXTRA_MEDIA),
|
arguments.getParcelableArrayList(EXTRA_MEDIA),
|
||||||
intent.getParcelableExtra(EXTRA_STICKER),
|
arguments.getParcelable(EXTRA_STICKER),
|
||||||
intent.getBooleanExtra(EXTRA_BORDERLESS, false),
|
arguments.getBoolean(EXTRA_BORDERLESS, false),
|
||||||
intent.getIntExtra(EXTRA_DISTRIBUTION_TYPE, ThreadDatabase.DistributionTypes.DEFAULT),
|
arguments.getInt(EXTRA_DISTRIBUTION_TYPE, ThreadDatabase.DistributionTypes.DEFAULT),
|
||||||
intent.getIntExtra(EXTRA_STARTING_POSITION, -1),
|
arguments.getInt(EXTRA_STARTING_POSITION, -1),
|
||||||
intent.getBooleanExtra(EXTRA_FIRST_TIME_IN_SELF_CREATED_GROUP, false),
|
arguments.getBoolean(EXTRA_FIRST_TIME_IN_SELF_CREATED_GROUP, false),
|
||||||
intent.getBooleanExtra(EXTRA_WITH_SEARCH_OPEN, false),
|
arguments.getBoolean(EXTRA_WITH_SEARCH_OPEN, false),
|
||||||
intent.getParcelableExtra(EXTRA_GIFT_BADGE));
|
arguments.getParcelable(EXTRA_GIFT_BADGE));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Args(@NonNull RecipientId recipientId,
|
private Args(@NonNull RecipientId recipientId,
|
||||||
|
|
|
@ -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_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 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 REQUEST_CODE_SETTINGS = 1000;
|
||||||
|
|
||||||
private static final int PICK_GALLERY = 1;
|
private static final int PICK_GALLERY = 1;
|
||||||
|
@ -460,12 +462,20 @@ public class ConversationParentFragment extends Fragment
|
||||||
private final LifecycleDisposable disposables = new LifecycleDisposable();
|
private final LifecycleDisposable disposables = new LifecycleDisposable();
|
||||||
private final Debouncer optionsMenuDebouncer = new Debouncer(50);
|
private final Debouncer optionsMenuDebouncer = new Debouncer(50);
|
||||||
|
|
||||||
private volatile boolean screenInitialized = false;
|
|
||||||
|
|
||||||
private IdentityRecordList identityRecords = new IdentityRecordList(Collections.emptyList());
|
private IdentityRecordList identityRecords = new IdentityRecordList(Collections.emptyList());
|
||||||
private Callback callback;
|
private Callback callback;
|
||||||
private RecentEmojiPageModel recentEmojis;
|
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
|
@Override
|
||||||
public @NonNull View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
public @NonNull View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
return inflater.inflate(R.layout.conversation_activity, container, false);
|
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
|
// 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!");
|
Log.w(TAG, "[onCreate] Missing recipientId!");
|
||||||
// TODO [greyson] Navigation
|
// TODO [greyson] Navigation
|
||||||
startActivity(MainActivity.clearTop(requireContext()));
|
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.
|
// TODO [alex] LargeScreenSupport -- Should be removed once we move to multi-pane layout.
|
||||||
new FullscreenHelper(requireActivity()).showSystemUI();
|
new FullscreenHelper(requireActivity()).showSystemUI();
|
||||||
|
|
||||||
// TODO [alex] LargeScreenSupport -- This will need to be built from requireArguments()
|
ConversationIntents.Args args = ConversationIntents.Args.from(requireArguments());
|
||||||
ConversationIntents.Args args = ConversationIntents.Args.from(requireActivity().getIntent());
|
|
||||||
if (savedInstanceState == null && args.getGiftBadge() != null) {
|
if (savedInstanceState == null && args.getGiftBadge() != null) {
|
||||||
GiftThanksSheet.show(getChildFragmentManager(), args.getRecipientId(), args.getGiftBadge());
|
GiftThanksSheet.show(getChildFragmentManager(), args.getRecipientId(), args.getGiftBadge());
|
||||||
}
|
}
|
||||||
|
@ -575,8 +584,6 @@ public class ConversationParentFragment extends Fragment
|
||||||
composeText.addTextChangedListener(typingTextWatcher);
|
composeText.addTextChangedListener(typingTextWatcher);
|
||||||
}
|
}
|
||||||
composeText.setSelection(composeText.length(), composeText.length());
|
composeText.setSelection(composeText.length(), composeText.length());
|
||||||
|
|
||||||
screenInitialized = true;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -600,78 +607,6 @@ public class ConversationParentFragment extends Fragment
|
||||||
sendButton.post(() -> sendButton.triggerSelectedChangedEvent());
|
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
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
@ -1598,9 +1533,10 @@ public class ConversationParentFragment extends Fragment
|
||||||
private void handleManualMmsRequired() {
|
private void handleManualMmsRequired() {
|
||||||
Toast.makeText(requireContext(), R.string.MmsDownloader_error_reading_mms_settings, Toast.LENGTH_LONG).show();
|
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);
|
Intent intent = new Intent(requireContext(), PromptMmsActivity.class);
|
||||||
if (extras != null) intent.putExtras(extras);
|
|
||||||
|
intent.putExtras(extras);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1676,8 +1612,8 @@ public class ConversationParentFragment extends Fragment
|
||||||
}
|
}
|
||||||
|
|
||||||
final CharSequence draftText = args.getDraftText();
|
final CharSequence draftText = args.getDraftText();
|
||||||
final Uri draftMedia = requireActivity().getIntent().getData();
|
final Uri draftMedia = ConversationIntents.getIntentData(requireArguments());
|
||||||
final String draftContentType = requireActivity().getIntent().getType();
|
final String draftContentType = ConversationIntents.getIntentType(requireArguments());
|
||||||
final MediaType draftMediaType = MediaType.from(draftContentType);
|
final MediaType draftMediaType = MediaType.from(draftContentType);
|
||||||
final List<Media> mediaList = args.getMedia();
|
final List<Media> mediaList = args.getMedia();
|
||||||
final StickerLocator stickerLocator = args.getStickerLocator();
|
final StickerLocator stickerLocator = args.getStickerLocator();
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:id="@+id/fragment_container"
|
android:id="@+id/fragment_container"
|
||||||
android:name="org.thoughtcrime.securesms.conversation.ConversationParentFragment"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" />
|
android:layout_height="match_parent" />
|
Loading…
Add table
Reference in a new issue