mirror of
https://github.com/lux-tel/session-desktop.git
synced 2026-10-30 20:33:24 +00:00
203 lines
6.5 KiB
TypeScript
203 lines
6.5 KiB
TypeScript
import { ReactNode, useMemo } from 'react';
|
|
import { useCurrentUserHasExpiredPro } from '../../hooks/useHasPro';
|
|
import { Localizer } from '../basic/Localizer';
|
|
import { CTADescriptionListItem, StyledCTADescriptionList } from './CTADescriptionList';
|
|
import { StyledScrollDescriptionContainer } from './SessionCTA';
|
|
import { tr } from '../../localization/localeTools';
|
|
import { CONVERSATION } from '../../session/constants';
|
|
import { formatNumber } from '../../util/i18n/formatting/generics';
|
|
import { assertUnreachable } from '../../types/sqlSharedTypes';
|
|
import { ProIconButton } from '../buttons/ProButton';
|
|
import { CTAVariant, type ProCTAVariant } from './cta/types';
|
|
import { useProBackendProDetails } from '../../state/selectors/proBackendData';
|
|
|
|
const variantsWithoutFeatureList = [
|
|
CTAVariant.PRO_GROUP_NON_ADMIN,
|
|
CTAVariant.PRO_GROUP_ACTIVATED,
|
|
CTAVariant.PRO_ANIMATED_DISPLAY_PICTURE_ACTIVATED,
|
|
] as const;
|
|
|
|
type VariantWithoutFeatureList = (typeof variantsWithoutFeatureList)[number];
|
|
type VariantWithFeatureList = Exclude<ProCTAVariant, VariantWithoutFeatureList>;
|
|
|
|
function isProFeatureListCTA(variant: CTAVariant): variant is VariantWithFeatureList {
|
|
return !variantsWithoutFeatureList.includes(variant as any);
|
|
}
|
|
|
|
enum ProFeatureKey {
|
|
LONGER_MESSAGES = 'proFeatureListLongerMessages',
|
|
MORE_PINNED_CONVOS = 'proFeatureListPinnedConversations',
|
|
ANIMATED_DP = 'proFeatureListAnimatedDisplayPicture',
|
|
LARGER_GROUPS = 'proFeatureListLargerGroups',
|
|
}
|
|
|
|
function getBaseFeatureList(variant: VariantWithFeatureList) {
|
|
switch (variant) {
|
|
case CTAVariant.PRO_MESSAGE_CHARACTER_LIMIT:
|
|
return [ProFeatureKey.LONGER_MESSAGES, ProFeatureKey.MORE_PINNED_CONVOS];
|
|
|
|
case CTAVariant.PRO_ANIMATED_DISPLAY_PICTURE:
|
|
return [ProFeatureKey.ANIMATED_DP, ProFeatureKey.LONGER_MESSAGES];
|
|
|
|
case CTAVariant.PRO_PINNED_CONVERSATION_LIMIT:
|
|
case CTAVariant.PRO_PINNED_CONVERSATION_LIMIT_GRANDFATHERED:
|
|
return [ProFeatureKey.MORE_PINNED_CONVOS, ProFeatureKey.LONGER_MESSAGES];
|
|
|
|
case CTAVariant.PRO_GENERIC: // yes generic has the same as above, reversed...
|
|
return [ProFeatureKey.LONGER_MESSAGES, ProFeatureKey.MORE_PINNED_CONVOS];
|
|
|
|
case CTAVariant.PRO_EXPIRING_SOON:
|
|
case CTAVariant.PRO_EXPIRED:
|
|
return [
|
|
ProFeatureKey.LONGER_MESSAGES,
|
|
ProFeatureKey.MORE_PINNED_CONVOS,
|
|
ProFeatureKey.ANIMATED_DP,
|
|
];
|
|
|
|
case CTAVariant.PRO_GROUP_ADMIN:
|
|
return [ProFeatureKey.LARGER_GROUPS, ProFeatureKey.LONGER_MESSAGES];
|
|
|
|
default:
|
|
assertUnreachable(variant, 'getFeatureList unreachable case');
|
|
throw new Error('unreachable');
|
|
}
|
|
}
|
|
|
|
function FeatureList({ variant }: { variant: CTAVariant }) {
|
|
const featureList = useMemo(() => {
|
|
if (!isProFeatureListCTA(variant)) {
|
|
return [];
|
|
}
|
|
|
|
const features = getBaseFeatureList(variant).map((token, i) => (
|
|
<CTADescriptionListItem key={token} index={i}>
|
|
{tr(token)}
|
|
</CTADescriptionListItem>
|
|
));
|
|
|
|
// Expiry related CTAs dont show the "more" feature item
|
|
if (variant !== CTAVariant.PRO_EXPIRED && variant !== CTAVariant.PRO_EXPIRING_SOON) {
|
|
features.push(
|
|
<CTADescriptionListItem
|
|
key={'proFeatureListLoadsMore'}
|
|
index={features.length}
|
|
customIconSrc={'images/sparkle-animated.svg'}
|
|
>
|
|
{tr('proFeatureListLoadsMore')}
|
|
</CTADescriptionListItem>
|
|
);
|
|
}
|
|
return features;
|
|
}, [variant]);
|
|
|
|
return featureList.length ? (
|
|
<StyledCTADescriptionList>{featureList}</StyledCTADescriptionList>
|
|
) : null;
|
|
}
|
|
|
|
function ProExpiringSoonDescription() {
|
|
const { data } = useProBackendProDetails();
|
|
return <Localizer token="proExpiringSoonDescription" time={data.expiryTimeRelativeString} />;
|
|
}
|
|
|
|
function getDescription(variant: ProCTAVariant, userHasProExpired: boolean): ReactNode {
|
|
switch (variant) {
|
|
case CTAVariant.PRO_PINNED_CONVERSATION_LIMIT:
|
|
return (
|
|
<Localizer
|
|
token={
|
|
userHasProExpired
|
|
? 'proRenewPinFiveConversations'
|
|
: 'proCallToActionPinnedConversationsMoreThan'
|
|
}
|
|
limit={formatNumber(CONVERSATION.MAX_PINNED_CONVERSATIONS_STANDARD)}
|
|
/>
|
|
);
|
|
|
|
case CTAVariant.PRO_PINNED_CONVERSATION_LIMIT_GRANDFATHERED:
|
|
return (
|
|
<Localizer
|
|
token={
|
|
userHasProExpired
|
|
? 'proRenewPinMoreConversations'
|
|
: 'proCallToActionPinnedConversations'
|
|
}
|
|
/>
|
|
);
|
|
|
|
case CTAVariant.PRO_ANIMATED_DISPLAY_PICTURE:
|
|
return (
|
|
<Localizer
|
|
token={
|
|
userHasProExpired
|
|
? 'proRenewAnimatedDisplayPicture'
|
|
: 'proAnimatedDisplayPictureCallToActionDescription'
|
|
}
|
|
/>
|
|
);
|
|
|
|
case CTAVariant.PRO_ANIMATED_DISPLAY_PICTURE_ACTIVATED:
|
|
return (
|
|
<>
|
|
<span>
|
|
<Localizer token="proAlreadyPurchased" />{' '}
|
|
<ProIconButton
|
|
iconSize={'small'}
|
|
dataTestId="invalid-data-testid"
|
|
onClick={undefined}
|
|
/>
|
|
</span>
|
|
<br />
|
|
<Localizer token="proAnimatedDisplayPicture" />
|
|
</>
|
|
);
|
|
|
|
case CTAVariant.PRO_MESSAGE_CHARACTER_LIMIT:
|
|
return (
|
|
<Localizer
|
|
token={userHasProExpired ? 'proRenewLongerMessages' : 'proCallToActionLongerMessages'}
|
|
/>
|
|
);
|
|
|
|
case CTAVariant.PRO_GENERIC:
|
|
return (
|
|
<Localizer
|
|
token={userHasProExpired ? 'proRenewMaxPotential' : 'proUserProfileModalCallToAction'}
|
|
/>
|
|
);
|
|
|
|
case CTAVariant.PRO_EXPIRING_SOON:
|
|
return <ProExpiringSoonDescription />;
|
|
|
|
case CTAVariant.PRO_EXPIRED:
|
|
return <Localizer token="proExpiredDescription" />;
|
|
|
|
// TODO: Group CTA string dont all exist yet and need to be implemented later
|
|
case CTAVariant.PRO_GROUP_ADMIN:
|
|
case CTAVariant.PRO_GROUP_NON_ADMIN:
|
|
case CTAVariant.PRO_GROUP_ACTIVATED:
|
|
return (
|
|
<span>
|
|
<Localizer token="proGroupActivatedDescription" />{' '}
|
|
<ProIconButton iconSize={'small'} dataTestId="invalid-data-testid" onClick={undefined} />
|
|
</span>
|
|
);
|
|
|
|
default:
|
|
assertUnreachable(variant, 'getDescription unreachable case');
|
|
throw new Error('unreachable');
|
|
}
|
|
}
|
|
|
|
export function ProCTADescription({ variant }: { variant: ProCTAVariant }) {
|
|
const userHasExpiredPro = useCurrentUserHasExpiredPro();
|
|
return (
|
|
<>
|
|
<StyledScrollDescriptionContainer data-testid="cta-body">
|
|
{getDescription(variant, userHasExpiredPro)}
|
|
</StyledScrollDescriptionContainer>
|
|
<FeatureList variant={variant} />
|
|
</>
|
|
);
|
|
}
|