Add backup media download progress to settings pane
Co-authored-by: trevor-signal <131492920+trevor-signal@users.noreply.github.com>
This commit is contained in:
parent
fd5b977190
commit
de847714e2
16 changed files with 355 additions and 189 deletions
|
@ -5565,11 +5565,11 @@
|
||||||
"description": "Text of the retry button of the error modal in the backup import screen"
|
"description": "Text of the retry button of the error modal in the backup import screen"
|
||||||
},
|
},
|
||||||
"icu:BackupMediaDownloadProgress__title-in-progress": {
|
"icu:BackupMediaDownloadProgress__title-in-progress": {
|
||||||
"messageformat": "Restoring media",
|
"messageformat": "Syncing media",
|
||||||
"description": "Label next to a progress bar showing active media (attachment) download progress after restoring from backup"
|
"description": "Label next to a progress bar showing active media (attachment) download progress after restoring from backup"
|
||||||
},
|
},
|
||||||
"icu:BackupMediaDownloadProgress__title-paused": {
|
"icu:BackupMediaDownloadProgress__title-paused": {
|
||||||
"messageformat": "Restore paused",
|
"messageformat": "Syncing paused",
|
||||||
"description": "Label indicating media (attachment) download progress has been paused (due to user interaction)"
|
"description": "Label indicating media (attachment) download progress has been paused (due to user interaction)"
|
||||||
},
|
},
|
||||||
"icu:BackupMediaDownloadProgress__title-idle": {
|
"icu:BackupMediaDownloadProgress__title-idle": {
|
||||||
|
@ -5589,15 +5589,15 @@
|
||||||
"description": "Description text when attachment download in progress but offline"
|
"description": "Description text when attachment download in progress but offline"
|
||||||
},
|
},
|
||||||
"icu:BackupMediaDownloadProgress__button-pause": {
|
"icu:BackupMediaDownloadProgress__button-pause": {
|
||||||
"messageformat": "Pause transfer",
|
"messageformat": "Pause",
|
||||||
"description": "Text for button to pause media (attachment) download after backup impor"
|
"description": "Text for button to pause media (attachment) download after backup impor"
|
||||||
},
|
},
|
||||||
"icu:BackupMediaDownloadProgress__button-resume": {
|
"icu:BackupMediaDownloadProgress__button-resume": {
|
||||||
"messageformat": "Resume transfer",
|
"messageformat": "Resume",
|
||||||
"description": "Text for button to resume media (attachment) download after backup import"
|
"description": "Text for button to resume media (attachment) download after backup import"
|
||||||
},
|
},
|
||||||
"icu:BackupMediaDownloadProgress__button-cancel": {
|
"icu:BackupMediaDownloadProgress__button-cancel": {
|
||||||
"messageformat": "Cancel transfer",
|
"messageformat": "Cancel syncing",
|
||||||
"description": "Text for button to cancel (pause) media (attachment) download after backup import"
|
"description": "Text for button to cancel (pause) media (attachment) download after backup import"
|
||||||
},
|
},
|
||||||
"icu:BackupMediaDownloadProgress__button-more": {
|
"icu:BackupMediaDownloadProgress__button-more": {
|
||||||
|
@ -5613,21 +5613,45 @@
|
||||||
"description": "Hint under the progressbar showing media (attachment) download progress after restoring from backup"
|
"description": "Hint under the progressbar showing media (attachment) download progress after restoring from backup"
|
||||||
},
|
},
|
||||||
"icu:BackupMediaDownloadCancelConfirmation__title": {
|
"icu:BackupMediaDownloadCancelConfirmation__title": {
|
||||||
"messageformat": "Cancel media transfer?",
|
"messageformat": "Cancel media syncing?",
|
||||||
"description": "Text for button to cancel (pause) media (attachment) download after backup import"
|
"description": "Text for button to cancel media (attachment) download after backup import"
|
||||||
},
|
},
|
||||||
"icu:BackupMediaDownloadCancelConfirmation__description": {
|
"icu:BackupMediaDownloadCancelConfirmation__description": {
|
||||||
"messageformat": "Your messages and media have not completed restoring. If you choose to cancel, you can transfer again from Settings.",
|
"messageformat": "Your media has not completed syncing. If you choose to cancel, you can sync again by re-linking this device. <learnMoreLink>Learn more</learnMoreLink>.",
|
||||||
"description": "Text for button to cancel (pause) media (attachment) download after backup import"
|
"description": "Text for button to cancel media (attachment) download after backup import"
|
||||||
},
|
},
|
||||||
"icu:BackupMediaDownloadCancelConfirmation__button-continue": {
|
"icu:BackupMediaDownloadCancelConfirmation__button-continue": {
|
||||||
"messageformat": "Continue transfer",
|
"messageformat": "Continue syncing",
|
||||||
"description": "Text for button to close confirmation dialog and continue media (attachment) download"
|
"description": "Text for button to close confirmation dialog and continue media (attachment) download"
|
||||||
},
|
},
|
||||||
"icu:BackupMediaDownloadCancelConfirmation__button-confirm-cancel": {
|
"icu:BackupMediaDownloadCancelConfirmation__button-confirm-cancel": {
|
||||||
"messageformat": "Cancel transfer",
|
"messageformat": "Cancel syncing",
|
||||||
"description": "Text for button to confirm cancellation of media (attachment) download"
|
"description": "Text for button to confirm cancellation of media (attachment) download"
|
||||||
},
|
},
|
||||||
|
"icu:BackupMediaDownloadProgressSettings__paused--title": {
|
||||||
|
"messageformat": "Syncing paused",
|
||||||
|
"description": "Label indicating media (attachment) download progress when the transfer has been paused"
|
||||||
|
},
|
||||||
|
"icu:BackupMediaDownloadProgressSettings__paused--description": {
|
||||||
|
"messageformat": "Click “{resumeButtonText}” to continue syncing",
|
||||||
|
"description": "Shown below progress bar when the transfer has been paused. {resumeButtonText} will be 'icu:BackupMediaDownloadProgressSettings__button-resume'"
|
||||||
|
},
|
||||||
|
"icu:BackupMediaDownloadProgressSettings__button-resume": {
|
||||||
|
"messageformat": "Resume",
|
||||||
|
"description": "Text for button to resume media (attachment) download after backup import"
|
||||||
|
},
|
||||||
|
"icu:BackupMediaDownloadProgressSettings__button-pause": {
|
||||||
|
"messageformat": "Pause",
|
||||||
|
"description": "Text for button to pause media (attachment) download after backup import"
|
||||||
|
},
|
||||||
|
"icu:BackupMediaDownloadProgressSettings__title-in-progress": {
|
||||||
|
"messageformat": "Syncing media",
|
||||||
|
"description": "Label next to a progress bar showing active media (attachment) download progress after restoring from backup"
|
||||||
|
},
|
||||||
|
"icu:BackupMediaDownloadProgressSettings__progressbar-hint": {
|
||||||
|
"messageformat": "{currentSize} of {totalSize} ({fractionComplete, number, percent})...",
|
||||||
|
"description": "Hint under the progressbar in the backup import screen"
|
||||||
|
},
|
||||||
"icu:CriticalIdlePrimaryDeviceModal__title": {
|
"icu:CriticalIdlePrimaryDeviceModal__title": {
|
||||||
"messageformat": "Account action required",
|
"messageformat": "Account action required",
|
||||||
"description": "Title for modal shown when a user must use their idle primary device to retain their account"
|
"description": "Title for modal shown when a user must use their idle primary device to retain their account"
|
||||||
|
|
|
@ -138,4 +138,7 @@ button.BackupMediaDownloadProgress__button-close {
|
||||||
|
|
||||||
.BackupMediaDownloadCancelConfirmation {
|
.BackupMediaDownloadCancelConfirmation {
|
||||||
min-width: 440px;
|
min-width: 440px;
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright 2025 Signal Messenger, LLC
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
@use '../mixins';
|
||||||
|
@use '../variables';
|
||||||
|
|
||||||
|
.BackupMediaDownloadProgressSettings {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
|
||||||
|
&__buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.BackupMediaDownloadProgressSettings__content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 5px;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.BackupMediaDownloadProgressSettings__description {
|
||||||
|
color: light-dark(variables.$color-gray-60, variables.$color-gray-25);
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 16px;
|
||||||
|
}
|
|
@ -33,6 +33,7 @@
|
||||||
@use 'components/AvatarTextEditor.scss';
|
@use 'components/AvatarTextEditor.scss';
|
||||||
@use 'components/BackfillFailureModal.scss';
|
@use 'components/BackfillFailureModal.scss';
|
||||||
@use 'components/BackupMediaDownloadProgress.scss';
|
@use 'components/BackupMediaDownloadProgress.scss';
|
||||||
|
@use 'components/BackupMediaDownloadProgressSettings.scss';
|
||||||
@use 'components/BadgeCarouselIndex.scss';
|
@use 'components/BadgeCarouselIndex.scss';
|
||||||
@use 'components/BadgeDialog.scss';
|
@use 'components/BadgeDialog.scss';
|
||||||
@use 'components/BadgeSustainerInstructionsDialog.scss';
|
@use 'components/BadgeSustainerInstructionsDialog.scss';
|
||||||
|
|
|
@ -5,7 +5,10 @@ import React from 'react';
|
||||||
|
|
||||||
import { ConfirmationDialog } from './ConfirmationDialog';
|
import { ConfirmationDialog } from './ConfirmationDialog';
|
||||||
import type { LocalizerType } from '../types/I18N';
|
import type { LocalizerType } from '../types/I18N';
|
||||||
|
import { I18n } from './I18n';
|
||||||
|
|
||||||
|
const BACKUP_AND_RESTORE_SUPPORT_PAGE =
|
||||||
|
'https://support.signal.org/hc/articles/360007059752-Backup-and-Restore-Messages';
|
||||||
export function BackupMediaDownloadCancelConfirmationDialog({
|
export function BackupMediaDownloadCancelConfirmationDialog({
|
||||||
i18n,
|
i18n,
|
||||||
handleConfirmCancel,
|
handleConfirmCancel,
|
||||||
|
@ -15,6 +18,11 @@ export function BackupMediaDownloadCancelConfirmationDialog({
|
||||||
handleConfirmCancel: VoidFunction;
|
handleConfirmCancel: VoidFunction;
|
||||||
handleDialogClose: VoidFunction;
|
handleDialogClose: VoidFunction;
|
||||||
}): JSX.Element | null {
|
}): JSX.Element | null {
|
||||||
|
const learnMoreLink = (parts: Array<string | JSX.Element>) => (
|
||||||
|
<a href={BACKUP_AND_RESTORE_SUPPORT_PAGE} rel="noreferrer" target="_blank">
|
||||||
|
{parts}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<ConfirmationDialog
|
<ConfirmationDialog
|
||||||
moduleClassName="BackupMediaDownloadCancelConfirmation"
|
moduleClassName="BackupMediaDownloadCancelConfirmation"
|
||||||
|
@ -35,7 +43,13 @@ export function BackupMediaDownloadCancelConfirmationDialog({
|
||||||
onClose={handleDialogClose}
|
onClose={handleDialogClose}
|
||||||
title={i18n('icu:BackupMediaDownloadCancelConfirmation__title')}
|
title={i18n('icu:BackupMediaDownloadCancelConfirmation__title')}
|
||||||
>
|
>
|
||||||
{i18n('icu:BackupMediaDownloadCancelConfirmation__description')}
|
<I18n
|
||||||
|
id="icu:BackupMediaDownloadCancelConfirmation__description"
|
||||||
|
i18n={i18n}
|
||||||
|
components={{
|
||||||
|
learnMoreLink,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</ConfirmationDialog>
|
</ConfirmationDialog>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
128
ts/components/BackupMediaDownloadProgressSettings.tsx
Normal file
128
ts/components/BackupMediaDownloadProgressSettings.tsx
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
// Copyright 2025 Signal Messenger, LLC
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
|
import type { LocalizerType } from '../types/Util';
|
||||||
|
import { formatFileSize } from '../util/formatFileSize';
|
||||||
|
import { roundFractionForProgressBar } from '../util/numbers';
|
||||||
|
import { ProgressBar } from './ProgressBar';
|
||||||
|
import { Button, ButtonSize, ButtonVariant } from './Button';
|
||||||
|
import { BackupMediaDownloadCancelConfirmationDialog } from './BackupMediaDownloadCancelConfirmationDialog';
|
||||||
|
|
||||||
|
export type PropsType = Readonly<{
|
||||||
|
i18n: LocalizerType;
|
||||||
|
completedBytes: number;
|
||||||
|
totalBytes: number;
|
||||||
|
isPaused: boolean;
|
||||||
|
handleCancel: VoidFunction;
|
||||||
|
handleResume: VoidFunction;
|
||||||
|
handlePause: VoidFunction;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export function BackupMediaDownloadProgressSettings({
|
||||||
|
i18n,
|
||||||
|
completedBytes,
|
||||||
|
totalBytes,
|
||||||
|
isPaused,
|
||||||
|
handleCancel,
|
||||||
|
handleResume,
|
||||||
|
handlePause,
|
||||||
|
}: PropsType): JSX.Element | null {
|
||||||
|
const [isShowingCancelConfirmation, setIsShowingCancelConfirmation] =
|
||||||
|
useState(false);
|
||||||
|
const isRTL = i18n.getLocaleDirection() === 'rtl';
|
||||||
|
if (totalBytes <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fractionComplete = roundFractionForProgressBar(
|
||||||
|
completedBytes / totalBytes
|
||||||
|
);
|
||||||
|
|
||||||
|
const isCompleted = fractionComplete === 1;
|
||||||
|
|
||||||
|
if (isCompleted) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let title: string;
|
||||||
|
let description: string;
|
||||||
|
let actionButton: JSX.Element | undefined;
|
||||||
|
|
||||||
|
if (isPaused) {
|
||||||
|
title = i18n('icu:BackupMediaDownloadProgressSettings__paused--title');
|
||||||
|
description = i18n(
|
||||||
|
'icu:BackupMediaDownloadProgressSettings__paused--description',
|
||||||
|
{
|
||||||
|
resumeButtonText: i18n(
|
||||||
|
'icu:BackupMediaDownloadProgressSettings__button-resume'
|
||||||
|
),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
actionButton = (
|
||||||
|
<Button
|
||||||
|
onClick={handleResume}
|
||||||
|
variant={ButtonVariant.Secondary}
|
||||||
|
size={ButtonSize.Small}
|
||||||
|
className="BackupMediaDownloadProgressSettings__button"
|
||||||
|
>
|
||||||
|
{i18n('icu:BackupMediaDownloadProgressSettings__button-resume')}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
title = i18n('icu:BackupMediaDownloadProgressSettings__title-in-progress');
|
||||||
|
description = i18n(
|
||||||
|
'icu:BackupMediaDownloadProgressSettings__progressbar-hint',
|
||||||
|
{
|
||||||
|
currentSize: formatFileSize(completedBytes),
|
||||||
|
totalSize: formatFileSize(totalBytes),
|
||||||
|
fractionComplete,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
actionButton = (
|
||||||
|
<Button
|
||||||
|
onClick={handlePause}
|
||||||
|
variant={ButtonVariant.Secondary}
|
||||||
|
size={ButtonSize.Small}
|
||||||
|
className="BackupMediaDownloadProgressSettings__button"
|
||||||
|
>
|
||||||
|
{i18n('icu:BackupMediaDownloadProgressSettings__button-pause')}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="BackupMediaDownloadProgressSettings">
|
||||||
|
<div className="BackupMediaDownloadProgressSettings__content">
|
||||||
|
<div className="BackupMediaDownloadProgressSettings__title">
|
||||||
|
{title}
|
||||||
|
</div>
|
||||||
|
<div className="BackupMediaDownloadProgressSettings__ProgressBar">
|
||||||
|
<ProgressBar fractionComplete={fractionComplete} isRTL={isRTL} />
|
||||||
|
</div>
|
||||||
|
<div className="BackupMediaDownloadProgressSettings__description">
|
||||||
|
{description}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="BackupMediaDownloadProgressSettings__buttons">
|
||||||
|
{actionButton}
|
||||||
|
<Button
|
||||||
|
onClick={() => setIsShowingCancelConfirmation(true)}
|
||||||
|
variant={ButtonVariant.SecondaryDestructive}
|
||||||
|
className="BackupMediaDownloadProgressSettings__button"
|
||||||
|
size={ButtonSize.Small}
|
||||||
|
>
|
||||||
|
{i18n('icu:cancel')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
{isShowingCancelConfirmation ? (
|
||||||
|
<BackupMediaDownloadCancelConfirmationDialog
|
||||||
|
i18n={i18n}
|
||||||
|
handleConfirmCancel={handleCancel}
|
||||||
|
handleDialogClose={() => setIsShowingCancelConfirmation(false)}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -10,20 +10,16 @@ import { PRODUCTION_DOWNLOAD_URL, BETA_DOWNLOAD_URL } from '../types/support';
|
||||||
import { I18n } from './I18n';
|
import { I18n } from './I18n';
|
||||||
import { LeftPaneDialog } from './LeftPaneDialog';
|
import { LeftPaneDialog } from './LeftPaneDialog';
|
||||||
import { formatFileSize } from '../util/formatFileSize';
|
import { formatFileSize } from '../util/formatFileSize';
|
||||||
import { getLocalizedUrl } from '../util/getLocalizedUrl';
|
|
||||||
|
|
||||||
import type { LocalizerType } from '../types/Util';
|
import type { LocalizerType } from '../types/Util';
|
||||||
import type { DismissOptions } from './LeftPaneDialog';
|
import type { DismissOptions } from './LeftPaneDialog';
|
||||||
import type { WidthBreakpoint } from './_util';
|
import type { WidthBreakpoint } from './_util';
|
||||||
|
|
||||||
function contactSupportLink(parts: ReactNode): JSX.Element {
|
function contactSupportLink(parts: ReactNode): JSX.Element {
|
||||||
const localizedSupportLink = getLocalizedUrl(
|
|
||||||
'https://support.signal.org/hc/LOCALE/requests/new?desktop'
|
|
||||||
);
|
|
||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
key="signal-support"
|
key="signal-support"
|
||||||
href={localizedSupportLink}
|
href="https://support.signal.org/hc/requests/new?desktop"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
|
|
|
@ -415,6 +415,9 @@ export default {
|
||||||
removeCustomColorOnConversations: action(
|
removeCustomColorOnConversations: action(
|
||||||
'removeCustomColorOnConversations'
|
'removeCustomColorOnConversations'
|
||||||
),
|
),
|
||||||
|
resumeBackupMediaDownload: action('resumeBackupMediaDownload'),
|
||||||
|
pauseBackupMediaDownload: action('pauseBackupMediaDownload'),
|
||||||
|
cancelBackupMediaDownload: action('cancelBackupMediaDownload'),
|
||||||
resetAllChatColors: action('resetAllChatColors'),
|
resetAllChatColors: action('resetAllChatColors'),
|
||||||
resetDefaultChatColor: action('resetDefaultChatColor'),
|
resetDefaultChatColor: action('resetDefaultChatColor'),
|
||||||
savePreferredLeftPaneWidth: action('savePreferredLeftPaneWidth'),
|
savePreferredLeftPaneWidth: action('savePreferredLeftPaneWidth'),
|
||||||
|
@ -528,6 +531,55 @@ PNPDiscoverabilityDisabled.args = {
|
||||||
page: Page.PNP,
|
page: Page.PNP,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const BackupsMediaDownloadActive = Template.bind({});
|
||||||
|
BackupsMediaDownloadActive.args = {
|
||||||
|
page: Page.BackupsDetails,
|
||||||
|
backupFeatureEnabled: true,
|
||||||
|
backupLocalBackupsEnabled: true,
|
||||||
|
cloudBackupStatus: {
|
||||||
|
protoSize: 100_000_000,
|
||||||
|
createdTimestamp: Date.now() - WEEK,
|
||||||
|
},
|
||||||
|
backupSubscriptionStatus: {
|
||||||
|
status: 'active',
|
||||||
|
cost: {
|
||||||
|
amount: 22.99,
|
||||||
|
currencyCode: 'USD',
|
||||||
|
},
|
||||||
|
renewalTimestamp: Date.now() + 20 * DAY,
|
||||||
|
},
|
||||||
|
backupMediaDownloadStatus: {
|
||||||
|
completedBytes: 123_456_789,
|
||||||
|
totalBytes: 987_654_321,
|
||||||
|
isPaused: false,
|
||||||
|
isIdle: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
export const BackupsMediaDownloadPaused = Template.bind({});
|
||||||
|
BackupsMediaDownloadPaused.args = {
|
||||||
|
page: Page.BackupsDetails,
|
||||||
|
backupFeatureEnabled: true,
|
||||||
|
backupLocalBackupsEnabled: true,
|
||||||
|
cloudBackupStatus: {
|
||||||
|
protoSize: 100_000_000,
|
||||||
|
createdTimestamp: Date.now() - WEEK,
|
||||||
|
},
|
||||||
|
backupSubscriptionStatus: {
|
||||||
|
status: 'active',
|
||||||
|
cost: {
|
||||||
|
amount: 22.99,
|
||||||
|
currencyCode: 'USD',
|
||||||
|
},
|
||||||
|
renewalTimestamp: Date.now() + 20 * DAY,
|
||||||
|
},
|
||||||
|
backupMediaDownloadStatus: {
|
||||||
|
completedBytes: 123_456_789,
|
||||||
|
totalBytes: 987_654_321,
|
||||||
|
isPaused: true,
|
||||||
|
isIdle: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export const BackupsPaidActive = Template.bind({});
|
export const BackupsPaidActive = Template.bind({});
|
||||||
BackupsPaidActive.args = {
|
BackupsPaidActive.args = {
|
||||||
page: Page.Backups,
|
page: Page.Backups,
|
||||||
|
|
|
@ -74,6 +74,7 @@ import type {
|
||||||
ThemeType,
|
ThemeType,
|
||||||
} from '../types/Util';
|
} from '../types/Util';
|
||||||
import type {
|
import type {
|
||||||
|
BackupMediaDownloadStatusType,
|
||||||
BackupsSubscriptionType,
|
BackupsSubscriptionType,
|
||||||
BackupStatusType,
|
BackupStatusType,
|
||||||
} from '../types/backups';
|
} from '../types/backups';
|
||||||
|
@ -118,6 +119,10 @@ export type PropsDataType = {
|
||||||
localBackupFolder: string | undefined;
|
localBackupFolder: string | undefined;
|
||||||
cloudBackupStatus?: BackupStatusType;
|
cloudBackupStatus?: BackupStatusType;
|
||||||
backupSubscriptionStatus: BackupsSubscriptionType;
|
backupSubscriptionStatus: BackupsSubscriptionType;
|
||||||
|
backupMediaDownloadStatus?: BackupMediaDownloadStatusType;
|
||||||
|
pauseBackupMediaDownload: VoidFunction;
|
||||||
|
cancelBackupMediaDownload: VoidFunction;
|
||||||
|
resumeBackupMediaDownload: VoidFunction;
|
||||||
blockedCount: number;
|
blockedCount: number;
|
||||||
customColors: Record<string, CustomColorType>;
|
customColors: Record<string, CustomColorType>;
|
||||||
defaultConversationColor: DefaultConversationColorType;
|
defaultConversationColor: DefaultConversationColorType;
|
||||||
|
@ -225,6 +230,8 @@ type PropsFunctionType = {
|
||||||
getMessageSampleForSchemaVersion: (
|
getMessageSampleForSchemaVersion: (
|
||||||
version: number
|
version: number
|
||||||
) => Promise<Array<MessageAttributesType>>;
|
) => Promise<Array<MessageAttributesType>>;
|
||||||
|
resumeBackupMediaDownload: () => void;
|
||||||
|
pauseBackupMediaDownload: () => void;
|
||||||
getConversationsWithCustomColor: (colorId: string) => Array<ConversationType>;
|
getConversationsWithCustomColor: (colorId: string) => Array<ConversationType>;
|
||||||
getPreferredBadge: PreferredBadgeSelectorType;
|
getPreferredBadge: PreferredBadgeSelectorType;
|
||||||
makeSyncRequest: () => unknown;
|
makeSyncRequest: () => unknown;
|
||||||
|
@ -386,6 +393,10 @@ export function Preferences({
|
||||||
availableMicrophones,
|
availableMicrophones,
|
||||||
availableSpeakers,
|
availableSpeakers,
|
||||||
backupFeatureEnabled,
|
backupFeatureEnabled,
|
||||||
|
backupMediaDownloadStatus,
|
||||||
|
pauseBackupMediaDownload,
|
||||||
|
resumeBackupMediaDownload,
|
||||||
|
cancelBackupMediaDownload,
|
||||||
backupKeyViewed,
|
backupKeyViewed,
|
||||||
backupSubscriptionStatus,
|
backupSubscriptionStatus,
|
||||||
backupLocalBackupsEnabled,
|
backupLocalBackupsEnabled,
|
||||||
|
@ -2160,6 +2171,10 @@ export function Preferences({
|
||||||
accountEntropyPool={accountEntropyPool}
|
accountEntropyPool={accountEntropyPool}
|
||||||
backupKeyViewed={backupKeyViewed}
|
backupKeyViewed={backupKeyViewed}
|
||||||
backupSubscriptionStatus={backupSubscriptionStatus}
|
backupSubscriptionStatus={backupSubscriptionStatus}
|
||||||
|
backupMediaDownloadStatus={backupMediaDownloadStatus}
|
||||||
|
cancelBackupMediaDownload={cancelBackupMediaDownload}
|
||||||
|
pauseBackupMediaDownload={pauseBackupMediaDownload}
|
||||||
|
resumeBackupMediaDownload={resumeBackupMediaDownload}
|
||||||
cloudBackupStatus={cloudBackupStatus}
|
cloudBackupStatus={cloudBackupStatus}
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
locale={resolvedLocale}
|
locale={resolvedLocale}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import React, { useEffect, useState } from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
|
BackupMediaDownloadStatusType,
|
||||||
BackupsSubscriptionType,
|
BackupsSubscriptionType,
|
||||||
BackupStatusType,
|
BackupStatusType,
|
||||||
} from '../types/backups';
|
} from '../types/backups';
|
||||||
|
@ -28,6 +29,7 @@ import type {
|
||||||
PromptOSAuthResultType,
|
PromptOSAuthResultType,
|
||||||
} from '../util/os/promptOSAuthMain';
|
} from '../util/os/promptOSAuthMain';
|
||||||
import { ConfirmationDialog } from './ConfirmationDialog';
|
import { ConfirmationDialog } from './ConfirmationDialog';
|
||||||
|
import { BackupMediaDownloadProgressSettings } from './BackupMediaDownloadProgressSettings';
|
||||||
|
|
||||||
export const SIGNAL_BACKUPS_LEARN_MORE_URL =
|
export const SIGNAL_BACKUPS_LEARN_MORE_URL =
|
||||||
'https://support.signal.org/hc/articles/360007059752-Backup-and-Restore-Messages';
|
'https://support.signal.org/hc/articles/360007059752-Backup-and-Restore-Messages';
|
||||||
|
@ -42,6 +44,10 @@ export function PreferencesBackups({
|
||||||
localBackupFolder,
|
localBackupFolder,
|
||||||
onBackupKeyViewedChange,
|
onBackupKeyViewedChange,
|
||||||
pickLocalBackupFolder,
|
pickLocalBackupFolder,
|
||||||
|
backupMediaDownloadStatus,
|
||||||
|
cancelBackupMediaDownload,
|
||||||
|
pauseBackupMediaDownload,
|
||||||
|
resumeBackupMediaDownload,
|
||||||
page,
|
page,
|
||||||
promptOSAuth,
|
promptOSAuth,
|
||||||
refreshCloudBackupStatus,
|
refreshCloudBackupStatus,
|
||||||
|
@ -58,6 +64,10 @@ export function PreferencesBackups({
|
||||||
locale: string;
|
locale: string;
|
||||||
onBackupKeyViewedChange: (keyViewed: boolean) => void;
|
onBackupKeyViewedChange: (keyViewed: boolean) => void;
|
||||||
page: PreferencesBackupPage;
|
page: PreferencesBackupPage;
|
||||||
|
backupMediaDownloadStatus: BackupMediaDownloadStatusType | undefined;
|
||||||
|
cancelBackupMediaDownload: () => void;
|
||||||
|
pauseBackupMediaDownload: () => void;
|
||||||
|
resumeBackupMediaDownload: () => void;
|
||||||
pickLocalBackupFolder: () => Promise<string | undefined>;
|
pickLocalBackupFolder: () => Promise<string | undefined>;
|
||||||
promptOSAuth: (
|
promptOSAuth: (
|
||||||
reason: PromptOSAuthReasonType
|
reason: PromptOSAuthReasonType
|
||||||
|
@ -90,6 +100,10 @@ export function PreferencesBackups({
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
cloudBackupStatus={cloudBackupStatus}
|
cloudBackupStatus={cloudBackupStatus}
|
||||||
backupSubscriptionStatus={backupSubscriptionStatus}
|
backupSubscriptionStatus={backupSubscriptionStatus}
|
||||||
|
backupMediaDownloadStatus={backupMediaDownloadStatus}
|
||||||
|
cancelBackupMediaDownload={cancelBackupMediaDownload}
|
||||||
|
pauseBackupMediaDownload={pauseBackupMediaDownload}
|
||||||
|
resumeBackupMediaDownload={resumeBackupMediaDownload}
|
||||||
locale={locale}
|
locale={locale}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -468,12 +482,25 @@ function BackupsDetailsPage({
|
||||||
backupSubscriptionStatus,
|
backupSubscriptionStatus,
|
||||||
i18n,
|
i18n,
|
||||||
locale,
|
locale,
|
||||||
|
cancelBackupMediaDownload,
|
||||||
|
pauseBackupMediaDownload,
|
||||||
|
resumeBackupMediaDownload,
|
||||||
|
backupMediaDownloadStatus,
|
||||||
}: {
|
}: {
|
||||||
cloudBackupStatus?: BackupStatusType;
|
cloudBackupStatus?: BackupStatusType;
|
||||||
backupSubscriptionStatus: BackupsSubscriptionType;
|
backupSubscriptionStatus: BackupsSubscriptionType;
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
locale: string;
|
locale: string;
|
||||||
|
cancelBackupMediaDownload: () => void;
|
||||||
|
pauseBackupMediaDownload: () => void;
|
||||||
|
resumeBackupMediaDownload: () => void;
|
||||||
|
backupMediaDownloadStatus?: BackupMediaDownloadStatusType;
|
||||||
}): JSX.Element {
|
}): JSX.Element {
|
||||||
|
const shouldShowMediaProgress =
|
||||||
|
backupMediaDownloadStatus &&
|
||||||
|
backupMediaDownloadStatus.completedBytes <
|
||||||
|
backupMediaDownloadStatus.totalBytes;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="Preferences--backups-summary__container">
|
<div className="Preferences--backups-summary__container">
|
||||||
|
@ -484,12 +511,12 @@ function BackupsDetailsPage({
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{cloudBackupStatus ? (
|
{cloudBackupStatus || shouldShowMediaProgress ? (
|
||||||
<SettingsRow
|
<SettingsRow
|
||||||
className="Preferences--backup-details"
|
className="Preferences--backup-details"
|
||||||
title={i18n('icu:Preferences--backup-details__header')}
|
title={i18n('icu:Preferences--backup-details__header')}
|
||||||
>
|
>
|
||||||
{cloudBackupStatus.createdTimestamp ? (
|
{cloudBackupStatus?.createdTimestamp ? (
|
||||||
<div className="Preferences--backup-details__row">
|
<div className="Preferences--backup-details__row">
|
||||||
<label>{i18n('icu:Preferences--backup-created-at__label')}</label>
|
<label>{i18n('icu:Preferences--backup-created-at__label')}</label>
|
||||||
<div
|
<div
|
||||||
|
@ -506,6 +533,17 @@ function BackupsDetailsPage({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
{shouldShowMediaProgress && backupMediaDownloadStatus ? (
|
||||||
|
<div className="Preferences--backup-details__row">
|
||||||
|
<BackupMediaDownloadProgressSettings
|
||||||
|
{...backupMediaDownloadStatus}
|
||||||
|
handleCancel={cancelBackupMediaDownload}
|
||||||
|
handlePause={pauseBackupMediaDownload}
|
||||||
|
handleResume={resumeBackupMediaDownload}
|
||||||
|
i18n={i18n}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
</SettingsRow>
|
</SettingsRow>
|
||||||
) : null}
|
) : null}
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -10,7 +10,6 @@ import { Button, ButtonSize, ButtonVariant } from '../Button';
|
||||||
import { SystemMessage } from './SystemMessage';
|
import { SystemMessage } from './SystemMessage';
|
||||||
import { ChatSessionRefreshedDialog } from './ChatSessionRefreshedDialog';
|
import { ChatSessionRefreshedDialog } from './ChatSessionRefreshedDialog';
|
||||||
import { openLinkInWebBrowser } from '../../util/openLinkInWebBrowser';
|
import { openLinkInWebBrowser } from '../../util/openLinkInWebBrowser';
|
||||||
import { getLocalizedUrl } from '../../util/getLocalizedUrl';
|
|
||||||
|
|
||||||
type PropsHousekeepingType = {
|
type PropsHousekeepingType = {
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
|
@ -34,9 +33,8 @@ export function ChatSessionRefreshedNotification(
|
||||||
const wrappedContactSupport = useCallback(() => {
|
const wrappedContactSupport = useCallback(() => {
|
||||||
setIsDialogOpen(false);
|
setIsDialogOpen(false);
|
||||||
|
|
||||||
const url = getLocalizedUrl(
|
const url =
|
||||||
'https://support.signal.org/hc/LOCALE/requests/new?desktop&chat_refreshed'
|
'https://support.signal.org/hc/requests/new?desktop&chat_refreshed';
|
||||||
);
|
|
||||||
|
|
||||||
openLinkInWebBrowser(url);
|
openLinkInWebBrowser(url);
|
||||||
}, [setIsDialogOpen]);
|
}, [setIsDialogOpen]);
|
||||||
|
|
|
@ -15,7 +15,6 @@ import type { SmartChooseGroupMembersModalPropsType } from '../../../state/smart
|
||||||
import type { SmartConfirmAdditionsModalPropsType } from '../../../state/smart/ConfirmAdditionsModal';
|
import type { SmartConfirmAdditionsModalPropsType } from '../../../state/smart/ConfirmAdditionsModal';
|
||||||
import { assertDev } from '../../../util/assert';
|
import { assertDev } from '../../../util/assert';
|
||||||
import { getMutedUntilText } from '../../../util/getMutedUntilText';
|
import { getMutedUntilText } from '../../../util/getMutedUntilText';
|
||||||
import { getLocalizedUrl } from '../../../util/getLocalizedUrl';
|
|
||||||
|
|
||||||
import type { LocalizerType, ThemeType } from '../../../types/Util';
|
import type { LocalizerType, ThemeType } from '../../../types/Util';
|
||||||
import type { BadgeType } from '../../../badges/types';
|
import type { BadgeType } from '../../../badges/types';
|
||||||
|
@ -521,9 +520,7 @@ export function ConversationDetails({
|
||||||
}
|
}
|
||||||
label={i18n('icu:ConversationDetails--support-center')}
|
label={i18n('icu:ConversationDetails--support-center')}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
openLinkInWebBrowser(
|
openLinkInWebBrowser('https://support.signal.org');
|
||||||
getLocalizedUrl('https://support.signal.org/hc/LOCALE')
|
|
||||||
);
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<PanelRow
|
<PanelRow
|
||||||
|
@ -536,9 +533,7 @@ export function ConversationDetails({
|
||||||
label={i18n('icu:contactUs')}
|
label={i18n('icu:contactUs')}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
openLinkInWebBrowser(
|
openLinkInWebBrowser(
|
||||||
getLocalizedUrl(
|
'https://support.signal.org/hc/requests/new?desktop'
|
||||||
'https://support.signal.org/hc/LOCALE/requests/new?desktop'
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -79,6 +79,11 @@ import type { WidthBreakpoint } from '../../components/_util';
|
||||||
import { DialogType } from '../../types/Dialogs';
|
import { DialogType } from '../../types/Dialogs';
|
||||||
import { promptOSAuth } from '../../util/promptOSAuth';
|
import { promptOSAuth } from '../../util/promptOSAuth';
|
||||||
import type { StateType } from '../reducer';
|
import type { StateType } from '../reducer';
|
||||||
|
import {
|
||||||
|
pauseBackupMediaDownload,
|
||||||
|
resumeBackupMediaDownload,
|
||||||
|
cancelBackupMediaDownload,
|
||||||
|
} from '../../util/backupMediaDownload';
|
||||||
|
|
||||||
const DEFAULT_NOTIFICATION_SETTING = 'message';
|
const DEFAULT_NOTIFICATION_SETTING = 'message';
|
||||||
|
|
||||||
|
@ -490,8 +495,15 @@ export function SmartPreferences(): JSX.Element | null {
|
||||||
|
|
||||||
// Simple, one-way items
|
// Simple, one-way items
|
||||||
|
|
||||||
const { backupSubscriptionStatus, cloudBackupStatus, localBackupFolder } =
|
const {
|
||||||
items;
|
backupSubscriptionStatus,
|
||||||
|
cloudBackupStatus,
|
||||||
|
localBackupFolder,
|
||||||
|
backupMediaDownloadCompletedBytes,
|
||||||
|
backupMediaDownloadTotalBytes,
|
||||||
|
attachmentDownloadManagerIdled,
|
||||||
|
backupMediaDownloadPaused,
|
||||||
|
} = items;
|
||||||
const defaultConversationColor =
|
const defaultConversationColor =
|
||||||
items.defaultConversationColor || DEFAULT_CONVERSATION_COLOR;
|
items.defaultConversationColor || DEFAULT_CONVERSATION_COLOR;
|
||||||
const hasLinkPreviews = items.linkPreviews ?? false;
|
const hasLinkPreviews = items.linkPreviews ?? false;
|
||||||
|
@ -712,6 +724,12 @@ export function SmartPreferences(): JSX.Element | null {
|
||||||
backupFeatureEnabled={backupFeatureEnabled}
|
backupFeatureEnabled={backupFeatureEnabled}
|
||||||
backupKeyViewed={backupKeyViewed}
|
backupKeyViewed={backupKeyViewed}
|
||||||
backupSubscriptionStatus={backupSubscriptionStatus ?? { status: 'off' }}
|
backupSubscriptionStatus={backupSubscriptionStatus ?? { status: 'off' }}
|
||||||
|
backupMediaDownloadStatus={{
|
||||||
|
completedBytes: backupMediaDownloadCompletedBytes ?? 0,
|
||||||
|
totalBytes: backupMediaDownloadTotalBytes ?? 0,
|
||||||
|
isPaused: Boolean(backupMediaDownloadPaused),
|
||||||
|
isIdle: Boolean(attachmentDownloadManagerIdled),
|
||||||
|
}}
|
||||||
backupLocalBackupsEnabled={backupLocalBackupsEnabled}
|
backupLocalBackupsEnabled={backupLocalBackupsEnabled}
|
||||||
badge={badge}
|
badge={badge}
|
||||||
blockedCount={blockedCount}
|
blockedCount={blockedCount}
|
||||||
|
@ -837,6 +855,9 @@ export function SmartPreferences(): JSX.Element | null {
|
||||||
resetDefaultChatColor={resetDefaultChatColor}
|
resetDefaultChatColor={resetDefaultChatColor}
|
||||||
resolvedLocale={resolvedLocale}
|
resolvedLocale={resolvedLocale}
|
||||||
savePreferredLeftPaneWidth={savePreferredLeftPaneWidth}
|
savePreferredLeftPaneWidth={savePreferredLeftPaneWidth}
|
||||||
|
resumeBackupMediaDownload={resumeBackupMediaDownload}
|
||||||
|
pauseBackupMediaDownload={pauseBackupMediaDownload}
|
||||||
|
cancelBackupMediaDownload={cancelBackupMediaDownload}
|
||||||
selectedCamera={selectedCamera}
|
selectedCamera={selectedCamera}
|
||||||
selectedMicrophone={selectedMicrophone}
|
selectedMicrophone={selectedMicrophone}
|
||||||
selectedSpeaker={selectedSpeaker}
|
selectedSpeaker={selectedSpeaker}
|
||||||
|
|
|
@ -40,6 +40,13 @@ export type BackupStatusType = {
|
||||||
protoSize?: number;
|
protoSize?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type BackupMediaDownloadStatusType = {
|
||||||
|
totalBytes: number;
|
||||||
|
completedBytes: number;
|
||||||
|
isPaused: boolean;
|
||||||
|
isIdle: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export type BackupsSubscriptionType =
|
export type BackupsSubscriptionType =
|
||||||
| {
|
| {
|
||||||
status: 'off' | 'not-found' | 'expired';
|
status: 'off' | 'not-found' | 'expired';
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
// Copyright 2025 Signal Messenger, LLC
|
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
|
|
||||||
import { mapToSupportLocale } from './mapToSupportLocale';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensures the provided string contains "LOCALE".
|
|
||||||
* If not, produces a readable TypeScript error.
|
|
||||||
*/
|
|
||||||
type RequiresLocale<T extends string> = T extends `${string}LOCALE${string}`
|
|
||||||
? T
|
|
||||||
: `Error: The URL must contain "LOCALE" but got "${T}"`;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replaces "LOCALE" in a URL with the appropriate localized support locale.
|
|
||||||
*
|
|
||||||
* @param url The URL string containing "LOCALE" to be replaced
|
|
||||||
* @returns The URL with "LOCALE" replaced with the appropriate locale
|
|
||||||
*/
|
|
||||||
export function getLocalizedUrl<T extends string>(
|
|
||||||
url: RequiresLocale<T>
|
|
||||||
): string {
|
|
||||||
const locale = window.SignalContext.getResolvedMessagesLocale();
|
|
||||||
const supportLocale = mapToSupportLocale(locale);
|
|
||||||
return url.replace('LOCALE', supportLocale);
|
|
||||||
}
|
|
|
@ -1,131 +0,0 @@
|
||||||
// Copyright 2021 Signal Messenger, LLC
|
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
|
|
||||||
export type SupportLocaleType =
|
|
||||||
| 'ar'
|
|
||||||
| 'de'
|
|
||||||
| 'en-us'
|
|
||||||
| 'es'
|
|
||||||
| 'fr'
|
|
||||||
| 'it'
|
|
||||||
| 'ja'
|
|
||||||
| 'pl'
|
|
||||||
| 'pt-br'
|
|
||||||
| 'ru'
|
|
||||||
| 'sq'
|
|
||||||
| 'zh-tw';
|
|
||||||
|
|
||||||
// See https://source.chromium.org/chromium/chromium/src/+/main:ui/base/l10n/l10n_util.cc
|
|
||||||
export type ElectronLocaleType =
|
|
||||||
| 'af'
|
|
||||||
| 'ar'
|
|
||||||
| 'bg'
|
|
||||||
| 'bn'
|
|
||||||
| 'ca'
|
|
||||||
| 'cs'
|
|
||||||
| 'cy'
|
|
||||||
| 'da'
|
|
||||||
| 'de'
|
|
||||||
| 'de-AT'
|
|
||||||
| 'de-CH'
|
|
||||||
| 'de-DE'
|
|
||||||
| 'de-LI'
|
|
||||||
| 'el'
|
|
||||||
| 'en'
|
|
||||||
| 'en-AU'
|
|
||||||
| 'en-CA'
|
|
||||||
| 'en-GB'
|
|
||||||
| 'en-GB-oxendict'
|
|
||||||
| 'en-IN'
|
|
||||||
| 'en-NZ'
|
|
||||||
| 'en-US'
|
|
||||||
| 'eo'
|
|
||||||
| 'es'
|
|
||||||
| 'es-419'
|
|
||||||
| 'et'
|
|
||||||
| 'eu'
|
|
||||||
| 'fa'
|
|
||||||
| 'fi'
|
|
||||||
| 'fr'
|
|
||||||
| 'fr-CA'
|
|
||||||
| 'fr-CH'
|
|
||||||
| 'fr-FR'
|
|
||||||
| 'he'
|
|
||||||
| 'hi'
|
|
||||||
| 'hr'
|
|
||||||
| 'hu'
|
|
||||||
| 'id'
|
|
||||||
| 'it'
|
|
||||||
| 'it-CH'
|
|
||||||
| 'it-IT'
|
|
||||||
| 'ja'
|
|
||||||
| 'km'
|
|
||||||
| 'kn'
|
|
||||||
| 'ko'
|
|
||||||
| 'lt'
|
|
||||||
| 'mk'
|
|
||||||
| 'mr'
|
|
||||||
| 'ms'
|
|
||||||
| 'nb'
|
|
||||||
| 'nl'
|
|
||||||
| 'nn'
|
|
||||||
| 'no'
|
|
||||||
| 'pl'
|
|
||||||
| 'pt-BR'
|
|
||||||
| 'pt-PT'
|
|
||||||
| 'ro'
|
|
||||||
| 'ru'
|
|
||||||
| 'sk'
|
|
||||||
| 'sl'
|
|
||||||
| 'sq'
|
|
||||||
| 'sr'
|
|
||||||
| 'sv'
|
|
||||||
| 'sw'
|
|
||||||
| 'ta'
|
|
||||||
| 'te'
|
|
||||||
| 'th'
|
|
||||||
| 'tr'
|
|
||||||
| 'uk'
|
|
||||||
| 'ur'
|
|
||||||
| 'vi'
|
|
||||||
| 'zh-CN'
|
|
||||||
| 'zh-HK'
|
|
||||||
| 'zh-TW';
|
|
||||||
|
|
||||||
export function mapToSupportLocale(ourLocale: string): SupportLocaleType {
|
|
||||||
if (ourLocale === 'ar') {
|
|
||||||
return ourLocale;
|
|
||||||
}
|
|
||||||
if (ourLocale === 'de') {
|
|
||||||
return ourLocale;
|
|
||||||
}
|
|
||||||
if (ourLocale === 'es') {
|
|
||||||
return ourLocale;
|
|
||||||
}
|
|
||||||
if (ourLocale === 'fr') {
|
|
||||||
return ourLocale;
|
|
||||||
}
|
|
||||||
if (ourLocale === 'it') {
|
|
||||||
return ourLocale;
|
|
||||||
}
|
|
||||||
if (ourLocale === 'ja') {
|
|
||||||
return ourLocale;
|
|
||||||
}
|
|
||||||
if (ourLocale === 'pl') {
|
|
||||||
return ourLocale;
|
|
||||||
}
|
|
||||||
if (ourLocale === 'pt-BR') {
|
|
||||||
return 'pt-br';
|
|
||||||
}
|
|
||||||
if (ourLocale === 'ru') {
|
|
||||||
return ourLocale;
|
|
||||||
}
|
|
||||||
if (ourLocale === 'sq') {
|
|
||||||
return ourLocale;
|
|
||||||
}
|
|
||||||
if (ourLocale === 'zh-TW') {
|
|
||||||
return 'zh-tw';
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'en-us';
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue