Removing unrequired APi checks (#1620)

* Removing unrequired APi checks

* Bumping min sdk to 26 and further cleaning version checks

* More clean ups

* Removed unused class
This commit is contained in:
ThomasSession 2024-08-15 15:32:41 +10:00 committed by GitHub
parent 5a248da445
commit 93a28906fb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
58 changed files with 201 additions and 1165 deletions

View File

@ -291,10 +291,6 @@
android:name="org.thoughtcrime.securesms.scribbles.StickerSelectActivity" android:name="org.thoughtcrime.securesms.scribbles.StickerSelectActivity"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
android:theme="@style/Theme.Session.ForceDark" /> android:theme="@style/Theme.Session.ForceDark" />
<activity
android:name="com.theartofdev.edmodo.cropper.CropImageActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.AppCompat" />
<activity <activity
android:name="org.thoughtcrime.securesms.ShortcutLauncherActivity" android:name="org.thoughtcrime.securesms.ShortcutLauncherActivity"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"

View File

@ -4,12 +4,8 @@ import android.app.ActivityManager;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
import android.view.KeyEvent;
import org.session.libsession.utilities.TextSecurePreferences; import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsession.utilities.dynamiclanguage.DynamicLanguageActivityHelper; import org.session.libsession.utilities.dynamiclanguage.DynamicLanguageActivityHelper;

View File

@ -39,7 +39,9 @@ import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.view.ActionMode; import androidx.appcompat.view.ActionMode;
import androidx.appcompat.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter; import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.loader.app.LoaderManager; import androidx.loader.app.LoaderManager;
@ -421,11 +423,13 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity {
mode.getMenuInflater().inflate(R.menu.media_overview_context, menu); mode.getMenuInflater().inflate(R.menu.media_overview_context, menu);
mode.setTitle("1"); mode.setTitle("1");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { FragmentActivity activity = getActivity();
Window window = getActivity().getWindow(); if (activity == null) return false;
Window window = activity.getWindow();
originalStatusBarColor = window.getStatusBarColor(); originalStatusBarColor = window.getStatusBarColor();
window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar)); window.setStatusBarColor(ContextCompat.getColor(activity, R.color.action_mode_status_bar));
}
return true; return true;
} }
@ -455,11 +459,12 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity {
public void onDestroyActionMode(ActionMode mode) { public void onDestroyActionMode(ActionMode mode) {
actionMode = null; actionMode = null;
getListAdapter().clearSelection(); getListAdapter().clearSelection();
((MediaOverviewActivity) getActivity()).onExitMultiSelect();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { MediaOverviewActivity activity = ((MediaOverviewActivity) getActivity());
getActivity().getWindow().setStatusBarColor(originalStatusBarColor); if(activity == null) return;
}
activity.onExitMultiSelect();
activity.getWindow().setStatusBarColor(originalStatusBarColor);
} }
} }
} }

View File

@ -17,7 +17,6 @@
package org.thoughtcrime.securesms; package org.thoughtcrime.securesms;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.database.Cursor; import android.database.Cursor;
@ -26,7 +25,6 @@ import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build; import android.os.Build;
import android.os.Build.VERSION; import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
@ -57,6 +55,9 @@ import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager.widget.PagerAdapter; import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager; import androidx.viewpager.widget.ViewPager;
import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestManager;
import org.session.libsession.messaging.messages.control.DataExtractionNotification; import org.session.libsession.messaging.messages.control.DataExtractionNotification;
import org.session.libsession.messaging.sending_receiving.MessageSender; import org.session.libsession.messaging.sending_receiving.MessageSender;
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment; import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment;
@ -72,8 +73,6 @@ import org.thoughtcrime.securesms.database.loaders.PagingMediaLoader;
import org.thoughtcrime.securesms.database.model.MmsMessageRecord; import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
import org.thoughtcrime.securesms.mediapreview.MediaPreviewViewModel; import org.thoughtcrime.securesms.mediapreview.MediaPreviewViewModel;
import org.thoughtcrime.securesms.mediapreview.MediaRailAdapter; import org.thoughtcrime.securesms.mediapreview.MediaRailAdapter;
import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestManager;
import org.thoughtcrime.securesms.mms.Slide; import org.thoughtcrime.securesms.mms.Slide;
import org.thoughtcrime.securesms.permissions.Permissions; import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.util.AttachmentUtil; import org.thoughtcrime.securesms.util.AttachmentUtil;

View File

@ -1,22 +1,19 @@
package org.thoughtcrime.securesms.audio; package org.thoughtcrime.securesms.audio;
import android.annotation.TargetApi;
import android.media.AudioFormat; import android.media.AudioFormat;
import android.media.AudioRecord; import android.media.AudioRecord;
import android.media.MediaCodec; import android.media.MediaCodec;
import android.media.MediaCodecInfo; import android.media.MediaCodecInfo;
import android.media.MediaFormat; import android.media.MediaFormat;
import android.media.MediaRecorder; import android.media.MediaRecorder;
import android.os.Build;
import org.session.libsignal.utilities.Log;
import org.session.libsession.utilities.Util; import org.session.libsession.utilities.Util;
import org.session.libsignal.utilities.Log;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public class AudioCodec { public class AudioCodec {
private static final String TAG = AudioCodec.class.getSimpleName(); private static final String TAG = AudioCodec.class.getSimpleName();

View File

@ -46,7 +46,7 @@ public class AudioSlidePlayer implements SensorEventListener {
private final @NonNull Handler progressEventHandler; private final @NonNull Handler progressEventHandler;
private final @NonNull AudioManager audioManager; private final @NonNull AudioManager audioManager;
private final @NonNull SensorManager sensorManager; private final @NonNull SensorManager sensorManager;
private final @NonNull Sensor proximitySensor; private final Sensor proximitySensor;
private final @Nullable WakeLock wakeLock; private final @Nullable WakeLock wakeLock;
private @NonNull WeakReference<Listener> listener; private @NonNull WeakReference<Listener> listener;
@ -132,7 +132,9 @@ public class AudioSlidePlayer implements SensorEventListener {
mediaPlayer.seekTo((long) (mediaPlayer.getDuration() * progress)); mediaPlayer.seekTo((long) (mediaPlayer.getDuration() * progress));
} }
if(proximitySensor != null) {
sensorManager.registerListener(AudioSlidePlayer.this, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL); sensorManager.registerListener(AudioSlidePlayer.this, proximitySensor, SensorManager.SENSOR_DELAY_NORMAL);
}
setPlaying(AudioSlidePlayer.this); setPlaying(AudioSlidePlayer.this);
} }

View File

