From 5c930baa0dd70f4eb919288cf69675dd1a11cf12 Mon Sep 17 00:00:00 2001 From: bjoern Date: Fri, 22 Mar 2024 15:57:28 +0100 Subject: [PATCH 1/2] remove dead code (#2981) * minSdkVersion is 16, remove checks that are always true or false * VideoView was used for SDK<16 only --- .../securesms/BaseActionBarActivity.java | 4 +- .../thoughtcrime/securesms/BaseActivity.java | 4 +- .../securesms/ConversationActivity.java | 7 --- .../securesms/ConversationFragment.java | 1 - .../securesms/MediaPreviewActivity.java | 5 +- .../securesms/audio/AudioCodec.java | 3 - .../securesms/audio/AudioRecorder.java | 3 - .../components/AttachmentTypeSelector.java | 5 -- .../securesms/components/AudioView.java | 4 +- .../securesms/components/InputPanel.java | 5 -- .../components/RepeatableImageKey.java | 10 +--- .../components/camera/CameraView.java | 18 +++--- .../camera/QuickAttachmentDrawer.java | 4 -- .../components/emoji/EmojiProvider.java | 4 +- .../securesms/connect/KeepAliveService.java | 4 +- .../thoughtcrime/securesms/util/ViewUtil.java | 36 ++---------- .../securesms/video/VideoPlayer.java | 57 +------------------ 17 files changed, 22 insertions(+), 152 deletions(-) diff --git a/src/org/thoughtcrime/securesms/BaseActionBarActivity.java b/src/org/thoughtcrime/securesms/BaseActionBarActivity.java index 6297cd58c..3177e9498 100644 --- a/src/org/thoughtcrime/securesms/BaseActionBarActivity.java +++ b/src/org/thoughtcrime/securesms/BaseActionBarActivity.java @@ -75,9 +75,7 @@ public abstract class BaseActionBarActivity extends AppCompatActivity { } private void initializeScreenshotSecurity() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH && - Prefs.isScreenSecurityEnabled(this)) - { + if (Prefs.isScreenSecurityEnabled(this)) { getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE); } } diff --git a/src/org/thoughtcrime/securesms/BaseActivity.java b/src/org/thoughtcrime/securesms/BaseActivity.java index 7dee2e786..319d3d56c 100644 --- a/src/org/thoughtcrime/securesms/BaseActivity.java +++ b/src/org/thoughtcrime/securesms/BaseActivity.java @@ -23,8 +23,6 @@ public abstract class BaseActivity extends FragmentActivity { } public static boolean isMenuWorkaroundRequired() { - return VERSION.SDK_INT < VERSION_CODES.KITKAT && - VERSION.SDK_INT > VERSION_CODES.GINGERBREAD_MR1 && - ("LGE".equalsIgnoreCase(Build.MANUFACTURER) || "E6710".equalsIgnoreCase(Build.DEVICE)); + return VERSION.SDK_INT < VERSION_CODES.KITKAT && ("LGE".equalsIgnoreCase(Build.MANUFACTURER) || "E6710".equalsIgnoreCase(Build.DEVICE)); } } diff --git a/src/org/thoughtcrime/securesms/ConversationActivity.java b/src/org/thoughtcrime/securesms/ConversationActivity.java index 84247f944..1eba00fae 100644 --- a/src/org/thoughtcrime/securesms/ConversationActivity.java +++ b/src/org/thoughtcrime/securesms/ConversationActivity.java @@ -923,13 +923,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity recipient = new Recipient(this, dcChat); glideRequests = GlideApp.with(this); - - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { - LinearLayout conversationContainer = ViewUtil.findById(this, R.id.conversation_container); - conversationContainer.setClipChildren(true); - conversationContainer.setClipToPadding(true); - } - setComposePanelVisibility(); initializeContactRequest(); } diff --git a/src/org/thoughtcrime/securesms/ConversationFragment.java b/src/org/thoughtcrime/securesms/ConversationFragment.java index 0a0a0376b..74a101416 100644 --- a/src/org/thoughtcrime/securesms/ConversationFragment.java +++ b/src/org/thoughtcrime/securesms/ConversationFragment.java @@ -138,7 +138,6 @@ public class ConversationFragment extends MessageSelectorFragment }, 60 * 1000, 60 * 1000); } - @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN) @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle bundle) { final View view = inflater.inflate(R.layout.conversation_fragment, container, false); diff --git a/src/org/thoughtcrime/securesms/MediaPreviewActivity.java b/src/org/thoughtcrime/securesms/MediaPreviewActivity.java index 664f878e8..db387fa7a 100644 --- a/src/org/thoughtcrime/securesms/MediaPreviewActivity.java +++ b/src/org/thoughtcrime/securesms/MediaPreviewActivity.java @@ -142,11 +142,8 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity Permissions.onRequestPermissionsResult(this, requestCode, permissions, grantResults); } - @TargetApi(VERSION_CODES.JELLY_BEAN) private void setFullscreenIfPossible() { - if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) { - getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN); - } + getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN); } @Override diff --git a/src/org/thoughtcrime/securesms/audio/AudioCodec.java b/src/org/thoughtcrime/securesms/audio/AudioCodec.java index 6c585c481..4bf7910b6 100644 --- a/src/org/thoughtcrime/securesms/audio/AudioCodec.java +++ b/src/org/thoughtcrime/securesms/audio/AudioCodec.java @@ -1,6 +1,5 @@ package org.thoughtcrime.securesms.audio; -import android.annotation.TargetApi; import android.content.Context; import android.media.AudioFormat; import android.media.AudioRecord; @@ -8,7 +7,6 @@ import android.media.MediaCodec; import android.media.MediaCodecInfo; import android.media.MediaFormat; import android.media.MediaRecorder; -import android.os.Build; import android.util.Log; import org.thoughtcrime.securesms.util.Prefs; @@ -18,7 +16,6 @@ import java.io.IOException; import java.io.OutputStream; import java.nio.ByteBuffer; -@TargetApi(Build.VERSION_CODES.JELLY_BEAN) public class AudioCodec { private static final String TAG = AudioCodec.class.getSimpleName(); diff --git a/src/org/thoughtcrime/securesms/audio/AudioRecorder.java b/src/org/thoughtcrime/securesms/audio/AudioRecorder.java index 776888bfb..826511012 100644 --- a/src/org/thoughtcrime/securesms/audio/AudioRecorder.java +++ b/src/org/thoughtcrime/securesms/audio/AudioRecorder.java @@ -1,9 +1,7 @@ package org.thoughtcrime.securesms.audio; -import android.annotation.TargetApi; import android.content.Context; import android.net.Uri; -import android.os.Build; import android.os.ParcelFileDescriptor; import androidx.annotation.NonNull; import android.util.Log; @@ -20,7 +18,6 @@ import org.thoughtcrime.securesms.util.Util; import java.io.IOException; import java.util.concurrent.ExecutorService; -@TargetApi(Build.VERSION_CODES.JELLY_BEAN) public class AudioRecorder { private static final String TAG = AudioRecorder.class.getSimpleName(); diff --git a/src/org/thoughtcrime/securesms/components/AttachmentTypeSelector.java b/src/org/thoughtcrime/securesms/components/AttachmentTypeSelector.java index 930521977..1312615ab 100644 --- a/src/org/thoughtcrime/securesms/components/AttachmentTypeSelector.java +++ b/src/org/thoughtcrime/securesms/components/AttachmentTypeSelector.java @@ -1,6 +1,5 @@ package org.thoughtcrime.securesms.components; -import android.Manifest; import android.animation.Animator; import android.annotation.TargetApi; import android.app.Activity; @@ -96,10 +95,6 @@ public class AttachmentTypeSelector extends PopupWindow { setLocationButtonImage(context); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { - ViewUtil.findById(layout, R.id.location_linear_layout).setVisibility(View.INVISIBLE); - } - setContentView(layout); setWidth(LinearLayout.LayoutParams.MATCH_PARENT); setHeight(LinearLayout.LayoutParams.WRAP_CONTENT); diff --git a/src/org/thoughtcrime/securesms/components/AudioView.java b/src/org/thoughtcrime/securesms/components/AudioView.java index e99c19dcc..c04f11d53 100644 --- a/src/org/thoughtcrime/securesms/components/AudioView.java +++ b/src/org/thoughtcrime/securesms/components/AudioView.java @@ -203,9 +203,7 @@ public class AudioView extends FrameLayout implements AudioSlidePlayer.Listener this.seekBar.getProgressDrawable().setColorFilter(foregroundTint, PorterDuff.Mode.SRC_IN); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - this.seekBar.getThumb().setColorFilter(foregroundTint, PorterDuff.Mode.SRC_IN); - } + this.seekBar.getThumb().setColorFilter(foregroundTint, PorterDuff.Mode.SRC_IN); } public void getSeekBarGlobalVisibleRect(@NonNull Rect rect) { diff --git a/src/org/thoughtcrime/securesms/components/InputPanel.java b/src/org/thoughtcrime/securesms/components/InputPanel.java index a466a2b45..902aaca88 100644 --- a/src/org/thoughtcrime/securesms/components/InputPanel.java +++ b/src/org/thoughtcrime/securesms/components/InputPanel.java @@ -106,11 +106,6 @@ public class InputPanel extends ConstraintLayout this.recordLockCancel.setOnClickListener(v -> microphoneRecorderView.cancelAction()); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { - this.microphoneRecorderView.setVisibility(View.GONE); - this.microphoneRecorderView.setClickable(false); - } - if (Prefs.isSystemEmojiPreferred(getContext())) { mediaKeyboard.setVisibility(View.GONE); emojiVisible = false; diff --git a/src/org/thoughtcrime/securesms/components/RepeatableImageKey.java b/src/org/thoughtcrime/securesms/components/RepeatableImageKey.java index 48e071c94..7b101f56b 100644 --- a/src/org/thoughtcrime/securesms/components/RepeatableImageKey.java +++ b/src/org/thoughtcrime/securesms/components/RepeatableImageKey.java @@ -58,13 +58,10 @@ public class RepeatableImageKey extends ImageButton { } private class Repeater implements Runnable { - @TargetApi(VERSION_CODES.HONEYCOMB_MR1) @Override public void run() { notifyListener(); - postDelayed(this, VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB_MR1 - ? ViewConfiguration.getKeyRepeatDelay() - : 50); + postDelayed(this, ViewConfiguration.getKeyRepeatDelay()); } } @@ -75,14 +72,11 @@ public class RepeatableImageKey extends ImageButton { this.repeater = new Repeater(); } - @TargetApi(VERSION_CODES.HONEYCOMB_MR1) @Override public boolean onTouch(View view, MotionEvent motionEvent) { switch (motionEvent.getAction()) { case MotionEvent.ACTION_DOWN: - view.postDelayed(repeater, VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB_MR1 - ? ViewConfiguration.getKeyRepeatTimeout() - : ViewConfiguration.getLongPressTimeout()); + view.postDelayed(repeater, ViewConfiguration.getKeyRepeatTimeout()); performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); return false; case MotionEvent.ACTION_CANCEL: diff --git a/src/org/thoughtcrime/securesms/components/camera/CameraView.java b/src/org/thoughtcrime/securesms/components/camera/CameraView.java index d5ce2efa0..e61283186 100644 --- a/src/org/thoughtcrime/securesms/components/camera/CameraView.java +++ b/src/org/thoughtcrime/securesms/components/camera/CameraView.java @@ -94,7 +94,6 @@ public class CameraView extends ViewGroup { addView(surface); } - @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) public void onResume() { if (state != State.PAUSED) return; state = State.RESUMED; @@ -272,19 +271,16 @@ public class CameraView extends ViewGroup { Prefs.setDirectCaptureCameraId(getContext(), cameraId); } } - - @TargetApi(14) + private void onCameraReady(final @NonNull Camera camera) { final Parameters parameters = camera.getParameters(); - if (VERSION.SDK_INT >= 14) { - parameters.setRecordingHint(true); - final List focusModes = parameters.getSupportedFocusModes(); - if (focusModes.contains(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { - parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); - } else if (focusModes.contains(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) { - parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); - } + parameters.setRecordingHint(true); + final List focusModes = parameters.getSupportedFocusModes(); + if (focusModes.contains(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { + parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); + } else if (focusModes.contains(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) { + parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); } displayOrientation = CameraUtils.getCameraDisplayOrientation(getActivity(), getCameraInfo()); diff --git a/src/org/thoughtcrime/securesms/components/camera/QuickAttachmentDrawer.java b/src/org/thoughtcrime/securesms/components/camera/QuickAttachmentDrawer.java index 96e7f5e2a..0c0be7909 100644 --- a/src/org/thoughtcrime/securesms/components/camera/QuickAttachmentDrawer.java +++ b/src/org/thoughtcrime/securesms/components/camera/QuickAttachmentDrawer.java @@ -489,10 +489,6 @@ public class QuickAttachmentDrawer extends ViewGroup implements InputView, Camer } private int computeCameraTopPosition(int slideOffset) { - if (VERSION.SDK_INT < VERSION_CODES.ICE_CREAM_SANDWICH) { - return getPaddingTop(); - } - final int baseCameraTop = (cameraView.getMeasuredHeight() - halfExpandedHeight) / 2; final int baseOffset = getMeasuredHeight() - slideOffset - baseCameraTop; final float slop = Util.clamp((float)(slideOffset - halfExpandedHeight) / (getMeasuredHeight() - halfExpandedHeight), diff --git a/src/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java b/src/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java index cd9c112b4..317bb2fdb 100644 --- a/src/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java +++ b/src/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java @@ -209,17 +209,15 @@ public class EmojiProvider { paint); } - @TargetApi(VERSION_CODES.HONEYCOMB_MR1) public void setBitmap(Bitmap bitmap) { setBitmap(bitmap, false); } - @TargetApi(VERSION_CODES.HONEYCOMB_MR1) public void setBitmap(Bitmap bitmap, boolean background) { if (!background) { Util.assertMainThread(); } - if (VERSION.SDK_INT < VERSION_CODES.HONEYCOMB_MR1 || bmp == null || !bmp.sameAs(bitmap)) { + if (bmp == null || !bmp.sameAs(bitmap)) { bmp = bitmap; invalidateSelf(); } diff --git a/src/org/thoughtcrime/securesms/connect/KeepAliveService.java b/src/org/thoughtcrime/securesms/connect/KeepAliveService.java index ba816bf82..0d9b6b7cc 100644 --- a/src/org/thoughtcrime/securesms/connect/KeepAliveService.java +++ b/src/org/thoughtcrime/securesms/connect/KeepAliveService.java @@ -100,9 +100,7 @@ public class KeepAliveService extends Service { builder.setContentTitle(getString(R.string.app_name)); builder.setContentText(getString(R.string.notify_background_connection_enabled)); - if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN ) { - builder.setPriority(NotificationCompat.PRIORITY_MIN); - } + builder.setPriority(NotificationCompat.PRIORITY_MIN); builder.setWhen(0); builder.setContentIntent(contentIntent); builder.setSmallIcon(R.drawable.notification_permanent); diff --git a/src/org/thoughtcrime/securesms/util/ViewUtil.java b/src/org/thoughtcrime/securesms/util/ViewUtil.java index c9f67e73d..a5b68257d 100644 --- a/src/org/thoughtcrime/securesms/util/ViewUtil.java +++ b/src/org/thoughtcrime/securesms/util/ViewUtil.java @@ -49,47 +49,19 @@ import org.thoughtcrime.securesms.util.views.Stub; public class ViewUtil { @SuppressWarnings("deprecation") public static void setBackground(final @NonNull View v, final @Nullable Drawable drawable) { - if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) { - v.setBackground(drawable); - } else { - v.setBackgroundDrawable(drawable); - } - } - - public static void setY(final @NonNull View v, final int y) { - if (VERSION.SDK_INT >= 11) { - ViewCompat.setY(v, y); - } else { - ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams)v.getLayoutParams(); - params.topMargin = y; - v.setLayoutParams(params); - } + v.setBackground(drawable); } public static float getY(final @NonNull View v) { - if (VERSION.SDK_INT >= 11) { - return ViewCompat.getY(v); - } else { - return ((ViewGroup.MarginLayoutParams)v.getLayoutParams()).topMargin; - } + return ViewCompat.getY(v); } public static void setX(final @NonNull View v, final int x) { - if (VERSION.SDK_INT >= 11) { - ViewCompat.setX(v, x); - } else { - ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams)v.getLayoutParams(); - params.leftMargin = x; - v.setLayoutParams(params); - } + ViewCompat.setX(v, x); } public static float getX(final @NonNull View v) { - if (VERSION.SDK_INT >= 11) { - return ViewCompat.getX(v); - } else { - return ((LayoutParams)v.getLayoutParams()).leftMargin; - } + return ViewCompat.getX(v); } public static void swapChildInPlace(ViewGroup parent, View toRemove, View toAdd, int defaultIndex) { diff --git a/src/org/thoughtcrime/securesms/video/VideoPlayer.java b/src/org/thoughtcrime/securesms/video/VideoPlayer.java index 7fddf7768..75b5f0d41 100644 --- a/src/org/thoughtcrime/securesms/video/VideoPlayer.java +++ b/src/org/thoughtcrime/securesms/video/VideoPlayer.java @@ -17,17 +17,12 @@ package org.thoughtcrime.securesms.video; import android.content.Context; -import android.os.Build; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import android.util.AttributeSet; -import android.util.Log; import android.view.Window; import android.view.WindowManager; import android.widget.FrameLayout; -import android.widget.MediaController; -import android.widget.Toast; -import android.widget.VideoView; import com.google.android.exoplayer2.DefaultLoadControl; import com.google.android.exoplayer2.ExoPlayerFactory; @@ -49,7 +44,6 @@ import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.attachments.AttachmentServer; -import org.thoughtcrime.securesms.mms.PartAuthority; import org.thoughtcrime.securesms.mms.VideoSlide; import org.thoughtcrime.securesms.util.ViewUtil; import org.thoughtcrime.securesms.video.exo.AttachmentDataSourceFactory; @@ -60,7 +54,6 @@ public class VideoPlayer extends FrameLayout { private static final String TAG = VideoPlayer.class.getName(); - @Nullable private final VideoView videoView; @Nullable private final SimpleExoPlayerView exoView; @Nullable private SimpleExoPlayer exoPlayer; @@ -80,27 +73,17 @@ public class VideoPlayer extends FrameLayout { inflate(context, R.layout.video_player, this); - if (Build.VERSION.SDK_INT >= 16) { - this.exoView = ViewUtil.findById(this, R.id.video_view); - this.videoView = null; - } else { - this.videoView = ViewUtil.findById(this, R.id.video_view); - this.exoView = null; - initializeVideoViewControls(videoView); - } + this.exoView = ViewUtil.findById(this, R.id.video_view); } public void setVideoSource(@NonNull VideoSlide videoSource, boolean autoplay) throws IOException { - if (Build.VERSION.SDK_INT >= 16) setExoViewSource(videoSource, autoplay); - else setVideoViewSource(videoSource, autoplay); + setExoViewSource(videoSource, autoplay); } public void pause() { - if (this.attachmentServer != null && this.videoView != null) { - this.videoView.stopPlayback(); - } else if (this.exoPlayer != null) { + if (this.exoPlayer != null) { this.exoPlayer.setPlayWhenReady(false); } } @@ -142,40 +125,6 @@ public class VideoPlayer extends FrameLayout { exoPlayer.setPlayWhenReady(autoplay); } - private void setVideoViewSource(@NonNull VideoSlide videoSource, boolean autoplay) - throws IOException - { - if (this.attachmentServer != null) { - this.attachmentServer.stop(); - } - - if (videoSource.getUri() != null && PartAuthority.isLocalUri(videoSource.getUri())) { - Log.w(TAG, "Starting video attachment server for part provider Uri..."); - this.attachmentServer = new AttachmentServer(getContext(), videoSource.asAttachment()); - this.attachmentServer.start(); - - //noinspection ConstantConditions - this.videoView.setVideoURI(this.attachmentServer.getUri()); - } else if (videoSource.getUri() != null) { - Log.w(TAG, "Playing video directly from non-local Uri..."); - //noinspection ConstantConditions - this.videoView.setVideoURI(videoSource.getUri()); - } else { - Toast.makeText(getContext(), getContext().getString(R.string.error), Toast.LENGTH_LONG).show(); - return; - } - - if (autoplay) this.videoView.start(); - } - - private void initializeVideoViewControls(@NonNull VideoView videoView) { - MediaController mediaController = new MediaController(getContext()); - mediaController.setAnchorView(videoView); - mediaController.setMediaPlayer(videoView); - - videoView.setMediaController(mediaController); - } - private static class ExoPlayerListener implements Player.EventListener { private final Window window; From 2faf7a640f7da03aa497beecb1d9e85a03c21c51 Mon Sep 17 00:00:00 2001 From: bjoern Date: Wed, 27 Mar 2024 17:33:13 +0100 Subject: [PATCH 2/2] react with any emoji (#2979) * add button to select any reaction * add emojipicker to build.gradle and manifest * fix build error * open reaction picker and send any reaction * use RelativeLayout as parent for EmojiPickerView * dismiss AlertDialog on emoji-selection * reduce columns to 8 like on iOS * disable "more reactions" button in android < 5 * show selected reactions instead of '...', this is what whatsapp, signal are doing * make '...' a bit less bold in light mode --------- Co-authored-by: adbenitez --- AndroidManifest.xml | 3 + build.gradle | 2 + res/layout/conversation_fragment.xml | 7 ++ res/layout/reaction_picker.xml | 14 ++++ .../securesms/reactions/AddReactionView.java | 68 ++++++++++++++++--- 5 files changed, 86 insertions(+), 8 deletions(-) create mode 100644 res/layout/reaction_picker.xml diff --git a/AndroidManifest.xml b/AndroidManifest.xml index e989c7d9b..d6498bbe4 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -40,6 +40,9 @@ + + + + diff --git a/res/layout/reaction_picker.xml b/res/layout/reaction_picker.xml new file mode 100644 index 000000000..4380b8173 --- /dev/null +++ b/res/layout/reaction_picker.xml @@ -0,0 +1,14 @@ + + + + + diff --git a/src/org/thoughtcrime/securesms/reactions/AddReactionView.java b/src/org/thoughtcrime/securesms/reactions/AddReactionView.java index 65c0912ed..d1464f434 100644 --- a/src/org/thoughtcrime/securesms/reactions/AddReactionView.java +++ b/src/org/thoughtcrime/securesms/reactions/AddReactionView.java @@ -1,11 +1,14 @@ package org.thoughtcrime.securesms.reactions; import android.content.Context; +import android.os.Build; import android.util.AttributeSet; import android.view.View; import android.widget.LinearLayout; +import androidx.appcompat.app.AlertDialog; import androidx.core.content.ContextCompat; +import androidx.emoji2.emojipicker.EmojiPickerView; import com.b44t.messenger.DcContact; import com.b44t.messenger.DcContext; @@ -16,13 +19,14 @@ import com.b44t.messenger.rpc.Rpc; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.components.emoji.EmojiTextView; import org.thoughtcrime.securesms.connect.DcHelper; -import org.thoughtcrime.securesms.util.Prefs; import org.thoughtcrime.securesms.util.ViewUtil; import java.util.Map; public class AddReactionView extends LinearLayout { private EmojiTextView [] defaultReactionViews; + private EmojiTextView anyReactionView; + private boolean anyReactionClearsReaction; private Context context; private DcContext dcContext; private Rpc rpc; @@ -51,7 +55,12 @@ public class AddReactionView extends LinearLayout { }; for (int i = 0; i < defaultReactionViews.length; i++) { final int ii = i; - defaultReactionViews[i].setOnClickListener(v -> reactionClicked(ii)); + defaultReactionViews[i].setOnClickListener(v -> defaultReactionClicked(ii)); + } + anyReactionView = findViewById(R.id.reaction_any); + anyReactionView.setOnClickListener(v -> anyReactionClicked()); + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + anyReactionView.setVisibility(View.GONE); // EmojiPickerView requires SDK 21 or newer } } } @@ -69,14 +78,26 @@ public class AddReactionView extends LinearLayout { this.listener = listener; final String existingReaction = getSelfReaction(); + boolean existingHilited = false; for (EmojiTextView defaultReactionView : defaultReactionViews) { if (defaultReactionView.getText().toString().equals(existingReaction)) { defaultReactionView.setBackground(ContextCompat.getDrawable(context, R.drawable.reaction_pill_background_selected)); + existingHilited = true; } else { defaultReactionView.setBackground(null); } } + if (existingReaction != null && !existingHilited) { + anyReactionView.setText(existingReaction); + anyReactionView.setBackground(ContextCompat.getDrawable(context, R.drawable.reaction_pill_background_selected)); + anyReactionClearsReaction = true; + } else { + anyReactionView.setText("•••"); + anyReactionView.setBackground(null); + anyReactionClearsReaction = false; + } + final int offset = (int)(this.getHeight() * 0.666); int x = (int)parentView.getX(); if (msgToReactTo.isOutgoing()) { @@ -117,17 +138,48 @@ public class AddReactionView extends LinearLayout { return result; } - private void reactionClicked(int i) { + private void defaultReactionClicked(int i) { + final String reaction = defaultReactionViews[i].getText().toString(); + sendReaction(reaction); + + if (listener != null) { + listener.onShallHide(); + } + } + + private void anyReactionClicked() { + if (anyReactionClearsReaction) { + sendReaction(null); + } else { + View pickerLayout = View.inflate(context, R.layout.reaction_picker, null); + + final AlertDialog alertDialog = new AlertDialog.Builder(context) + .setView(pickerLayout) + .setTitle(R.string.react) + .setPositiveButton(R.string.cancel, null) + .create(); + + EmojiPickerView pickerView = ViewUtil.findById(pickerLayout, R.id.emoji_picker); + pickerView.setOnEmojiPickedListener((it) -> { + sendReaction(it.getEmoji()); + alertDialog.dismiss(); + }); + + alertDialog.show(); + } + + if (listener != null) { + listener.onShallHide(); + } + } + + private void sendReaction(final String reaction) { try { - final String reaction = defaultReactionViews[i].getText().toString(); - if (reaction.equals(getSelfReaction())) { + if (reaction == null || reaction.equals(getSelfReaction())) { rpc.sendReaction(dcContext.getAccountId(), msgToReactTo.getId(), ""); } else { rpc.sendReaction(dcContext.getAccountId(), msgToReactTo.getId(), reaction); } - if (listener != null) { - listener.onShallHide(); - } } catch(Exception e) { e.printStackTrace(); }