Add emoji button to text story creation
This commit is contained in:
parent
d6d53f9d18
commit
77f92b6cc3
7 changed files with 285 additions and 213 deletions
|
@ -316,4 +316,10 @@
|
||||||
width: 24px;
|
width: 24px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__emoji-button,
|
||||||
|
&__emoji-button::after {
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,8 +55,13 @@ export default {
|
||||||
onDistributionListCreated: { action: true },
|
onDistributionListCreated: { action: true },
|
||||||
onHideMyStoriesFrom: { action: true },
|
onHideMyStoriesFrom: { action: true },
|
||||||
onSend: { action: true },
|
onSend: { action: true },
|
||||||
|
onSetSkinTone: { action: true },
|
||||||
|
onUseEmoji: { action: true },
|
||||||
onViewersUpdated: { action: true },
|
onViewersUpdated: { action: true },
|
||||||
processAttachment: { action: true },
|
processAttachment: { action: true },
|
||||||
|
recentEmojis: {
|
||||||
|
defaultValue: [],
|
||||||
|
},
|
||||||
recentStickers: {
|
recentStickers: {
|
||||||
defaultValue: [],
|
defaultValue: [],
|
||||||
},
|
},
|
||||||
|
@ -65,6 +70,9 @@ export default {
|
||||||
signalConnections: {
|
signalConnections: {
|
||||||
defaultValue: Array.from(Array(42), getDefaultConversation),
|
defaultValue: Array.from(Array(42), getDefaultConversation),
|
||||||
},
|
},
|
||||||
|
skinTone: {
|
||||||
|
defaultValue: 0,
|
||||||
|
},
|
||||||
toggleSignalConnectionsModal: { action: true },
|
toggleSignalConnectionsModal: { action: true },
|
||||||
},
|
},
|
||||||
} as Meta;
|
} as Meta;
|
||||||
|
|
|
@ -15,6 +15,7 @@ import type { Props as StickerButtonProps } from './stickers/StickerButton';
|
||||||
import type { PropsType as SendStoryModalPropsType } from './SendStoryModal';
|
import type { PropsType as SendStoryModalPropsType } from './SendStoryModal';
|
||||||
import type { UUIDStringType } from '../types/UUID';
|
import type { UUIDStringType } from '../types/UUID';
|
||||||
import type { imageToBlurHash } from '../util/imageToBlurHash';
|
import type { imageToBlurHash } from '../util/imageToBlurHash';
|
||||||
|
import type { PropsType as TextStoryCreatorPropsType } from './TextStoryCreator';
|
||||||
|
|
||||||
import { TEXT_ATTACHMENT } from '../types/MIME';
|
import { TEXT_ATTACHMENT } from '../types/MIME';
|
||||||
import { isVideoAttachment } from '../types/Attachment';
|
import { isVideoAttachment } from '../types/Attachment';
|
||||||
|
@ -70,6 +71,10 @@ export type PropsType = {
|
||||||
| 'toggleGroupsForStorySend'
|
| 'toggleGroupsForStorySend'
|
||||||
| 'mostRecentActiveStoryTimestampByGroupOrDistributionList'
|
| 'mostRecentActiveStoryTimestampByGroupOrDistributionList'
|
||||||
| 'toggleSignalConnectionsModal'
|
| 'toggleSignalConnectionsModal'
|
||||||
|
> &
|
||||||
|
Pick<
|
||||||
|
TextStoryCreatorPropsType,
|
||||||
|
'onUseEmoji' | 'skinTone' | 'onSetSkinTone' | 'recentEmojis'
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export function StoryCreator({
|
export function StoryCreator({
|
||||||
|
@ -87,7 +92,7 @@ export function StoryCreator({
|
||||||
isSending,
|
isSending,
|
||||||
linkPreview,
|
linkPreview,
|
||||||
me,
|
me,
|
||||||
ourConversationId,
|
mostRecentActiveStoryTimestampByGroupOrDistributionList,
|
||||||
onClose,
|
onClose,
|
||||||
onDeleteList,
|
onDeleteList,
|
||||||
onDistributionListCreated,
|
onDistributionListCreated,
|
||||||
|
@ -96,15 +101,19 @@ export function StoryCreator({
|
||||||
onRepliesNReactionsChanged,
|
onRepliesNReactionsChanged,
|
||||||
onSelectedStoryList,
|
onSelectedStoryList,
|
||||||
onSend,
|
onSend,
|
||||||
|
onSetSkinTone,
|
||||||
|
onUseEmoji,
|
||||||
onViewersUpdated,
|
onViewersUpdated,
|
||||||
|
ourConversationId,
|
||||||
processAttachment,
|
processAttachment,
|
||||||
|
recentEmojis,
|
||||||
recentStickers,
|
recentStickers,
|
||||||
renderCompositionTextArea,
|
renderCompositionTextArea,
|
||||||
sendStoryModalOpenStateChanged,
|
sendStoryModalOpenStateChanged,
|
||||||
setMyStoriesToAllSignalConnections,
|
setMyStoriesToAllSignalConnections,
|
||||||
signalConnections,
|
signalConnections,
|
||||||
|
skinTone,
|
||||||
toggleGroupsForStorySend,
|
toggleGroupsForStorySend,
|
||||||
mostRecentActiveStoryTimestampByGroupOrDistributionList,
|
|
||||||
toggleSignalConnectionsModal,
|
toggleSignalConnectionsModal,
|
||||||
}: PropsType): JSX.Element {
|
}: PropsType): JSX.Element {
|
||||||
const [draftAttachment, setDraftAttachment] = useState<
|
const [draftAttachment, setDraftAttachment] = useState<
|
||||||
|
@ -236,6 +245,10 @@ export function StoryCreator({
|
||||||
});
|
});
|
||||||
setIsReadyToSend(true);
|
setIsReadyToSend(true);
|
||||||
}}
|
}}
|
||||||
|
onUseEmoji={onUseEmoji}
|
||||||
|
onSetSkinTone={onSetSkinTone}
|
||||||
|
recentEmojis={recentEmojis}
|
||||||
|
skinTone={skinTone}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import Measure from 'react-measure';
|
import Measure from 'react-measure';
|
||||||
import React, { useEffect, useRef, useState } from 'react';
|
import React, { forwardRef, useEffect, useRef, useState } from 'react';
|
||||||
import TextareaAutosize from 'react-textarea-autosize';
|
import TextareaAutosize from 'react-textarea-autosize';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ import {
|
||||||
getBackgroundColor,
|
getBackgroundColor,
|
||||||
} from '../util/getStoryBackground';
|
} from '../util/getStoryBackground';
|
||||||
import { SECOND } from '../util/durations';
|
import { SECOND } from '../util/durations';
|
||||||
|
import { useRefMerger } from '../hooks/useRefMerger';
|
||||||
|
|
||||||
const renderNewLines: RenderTextCallbackType = ({
|
const renderNewLines: RenderTextCallbackType = ({
|
||||||
text: textWithNewLines,
|
text: textWithNewLines,
|
||||||
|
@ -105,7 +106,9 @@ function getTextStyles(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function TextAttachment({
|
export const TextAttachment = forwardRef<HTMLTextAreaElement, PropsType>(
|
||||||
|
function TextAttachmentForwarded(
|
||||||
|
{
|
||||||
disableLinkPreviewPopup,
|
disableLinkPreviewPopup,
|
||||||
i18n,
|
i18n,
|
||||||
isEditingText,
|
isEditingText,
|
||||||
|
@ -114,18 +117,20 @@ export function TextAttachment({
|
||||||
onClick,
|
onClick,
|
||||||
onRemoveLinkPreview,
|
onRemoveLinkPreview,
|
||||||
textAttachment,
|
textAttachment,
|
||||||
}: PropsType): JSX.Element | null {
|
},
|
||||||
|
forwardedTextEditorRef
|
||||||
|
): JSX.Element | null {
|
||||||
const linkPreview = useRef<HTMLDivElement | null>(null);
|
const linkPreview = useRef<HTMLDivElement | null>(null);
|
||||||
const [linkPreviewOffsetTop, setLinkPreviewOffsetTop] = useState<
|
const [linkPreviewOffsetTop, setLinkPreviewOffsetTop] = useState<
|
||||||
number | undefined
|
number | undefined
|
||||||
>();
|
>();
|
||||||
|
|
||||||
const textContent = textAttachment.text || '';
|
const textContent = textAttachment.text || '';
|
||||||
|
|
||||||
const textEditorRef = useRef<HTMLTextAreaElement | null>(null);
|
const textEditorRef = useRef<HTMLTextAreaElement | null>(null);
|
||||||
|
const refMerger = useRefMerger();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const node = textEditorRef.current;
|
const node = textEditorRef?.current;
|
||||||
if (!node) {
|
if (!node) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -241,7 +246,7 @@ export function TextAttachment({
|
||||||
disabled={!isEditingText}
|
disabled={!isEditingText}
|
||||||
onChange={ev => onChange(ev.currentTarget.value)}
|
onChange={ev => onChange(ev.currentTarget.value)}
|
||||||
placeholder={i18n('TextAttachment__placeholder')}
|
placeholder={i18n('TextAttachment__placeholder')}
|
||||||
ref={textEditorRef}
|
ref={refMerger(forwardedTextEditorRef, textEditorRef)}
|
||||||
style={getTextStyles(
|
style={getTextStyles(
|
||||||
textContent,
|
textContent,
|
||||||
textAttachment.textForegroundColor,
|
textAttachment.textForegroundColor,
|
||||||
|
@ -284,7 +289,9 @@ export function TextAttachment({
|
||||||
{onRemoveLinkPreview && (
|
{onRemoveLinkPreview && (
|
||||||
<div className="TextAttachment__preview__remove">
|
<div className="TextAttachment__preview__remove">
|
||||||
<button
|
<button
|
||||||
aria-label={i18n('Keyboard--remove-draft-link-preview')}
|
aria-label={i18n(
|
||||||
|
'Keyboard--remove-draft-link-preview'
|
||||||
|
)}
|
||||||
type="button"
|
type="button"
|
||||||
onClick={onRemoveLinkPreview}
|
onClick={onRemoveLinkPreview}
|
||||||
/>
|
/>
|
||||||
|
@ -309,3 +316,4 @@ export function TextAttachment({
|
||||||
</Measure>
|
</Measure>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
|
|
@ -7,12 +7,15 @@ import classNames from 'classnames';
|
||||||
import { get, has, noop } from 'lodash';
|
import { get, has, noop } from 'lodash';
|
||||||
import { usePopper } from 'react-popper';
|
import { usePopper } from 'react-popper';
|
||||||
|
|
||||||
|
import type { EmojiPickDataType } from './emoji/EmojiPicker';
|
||||||
import type { LinkPreviewType } from '../types/message/LinkPreviews';
|
import type { LinkPreviewType } from '../types/message/LinkPreviews';
|
||||||
import type { LocalizerType } from '../types/Util';
|
import type { LocalizerType } from '../types/Util';
|
||||||
|
import type { Props as EmojiButtonPropsType } from './emoji/EmojiButton';
|
||||||
import type { TextAttachmentType } from '../types/Attachment';
|
import type { TextAttachmentType } from '../types/Attachment';
|
||||||
|
|
||||||
import { Button, ButtonVariant } from './Button';
|
import { Button, ButtonVariant } from './Button';
|
||||||
import { ContextMenu } from './ContextMenu';
|
import { ContextMenu } from './ContextMenu';
|
||||||
|
import { EmojiButton } from './emoji/EmojiButton';
|
||||||
import { LinkPreviewSourceType, findLinks } from '../types/LinkPreview';
|
import { LinkPreviewSourceType, findLinks } from '../types/LinkPreview';
|
||||||
import type { MaybeGrabLinkPreviewOptionsType } from '../types/LinkPreview';
|
import type { MaybeGrabLinkPreviewOptionsType } from '../types/LinkPreview';
|
||||||
import { Input } from './Input';
|
import { Input } from './Input';
|
||||||
|
@ -26,6 +29,7 @@ import {
|
||||||
COLOR_WHITE_INT,
|
COLOR_WHITE_INT,
|
||||||
getBackgroundColor,
|
getBackgroundColor,
|
||||||
} from '../util/getStoryBackground';
|
} from '../util/getStoryBackground';
|
||||||
|
import { convertShortName } from './emoji/lib';
|
||||||
import { objectMap } from '../util/objectMap';
|
import { objectMap } from '../util/objectMap';
|
||||||
import { handleOutsideClick } from '../util/handleOutsideClick';
|
import { handleOutsideClick } from '../util/handleOutsideClick';
|
||||||
import { ConfirmDiscardDialog } from './ConfirmDiscardDialog';
|
import { ConfirmDiscardDialog } from './ConfirmDiscardDialog';
|
||||||
|
@ -42,7 +46,8 @@ export type PropsType = {
|
||||||
linkPreview?: LinkPreviewType;
|
linkPreview?: LinkPreviewType;
|
||||||
onClose: () => unknown;
|
onClose: () => unknown;
|
||||||
onDone: (textAttachment: TextAttachmentType) => unknown;
|
onDone: (textAttachment: TextAttachmentType) => unknown;
|
||||||
};
|
onUseEmoji: (_: EmojiPickDataType) => unknown;
|
||||||
|
} & Pick<EmojiButtonPropsType, 'onSetSkinTone' | 'recentEmojis' | 'skinTone'>;
|
||||||
|
|
||||||
enum LinkPreviewApplied {
|
enum LinkPreviewApplied {
|
||||||
None = 'None',
|
None = 'None',
|
||||||
|
@ -128,6 +133,10 @@ export function TextStoryCreator({
|
||||||
linkPreview,
|
linkPreview,
|
||||||
onClose,
|
onClose,
|
||||||
onDone,
|
onDone,
|
||||||
|
onSetSkinTone,
|
||||||
|
onUseEmoji,
|
||||||
|
recentEmojis,
|
||||||
|
skinTone,
|
||||||
}: PropsType): JSX.Element {
|
}: PropsType): JSX.Element {
|
||||||
const [showConfirmDiscardModal, setShowConfirmDiscardModal] = useState(false);
|
const [showConfirmDiscardModal, setShowConfirmDiscardModal] = useState(false);
|
||||||
|
|
||||||
|
@ -145,16 +154,6 @@ export function TextStoryCreator({
|
||||||
const [sliderValue, setSliderValue] = useState<number>(100);
|
const [sliderValue, setSliderValue] = useState<number>(100);
|
||||||
const [text, setText] = useState<string>('');
|
const [text, setText] = useState<string>('');
|
||||||
|
|
||||||
const textEditorRef = useRef<HTMLInputElement | null>(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (isEditingText) {
|
|
||||||
textEditorRef.current?.focus();
|
|
||||||
} else {
|
|
||||||
textEditorRef.current?.blur();
|
|
||||||
}
|
|
||||||
}, [isEditingText]);
|
|
||||||
|
|
||||||
const [isColorPickerShowing, setIsColorPickerShowing] = useState(false);
|
const [isColorPickerShowing, setIsColorPickerShowing] = useState(false);
|
||||||
const [colorPickerPopperButtonRef, setColorPickerPopperButtonRef] =
|
const [colorPickerPopperButtonRef, setColorPickerPopperButtonRef] =
|
||||||
useState<HTMLButtonElement | null>(null);
|
useState<HTMLButtonElement | null>(null);
|
||||||
|
@ -328,6 +327,8 @@ export function TextStoryCreator({
|
||||||
|
|
||||||
const hasChanges = Boolean(text || hasLinkPreviewApplied);
|
const hasChanges = Boolean(text || hasLinkPreviewApplied);
|
||||||
|
|
||||||
|
const textEditorRef = useRef<HTMLTextAreaElement | null>(null);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FocusTrap focusTrapOptions={{ allowOutsideClick: true }}>
|
<FocusTrap focusTrapOptions={{ allowOutsideClick: true }}>
|
||||||
<div className="StoryCreator">
|
<div className="StoryCreator">
|
||||||
|
@ -345,6 +346,7 @@ export function TextStoryCreator({
|
||||||
onRemoveLinkPreview={() => {
|
onRemoveLinkPreview={() => {
|
||||||
setLinkPreviewApplied(LinkPreviewApplied.None);
|
setLinkPreviewApplied(LinkPreviewApplied.None);
|
||||||
}}
|
}}
|
||||||
|
ref={textEditorRef}
|
||||||
textAttachment={textAttachment}
|
textAttachment={textAttachment}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -428,6 +430,26 @@ export function TextStoryCreator({
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
/>
|
/>
|
||||||
|
<EmojiButton
|
||||||
|
className="StoryCreator__emoji-button"
|
||||||
|
i18n={i18n}
|
||||||
|
onPickEmoji={data => {
|
||||||
|
onUseEmoji(data);
|
||||||
|
const emoji = convertShortName(data.shortName, data.skinTone);
|
||||||
|
const insertAt =
|
||||||
|
textEditorRef.current?.selectionEnd ?? text.length;
|
||||||
|
setText(
|
||||||
|
originalText =>
|
||||||
|
`${originalText.substr(
|
||||||
|
0,
|
||||||
|
insertAt
|
||||||
|
)}${emoji}${originalText.substr(insertAt, text.length)}`
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
recentEmojis={recentEmojis}
|
||||||
|
skinTone={skinTone}
|
||||||
|
onSetSkinTone={onSetSkinTone}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="StoryCreator__toolbar--space" />
|
<div className="StoryCreator__toolbar--space" />
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { useSelector } from 'react-redux';
|
||||||
import type { LocalizerType } from '../../types/Util';
|
import type { LocalizerType } from '../../types/Util';
|
||||||
import type { StateType } from '../reducer';
|
import type { StateType } from '../reducer';
|
||||||
import { LinkPreviewSourceType } from '../../types/LinkPreview';
|
import { LinkPreviewSourceType } from '../../types/LinkPreview';
|
||||||
|
import { SmartCompositionTextArea } from './CompositionTextArea';
|
||||||
import { StoryCreator } from '../../components/StoryCreator';
|
import { StoryCreator } from '../../components/StoryCreator';
|
||||||
import {
|
import {
|
||||||
getAllSignalConnections,
|
getAllSignalConnections,
|
||||||
|
@ -22,18 +23,23 @@ import {
|
||||||
getInstalledStickerPacks,
|
getInstalledStickerPacks,
|
||||||
getRecentStickers,
|
getRecentStickers,
|
||||||
} from '../selectors/stickers';
|
} from '../selectors/stickers';
|
||||||
import { getHasSetMyStoriesPrivacy } from '../selectors/items';
|
import { getAddStoryData } from '../selectors/stories';
|
||||||
|
import {
|
||||||
|
getEmojiSkinTone,
|
||||||
|
getHasSetMyStoriesPrivacy,
|
||||||
|
} from '../selectors/items';
|
||||||
import { getLinkPreview } from '../selectors/linkPreviews';
|
import { getLinkPreview } from '../selectors/linkPreviews';
|
||||||
import { getPreferredBadgeSelector } from '../selectors/badges';
|
import { getPreferredBadgeSelector } from '../selectors/badges';
|
||||||
import { processAttachment } from '../../util/processAttachment';
|
|
||||||
import { imageToBlurHash } from '../../util/imageToBlurHash';
|
import { imageToBlurHash } from '../../util/imageToBlurHash';
|
||||||
|
import { processAttachment } from '../../util/processAttachment';
|
||||||
import { useConversationsActions } from '../ducks/conversations';
|
import { useConversationsActions } from '../ducks/conversations';
|
||||||
|
import { useActions as useEmojisActions } from '../ducks/emojis';
|
||||||
import { useGlobalModalActions } from '../ducks/globalModals';
|
import { useGlobalModalActions } from '../ducks/globalModals';
|
||||||
|
import { useActions as useItemsActions } from '../ducks/items';
|
||||||
import { useLinkPreviewActions } from '../ducks/linkPreviews';
|
import { useLinkPreviewActions } from '../ducks/linkPreviews';
|
||||||
|
import { useRecentEmojis } from '../selectors/emojis';
|
||||||
import { useStoriesActions } from '../ducks/stories';
|
import { useStoriesActions } from '../ducks/stories';
|
||||||
import { useStoryDistributionListsActions } from '../ducks/storyDistributionLists';
|
import { useStoryDistributionListsActions } from '../ducks/storyDistributionLists';
|
||||||
import { SmartCompositionTextArea } from './CompositionTextArea';
|
|
||||||
import { getAddStoryData } from '../selectors/stories';
|
|
||||||
|
|
||||||
export type PropsType = {
|
export type PropsType = {
|
||||||
file?: File;
|
file?: File;
|
||||||
|
@ -81,6 +87,11 @@ export function SmartStoryCreator(): JSX.Element | null {
|
||||||
const file = addStoryData?.type === 'Media' ? addStoryData.file : undefined;
|
const file = addStoryData?.type === 'Media' ? addStoryData.file : undefined;
|
||||||
const isSending = addStoryData?.sending || false;
|
const isSending = addStoryData?.sending || false;
|
||||||
|
|
||||||
|
const recentEmojis = useRecentEmojis();
|
||||||
|
const skinTone = useSelector<StateType, number>(getEmojiSkinTone);
|
||||||
|
const { onSetSkinTone } = useItemsActions();
|
||||||
|
const { onUseEmoji } = useEmojisActions();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StoryCreator
|
<StoryCreator
|
||||||
candidateConversations={candidateConversations}
|
candidateConversations={candidateConversations}
|
||||||
|
@ -97,7 +108,9 @@ export function SmartStoryCreator(): JSX.Element | null {
|
||||||
isSending={isSending}
|
isSending={isSending}
|
||||||
linkPreview={linkPreviewForSource(LinkPreviewSourceType.StoryCreator)}
|
linkPreview={linkPreviewForSource(LinkPreviewSourceType.StoryCreator)}
|
||||||
me={me}
|
me={me}
|
||||||
ourConversationId={ourConversationId}
|
mostRecentActiveStoryTimestampByGroupOrDistributionList={
|
||||||
|
mostRecentActiveStoryTimestampByGroupOrDistributionList
|
||||||
|
}
|
||||||
onClose={() => setAddStoryData(undefined)}
|
onClose={() => setAddStoryData(undefined)}
|
||||||
onDeleteList={deleteDistributionList}
|
onDeleteList={deleteDistributionList}
|
||||||
onDistributionListCreated={createDistributionList}
|
onDistributionListCreated={createDistributionList}
|
||||||
|
@ -106,17 +119,19 @@ export function SmartStoryCreator(): JSX.Element | null {
|
||||||
onRepliesNReactionsChanged={allowsRepliesChanged}
|
onRepliesNReactionsChanged={allowsRepliesChanged}
|
||||||
onSelectedStoryList={verifyStoryListMembers}
|
onSelectedStoryList={verifyStoryListMembers}
|
||||||
onSend={sendStoryMessage}
|
onSend={sendStoryMessage}
|
||||||
|
onSetSkinTone={onSetSkinTone}
|
||||||
|
onUseEmoji={onUseEmoji}
|
||||||
onViewersUpdated={updateStoryViewers}
|
onViewersUpdated={updateStoryViewers}
|
||||||
|
ourConversationId={ourConversationId}
|
||||||
processAttachment={processAttachment}
|
processAttachment={processAttachment}
|
||||||
|
recentEmojis={recentEmojis}
|
||||||
recentStickers={recentStickers}
|
recentStickers={recentStickers}
|
||||||
renderCompositionTextArea={SmartCompositionTextArea}
|
renderCompositionTextArea={SmartCompositionTextArea}
|
||||||
sendStoryModalOpenStateChanged={sendStoryModalOpenStateChanged}
|
sendStoryModalOpenStateChanged={sendStoryModalOpenStateChanged}
|
||||||
setMyStoriesToAllSignalConnections={setMyStoriesToAllSignalConnections}
|
setMyStoriesToAllSignalConnections={setMyStoriesToAllSignalConnections}
|
||||||
signalConnections={signalConnections}
|
signalConnections={signalConnections}
|
||||||
|
skinTone={skinTone}
|
||||||
toggleGroupsForStorySend={toggleGroupsForStorySend}
|
toggleGroupsForStorySend={toggleGroupsForStorySend}
|
||||||
mostRecentActiveStoryTimestampByGroupOrDistributionList={
|
|
||||||
mostRecentActiveStoryTimestampByGroupOrDistributionList
|
|
||||||
}
|
|
||||||
toggleSignalConnectionsModal={toggleSignalConnectionsModal}
|
toggleSignalConnectionsModal={toggleSignalConnectionsModal}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -9093,7 +9093,7 @@
|
||||||
{
|
{
|
||||||
"rule": "React-useRef",
|
"rule": "React-useRef",
|
||||||
"path": "ts/components/TextStoryCreator.tsx",
|
"path": "ts/components/TextStoryCreator.tsx",
|
||||||
"line": " const textEditorRef = useRef<HTMLInputElement | null>(null);",
|
"line": " const textEditorRef = useRef<HTMLTextAreaElement | null>(null);",
|
||||||
"reasonCategory": "usageTrusted",
|
"reasonCategory": "usageTrusted",
|
||||||
"updated": "2022-06-16T23:23:32.306Z"
|
"updated": "2022-06-16T23:23:32.306Z"
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue