kopia lustrzana https://github.com/ryukoposting/Signal-Android
Add a megaphone to celebrate Valentine's Day.
rodzic
65af5f0849
commit
597cf3f576
|
@ -7,6 +7,7 @@ import android.provider.Settings;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.annotation.WorkerThread;
|
||||||
|
|
||||||
import com.annimon.stream.Stream;
|
import com.annimon.stream.Stream;
|
||||||
|
|
||||||
|
@ -15,7 +16,6 @@ import org.signal.core.util.logging.Log;
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.badges.models.Badge;
|
import org.thoughtcrime.securesms.badges.models.Badge;
|
||||||
import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity;
|
import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity;
|
||||||
import org.thoughtcrime.securesms.conversationlist.ConversationListFragment;
|
|
||||||
import org.thoughtcrime.securesms.database.model.MegaphoneRecord;
|
import org.thoughtcrime.securesms.database.model.MegaphoneRecord;
|
||||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||||
|
@ -24,37 +24,38 @@ import org.thoughtcrime.securesms.lock.SignalPinReminderDialog;
|
||||||
import org.thoughtcrime.securesms.lock.SignalPinReminders;
|
import org.thoughtcrime.securesms.lock.SignalPinReminders;
|
||||||
import org.thoughtcrime.securesms.lock.v2.CreateKbsPinActivity;
|
import org.thoughtcrime.securesms.lock.v2.CreateKbsPinActivity;
|
||||||
import org.thoughtcrime.securesms.lock.v2.KbsMigrationActivity;
|
import org.thoughtcrime.securesms.lock.v2.KbsMigrationActivity;
|
||||||
import org.thoughtcrime.securesms.messagerequests.MessageRequestMegaphoneActivity;
|
|
||||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||||
import org.thoughtcrime.securesms.profiles.AvatarHelper;
|
import org.thoughtcrime.securesms.profiles.AvatarHelper;
|
||||||
import org.thoughtcrime.securesms.profiles.ProfileName;
|
|
||||||
import org.thoughtcrime.securesms.profiles.manage.ManageProfileActivity;
|
import org.thoughtcrime.securesms.profiles.manage.ManageProfileActivity;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.util.FeatureFlags;
|
import org.thoughtcrime.securesms.util.FeatureFlags;
|
||||||
import org.thoughtcrime.securesms.util.LocaleFeatureFlags;
|
import org.thoughtcrime.securesms.util.LocaleFeatureFlags;
|
||||||
import org.thoughtcrime.securesms.util.PlayServicesUtil;
|
import org.thoughtcrime.securesms.util.PlayServicesUtil;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.SetUtil;
|
||||||
import org.thoughtcrime.securesms.util.VersionTracker;
|
import org.thoughtcrime.securesms.util.VersionTracker;
|
||||||
import org.thoughtcrime.securesms.util.dynamiclanguage.DynamicLanguageContextWrapper;
|
import org.thoughtcrime.securesms.util.dynamiclanguage.DynamicLanguageContextWrapper;
|
||||||
import org.thoughtcrime.securesms.wallpaper.ChatWallpaperActivity;
|
import org.thoughtcrime.securesms.wallpaper.ChatWallpaperActivity;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.Month;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creating a new megaphone:
|
* Creating a new megaphone:
|
||||||
* - Add an enum to {@link Event}
|
* - Add an enum to {@link Event}
|
||||||
* - Return a megaphone in {@link #forRecord(Context, MegaphoneRecord)}
|
* - Return a megaphone in {@link #forRecord(Context, MegaphoneRecord)}
|
||||||
* - Include the event in {@link #buildDisplayOrder(Context)}
|
* - Include the event in {@link #buildDisplayOrder(Context, Map)}
|
||||||
*
|
*
|
||||||
* Common patterns:
|
* Common patterns:
|
||||||
* - For events that have a snooze-able recurring display schedule, use a {@link RecurringSchedule}.
|
* - For events that have a snooze-able recurring display schedule, use a {@link RecurringSchedule}.
|
||||||
* - For events guarded by feature flags, set a {@link ForeverSchedule} with false in
|
* - For events guarded by feature flags, set a {@link ForeverSchedule} with false in
|
||||||
* {@link #buildDisplayOrder(Context)}.
|
* {@link #buildDisplayOrder(Context, Map)}.
|
||||||
* - For events that change, return different megaphones in {@link #forRecord(Context, MegaphoneRecord)}
|
* - For events that change, return different megaphones in {@link #forRecord(Context, MegaphoneRecord)}
|
||||||
* based on whatever properties you're interested in.
|
* based on whatever properties you're interested in.
|
||||||
*/
|
*/
|
||||||
|
@ -65,12 +66,16 @@ public final class Megaphones {
|
||||||
private static final MegaphoneSchedule ALWAYS = new ForeverSchedule(true);
|
private static final MegaphoneSchedule ALWAYS = new ForeverSchedule(true);
|
||||||
private static final MegaphoneSchedule NEVER = new ForeverSchedule(false);
|
private static final MegaphoneSchedule NEVER = new ForeverSchedule(false);
|
||||||
|
|
||||||
|
private static final Set<Event> DONATE_EVENTS = SetUtil.newHashSet(Event.VALENTINES_DONATIONS_2022, Event.BECOME_A_SUSTAINER);
|
||||||
|
private static final long MIN_TIME_BETWEEN_DONATE_MEGAPHONES = TimeUnit.DAYS.toMillis(30);
|
||||||
|
|
||||||
private Megaphones() {}
|
private Megaphones() {}
|
||||||
|
|
||||||
|
@WorkerThread
|
||||||
static @Nullable Megaphone getNextMegaphone(@NonNull Context context, @NonNull Map<Event, MegaphoneRecord> records) {
|
static @Nullable Megaphone getNextMegaphone(@NonNull Context context, @NonNull Map<Event, MegaphoneRecord> records) {
|
||||||
long currentTime = System.currentTimeMillis();
|
long currentTime = System.currentTimeMillis();
|
||||||
|
|
||||||
List<Megaphone> megaphones = Stream.of(buildDisplayOrder(context))
|
List<Megaphone> megaphones = Stream.of(buildDisplayOrder(context, records))
|
||||||
.filter(e -> {
|
.filter(e -> {
|
||||||
MegaphoneRecord record = Objects.requireNonNull(records.get(e.getKey()));
|
MegaphoneRecord record = Objects.requireNonNull(records.get(e.getKey()));
|
||||||
MegaphoneSchedule schedule = e.getValue();
|
MegaphoneSchedule schedule = e.getValue();
|
||||||
|
@ -95,13 +100,14 @@ public final class Megaphones {
|
||||||
*
|
*
|
||||||
* This is also when you would hide certain megaphones based on things like {@link FeatureFlags}.
|
* This is also when you would hide certain megaphones based on things like {@link FeatureFlags}.
|
||||||
*/
|
*/
|
||||||
private static Map<Event, MegaphoneSchedule> buildDisplayOrder(@NonNull Context context) {
|
private static Map<Event, MegaphoneSchedule> buildDisplayOrder(@NonNull Context context, @NonNull Map<Event, MegaphoneRecord> records) {
|
||||||
return new LinkedHashMap<Event, MegaphoneSchedule>() {{
|
return new LinkedHashMap<Event, MegaphoneSchedule>() {{
|
||||||
put(Event.PINS_FOR_ALL, new PinsForAllSchedule());
|
put(Event.PINS_FOR_ALL, new PinsForAllSchedule());
|
||||||
put(Event.CLIENT_DEPRECATED, SignalStore.misc().isClientDeprecated() ? ALWAYS : NEVER);
|
put(Event.CLIENT_DEPRECATED, SignalStore.misc().isClientDeprecated() ? ALWAYS : NEVER);
|
||||||
put(Event.NOTIFICATIONS, shouldShowNotificationsMegaphone(context) ? RecurringSchedule.every(TimeUnit.DAYS.toMillis(30)) : NEVER);
|
put(Event.NOTIFICATIONS, shouldShowNotificationsMegaphone(context) ? RecurringSchedule.every(TimeUnit.DAYS.toMillis(30)) : NEVER);
|
||||||
put(Event.ONBOARDING, shouldShowOnboardingMegaphone(context) ? ALWAYS : NEVER);
|
put(Event.ONBOARDING, shouldShowOnboardingMegaphone(context) ? ALWAYS : NEVER);
|
||||||
put(Event.BECOME_A_SUSTAINER, shouldShowDonateMegaphone(context) ? ShowForDurationSchedule.showForDays(7) : NEVER);
|
put(Event.BECOME_A_SUSTAINER, shouldShowDonateMegaphone(context, records) ? ShowForDurationSchedule.showForDays(7) : NEVER);
|
||||||
|
put(Event.VALENTINES_DONATIONS_2022, shouldShowValentinesDonationsMegaphone(context, records) ? ShowForDurationSchedule.showForDays(1) : NEVER);
|
||||||
put(Event.PIN_REMINDER, new SignalPinReminderSchedule());
|
put(Event.PIN_REMINDER, new SignalPinReminderSchedule());
|
||||||
|
|
||||||
// Feature-introduction megaphones should *probably* be added below this divider
|
// Feature-introduction megaphones should *probably* be added below this divider
|
||||||
|
@ -129,6 +135,8 @@ public final class Megaphones {
|
||||||
return buildAddAProfilePhotoMegaphone(context);
|
return buildAddAProfilePhotoMegaphone(context);
|
||||||
case BECOME_A_SUSTAINER:
|
case BECOME_A_SUSTAINER:
|
||||||
return buildBecomeASustainerMegaphone(context);
|
return buildBecomeASustainerMegaphone(context);
|
||||||
|
case VALENTINES_DONATIONS_2022:
|
||||||
|
return buildValentinesDonationsMegaphone(context);
|
||||||
case NOTIFICATION_PROFILES:
|
case NOTIFICATION_PROFILES:
|
||||||
return buildNotificationProfilesMegaphone(context);
|
return buildNotificationProfilesMegaphone(context);
|
||||||
default:
|
default:
|
||||||
|
@ -275,6 +283,21 @@ public final class Megaphones {
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static @NonNull Megaphone buildValentinesDonationsMegaphone(@NonNull Context context) {
|
||||||
|
return new Megaphone.Builder(Event.VALENTINES_DONATIONS_2022, Megaphone.Style.BASIC)
|
||||||
|
.setTitle(R.string.ValentinesDayMegaphone_happy_heart_day)
|
||||||
|
.setImage(R.drawable.ic_valentines_donor_megaphone_64)
|
||||||
|
.setBody(R.string.ValentinesDayMegaphone_show_your_affection)
|
||||||
|
.setActionButton(R.string.BecomeASustainerMegaphone__contribute, (megaphone, listener) -> {
|
||||||
|
listener.onMegaphoneNavigationRequested(AppSettingsActivity.subscriptions(context));
|
||||||
|
listener.onMegaphoneCompleted(Event.VALENTINES_DONATIONS_2022);
|
||||||
|
})
|
||||||
|
.setSecondaryButton(R.string.BecomeASustainerMegaphone__no_thanks, (megaphone, listener) -> {
|
||||||
|
listener.onMegaphoneCompleted(Event.VALENTINES_DONATIONS_2022);
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
private static @NonNull Megaphone buildNotificationProfilesMegaphone(@NonNull Context context) {
|
private static @NonNull Megaphone buildNotificationProfilesMegaphone(@NonNull Context context) {
|
||||||
return new Megaphone.Builder(Event.NOTIFICATION_PROFILES, Megaphone.Style.BASIC)
|
return new Megaphone.Builder(Event.NOTIFICATION_PROFILES, Megaphone.Style.BASIC)
|
||||||
.setTitle(R.string.NotificationProfilesMegaphone__notification_profiles)
|
.setTitle(R.string.NotificationProfilesMegaphone__notification_profiles)
|
||||||
|
@ -290,8 +313,11 @@ public final class Megaphones {
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean shouldShowDonateMegaphone(@NonNull Context context) {
|
private static boolean shouldShowDonateMegaphone(@NonNull Context context, @NonNull Map<Event, MegaphoneRecord> records) {
|
||||||
return VersionTracker.getDaysSinceFirstInstalled(context) >= 7 &&
|
long timeSinceLastDonatePrompt = timeSinceLastDonatePrompt(records);
|
||||||
|
|
||||||
|
return timeSinceLastDonatePrompt > MIN_TIME_BETWEEN_DONATE_MEGAPHONES &&
|
||||||
|
VersionTracker.getDaysSinceFirstInstalled(context) >= 7 &&
|
||||||
LocaleFeatureFlags.isInDonateMegaphone() &&
|
LocaleFeatureFlags.isInDonateMegaphone() &&
|
||||||
PlayServicesUtil.getPlayServicesStatus(context) == PlayServicesUtil.PlayServicesStatus.SUCCESS &&
|
PlayServicesUtil.getPlayServicesStatus(context) == PlayServicesUtil.PlayServicesStatus.SUCCESS &&
|
||||||
Recipient.self()
|
Recipient.self()
|
||||||
|
@ -301,6 +327,24 @@ public final class Megaphones {
|
||||||
.noneMatch(badge -> badge.getCategory() == Badge.Category.Donor);
|
.noneMatch(badge -> badge.getCategory() == Badge.Category.Donor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean shouldShowValentinesDonationsMegaphone(@NonNull Context context, @NonNull Map<Event, MegaphoneRecord> records) {
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
long timeSinceLastDonatePrompt = timeSinceLastDonatePrompt(records);
|
||||||
|
|
||||||
|
return timeSinceLastDonatePrompt > MIN_TIME_BETWEEN_DONATE_MEGAPHONES &&
|
||||||
|
VersionTracker.getDaysSinceFirstInstalled(context) >= 7 &&
|
||||||
|
LocaleFeatureFlags.isInValentinesDonateMegaphone() &&
|
||||||
|
now.getMonth() == Month.FEBRUARY &&
|
||||||
|
now.getDayOfMonth() == 14 &&
|
||||||
|
now.getYear() == 2022 &&
|
||||||
|
PlayServicesUtil.getPlayServicesStatus(context) == PlayServicesUtil.PlayServicesStatus.SUCCESS &&
|
||||||
|
Recipient.self()
|
||||||
|
.getBadges()
|
||||||
|
.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.noneMatch(badge -> badge.getCategory() == Badge.Category.Donor);
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean shouldShowOnboardingMegaphone(@NonNull Context context) {
|
private static boolean shouldShowOnboardingMegaphone(@NonNull Context context) {
|
||||||
return SignalStore.onboarding().hasOnboarding(context);
|
return SignalStore.onboarding().hasOnboarding(context);
|
||||||
}
|
}
|
||||||
|
@ -316,7 +360,8 @@ public final class Megaphones {
|
||||||
.textExistsInUsersLanguage(R.string.NotificationsMegaphone_turn_on_notifications,
|
.textExistsInUsersLanguage(R.string.NotificationsMegaphone_turn_on_notifications,
|
||||||
R.string.NotificationsMegaphone_never_miss_a_message,
|
R.string.NotificationsMegaphone_never_miss_a_message,
|
||||||
R.string.NotificationsMegaphone_turn_on,
|
R.string.NotificationsMegaphone_turn_on,
|
||||||
R.string.NotificationsMegaphone_not_now)) {
|
R.string.NotificationsMegaphone_not_now))
|
||||||
|
{
|
||||||
Log.i(TAG, "Would show NotificationsMegaphone but is not yet translated in " + locale);
|
Log.i(TAG, "Would show NotificationsMegaphone but is not yet translated in " + locale);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -338,6 +383,23 @@ public final class Megaphones {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unfortunately lastSeen is only set today upon snoozing, which never happens to donate prompts.
|
||||||
|
* So we use firstVisible as a proxy.
|
||||||
|
*/
|
||||||
|
private static long timeSinceLastDonatePrompt(@NonNull Map<Event, MegaphoneRecord> records) {
|
||||||
|
long lastSeenDonatePrompt = records.entrySet()
|
||||||
|
.stream()
|
||||||
|
.filter(e -> DONATE_EVENTS.contains(e.getKey()))
|
||||||
|
.map(e -> e.getValue().getFirstVisible())
|
||||||
|
.filter(t -> t > 0)
|
||||||
|
.sorted()
|
||||||
|
.findFirst()
|
||||||
|
.orElse(0L);
|
||||||
|
return System.currentTimeMillis() - lastSeenDonatePrompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public enum Event {
|
public enum Event {
|
||||||
PINS_FOR_ALL("pins_for_all"),
|
PINS_FOR_ALL("pins_for_all"),
|
||||||
PIN_REMINDER("pin_reminder"),
|
PIN_REMINDER("pin_reminder"),
|
||||||
|
@ -347,6 +409,7 @@ public final class Megaphones {
|
||||||
CHAT_COLORS("chat_colors"),
|
CHAT_COLORS("chat_colors"),
|
||||||
ADD_A_PROFILE_PHOTO("add_a_profile_photo"),
|
ADD_A_PROFILE_PHOTO("add_a_profile_photo"),
|
||||||
BECOME_A_SUSTAINER("become_a_sustainer"),
|
BECOME_A_SUSTAINER("become_a_sustainer"),
|
||||||
|
VALENTINES_DONATIONS_2022("valentines_donations_2022"),
|
||||||
NOTIFICATION_PROFILES("notification_profiles");
|
NOTIFICATION_PROFILES("notification_profiles");
|
||||||
|
|
||||||
private final String key;
|
private final String key;
|
||||||
|
|
|
@ -63,6 +63,7 @@ public final class FeatureFlags {
|
||||||
private static final String PHONE_NUMBER_PRIVACY_VERSION = "android.phoneNumberPrivacyVersion";
|
private static final String PHONE_NUMBER_PRIVACY_VERSION = "android.phoneNumberPrivacyVersion";
|
||||||
private static final String CLIENT_EXPIRATION = "android.clientExpiration";
|
private static final String CLIENT_EXPIRATION = "android.clientExpiration";
|
||||||
public static final String DONATE_MEGAPHONE = "android.donate.2";
|
public static final String DONATE_MEGAPHONE = "android.donate.2";
|
||||||
|
public static final String VALENTINES_DONATE_MEGAPHONE = "android.donate.valentines.2022";
|
||||||
private static final String CUSTOM_VIDEO_MUXER = "android.customVideoMuxer";
|
private static final String CUSTOM_VIDEO_MUXER = "android.customVideoMuxer";
|
||||||
private static final String CDS_REFRESH_INTERVAL = "cds.syncInterval.seconds";
|
private static final String CDS_REFRESH_INTERVAL = "cds.syncInterval.seconds";
|
||||||
private static final String AUTOMATIC_SESSION_RESET = "android.automaticSessionReset.2";
|
private static final String AUTOMATIC_SESSION_RESET = "android.automaticSessionReset.2";
|
||||||
|
@ -132,7 +133,8 @@ public final class FeatureFlags {
|
||||||
DONOR_BADGES_DISPLAY,
|
DONOR_BADGES_DISPLAY,
|
||||||
CHANGE_NUMBER_ENABLED,
|
CHANGE_NUMBER_ENABLED,
|
||||||
HARDWARE_AEC_MODELS,
|
HARDWARE_AEC_MODELS,
|
||||||
FORCE_DEFAULT_AEC
|
FORCE_DEFAULT_AEC,
|
||||||
|
VALENTINES_DONATE_MEGAPHONE
|
||||||
);
|
);
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
|
@ -187,7 +189,8 @@ public final class FeatureFlags {
|
||||||
SENDER_KEY_MAX_AGE,
|
SENDER_KEY_MAX_AGE,
|
||||||
DONOR_BADGES_DISPLAY,
|
DONOR_BADGES_DISPLAY,
|
||||||
DONATE_MEGAPHONE,
|
DONATE_MEGAPHONE,
|
||||||
FORCE_DEFAULT_AEC
|
FORCE_DEFAULT_AEC,
|
||||||
|
VALENTINES_DONATE_MEGAPHONE
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -303,6 +306,11 @@ public final class FeatureFlags {
|
||||||
return getString(DONATE_MEGAPHONE, "");
|
return getString(DONATE_MEGAPHONE, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** The raw valentine's day donate megaphone CSV string */
|
||||||
|
public static String valentinesDonateMegaphone() {
|
||||||
|
return getString(VALENTINES_DONATE_MEGAPHONE, "");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the user can choose phone number privacy settings, and;
|
* Whether the user can choose phone number privacy settings, and;
|
||||||
* Whether to fetch and store the secondary certificate
|
* Whether to fetch and store the secondary certificate
|
||||||
|
|
|
@ -37,6 +37,13 @@ public final class LocaleFeatureFlags {
|
||||||
return isEnabled(FeatureFlags.DONATE_MEGAPHONE, FeatureFlags.donateMegaphone());
|
return isEnabled(FeatureFlags.DONATE_MEGAPHONE, FeatureFlags.donateMegaphone());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In valentines donation megaphone group for given country code
|
||||||
|
*/
|
||||||
|
public static boolean isInValentinesDonateMegaphone() {
|
||||||
|
return isEnabled(FeatureFlags.VALENTINES_DONATE_MEGAPHONE, FeatureFlags.valentinesDonateMegaphone());
|
||||||
|
}
|
||||||
|
|
||||||
public static @NonNull Optional<PushMediaConstraints.MediaConfig> getMediaQualityLevel() {
|
public static @NonNull Optional<PushMediaConstraints.MediaConfig> getMediaQualityLevel() {
|
||||||
Map<String, Integer> countryValues = parseCountryValues(FeatureFlags.getMediaQualityLevels(), NOT_FOUND);
|
Map<String, Integer> countryValues = parseCountryValues(FeatureFlags.getMediaQualityLevels(), NOT_FOUND);
|
||||||
int level = getCountryValue(countryValues, Recipient.self().getE164().or(""), NOT_FOUND);
|
int level = getCountryValue(countryValues, Recipient.self().getE164().or(""), NOT_FOUND);
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1445,6 +1445,12 @@
|
||||||
<string name="RedPhone_the_number_you_dialed_does_not_support_secure_voice">The number you dialed does not support secure voice!</string>
|
<string name="RedPhone_the_number_you_dialed_does_not_support_secure_voice">The number you dialed does not support secure voice!</string>
|
||||||
<string name="RedPhone_got_it">Got it</string>
|
<string name="RedPhone_got_it">Got it</string>
|
||||||
|
|
||||||
|
<!-- Valentine's Day Megaphone -->
|
||||||
|
<!-- Title text for the Valentine's Day donation megaphone. The placeholder will always be a heart emoji. Needs to be a placeholder for Android reasons. -->
|
||||||
|
<string name="ValentinesDayMegaphone_happy_heart_day">Happy 💜 Day!</string>
|
||||||
|
<!-- Body text for the Valentine's Day donation megaphone. -->
|
||||||
|
<string name="ValentinesDayMegaphone_show_your_affection">Show your affection by becoming a Signal sustainer.</string>
|
||||||
|
|
||||||
<!-- WebRtcCallActivity -->
|
<!-- WebRtcCallActivity -->
|
||||||
<string name="WebRtcCallActivity__tap_here_to_turn_on_your_video">Tap here to turn on your video</string>
|
<string name="WebRtcCallActivity__tap_here_to_turn_on_your_video">Tap here to turn on your video</string>
|
||||||
<string name="WebRtcCallActivity__to_call_s_signal_needs_access_to_your_camera">To call %1$s, Signal needs access to your camera</string>
|
<string name="WebRtcCallActivity__to_call_s_signal_needs_access_to_your_camera">To call %1$s, Signal needs access to your camera</string>
|
||||||
|
|
Ładowanie…
Reference in New Issue