DOE stories when they are part of deleted lists
This commit is contained in:
parent
b12de415f4
commit
b2792639aa
6 changed files with 226 additions and 189 deletions
|
@ -5516,7 +5516,7 @@
|
|||
"description": "Button label to delete a private distribution list"
|
||||
},
|
||||
"StoriesSettings__delete-list--confirm": {
|
||||
"message": "Delete private story?",
|
||||
"message": "Are you sure you want to delete \"$name$\"? Updates shared to this story will also be deleted.",
|
||||
"description": "Confirmation text to delete a private distribution list"
|
||||
},
|
||||
"StoriesSettings__choose-viewers": {
|
||||
|
|
|
@ -214,8 +214,8 @@ export const SendStoryModal = ({
|
|||
const [confirmRemoveGroupId, setConfirmRemoveGroupId] = useState<
|
||||
string | undefined
|
||||
>();
|
||||
const [confirmDeleteListId, setConfirmDeleteListId] = useState<
|
||||
string | undefined
|
||||
const [confirmDeleteList, setConfirmDeleteList] = useState<
|
||||
{ id: string; name: string } | undefined
|
||||
>();
|
||||
|
||||
const [listIdToEdit, setListIdToEdit] = useState<string | undefined>();
|
||||
|
@ -397,7 +397,7 @@ export const SendStoryModal = ({
|
|||
listToEdit={listToEdit}
|
||||
onRemoveMember={onRemoveMember}
|
||||
onRepliesNReactionsChanged={onRepliesNReactionsChanged}
|
||||
setConfirmDeleteListId={setConfirmDeleteListId}
|
||||
setConfirmDeleteList={setConfirmDeleteList}
|
||||
setMyStoriesToAllSignalConnections={setMyStoriesToAllSignalConnections}
|
||||
setPage={setPage}
|
||||
setSelectedContacts={setSelectedContacts}
|
||||
|
@ -719,7 +719,7 @@ export const SendStoryModal = ({
|
|||
{
|
||||
label: i18n('SendStoryModal__delete-story'),
|
||||
icon: 'SendStoryModal__icon--delete',
|
||||
onClick: () => setConfirmDeleteListId(list.id),
|
||||
onClick: () => setConfirmDeleteList(list),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
@ -897,19 +897,19 @@ export const SendStoryModal = ({
|
|||
onClose={() => {
|
||||
setConfirmRemoveGroupId(undefined);
|
||||
}}
|
||||
theme={Theme.Dark}
|
||||
>
|
||||
{i18n('SendStoryModal__confirm-remove-group')}
|
||||
</ConfirmationDialog>
|
||||
)}
|
||||
{confirmDeleteListId && (
|
||||
{confirmDeleteList && (
|
||||
<ConfirmationDialog
|
||||
dialogName="SendStoryModal.confirmDeleteList"
|
||||
actions={[
|
||||
{
|
||||
action: () => {
|
||||
onDeleteList(confirmDeleteListId);
|
||||
setConfirmDeleteListId(undefined);
|
||||
// setListToEditId(undefined);
|
||||
onDeleteList(confirmDeleteList.id);
|
||||
setConfirmDeleteList(undefined);
|
||||
},
|
||||
style: 'negative',
|
||||
text: i18n('delete'),
|
||||
|
@ -917,10 +917,13 @@ export const SendStoryModal = ({
|
|||
]}
|
||||
i18n={i18n}
|
||||
onClose={() => {
|
||||
setConfirmDeleteListId(undefined);
|
||||
setConfirmDeleteList(undefined);
|
||||
}}
|
||||
theme={Theme.Dark}
|
||||
>
|
||||
{i18n('StoriesSettings__delete-list--confirm')}
|
||||
{i18n('StoriesSettings__delete-list--confirm', [
|
||||
confirmDeleteList.name,
|
||||
])}
|
||||
</ConfirmationDialog>
|
||||
)}
|
||||
{confirmDiscardModal}
|
||||
|
|
|
@ -126,8 +126,8 @@ export const StoriesSettingsModal = ({
|
|||
setPage(Page.DistributionLists);
|
||||
}, []);
|
||||
|
||||
const [confirmDeleteListId, setConfirmDeleteListId] = useState<
|
||||
string | undefined
|
||||
const [confirmDeleteList, setConfirmDeleteList] = useState<
|
||||
{ id: string; name: string } | undefined
|
||||
>();
|
||||
|
||||
let modal: RenderModalPage | null;
|
||||
|
@ -188,7 +188,7 @@ export const StoriesSettingsModal = ({
|
|||
listToEdit={listToEdit}
|
||||
onRemoveMember={onRemoveMember}
|
||||
onRepliesNReactionsChanged={onRepliesNReactionsChanged}
|
||||
setConfirmDeleteListId={setConfirmDeleteListId}
|
||||
setConfirmDeleteList={setConfirmDeleteList}
|
||||
setMyStoriesToAllSignalConnections={setMyStoriesToAllSignalConnections}
|
||||
setPage={setPage}
|
||||
setSelectedContacts={setSelectedContacts}
|
||||
|
@ -297,13 +297,13 @@ export const StoriesSettingsModal = ({
|
|||
{modal}
|
||||
</PagedModal>
|
||||
)}
|
||||
{confirmDeleteListId && (
|
||||
{confirmDeleteList && (
|
||||
<ConfirmationDialog
|
||||
dialogName="StoriesSettings.deleteList"
|
||||
actions={[
|
||||
{
|
||||
action: () => {
|
||||
onDeleteList(confirmDeleteListId);
|
||||
onDeleteList(confirmDeleteList.id);
|
||||
setListToEditId(undefined);
|
||||
},
|
||||
style: 'negative',
|
||||
|
@ -312,10 +312,13 @@ export const StoriesSettingsModal = ({
|
|||
]}
|
||||
i18n={i18n}
|
||||
onClose={() => {
|
||||
setConfirmDeleteListId(undefined);
|
||||
setConfirmDeleteList(undefined);
|
||||
}}
|
||||
theme={Theme.Dark}
|
||||
>
|
||||
{i18n('StoriesSettings__delete-list--confirm')}
|
||||
{i18n('StoriesSettings__delete-list--confirm', [
|
||||
confirmDeleteList.name,
|
||||
])}
|
||||
</ConfirmationDialog>
|
||||
)}
|
||||
{confirmDiscardModal}
|
||||
|
@ -326,7 +329,7 @@ export const StoriesSettingsModal = ({
|
|||
type DistributionListSettingsModalPropsType = {
|
||||
i18n: LocalizerType;
|
||||
listToEdit: StoryDistributionListWithMembersDataType;
|
||||
setConfirmDeleteListId: (id: string) => unknown;
|
||||
setConfirmDeleteList: (_: { id: string; name: string }) => unknown;
|
||||
setPage: (page: Page) => unknown;
|
||||
setSelectedContacts: (contacts: Array<ConversationType>) => unknown;
|
||||
onBackButtonClick: (() => void) | undefined;
|
||||
|
@ -348,7 +351,7 @@ export const DistributionListSettingsModal = ({
|
|||
onRepliesNReactionsChanged,
|
||||
onBackButtonClick,
|
||||
onClose,
|
||||
setConfirmDeleteListId,
|
||||
setConfirmDeleteList,
|
||||
setMyStoriesToAllSignalConnections,
|
||||
setPage,
|
||||
setSelectedContacts,
|
||||
|
@ -504,7 +507,7 @@ export const DistributionListSettingsModal = ({
|
|||
|
||||
<button
|
||||
className="StoriesSettingsModal__delete-list"
|
||||
onClick={() => setConfirmDeleteListId(listToEdit.id)}
|
||||
onClick={() => setConfirmDeleteList(listToEdit)}
|
||||
type="button"
|
||||
>
|
||||
{i18n('StoriesSettings__delete-list')}
|
||||
|
@ -530,6 +533,7 @@ export const DistributionListSettingsModal = ({
|
|||
onClose={() => {
|
||||
setConfirmRemoveMember(undefined);
|
||||
}}
|
||||
theme={Theme.Dark}
|
||||
title={i18n('StoriesSettings__remove--title', [
|
||||
confirmRemoveMember.title,
|
||||
])}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type { ThunkAction, ThunkDispatch } from 'redux-thunk';
|
||||
import { isEqual, noop, pick } from 'lodash';
|
||||
import { isEqual, pick } from 'lodash';
|
||||
import type { AttachmentType } from '../../types/Attachment';
|
||||
import type { BodyRangeType } from '../../types/Util';
|
||||
import type { ConversationModel } from '../../models/conversations';
|
||||
|
@ -19,20 +19,18 @@ import type { SyncType } from '../../jobs/helpers/syncHelpers';
|
|||
import type { UUIDStringType } from '../../types/UUID';
|
||||
import * as log from '../../logging/log';
|
||||
import dataInterface from '../../sql/Client';
|
||||
import { DAY } from '../../util/durations';
|
||||
import { ReadStatus } from '../../messages/MessageReadStatus';
|
||||
import { SafetyNumberChangeSource } from '../../components/SafetyNumberChangeDialog';
|
||||
import { StoryViewDirectionType, StoryViewModeType } from '../../types/Stories';
|
||||
import { StoryRecipientUpdateEvent } from '../../textsecure/messageReceiverEvents';
|
||||
import { ToastReactionFailed } from '../../components/ToastReactionFailed';
|
||||
import { assertDev } from '../../util/assert';
|
||||
import { blockSendUntilConversationsAreVerified } from '../../util/blockSendUntilConversationsAreVerified';
|
||||
import { deleteStoryForEveryone as doDeleteStoryForEveryone } from '../../util/deleteStoryForEveryone';
|
||||
import { enqueueReactionForSend } from '../../reactions/enqueueReactionForSend';
|
||||
import { getMessageById } from '../../messages/getMessageById';
|
||||
import { markViewed } from '../../services/MessageUpdater';
|
||||
import { queueAttachmentDownloads } from '../../util/queueAttachmentDownloads';
|
||||
import { replaceIndex } from '../../util/replaceIndex';
|
||||
import { sendDeleteForEveryoneMessage } from '../../util/sendDeleteForEveryoneMessage';
|
||||
import { showToast } from '../../util/showToast';
|
||||
import {
|
||||
hasFailed,
|
||||
|
@ -44,13 +42,11 @@ import {
|
|||
getConversationSelector,
|
||||
getHideStoryConversationIds,
|
||||
} from '../selectors/conversations';
|
||||
import { getSendOptions } from '../../util/getSendOptions';
|
||||
import { getStories } from '../selectors/stories';
|
||||
import { getStoryDataFromMessageAttributes } from '../../services/storyLoader';
|
||||
import { isGroup } from '../../util/whatTypeOfConversation';
|
||||
import { isNotNil } from '../../util/isNotNil';
|
||||
import { isStory } from '../../messages/helpers';
|
||||
import { onStoryRecipientUpdate } from '../../util/onStoryRecipientUpdate';
|
||||
import { sendStoryMessage as doSendStoryMessage } from '../../util/sendStoryMessage';
|
||||
import { useBoundActions } from '../../hooks/useBoundActions';
|
||||
import { verifyStoryListMembers as doVerifyStoryListMembers } from '../../util/verifyStoryListMembers';
|
||||
|
@ -214,169 +210,13 @@ function deleteStoryForEveryone(
|
|||
return;
|
||||
}
|
||||
|
||||
const conversationIds = new Set(
|
||||
story.sendState.map(({ recipient }) => recipient.id)
|
||||
);
|
||||
const updatedStoryRecipients = new Map<
|
||||
string,
|
||||
{
|
||||
distributionListIds: Set<string>;
|
||||
isAllowedToReply: boolean;
|
||||
}
|
||||
>();
|
||||
|
||||
const ourConversation =
|
||||
window.ConversationController.getOurConversationOrThrow();
|
||||
|
||||
// Remove ourselves from the DOE.
|
||||
conversationIds.delete(ourConversation.id);
|
||||
|
||||
// Find stories that were sent to other distribution lists so that we don't
|
||||
// send a DOE request to the members of those lists.
|
||||
const { stories } = getState().stories;
|
||||
stories.forEach(item => {
|
||||
const { sendStateByConversationId } = item;
|
||||
// We only want matching timestamp stories which are stories that were
|
||||
// sent to multi distribution lists.
|
||||
// We don't want the story we just passed in.
|
||||
// Don't need to check for stories that have already been deleted.
|
||||
// And only for sent stories, not incoming.
|
||||
if (
|
||||
item.timestamp !== story.timestamp ||
|
||||
item.messageId === story.messageId ||
|
||||
item.deletedForEveryone ||
|
||||
!sendStateByConversationId
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
Object.keys(sendStateByConversationId).forEach(conversationId => {
|
||||
if (conversationId === ourConversation.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
const destinationUuid =
|
||||
window.ConversationController.get(conversationId)?.get('uuid');
|
||||
|
||||
if (!destinationUuid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const distributionListIds =
|
||||
updatedStoryRecipients.get(destinationUuid)?.distributionListIds ||
|
||||
new Set();
|
||||
|
||||
// These are the remaining distribution list ids that the user has
|
||||
// access to.
|
||||
updatedStoryRecipients.set(destinationUuid, {
|
||||
distributionListIds: item.storyDistributionListId
|
||||
? new Set([...distributionListIds, item.storyDistributionListId])
|
||||
: distributionListIds,
|
||||
isAllowedToReply:
|
||||
sendStateByConversationId[conversationId]
|
||||
.isAllowedToReplyToStory !== false,
|
||||
});
|
||||
|
||||
// Remove this conversationId so we don't send the DOE to those that
|
||||
// still have access.
|
||||
conversationIds.delete(conversationId);
|
||||
});
|
||||
});
|
||||
|
||||
// Send the DOE
|
||||
conversationIds.forEach(cid => {
|
||||
// Don't DOE yourself!
|
||||
if (cid === ourConversation.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
const conversation = window.ConversationController.get(cid);
|
||||
|
||||
if (!conversation) {
|
||||
return;
|
||||
}
|
||||
|
||||
sendDeleteForEveryoneMessage(conversation.attributes, {
|
||||
deleteForEveryoneDuration: DAY,
|
||||
id: story.messageId,
|
||||
timestamp: story.timestamp,
|
||||
});
|
||||
});
|
||||
|
||||
// If it's the last story sent to a distribution list we don't have to send
|
||||
// the sync message, but to be consistent let's build up the updated
|
||||
// storyMessageRecipients and send the sync message.
|
||||
if (!updatedStoryRecipients.size) {
|
||||
story.sendState.forEach(item => {
|
||||
if (item.recipient.id === ourConversation.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
const destinationUuid = window.ConversationController.get(
|
||||
item.recipient.id
|
||||
)?.get('uuid');
|
||||
|
||||
if (!destinationUuid) {
|
||||
return;
|
||||
}
|
||||
|
||||
updatedStoryRecipients.set(destinationUuid, {
|
||||
distributionListIds: new Set(),
|
||||
isAllowedToReply: item.isAllowedToReplyToStory !== false,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Send the sync message with the updated storyMessageRecipients list
|
||||
const sender = window.textsecure.messaging;
|
||||
if (sender) {
|
||||
const options = await getSendOptions(ourConversation.attributes, {
|
||||
syncMessage: true,
|
||||
});
|
||||
|
||||
const storyMessageRecipients: Array<{
|
||||
destinationUuid: string;
|
||||
distributionListIds: Array<string>;
|
||||
isAllowedToReply: boolean;
|
||||
}> = [];
|
||||
|
||||
updatedStoryRecipients.forEach((recipientData, destinationUuid) => {
|
||||
storyMessageRecipients.push({
|
||||
destinationUuid,
|
||||
distributionListIds: Array.from(recipientData.distributionListIds),
|
||||
isAllowedToReply: recipientData.isAllowedToReply,
|
||||
});
|
||||
});
|
||||
|
||||
const destinationUuid = ourConversation.get('uuid');
|
||||
|
||||
if (!destinationUuid) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Sync message for other devices
|
||||
sender.sendSyncMessage({
|
||||
destination: undefined,
|
||||
destinationUuid,
|
||||
storyMessageRecipients,
|
||||
expirationStartTimestamp: null,
|
||||
isUpdate: true,
|
||||
options,
|
||||
timestamp: story.timestamp,
|
||||
urgent: false,
|
||||
});
|
||||
|
||||
// Sync message for Desktop
|
||||
const ev = new StoryRecipientUpdateEvent(
|
||||
{
|
||||
destinationUuid,
|
||||
timestamp: story.timestamp,
|
||||
storyMessageRecipients,
|
||||
},
|
||||
noop
|
||||
);
|
||||
onStoryRecipientUpdate(ev);
|
||||
const storyData = stories.find(item => item.messageId === story.messageId);
|
||||
if (!storyData) {
|
||||
log.warn('deleteStoryForEveryone: Could not find story in redux data');
|
||||
return;
|
||||
}
|
||||
await doDeleteStoryForEveryone(stories, storyData);
|
||||
|
||||
dispatch({
|
||||
type: DOE_STORY,
|
||||
|
|
|
@ -10,6 +10,7 @@ import * as log from '../../logging/log';
|
|||
import dataInterface from '../../sql/Client';
|
||||
import { MY_STORIES_ID } from '../../types/Stories';
|
||||
import { UUID } from '../../types/UUID';
|
||||
import { deleteStoryForEveryone } from '../../util/deleteStoryForEveryone';
|
||||
import { replaceIndex } from '../../util/replaceIndex';
|
||||
import { storageServiceUploadJob } from '../../services/storage';
|
||||
import { useBoundActions } from '../../hooks/useBoundActions';
|
||||
|
@ -201,7 +202,7 @@ function createDistributionList(
|
|||
function deleteDistributionList(
|
||||
listId: string
|
||||
): ThunkAction<void, RootStateType, unknown, DeleteListActionType> {
|
||||
return async dispatch => {
|
||||
return async (dispatch, getState) => {
|
||||
const deletedAtTimestamp = Date.now();
|
||||
|
||||
const storyDistribution =
|
||||
|
@ -225,6 +226,14 @@ function deleteDistributionList(
|
|||
}
|
||||
);
|
||||
|
||||
const { stories } = getState().stories;
|
||||
const storiesToDelete = stories.filter(
|
||||
story => story.storyDistributionListId === listId
|
||||
);
|
||||
await Promise.all(
|
||||
storiesToDelete.map(story => deleteStoryForEveryone(stories, story))
|
||||
);
|
||||
|
||||
log.info(
|
||||
'storyDistributionLists.deleteDistributionList: list deleted',
|
||||
listId
|
||||
|
|
181
ts/util/deleteStoryForEveryone.ts
Normal file
181
ts/util/deleteStoryForEveryone.ts
Normal file
|
@ -0,0 +1,181 @@
|
|||
// Copyright 2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { noop } from 'lodash';
|
||||
import type { StoryDataType } from '../state/ducks/stories';
|
||||
import { DAY } from './durations';
|
||||
import { StoryRecipientUpdateEvent } from '../textsecure/messageReceiverEvents';
|
||||
import { getSendOptions } from './getSendOptions';
|
||||
import { onStoryRecipientUpdate } from './onStoryRecipientUpdate';
|
||||
import { sendDeleteForEveryoneMessage } from './sendDeleteForEveryoneMessage';
|
||||
|
||||
export async function deleteStoryForEveryone(
|
||||
stories: Array<StoryDataType>,
|
||||
story: StoryDataType
|
||||
): Promise<void> {
|
||||
if (!story.sendStateByConversationId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const conversationIds = new Set(Object.keys(story.sendStateByConversationId));
|
||||
const updatedStoryRecipients = new Map<
|
||||
string,
|
||||
{
|
||||
distributionListIds: Set<string>;
|
||||
isAllowedToReply: boolean;
|
||||
}
|
||||
>();
|
||||
|
||||
const ourConversation =
|
||||
window.ConversationController.getOurConversationOrThrow();
|
||||
|
||||
// Remove ourselves from the DOE.
|
||||
conversationIds.delete(ourConversation.id);
|
||||
|
||||
// Find stories that were sent to other distribution lists so that we don't
|
||||
// send a DOE request to the members of those lists.
|
||||
stories.forEach(item => {
|
||||
const { sendStateByConversationId } = item;
|
||||
// We only want matching timestamp stories which are stories that were
|
||||
// sent to multi distribution lists.
|
||||
// We don't want the story we just passed in.
|
||||
// Don't need to check for stories that have already been deleted.
|
||||
// And only for sent stories, not incoming.
|
||||
if (
|
||||
item.timestamp !== story.timestamp ||
|
||||
item.messageId === story.messageId ||
|
||||
item.deletedForEveryone ||
|
||||
!sendStateByConversationId
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
Object.keys(sendStateByConversationId).forEach(conversationId => {
|
||||
if (conversationId === ourConversation.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
const destinationUuid =
|
||||
window.ConversationController.get(conversationId)?.get('uuid');
|
||||
|
||||
if (!destinationUuid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const distributionListIds =
|
||||
updatedStoryRecipients.get(destinationUuid)?.distributionListIds ||
|
||||
new Set();
|
||||
|
||||
// These are the remaining distribution list ids that the user has
|
||||
// access to.
|
||||
updatedStoryRecipients.set(destinationUuid, {
|
||||
distributionListIds: item.storyDistributionListId
|
||||
? new Set([...distributionListIds, item.storyDistributionListId])
|
||||
: distributionListIds,
|
||||
isAllowedToReply:
|
||||
sendStateByConversationId[conversationId].isAllowedToReplyToStory !==
|
||||
false,
|
||||
});
|
||||
|
||||
// Remove this conversationId so we don't send the DOE to those that
|
||||
// still have access.
|
||||
conversationIds.delete(conversationId);
|
||||
});
|
||||
});
|
||||
|
||||
// Send the DOE
|
||||
conversationIds.forEach(cid => {
|
||||
// Don't DOE yourself!
|
||||
if (cid === ourConversation.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
const conversation = window.ConversationController.get(cid);
|
||||
|
||||
if (!conversation) {
|
||||
return;
|
||||
}
|
||||
|
||||
sendDeleteForEveryoneMessage(conversation.attributes, {
|
||||
deleteForEveryoneDuration: DAY,
|
||||
id: story.messageId,
|
||||
timestamp: story.timestamp,
|
||||
});
|
||||
});
|
||||
|
||||
// If it's the last story sent to a distribution list we don't have to send
|
||||
// the sync message, but to be consistent let's build up the updated
|
||||
// storyMessageRecipients and send the sync message.
|
||||
if (!updatedStoryRecipients.size) {
|
||||
Object.entries(story.sendStateByConversationId).forEach(
|
||||
([recipientId, sendState]) => {
|
||||
if (recipientId === ourConversation.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
const destinationUuid =
|
||||
window.ConversationController.get(recipientId)?.get('uuid');
|
||||
|
||||
if (!destinationUuid) {
|
||||
return;
|
||||
}
|
||||
|
||||
updatedStoryRecipients.set(destinationUuid, {
|
||||
distributionListIds: new Set(),
|
||||
isAllowedToReply: sendState.isAllowedToReplyToStory !== false,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Send the sync message with the updated storyMessageRecipients list
|
||||
const sender = window.textsecure.messaging;
|
||||
if (sender) {
|
||||
const options = await getSendOptions(ourConversation.attributes, {
|
||||
syncMessage: true,
|
||||
});
|
||||
|
||||
const storyMessageRecipients: Array<{
|
||||
destinationUuid: string;
|
||||
distributionListIds: Array<string>;
|
||||
isAllowedToReply: boolean;
|
||||
}> = [];
|
||||
|
||||
updatedStoryRecipients.forEach((recipientData, destinationUuid) => {
|
||||
storyMessageRecipients.push({
|
||||
destinationUuid,
|
||||
distributionListIds: Array.from(recipientData.distributionListIds),
|
||||
isAllowedToReply: recipientData.isAllowedToReply,
|
||||
});
|
||||
});
|
||||
|
||||
const destinationUuid = ourConversation.get('uuid');
|
||||
|
||||
if (!destinationUuid) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Sync message for other devices
|
||||
sender.sendSyncMessage({
|
||||
destination: undefined,
|
||||
destinationUuid,
|
||||
storyMessageRecipients,
|
||||
expirationStartTimestamp: null,
|
||||
isUpdate: true,
|
||||
options,
|
||||
timestamp: story.timestamp,
|
||||
urgent: false,
|
||||
});
|
||||
|
||||
// Sync message for Desktop
|
||||
const ev = new StoryRecipientUpdateEvent(
|
||||
{
|
||||
destinationUuid,
|
||||
timestamp: story.timestamp,
|
||||
storyMessageRecipients,
|
||||
},
|
||||
noop
|
||||
);
|
||||
onStoryRecipientUpdate(ev);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue