diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 66cbf5c872..0278777a0b 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -7179,6 +7179,14 @@ "message": "Add a story", "description": "Description hint to add a story" }, + "Stories__add-story--text": { + "message": "Text story", + "description": "Label to create a new text story" + }, + "Stories__add-story--media": { + "message": "Photo or video", + "description": "Label to create a new multimedia story" + }, "Stories__hidden-stories": { "message": "Hidden stories", "description": "Button label to go to hidden stories pane" @@ -7495,8 +7503,16 @@ "message": "Can’t download story. You will need to share it again.", "description": "Description for image errors but when it is your own image" }, - "StoryCreator__text-bg": { - "message": "Toggle text background color", + "StoryCreator__text-bg--background": { + "message": "Text has a white background color", + "description": "Button label" + }, + "StoryCreator__text-bg--inverse": { + "message": "Text has selected color as the background color", + "description": "Button label" + }, + "StoryCreator__text-bg--none": { + "message": "Text has no background color", "description": "Button label" }, "StoryCreator__story-bg": { diff --git a/stylesheets/components/Stories.scss b/stylesheets/components/Stories.scss index 67a63ceb13..d05d6ad0af 100644 --- a/stylesheets/components/Stories.scss +++ b/stylesheets/components/Stories.scss @@ -21,6 +21,15 @@ width: 380px; padding-top: calc(14px + var(--title-bar-drag-area-height)); + &__add-story__button { + @include color-svg('../images/icons/v2/plus-24.svg', $color-white); + height: 22px; + position: absolute; + right: 63px; + top: 0px; + width: 22px; + } + &__settings__button { @include dark-theme { @include color-svg( @@ -61,18 +70,6 @@ width: 100%; } - &--camera { - @include button-reset; - @include color-svg( - '../images/icons/v2/camera-outline-24.svg', - $color-white - ); - height: 22px; - position: absolute; - right: 63px; - width: 22px; - } - &--back { @include button-reset; diff --git a/ts/components/SendStoryModal.tsx b/ts/components/SendStoryModal.tsx index 3e28f9b6f8..0a5f9036f8 100644 --- a/ts/components/SendStoryModal.tsx +++ b/ts/components/SendStoryModal.tsx @@ -36,7 +36,7 @@ function getListViewers( } return memberCount === 1 - ? i18n('StoriesSettingsModal__list__viewers--singular', ['1']) + ? i18n('StoriesSettingsModal__viewers--singular', ['1']) : i18n('StoriesSettings__viewers--plural', [String(memberCount)]); } diff --git a/ts/components/Stories.tsx b/ts/components/Stories.tsx index 3dd6f6d0d7..dcfa3cd40c 100644 --- a/ts/components/Stories.tsx +++ b/ts/components/Stories.tsx @@ -1,7 +1,6 @@ // Copyright 2022 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import FocusTrap from 'focus-trap-react'; import React, { useState } from 'react'; import classNames from 'classnames'; import type { @@ -43,6 +42,14 @@ export type PropsType = { viewStory: ViewStoryActionCreatorType; }; +type AddStoryType = + | { + type: 'Media'; + file: File; + } + | { type: 'Text' } + | undefined; + export const Stories = ({ deleteStoryForEveryone, getPreferredBadge, @@ -67,54 +74,57 @@ export const Stories = ({ requiresFullWidth: true, }); - const [isShowingStoryCreator, setIsShowingStoryCreator] = useState(false); + const [addStoryData, setAddStoryData] = useState(); const [isMyStories, setIsMyStories] = useState(false); return (
- {isShowingStoryCreator && + {addStoryData && renderStoryCreator({ - onClose: () => setIsShowingStoryCreator(false), + file: addStoryData.type === 'Media' ? addStoryData.file : undefined, + onClose: () => setAddStoryData(undefined), })} - -
- {isMyStories && myStories.length ? ( - setIsMyStories(false)} - onDelete={deleteStoryForEveryone} - onForward={onForwardStory} - onSave={onSaveStory} - queueStoryDownload={queueStoryDownload} - viewStory={viewStory} - /> - ) : ( - setIsShowingStoryCreator(true)} - onMyStoriesClicked={() => { - if (myStories.length) { - setIsMyStories(true); - } else { - setIsShowingStoryCreator(true); - } - }} - onStoriesSettings={showStoriesSettings} - queueStoryDownload={queueStoryDownload} - showConversation={showConversation} - stories={stories} - toggleHideStories={toggleHideStories} - toggleStoriesView={toggleStoriesView} - viewUserStories={viewUserStories} - /> - )} -
-
+
+ {isMyStories && myStories.length ? ( + setIsMyStories(false)} + onDelete={deleteStoryForEveryone} + onForward={onForwardStory} + onSave={onSaveStory} + queueStoryDownload={queueStoryDownload} + viewStory={viewStory} + /> + ) : ( + + file + ? setAddStoryData({ type: 'Media', file }) + : setAddStoryData({ type: 'Text' }) + } + onMyStoriesClicked={() => { + if (myStories.length) { + setIsMyStories(true); + } else { + setAddStoryData({ type: 'Text' }); + } + }} + onStoriesSettings={showStoriesSettings} + queueStoryDownload={queueStoryDownload} + showConversation={showConversation} + stories={stories} + toggleHideStories={toggleHideStories} + toggleStoriesView={toggleStoriesView} + viewUserStories={viewUserStories} + /> + )} +
{i18n('Stories__placeholder--text')} diff --git a/ts/components/StoriesPane.tsx b/ts/components/StoriesPane.tsx index 1a16c8458d..bdc305f9dd 100644 --- a/ts/components/StoriesPane.tsx +++ b/ts/components/StoriesPane.tsx @@ -65,7 +65,7 @@ export type PropsType = { i18n: LocalizerType; me: ConversationType; myStories: Array; - onAddStory: () => unknown; + onAddStory: (file?: File) => unknown; onMyStoriesClicked: () => unknown; onStoriesSettings: () => unknown; queueStoryDownload: (storyId: string) => unknown; @@ -118,18 +118,45 @@ export const StoriesPane = ({
{i18n('Stories__title')}
-
- ) : ( -
- )} -
- -
-
- )} - - - ) : ( -
-
- {i18n('StoryCreator__link-preview-empty')} -
- )} -
-
- )} -
- -
-
- - + {attachmentUrl && ( + { + setDraftAttachment({ + contentType: IMAGE_JPEG, + data, + size: data.byteLength, + }); + }} + recentStickers={recentStickers} + /> + )} + {!file && ( + { + setDraftAttachment({ + contentType: TEXT_ATTACHMENT, + textAttachment, + size: textAttachment.text?.length || 0, + }); + }} + /> + )} ); }; diff --git a/ts/components/TextStoryCreator.tsx b/ts/components/TextStoryCreator.tsx new file mode 100644 index 0000000000..be6f4b80c0 --- /dev/null +++ b/ts/components/TextStoryCreator.tsx @@ -0,0 +1,514 @@ +// Copyright 2022 Signal Messenger, LLC +// SPDX-License-Identifier: AGPL-3.0-only + +import FocusTrap from 'focus-trap-react'; +import React, { useEffect, useRef, useState } from 'react'; +import classNames from 'classnames'; +import { get, has } from 'lodash'; +import { usePopper } from 'react-popper'; + +import type { LinkPreviewType } from '../types/message/LinkPreviews'; +import type { LocalizerType } from '../types/Util'; +import type { TextAttachmentType } from '../types/Attachment'; + +import { Button, ButtonVariant } from './Button'; +import { ContextMenu } from './ContextMenu'; +import { LinkPreviewSourceType, findLinks } from '../types/LinkPreview'; +import { Input } from './Input'; +import { Slider } from './Slider'; +import { StagedLinkPreview } from './conversation/StagedLinkPreview'; +import { TextAttachment } from './TextAttachment'; +import { Theme, themeClassName } from '../util/theme'; +import { getRGBA, getRGBANumber } from '../mediaEditor/util/color'; +import { + COLOR_BLACK_INT, + COLOR_WHITE_INT, + getBackgroundColor, +} from '../util/getStoryBackground'; +import { objectMap } from '../util/objectMap'; + +export type PropsType = { + debouncedMaybeGrabLinkPreview: ( + message: string, + source: LinkPreviewSourceType + ) => unknown; + i18n: LocalizerType; + linkPreview?: LinkPreviewType; + onClose: () => unknown; + onDone: (textAttachment: TextAttachmentType) => unknown; +}; + +enum TextStyle { + Default, + Regular, + Bold, + Serif, + Script, + Condensed, +} + +enum TextBackground { + None, + Background, + Inverse, +} + +const BackgroundStyle = { + BG1099: { angle: 191, endColor: 4282529679, startColor: 4294260804 }, + BG1098: { startColor: 4293938406, endColor: 4279119837, angle: 192 }, + BG1031: { startColor: 4294950980, endColor: 4294859832, angle: 175 }, + BG1101: { startColor: 4278227945, endColor: 4286632135, angle: 180 }, + BG1100: { startColor: 4284861868, endColor: 4278884698, angle: 180 }, + BG1070: { color: 4294951251 }, + BG1080: { color: 4291607859 }, + BG1079: { color: 4286869806 }, + BG1083: { color: 4278825851 }, + BG1095: { color: 4287335417 }, + BG1088: { color: 4283519478 }, + BG1077: { color: 4294405742 }, + BG1094: { color: 4291315265 }, + BG1097: { color: 4291216549 }, + BG1074: { color: 4288976277 }, + BG1092: { color: 4280887593 }, +}; + +type BackgroundStyleType = typeof BackgroundStyle[keyof typeof BackgroundStyle]; + +function getBackground( + bgStyle: BackgroundStyleType +): Pick { + if (has(bgStyle, 'color')) { + return { color: get(bgStyle, 'color') }; + } + + const angle = get(bgStyle, 'angle'); + const startColor = get(bgStyle, 'startColor'); + const endColor = get(bgStyle, 'endColor'); + + return { + gradient: { angle, startColor, endColor }, + }; +} + +function getBgButtonAriaLabel( + i18n: LocalizerType, + textBackground: TextBackground +): string { + if (textBackground === TextBackground.Background) { + return i18n('StoryCreator__text-bg--background'); + } + + if (textBackground === TextBackground.Inverse) { + return i18n('StoryCreator__text-bg--inverse'); + } + + return i18n('StoryCreator__text-bg--none'); +} + +export const TextStoryCreator = ({ + debouncedMaybeGrabLinkPreview, + i18n, + linkPreview, + onClose, + onDone, +}: PropsType): JSX.Element => { + const [isEditingText, setIsEditingText] = useState(false); + const [selectedBackground, setSelectedBackground] = + useState(BackgroundStyle.BG1099); + const [textStyle, setTextStyle] = useState(TextStyle.Regular); + const [textBackground, setTextBackground] = useState( + TextBackground.None + ); + const [sliderValue, setSliderValue] = useState(100); + const [text, setText] = useState(''); + + const textEditorRef = useRef(null); + + useEffect(() => { + if (isEditingText) { + textEditorRef.current?.focus(); + } else { + textEditorRef.current?.blur(); + } + }, [isEditingText]); + + const [isColorPickerShowing, setIsColorPickerShowing] = useState(false); + const [colorPickerPopperButtonRef, setColorPickerPopperButtonRef] = + useState(null); + const [colorPickerPopperRef, setColorPickerPopperRef] = + useState(null); + + const colorPickerPopper = usePopper( + colorPickerPopperButtonRef, + colorPickerPopperRef, + { + modifiers: [ + { + name: 'arrow', + }, + ], + placement: 'top', + strategy: 'fixed', + } + ); + + const [hasLinkPreviewApplied, setHasLinkPreviewApplied] = useState(false); + const [linkPreviewInputValue, setLinkPreviewInputValue] = useState(''); + + useEffect(() => { + if (!linkPreviewInputValue) { + return; + } + debouncedMaybeGrabLinkPreview( + linkPreviewInputValue, + LinkPreviewSourceType.StoryCreator + ); + }, [debouncedMaybeGrabLinkPreview, linkPreviewInputValue]); + + useEffect(() => { + if (!text) { + return; + } + debouncedMaybeGrabLinkPreview(text, LinkPreviewSourceType.StoryCreator); + }, [debouncedMaybeGrabLinkPreview, text]); + + useEffect(() => { + if (!linkPreview || !text) { + return; + } + + const links = findLinks(text); + + const shouldApplyLinkPreview = links.includes(linkPreview.url); + setHasLinkPreviewApplied(shouldApplyLinkPreview); + }, [linkPreview, text]); + + const [isLinkPreviewInputShowing, setIsLinkPreviewInputShowing] = + useState(false); + const [linkPreviewInputPopperButtonRef, setLinkPreviewInputPopperButtonRef] = + useState(null); + const [linkPreviewInputPopperRef, setLinkPreviewInputPopperRef] = + useState(null); + + const linkPreviewInputPopper = usePopper( + linkPreviewInputPopperButtonRef, + linkPreviewInputPopperRef, + { + modifiers: [ + { + name: 'arrow', + }, + ], + placement: 'top', + strategy: 'fixed', + } + ); + + useEffect(() => { + const handleOutsideClick = (event: MouseEvent) => { + if (!colorPickerPopperButtonRef?.contains(event.target as Node)) { + setIsColorPickerShowing(false); + event.stopPropagation(); + event.preventDefault(); + } + }; + const handleEscape = (event: KeyboardEvent) => { + if (event.key === 'Escape') { + setIsColorPickerShowing(false); + event.preventDefault(); + event.stopPropagation(); + } + }; + + document.addEventListener('click', handleOutsideClick); + document.addEventListener('keydown', handleEscape); + + return () => { + document.removeEventListener('click', handleOutsideClick); + document.removeEventListener('keydown', handleEscape); + }; + }, [isColorPickerShowing, colorPickerPopperButtonRef]); + + const sliderColorNumber = getRGBANumber(sliderValue); + + let textForegroundColor = sliderColorNumber; + let textBackgroundColor: number | undefined; + + if (textBackground === TextBackground.Background) { + textBackgroundColor = COLOR_WHITE_INT; + textForegroundColor = + sliderValue >= 95 ? COLOR_BLACK_INT : sliderColorNumber; + } else if (textBackground === TextBackground.Inverse) { + textBackgroundColor = + sliderValue >= 95 ? COLOR_BLACK_INT : sliderColorNumber; + textForegroundColor = COLOR_WHITE_INT; + } + + const textAttachment: TextAttachmentType = { + ...getBackground(selectedBackground), + text, + textStyle, + textForegroundColor, + textBackgroundColor, + preview: hasLinkPreviewApplied ? linkPreview : undefined, + }; + + const hasChanges = Boolean(text || hasLinkPreviewApplied); + + return ( + +
+
+ { + if (!isEditingText) { + setIsEditingText(true); + } + }} + onRemoveLinkPreview={() => { + setHasLinkPreviewApplied(false); + }} + textAttachment={textAttachment} + /> +
+
+ {isEditingText ? ( +
+ + setTextStyle(TextStyle.Regular), + value: TextStyle.Regular, + }, + { + icon: 'StoryCreator__icon--font-bold', + label: i18n('StoryCreator__text--bold'), + onClick: () => setTextStyle(TextStyle.Bold), + value: TextStyle.Bold, + }, + { + icon: 'StoryCreator__icon--font-serif', + label: i18n('StoryCreator__text--serif'), + onClick: () => setTextStyle(TextStyle.Serif), + value: TextStyle.Serif, + }, + { + icon: 'StoryCreator__icon--font-script', + label: i18n('StoryCreator__text--script'), + onClick: () => setTextStyle(TextStyle.Script), + value: TextStyle.Script, + }, + { + icon: 'StoryCreator__icon--font-condensed', + label: i18n('StoryCreator__text--condensed'), + onClick: () => setTextStyle(TextStyle.Condensed), + value: TextStyle.Condensed, + }, + ]} + moduleClassName={classNames('StoryCreator__tools__tool', { + 'StoryCreator__tools__button--font-regular': + textStyle === TextStyle.Regular, + 'StoryCreator__tools__button--font-bold': + textStyle === TextStyle.Bold, + 'StoryCreator__tools__button--font-serif': + textStyle === TextStyle.Serif, + 'StoryCreator__tools__button--font-script': + textStyle === TextStyle.Script, + 'StoryCreator__tools__button--font-condensed': + textStyle === TextStyle.Condensed, + })} + theme={Theme.Dark} + value={textStyle} + /> +
+ ) : ( +
+ )} +
+ +
+
+ )} + + + ) : ( +
+
+ {i18n('StoryCreator__link-preview-empty')} +
+ )} +
+
+ )} +
+ +
+
+ +
+ ); +}; diff --git a/ts/jobs/conversationJobQueue.ts b/ts/jobs/conversationJobQueue.ts index e43091e4af..3aa4c6db7a 100644 --- a/ts/jobs/conversationJobQueue.ts +++ b/ts/jobs/conversationJobQueue.ts @@ -112,7 +112,6 @@ const storyJobDataSchema = z.object({ conversationId: z.string(), // Note: recipients are baked into the message itself messageIds: z.string().array(), - textAttachment: z.any(), // TODO TextAttachmentType timestamp: z.number(), revision: z.number().optional(), }); diff --git a/ts/jobs/helpers/sendStory.ts b/ts/jobs/helpers/sendStory.ts index 1e9b1013db..b6dd92a091 100644 --- a/ts/jobs/helpers/sendStory.ts +++ b/ts/jobs/helpers/sendStory.ts @@ -2,6 +2,10 @@ // SPDX-License-Identifier: AGPL-3.0-only import { isEqual } from 'lodash'; +import type { + AttachmentWithHydratedData, + TextAttachmentType, +} from '../../types/Attachment'; import type { ConversationModel } from '../../models/conversations'; import type { ConversationQueueJobBundle, @@ -42,7 +46,7 @@ export async function sendStory( }: ConversationQueueJobBundle, data: StoryJobData ): Promise { - const { messageIds, textAttachment, timestamp } = data; + const { messageIds, timestamp } = data; const profileKey = await ourProfileKeyService.get(); @@ -51,14 +55,57 @@ export async function sendStory( return; } - // Some distribution lists need allowsReplies false, some need it set to true - // we create this proto (for the sync message) and also to re-use some of the - // attributes inside it. - const originalStoryMessage = await messaging.getStoryMessage({ - allowsReplies: true, - textAttachment, - profileKey, - }); + // We want to generate the StoryMessage proto once at the top level so we + // can reuse it but first we'll need textAttachment | fileAttachment. + // This function pulls off the attachment and generates the proto from the + // first message on the list prior to continuing. + const originalStoryMessage = await (async (): Promise< + Proto.StoryMessage | undefined + > => { + const [messageId] = messageIds; + const message = await getMessageById(messageId); + if (!message) { + log.info( + `stories.sendStory: message ${messageId} was not found, maybe because it was deleted. Giving up on sending it` + ); + return; + } + + const attachments = message.get('attachments') || []; + const [attachment] = attachments; + + if (!attachment) { + log.info( + `stories.sendStory: message ${messageId} does not have any attachments to send. Giving up on sending it` + ); + return; + } + + let textAttachment: TextAttachmentType | undefined; + let fileAttachment: AttachmentWithHydratedData | undefined; + + if (attachment.textAttachment) { + textAttachment = attachment.textAttachment; + } else { + fileAttachment = await window.Signal.Migrations.loadAttachmentData( + attachment + ); + } + + // Some distribution lists need allowsReplies false, some need it set to true + // we create this proto (for the sync message) and also to re-use some of the + // attributes inside it. + return messaging.getStoryMessage({ + allowsReplies: true, + fileAttachment, + textAttachment, + profileKey, + }); + })(); + + if (!originalStoryMessage) { + return; + } const accSendStateByConversationId = new Map(); const canReplyUuids = new Set(); diff --git a/ts/state/ducks/stories.ts b/ts/state/ducks/stories.ts index 661de32373..c1d4d2ca3d 100644 --- a/ts/state/ducks/stories.ts +++ b/ts/state/ducks/stories.ts @@ -3,10 +3,7 @@ import type { ThunkAction, ThunkDispatch } from 'redux-thunk'; import { isEqual, noop, pick } from 'lodash'; -import type { - AttachmentType, - TextAttachmentType, -} from '../../types/Attachment'; +import type { AttachmentType } from '../../types/Attachment'; import type { BodyRangeType } from '../../types/Util'; import type { MessageAttributesType } from '../../model-types.d'; import type { @@ -562,10 +559,10 @@ function replyToStory( function sendStoryMessage( listIds: Array, - textAttachment: TextAttachmentType + attachment: AttachmentType ): ThunkAction { return async dispatch => { - await doSendStoryMessage(listIds, textAttachment); + await doSendStoryMessage(listIds, attachment); dispatch({ type: 'NOOP', diff --git a/ts/state/smart/Stories.tsx b/ts/state/smart/Stories.tsx index a101996577..8b311609e9 100644 --- a/ts/state/smart/Stories.tsx +++ b/ts/state/smart/Stories.tsx @@ -20,9 +20,10 @@ import { useGlobalModalActions } from '../ducks/globalModals'; import { useStoriesActions } from '../ducks/stories'; function renderStoryCreator({ + file, onClose, }: SmartStoryCreatorPropsType): JSX.Element { - return ; + return ; } export function SmartStories(): JSX.Element | null { diff --git a/ts/state/smart/StoryCreator.tsx b/ts/state/smart/StoryCreator.tsx index 304d7e7436..02533e4d52 100644 --- a/ts/state/smart/StoryCreator.tsx +++ b/ts/state/smart/StoryCreator.tsx @@ -8,25 +8,36 @@ import type { LocalizerType } from '../../types/Util'; import type { StateType } from '../reducer'; import { LinkPreviewSourceType } from '../../types/LinkPreview'; import { StoryCreator } from '../../components/StoryCreator'; +import { getAllSignalConnections, getMe } from '../selectors/conversations'; import { getDistributionLists } from '../selectors/storyDistributionLists'; import { getIntl } from '../selectors/user'; +import { + getInstalledStickerPacks, + getRecentStickers, +} from '../selectors/stickers'; import { getLinkPreview } from '../selectors/linkPreviews'; -import { getAllSignalConnections, getMe } from '../selectors/conversations'; +import { processAttachment } from '../../util/processAttachment'; import { useLinkPreviewActions } from '../ducks/linkPreviews'; import { useStoriesActions } from '../ducks/stories'; export type PropsType = { + file?: File; onClose: () => unknown; }; -export function SmartStoryCreator({ onClose }: PropsType): JSX.Element | null { +export function SmartStoryCreator({ + file, + onClose, +}: PropsType): JSX.Element | null { const { debouncedMaybeGrabLinkPreview } = useLinkPreviewActions(); const { sendStoryMessage } = useStoriesActions(); const i18n = useSelector(getIntl); - const linkPreviewForSource = useSelector(getLinkPreview); const distributionLists = useSelector(getDistributionLists); + const installedPacks = useSelector(getInstalledStickerPacks); + const linkPreviewForSource = useSelector(getLinkPreview); const me = useSelector(getMe); + const recentStickers = useSelector(getRecentStickers); const signalConnections = useSelector(getAllSignalConnections); return ( @@ -34,10 +45,14 @@ export function SmartStoryCreator({ onClose }: PropsType): JSX.Element | null { debouncedMaybeGrabLinkPreview={debouncedMaybeGrabLinkPreview} distributionLists={distributionLists} i18n={i18n} + installedPacks={installedPacks} + file={file} linkPreview={linkPreviewForSource(LinkPreviewSourceType.StoryCreator)} me={me} onClose={onClose} onSend={sendStoryMessage} + processAttachment={processAttachment} + recentStickers={recentStickers} signalConnections={signalConnections} /> ); diff --git a/ts/util/lint/exceptions.json b/ts/util/lint/exceptions.json index 5e072d4b21..e1b405ab22 100644 --- a/ts/util/lint/exceptions.json +++ b/ts/util/lint/exceptions.json @@ -9205,7 +9205,7 @@ }, { "rule": "React-useRef", - "path": "ts/components/StoryCreator.tsx", + "path": "ts/components/TextStoryCreator.tsx", "line": " const textEditorRef = useRef(null);", "reasonCategory": "usageTrusted", "updated": "2022-06-16T23:23:32.306Z" diff --git a/ts/util/sendStoryMessage.ts b/ts/util/sendStoryMessage.ts index 7a5107103c..bc99296872 100644 --- a/ts/util/sendStoryMessage.ts +++ b/ts/util/sendStoryMessage.ts @@ -1,9 +1,9 @@ // Copyright 2022 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only +import type { AttachmentType } from '../types/Attachment'; import type { MessageAttributesType } from '../model-types.d'; import type { SendStateByConversationId } from '../messages/MessageSendState'; -import type { TextAttachmentType } from '../types/Attachment'; import type { UUIDStringType } from '../types/UUID'; import * as log from '../logging/log'; import dataInterface from '../sql/Client'; @@ -12,7 +12,6 @@ import { MY_STORIES_ID } from '../types/Stories'; import { ReadStatus } from '../messages/MessageReadStatus'; import { SeenStatus } from '../MessageSeenStatus'; import { SendStatus } from '../messages/MessageSendState'; -import { TEXT_ATTACHMENT } from '../types/MIME'; import { UUID } from '../types/UUID'; import { conversationJobQueue, @@ -25,7 +24,7 @@ import { isNotNil } from './isNotNil'; export async function sendStoryMessage( listIds: Array, - textAttachment: TextAttachmentType + attachment: AttachmentType ): Promise { const { messaging } = window.textsecure; @@ -124,6 +123,8 @@ export async function sendStoryMessage( sendStateByListId.set(distributionList.id, sendStateByConversationId); }); + const attachments: Array = [attachment]; + // * Gather all the job data we'll be sending to the sendStory job // * Create the message for each distribution list const messagesToSave: Array = await Promise.all( @@ -140,13 +141,7 @@ export async function sendStoryMessage( } return window.Signal.Migrations.upgradeMessageSchema({ - attachments: [ - { - contentType: TEXT_ATTACHMENT, - textAttachment, - size: textAttachment.text?.length || 0, - }, - ], + attachments, conversationId: ourConversation.id, expireTimer: DAY / SECOND, id: UUID.generate().toString(), @@ -189,7 +184,6 @@ export async function sendStoryMessage( type: conversationQueueJobEnum.enum.Story, conversationId: ourConversation.id, messageIds: messagesToSave.map(m => m.id), - textAttachment, timestamp, }, async jobToInsert => {