mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-22 18:00:02 +01:00
Optimize uploads during media composition.
By uploading in advance (when on unmetered connections), media messages can send almost instantly.
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
package org.thoughtcrime.securesms.util;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Helps determine the difference between two collections based on their {@link #equals(Object)}
|
||||
* implementations.
|
||||
*/
|
||||
public class DiffHelper {
|
||||
|
||||
/**
|
||||
* @return Result indicating the differences between the two collections. Important: The iteration
|
||||
* order of the result will not necessarily match the iteration order of the original
|
||||
* collection.
|
||||
*/
|
||||
public static <E> Result<E> calculate(@NonNull Collection<E> oldList, @NonNull Collection<E> newList) {
|
||||
Set<E> inserted = SetUtil.difference(newList, oldList);
|
||||
Set<E> removed = SetUtil.difference(oldList, newList);
|
||||
|
||||
return new Result<>(inserted, removed);
|
||||
}
|
||||
|
||||
public static class Result<E> {
|
||||
private final Collection<E> inserted;
|
||||
private final Collection<E> removed;
|
||||
|
||||
public Result(@NonNull Collection<E> inserted, @NonNull Collection<E> removed) {
|
||||
this.removed = removed;
|
||||
this.inserted = inserted;
|
||||
}
|
||||
|
||||
public @NonNull Collection<E> getInserted() {
|
||||
return inserted;
|
||||
}
|
||||
|
||||
public @NonNull Collection<E> getRemoved() {
|
||||
return removed;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package org.thoughtcrime.securesms.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.mms.TextSlide;
|
||||
import org.thoughtcrime.securesms.providers.BlobProvider;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
public final class MessageUtil {
|
||||
|
||||
private MessageUtil() {}
|
||||
|
||||
/**
|
||||
* @return If the message is longer than the allowed text size, this will return trimmed text with
|
||||
* an accompanying TextSlide. Otherwise it'll just return the original text.
|
||||
*/
|
||||
public static SplitResult getSplitMessage(@NonNull Context context, @NonNull String rawText, int maxPrimaryMessageSize) {
|
||||
String bodyText = rawText;
|
||||
Optional<TextSlide> textSlide = Optional.absent();
|
||||
|
||||
if (bodyText.length() > maxPrimaryMessageSize) {
|
||||
bodyText = rawText.substring(0, maxPrimaryMessageSize);
|
||||
|
||||
byte[] textData = rawText.getBytes();
|
||||
String timestamp = new SimpleDateFormat("yyyy-MM-dd-HHmmss", Locale.US).format(new Date());
|
||||
String filename = String.format("signal-%s.txt", timestamp);
|
||||
Uri textUri = BlobProvider.getInstance()
|
||||
.forData(textData)
|
||||
.withMimeType(MediaUtil.LONG_TEXT)
|
||||
.withFileName(filename)
|
||||
.createForSingleSessionInMemory();
|
||||
|
||||
textSlide = Optional.of(new TextSlide(context, textUri, filename, textData.length));
|
||||
}
|
||||
|
||||
return new SplitResult(bodyText, textSlide);
|
||||
}
|
||||
|
||||
public static class SplitResult {
|
||||
private final String body;
|
||||
private final Optional<TextSlide> textSlide;
|
||||
|
||||
private SplitResult(@NonNull String body, @NonNull Optional<TextSlide> textSlide) {
|
||||
this.body = body;
|
||||
this.textSlide = textSlide;
|
||||
}
|
||||
|
||||
public @NonNull String getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public @NonNull Optional<TextSlide> getTextSlide() {
|
||||
return textSlide;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,15 @@ package org.thoughtcrime.securesms.util;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.attachments.AttachmentId;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class ParcelUtil {
|
||||
|
||||
public static byte[] serialize(Parcelable parceable) {
|
||||
@@ -25,4 +34,31 @@ public class ParcelUtil {
|
||||
return creator.createFromParcel(parcel);
|
||||
}
|
||||
|
||||
public static void writeStringCollection(@NonNull Parcel dest, @NonNull Collection<String> collection) {
|
||||
dest.writeStringList(new ArrayList<>(collection));
|
||||
}
|
||||
|
||||
public static @NonNull Collection<String> readStringCollection(@NonNull Parcel in) {
|
||||
List<String> list = new ArrayList<>();
|
||||
in.readStringList(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
public static void writeParcelableCollection(@NonNull Parcel dest, @NonNull Collection<? extends Parcelable> collection) {
|
||||
Parcelable[] values = collection.toArray(new Parcelable[0]);
|
||||
dest.writeParcelableArray(values, 0);
|
||||
}
|
||||
|
||||
public static @NonNull <E> Collection<E> readParcelableCollection(@NonNull Parcel in, Class<E> clazz) {
|
||||
//noinspection unchecked
|
||||
return Arrays.asList((E[]) in.readParcelableArray(clazz.getClassLoader()));
|
||||
}
|
||||
|
||||
public static void writeBoolean(@NonNull Parcel dest, boolean value) {
|
||||
dest.writeByte(value ? (byte) 1 : 0);
|
||||
}
|
||||
|
||||
public static boolean readBoolean(@NonNull Parcel in) {
|
||||
return in.readByte() != 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
package org.thoughtcrime.securesms.util;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public final class SetUtil {
|
||||
private SetUtil() {}
|
||||
|
||||
public static <E> Set<E> intersection(Set<E> a, Set<E> b) {
|
||||
public static <E> Set<E> intersection(Collection<E> a, Collection<E> b) {
|
||||
Set<E> intersection = new LinkedHashSet<>(a);
|
||||
intersection.retainAll(b);
|
||||
return intersection;
|
||||
}
|
||||
|
||||
public static <E> Set<E> difference(Set<E> a, Set<E> b) {
|
||||
public static <E> Set<E> difference(Collection<E> a, Collection<E> b) {
|
||||
Set<E> difference = new LinkedHashSet<>(a);
|
||||
difference.removeAll(b);
|
||||
return difference;
|
||||
|
||||
Reference in New Issue
Block a user