Move reaction overlay UI into a stub.
This commit is contained in:
parent
f6cd190245
commit
1b448c2bdf
4 changed files with 183 additions and 48 deletions
|
@ -269,7 +269,6 @@ import org.thoughtcrime.securesms.util.SmsUtil;
|
|||
import org.thoughtcrime.securesms.util.SpanUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences.MediaKeyboardMode;
|
||||
import org.thoughtcrime.securesms.util.ThemeUtil;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.WindowUtil;
|
||||
|
@ -344,26 +343,26 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
|||
private static final int SMS_DEFAULT = 11;
|
||||
private static final int MEDIA_SENDER = 12;
|
||||
|
||||
private GlideRequests glideRequests;
|
||||
protected ComposeText composeText;
|
||||
private AnimatingToggle buttonToggle;
|
||||
private SendButton sendButton;
|
||||
private ImageButton attachButton;
|
||||
protected ConversationTitleView titleView;
|
||||
private TextView charactersLeft;
|
||||
private ConversationFragment fragment;
|
||||
private Button unblockButton;
|
||||
private Button makeDefaultSmsButton;
|
||||
private Button registerButton;
|
||||
private InputAwareLayout container;
|
||||
protected Stub<ReminderView> reminderView;
|
||||
private Stub<UnverifiedBannerView> unverifiedBannerView;
|
||||
private Stub<ReviewBannerView> reviewBanner;
|
||||
private TypingStatusTextWatcher typingTextWatcher;
|
||||
private ConversationSearchBottomBar searchNav;
|
||||
private MenuItem searchViewItem;
|
||||
private MessageRequestsBottomView messageRequestBottomView;
|
||||
private ConversationReactionOverlay reactionOverlay;
|
||||
private GlideRequests glideRequests;
|
||||
protected ComposeText composeText;
|
||||
private AnimatingToggle buttonToggle;
|
||||
private SendButton sendButton;
|
||||
private ImageButton attachButton;
|
||||
protected ConversationTitleView titleView;
|
||||
private TextView charactersLeft;
|
||||
private ConversationFragment fragment;
|
||||
private Button unblockButton;
|
||||
private Button makeDefaultSmsButton;
|
||||
private Button registerButton;
|
||||
private InputAwareLayout container;
|
||||
protected Stub<ReminderView> reminderView;
|
||||
private Stub<UnverifiedBannerView> unverifiedBannerView;
|
||||
private Stub<ReviewBannerView> reviewBanner;
|
||||
private TypingStatusTextWatcher typingTextWatcher;
|
||||
private ConversationSearchBottomBar searchNav;
|
||||
private MenuItem searchViewItem;
|
||||
private MessageRequestsBottomView messageRequestBottomView;
|
||||
private ConversationReactionDelegate reactionDelegate;
|
||||
|
||||
private AttachmentManager attachmentManager;
|
||||
private AudioRecorder audioRecorder;
|
||||
|
@ -594,8 +593,8 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
|||
container.hideAttachedInput(true);
|
||||
}
|
||||
|
||||
if (reactionOverlay != null && reactionOverlay.isShowing()) {
|
||||
reactionOverlay.hide();
|
||||
if (reactionDelegate.isShowing()) {
|
||||
reactionDelegate.hide();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -608,7 +607,7 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
|||
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent ev) {
|
||||
return reactionOverlay.applyTouchEvent(ev) || super.dispatchTouchEvent(ev);
|
||||
return reactionDelegate.applyTouchEvent(ev) || super.dispatchTouchEvent(ev);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1030,8 +1029,8 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
|||
@Override
|
||||
public void onBackPressed() {
|
||||
Log.d(TAG, "onBackPressed()");
|
||||
if (reactionOverlay.isShowing()) {
|
||||
reactionOverlay.hide();
|
||||
if (reactionDelegate.isShowing()) {
|
||||
reactionDelegate.hide();
|
||||
} else if (container.isInputOpen()) {
|
||||
container.hideCurrentInput(composeText);
|
||||
} else {
|
||||
|
@ -1919,7 +1918,6 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
|||
panelParent = findViewById(R.id.conversation_activity_panel_parent);
|
||||
searchNav = findViewById(R.id.conversation_search_nav);
|
||||
messageRequestBottomView = findViewById(R.id.conversation_activity_message_request_bottom_bar);
|
||||
reactionOverlay = findViewById(R.id.conversation_reaction_scrubber);
|
||||
mentionsSuggestions = ViewUtil.findStubById(this, R.id.conversation_mention_suggestions_stub);
|
||||
wallpaper = findViewById(R.id.conversation_wallpaper);
|
||||
wallpaperDim = findViewById(R.id.conversation_wallpaper_dim);
|
||||
|
@ -1927,6 +1925,10 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
|||
ImageButton quickCameraToggle = findViewById(R.id.quick_camera_toggle);
|
||||
ImageButton inlineAttachmentButton = findViewById(R.id.inline_attachment_button);
|
||||
|
||||
Stub<ConversationReactionOverlay> reactionOverlayStub = ViewUtil.findStubById(this, R.id.conversation_reaction_scrubber_stub);
|
||||
reactionDelegate = new ConversationReactionDelegate(reactionOverlayStub);
|
||||
|
||||
|
||||
noLongerMemberBanner = findViewById(R.id.conversation_no_longer_member_banner);
|
||||
requestingMemberBanner = findViewById(R.id.conversation_requesting_banner);
|
||||
cancelJoinRequest = findViewById(R.id.conversation_cancel_request);
|
||||
|
@ -1984,7 +1986,7 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
|||
|
||||
inlineAttachmentButton.setOnClickListener(v -> handleAddAttachment());
|
||||
|
||||
reactionOverlay.setOnReactionSelectedListener(this);
|
||||
reactionDelegate.setOnReactionSelectedListener(this);
|
||||
|
||||
joinGroupCallButton.setOnClickListener(v -> handleVideo(getRecipient()));
|
||||
}
|
||||
|
@ -2212,7 +2214,7 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
|||
public void onReactionSelected(MessageRecord messageRecord, String emoji) {
|
||||
final Context context = getApplicationContext();
|
||||
|
||||
reactionOverlay.hide();
|
||||
reactionDelegate.hide();
|
||||
|
||||
SignalExecutors.BOUNDED.execute(() -> {
|
||||
ReactionRecord oldRecord = Stream.of(messageRecord.getReactions())
|
||||
|
@ -2238,14 +2240,14 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
|||
if (oldRecord != null && hasAddedCustomEmoji) {
|
||||
final Context context = getApplicationContext();
|
||||
|
||||
reactionOverlay.hide();
|
||||
reactionDelegate.hide();
|
||||
|
||||
SignalExecutors.BOUNDED.execute(() -> MessageSender.sendReactionRemoval(context,
|
||||
messageRecord.getId(),
|
||||
messageRecord.isMms(),
|
||||
oldRecord));
|
||||
} else {
|
||||
reactionOverlay.hideAllButMask();
|
||||
reactionDelegate.hideAllButMask();
|
||||
|
||||
ReactWithAnyEmojiBottomSheetDialogFragment.createForMessageRecord(messageRecord, reactWithAnyEmojiStartPage)
|
||||
.show(getSupportFragmentManager(), "BOTTOM");
|
||||
|
@ -2254,7 +2256,7 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
|||
|
||||
@Override
|
||||
public void onReactWithAnyEmojiDialogDismissed() {
|
||||
reactionOverlay.hideMask();
|
||||
reactionDelegate.hideMask();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -3128,7 +3130,7 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
|||
|
||||
@Override
|
||||
public void onReactionsDialogDismissed() {
|
||||
reactionOverlay.hideMask();
|
||||
reactionDelegate.hideMask();
|
||||
}
|
||||
|
||||
// Listeners
|
||||
|
@ -3359,14 +3361,14 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
|||
@NonNull Toolbar.OnMenuItemClickListener toolbarListener,
|
||||
@NonNull ConversationReactionOverlay.OnHideListener onHideListener)
|
||||
{
|
||||
reactionOverlay.setOnToolbarItemClickedListener(toolbarListener);
|
||||
reactionOverlay.setOnHideListener(onHideListener);
|
||||
reactionOverlay.show(this, maskTarget, recipient.get(), messageRecord, inputAreaHeight());
|
||||
reactionDelegate.setOnToolbarItemClickedListener(toolbarListener);
|
||||
reactionDelegate.setOnHideListener(onHideListener);
|
||||
reactionDelegate.show(this, maskTarget, recipient.get(), messageRecord, inputAreaHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onListVerticalTranslationChanged(float translationY) {
|
||||
reactionOverlay.setListVerticalTranslation(translationY);
|
||||
reactionDelegate.setListVerticalTranslation(translationY);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -3386,22 +3388,22 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
|||
|
||||
@Override
|
||||
public void handleReactionDetails(@NonNull View maskTarget) {
|
||||
reactionOverlay.showMask(maskTarget, titleView.getMeasuredHeight(), inputAreaHeight());
|
||||
reactionDelegate.showMask(maskTarget, titleView.getMeasuredHeight(), inputAreaHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCursorChanged() {
|
||||
if (!reactionOverlay.isShowing()) {
|
||||
if (!reactionDelegate.isShowing()) {
|
||||
return;
|
||||
}
|
||||
|
||||
SimpleTask.run(() -> {
|
||||
//noinspection CodeBlock2Expr
|
||||
return DatabaseFactory.getMmsSmsDatabase(this)
|
||||
.checkMessageExists(reactionOverlay.getMessageRecord());
|
||||
.checkMessageExists(reactionDelegate.getMessageRecord());
|
||||
}, messageExists -> {
|
||||
if (!messageExists) {
|
||||
reactionOverlay.hide();
|
||||
reactionDelegate.hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
package org.thoughtcrime.securesms.conversation;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.graphics.PointF;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.views.Stub;
|
||||
|
||||
/**
|
||||
* Delegate class that mimics the ConversationReactionOverlay public API
|
||||
*
|
||||
* This allows us to properly stub out the ConversationReactionOverlay View class while still
|
||||
* respecting listeners and other positional information that can be set BEFORE we want to actually
|
||||
* resolve the view.
|
||||
*/
|
||||
final class ConversationReactionDelegate {
|
||||
|
||||
private final Stub<ConversationReactionOverlay> overlayStub;
|
||||
private final PointF lastSeenDownPoint = new PointF();
|
||||
|
||||
private ConversationReactionOverlay.OnReactionSelectedListener onReactionSelectedListener;
|
||||
private Toolbar.OnMenuItemClickListener onToolbarItemClickedListener;
|
||||
private ConversationReactionOverlay.OnHideListener onHideListener;
|
||||
private float translationY;
|
||||
|
||||
ConversationReactionDelegate(@NonNull Stub<ConversationReactionOverlay> overlayStub) {
|
||||
this.overlayStub = overlayStub;
|
||||
}
|
||||
|
||||
boolean isShowing() {
|
||||
return overlayStub.resolved() && overlayStub.get().isShowing();
|
||||
}
|
||||
|
||||
void show(@NonNull Activity activity,
|
||||
@NonNull View maskTarget,
|
||||
@NonNull Recipient conversationRecipient,
|
||||
@NonNull MessageRecord messageRecord,
|
||||
int maskPaddingBottom)
|
||||
{
|
||||
resolveOverlay().show(activity, maskTarget, conversationRecipient, messageRecord, maskPaddingBottom, lastSeenDownPoint);
|
||||
}
|
||||
|
||||
void showMask(@NonNull View maskTarget, int maskPaddingTop, int maskPaddingBottom) {
|
||||
resolveOverlay().showMask(maskTarget, maskPaddingTop, maskPaddingBottom);
|
||||
}
|
||||
|
||||
void hide() {
|
||||
overlayStub.get().hide();
|
||||
}
|
||||
|
||||
void hideAllButMask() {
|
||||
overlayStub.get().hideAllButMask();
|
||||
}
|
||||
|
||||
void hideMask() {
|
||||
overlayStub.get().hideMask();
|
||||
}
|
||||
|
||||
void setOnReactionSelectedListener(@NonNull ConversationReactionOverlay.OnReactionSelectedListener onReactionSelectedListener) {
|
||||
this.onReactionSelectedListener = onReactionSelectedListener;
|
||||
|
||||
if (overlayStub.resolved()) {
|
||||
overlayStub.get().setOnReactionSelectedListener(onReactionSelectedListener);
|
||||
}
|
||||
}
|
||||
|
||||
void setOnToolbarItemClickedListener(@NonNull Toolbar.OnMenuItemClickListener onToolbarItemClickedListener) {
|
||||
this.onToolbarItemClickedListener = onToolbarItemClickedListener;
|
||||
|
||||
if (overlayStub.resolved()) {
|
||||
overlayStub.get().setOnToolbarItemClickedListener(onToolbarItemClickedListener);
|
||||
}
|
||||
}
|
||||
|
||||
void setOnHideListener(@NonNull ConversationReactionOverlay.OnHideListener onHideListener) {
|
||||
this.onHideListener = onHideListener;
|
||||
|
||||
if (overlayStub.resolved()) {
|
||||
overlayStub.get().setOnHideListener(onHideListener);
|
||||
}
|
||||
}
|
||||
|
||||
void setListVerticalTranslation(float translationY) {
|
||||
this.translationY = translationY;
|
||||
|
||||
if (overlayStub.resolved()) {
|
||||
overlayStub.get().setListVerticalTranslation(translationY);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull MessageRecord getMessageRecord() {
|
||||
if (!overlayStub.resolved()) {
|
||||
throw new IllegalStateException("Cannot call getMessageRecord right now.");
|
||||
}
|
||||
|
||||
return overlayStub.get().getMessageRecord();
|
||||
}
|
||||
|
||||
boolean applyTouchEvent(@NonNull MotionEvent motionEvent) {
|
||||
if (!overlayStub.resolved() || !overlayStub.get().isShowing()) {
|
||||
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
lastSeenDownPoint.set(motionEvent.getX(), motionEvent.getY());
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return overlayStub.get().applyTouchEvent(motionEvent);
|
||||
}
|
||||
}
|
||||
|
||||
private @NonNull ConversationReactionOverlay resolveOverlay() {
|
||||
ConversationReactionOverlay overlay = overlayStub.get();
|
||||
|
||||
overlay.setListVerticalTranslation(translationY);
|
||||
overlay.setOnHideListener(onHideListener);
|
||||
overlay.setOnToolbarItemClickedListener(onToolbarItemClickedListener);
|
||||
overlay.setOnReactionSelectedListener(onReactionSelectedListener);
|
||||
|
||||
return overlay;
|
||||
}
|
||||
}
|
|
@ -56,7 +56,6 @@ public final class ConversationReactionOverlay extends RelativeLayout {
|
|||
private final Boundary horizontalEmojiBoundary = new Boundary();
|
||||
private final Boundary verticalScrubBoundary = new Boundary();
|
||||
private final PointF deadzoneTouchPoint = new PointF();
|
||||
private final PointF lastSeenDownPoint = new PointF();
|
||||
|
||||
private Activity activity;
|
||||
private Recipient conversationRecipient;
|
||||
|
@ -149,7 +148,8 @@ public final class ConversationReactionOverlay extends RelativeLayout {
|
|||
@NonNull View maskTarget,
|
||||
@NonNull Recipient conversationRecipient,
|
||||
@NonNull MessageRecord messageRecord,
|
||||
int maskPaddingBottom)
|
||||
int maskPaddingBottom,
|
||||
@NonNull PointF lastSeenDownPoint)
|
||||
{
|
||||
|
||||
if (overlayState != OverlayState.HIDDEN) {
|
||||
|
@ -292,10 +292,7 @@ public final class ConversationReactionOverlay extends RelativeLayout {
|
|||
|
||||
public boolean applyTouchEvent(@NonNull MotionEvent motionEvent) {
|
||||
if (!isShowing()) {
|
||||
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
lastSeenDownPoint.set(motionEvent.getX(), motionEvent.getY());
|
||||
}
|
||||
return false;
|
||||
throw new IllegalStateException("Touch events should only be propagated to this method if we are displaying the scrubber.");
|
||||
}
|
||||
|
||||
if ((motionEvent.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) != 0) {
|
||||
|
|
|
@ -221,5 +221,15 @@
|
|||
|
||||
</org.thoughtcrime.securesms.components.InputAwareLayout>
|
||||
|
||||
<include layout="@layout/conversation_reaction_scrubber" />
|
||||
<ViewStub
|
||||
android:id="@+id/conversation_reaction_scrubber_stub"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintTop_toTopOf="@+id/status_bar_guideline"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/navigation_bar_guideline"
|
||||
app:layout_constraintStart_toStartOf="@+id/parent_start_guideline"
|
||||
app:layout_constraintEnd_toEndOf="@+id/parent_end_guideline"
|
||||
android:inflatedId="@+id/conversation_reaction_scrubber"
|
||||
android:layout="@layout/conversation_reaction_scrubber" />
|
||||
|
||||
</org.thoughtcrime.securesms.components.InsetAwareConstraintLayout>
|
||||
|
|
Loading…
Add table
Reference in a new issue