@ -2,15 +2,10 @@ package org.thoughtcrime.securesms.components;
import android.Manifest; import android.Manifest;
import android.animation.Animator; import android.animation.Animator;
import android.annotation.TargetApi;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.BitmapDrawable;
import android.net.Uri; import android.net.Uri;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.loader.app.LoaderManager;
import android.util.Pair; import android.util.Pair;
import android.view.Gravity; import android.view.Gravity;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -26,8 +21,12 @@ import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.PopupWindow; import android.widget.PopupWindow;
import org.thoughtcrime.securesms.permissions.Permissions; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.loader.app.LoaderManager;
import org.session.libsession.utilities.ViewUtil; import org.session.libsession.utilities.ViewUtil;
import org.thoughtcrime.securesms.permissions.Permissions;
import network.loki.messenger.R; import network.loki.messenger.R;
@ -126,15 +125,10 @@ public class AttachmentTypeSelector extends PopupWindow {
public void onGlobalLayout() { public void onGlobalLayout() {
getContentView().getViewTreeObserver().removeGlobalOnLayoutListener(this); getContentView().getViewTreeObserver().removeGlobalOnLayoutListener(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
animateWindowInCircular(anchor, getContentView()); animateWindowInCircular(anchor, getContentView());
} else {
animateWindowInTranslate(getContentView());
}
} }
}); });
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
animateButtonIn(imageButton, ANIMATION_DURATION / 2); animateButtonIn(imageButton, ANIMATION_DURATION / 2);
animateButtonIn(cameraButton, ANIMATION_DURATION / 2); animateButtonIn(cameraButton, ANIMATION_DURATION / 2);
@ -145,7 +139,6 @@ public class AttachmentTypeSelector extends PopupWindow {
animateButtonIn(contactButton, 0); animateButtonIn(contactButton, 0);
animateButtonIn(closeButton, 0); animateButtonIn(closeButton, 0);
} }
}
private void updateHeight() { private void updateHeight() {
int thresholdInDP = 120; int thresholdInDP = 120;
@ -159,11 +152,7 @@ public class AttachmentTypeSelector extends PopupWindow {
@Override @Override
public void dismiss() { public void dismiss() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
animateWindowOutCircular(currentAnchor, getContentView()); animateWindowOutCircular(currentAnchor, getContentView());
} else {
animateWindowOutTranslate(getContentView());
}
} }
public void setListener(@Nullable AttachmentClickedListener listener) { public void setListener(@Nullable AttachmentClickedListener listener) {
@ -182,7 +171,6 @@ public class AttachmentTypeSelector extends PopupWindow {
button.startAnimation(animation); button.startAnimation(animation);
} }
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void animateWindowInCircular(@Nullable View anchor, @NonNull View contentView) { private void animateWindowInCircular(@Nullable View anchor, @NonNull View contentView) {
Pair<Integer, Integer> coordinates = getClickOrigin(anchor, contentView); Pair<Integer, Integer> coordinates = getClickOrigin(anchor, contentView);
Animator animator = ViewAnimationUtils.createCircularReveal(contentView, Animator animator = ViewAnimationUtils.createCircularReveal(contentView,
@ -201,7 +189,6 @@ public class AttachmentTypeSelector extends PopupWindow {
getContentView().startAnimation(animation); getContentView().startAnimation(animation);
} }
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void animateWindowOutCircular(@Nullable View anchor, @NonNull View contentView) { private void animateWindowOutCircular(@Nullable View anchor, @NonNull View contentView) {
Pair<Integer, Integer> coordinates = getClickOrigin(anchor, contentView); Pair<Integer, Integer> coordinates = getClickOrigin(anchor, contentView);
Animator animator = ViewAnimationUtils.createCircularReveal(getContentView(), Animator animator = ViewAnimationUtils.createCircularReveal(getContentView(),

View File

@ -1,7 +1,6 @@
package org.thoughtcrime.securesms.components; package org.thoughtcrime.securesms.components;
import android.content.Context; import android.content.Context;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.text.InputType; import android.text.InputType;
import android.text.Spannable; import android.text.Spannable;
@ -16,15 +15,14 @@ import android.view.inputmethod.InputConnection;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.core.os.BuildCompat; import androidx.core.os.BuildCompat;
import androidx.core.view.inputmethod.EditorInfoCompat; import androidx.core.view.inputmethod.EditorInfoCompat;
import androidx.core.view.inputmethod.InputConnectionCompat; import androidx.core.view.inputmethod.InputConnectionCompat;
import androidx.core.view.inputmethod.InputContentInfoCompat; import androidx.core.view.inputmethod.InputContentInfoCompat;
import org.thoughtcrime.securesms.components.emoji.EmojiEditText;
import org.session.libsignal.utilities.Log;
import org.session.libsession.utilities.TextSecurePreferences; import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.components.emoji.EmojiEditText;
public class ComposeText extends EmojiEditText { public class ComposeText extends EmojiEditText {
@ -136,7 +134,6 @@ public class ComposeText extends EmojiEditText {
editorInfo.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION; editorInfo.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION;
} }
if (Build.VERSION.SDK_INT < 21) return inputConnection;
if (mediaListener == null) return inputConnection; if (mediaListener == null) return inputConnection;
if (inputConnection == null) return null; if (inputConnection == null) return null;
@ -154,7 +151,6 @@ public class ComposeText extends EmojiEditText {
} }
} }
@RequiresApi(api = Build.VERSION_CODES.HONEYCOMB_MR2)
private static class CommitContentListener implements InputConnectionCompat.OnCommitContentListener { private static class CommitContentListener implements InputConnectionCompat.OnCommitContentListener {
private static final String TAG = CommitContentListener.class.getSimpleName(); private static final String TAG = CommitContentListener.class.getSimpleName();

View File

@ -1,9 +1,7 @@
package org.thoughtcrime.securesms.components; package org.thoughtcrime.securesms.components;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.os.Build.VERSION_CODES;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View; import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
@ -27,7 +25,6 @@ public class ConversationItemAlertView extends LinearLayout {
initialize(attrs); initialize(attrs);
} }
@TargetApi(VERSION_CODES.HONEYCOMB)
public ConversationItemAlertView(final Context context, AttributeSet attrs, int defStyle) { public ConversationItemAlertView(final Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle); super(context, attrs, defStyle);
initialize(attrs); initialize(attrs);

View File

@ -1,9 +1,6 @@
package org.thoughtcrime.securesms.components; package org.thoughtcrime.securesms.components;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.os.Build;
import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.animation.AlphaAnimation; import android.view.animation.AlphaAnimation;
import android.view.animation.Animation; import android.view.animation.Animation;
@ -11,6 +8,8 @@ import android.view.animation.AnimationSet;
import android.view.animation.ScaleAnimation; import android.view.animation.ScaleAnimation;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
public class HidingLinearLayout extends LinearLayout { public class HidingLinearLayout extends LinearLayout {
public HidingLinearLayout(Context context) { public HidingLinearLayout(Context context) {
@ -21,7 +20,6 @@ public class HidingLinearLayout extends LinearLayout {
super(context, attrs); super(context, attrs);
} }
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public HidingLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) { public HidingLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr); super(context, attrs, defStyleAttr);
} }

View File

@ -1,13 +1,12 @@
package org.thoughtcrime.securesms.components; package org.thoughtcrime.securesms.components;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.net.Uri; import android.net.Uri;
import android.os.Build;
import androidx.annotation.NonNull;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import androidx.annotation.NonNull;
public class InputPanel extends LinearLayout { public class InputPanel extends LinearLayout {
public InputPanel(Context context) { public InputPanel(Context context) {
@ -18,7 +17,6 @@ public class InputPanel extends LinearLayout {
super(context, attrs); super(context, attrs);
} }
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public InputPanel(Context context, AttributeSet attrs, int defStyleAttr) { public InputPanel(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr); super(context, attrs, defStyleAttr);
} }

View File

@ -16,26 +16,25 @@
*/ */
package org.thoughtcrime.securesms.components; package org.thoughtcrime.securesms.components;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import androidx.appcompat.widget.LinearLayoutCompat;
import android.util.AttributeSet; import android.util.AttributeSet;
import org.session.libsignal.utilities.Log;
import android.view.Surface; import android.view.Surface;
import android.view.View; import android.view.View;
import network.loki.messenger.R; import androidx.appcompat.widget.LinearLayoutCompat;
import org.session.libsession.utilities.ServiceUtil; import org.session.libsession.utilities.ServiceUtil;
import org.session.libsession.utilities.Util; import org.session.libsession.utilities.Util;
import org.session.libsignal.utilities.Log;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import network.loki.messenger.R;
/** /**
* LinearLayout that, when a view container, will report back when it thinks a soft keyboard * LinearLayout that, when a view container, will report back when it thinks a soft keyboard
* has been opened and what its height would be. * has been opened and what its height would be.
@ -95,7 +94,7 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat {
} }
private void updateKeyboardState() { private void updateKeyboardState() {
if (viewInset == 0 && Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) viewInset = getViewInset(); if (viewInset == 0) viewInset = getViewInset();
getWindowVisibleDisplayFrame(rect); getWindowVisibleDisplayFrame(rect);
@ -118,7 +117,6 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat {
} }
} }
@TargetApi(VERSION_CODES.LOLLIPOP)
private int getViewInset() { private int getViewInset() {
try { try {
Field attachInfoField = View.class.getDeclaredField("mAttachInfo"); Field attachInfoField = View.class.getDeclaredField("mAttachInfo");

View File

@ -3,24 +3,24 @@ package org.thoughtcrime.securesms.components;
import android.content.Context; import android.content.Context;
import android.net.Uri; import android.net.Uri;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View; import android.view.View;
import android.view.Window; import android.view.Window;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import network.loki.messenger.R; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.bumptech.glide.RequestManager; import com.bumptech.glide.RequestManager;
import org.session.libsession.utilities.Stub;
import org.thoughtcrime.securesms.mms.VideoSlide; import org.thoughtcrime.securesms.mms.VideoSlide;
import org.thoughtcrime.securesms.video.VideoPlayer; import org.thoughtcrime.securesms.video.VideoPlayer;
import org.session.libsession.utilities.Stub;
import java.io.IOException; import java.io.IOException;
import network.loki.messenger.R;
public class MediaView extends FrameLayout { public class MediaView extends FrameLayout {
private ZoomingImageView imageView; private ZoomingImageView imageView;
@ -41,12 +41,6 @@ public class MediaView extends FrameLayout {
initialize(); initialize();
} }
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public MediaView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initialize();
}
private void initialize() { private void initialize() {
inflate(getContext(), R.layout.media_view, this); inflate(getContext(), R.layout.media_view, this);

View File

@ -1,19 +1,11 @@
package org.thoughtcrime.securesms.components; package org.thoughtcrime.securesms.components;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.provider.MediaStore; import android.provider.MediaStore;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.loader.app.LoaderManager;
import androidx.loader.content.Loader;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@ -21,16 +13,24 @@ import android.view.ViewGroup;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.ImageView; import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.loader.app.LoaderManager;
import androidx.loader.content.Loader;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.Key; import com.bumptech.glide.load.Key;
import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.signature.MediaStoreSignature; import com.bumptech.glide.signature.MediaStoreSignature;
import network.loki.messenger.R; import org.session.libsession.utilities.ViewUtil;
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter; import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
import org.thoughtcrime.securesms.database.loaders.RecentPhotosLoader; import org.thoughtcrime.securesms.database.loaders.RecentPhotosLoader;
import com.bumptech.glide.Glide;
import org.session.libsession.utilities.ViewUtil; import network.loki.messenger.R;
public class RecentPhotoViewRail extends FrameLayout implements LoaderManager.LoaderCallbacks<Cursor> { public class RecentPhotoViewRail extends FrameLayout implements LoaderManager.LoaderCallbacks<Cursor> {
@ -130,14 +130,12 @@ public class RecentPhotoViewRail extends FrameLayout implements LoaderManager.Lo
} }
@TargetApi(16)
@SuppressWarnings("SuspiciousNameCombination") @SuppressWarnings("SuspiciousNameCombination")
private String getWidthColumn(int orientation) { private String getWidthColumn(int orientation) {
if (orientation == 0 || orientation == 180) return MediaStore.Images.ImageColumns.WIDTH; if (orientation == 0 || orientation == 180) return MediaStore.Images.ImageColumns.WIDTH;
else return MediaStore.Images.ImageColumns.HEIGHT; else return MediaStore.Images.ImageColumns.HEIGHT;
} }
@TargetApi(16)
@SuppressWarnings("SuspiciousNameCombination") @SuppressWarnings("SuspiciousNameCombination")
private String getHeightColumn(int orientation) { private String getHeightColumn(int orientation) {
if (orientation == 0 || orientation == 180) return MediaStore.Images.ImageColumns.HEIGHT; if (orientation == 0 || orientation == 180) return MediaStore.Images.ImageColumns.HEIGHT;

View File

@ -94,15 +94,11 @@ public class SearchToolbar extends LinearLayout {
searchItem.expandActionView(); searchItem.expandActionView();
if (Build.VERSION.SDK_INT >= 21) {
Animator animator = ViewAnimationUtils.createCircularReveal(this, (int)x, (int)y, 0, getWidth()); Animator animator = ViewAnimationUtils.createCircularReveal(this, (int)x, (int)y, 0, getWidth());
animator.setDuration(400); animator.setDuration(400);
setVisibility(View.VISIBLE); setVisibility(View.VISIBLE);
animator.start(); animator.start();
} else {
setVisibility(View.VISIBLE);
}
} }
} }
@ -116,7 +112,6 @@ public class SearchToolbar extends LinearLayout {
if (listener != null) listener.onSearchClosed(); if (listener != null) listener.onSearchClosed();
if (Build.VERSION.SDK_INT >= 21) {
Animator animator = ViewAnimationUtils.createCircularReveal(this, (int)x, (int)y, getWidth(), 0); Animator animator = ViewAnimationUtils.createCircularReveal(this, (int)x, (int)y, getWidth(), 0);
animator.setDuration(400); animator.setDuration(400);
animator.addListener(new AnimationCompleteListener() { animator.addListener(new AnimationCompleteListener() {
@ -126,9 +121,6 @@ public class SearchToolbar extends LinearLayout {
} }
}); });
animator.start(); animator.start();
} else {
setVisibility(View.INVISIBLE);
}
} }
} }

View File

@ -1,10 +1,7 @@
package org.thoughtcrime.securesms.components; package org.thoughtcrime.securesms.components;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.BitmapFactory;
import android.os.Build.VERSION_CODES;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.widget.FrameLayout; import android.widget.FrameLayout;
@ -24,7 +21,7 @@ public class SquareFrameLayout extends FrameLayout {
this(context, attrs, 0); this(context, attrs, 0);
} }
@TargetApi(VERSION_CODES.HONEYCOMB) @SuppressWarnings("unused") @SuppressWarnings("unused")
public SquareFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) { public SquareFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr); super(context, attrs, defStyleAttr);

View File

@ -15,7 +15,6 @@
package org.thoughtcrime.securesms.components.camera; package org.thoughtcrime.securesms.components.camera;
import android.annotation.TargetApi;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo;
@ -28,26 +27,26 @@ import android.hardware.Camera.Parameters;
import android.hardware.Camera.Size; import android.hardware.Camera.Size;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build; import android.os.Build;
import android.os.Build.VERSION;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.util.AttributeSet; import android.util.AttributeSet;
import org.session.libsignal.utilities.Log;
import android.view.OrientationEventListener; import android.view.OrientationEventListener;
import android.view.ViewGroup; import android.view.ViewGroup;
import network.loki.messenger.R; import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.util.BitmapUtil; import androidx.annotation.Nullable;
import org.session.libsignal.utilities.guava.Optional;
import org.session.libsession.utilities.TextSecurePreferences; import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsession.utilities.Util; import org.session.libsession.utilities.Util;
import org.session.libsignal.utilities.Log;
import org.session.libsignal.utilities.guava.Optional;
import org.thoughtcrime.securesms.util.BitmapUtil;
import java.io.IOException; import java.io.IOException;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import network.loki.messenger.R;
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public class CameraView extends ViewGroup { public class CameraView extends ViewGroup {
private static final String TAG = CameraView.class.getSimpleName(); private static final String TAG = CameraView.class.getSimpleName();
@ -91,7 +90,6 @@ public class CameraView extends ViewGroup {
addView(surface); addView(surface);
} }
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public void onResume() { public void onResume() {
if (state != State.PAUSED) return; if (state != State.PAUSED) return;
state = State.RESUMED; state = State.RESUMED;
@ -255,26 +253,9 @@ public class CameraView extends ViewGroup {
return Camera.getNumberOfCameras() > 1; return Camera.getNumberOfCameras() > 1;
} }
public boolean isRearCamera() {
return cameraId == CameraInfo.CAMERA_FACING_BACK;
}
public void flipCamera() {
if (Camera.getNumberOfCameras() > 1) {
cameraId = cameraId == CameraInfo.CAMERA_FACING_BACK
? CameraInfo.CAMERA_FACING_FRONT
: CameraInfo.CAMERA_FACING_BACK;
onPause();
onResume();
TextSecurePreferences.setDirectCaptureCameraId(getContext(), cameraId);
}
}
@TargetApi(14)
private void onCameraReady(final @NonNull Camera camera) { private void onCameraReady(final @NonNull Camera camera) {
final Parameters parameters = camera.getParameters(); final Parameters parameters = camera.getParameters();
if (VERSION.SDK_INT >= 14) {
parameters.setRecordingHint(true); parameters.setRecordingHint(true);
final List<String> focusModes = parameters.getSupportedFocusModes(); final List<String> focusModes = parameters.getSupportedFocusModes();
if (focusModes.contains(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { if (focusModes.contains(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
@ -282,7 +263,6 @@ public class CameraView extends ViewGroup {
} else if (focusModes.contains(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) { } else if (focusModes.contains(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
} }
}
displayOrientation = CameraUtils.getCameraDisplayOrientation(getActivity(), getCameraInfo()); displayOrientation = CameraUtils.getCameraDisplayOrientation(getActivity(), getCameraInfo());
camera.setDisplayOrientation(displayOrientation); camera.setDisplayOrientation(displayOrientation);
@ -465,7 +445,7 @@ public class CameraView extends ViewGroup {
} }
final float newWidth = visibleRect.width() * scale; final float newWidth = visibleRect.width() * scale;
final float newHeight = visibleRect.height() * scale; final float newHeight = visibleRect.height() * scale;
final float centerX = (VERSION.SDK_INT < 14 || isTroublemaker()) ? previewWidth - newWidth / 2 : previewWidth / 2; final float centerX = (isTroublemaker()) ? previewWidth - newWidth / 2 : previewWidth / 2;
final float centerY = previewHeight / 2; final float centerY = previewHeight / 2;
visibleRect.set((int) (centerX - newWidth / 2), visibleRect.set((int) (centerX - newWidth / 2),

View File

@ -16,15 +16,9 @@
*/ */
package org.thoughtcrime.securesms.conversation.v2 package org.thoughtcrime.securesms.conversation.v2
import android.annotation.TargetApi
import android.app.ActivityManager
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context import android.content.Context
import android.graphics.Typeface import android.graphics.Typeface
import android.net.Uri import android.net.Uri
import android.os.Build.VERSION
import android.os.Build.VERSION_CODES
import android.text.Spannable import android.text.Spannable
import android.text.SpannableString import android.text.SpannableString
import android.text.TextUtils import android.text.TextUtils
@ -33,22 +27,16 @@ import android.view.View
import com.annimon.stream.Stream import com.annimon.stream.Stream
import com.google.android.mms.pdu_alt.CharacterSets import com.google.android.mms.pdu_alt.CharacterSets
import com.google.android.mms.pdu_alt.EncodedStringValue import com.google.android.mms.pdu_alt.EncodedStringValue
import network.loki.messenger.R
import org.session.libsignal.utilities.Log import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.components.ComposeText import org.thoughtcrime.securesms.components.ComposeText
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import java.io.IOException import java.io.IOException
import java.io.UnsupportedEncodingException import java.io.UnsupportedEncodingException
import java.util.Collections import java.util.Collections
import java.util.concurrent.TimeUnit
import kotlin.math.max
import kotlin.math.min
object Util { object Util {
private val TAG: String = Log.tag(Util::class.java) private val TAG: String = Log.tag(Util::class.java)
private val BUILD_LIFESPAN = TimeUnit.DAYS.toMillis(90)
fun <T> asList(vararg elements: T): List<T> { fun <T> asList(vararg elements: T): List<T> {
val result = mutableListOf<T>() // LinkedList() val result = mutableListOf<T>() // LinkedList()
Collections.addAll(result, *elements) Collections.addAll(result, *elements)
@ -104,19 +92,6 @@ object Util {
return sb.toString() return sb.toString()
} }
fun rightPad(value: String, length: Int): String {
if (value.length >= length) {
return value
}
val out = StringBuilder(value)
while (out.length < length) {
out.append(" ")
}
return out.toString()
}
fun isEmpty(value: Array<EncodedStringValue?>?): Boolean { fun isEmpty(value: Array<EncodedStringValue?>?): Boolean {
return value == null || value.size == 0 return value == null || value.size == 0
} }
@ -133,64 +108,6 @@ object Util {
return charSequence == null || charSequence.length == 0 return charSequence == null || charSequence.length == 0
} }
fun hasItems(collection: Collection<*>?): Boolean {
return collection != null && !collection.isEmpty()
}
fun <K, V> getOrDefault(map: Map<K, V>, key: K, defaultValue: V): V? {
return if (map.containsKey(key)) map[key] else defaultValue
}
fun getFirstNonEmpty(vararg values: String?): String {
for (value in values) {
if (!value.isNullOrEmpty()) { return value }
}
return ""
}
fun emptyIfNull(value: String?): String {
return value ?: ""
}
fun emptyIfNull(value: CharSequence?): CharSequence {
return value ?: ""
}
fun getBoldedString(value: String?): CharSequence {
val spanned = SpannableString(value)
spanned.setSpan(
StyleSpan(Typeface.BOLD), 0,
spanned.length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
return spanned
}
fun toIsoString(bytes: ByteArray?): String {
try {
return String(bytes!!, charset(CharacterSets.MIMENAME_ISO_8859_1))
} catch (e: UnsupportedEncodingException) {
throw AssertionError("ISO_8859_1 must be supported!")
}
}
fun toIsoBytes(isoString: String): ByteArray {
try {
return isoString.toByteArray(charset(CharacterSets.MIMENAME_ISO_8859_1))
} catch (e: UnsupportedEncodingException) {
throw AssertionError("ISO_8859_1 must be supported!")
}
}
fun toUtf8Bytes(utf8String: String): ByteArray {
try {
return utf8String.toByteArray(charset(CharacterSets.MIMENAME_UTF_8))
} catch (e: UnsupportedEncodingException) {
throw AssertionError("UTF_8 must be supported!")
}
}
fun wait(lock: Any, timeout: Long) { fun wait(lock: Any, timeout: Long) {
try { try {
(lock as Object).wait(timeout) (lock as Object).wait(timeout)
@ -225,20 +142,6 @@ object Util {
return parts return parts
} }
fun combine(vararg elements: ByteArray?): ByteArray {
try {
val baos = ByteArrayOutputStream()
for (element in elements) {
baos.write(element)
}
return baos.toByteArray()
} catch (e: IOException) {
throw AssertionError(e)
}
}
fun trim(input: ByteArray?, length: Int): ByteArray { fun trim(input: ByteArray?, length: Int): ByteArray {
val result = ByteArray(length) val result = ByteArray(length)
System.arraycopy(input, 0, result, 0, result.size) System.arraycopy(input, 0, result, 0, result.size)
@ -251,26 +154,6 @@ object Util {
else Uri.parse(uri) else Uri.parse(uri)
} }
@TargetApi(VERSION_CODES.KITKAT)
fun isLowMemory(context: Context): Boolean {
val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
return (VERSION.SDK_INT >= VERSION_CODES.KITKAT && activityManager.isLowRamDevice) ||
activityManager.largeMemoryClass <= 64
}
fun clamp(value: Int, min: Int, max: Int): Int {
return min(max(value.toDouble(), min.toDouble()), max.toDouble()).toInt()
}
fun clamp(value: Long, min: Long, max: Long): Long {
return min(max(value.toDouble(), min.toDouble()), max.toDouble()).toLong()
}
fun clamp(value: Float, min: Float, max: Float): Float {
return min(max(value.toDouble(), min.toDouble()), max.toDouble()).toFloat()
}
/** /**
* Returns half of the difference between the given length, and the length when scaled by the * Returns half of the difference between the given length, and the length when scaled by the
* given scale. * given scale.
@ -280,74 +163,6 @@ object Util {
return (length - scaledLength) / 2 return (length - scaledLength) / 2
} }
fun readTextFromClipboard(context: Context): String? {
run {
val clipboardManager =
context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
return if (clipboardManager.hasPrimaryClip() && clipboardManager.primaryClip!!.itemCount > 0) {
clipboardManager.primaryClip!!.getItemAt(0).text.toString()
} else {
null
}
}
}
fun writeTextToClipboard(context: Context, text: String) {
writeTextToClipboard(context, context.getString(R.string.app_name), text)
}
fun writeTextToClipboard(context: Context, label: String, text: String) {
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clip = ClipData.newPlainText(label, text)
clipboard.setPrimaryClip(clip)
}
fun toIntExact(value: Long): Int {
if (value.toInt().toLong() != value) {
throw ArithmeticException("integer overflow")
}
return value.toInt()
}
fun isEquals(first: Long?, second: Long): Boolean {
return first != null && first == second
}
@SafeVarargs
fun <T> concatenatedList(vararg items: Collection<T>): List<T> {
val concat: MutableList<T> = ArrayList(
Stream.of(*items).reduce(0) { sum: Int, list: Collection<T> -> sum + list.size })
for (list in items) {
concat.addAll(list)
}
return concat
}
fun isLong(value: String): Boolean {
try {
value.toLong()
return true
} catch (e: NumberFormatException) {
return false
}
}
fun parseInt(integer: String, defaultValue: Int): Int {
return try {
integer.toInt()
} catch (e: NumberFormatException) {
defaultValue
}
}
// Method to determine if we're currently in a left-to-right or right-to-left language like Arabic
fun usingRightToLeftLanguage(context: Context): Boolean {
val config = context.resources.configuration
return config.layoutDirection == View.LAYOUT_DIRECTION_RTL
}
// Method to determine if we're currently in a left-to-right or right-to-left language like Arabic // Method to determine if we're currently in a left-to-right or right-to-left language like Arabic
fun usingLeftToRightLanguage(context: Context): Boolean { fun usingLeftToRightLanguage(context: Context): Boolean {
val config = context.resources.configuration val config = context.resources.configuration

View File

@ -148,11 +148,8 @@ class InputBarButton : RelativeLayout {
private fun onDown(event: MotionEvent) { private fun onDown(event: MotionEvent) {
expand() expand()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK) performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK)
} else {
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
}
longPressCallback?.let { gestureHandler.removeCallbacks(it) } longPressCallback?.let { gestureHandler.removeCallbacks(it) }
val newLongPressCallback = Runnable { onLongPress?.invoke() } val newLongPressCallback = Runnable { onLongPress?.invoke() }
this.longPressCallback = newLongPressCallback this.longPressCallback = newLongPressCallback

View File

@ -3,7 +3,6 @@ package org.thoughtcrime.securesms.conversation.v2.input_bar
import android.content.Context import android.content.Context
import android.content.res.Resources import android.content.res.Resources
import android.net.Uri import android.net.Uri
import android.os.Build
import android.util.AttributeSet import android.util.AttributeSet
import android.view.inputmethod.EditorInfo import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputConnection import android.view.inputmethod.InputConnection
@ -57,7 +56,7 @@ class InputBarEditText : AppCompatEditText {
InputConnectionCompat.OnCommitContentListener { inputContentInfo, flags, opts -> InputConnectionCompat.OnCommitContentListener { inputContentInfo, flags, opts ->
val lacksPermission = (flags and InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0 val lacksPermission = (flags and InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0
// read and display inputContentInfo asynchronously // read and display inputContentInfo asynchronously
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1 && lacksPermission) { if (lacksPermission) {
try { try {
inputContentInfo.requestPermission() inputContentInfo.requestPermission()
} catch (e: Exception) { } catch (e: Exception) {

View File

@ -59,9 +59,6 @@ public class AttachmentSecretProvider {
{ {
AttachmentSecret attachmentSecret = AttachmentSecret.fromString(unencryptedSecret); AttachmentSecret attachmentSecret = AttachmentSecret.fromString(unencryptedSecret);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return attachmentSecret;
} else {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(attachmentSecret.serialize().getBytes()); KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(attachmentSecret.serialize().getBytes());
TextSecurePreferences.setAttachmentEncryptedSecret(context, encryptedSecret.serialize()); TextSecurePreferences.setAttachmentEncryptedSecret(context, encryptedSecret.serialize());
@ -69,16 +66,11 @@ public class AttachmentSecretProvider {
return attachmentSecret; return attachmentSecret;
} }
}
private AttachmentSecret getEncryptedAttachmentSecret(@NonNull String serializedEncryptedSecret) { private AttachmentSecret getEncryptedAttachmentSecret(@NonNull String serializedEncryptedSecret) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
throw new AssertionError("OS downgrade not supported. KeyStore sealed data exists on platform < M!");
} else {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.SealedData.fromString(serializedEncryptedSecret); KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.SealedData.fromString(serializedEncryptedSecret);
return AttachmentSecret.fromString(new String(KeyStoreHelper.unseal(encryptedSecret))); return AttachmentSecret.fromString(new String(KeyStoreHelper.unseal(encryptedSecret)));
} }
}
private AttachmentSecret createAndStoreAttachmentSecret(@NonNull Context context) { private AttachmentSecret createAndStoreAttachmentSecret(@NonNull Context context) {
byte[] secret = new byte[32]; byte[] secret = new byte[32];
@ -91,12 +83,8 @@ public class AttachmentSecretProvider {
} }
private void storeAttachmentSecret(@NonNull Context context, @NonNull AttachmentSecret attachmentSecret) { private void storeAttachmentSecret(@NonNull Context context, @NonNull AttachmentSecret attachmentSecret) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(attachmentSecret.serialize().getBytes()); KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(attachmentSecret.serialize().getBytes());
TextSecurePreferences.setAttachmentEncryptedSecret(context, encryptedSecret.serialize()); TextSecurePreferences.setAttachmentEncryptedSecret(context, encryptedSecret.serialize());
} else {
TextSecurePreferences.setAttachmentUnencryptedSecret(context, attachmentSecret.serialize());
}
} }
} }

View File

@ -42,9 +42,8 @@ class BiometricSecretProvider {
builder.setUnlockedDeviceRequired(true) builder.setUnlockedDeviceRequired(true)
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
builder.setInvalidatedByBiometricEnrollment(true) builder.setInvalidatedByBiometricEnrollment(true)
}
keyGenerator.initialize(builder.build()) keyGenerator.initialize(builder.build())
keyGenerator.generateKeyPair() keyGenerator.generateKeyPair()
} }

View File

@ -36,29 +36,21 @@ public class DatabaseSecretProvider {
try { try {
DatabaseSecret databaseSecret = new DatabaseSecret(unencryptedSecret); DatabaseSecret databaseSecret = new DatabaseSecret(unencryptedSecret);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return databaseSecret;
} else {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(databaseSecret.asBytes()); KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(databaseSecret.asBytes());
TextSecurePreferences.setDatabaseEncryptedSecret(context, encryptedSecret.serialize()); TextSecurePreferences.setDatabaseEncryptedSecret(context, encryptedSecret.serialize());
TextSecurePreferences.setDatabaseUnencryptedSecret(context, null); TextSecurePreferences.setDatabaseUnencryptedSecret(context, null);
return databaseSecret; return databaseSecret;
}
} catch (IOException e) { } catch (IOException e) {
throw new AssertionError(e); throw new AssertionError(e);
} }
} }
private DatabaseSecret getEncryptedDatabaseSecret(@NonNull String serializedEncryptedSecret) { private DatabaseSecret getEncryptedDatabaseSecret(@NonNull String serializedEncryptedSecret) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
throw new AssertionError("OS downgrade not supported. KeyStore sealed data exists on platform < M!");
} else {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.SealedData.fromString(serializedEncryptedSecret); KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.SealedData.fromString(serializedEncryptedSecret);
return new DatabaseSecret(KeyStoreHelper.unseal(encryptedSecret)); return new DatabaseSecret(KeyStoreHelper.unseal(encryptedSecret));
} }
}
private DatabaseSecret createAndStoreDatabaseSecret(@NonNull Context context) { private DatabaseSecret createAndStoreDatabaseSecret(@NonNull Context context) {
byte[] secret = new byte[32]; byte[] secret = new byte[32];
@ -66,12 +58,8 @@ public class DatabaseSecretProvider {
DatabaseSecret databaseSecret = new DatabaseSecret(secret); DatabaseSecret databaseSecret = new DatabaseSecret(secret);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(databaseSecret.asBytes()); KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(databaseSecret.asBytes());
TextSecurePreferences.setDatabaseEncryptedSecret(context, encryptedSecret.serialize()); TextSecurePreferences.setDatabaseEncryptedSecret(context, encryptedSecret.serialize());
} else {
TextSecurePreferences.setDatabaseUnencryptedSecret(context, databaseSecret.asString());
}
return databaseSecret; return databaseSecret;
} }

View File

@ -129,9 +129,6 @@ public class IdentityKeyUtil {
} }
private static String getUnencryptedSecret(String key, String unencryptedSecret, Context context) { private static String getUnencryptedSecret(String key, String unencryptedSecret, Context context) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return unencryptedSecret;
} else {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(unencryptedSecret.getBytes()); KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(unencryptedSecret.getBytes());
// save the encrypted suffix secret "key_encrypted" // save the encrypted suffix secret "key_encrypted"
@ -141,23 +138,17 @@ public class IdentityKeyUtil {
return unencryptedSecret; return unencryptedSecret;
} }
}
private static String getEncryptedSecret(String encryptedSecret) { private static String getEncryptedSecret(String encryptedSecret) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
throw new AssertionError("OS downgrade not supported. KeyStore sealed data exists on platform < M!");
} else {
KeyStoreHelper.SealedData sealedData = KeyStoreHelper.SealedData.fromString(encryptedSecret); KeyStoreHelper.SealedData sealedData = KeyStoreHelper.SealedData.fromString(encryptedSecret);
return new String(KeyStoreHelper.unseal(sealedData)); return new String(KeyStoreHelper.unseal(sealedData));
} }
}
public static void save(Context context, String key, String value) { public static void save(Context context, String key, String value) {
SharedPreferences preferences = context.getSharedPreferences(MASTER_SECRET_UTIL_PREFERENCES_NAME, 0); SharedPreferences preferences = context.getSharedPreferences(MASTER_SECRET_UTIL_PREFERENCES_NAME, 0);
Editor preferencesEditor = preferences.edit(); Editor preferencesEditor = preferences.edit();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
boolean isEncryptedSuffix = key.endsWith(ENCRYPTED_SUFFIX); boolean isEncryptedSuffix = key.endsWith(ENCRYPTED_SUFFIX);
if (isEncryptedSuffix) { if (isEncryptedSuffix) {
preferencesEditor.putString(key, value); preferencesEditor.putString(key, value);
@ -165,9 +156,7 @@ public class IdentityKeyUtil {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(value.getBytes()); KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(value.getBytes());
preferencesEditor.putString(key+ENCRYPTED_SUFFIX, encryptedSecret.serialize()); preferencesEditor.putString(key+ENCRYPTED_SUFFIX, encryptedSecret.serialize());
} }
} else {
preferencesEditor.putString(key, value);
}
if (!preferencesEditor.commit()) throw new AssertionError("failed to save identity key/value to shared preferences"); if (!preferencesEditor.commit()) throw new AssertionError("failed to save identity key/value to shared preferences");
} }

View File

@ -966,11 +966,6 @@ public class AttachmentDatabase extends Database {
@SuppressLint("NewApi") @SuppressLint("NewApi")
private ThumbnailData generateVideoThumbnail(AttachmentId attachmentId) { private ThumbnailData generateVideoThumbnail(AttachmentId attachmentId) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
Log.w(TAG, "Video thumbnails not supported...");
return null;
}
DataInfo dataInfo = getAttachmentDataFileInfo(attachmentId, DATA); DataInfo dataInfo = getAttachmentDataFileInfo(attachmentId, DATA);
if (dataInfo == null) { if (dataInfo == null) {

View File

@ -252,11 +252,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
NotificationManager notificationManager = context.getSystemService(NotificationManager.class); NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
String channelId = context.getString(R.string.NotificationChannel_failures); String channelId = context.getString(R.string.NotificationChannel_failures);
if (NotificationChannels.supported()) {
NotificationChannel channel = new NotificationChannel(channelId, channelId, NotificationManager.IMPORTANCE_HIGH); NotificationChannel channel = new NotificationChannel(channelId, channelId, NotificationManager.IMPORTANCE_HIGH);
channel.enableVibration(true); channel.enableVibration(true);
notificationManager.createNotificationChannel(channel); notificationManager.createNotificationChannel(channel);
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channelId) NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channelId)
.setSmallIcon(R.drawable.ic_notification) .setSmallIcon(R.drawable.ic_notification)
@ -266,10 +264,6 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
.setContentText(context.getString(R.string.ErrorNotifier_migration_downgrade)) .setContentText(context.getString(R.string.ErrorNotifier_migration_downgrade))
.setAutoCancel(true); .setAutoCancel(true);
if (!NotificationChannels.supported()) {
builder.setPriority(NotificationCompat.PRIORITY_HIGH);
}
notificationManager.notify(5874, builder.build()); notificationManager.notify(5874, builder.build());
// Throw the error (app will crash but there is nothing else we can do unfortunately) // Throw the error (app will crash but there is nothing else we can do unfortunately)

View File

@ -15,6 +15,7 @@ import android.widget.RelativeLayout
import android.widget.TextView import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.annotation.ColorRes import androidx.annotation.ColorRes
import androidx.core.content.ContextCompat
import androidx.localbroadcastmanager.content.LocalBroadcastManager import androidx.localbroadcastmanager.content.LocalBroadcastManager
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
@ -38,7 +39,6 @@ import org.thoughtcrime.securesms.util.disableClipping
import org.thoughtcrime.securesms.util.fadeIn import org.thoughtcrime.securesms.util.fadeIn
import org.thoughtcrime.securesms.util.fadeOut import org.thoughtcrime.securesms.util.fadeOut
import org.thoughtcrime.securesms.util.getAccentColor import org.thoughtcrime.securesms.util.getAccentColor
import org.thoughtcrime.securesms.util.getColorWithID
class PathActivity : PassphraseRequiredActionBarActivity() { class PathActivity : PassphraseRequiredActionBarActivity() {
private lateinit var binding: ActivityPathBinding private lateinit var binding: ActivityPathBinding
@ -283,7 +283,7 @@ class PathActivity : PassphraseRequiredActionBarActivity() {
private fun expand() { private fun expand() {
dotView.animateSizeChange(R.dimen.path_row_dot_size, R.dimen.path_row_expanded_dot_size) dotView.animateSizeChange(R.dimen.path_row_dot_size, R.dimen.path_row_expanded_dot_size)
@ColorRes val startColorID = if (UiModeUtilities.isDayUiMode(context)) R.color.transparent_black_30 else R.color.black @ColorRes val startColorID = if (UiModeUtilities.isDayUiMode(context)) R.color.transparent_black_30 else R.color.black
val startColor = context.resources.getColorWithID(startColorID, context.theme) val startColor = ContextCompat.getColor(context, startColorID)
val endColor = context.getAccentColor() val endColor = context.getAccentColor()
GlowViewUtilities.animateShadowColorChange(dotView, startColor, endColor) GlowViewUtilities.animateShadowColorChange(dotView, startColor, endColor)
} }
@ -292,7 +292,7 @@ class PathActivity : PassphraseRequiredActionBarActivity() {
dotView.animateSizeChange(R.dimen.path_row_expanded_dot_size, R.dimen.path_row_dot_size) dotView.animateSizeChange(R.dimen.path_row_expanded_dot_size, R.dimen.path_row_dot_size)
@ColorRes val endColorID = if (UiModeUtilities.isDayUiMode(context)) R.color.transparent_black_30 else R.color.black @ColorRes val endColorID = if (UiModeUtilities.isDayUiMode(context)) R.color.transparent_black_30 else R.color.black
val startColor = context.getAccentColor() val startColor = context.getAccentColor()
val endColor = context.resources.getColorWithID(endColorID, context.theme) val endColor = ContextCompat.getColor(context, endColorID)
GlowViewUtilities.animateShadowColorChange(dotView, startColor, endColor) GlowViewUtilities.animateShadowColorChange(dotView, startColor, endColor)
} }

View File

@ -9,6 +9,7 @@ import android.graphics.Paint
import android.util.AttributeSet import android.util.AttributeSet
import android.view.View import android.view.View
import androidx.annotation.ColorInt import androidx.annotation.ColorInt
import androidx.core.content.ContextCompat
import androidx.lifecycle.coroutineScope import androidx.lifecycle.coroutineScope
import androidx.localbroadcastmanager.content.LocalBroadcastManager import androidx.localbroadcastmanager.content.LocalBroadcastManager
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -17,7 +18,6 @@ import kotlinx.coroutines.withContext
import network.loki.messenger.R import network.loki.messenger.R
import org.session.libsession.snode.OnionRequestAPI import org.session.libsession.snode.OnionRequestAPI
import org.thoughtcrime.securesms.conversation.v2.ViewUtil import org.thoughtcrime.securesms.conversation.v2.ViewUtil
import org.thoughtcrime.securesms.util.getColorWithID
import org.thoughtcrime.securesms.util.toPx import org.thoughtcrime.securesms.util.toPx
class PathStatusView : View { class PathStatusView : View {
@ -104,7 +104,7 @@ class PathStatusView : View {
sessionShadowColor = hasPathsColor sessionShadowColor = hasPathsColor
} else { } else {
setBackgroundResource(R.drawable.paths_building_dot) setBackgroundResource(R.drawable.paths_building_dot)
val pathsBuildingColor = resources.getColorWithID(R.color.paths_building, context.theme) val pathsBuildingColor = ContextCompat.getColor(context, R.color.paths_building)
mainColor = pathsBuildingColor mainColor = pathsBuildingColor
sessionShadowColor = pathsBuildingColor sessionShadowColor = pathsBuildingColor
} }

View File

@ -8,11 +8,6 @@ public interface Constraint {
boolean isMet(); boolean isMet();
@NonNull String getFactoryKey();
@RequiresApi(26)
void applyToJobInfo(@NonNull JobInfo.Builder jobInfoBuilder);
interface Factory<T extends Constraint> { interface Factory<T extends Constraint> {
T create(); T create();
} }

View File

@ -28,17 +28,6 @@ public class NetworkConstraint implements Constraint {
return activeNetworkInfo != null && activeNetworkInfo.isConnected(); return activeNetworkInfo != null && activeNetworkInfo.isConnected();
} }
@Override
public @NonNull String getFactoryKey() {
return KEY;
}
@RequiresApi(26)
@Override
public void applyToJobInfo(@NonNull JobInfo.Builder jobInfoBuilder) {
jobInfoBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
}
public static final class Factory implements Constraint.Factory<NetworkConstraint> { public static final class Factory implements Constraint.Factory<NetworkConstraint> {
private final Application application; private final Application application;

View File

@ -32,24 +32,16 @@ class LogSecretProvider {
} }
private static byte[] parseEncryptedSecret(String secret) { private static byte[] parseEncryptedSecret(String secret) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.SealedData.fromString(secret); KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.SealedData.fromString(secret);
return KeyStoreHelper.unseal(encryptedSecret); return KeyStoreHelper.unseal(encryptedSecret);
} else {
throw new AssertionError("OS downgrade not supported. KeyStore sealed data exists on platform < M!");
}
} }
private static byte[] createAndStoreSecret(@NonNull Context context) { private static byte[] createAndStoreSecret(@NonNull Context context) {
byte[] secret = new byte[32]; byte[] secret = new byte[32];
SECURE_RANDOM.nextBytes(secret); SECURE_RANDOM.nextBytes(secret);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(secret); KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(secret);
TextSecurePreferences.setLogEncryptedSecret(context, encryptedSecret.serialize()); TextSecurePreferences.setLogEncryptedSecret(context, encryptedSecret.serialize());
} else {
TextSecurePreferences.setLogUnencryptedSecret(context, Base64.encodeBytes(secret));
}
return secret; return secret;
} }

View File

@ -1,6 +1,5 @@
package org.thoughtcrime.securesms.mediasend; package org.thoughtcrime.securesms.mediasend;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
@ -200,14 +199,12 @@ class MediaRepository {
}).toList(); }).toList();
} }
@TargetApi(16)
@SuppressWarnings("SuspiciousNameCombination") @SuppressWarnings("SuspiciousNameCombination")
private String getWidthColumn(int orientation) { private String getWidthColumn(int orientation) {
if (orientation == 0 || orientation == 180) return Images.Media.WIDTH; if (orientation == 0 || orientation == 180) return Images.Media.WIDTH;
else return Images.Media.HEIGHT; else return Images.Media.HEIGHT;
} }
@TargetApi(16)
@SuppressWarnings("SuspiciousNameCombination") @SuppressWarnings("SuspiciousNameCombination")
private String getHeightColumn(int orientation) { private String getHeightColumn(int orientation) {
if (orientation == 0 || orientation == 180) return Images.Media.HEIGHT; if (orientation == 0 || orientation == 180) return Images.Media.HEIGHT;

View File

@ -50,8 +50,8 @@ public abstract class AbstractNotificationBuilder extends NotificationCompat.Bui
} }
public void setAlarms(@Nullable Uri ringtone, VibrateState vibrate) { public void setAlarms(@Nullable Uri ringtone, VibrateState vibrate) {
Uri defaultRingtone = NotificationChannels.supported() ? NotificationChannels.getMessageRingtone(context) : TextSecurePreferences.getNotificationRingtone(context); Uri defaultRingtone = NotificationChannels.getMessageRingtone(context);
boolean defaultVibrate = NotificationChannels.supported() ? NotificationChannels.getMessageVibrate(context) : TextSecurePreferences.isNotificationVibrateEnabled(context); boolean defaultVibrate = NotificationChannels.getMessageVibrate(context);
if (ringtone == null && !TextUtils.isEmpty(defaultRingtone.toString())) setSound(defaultRingtone); if (ringtone == null && !TextUtils.isEmpty(defaultRingtone.toString())) setSound(defaultRingtone);
else if (ringtone != null && !ringtone.toString().isEmpty()) setSound(ringtone); else if (ringtone != null && !ringtone.toString().isEmpty()) setSound(ringtone);

View File

@ -37,10 +37,6 @@ public class MultipleRecipientNotificationBuilder extends AbstractNotificationBu
setContentIntent(PendingIntent.getActivity(context, 0, new Intent(context, HomeActivity.class), PendingIntent.FLAG_IMMUTABLE)); setContentIntent(PendingIntent.getActivity(context, 0, new Intent(context, HomeActivity.class), PendingIntent.FLAG_IMMUTABLE));
setCategory(NotificationCompat.CATEGORY_MESSAGE); setCategory(NotificationCompat.CATEGORY_MESSAGE);
setGroupSummary(true); setGroupSummary(true);
if (!NotificationChannels.supported()) {
setPriority(TextSecurePreferences.getNotificationPriority(context));
}
} }
public void setMessageCount(int messageCount, int threadCount) { public void setMessageCount(int messageCount, int threadCount) {

View File

@ -1,15 +1,12 @@
package org.thoughtcrime.securesms.notifications; package org.thoughtcrime.securesms.notifications;
import android.annotation.TargetApi;
import android.app.NotificationChannel; import android.app.NotificationChannel;
import android.app.NotificationChannelGroup; import android.app.NotificationChannelGroup;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.media.AudioAttributes; import android.media.AudioAttributes;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build;
import android.provider.Settings; import android.provider.Settings;
import android.text.TextUtils; import android.text.TextUtils;
@ -24,7 +21,6 @@ import org.session.libsession.utilities.Address;
import org.session.libsession.utilities.ServiceUtil; import org.session.libsession.utilities.ServiceUtil;
import org.session.libsession.utilities.TextSecurePreferences; import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsession.utilities.recipients.Recipient; import org.session.libsession.utilities.recipients.Recipient;
import org.session.libsession.utilities.recipients.Recipient.VibrateState;
import org.session.libsignal.utilities.Log; import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.database.RecipientDatabase; import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent; import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
@ -63,10 +59,6 @@ public class NotificationChannels {
* ignored for API < 26. * ignored for API < 26.
*/ */
public static synchronized void create(@NonNull Context context) { public static synchronized void create(@NonNull Context context) {
if (!supported()) {
return;
}
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context); NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
int oldVersion = TextSecurePreferences.getNotificationChannelVersion(context); int oldVersion = TextSecurePreferences.getNotificationChannelVersion(context);
@ -82,32 +74,6 @@ public class NotificationChannels {
}); });
} }
/**
* Recreates all notification channels for contacts with custom notifications enabled. Should be
* safe to call repeatedly. Needs to be executed on a background thread.
*/
@WorkerThread
public static synchronized void restoreContactNotificationChannels(@NonNull Context context) {
if (!NotificationChannels.supported()) {
return;
}
RecipientDatabase db = DatabaseComponent.get(context).recipientDatabase();
try (RecipientDatabase.RecipientReader reader = db.getRecipientsWithNotificationChannels()) {
Recipient recipient;
while ((recipient = reader.getNext()) != null) {
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
if (!channelExists(notificationManager.getNotificationChannel(recipient.getNotificationChannel()))) {
String id = createChannelFor(context, recipient);
db.setNotificationChannel(recipient, id);
}
}
}
ensureCustomChannelConsistency(context);
}
/** /**
* @return The channel ID for the default messages channel. * @return The channel ID for the default messages channel.
*/ */
@ -115,13 +81,6 @@ public class NotificationChannels {
return getMessagesChannelId(TextSecurePreferences.getNotificationMessagesChannelVersion(context)); return getMessagesChannelId(TextSecurePreferences.getNotificationMessagesChannelVersion(context));
} }
/**
* @return Whether or not notification channels are supported.
*/
public static boolean supported() {
return Build.VERSION.SDK_INT >= 26;
}
/** /**
* @return A name suitable to be displayed as the notification channel title. * @return A name suitable to be displayed as the notification channel title.
*/ */
@ -137,119 +96,18 @@ public class NotificationChannels {
} }
} }
/**
* Creates a channel for the specified recipient.
* @return The channel ID for the newly-created channel.
*/
public static synchronized String createChannelFor(@NonNull Context context, @NonNull Recipient recipient) {
VibrateState vibrateState = recipient.getMessageVibrate();
boolean vibrationEnabled = vibrateState == VibrateState.DEFAULT ? TextSecurePreferences.isNotificationVibrateEnabled(context) : vibrateState == VibrateState.ENABLED;
Uri messageRingtone = recipient.getMessageRingtone() != null ? recipient.getMessageRingtone() : getMessageRingtone(context);
String displayName = getChannelDisplayNameFor(context, recipient.getName(), recipient.getProfileName(), recipient.getAddress());
return createChannelFor(context, recipient.getAddress(), displayName, messageRingtone, vibrationEnabled);
}
/**
* More verbose version of {@link #createChannelFor(Context, Recipient)}.
*/
public static synchronized @Nullable String createChannelFor(@NonNull Context context,
@NonNull Address address,
@NonNull String displayName,
@Nullable Uri messageSound,
boolean vibrationEnabled)
{
if (!supported()) {
return null;
}
String channelId = generateChannelIdFor(address);
NotificationChannel channel = new NotificationChannel(channelId, displayName, NotificationManager.IMPORTANCE_HIGH);
setLedPreference(channel, TextSecurePreferences.getNotificationLedColor(context));
channel.setGroup(CATEGORY_MESSAGES);
channel.enableVibration(vibrationEnabled);
if (messageSound != null) {
channel.setSound(messageSound, new AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
.setUsage(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT)
.build());
}
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
notificationManager.createNotificationChannel(channel);
return channelId;
}
/**
* Deletes the channel generated for the provided recipient. Safe to call even if there was never
* a channel made for that recipient.
*/
public static synchronized void deleteChannelFor(@NonNull Context context, @NonNull Recipient recipient) {
if (!supported()) {
return;
}
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
String channel = recipient.getNotificationChannel();
if (channel != null) {
Log.i(TAG, "Deleting channel");
notificationManager.deleteNotificationChannel(channel);
}
}
/**
* Navigates the user to the system settings for the desired notification channel.
*/
public static void openChannelSettings(@NonNull Context context, @NonNull String channelId) {
if (!supported()) {
return;
}
Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
intent.putExtra(Settings.EXTRA_CHANNEL_ID, channelId);
intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName());
context.startActivity(intent);
}
/**
* Updates the LED color for message notifications and all contact-specific message notification
* channels. Performs database operations and should therefore be invoked on a background thread.
*/
@WorkerThread
public static synchronized void updateMessagesLedColor(@NonNull Context context, @NonNull Integer color) {
if (!supported()) {
return;
}
Log.i(TAG, "Updating LED color.");
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
updateMessageChannel(context, channel -> setLedPreference(channel, color));
updateAllRecipientChannelLedColors(context, notificationManager, color);
ensureCustomChannelConsistency(context);
}
/** /**
* @return The message ringtone set for the default message channel. * @return The message ringtone set for the default message channel.
*/ */
public static synchronized @NonNull Uri getMessageRingtone(@NonNull Context context) { public static synchronized @NonNull Uri getMessageRingtone(@NonNull Context context) {
if (!supported()) {
return Uri.EMPTY;
}
Uri sound = ServiceUtil.getNotificationManager(context).getNotificationChannel(getMessagesChannel(context)).getSound(); Uri sound = ServiceUtil.getNotificationManager(context).getNotificationChannel(getMessagesChannel(context)).getSound();
return sound == null ? Uri.EMPTY : sound; return sound == null ? Uri.EMPTY : sound;
} }
public static synchronized @Nullable Uri getMessageRingtone(@NonNull Context context, @NonNull Recipient recipient) { public static synchronized @Nullable Uri getMessageRingtone(@NonNull Context context, @NonNull Recipient recipient) {
if (!supported() || recipient.getNotificationChannel() == null) {
return null;
}
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context); NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
NotificationChannel channel = notificationManager.getNotificationChannel(recipient.getNotificationChannel()); NotificationChannel channel = notificationManager.getNotificationChannel(recipient.getNotificationChannel());
@ -265,9 +123,6 @@ public class NotificationChannels {
* Update the message ringtone for the default message channel. * Update the message ringtone for the default message channel.
*/ */
public static synchronized void updateMessageRingtone(@NonNull Context context, @Nullable Uri uri) { public static synchronized void updateMessageRingtone(@NonNull Context context, @Nullable Uri uri) {
if (!supported()) {
return;
}
Log.i(TAG, "Updating default message ringtone with URI: " + String.valueOf(uri)); Log.i(TAG, "Updating default message ringtone with URI: " + String.valueOf(uri));
updateMessageChannel(context, channel -> { updateMessageChannel(context, channel -> {
@ -275,121 +130,23 @@ public class NotificationChannels {
}); });
} }
/**
* Updates the message ringtone for a specific recipient. If that recipient has no channel, this
* does nothing.
*
* This has to update the database, and therefore should be run on a background thread.
*/
@WorkerThread
public static synchronized void updateMessageRingtone(@NonNull Context context, @NonNull Recipient recipient, @Nullable Uri uri) {
if (!supported() || recipient.getNotificationChannel() == null) {
return;
}
Log.i(TAG, "Updating recipient message ringtone with URI: " + String.valueOf(uri));
String newChannelId = generateChannelIdFor(recipient.getAddress());
boolean success = updateExistingChannel(ServiceUtil.getNotificationManager(context),
recipient.getNotificationChannel(),
generateChannelIdFor(recipient.getAddress()),
channel -> channel.setSound(uri == null ? Settings.System.DEFAULT_NOTIFICATION_URI : uri, getRingtoneAudioAttributes()));
DatabaseComponent.get(context).recipientDatabase().setNotificationChannel(recipient, success ? newChannelId : null);
ensureCustomChannelConsistency(context);
}
/** /**
* @return The vibrate settings for the default message channel. * @return The vibrate settings for the default message channel.
*/ */
public static synchronized boolean getMessageVibrate(@NonNull Context context) { public static synchronized boolean getMessageVibrate(@NonNull Context context) {
if (!supported()) {
return false;
}
return ServiceUtil.getNotificationManager(context).getNotificationChannel(getMessagesChannel(context)).shouldVibrate(); return ServiceUtil.getNotificationManager(context).getNotificationChannel(getMessagesChannel(context)).shouldVibrate();
} }
/**
* @return The vibrate setting for a specific recipient. If that recipient has no channel, this
* will return the setting for the default message channel.
*/
public static synchronized boolean getMessageVibrate(@NonNull Context context, @NonNull Recipient recipient) {
if (!supported()) {
return getMessageVibrate(context);
}
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
NotificationChannel channel = notificationManager.getNotificationChannel(recipient.getNotificationChannel());
if (!channelExists(channel)) {
Log.w(TAG, "Recipient didn't have a channel. Returning message default.");
return getMessageVibrate(context);
}
return channel.shouldVibrate();
}
/** /**
* Sets the vibrate property for the default message channel. * Sets the vibrate property for the default message channel.
*/ */
public static synchronized void updateMessageVibrate(@NonNull Context context, boolean enabled) { public static synchronized void updateMessageVibrate(@NonNull Context context, boolean enabled) {
if (!supported()) {
return;
}
Log.i(TAG, "Updating default vibrate with value: " + enabled); Log.i(TAG, "Updating default vibrate with value: " + enabled);
updateMessageChannel(context, channel -> channel.enableVibration(enabled)); updateMessageChannel(context, channel -> channel.enableVibration(enabled));
} }
/**
* Updates the message ringtone for a specific recipient. If that recipient has no channel, this
* does nothing.
*
* This has to update the database and should therefore be run on a background thread.
*/
@WorkerThread
public static synchronized void updateMessageVibrate(@NonNull Context context, @NonNull Recipient recipient, VibrateState vibrateState) {
if (!supported() || recipient.getNotificationChannel() == null) {
return ;
}
Log.i(TAG, "Updating recipient vibrate with value: " + vibrateState);
boolean enabled = vibrateState == VibrateState.DEFAULT ? getMessageVibrate(context) : vibrateState == VibrateState.ENABLED;
String newChannelId = generateChannelIdFor(recipient.getAddress());
boolean success = updateExistingChannel(ServiceUtil.getNotificationManager(context),
recipient.getNotificationChannel(),
newChannelId,
channel -> channel.enableVibration(enabled));
DatabaseComponent.get(context).recipientDatabase().setNotificationChannel(recipient, success ? newChannelId : null);
ensureCustomChannelConsistency(context);
}
/**
* Updates the name of an existing channel to match the recipient's current name. Will have no
* effect if the recipient doesn't have an existing valid channel.
*/
public static synchronized void updateContactChannelName(@NonNull Context context, @NonNull Recipient recipient) {
if (!supported() || recipient.getNotificationChannel() == null) {
return;
}
Log.i(TAG, "Updating contact channel name");
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
if (notificationManager.getNotificationChannel(recipient.getNotificationChannel()) == null) {
Log.w(TAG, "Tried to update the name of a channel, but that channel doesn't exist.");
return;
}
NotificationChannel channel = new NotificationChannel(recipient.getNotificationChannel(),
getChannelDisplayNameFor(context, recipient.getName(), recipient.getProfileName(), recipient.getAddress()),
NotificationManager.IMPORTANCE_HIGH);
channel.setGroup(CATEGORY_MESSAGES);
notificationManager.createNotificationChannel(channel);
}
@TargetApi(26)
@WorkerThread @WorkerThread
public static synchronized void ensureCustomChannelConsistency(@NonNull Context context) { public static synchronized void ensureCustomChannelConsistency(@NonNull Context context) {
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context); NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
@ -421,7 +178,6 @@ public class NotificationChannels {
} }
} }
@TargetApi(26)
private static void onCreate(@NonNull Context context, @NonNull NotificationManager notificationManager) { private static void onCreate(@NonNull Context context, @NonNull NotificationManager notificationManager) {
NotificationChannelGroup messagesGroup = new NotificationChannelGroup(CATEGORY_MESSAGES, context.getResources().getString(R.string.NotificationChannel_group_messages)); NotificationChannelGroup messagesGroup = new NotificationChannelGroup(CATEGORY_MESSAGES, context.getResources().getString(R.string.NotificationChannel_group_messages));
notificationManager.createNotificationChannelGroup(messagesGroup); notificationManager.createNotificationChannelGroup(messagesGroup);
@ -454,7 +210,6 @@ public class NotificationChannels {
} }
} }
@TargetApi(26)
private static void onUpgrade(@NonNull NotificationManager notificationManager, int oldVersion, int newVersion) { private static void onUpgrade(@NonNull NotificationManager notificationManager, int oldVersion, int newVersion) {
Log.i(TAG, "Upgrading channels from " + oldVersion + " to " + newVersion); Log.i(TAG, "Upgrading channels from " + oldVersion + " to " + newVersion);
@ -469,7 +224,6 @@ public class NotificationChannels {
} }
} }
@TargetApi(26)
private static void setLedPreference(@NonNull NotificationChannel channel, @NonNull Integer ledColor) { private static void setLedPreference(@NonNull NotificationChannel channel, @NonNull Integer ledColor) {
if ("none".equals(ledColor)) { if ("none".equals(ledColor)) {
channel.enableLights(false); channel.enableLights(false);
@ -484,7 +238,6 @@ public class NotificationChannels {
return CONTACT_PREFIX + address.serialize() + "_" + System.currentTimeMillis(); return CONTACT_PREFIX + address.serialize() + "_" + System.currentTimeMillis();
} }
@TargetApi(26)
private static @NonNull NotificationChannel copyChannel(@NonNull NotificationChannel original, @NonNull String id) { private static @NonNull NotificationChannel copyChannel(@NonNull NotificationChannel original, @NonNull String id) {
NotificationChannel copy = new NotificationChannel(id, original.getName(), original.getImportance()); NotificationChannel copy = new NotificationChannel(id, original.getName(), original.getImportance());
@ -505,27 +258,7 @@ public class NotificationChannels {
return MESSAGES_PREFIX + version; return MESSAGES_PREFIX + version;
} }
@WorkerThread
@TargetApi(26)
private static void updateAllRecipientChannelLedColors(@NonNull Context context, @NonNull NotificationManager notificationManager, @NonNull Integer color) {
RecipientDatabase database = DatabaseComponent.get(context).recipientDatabase();
try (RecipientDatabase.RecipientReader recipients = database.getRecipientsWithNotificationChannels()) {
Recipient recipient;
while ((recipient = recipients.getNext()) != null) {
assert recipient.getNotificationChannel() != null;
String newChannelId = generateChannelIdFor(recipient.getAddress());
boolean success = updateExistingChannel(notificationManager, recipient.getNotificationChannel(), newChannelId, channel -> setLedPreference(channel, color));
database.setNotificationChannel(recipient, success ? newChannelId : null);
}
}
ensureCustomChannelConsistency(context);
}
@TargetApi(26)
private static void updateMessageChannel(@NonNull Context context, @NonNull ChannelUpdater updater) { private static void updateMessageChannel(@NonNull Context context, @NonNull ChannelUpdater updater) {
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context); NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
int existingVersion = TextSecurePreferences.getNotificationMessagesChannelVersion(context); int existingVersion = TextSecurePreferences.getNotificationMessagesChannelVersion(context);
@ -539,7 +272,6 @@ public class NotificationChannels {
} }
} }
@TargetApi(26)
private static boolean updateExistingChannel(@NonNull NotificationManager notificationManager, private static boolean updateExistingChannel(@NonNull NotificationManager notificationManager,
@NonNull String channelId, @NonNull String channelId,
@NonNull String newChannelId, @NonNull String newChannelId,
@ -559,20 +291,17 @@ public class NotificationChannels {
return true; return true;
} }
@TargetApi(21)
private static AudioAttributes getRingtoneAudioAttributes() { private static AudioAttributes getRingtoneAudioAttributes() {
return new AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN) return new AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
.setUsage(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT) .setUsage(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT)
.build(); .build();
} }
@TargetApi(26)
private static boolean channelExists(@Nullable NotificationChannel channel) { private static boolean channelExists(@Nullable NotificationChannel channel) {
return channel != null && !NotificationChannel.DEFAULT_CHANNEL_ID.equals(channel.getId()); return channel != null && !NotificationChannel.DEFAULT_CHANNEL_ID.equals(channel.getId());
} }
private interface ChannelUpdater { private interface ChannelUpdater {
@TargetApi(26)
void update(@NonNull NotificationChannel channel); void update(@NonNull NotificationChannel channel);
} }
} }

View File

@ -51,8 +51,7 @@ public class NotificationState {
Recipient recipient = notifications.getFirst().getRecipient(); Recipient recipient = notifications.getFirst().getRecipient();
if (recipient != null) { if (recipient != null) {
return NotificationChannels.supported() ? NotificationChannels.getMessageRingtone(context, recipient) return NotificationChannels.getMessageRingtone(context, recipient);
: recipient.resolve().getMessageRingtone();
} }
} }

View File

@ -32,9 +32,5 @@ public class PendingMessageNotificationBuilder extends AbstractNotificationBuild
setContentIntent(PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)); setContentIntent(PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE));
setAutoCancel(true); setAutoCancel(true);
setAlarms(null, Recipient.VibrateState.DEFAULT); setAlarms(null, Recipient.VibrateState.DEFAULT);
if (!NotificationChannels.supported()) {
setPriority(TextSecurePreferences.getNotificationPriority(context));
}
} }
} }

View File

@ -13,7 +13,6 @@ import android.graphics.Rect;
import android.graphics.RectF; import android.graphics.RectF;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Uri; import android.net.Uri;
import android.os.Build;
import android.text.SpannableStringBuilder; import android.text.SpannableStringBuilder;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@ -24,11 +23,10 @@ import androidx.core.app.NotificationCompat.Action;
import androidx.core.app.RemoteInput; import androidx.core.app.RemoteInput;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.load.engine.DiskCacheStrategy;
import org.session.libsession.avatars.ContactColors;
import org.session.libsession.avatars.ContactPhoto; import org.session.libsession.avatars.ContactPhoto;
import org.session.libsession.avatars.ResourceContactPhoto;
import org.session.libsession.messaging.contacts.Contact; import org.session.libsession.messaging.contacts.Contact;
import org.session.libsession.utilities.NotificationPrivacyPreference; import org.session.libsession.utilities.NotificationPrivacyPreference;
import org.session.libsession.utilities.TextSecurePreferences; import org.session.libsession.utilities.TextSecurePreferences;
@ -38,7 +36,6 @@ import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.database.SessionContactDatabase; import org.thoughtcrime.securesms.database.SessionContactDatabase;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent; import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader; import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
import com.bumptech.glide.Glide;
import org.thoughtcrime.securesms.mms.Slide; import org.thoughtcrime.securesms.mms.Slide;
import org.thoughtcrime.securesms.mms.SlideDeck; import org.thoughtcrime.securesms.mms.SlideDeck;
import org.thoughtcrime.securesms.util.AvatarPlaceholderGenerator; import org.thoughtcrime.securesms.util.AvatarPlaceholderGenerator;
@ -69,10 +66,6 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil
setSmallIcon(R.drawable.ic_notification); setSmallIcon(R.drawable.ic_notification);
setColor(ContextCompat.getColor(context, R.color.accent_green)); setColor(ContextCompat.getColor(context, R.color.accent_green));
setCategory(NotificationCompat.CATEGORY_MESSAGE); setCategory(NotificationCompat.CATEGORY_MESSAGE);
if (!NotificationChannels.supported()) {
setPriority(TextSecurePreferences.getNotificationPriority(context));
}
} }
public void setThread(@NonNull Recipient recipient) { public void setThread(@NonNull Recipient recipient) {
@ -179,13 +172,11 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil
Action replyAction = new Action(R.drawable.ic_reply_white_36dp, actionName, quickReplyIntent); Action replyAction = new Action(R.drawable.ic_reply_white_36dp, actionName, quickReplyIntent);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
replyAction = new Action.Builder(R.drawable.ic_reply_white_36dp, replyAction = new Action.Builder(R.drawable.ic_reply_white_36dp,
actionName, actionName,
wearableReplyIntent) wearableReplyIntent)
.addRemoteInput(new RemoteInput.Builder(DefaultMessageNotifier.EXTRA_REMOTE_REPLY).setLabel(label).build()) .addRemoteInput(new RemoteInput.Builder(DefaultMessageNotifier.EXTRA_REMOTE_REPLY).setLabel(label).build())
.build(); .build();
}
Action wearableReplyAction = new Action.Builder(R.drawable.ic_reply, Action wearableReplyAction = new Action.Builder(R.drawable.ic_reply,
actionName, actionName,

View File

@ -210,15 +210,8 @@ public class Permissions {
.toArray(new String[0]); .toArray(new String[0]);
} }
public static boolean hasAny(@NonNull Context context, String... permissions) {
return Build.VERSION.SDK_INT < Build.VERSION_CODES.M ||
Stream.of(permissions).anyMatch(permission -> ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED);
}
public static boolean hasAll(@NonNull Context context, String... permissions) { public static boolean hasAll(@NonNull Context context, String... permissions) {
return Build.VERSION.SDK_INT < Build.VERSION_CODES.M || return Stream.of(permissions).allMatch(permission -> ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED);
Stream.of(permissions).allMatch(permission -> ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED);
} }

View File

@ -56,14 +56,14 @@ class NotificationsPreferenceFragment : ListSummaryPreferenceFragment() {
true true
} }
if (NotificationChannels.supported()) {
prefs.setNotificationRingtone( prefs.setNotificationRingtone(
NotificationChannels.getMessageRingtone(requireContext()).toString() NotificationChannels.getMessageRingtone(requireContext()).toString()
) )
prefs.setNotificationVibrateEnabled( prefs.setNotificationVibrateEnabled(
NotificationChannels.getMessageVibrate(requireContext()) NotificationChannels.getMessageVibrate(requireContext())
) )
}
findPreference<Preference>(TextSecurePreferences.RINGTONE_PREF)!!.onPreferenceChangeListener = RingtoneSummaryListener() findPreference<Preference>(TextSecurePreferences.RINGTONE_PREF)!!.onPreferenceChangeListener = RingtoneSummaryListener()
findPreference<Preference>(TextSecurePreferences.NOTIFICATION_PRIVACY_PREF)!!.onPreferenceChangeListener = NotificationPrivacyListener() findPreference<Preference>(TextSecurePreferences.NOTIFICATION_PRIVACY_PREF)!!.onPreferenceChangeListener = NotificationPrivacyListener()
findPreference<Preference>(TextSecurePreferences.VIBRATE_PREF)!!.onPreferenceChangeListener = findPreference<Preference>(TextSecurePreferences.VIBRATE_PREF)!!.onPreferenceChangeListener =
@ -99,7 +99,7 @@ class NotificationsPreferenceFragment : ListSummaryPreferenceFragment() {
true true
} }
initializeListSummary(findPreference<Preference>(TextSecurePreferences.NOTIFICATION_PRIVACY_PREF) as ListPreference?) initializeListSummary(findPreference<Preference>(TextSecurePreferences.NOTIFICATION_PRIVACY_PREF) as ListPreference?)
if (NotificationChannels.supported()) {
findPreference<Preference>(TextSecurePreferences.NOTIFICATION_PRIORITY_PREF)!!.onPreferenceClickListener = findPreference<Preference>(TextSecurePreferences.NOTIFICATION_PRIORITY_PREF)!!.onPreferenceClickListener =
Preference.OnPreferenceClickListener { Preference.OnPreferenceClickListener {
val intent = Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS) val intent = Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS)
@ -110,7 +110,7 @@ class NotificationsPreferenceFragment : ListSummaryPreferenceFragment() {
startActivity(intent) startActivity(intent)
true true
} }
}
initializeRingtoneSummary(findPreference(TextSecurePreferences.RINGTONE_PREF)) initializeRingtoneSummary(findPreference(TextSecurePreferences.RINGTONE_PREF))
initializeMessageVibrateSummary(findPreference<Preference>(TextSecurePreferences.VIBRATE_PREF) as SwitchPreferenceCompat?) initializeMessageVibrateSummary(findPreference<Preference>(TextSecurePreferences.VIBRATE_PREF) as SwitchPreferenceCompat?)
} }

