Update username UX and UI.

This commit is contained in:
Alex Hart 2020-08-27 10:49:45 -03:00 committed by Alan Evans
parent b1befbeefc
commit 1425b651d4
31 changed files with 311 additions and 180 deletions

View file

@ -17,12 +17,15 @@
*/ */
package org.thoughtcrime.securesms; package org.thoughtcrime.securesms;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.graphics.PorterDuff; import android.graphics.PorterDuff;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
@ -30,6 +33,7 @@ import androidx.fragment.app.FragmentTransaction;
import androidx.preference.Preference; import androidx.preference.Preference;
import org.thoughtcrime.securesms.help.HelpFragment; import org.thoughtcrime.securesms.help.HelpFragment;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.preferences.AdvancedPreferenceFragment; import org.thoughtcrime.securesms.preferences.AdvancedPreferenceFragment;
import org.thoughtcrime.securesms.preferences.AppProtectionPreferenceFragment; import org.thoughtcrime.securesms.preferences.AppProtectionPreferenceFragment;
import org.thoughtcrime.securesms.preferences.AppearancePreferenceFragment; import org.thoughtcrime.securesms.preferences.AppearancePreferenceFragment;
@ -39,10 +43,13 @@ import org.thoughtcrime.securesms.preferences.NotificationsPreferenceFragment;
import org.thoughtcrime.securesms.preferences.SmsMmsPreferenceFragment; import org.thoughtcrime.securesms.preferences.SmsMmsPreferenceFragment;
import org.thoughtcrime.securesms.preferences.StoragePreferenceFragment; import org.thoughtcrime.securesms.preferences.StoragePreferenceFragment;
import org.thoughtcrime.securesms.preferences.widgets.ProfilePreference; import org.thoughtcrime.securesms.preferences.widgets.ProfilePreference;
import org.thoughtcrime.securesms.preferences.widgets.UsernamePreference;
import org.thoughtcrime.securesms.profiles.edit.EditProfileActivity; import org.thoughtcrime.securesms.profiles.edit.EditProfileActivity;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.service.KeyCachingService; import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.ThemeUtil; import org.thoughtcrime.securesms.util.ThemeUtil;
@ -60,6 +67,7 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActivity
private static final String TAG = ApplicationPreferencesActivity.class.getSimpleName(); private static final String TAG = ApplicationPreferencesActivity.class.getSimpleName();
private static final String PREFERENCE_CATEGORY_PROFILE = "preference_category_profile"; private static final String PREFERENCE_CATEGORY_PROFILE = "preference_category_profile";
private static final String PREFERENCE_CATEGORY_USERNAME = "preference_category_username";
private static final String PREFERENCE_CATEGORY_SMS_MMS = "preference_category_sms_mms"; private static final String PREFERENCE_CATEGORY_SMS_MMS = "preference_category_sms_mms";
private static final String PREFERENCE_CATEGORY_NOTIFICATIONS = "preference_category_notifications"; private static final String PREFERENCE_CATEGORY_NOTIFICATIONS = "preference_category_notifications";
private static final String PREFERENCE_CATEGORY_APP_PROTECTION = "preference_category_app_protection"; private static final String PREFERENCE_CATEGORY_APP_PROTECTION = "preference_category_app_protection";
@ -142,6 +150,8 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActivity
this.findPreference(PREFERENCE_CATEGORY_PROFILE) this.findPreference(PREFERENCE_CATEGORY_PROFILE)
.setOnPreferenceClickListener(new ProfileClickListener()); .setOnPreferenceClickListener(new ProfileClickListener());
this.findPreference(PREFERENCE_CATEGORY_USERNAME)
.setOnPreferenceClickListener(new UsernameClickListener());
this.findPreference(PREFERENCE_CATEGORY_SMS_MMS) this.findPreference(PREFERENCE_CATEGORY_SMS_MMS)
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_SMS_MMS)); .setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_SMS_MMS));
this.findPreference(PREFERENCE_CATEGORY_NOTIFICATIONS) this.findPreference(PREFERENCE_CATEGORY_NOTIFICATIONS)
@ -174,6 +184,24 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActivity
@Override @Override
public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) { public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.preferences); addPreferencesFromResource(R.xml.preferences);
if (FeatureFlags.usernames()) {
UsernamePreference pref = (UsernamePreference) findPreference(PREFERENCE_CATEGORY_USERNAME);
pref.setVisible(shouldDisplayUsernameReminder());
pref.setOnLongClickListener(v -> {
new AlertDialog.Builder(requireContext())
.setMessage(R.string.ApplicationPreferencesActivity_hide_reminder)
.setPositiveButton(R.string.ApplicationPreferencesActivity_hide, (dialog, which) -> {
dialog.dismiss();
SignalStore.misc().hideUsernameReminder();
findPreference(PREFERENCE_CATEGORY_USERNAME).setVisible(false);
})
.setNegativeButton(android.R.string.cancel, ((dialog, which) -> dialog.dismiss()))
.setCancelable(true)
.show();
return true;
});
}
} }
@Override @Override
@ -188,6 +216,11 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActivity
private void setCategorySummaries() { private void setCategorySummaries() {
((ProfilePreference)this.findPreference(PREFERENCE_CATEGORY_PROFILE)).refresh(); ((ProfilePreference)this.findPreference(PREFERENCE_CATEGORY_PROFILE)).refresh();
if (FeatureFlags.usernames()) {
this.findPreference(PREFERENCE_CATEGORY_USERNAME)
.setVisible(shouldDisplayUsernameReminder());
}
this.findPreference(PREFERENCE_CATEGORY_SMS_MMS) this.findPreference(PREFERENCE_CATEGORY_SMS_MMS)
.setSummary(SmsMmsPreferenceFragment.getSummary(getActivity())); .setSummary(SmsMmsPreferenceFragment.getSummary(getActivity()));
this.findPreference(PREFERENCE_CATEGORY_NOTIFICATIONS) this.findPreference(PREFERENCE_CATEGORY_NOTIFICATIONS)
@ -207,6 +240,10 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActivity
} }
} }
private static boolean shouldDisplayUsernameReminder() {
return FeatureFlags.usernames() && !Recipient.self().getUsername().isPresent() && SignalStore.misc().shouldShowUsernameReminder();
}
private class CategoryClickListener implements Preference.OnPreferenceClickListener { private class CategoryClickListener implements Preference.OnPreferenceClickListener {
private String category; private String category;
@ -276,6 +313,14 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActivity
return true; return true;
} }
} }
private class UsernameClickListener implements Preference.OnPreferenceClickListener {
@Override
public boolean onPreferenceClick(Preference preference) {
requireActivity().startActivity(EditProfileActivity.getIntentForUsernameEdit(preference.getContext()));
return true;
}
}
} }
} }

