// Copyright 2025 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
import type {
BackupsSubscriptionType,
BackupStatusType,
} from '../types/backups';
import type { LocalizerType } from '../types/I18N';
import { formatTimestamp } from '../util/formatTimestamp';
import { formatFileSize } from '../util/formatFileSize';
import { SettingsRow } from './PreferencesUtil';
import { missingCaseError } from '../util/missingCaseError';
export function PreferencesBackups({
cloudBackupStatus,
backupSubscriptionStatus,
i18n,
locale,
}: {
cloudBackupStatus?: BackupStatusType;
backupSubscriptionStatus?: BackupsSubscriptionType;
i18n: LocalizerType;
locale: string;
}): JSX.Element {
return (
<>
{getBackupsSubscriptionSummary({
subscriptionStatus: backupSubscriptionStatus,
i18n,
locale,
})}
{cloudBackupStatus ? (
{cloudBackupStatus.createdAt ? (
{/* TODO (DESKTOP-8509) */}
{i18n('icu:Preferences--backup-created-by-phone')}
{formatTimestamp(cloudBackupStatus.createdAt, {
dateStyle: 'medium',
timeStyle: 'short',
})}
) : null}
{cloudBackupStatus.mediaSize != null ||
cloudBackupStatus.protoSize != null}
) : null}
>
);
}
function getSubscriptionDetails({
i18n,
subscriptionStatus,
locale,
}: {
i18n: LocalizerType;
locale: string;
subscriptionStatus: BackupsSubscriptionType;
}): JSX.Element | null {
if (subscriptionStatus.status === 'active') {
return (
<>
{subscriptionStatus.cost ? (
{new Intl.NumberFormat(locale, {
style: 'currency',
currency: subscriptionStatus.cost.currencyCode,
currencyDisplay: 'narrowSymbol',
}).format(subscriptionStatus.cost.amount)}{' '}
/ month
) : null}
{subscriptionStatus.renewalDate ? (
{i18n('icu:Preferences--backup-plan__renewal-date', {
date: formatTimestamp(subscriptionStatus.renewalDate.getTime(), {
dateStyle: 'medium',
}),
})}
) : null}
>
);
}
if (subscriptionStatus.status === 'pending-cancellation') {
return (
<>
{i18n('icu:Preferences--backup-plan__canceled')}
{subscriptionStatus.expiryDate ? (
{i18n('icu:Preferences--backup-plan__expiry-date', {
date: formatTimestamp(subscriptionStatus.expiryDate.getTime(), {
dateStyle: 'medium',
}),
})}
) : null}
>
);
}
return null;
}
export function getBackupsSubscriptionSummary({
subscriptionStatus,
i18n,
locale,
}: {
locale: string;
subscriptionStatus?: BackupsSubscriptionType;
i18n: LocalizerType;
}): JSX.Element | null {
if (!subscriptionStatus) {
return null;
}
const { status } = subscriptionStatus;
switch (status) {
case 'active':
case 'pending-cancellation':
return (
<>
{i18n('icu:Preferences--backup-media-plan__description')}
{getSubscriptionDetails({ i18n, locale, subscriptionStatus })}
{subscriptionStatus.status === 'active' ? (
) : (
)}
{i18n('icu:Preferences--backup-media-plan__note')}
>
);
case 'free':
return (
<>
{i18n('icu:Preferences--backup-messages-plan__description', {
mediaDayCount:
subscriptionStatus.mediaIncludedInBackupDurationDays,
})}
{i18n(
'icu:Preferences--backup-messages-plan__cost-description'
)}
{i18n('icu:Preferences--backup-messages-plan__note')}
>
);
case 'not-found':
case 'expired':
return (
<>
{i18n('icu:Preferences--backup-plan-not-found__description')}
{i18n('icu:Preferences--backup-plan__not-found__note')}
>
);
default:
throw missingCaseError(status);
}
}