remove com.annimon:stream dependency

This commit is contained in:
adbenitez 2025-08-07 17:45:01 +02:00
parent a68f3a7024
commit fd057485db
7 changed files with 61 additions and 86 deletions

View file

@ -187,7 +187,6 @@ dependencies {
implementation ('com.davemorrissey.labs:subsampling-scale-image-view:3.10.0') { // for the zooming on photos / media
exclude group: 'com.android.support', module: 'support-annotations'
}
implementation 'com.annimon:stream:1.1.8' // brings future java streams api to SDK Version < 24
// Replacement for ContentResolver
// that protects against the Surreptitious Sharing attack.

View file

@ -35,7 +35,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.amulyakhare.textdrawable.TextDrawable;
import com.annimon.stream.Stream;
import com.b44t.messenger.DcChat;
import com.b44t.messenger.DcContact;
import com.b44t.messenger.DcContext;
@ -55,7 +54,6 @@ import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import java.util.Collections;
import java.util.List;
import java.util.Set;
public class ConversationListItem extends RelativeLayout
@ -318,15 +316,12 @@ public class ConversationListItem extends RelativeLayout
String normalizedValue = value.toLowerCase(Util.getLocale());
String normalizedTest = highlight.toLowerCase(Util.getLocale());
List<String> testTokens;
try (Stream<String> stream = Stream.of(normalizedTest.split(" "))) {
testTokens = stream.filter(s -> !s.trim().isEmpty()).toList();
}
Spannable spanned = new SpannableString(value);
int searchStartIndex = 0;
for (String token : testTokens) {
for (String token : normalizedTest.split(" ")) {
if (token.trim().isEmpty()) continue;
if (searchStartIndex >= spanned.length()) {
break;
}

View file

@ -16,7 +16,6 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.annimon.stream.Stream;
import com.b44t.messenger.DcContact;
import com.b44t.messenger.DcMsg;
import com.b44t.messenger.rpc.RpcException;
@ -194,18 +193,17 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
}
private void setQuoteAttachment(@NonNull GlideRequests glideRequests, @NonNull SlideDeck slideDeck) {
List<Slide> thumbnailSlides = Stream.of(slideDeck.getSlides()).filter(s -> s.hasImage() || s.hasVideo() || s.hasSticker() || s.isWebxdcDocument() || s.isVcard()).limit(1).toList();
List<Slide> audioSlides = Stream.of(slideDeck.getSlides()).filter(s -> s.hasAudio()).limit(1).toList();
List<Slide> documentSlides = Stream.of(attachments.getSlides()).filter(Slide::hasDocument).limit(1).toList();
List<Slide> slides = slideDeck.getSlides();
Slide slide = slides.isEmpty()? null : slides.get(0);
attachmentVideoOverlayView.setVisibility(GONE);
if (!thumbnailSlides.isEmpty() && thumbnailSlides.get(0).getUri() != null) {
if (slide != null && slide.hasQuoteThumbnail()) {
thumbnailView.setVisibility(VISIBLE);
attachmentContainerView.setVisibility(GONE);
dismissView.setBackgroundResource(R.drawable.dismiss_background);
if (thumbnailSlides.get(0).isWebxdcDocument()) {
if (slide.isWebxdcDocument()) {
try {
JSONObject info = quotedMsg.getWebxdcInfo();
byte[] blob = quotedMsg.getWebxdcBlob(info.getString("icon"));
@ -218,7 +216,7 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
Log.e(TAG, "failed to get webxdc icon", e);
thumbnailView.setVisibility(GONE);
}
} else if (thumbnailSlides.get(0).isVcard()) {
} else if (slide.isVcard()) {
try {
VcardContact vcardContact = DcHelper.getRpc(getContext()).parseVcard(quotedMsg.getFile()).get(0);
Recipient recipient = new Recipient(getContext(), vcardContact);
@ -233,11 +231,11 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
thumbnailView.setVisibility(GONE);
}
} else {
Uri thumbnailUri = thumbnailSlides.get(0).getUri();
if (thumbnailSlides.get(0).hasVideo()) {
Uri thumbnailUri = slide.getUri();
if (slide.hasVideo()) {
attachmentVideoOverlayView.setVisibility(VISIBLE);
MediaUtil.createVideoThumbnailIfNeeded(getContext(), thumbnailSlides.get(0).getUri(), thumbnailSlides.get(0).getThumbnailUri(), null);
thumbnailUri = thumbnailSlides.get(0).getThumbnailUri();
MediaUtil.createVideoThumbnailIfNeeded(getContext(), slide.getUri(), slide.getThumbnailUri(), null);
thumbnailUri = slide.getThumbnailUri();
}
glideRequests.load(new DecryptableUri(thumbnailUri))
.centerCrop()
@ -245,10 +243,10 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
.into(thumbnailView);
}
} else if(!audioSlides.isEmpty()) {
} else if(slide != null && slide.hasAudio()) {
thumbnailView.setVisibility(GONE);
attachmentContainerView.setVisibility(GONE);
} else if (!documentSlides.isEmpty()) {
} else if (slide != null && slide.hasDocument()) {
thumbnailView.setVisibility(GONE);
attachmentContainerView.setVisibility(VISIBLE);
} else {

View file

@ -6,7 +6,6 @@ import android.content.Context;
import androidx.annotation.NonNull;
import androidx.loader.content.AsyncTaskLoader;
import com.annimon.stream.Stream;
import com.b44t.messenger.DcContext;
import com.b44t.messenger.DcMsg;
@ -128,28 +127,38 @@ public class BucketedThreadMediaLoader extends AsyncTaskLoader<BucketedThreadMed
}
public int getSectionCount() {
return (int)Stream.of(TIME_SECTIONS)
.filter(timeBucket -> !timeBucket.isEmpty())
.count() +
OLDER.getSectionCount();
int count = 0;
for (TimeBucket section : TIME_SECTIONS) {
if (!section.isEmpty()) count++;
}
return count + OLDER.getSectionCount();
}
public int getSectionItemCount(int section) {
List<TimeBucket> activeTimeBuckets = Stream.of(TIME_SECTIONS).filter(timeBucket -> !timeBucket.isEmpty()).toList();
List<TimeBucket> activeTimeBuckets = new ArrayList<>();
for (TimeBucket bucket : TIME_SECTIONS) {
if (!bucket.isEmpty()) activeTimeBuckets.add(bucket);
}
if (section < activeTimeBuckets.size()) return activeTimeBuckets.get(section).getItemCount();
else return OLDER.getSectionItemCount(section - activeTimeBuckets.size());
}
public DcMsg get(int section, int item) {
List<TimeBucket> activeTimeBuckets = Stream.of(TIME_SECTIONS).filter(timeBucket -> !timeBucket.isEmpty()).toList();
List<TimeBucket> activeTimeBuckets = new ArrayList<>();
for (TimeBucket bucket : TIME_SECTIONS) {
if (!bucket.isEmpty()) activeTimeBuckets.add(bucket);
}
if (section < activeTimeBuckets.size()) return activeTimeBuckets.get(section).getItem(item);
else return OLDER.getItem(section - activeTimeBuckets.size(), item);
}
public String getName(int section) {
List<TimeBucket> activeTimeBuckets = Stream.of(TIME_SECTIONS).filter(timeBucket -> !timeBucket.isEmpty()).toList();
List<TimeBucket> activeTimeBuckets = new ArrayList<>();
for (TimeBucket bucket : TIME_SECTIONS) {
if (!bucket.isEmpty()) activeTimeBuckets.add(bucket);
}
if (section < activeTimeBuckets.size()) return activeTimeBuckets.get(section).getName();
else return OLDER.getName(section - activeTimeBuckets.size());

View file

@ -76,6 +76,11 @@ public abstract class Slide {
return attachment.getSize();
}
/* Return true if this slide has a thumbnail when being quoted, false otherwise */
public boolean hasQuoteThumbnail() {
return (hasImage() || hasVideo() || hasSticker() || isWebxdcDocument() || isVcard()) && getUri() != null;
}
public boolean hasImage() {
return false;
}

View file

@ -21,15 +21,13 @@ import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import com.annimon.stream.Stream;
import com.annimon.stream.function.Consumer;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.util.LRUCache;
import org.thoughtcrime.securesms.util.ServiceUtil;
import java.lang.ref.WeakReference;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@ -70,10 +68,6 @@ public class Permissions {
private Runnable anyPermanentlyDeniedListener;
private Runnable anyResultListener;
private Consumer<List<String>> someGrantedListener;
private Consumer<List<String>> someDeniedListener;
private Consumer<List<String>> somePermanentlyDeniedListener;
private @DrawableRes int[] rationalDialogHeader;
private String rationaleDialogMessage;
@ -148,29 +142,13 @@ public class Permissions {
return this;
}
public PermissionsBuilder onSomeGranted(Consumer<List<String>> someGrantedListener) {
this.someGrantedListener = someGrantedListener;
return this;
}
public PermissionsBuilder onSomeDenied(Consumer<List<String>> someDeniedListener) {
this.someDeniedListener = someDeniedListener;
return this;
}
public PermissionsBuilder onSomePermanentlyDenied(Consumer<List<String>> somePermanentlyDeniedListener) {
this.somePermanentlyDeniedListener = somePermanentlyDeniedListener;
return this;
}
public void execute() {
if (alwaysGranted) {
allGrantedListener.run();
return;
}
PermissionsRequest request = new PermissionsRequest(allGrantedListener, anyDeniedListener, anyPermanentlyDeniedListener, anyResultListener,
someGrantedListener, someDeniedListener, somePermanentlyDeniedListener);
PermissionsRequest request = new PermissionsRequest(allGrantedListener, anyDeniedListener, anyPermanentlyDeniedListener, anyResultListener);
if (ifNecesary && (permissionObject.hasAll(requestedPermissions) || !condition)) {
executePreGrantedPermissionsRequest(request);
@ -183,7 +161,7 @@ public class Permissions {
private void executePreGrantedPermissionsRequest(PermissionsRequest request) {
int[] grantResults = new int[requestedPermissions.length];
for (int i=0;i<grantResults.length;i++) grantResults[i] = PackageManager.PERMISSION_GRANTED;
Arrays.fill(grantResults, PackageManager.PERMISSION_GRANTED);
request.onResult(requestedPermissions, grantResults, new boolean[requestedPermissions.length]);
}
@ -218,7 +196,8 @@ public class Permissions {
}
String[] permissions = filterNotGranted(permissionObject.getContext(), requestedPermissions);
int[] grantResults = Stream.of(permissions).mapToInt(permission -> PackageManager.PERMISSION_DENIED).toArray();
int[] grantResults = new int[permissions.length];
Arrays.fill(grantResults, PackageManager.PERMISSION_DENIED);
boolean[] showDialog = new boolean[permissions.length];
Arrays.fill(showDialog, true);
@ -236,22 +215,29 @@ public class Permissions {
}
private static String[] filterNotGranted(@NonNull Context context, String... permissions) {
return Stream.of(permissions)
.filter(permission -> ContextCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED)
.toList()
.toArray(new String[0]);
List<String> notGranted = new ArrayList<>();
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
notGranted.add(permission);
}
}
return notGranted.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);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return true;
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED) return true;
}
return false;
}
public static boolean hasAll(@NonNull Context context, String... permissions) {
return Build.VERSION.SDK_INT < Build.VERSION_CODES.M ||
Stream.of(permissions).allMatch(permission -> ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return true;
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) return false;
}
return true;
}
public static void onRequestPermissionsResult(Fragment fragment, int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

View file

@ -5,8 +5,6 @@ import android.content.pm.PackageManager;
import androidx.annotation.Nullable;
import com.annimon.stream.function.Consumer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -22,27 +20,16 @@ class PermissionsRequest {
private final @Nullable Runnable anyPermanentlyDeniedListener;
private final @Nullable Runnable anyResultListener;
private final @Nullable Consumer<List<String>> someGrantedListener;
private final @Nullable Consumer<List<String>> someDeniedListener;
private final @Nullable Consumer<List<String>> somePermanentlyDeniedListener;
PermissionsRequest(@Nullable Runnable allGrantedListener,
@Nullable Runnable anyDeniedListener,
@Nullable Runnable anyPermanentlyDeniedListener,
@Nullable Runnable anyResultListener,
@Nullable Consumer<List<String>> someGrantedListener,
@Nullable Consumer<List<String>> someDeniedListener,
@Nullable Consumer<List<String>> somePermanentlyDeniedListener)
@Nullable Runnable anyResultListener)
{
this.allGrantedListener = allGrantedListener;
this.anyDeniedListener = anyDeniedListener;
this.anyPermanentlyDeniedListener = anyPermanentlyDeniedListener;
this.anyResultListener = anyResultListener;
this.someGrantedListener = someGrantedListener;
this.someDeniedListener = someDeniedListener;
this.somePermanentlyDeniedListener = somePermanentlyDeniedListener;
}
void onResult(String[] permissions, int[] grantResults, boolean[] shouldShowRationaleDialog) {
@ -56,9 +43,9 @@ class PermissionsRequest {
} else {
boolean preRequestShouldShowRationaleDialog = PRE_REQUEST_MAPPING.get(permissions[i]);
if ((somePermanentlyDeniedListener != null || anyPermanentlyDeniedListener != null) &&
!preRequestShouldShowRationaleDialog && !shouldShowRationaleDialog[i])
{
if (anyPermanentlyDeniedListener != null
&& !preRequestShouldShowRationaleDialog
&& !shouldShowRationaleDialog[i]) {
permanentlyDenied.add(permissions[i]);
} else {
denied.add(permissions[i]);
@ -68,18 +55,14 @@ class PermissionsRequest {
if (allGrantedListener != null && !granted.isEmpty() && (denied.isEmpty() && permanentlyDenied.isEmpty())) {
allGrantedListener.run();
} else if (someGrantedListener != null && !granted.isEmpty()) {
someGrantedListener.accept(granted);
}
if (!denied.isEmpty()) {
if (anyDeniedListener != null) anyDeniedListener.run();
if (someDeniedListener != null) someDeniedListener.accept(denied);
}
if (!permanentlyDenied.isEmpty()) {
if (anyPermanentlyDeniedListener != null) anyPermanentlyDeniedListener.run();
if (somePermanentlyDeniedListener != null) somePermanentlyDeniedListener.accept(permanentlyDenied);
}
if (anyResultListener != null) {