View File

@ -78,14 +78,9 @@ class PrivacySettingsPreferenceFragment : ListSummaryPreferenceFragment() {
title(R.string.CallNotificationBuilder_system_notification_title) title(R.string.CallNotificationBuilder_system_notification_title)
text(R.string.CallNotificationBuilder_system_notification_message) text(R.string.CallNotificationBuilder_system_notification_message)
button(R.string.activity_notification_settings_title) { button(R.string.activity_notification_settings_title) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS) Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
.putExtra(Settings.EXTRA_APP_PACKAGE, BuildConfig.APPLICATION_ID) .putExtra(Settings.EXTRA_APP_PACKAGE, BuildConfig.APPLICATION_ID)
} else { .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
.setData(Uri.parse("package:" + BuildConfig.APPLICATION_ID))
}
.apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) }
.takeIf { IntentUtils.isResolvable(requireContext(), it) }.let { .takeIf { IntentUtils.isResolvable(requireContext(), it) }.let {
startActivity(it) startActivity(it)
} }

View File

@ -7,7 +7,6 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.net.Uri import android.net.Uri
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.Parcelable import android.os.Parcelable
import android.util.SparseArray import android.util.SparseArray
@ -210,7 +209,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
override fun onCreateOptionsMenu(menu: Menu): Boolean { override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.settings_general, menu) menuInflater.inflate(R.menu.settings_general, menu)
if (BuildConfig.DEBUG && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (BuildConfig.DEBUG) {
menu.findItem(R.id.action_qr_code)?.contentDescription = resources.getString(R.string.AccessibilityId_view_qr_code) menu.findItem(R.id.action_qr_code)?.contentDescription = resources.getString(R.string.AccessibilityId_view_qr_code)
} }
return true return true

