Wrap ConversationActivity code in a Fragment.

This commit is contained in:
Alex Hart 2022-01-14 09:06:28 -04:00 committed by Greyson Parrelli
parent afd6af6f57
commit b2b51e63be
11 changed files with 531 additions and 405 deletions

View file

@ -16,6 +16,7 @@ import android.support.v4.media.session.PlaybackStateCompat;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.DefaultLifecycleObserver; import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
@ -50,7 +51,7 @@ public class VoiceNoteMediaController implements DefaultLifecycleObserver {
private static final String TAG = Log.tag(VoiceNoteMediaController.class); private static final String TAG = Log.tag(VoiceNoteMediaController.class);
private MediaBrowserCompat mediaBrowser; private MediaBrowserCompat mediaBrowser;
private AppCompatActivity activity; private FragmentActivity activity;
private ProgressEventHandler progressEventHandler; private ProgressEventHandler progressEventHandler;
private MutableLiveData<VoiceNotePlaybackState> voiceNotePlaybackState = new MutableLiveData<>(VoiceNotePlaybackState.NONE); private MutableLiveData<VoiceNotePlaybackState> voiceNotePlaybackState = new MutableLiveData<>(VoiceNotePlaybackState.NONE);
private LiveData<Optional<VoiceNotePlayerView.State>> voiceNotePlayerViewState; private LiveData<Optional<VoiceNotePlayerView.State>> voiceNotePlayerViewState;
@ -58,7 +59,7 @@ public class VoiceNoteMediaController implements DefaultLifecycleObserver {
private final MediaControllerCompatCallback mediaControllerCompatCallback = new MediaControllerCompatCallback(); private final MediaControllerCompatCallback mediaControllerCompatCallback = new MediaControllerCompatCallback();
public VoiceNoteMediaController(@NonNull AppCompatActivity activity) { public VoiceNoteMediaController(@NonNull FragmentActivity activity) {
this.activity = activity; this.activity = activity;
this.mediaBrowser = new MediaBrowserCompat(activity, this.mediaBrowser = new MediaBrowserCompat(activity,
new ComponentName(activity, VoiceNotePlaybackService.class), new ComponentName(activity, VoiceNotePlaybackService.class),

View file

@ -10,7 +10,7 @@ import android.os.Bundle
import android.os.PowerManager import android.os.PowerManager
import android.support.v4.media.session.MediaControllerCompat import android.support.v4.media.session.MediaControllerCompat
import android.support.v4.media.session.PlaybackStateCompat import android.support.v4.media.session.PlaybackStateCompat
import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
@ -25,7 +25,7 @@ private const val PROXIMITY_THRESHOLD = 5f
* Manages the WakeLock while a VoiceNote is playing back in the target activity. * Manages the WakeLock while a VoiceNote is playing back in the target activity.
*/ */
class VoiceNoteProximityWakeLockManager( class VoiceNoteProximityWakeLockManager(
private val activity: AppCompatActivity, private val activity: FragmentActivity,
private val mediaController: MediaControllerCompat private val mediaController: MediaControllerCompat
) : DefaultLifecycleObserver { ) : DefaultLifecycleObserver {

View file

@ -1,5 +1,8 @@
package org.thoughtcrime.securesms.conversation; package org.thoughtcrime.securesms.conversation;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
/** /**
* Activity which encapsulates a conversation for a Bubble window. * Activity which encapsulates a conversation for a Bubble window.
* *
@ -9,7 +12,11 @@ package org.thoughtcrime.securesms.conversation;
*/ */
public class BubbleConversationActivity extends ConversationActivity { public class BubbleConversationActivity extends ConversationActivity {
@Override @Override
protected boolean isInBubble() { public boolean isInBubble() {
return true; return true;
} }
@Override
public void onInitializeToolbar(@NonNull Toolbar toolbar) {
}
} }

View file

@ -0,0 +1,76 @@
package org.thoughtcrime.securesms.conversation
import android.content.Intent
import android.os.Bundle
import android.view.MotionEvent
import android.view.View
import androidx.appcompat.content.res.AppCompatResources
import androidx.appcompat.widget.Toolbar
import org.thoughtcrime.securesms.PassphraseRequiredActivity
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.HidingLinearLayout
import org.thoughtcrime.securesms.components.reminder.ReminderView
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme
import org.thoughtcrime.securesms.util.DynamicTheme
import org.thoughtcrime.securesms.util.concurrent.ListenableFuture
import org.thoughtcrime.securesms.util.views.Stub
open class ConversationActivity : PassphraseRequiredActivity(), ConversationParentFragment.Callback {
private lateinit var fragment: ConversationParentFragment
private val dynamicTheme: DynamicTheme = DynamicNoActionBarTheme()
override fun onPreCreate() {
dynamicTheme.onCreate(this)
}
override fun onCreate(savedInstanceState: Bundle?, ready: Boolean) {
setContentView(R.layout.conversation_parent_fragment_container)
fragment = supportFragmentManager.findFragmentById(R.id.fragment_container) as ConversationParentFragment
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
fragment.onNewIntent(intent)
}
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
return fragment.dispatchTouchEvent(ev) || super.dispatchTouchEvent(ev)
}
override fun onResume() {
super.onResume()
dynamicTheme.onResume(this)
}
override fun onInitializeToolbar(toolbar: Toolbar) {
toolbar.navigationIcon = AppCompatResources.getDrawable(this, R.drawable.ic_arrow_left_24)
toolbar.setNavigationOnClickListener { finish() }
}
fun saveDraft(): ListenableFuture<Long> {
return fragment.saveDraft()
}
fun getRecipient(): Recipient {
return fragment.recipient
}
fun getTitleView(): View {
return fragment.titleView
}
fun getComposeText(): View {
return fragment.composeText
}
fun getQuickAttachmentToggle(): HidingLinearLayout {
return fragment.quickAttachmentToggle
}
fun getReminderView(): Stub<ReminderView> {
return fragment.reminderView
}
}

View file

@ -58,6 +58,7 @@ import androidx.core.view.ViewCompat;
import androidx.core.view.ViewKt; import androidx.core.view.ViewKt;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer; import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelProviders; import androidx.lifecycle.ViewModelProviders;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
@ -253,7 +254,7 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
@Override @Override
public void onCreate(Bundle icicle) { public void onCreate(Bundle icicle) {
super.onCreate(icicle); super.onCreate(icicle);
this.locale = (Locale) getArguments().getSerializable(PassphraseRequiredActivity.LOCALE_EXTRA); this.locale = Locale.getDefault();
startupStopwatch = new Stopwatch("conversation-open"); startupStopwatch = new Stopwatch("conversation-open");
SignalLocalMetrics.ConversationOpen.start(); SignalLocalMetrics.ConversationOpen.start();
} }
@ -323,9 +324,9 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
giphyMp4ProjectionRecycler = initializeGiphyMp4(); giphyMp4ProjectionRecycler = initializeGiphyMp4();
this.groupViewModel = ViewModelProviders.of(requireActivity(), new ConversationGroupViewModel.Factory()).get(ConversationGroupViewModel.class); this.groupViewModel = new ViewModelProvider(getParentFragment(), new ConversationGroupViewModel.Factory()).get(ConversationGroupViewModel.class);
this.messageCountsViewModel = ViewModelProviders.of(requireActivity()).get(MessageCountsViewModel.class); this.messageCountsViewModel = new ViewModelProvider(getParentFragment()).get(MessageCountsViewModel.class);
this.conversationViewModel = ViewModelProviders.of(requireActivity(), new ConversationViewModel.Factory()).get(ConversationViewModel.class); this.conversationViewModel = new ViewModelProvider(getParentFragment(), new ConversationViewModel.Factory()).get(ConversationViewModel.class);
conversationViewModel.getChatColors().observe(getViewLifecycleOwner(), recyclerViewColorizer::setChatColors); conversationViewModel.getChatColors().observe(getViewLifecycleOwner(), recyclerViewColorizer::setChatColors);
conversationViewModel.getMessages().observe(getViewLifecycleOwner(), messages -> { conversationViewModel.getMessages().observe(getViewLifecycleOwner(), messages -> {
@ -381,6 +382,13 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
conversationViewModel.getActiveNotificationProfile().observe(getViewLifecycleOwner(), this::updateNotificationProfileStatus); conversationViewModel.getActiveNotificationProfile().observe(getViewLifecycleOwner(), this::updateNotificationProfileStatus);
initializeScrollButtonAnimations();
initializeResources();
initializeMessageRequestViewModel();
initializeListAdapter();
// TODO [alex] LargeScreenSupport -- conversationViewModel.getSearchQuery().observe(getViewLifecycleOwner(), this::onSearchQueryUpdated);
return view; return view;
} }
@ -414,21 +422,9 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
} }
@Override @Override
public void onActivityCreated(Bundle bundle) { public void onAttach(Context context) {
super.onActivityCreated(bundle); super.onAttach(context);
this.listener = (ConversationFragmentListener) getParentFragment();
Log.d(TAG, "[onActivityCreated]");
initializeScrollButtonAnimations();
initializeResources();
initializeMessageRequestViewModel();
initializeListAdapter();
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
this.listener = (ConversationFragmentListener)activity;
} }
@Override @Override
@ -525,7 +521,7 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
private void initializeMessageRequestViewModel() { private void initializeMessageRequestViewModel() {
MessageRequestViewModel.Factory factory = new MessageRequestViewModel.Factory(requireContext()); MessageRequestViewModel.Factory factory = new MessageRequestViewModel.Factory(requireContext());
messageRequestViewModel = ViewModelProviders.of(requireActivity(), factory).get(MessageRequestViewModel.class); messageRequestViewModel = new ViewModelProvider(requireParentFragment(), factory).get(MessageRequestViewModel.class);
messageRequestViewModel.setConversationInfo(recipient.getId(), threadId); messageRequestViewModel.setConversationInfo(recipient.getId(), threadId);
listener.onMessageRequest(messageRequestViewModel); listener.onMessageRequest(messageRequestViewModel);

View file

@ -10,6 +10,7 @@ import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.WindowManager; import android.view.WindowManager;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityOptionsCompat; import androidx.core.app.ActivityOptionsCompat;
import org.signal.core.util.logging.Log; import org.signal.core.util.logging.Log;
@ -48,14 +49,14 @@ public class ConversationPopupActivity extends ConversationActivity {
super.onCreate(bundle, ready); super.onCreate(bundle, ready);
titleView.setOnClickListener(null); getTitleView().setOnClickListener(null);
} }
@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
composeText.requestFocus(); getComposeText().requestFocus();
quickAttachmentToggle.disable(); getQuickAttachmentToggle().disable();
} }
@Override @Override
@ -101,21 +102,20 @@ public class ConversationPopupActivity extends ConversationActivity {
} }
@Override @Override
protected void initializeActionBar() { public void onInitializeToolbar(Toolbar toolbar) {
super.initializeActionBar();
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
} }
@Override @Override
protected void sendComplete(long threadId) { public void onSendComplete(long threadId) {
super.sendComplete(threadId);
finish(); finish();
} }
@Override @Override
protected void updateReminders() { public boolean onUpdateReminders() {
if (reminderView.resolved()) { if (getReminderView().resolved()) {
reminderView.get().setVisibility(View.GONE); getReminderView().get().setVisibility(View.GONE);
} }
return false;
} }
} }

View file

@ -9,7 +9,7 @@ import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import org.thoughtcrime.securesms.LoggingFragment import org.thoughtcrime.securesms.LoggingFragment
import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.conversation.ConversationActivity import org.thoughtcrime.securesms.conversation.ConversationParentFragment
import org.thoughtcrime.securesms.giph.mp4.GiphyMp4Fragment import org.thoughtcrime.securesms.giph.mp4.GiphyMp4Fragment
import org.thoughtcrime.securesms.giph.mp4.GiphyMp4SaveResult import org.thoughtcrime.securesms.giph.mp4.GiphyMp4SaveResult
import org.thoughtcrime.securesms.giph.mp4.GiphyMp4ViewModel import org.thoughtcrime.securesms.giph.mp4.GiphyMp4ViewModel
@ -107,7 +107,7 @@ class GifKeyboardPageFragment : LoggingFragment(R.layout.gif_keyboard_page_fragm
} }
private fun openGifSearch() { private fun openGifSearch() {
AttachmentManager.selectGif(requireActivity(), ConversationActivity.PICK_GIF, host.isMms()) AttachmentManager.selectGif(requireActivity(), ConversationParentFragment.PICK_GIF, host.isMms())
} }
interface Host { interface Host {

View file

@ -100,6 +100,10 @@ public final class ViewUtil {
return new Stub<>(parent.findViewById(resId)); return new Stub<>(parent.findViewById(resId));
} }
public static <T extends View> Stub<T> findStubById(@NonNull View parent, @IdRes int resId) {
return new Stub<>(parent.findViewById(resId));
}
private static Animation getAlphaAnimation(float from, float to, int duration) { private static Animation getAlphaAnimation(float from, float to, int duration) {
final Animation anim = new AlphaAnimation(from, to); final Animation anim = new AlphaAnimation(from, to);
anim.setInterpolator(new FastOutSlowInInterpolator()); anim.setInterpolator(new FastOutSlowInInterpolator());

View file

@ -161,14 +161,14 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
android:background="@color/conversation_toolbar_color" android:background="@color/conversation_toolbar_color"
android:theme="?attr/actionBarStyle" android:clipChildren="false"
app:contentInsetStartWithNavigation="0dp"
app:layout_constraintStart_toStartOf="@id/parent_start_guideline"
app:layout_constraintEnd_toEndOf="@id/parent_end_guideline"
app:layout_constraintTop_toTopOf="@id/status_bar_guideline"
app:contentInsetStart="46dp"
android:clipToPadding="false" android:clipToPadding="false"
android:clipChildren="false"> android:theme="?attr/actionBarStyle"
app:contentInsetStart="46dp"
app:contentInsetStartWithNavigation="0dp"
app:layout_constraintEnd_toEndOf="@id/parent_end_guideline"
app:layout_constraintStart_toStartOf="@id/parent_start_guideline"
app:layout_constraintTop_toTopOf="@id/status_bar_guideline">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"

View file

@ -0,0 +1,6 @@
<?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" />