Reimplement Phase 0 for SMS removal.

fork-5.53.8
Cody Henthorne 2022-10-20 15:50:38 -04:00 zatwierdzone przez Greyson Parrelli
rodzic 690e1e60ba
commit a535b4f97c
21 zmienionych plików z 107 dodań i 42 usunięć

Wyświetl plik

@ -70,7 +70,7 @@ public abstract class ContactSelectionActivity extends PassphraseRequiredActivit
@Override @Override
protected void onCreate(Bundle icicle, boolean ready) { protected void onCreate(Bundle icicle, boolean ready) {
if (!getIntent().hasExtra(ContactSelectionListFragment.DISPLAY_MODE)) { if (!getIntent().hasExtra(ContactSelectionListFragment.DISPLAY_MODE)) {
boolean includeSms = Util.isDefaultSmsProvider(this) && SignalStore.misc().getSmsExportPhase().isSmsSupported(); boolean includeSms = SignalStore.misc().getSmsExportPhase().allowSmsFeatures();
int displayMode = includeSms ? DisplayMode.FLAG_ALL : DisplayMode.FLAG_PUSH | DisplayMode.FLAG_ACTIVE_GROUPS | DisplayMode.FLAG_INACTIVE_GROUPS | DisplayMode.FLAG_SELF; int displayMode = includeSms ? DisplayMode.FLAG_ALL : DisplayMode.FLAG_PUSH | DisplayMode.FLAG_ACTIVE_GROUPS | DisplayMode.FLAG_INACTIVE_GROUPS | DisplayMode.FLAG_SELF;
getIntent().putExtra(ContactSelectionListFragment.DISPLAY_MODE, displayMode); getIntent().putExtra(ContactSelectionListFragment.DISPLAY_MODE, displayMode);
} }

Wyświetl plik

@ -106,7 +106,7 @@ public class NewConversationActivity extends ContactSelectionActivity
@Override @Override
public void onBeforeContactSelected(@NonNull Optional<RecipientId> recipientId, String number, @NonNull Consumer<Boolean> callback) { public void onBeforeContactSelected(@NonNull Optional<RecipientId> recipientId, String number, @NonNull Consumer<Boolean> callback) {
boolean smsSupported = Util.isDefaultSmsProvider(this) && SignalStore.misc().getSmsExportPhase().isSmsSupported(); boolean smsSupported = SignalStore.misc().getSmsExportPhase().allowSmsFeatures();
if (recipientId.isPresent()) { if (recipientId.isPresent()) {
launch(Recipient.resolved(recipientId.get())); launch(Recipient.resolved(recipientId.get()));
@ -283,7 +283,7 @@ public class NewConversationActivity extends ContactSelectionActivity
return null; return null;
} }
if (recipient.isRegistered() || (Util.isDefaultSmsProvider(this) && SignalStore.misc().getSmsExportPhase().isSmsSupported())) { if (recipient.isRegistered() || (SignalStore.misc().getSmsExportPhase().allowSmsFeatures())) {
return new ActionItem( return new ActionItem(
R.drawable.ic_phone_right_24, R.drawable.ic_phone_right_24,
getString(R.string.NewConversationActivity__audio_call), getString(R.string.NewConversationActivity__audio_call),

Wyświetl plik

@ -13,7 +13,6 @@ import org.thoughtcrime.securesms.components.menu.ActionItem
import org.thoughtcrime.securesms.components.menu.SignalContextMenu import org.thoughtcrime.securesms.components.menu.SignalContextMenu
import org.thoughtcrime.securesms.conversation.MessageSendType import org.thoughtcrime.securesms.conversation.MessageSendType
import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.util.Util
import org.thoughtcrime.securesms.util.ViewUtil import org.thoughtcrime.securesms.util.ViewUtil
import java.lang.AssertionError import java.lang.AssertionError
import java.util.concurrent.CopyOnWriteArrayList import java.util.concurrent.CopyOnWriteArrayList
@ -157,7 +156,7 @@ class SendButton(context: Context, attributeSet: AttributeSet?) : AppCompatImage
} }
if (availableSendTypes.size == 1) { if (availableSendTypes.size == 1) {
return if (!Util.isDefaultSmsProvider(context) || !SignalStore.misc().smsExportPhase.isSmsSupported()) { return if (!SignalStore.misc().smsExportPhase.allowSmsFeatures()) {
Snackbar.make(snackbarContainer, R.string.InputPanel__sms_messaging_is_no_longer_supported_in_signal, Snackbar.LENGTH_SHORT).show() Snackbar.make(snackbarContainer, R.string.InputPanel__sms_messaging_is_no_longer_supported_in_signal, Snackbar.LENGTH_SHORT).show()
true true
} else { } else {

Wyświetl plik

@ -14,6 +14,7 @@ import org.thoughtcrime.securesms.components.settings.app.chats.sms.SmsExportSta
import org.thoughtcrime.securesms.components.settings.configure import org.thoughtcrime.securesms.components.settings.configure
import org.thoughtcrime.securesms.exporter.flow.SmsExportActivity import org.thoughtcrime.securesms.exporter.flow.SmsExportActivity
import org.thoughtcrime.securesms.exporter.flow.SmsExportDialogs import org.thoughtcrime.securesms.exporter.flow.SmsExportDialogs
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
import org.thoughtcrime.securesms.util.navigation.safeNavigate import org.thoughtcrime.securesms.util.navigation.safeNavigate
@ -45,7 +46,7 @@ class ChatsSettingsFragment : DSLSettingsFragment(R.string.preferences_chats__ch
private fun getConfiguration(state: ChatsSettingsState): DSLConfiguration { private fun getConfiguration(state: ChatsSettingsState): DSLConfiguration {
return configure { return configure {
if (!state.useAsDefaultSmsApp) { if (!state.useAsDefaultSmsApp && SignalStore.misc().smsExportPhase.isAtLeastPhase1()) {
when (state.smsExportState) { when (state.smsExportState) {
SmsExportState.FETCHING -> Unit SmsExportState.FETCHING -> Unit
SmsExportState.HAS_UNEXPORTED_MESSAGES -> { SmsExportState.HAS_UNEXPORTED_MESSAGES -> {
@ -73,9 +74,7 @@ class ChatsSettingsFragment : DSLSettingsFragment(R.string.preferences_chats__ch
SmsExportState.NO_SMS_MESSAGES_IN_DATABASE -> Unit SmsExportState.NO_SMS_MESSAGES_IN_DATABASE -> Unit
SmsExportState.NOT_AVAILABLE -> Unit SmsExportState.NOT_AVAILABLE -> Unit
} }
} } else {
if (state.useAsDefaultSmsApp) {
clickPref( clickPref(
title = DSLSettingsText.from(R.string.preferences__sms_mms), title = DSLSettingsText.from(R.string.preferences__sms_mms),
onClick = { onClick = {

Wyświetl plik

@ -19,6 +19,8 @@ import org.thoughtcrime.securesms.components.settings.models.OutlinedLearnMore
import org.thoughtcrime.securesms.exporter.flow.SmsExportActivity import org.thoughtcrime.securesms.exporter.flow.SmsExportActivity
import org.thoughtcrime.securesms.exporter.flow.SmsExportDialogs import org.thoughtcrime.securesms.exporter.flow.SmsExportDialogs
import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.keyvalue.SmsExportPhase
import org.thoughtcrime.securesms.util.SmsUtil
import org.thoughtcrime.securesms.util.Util import org.thoughtcrime.securesms.util.Util
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
import org.thoughtcrime.securesms.util.navigation.safeNavigate import org.thoughtcrime.securesms.util.navigation.safeNavigate
@ -56,14 +58,16 @@ class SmsSettingsFragment : DSLSettingsFragment(R.string.preferences__sms_mms) {
SignalStore.settings().setDefaultSms(true) SignalStore.settings().setDefaultSms(true)
} else { } else {
SignalStore.settings().setDefaultSms(false) SignalStore.settings().setDefaultSms(false)
findNavController().navigateUp() if (SignalStore.misc().smsExportPhase.isAtLeastPhase1()) {
findNavController().navigateUp()
}
} }
} }
private fun getConfiguration(state: SmsSettingsState): DSLConfiguration { private fun getConfiguration(state: SmsSettingsState): DSLConfiguration {
return configure { return configure {
if (state.useAsDefaultSmsApp) { if (state.useAsDefaultSmsApp && SignalStore.misc().smsExportPhase.isAtLeastPhase1()) {
customPref( customPref(
OutlinedLearnMore.Model( OutlinedLearnMore.Model(
summary = DSLSettingsText.from(R.string.SmsSettingsFragment__sms_support_will_be_removed_soon_to_focus_on_encrypted_messaging), summary = DSLSettingsText.from(R.string.SmsSettingsFragment__sms_support_will_be_removed_soon_to_focus_on_encrypted_messaging),
@ -100,13 +104,17 @@ class SmsSettingsFragment : DSLSettingsFragment(R.string.preferences__sms_mms) {
SmsExportState.NOT_AVAILABLE -> Unit SmsExportState.NOT_AVAILABLE -> Unit
} }
if (state.useAsDefaultSmsApp) { if (state.useAsDefaultSmsApp || SignalStore.misc().smsExportPhase == SmsExportPhase.PHASE_0) {
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
clickPref( clickPref(
title = DSLSettingsText.from(R.string.SmsSettingsFragment__use_as_default_sms_app), title = DSLSettingsText.from(R.string.SmsSettingsFragment__use_as_default_sms_app),
summary = DSLSettingsText.from(R.string.arrays__enabled), summary = DSLSettingsText.from(if (state.useAsDefaultSmsApp) R.string.arrays__enabled else R.string.arrays__disabled),
onClick = { onClick = {
startDefaultAppSelectionIntent() if (state.useAsDefaultSmsApp) {
startDefaultAppSelectionIntent()
} else {
startActivityForResult(SmsUtil.getSmsRoleIntent(requireContext()), SMS_REQUEST_CODE.toInt())
}
} }
) )
} }

Wyświetl plik

@ -18,7 +18,6 @@ import org.thoughtcrime.securesms.groups.SelectionLimits
import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.util.LifecycleDisposable import org.thoughtcrime.securesms.util.LifecycleDisposable
import org.thoughtcrime.securesms.util.Util
import org.thoughtcrime.securesms.util.ViewUtil import org.thoughtcrime.securesms.util.ViewUtil
import org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton import org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton
import java.util.Optional import java.util.Optional
@ -106,7 +105,7 @@ class SelectRecipientsFragment : LoggingFragment(), ContactSelectionListFragment
ContactsCursorLoader.DisplayMode.FLAG_HIDE_RECENT_HEADER or ContactsCursorLoader.DisplayMode.FLAG_HIDE_RECENT_HEADER or
ContactsCursorLoader.DisplayMode.FLAG_GROUPS_AFTER_CONTACTS ContactsCursorLoader.DisplayMode.FLAG_GROUPS_AFTER_CONTACTS
if (Util.isDefaultSmsProvider(requireContext()) && SignalStore.misc().smsExportPhase.isSmsSupported()) { if (SignalStore.misc().smsExportPhase.allowSmsFeatures()) {
mode = mode or ContactsCursorLoader.DisplayMode.FLAG_SMS mode = mode or ContactsCursorLoader.DisplayMode.FLAG_SMS
} }

Wyświetl plik

@ -16,7 +16,6 @@ import org.thoughtcrime.securesms.components.settings.conversation.preferences.L
import org.thoughtcrime.securesms.database.AttachmentDatabase import org.thoughtcrime.securesms.database.AttachmentDatabase
import org.thoughtcrime.securesms.database.RecipientDatabase import org.thoughtcrime.securesms.database.RecipientDatabase
import org.thoughtcrime.securesms.database.model.StoryViewState import org.thoughtcrime.securesms.database.model.StoryViewState
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
import org.thoughtcrime.securesms.groups.GroupId import org.thoughtcrime.securesms.groups.GroupId
import org.thoughtcrime.securesms.groups.LiveGroup import org.thoughtcrime.securesms.groups.LiveGroup
import org.thoughtcrime.securesms.groups.v2.GroupAddMembersResult import org.thoughtcrime.securesms.groups.v2.GroupAddMembersResult
@ -26,7 +25,6 @@ import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.recipients.RecipientUtil import org.thoughtcrime.securesms.recipients.RecipientUtil
import org.thoughtcrime.securesms.util.FeatureFlags import org.thoughtcrime.securesms.util.FeatureFlags
import org.thoughtcrime.securesms.util.SingleLiveEvent import org.thoughtcrime.securesms.util.SingleLiveEvent
import org.thoughtcrime.securesms.util.Util
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil import org.thoughtcrime.securesms.util.livedata.LiveDataUtil
import org.thoughtcrime.securesms.util.livedata.Store import org.thoughtcrime.securesms.util.livedata.Store
import java.util.Optional import java.util.Optional
@ -141,7 +139,7 @@ sealed class ConversationSettingsViewModel(
} }
store.update(liveRecipient.liveData) { recipient, state -> store.update(liveRecipient.liveData) { recipient, state ->
val isAudioAvailable = (recipient.isRegistered || (Util.isDefaultSmsProvider(ApplicationDependencies.getApplication()) && SignalStore.misc().smsExportPhase.isSmsSupported())) && val isAudioAvailable = (recipient.isRegistered || SignalStore.misc().smsExportPhase.allowSmsFeatures()) &&
!recipient.isGroup && !recipient.isGroup &&
!recipient.isBlocked && !recipient.isBlocked &&
!recipient.isSelf && !recipient.isSelf &&

Wyświetl plik

@ -929,7 +929,7 @@ public class ConversationParentFragment extends Fragment
if (isSingleConversation()) { if (isSingleConversation()) {
if (viewModel.isPushAvailable()) { if (viewModel.isPushAvailable()) {
inflater.inflate(R.menu.conversation_callable_secure, menu); inflater.inflate(R.menu.conversation_callable_secure, menu);
} else if (!recipient.get().isReleaseNotes() && Util.isDefaultSmsProvider(requireContext()) && SignalStore.misc().getSmsExportPhase().isSmsSupported()) { } else if (!recipient.get().isReleaseNotes() && SignalStore.misc().getSmsExportPhase().allowSmsFeatures()) {
inflater.inflate(R.menu.conversation_callable_insecure, menu); inflater.inflate(R.menu.conversation_callable_insecure, menu);
} }
} else if (isGroupConversation()) { } else if (isGroupConversation()) {
@ -2742,7 +2742,14 @@ public class ConversationParentFragment extends Fragment
TextView message = smsExportStub.get().findViewById(R.id.export_sms_message); TextView message = smsExportStub.get().findViewById(R.id.export_sms_message);
MaterialButton actionButton = smsExportStub.get().findViewById(R.id.export_sms_button); MaterialButton actionButton = smsExportStub.get().findViewById(R.id.export_sms_button);
boolean isPhase1 = SignalStore.misc().getSmsExportPhase() == SmsExportPhase.PHASE_1; boolean isPhase1 = SignalStore.misc().getSmsExportPhase() == SmsExportPhase.PHASE_1;
if (conversationSecurityInfo.getHasUnexportedInsecureMessages()) {
if (SignalStore.misc().getSmsExportPhase() == SmsExportPhase.PHASE_0) {
message.setText(getString(R.string.NewConversationActivity__s_is_not_a_signal_user, recipient.getDisplayName(requireContext())));
actionButton.setText(R.string.conversation_activity__enable_signal_for_sms);
actionButton.setOnClickListener(v -> {
handleMakeDefaultSms();
});
} else if (conversationSecurityInfo.getHasUnexportedInsecureMessages()) {
message.setText(isPhase1 ? R.string.ConversationActivity__sms_messaging_is_currently_disabled_you_can_export_your_messages_to_another_app_on_your_phone message.setText(isPhase1 ? R.string.ConversationActivity__sms_messaging_is_currently_disabled_you_can_export_your_messages_to_another_app_on_your_phone
: R.string.ConversationActivity__sms_messaging_is_no_longer_supported_in_signal_you_can_export_your_messages_to_another_app_on_your_phone); : R.string.ConversationActivity__sms_messaging_is_no_longer_supported_in_signal_you_can_export_your_messages_to_another_app_on_your_phone);
actionButton.setText(R.string.ConversationActivity__export_sms_messages); actionButton.setText(R.string.ConversationActivity__export_sms_messages);

Wyświetl plik

@ -31,6 +31,7 @@ import org.thoughtcrime.securesms.database.DatabaseObserver;
import org.thoughtcrime.securesms.database.model.MessageId; import org.thoughtcrime.securesms.database.model.MessageId;
import org.thoughtcrime.securesms.database.model.StoryViewState; import org.thoughtcrime.securesms.database.model.StoryViewState;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.mediasend.Media; import org.thoughtcrime.securesms.mediasend.Media;
import org.thoughtcrime.securesms.mediasend.MediaRepository; import org.thoughtcrime.securesms.mediasend.MediaRepository;
import org.thoughtcrime.securesms.notifications.profiles.NotificationProfile; import org.thoughtcrime.securesms.notifications.profiles.NotificationProfile;
@ -443,7 +444,9 @@ public class ConversationViewModel extends ViewModel {
} }
public void insertSmsExportUpdateEvent(@NonNull Recipient recipient) { public void insertSmsExportUpdateEvent(@NonNull Recipient recipient) {
conversationRepository.insertSmsExportUpdateEvent(recipient); if (SignalStore.misc().getSmsExportPhase().isAtLeastPhase1()) {
conversationRepository.insertSmsExportUpdateEvent(recipient);
}
} }
enum Event { enum Event {

Wyświetl plik

@ -14,7 +14,6 @@ import org.thoughtcrime.securesms.util.CharacterCalculator
import org.thoughtcrime.securesms.util.MmsCharacterCalculator import org.thoughtcrime.securesms.util.MmsCharacterCalculator
import org.thoughtcrime.securesms.util.PushCharacterCalculator import org.thoughtcrime.securesms.util.PushCharacterCalculator
import org.thoughtcrime.securesms.util.SmsCharacterCalculator import org.thoughtcrime.securesms.util.SmsCharacterCalculator
import org.thoughtcrime.securesms.util.Util
import org.thoughtcrime.securesms.util.dualsim.SubscriptionInfoCompat import org.thoughtcrime.securesms.util.dualsim.SubscriptionInfoCompat
import org.thoughtcrime.securesms.util.dualsim.SubscriptionManagerCompat import org.thoughtcrime.securesms.util.dualsim.SubscriptionManagerCompat
import java.lang.IllegalArgumentException import java.lang.IllegalArgumentException
@ -140,7 +139,7 @@ sealed class MessageSendType(
options += SignalMessageSendType options += SignalMessageSendType
if (Util.isDefaultSmsProvider(context) && SignalStore.misc().smsExportPhase.isSmsSupported()) { if (SignalStore.misc().smsExportPhase.allowSmsFeatures()) {
try { try {
val subscriptions: Collection<SubscriptionInfoCompat> = SubscriptionManagerCompat(context).activeAndReadySubscriptionInfos val subscriptions: Collection<SubscriptionInfoCompat> = SubscriptionManagerCompat(context).activeAndReadySubscriptionInfos

Wyświetl plik

@ -51,7 +51,7 @@ public class CreateGroupActivity extends ContactSelectionActivity {
intent.putExtra(ContactSelectionListFragment.REFRESHABLE, false); intent.putExtra(ContactSelectionListFragment.REFRESHABLE, false);
intent.putExtra(ContactSelectionActivity.EXTRA_LAYOUT_RES_ID, R.layout.create_group_activity); intent.putExtra(ContactSelectionActivity.EXTRA_LAYOUT_RES_ID, R.layout.create_group_activity);
boolean smsEnabled = Util.isDefaultSmsProvider(context) && SignalStore.misc().getSmsExportPhase().isSmsSupported(); boolean smsEnabled = SignalStore.misc().getSmsExportPhase().allowSmsFeatures();
int displayMode = smsEnabled ? ContactsCursorLoader.DisplayMode.FLAG_SMS | ContactsCursorLoader.DisplayMode.FLAG_PUSH int displayMode = smsEnabled ? ContactsCursorLoader.DisplayMode.FLAG_SMS | ContactsCursorLoader.DisplayMode.FLAG_PUSH
: ContactsCursorLoader.DisplayMode.FLAG_PUSH; : ContactsCursorLoader.DisplayMode.FLAG_PUSH;

Wyświetl plik

@ -100,6 +100,7 @@ public class AddGroupDetailsFragment extends LoggingFragment {
GroupMemberListView members = view.findViewById(R.id.member_list); GroupMemberListView members = view.findViewById(R.id.member_list);
ImageView avatar = view.findViewById(R.id.group_avatar); ImageView avatar = view.findViewById(R.id.group_avatar);
View mmsWarning = view.findViewById(R.id.mms_warning); View mmsWarning = view.findViewById(R.id.mms_warning);
TextView mmsWarningText = view.findViewById(R.id.mms_warning_text);
View addLater = view.findViewById(R.id.add_later); View addLater = view.findViewById(R.id.add_later);
TextView disappearingMessageValue = view.findViewById(R.id.group_disappearing_messages_value); TextView disappearingMessageValue = view.findViewById(R.id.group_disappearing_messages_value);
@ -127,6 +128,8 @@ public class AddGroupDetailsFragment extends LoggingFragment {
viewModel.getIsMms().observe(getViewLifecycleOwner(), isMms -> { viewModel.getIsMms().observe(getViewLifecycleOwner(), isMms -> {
disappearingMessagesRow.setVisibility(isMms ? View.GONE : View.VISIBLE); disappearingMessagesRow.setVisibility(isMms ? View.GONE : View.VISIBLE);
mmsWarning.setVisibility(isMms ? View.VISIBLE : View.GONE); mmsWarning.setVisibility(isMms ? View.VISIBLE : View.GONE);
mmsWarningText.setText(SignalStore.misc().getSmsExportPhase().isAtLeastPhase1() ? R.string.AddGroupDetailsFragment__youve_selected_a_contact_that_doesnt_support_signal_groups_mms_removal
: R.string.AddGroupDetailsFragment__youve_selected_a_contact_that_doesnt_support);
name.setHint(isMms ? R.string.AddGroupDetailsFragment__group_name_optional : R.string.AddGroupDetailsFragment__group_name_required); name.setHint(isMms ? R.string.AddGroupDetailsFragment__group_name_optional : R.string.AddGroupDetailsFragment__group_name_required);
toolbar.setTitle(isMms ? R.string.AddGroupDetailsFragment__create_group : R.string.AddGroupDetailsFragment__name_this_group); toolbar.setTitle(isMms ? R.string.AddGroupDetailsFragment__create_group : R.string.AddGroupDetailsFragment__name_this_group);
}); });

Wyświetl plik

@ -26,7 +26,8 @@ public final class MiscellaneousValues extends SignalStoreValues {
private static final String LAST_FCM_FOREGROUND_TIME = "misc.last_fcm_foreground_time"; private static final String LAST_FCM_FOREGROUND_TIME = "misc.last_fcm_foreground_time";
private static final String LAST_FOREGROUND_TIME = "misc.last_foreground_time"; private static final String LAST_FOREGROUND_TIME = "misc.last_foreground_time";
private static final String PNI_INITIALIZED_DEVICES = "misc.pni_initialized_devices"; private static final String PNI_INITIALIZED_DEVICES = "misc.pni_initialized_devices";
private static final String SMS_EXPORT_TIME = "misc.sms_export_time"; private static final String SMS_PHASE_1_START_MS = "misc.sms_export.phase_1_start";
private static final String STORIES_FEATURE_AVAILABLE_MS = "misc.stories_feature_available_ms";
MiscellaneousValues(@NonNull KeyValueStore store) { MiscellaneousValues(@NonNull KeyValueStore store) {
super(store); super(store);
@ -40,7 +41,8 @@ public final class MiscellaneousValues extends SignalStoreValues {
@Override @Override
@NonNull List<String> getKeysToIncludeInBackup() { @NonNull List<String> getKeysToIncludeInBackup() {
return Arrays.asList( return Arrays.asList(
SMS_EXPORT_TIME SMS_PHASE_1_START_MS,
STORIES_FEATURE_AVAILABLE_MS
); );
} }
@ -188,14 +190,26 @@ public final class MiscellaneousValues extends SignalStoreValues {
putBoolean(PNI_INITIALIZED_DEVICES, value); putBoolean(PNI_INITIALIZED_DEVICES, value);
} }
public void setHasSeenSmsExportMegaphone() { public void startSmsPhase1() {
if (!getStore().containsKey(SMS_EXPORT_TIME)) { if (!getStore().containsKey(SMS_PHASE_1_START_MS)) {
putLong(SMS_EXPORT_TIME, System.currentTimeMillis()); putLong(SMS_PHASE_1_START_MS, System.currentTimeMillis());
} }
} }
public long getStoriesFeatureAvailableTimestamp() {
return getLong(STORIES_FEATURE_AVAILABLE_MS, 0);
}
public void setStoriesFeatureAvailableTimestamp(long timestamp) {
putLong(STORIES_FEATURE_AVAILABLE_MS, timestamp);
}
public @NonNull SmsExportPhase getSmsExportPhase() { public @NonNull SmsExportPhase getSmsExportPhase() {
if (getLong(SMS_PHASE_1_START_MS, 0) == 0) {
return SmsExportPhase.PHASE_0;
}
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
return SmsExportPhase.getCurrentPhase(now - getLong(SMS_EXPORT_TIME, now)); return SmsExportPhase.getCurrentPhase(now - getLong(SMS_PHASE_1_START_MS, now));
} }
} }

Wyświetl plik

@ -1,24 +1,35 @@
package org.thoughtcrime.securesms.keyvalue package org.thoughtcrime.securesms.keyvalue
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
import org.thoughtcrime.securesms.util.Util
import kotlin.time.Duration.Companion.days import kotlin.time.Duration.Companion.days
enum class SmsExportPhase(val duration: Long) { enum class SmsExportPhase(val duration: Long) {
PHASE_0(-1),
PHASE_1(0.days.inWholeMilliseconds), PHASE_1(0.days.inWholeMilliseconds),
PHASE_2(45.days.inWholeMilliseconds), PHASE_2(45.days.inWholeMilliseconds),
PHASE_3(105.days.inWholeMilliseconds); PHASE_3(105.days.inWholeMilliseconds);
fun allowSmsFeatures(): Boolean {
return this == PHASE_0 || (Util.isDefaultSmsProvider(ApplicationDependencies.getApplication()) && SignalStore.misc().smsExportPhase.isSmsSupported())
}
fun isSmsSupported(): Boolean { fun isSmsSupported(): Boolean {
return this != PHASE_3 return this != PHASE_3
} }
fun isFullscreen(): Boolean { fun isFullscreen(): Boolean {
return this != PHASE_1 return this.ordinal > PHASE_1.ordinal
} }
fun isBlockingUi(): Boolean { fun isBlockingUi(): Boolean {
return this == PHASE_3 return this == PHASE_3
} }
fun isAtLeastPhase1(): Boolean {
return this.ordinal >= PHASE_1.ordinal
}
companion object { companion object {
@JvmStatic @JvmStatic
fun getCurrentPhase(duration: Long): SmsExportPhase { fun getCurrentPhase(duration: Long): SmsExportPhase {

Wyświetl plik

@ -362,14 +362,16 @@ public final class Megaphones {
private static @NonNull Megaphone buildSmsExportMegaphone(@NonNull Context context) { private static @NonNull Megaphone buildSmsExportMegaphone(@NonNull Context context) {
SmsExportPhase phase = SignalStore.misc().getSmsExportPhase(); SmsExportPhase phase = SignalStore.misc().getSmsExportPhase();
if (phase == SmsExportPhase.PHASE_1) { if (phase == SmsExportPhase.PHASE_0) {
throw new AssertionError("Should not be showing megaphone for Phase 0");
} else if (phase == SmsExportPhase.PHASE_1) {
return new Megaphone.Builder(Event.SMS_EXPORT, Megaphone.Style.BASIC) return new Megaphone.Builder(Event.SMS_EXPORT, Megaphone.Style.BASIC)
.setTitle(R.string.SmsExportMegaphone__sms_support_going_away) .setTitle(R.string.SmsExportMegaphone__sms_support_going_away)
.setImage(R.drawable.sms_megaphone) .setImage(R.drawable.sms_megaphone)
.setBody(R.string.SmsExportMegaphone__sms_support_will_be_removed_soon_to_focus_on_encrypted_messaging) .setBody(R.string.SmsExportMegaphone__sms_support_will_be_removed_soon_to_focus_on_encrypted_messaging)
.setActionButton(R.string.SmsExportMegaphone__export_sms, (megaphone, controller) -> controller.onMegaphoneNavigationRequested(SmsExportActivity.createIntent(context), SmsExportMegaphoneActivity.REQUEST_CODE)) .setActionButton(R.string.SmsExportMegaphone__export_sms, (megaphone, controller) -> controller.onMegaphoneNavigationRequested(SmsExportActivity.createIntent(context), SmsExportMegaphoneActivity.REQUEST_CODE))
.setSecondaryButton(R.string.Megaphones_remind_me_later, (megaphone, controller) -> controller.onMegaphoneSnooze(Event.SMS_EXPORT)) .setSecondaryButton(R.string.Megaphones_remind_me_later, (megaphone, controller) -> controller.onMegaphoneSnooze(Event.SMS_EXPORT))
.setOnVisibleListener((megaphone, controller) -> SignalStore.misc().setHasSeenSmsExportMegaphone()) .setOnVisibleListener((megaphone, controller) -> SignalStore.misc().startSmsPhase1())
.build(); .build();
} else { } else {
Megaphone.Builder builder = new Megaphone.Builder(Event.SMS_EXPORT, Megaphone.Style.FULLSCREEN) Megaphone.Builder builder = new Megaphone.Builder(Event.SMS_EXPORT, Megaphone.Style.FULLSCREEN)

Wyświetl plik

@ -2,9 +2,9 @@ package org.thoughtcrime.securesms.megaphone
import android.content.Context import android.content.Context
import androidx.annotation.WorkerThread import androidx.annotation.WorkerThread
import org.thoughtcrime.securesms.database.SignalDatabase.Companion.mmsSms
import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.keyvalue.SmsExportPhase import org.thoughtcrime.securesms.keyvalue.SmsExportPhase
import org.thoughtcrime.securesms.stories.Stories
import org.thoughtcrime.securesms.util.FeatureFlags import org.thoughtcrime.securesms.util.FeatureFlags
import org.thoughtcrime.securesms.util.Util import org.thoughtcrime.securesms.util.Util
import kotlin.time.Duration.Companion.days import kotlin.time.Duration.Companion.days
@ -23,6 +23,7 @@ class SmsExportReminderSchedule(private val context: Context) : MegaphoneSchedul
override fun shouldDisplay(seenCount: Int, lastSeen: Long, firstVisible: Long, currentTime: Long): Boolean { override fun shouldDisplay(seenCount: Int, lastSeen: Long, firstVisible: Long, currentTime: Long): Boolean {
return if (shouldShowMegaphone()) { return if (shouldShowMegaphone()) {
when (SignalStore.misc().smsExportPhase) { when (SignalStore.misc().smsExportPhase) {
SmsExportPhase.PHASE_0 -> false
SmsExportPhase.PHASE_1 -> basicMegaphoneSchedule.shouldDisplay(seenCount, lastSeen, firstVisible, currentTime) SmsExportPhase.PHASE_1 -> basicMegaphoneSchedule.shouldDisplay(seenCount, lastSeen, firstVisible, currentTime)
SmsExportPhase.PHASE_2 -> fullScreenSchedule.shouldDisplay(seenCount, lastSeen, firstVisible, currentTime) SmsExportPhase.PHASE_2 -> fullScreenSchedule.shouldDisplay(seenCount, lastSeen, firstVisible, currentTime)
SmsExportPhase.PHASE_3 -> showPhase3Megaphone SmsExportPhase.PHASE_3 -> showPhase3Megaphone
@ -32,8 +33,17 @@ class SmsExportReminderSchedule(private val context: Context) : MegaphoneSchedul
} }
} }
@Suppress("UsePropertyAccessSyntax")
@WorkerThread @WorkerThread
fun shouldShowMegaphone(): Boolean { fun shouldShowMegaphone(): Boolean {
return FeatureFlags.smsExporter() && (Util.isDefaultSmsProvider(context) || mmsSms.unexportedInsecureMessagesCount > 0) return if (Stories.isFeatureFlagEnabled() && SignalStore.misc().storiesFeatureAvailableTimestamp == 0L) {
SignalStore.misc().storiesFeatureAvailableTimestamp = System.currentTimeMillis()
false
} else if (System.currentTimeMillis() > (SignalStore.misc().storiesFeatureAvailableTimestamp + FeatureFlags.smsExportMegaphoneDelayDays().days.inWholeMilliseconds)) {
SignalStore.misc().startSmsPhase1()
FeatureFlags.smsExporter() && Util.isDefaultSmsProvider(context)
} else {
false
}
} }
} }

Wyświetl plik

@ -222,7 +222,7 @@ public final class RecipientBottomSheetDialogFragment extends BottomSheetDialogF
unblockButton.setVisibility(View.GONE); unblockButton.setVisibility(View.GONE);
} }
boolean isAudioAvailable = (recipient.isRegistered() || (Util.isDefaultSmsProvider(requireContext()) && SignalStore.misc().getSmsExportPhase().isSmsSupported())) && boolean isAudioAvailable = (recipient.isRegistered() || SignalStore.misc().getSmsExportPhase().allowSmsFeatures()) &&
!recipient.isGroup() && !recipient.isGroup() &&
!recipient.isBlocked() && !recipient.isBlocked() &&
!recipient.isSelf() && !recipient.isSelf() &&

Wyświetl plik

@ -104,7 +104,8 @@ public final class FeatureFlags {
private static final String CDS_V2_COMPAT = "android.cdsV2Compat.4"; private static final String CDS_V2_COMPAT = "android.cdsV2Compat.4";
public static final String STORIES_LOCALE = "android.stories.locale"; public static final String STORIES_LOCALE = "android.stories.locale";
private static final String HIDE_CONTACTS = "android.hide.contacts"; private static final String HIDE_CONTACTS = "android.hide.contacts";
public static final String MEDIA_PREVIEW_V2 = "android.mediaPreviewV2"; private static final String MEDIA_PREVIEW_V2 = "android.mediaPreviewV2";
private static final String SMS_EXPORT_MEGAPHONE_DELAY_DAYS = "android.smsExport.megaphoneDelayDays";
/** /**
* We will only store remote values for flags in this set. If you want a flag to be controllable * We will only store remote values for flags in this set. If you want a flag to be controllable
@ -161,7 +162,8 @@ public final class FeatureFlags {
CDS_V2_COMPAT, CDS_V2_COMPAT,
STORIES_LOCALE, STORIES_LOCALE,
HIDE_CONTACTS, HIDE_CONTACTS,
MEDIA_PREVIEW_V2 MEDIA_PREVIEW_V2,
SMS_EXPORT_MEGAPHONE_DELAY_DAYS
); );
@VisibleForTesting @VisibleForTesting
@ -225,7 +227,8 @@ public final class FeatureFlags {
CDS_V2_LOAD_TEST, CDS_V2_LOAD_TEST,
CDS_V2_COMPAT, CDS_V2_COMPAT,
STORIES, STORIES,
MEDIA_PREVIEW_V2 MEDIA_PREVIEW_V2,
SMS_EXPORT_MEGAPHONE_DELAY_DAYS
); );
/** /**
@ -585,6 +588,13 @@ public final class FeatureFlags {
return getBoolean(MEDIA_PREVIEW_V2, false); return getBoolean(MEDIA_PREVIEW_V2, false);
} }
/**
* Number of days to postpone the sms export megaphone and Phase 1 start.
*/
public static int smsExportMegaphoneDelayDays() {
return getInteger(SMS_EXPORT_MEGAPHONE_DELAY_DAYS, 14);
}
/** Only for rendering debug info. */ /** Only for rendering debug info. */
public static synchronized @NonNull Map<String, Object> getMemoryValues() { public static synchronized @NonNull Map<String, Object> getMemoryValues() {
return new TreeMap<>(REMOTE_VALUES); return new TreeMap<>(REMOTE_VALUES);

Wyświetl plik

@ -30,7 +30,7 @@ public class Stub<T extends View> {
} }
public void setVisibility(int visibility) { public void setVisibility(int visibility) {
if (resolved()) { if (resolved() || visibility == View.VISIBLE) {
get().setVisibility(visibility); get().setVisibility(visibility);
} }
} }

Wyświetl plik

@ -104,6 +104,7 @@
tools:visibility="visible"> tools:visibility="visible">
<TextView <TextView
android:id="@+id/mms_warning_text"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@drawable/rounded_outline_12" android:background="@drawable/rounded_outline_12"

Wyświetl plik

@ -822,7 +822,9 @@
<string name="AddGroupDetailsFragment__remove">Remove</string> <string name="AddGroupDetailsFragment__remove">Remove</string>
<string name="AddGroupDetailsFragment__sms_contact">SMS contact</string> <string name="AddGroupDetailsFragment__sms_contact">SMS contact</string>
<string name="AddGroupDetailsFragment__remove_s_from_this_group">Remove %1$s from this group?</string> <string name="AddGroupDetailsFragment__remove_s_from_this_group">Remove %1$s from this group?</string>
<!-- Displayed when adding group details to an MMS Group --> <!-- Info message shown in the middle of the screen, displayed when adding group details to an MMS Group -->
<string name="AddGroupDetailsFragment__youve_selected_a_contact_that_doesnt_support">You\'ve selected a contact that doesn\'t support Signal groups, so this group will be MMS. Custom MMS group names and photos will only be visible to you.</string>
<!-- Info message shown in the middle of the screen, displayed when adding group details to an MMS Group after SMS Phase 0 -->
<string name="AddGroupDetailsFragment__youve_selected_a_contact_that_doesnt_support_signal_groups_mms_removal">You\'ve selected a contact that dosen\'t support Signal groups, this group will be MMS. Custom MMS group names and photos will only be visible to you. Support for MMS groups will be removed soon to focus on encrypted messaging.</string> <string name="AddGroupDetailsFragment__youve_selected_a_contact_that_doesnt_support_signal_groups_mms_removal">You\'ve selected a contact that dosen\'t support Signal groups, this group will be MMS. Custom MMS group names and photos will only be visible to you. Support for MMS groups will be removed soon to focus on encrypted messaging.</string>
<!-- ManageGroupActivity --> <!-- ManageGroupActivity -->