Improve message requests, add megaphone.

This commit is contained in:
Alex Hart
2020-02-19 18:08:34 -04:00
committed by Greyson Parrelli
parent dc689d325b
commit 9e5f64c431
83 changed files with 2406 additions and 735 deletions

View File

@@ -47,7 +47,6 @@ public final class FeatureFlags {
private static final long FETCH_INTERVAL = TimeUnit.HOURS.toMillis(2);
private static final String UUIDS = generateKey("uuids");
private static final String PROFILE_DISPLAY = generateKey("profileDisplay");
private static final String MESSAGE_REQUESTS = generateKey("messageRequests");
private static final String USERNAMES = generateKey("usernames");
private static final String STORAGE_SERVICE = generateKey("storageService");
@@ -65,7 +64,8 @@ public final class FeatureFlags {
VIDEO_TRIMMING,
PINS_FOR_ALL,
PINS_MEGAPHONE_KILL_SWITCH,
PROFILE_NAMES_MEGAPHONE
PROFILE_NAMES_MEGAPHONE,
MESSAGE_REQUESTS
);
/**
@@ -139,7 +139,7 @@ public final class FeatureFlags {
/** Favoring profile names when displaying contacts. */
public static synchronized boolean profileDisplay() {
return getValue(PROFILE_DISPLAY, false);
return messageRequests();
}
/** MessageRequest stuff */
@@ -172,7 +172,7 @@ public final class FeatureFlags {
}
/** Safety switch for disabling profile names megaphone */
public static boolean profileNamesMegaphoneEnabled() {
public static boolean profileNamesMegaphone() {
return getValue(PROFILE_NAMES_MEGAPHONE, false) &&
TextSecurePreferences.getFirstInstallVersion(ApplicationDependencies.getApplication()) < 600;
}

View File

@@ -0,0 +1,9 @@
package org.thoughtcrime.securesms.util;
import androidx.annotation.NonNull;
public class HtmlUtil {
public static @NonNull String bold(@NonNull String target) {
return "<b>" + target + "</b>";
}
}

View File

@@ -0,0 +1,43 @@
package org.thoughtcrime.securesms.util;
import androidx.annotation.Nullable;
import androidx.core.util.ObjectsCompat;
public class Triple<A, B, C> {
private final A a;
private final B b;
private final C c;
public Triple(@Nullable A a, @Nullable B b, @Nullable C c) {
this.a = a;
this.b = b;
this.c = c;
}
public @Nullable A first() {
return a;
}
public @Nullable B second() {
return b;
}
public @Nullable C third() {
return c;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Triple)) {
return false;
}
Triple<?, ?, ?> t = (Triple<?, ?, ?>) o;
return ObjectsCompat.equals(t.a, a) && ObjectsCompat.equals(t.b, b) && ObjectsCompat.equals(t.c, c);
}
@Override
public int hashCode() {
return (a == null ? 0 : a.hashCode()) ^ (b == null ? 0 : b.hashCode()) ^ (c == null ? 0 : c.hashCode());
}
}

View File

@@ -320,6 +320,17 @@ public class Util {
return Optional.fromNullable(simCountryIso != null ? simCountryIso.toUpperCase() : null);
}
@SafeVarargs
public static @NonNull <T> T firstNonNull(T ... ts) {
for (T t : ts) {
if (t != null) {
return t;
}
}
throw new IllegalStateException("All choices were null.");
}
public static <T> List<List<T>> partition(List<T> list, int partitionSize) {
List<List<T>> results = new LinkedList<>();

View File

@@ -0,0 +1,136 @@
package org.thoughtcrime.securesms.util.livedata;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MediatorLiveData;
import org.thoughtcrime.securesms.util.Triple;
import org.whispersystems.libsignal.util.Pair;
public final class LiveDataTriple<A, B, C> extends MediatorLiveData<Triple<A, B, C>> {
private A a;
private B b;
private C c;
public LiveDataTriple(@NonNull LiveData<A> liveDataA,
@NonNull LiveData<B> liveDataB,
@NonNull LiveData<C> liveDataC)
{
this(liveDataA, liveDataB, liveDataC, null, null, null);
}
public LiveDataTriple(@NonNull LiveData<A> liveDataA,
@NonNull LiveData<B> liveDataB,
@NonNull LiveData<C> liveDataC,
@Nullable A initialA,
@Nullable B initialB,
@Nullable C initialC)
{
a = initialA;
b = initialB;
c = initialC;
setValue(new Triple<>(a, b, c));
if (liveDataA == liveDataB && liveDataA == liveDataC) {
addSource(liveDataA, a -> {
if (a != null) {
this.a = a;
//noinspection unchecked: A is B if live datas are same instance
this.b = (B) a;
//noinspection unchecked: A is C if live datas are same instance
this.c = (C) a;
}
setValue(new Triple<>(a, b, c));
});
} else if (liveDataA == liveDataB) {
addSource(liveDataA, a -> {
if (a != null) {
this.a = a;
//noinspection unchecked: A is B if live datas are same instance
this.b = (B) a;
}
setValue(new Triple<>(a, b, c));
});
addSource(liveDataC, c -> {
if (c != null) {
this.c = c;
}
setValue(new Triple<>(a, b, c));
});
} else if (liveDataA == liveDataC) {
addSource(liveDataA, a -> {
if (a != null) {
this.a = a;
//noinspection unchecked: A is C if live datas are same instance
this.c = (C) a;
}
setValue(new Triple<>(a, b, c));
});
addSource(liveDataB, b -> {
if (b != null) {
this.b = b;
}
setValue(new Triple<>(a, b, c));
});
} else if (liveDataB == liveDataC) {
addSource(liveDataB, b -> {
if (b != null) {
this.b = b;
//noinspection unchecked: A is C if live datas are same instance
this.c = (C) b;
}
setValue(new Triple<>(a, b, c));
});
addSource(liveDataA, a -> {
if (a != null) {
this.a = a;
}
setValue(new Triple<>(a, b, c));
});
} else {
addSource(liveDataA, a -> {
if (a != null) {
this.a = a;
}
setValue(new Triple<>(a, b, c));
});
addSource(liveDataB, b -> {
if (b != null) {
this.b = b;
}
setValue(new Triple<>(a, b, c));
});
addSource(liveDataC, c -> {
if (c != null) {
this.c = c;
}
setValue(new Triple<>(a, b, c));
});
}
}
}