Username onboarding

This commit is contained in:
Fedor Indutny 2023-02-13 10:51:41 -08:00 committed by GitHub
parent 5626cea9c3
commit f9aaf30a32
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 309 additions and 3 deletions

View file

@ -6383,6 +6383,30 @@
"message": "These digits help keep your username private so you can avoid unwanted messages. Share your username with only the people and groups youd like to chat with. If you change usernames youll get a new set of digits.",
"description": "Body of the popup with information about discriminator in username"
},
"icu:UsernameOnboardingModalBody__title": {
"messageformat": "Set up your Signal username",
"description": "Title of username onboarding modal"
},
"icu:UsernameOnboardingModalBody__row__number": {
"messageformat": "Usernames are paired with a set of digits and arent shared on your profile",
"description": "Content of the first row of username onboarding modal"
},
"icu:UsernameOnboardingModalBody__row__link": {
"messageformat": "Each username has a unique link you can share with your friends to start a chat with you",
"description": "Content of the second row of username onboarding modal"
},
"icu:UsernameOnboardingModalBody__row__lock": {
"messageformat": "Turn off phone number discovery under Settings > Phone Number > Who can find my number, to use your username as the primary way others can contact you.",
"description": "Content of the third row of username onboarding modal"
},
"icu:UsernameOnboardingModalBody__learn-more": {
"messageformat": "Learn More",
"description": "Text that open a popup with information about username onboarding"
},
"icu:UsernameOnboardingModalBody__continue": {
"messageformat": "Continue",
"description": "Text of the primary button on username onboarding modal"
},
"icu:UnsupportedOSWarningDialog__body": {
"messageformat": "Signal desktop will no longer support your computers version of {OS} soon. To keep using Signal, update your computers operating system by {expirationDate}. <learnMoreLink>Learn more</learnMoreLink>",
"description": "Body of a dialog displayed on unsupported operating systems"

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="none"><path fill="#fff" fill-rule="evenodd" d="M20.648 18.834a.945.945 0 0 1 0-1.31l2.976-3.06c1.761-1.81 1.761-4.744 0-6.554a4.424 4.424 0 0 0-6.377 0l-2.976 3.059a.885.885 0 0 1-1.276 0 .945.945 0 0 1 0-1.311l2.976-3.06a6.194 6.194 0 0 1 8.929 0c2.465 2.535 2.465 6.643 0 9.178l-2.976 3.058a.885.885 0 0 1-1.276 0ZM10.02 14.028a.945.945 0 0 1 0 1.311l-2.976 3.059c-1.761 1.81-1.761 4.744 0 6.555a4.424 4.424 0 0 0 6.378 0l2.976-3.06a.885.885 0 0 1 1.275 0 .945.945 0 0 1 0 1.312l-2.976 3.059a6.193 6.193 0 0 1-8.928 0c-2.466-2.534-2.466-6.643 0-9.177l2.976-3.059a.885.885 0 0 1 1.275 0Zm8.504.437a.945.945 0 0 0 0-1.31.885.885 0 0 0-1.276 0l-5.102 5.243a.945.945 0 0 0 0 1.311.885.885 0 0 0 1.276 0l5.102-5.244Z" clip-rule="evenodd"/><path fill="#647392" fill-rule="evenodd" d="M19.573 19.88a2.445 2.445 0 0 1 0-3.403l2.976-3.059c1.195-1.227 1.195-3.234 0-4.462a2.924 2.924 0 0 0-4.227 0l-2.976 3.059a2.385 2.385 0 0 1-3.426 0 2.445 2.445 0 0 1 0-3.403l2.976-3.06L15.971 6.6l-2.976 3.059a.945.945 0 0 0 0 1.31.885.885 0 0 0 1.276 0l2.976-3.058a4.424 4.424 0 0 1 6.377 0c1.761 1.81 1.761 4.745 0 6.554l-2.976 3.06a.945.945 0 0 0 0 1.31.885.885 0 0 0 1.276 0l2.976-3.059c2.465-2.534 2.465-6.642 0-9.176a6.194 6.194 0 0 0-8.929 0l-1.075-1.046a7.693 7.693 0 0 1 11.079 0c3.032 3.116 3.032 8.152 0 11.269l-2.976 3.058a2.385 2.385 0 0 1-3.426 0Zm-1.765 1.882.94-.914a2.445 2.445 0 0 1 0 3.403l-2.977 3.058a7.693 7.693 0 0 1-11.078 0c-3.033-3.116-3.033-8.152 0-11.268l2.976-3.059a2.385 2.385 0 0 1 3.425 0 2.445 2.445 0 0 1 0 3.403l-2.976 3.059c-1.194 1.228-1.194 3.235 0 4.463a2.924 2.924 0 0 0 4.228 0l2.976-3.06a2.385 2.385 0 0 1 3.425 0l-.939.915Zm1.79-9.654a2.445 2.445 0 0 1 0 3.403l-5.102 5.244a2.385 2.385 0 0 1-3.426 0 2.445 2.445 0 0 1 0-3.403l5.102-5.244a2.385 2.385 0 0 1 3.426 0Zm-9.579 3.231a.945.945 0 0 0 0-1.31.885.885 0 0 0-1.275 0l-2.976 3.058c-2.466 2.534-2.466 6.643 0 9.177a6.193 6.193 0 0 0 8.928 0l2.976-3.06a.945.945 0 0 0 0-1.31.885.885 0 0 0-1.275 0l-2.976 3.059a4.424 4.424 0 0 1-6.378 0c-1.761-1.81-1.761-4.745 0-6.555l2.976-3.059Zm8.504-2.185a.945.945 0 0 1 0 1.311L13.42 19.71a.885.885 0 0 1-1.276 0 .945.945 0 0 1 0-1.31l5.102-5.245a.885.885 0 0 1 1.276 0Z" clip-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="none"><path fill="#FFE3A5" d="M8 8.667a8 8 0 1 1 16 0v4.252c-.44-.22-.93-.32-1.525-.37a22.132 22.132 0 0 0-1.675-.048V8.8a4.8 4.8 0 1 0-9.6 0v3.7a22.12 22.12 0 0 0-1.675.048c-.595.05-1.084.15-1.525.37V8.666ZM8.658 14.266c.2-.102.476-.18.99-.222.526-.043 1.204-.044 2.192-.044h8.32c.988 0 1.666 0 2.192.044.514.042.79.12.99.222.456.235.828.609 1.06 1.069.102.2.179.479.22.996.044.53.045 1.213.045 2.209v5.587c0 .995-.001 1.678-.044 2.208-.042.518-.12.796-.22.997-.233.46-.605.834-1.061 1.068-.2.103-.476.18-.99.223-.526.043-1.204.044-2.192.044h-8.32c-.988 0-1.666-.001-2.192-.044-.514-.043-.79-.12-.99-.223a2.436 2.436 0 0 1-1.06-1.068c-.102-.201-.179-.48-.22-.997-.044-.53-.045-1.213-.045-2.208V18.54c0-.995.001-1.679.044-2.209.042-.517.119-.795.22-.996.233-.46.605-.834 1.061-1.069Z"/><path fill="#B3841C" fill-rule="evenodd" d="M16 .667a8 8 0 0 0-8 8v4.251c.435-.217.916-.317 1.5-.367V8.667a6.5 6.5 0 1 1 13 0v3.884c.584.05 1.065.15 1.5.367V8.668a8 8 0 0 0-8-8ZM20.8 12.5V8.8a4.8 4.8 0 1 0-9.6 0v3.7l.618-.001h.882V8.8a3.3 3.3 0 0 1 6.6 0v3.7h1.5Z" clip-rule="evenodd"/><path fill="#B2841C" fill-rule="evenodd" d="M11.818 12.5c-.952 0-1.696 0-2.293.05-.607.05-1.104.152-1.552.382-.74.38-1.339.984-1.714 1.726-.226.447-.328.943-.377 1.552-.049.6-.049 1.349-.049 2.31v5.628c0 .96 0 1.708.049 2.308.05.61.151 1.106.377 1.553a3.935 3.935 0 0 0 1.714 1.726c.448.23.945.333 1.552.383.597.049 1.341.049 2.293.049h8.364c.952 0 1.696 0 2.293-.05.607-.05 1.104-.152 1.552-.382.74-.38 1.339-.985 1.714-1.726.226-.447.328-.944.377-1.553.049-.6.049-1.348.049-2.308v-5.629c0-.96 0-1.708-.049-2.309-.05-.609-.151-1.105-.377-1.552a3.936 3.936 0 0 0-1.714-1.726c-.448-.23-.945-.333-1.552-.383-.597-.049-1.341-.049-2.293-.049h-8.364Zm-2.17 1.544c-.514.042-.79.12-.99.222a2.436 2.436 0 0 0-1.06 1.069c-.102.2-.179.479-.22.996-.044.53-.045 1.213-.045 2.209v5.587c0 .995.001 1.678.044 2.208.042.518.119.796.22.997.233.46.605.834 1.061 1.068.2.103.476.18.99.223.526.043 1.204.044 2.192.044h8.32c.988 0 1.666-.001 2.192-.044.514-.043.79-.12.99-.223a2.436 2.436 0 0 0 1.06-1.068c.102-.201.179-.48.22-.997.044-.53.045-1.213.045-2.208V18.54c0-.995-.001-1.679-.044-2.209-.042-.517-.12-.795-.22-.996a2.436 2.436 0 0 0-1.061-1.069c-.2-.102-.476-.18-.99-.222-.526-.043-1.204-.044-2.192-.044h-8.32c-.988 0-1.666 0-2.192.044Z" clip-rule="evenodd"/><path fill="#B2841C" d="M15 21.066a2 2 0 1 1 2 0v2.1a1 1 0 1 1-2 0v-2.1Z"/></svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="none"><path fill="#CCD1FF" fill-rule="evenodd" d="M23.806 5.583a1.167 1.167 0 0 0-2.28-.499l-1.11 5.083h-6.279l1.003-4.584a1.167 1.167 0 1 0-2.28-.499l-1.111 5.083H7.332a1.167 1.167 0 1 0 0 2.333h3.905l-1.531 7H5.333a1.167 1.167 0 1 0 0 2.333h3.863l-1.002 4.584a1.167 1.167 0 0 0 2.28.499l1.11-5.083h6.279l-1.003 4.584a1.167 1.167 0 1 0 2.28.499l1.111-5.083h4.416a1.167 1.167 0 1 0 0-2.333h-3.905l1.531-7h4.374a1.167 1.167 0 0 0 0-2.333h-3.863l1.002-4.584ZM19.905 12.5h-6.278l-1.532 7h6.278l1.532-7Z" clip-rule="evenodd"/><path fill="#6771CC" fill-rule="evenodd" d="M8.763 29.272a2.667 2.667 0 0 1-2.035-3.175l.605-2.764h-2a2.667 2.667 0 1 1 0-5.333H8.5l.875-4h-2.04a2.667 2.667 0 0 1 0-5.333h3.207l.854-3.904a2.667 2.667 0 1 1 5.21 1.14l-.604 2.764h3.207l.854-3.904a2.667 2.667 0 1 1 5.21 1.14l-.605 2.764h2a2.667 2.667 0 0 1 0 5.333H23.5l-.875 4h2.042a2.667 2.667 0 0 1 0 5.333h-3.208l-.854 3.904a2.667 2.667 0 1 1-5.21-1.14l.604-2.764h-3.207l-.854 3.904a2.667 2.667 0 0 1-3.175 2.035Zm-.57-2.855a1.167 1.167 0 0 0 2.28.499l1.112-5.083h6.278l-1.003 4.584a1.167 1.167 0 1 0 2.28.499l1.111-5.083h4.416a1.167 1.167 0 1 0 0-2.333h-3.905l1.531-7h4.374a1.167 1.167 0 0 0 0-2.333h-3.863l1.002-4.584a1.167 1.167 0 0 0-2.28-.499l-1.11 5.083h-6.279l1.003-4.584a1.167 1.167 0 1 0-2.28-.499l-1.111 5.083H7.332a1.167 1.167 0 1 0 0 2.333h3.905l-1.531 7H5.333a1.167 1.167 0 1 0 0 2.333h3.863l-1.002 4.584ZM14.834 14l-.874 4h3.207l.875-4h-3.207Zm-1.206-1.5-1.532 7h6.278l1.532-7h-6.278Z" clip-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -176,6 +176,7 @@ message AccountRecord {
reserved 31; // hasReadOnboardingStory
reserved 32; // hasSeenGroupStoryEducationSheet
optional string username = 33;
optional bool hasCompletedUsernameOnboarding = 34;
}
message StoryDistributionListRecord {

View file

@ -0,0 +1,107 @@
// Copyright 2023 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
.UsernameOnboardingModalBody {
display: flex;
flex-direction: column;
align-items: center;
user-select: none;
&__large-at {
display: flex;
align-items: center;
justify-content: center;
width: 48px;
height: 48px;
border-radius: 24px;
margin-bottom: 12px;
@include light-theme {
background-color: $color-gray-04;
}
@include dark-theme {
background-color: $color-gray-65;
}
&::after {
display: block;
width: 28px;
height: 28px;
-webkit-mask-size: 100%;
content: '';
@include light-theme {
background-color: $color-gray-75;
}
@include dark-theme {
background-color: $color-gray-15;
}
-webkit-mask: url(../images/icons/v2/at-24.svg) no-repeat center;
}
}
&__title {
@include font-title-2;
margin-bottom: 20px;
max-width: 240px;
text-align: center;
}
&__row {
display: flex;
gap: 16px;
margin-bottom: 24px;
&__icon {
flex-shrink: 0;
width: 32px;
height: 32px;
&--number {
background: url(../images/icons/v2/number_color_32.svg);
}
&--link {
background: url(../images/icons/v2/link_color_32.svg);
}
&--lock {
background: url(../images/icons/v2/lock_color_32.svg);
}
}
&__body {
@include font-body-2;
@include light-theme {
color: $color-gray-60;
}
@include dark-theme {
color: $color-gray-25;
}
max-width: 248px;
}
&--center {
justify-content: center;
}
}
&__learn-more {
text-decoration: none;
font-weight: 600;
}
&__submit {
width: 100%;
max-width: 296px;
margin-bottom: 16px;
}
}

View file

@ -134,4 +134,5 @@
@import './components/TimelineWarnings.scss';
@import './components/TitleBarContainer.scss';
@import './components/Toast.scss';
@import './components/UsernameOnboardingModalBody.scss';
@import './components/WhatsNew.scss';

View file

@ -71,6 +71,7 @@ export default {
},
replaceAvatar: { action: true },
saveAvatarToDisk: { action: true },
markCompletedUsernameOnboarding: { action: true },
openUsernameReservationModal: { action: true },
setUsernameEditState: { action: true },
deleteUsername: { action: true },

View file

@ -34,6 +34,7 @@ import { assertDev } from '../util/assert';
import { missingCaseError } from '../util/missingCaseError';
import { ConfirmationDialog } from './ConfirmationDialog';
import { ContextMenu } from './ContextMenu';
import { UsernameOnboardingModalBody } from './UsernameOnboardingModalBody';
import {
ConversationDetailsIcon,
IconType,
@ -48,6 +49,7 @@ export enum EditState {
ProfileName = 'ProfileName',
Bio = 'Bio',
Username = 'Username',
UsernameOnboarding = 'UsernameOnboarding',
}
type PropsExternalType = {
@ -67,11 +69,13 @@ export type PropsDataType = {
conversationId: string;
familyName?: string;
firstName: string;
hasCompletedUsernameOnboarding: boolean;
i18n: LocalizerType;
isUsernameFlagEnabled: boolean;
userAvatarData: ReadonlyArray<AvatarDataType>;
username?: string;
usernameEditState: UsernameEditState;
markCompletedUsernameOnboarding: () => void;
} & Pick<EmojiButtonProps, 'recentEmojis' | 'skinTone'>;
type PropsActionType = {
@ -124,8 +128,10 @@ export function ProfileEditor({
deleteUsername,
familyName,
firstName,
hasCompletedUsernameOnboarding,
i18n,
isUsernameFlagEnabled,
markCompletedUsernameOnboarding,
onEditStateChanged,
onProfileChanged,
onSetSkinTone,
@ -481,6 +487,16 @@ export function ProfileEditor({
content = renderEditUsernameModalBody({
onClose: () => setEditState(EditState.None),
});
} else if (editState === EditState.UsernameOnboarding) {
content = (
<UsernameOnboardingModalBody
i18n={i18n}
onNext={() => {
markCompletedUsernameOnboarding();
setEditState(EditState.Username);
}}
/>
);
} else if (editState === EditState.None) {
let maybeUsernameRow: JSX.Element | undefined;
if (isUsernameFlagEnabled) {
@ -560,7 +576,11 @@ export function ProfileEditor({
info={username && generateUsernameLink(username, { short: true })}
onClick={() => {
openUsernameReservationModal();
if (username || hasCompletedUsernameOnboarding) {
setEditState(EditState.Username);
} else {
setEditState(EditState.UsernameOnboarding);
}
}}
actions={actions}
/>

View file

@ -32,11 +32,12 @@ export function ProfileEditorModal({
toggleProfileEditorHasError,
...restProps
}: PropsType): JSX.Element {
const MODAL_TITLES_BY_EDIT_STATE: Record<EditState, string> = {
const MODAL_TITLES_BY_EDIT_STATE: Record<EditState, string | undefined> = {
[EditState.BetterAvatar]: i18n('ProfileEditorModal--avatar'),
[EditState.Bio]: i18n('ProfileEditorModal--about'),
[EditState.None]: i18n('ProfileEditorModal--profile'),
[EditState.ProfileName]: i18n('ProfileEditorModal--name'),
[EditState.UsernameOnboarding]: undefined,
[EditState.Username]: i18n('ProfileEditorModal--username'),
};

View file

@ -0,0 +1,37 @@
// Copyright 2023 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
import type { Meta, Story } from '@storybook/react';
import enMessages from '../../_locales/en/messages.json';
import { setupI18n } from '../util/setupI18n';
import type { PropsType } from './UsernameOnboardingModalBody';
import { UsernameOnboardingModalBody } from './UsernameOnboardingModalBody';
const i18n = setupI18n('en', enMessages);
export default {
component: UsernameOnboardingModalBody,
title: 'Components/UsernameOnboardingModalBody',
argTypes: {
i18n: {
defaultValue: i18n,
},
onNext: { action: true },
},
} as Meta;
type ArgsType = PropsType;
// eslint-disable-next-line react/function-component-definition
const Template: Story<ArgsType> = args => {
return <UsernameOnboardingModalBody {...args} />;
};
export const Normal = Template.bind({});
Normal.args = {};
Normal.story = {
name: 'normal',
};

View file

@ -0,0 +1,68 @@
// Copyright 2023 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
import type { LocalizerType } from '../types/Util';
import { Button } from './Button';
export type PropsType = Readonly<{
i18n: LocalizerType;
onNext: () => void;
}>;
const CLASS = 'UsernameOnboardingModalBody';
const SUPPORT_URL = 'https://support.signal.org/hc/articles/5389476324250';
export function UsernameOnboardingModalBody({
i18n,
onNext,
}: PropsType): JSX.Element {
return (
<div className={CLASS}>
<div className={`${CLASS}__large-at`} />
<div className={`${CLASS}__title`}>{i18n(`icu:${CLASS}__title`)}</div>
<div className={`${CLASS}__row`}>
<div className={`${CLASS}__row__icon ${CLASS}__row__icon--number`} />
<div className={`${CLASS}__row__body`}>
{i18n(`icu:${CLASS}__row__number`)}
</div>
</div>
<div className={`${CLASS}__row`}>
<div className={`${CLASS}__row__icon ${CLASS}__row__icon--link`} />
<div className={`${CLASS}__row__body`}>
{i18n(`icu:${CLASS}__row__link`)}
</div>
</div>
<div className={`${CLASS}__row`}>
<div className={`${CLASS}__row__icon ${CLASS}__row__icon--lock`} />
<div className={`${CLASS}__row__body`}>
{i18n(`icu:${CLASS}__row__lock`)}
</div>
</div>
<div className={`${CLASS}__row ${CLASS}__row--center`}>
<a
className={`${CLASS}__learn-more`}
href={SUPPORT_URL}
rel="noreferrer"
target="_blank"
>
{i18n(`icu:${CLASS}__learn-more`)}
</a>
</div>
<Button className={`${CLASS}__submit`} onClick={onNext}>
{i18n(`icu:${CLASS}__continue`)}
</Button>
</div>
);
}

View file

@ -395,6 +395,14 @@ export function toAccountRecord(
accountRecord.hasViewedOnboardingStory = hasViewedOnboardingStory;
}
const hasCompletedUsernameOnboarding = window.storage.get(
'hasCompletedUsernameOnboarding'
);
if (hasCompletedUsernameOnboarding !== undefined) {
accountRecord.hasCompletedUsernameOnboarding =
hasCompletedUsernameOnboarding;
}
const hasStoriesDisabled = window.storage.get('hasStoriesDisabled');
accountRecord.storiesDisabled = hasStoriesDisabled === true;
@ -1137,6 +1145,7 @@ export async function mergeAccountRecord(
subscriberCurrencyCode,
displayBadgesOnProfile,
keepMutedChatsArchived,
hasCompletedUsernameOnboarding,
hasSetMyStoriesPrivacy,
hasViewedOnboardingStory,
storiesDisabled,
@ -1368,6 +1377,15 @@ export async function mergeAccountRecord(
void findAndDeleteOnboardingStoryIfExists();
}
}
{
const hasCompletedUsernameOnboardingBool = Boolean(
hasCompletedUsernameOnboarding
);
await window.storage.put(
'hasCompletedUsernameOnboarding',
hasCompletedUsernameOnboardingBool
);
}
{
const hasStoriesDisabled = Boolean(storiesDisabled);
await window.storage.put('hasStoriesDisabled', hasStoriesDisabled);

View file

@ -74,6 +74,12 @@ export const getUsernamesEnabled = createSelector(
isRemoteConfigFlagEnabled(remoteConfig, 'desktop.usernames')
);
export const getHasCompletedUsernameOnboarding = createSelector(
getItems,
(state: ItemsStateType): boolean =>
Boolean(state.hasCompletedUsernameOnboarding)
);
export const isInternalUser = createSelector(
getRemoteConfig,
(remoteConfig: ConfigMapType): boolean => {

View file

@ -8,10 +8,15 @@ import { mapDispatchToProps } from '../actions';
import type { PropsDataType as ProfileEditorModalPropsType } from '../../components/ProfileEditorModal';
import { ProfileEditorModal } from '../../components/ProfileEditorModal';
import type { PropsDataType } from '../../components/ProfileEditor';
import { storageServiceUploadJob } from '../../services/storage';
import { SmartEditUsernameModalBody } from './EditUsernameModalBody';
import type { StateType } from '../reducer';
import { getIntl } from '../selectors/user';
import { getEmojiSkinTone, getUsernamesEnabled } from '../selectors/items';
import {
getEmojiSkinTone,
getUsernamesEnabled,
getHasCompletedUsernameOnboarding,
} from '../selectors/items';
import { getMe } from '../selectors/conversations';
import { selectRecentEmojis } from '../selectors/emojis';
import { getUsernameEditState } from '../selectors/username';
@ -22,6 +27,12 @@ function renderEditUsernameModalBody(props: {
return <SmartEditUsernameModalBody {...props} />;
}
async function markCompletedUsernameOnboarding(): Promise<void> {
await window.storage.put('hasCompletedUsernameOnboarding', true);
storageServiceUploadJob();
}
function mapStateToProps(
state: StateType
): Omit<PropsDataType, 'onEditStateChange' | 'onProfileChanged'> &
@ -40,6 +51,8 @@ function mapStateToProps(
const recentEmojis = selectRecentEmojis(state);
const skinTone = getEmojiSkinTone(state);
const isUsernameFlagEnabled = getUsernamesEnabled(state);
const hasCompletedUsernameOnboarding =
getHasCompletedUsernameOnboarding(state);
const usernameEditState = getUsernameEditState(state);
return {
@ -50,9 +63,11 @@ function mapStateToProps(
conversationId,
familyName,
firstName: String(firstName),
hasCompletedUsernameOnboarding,
hasError: state.globalModals.profileEditorHasError,
i18n: getIntl(state),
isUsernameFlagEnabled,
markCompletedUsernameOnboarding,
recentEmojis,
skinTone,
userAvatarData,

View file

@ -154,6 +154,9 @@ describe('pnp/username', function needsName() {
const profileEditor = window.locator('.ProfileEditor');
await profileEditor.locator('.ProfileEditor__row >> "Username"').click();
debug('skipping onboarding');
await profileEditor.locator('.module-Button >> "Continue"').click();
debug('entering new username');
const usernameField = profileEditor.locator('.Input__input');
await usernameField.type(NICKNAME);

View file

@ -71,6 +71,7 @@ export type StorageAccessType = {
existingOnboardingStoryMessageIds: ReadonlyArray<string> | undefined;
hasRegisterSupportForUnauthenticatedDelivery: boolean;
hasSetMyStoriesPrivacy: boolean;
hasCompletedUsernameOnboarding: boolean;
hasViewedOnboardingStory: boolean;
hasStoriesDisabled: boolean;
storyViewReceiptsEnabled: boolean;