Improve handling of unregistered states in profile screen.

This commit is contained in:
Greyson Parrelli
2024-03-12 11:37:59 -04:00
committed by Cody Henthorne
parent ce778be895
commit 5027159ed8
12 changed files with 162 additions and 111 deletions
@@ -1,25 +0,0 @@
package org.thoughtcrime.securesms.components.reminder;
import android.content.Context;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.registration.RegistrationNavigationActivity;
public class PushRegistrationReminder extends Reminder {
public PushRegistrationReminder(final Context context) {
super(R.string.reminder_header_push_title, R.string.reminder_header_push_text);
setOkListener(v -> context.startActivity(RegistrationNavigationActivity.newIntentForReRegistration(context)));
}
@Override
public boolean isDismissable() {
return false;
}
public static boolean isEligible() {
return !SignalStore.account().isRegistered();
}
}
@@ -5,6 +5,7 @@ import android.content.Context;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.registration.RegistrationNavigationActivity; import org.thoughtcrime.securesms.registration.RegistrationNavigationActivity;
import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.TextSecurePreferences;
@@ -26,6 +27,6 @@ public class UnauthorizedReminder extends Reminder {
} }
public static boolean isEligible(Context context) { public static boolean isEligible(Context context) {
return TextSecurePreferences.isUnauthorizedReceived(context); return TextSecurePreferences.isUnauthorizedReceived(context) || !SignalStore.account().isRegistered();
} }
} }
@@ -160,7 +160,7 @@ class AppSettingsFragment : DSLSettingsFragment(
onClick = { onClick = {
findNavController().safeNavigate(R.id.action_appSettingsFragment_to_deviceActivity) findNavController().safeNavigate(R.id.action_appSettingsFragment_to_deviceActivity)
}, },
isEnabled = state.isDeprecatedOrUnregistered() isEnabled = state.isRegisteredAndUpToDate()
) )
if (state.allowUserToGoToDonationManagementScreen) { if (state.allowUserToGoToDonationManagementScreen) {
@@ -197,7 +197,7 @@ class AppSettingsFragment : DSLSettingsFragment(
onClick = { onClick = {
findNavController().safeNavigate(R.id.action_appSettingsFragment_to_chatsSettingsFragment) findNavController().safeNavigate(R.id.action_appSettingsFragment_to_chatsSettingsFragment)
}, },
isEnabled = state.isDeprecatedOrUnregistered() isEnabled = state.isRegisteredAndUpToDate()
) )
clickPref( clickPref(
@@ -206,7 +206,7 @@ class AppSettingsFragment : DSLSettingsFragment(
onClick = { onClick = {
findNavController().safeNavigate(AppSettingsFragmentDirections.actionAppSettingsFragmentToStoryPrivacySettings(R.string.preferences__stories)) findNavController().safeNavigate(AppSettingsFragmentDirections.actionAppSettingsFragmentToStoryPrivacySettings(R.string.preferences__stories))
}, },
isEnabled = state.isDeprecatedOrUnregistered() isEnabled = state.isRegisteredAndUpToDate()
) )
clickPref( clickPref(
@@ -215,7 +215,7 @@ class AppSettingsFragment : DSLSettingsFragment(
onClick = { onClick = {
findNavController().safeNavigate(R.id.action_appSettingsFragment_to_notificationsSettingsFragment) findNavController().safeNavigate(R.id.action_appSettingsFragment_to_notificationsSettingsFragment)
}, },
isEnabled = state.isDeprecatedOrUnregistered() isEnabled = state.isRegisteredAndUpToDate()
) )
clickPref( clickPref(
@@ -224,7 +224,7 @@ class AppSettingsFragment : DSLSettingsFragment(
onClick = { onClick = {
findNavController().safeNavigate(R.id.action_appSettingsFragment_to_privacySettingsFragment) findNavController().safeNavigate(R.id.action_appSettingsFragment_to_privacySettingsFragment)
}, },
isEnabled = state.isDeprecatedOrUnregistered() isEnabled = state.isRegisteredAndUpToDate()
) )
clickPref( clickPref(
@@ -10,7 +10,7 @@ data class AppSettingsState(
val userUnregistered: Boolean, val userUnregistered: Boolean,
val clientDeprecated: Boolean val clientDeprecated: Boolean
) { ) {
fun isDeprecatedOrUnregistered(): Boolean { fun isRegisteredAndUpToDate(): Boolean {
return !(userUnregistered || clientDeprecated) return !userUnregistered && !clientDeprecated
} }
} }
@@ -24,7 +24,7 @@ class AppSettingsViewModel(
0, 0,
SignalStore.donationsValues().getExpiredGiftBadge() != null, SignalStore.donationsValues().getExpiredGiftBadge() != null,
SignalStore.donationsValues().isLikelyASustainer() || InAppDonations.hasAtLeastOnePaymentMethodAvailable(), SignalStore.donationsValues().isLikelyASustainer() || InAppDonations.hasAtLeastOnePaymentMethodAvailable(),
TextSecurePreferences.isUnauthorizedReceived(ApplicationDependencies.getApplication()), TextSecurePreferences.isUnauthorizedReceived(ApplicationDependencies.getApplication()) || !SignalStore.account().isRegistered,
SignalStore.misc().isClientDeprecated SignalStore.misc().isClientDeprecated
) )
) )
@@ -54,7 +54,12 @@ class AppSettingsViewModel(
} }
fun refreshDeprecatedOrUnregistered() { fun refreshDeprecatedOrUnregistered() {
store.update { it.copy(clientDeprecated = SignalStore.misc().isClientDeprecated, userUnregistered = TextSecurePreferences.isUnauthorizedReceived(ApplicationDependencies.getApplication())) } store.update {
it.copy(
clientDeprecated = SignalStore.misc().isClientDeprecated,
userUnregistered = TextSecurePreferences.isUnauthorizedReceived(ApplicationDependencies.getApplication()) || !SignalStore.account().isRegistered
)
}
} }
fun refreshExpiredGiftBadge() { fun refreshExpiredGiftBadge() {
@@ -12,6 +12,7 @@ import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.signal.core.util.AppUtil import org.signal.core.util.AppUtil
import org.signal.core.util.ThreadUtil
import org.signal.core.util.concurrent.SignalExecutors import org.signal.core.util.concurrent.SignalExecutors
import org.signal.core.util.concurrent.SimpleTask import org.signal.core.util.concurrent.SimpleTask
import org.signal.core.util.logging.Log import org.signal.core.util.logging.Log
@@ -24,6 +25,7 @@ import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.settings.DSLConfiguration import org.thoughtcrime.securesms.components.settings.DSLConfiguration
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
import org.thoughtcrime.securesms.components.settings.DSLSettingsText import org.thoughtcrime.securesms.components.settings.DSLSettingsText
import org.thoughtcrime.securesms.components.settings.app.privacy.advanced.AdvancedPrivacySettingsRepository
import org.thoughtcrime.securesms.components.settings.configure import org.thoughtcrime.securesms.components.settings.configure
import org.thoughtcrime.securesms.database.JobDatabase import org.thoughtcrime.securesms.database.JobDatabase
import org.thoughtcrime.securesms.database.LocalMetricsDatabase import org.thoughtcrime.securesms.database.LocalMetricsDatabase
@@ -140,6 +142,14 @@ class InternalSettingsFragment : DSLSettingsFragment(R.string.preferences__inter
} }
) )
clickPref(
title = DSLSettingsText.from("Unregister"),
summary = DSLSettingsText.from("This will unregister your account without deleting it."),
onClick = {
onUnregisterClicked()
}
)
dividerPref() dividerPref()
sectionHeaderPref(DSLSettingsText.from("Miscellaneous")) sectionHeaderPref(DSLSettingsText.from("Miscellaneous"))
@@ -803,6 +813,32 @@ class InternalSettingsFragment : DSLSettingsFragment(R.string.preferences__inter
} }
} }
private fun onUnregisterClicked() {
MaterialAlertDialogBuilder(requireContext())
.setTitle("Unregister?")
.setMessage("Are you sure? You'll have to re-register to use Signal again -- no promises that the process will go smoothly.")
.setPositiveButton(android.R.string.ok) { _, _ ->
AdvancedPrivacySettingsRepository(requireContext()).disablePushMessages {
ThreadUtil.runOnMain {
when (it) {
AdvancedPrivacySettingsRepository.DisablePushMessagesResult.SUCCESS -> {
SignalStore.account().setRegistered(false)
SignalStore.registrationValues().clearRegistrationComplete()
SignalStore.registrationValues().clearHasUploadedProfile()
Toast.makeText(context, "Unregistered!", Toast.LENGTH_SHORT).show()
}
AdvancedPrivacySettingsRepository.DisablePushMessagesResult.NETWORK_ERROR -> {
Toast.makeText(context, "Network error!", Toast.LENGTH_SHORT).show()
}
}
}
}
}
.setNegativeButton(android.R.string.cancel, null)
.show()
}
private fun copyPaymentsDataToClipboard() { private fun copyPaymentsDataToClipboard() {
MaterialAlertDialogBuilder(requireContext()) MaterialAlertDialogBuilder(requireContext())
.setMessage( .setMessage(
@@ -6,16 +6,12 @@ import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.graphics.PorterDuff import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter import android.graphics.PorterDuffColorFilter
import android.graphics.drawable.Drawable
import android.net.ConnectivityManager import android.net.ConnectivityManager
import android.text.SpannableStringBuilder import android.text.SpannableStringBuilder
import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.widget.TextViewCompat
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.SignalProgressDialog import org.thoughtcrime.securesms.components.SignalProgressDialog
import org.thoughtcrime.securesms.components.settings.DSLConfiguration import org.thoughtcrime.securesms.components.settings.DSLConfiguration
@@ -24,7 +20,6 @@ import org.thoughtcrime.securesms.components.settings.DSLSettingsText
import org.thoughtcrime.securesms.components.settings.configure import org.thoughtcrime.securesms.components.settings.configure
import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter
import org.thoughtcrime.securesms.registration.RegistrationNavigationActivity
import org.thoughtcrime.securesms.util.CommunicationActions import org.thoughtcrime.securesms.util.CommunicationActions
import org.thoughtcrime.securesms.util.SpanUtil import org.thoughtcrime.securesms.util.SpanUtil
import org.thoughtcrime.securesms.util.ViewUtil import org.thoughtcrime.securesms.util.ViewUtil
@@ -107,40 +102,6 @@ class AdvancedPrivacySettingsFragment : DSLSettingsFragment(R.string.preferences
private fun getConfiguration(state: AdvancedPrivacySettingsState): DSLConfiguration { private fun getConfiguration(state: AdvancedPrivacySettingsState): DSLConfiguration {
return configure { return configure {
switchPref(
title = DSLSettingsText.from(R.string.preferences__signal_messages_and_calls),
summary = DSLSettingsText.from(getPushToggleSummary(state.isPushEnabled)),
isChecked = state.isPushEnabled
) {
if (state.isPushEnabled) {
val builder = MaterialAlertDialogBuilder(requireContext()).apply {
setMessage(R.string.ApplicationPreferencesActivity_disable_signal_messages_and_calls_by_unregistering)
setNegativeButton(android.R.string.cancel, null)
setPositiveButton(
android.R.string.ok
) { _, _ -> viewModel.disablePushMessages() }
}
val icon: Drawable = requireNotNull(ContextCompat.getDrawable(builder.context, R.drawable.symbol_info_24))
icon.setBounds(0, 0, ViewUtil.dpToPx(32), ViewUtil.dpToPx(32))
val title = TextView(builder.context)
val padding = ViewUtil.dpToPx(16)
title.setText(R.string.ApplicationPreferencesActivity_disable_signal_messages_and_calls)
title.setPadding(padding, padding, padding, padding)
title.compoundDrawablePadding = padding / 2
TextViewCompat.setTextAppearance(title, R.style.TextAppearance_Signal_Title2_MaterialDialog)
TextViewCompat.setCompoundDrawablesRelative(title, icon, null, null, null)
builder
.setCustomTitle(title)
.setOnDismissListener { viewModel.refresh() }
.show()
} else {
startActivity(RegistrationNavigationActivity.newIntentForReRegistration(requireContext()))
}
}
switchPref( switchPref(
title = DSLSettingsText.from(R.string.preferences_advanced__always_relay_calls), title = DSLSettingsText.from(R.string.preferences_advanced__always_relay_calls),
summary = DSLSettingsText.from(R.string.preferences_advanced__relay_all_calls_through_the_signal_server_to_avoid_revealing_your_ip_address), summary = DSLSettingsText.from(R.string.preferences_advanced__relay_all_calls_through_the_signal_server_to_avoid_revealing_your_ip_address),
@@ -38,25 +38,6 @@ class AdvancedPrivacySettingsViewModel(
) )
} }
fun disablePushMessages() {
store.update { getState().copy(showProgressSpinner = true) }
repository.disablePushMessages {
when (it) {
AdvancedPrivacySettingsRepository.DisablePushMessagesResult.SUCCESS -> {
SignalStore.account().setRegistered(false)
SignalStore.registrationValues().clearRegistrationComplete()
SignalStore.registrationValues().clearHasUploadedProfile()
}
AdvancedPrivacySettingsRepository.DisablePushMessagesResult.NETWORK_ERROR -> {
singleEvents.postValue(Event.DISABLE_PUSH_FAILED)
}
}
store.update { getState().copy(showProgressSpinner = false) }
}
}
fun setAlwaysRelayCalls(enabled: Boolean) { fun setAlwaysRelayCalls(enabled: Boolean) {
sharedPreferences.edit().putBoolean(TextSecurePreferences.ALWAYS_RELAY_CALLS_PREF, enabled).apply() sharedPreferences.edit().putBoolean(TextSecurePreferences.ALWAYS_RELAY_CALLS_PREF, enabled).apply()
refresh() refresh()
@@ -105,7 +105,6 @@ import org.thoughtcrime.securesms.components.reminder.CdsTemporaryErrorReminder;
import org.thoughtcrime.securesms.components.reminder.DozeReminder; import org.thoughtcrime.securesms.components.reminder.DozeReminder;
import org.thoughtcrime.securesms.components.reminder.ExpiredBuildReminder; import org.thoughtcrime.securesms.components.reminder.ExpiredBuildReminder;
import org.thoughtcrime.securesms.components.reminder.OutdatedBuildReminder; import org.thoughtcrime.securesms.components.reminder.OutdatedBuildReminder;
import org.thoughtcrime.securesms.components.reminder.PushRegistrationReminder;
import org.thoughtcrime.securesms.components.reminder.Reminder; import org.thoughtcrime.securesms.components.reminder.Reminder;
import org.thoughtcrime.securesms.components.reminder.ReminderView; import org.thoughtcrime.securesms.components.reminder.ReminderView;
import org.thoughtcrime.securesms.components.reminder.ServiceOutageReminder; import org.thoughtcrime.securesms.components.reminder.ServiceOutageReminder;
@@ -1047,8 +1046,6 @@ public class ConversationListFragment extends MainFragment implements ActionMode
return Optional.of(new ServiceOutageReminder()); return Optional.of(new ServiceOutageReminder());
} else if (OutdatedBuildReminder.isEligible()) { } else if (OutdatedBuildReminder.isEligible()) {
return Optional.of(new OutdatedBuildReminder(context)); return Optional.of(new OutdatedBuildReminder(context));
} else if (PushRegistrationReminder.isEligible()) {
return Optional.of((new PushRegistrationReminder(context)));
} else if (DozeReminder.isEligible(context)) { } else if (DozeReminder.isEligible(context)) {
return Optional.of(new DozeReminder(context)); return Optional.of(new DozeReminder(context));
} else if (CdsTemporaryErrorReminder.isEligible()) { } else if (CdsTemporaryErrorReminder.isEligible()) {
@@ -37,7 +37,9 @@ import org.thoughtcrime.securesms.profiles.ProfileName
import org.thoughtcrime.securesms.profiles.manage.EditProfileViewModel.AvatarState import org.thoughtcrime.securesms.profiles.manage.EditProfileViewModel.AvatarState
import org.thoughtcrime.securesms.profiles.manage.UsernameRepository.UsernameDeleteResult import org.thoughtcrime.securesms.profiles.manage.UsernameRepository.UsernameDeleteResult
import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.registration.RegistrationNavigationActivity
import org.thoughtcrime.securesms.util.NameUtil.getAbbreviation import org.thoughtcrime.securesms.util.NameUtil.getAbbreviation
import org.thoughtcrime.securesms.util.PlayStoreUtil
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil import org.thoughtcrime.securesms.util.livedata.LiveDataUtil
import org.thoughtcrime.securesms.util.navigation.safeNavigate import org.thoughtcrime.securesms.util.navigation.safeNavigate
import org.thoughtcrime.securesms.util.views.SimpleProgressDialog import org.thoughtcrime.securesms.util.views.SimpleProgressDialog
@@ -55,6 +57,8 @@ class EditProfileFragment : LoggingFragment() {
private lateinit var binding: EditProfileFragmentBinding private lateinit var binding: EditProfileFragmentBinding
private lateinit var disposables: LifecycleDisposable private lateinit var disposables: LifecycleDisposable
private val DISABLED_ALPHA = 0.4f
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
binding = EditProfileFragmentBinding.inflate(inflater, container, false) binding = EditProfileFragmentBinding.inflate(inflater, container, false)
return binding.root return binding.root
@@ -75,11 +79,27 @@ class EditProfileFragment : LoggingFragment() {
initializeViewModel() initializeViewModel()
binding.toolbar.setNavigationOnClickListener { requireActivity().finish() } binding.toolbar.setNavigationOnClickListener { requireActivity().finish() }
binding.manageProfileEditPhoto.setOnClickListener { onEditAvatarClicked() }
binding.manageProfileNameContainer.setOnClickListener { v: View -> findNavController(v).safeNavigate(EditProfileFragmentDirections.actionManageProfileName()) } binding.manageProfileEditPhoto.setOnClickListener {
if (!viewModel.isRegisteredAndUpToDate) {
onClickWhenUnregisteredOrDeprecated()
} else {
onEditAvatarClicked()
}
}
binding.manageProfileNameContainer.setOnClickListener { v: View ->
if (!viewModel.isRegisteredAndUpToDate) {
onClickWhenUnregisteredOrDeprecated()
} else {
findNavController(v).safeNavigate(EditProfileFragmentDirections.actionManageProfileName())
}
}
binding.manageProfileUsernameContainer.setOnClickListener { v: View -> binding.manageProfileUsernameContainer.setOnClickListener { v: View ->
if (SignalStore.account().username != null) { if (!viewModel.isRegisteredAndUpToDate) {
onClickWhenUnregisteredOrDeprecated()
} else if (SignalStore.account().username != null) {
MaterialAlertDialogBuilder(requireContext(), R.style.ThemeOverlay_Signal_MaterialAlertDialog_List) MaterialAlertDialogBuilder(requireContext(), R.style.ThemeOverlay_Signal_MaterialAlertDialog_List)
.setItems(R.array.username_edit_entries) { _: DialogInterface?, w: Int -> .setItems(R.array.username_edit_entries) { _: DialogInterface?, w: Int ->
when (w) { when (w) {
@@ -94,10 +114,18 @@ class EditProfileFragment : LoggingFragment() {
} }
} }
binding.manageProfileAboutContainer.setOnClickListener { v: View -> findNavController(v).safeNavigate(EditProfileFragmentDirections.actionManageAbout()) } binding.manageProfileAboutContainer.setOnClickListener { v: View ->
if (!viewModel.isRegisteredAndUpToDate) {
onClickWhenUnregisteredOrDeprecated()
} else {
findNavController(v).safeNavigate(EditProfileFragmentDirections.actionManageAbout())
}
}
parentFragmentManager.setFragmentResultListener(AvatarPickerFragment.REQUEST_KEY_SELECT_AVATAR, viewLifecycleOwner) { _: String?, bundle: Bundle -> parentFragmentManager.setFragmentResultListener(AvatarPickerFragment.REQUEST_KEY_SELECT_AVATAR, viewLifecycleOwner) { _: String?, bundle: Bundle ->
if (bundle.getBoolean(AvatarPickerFragment.SELECT_AVATAR_CLEAR)) { if (!viewModel.isRegisteredAndUpToDate) {
onClickWhenUnregisteredOrDeprecated()
} else if (bundle.getBoolean(AvatarPickerFragment.SELECT_AVATAR_CLEAR)) {
viewModel.onAvatarSelected(requireContext(), null) viewModel.onAvatarSelected(requireContext(), null)
} else { } else {
val result = bundle.getParcelable<Media>(AvatarPickerFragment.SELECT_AVATAR_MEDIA) val result = bundle.getParcelable<Media>(AvatarPickerFragment.SELECT_AVATAR_MEDIA)
@@ -113,7 +141,9 @@ class EditProfileFragment : LoggingFragment() {
} }
binding.manageProfileBadgesContainer.setOnClickListener { v: View -> binding.manageProfileBadgesContainer.setOnClickListener { v: View ->
if (Recipient.self().badges.isEmpty()) { if (!viewModel.isRegisteredAndUpToDate) {
onClickWhenUnregisteredOrDeprecated()
} else if (Recipient.self().badges.isEmpty()) {
show(parentFragmentManager) show(parentFragmentManager)
} else { } else {
findNavController(v).safeNavigate(EditProfileFragmentDirections.actionManageProfileFragmentToBadgeManageFragment()) findNavController(v).safeNavigate(EditProfileFragmentDirections.actionManageProfileFragmentToBadgeManageFragment())
@@ -121,10 +151,14 @@ class EditProfileFragment : LoggingFragment() {
} }
binding.manageProfileAvatar.setOnClickListener { binding.manageProfileAvatar.setOnClickListener {
startActivity( if (!viewModel.isRegisteredAndUpToDate) {
AvatarPreviewActivity.intentFromRecipientId(requireContext(), Recipient.self().id), onClickWhenUnregisteredOrDeprecated()
AvatarPreviewActivity.createTransitionBundle(requireActivity(), binding.manageProfileAvatar) } else {
) startActivity(
AvatarPreviewActivity.intentFromRecipientId(requireContext(), Recipient.self().id),
AvatarPreviewActivity.createTransitionBundle(requireActivity(), binding.manageProfileAvatar)
)
}
} }
} }
@@ -154,6 +188,10 @@ class EditProfileFragment : LoggingFragment() {
} else { } else {
Glide.with(this).load(null as Drawable?).into(binding.manageProfileAvatar) Glide.with(this).load(null as Drawable?).into(binding.manageProfileAvatar)
} }
binding.manageProfileAvatar.alpha = if (viewModel.isRegisteredAndUpToDate) 1.0f else DISABLED_ALPHA
binding.manageProfileAvatarInitials.alpha = if (viewModel.isRegisteredAndUpToDate) 1.0f else DISABLED_ALPHA
binding.manageProfileEditPhoto.isEnabled = viewModel.isRegisteredAndUpToDate
} }
private fun presentAvatarPlaceholder(avatarState: AvatarState) { private fun presentAvatarPlaceholder(avatarState: AvatarState) {
@@ -205,6 +243,9 @@ class EditProfileFragment : LoggingFragment() {
} else { } else {
binding.manageProfileName.text = profileName.toString() binding.manageProfileName.text = profileName.toString()
} }
binding.manageProfileName.isEnabled = viewModel.isRegisteredAndUpToDate
binding.manageProfileNameIcon.alpha = if (viewModel.isRegisteredAndUpToDate) 1.0f else DISABLED_ALPHA
} }
private fun presentUsername(username: String?) { private fun presentUsername(username: String?) {
@@ -244,6 +285,9 @@ class EditProfileFragment : LoggingFragment() {
binding.usernameLinkContainer.visibility = View.GONE binding.usernameLinkContainer.visibility = View.GONE
binding.usernameInfoText.setText(R.string.ManageProfileFragment__username_footer_no_username) binding.usernameInfoText.setText(R.string.ManageProfileFragment__username_footer_no_username)
} }
binding.manageProfileUsername.isEnabled = viewModel.isRegisteredAndUpToDate
binding.manageProfileUsernameIcon.alpha = if (viewModel.isRegisteredAndUpToDate) 1.0f else DISABLED_ALPHA
} }
private fun presentAbout(about: String?) { private fun presentAbout(about: String?) {
@@ -252,6 +296,9 @@ class EditProfileFragment : LoggingFragment() {
} else { } else {
binding.manageProfileAbout.text = about binding.manageProfileAbout.text = about
} }
binding.manageProfileAbout.isEnabled = viewModel.isRegisteredAndUpToDate
binding.manageProfileAboutIcon.alpha = if (viewModel.isRegisteredAndUpToDate) 1.0f else DISABLED_ALPHA
} }
private fun presentAboutEmoji(aboutEmoji: String?) { private fun presentAboutEmoji(aboutEmoji: String?) {
@@ -273,6 +320,14 @@ class EditProfileFragment : LoggingFragment() {
} else { } else {
binding.manageProfileBadge.setBadge(null) binding.manageProfileBadge.setBadge(null)
} }
binding.manageProfileBadges.isEnabled = viewModel.isRegisteredAndUpToDate
binding.manageProfileBadge.alpha = if (viewModel.isRegisteredAndUpToDate) 1.0f else DISABLED_ALPHA
binding.manageProfileBadgesIcon.alpha = if (viewModel.isRegisteredAndUpToDate) 1.0f else DISABLED_ALPHA
if (!viewModel.isRegisteredAndUpToDate) {
binding.manageProfileBadge.setOnClickListener { onClickWhenUnregisteredOrDeprecated() }
}
} }
private fun presentEvent(event: EditProfileViewModel.Event) { private fun presentEvent(event: EditProfileViewModel.Event) {
@@ -316,4 +371,28 @@ class EditProfileFragment : LoggingFragment() {
UsernameDeleteResult.NETWORK_ERROR -> Snackbar.make(requireView(), R.string.ManageProfileFragment__couldnt_delete_username, Snackbar.LENGTH_SHORT).show() UsernameDeleteResult.NETWORK_ERROR -> Snackbar.make(requireView(), R.string.ManageProfileFragment__couldnt_delete_username, Snackbar.LENGTH_SHORT).show()
} }
} }
private fun onClickWhenUnregisteredOrDeprecated() {
if (viewModel.isDeprecated) {
MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.EditProfileFragment_deprecated_dialog_title)
.setMessage(R.string.EditProfileFragment_deprecated_dialog_body)
.setNegativeButton(android.R.string.cancel) { d, _ -> d.dismiss() }
.setPositiveButton(R.string.EditProfileFragment_deprecated_dialog_update_button) { d, _ ->
PlayStoreUtil.openPlayStoreOrOurApkDownloadPage(requireContext())
d.dismiss()
}
.show()
} else {
MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.EditProfileFragment_unregistered_dialog_title)
.setMessage(R.string.EditProfileFragment_unregistered_dialog_body)
.setNegativeButton(android.R.string.cancel) { d, _ -> d.dismiss() }
.setPositiveButton(R.string.EditProfileFragment_unregistered_dialog_reregister_button) { d, _ ->
startActivity(RegistrationNavigationActivity.newIntentForReRegistration(requireContext()))
d.dismiss()
}
.show()
}
}
} }
@@ -24,8 +24,8 @@ import org.thoughtcrime.securesms.providers.BlobProvider;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientForeverObserver; import org.thoughtcrime.securesms.recipients.RecipientForeverObserver;
import org.thoughtcrime.securesms.util.DefaultValueLiveData; import org.thoughtcrime.securesms.util.DefaultValueLiveData;
import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.SingleLiveEvent; import org.thoughtcrime.securesms.util.SingleLiveEvent;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil; import org.thoughtcrime.securesms.util.livedata.LiveDataUtil;
import org.whispersystems.signalservice.api.util.StreamDetails; import org.whispersystems.signalservice.api.util.StreamDetails;
@@ -107,6 +107,14 @@ class EditProfileViewModel extends ViewModel {
return UsernameRepository.deleteUsernameAndLink().observeOn(AndroidSchedulers.mainThread()); return UsernameRepository.deleteUsernameAndLink().observeOn(AndroidSchedulers.mainThread());
} }
public boolean isRegisteredAndUpToDate() {
return !TextSecurePreferences.isUnauthorizedReceived(ApplicationDependencies.getApplication()) && SignalStore.account().isRegistered() && !SignalStore.misc().isClientDeprecated();
}
public boolean isDeprecated() {
return SignalStore.misc().isClientDeprecated();
}
public void onAvatarSelected(@NonNull Context context, @Nullable Media media) { public void onAvatarSelected(@NonNull Context context, @Nullable Media media) {
previousAvatar = internalAvatarState.getValue() != null ? internalAvatarState.getValue().getAvatar() : null; previousAvatar = internalAvatarState.getValue() != null ? internalAvatarState.getValue().getAvatar() : null;
+12 -4
View File
@@ -45,8 +45,6 @@
<string name="ApplicationPreferencesActivity_disable_passphrase">Disable passphrase?</string> <string name="ApplicationPreferencesActivity_disable_passphrase">Disable passphrase?</string>
<string name="ApplicationPreferencesActivity_this_will_permanently_unlock_signal_and_message_notifications">This will permanently unlock Signal and message notifications.</string> <string name="ApplicationPreferencesActivity_this_will_permanently_unlock_signal_and_message_notifications">This will permanently unlock Signal and message notifications.</string>
<string name="ApplicationPreferencesActivity_disable">Disable</string> <string name="ApplicationPreferencesActivity_disable">Disable</string>
<string name="ApplicationPreferencesActivity_disable_signal_messages_and_calls">Disable Signal messages and calls?</string>
<string name="ApplicationPreferencesActivity_disable_signal_messages_and_calls_by_unregistering">Disable Signal messages and calls by unregistering from the server. You will need to re-register your phone number to use them again in the future.</string>
<string name="ApplicationPreferencesActivity_error_connecting_to_server">Error connecting to server!</string> <string name="ApplicationPreferencesActivity_error_connecting_to_server">Error connecting to server!</string>
<string name="ApplicationPreferencesActivity_pins_are_required_for_registration_lock">PINs are required for registration lock. To disable PINs, please first disable registration lock.</string> <string name="ApplicationPreferencesActivity_pins_are_required_for_registration_lock">PINs are required for registration lock. To disable PINs, please first disable registration lock.</string>
<string name="ApplicationPreferencesActivity_pin_created">PIN created.</string> <string name="ApplicationPreferencesActivity_pin_created">PIN created.</string>
@@ -2928,6 +2926,18 @@
<string name="EditProfileFragment__group_name">Group name</string> <string name="EditProfileFragment__group_name">Group name</string>
<string name="EditProfileFragment__group_description">Group description</string> <string name="EditProfileFragment__group_description">Group description</string>
<string name="EditProfileFragment__support_link" translatable="false">https://support.signal.org/hc/articles/360007459591</string> <string name="EditProfileFragment__support_link" translatable="false">https://support.signal.org/hc/articles/360007459591</string>
<!-- The title of a dialog prompting user to update to the latest version of Signal. -->
<string name="EditProfileFragment_deprecated_dialog_title">Update Signal</string>
<!-- The body of a dialog prompting user to update to the latest version of Signal. -->
<string name="EditProfileFragment_deprecated_dialog_body">This version of Signal has expired. Update now to continue using Signal.</string>
<!-- The button on a dialog prompting user to update to the latest version of Signal. When clicked, the user will be taken to the store to update their app. -->
<string name="EditProfileFragment_deprecated_dialog_update_button">Update</string>
<!-- The title of a dialog informing the user that they cannot use this app feature when they are unregistered. -->
<string name="EditProfileFragment_unregistered_dialog_title">Device not registered</string>
<!-- The body of a dialog informing the user that they cannot use this app feature when they are unregistered. -->
<string name="EditProfileFragment_unregistered_dialog_body">This device is no longer registered. Re-register to make changes to your account.</string>
<!-- The button on a dialog informing the user that they cannot use this app feature when they are unregistered. When clicked, the user will be taken to a screen to help them re-register. -->
<string name="EditProfileFragment_unregistered_dialog_reregister_button">Re-register</string>
<!-- EditProfileNameFragment --> <!-- EditProfileNameFragment -->
<string name="EditProfileNameFragment_your_name">Your name</string> <string name="EditProfileNameFragment_your_name">Your name</string>
@@ -3666,8 +3676,6 @@
<string name="verify_display_fragment_context_menu__compare_with_clipboard">Compare with clipboard</string> <string name="verify_display_fragment_context_menu__compare_with_clipboard">Compare with clipboard</string>
<!-- reminder_header --> <!-- reminder_header -->
<string name="reminder_header_push_title">Enable Signal messages and calls</string>
<string name="reminder_header_push_text">Upgrade your communication experience.</string>
<string name="reminder_header_service_outage_text">Signal is experiencing technical difficulties. We are working hard to restore service as quickly as possible.</string> <string name="reminder_header_service_outage_text">Signal is experiencing technical difficulties. We are working hard to restore service as quickly as possible.</string>
<string name="reminder_header_progress">%1$d%%</string> <string name="reminder_header_progress">%1$d%%</string>
<!-- Body text of a banner that will show at the top of the chat list when we temporarily cannot process the user\'s contacts --> <!-- Body text of a banner that will show at the top of the chat list when we temporarily cannot process the user\'s contacts -->