View File

@ -2,14 +2,12 @@ package org.thoughtcrime.securesms.preferences.widgets;
import android.content.Context; import android.content.Context;
import android.os.Build;
import androidx.annotation.RequiresApi;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.widget.TextView; import android.widget.TextView;
import androidx.preference.ListPreference;
import androidx.preference.PreferenceViewHolder;
import network.loki.messenger.R; import network.loki.messenger.R;
public class SignalListPreference extends ListPreference { public class SignalListPreference extends ListPreference {
@ -18,13 +16,11 @@ public class SignalListPreference extends ListPreference {
private CharSequence summary; private CharSequence summary;
private OnPreferenceClickListener clickListener; private OnPreferenceClickListener clickListener;
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public SignalListPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { public SignalListPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes); super(context, attrs, defStyleAttr, defStyleRes);
initialize(); initialize();
} }
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public SignalListPreference(Context context, AttributeSet attrs, int defStyleAttr) { public SignalListPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr); super(context, attrs, defStyleAttr);
initialize(); initialize();

View File

@ -23,7 +23,6 @@
package org.thoughtcrime.securesms.scribbles.widget; package org.thoughtcrime.securesms.scribbles.widget;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.Bitmap; import android.graphics.Bitmap;
@ -34,7 +33,6 @@ import android.graphics.Paint;
import android.graphics.Path; import android.graphics.Path;
import android.graphics.RectF; import android.graphics.RectF;
import android.graphics.Shader; import android.graphics.Shader;
import android.os.Build;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
@ -98,12 +96,6 @@ public class VerticalSlideColorPicker extends View {
init(); init();
} }
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public VerticalSlideColorPicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() { private void init() {
setWillNotDraw(false); setWillNotDraw(false);

View File

@ -18,17 +18,15 @@ package org.thoughtcrime.securesms.util;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.text.format.DateFormat;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import android.os.Build;
import android.text.format.DateFormat;
import org.session.libsignal.utilities.Log; import org.session.libsignal.utilities.Log;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.Locale; import java.util.Locale;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -127,11 +125,7 @@ public class DateUtils extends android.text.format.DateUtils {
@SuppressLint("ObsoleteSdkInt") @SuppressLint("ObsoleteSdkInt")
public static long parseIso8601(@Nullable String date) { public static long parseIso8601(@Nullable String date) {
SimpleDateFormat format; SimpleDateFormat format;
if (Build.VERSION.SDK_INT >= 24) {
format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX", Locale.getDefault()); format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX", Locale.getDefault());
} else {
format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault());
}
if (date.isEmpty()) { if (date.isEmpty()) {
return -1; return -1;

View File

@ -14,10 +14,7 @@ public class FileProviderUtil {
private static final String AUTHORITY = "network.loki.securesms.fileprovider"; private static final String AUTHORITY = "network.loki.securesms.fileprovider";
public static Uri getUriFor(@NonNull Context context, @NonNull File file) { public static Uri getUriFor(@NonNull Context context, @NonNull File file) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
return FileProvider.getUriForFile(context, AUTHORITY, file); return FileProvider.getUriForFile(context, AUTHORITY, file);
else
return Uri.fromFile(file);
} }
public static boolean delete(@NonNull Context context, @NonNull Uri uri) { public static boolean delete(@NonNull Context context, @NonNull Uri uri) {

View File

@ -1,20 +1,9 @@
package org.thoughtcrime.securesms.util package org.thoughtcrime.securesms.util
import android.content.res.Resources import android.content.res.Resources
import android.os.Build
import androidx.annotation.ColorRes
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import kotlin.math.max
import kotlin.math.roundToInt import kotlin.math.roundToInt
fun Resources.getColorWithID(@ColorRes id: Int, theme: Resources.Theme?): Int {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
getColor(id, theme)
} else {
@Suppress("DEPRECATION") getColor(id)
}
}
fun toPx(dp: Int, resources: Resources): Int { fun toPx(dp: Int, resources: Resources): Int {
return toPx(dp.toFloat(), resources).roundToInt() return toPx(dp.toFloat(), resources).roundToInt()
} }

View File

@ -11,7 +11,6 @@ import android.view.animation.AccelerateDecelerateInterpolator
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.RelativeLayout import android.widget.RelativeLayout
import androidx.annotation.ColorInt import androidx.annotation.ColorInt
import androidx.annotation.ColorRes
import network.loki.messenger.R import network.loki.messenger.R
import kotlin.math.roundToInt import kotlin.math.roundToInt
@ -22,18 +21,6 @@ interface GlowView {
object GlowViewUtilities { object GlowViewUtilities {
fun animateColorIdChange(context: Context, view: GlowView, @ColorRes startColorID: Int, @ColorRes endColorID: Int) {
val startColor = context.resources.getColorWithID(startColorID, context.theme)
val endColor = context.resources.getColorWithID(endColorID, context.theme)
val animation = ValueAnimator.ofObject(ArgbEvaluator(), startColor, endColor)
animation.duration = 250
animation.addUpdateListener { animator ->
val color = animator.animatedValue as Int
view.mainColor = color
}
animation.start()
}
fun animateColorChange(view: GlowView, @ColorInt startColor: Int, @ColorInt endColor: Int) { fun animateColorChange(view: GlowView, @ColorInt startColor: Int, @ColorInt endColor: Int) {
val animation = ValueAnimator.ofObject(ArgbEvaluator(), startColor, endColor) val animation = ValueAnimator.ofObject(ArgbEvaluator(), startColor, endColor)
animation.duration = 250 animation.duration = 250
@ -44,18 +31,6 @@ object GlowViewUtilities {
animation.start() animation.start()
} }
fun animateShadowColorIdChange(context: Context, view: GlowView, @ColorRes startColorID: Int, @ColorRes endColorID: Int) {
val startColor = context.resources.getColorWithID(startColorID, context.theme)
val endColor = context.resources.getColorWithID(endColorID, context.theme)
val animation = ValueAnimator.ofObject(ArgbEvaluator(), startColor, endColor)
animation.duration = 250
animation.addUpdateListener { animator ->
val color = animator.animatedValue as Int
view.sessionShadowColor = color
}
animation.start()
}
fun animateShadowColorChange( fun animateShadowColorChange(
view: GlowView, view: GlowView,
@ColorInt startColor: Int, @ColorInt startColor: Int,

View File

@ -1,74 +0,0 @@
package org.thoughtcrime.securesms.util;
import android.annotation.TargetApi;
import android.content.ClipData;
import android.content.Context;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import android.text.TextPaint;
import android.text.style.URLSpan;
import android.view.View;
import android.widget.Toast;
import network.loki.messenger.R;
public class LongClickCopySpan extends URLSpan {
private static final String PREFIX_MAILTO = "mailto:";
private static final String PREFIX_TEL = "tel:";
private boolean isHighlighted;
@ColorInt
private int highlightColor;
public LongClickCopySpan(String url) {
super(url);
}
void onLongClick(View widget) {
Context context = widget.getContext();
String preparedUrl = prepareUrl(getURL());
copyUrl(context, preparedUrl);
Toast.makeText(context,
context.getString(R.string.ConversationItem_copied_text, preparedUrl), Toast.LENGTH_SHORT).show();
}
@Override
public void updateDrawState(@NonNull TextPaint ds) {
super.updateDrawState(ds);
ds.bgColor = highlightColor;
ds.setUnderlineText(!isHighlighted);
}
void setHighlighted(boolean highlighted, @ColorInt int highlightColor) {
this.isHighlighted = highlighted;
this.highlightColor = highlightColor;
}
private void copyUrl(Context context, String url) {
int sdk = android.os.Build.VERSION.SDK_INT;
if (sdk < android.os.Build.VERSION_CODES.HONEYCOMB) {
@SuppressWarnings("deprecation") android.text.ClipboardManager clipboard =
(android.text.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.setText(url);
} else {
copyUriSdk11(context, url);
}
}
@TargetApi(android.os.Build.VERSION_CODES.HONEYCOMB)
private void copyUriSdk11(Context context, String url) {
android.content.ClipboardManager clipboard =
(android.content.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText(context.getString(R.string.app_name), url);
clipboard.setPrimaryClip(clip);
}
private String prepareUrl(String url) {
if (url.startsWith(PREFIX_MAILTO)) {
return url.substring(PREFIX_MAILTO.length());
} else if (url.startsWith(PREFIX_TEL)) {
return url.substring(PREFIX_TEL.length());
}
return url;
}
}

View File

@ -131,7 +131,7 @@ public class StickyHeaderDecoration extends RecyclerView.ItemDecoration {
int layoutPos) int layoutPos)
{ {
int headerHeight = getHeaderHeightForLayout(header); int headerHeight = getHeaderHeightForLayout(header);
int top = getChildY(parent, child) - headerHeight; int top = (int)child.getY() - headerHeight;
if (sticky && layoutPos == 0) { if (sticky && layoutPos == 0) {
final int count = parent.getChildCount(); final int count = parent.getChildCount();
final long currentId = adapter.getHeaderId(adapterPos); final long currentId = adapter.getHeaderId(adapterPos);
@ -142,7 +142,7 @@ public class StickyHeaderDecoration extends RecyclerView.ItemDecoration {
long nextId = adapter.getHeaderId(adapterPosHere); long nextId = adapter.getHeaderId(adapterPosHere);
if (nextId != currentId) { if (nextId != currentId) {
final View next = parent.getChildAt(translatedChildPosition(parent, i)); final View next = parent.getChildAt(translatedChildPosition(parent, i));
final int offset = getChildY(parent, next) - (headerHeight + getHeader(parent, adapter, adapterPosHere).itemView.getHeight()); final int offset = (int)next.getY() - (headerHeight + getHeader(parent, adapter, adapterPosHere).itemView.getHeight());
if (offset < 0) { if (offset < 0) {
return offset; return offset;
} else { } else {
@ -162,16 +162,6 @@ public class StickyHeaderDecoration extends RecyclerView.ItemDecoration {
return isReverseLayout(parent) ? parent.getChildCount() - 1 - position : position; return isReverseLayout(parent) ? parent.getChildCount() - 1 - position : position;
} }
private int getChildY(RecyclerView parent, View child) {
if (VERSION.SDK_INT < 11) {
Rect rect = new Rect();
parent.getChildVisibleRect(child, rect, null);
return rect.top;
} else {
return (int)ViewCompat.getY(child);
}
}
protected int getHeaderHeightForLayout(View header) { protected int getHeaderHeightForLayout(View header) {
return renderInline ? 0 : header.getHeight(); return renderInline ? 0 : header.getHeight();
} }

View File

@ -1,22 +1,20 @@
package org.thoughtcrime.securesms.video; package org.thoughtcrime.securesms.video;
import android.annotation.TargetApi;
import android.media.MediaDataSource; import android.media.MediaDataSource;
import android.os.Build;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import org.session.libsession.utilities.Util;
import org.thoughtcrime.securesms.crypto.AttachmentSecret; import org.thoughtcrime.securesms.crypto.AttachmentSecret;
import org.thoughtcrime.securesms.crypto.ClassicDecryptingPartInputStream; import org.thoughtcrime.securesms.crypto.ClassicDecryptingPartInputStream;
import org.thoughtcrime.securesms.crypto.ModernDecryptingPartInputStream; import org.thoughtcrime.securesms.crypto.ModernDecryptingPartInputStream;
import org.session.libsession.utilities.Util;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@TargetApi(Build.VERSION_CODES.M)
public class EncryptedMediaDataSource extends MediaDataSource { public class EncryptedMediaDataSource extends MediaDataSource {
private final AttachmentSecret attachmentSecret; private final AttachmentSecret attachmentSecret;

View File

@ -8,10 +8,8 @@ import android.media.AudioDeviceInfo;
import android.media.AudioFocusRequest; import android.media.AudioFocusRequest;
import android.media.AudioManager; import android.media.AudioManager;
import android.media.SoundPool; import android.media.SoundPool;
import android.os.Build;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import org.session.libsession.utilities.ServiceUtil; import org.session.libsession.utilities.ServiceUtil;
import org.session.libsignal.utilities.Log; import org.session.libsignal.utilities.Log;
@ -116,14 +114,9 @@ public abstract class AudioManagerCompat {
abstract public void abandonCallAudioFocus(); abstract public void abandonCallAudioFocus();
public static AudioManagerCompat create(@NonNull Context context) { public static AudioManagerCompat create(@NonNull Context context) {
if (Build.VERSION.SDK_INT >= 26) {
return new Api26AudioManagerCompat(context); return new Api26AudioManagerCompat(context);
} else {
return new Api21AudioManagerCompat(context);
}
} }
@RequiresApi(26)
private static class Api26AudioManagerCompat extends AudioManagerCompat { private static class Api26AudioManagerCompat extends AudioManagerCompat {
private static AudioAttributes AUDIO_ATTRIBUTES = new AudioAttributes.Builder() private static AudioAttributes AUDIO_ATTRIBUTES = new AudioAttributes.Builder()
@ -180,44 +173,4 @@ public abstract class AudioManagerCompat {
audioFocusRequest = null; audioFocusRequest = null;
} }
} }
@RequiresApi(21)
private static class Api21AudioManagerCompat extends AudioManagerCompat {
private static AudioAttributes AUDIO_ATTRIBUTES = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
.setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
.setLegacyStreamType(AudioManager.STREAM_VOICE_CALL)
.build();
private Api21AudioManagerCompat(@NonNull Context context) {
super(context);
}
@Override
public SoundPool createSoundPool() {
return new SoundPool.Builder()
.setAudioAttributes(AUDIO_ATTRIBUTES)
.setMaxStreams(1)
.build();
}
@Override
public void requestCallAudioFocus() {
int result = audioManager.requestAudioFocus(onAudioFocusChangeListener, AudioManager.STREAM_VOICE_CALL, AUDIOFOCUS_GAIN);
if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
Log.w(TAG, "Audio focus not granted. Result code: " + result);
}
}
@Override
public void abandonCallAudioFocus() {
int result = audioManager.abandonAudioFocus(onAudioFocusChangeListener);
if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
Log.w(TAG, "Audio focus abandon failed. Result code: " + result);
}
}
}
} }

View File

@ -69,7 +69,7 @@ allprojects {
} }
project.ext { project.ext {
androidMinimumSdkVersion = 23 androidMinimumSdkVersion = 26
androidTargetSdkVersion = 34 androidTargetSdkVersion = 34
androidCompileSdkVersion = 34 androidCompileSdkVersion = 34
} }

View File

@ -73,8 +73,8 @@ object SnodeAPI {
private const val maxRetryCount = 6 private const val maxRetryCount = 6
private const val minimumSnodePoolCount = 12 private const val minimumSnodePoolCount = 12
private const val minimumSwarmSnodeCount = 3 private const val minimumSwarmSnodeCount = 3
// Use port 4433 if the API level can handle the network security configuration and enforce pinned certificates // Use port 4433 to enforce pinned certificates
private val seedNodePort = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) 443 else 4443 private val seedNodePort = 4443
private const val useTestnet = false private const val useTestnet = false

View File

@ -5,17 +5,12 @@ import android.media.MediaCodec
import android.media.MediaDataSource import android.media.MediaDataSource
import android.media.MediaExtractor import android.media.MediaExtractor
import android.media.MediaFormat import android.media.MediaFormat
import android.os.Build
import androidx.annotation.RequiresApi
import java.io.FileDescriptor import java.io.FileDescriptor
import java.io.IOException import java.io.IOException
import java.io.InputStream import java.io.InputStream
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.nio.ByteOrder import java.nio.ByteOrder
import java.nio.ShortBuffer import java.nio.ShortBuffer
import kotlin.jvm.Throws
import kotlin.math.ceil import kotlin.math.ceil
import kotlin.math.roundToInt import kotlin.math.roundToInt
import kotlin.math.sqrt import kotlin.math.sqrt
@ -44,7 +39,6 @@ class DecodedAudio {
} }
@JvmStatic @JvmStatic
@RequiresApi(api = Build.VERSION_CODES.M)
@Throws(IOException::class) @Throws(IOException::class)
fun create(dataSource: MediaDataSource): DecodedAudio { fun create(dataSource: MediaDataSource): DecodedAudio {
val mediaExtractor = MediaExtractor().apply { setDataSource(dataSource) } val mediaExtractor = MediaExtractor().apply { setDataSource(dataSource) }
@ -69,15 +63,7 @@ class DecodedAudio {
val samples: ShortBuffer val samples: ShortBuffer
get() { get() {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && return decodedSamples.asReadOnlyBuffer()
Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1
) {
// Hack for Nougat where asReadOnlyBuffer fails to respect byte ordering.
// See https://code.google.com/p/android/issues/detail?id=223824
decodedSamples
} else {
decodedSamples.asReadOnlyBuffer()
}
} }
/** /**
@ -128,7 +114,6 @@ class DecodedAudio {
codec.start() codec.start()
// Check if the track is in PCM 16 bit encoding. // Check if the track is in PCM 16 bit encoding.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
try { try {
val pcmEncoding = codec.outputFormat.getInteger(MediaFormat.KEY_PCM_ENCODING) val pcmEncoding = codec.outputFormat.getInteger(MediaFormat.KEY_PCM_ENCODING)
if (pcmEncoding != AudioFormat.ENCODING_PCM_16BIT) { if (pcmEncoding != AudioFormat.ENCODING_PCM_16BIT) {
@ -137,7 +122,6 @@ class DecodedAudio {
} catch (e: NullPointerException) { } catch (e: NullPointerException) {
// If KEY_PCM_ENCODING is not specified, means it's ENCODING_PCM_16BIT. // If KEY_PCM_ENCODING is not specified, means it's ENCODING_PCM_16BIT.
} }
}
var decodedSamplesSize: Int = 0 // size of the output buffer containing decoded samples. var decodedSamplesSize: Int = 0 // size of the output buffer containing decoded samples.
var decodedSamples: ByteArray? = null var decodedSamples: ByteArray? = null

View File

@ -6,13 +6,8 @@ import android.app.NotificationManager;
import android.content.Context; import android.content.Context;
import android.media.AudioManager; import android.media.AudioManager;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.os.Build;
import android.os.PowerManager; import android.os.PowerManager;
import android.os.Vibrator; import android.os.Vibrator;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import android.view.WindowManager; import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
@ -54,8 +49,4 @@ public class ServiceUtil {
return (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE); return (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
} }
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP_MR1)
public static @Nullable SubscriptionManager getSubscriptionManager(@NonNull Context context) {
return (SubscriptionManager) context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
}
} }

View File

@ -19,21 +19,16 @@ package org.session.libsession.utilities;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewStub;
import android.view.animation.AlphaAnimation; import android.view.animation.AlphaAnimation;
import android.view.animation.Animation; import android.view.animation.Animation;
import android.widget.LinearLayout.LayoutParams;
import androidx.annotation.IdRes; import androidx.annotation.IdRes;
import androidx.annotation.LayoutRes; import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat;
import androidx.interpolator.view.animation.FastOutSlowInInterpolator; import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
import org.session.libsignal.utilities.ListenableFuture; import org.session.libsignal.utilities.ListenableFuture;
@ -42,58 +37,7 @@ import org.session.libsignal.utilities.SettableFuture;
public class ViewUtil { public class ViewUtil {
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public static void setBackground(final @NonNull View v, final @Nullable Drawable drawable) { public static void setBackground(final @NonNull View v, final @Nullable Drawable drawable) {
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {
v.setBackground(drawable); 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);
}
}
public static float getY(final @NonNull View v) {
if (VERSION.SDK_INT >= 11) {
return ViewCompat.getY(v);
} else {
return ((ViewGroup.MarginLayoutParams)v.getLayoutParams()).topMargin;
}
}
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);
}
}
public static float getX(final @NonNull View v) {
if (VERSION.SDK_INT >= 11) {
return ViewCompat.getX(v);
} else {
return ((LayoutParams)v.getLayoutParams()).leftMargin;
}
}
public static void swapChildInPlace(ViewGroup parent, View toRemove, View toAdd, int defaultIndex) {
int childIndex = parent.indexOfChild(toRemove);
if (childIndex > -1) parent.removeView(toRemove);
parent.addView(toAdd, childIndex > -1 ? childIndex : defaultIndex);
}
@SuppressWarnings("unchecked")
public static <T extends View> T inflateStub(@NonNull View parent, @IdRes int stubId) {
return (T)((ViewStub)parent.findViewById(stubId)).inflate();
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -106,10 +50,6 @@ public class ViewUtil {
return (T) parent.findViewById(resId); return (T) parent.findViewById(resId);
} }
public static <T extends View> Stub<T> findStubById(@NonNull Activity parent, @IdRes int resId) {
return new Stub<T>((ViewStub)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());
@ -177,58 +117,4 @@ public class ViewUtil {
return (int)((dp * context.getResources().getDisplayMetrics().density) + 0.5); return (int)((dp * context.getResources().getDisplayMetrics().density) + 0.5);
} }
public static void updateLayoutParams(@NonNull View view, int width, int height) {
view.getLayoutParams().width = width;
view.getLayoutParams().height = height;
view.requestLayout();
}
public static int getLeftMargin(@NonNull View view) {
if (ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_LTR) {
return ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).leftMargin;
}
return ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).rightMargin;
}
public static int getRightMargin(@NonNull View view) {
if (ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_LTR) {
return ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).rightMargin;
}
return ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).leftMargin;
}
public static void setLeftMargin(@NonNull View view, int margin) {
if (ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_LTR) {
((ViewGroup.MarginLayoutParams) view.getLayoutParams()).leftMargin = margin;
} else {
((ViewGroup.MarginLayoutParams) view.getLayoutParams()).rightMargin = margin;
}
view.forceLayout();
view.requestLayout();
}
public static void setTopMargin(@NonNull View view, int margin) {
((ViewGroup.MarginLayoutParams) view.getLayoutParams()).topMargin = margin;
view.requestLayout();
}
public static void setPaddingTop(@NonNull View view, int padding) {
view.setPadding(view.getPaddingLeft(), padding, view.getPaddingRight(), view.getPaddingBottom());
}
public static void setPaddingBottom(@NonNull View view, int padding) {
view.setPadding(view.getPaddingLeft(), view.getPaddingTop(), view.getPaddingRight(), padding);
}
public static boolean isPointInsideView(@NonNull View view, float x, float y) {
int[] location = new int[2];
view.getLocationOnScreen(location);
int viewX = location[0];
int viewY = location[1];
return x > viewX && x < viewX + view.getWidth() &&
y > viewY && y < viewY + view.getHeight();
}
} }

View File

@ -718,7 +718,7 @@ public class Recipient implements RecipientModifiedListener {
} }
public synchronized @Nullable String getNotificationChannel() { public synchronized @Nullable String getNotificationChannel() {
return !(Build.VERSION.SDK_INT >= 26) ? null : notificationChannel; return notificationChannel;
} }
public void setNotificationChannel(@Nullable String value) { public void setNotificationChannel(@Nullable String value) {