Cleanup released remote config flags

This commit is contained in:
Fedor Indutny
2026-03-17 18:34:29 -07:00
committed by GitHub
parent d8113d4d12
commit 36f1e20400
19 changed files with 59 additions and 226 deletions

View File

@@ -36,26 +36,16 @@ const SemverKeys = [
'desktop.adminDelete.send.prod',
'desktop.binaryServiceId.beta',
'desktop.binaryServiceId.prod',
'desktop.callQualitySurvey.beta',
'desktop.callQualitySurvey.prod',
'desktop.donationPaypal.beta',
'desktop.donationPaypal.prod',
'desktop.groupMemberLabels.edit.beta',
'desktop.groupMemberLabels.edit.prod',
'desktop.keyTransparency.beta',
'desktop.keyTransparency.prod',
'desktop.localBackups.beta',
'desktop.localBackups.prod',
'desktop.pinnedMessages.receive.beta',
'desktop.pinnedMessages.receive.prod',
'desktop.pinnedMessages.send.beta',
'desktop.pinnedMessages.send.prod',
'desktop.plaintextExport.beta',
'desktop.plaintextExport.prod',
'desktop.pollSend1to1.beta',
'desktop.pollSend1to1.prod',
'desktop.remoteMegaphone.beta',
'desktop.remoteMegaphone.prod',
'desktop.remoteMute.send.beta',
'desktop.remoteMute.send.prod',
'desktop.retireAccessKeyGroupSend.beta',
@@ -66,9 +56,6 @@ export type SemverKeyType = ArrayValues<typeof SemverKeys>;
const ScalarKeys = [
'desktop.callQualitySurveyPPM',
'desktop.chatFolders.alpha',
'desktop.chatFolders.beta',
'desktop.chatFolders.prod',
'desktop.clientExpiration',
'desktop.internalUser',
'desktop.loggingErrorToasts',

View File

@@ -282,7 +282,6 @@ import {
} from './types/Message2.preload.js';
import { JobCancelReason } from './jobs/types.std.js';
import { itemStorage } from './textsecure/Storage.preload.js';
import { isPinnedMessagesReceiveEnabled } from './util/isPinnedMessagesEnabled.dom.js';
import { initMessageCleanup } from './services/messageStateCleanup.dom.js';
import { MessageCache } from './services/MessageCache.preload.js';
import { saveAndNotify } from './messages/saveAndNotify.preload.js';
@@ -2510,11 +2509,6 @@ export async function startApp(): Promise<void> {
}
if (data.message.pinMessage != null) {
if (!isPinnedMessagesReceiveEnabled()) {
log.warn('Dropping PinMessage because the flag is disabled');
confirm();
return;
}
await PinnedMessages.onPinnedMessageAdd({
targetSentTimestamp: data.message.pinMessage.targetSentTimestamp,
targetAuthorAci: data.message.pinMessage.targetAuthorAci,
@@ -2700,11 +2694,6 @@ export async function startApp(): Promise<void> {
}
if (data.message.unpinMessage != null) {
if (!isPinnedMessagesReceiveEnabled()) {
log.warn('Dropping UnpinMessage because the flag is disabled');
confirm();
return;
}
await PinnedMessages.onPinnedMessageRemove({
targetSentTimestamp: data.message.unpinMessage.targetSentTimestamp,
targetAuthorAci: data.message.unpinMessage.targetAuthorAci,
@@ -3070,11 +3059,6 @@ export async function startApp(): Promise<void> {
}
if (data.message.pinMessage != null) {
if (!isPinnedMessagesReceiveEnabled()) {
log.warn('Dropping PinMessage because the flag is disabled');
confirm();
return;
}
strictAssert(data.timestamp != null, 'Missing sent timestamp');
await PinnedMessages.onPinnedMessageAdd({
targetSentTimestamp: data.message.pinMessage.targetSentTimestamp,
@@ -3262,11 +3246,6 @@ export async function startApp(): Promise<void> {
}
if (data.message.unpinMessage != null) {
if (!isPinnedMessagesReceiveEnabled()) {
log.warn('Dropping UnpinMessage because the flag is disabled');
confirm();
return;
}
await PinnedMessages.onPinnedMessageRemove({
targetSentTimestamp: data.message.unpinMessage.targetSentTimestamp,
targetAuthorAci: data.message.unpinMessage.targetAuthorAci,

View File

@@ -207,7 +207,6 @@ const useProps = (overrideProps: OverridePropsType = {}): PropsType => {
usernameLinkCorrupted: false,
isUpdateDownloaded,
isNotificationProfileActive: false,
isChatFoldersEnabled: true,
navTabsCollapsed: false,
setChallengeStatus: action('setChallengeStatus'),

View File

@@ -127,7 +127,6 @@ export type PropsType = {
i18n: LocalizerType;
isMacOS: boolean;
isNotificationProfileActive: boolean;
isChatFoldersEnabled: boolean;
preferredWidthFromStorage: number;
selectedChatFolder: ChatFolder | null;
selectedConversationId: undefined | string;
@@ -248,7 +247,6 @@ export function LeftPane({
lookupConversationWithoutServiceId,
isMacOS,
isNotificationProfileActive,
isChatFoldersEnabled,
isOnline,
isUpdateDownloaded,
modeSpecificProps,
@@ -818,7 +816,7 @@ export function LeftPane({
>
{i18n('icu:avatarMenuViewArchive')}
</AxoDropdownMenu.Item>
{isChatFoldersEnabled && !hasAnyCurrentCustomChatFolders && (
{!hasAnyCurrentCustomChatFolders && (
<AxoDropdownMenu.Item
symbol="folder-plus"
onSelect={onChatFoldersOpenSettings}
@@ -826,7 +824,7 @@ export function LeftPane({
{i18n('icu:LeftPane__MoreActionsMenu__AddChatFolder')}
</AxoDropdownMenu.Item>
)}
{isChatFoldersEnabled && hasAnyCurrentCustomChatFolders && (
{hasAnyCurrentCustomChatFolders && (
<AxoDropdownMenu.Item
symbol="folder-settings"
onSelect={onChatFoldersOpenSettings}

View File

@@ -266,7 +266,6 @@ function renderDonationsPane(props: {
clearWorkflow={action('clearWorkflow')}
initialCurrency="usd"
resumeWorkflow={action('resumeWorkflow')}
isDonationPaypalEnabled
isOnline
settingsLocation={props.settingsLocation}
setSettingsLocation={props.setSettingsLocation}
@@ -418,7 +417,6 @@ export default {
availableLocales: ['en'],
availableMicrophones,
availableSpeakers,
chatFoldersFeatureEnabled: true,
backupFreeMediaDays: 45,
backupKeyViewed: false,
backupLocalBackupsEnabled: false,

View File

@@ -118,7 +118,6 @@ export type PropsDataType = {
backupTier: BackupLevel | null;
lastLocalBackup: LocalBackupExportMetadata | undefined;
localBackupFolder: string | undefined;
chatFoldersFeatureEnabled: boolean;
currentChatFoldersCount: number;
cloudBackupStatus?: BackupStatusType;
backupSubscriptionStatus: BackupsSubscriptionType;
@@ -392,7 +391,6 @@ export function Preferences({
availableMicrophones,
availableSpeakers,
backupMediaDownloadStatus,
chatFoldersFeatureEnabled,
pauseBackupMediaDownload,
resumeBackupMediaDownload,
cancelBackupMediaDownload,
@@ -1198,55 +1196,51 @@ export function Preferences({
/>
</SettingsRow>
</SettingsRow>
{chatFoldersFeatureEnabled && (
<SettingsRow
title={i18n(
'icu:Preferences__ChatsPage__ChatFoldersSection__Title'
)}
>
<Control
left={
hasAnyCurrentCustomChatFolders
<SettingsRow
title={i18n('icu:Preferences__ChatsPage__ChatFoldersSection__Title')}
>
<Control
left={
hasAnyCurrentCustomChatFolders
? i18n(
'icu:Preferences__ChatsPage__ChatFoldersSection__AddChatFolderItem__Title--WithChatFolders'
)
: i18n(
'icu:Preferences__ChatsPage__ChatFoldersSection__AddChatFolderItem__Title'
)
}
description={
hasAnyCurrentCustomChatFolders
? i18n(
'icu:Preferences__ChatsPage__ChatFoldersSection__AddChatFolderItem__Description--WithChatFolders',
{ chatFoldersCount: currentChatFoldersCount }
)
: i18n(
'icu:Preferences__ChatsPage__ChatFoldersSection__AddChatFolderItem__Description'
)
}
right={
<AxoButton.Root
size="lg"
variant="secondary"
onClick={() => {
setSettingsLocation({
page: SettingsPage.ChatFolders,
previousLocation: null,
});
}}
>
{hasAnyCurrentCustomChatFolders
? i18n(
'icu:Preferences__ChatsPage__ChatFoldersSection__AddChatFolderItem__Title--WithChatFolders'
'icu:Preferences__ChatsPage__ChatFoldersSection__AddChatFolderItem__Button--WithChatFolders'
)
: i18n(
'icu:Preferences__ChatsPage__ChatFoldersSection__AddChatFolderItem__Title'
)
}
description={
hasAnyCurrentCustomChatFolders
? i18n(
'icu:Preferences__ChatsPage__ChatFoldersSection__AddChatFolderItem__Description--WithChatFolders',
{ chatFoldersCount: currentChatFoldersCount }
)
: i18n(
'icu:Preferences__ChatsPage__ChatFoldersSection__AddChatFolderItem__Description'
)
}
right={
<AxoButton.Root
size="lg"
variant="secondary"
onClick={() => {
setSettingsLocation({
page: SettingsPage.ChatFolders,
previousLocation: null,
});
}}
>
{hasAnyCurrentCustomChatFolders
? i18n(
'icu:Preferences__ChatsPage__ChatFoldersSection__AddChatFolderItem__Button--WithChatFolders'
)
: i18n(
'icu:Preferences__ChatsPage__ChatFoldersSection__AddChatFolderItem__Button'
)}
</AxoButton.Root>
}
/>
</SettingsRow>
)}
'icu:Preferences__ChatsPage__ChatFoldersSection__AddChatFolderItem__Button'
)}
</AxoButton.Root>
}
/>
</SettingsRow>
{isPlaintextExportEnabled && (
<SettingsRow>

View File

@@ -86,7 +86,6 @@ const SUPPORT_URL = 'https://support.signal.org/hc/requests/new?desktop';
export type PropsDataType = {
i18n: LocalizerType;
initialCurrency: string;
isDonationPaypalEnabled: boolean;
isOnline: boolean;
donationAmountsConfig: ReadonlyDeep<OneTimeDonationHumanAmounts> | undefined;
lastError: DonationErrorType | undefined;
@@ -124,7 +123,6 @@ export function PreferencesDonateFlow({
contentsRef,
i18n,
initialCurrency,
isDonationPaypalEnabled,
isOnline,
donationAmountsConfig,
lastError,
@@ -203,13 +201,10 @@ export function PreferencesDonateFlow({
return false;
}
return (
isDonationPaypalEnabled &&
donationAmountsConfig[currency].supportedPaymentMethods.includes(
PaymentMethod.Paypal
)
return donationAmountsConfig[currency].supportedPaymentMethods.includes(
PaymentMethod.Paypal
);
}, [isDonationPaypalEnabled, donationAmountsConfig, currency]);
}, [donationAmountsConfig, currency]);
const handleAmountPickerResult = useCallback(
(result: AmountPickerResult) => {

View File

@@ -70,7 +70,6 @@ type PropsExternalType = {
export type PropsDataType = {
i18n: LocalizerType;
initialCurrency: string;
isDonationPaypalEnabled: boolean;
isOnline: boolean;
settingsLocation: SettingsLocation;
didResumeWorkflowAtStartup: boolean;
@@ -548,7 +547,6 @@ export function PreferencesDonations({
contentsRef,
i18n,
initialCurrency,
isDonationPaypalEnabled,
isOnline,
settingsLocation,
workflow,
@@ -752,7 +750,6 @@ export function PreferencesDonations({
<PreferencesDonateFlow
contentsRef={contentsRef}
i18n={i18n}
isDonationPaypalEnabled={isDonationPaypalEnabled}
isOnline={isOnline}
initialCurrency={initialCurrency}
donationAmountsConfig={donationAmountsConfig}

View File

@@ -20,7 +20,6 @@ import { safeSetTimeout } from '../util/timeout.std.js';
import { clearTimeoutIfNecessary } from '../util/clearTimeoutIfNecessary.std.js';
import { itemStorage } from '../textsecure/Storage.preload.js';
import { isMoreRecentThan } from '../util/timestamp.std.js';
import { isFeaturedEnabledNoRedux } from '../util/isFeatureEnabled.dom.js';
import { maybeHydrateDonationConfigCache } from '../util/subscriptionConfiguration.preload.js';
const log = createLogger('megaphoneService');
@@ -48,11 +47,6 @@ export function initMegaphoneCheckService(): void {
export async function runMegaphoneCheck(): Promise<void> {
try {
if (!isRemoteMegaphoneEnabled()) {
log.info('runMegaphoneCheck: not enabled, skipping');
return;
}
const megaphones = await DataReader.getAllMegaphones();
const shownIds: Set<RemoteMegaphoneId> = new Set();
@@ -92,13 +86,6 @@ export async function runMegaphoneCheck(): Promise<void> {
}
}
export function isRemoteMegaphoneEnabled(): boolean {
return isFeaturedEnabledNoRedux({
betaKey: 'desktop.remoteMegaphone.beta',
prodKey: 'desktop.remoteMegaphone.prod',
});
}
export function isConditionalActive(conditionalId: string | null): boolean {
if (conditionalId == null) {
return true;

View File

@@ -48,7 +48,6 @@ import { isCountryPpmCsvBucketEnabled } from '../RemoteConfig.dom.js';
import type { AciString } from '../types/ServiceId.std.js';
import {
deleteMegaphoneAndRemoveFromRedux,
isRemoteMegaphoneEnabled,
runMegaphoneCheck,
} from './megaphone.preload.js';
@@ -574,18 +573,16 @@ export class ReleaseNoteAndMegaphoneFetcher {
const manifest = await this.#server.getReleaseNotesManifest();
const currentVersion = window.getVersion();
if (isRemoteMegaphoneEnabled()) {
// Remote megaphones can be saved prior to desktopMinVersion.
// Saved megaphones are periodically checked to see if we should show them.
const validMegaphones = manifest.megaphones.filter(
(megaphone): megaphone is ManifestMegaphoneType =>
megaphone.desktopMinVersion != null
);
await this.#deleteUnknownMegaphones(validMegaphones);
const savedCount = await this.#saveNewMegaphones(validMegaphones);
if (savedCount > 0) {
drop(runMegaphoneCheck());
}
// Remote megaphones can be saved prior to desktopMinVersion.
// Saved megaphones are periodically checked to see if we should show them.
const validMegaphones = manifest.megaphones.filter(
(megaphone): megaphone is ManifestMegaphoneType =>
megaphone.desktopMinVersion != null
);
await this.#deleteUnknownMegaphones(validMegaphones);
const savedCount = await this.#saveNewMegaphones(validMegaphones);
if (savedCount > 0) {
drop(runMegaphoneCheck());
}
const validNotes = manifest.announcements.filter(

View File

@@ -77,7 +77,6 @@ import {
type ChatFolder,
isConversationInChatFolder,
} from '../../types/ChatFolder.std.js';
import { isChatFoldersEnabled } from '../../util/isChatFoldersEnabled.dom.js';
import {
getSelectedChatFolder,
getCurrentChatFolders,
@@ -458,7 +457,6 @@ export const _getLeftPaneLists = ({
for (let conversation of Object.values(conversationLookup)) {
if (
isChatFoldersEnabled(window.SignalContext.getVersion()) &&
!_shouldIncludeInChatFolder(
conversation,
selectedChatFolder,

View File

@@ -176,7 +176,6 @@ import { getCallIdFromEra } from '../../util/callDisposition.preload.js';
import { LONG_MESSAGE } from '../../types/MIME.std.js';
import type { MessageRequestResponseNotificationData } from '../../components/conversation/MessageRequestResponseNotification.dom.js';
import type { PinnedMessageNotificationData } from '../../components/conversation/pinned-messages/PinnedMessageNotification.dom.js';
import { isPinnedMessagesSendEnabled } from '../../util/isPinnedMessagesEnabled.dom.js';
import type { PollTerminateNotificationDataType } from '../../components/conversation/PollTerminateNotification.dom.js';
const { groupBy, isEmpty, isNumber, isObject, map } = lodash;
@@ -2618,9 +2617,6 @@ export function canForward(message: ReadonlyMessageAttributesType): boolean {
}
export function canPinMessages(conversation: ConversationType): boolean {
if (!isPinnedMessagesSendEnabled()) {
return false;
}
return (
conversation.type === 'direct' || conversation.canEditGroupInfo === true
);

View File

@@ -17,7 +17,6 @@ import {
import { LeftPaneMode } from '../../types/leftPane.std.js';
import { getUsernameFromSearch } from '../../util/Username.dom.js';
import { getCountryDataForLocale } from '../../util/getCountryData.dom.js';
import { isChatFoldersEnabled } from '../../util/isChatFoldersEnabled.dom.js';
import { lookupConversationWithoutServiceId } from '../../util/lookupConversationWithoutServiceId.preload.js';
import { missingCaseError } from '../../util/missingCaseError.std.js';
import { isDone as isRegistrationDone } from '../../util/registration.preload.js';
@@ -314,7 +313,6 @@ export const SmartLeftPane = memo(function SmartLeftPane({
hasPendingUpdate,
otherTabsUnreadStats,
}: NavTabPanelProps) {
const version = window.SignalContext.getVersion();
const challengeStatus = useSelector(getChallengeStatus);
const composerStep = useSelector(getComposerStep);
const crashReportCount = useSelector(getCrashReportCount);
@@ -474,7 +472,6 @@ export const SmartLeftPane = memo(function SmartLeftPane({
isMacOS={isMacOS}
isOnline={isOnline}
isNotificationProfileActive={isNotificationProfileActive}
isChatFoldersEnabled={isChatFoldersEnabled(version)}
isUpdateDownloaded={isUpdateDownloaded}
lookupConversationWithoutServiceId={lookupConversationWithoutServiceId}
modeSpecificProps={modeSpecificProps}

View File

@@ -16,7 +16,6 @@ import { useChatFolderActions } from '../ducks/chatFolders.preload.js';
import { NavSidebarWidthBreakpointContext } from '../../components/NavSidebar.dom.js';
import { useNavActions } from '../ducks/nav.std.js';
import { NavTab, SettingsPage } from '../../types/Nav.std.js';
import { isChatFoldersEnabled } from '../../util/isChatFoldersEnabled.dom.js';
import type { ChatFolderId } from '../../types/ChatFolder.std.js';
import { getSelectedLocation } from '../selectors/nav.std.js';
import { useConversationsActions } from '../ducks/conversations.preload.js';
@@ -53,11 +52,6 @@ export const SmartLeftPaneChatFolders = memo(
[changeLocation, location]
);
const version = window.SignalContext.getVersion();
if (!isChatFoldersEnabled(version)) {
return null;
}
return (
<LeftPaneChatFolders
i18n={i18n}

View File

@@ -29,7 +29,6 @@ import {
setPhoneNumberDiscoverability,
} from '../../textsecure/WebAPI.preload.js';
import { DEFAULT_CONVERSATION_COLOR } from '../../types/Colors.std.js';
import { isChatFoldersEnabled } from '../../util/isChatFoldersEnabled.dom.js';
import { saveAttachmentToDisk } from '../../util/migrations.preload.js';
import { format } from '../../types/PhoneNumber.std.js';
import {
@@ -826,7 +825,6 @@ export function SmartPreferences(): React.JSX.Element | null {
backupLocalBackupsEnabled={backupLocalBackupsEnabled}
badge={badge}
blockedCount={blockedCount}
chatFoldersFeatureEnabled={isChatFoldersEnabled(version)}
currentChatFoldersCount={currentChatFoldersCount}
cloudBackupStatus={cloudBackupStatus}
customColors={customColors}

View File

@@ -6,12 +6,7 @@ import { useSelector } from 'react-redux';
import type { MutableRefObject } from 'react';
import {
getIntl,
getTheme,
getUserNumber,
getVersion,
} from '../selectors/user.std.js';
import { getIntl, getTheme, getUserNumber } from '../selectors/user.std.js';
import { getMe } from '../selectors/conversations.dom.js';
import { PreferencesDonations } from '../../components/PreferencesDonations.dom.js';
import type { SettingsLocation } from '../../types/Nav.std.js';
@@ -39,8 +34,6 @@ import { parseBoostBadgeListFromServer } from '../../badges/parseBadgesFromServe
import { createLogger } from '../../logging/log.std.js';
import { useBadgesActions } from '../ducks/badges.preload.js';
import { getNetworkIsOnline } from '../selectors/network.preload.js';
import { getItems } from '../selectors/items.dom.js';
import { isFeaturedEnabledSelector } from '../../util/isFeatureEnabled.dom.js';
import {
getDonationConfigCache,
getDonationsState,
@@ -62,7 +55,6 @@ export const SmartPreferencesDonations = memo(
const isOnline = useSelector(getNetworkIsOnline);
const i18n = useSelector(getIntl);
const items = useSelector(getItems);
const theme = useSelector(getTheme);
const donationsState = useSelector(getDonationsState);
@@ -92,15 +84,6 @@ export const SmartPreferencesDonations = memo(
(state: StateType) => state.donations.receipts
);
const version = useSelector(getVersion);
const isDonationPaypalEnabled = isFeaturedEnabledSelector({
currentVersion: version,
remoteConfig: items.remoteConfig,
betaKey: 'desktop.donationPaypal.beta',
prodKey: 'desktop.donationPaypal.prod',
});
const { updateOrCreate } = useBadgesActions();
// Function to fetch donation badge data
@@ -155,7 +138,6 @@ export const SmartPreferencesDonations = memo(
showToast={showToast}
contentsRef={contentsRef}
initialCurrency={initialCurrency}
isDonationPaypalEnabled={isDonationPaypalEnabled}
isOnline={isOnline}
settingsLocation={settingsLocation}
didResumeWorkflowAtStartup={donationsState.didResumeWorkflowAtStartup}

View File

@@ -3,7 +3,6 @@
import type { CallSummary } from '@signalapp/ringrtc';
import { DAY, SECOND } from './durations/index.std.js';
import { isFeaturedEnabledNoRedux } from './isFeatureEnabled.dom.js';
import { isMockEnvironment } from '../environment.std.js';
import {
COUNTRY_CODE_FALLBACK,
@@ -30,13 +29,6 @@ export function isCallFailure(callEndReasonText: string): boolean {
return FAILURE_END_REASONS.has(callEndReasonText);
}
export function isCallQualitySurveyEnabled(): boolean {
return isFeaturedEnabledNoRedux({
betaKey: 'desktop.callQualitySurvey.beta',
prodKey: 'desktop.callQualitySurvey.prod',
});
}
export function shouldShowCallQualitySurvey({
callSummary,
lastSurveyTime,
@@ -50,11 +42,7 @@ export function shouldShowCallQualitySurvey({
e164: string | undefined;
cqsTestMode?: boolean;
}): boolean {
if (
isMockEnvironment() ||
!isCallQualitySurveyEnabled() ||
!callSummary.isSurveyCandidate
) {
if (isMockEnvironment() || !callSummary.isSurveyCandidate) {
return false;
}

View File

@@ -1,33 +0,0 @@
// Copyright 2025 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import * as RemoteConfig from '../RemoteConfig.dom.js';
import {
Environment,
getEnvironment,
isMockEnvironment,
} from '../environment.std.js';
import { isAlpha, isBeta, isProduction } from './version.std.js';
export function isChatFoldersEnabled(version: string): boolean {
const env = getEnvironment();
if (
env === Environment.Development ||
env === Environment.Test ||
isMockEnvironment()
) {
return true;
}
if (isProduction(version)) {
return RemoteConfig.isEnabled('desktop.chatFolders.prod');
}
if (isBeta(version)) {
return RemoteConfig.isEnabled('desktop.chatFolders.beta');
}
if (isAlpha(version)) {
return RemoteConfig.isEnabled('desktop.chatFolders.alpha');
}
return false;
}

View File

@@ -1,18 +0,0 @@
// Copyright 2025 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { isFeaturedEnabledNoRedux } from './isFeatureEnabled.dom.js';
export function isPinnedMessagesReceiveEnabled(): boolean {
return isFeaturedEnabledNoRedux({
betaKey: 'desktop.pinnedMessages.receive.beta',
prodKey: 'desktop.pinnedMessages.receive.prod',
});
}
export function isPinnedMessagesSendEnabled(): boolean {
return isFeaturedEnabledNoRedux({
betaKey: 'desktop.pinnedMessages.send.beta',
prodKey: 'desktop.pinnedMessages.send.prod',
});
}