Cleanup RemoteConfig
This commit is contained in:
parent
7bad05f5a0
commit
b2a3605d77
53 changed files with 121 additions and 614 deletions
|
@ -16,32 +16,18 @@ import { getCountryCode } from './types/PhoneNumber';
|
||||||
|
|
||||||
export type ConfigKeyType =
|
export type ConfigKeyType =
|
||||||
| 'cds.disableCompatibilityMode'
|
| 'cds.disableCompatibilityMode'
|
||||||
| 'desktop.announcementGroup'
|
|
||||||
| 'desktop.calling.sendScreenShare1800'
|
| 'desktop.calling.sendScreenShare1800'
|
||||||
| 'desktop.cdsi.returnAcisWithoutUaks'
|
| 'desktop.cdsi.returnAcisWithoutUaks'
|
||||||
| 'desktop.clientExpiration'
|
| 'desktop.clientExpiration'
|
||||||
| 'desktop.editMessageSend'
|
|
||||||
| 'desktop.groupCallOutboundRing2.beta'
|
|
||||||
| 'desktop.groupCallOutboundRing2'
|
|
||||||
| 'desktop.groupMultiTypingIndicators'
|
| 'desktop.groupMultiTypingIndicators'
|
||||||
| 'desktop.internalUser'
|
| 'desktop.internalUser'
|
||||||
| 'desktop.mandatoryProfileSharing'
|
|
||||||
| 'desktop.mediaQuality.levels'
|
| 'desktop.mediaQuality.levels'
|
||||||
| 'desktop.messageCleanup'
|
| 'desktop.messageCleanup'
|
||||||
| 'desktop.messageRequests'
|
|
||||||
| 'desktop.pnp'
|
| 'desktop.pnp'
|
||||||
| 'desktop.pnp.accountE164Deprecation'
|
| 'desktop.pnp.accountE164Deprecation'
|
||||||
| 'desktop.retryRespondMaxAge'
|
| 'desktop.retryRespondMaxAge'
|
||||||
| 'desktop.senderKey.retry'
|
| 'desktop.senderKey.retry'
|
||||||
| 'desktop.senderKey.send'
|
|
||||||
| 'desktop.senderKeyMaxAge'
|
| 'desktop.senderKeyMaxAge'
|
||||||
| 'desktop.sendSenderKey3'
|
|
||||||
| 'desktop.showUserBadges.beta'
|
|
||||||
| 'desktop.showUserBadges2'
|
|
||||||
| 'desktop.stories2.beta'
|
|
||||||
| 'desktop.stories2'
|
|
||||||
| 'desktop.textFormatting.spoilerSend'
|
|
||||||
| 'desktop.textFormatting'
|
|
||||||
| 'desktop.usernames'
|
| 'desktop.usernames'
|
||||||
| 'global.attachments.maxBytes'
|
| 'global.attachments.maxBytes'
|
||||||
| 'global.attachments.maxReceiveBytes'
|
| 'global.attachments.maxReceiveBytes'
|
||||||
|
|
|
@ -1511,27 +1511,6 @@ export async function startApp(): Promise<void> {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// Listen for changes to the `desktop.messageRequests` remote configuration flag
|
|
||||||
const removeMessageRequestListener = window.Signal.RemoteConfig.onChange(
|
|
||||||
'desktop.messageRequests',
|
|
||||||
({ enabled }) => {
|
|
||||||
if (!enabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const conversations = window.getConversations();
|
|
||||||
conversations.forEach(conversation => {
|
|
||||||
conversation.set({
|
|
||||||
messageCountBeforeMessageRequests:
|
|
||||||
conversation.get('messageCount') || 0,
|
|
||||||
});
|
|
||||||
window.Signal.Data.updateConversation(conversation.attributes);
|
|
||||||
});
|
|
||||||
|
|
||||||
removeMessageRequestListener();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (resolveOnAppView) {
|
if (resolveOnAppView) {
|
||||||
resolveOnAppView();
|
resolveOnAppView();
|
||||||
resolveOnAppView = undefined;
|
resolveOnAppView = undefined;
|
||||||
|
|
|
@ -73,7 +73,6 @@ const createProps = (storyProps: Partial<PropsType> = {}): PropsType => ({
|
||||||
getPresentingSources: action('get-presenting-sources'),
|
getPresentingSources: action('get-presenting-sources'),
|
||||||
hangUpActiveCall: action('hang-up-active-call'),
|
hangUpActiveCall: action('hang-up-active-call'),
|
||||||
i18n,
|
i18n,
|
||||||
isGroupCallOutboundRingEnabled: true,
|
|
||||||
isGroupCallRaiseHandEnabled: true,
|
isGroupCallRaiseHandEnabled: true,
|
||||||
isGroupCallReactionsEnabled: true,
|
isGroupCallReactionsEnabled: true,
|
||||||
keyChangeOk: action('key-change-ok'),
|
keyChangeOk: action('key-change-ok'),
|
||||||
|
|
|
@ -87,7 +87,6 @@ export type PropsType = {
|
||||||
bounceAppIconStop: () => unknown;
|
bounceAppIconStop: () => unknown;
|
||||||
declineCall: (_: DeclineCallType) => void;
|
declineCall: (_: DeclineCallType) => void;
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
isGroupCallOutboundRingEnabled: boolean;
|
|
||||||
isGroupCallRaiseHandEnabled: boolean;
|
isGroupCallRaiseHandEnabled: boolean;
|
||||||
isGroupCallReactionsEnabled: boolean;
|
isGroupCallReactionsEnabled: boolean;
|
||||||
me: ConversationType;
|
me: ConversationType;
|
||||||
|
@ -132,7 +131,6 @@ function ActiveCallManager({
|
||||||
closeNeedPermissionScreen,
|
closeNeedPermissionScreen,
|
||||||
hangUpActiveCall,
|
hangUpActiveCall,
|
||||||
i18n,
|
i18n,
|
||||||
isGroupCallOutboundRingEnabled,
|
|
||||||
isGroupCallRaiseHandEnabled,
|
isGroupCallRaiseHandEnabled,
|
||||||
isGroupCallReactionsEnabled,
|
isGroupCallReactionsEnabled,
|
||||||
keyChangeOk,
|
keyChangeOk,
|
||||||
|
@ -271,7 +269,6 @@ function ActiveCallManager({
|
||||||
hasLocalVideo={hasLocalVideo}
|
hasLocalVideo={hasLocalVideo}
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
isGroupCall={activeCall.callMode === CallMode.Group}
|
isGroupCall={activeCall.callMode === CallMode.Group}
|
||||||
isGroupCallOutboundRingEnabled={isGroupCallOutboundRingEnabled}
|
|
||||||
isCallFull={isCallFull}
|
isCallFull={isCallFull}
|
||||||
isConversationTooBigToRing={isConvoTooBigToRing}
|
isConversationTooBigToRing={isConvoTooBigToRing}
|
||||||
me={me}
|
me={me}
|
||||||
|
|
|
@ -51,7 +51,6 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => {
|
||||||
hasLocalVideo: overrideProps.hasLocalVideo ?? false,
|
hasLocalVideo: overrideProps.hasLocalVideo ?? false,
|
||||||
i18n,
|
i18n,
|
||||||
isGroupCall,
|
isGroupCall,
|
||||||
isGroupCallOutboundRingEnabled: true,
|
|
||||||
isConversationTooBigToRing: false,
|
isConversationTooBigToRing: false,
|
||||||
isCallFull: overrideProps.isCallFull ?? false,
|
isCallFull: overrideProps.isCallFull ?? false,
|
||||||
me:
|
me:
|
||||||
|
|
|
@ -49,7 +49,6 @@ export type PropsType = {
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
isConversationTooBigToRing: boolean;
|
isConversationTooBigToRing: boolean;
|
||||||
isGroupCall: boolean;
|
isGroupCall: boolean;
|
||||||
isGroupCallOutboundRingEnabled: boolean;
|
|
||||||
isCallFull?: boolean;
|
isCallFull?: boolean;
|
||||||
me: Readonly<
|
me: Readonly<
|
||||||
Pick<ConversationType, 'avatarPath' | 'color' | 'id' | 'serviceId'>
|
Pick<ConversationType, 'avatarPath' | 'color' | 'id' | 'serviceId'>
|
||||||
|
@ -75,7 +74,6 @@ export function CallingLobby({
|
||||||
hasLocalVideo,
|
hasLocalVideo,
|
||||||
i18n,
|
i18n,
|
||||||
isGroupCall = false,
|
isGroupCall = false,
|
||||||
isGroupCallOutboundRingEnabled,
|
|
||||||
isCallFull = false,
|
isCallFull = false,
|
||||||
isConversationTooBigToRing,
|
isConversationTooBigToRing,
|
||||||
me,
|
me,
|
||||||
|
@ -157,7 +155,6 @@ export function CallingLobby({
|
||||||
|
|
||||||
const isRingButtonVisible: boolean =
|
const isRingButtonVisible: boolean =
|
||||||
isGroupCall &&
|
isGroupCall &&
|
||||||
isGroupCallOutboundRingEnabled &&
|
|
||||||
peekedParticipants.length === 0 &&
|
peekedParticipants.length === 0 &&
|
||||||
(groupMembers || []).length > 1;
|
(groupMembers || []).length > 1;
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,6 @@ export default {
|
||||||
options: Object.keys(RecordingState),
|
options: Object.keys(RecordingState),
|
||||||
mappings: RecordingState,
|
mappings: RecordingState,
|
||||||
},
|
},
|
||||||
messageRequestsEnabled: { control: { type: 'boolean' } },
|
|
||||||
announcementsOnly: { control: { type: 'boolean' } },
|
announcementsOnly: { control: { type: 'boolean' } },
|
||||||
areWePendingApproval: { control: { type: 'boolean' } },
|
areWePendingApproval: { control: { type: 'boolean' } },
|
||||||
},
|
},
|
||||||
|
@ -45,8 +44,6 @@ export default {
|
||||||
sendCounter: 0,
|
sendCounter: 0,
|
||||||
i18n,
|
i18n,
|
||||||
isDisabled: false,
|
isDisabled: false,
|
||||||
isFormattingFlagEnabled: true,
|
|
||||||
isFormattingSpoilersFlagEnabled: true,
|
|
||||||
isFormattingEnabled: true,
|
isFormattingEnabled: true,
|
||||||
messageCompositionId: '456',
|
messageCompositionId: '456',
|
||||||
sendEditedMessage: action('sendEditedMessage'),
|
sendEditedMessage: action('sendEditedMessage'),
|
||||||
|
@ -111,7 +108,6 @@ export default {
|
||||||
blockConversation: action('blockConversation'),
|
blockConversation: action('blockConversation'),
|
||||||
blockAndReportSpam: action('blockAndReportSpam'),
|
blockAndReportSpam: action('blockAndReportSpam'),
|
||||||
deleteConversation: action('deleteConversation'),
|
deleteConversation: action('deleteConversation'),
|
||||||
messageRequestsEnabled: false,
|
|
||||||
title: '',
|
title: '',
|
||||||
// GroupV1 Disabled Actions
|
// GroupV1 Disabled Actions
|
||||||
showGV2MigrationDialog: action('showGV2MigrationDialog'),
|
showGV2MigrationDialog: action('showGV2MigrationDialog'),
|
||||||
|
@ -164,7 +160,7 @@ export function StickerButton(args: Props): JSX.Element {
|
||||||
|
|
||||||
export function MessageRequest(args: Props): JSX.Element {
|
export function MessageRequest(args: Props): JSX.Element {
|
||||||
const theme = useContext(StorybookThemeContext);
|
const theme = useContext(StorybookThemeContext);
|
||||||
return <CompositionArea {...args} theme={theme} messageRequestsEnabled />;
|
return <CompositionArea {...args} theme={theme} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SmsOnlyFetchingUuid(args: Props): JSX.Element {
|
export function SmsOnlyFetchingUuid(args: Props): JSX.Element {
|
||||||
|
@ -260,21 +256,3 @@ export function NoFormattingMenu(args: Props): JSX.Element {
|
||||||
<CompositionArea {...args} theme={theme} isFormattingEnabled={false} />
|
<CompositionArea {...args} theme={theme} isFormattingEnabled={false} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function NoFormattingFlag(args: Props): JSX.Element {
|
|
||||||
const theme = useContext(StorybookThemeContext);
|
|
||||||
return (
|
|
||||||
<CompositionArea {...args} theme={theme} isFormattingFlagEnabled={false} />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function NoSpoilerFormattingFlag(args: Props): JSX.Element {
|
|
||||||
const theme = useContext(StorybookThemeContext);
|
|
||||||
return (
|
|
||||||
<CompositionArea
|
|
||||||
{...args}
|
|
||||||
theme={theme}
|
|
||||||
isFormattingSpoilersFlagEnabled={false}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
|
@ -105,8 +105,6 @@ export type OwnProps = Readonly<{
|
||||||
isDisabled: boolean;
|
isDisabled: boolean;
|
||||||
isFetchingUUID?: boolean;
|
isFetchingUUID?: boolean;
|
||||||
isFormattingEnabled: boolean;
|
isFormattingEnabled: boolean;
|
||||||
isFormattingFlagEnabled: boolean;
|
|
||||||
isFormattingSpoilersFlagEnabled: boolean;
|
|
||||||
isGroupV1AndDisabled?: boolean;
|
isGroupV1AndDisabled?: boolean;
|
||||||
isMissingMandatoryProfileSharing?: boolean;
|
isMissingMandatoryProfileSharing?: boolean;
|
||||||
isSignalConversation?: boolean;
|
isSignalConversation?: boolean;
|
||||||
|
@ -118,7 +116,6 @@ export type OwnProps = Readonly<{
|
||||||
left?: boolean;
|
left?: boolean;
|
||||||
linkPreviewLoading: boolean;
|
linkPreviewLoading: boolean;
|
||||||
linkPreviewResult?: LinkPreviewType;
|
linkPreviewResult?: LinkPreviewType;
|
||||||
messageRequestsEnabled?: boolean;
|
|
||||||
onClearAttachments(conversationId: string): unknown;
|
onClearAttachments(conversationId: string): unknown;
|
||||||
onCloseLinkPreview(conversationId: string): unknown;
|
onCloseLinkPreview(conversationId: string): unknown;
|
||||||
platform: string;
|
platform: string;
|
||||||
|
@ -276,8 +273,6 @@ export function CompositionArea({
|
||||||
getPreferredBadge,
|
getPreferredBadge,
|
||||||
getQuotedMessage,
|
getQuotedMessage,
|
||||||
isFormattingEnabled,
|
isFormattingEnabled,
|
||||||
isFormattingFlagEnabled,
|
|
||||||
isFormattingSpoilersFlagEnabled,
|
|
||||||
onEditorStateChange,
|
onEditorStateChange,
|
||||||
onTextTooLong,
|
onTextTooLong,
|
||||||
sendCounter,
|
sendCounter,
|
||||||
|
@ -308,7 +303,6 @@ export function CompositionArea({
|
||||||
isBlocked,
|
isBlocked,
|
||||||
isMissingMandatoryProfileSharing,
|
isMissingMandatoryProfileSharing,
|
||||||
left,
|
left,
|
||||||
messageRequestsEnabled,
|
|
||||||
removalStage,
|
removalStage,
|
||||||
acceptConversation,
|
acceptConversation,
|
||||||
blockConversation,
|
blockConversation,
|
||||||
|
@ -736,9 +730,7 @@ export function CompositionArea({
|
||||||
if (
|
if (
|
||||||
isBlocked ||
|
isBlocked ||
|
||||||
areWePending ||
|
areWePending ||
|
||||||
(messageRequestsEnabled &&
|
(!acceptedMessageRequest && removalStage !== 'justNotification')
|
||||||
!acceptedMessageRequest &&
|
|
||||||
removalStage !== 'justNotification')
|
|
||||||
) {
|
) {
|
||||||
return (
|
return (
|
||||||
<MessageRequestActions
|
<MessageRequestActions
|
||||||
|
@ -867,8 +859,6 @@ export function CompositionArea({
|
||||||
imageToBlurHash={imageToBlurHash}
|
imageToBlurHash={imageToBlurHash}
|
||||||
installedPacks={installedPacks}
|
installedPacks={installedPacks}
|
||||||
isFormattingEnabled={isFormattingEnabled}
|
isFormattingEnabled={isFormattingEnabled}
|
||||||
isFormattingFlagEnabled={isFormattingFlagEnabled}
|
|
||||||
isFormattingSpoilersFlagEnabled={isFormattingSpoilersFlagEnabled}
|
|
||||||
isSending={false}
|
isSending={false}
|
||||||
onClose={() => setAttachmentToEdit(undefined)}
|
onClose={() => setAttachmentToEdit(undefined)}
|
||||||
onDone={({
|
onDone={({
|
||||||
|
@ -992,8 +982,6 @@ export function CompositionArea({
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
inputApi={inputApiRef}
|
inputApi={inputApiRef}
|
||||||
isFormattingEnabled={isFormattingEnabled}
|
isFormattingEnabled={isFormattingEnabled}
|
||||||
isFormattingFlagEnabled={isFormattingFlagEnabled}
|
|
||||||
isFormattingSpoilersFlagEnabled={isFormattingSpoilersFlagEnabled}
|
|
||||||
large={large}
|
large={large}
|
||||||
linkPreviewLoading={linkPreviewLoading}
|
linkPreviewLoading={linkPreviewLoading}
|
||||||
linkPreviewResult={linkPreviewResult}
|
linkPreviewResult={linkPreviewResult}
|
||||||
|
|
|
@ -29,14 +29,6 @@ const useProps = (overrideProps: Partial<Props> = {}): Props => ({
|
||||||
clearQuotedMessage: action('clearQuotedMessage'),
|
clearQuotedMessage: action('clearQuotedMessage'),
|
||||||
getPreferredBadge: () => undefined,
|
getPreferredBadge: () => undefined,
|
||||||
getQuotedMessage: action('getQuotedMessage'),
|
getQuotedMessage: action('getQuotedMessage'),
|
||||||
isFormattingFlagEnabled:
|
|
||||||
overrideProps.isFormattingFlagEnabled === false
|
|
||||||
? overrideProps.isFormattingFlagEnabled
|
|
||||||
: true,
|
|
||||||
isFormattingSpoilersFlagEnabled:
|
|
||||||
overrideProps.isFormattingSpoilersFlagEnabled === false
|
|
||||||
? overrideProps.isFormattingSpoilersFlagEnabled
|
|
||||||
: true,
|
|
||||||
isFormattingEnabled:
|
isFormattingEnabled:
|
||||||
overrideProps.isFormattingEnabled === false
|
overrideProps.isFormattingEnabled === false
|
||||||
? overrideProps.isFormattingEnabled
|
? overrideProps.isFormattingEnabled
|
||||||
|
@ -140,15 +132,3 @@ export function Mentions(): JSX.Element {
|
||||||
export function NoFormattingMenu(): JSX.Element {
|
export function NoFormattingMenu(): JSX.Element {
|
||||||
return <CompositionInput {...useProps({ isFormattingEnabled: false })} />;
|
return <CompositionInput {...useProps({ isFormattingEnabled: false })} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function NoFormattingFlag(): JSX.Element {
|
|
||||||
return <CompositionInput {...useProps({ isFormattingFlagEnabled: false })} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function NoSpoilerFormattingFlag(): JSX.Element {
|
|
||||||
return (
|
|
||||||
<CompositionInput
|
|
||||||
{...useProps({ isFormattingSpoilersFlagEnabled: false })}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
|
@ -100,8 +100,6 @@ export type Props = Readonly<{
|
||||||
large?: boolean;
|
large?: boolean;
|
||||||
inputApi?: React.MutableRefObject<InputApi | undefined>;
|
inputApi?: React.MutableRefObject<InputApi | undefined>;
|
||||||
isFormattingEnabled: boolean;
|
isFormattingEnabled: boolean;
|
||||||
isFormattingFlagEnabled: boolean;
|
|
||||||
isFormattingSpoilersFlagEnabled: boolean;
|
|
||||||
sendCounter: number;
|
sendCounter: number;
|
||||||
skinTone?: EmojiPickDataType['skinTone'];
|
skinTone?: EmojiPickDataType['skinTone'];
|
||||||
draftText?: string;
|
draftText?: string;
|
||||||
|
@ -155,8 +153,6 @@ export function CompositionInput(props: Props): React.ReactElement {
|
||||||
i18n,
|
i18n,
|
||||||
inputApi,
|
inputApi,
|
||||||
isFormattingEnabled,
|
isFormattingEnabled,
|
||||||
isFormattingFlagEnabled,
|
|
||||||
isFormattingSpoilersFlagEnabled,
|
|
||||||
large,
|
large,
|
||||||
linkPreviewLoading,
|
linkPreviewLoading,
|
||||||
linkPreviewResult,
|
linkPreviewResult,
|
||||||
|
@ -250,15 +246,6 @@ export function CompositionInput(props: Props): React.ReactElement {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (BodyRange.isFormatting(range)) {
|
if (BodyRange.isFormatting(range)) {
|
||||||
if (!isFormattingFlagEnabled) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
range.style === BodyRange.Style.SPOILER &&
|
|
||||||
!isFormattingSpoilersFlagEnabled
|
|
||||||
) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
throw missingCaseError(range);
|
throw missingCaseError(range);
|
||||||
|
@ -395,54 +382,27 @@ export function CompositionInput(props: Props): React.ReactElement {
|
||||||
isFormattingEnabled,
|
isFormattingEnabled,
|
||||||
isFormattingEnabled
|
isFormattingEnabled
|
||||||
);
|
);
|
||||||
const previousFormattingFlagEnabled = usePrevious(
|
|
||||||
isFormattingFlagEnabled,
|
|
||||||
isFormattingFlagEnabled
|
|
||||||
);
|
|
||||||
const previousFormattingSpoilersFlagEnabled = usePrevious(
|
|
||||||
isFormattingSpoilersFlagEnabled,
|
|
||||||
isFormattingSpoilersFlagEnabled
|
|
||||||
);
|
|
||||||
const previousIsMouseDown = usePrevious(isMouseDown, isMouseDown);
|
const previousIsMouseDown = usePrevious(isMouseDown, isMouseDown);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const formattingChanged =
|
const formattingChanged =
|
||||||
typeof previousFormattingEnabled === 'boolean' &&
|
typeof previousFormattingEnabled === 'boolean' &&
|
||||||
previousFormattingEnabled !== isFormattingEnabled;
|
previousFormattingEnabled !== isFormattingEnabled;
|
||||||
const flagChanged =
|
|
||||||
typeof previousFormattingFlagEnabled === 'boolean' &&
|
|
||||||
previousFormattingFlagEnabled !== isFormattingFlagEnabled;
|
|
||||||
const spoilersFlagChanged =
|
|
||||||
typeof previousFormattingSpoilersFlagEnabled === 'boolean' &&
|
|
||||||
previousFormattingSpoilersFlagEnabled !== isFormattingSpoilersFlagEnabled;
|
|
||||||
const mouseDownChanged = previousIsMouseDown !== isMouseDown;
|
const mouseDownChanged = previousIsMouseDown !== isMouseDown;
|
||||||
|
|
||||||
const quill = quillRef.current;
|
const quill = quillRef.current;
|
||||||
const changed =
|
const changed = formattingChanged || mouseDownChanged;
|
||||||
formattingChanged ||
|
|
||||||
flagChanged ||
|
|
||||||
spoilersFlagChanged ||
|
|
||||||
mouseDownChanged;
|
|
||||||
if (quill && changed) {
|
if (quill && changed) {
|
||||||
quill.getModule('formattingMenu').updateOptions({
|
quill.getModule('formattingMenu').updateOptions({
|
||||||
isMenuEnabled: isFormattingEnabled,
|
isMenuEnabled: isFormattingEnabled,
|
||||||
isMouseDown,
|
isMouseDown,
|
||||||
isEnabled: isFormattingFlagEnabled,
|
|
||||||
isSpoilersEnabled: isFormattingSpoilersFlagEnabled,
|
|
||||||
});
|
|
||||||
quill.options.formats = getQuillFormats({
|
|
||||||
isFormattingFlagEnabled,
|
|
||||||
isFormattingSpoilersFlagEnabled,
|
|
||||||
});
|
});
|
||||||
|
quill.options.formats = getQuillFormats();
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
isFormattingEnabled,
|
isFormattingEnabled,
|
||||||
isFormattingFlagEnabled,
|
|
||||||
isFormattingSpoilersFlagEnabled,
|
|
||||||
isMouseDown,
|
isMouseDown,
|
||||||
previousFormattingEnabled,
|
previousFormattingEnabled,
|
||||||
previousFormattingFlagEnabled,
|
|
||||||
previousFormattingSpoilersFlagEnabled,
|
|
||||||
previousIsMouseDown,
|
previousIsMouseDown,
|
||||||
quillRef,
|
quillRef,
|
||||||
]);
|
]);
|
||||||
|
@ -772,8 +732,6 @@ export function CompositionInput(props: Props): React.ReactElement {
|
||||||
formattingMenu: {
|
formattingMenu: {
|
||||||
i18n,
|
i18n,
|
||||||
isMenuEnabled: isFormattingEnabled,
|
isMenuEnabled: isFormattingEnabled,
|
||||||
isEnabled: isFormattingFlagEnabled,
|
|
||||||
isSpoilersEnabled: isFormattingSpoilersFlagEnabled,
|
|
||||||
platform,
|
platform,
|
||||||
setFormattingChooserElement,
|
setFormattingChooserElement,
|
||||||
},
|
},
|
||||||
|
@ -788,10 +746,7 @@ export function CompositionInput(props: Props): React.ReactElement {
|
||||||
theme,
|
theme,
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
formats={getQuillFormats({
|
formats={getQuillFormats()}
|
||||||
isFormattingFlagEnabled,
|
|
||||||
isFormattingSpoilersFlagEnabled,
|
|
||||||
})}
|
|
||||||
placeholder={placeholder || i18n('icu:sendMessage')}
|
placeholder={placeholder || i18n('icu:sendMessage')}
|
||||||
readOnly={disabled}
|
readOnly={disabled}
|
||||||
ref={element => {
|
ref={element => {
|
||||||
|
@ -951,30 +906,17 @@ export function CompositionInput(props: Props): React.ReactElement {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getQuillFormats({
|
function getQuillFormats(): Array<string> {
|
||||||
isFormattingFlagEnabled,
|
|
||||||
isFormattingSpoilersFlagEnabled,
|
|
||||||
}: {
|
|
||||||
isFormattingFlagEnabled: boolean;
|
|
||||||
isFormattingSpoilersFlagEnabled: boolean;
|
|
||||||
}): Array<string> {
|
|
||||||
return [
|
return [
|
||||||
// For image replacement (local-only)
|
// For image replacement (local-only)
|
||||||
'emoji',
|
'emoji',
|
||||||
// @mentions
|
// @mentions
|
||||||
'mention',
|
'mention',
|
||||||
...(isFormattingFlagEnabled
|
QuillFormattingStyle.spoiler,
|
||||||
? [
|
QuillFormattingStyle.monospace,
|
||||||
// Custom
|
// Built-in
|
||||||
...(isFormattingSpoilersFlagEnabled
|
QuillFormattingStyle.bold,
|
||||||
? [QuillFormattingStyle.spoiler]
|
QuillFormattingStyle.italic,
|
||||||
: []),
|
QuillFormattingStyle.strike,
|
||||||
QuillFormattingStyle.monospace,
|
|
||||||
// Built-in
|
|
||||||
QuillFormattingStyle.bold,
|
|
||||||
QuillFormattingStyle.italic,
|
|
||||||
QuillFormattingStyle.strike,
|
|
||||||
]
|
|
||||||
: []),
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,8 +22,6 @@ export type CompositionTextAreaProps = {
|
||||||
bodyRanges?: HydratedBodyRangesType;
|
bodyRanges?: HydratedBodyRangesType;
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
isFormattingEnabled: boolean;
|
isFormattingEnabled: boolean;
|
||||||
isFormattingFlagEnabled: boolean;
|
|
||||||
isFormattingSpoilersFlagEnabled: boolean;
|
|
||||||
maxLength?: number;
|
maxLength?: number;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
whenToShowRemainingCount?: number;
|
whenToShowRemainingCount?: number;
|
||||||
|
@ -61,8 +59,6 @@ export function CompositionTextArea({
|
||||||
getPreferredBadge,
|
getPreferredBadge,
|
||||||
i18n,
|
i18n,
|
||||||
isFormattingEnabled,
|
isFormattingEnabled,
|
||||||
isFormattingFlagEnabled,
|
|
||||||
isFormattingSpoilersFlagEnabled,
|
|
||||||
maxLength,
|
maxLength,
|
||||||
onChange,
|
onChange,
|
||||||
onPickEmoji,
|
onPickEmoji,
|
||||||
|
@ -144,8 +140,6 @@ export function CompositionTextArea({
|
||||||
getQuotedMessage={noop}
|
getQuotedMessage={noop}
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
isFormattingEnabled={isFormattingEnabled}
|
isFormattingEnabled={isFormattingEnabled}
|
||||||
isFormattingFlagEnabled={isFormattingFlagEnabled}
|
|
||||||
isFormattingSpoilersFlagEnabled={isFormattingSpoilersFlagEnabled}
|
|
||||||
inputApi={inputApiRef}
|
inputApi={inputApiRef}
|
||||||
large
|
large
|
||||||
moduleClassName="CompositionTextArea__input"
|
moduleClassName="CompositionTextArea__input"
|
||||||
|
|
|
@ -59,8 +59,6 @@ const useProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
||||||
getPreferredBadge={() => undefined}
|
getPreferredBadge={() => undefined}
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
isFormattingEnabled
|
isFormattingEnabled
|
||||||
isFormattingFlagEnabled
|
|
||||||
isFormattingSpoilersFlagEnabled
|
|
||||||
onPickEmoji={action('onPickEmoji')}
|
onPickEmoji={action('onPickEmoji')}
|
||||||
onSetSkinTone={action('onSetSkinTone')}
|
onSetSkinTone={action('onSetSkinTone')}
|
||||||
onTextTooLong={action('onTextTooLong')}
|
onTextTooLong={action('onTextTooLong')}
|
||||||
|
|
|
@ -27,8 +27,6 @@ export default {
|
||||||
imageSrc: IMAGE_2,
|
imageSrc: IMAGE_2,
|
||||||
installedPacks,
|
installedPacks,
|
||||||
isFormattingEnabled: true,
|
isFormattingEnabled: true,
|
||||||
isFormattingFlagEnabled: true,
|
|
||||||
isFormattingSpoilersFlagEnabled: true,
|
|
||||||
isSending: false,
|
isSending: false,
|
||||||
onClose: action('onClose'),
|
onClose: action('onClose'),
|
||||||
onDone: action('onDone'),
|
onDone: action('onDone'),
|
||||||
|
|
|
@ -86,8 +86,6 @@ export type PropsType = {
|
||||||
| 'draftBodyRanges'
|
| 'draftBodyRanges'
|
||||||
| 'getPreferredBadge'
|
| 'getPreferredBadge'
|
||||||
| 'isFormattingEnabled'
|
| 'isFormattingEnabled'
|
||||||
| 'isFormattingFlagEnabled'
|
|
||||||
| 'isFormattingSpoilersFlagEnabled'
|
|
||||||
| 'onPickEmoji'
|
| 'onPickEmoji'
|
||||||
| 'onTextTooLong'
|
| 'onTextTooLong'
|
||||||
| 'platform'
|
| 'platform'
|
||||||
|
@ -156,8 +154,6 @@ export function MediaEditor({
|
||||||
draftBodyRanges,
|
draftBodyRanges,
|
||||||
getPreferredBadge,
|
getPreferredBadge,
|
||||||
isFormattingEnabled,
|
isFormattingEnabled,
|
||||||
isFormattingFlagEnabled,
|
|
||||||
isFormattingSpoilersFlagEnabled,
|
|
||||||
onPickEmoji,
|
onPickEmoji,
|
||||||
onTextTooLong,
|
onTextTooLong,
|
||||||
platform,
|
platform,
|
||||||
|
@ -1306,10 +1302,6 @@ export function MediaEditor({
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
inputApi={inputApiRef}
|
inputApi={inputApiRef}
|
||||||
isFormattingEnabled={isFormattingEnabled}
|
isFormattingEnabled={isFormattingEnabled}
|
||||||
isFormattingFlagEnabled={isFormattingFlagEnabled}
|
|
||||||
isFormattingSpoilersFlagEnabled={
|
|
||||||
isFormattingSpoilersFlagEnabled
|
|
||||||
}
|
|
||||||
moduleClassName="StoryViewsNRepliesModal__input"
|
moduleClassName="StoryViewsNRepliesModal__input"
|
||||||
onCloseLinkPreview={noop}
|
onCloseLinkPreview={noop}
|
||||||
onEditorStateChange={({ bodyRanges, messageText }) => {
|
onEditorStateChange={({ bodyRanges, messageText }) => {
|
||||||
|
|
|
@ -101,7 +101,6 @@ export default {
|
||||||
initialSpellCheckSetting: true,
|
initialSpellCheckSetting: true,
|
||||||
isAutoDownloadUpdatesSupported: true,
|
isAutoDownloadUpdatesSupported: true,
|
||||||
isAutoLaunchSupported: true,
|
isAutoLaunchSupported: true,
|
||||||
isFormattingFlagEnabled: true,
|
|
||||||
isHideMenuBarSupported: true,
|
isHideMenuBarSupported: true,
|
||||||
isNotificationAttentionSupported: true,
|
isNotificationAttentionSupported: true,
|
||||||
isPhoneNumberSharingSupported: true,
|
isPhoneNumberSharingSupported: true,
|
||||||
|
@ -117,7 +116,6 @@ export default {
|
||||||
'dfbe6effe70b0611ba0fdc2a9ea3f39f6cb110e6687948f7e5f016c111b7329c',
|
'dfbe6effe70b0611ba0fdc2a9ea3f39f6cb110e6687948f7e5f016c111b7329c',
|
||||||
selectedMicrophone: availableMicrophones[0],
|
selectedMicrophone: availableMicrophones[0],
|
||||||
selectedSpeaker: availableSpeakers[1],
|
selectedSpeaker: availableSpeakers[1],
|
||||||
shouldShowStoriesSettings: true,
|
|
||||||
sentMediaQualitySetting: 'standard',
|
sentMediaQualitySetting: 'standard',
|
||||||
themeSetting: 'system',
|
themeSetting: 'system',
|
||||||
universalExpireTimer: DurationInSeconds.HOUR,
|
universalExpireTimer: DurationInSeconds.HOUR,
|
||||||
|
@ -216,8 +214,3 @@ PNPDiscoverabilityDisabled.args = {
|
||||||
whoCanFindMe: PhoneNumberDiscoverability.NotDiscoverable,
|
whoCanFindMe: PhoneNumberDiscoverability.NotDiscoverable,
|
||||||
isPhoneNumberSharingSupported: true,
|
isPhoneNumberSharingSupported: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FormattingDisabled = Template.bind({});
|
|
||||||
FormattingDisabled.args = {
|
|
||||||
isFormattingFlagEnabled: false,
|
|
||||||
};
|
|
||||||
|
|
|
@ -117,10 +117,6 @@ export type PropsDataType = {
|
||||||
// Other props
|
// Other props
|
||||||
hasCustomTitleBar: boolean;
|
hasCustomTitleBar: boolean;
|
||||||
initialSpellCheckSetting: boolean;
|
initialSpellCheckSetting: boolean;
|
||||||
shouldShowStoriesSettings: boolean;
|
|
||||||
|
|
||||||
// Feature flags
|
|
||||||
isFormattingFlagEnabled: boolean;
|
|
||||||
|
|
||||||
// Limited support features
|
// Limited support features
|
||||||
isAutoDownloadUpdatesSupported: boolean;
|
isAutoDownloadUpdatesSupported: boolean;
|
||||||
|
@ -286,7 +282,6 @@ export function Preferences({
|
||||||
initialSpellCheckSetting,
|
initialSpellCheckSetting,
|
||||||
isAutoDownloadUpdatesSupported,
|
isAutoDownloadUpdatesSupported,
|
||||||
isAutoLaunchSupported,
|
isAutoLaunchSupported,
|
||||||
isFormattingFlagEnabled,
|
|
||||||
isHideMenuBarSupported,
|
isHideMenuBarSupported,
|
||||||
isPhoneNumberSharingSupported,
|
isPhoneNumberSharingSupported,
|
||||||
isNotificationAttentionSupported,
|
isNotificationAttentionSupported,
|
||||||
|
@ -339,7 +334,6 @@ export function Preferences({
|
||||||
selectedSpeaker,
|
selectedSpeaker,
|
||||||
sentMediaQualitySetting,
|
sentMediaQualitySetting,
|
||||||
setGlobalDefaultConversationColor,
|
setGlobalDefaultConversationColor,
|
||||||
shouldShowStoriesSettings,
|
|
||||||
localeOverride,
|
localeOverride,
|
||||||
themeSetting,
|
themeSetting,
|
||||||
universalExpireTimer = DurationInSeconds.ZERO,
|
universalExpireTimer = DurationInSeconds.ZERO,
|
||||||
|
@ -846,15 +840,13 @@ export function Preferences({
|
||||||
name="spellcheck"
|
name="spellcheck"
|
||||||
onChange={onSpellCheckChange}
|
onChange={onSpellCheckChange}
|
||||||
/>
|
/>
|
||||||
{isFormattingFlagEnabled && (
|
<Checkbox
|
||||||
<Checkbox
|
checked={hasTextFormatting}
|
||||||
checked={hasTextFormatting}
|
label={i18n('icu:textFormattingDescription')}
|
||||||
label={i18n('icu:textFormattingDescription')}
|
moduleClassName="Preferences__checkbox"
|
||||||
moduleClassName="Preferences__checkbox"
|
name="textFormatting"
|
||||||
name="textFormatting"
|
onChange={onTextFormattingChange}
|
||||||
onChange={onTextFormattingChange}
|
/>
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<Checkbox
|
<Checkbox
|
||||||
checked={hasLinkPreviews}
|
checked={hasLinkPreviews}
|
||||||
description={i18n('icu:Preferences__link-previews--description')}
|
description={i18n('icu:Preferences__link-previews--description')}
|
||||||
|
@ -1287,38 +1279,36 @@ export function Preferences({
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</SettingsRow>
|
</SettingsRow>
|
||||||
{shouldShowStoriesSettings && (
|
<SettingsRow title={i18n('icu:Stories__title')}>
|
||||||
<SettingsRow title={i18n('icu:Stories__title')}>
|
<Control
|
||||||
<Control
|
left={
|
||||||
left={
|
<label htmlFor={storiesId}>
|
||||||
<label htmlFor={storiesId}>
|
<div>{i18n('icu:Stories__settings-toggle--title')}</div>
|
||||||
<div>{i18n('icu:Stories__settings-toggle--title')}</div>
|
<div className="Preferences__description">
|
||||||
<div className="Preferences__description">
|
{i18n('icu:Stories__settings-toggle--description')}
|
||||||
{i18n('icu:Stories__settings-toggle--description')}
|
</div>
|
||||||
</div>
|
</label>
|
||||||
</label>
|
}
|
||||||
}
|
right={
|
||||||
right={
|
hasStoriesDisabled ? (
|
||||||
hasStoriesDisabled ? (
|
<Button
|
||||||
<Button
|
onClick={() => onHasStoriesDisabledChanged(false)}
|
||||||
onClick={() => onHasStoriesDisabledChanged(false)}
|
variant={ButtonVariant.Secondary}
|
||||||
variant={ButtonVariant.Secondary}
|
>
|
||||||
>
|
{i18n('icu:Preferences__turn-stories-on')}
|
||||||
{i18n('icu:Preferences__turn-stories-on')}
|
</Button>
|
||||||
</Button>
|
) : (
|
||||||
) : (
|
<Button
|
||||||
<Button
|
className="Preferences__stories-off"
|
||||||
className="Preferences__stories-off"
|
onClick={() => setConfirmStoriesOff(true)}
|
||||||
onClick={() => setConfirmStoriesOff(true)}
|
variant={ButtonVariant.SecondaryDestructive}
|
||||||
variant={ButtonVariant.SecondaryDestructive}
|
>
|
||||||
>
|
{i18n('icu:Preferences__turn-stories-off')}
|
||||||
{i18n('icu:Preferences__turn-stories-off')}
|
</Button>
|
||||||
</Button>
|
)
|
||||||
)
|
}
|
||||||
}
|
/>
|
||||||
/>
|
</SettingsRow>
|
||||||
</SettingsRow>
|
|
||||||
)}
|
|
||||||
<SettingsRow>
|
<SettingsRow>
|
||||||
<Control
|
<Control
|
||||||
left={
|
left={
|
||||||
|
|
|
@ -18,14 +18,6 @@ export default {
|
||||||
const createProps = (overrideProps: Partial<Props> = {}): Props => ({
|
const createProps = (overrideProps: Partial<Props> = {}): Props => ({
|
||||||
i18n,
|
i18n,
|
||||||
close: action('close'),
|
close: action('close'),
|
||||||
isFormattingFlagEnabled:
|
|
||||||
overrideProps.isFormattingFlagEnabled === false
|
|
||||||
? overrideProps.isFormattingFlagEnabled
|
|
||||||
: true,
|
|
||||||
isFormattingSpoilersFlagEnabled:
|
|
||||||
overrideProps.isFormattingSpoilersFlagEnabled === false
|
|
||||||
? overrideProps.isFormattingSpoilersFlagEnabled
|
|
||||||
: true,
|
|
||||||
hasInstalledStickers: overrideProps.hasInstalledStickers === true || false,
|
hasInstalledStickers: overrideProps.hasInstalledStickers === true || false,
|
||||||
platform: overrideProps.platform || 'other',
|
platform: overrideProps.platform || 'other',
|
||||||
});
|
});
|
||||||
|
@ -44,13 +36,3 @@ export function HasStickers(): JSX.Element {
|
||||||
const props = createProps({ hasInstalledStickers: true });
|
const props = createProps({ hasInstalledStickers: true });
|
||||||
return <ShortcutGuide {...props} />;
|
return <ShortcutGuide {...props} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function NoFormatting(): JSX.Element {
|
|
||||||
const props = createProps({ isFormattingFlagEnabled: false });
|
|
||||||
return <ShortcutGuide {...props} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function NoSpoilerFormatting(): JSX.Element {
|
|
||||||
const props = createProps({ isFormattingSpoilersFlagEnabled: false });
|
|
||||||
return <ShortcutGuide {...props} />;
|
|
||||||
}
|
|
||||||
|
|
|
@ -8,8 +8,6 @@ import type { LocalizerType } from '../types/Util';
|
||||||
|
|
||||||
export type Props = {
|
export type Props = {
|
||||||
hasInstalledStickers: boolean;
|
hasInstalledStickers: boolean;
|
||||||
isFormattingFlagEnabled: boolean;
|
|
||||||
isFormattingSpoilersFlagEnabled: boolean;
|
|
||||||
platform: string;
|
platform: string;
|
||||||
readonly close: () => unknown;
|
readonly close: () => unknown;
|
||||||
readonly i18n: LocalizerType;
|
readonly i18n: LocalizerType;
|
||||||
|
@ -239,11 +237,7 @@ function getMessageShortcuts(i18n: LocalizerType): Array<ShortcutType> {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
function getComposerShortcuts(
|
function getComposerShortcuts(i18n: LocalizerType): Array<ShortcutType> {
|
||||||
i18n: LocalizerType,
|
|
||||||
isFormattingFlagEnabled: boolean,
|
|
||||||
isFormattingSpoilersFlagEnabled: boolean
|
|
||||||
): Array<ShortcutType> {
|
|
||||||
const shortcuts: Array<ShortcutType> = [
|
const shortcuts: Array<ShortcutType> = [
|
||||||
{
|
{
|
||||||
id: 'Keyboard--add-newline',
|
id: 'Keyboard--add-newline',
|
||||||
|
@ -280,38 +274,32 @@ function getComposerShortcuts(
|
||||||
description: i18n('icu:Keyboard--edit-last-message'),
|
description: i18n('icu:Keyboard--edit-last-message'),
|
||||||
keys: [['↑']],
|
keys: [['↑']],
|
||||||
},
|
},
|
||||||
];
|
{
|
||||||
|
|
||||||
if (isFormattingFlagEnabled) {
|
|
||||||
shortcuts.push({
|
|
||||||
id: 'Keyboard--composer--bold',
|
id: 'Keyboard--composer--bold',
|
||||||
description: i18n('icu:Keyboard--composer--bold'),
|
description: i18n('icu:Keyboard--composer--bold'),
|
||||||
keys: [['commandOrCtrl', 'B']],
|
keys: [['commandOrCtrl', 'B']],
|
||||||
});
|
},
|
||||||
shortcuts.push({
|
{
|
||||||
id: 'Keyboard--composer--italic',
|
id: 'Keyboard--composer--italic',
|
||||||
description: i18n('icu:Keyboard--composer--italic'),
|
description: i18n('icu:Keyboard--composer--italic'),
|
||||||
keys: [['commandOrCtrl', 'I']],
|
keys: [['commandOrCtrl', 'I']],
|
||||||
});
|
},
|
||||||
shortcuts.push({
|
{
|
||||||
id: 'Keyboard--composer--strikethrough',
|
id: 'Keyboard--composer--strikethrough',
|
||||||
description: i18n('icu:Keyboard--composer--strikethrough'),
|
description: i18n('icu:Keyboard--composer--strikethrough'),
|
||||||
keys: [['commandOrCtrl', 'shift', 'X']],
|
keys: [['commandOrCtrl', 'shift', 'X']],
|
||||||
});
|
},
|
||||||
shortcuts.push({
|
{
|
||||||
id: 'Keyboard--composer--monospace',
|
id: 'Keyboard--composer--monospace',
|
||||||
description: i18n('icu:Keyboard--composer--monospace'),
|
description: i18n('icu:Keyboard--composer--monospace'),
|
||||||
keys: [['commandOrCtrl', 'E']],
|
keys: [['commandOrCtrl', 'E']],
|
||||||
});
|
},
|
||||||
|
{
|
||||||
if (isFormattingSpoilersFlagEnabled) {
|
id: 'Keyboard--composer--spoiler',
|
||||||
shortcuts.push({
|
description: i18n('icu:Keyboard--composer--spoiler'),
|
||||||
id: 'Keyboard--composer--spoiler',
|
keys: [['commandOrCtrl', 'shift', 'B']],
|
||||||
description: i18n('icu:Keyboard--composer--spoiler'),
|
},
|
||||||
keys: [['commandOrCtrl', 'shift', 'B']],
|
];
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return shortcuts;
|
return shortcuts;
|
||||||
}
|
}
|
||||||
|
@ -362,14 +350,7 @@ function getCallingShortcuts(i18n: LocalizerType): Array<ShortcutType> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ShortcutGuide(props: Props): JSX.Element {
|
export function ShortcutGuide(props: Props): JSX.Element {
|
||||||
const {
|
const { i18n, close, hasInstalledStickers, platform } = props;
|
||||||
i18n,
|
|
||||||
close,
|
|
||||||
hasInstalledStickers,
|
|
||||||
isFormattingFlagEnabled,
|
|
||||||
isFormattingSpoilersFlagEnabled,
|
|
||||||
platform,
|
|
||||||
} = props;
|
|
||||||
const isMacOS = platform === 'darwin';
|
const isMacOS = platform === 'darwin';
|
||||||
|
|
||||||
// Restore focus on teardown
|
// Restore focus on teardown
|
||||||
|
@ -427,11 +408,7 @@ export function ShortcutGuide(props: Props): JSX.Element {
|
||||||
{i18n('icu:Keyboard--composer-header')}
|
{i18n('icu:Keyboard--composer-header')}
|
||||||
</div>
|
</div>
|
||||||
<div className="module-shortcut-guide__section-list">
|
<div className="module-shortcut-guide__section-list">
|
||||||
{getComposerShortcuts(
|
{getComposerShortcuts(i18n).map((shortcut, index) =>
|
||||||
i18n,
|
|
||||||
isFormattingFlagEnabled,
|
|
||||||
isFormattingSpoilersFlagEnabled
|
|
||||||
).map((shortcut, index) =>
|
|
||||||
renderShortcut(shortcut, index, isMacOS, i18n)
|
renderShortcut(shortcut, index, isMacOS, i18n)
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -8,8 +8,6 @@ import { ShortcutGuide } from './ShortcutGuide';
|
||||||
|
|
||||||
export type PropsType = {
|
export type PropsType = {
|
||||||
hasInstalledStickers: boolean;
|
hasInstalledStickers: boolean;
|
||||||
isFormattingFlagEnabled: boolean;
|
|
||||||
isFormattingSpoilersFlagEnabled: boolean;
|
|
||||||
platform: string;
|
platform: string;
|
||||||
readonly closeShortcutGuideModal: () => unknown;
|
readonly closeShortcutGuideModal: () => unknown;
|
||||||
readonly i18n: LocalizerType;
|
readonly i18n: LocalizerType;
|
||||||
|
@ -18,14 +16,8 @@ export type PropsType = {
|
||||||
export const ShortcutGuideModal = React.memo(function ShortcutGuideModalInner(
|
export const ShortcutGuideModal = React.memo(function ShortcutGuideModalInner(
|
||||||
props: PropsType
|
props: PropsType
|
||||||
) {
|
) {
|
||||||
const {
|
const { i18n, closeShortcutGuideModal, hasInstalledStickers, platform } =
|
||||||
i18n,
|
props;
|
||||||
closeShortcutGuideModal,
|
|
||||||
hasInstalledStickers,
|
|
||||||
isFormattingFlagEnabled,
|
|
||||||
isFormattingSpoilersFlagEnabled,
|
|
||||||
platform,
|
|
||||||
} = props;
|
|
||||||
const [root, setRoot] = React.useState<HTMLElement | null>(null);
|
const [root, setRoot] = React.useState<HTMLElement | null>(null);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
|
@ -45,8 +37,6 @@ export const ShortcutGuideModal = React.memo(function ShortcutGuideModalInner(
|
||||||
<ShortcutGuide
|
<ShortcutGuide
|
||||||
close={closeShortcutGuideModal}
|
close={closeShortcutGuideModal}
|
||||||
hasInstalledStickers={hasInstalledStickers}
|
hasInstalledStickers={hasInstalledStickers}
|
||||||
isFormattingFlagEnabled={isFormattingFlagEnabled}
|
|
||||||
isFormattingSpoilersFlagEnabled={isFormattingSpoilersFlagEnabled}
|
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
platform={platform}
|
platform={platform}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -96,12 +96,7 @@ export type PropsType = {
|
||||||
> &
|
> &
|
||||||
Pick<
|
Pick<
|
||||||
MediaEditorPropsType,
|
MediaEditorPropsType,
|
||||||
| 'isFormattingEnabled'
|
'isFormattingEnabled' | 'onPickEmoji' | 'onTextTooLong' | 'platform'
|
||||||
| 'isFormattingFlagEnabled'
|
|
||||||
| 'isFormattingSpoilersFlagEnabled'
|
|
||||||
| 'onPickEmoji'
|
|
||||||
| 'onTextTooLong'
|
|
||||||
| 'platform'
|
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export function StoryCreator({
|
export function StoryCreator({
|
||||||
|
@ -117,8 +112,6 @@ export function StoryCreator({
|
||||||
imageToBlurHash,
|
imageToBlurHash,
|
||||||
installedPacks,
|
installedPacks,
|
||||||
isFormattingEnabled,
|
isFormattingEnabled,
|
||||||
isFormattingFlagEnabled,
|
|
||||||
isFormattingSpoilersFlagEnabled,
|
|
||||||
isSending,
|
isSending,
|
||||||
linkPreview,
|
linkPreview,
|
||||||
me,
|
me,
|
||||||
|
@ -254,8 +247,6 @@ export function StoryCreator({
|
||||||
imageToBlurHash={imageToBlurHash}
|
imageToBlurHash={imageToBlurHash}
|
||||||
installedPacks={installedPacks}
|
installedPacks={installedPacks}
|
||||||
isFormattingEnabled={isFormattingEnabled}
|
isFormattingEnabled={isFormattingEnabled}
|
||||||
isFormattingFlagEnabled={isFormattingFlagEnabled}
|
|
||||||
isFormattingSpoilersFlagEnabled={isFormattingSpoilersFlagEnabled}
|
|
||||||
isSending={isSending}
|
isSending={isSending}
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
onDone={({
|
onDone={({
|
||||||
|
|
|
@ -87,8 +87,6 @@ export type PropsType = {
|
||||||
hasViewReceiptSetting: boolean;
|
hasViewReceiptSetting: boolean;
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
isFormattingEnabled: boolean;
|
isFormattingEnabled: boolean;
|
||||||
isFormattingFlagEnabled: boolean;
|
|
||||||
isFormattingSpoilersFlagEnabled: boolean;
|
|
||||||
isInternalUser?: boolean;
|
isInternalUser?: boolean;
|
||||||
isSignalConversation?: boolean;
|
isSignalConversation?: boolean;
|
||||||
isWindowActive: boolean;
|
isWindowActive: boolean;
|
||||||
|
@ -150,8 +148,6 @@ export function StoryViewer({
|
||||||
hasViewReceiptSetting,
|
hasViewReceiptSetting,
|
||||||
i18n,
|
i18n,
|
||||||
isFormattingEnabled,
|
isFormattingEnabled,
|
||||||
isFormattingFlagEnabled,
|
|
||||||
isFormattingSpoilersFlagEnabled,
|
|
||||||
isInternalUser,
|
isInternalUser,
|
||||||
isSignalConversation,
|
isSignalConversation,
|
||||||
isWindowActive,
|
isWindowActive,
|
||||||
|
@ -946,8 +942,6 @@ export function StoryViewer({
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
platform={platform}
|
platform={platform}
|
||||||
isFormattingEnabled={isFormattingEnabled}
|
isFormattingEnabled={isFormattingEnabled}
|
||||||
isFormattingFlagEnabled={isFormattingFlagEnabled}
|
|
||||||
isFormattingSpoilersFlagEnabled={isFormattingSpoilersFlagEnabled}
|
|
||||||
isInternalUser={isInternalUser}
|
isInternalUser={isInternalUser}
|
||||||
group={group}
|
group={group}
|
||||||
onClose={() => setCurrentViewTarget(null)}
|
onClose={() => setCurrentViewTarget(null)}
|
||||||
|
|
|
@ -91,8 +91,6 @@ export type PropsType = {
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
platform: string;
|
platform: string;
|
||||||
isFormattingEnabled: boolean;
|
isFormattingEnabled: boolean;
|
||||||
isFormattingFlagEnabled: boolean;
|
|
||||||
isFormattingSpoilersFlagEnabled: boolean;
|
|
||||||
isInternalUser?: boolean;
|
isInternalUser?: boolean;
|
||||||
onChangeViewTarget: (target: StoryViewTargetType) => unknown;
|
onChangeViewTarget: (target: StoryViewTargetType) => unknown;
|
||||||
onClose: () => unknown;
|
onClose: () => unknown;
|
||||||
|
@ -128,8 +126,6 @@ export function StoryViewsNRepliesModal({
|
||||||
i18n,
|
i18n,
|
||||||
platform,
|
platform,
|
||||||
isFormattingEnabled,
|
isFormattingEnabled,
|
||||||
isFormattingFlagEnabled,
|
|
||||||
isFormattingSpoilersFlagEnabled,
|
|
||||||
isInternalUser,
|
isInternalUser,
|
||||||
onChangeViewTarget,
|
onChangeViewTarget,
|
||||||
onClose,
|
onClose,
|
||||||
|
@ -241,8 +237,6 @@ export function StoryViewsNRepliesModal({
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
inputApi={inputApiRef}
|
inputApi={inputApiRef}
|
||||||
isFormattingEnabled={isFormattingEnabled}
|
isFormattingEnabled={isFormattingEnabled}
|
||||||
isFormattingFlagEnabled={isFormattingFlagEnabled}
|
|
||||||
isFormattingSpoilersFlagEnabled={isFormattingSpoilersFlagEnabled}
|
|
||||||
moduleClassName="StoryViewsNRepliesModal__input"
|
moduleClassName="StoryViewsNRepliesModal__input"
|
||||||
onCloseLinkPreview={noop}
|
onCloseLinkPreview={noop}
|
||||||
onEditorStateChange={({ messageText }) => {
|
onEditorStateChange={({ messageText }) => {
|
||||||
|
|
|
@ -63,8 +63,6 @@ export class SettingsChannel extends EventEmitter {
|
||||||
this.installCallback('isPrimary');
|
this.installCallback('isPrimary');
|
||||||
this.installCallback('syncRequest');
|
this.installCallback('syncRequest');
|
||||||
this.installCallback('isPhoneNumberSharingEnabled');
|
this.installCallback('isPhoneNumberSharingEnabled');
|
||||||
this.installCallback('isFormattingFlagEnabled');
|
|
||||||
this.installCallback('shouldShowStoriesSettings');
|
|
||||||
|
|
||||||
// Getters only. These are set by the primary device
|
// Getters only. These are set by the primary device
|
||||||
this.installSetting('blockedCount', { setter: false });
|
this.installSetting('blockedCount', { setter: false });
|
||||||
|
|
|
@ -129,7 +129,6 @@ import {
|
||||||
conversationQueueJobEnum,
|
conversationQueueJobEnum,
|
||||||
} from '../jobs/conversationJobQueue';
|
} from '../jobs/conversationJobQueue';
|
||||||
import type { ReactionAttributesType } from '../messageModifiers/Reactions';
|
import type { ReactionAttributesType } from '../messageModifiers/Reactions';
|
||||||
import { isAnnouncementGroupReady } from '../util/isAnnouncementGroupReady';
|
|
||||||
import { getProfile } from '../util/getProfile';
|
import { getProfile } from '../util/getProfile';
|
||||||
import { SEALED_SENDER } from '../types/SealedSender';
|
import { SEALED_SENDER } from '../types/SealedSender';
|
||||||
import { createIdenticon } from '../util/createIdenticon';
|
import { createIdenticon } from '../util/createIdenticon';
|
||||||
|
@ -3528,10 +3527,6 @@ export class ConversationModel extends window.Backbone
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isAnnouncementGroupReady()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3692,11 +3687,7 @@ export class ConversationModel extends window.Backbone
|
||||||
const { clearUnreadMetrics } = window.reduxActions.conversations;
|
const { clearUnreadMetrics } = window.reduxActions.conversations;
|
||||||
clearUnreadMetrics(this.id);
|
clearUnreadMetrics(this.id);
|
||||||
|
|
||||||
const mandatoryProfileSharingEnabled =
|
const enabledProfileSharing = Boolean(!this.get('profileSharing'));
|
||||||
window.Signal.RemoteConfig.isEnabled('desktop.mandatoryProfileSharing');
|
|
||||||
const enabledProfileSharing = Boolean(
|
|
||||||
mandatoryProfileSharingEnabled && !this.get('profileSharing')
|
|
||||||
);
|
|
||||||
const unarchivedConversation = Boolean(this.get('isArchived'));
|
const unarchivedConversation = Boolean(this.get('isArchived'));
|
||||||
|
|
||||||
log.info(
|
log.info(
|
||||||
|
|
|
@ -33,8 +33,6 @@ type FormattingPickerOptions = {
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
isMenuEnabled: boolean;
|
isMenuEnabled: boolean;
|
||||||
isMouseDown?: boolean;
|
isMouseDown?: boolean;
|
||||||
isEnabled: boolean;
|
|
||||||
isSpoilersEnabled: boolean;
|
|
||||||
platform: string;
|
platform: string;
|
||||||
setFormattingChooserElement: (element: JSX.Element | null) => void;
|
setFormattingChooserElement: (element: JSX.Element | null) => void;
|
||||||
};
|
};
|
||||||
|
@ -173,7 +171,7 @@ export class FormattingMenu {
|
||||||
}
|
}
|
||||||
|
|
||||||
onEditorChange(): void {
|
onEditorChange(): void {
|
||||||
if (!this.options.isMenuEnabled || !this.options.isEnabled) {
|
if (!this.options.isMenuEnabled) {
|
||||||
this.scheduleRemoval();
|
this.scheduleRemoval();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -281,16 +279,6 @@ export class FormattingMenu {
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleForStyle(style: QuillFormattingStyle, context?: KeyboardContext): void {
|
toggleForStyle(style: QuillFormattingStyle, context?: KeyboardContext): void {
|
||||||
if (!this.options.isEnabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
!this.options.isSpoilersEnabled &&
|
|
||||||
style === QuillFormattingStyle.spoiler
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const isEnabled = context
|
const isEnabled = context
|
||||||
? Boolean(context.format[style])
|
? Boolean(context.format[style])
|
||||||
|
@ -314,7 +302,7 @@ export class FormattingMenu {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { i18n, isSpoilersEnabled, platform } = this.options;
|
const { i18n, platform } = this.options;
|
||||||
const metaKey = getMetaKey(platform, i18n);
|
const metaKey = getMetaKey(platform, i18n);
|
||||||
const shiftKey = i18n('icu:Keyboard--Key--shift');
|
const shiftKey = i18n('icu:Keyboard--Key--shift');
|
||||||
|
|
||||||
|
@ -395,20 +383,18 @@ export class FormattingMenu {
|
||||||
style={QuillFormattingStyle.monospace}
|
style={QuillFormattingStyle.monospace}
|
||||||
toggleForStyle={toggleForStyle}
|
toggleForStyle={toggleForStyle}
|
||||||
/>
|
/>
|
||||||
{isSpoilersEnabled ? (
|
<FormattingButton
|
||||||
<FormattingButton
|
hasLongHovered={hasLongHovered}
|
||||||
hasLongHovered={hasLongHovered}
|
isActive={isStyleEnabledInSelection(
|
||||||
isActive={isStyleEnabledInSelection(
|
QuillFormattingStyle.spoiler
|
||||||
QuillFormattingStyle.spoiler
|
)}
|
||||||
)}
|
onLongHover={onLongHover}
|
||||||
onLongHover={onLongHover}
|
popupGuideShortcut={`${metaKey} + ${shiftKey} + ${SPOILER_CHAR}`}
|
||||||
popupGuideShortcut={`${metaKey} + ${shiftKey} + ${SPOILER_CHAR}`}
|
popupGuideText={i18n('icu:FormatMenu--guide--spoiler')}
|
||||||
popupGuideText={i18n('icu:FormatMenu--guide--spoiler')}
|
label={i18n('icu:Keyboard--composer--spoiler')}
|
||||||
label={i18n('icu:Keyboard--composer--spoiler')}
|
style={QuillFormattingStyle.spoiler}
|
||||||
style={QuillFormattingStyle.spoiler}
|
toggleForStyle={toggleForStyle}
|
||||||
toggleForStyle={toggleForStyle}
|
/>
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -40,7 +40,6 @@ import {
|
||||||
} from '../../types/Calling';
|
} from '../../types/Calling';
|
||||||
import { callingTones } from '../../util/callingTones';
|
import { callingTones } from '../../util/callingTones';
|
||||||
import { requestCameraPermissions } from '../../util/callingPermissions';
|
import { requestCameraPermissions } from '../../util/callingPermissions';
|
||||||
import { isGroupCallOutboundRingEnabled } from '../../util/isGroupCallOutboundRingEnabled';
|
|
||||||
import { sleep } from '../../util/sleep';
|
import { sleep } from '../../util/sleep';
|
||||||
import { LatestQueue } from '../../util/LatestQueue';
|
import { LatestQueue } from '../../util/LatestQueue';
|
||||||
import type { AciString } from '../../types/ServiceId';
|
import type { AciString } from '../../types/ServiceId';
|
||||||
|
@ -1573,7 +1572,7 @@ function startCall(
|
||||||
|
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const { activeCallState } = state.calling;
|
const { activeCallState } = state.calling;
|
||||||
if (isGroupCallOutboundRingEnabled() && activeCallState?.outgoingRing) {
|
if (activeCallState?.outgoingRing) {
|
||||||
const conversation = getOwn(
|
const conversation = getOwn(
|
||||||
state.conversations.conversationLookup,
|
state.conversations.conversationLookup,
|
||||||
activeCallState.conversationId
|
activeCallState.conversationId
|
||||||
|
@ -1777,7 +1776,6 @@ export function reducer(
|
||||||
...ringState,
|
...ringState,
|
||||||
};
|
};
|
||||||
outgoingRing =
|
outgoingRing =
|
||||||
isGroupCallOutboundRingEnabled() &&
|
|
||||||
!ringState.ringId &&
|
!ringState.ringId &&
|
||||||
!call.peekInfo?.acis.length &&
|
!call.peekInfo?.acis.length &&
|
||||||
!call.remoteParticipants.length &&
|
!call.remoteParticipants.length &&
|
||||||
|
|
|
@ -322,7 +322,6 @@ export type ConversationType = ReadonlyDeep<
|
||||||
groupVersion?: 1 | 2;
|
groupVersion?: 1 | 2;
|
||||||
groupId?: string;
|
groupId?: string;
|
||||||
groupLink?: string;
|
groupLink?: string;
|
||||||
messageRequestsEnabled?: boolean;
|
|
||||||
acceptedMessageRequest: boolean;
|
acceptedMessageRequest: boolean;
|
||||||
secretParams?: string;
|
secretParams?: string;
|
||||||
publicParams?: string;
|
publicParams?: string;
|
||||||
|
|
|
@ -6,7 +6,6 @@ import { createSelector } from 'reselect';
|
||||||
import type { StateType } from '../reducer';
|
import type { StateType } from '../reducer';
|
||||||
import type { ComposerStateType, QuotedMessageType } from '../ducks/composer';
|
import type { ComposerStateType, QuotedMessageType } from '../ducks/composer';
|
||||||
import { getComposerStateForConversation } from '../ducks/composer';
|
import { getComposerStateForConversation } from '../ducks/composer';
|
||||||
import { getRemoteConfig, isRemoteConfigFlagEnabled } from './items';
|
|
||||||
|
|
||||||
export const getComposerState = (state: StateType): ComposerStateType =>
|
export const getComposerState = (state: StateType): ComposerStateType =>
|
||||||
state.composer;
|
state.composer;
|
||||||
|
@ -23,20 +22,3 @@ export const getQuotedMessageSelector = createSelector(
|
||||||
(conversationId: string): QuotedMessageType | undefined =>
|
(conversationId: string): QuotedMessageType | undefined =>
|
||||||
composerStateForConversationIdSelector(conversationId).quotedMessage
|
composerStateForConversationIdSelector(conversationId).quotedMessage
|
||||||
);
|
);
|
||||||
|
|
||||||
export const getIsFormattingFlagEnabled = createSelector(
|
|
||||||
getRemoteConfig,
|
|
||||||
remoteConfig => {
|
|
||||||
return isRemoteConfigFlagEnabled(remoteConfig, 'desktop.textFormatting');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
export const getIsFormattingSpoilersFlagEnabled = createSelector(
|
|
||||||
getRemoteConfig,
|
|
||||||
remoteConfig => {
|
|
||||||
return isRemoteConfigFlagEnabled(
|
|
||||||
remoteConfig,
|
|
||||||
'desktop.textFormatting.spoilerSend'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
|
@ -1054,7 +1054,6 @@ export function isMissingRequiredProfileSharing(
|
||||||
return Boolean(
|
return Boolean(
|
||||||
doesConversationRequireIt &&
|
doesConversationRequireIt &&
|
||||||
!conversation.profileSharing &&
|
!conversation.profileSharing &&
|
||||||
window.Signal.RemoteConfig.isEnabled('desktop.mandatoryProfileSharing') &&
|
|
||||||
conversation.hasMessages
|
conversation.hasMessages
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,10 +16,8 @@ import type {
|
||||||
import type { AciString } from '../../types/ServiceId';
|
import type { AciString } from '../../types/ServiceId';
|
||||||
import { DEFAULT_CONVERSATION_COLOR } from '../../types/Colors';
|
import { DEFAULT_CONVERSATION_COLOR } from '../../types/Colors';
|
||||||
import { getPreferredReactionEmoji as getPreferredReactionEmojiFromStoredValue } from '../../reactions/preferredReactionEmoji';
|
import { getPreferredReactionEmoji as getPreferredReactionEmojiFromStoredValue } from '../../reactions/preferredReactionEmoji';
|
||||||
import { isBeta } from '../../util/version';
|
|
||||||
import { DurationInSeconds } from '../../util/durations';
|
import { DurationInSeconds } from '../../util/durations';
|
||||||
import * as Bytes from '../../Bytes';
|
import * as Bytes from '../../Bytes';
|
||||||
import { getUserNumber, getUserACI } from './user';
|
|
||||||
import { contactByEncryptedUsernameRoute } from '../../util/signalRoutes';
|
import { contactByEncryptedUsernameRoute } from '../../util/signalRoutes';
|
||||||
|
|
||||||
const DEFAULT_PREFERRED_LEFT_PANE_WIDTH = 320;
|
const DEFAULT_PREFERRED_LEFT_PANE_WIDTH = 320;
|
||||||
|
@ -55,7 +53,7 @@ export const isRemoteConfigFlagEnabled = (
|
||||||
): boolean => Boolean(config[key]?.enabled);
|
): boolean => Boolean(config[key]?.enabled);
|
||||||
|
|
||||||
// See isBucketValueEnabled in RemoteConfig.ts
|
// See isBucketValueEnabled in RemoteConfig.ts
|
||||||
const isRemoteConfigBucketEnabled = (
|
export const isRemoteConfigBucketEnabled = (
|
||||||
config: Readonly<ConfigMapType>,
|
config: Readonly<ConfigMapType>,
|
||||||
name: ConfigKeyType,
|
name: ConfigKeyType,
|
||||||
e164: string | undefined,
|
e164: string | undefined,
|
||||||
|
@ -138,38 +136,7 @@ export const isInternalUser = createSelector(
|
||||||
// Note: ts/util/stories is the other place this check is done
|
// Note: ts/util/stories is the other place this check is done
|
||||||
export const getStoriesEnabled = createSelector(
|
export const getStoriesEnabled = createSelector(
|
||||||
getItems,
|
getItems,
|
||||||
getRemoteConfig,
|
(state: ItemsStateType): boolean => !state.hasStoriesDisabled
|
||||||
getUserNumber,
|
|
||||||
getUserACI,
|
|
||||||
(
|
|
||||||
state: ItemsStateType,
|
|
||||||
remoteConfig: ConfigMapType,
|
|
||||||
e164: string | undefined,
|
|
||||||
aci: AciString | undefined
|
|
||||||
): boolean => {
|
|
||||||
if (state.hasStoriesDisabled) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
isRemoteConfigBucketEnabled(remoteConfig, 'desktop.stories2', e164, aci)
|
|
||||||
) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isRemoteConfigFlagEnabled(remoteConfig, 'desktop.internalUser')) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
isRemoteConfigFlagEnabled(remoteConfig, 'desktop.stories2.beta') &&
|
|
||||||
isBeta(window.getVersion())
|
|
||||||
) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
export const getDefaultConversationColor = createSelector(
|
export const getDefaultConversationColor = createSelector(
|
||||||
|
|
|
@ -12,7 +12,6 @@ import { getMe, getConversationSelector } from '../selectors/conversations';
|
||||||
import { getActiveCall } from '../ducks/calling';
|
import { getActiveCall } from '../ducks/calling';
|
||||||
import type { ConversationType } from '../ducks/conversations';
|
import type { ConversationType } from '../ducks/conversations';
|
||||||
import { getIncomingCall } from '../selectors/calling';
|
import { getIncomingCall } from '../selectors/calling';
|
||||||
import { isGroupCallOutboundRingEnabled } from '../../util/isGroupCallOutboundRingEnabled';
|
|
||||||
import { isGroupCallRaiseHandEnabled } from '../../util/isGroupCallRaiseHandEnabled';
|
import { isGroupCallRaiseHandEnabled } from '../../util/isGroupCallRaiseHandEnabled';
|
||||||
import { isGroupCallReactionsEnabled } from '../../util/isGroupCallReactionsEnabled';
|
import { isGroupCallReactionsEnabled } from '../../util/isGroupCallReactionsEnabled';
|
||||||
import type {
|
import type {
|
||||||
|
@ -375,7 +374,6 @@ const mapStateToProps = (state: StateType) => {
|
||||||
getGroupCallVideoFrameSource,
|
getGroupCallVideoFrameSource,
|
||||||
getPreferredBadge: getPreferredBadgeSelector(state),
|
getPreferredBadge: getPreferredBadgeSelector(state),
|
||||||
i18n: getIntl(state),
|
i18n: getIntl(state),
|
||||||
isGroupCallOutboundRingEnabled: isGroupCallOutboundRingEnabled(),
|
|
||||||
isGroupCallRaiseHandEnabled: isGroupCallRaiseHandEnabled(),
|
isGroupCallRaiseHandEnabled: isGroupCallRaiseHandEnabled(),
|
||||||
isGroupCallReactionsEnabled: isGroupCallReactionsEnabled(),
|
isGroupCallReactionsEnabled: isGroupCallReactionsEnabled(),
|
||||||
incomingCall,
|
incomingCall,
|
||||||
|
|
|
@ -48,11 +48,7 @@ import {
|
||||||
getRecentStickers,
|
getRecentStickers,
|
||||||
} from '../selectors/stickers';
|
} from '../selectors/stickers';
|
||||||
import { isSignalConversation } from '../../util/isSignalConversation';
|
import { isSignalConversation } from '../../util/isSignalConversation';
|
||||||
import {
|
import { getComposerStateForConversationIdSelector } from '../selectors/composer';
|
||||||
getComposerStateForConversationIdSelector,
|
|
||||||
getIsFormattingFlagEnabled,
|
|
||||||
getIsFormattingSpoilersFlagEnabled,
|
|
||||||
} from '../selectors/composer';
|
|
||||||
import type { SmartCompositionRecordingProps } from './CompositionRecording';
|
import type { SmartCompositionRecordingProps } from './CompositionRecording';
|
||||||
import { SmartCompositionRecording } from './CompositionRecording';
|
import { SmartCompositionRecording } from './CompositionRecording';
|
||||||
import type { SmartCompositionRecordingDraftProps } from './CompositionRecordingDraft';
|
import type { SmartCompositionRecordingDraftProps } from './CompositionRecordingDraft';
|
||||||
|
@ -131,9 +127,6 @@ const mapStateToProps = (state: StateType, props: ExternalProps) => {
|
||||||
const selectedMessageIds = getSelectedMessageIds(state);
|
const selectedMessageIds = getSelectedMessageIds(state);
|
||||||
|
|
||||||
const isFormattingEnabled = getTextFormattingEnabled(state);
|
const isFormattingEnabled = getTextFormattingEnabled(state);
|
||||||
const isFormattingFlagEnabled = getIsFormattingFlagEnabled(state);
|
|
||||||
const isFormattingSpoilersFlagEnabled =
|
|
||||||
getIsFormattingSpoilersFlagEnabled(state);
|
|
||||||
|
|
||||||
const lastEditableMessageId = getLastEditableMessageId(state);
|
const lastEditableMessageId = getLastEditableMessageId(state);
|
||||||
|
|
||||||
|
@ -152,8 +145,6 @@ const mapStateToProps = (state: StateType, props: ExternalProps) => {
|
||||||
i18n: getIntl(state),
|
i18n: getIntl(state),
|
||||||
isDisabled,
|
isDisabled,
|
||||||
isFormattingEnabled,
|
isFormattingEnabled,
|
||||||
isFormattingFlagEnabled,
|
|
||||||
isFormattingSpoilersFlagEnabled,
|
|
||||||
lastEditableMessageId,
|
lastEditableMessageId,
|
||||||
messageCompositionId,
|
messageCompositionId,
|
||||||
platform,
|
platform,
|
||||||
|
|
|
@ -10,10 +10,6 @@ import { useActions as useEmojiActions } from '../ducks/emojis';
|
||||||
import { useItemsActions } from '../ducks/items';
|
import { useItemsActions } from '../ducks/items';
|
||||||
import { getPreferredBadgeSelector } from '../selectors/badges';
|
import { getPreferredBadgeSelector } from '../selectors/badges';
|
||||||
import { useComposerActions } from '../ducks/composer';
|
import { useComposerActions } from '../ducks/composer';
|
||||||
import {
|
|
||||||
getIsFormattingFlagEnabled,
|
|
||||||
getIsFormattingSpoilersFlagEnabled,
|
|
||||||
} from '../selectors/composer';
|
|
||||||
import { getTextFormattingEnabled } from '../selectors/items';
|
import { getTextFormattingEnabled } from '../selectors/items';
|
||||||
|
|
||||||
export type SmartCompositionTextAreaProps = Pick<
|
export type SmartCompositionTextAreaProps = Pick<
|
||||||
|
@ -42,10 +38,6 @@ export function SmartCompositionTextArea(
|
||||||
|
|
||||||
const getPreferredBadge = useSelector(getPreferredBadgeSelector);
|
const getPreferredBadge = useSelector(getPreferredBadgeSelector);
|
||||||
const isFormattingEnabled = useSelector(getTextFormattingEnabled);
|
const isFormattingEnabled = useSelector(getTextFormattingEnabled);
|
||||||
const isFormattingFlagEnabled = useSelector(getIsFormattingFlagEnabled);
|
|
||||||
const isFormattingSpoilersFlagEnabled = useSelector(
|
|
||||||
getIsFormattingSpoilersFlagEnabled
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CompositionTextArea
|
<CompositionTextArea
|
||||||
|
@ -53,8 +45,6 @@ export function SmartCompositionTextArea(
|
||||||
getPreferredBadge={getPreferredBadge}
|
getPreferredBadge={getPreferredBadge}
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
isFormattingEnabled={isFormattingEnabled}
|
isFormattingEnabled={isFormattingEnabled}
|
||||||
isFormattingFlagEnabled={isFormattingFlagEnabled}
|
|
||||||
isFormattingSpoilersFlagEnabled={isFormattingSpoilersFlagEnabled}
|
|
||||||
onPickEmoji={onPickEmoji}
|
onPickEmoji={onPickEmoji}
|
||||||
onSetSkinTone={onSetSkinTone}
|
onSetSkinTone={onSetSkinTone}
|
||||||
onTextTooLong={onTextTooLong}
|
onTextTooLong={onTextTooLong}
|
||||||
|
|
|
@ -14,10 +14,6 @@ import {
|
||||||
getKnownStickerPacks,
|
getKnownStickerPacks,
|
||||||
getReceivedStickerPacks,
|
getReceivedStickerPacks,
|
||||||
} from '../selectors/stickers';
|
} from '../selectors/stickers';
|
||||||
import {
|
|
||||||
getIsFormattingFlagEnabled,
|
|
||||||
getIsFormattingSpoilersFlagEnabled,
|
|
||||||
} from '../selectors/composer';
|
|
||||||
|
|
||||||
const mapStateToProps = (state: StateType) => {
|
const mapStateToProps = (state: StateType) => {
|
||||||
const blessedPacks = getBlessedStickerPacks(state);
|
const blessedPacks = getBlessedStickerPacks(state);
|
||||||
|
@ -25,10 +21,6 @@ const mapStateToProps = (state: StateType) => {
|
||||||
const knownPacks = getKnownStickerPacks(state);
|
const knownPacks = getKnownStickerPacks(state);
|
||||||
const receivedPacks = getReceivedStickerPacks(state);
|
const receivedPacks = getReceivedStickerPacks(state);
|
||||||
|
|
||||||
const isFormattingFlagEnabled = getIsFormattingFlagEnabled(state);
|
|
||||||
const isFormattingSpoilersFlagEnabled =
|
|
||||||
getIsFormattingSpoilersFlagEnabled(state);
|
|
||||||
|
|
||||||
const hasInstalledStickers =
|
const hasInstalledStickers =
|
||||||
countStickers({
|
countStickers({
|
||||||
knownPacks,
|
knownPacks,
|
||||||
|
@ -41,8 +33,6 @@ const mapStateToProps = (state: StateType) => {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
hasInstalledStickers,
|
hasInstalledStickers,
|
||||||
isFormattingFlagEnabled,
|
|
||||||
isFormattingSpoilersFlagEnabled,
|
|
||||||
platform,
|
platform,
|
||||||
i18n: getIntl(state),
|
i18n: getIntl(state),
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,10 +23,6 @@ import {
|
||||||
getRecentStickers,
|
getRecentStickers,
|
||||||
} from '../selectors/stickers';
|
} from '../selectors/stickers';
|
||||||
import { getAddStoryData } from '../selectors/stories';
|
import { getAddStoryData } from '../selectors/stories';
|
||||||
import {
|
|
||||||
getIsFormattingFlagEnabled,
|
|
||||||
getIsFormattingSpoilersFlagEnabled,
|
|
||||||
} from '../selectors/composer';
|
|
||||||
import { getLinkPreview } from '../selectors/linkPreviews';
|
import { getLinkPreview } from '../selectors/linkPreviews';
|
||||||
import { getPreferredBadgeSelector } from '../selectors/badges';
|
import { getPreferredBadgeSelector } from '../selectors/badges';
|
||||||
import {
|
import {
|
||||||
|
@ -108,10 +104,6 @@ export function SmartStoryCreator(): JSX.Element | null {
|
||||||
const { onUseEmoji: onPickEmoji } = useEmojisActions();
|
const { onUseEmoji: onPickEmoji } = useEmojisActions();
|
||||||
|
|
||||||
const isFormattingEnabled = useSelector(getTextFormattingEnabled);
|
const isFormattingEnabled = useSelector(getTextFormattingEnabled);
|
||||||
const isFormattingFlagEnabled = useSelector(getIsFormattingFlagEnabled);
|
|
||||||
const isFormattingSpoilersFlagEnabled = useSelector(
|
|
||||||
getIsFormattingSpoilersFlagEnabled
|
|
||||||
);
|
|
||||||
const platform = useSelector(getPlatform);
|
const platform = useSelector(getPlatform);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -128,8 +120,6 @@ export function SmartStoryCreator(): JSX.Element | null {
|
||||||
imageToBlurHash={imageToBlurHash}
|
imageToBlurHash={imageToBlurHash}
|
||||||
installedPacks={installedPacks}
|
installedPacks={installedPacks}
|
||||||
isFormattingEnabled={isFormattingEnabled}
|
isFormattingEnabled={isFormattingEnabled}
|
||||||
isFormattingFlagEnabled={isFormattingFlagEnabled}
|
|
||||||
isFormattingSpoilersFlagEnabled={isFormattingSpoilersFlagEnabled}
|
|
||||||
isSending={isSending}
|
isSending={isSending}
|
||||||
linkPreview={linkPreviewForSource(LinkPreviewSourceType.StoryCreator)}
|
linkPreview={linkPreviewForSource(LinkPreviewSourceType.StoryCreator)}
|
||||||
me={me}
|
me={me}
|
||||||
|
|
|
@ -40,10 +40,6 @@ import { useAudioPlayerActions } from '../ducks/audioPlayer';
|
||||||
import { useGlobalModalActions } from '../ducks/globalModals';
|
import { useGlobalModalActions } from '../ducks/globalModals';
|
||||||
import { useStoriesActions } from '../ducks/stories';
|
import { useStoriesActions } from '../ducks/stories';
|
||||||
import { useIsWindowActive } from '../../hooks/useIsWindowActive';
|
import { useIsWindowActive } from '../../hooks/useIsWindowActive';
|
||||||
import {
|
|
||||||
getIsFormattingFlagEnabled,
|
|
||||||
getIsFormattingSpoilersFlagEnabled,
|
|
||||||
} from '../selectors/composer';
|
|
||||||
|
|
||||||
export function SmartStoryViewer(): JSX.Element | null {
|
export function SmartStoryViewer(): JSX.Element | null {
|
||||||
const storiesActions = useStoriesActions();
|
const storiesActions = useStoriesActions();
|
||||||
|
@ -95,10 +91,6 @@ export function SmartStoryViewer(): JSX.Element | null {
|
||||||
);
|
);
|
||||||
|
|
||||||
const isFormattingEnabled = useSelector(getTextFormattingEnabled);
|
const isFormattingEnabled = useSelector(getTextFormattingEnabled);
|
||||||
const isFormattingFlagEnabled = useSelector(getIsFormattingFlagEnabled);
|
|
||||||
const isFormattingSpoilersFlagEnabled = useSelector(
|
|
||||||
getIsFormattingSpoilersFlagEnabled
|
|
||||||
);
|
|
||||||
|
|
||||||
const { pauseVoiceNotePlayer } = useAudioPlayerActions();
|
const { pauseVoiceNotePlayer } = useAudioPlayerActions();
|
||||||
|
|
||||||
|
@ -126,8 +118,6 @@ export function SmartStoryViewer(): JSX.Element | null {
|
||||||
platform={platform}
|
platform={platform}
|
||||||
isInternalUser={internalUser}
|
isInternalUser={internalUser}
|
||||||
isFormattingEnabled={isFormattingEnabled}
|
isFormattingEnabled={isFormattingEnabled}
|
||||||
isFormattingFlagEnabled={isFormattingFlagEnabled}
|
|
||||||
isFormattingSpoilersFlagEnabled={isFormattingSpoilersFlagEnabled}
|
|
||||||
isSignalConversation={isSignalConversation({
|
isSignalConversation={isSignalConversation({
|
||||||
id: conversationStory.conversationId,
|
id: conversationStory.conversationId,
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -244,10 +244,7 @@ const mapStateToProps = (state: StateType, props: ExternalProps) => {
|
||||||
'typingContactIdTimestamps',
|
'typingContactIdTimestamps',
|
||||||
]),
|
]),
|
||||||
isConversationSelected: state.conversations.selectedConversationId === id,
|
isConversationSelected: state.conversations.selectedConversationId === id,
|
||||||
isIncomingMessageRequest: Boolean(
|
isIncomingMessageRequest: Boolean(!conversation.acceptedMessageRequest),
|
||||||
conversation.messageRequestsEnabled &&
|
|
||||||
!conversation.acceptedMessageRequest
|
|
||||||
),
|
|
||||||
isSomeoneTyping: Boolean(
|
isSomeoneTyping: Boolean(
|
||||||
Object.keys(conversation.typingContactIdTimestamps ?? {}).length > 0
|
Object.keys(conversation.typingContactIdTimestamps ?? {}).length > 0
|
||||||
),
|
),
|
||||||
|
|
|
@ -11,15 +11,15 @@ import {
|
||||||
} from '../RemoteConfig';
|
} from '../RemoteConfig';
|
||||||
|
|
||||||
describe('RemoteConfig', () => {
|
describe('RemoteConfig', () => {
|
||||||
const aci = normalizeAci('15b9729c-51ea-4ddb-b516-652befe78062', 'test');
|
const aci = normalizeAci('95b9729c-51ea-4ddb-b516-652befe78062', 'test');
|
||||||
|
|
||||||
describe('#innerIsBucketValueEnabled', () => {
|
describe('#innerIsBucketValueEnabled', () => {
|
||||||
// Note: bucketValue is 497941 for 'desktop.stories2' key
|
// Note: bucketValue is 627610 for 'desktop.pnp' key
|
||||||
|
|
||||||
it('returns true for 100% wildcard', () => {
|
it('returns true for 100% wildcard', () => {
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
innerIsBucketValueEnabled(
|
innerIsBucketValueEnabled(
|
||||||
'desktop.stories2',
|
'desktop.pnp',
|
||||||
'*:1000000',
|
'*:1000000',
|
||||||
'+12125550000',
|
'+12125550000',
|
||||||
aci
|
aci
|
||||||
|
@ -28,11 +28,11 @@ describe('RemoteConfig', () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns true for 50% on country code 1', () => {
|
it('returns true for 70% on country code 1', () => {
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
innerIsBucketValueEnabled(
|
innerIsBucketValueEnabled(
|
||||||
'desktop.stories2',
|
'desktop.pnp',
|
||||||
'1:500000',
|
'1:700000',
|
||||||
'+12125550000',
|
'+12125550000',
|
||||||
aci
|
aci
|
||||||
),
|
),
|
||||||
|
@ -40,11 +40,11 @@ describe('RemoteConfig', () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns false for 40% on country code 1', () => {
|
it('returns false for 50% on country code 1', () => {
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
innerIsBucketValueEnabled(
|
innerIsBucketValueEnabled(
|
||||||
'desktop.stories2',
|
'desktop.pnp',
|
||||||
'1:400000',
|
'1:500000',
|
||||||
'+12125550000',
|
'+12125550000',
|
||||||
aci
|
aci
|
||||||
),
|
),
|
||||||
|
@ -92,7 +92,7 @@ describe('RemoteConfig', () => {
|
||||||
it('returns undefined for empty value', () => {
|
it('returns undefined for empty value', () => {
|
||||||
const flagName = 'research.megaphone.1';
|
const flagName = 'research.megaphone.1';
|
||||||
|
|
||||||
assert.strictEqual(getBucketValue(aci, flagName), 243315);
|
assert.strictEqual(getBucketValue(aci, flagName), 222732);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -76,6 +76,12 @@ Bootstrap.benchmark(async (bootstrap: Bootstrap): Promise<void> => {
|
||||||
'.timeline-wrapper, .Inbox__conversation .ConversationView'
|
'.timeline-wrapper, .Inbox__conversation .ConversationView'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
debug('accepting conversation');
|
||||||
|
await window.getByRole('button', { name: 'Continue' }).click();
|
||||||
|
|
||||||
|
const { dataMessage: profileKeyMsg } = await first.waitForMessage();
|
||||||
|
assert(profileKeyMsg.profileKey != null, 'Profile key message');
|
||||||
|
|
||||||
const deltaList = new Array<number>();
|
const deltaList = new Array<number>();
|
||||||
for (let runId = 0; runId < RUN_COUNT + DISCARD_COUNT; runId += 1) {
|
for (let runId = 0; runId < RUN_COUNT + DISCARD_COUNT; runId += 1) {
|
||||||
debug('finding composition input and clicking it');
|
debug('finding composition input and clicking it');
|
||||||
|
|
|
@ -296,6 +296,12 @@ describe('editing', function (this: Mocha.Suite) {
|
||||||
debug('checking for message');
|
debug('checking for message');
|
||||||
await window.locator('.module-message__text >> "hello"').waitFor();
|
await window.locator('.module-message__text >> "hello"').waitFor();
|
||||||
|
|
||||||
|
debug('accepting conversation');
|
||||||
|
await window.getByRole('button', { name: 'Continue' }).click();
|
||||||
|
|
||||||
|
const { dataMessage: profileKeyMsg } = await friend.waitForMessage();
|
||||||
|
assert(profileKeyMsg.profileKey != null, 'Profile key message');
|
||||||
|
|
||||||
debug('finding composition input and clicking it');
|
debug('finding composition input and clicking it');
|
||||||
{
|
{
|
||||||
const input = await app.waitForEnabledComposer();
|
const input = await app.waitForEnabledComposer();
|
||||||
|
@ -529,6 +535,12 @@ describe('editing', function (this: Mocha.Suite) {
|
||||||
.click();
|
.click();
|
||||||
await page.locator('.module-conversation-hero').waitFor();
|
await page.locator('.module-conversation-hero').waitFor();
|
||||||
|
|
||||||
|
debug('accepting conversation');
|
||||||
|
await page.getByRole('button', { name: 'Continue' }).click();
|
||||||
|
|
||||||
|
const { dataMessage: profileKeyMsg } = await friend.waitForMessage();
|
||||||
|
assert(profileKeyMsg.profileKey != null, 'Profile key message');
|
||||||
|
|
||||||
// Sending the original message
|
// Sending the original message
|
||||||
// getting a read receipt
|
// getting a read receipt
|
||||||
// testing the message's send state
|
// testing the message's send state
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import type { ConversationAttributesType } from '../model-types.d';
|
import type { ConversationAttributesType } from '../model-types.d';
|
||||||
import { isAnnouncementGroupReady } from './isAnnouncementGroupReady';
|
|
||||||
import { isGroupV2 } from './whatTypeOfConversation';
|
import { isGroupV2 } from './whatTypeOfConversation';
|
||||||
|
|
||||||
export function canBeAnnouncementGroup(
|
export function canBeAnnouncementGroup(
|
||||||
|
@ -15,9 +14,5 @@ export function canBeAnnouncementGroup(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isAnnouncementGroupReady()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
import type { MessageAttributesType } from '../model-types.d';
|
import type { MessageAttributesType } from '../model-types.d';
|
||||||
import { DAY } from './durations';
|
import { DAY } from './durations';
|
||||||
import { canEditMessages } from './canEditMessages';
|
|
||||||
import { isMoreRecentThan } from './timestamp';
|
import { isMoreRecentThan } from './timestamp';
|
||||||
import { isOutgoing } from '../messages/helpers';
|
import { isOutgoing } from '../messages/helpers';
|
||||||
|
|
||||||
|
@ -11,7 +10,6 @@ export const MESSAGE_MAX_EDIT_COUNT = 10;
|
||||||
|
|
||||||
export function canEditMessage(message: MessageAttributesType): boolean {
|
export function canEditMessage(message: MessageAttributesType): boolean {
|
||||||
const result =
|
const result =
|
||||||
canEditMessages() &&
|
|
||||||
!message.deletedForEveryone &&
|
!message.deletedForEveryone &&
|
||||||
isOutgoing(message) &&
|
isOutgoing(message) &&
|
||||||
isMoreRecentThan(message.sent_at, DAY) &&
|
isMoreRecentThan(message.sent_at, DAY) &&
|
||||||
|
@ -25,9 +23,7 @@ export function canEditMessage(message: MessageAttributesType): boolean {
|
||||||
message.conversationId ===
|
message.conversationId ===
|
||||||
window.ConversationController.getOurConversationId()
|
window.ConversationController.getOurConversationId()
|
||||||
) {
|
) {
|
||||||
return (
|
return !message.deletedForEveryone && Boolean(message.body);
|
||||||
canEditMessages() && !message.deletedForEveryone && Boolean(message.body)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
// Copyright 2023 Signal Messenger, LLC
|
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
|
|
||||||
import { isEnabled } from '../RemoteConfig';
|
|
||||||
import { isBeta } from './version';
|
|
||||||
|
|
||||||
export function canEditMessages(): boolean {
|
|
||||||
return (
|
|
||||||
isBeta(window.getVersion()) ||
|
|
||||||
isEnabled('desktop.internalUser') ||
|
|
||||||
isEnabled('desktop.editMessageSend')
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -4,7 +4,6 @@
|
||||||
import { webFrame } from 'electron';
|
import { webFrame } from 'electron';
|
||||||
import type { AudioDevice } from '@signalapp/ringrtc';
|
import type { AudioDevice } from '@signalapp/ringrtc';
|
||||||
import { noop } from 'lodash';
|
import { noop } from 'lodash';
|
||||||
import { getStoriesAvailable } from './stories';
|
|
||||||
|
|
||||||
import type { ZoomFactorType } from '../types/Storage.d';
|
import type { ZoomFactorType } from '../types/Storage.d';
|
||||||
import type {
|
import type {
|
||||||
|
@ -38,7 +37,6 @@ import * as Registration from './registration';
|
||||||
import { lookupConversationWithoutServiceId } from './lookupConversationWithoutServiceId';
|
import { lookupConversationWithoutServiceId } from './lookupConversationWithoutServiceId';
|
||||||
import * as log from '../logging/log';
|
import * as log from '../logging/log';
|
||||||
import { deleteAllMyStories } from './deleteAllMyStories';
|
import { deleteAllMyStories } from './deleteAllMyStories';
|
||||||
import { isEnabled } from '../RemoteConfig';
|
|
||||||
import type { NotificationClickData } from '../services/notifications';
|
import type { NotificationClickData } from '../services/notifications';
|
||||||
import { StoryViewModeType, StoryViewTargetType } from '../types/Stories';
|
import { StoryViewModeType, StoryViewTargetType } from '../types/Stories';
|
||||||
import { isValidE164 } from './isValidE164';
|
import { isValidE164 } from './isValidE164';
|
||||||
|
@ -111,7 +109,6 @@ export type IPCEventsCallbacksType = {
|
||||||
mediaType: 'screen' | 'microphone' | 'camera'
|
mediaType: 'screen' | 'microphone' | 'camera'
|
||||||
) => Promise<string | unknown>;
|
) => Promise<string | unknown>;
|
||||||
installStickerPack: (packId: string, key: string) => Promise<void>;
|
installStickerPack: (packId: string, key: string) => Promise<void>;
|
||||||
isFormattingFlagEnabled: () => boolean;
|
|
||||||
isPhoneNumberSharingEnabled: () => boolean;
|
isPhoneNumberSharingEnabled: () => boolean;
|
||||||
isPrimary: () => boolean;
|
isPrimary: () => boolean;
|
||||||
removeCustomColor: (x: string) => void;
|
removeCustomColor: (x: string) => void;
|
||||||
|
@ -136,7 +133,6 @@ export type IPCEventsCallbacksType = {
|
||||||
color: ConversationColorType,
|
color: ConversationColorType,
|
||||||
customColor?: { id: string; value: CustomColorType }
|
customColor?: { id: string; value: CustomColorType }
|
||||||
) => void;
|
) => void;
|
||||||
shouldShowStoriesSettings: () => boolean;
|
|
||||||
getDefaultConversationColor: () => DefaultConversationColorType;
|
getDefaultConversationColor: () => DefaultConversationColorType;
|
||||||
persistZoomFactor: (factor: number) => Promise<void>;
|
persistZoomFactor: (factor: number) => Promise<void>;
|
||||||
};
|
};
|
||||||
|
@ -429,10 +425,8 @@ export function createIPCEvents(
|
||||||
return window.IPC.setAutoLaunch(value);
|
return window.IPC.setAutoLaunch(value);
|
||||||
},
|
},
|
||||||
|
|
||||||
isFormattingFlagEnabled: () => isEnabled('desktop.textFormatting'),
|
|
||||||
isPhoneNumberSharingEnabled: () => isPhoneNumberSharingEnabled(),
|
isPhoneNumberSharingEnabled: () => isPhoneNumberSharingEnabled(),
|
||||||
isPrimary: () => window.textsecure.storage.user.getDeviceId() === 1,
|
isPrimary: () => window.textsecure.storage.user.getDeviceId() === 1,
|
||||||
shouldShowStoriesSettings: () => getStoriesAvailable(),
|
|
||||||
syncRequest: () =>
|
syncRequest: () =>
|
||||||
new Promise<void>((resolve, reject) => {
|
new Promise<void>((resolve, reject) => {
|
||||||
const FIVE_MINUTES = 5 * durations.MINUTE;
|
const FIVE_MINUTES = 5 * durations.MINUTE;
|
||||||
|
|
|
@ -97,9 +97,6 @@ export function getConversation(model: ConversationModel): ConversationType {
|
||||||
hasDraft(attributes) && draftTimestamp && draftTimestamp >= (timestamp || 0)
|
hasDraft(attributes) && draftTimestamp && draftTimestamp >= (timestamp || 0)
|
||||||
);
|
);
|
||||||
const inboxPosition = attributes.inbox_position;
|
const inboxPosition = attributes.inbox_position;
|
||||||
const messageRequestsEnabled = window.Signal.RemoteConfig.isEnabled(
|
|
||||||
'desktop.messageRequests'
|
|
||||||
);
|
|
||||||
const ourConversationId =
|
const ourConversationId =
|
||||||
window.ConversationController.getOurConversationId();
|
window.ConversationController.getOurConversationId();
|
||||||
|
|
||||||
|
@ -198,7 +195,6 @@ export function getConversation(model: ConversationModel): ConversationType {
|
||||||
pendingApprovalMemberships: getPendingApprovalMemberships(attributes),
|
pendingApprovalMemberships: getPendingApprovalMemberships(attributes),
|
||||||
bannedMemberships: getBannedMemberships(attributes),
|
bannedMemberships: getBannedMemberships(attributes),
|
||||||
profileKey: attributes.profileKey,
|
profileKey: attributes.profileKey,
|
||||||
messageRequestsEnabled,
|
|
||||||
accessControlAddFromInviteLink: attributes.accessControl?.addFromInviteLink,
|
accessControlAddFromInviteLink: attributes.accessControl?.addFromInviteLink,
|
||||||
accessControlAttributes: attributes.accessControl?.attributes,
|
accessControlAttributes: attributes.accessControl?.attributes,
|
||||||
accessControlMembers: attributes.accessControl?.members,
|
accessControlMembers: attributes.accessControl?.members,
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
// Copyright 2021 Signal Messenger, LLC
|
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
|
|
||||||
import * as RemoteConfig from '../RemoteConfig';
|
|
||||||
|
|
||||||
export function isAnnouncementGroupReady(): boolean {
|
|
||||||
return Boolean(
|
|
||||||
RemoteConfig.isEnabled('desktop.internalUser') ||
|
|
||||||
RemoteConfig.isEnabled('desktop.announcementGroup')
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -14,14 +14,6 @@ export function isConversationAccepted(
|
||||||
conversationAttrs: ConversationAttributesType,
|
conversationAttrs: ConversationAttributesType,
|
||||||
{ ignoreEmptyConvo = false } = {}
|
{ ignoreEmptyConvo = false } = {}
|
||||||
): boolean {
|
): boolean {
|
||||||
const messageRequestsEnabled = window.Signal.RemoteConfig.isEnabled(
|
|
||||||
'desktop.messageRequests'
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!messageRequestsEnabled) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isMe(conversationAttrs)) {
|
if (isMe(conversationAttrs)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
// Copyright 2021 Signal Messenger, LLC
|
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
|
|
||||||
import * as RemoteConfig from '../RemoteConfig';
|
|
||||||
import { isBeta } from './version';
|
|
||||||
|
|
||||||
export function isGroupCallOutboundRingEnabled(): boolean {
|
|
||||||
return Boolean(
|
|
||||||
RemoteConfig.isEnabled('desktop.internalUser') ||
|
|
||||||
RemoteConfig.isEnabled('desktop.groupCallOutboundRing2') ||
|
|
||||||
(isBeta(window.getVersion()) &&
|
|
||||||
RemoteConfig.isEnabled('desktop.groupCallOutboundRing2.beta'))
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -23,7 +23,7 @@ import {
|
||||||
import { Address } from '../types/Address';
|
import { Address } from '../types/Address';
|
||||||
import { QualifiedAddress } from '../types/QualifiedAddress';
|
import { QualifiedAddress } from '../types/QualifiedAddress';
|
||||||
import * as Errors from '../types/errors';
|
import * as Errors from '../types/errors';
|
||||||
import { getValue, isEnabled } from '../RemoteConfig';
|
import { getValue } from '../RemoteConfig';
|
||||||
import type { ServiceIdString } from '../types/ServiceId';
|
import type { ServiceIdString } from '../types/ServiceId';
|
||||||
import { ServiceIdKind } from '../types/ServiceId';
|
import { ServiceIdKind } from '../types/ServiceId';
|
||||||
import { isRecord } from './isRecord';
|
import { isRecord } from './isRecord';
|
||||||
|
@ -199,11 +199,7 @@ export async function sendContentMessageToGroup({
|
||||||
'sendContentMessageToGroup: textsecure.messaging not available!'
|
'sendContentMessageToGroup: textsecure.messaging not available!'
|
||||||
);
|
);
|
||||||
|
|
||||||
if (
|
if (sendTarget.isValid()) {
|
||||||
isEnabled('desktop.sendSenderKey3') &&
|
|
||||||
isEnabled('desktop.senderKey.send') &&
|
|
||||||
sendTarget.isValid()
|
|
||||||
) {
|
|
||||||
try {
|
try {
|
||||||
return await sendToGroupViaSenderKey({
|
return await sendToGroupViaSenderKey({
|
||||||
contentHint,
|
contentHint,
|
||||||
|
|
|
@ -1,34 +1,7 @@
|
||||||
// Copyright 2022 Signal Messenger, LLC
|
// Copyright 2022 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import { isBucketValueEnabled, isEnabled } from '../RemoteConfig';
|
|
||||||
import { isBeta } from './version';
|
|
||||||
|
|
||||||
// Note: selectors/items is the other place this check is done
|
|
||||||
export const getStoriesAvailable = (): boolean => {
|
|
||||||
if (
|
|
||||||
isBucketValueEnabled(
|
|
||||||
'desktop.stories2',
|
|
||||||
window.textsecure.storage.user.getNumber(),
|
|
||||||
window.textsecure.storage.user.getAci()
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isEnabled('desktop.internalUser')) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isEnabled('desktop.stories2.beta') && isBeta(window.getVersion())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getStoriesDisabled = (): boolean =>
|
export const getStoriesDisabled = (): boolean =>
|
||||||
window.Events.getHasStoriesDisabled();
|
window.Events.getHasStoriesDisabled();
|
||||||
|
|
||||||
export const getStoriesBlocked = (): boolean =>
|
export const getStoriesBlocked = (): boolean => getStoriesDisabled();
|
||||||
!getStoriesAvailable() || getStoriesDisabled();
|
|
||||||
|
|
|
@ -31,10 +31,8 @@ installSetting('typingIndicatorSetting', {
|
||||||
});
|
});
|
||||||
|
|
||||||
installCallback('deleteAllMyStories');
|
installCallback('deleteAllMyStories');
|
||||||
installCallback('isFormattingFlagEnabled');
|
|
||||||
installCallback('isPhoneNumberSharingEnabled');
|
installCallback('isPhoneNumberSharingEnabled');
|
||||||
installCallback('isPrimary');
|
installCallback('isPrimary');
|
||||||
installCallback('shouldShowStoriesSettings');
|
|
||||||
installCallback('syncRequest');
|
installCallback('syncRequest');
|
||||||
|
|
||||||
installSetting('alwaysRelayCalls');
|
installSetting('alwaysRelayCalls');
|
||||||
|
@ -56,7 +54,6 @@ installSetting('notificationSetting');
|
||||||
installSetting('spellCheck');
|
installSetting('spellCheck');
|
||||||
installSetting('systemTraySetting');
|
installSetting('systemTraySetting');
|
||||||
installSetting('sentMediaQualitySetting');
|
installSetting('sentMediaQualitySetting');
|
||||||
installSetting('textFormatting');
|
|
||||||
installSetting('themeSetting');
|
installSetting('themeSetting');
|
||||||
installSetting('universalExpireTimer');
|
installSetting('universalExpireTimer');
|
||||||
installSetting('zoomFactor');
|
installSetting('zoomFactor');
|
||||||
|
|
|
@ -59,7 +59,6 @@ SettingsWindowProps.onRender(
|
||||||
initialSpellCheckSetting,
|
initialSpellCheckSetting,
|
||||||
isAutoDownloadUpdatesSupported,
|
isAutoDownloadUpdatesSupported,
|
||||||
isAutoLaunchSupported,
|
isAutoLaunchSupported,
|
||||||
isFormattingFlagEnabled,
|
|
||||||
isHideMenuBarSupported,
|
isHideMenuBarSupported,
|
||||||
isMinimizeToAndStartInSystemTraySupported,
|
isMinimizeToAndStartInSystemTraySupported,
|
||||||
isNotificationAttentionSupported,
|
isNotificationAttentionSupported,
|
||||||
|
@ -111,7 +110,6 @@ SettingsWindowProps.onRender(
|
||||||
selectedSpeaker,
|
selectedSpeaker,
|
||||||
sentMediaQualitySetting,
|
sentMediaQualitySetting,
|
||||||
setGlobalDefaultConversationColor,
|
setGlobalDefaultConversationColor,
|
||||||
shouldShowStoriesSettings,
|
|
||||||
localeOverride,
|
localeOverride,
|
||||||
themeSetting,
|
themeSetting,
|
||||||
universalExpireTimer,
|
universalExpireTimer,
|
||||||
|
@ -163,7 +161,6 @@ SettingsWindowProps.onRender(
|
||||||
initialSpellCheckSetting={initialSpellCheckSetting}
|
initialSpellCheckSetting={initialSpellCheckSetting}
|
||||||
isAutoDownloadUpdatesSupported={isAutoDownloadUpdatesSupported}
|
isAutoDownloadUpdatesSupported={isAutoDownloadUpdatesSupported}
|
||||||
isAutoLaunchSupported={isAutoLaunchSupported}
|
isAutoLaunchSupported={isAutoLaunchSupported}
|
||||||
isFormattingFlagEnabled={isFormattingFlagEnabled}
|
|
||||||
isHideMenuBarSupported={isHideMenuBarSupported}
|
isHideMenuBarSupported={isHideMenuBarSupported}
|
||||||
isMinimizeToAndStartInSystemTraySupported={
|
isMinimizeToAndStartInSystemTraySupported={
|
||||||
isMinimizeToAndStartInSystemTraySupported
|
isMinimizeToAndStartInSystemTraySupported
|
||||||
|
@ -220,7 +217,6 @@ SettingsWindowProps.onRender(
|
||||||
selectedSpeaker={selectedSpeaker}
|
selectedSpeaker={selectedSpeaker}
|
||||||
sentMediaQualitySetting={sentMediaQualitySetting}
|
sentMediaQualitySetting={sentMediaQualitySetting}
|
||||||
setGlobalDefaultConversationColor={setGlobalDefaultConversationColor}
|
setGlobalDefaultConversationColor={setGlobalDefaultConversationColor}
|
||||||
shouldShowStoriesSettings={shouldShowStoriesSettings}
|
|
||||||
themeSetting={themeSetting}
|
themeSetting={themeSetting}
|
||||||
universalExpireTimer={universalExpireTimer}
|
universalExpireTimer={universalExpireTimer}
|
||||||
whoCanFindMe={whoCanFindMe}
|
whoCanFindMe={whoCanFindMe}
|
||||||
|
|
|
@ -79,13 +79,9 @@ const settingUniversalExpireTimer = createSetting('universalExpireTimer');
|
||||||
// Callbacks
|
// Callbacks
|
||||||
const ipcGetAvailableIODevices = createCallback('getAvailableIODevices');
|
const ipcGetAvailableIODevices = createCallback('getAvailableIODevices');
|
||||||
const ipcGetCustomColors = createCallback('getCustomColors');
|
const ipcGetCustomColors = createCallback('getCustomColors');
|
||||||
const ipcIsFormattingFlagEnabled = createCallback('isFormattingFlagEnabled');
|
|
||||||
const ipcIsSyncNotSupported = createCallback('isPrimary');
|
const ipcIsSyncNotSupported = createCallback('isPrimary');
|
||||||
const ipcMakeSyncRequest = createCallback('syncRequest');
|
const ipcMakeSyncRequest = createCallback('syncRequest');
|
||||||
const ipcPNP = createCallback('isPhoneNumberSharingEnabled');
|
const ipcPNP = createCallback('isPhoneNumberSharingEnabled');
|
||||||
const ipcShouldShowStoriesSettings = createCallback(
|
|
||||||
'shouldShowStoriesSettings'
|
|
||||||
);
|
|
||||||
const ipcDeleteAllMyStories = createCallback('deleteAllMyStories');
|
const ipcDeleteAllMyStories = createCallback('deleteAllMyStories');
|
||||||
|
|
||||||
// ChatColorPicker redux hookups
|
// ChatColorPicker redux hookups
|
||||||
|
@ -162,7 +158,6 @@ async function renderPreferences() {
|
||||||
hasStoriesDisabled,
|
hasStoriesDisabled,
|
||||||
hasTextFormatting,
|
hasTextFormatting,
|
||||||
hasTypingIndicators,
|
hasTypingIndicators,
|
||||||
isFormattingFlagEnabled,
|
|
||||||
isPhoneNumberSharingSupported,
|
isPhoneNumberSharingSupported,
|
||||||
lastSyncTime,
|
lastSyncTime,
|
||||||
notificationContent,
|
notificationContent,
|
||||||
|
@ -182,7 +177,6 @@ async function renderPreferences() {
|
||||||
customColors,
|
customColors,
|
||||||
defaultConversationColor,
|
defaultConversationColor,
|
||||||
isSyncNotSupported,
|
isSyncNotSupported,
|
||||||
shouldShowStoriesSettings,
|
|
||||||
} = await awaitObject({
|
} = await awaitObject({
|
||||||
blockedCount: settingBlockedCount.getValue(),
|
blockedCount: settingBlockedCount.getValue(),
|
||||||
deviceName: settingDeviceName.getValue(),
|
deviceName: settingDeviceName.getValue(),
|
||||||
|
@ -224,9 +218,7 @@ async function renderPreferences() {
|
||||||
availableIODevices: ipcGetAvailableIODevices(),
|
availableIODevices: ipcGetAvailableIODevices(),
|
||||||
customColors: ipcGetCustomColors(),
|
customColors: ipcGetCustomColors(),
|
||||||
defaultConversationColor: ipcGetDefaultConversationColor(),
|
defaultConversationColor: ipcGetDefaultConversationColor(),
|
||||||
isFormattingFlagEnabled: ipcIsFormattingFlagEnabled(),
|
|
||||||
isSyncNotSupported: ipcIsSyncNotSupported(),
|
isSyncNotSupported: ipcIsSyncNotSupported(),
|
||||||
shouldShowStoriesSettings: ipcShouldShowStoriesSettings(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const { availableCameras, availableMicrophones, availableSpeakers } =
|
const { availableCameras, availableMicrophones, availableSpeakers } =
|
||||||
|
@ -306,7 +298,6 @@ async function renderPreferences() {
|
||||||
resetAllChatColors: ipcResetAllChatColors,
|
resetAllChatColors: ipcResetAllChatColors,
|
||||||
resetDefaultChatColor: ipcResetDefaultChatColor,
|
resetDefaultChatColor: ipcResetDefaultChatColor,
|
||||||
setGlobalDefaultConversationColor: ipcSetGlobalDefaultConversationColor,
|
setGlobalDefaultConversationColor: ipcSetGlobalDefaultConversationColor,
|
||||||
shouldShowStoriesSettings,
|
|
||||||
|
|
||||||
// Limited support features
|
// Limited support features
|
||||||
isAutoDownloadUpdatesSupported: Settings.isAutoDownloadUpdatesSupported(OS),
|
isAutoDownloadUpdatesSupported: Settings.isAutoDownloadUpdatesSupported(OS),
|
||||||
|
@ -325,9 +316,6 @@ async function renderPreferences() {
|
||||||
MinimalSignalContext.getVersion()
|
MinimalSignalContext.getVersion()
|
||||||
),
|
),
|
||||||
|
|
||||||
// Feature flags
|
|
||||||
isFormattingFlagEnabled,
|
|
||||||
|
|
||||||
// Change handlers
|
// Change handlers
|
||||||
onAudioNotificationsChange: attachRenderCallback(
|
onAudioNotificationsChange: attachRenderCallback(
|
||||||
settingAudioNotification.setValue
|
settingAudioNotification.setValue
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue