Keep story creator around until we've verified contacts and queued job
This commit is contained in:
parent
4fc1b6388c
commit
9fba33943a
11 changed files with 178 additions and 41 deletions
|
@ -587,6 +587,7 @@ export const CompositionArea = ({
|
|||
<MediaEditor
|
||||
i18n={i18n}
|
||||
imageSrc={attachmentToEdit.url}
|
||||
isSending={false}
|
||||
onClose={() => setAttachmentToEdit(undefined)}
|
||||
onDone={data => {
|
||||
const newAttachment = {
|
||||
|
|
|
@ -27,6 +27,7 @@ const getDefaultProps = (): PropsType => ({
|
|||
imageSrc: IMAGE_2,
|
||||
onClose: action('onClose'),
|
||||
onDone: action('onDone'),
|
||||
isSending: false,
|
||||
|
||||
// StickerButtonProps
|
||||
installedPacks,
|
||||
|
@ -49,6 +50,10 @@ export const Portrait = (): JSX.Element => (
|
|||
<MediaEditor {...getDefaultProps()} imageSrc={IMAGE_4} />
|
||||
);
|
||||
|
||||
export const Sending = (): JSX.Element => (
|
||||
<MediaEditor {...getDefaultProps()} isSending />
|
||||
);
|
||||
|
||||
export const WithCaption = (): JSX.Element => (
|
||||
<MediaEditor
|
||||
{...getDefaultProps()}
|
||||
|
|
|
@ -39,11 +39,13 @@ import type { SmartCompositionTextAreaProps } from '../state/smart/CompositionTe
|
|||
import { Emojify } from './conversation/Emojify';
|
||||
import { AddNewLines } from './conversation/AddNewLines';
|
||||
import { useConfirmDiscard } from '../hooks/useConfirmDiscard';
|
||||
import { Spinner } from './Spinner';
|
||||
|
||||
export type PropsType = {
|
||||
doneButtonLabel?: string;
|
||||
i18n: LocalizerType;
|
||||
imageSrc: string;
|
||||
isSending: boolean;
|
||||
onClose: () => unknown;
|
||||
onDone: (data: Uint8Array, caption?: string | undefined) => unknown;
|
||||
} & Pick<StickerButtonProps, 'installedPacks' | 'recentStickers'> &
|
||||
|
@ -106,6 +108,7 @@ export const MediaEditor = ({
|
|||
doneButtonLabel,
|
||||
i18n,
|
||||
imageSrc,
|
||||
isSending,
|
||||
onClose,
|
||||
onDone,
|
||||
|
||||
|
@ -1102,7 +1105,7 @@ export const MediaEditor = ({
|
|||
/>
|
||||
</div>
|
||||
<Button
|
||||
disabled={!image || isSaving}
|
||||
disabled={!image || isSaving || isSending}
|
||||
onClick={async () => {
|
||||
if (!fabricCanvas) {
|
||||
return;
|
||||
|
@ -1160,7 +1163,11 @@ export const MediaEditor = ({
|
|||
theme={Theme.Dark}
|
||||
variant={ButtonVariant.Primary}
|
||||
>
|
||||
{doneButtonLabel || i18n('save')}
|
||||
{isSending ? (
|
||||
<Spinner svgSize="small" />
|
||||
) : (
|
||||
doneButtonLabel || i18n('save')
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -14,9 +14,9 @@ import type {
|
|||
} from '../types/Stories';
|
||||
import type { LocalizerType } from '../types/Util';
|
||||
import type { PreferredBadgeSelectorType } from '../state/selectors/badges';
|
||||
import type { PropsType as SmartStoryCreatorPropsType } from '../state/smart/StoryCreator';
|
||||
import type { ShowToastActionCreatorType } from '../state/ducks/toast';
|
||||
import type {
|
||||
AddStoryData,
|
||||
ViewUserStoriesActionCreatorType,
|
||||
ViewStoryActionCreatorType,
|
||||
} from '../state/ducks/stories';
|
||||
|
@ -27,6 +27,7 @@ import { getWidthFromPreferredWidth } from '../util/leftPaneWidth';
|
|||
import { useEscapeHandling } from '../hooks/useEscapeHandling';
|
||||
|
||||
export type PropsType = {
|
||||
addStoryData: AddStoryData;
|
||||
deleteStoryForEveryone: (story: StoryViewType) => unknown;
|
||||
getPreferredBadge: PreferredBadgeSelectorType;
|
||||
hiddenStories: Array<ConversationStoryType>;
|
||||
|
@ -37,7 +38,8 @@ export type PropsType = {
|
|||
onSaveStory: (story: StoryViewType) => unknown;
|
||||
preferredWidthFromStorage: number;
|
||||
queueStoryDownload: (storyId: string) => unknown;
|
||||
renderStoryCreator: (props: SmartStoryCreatorPropsType) => JSX.Element;
|
||||
renderStoryCreator: () => JSX.Element;
|
||||
setAddStoryData: (data: AddStoryData) => unknown;
|
||||
showConversation: ShowConversationType;
|
||||
showStoriesSettings: () => unknown;
|
||||
showToast: ShowToastActionCreatorType;
|
||||
|
@ -51,15 +53,8 @@ export type PropsType = {
|
|||
hasViewReceiptSetting: boolean;
|
||||
};
|
||||
|
||||
type AddStoryType =
|
||||
| {
|
||||
type: 'Media';
|
||||
file: File;
|
||||
}
|
||||
| { type: 'Text' }
|
||||
| undefined;
|
||||
|
||||
export const Stories = ({
|
||||
addStoryData,
|
||||
deleteStoryForEveryone,
|
||||
getPreferredBadge,
|
||||
hiddenStories,
|
||||
|
@ -71,6 +66,7 @@ export const Stories = ({
|
|||
preferredWidthFromStorage,
|
||||
queueStoryDownload,
|
||||
renderStoryCreator,
|
||||
setAddStoryData,
|
||||
showConversation,
|
||||
showStoriesSettings,
|
||||
showToast,
|
||||
|
@ -87,7 +83,6 @@ export const Stories = ({
|
|||
requiresFullWidth: true,
|
||||
});
|
||||
|
||||
const [addStoryData, setAddStoryData] = useState<AddStoryType>();
|
||||
const [isMyStories, setIsMyStories] = useState(false);
|
||||
|
||||
// only handle ESC if not showing a child that handles their own ESC
|
||||
|
@ -102,11 +97,7 @@ export const Stories = ({
|
|||
|
||||
return (
|
||||
<div className={classNames('Stories', themeClassName(Theme.Dark))}>
|
||||
{addStoryData &&
|
||||
renderStoryCreator({
|
||||
file: addStoryData.type === 'Media' ? addStoryData.file : undefined,
|
||||
onClose: () => setAddStoryData(undefined),
|
||||
})}
|
||||
{addStoryData && renderStoryCreator()}
|
||||
<div className="Stories__pane" style={{ width }}>
|
||||
{isMyStories && myStories.length ? (
|
||||
<MyStories
|
||||
|
|
|
@ -40,6 +40,9 @@ export default {
|
|||
installedPacks: {
|
||||
defaultValue: [],
|
||||
},
|
||||
isSending: {
|
||||
defaultValue: false,
|
||||
},
|
||||
linkPreview: {
|
||||
defaultValue: undefined,
|
||||
},
|
||||
|
@ -95,3 +98,8 @@ FirstTime.args = {
|
|||
FirstTime.story = {
|
||||
name: 'First time posting a story',
|
||||
};
|
||||
|
||||
export const Sending = Template.bind({});
|
||||
Sending.args = {
|
||||
isSending: true,
|
||||
};
|
||||
|
|
|
@ -30,6 +30,7 @@ export type PropsType = {
|
|||
) => unknown;
|
||||
file?: File;
|
||||
i18n: LocalizerType;
|
||||
isSending: boolean;
|
||||
linkPreview?: LinkPreviewType;
|
||||
onClose: () => unknown;
|
||||
onSend: (
|
||||
|
@ -78,6 +79,7 @@ export const StoryCreator = ({
|
|||
hasFirstStoryPostExperience,
|
||||
i18n,
|
||||
installedPacks,
|
||||
isSending,
|
||||
linkPreview,
|
||||
me,
|
||||
onClose,
|
||||
|
@ -162,7 +164,6 @@ export const StoryCreator = ({
|
|||
onSend={(listIds, groupIds) => {
|
||||
onSend(listIds, groupIds, draftAttachment);
|
||||
setDraftAttachment(undefined);
|
||||
onClose();
|
||||
}}
|
||||
onViewersUpdated={onViewersUpdated}
|
||||
setMyStoriesToAllSignalConnections={
|
||||
|
@ -179,6 +180,7 @@ export const StoryCreator = ({
|
|||
i18n={i18n}
|
||||
imageSrc={attachmentUrl}
|
||||
installedPacks={installedPacks}
|
||||
isSending={isSending}
|
||||
onClose={onClose}
|
||||
supportsCaption
|
||||
renderCompositionTextArea={renderCompositionTextArea}
|
||||
|
@ -197,6 +199,7 @@ export const StoryCreator = ({
|
|||
<TextStoryCreator
|
||||
debouncedMaybeGrabLinkPreview={debouncedMaybeGrabLinkPreview}
|
||||
i18n={i18n}
|
||||
isSending={isSending}
|
||||
linkPreview={linkPreview}
|
||||
onClose={onClose}
|
||||
onDone={textAttachment => {
|
||||
|
|
|
@ -29,6 +29,7 @@ import {
|
|||
import { objectMap } from '../util/objectMap';
|
||||
import { handleOutsideClick } from '../util/handleOutsideClick';
|
||||
import { ConfirmDiscardDialog } from './ConfirmDiscardDialog';
|
||||
import { Spinner } from './Spinner';
|
||||
|
||||
export type PropsType = {
|
||||
debouncedMaybeGrabLinkPreview: (
|
||||
|
@ -37,6 +38,7 @@ export type PropsType = {
|
|||
options?: MaybeGrabLinkPreviewOptionsType
|
||||
) => unknown;
|
||||
i18n: LocalizerType;
|
||||
isSending: boolean;
|
||||
linkPreview?: LinkPreviewType;
|
||||
onClose: () => unknown;
|
||||
onDone: (textAttachment: TextAttachmentType) => unknown;
|
||||
|
@ -122,6 +124,7 @@ function getBgButtonAriaLabel(
|
|||
export const TextStoryCreator = ({
|
||||
debouncedMaybeGrabLinkPreview,
|
||||
i18n,
|
||||
isSending,
|
||||
linkPreview,
|
||||
onClose,
|
||||
onDone,
|
||||
|
@ -566,12 +569,16 @@ export const TextStoryCreator = ({
|
|||
)}
|
||||
</div>
|
||||
<Button
|
||||
disabled={!hasChanges}
|
||||
disabled={!hasChanges || isSending}
|
||||
onClick={() => onDone(textAttachment)}
|
||||
theme={Theme.Dark}
|
||||
variant={ButtonVariant.Primary}
|
||||
>
|
||||
{i18n('StoryCreator__next')}
|
||||
{isSending ? (
|
||||
<Spinner svgSize="small" />
|
||||
) : (
|
||||
i18n('StoryCreator__next')
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
import type { ThunkAction, ThunkDispatch } from 'redux-thunk';
|
||||
import { isEqual, pick } from 'lodash';
|
||||
|
||||
import * as Errors from '../../types/errors';
|
||||
import type { AttachmentType } from '../../types/Attachment';
|
||||
import type { BodyRangeType } from '../../types/Util';
|
||||
import type { ConversationModel } from '../../models/conversations';
|
||||
|
@ -87,6 +89,18 @@ export type SelectedStoryDataType = {
|
|||
viewTarget?: StoryViewTargetType;
|
||||
};
|
||||
|
||||
export type AddStoryData =
|
||||
| {
|
||||
type: 'Media';
|
||||
file: File;
|
||||
sending?: boolean;
|
||||
}
|
||||
| {
|
||||
type: 'Text';
|
||||
sending?: boolean;
|
||||
}
|
||||
| undefined;
|
||||
|
||||
// State
|
||||
|
||||
export type StoriesStateType = {
|
||||
|
@ -97,6 +111,7 @@ export type StoriesStateType = {
|
|||
replies: Array<MessageAttributesType>;
|
||||
};
|
||||
readonly selectedStoryData?: SelectedStoryDataType;
|
||||
readonly addStoryData: AddStoryData;
|
||||
readonly sendStoryModalData?: {
|
||||
untrustedUuids: Array<string>;
|
||||
verifiedUuids: Array<string>;
|
||||
|
@ -117,6 +132,8 @@ const STORY_CHANGED = 'stories/STORY_CHANGED';
|
|||
const TOGGLE_VIEW = 'stories/TOGGLE_VIEW';
|
||||
const VIEW_STORY = 'stories/VIEW_STORY';
|
||||
const REMOVE_ALL_STORIES = 'stories/REMOVE_ALL_STORIES';
|
||||
const SET_ADD_STORY_DATA = 'stories/SET_ADD_STORY_DATA';
|
||||
const SET_STORY_SENDING = 'stories/SET_STORY_SENDING';
|
||||
|
||||
type DOEStoryActionType = {
|
||||
type: typeof DOE_STORY;
|
||||
|
@ -175,6 +192,16 @@ type RemoveAllStoriesActionType = {
|
|||
type: typeof REMOVE_ALL_STORIES;
|
||||
};
|
||||
|
||||
type SetAddStoryDataType = {
|
||||
type: typeof SET_ADD_STORY_DATA;
|
||||
payload: AddStoryData;
|
||||
};
|
||||
|
||||
type SetStorySendingType = {
|
||||
type: typeof SET_STORY_SENDING;
|
||||
payload: boolean;
|
||||
};
|
||||
|
||||
export type StoriesActionType =
|
||||
| DOEStoryActionType
|
||||
| ListMembersVerified
|
||||
|
@ -188,7 +215,9 @@ export type StoriesActionType =
|
|||
| StoryChangedActionType
|
||||
| ToggleViewActionType
|
||||
| ViewStoryActionType
|
||||
| RemoveAllStoriesActionType;
|
||||
| RemoveAllStoriesActionType
|
||||
| SetAddStoryDataType
|
||||
| SetStorySendingType;
|
||||
|
||||
// Action Creators
|
||||
|
||||
|
@ -451,10 +480,22 @@ function sendStoryMessage(
|
|||
listIds: Array<UUIDStringType>,
|
||||
conversationIds: Array<string>,
|
||||
attachment: AttachmentType
|
||||
): ThunkAction<void, RootStateType, unknown, SendStoryModalOpenStateChanged> {
|
||||
): ThunkAction<
|
||||
void,
|
||||
RootStateType,
|
||||
unknown,
|
||||
SendStoryModalOpenStateChanged | SetStorySendingType | SetAddStoryDataType
|
||||
> {
|
||||
return async (dispatch, getState) => {
|
||||
const { stories } = getState();
|
||||
const { openedAtTimestamp, sendStoryModalData } = stories;
|
||||
|
||||
// Add spinners in the story creator
|
||||
dispatch({
|
||||
type: SET_STORY_SENDING,
|
||||
payload: true,
|
||||
});
|
||||
|
||||
assertDev(
|
||||
openedAtTimestamp,
|
||||
'sendStoryMessage: openedAtTimestamp is undefined, cannot send'
|
||||
|
@ -464,11 +505,6 @@ function sendStoryMessage(
|
|||
'sendStoryMessage: sendStoryModalData is not defined, cannot send'
|
||||
);
|
||||
|
||||
dispatch({
|
||||
type: SEND_STORY_MODAL_OPEN_STATE_CHANGED,
|
||||
payload: undefined,
|
||||
});
|
||||
|
||||
if (sendStoryModalData.untrustedUuids.length) {
|
||||
log.info('sendStoryMessage: SN changed for some conversations');
|
||||
|
||||
|
@ -491,12 +527,39 @@ function sendStoryMessage(
|
|||
);
|
||||
|
||||
if (!result) {
|
||||
log.info('sendStoryMessage: did not send');
|
||||
log.info('sendStoryMessage: failed to verify untrusted; stopping send');
|
||||
dispatch({
|
||||
type: SET_STORY_SENDING,
|
||||
payload: false,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear all untrusted and verified uuids; we're clear to send!
|
||||
dispatch({
|
||||
type: SEND_STORY_MODAL_OPEN_STATE_CHANGED,
|
||||
payload: undefined,
|
||||
});
|
||||
}
|
||||
|
||||
await doSendStoryMessage(listIds, conversationIds, attachment);
|
||||
try {
|
||||
await doSendStoryMessage(listIds, conversationIds, attachment);
|
||||
|
||||
// Note: Only when we've successfully queued the message do we dismiss the story
|
||||
// composer view.
|
||||
dispatch({
|
||||
type: SET_ADD_STORY_DATA,
|
||||
payload: undefined,
|
||||
});
|
||||
} catch (error) {
|
||||
log.error('sendStoryMessage:', Errors.toLogFormat(error));
|
||||
|
||||
// Get rid of spinners in the story creator
|
||||
dispatch({
|
||||
type: SET_STORY_SENDING,
|
||||
payload: false,
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1111,6 +1174,20 @@ const viewStory: ViewStoryActionCreatorType = (
|
|||
};
|
||||
};
|
||||
|
||||
function setAddStoryData(addStoryData: AddStoryData): SetAddStoryDataType {
|
||||
return {
|
||||
type: SET_ADD_STORY_DATA,
|
||||
payload: addStoryData,
|
||||
};
|
||||
}
|
||||
|
||||
function setStorySending(sending: boolean): SetStorySendingType {
|
||||
return {
|
||||
type: SET_STORY_SENDING,
|
||||
payload: sending,
|
||||
};
|
||||
}
|
||||
|
||||
function setStoriesDisabled(
|
||||
value: boolean
|
||||
): ThunkAction<void, RootStateType, unknown, never> {
|
||||
|
@ -1134,7 +1211,9 @@ export const actions = {
|
|||
verifyStoryListMembers,
|
||||
viewUserStories,
|
||||
viewStory,
|
||||
setAddStoryData,
|
||||
setStoriesDisabled,
|
||||
setStorySending,
|
||||
};
|
||||
|
||||
export const useStoriesActions = (): typeof actions => useBoundActions(actions);
|
||||
|
@ -1147,6 +1226,7 @@ export function getEmptyState(
|
|||
return {
|
||||
lastOpenedAtTimestamp: undefined,
|
||||
openedAtTimestamp: undefined,
|
||||
addStoryData: undefined,
|
||||
stories: [],
|
||||
...overrideState,
|
||||
};
|
||||
|
@ -1475,5 +1555,31 @@ export function reducer(
|
|||
};
|
||||
}
|
||||
|
||||
if (action.type === SET_ADD_STORY_DATA) {
|
||||
return {
|
||||
...state,
|
||||
addStoryData: action.payload,
|
||||
};
|
||||
}
|
||||
|
||||
if (action.type === SET_STORY_SENDING) {
|
||||
const existing = state.addStoryData;
|
||||
|
||||
if (!existing) {
|
||||
log.warn(
|
||||
'stories/reducer: Set story sending, but no existing addStoryData'
|
||||
);
|
||||
return state;
|
||||
}
|
||||
|
||||
return {
|
||||
...state,
|
||||
addStoryData: {
|
||||
...existing,
|
||||
sending: action.payload,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import type {
|
|||
SelectedStoryDataType,
|
||||
StoryDataType,
|
||||
StoriesStateType,
|
||||
AddStoryData,
|
||||
} from '../ducks/stories';
|
||||
import { HasStories, MY_STORIES_ID } from '../../types/Stories';
|
||||
import { ReadStatus } from '../../messages/MessageReadStatus';
|
||||
|
@ -58,6 +59,11 @@ export const getSelectedStoryData = createSelector(
|
|||
selectedStoryData
|
||||
);
|
||||
|
||||
export const getAddStoryData = createSelector(
|
||||
getStoriesState,
|
||||
({ addStoryData }): AddStoryData => addStoryData
|
||||
);
|
||||
|
||||
function getReactionUniqueId(reaction: MessageReactionType): string {
|
||||
return `${reaction.fromId}:${reaction.targetAuthorUuid}:${reaction.timestamp}`;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import { useSelector } from 'react-redux';
|
|||
|
||||
import type { LocalizerType } from '../../types/Util';
|
||||
import type { StateType } from '../reducer';
|
||||
import type { PropsType as SmartStoryCreatorPropsType } from './StoryCreator';
|
||||
import { SmartStoryCreator } from './StoryCreator';
|
||||
import { Stories } from '../../components/Stories';
|
||||
import { getMe } from '../selectors/conversations';
|
||||
|
@ -17,6 +16,7 @@ import {
|
|||
getPreferredLeftPaneWidth,
|
||||
} from '../selectors/items';
|
||||
import {
|
||||
getAddStoryData,
|
||||
getSelectedStoryData,
|
||||
getStories,
|
||||
shouldShowStoriesView,
|
||||
|
@ -27,11 +27,8 @@ import { useGlobalModalActions } from '../ducks/globalModals';
|
|||
import { useStoriesActions } from '../ducks/stories';
|
||||
import { useToastActions } from '../ducks/toast';
|
||||
|
||||
function renderStoryCreator({
|
||||
file,
|
||||
onClose,
|
||||
}: SmartStoryCreatorPropsType): JSX.Element {
|
||||
return <SmartStoryCreator file={file} onClose={onClose} />;
|
||||
function renderStoryCreator(): JSX.Element {
|
||||
return <SmartStoryCreator />;
|
||||
}
|
||||
|
||||
export function SmartStories(): JSX.Element | null {
|
||||
|
@ -52,6 +49,7 @@ export function SmartStories(): JSX.Element | null {
|
|||
);
|
||||
const getPreferredBadge = useSelector(getPreferredBadgeSelector);
|
||||
|
||||
const addStoryData = useSelector(getAddStoryData);
|
||||
const { hiddenStories, myStories, stories } = useSelector(getStories);
|
||||
|
||||
const me = useSelector(getMe);
|
||||
|
@ -70,6 +68,7 @@ export function SmartStories(): JSX.Element | null {
|
|||
|
||||
return (
|
||||
<Stories
|
||||
addStoryData={addStoryData}
|
||||
getPreferredBadge={getPreferredBadge}
|
||||
hiddenStories={hiddenStories}
|
||||
i18n={i18n}
|
||||
|
|
|
@ -31,21 +31,20 @@ import { useLinkPreviewActions } from '../ducks/linkPreviews';
|
|||
import { useStoriesActions } from '../ducks/stories';
|
||||
import { useStoryDistributionListsActions } from '../ducks/storyDistributionLists';
|
||||
import { SmartCompositionTextArea } from './CompositionTextArea';
|
||||
import { getAddStoryData } from '../selectors/stories';
|
||||
|
||||
export type PropsType = {
|
||||
file?: File;
|
||||
onClose: () => unknown;
|
||||
};
|
||||
|
||||
export function SmartStoryCreator({
|
||||
file,
|
||||
onClose,
|
||||
}: PropsType): JSX.Element | null {
|
||||
export function SmartStoryCreator(): JSX.Element | null {
|
||||
const { debouncedMaybeGrabLinkPreview } = useLinkPreviewActions();
|
||||
const {
|
||||
sendStoryModalOpenStateChanged,
|
||||
sendStoryMessage,
|
||||
verifyStoryListMembers,
|
||||
setAddStoryData,
|
||||
} = useStoriesActions();
|
||||
const { toggleGroupsForStorySend } = useConversationsActions();
|
||||
const {
|
||||
|
@ -72,6 +71,10 @@ export function SmartStoryCreator({
|
|||
const recentStickers = useSelector(getRecentStickers);
|
||||
const signalConnections = useSelector(getAllSignalConnections);
|
||||
|
||||
const addStoryData = useSelector(getAddStoryData);
|
||||
const file = addStoryData?.type === 'Media' ? addStoryData.file : undefined;
|
||||
const isSending = addStoryData?.sending || false;
|
||||
|
||||
return (
|
||||
<StoryCreator
|
||||
candidateConversations={candidateConversations}
|
||||
|
@ -84,9 +87,10 @@ export function SmartStoryCreator({
|
|||
hasFirstStoryPostExperience={!hasSetMyStoriesPrivacy}
|
||||
i18n={i18n}
|
||||
installedPacks={installedPacks}
|
||||
isSending={isSending}
|
||||
linkPreview={linkPreviewForSource(LinkPreviewSourceType.StoryCreator)}
|
||||
me={me}
|
||||
onClose={onClose}
|
||||
onClose={() => setAddStoryData(undefined)}
|
||||
onDeleteList={deleteDistributionList}
|
||||
onDistributionListCreated={createDistributionList}
|
||||
onHideMyStoriesFrom={hideMyStoriesFrom}
|
||||
|
|
Loading…
Add table
Reference in a new issue