diff --git a/AndroidManifest.xml b/AndroidManifest.xml index dc801ddc5..e5bfbf588 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/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 7d07bd322..95c7e41ff 100644 --- a/src/org/thoughtcrime/securesms/ConversationActivity.java +++ b/src/org/thoughtcrime/securesms/ConversationActivity.java @@ -917,13 +917,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 120785591..bb8b69947 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 77ff021a7..30a5c7fb3 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 57488296f..79c857a74 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/emoji/EmojiProvider.java b/src/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java index cb3c4581f..b89577660 100644 --- a/src/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java +++ b/src/org/thoughtcrime/securesms/components/emoji/EmojiProvider.java @@ -231,17 +231,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/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(); } 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 0f74726d4..961f80874 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; @@ -50,7 +45,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; @@ -61,7 +55,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; @@ -81,27 +74,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); } } @@ -143,40 +126,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;