diff --git a/app/src/main/java/org/thoughtcrime/securesms/megaphone/Megaphones.java b/app/src/main/java/org/thoughtcrime/securesms/megaphone/Megaphones.java index e9c0fc832a..1474b5a7b8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/megaphone/Megaphones.java +++ b/app/src/main/java/org/thoughtcrime/securesms/megaphone/Megaphones.java @@ -22,8 +22,9 @@ import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.messagerequests.MessageRequestMegaphoneActivity; import org.thoughtcrime.securesms.profiles.ProfileName; import org.thoughtcrime.securesms.recipients.Recipient; +import org.thoughtcrime.securesms.util.CommunicationActions; import org.thoughtcrime.securesms.util.FeatureFlags; -import org.thoughtcrime.securesms.util.ResearchMegaphone; +import org.thoughtcrime.securesms.util.PopulationFeatureFlags; import org.thoughtcrime.securesms.util.TextSecurePreferences; import java.util.LinkedHashMap; @@ -89,6 +90,7 @@ public final class Megaphones { put(Event.LINK_PREVIEWS, shouldShowLinkPreviewsMegaphone(context) ? ALWAYS : NEVER); put(Event.CLIENT_DEPRECATED, SignalStore.misc().isClientDeprecated() ? ALWAYS : NEVER); put(Event.RESEARCH, shouldShowResearchMegaphone() ? ShowForDurationSchedule.showForDays(7) : NEVER); + put(Event.DONATE, shouldShowDonateMegaphone() ? ShowForDurationSchedule.showForDays(7) : NEVER); }}; } @@ -108,6 +110,8 @@ public final class Megaphones { return buildClientDeprecatedMegaphone(context); case RESEARCH: return buildResearchMegaphone(context); + case DONATE: + return buildDonateMegaphone(context); default: throw new IllegalArgumentException("Event not handled!"); } @@ -219,12 +223,31 @@ public final class Megaphones { .build(); } + private static @NonNull Megaphone buildDonateMegaphone(@NonNull Context context) { + return new Megaphone.Builder(Event.DONATE, Megaphone.Style.BASIC) + .disableSnooze() + .setTitle(R.string.DonateMegaphone_donate_to_signal) + .setBody(R.string.DonateMegaphone_Signal_is_powered_by_people_like_you_show_your_support_today) + .setImage(R.drawable.ic_donate_megaphone) + .setActionButton(R.string.DonateMegaphone_donate, (megaphone, controller) -> { + controller.onMegaphoneCompleted(megaphone.getEvent()); + CommunicationActions.openBrowserLink(controller.getMegaphoneActivity(), context.getString(R.string.donate_url)); + }) + .setSecondaryButton(R.string.DonateMegaphone_not_now, (megaphone, controller) -> controller.onMegaphoneCompleted(megaphone.getEvent())) + .setPriority(Megaphone.Priority.DEFAULT) + .build(); + } + private static boolean shouldShowMessageRequestsMegaphone() { return Recipient.self().getProfileName() == ProfileName.EMPTY; } private static boolean shouldShowResearchMegaphone() { - return ResearchMegaphone.isInResearchMegaphone(); + return PopulationFeatureFlags.isInResearchMegaphone(); + } + + private static boolean shouldShowDonateMegaphone() { + return PopulationFeatureFlags.isInDonateMegaphone(); } private static boolean shouldShowLinkPreviewsMegaphone(@NonNull Context context) { @@ -238,7 +261,8 @@ public final class Megaphones { MESSAGE_REQUESTS("message_requests"), LINK_PREVIEWS("link_previews"), CLIENT_DEPRECATED("client_deprecated"), - RESEARCH("research"); + RESEARCH("research"), + DONATE("donate"); private final String key; diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java b/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java index 8885d7a718..109c5b3b32 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java @@ -60,6 +60,7 @@ public final class FeatureFlags { private static final String PHONE_NUMBER_PRIVACY_VERSION = "android.phoneNumberPrivacyVersion"; private static final String CLIENT_EXPIRATION = "android.clientExpiration"; public static final String RESEARCH_MEGAPHONE_1 = "research.megaphone.1"; + public static final String DONATE_MEGAPHONE = "android.donate"; private static final String VIEWED_RECEIPTS = "android.viewed.receipts"; private static final String MAX_ENVELOPE_SIZE = "android.maxEnvelopeSize"; private static final String GV1_AUTO_MIGRATE_VERSION = "android.groupsv2.autoMigrateVersion"; @@ -82,6 +83,7 @@ public final class FeatureFlags { VERIFY_V2, CLIENT_EXPIRATION, RESEARCH_MEGAPHONE_1, + DONATE_MEGAPHONE, VIEWED_RECEIPTS, MAX_ENVELOPE_SIZE, GV1_AUTO_MIGRATE_VERSION, @@ -243,6 +245,11 @@ public final class FeatureFlags { return getString(RESEARCH_MEGAPHONE_1, ""); } + /** The raw donate megaphone CSV string */ + public static String donateMegaphone() { + return getString(DONATE_MEGAPHONE, ""); + } + /** * Whether the user can choose phone number privacy settings, and; * Whether to fetch and store the secondary certificate diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/ResearchMegaphone.java b/app/src/main/java/org/thoughtcrime/securesms/util/PopulationFeatureFlags.java similarity index 80% rename from app/src/main/java/org/thoughtcrime/securesms/util/ResearchMegaphone.java rename to app/src/main/java/org/thoughtcrime/securesms/util/PopulationFeatureFlags.java index ac071918cb..6daa5aac85 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/ResearchMegaphone.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/PopulationFeatureFlags.java @@ -19,9 +19,9 @@ import java.util.Map; * in the list. For example, "1:20000,*:40000" would mean 2% of the NANPA phone numbers and 4% of the rest of * the world should see the megaphone. */ -public final class ResearchMegaphone { +public final class PopulationFeatureFlags { - private static final String TAG = Log.tag(ResearchMegaphone.class); + private static final String TAG = Log.tag(PopulationFeatureFlags.class); private static final String COUNTRY_WILDCARD = "*"; @@ -29,7 +29,18 @@ public final class ResearchMegaphone { * In research megaphone group for given country code */ public static boolean isInResearchMegaphone() { - Map countryCountEnabled = parseCountryCounts(FeatureFlags.researchMegaphone()); + return isEnabled(FeatureFlags.RESEARCH_MEGAPHONE_1, FeatureFlags.researchMegaphone()); + } + + /** + * In donate megaphone group for given country code + */ + public static boolean isInDonateMegaphone() { + return isEnabled(FeatureFlags.DONATE_MEGAPHONE, FeatureFlags.donateMegaphone()); + } + + private static boolean isEnabled(@NonNull String flag, @NonNull String serialized) { + Map countryCountEnabled = parseCountryCounts(serialized); Recipient self = Recipient.self(); if (countryCountEnabled.isEmpty() || !self.getE164().isPresent() || !self.getUuid().isPresent()) { @@ -37,7 +48,7 @@ public final class ResearchMegaphone { } long countEnabled = determineCountEnabled(countryCountEnabled, self.getE164().or("")); - long currentUserBucket = BucketingUtil.bucket(FeatureFlags.RESEARCH_MEGAPHONE_1, self.requireUuid(), 1_000_000); + long currentUserBucket = BucketingUtil.bucket(flag, self.requireUuid(), 1_000_000); return countEnabled > currentUserBucket; } diff --git a/app/src/main/res/drawable/ic_donate_megaphone.xml b/app/src/main/res/drawable/ic_donate_megaphone.xml new file mode 100644 index 0000000000..6f21605596 --- /dev/null +++ b/app/src/main/res/drawable/ic_donate_megaphone.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 725357f730..364ac2088b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -473,6 +473,13 @@ Unnamed file + + + Donate to Signal + Signal is powered by people like you. Show your support today! + Donate + Not Now + Optimize for missing Play Services This device does not support Play Services. Tap to disable system battery optimizations that prevent Signal from retrieving messages while inactive. diff --git a/app/src/test/java/org/thoughtcrime/securesms/util/ResearchMegaphoneTest_determineCountEnabled.java b/app/src/test/java/org/thoughtcrime/securesms/util/PopulationFeatureFlagsTest_determineCountEnabled.java similarity index 83% rename from app/src/test/java/org/thoughtcrime/securesms/util/ResearchMegaphoneTest_determineCountEnabled.java rename to app/src/test/java/org/thoughtcrime/securesms/util/PopulationFeatureFlagsTest_determineCountEnabled.java index a1948e321c..a31665815d 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/util/ResearchMegaphoneTest_determineCountEnabled.java +++ b/app/src/test/java/org/thoughtcrime/securesms/util/PopulationFeatureFlagsTest_determineCountEnabled.java @@ -2,8 +2,6 @@ package org.thoughtcrime.securesms.util; import androidx.annotation.NonNull; -import com.google.protobuf.Empty; - import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; @@ -19,7 +17,7 @@ import java.util.Map; import static org.junit.Assert.*; @RunWith(Parameterized.class) -public class ResearchMegaphoneTest_determineCountEnabled { +public class PopulationFeatureFlagsTest_determineCountEnabled { private final String phoneNumber; private final Map countryCounts; @@ -68,9 +66,9 @@ public class ResearchMegaphoneTest_determineCountEnabled { Log.initialize(new EmptyLogger()); } - public ResearchMegaphoneTest_determineCountEnabled(@NonNull String phoneNumber, - @NonNull Map countryCounts, - long output) + public PopulationFeatureFlagsTest_determineCountEnabled(@NonNull String phoneNumber, + @NonNull Map countryCounts, + long output) { this.phoneNumber = phoneNumber; this.countryCounts = countryCounts; @@ -79,7 +77,7 @@ public class ResearchMegaphoneTest_determineCountEnabled { @Test public void determineCountEnabled() { - assertEquals(output, ResearchMegaphone.determineCountEnabled(countryCounts, phoneNumber)); + assertEquals(output, PopulationFeatureFlags.determineCountEnabled(countryCounts, phoneNumber)); } } diff --git a/app/src/test/java/org/thoughtcrime/securesms/util/ResearchMegaphoneTest_parseCountryCounts.java b/app/src/test/java/org/thoughtcrime/securesms/util/PopulationFeatureFlagsTest_parseCountryCounts.java similarity index 85% rename from app/src/test/java/org/thoughtcrime/securesms/util/ResearchMegaphoneTest_parseCountryCounts.java rename to app/src/test/java/org/thoughtcrime/securesms/util/PopulationFeatureFlagsTest_parseCountryCounts.java index fbd9b642f1..ce82279079 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/util/ResearchMegaphoneTest_parseCountryCounts.java +++ b/app/src/test/java/org/thoughtcrime/securesms/util/PopulationFeatureFlagsTest_parseCountryCounts.java @@ -12,7 +12,7 @@ import java.util.Map; import static org.junit.Assert.assertEquals; @RunWith(Parameterized.class) -public class ResearchMegaphoneTest_parseCountryCounts { +public class PopulationFeatureFlagsTest_parseCountryCounts { private final String input; private final Map output; @@ -46,14 +46,14 @@ public class ResearchMegaphoneTest_parseCountryCounts { }); } - public ResearchMegaphoneTest_parseCountryCounts(String input, Map output) { + public PopulationFeatureFlagsTest_parseCountryCounts(String input, Map output) { this.input = input; this.output = output; } @Test public void parseCountryCounts() { - assertEquals(output, ResearchMegaphone.parseCountryCounts(input)); + assertEquals(output, PopulationFeatureFlags.parseCountryCounts(input)); } }