View file

@ -2015,11 +2015,7 @@ public class ConversationActivity extends PassphraseRequiredActivity
}); });
mentionsViewModel.getSelectedRecipient().observe(this, recipient -> { mentionsViewModel.getSelectedRecipient().observe(this, recipient -> {
String replacementDisplayName = recipient.getDisplayName(this); composeText.replaceTextWithMention(recipient.getDisplayName(this), recipient.getId());
if (replacementDisplayName.equals(recipient.getDisplayUsername())) {
replacementDisplayName = recipient.getUsername().or(replacementDisplayName);
}
composeText.replaceTextWithMention(replacementDisplayName, recipient.getId());
}); });
} }

View file

@ -394,7 +394,7 @@ public class ConversationFragment extends LoggingFragment {
if (recipient != null) { if (recipient != null) {
conversationBanner.setAvatar(GlideApp.with(context), recipient); conversationBanner.setAvatar(GlideApp.with(context), recipient);
String title = isSelf ? context.getString(R.string.note_to_self) : recipient.getDisplayName(context); String title = isSelf ? context.getString(R.string.note_to_self) : recipient.getDisplayNameOrUsername(context);
conversationBanner.setTitle(title); conversationBanner.setTitle(title);
if (recipient.isGroup()) { if (recipient.isGroup()) {
@ -411,7 +411,7 @@ public class ConversationFragment extends LoggingFragment {
} else if (isSelf) { } else if (isSelf) {
conversationBanner.setSubtitle(context.getString(R.string.ConversationFragment__you_can_add_notes_for_yourself_in_this_conversation)); conversationBanner.setSubtitle(context.getString(R.string.ConversationFragment__you_can_add_notes_for_yourself_in_this_conversation));
} else { } else {
String subtitle = recipient.getUsername().or(recipient.getE164()).orNull(); String subtitle = recipient.getE164().orNull();
if (subtitle == null || subtitle.equals(title)) { if (subtitle == null || subtitle.equals(title)) {
conversationBanner.hideSubtitle(); conversationBanner.hideSubtitle();

View file

@ -159,7 +159,7 @@ public class ConversationTitleView extends RelativeLayout {
} }
private void setIndividualRecipientTitle(Recipient recipient) { private void setIndividualRecipientTitle(Recipient recipient) {
final String displayName = recipient.getDisplayName(getContext()); final String displayName = recipient.getDisplayNameOrUsername(getContext());
this.title.setText(displayName); this.title.setText(displayName);
this.subtitle.setText(null); this.subtitle.setText(null);
updateVerifiedSubtitleVisibility(); updateVerifiedSubtitleVisibility();

View file

@ -16,7 +16,6 @@ public class MentionViewHolder extends MappingViewHolder<MentionViewState> {
private final AvatarImageView avatar; private final AvatarImageView avatar;
private final TextView name; private final TextView name;
private final TextView username;
@Nullable private final MentionEventsListener mentionEventsListener; @Nullable private final MentionEventsListener mentionEventsListener;
@ -26,14 +25,12 @@ public class MentionViewHolder extends MappingViewHolder<MentionViewState> {
avatar = findViewById(R.id.mention_recipient_avatar); avatar = findViewById(R.id.mention_recipient_avatar);
name = findViewById(R.id.mention_recipient_name); name = findViewById(R.id.mention_recipient_name);
username = findViewById(R.id.mention_recipient_username);
} }
@Override @Override
public void bind(@NonNull MentionViewState model) { public void bind(@NonNull MentionViewState model) {
avatar.setRecipient(model.getRecipient()); avatar.setRecipient(model.getRecipient());
name.setText(model.getName(context)); name.setText(model.getName(context));
username.setText(model.getUsername());
itemView.setOnClickListener(v -> { itemView.setOnClickListener(v -> {
if (mentionEventsListener != null) { if (mentionEventsListener != null) {
mentionEventsListener.onMentionClicked(model.getRecipient()); mentionEventsListener.onMentionClicked(model.getRecipient());

View file

@ -27,10 +27,6 @@ public final class MentionViewState implements MappingModel<MentionViewState> {
return recipient; return recipient;
} }
@NonNull String getUsername() {
return Util.emptyIfNull(recipient.getDisplayUsername());
}
@Override @Override
public boolean areItemsTheSame(@NonNull MentionViewState newItem) { public boolean areItemsTheSame(@NonNull MentionViewState newItem) {
return recipient.getId().equals(newItem.recipient.getId()); return recipient.getId().equals(newItem.recipient.getId());

View file

@ -18,6 +18,7 @@ import org.thoughtcrime.securesms.components.AvatarImageView;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.LifecycleRecyclerAdapter; import org.thoughtcrime.securesms.util.LifecycleRecyclerAdapter;
import org.thoughtcrime.securesms.util.LifecycleViewHolder; import org.thoughtcrime.securesms.util.LifecycleViewHolder;
import org.thoughtcrime.securesms.util.Util;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
@ -333,7 +334,7 @@ final class GroupMemberListAdapter extends LifecycleRecyclerAdapter<GroupMemberL
GroupMemberEntry.PendingMember pendingMember = (GroupMemberEntry.PendingMember) memberEntry; GroupMemberEntry.PendingMember pendingMember = (GroupMemberEntry.PendingMember) memberEntry;
bindRecipient(pendingMember.getInvitee()); bindImageAndText(pendingMember.getInvitee(), pendingMember.getInvitee().getDisplayNameOrUsername(context));
bindRecipientClick(pendingMember.getInvitee()); bindRecipientClick(pendingMember.getInvitee());
if (pendingMember.isCancellable() && adminActionsListener != null) { if (pendingMember.isCancellable() && adminActionsListener != null) {

View file

@ -30,7 +30,6 @@ import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.transport.RetryLaterException; import org.thoughtcrime.securesms.transport.RetryLaterException;
import org.thoughtcrime.securesms.util.Base64; import org.thoughtcrime.securesms.util.Base64;
import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.IdentityUtil; import org.thoughtcrime.securesms.util.IdentityUtil;
import org.thoughtcrime.securesms.util.ProfileUtil; import org.thoughtcrime.securesms.util.ProfileUtil;
import org.thoughtcrime.securesms.util.SetUtil; import org.thoughtcrime.securesms.util.SetUtil;
@ -55,7 +54,6 @@ import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -292,7 +290,7 @@ public class RetrieveProfileJob extends BaseJob {
setProfileName(recipient, profile.getName()); setProfileName(recipient, profile.getName());
setProfileAvatar(recipient, profile.getAvatar()); setProfileAvatar(recipient, profile.getAvatar());
if (FeatureFlags.usernames()) setUsername(recipient, profile.getUsername()); clearUsername(recipient);
setProfileCapabilities(recipient, profile.getCapabilities()); setProfileCapabilities(recipient, profile.getCapabilities());
setIdentityKey(recipient, profile.getIdentityKey()); setIdentityKey(recipient, profile.getIdentityKey());
setUnidentifiedAccessMode(recipient, profile.getUnidentifiedAccess(), profile.isUnrestrictedUnidentifiedAccess()); setUnidentifiedAccessMode(recipient, profile.getUnidentifiedAccess(), profile.isUnrestrictedUnidentifiedAccess());
@ -425,8 +423,8 @@ public class RetrieveProfileJob extends BaseJob {
} }
} }
private void setUsername(Recipient recipient, @Nullable String username) { private void clearUsername(Recipient recipient) {
DatabaseFactory.getRecipientDatabase(context).setUsername(recipient.getId(), username); DatabaseFactory.getRecipientDatabase(context).setUsername(recipient.getId(), null);
} }
private void setProfileCapabilities(@NonNull Recipient recipient, @Nullable SignalServiceProfile.Capabilities capabilities) { private void setProfileCapabilities(@NonNull Recipient recipient, @Nullable SignalServiceProfile.Capabilities capabilities) {

View file

@ -7,6 +7,7 @@ public final class MiscellaneousValues extends SignalStoreValues {
private static final String LAST_PREKEY_REFRESH_TIME = "last_prekey_refresh_time"; private static final String LAST_PREKEY_REFRESH_TIME = "last_prekey_refresh_time";
private static final String MESSAGE_REQUEST_ENABLE_TIME = "message_request_enable_time"; private static final String MESSAGE_REQUEST_ENABLE_TIME = "message_request_enable_time";
private static final String LAST_PROFILE_REFRESH_TIME = "misc.last_profile_refresh_time"; private static final String LAST_PROFILE_REFRESH_TIME = "misc.last_profile_refresh_time";
private static final String USERNAME_SHOW_REMINDER = "username.show.reminder";
MiscellaneousValues(@NonNull KeyValueStore store) { MiscellaneousValues(@NonNull KeyValueStore store) {
super(store); super(store);
@ -36,4 +37,12 @@ public final class MiscellaneousValues extends SignalStoreValues {
public void setLastProfileRefreshTime(long time) { public void setLastProfileRefreshTime(long time) {
putLong(LAST_PROFILE_REFRESH_TIME, time); putLong(LAST_PROFILE_REFRESH_TIME, time);
} }
public void hideUsernameReminder() {
putBoolean(USERNAME_SHOW_REMINDER, false);
}
public boolean shouldShowUsernameReminder() {
return getBoolean(USERNAME_SHOW_REMINDER, true);
}
} }

View file

@ -811,11 +811,7 @@ public class MediaSendActivity extends PassphraseRequiredActivity implements Med
}); });
mentionsViewModel.getSelectedRecipient().observe(this, recipient -> { mentionsViewModel.getSelectedRecipient().observe(this, recipient -> {
String replacementDisplayName = recipient.getDisplayName(this); composeText.replaceTextWithMention(recipient.getDisplayName(this), recipient.getId());
if (replacementDisplayName.equals(recipient.getDisplayUsername())) {
replacementDisplayName = recipient.getUsername().or(replacementDisplayName);
}
composeText.replaceTextWithMention(replacementDisplayName, recipient.getId());
}); });
MentionPickerPlacer mentionPickerPlacer = new MentionPickerPlacer(); MentionPickerPlacer mentionPickerPlacer = new MentionPickerPlacer();

View file

@ -0,0 +1,49 @@
package org.thoughtcrime.securesms.preferences.widgets;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
import org.thoughtcrime.securesms.R;
public class UsernamePreference extends Preference {
private View.OnLongClickListener onLongClickListener;
public UsernamePreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initialize();
}
public UsernamePreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initialize();
}
public UsernamePreference(Context context, AttributeSet attrs) {
super(context, attrs);
initialize();
}
public UsernamePreference(Context context) {
super(context);
initialize();
}
private void initialize() {
setLayoutResource(R.layout.preference_username);
}
public void setOnLongClickListener(View.OnLongClickListener onLongClickListener) {
this.onLongClickListener = onLongClickListener;
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
holder.itemView.setOnLongClickListener(onLongClickListener);
}
}

View file

@ -7,6 +7,7 @@ import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.navigation.NavDirections;
import androidx.navigation.NavGraph; import androidx.navigation.NavGraph;
import androidx.navigation.Navigation; import androidx.navigation.Navigation;
@ -19,12 +20,13 @@ import org.thoughtcrime.securesms.util.DynamicTheme;
@SuppressLint("StaticFieldLeak") @SuppressLint("StaticFieldLeak")
public class EditProfileActivity extends BaseActivity implements EditProfileFragment.Controller { public class EditProfileActivity extends BaseActivity implements EditProfileFragment.Controller {
public static final String NEXT_INTENT = "next_intent"; public static final String NEXT_INTENT = "next_intent";
public static final String EXCLUDE_SYSTEM = "exclude_system"; public static final String EXCLUDE_SYSTEM = "exclude_system";
public static final String DISPLAY_USERNAME = "display_username"; public static final String DISPLAY_USERNAME = "display_username";
public static final String NEXT_BUTTON_TEXT = "next_button_text"; public static final String NEXT_BUTTON_TEXT = "next_button_text";
public static final String SHOW_TOOLBAR = "show_back_arrow"; public static final String SHOW_TOOLBAR = "show_back_arrow";
public static final String GROUP_ID = "group_id"; public static final String GROUP_ID = "group_id";
public static final String START_AT_USERNAME = "start_at_username";
private final DynamicTheme dynamicTheme = new DynamicRegistrationTheme(); private final DynamicTheme dynamicTheme = new DynamicRegistrationTheme();
@ -50,6 +52,14 @@ public class EditProfileActivity extends BaseActivity implements EditProfileFrag
return intent; return intent;
} }
public static @NonNull Intent getIntentForUsernameEdit(@NonNull Context context) {
Intent intent = new Intent(context, EditProfileActivity.class);
intent.putExtra(EditProfileActivity.SHOW_TOOLBAR, true);
intent.putExtra(EditProfileActivity.DISPLAY_USERNAME, true);
intent.putExtra(EditProfileActivity.START_AT_USERNAME, true);
return intent;
}
@Override @Override
public void onCreate(Bundle bundle) { public void onCreate(Bundle bundle) {
super.onCreate(bundle); super.onCreate(bundle);
@ -63,6 +73,13 @@ public class EditProfileActivity extends BaseActivity implements EditProfileFrag
NavGraph graph = Navigation.findNavController(this, R.id.nav_host_fragment).getGraph(); NavGraph graph = Navigation.findNavController(this, R.id.nav_host_fragment).getGraph();
Navigation.findNavController(this, R.id.nav_host_fragment).setGraph(graph, extras != null ? extras : new Bundle()); Navigation.findNavController(this, R.id.nav_host_fragment).setGraph(graph, extras != null ? extras : new Bundle());
if (extras != null &&
extras.getBoolean(DISPLAY_USERNAME, false) &&
extras.getBoolean(START_AT_USERNAME, false)) {
NavDirections action = EditProfileFragmentDirections.actionEditUsername();
Navigation.findNavController(this, R.id.nav_host_fragment).navigate(action);
}
} }
} }

View file

@ -144,19 +144,6 @@ class EditSelfProfileRepository implements EditProfileRepository {
@Override @Override
public void getCurrentUsername(@NonNull Consumer<Optional<String>> callback) { public void getCurrentUsername(@NonNull Consumer<Optional<String>> callback) {
callback.accept(Optional.fromNullable(TextSecurePreferences.getLocalUsername(context))); callback.accept(Recipient.self().getUsername());
SignalExecutors.UNBOUNDED.execute(() -> callback.accept(getUsernameInternal()));
}
@WorkerThread
private @NonNull Optional<String> getUsernameInternal() {
try {
SignalServiceProfile profile = ProfileUtil.retrieveProfile(context, Recipient.self(), SignalServiceProfile.RequestType.PROFILE).get(5, TimeUnit.SECONDS).getProfile();
TextSecurePreferences.setLocalUsername(context, profile.getUsername());
DatabaseFactory.getRecipientDatabase(context).setUsername(Recipient.self().getId(), profile.getUsername());
} catch (TimeoutException | InterruptedException | ExecutionException e) {
Log.w(TAG, "Failed to retrieve username remotely! Using locally-cached version.");
}
return Optional.fromNullable(TextSecurePreferences.getLocalUsername(context));
} }
} }

View file

@ -398,15 +398,13 @@ public class Recipient {
* False iff it {@link #getDisplayName} would fall back to e164, email or unknown. * False iff it {@link #getDisplayName} would fall back to e164, email or unknown.
*/ */
public boolean hasAUserSetDisplayName(@NonNull Context context) { public boolean hasAUserSetDisplayName(@NonNull Context context) {
return !TextUtils.isEmpty(getName(context)) || return !TextUtils.isEmpty(getName(context)) ||
!TextUtils.isEmpty(getProfileName().toString()) || !TextUtils.isEmpty(getProfileName().toString());
!TextUtils.isEmpty(getDisplayUsername());
} }
public @NonNull String getDisplayName(@NonNull Context context) { public @NonNull String getDisplayName(@NonNull Context context) {
String name = Util.getFirstNonEmpty(getName(context), String name = Util.getFirstNonEmpty(getName(context),
getProfileName().toString(), getProfileName().toString(),
getDisplayUsername(),
e164, e164,
email, email,
context.getString(R.string.Recipient_unknown)); context.getString(R.string.Recipient_unknown));
@ -414,10 +412,20 @@ public class Recipient {
return StringUtil.isolateBidi(name); return StringUtil.isolateBidi(name);
} }
public @NonNull String getDisplayNameOrUsername(@NonNull Context context) {
String name = Util.getFirstNonEmpty(getName(context),
getProfileName().toString(),
e164,
email,
username,
context.getString(R.string.Recipient_unknown));
return StringUtil.isolateBidi(name);
}
public @NonNull String getMentionDisplayName(@NonNull Context context) { public @NonNull String getMentionDisplayName(@NonNull Context context) {
String name = Util.getFirstNonEmpty(localNumber ? getProfileName().toString() : getName(context), String name = Util.getFirstNonEmpty(localNumber ? getProfileName().toString() : getName(context),
localNumber ? getName(context) : getProfileName().toString(), localNumber ? getName(context) : getProfileName().toString(),
getDisplayUsername(),
e164, e164,
email, email,
context.getString(R.string.Recipient_unknown)); context.getString(R.string.Recipient_unknown));
@ -817,14 +825,6 @@ public class Recipient {
return ApplicationDependencies.getRecipientCache().getLive(id); return ApplicationDependencies.getRecipientCache().getLive(id);
} }
public @Nullable String getDisplayUsername() {
if (!TextUtils.isEmpty(username)) {
return "@" + username;
} else {
return null;
}
}
public @NonNull MentionSetting getMentionSetting() { public @NonNull MentionSetting getMentionSetting() {
return mentionSetting; return mentionSetting;
} }

View file

@ -157,7 +157,7 @@ public final class RecipientBottomSheetDialogFragment extends BottomSheetDialogF
} }
String usernameNumberString = recipient.hasAUserSetDisplayName(requireContext()) && !recipient.isLocalNumber() String usernameNumberString = recipient.hasAUserSetDisplayName(requireContext()) && !recipient.isLocalNumber()
? String.format("%s %s", recipient.getUsername().or(""), recipient.getSmsAddress().or("")).trim() ? recipient.getSmsAddress().or("").trim()
: ""; : "";
usernameNumber.setText(usernameNumberString); usernameNumber.setText(usernameNumberString);
usernameNumber.setVisibility(TextUtils.isEmpty(usernameNumberString) ? View.GONE : View.VISIBLE); usernameNumber.setVisibility(TextUtils.isEmpty(usernameNumberString) ? View.GONE : View.VISIBLE);

View file

@ -124,8 +124,7 @@ public final class ManageRecipientViewModel extends ViewModel {
private static @NonNull String getDisplaySubtitle(@NonNull Recipient recipient, @NonNull Context context) { private static @NonNull String getDisplaySubtitle(@NonNull Recipient recipient, @NonNull Context context) {
if (!recipient.isLocalNumber() && recipient.hasAUserSetDisplayName(context)) { if (!recipient.isLocalNumber() && recipient.hasAUserSetDisplayName(context)) {
return String.format("%s %s", recipient.getUsername().or(""), recipient.getSmsAddress().or("")) return recipient.getSmsAddress().or("").trim();
.trim();
} else { } else {
return ""; return "";
} }

View file

@ -13,8 +13,10 @@ import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProviders; import androidx.lifecycle.ViewModelProviders;
import androidx.navigation.Navigation;
import androidx.navigation.fragment.NavHostFragment; import androidx.navigation.fragment.NavHostFragment;
import com.dd.CircularProgressButton; import com.dd.CircularProgressButton;
@ -22,6 +24,7 @@ import com.dd.CircularProgressButton;
import org.thoughtcrime.securesms.LoggingFragment; import org.thoughtcrime.securesms.LoggingFragment;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.contactshare.SimpleTextWatcher; import org.thoughtcrime.securesms.contactshare.SimpleTextWatcher;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.UsernameUtil; import org.thoughtcrime.securesms.util.UsernameUtil;
@ -52,6 +55,10 @@ public class UsernameEditFragment extends LoggingFragment {
submitButton = view.findViewById(R.id.username_submit_button); submitButton = view.findViewById(R.id.username_submit_button);
deleteButton = view.findViewById(R.id.username_delete_button); deleteButton = view.findViewById(R.id.username_delete_button);
view.<Toolbar>findViewById(R.id.toolbar)
.setNavigationOnClickListener(v -> Navigation.findNavController(view)
.popBackStack());
viewModel = ViewModelProviders.of(this, new UsernameEditViewModel.Factory()).get(UsernameEditViewModel.class); viewModel = ViewModelProviders.of(this, new UsernameEditViewModel.Factory()).get(UsernameEditViewModel.class);
viewModel.getUiState().observe(getViewLifecycleOwner(), this::onUiStateChanged); viewModel.getUiState().observe(getViewLifecycleOwner(), this::onUiStateChanged);
@ -60,7 +67,7 @@ public class UsernameEditFragment extends LoggingFragment {
submitButton.setOnClickListener(v -> viewModel.onUsernameSubmitted(usernameInput.getText().toString())); submitButton.setOnClickListener(v -> viewModel.onUsernameSubmitted(usernameInput.getText().toString()));
deleteButton.setOnClickListener(v -> viewModel.onUsernameDeleted()); deleteButton.setOnClickListener(v -> viewModel.onUsernameDeleted());
usernameInput.setText(TextSecurePreferences.getLocalUsername(requireContext())); usernameInput.setText(Recipient.self().getUsername().orNull());
usernameInput.addTextChangedListener(new SimpleTextWatcher() { usernameInput.addTextChangedListener(new SimpleTextWatcher() {
@Override @Override
public void onTextChanged(String text) { public void onTextChanged(String text) {

View file

@ -12,16 +12,11 @@ import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.concurrent.SignalExecutors; import org.thoughtcrime.securesms.util.concurrent.SignalExecutors;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.SignalServiceAccountManager; import org.whispersystems.signalservice.api.SignalServiceAccountManager;
import org.whispersystems.signalservice.api.profiles.SignalServiceProfile;
import org.whispersystems.signalservice.api.push.exceptions.NotFoundException;
import org.whispersystems.signalservice.api.push.exceptions.UsernameMalformedException; import org.whispersystems.signalservice.api.push.exceptions.UsernameMalformedException;
import org.whispersystems.signalservice.api.push.exceptions.UsernameTakenException; import org.whispersystems.signalservice.api.push.exceptions.UsernameTakenException;
import org.whispersystems.signalservice.api.util.UuidUtil;
import java.io.IOException; import java.io.IOException;
import java.util.UUID;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
class UsernameEditRepository { class UsernameEditRepository {
@ -50,7 +45,6 @@ class UsernameEditRepository {
private @NonNull UsernameSetResult setUsernameInternal(@NonNull String username) { private @NonNull UsernameSetResult setUsernameInternal(@NonNull String username) {
try { try {
accountManager.setUsername(username); accountManager.setUsername(username);
TextSecurePreferences.setLocalUsername(application, username);
DatabaseFactory.getRecipientDatabase(application).setUsername(Recipient.self().getId(), username); DatabaseFactory.getRecipientDatabase(application).setUsername(Recipient.self().getId(), username);
Log.i(TAG, "[setUsername] Successfully set username."); Log.i(TAG, "[setUsername] Successfully set username.");
return UsernameSetResult.SUCCESS; return UsernameSetResult.SUCCESS;
@ -70,7 +64,6 @@ class UsernameEditRepository {
private @NonNull UsernameDeleteResult deleteUsernameInternal() { private @NonNull UsernameDeleteResult deleteUsernameInternal() {
try { try {
accountManager.deleteUsername(); accountManager.deleteUsername();
TextSecurePreferences.setLocalUsername(application, null);
DatabaseFactory.getRecipientDatabase(application).setUsername(Recipient.self().getId(), null); DatabaseFactory.getRecipientDatabase(application).setUsername(Recipient.self().getId(), null);
Log.i(TAG, "[deleteUsername] Successfully deleted the username."); Log.i(TAG, "[deleteUsername] Successfully deleted the username.");
return UsernameDeleteResult.SUCCESS; return UsernameDeleteResult.SUCCESS;

View file

@ -12,6 +12,7 @@ import androidx.lifecycle.ViewModelProvider;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.Debouncer; import org.thoughtcrime.securesms.util.Debouncer;
import org.thoughtcrime.securesms.util.SingleLiveEvent; import org.thoughtcrime.securesms.util.SingleLiveEvent;
import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.TextSecurePreferences;
@ -39,12 +40,12 @@ class UsernameEditViewModel extends ViewModel {
} }
void onUsernameUpdated(@NonNull String username) { void onUsernameUpdated(@NonNull String username) {
if (TextUtils.isEmpty(username) && TextSecurePreferences.getLocalUsername(application) != null) { if (TextUtils.isEmpty(username) && Recipient.self().getUsername().isPresent()) {
uiState.setValue(new State(ButtonState.DELETE, UsernameStatus.NONE)); uiState.setValue(new State(ButtonState.DELETE, UsernameStatus.NONE));
return; return;
} }
if (username.equals(TextSecurePreferences.getLocalUsername(application))) { if (username.equals(Recipient.self().getUsername().orNull())) {
uiState.setValue(new State(ButtonState.SUBMIT_DISABLED, UsernameStatus.NONE)); uiState.setValue(new State(ButtonState.SUBMIT_DISABLED, UsernameStatus.NONE));
return; return;
} }
@ -60,7 +61,7 @@ class UsernameEditViewModel extends ViewModel {
} }
void onUsernameSubmitted(@NonNull String username) { void onUsernameSubmitted(@NonNull String username) {
if (username.equals(TextSecurePreferences.getLocalUsername(application))) { if (username.equals(Recipient.self().getUsername().orNull())) {
uiState.setValue(new State(ButtonState.SUBMIT_DISABLED, UsernameStatus.NONE)); uiState.setValue(new State(ButtonState.SUBMIT_DISABLED, UsernameStatus.NONE));
return; return;
} }

View file

@ -79,6 +79,7 @@ public final class FeatureFlags {
GROUPS_V2_LINKS_VERSION, GROUPS_V2_LINKS_VERSION,
CDS, CDS,
INTERNAL_USER, INTERNAL_USER,
USERNAMES,
MENTIONS, MENTIONS,
VERIFY_V2 VERIFY_V2
); );

View file

@ -694,14 +694,6 @@ public class TextSecurePreferences {
setStringPreference(context, LOCAL_UUID_PREF, uuid.toString()); setStringPreference(context, LOCAL_UUID_PREF, uuid.toString());
} }
public static String getLocalUsername(Context context) {
return getStringPreference(context, LOCAL_USERNAME_PREF, null);
}
public static void setLocalUsername(Context context, String username) {
setStringPreference(context, LOCAL_USERNAME_PREF, username);
}
public static String getPushServerPassword(Context context) { public static String getPushServerPassword(Context context) {
return getStringPreference(context, GCM_PASSWORD_PREF, null); return getStringPreference(context, GCM_PASSWORD_PREF, null);
} }

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke android:color="@color/core_grey_85" android:width="1.5dp" />
<corners android:radius="12dp" />
</shape>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke android:color="@color/core_grey_05" android:width="1.5dp" />
<corners android:radius="12dp" />
</shape>

View file

@ -30,15 +30,4 @@
android:textAppearance="@style/Signal.Text.Preview" android:textAppearance="@style/Signal.Text.Preview"
tools:text="@tools:sample/full_names" /> tools:text="@tools:sample/full_names" />
<TextView
android:id="@+id/mention_recipient_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:textAlignment="viewStart"
android:textAppearance="@style/Signal.Text.Preview"
android:textColor="@color/core_grey_60"
tools:text="@tools:sample/last_names" />
</LinearLayout> </LinearLayout>

View file

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="?attr/selectableItemBackground"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="15dp"
android:layout_marginBottom="8dp"
android:background="?attr/preference_username_background"
android:drawablePadding="18dp"
android:gravity="center_vertical"
android:paddingStart="18dp"
android:paddingEnd="18dp"
android:text="@string/preferences_setup_a_username"
android:textAppearance="@style/Signal.Text.Body"
app:drawableStartCompat="@drawable/ic_at_24"
app:drawableTint="?colorAccent" />
</FrameLayout>

View file

@ -4,89 +4,108 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:orientation="vertical"> android:orientation="vertical">
<EditText <androidx.appcompat.widget.Toolbar
android:id="@+id/username_text" android:id="@+id/toolbar"
style="@style/Signal.Text.Body" android:layout_width="match_parent"
android:layout_width="0dp" android:layout_height="?attr/actionBarSize"
android:layout_height="wrap_content" android:visibility="visible"
android:layout_marginTop="48dp" app:layout_constraintEnd_toEndOf="parent"
android:hint="@string/CreateProfileActivity__create_a_username" app:layout_constraintStart_toStartOf="parent"
android:imeOptions="actionDone" app:layout_constraintTop_toTopOf="parent"
android:inputType="text" app:navigationIcon="@drawable/ic_arrow_left_24"
android:maxLines="1" app:title="@string/UsernameEditFragment_username" />
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView <EditText
android:id="@+id/username_subtext" android:id="@+id/username_text"
style="@style/Signal.Text.Caption" style="@style/Signal.Text.Body"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="16dp" android:layout_marginStart="16dp"
app:layout_constraintEnd_toEndOf="parent" android:layout_marginTop="8dp"
app:layout_constraintStart_toStartOf="parent" android:layout_marginEnd="16dp"
app:layout_constraintTop_toBottomOf="@id/username_text" android:hint="@string/UsernameEditFragment_username"
tools:text="Some error code" /> android:imeOptions="actionDone"
android:inputType="text"
android:maxLines="1"
android:minHeight="56dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/toolbar" />
<TextView <TextView
android:id="@+id/username_description" android:id="@+id/username_subtext"
style="@style/Signal.Text.Caption" style="@style/Signal.Text.Caption"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="wrap_content"
android:layout_marginTop="16dp" android:layout_marginStart="16dp"
android:layout_marginBottom="16dp" android:layout_marginTop="16dp"
android:text="@string/UsernameEditFragment_other_signal_users_can_send_message_requests_to_your_unique_username" android:layout_marginEnd="16dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/username_subtext" app:layout_constraintTop_toBottomOf="@id/username_text"
app:layout_constraintBottom_toTopOf="@id/username_button_barrier" /> tools:text="Some error code" />
<com.dd.CircularProgressButton <TextView
android:id="@+id/username_submit_button" android:id="@+id/username_description"
android:layout_width="0dp" style="@style/Signal.Text.Caption"
android:layout_height="wrap_content" android:layout_width="0dp"
android:layout_marginTop="32dp" android:layout_height="0dp"
android:background="@color/core_ultramarine" android:layout_marginStart="16dp"
android:textAllCaps="true" android:layout_marginTop="16dp"
android:textColor="@color/white" android:layout_marginEnd="16dp"
app:cpb_colorIndicator="@color/white" android:layout_marginBottom="16dp"
app:cpb_colorProgress="@color/core_ultramarine" android:text="@string/UsernameEditFragment_usernames_on_signal_are_optional"
app:cpb_cornerRadius="4dp" app:layout_constraintBottom_toTopOf="@id/username_button_barrier"
app:cpb_selectorIdle="@drawable/progress_button_state_light" app:layout_constraintEnd_toEndOf="parent"
app:cpb_textIdle="@string/UsernameEditFragment_submit" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toBottomOf="@id/username_subtext" />
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<com.dd.CircularProgressButton <com.dd.CircularProgressButton
android:id="@+id/username_delete_button" android:id="@+id/username_submit_button"
android:layout_width="0dp" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="32dp" android:layout_marginStart="16dp"
android:background="@color/core_red" android:layout_marginTop="32dp"
android:textAllCaps="true" android:layout_marginEnd="16dp"
android:textColor="@color/white" android:layout_marginBottom="16dp"
android:visibility="gone" android:background="@color/core_ultramarine"
app:cpb_colorIndicator="@color/white" android:textAllCaps="true"
app:cpb_colorProgress="@color/core_red" android:textColor="@color/white"
app:cpb_cornerRadius="4dp" app:cpb_colorIndicator="?colorAccent"
app:cpb_selectorIdle="@drawable/progress_button_state_red" app:cpb_colorProgress="@color/transparent"
app:cpb_textIdle="@string/UsernameEditFragment_delete" app:cpb_cornerRadius="4dp"
app:layout_constraintBottom_toBottomOf="parent" app:cpb_selectorIdle="@drawable/progress_button_state_light"
app:layout_constraintEnd_toEndOf="parent" app:cpb_textIdle="@string/save"
app:layout_constraintStart_toStartOf="parent" /> app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<androidx.constraintlayout.widget.Barrier <com.dd.CircularProgressButton
android:id="@+id/username_button_barrier" android:id="@+id/username_delete_button"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:barrierDirection="top" android:layout_marginStart="16dp"
app:constraint_referenced_ids="username_submit_button,username_delete_button"/> android:layout_marginTop="32dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:background="@color/core_red"
android:textAllCaps="true"
android:textColor="@color/white"
android:visibility="gone"
app:cpb_colorIndicator="@color/core_red"
app:cpb_colorProgress="@color/transparent"
app:cpb_cornerRadius="4dp"
app:cpb_selectorIdle="@drawable/progress_button_state_red"
app:cpb_textIdle="@string/UsernameEditFragment_delete"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/username_button_barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="top"
app:constraint_referenced_ids="username_submit_button,username_delete_button" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -253,6 +253,8 @@
<attr name="pref_divider" format="reference" /> <attr name="pref_divider" format="reference" />
<attr name="preference_username_background" format="reference" />
<attr name="quote_missing_icon_color" format="color" /> <attr name="quote_missing_icon_color" format="color" />
<attr name="quote_dismiss_button_tint" format="color" /> <attr name="quote_dismiss_button_tint" format="color" />

View file

@ -56,6 +56,8 @@
<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>
<string name="ApplicationPreferencesActivity_pin_disabled">PIN disabled.</string> <string name="ApplicationPreferencesActivity_pin_disabled">PIN disabled.</string>
<string name="ApplicationPreferencesActivity_hide">Hide</string>
<string name="ApplicationPreferencesActivity_hide_reminder">Hide reminder?</string>
<!-- AppProtectionPreferenceFragment --> <!-- AppProtectionPreferenceFragment -->
<plurals name="AppProtectionPreferenceFragment_minutes"> <plurals name="AppProtectionPreferenceFragment_minutes">
@ -1381,7 +1383,6 @@
<!-- UsernameEditFragment --> <!-- UsernameEditFragment -->
<string name="UsernameEditFragment_username">Username</string> <string name="UsernameEditFragment_username">Username</string>
<string name="UsernameEditFragment_submit">Submit</string>
<string name="UsernameEditFragment_delete">Delete</string> <string name="UsernameEditFragment_delete">Delete</string>
<string name="UsernameEditFragment_successfully_set_username">Successfully set username.</string> <string name="UsernameEditFragment_successfully_set_username">Successfully set username.</string>
<string name="UsernameEditFragment_successfully_removed_username">Successfully removed username.</string> <string name="UsernameEditFragment_successfully_removed_username">Successfully removed username.</string>
@ -1392,7 +1393,7 @@
<string name="UsernameEditFragment_usernames_cannot_begin_with_a_number">Usernames cannot begin with a number.</string> <string name="UsernameEditFragment_usernames_cannot_begin_with_a_number">Usernames cannot begin with a number.</string>
<string name="UsernameEditFragment_username_is_invalid">Username is invalid.</string> <string name="UsernameEditFragment_username_is_invalid">Username is invalid.</string>
<string name="UsernameEditFragment_usernames_must_be_between_a_and_b_characters">Usernames must be between %1$d and %2$d characters.</string> <string name="UsernameEditFragment_usernames_must_be_between_a_and_b_characters">Usernames must be between %1$d and %2$d characters.</string>
<string name="UsernameEditFragment_other_signal_users_can_send_message_requests_to_your_unique_username">Other Signal users can send message requests to your unique username without knowing your phone number. Choosing a username is optional.</string> <string name="UsernameEditFragment_usernames_on_signal_are_optional">Usernames on Signal are optional. If you choose to create a username, other Signal users will be able to find you by this username and contact you without knowing your phone number.</string>
<!-- VerifyIdentityActivity --> <!-- VerifyIdentityActivity -->
<string name="VerifyIdentityActivity_your_contact_is_running_an_old_version_of_signal">Your contact is running an old version of Signal. Please ask them to update before verifying your safety number.</string> <string name="VerifyIdentityActivity_your_contact_is_running_an_old_version_of_signal">Your contact is running an old version of Signal. Please ask them to update before verifying your safety number.</string>
@ -2125,6 +2126,7 @@
<string name="preferences_notifications__mentions">Mentions</string> <string name="preferences_notifications__mentions">Mentions</string>
<string name="preferences_notifications__notify_me">Notify me</string> <string name="preferences_notifications__notify_me">Notify me</string>
<string name="preferences_notifications__receive_notifications_when_youre_mentioned_in_muted_chats">Receive notifications when youre mentioned in muted chats</string> <string name="preferences_notifications__receive_notifications_when_youre_mentioned_in_muted_chats">Receive notifications when youre mentioned in muted chats</string>
<string name="preferences_setup_a_username">Setup a username</string>
<!-- Internal only preferences --> <!-- Internal only preferences -->
<string name="preferences__internal_preferences" translatable="false">Internal Preferences</string> <string name="preferences__internal_preferences" translatable="false">Internal Preferences</string>
@ -2595,7 +2597,6 @@
<string name="GroupsLearnMore_paragraph_2">Legacy Groups cant be converted into New Groups, but you can create a New Group with the same members.</string> <string name="GroupsLearnMore_paragraph_2">Legacy Groups cant be converted into New Groups, but you can create a New Group with the same members.</string>
<string name="GroupsLearnMore_paragraph_3">To create a New Group, all members should update to the latest version of Signal.</string> <string name="GroupsLearnMore_paragraph_3">To create a New Group, all members should update to the latest version of Signal.</string>
<!-- GroupLinkBottomSheetDialogFragment --> <!-- GroupLinkBottomSheetDialogFragment -->
<string name="GroupLinkBottomSheet_share_via_signal">Share via Signal</string> <string name="GroupLinkBottomSheet_share_via_signal">Share via Signal</string>
<string name="GroupLinkBottomSheet_copy">Copy</string> <string name="GroupLinkBottomSheet_copy">Copy</string>

View file

@ -431,6 +431,8 @@
<item name="pref_divider">@drawable/preference_divider_light</item> <item name="pref_divider">@drawable/preference_divider_light</item>
<item name="preference_username_background">@drawable/preference_username_background_light</item>
<item name="quote_missing_icon_color">@color/core_grey_60</item> <item name="quote_missing_icon_color">@color/core_grey_60</item>
<item name="quote_dismiss_button_tint">@color/core_grey_70</item> <item name="quote_dismiss_button_tint">@color/core_grey_70</item>
@ -758,6 +760,8 @@
<item name="pref_divider">@drawable/preference_divider_dark</item> <item name="pref_divider">@drawable/preference_divider_dark</item>
<item name="preference_username_background">@drawable/preference_username_background_dark</item>
<item name="quote_missing_icon_color">@color/core_grey_05</item> <item name="quote_missing_icon_color">@color/core_grey_05</item>
<item name="quote_dismiss_button_tint">@color/core_white</item> <item name="quote_dismiss_button_tint">@color/core_white</item>

View file

@ -1,10 +1,15 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<org.thoughtcrime.securesms.preferences.widgets.ProfilePreference <org.thoughtcrime.securesms.preferences.widgets.ProfilePreference
android:key="preference_category_profile"/> android:key="preference_category_profile"/>
<org.thoughtcrime.securesms.preferences.widgets.UsernamePreference
app:isPreferenceVisible="false"
android:key="preference_category_username"/>
<Preference android:key="preference_category_sms_mms" <Preference android:key="preference_category_sms_mms"
android:title="@string/preferences__sms_mms" android:title="@string/preferences__sms_mms"
android:icon="?attr/message_icon"/> android:icon="?attr/message_icon"/>

View file

@ -41,9 +41,6 @@ public class SignalServiceProfile {
@JsonProperty @JsonProperty
private Capabilities capabilities; private Capabilities capabilities;
@JsonProperty
private String username;
@JsonProperty @JsonProperty
@JsonSerialize(using = JsonUtil.UuidSerializer.class) @JsonSerialize(using = JsonUtil.UuidSerializer.class)
@JsonDeserialize(using = JsonUtil.UuidDeserializer.class) @JsonDeserialize(using = JsonUtil.UuidDeserializer.class)
@ -81,10 +78,6 @@ public class SignalServiceProfile {
return capabilities; return capabilities;
} }
public String getUsername() {
return username;
}
public UUID getUuid() { public UUID getUuid() {
return uuid; return uuid;
} }