[Email Aliases] Limit Reached dialog (#35208)
* Updated dialogs width (as defined in Figma). * Added strings for Limit Reached dialog. * Added Limit Reached content. * Limit Reached dialog integrated. * Updated storybook.
This commit is contained in:
@@ -25,7 +25,7 @@ namespace {
|
||||
inline constexpr char kEmailAliasesPanelURL[] = "chrome://email-aliases.panel/";
|
||||
|
||||
constexpr char kEmailAliasesSettingsURL[] = "brave://settings/email-aliases";
|
||||
constexpr int kDialogWidth = 420;
|
||||
constexpr int kDialogWidth = 512;
|
||||
constexpr gfx::Size kDialogMinSize(kDialogWidth, 336);
|
||||
constexpr gfx::Size kDialogMaxSize(kDialogWidth, 794);
|
||||
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
// Copyright (c) 2026 The Brave Authors. All rights reserved.
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
import { color, font, radius, spacing } from '@brave/leo/tokens/css/variables'
|
||||
import * as React from 'react'
|
||||
import { formatLocale, getLocale } from '$web-common/locale'
|
||||
import Alert from '@brave/leo/react/alert'
|
||||
import Col from './styles/Col'
|
||||
import styled from 'styled-components'
|
||||
import { Alias } from 'gen/brave/components/email_aliases/email_aliases.mojom.m'
|
||||
import './strings'
|
||||
|
||||
const SectionCol = styled(Col)`
|
||||
row-gap: ${spacing['2Xl']};
|
||||
`
|
||||
|
||||
const LimitAlertTitle = styled.div`
|
||||
font: ${font.heading.h4};
|
||||
`
|
||||
|
||||
const LimitDescription = styled.div`
|
||||
font: ${font.default.regular};
|
||||
`
|
||||
|
||||
const ListLabel = styled.div`
|
||||
font: ${font.small.semibold};
|
||||
margin: 0;
|
||||
padding: 0 ${spacing.s};
|
||||
`
|
||||
|
||||
const AliasListBox = styled.div`
|
||||
border: 1px solid ${color.divider.subtle};
|
||||
border-radius: ${radius.xl};
|
||||
overflow: hidden auto;
|
||||
max-height: 208px;
|
||||
`
|
||||
|
||||
const AliasRow = styled.div<{ showDivider: boolean }>`
|
||||
font: ${font.default.semibold};
|
||||
padding: ${spacing.m} ${spacing.l};
|
||||
gap: 8px;
|
||||
border-bottom: ${(p) =>
|
||||
p.showDivider
|
||||
? `1px solid ${color.divider.subtle}`
|
||||
: '1px solid transparent'};
|
||||
`
|
||||
|
||||
export const EmailAliasLimitReached = ({
|
||||
aliases,
|
||||
aliasLimit,
|
||||
}: {
|
||||
aliases: Alias[]
|
||||
aliasLimit: number
|
||||
}) => {
|
||||
const count = aliases.length
|
||||
return (
|
||||
<SectionCol>
|
||||
<Alert type='warning'>
|
||||
<LimitAlertTitle>
|
||||
{getLocale(S.SETTINGS_EMAIL_ALIASES_LIMIT_REACHED_ALERT_TITLE)}
|
||||
</LimitAlertTitle>
|
||||
<LimitDescription>
|
||||
{formatLocale(S.SETTINGS_EMAIL_ALIASES_LIMIT_REACHED_ALERT_BODY, {
|
||||
$1: aliasLimit,
|
||||
})}
|
||||
</LimitDescription>
|
||||
</Alert>
|
||||
<div>
|
||||
<ListLabel>
|
||||
{formatLocale(S.SETTINGS_EMAIL_ALIASES_YOUR_ALIASES_COUNT_LABEL, {
|
||||
$1: count,
|
||||
$2: aliasLimit,
|
||||
})}
|
||||
</ListLabel>
|
||||
<AliasListBox>
|
||||
{aliases.map((alias, index) => (
|
||||
<AliasRow
|
||||
key={alias.email}
|
||||
showDivider={index < aliases.length - 1}
|
||||
>
|
||||
{alias.email}
|
||||
</AliasRow>
|
||||
))}
|
||||
</AliasListBox>
|
||||
</div>
|
||||
</SectionCol>
|
||||
)
|
||||
}
|
||||
@@ -119,7 +119,7 @@ export const AliasList = ({
|
||||
editing={editState.mode === 'Edit'}
|
||||
editAlias={editState.alias}
|
||||
mainEmail={authEmail}
|
||||
aliasCount={aliases.length}
|
||||
aliases={aliases}
|
||||
emailAliasesService={emailAliasesService}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -26,6 +26,7 @@ import {
|
||||
EmailAliasesServiceInterface,
|
||||
MAX_ALIASES,
|
||||
} from 'gen/brave/components/email_aliases/email_aliases.mojom.m'
|
||||
import { EmailAliasLimitReached } from './email_alias_limit_reached'
|
||||
import './strings'
|
||||
|
||||
const ModalCol = styled(Col)`
|
||||
@@ -103,12 +104,9 @@ const NoteInput = styled(Input)`
|
||||
margin 0;
|
||||
`
|
||||
|
||||
const WarningText = styled.div`
|
||||
font: ${font.default.semibold};
|
||||
`
|
||||
|
||||
const ButtonRow = styled(Row)<{ bubble?: boolean }>`
|
||||
justify-content: ${(props) => (props.bubble ? 'space-between' : 'end')};
|
||||
const ButtonRow = styled(Row)<{ bubble?: boolean; limitReached?: boolean }>`
|
||||
justify-content: ${(props) =>
|
||||
!props.bubble || props.limitReached ? 'end' : 'space-between'};
|
||||
& leo-button {
|
||||
flex-grow: 0;
|
||||
}
|
||||
@@ -119,6 +117,20 @@ const ButtonRow = styled(Row)<{ bubble?: boolean }>`
|
||||
}
|
||||
`
|
||||
|
||||
const ManageButton = styled(Button)<{ limitReached?: boolean }>`
|
||||
${(props) =>
|
||||
props.limitReached
|
||||
&& `
|
||||
order: 1; // Move Manage button to the right.
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
!props.limitReached
|
||||
&& `
|
||||
margin-right: auto; // Move Manage button to the left.
|
||||
`}
|
||||
`
|
||||
|
||||
const LoadingIcon = styled(ProgressRing)`
|
||||
--leo-progressring-color: ${color.icon.default};
|
||||
--leo-progressring-size: 24px;
|
||||
@@ -188,21 +200,19 @@ export const DeleteAliasModal = ({
|
||||
{getLocale(S.SETTINGS_EMAIL_ALIASES_DELETE_WARNING)}
|
||||
</Alert>
|
||||
<ButtonRow>
|
||||
<span>
|
||||
<Button
|
||||
onClick={onReturnToMain}
|
||||
kind='plain-faint'
|
||||
>
|
||||
{getLocale(S.SETTINGS_EMAIL_ALIASES_CANCEL_BUTTON)}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={onDeleteAlias}
|
||||
kind='filled'
|
||||
isDisabled={deleting}
|
||||
>
|
||||
{getLocale(S.SETTINGS_EMAIL_ALIASES_DELETE_ALIAS_BUTTON)}
|
||||
</Button>
|
||||
</span>
|
||||
<Button
|
||||
onClick={onReturnToMain}
|
||||
kind='plain-faint'
|
||||
>
|
||||
{getLocale(S.SETTINGS_EMAIL_ALIASES_CANCEL_BUTTON)}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={onDeleteAlias}
|
||||
kind='filled'
|
||||
isDisabled={deleting}
|
||||
>
|
||||
{getLocale(S.SETTINGS_EMAIL_ALIASES_DELETE_ALIAS_BUTTON)}
|
||||
</Button>
|
||||
</ButtonRow>
|
||||
{deleteErrorMessage && <Alert>{deleteErrorMessage}</Alert>}
|
||||
</ModalCol>
|
||||
@@ -225,7 +235,8 @@ export const EmailAliasModal = ({
|
||||
editing,
|
||||
editAlias,
|
||||
mainEmail,
|
||||
aliasCount,
|
||||
aliases,
|
||||
aliasLimit = MAX_ALIASES,
|
||||
emailAliasesService,
|
||||
bubble,
|
||||
}: {
|
||||
@@ -234,7 +245,8 @@ export const EmailAliasModal = ({
|
||||
editAlias?: Alias
|
||||
bubble?: boolean
|
||||
mainEmail: string
|
||||
aliasCount: number
|
||||
aliases?: Alias[]
|
||||
aliasLimit?: number
|
||||
emailAliasesService: EmailAliasesServiceInterface
|
||||
}) => {
|
||||
const [limitReached, setLimitReached] = React.useState<boolean>(false)
|
||||
@@ -295,13 +307,15 @@ export const EmailAliasModal = ({
|
||||
setAwaitingProposedAlias(false)
|
||||
}
|
||||
React.useEffect(() => {
|
||||
if (bubble) {
|
||||
setLimitReached(aliasCount >= MAX_ALIASES)
|
||||
setLimitReached((aliases?.length ?? 0) >= aliasLimit)
|
||||
}, [aliases, aliasLimit])
|
||||
|
||||
React.useEffect(() => {
|
||||
if (editing || (aliases?.length ?? 0) >= aliasLimit) {
|
||||
return
|
||||
}
|
||||
if (!editing) {
|
||||
regenerateAlias()
|
||||
}
|
||||
}, [editing])
|
||||
regenerateAlias()
|
||||
}, [editing, aliases, aliasLimit])
|
||||
return (
|
||||
<ModalCol>
|
||||
<ModalTitle>
|
||||
@@ -314,10 +328,11 @@ export const EmailAliasModal = ({
|
||||
{getLocale(S.SETTINGS_EMAIL_ALIASES_BUBBLE_DESCRIPTION)}
|
||||
</ModalDescription>
|
||||
)}
|
||||
{bubble && limitReached ? (
|
||||
<WarningText>
|
||||
{getLocale(S.SETTINGS_EMAIL_ALIASES_BUBBLE_LIMIT_REACHED)}
|
||||
</WarningText>
|
||||
{limitReached ? (
|
||||
<EmailAliasLimitReached
|
||||
aliases={aliases!}
|
||||
aliasLimit={aliasLimit}
|
||||
/>
|
||||
) : (
|
||||
<ModalCol>
|
||||
<ModalSectionCol>
|
||||
@@ -372,39 +387,41 @@ export const EmailAliasModal = ({
|
||||
</ModalSectionCol>
|
||||
</ModalCol>
|
||||
)}
|
||||
<ButtonRow bubble={bubble}>
|
||||
<span>
|
||||
{bubble && (
|
||||
<Button
|
||||
id='manage-button'
|
||||
onClick={() => {
|
||||
onReturnToMain({
|
||||
type: EmailAliasModalResultType.ShouldManageAliases,
|
||||
})
|
||||
}}
|
||||
kind='plain'
|
||||
>
|
||||
{getLocale(S.SETTINGS_EMAIL_ALIASES_MANAGE_BUTTON)}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
id='cancel-button'
|
||||
onClick={() =>
|
||||
onReturnToMain({ type: EmailAliasModalResultType.Cancelled })
|
||||
}
|
||||
kind='plain-faint'
|
||||
<ButtonRow
|
||||
bubble={bubble}
|
||||
limitReached={limitReached}
|
||||
>
|
||||
{bubble && (
|
||||
<ManageButton
|
||||
limitReached={limitReached}
|
||||
id='manage-button'
|
||||
onClick={() => {
|
||||
onReturnToMain({
|
||||
type: EmailAliasModalResultType.ShouldManageAliases,
|
||||
})
|
||||
}}
|
||||
kind={limitReached ? 'filled' : 'plain'}
|
||||
>
|
||||
{getLocale(S.SETTINGS_EMAIL_ALIASES_CANCEL_BUTTON)}
|
||||
</Button>
|
||||
{getLocale(S.SETTINGS_EMAIL_ALIASES_MANAGE_BUTTON)}
|
||||
</ManageButton>
|
||||
)}
|
||||
<Button
|
||||
id='cancel-button'
|
||||
onClick={() =>
|
||||
onReturnToMain({ type: EmailAliasModalResultType.Cancelled })
|
||||
}
|
||||
kind='plain-faint'
|
||||
>
|
||||
{getLocale(S.SETTINGS_EMAIL_ALIASES_CANCEL_BUTTON)}
|
||||
</Button>
|
||||
{!limitReached && (
|
||||
<Button
|
||||
id='create-alias-button'
|
||||
kind='filled'
|
||||
isDisabled={
|
||||
awaitingUpdate
|
||||
|| (!editing
|
||||
&& (limitReached
|
||||
|| awaitingProposedAlias
|
||||
|| !generateAliasResult?.aliasEmail))
|
||||
&& (awaitingProposedAlias || !generateAliasResult?.aliasEmail))
|
||||
}
|
||||
onClick={createOrSave}
|
||||
>
|
||||
@@ -412,7 +429,7 @@ export const EmailAliasModal = ({
|
||||
? getLocale(S.SETTINGS_EMAIL_ALIASES_CREATE_ALIAS_BUTTON)
|
||||
: getLocale(S.SETTINGS_EMAIL_ALIASES_SAVE_ALIAS_BUTTON)}
|
||||
</Button>
|
||||
</span>
|
||||
)}
|
||||
</ButtonRow>
|
||||
{updateErrorMessage && <Alert>{updateErrorMessage}</Alert>}
|
||||
</ModalCol>
|
||||
|
||||
@@ -16,8 +16,7 @@
|
||||
}
|
||||
:host, body, #mountPoint {
|
||||
display: block;
|
||||
width: 420px;
|
||||
max-width: 420px;
|
||||
width: 100vw;
|
||||
height: auto;
|
||||
}
|
||||
#mountPoint {
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
EmailAliasesService,
|
||||
EmailAliasesPanelHandlerInterface,
|
||||
EmailAliasesPanelHandler,
|
||||
MAX_ALIASES,
|
||||
} from 'gen/brave/components/email_aliases/email_aliases.mojom.m'
|
||||
|
||||
export const EmailAliasesPanelConnected = ({
|
||||
@@ -59,6 +60,8 @@ export const EmailAliasesPanelConnected = ({
|
||||
}, [])
|
||||
return (
|
||||
<EmailAliasModal
|
||||
aliases={aliasesState}
|
||||
aliasLimit={MAX_ALIASES}
|
||||
onReturnToMain={(action: EmailAliasModalResult) => {
|
||||
switch (action.type) {
|
||||
case EmailAliasModalResultType.Cancelled:
|
||||
@@ -74,7 +77,6 @@ export const EmailAliasesPanelConnected = ({
|
||||
}}
|
||||
editing={false}
|
||||
mainEmail={authState.email}
|
||||
aliasCount={aliasesState.length}
|
||||
emailAliasesService={emailAliasesService}
|
||||
bubble
|
||||
/>
|
||||
|
||||
@@ -9,7 +9,11 @@ import {
|
||||
EmailAliasModal,
|
||||
} from '../content/email_aliases_modal'
|
||||
import { StubEmailAliasesService, demoData } from './utils/stubs'
|
||||
import { AuthenticationStatus } from 'gen/brave/components/email_aliases/email_aliases.mojom.m'
|
||||
import {
|
||||
Alias,
|
||||
AuthenticationStatus,
|
||||
MAX_ALIASES,
|
||||
} from 'gen/brave/components/email_aliases/email_aliases.mojom.m'
|
||||
|
||||
const stubEmailAliasesServiceAccountReadyInstance = new StubEmailAliasesService(
|
||||
{
|
||||
@@ -21,7 +25,8 @@ const stubEmailAliasesServiceAccountReadyInstance = new StubEmailAliasesService(
|
||||
export const NewAliasDialog = () => {
|
||||
return (
|
||||
<EmailAliasModal
|
||||
aliasCount={demoData.aliases.length}
|
||||
aliases={demoData.aliases}
|
||||
aliasLimit={MAX_ALIASES}
|
||||
onReturnToMain={() => {}}
|
||||
editing={false}
|
||||
mainEmail={demoData.email}
|
||||
@@ -35,7 +40,8 @@ export const EditAliasDialog = () => {
|
||||
return (
|
||||
<EmailAliasModal
|
||||
editAlias={demoData.aliases[0]}
|
||||
aliasCount={demoData.aliases.length}
|
||||
aliases={demoData.aliases}
|
||||
aliasLimit={MAX_ALIASES}
|
||||
onReturnToMain={() => {}}
|
||||
editing
|
||||
mainEmail={demoData.email}
|
||||
@@ -59,7 +65,32 @@ export const DeleteAliasDialog = () => {
|
||||
export const Panel = () => {
|
||||
return (
|
||||
<EmailAliasModal
|
||||
aliasCount={demoData.aliases.length}
|
||||
aliases={demoData.aliases}
|
||||
aliasLimit={MAX_ALIASES}
|
||||
onReturnToMain={() => {}}
|
||||
editing={false}
|
||||
mainEmail={demoData.email}
|
||||
bubble={true}
|
||||
// @ts-expect-error https://github.com/brave/brave-browser/issues/48960
|
||||
emailAliasesService={stubEmailAliasesServiceAccountReadyInstance}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const atLimitAliases: Alias[] = Array.from(
|
||||
{ length: MAX_ALIASES + Math.round(Math.random() * MAX_ALIASES) },
|
||||
(_, i) => ({
|
||||
email: `isolating-cubicle${i}@bravealias.com`,
|
||||
note: undefined,
|
||||
domains: undefined,
|
||||
}),
|
||||
)
|
||||
|
||||
export const LimitReachedBubble = () => {
|
||||
return (
|
||||
<EmailAliasModal
|
||||
aliases={atLimitAliases}
|
||||
aliasLimit={MAX_ALIASES}
|
||||
onReturnToMain={() => {}}
|
||||
editing={false}
|
||||
mainEmail={demoData.email}
|
||||
@@ -75,7 +106,7 @@ export default {
|
||||
decorators: [
|
||||
(Story: any) => {
|
||||
return (
|
||||
<div style={{ width: '420px', margin: '0 auto' }}>
|
||||
<div style={{ width: '464px', margin: '0 auto' }}>
|
||||
<Story />
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -59,7 +59,6 @@ describe('EmailAliasModal', () => {
|
||||
<EmailAliasModal
|
||||
editing={false}
|
||||
mainEmail={mockEmail}
|
||||
aliasCount={0}
|
||||
onReturnToMain={mockOnReturnToMain}
|
||||
emailAliasesService={mockEmailAliasesService}
|
||||
/>,
|
||||
@@ -88,7 +87,6 @@ describe('EmailAliasModal', () => {
|
||||
editing={true}
|
||||
editAlias={mockEditAlias}
|
||||
mainEmail={mockEmail}
|
||||
aliasCount={0}
|
||||
onReturnToMain={mockOnReturnToMain}
|
||||
emailAliasesService={mockEmailAliasesService}
|
||||
/>,
|
||||
@@ -158,7 +156,6 @@ describe('EmailAliasModal', () => {
|
||||
<EmailAliasModal
|
||||
editing={false}
|
||||
mainEmail={mockEmail}
|
||||
aliasCount={0}
|
||||
onReturnToMain={mockOnReturnToMain}
|
||||
emailAliasesService={mockEmailAliasesService}
|
||||
/>,
|
||||
@@ -202,7 +199,6 @@ describe('EmailAliasModal', () => {
|
||||
<EmailAliasModal
|
||||
editing={false}
|
||||
mainEmail={mockEmail}
|
||||
aliasCount={0}
|
||||
onReturnToMain={mockOnReturnToMain}
|
||||
emailAliasesService={mockEmailAliasesService}
|
||||
/>,
|
||||
@@ -228,24 +224,38 @@ describe('EmailAliasModal', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('shows limit reached message in bubble mode', async () => {
|
||||
it('shows limit reached dialog in bubble mode without generating an alias', async () => {
|
||||
const atLimitAliases: Alias[] = Array.from({ length: 5 }, (_, i) => ({
|
||||
email: `alias-${i}@bravealias.com`,
|
||||
note: undefined,
|
||||
domains: undefined,
|
||||
}))
|
||||
|
||||
render(
|
||||
<EmailAliasModal
|
||||
editing={false}
|
||||
mainEmail={mockEmail}
|
||||
aliasCount={5}
|
||||
aliases={atLimitAliases}
|
||||
onReturnToMain={mockOnReturnToMain}
|
||||
emailAliasesService={mockEmailAliasesService}
|
||||
bubble={true}
|
||||
/>,
|
||||
)
|
||||
|
||||
// Wait for limit check
|
||||
await waitFor(() => {
|
||||
expect(
|
||||
screen.getByText(S.SETTINGS_EMAIL_ALIASES_BUBBLE_LIMIT_REACHED),
|
||||
screen.getByText(S.SETTINGS_EMAIL_ALIASES_LIMIT_REACHED_ALERT_TITLE),
|
||||
).toBeInTheDocument()
|
||||
})
|
||||
|
||||
expect(mockEmailAliasesService.generateAlias).not.toHaveBeenCalled()
|
||||
expect(screen.getByText('alias-0@bravealias.com')).toBeInTheDocument()
|
||||
expect(
|
||||
screen.queryByText(S.SETTINGS_EMAIL_ALIASES_CREATE_ALIAS_BUTTON),
|
||||
).not.toBeInTheDocument()
|
||||
expect(
|
||||
screen.getByText(S.SETTINGS_EMAIL_ALIASES_MANAGE_BUTTON),
|
||||
).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('shows loading state while generating alias', async () => {
|
||||
@@ -258,7 +268,6 @@ describe('EmailAliasModal', () => {
|
||||
<EmailAliasModal
|
||||
editing={false}
|
||||
mainEmail={mockEmail}
|
||||
aliasCount={0}
|
||||
onReturnToMain={mockOnReturnToMain}
|
||||
emailAliasesService={mockEmailAliasesService}
|
||||
/>,
|
||||
@@ -299,7 +308,6 @@ describe('EmailAliasModal', () => {
|
||||
<EmailAliasModal
|
||||
editing={false}
|
||||
mainEmail={mockEmail}
|
||||
aliasCount={0}
|
||||
onReturnToMain={mockOnReturnToMain}
|
||||
emailAliasesService={mockEmailAliasesService}
|
||||
/>,
|
||||
@@ -337,7 +345,6 @@ describe('EmailAliasModal', () => {
|
||||
editing={true}
|
||||
editAlias={mockEditAlias}
|
||||
mainEmail={mockEmail}
|
||||
aliasCount={0}
|
||||
onReturnToMain={mockOnReturnToMain}
|
||||
emailAliasesService={mockEmailAliasesService}
|
||||
/>,
|
||||
@@ -400,7 +407,6 @@ describe('EmailAliasModal', () => {
|
||||
editing={isEditing}
|
||||
editAlias={alias}
|
||||
mainEmail={mockEmail}
|
||||
aliasCount={0}
|
||||
onReturnToMain={mockOnReturnToMain}
|
||||
emailAliasesService={mockEmailAliasesService}
|
||||
/>,
|
||||
@@ -463,7 +469,6 @@ describe('EmailAliasModal', () => {
|
||||
<EmailAliasModal
|
||||
editing={false}
|
||||
mainEmail={mockEmail}
|
||||
aliasCount={0}
|
||||
onReturnToMain={mockOnReturnToMain}
|
||||
emailAliasesService={mockEmailAliasesService}
|
||||
bubble={true}
|
||||
|
||||
@@ -39,8 +39,14 @@
|
||||
<message name="IDS_SETTINGS_EMAIL_ALIASES_BUBBLE_DESCRIPTION" desc="The description for the email alias bubble" formatter_data="webui=EmailAliases">
|
||||
Create a random email address that forwards to your inbox while keeping your personal email private.
|
||||
</message>
|
||||
<message name="IDS_SETTINGS_EMAIL_ALIASES_BUBBLE_LIMIT_REACHED" desc="The description for the email alias bubble when the limit is reached" formatter_data="webui=EmailAliases">
|
||||
You have reached the limit of 5 free email aliases. Click "Manage" to re-use or delete an alias.
|
||||
<message name="IDS_SETTINGS_EMAIL_ALIASES_LIMIT_REACHED_ALERT_TITLE" desc="Title for the email alias limit reached banner in the new-alias dialog" formatter_data="webui=EmailAliases">
|
||||
Alias limit reached
|
||||
</message>
|
||||
<message name="IDS_SETTINGS_EMAIL_ALIASES_LIMIT_REACHED_ALERT_BODY" desc="Body for the email alias limit reached banner; placeholder is the max aliases allowed for the user's plan" formatter_data="webui=EmailAliases">
|
||||
You've used all <ph name="MAX_ALIASES">$1<ex>5</ex></ph> of your email aliases. Delete an existing alias to create a new one.
|
||||
</message>
|
||||
<message name="IDS_SETTINGS_EMAIL_ALIASES_YOUR_ALIASES_COUNT_LABEL" desc="Label above the alias list when showing usage versus plan limit" formatter_data="webui=EmailAliases">
|
||||
Your aliases (<ph name="CURRENT">$1<ex>5</ex></ph> / <ph name="MAX">$2<ex>5</ex></ph>)
|
||||
</message>
|
||||
<message name="IDS_SETTINGS_EMAIL_ALIASES_CREATE_ALIAS_LABEL" desc="The label for the create alias" formatter_data="webui=EmailAliases">
|
||||
New alias
|
||||
|
||||
Reference in New Issue
Block a user