@@ -7,6 +7,7 @@ import React, {
77 useState ,
88} from 'react' ;
99import classNames from 'classnames' ;
10+ import { useQueryClient } from '@tanstack/react-query' ;
1011import type { LazyModalCommonProps } from '../common/Modal' ;
1112import { Modal } from '../common/Modal' ;
1213import { ModalKind , ModalSize } from '../common/types' ;
@@ -30,7 +31,8 @@ import { useLogContext } from '../../../contexts/LogContext';
3031import { LogEvent } from '../../../lib/log' ;
3132import { useViewSize , ViewSize } from '../../../hooks' ;
3233import { usePrompt } from '../../../hooks/usePrompt' ;
33- import type { ExternalLinkPreview } from '../../../graphql/posts' ;
34+ import type { ExternalLinkPreview , Post } from '../../../graphql/posts' ;
35+ import { getPostByIdKey } from '../../../lib/query' ;
3436import { AudienceChip } from '../../post/composer/AudienceChip' ;
3537import { KindModePicker } from '../../post/composer/KindModePicker' ;
3638import {
@@ -64,36 +66,66 @@ export interface SmartComposerModalProps extends LazyModalCommonProps {
6466 initialUrl ?: string ;
6567 initialSquadHandle ?: string ;
6668 preview ?: ExternalLinkPreview ;
69+ editPost ?: Post ;
6770}
6871
6972export function SmartComposerModal ( {
7073 onRequestClose,
7174 initialUrl,
7275 initialSquadHandle,
7376 preview : initialPreview ,
77+ editPost,
7478 ...props
7579} : SmartComposerModalProps ) : ReactElement {
7680 const { user } = useAuthContext ( ) ;
7781 const { logEvent } = useLogContext ( ) ;
7882 const isLaptop = useViewSize ( ViewSize . Laptop ) ;
83+ const queryClient = useQueryClient ( ) ;
7984 const { showPrompt } = usePrompt ( ) ;
8085 const { shouldShowCta, isEnabled, onToggle, onSubmitted } =
8186 useNotificationToggle ( ) ;
8287 const isStandupEnabled = useStandupCreation ( ) ;
83- const [ kind , setKind ] = useState < ComposerKind > ( initialUrl ? 'link' : 'text' ) ;
84- const [ text , setText ] = useState < TextFormState > ( DEFAULT_TEXT ) ;
88+ const isEditing = ! ! editPost ;
89+ const [ kind , setKind ] = useState < ComposerKind > ( ( ) => {
90+ if ( isEditing ) {
91+ return 'text' ;
92+ }
93+ return initialUrl ? 'link' : 'text' ;
94+ } ) ;
95+ const [ text , setText ] = useState < TextFormState > ( ( ) =>
96+ editPost
97+ ? { title : editPost . title ?? '' , body : editPost . content ?? '' }
98+ : DEFAULT_TEXT ,
99+ ) ;
85100 const [ link , setLink ] = useState < LinkFormState > ( {
86101 ...DEFAULT_LINK ,
87102 url : initialUrl ?? '' ,
88103 } ) ;
89104 const [ poll , setPoll ] = useState < PollFormState > ( DEFAULT_POLL ) ;
90105 const [ standup , setStandup ] = useState < StandupFormState > ( DEFAULT_STANDUP ) ;
91- const [ cover , setCover ] = useState < TextFormCover | null > ( null ) ;
106+ const [ cover , setCover ] = useState < TextFormCover | null > ( ( ) =>
107+ editPost ?. image ? { preview : editPost . image } : null ,
108+ ) ;
92109 const [ isExpanded , setIsExpanded ] = useState ( false ) ;
93110 const [ isMarkdownMode , setIsMarkdownMode ] = useState ( false ) ;
94111 const textFormRef = useRef < TextFormHandle > ( null ) ;
95112
96113 const isDirty = useMemo ( ( ) => {
114+ if ( editPost ) {
115+ if ( text . title !== ( editPost . title ?? '' ) ) {
116+ return true ;
117+ }
118+ if ( text . body !== ( editPost . content ?? '' ) ) {
119+ return true ;
120+ }
121+ if ( cover ?. file ) {
122+ return true ;
123+ }
124+ if ( ! cover && editPost . image ) {
125+ return true ;
126+ }
127+ return false ;
128+ }
97129 if ( cover ) {
98130 return true ;
99131 }
@@ -110,7 +142,7 @@ export function SmartComposerModal({
110142 return true ;
111143 }
112144 return false ;
113- } , [ cover , text , link , poll , standup ] ) ;
145+ } , [ cover , text , link , poll , standup , editPost ] ) ;
114146
115147 const handleClose = useCallback (
116148 async ( event ?: React . MouseEvent | React . KeyboardEvent ) => {
@@ -126,7 +158,7 @@ export function SmartComposerModal({
126158 return ;
127159 }
128160 const confirmed = await showPrompt ( {
129- title : 'Discard draft?' ,
161+ title : isEditing ? 'Discard changes?' : 'Discard draft?' ,
130162 description :
131163 'You have unsaved changes. Are you sure you want to discard them?' ,
132164 okButton : {
@@ -140,7 +172,7 @@ export function SmartComposerModal({
140172 closeAndLog ( ) ;
141173 }
142174 } ,
143- [ isDirty , kind , logEvent , onRequestClose , showPrompt ] ,
175+ [ isDirty , kind , logEvent , onRequestClose , showPrompt , isEditing ] ,
144176 ) ;
145177
146178 useEffect ( ( ) => {
@@ -206,7 +238,7 @@ export function SmartComposerModal({
206238 ) ;
207239
208240 const { audiences, selectedIds, selected, setSelectedIds, userAudienceId } =
209- useComposerAudience ( initialSquadHandle ) ;
241+ useComposerAudience ( initialSquadHandle , editPost ?. source ?. id ) ;
210242 const primary = selected [ 0 ] ;
211243 const isMulti = selected . length > 1 ;
212244
@@ -229,7 +261,13 @@ export function SmartComposerModal({
229261 selectedIds,
230262 isMulti,
231263 initialPreview,
264+ editPostId : editPost ?. id ,
232265 onComplete : ( ) => {
266+ if ( editPost ?. id ) {
267+ queryClient . invalidateQueries ( {
268+ queryKey : getPostByIdKey ( editPost . id ) ,
269+ } ) ;
270+ }
233271 onSubmitted ( ) ;
234272 onRequestClose ?.( ) ;
235273 } ,
@@ -241,15 +279,17 @@ export function SmartComposerModal({
241279 selected . filter ( ( audience ) => ! isUserAudience ( audience ) ) . length > 1 ;
242280 const isStandupScheduled = standup . scheduleChoice === 'later' ;
243281 let submitLabel : string ;
244- if ( isStandup ) {
282+ if ( isEditing ) {
283+ submitLabel = 'Save changes' ;
284+ } else if ( isStandup ) {
245285 submitLabel = isStandupScheduled ? 'Schedule standup' : 'Create standup' ;
246286 } else if ( kind === 'poll' ) {
247287 submitLabel = 'Post poll' ;
248288 } else {
249289 submitLabel = 'Post' ;
250290 }
251291
252- const kindPickerNode = (
292+ const kindPickerNode = isEditing ? null : (
253293 < KindModePicker
254294 value = { kind }
255295 onChange = { onKindChange }
@@ -276,7 +316,7 @@ export function SmartComposerModal({
276316 type = "submit"
277317 variant = { ButtonVariant . Primary }
278318 size = { ButtonSize . Small }
279- disabled = { isSubmitDisabled || isCoverUploading }
319+ disabled = { isSubmitDisabled || isCoverUploading || ( isEditing && ! isDirty ) }
280320 loading = { isInFlight || isCoverUploading }
281321 className = "ml-2 px-5"
282322 >
@@ -322,7 +362,7 @@ export function SmartComposerModal({
322362 selectedIds = { selectedIds }
323363 onChange = { setSelectedIds }
324364 userAudienceId = { userAudienceId }
325- disabled = { isInFlight }
365+ disabled = { isInFlight || isEditing }
326366 />
327367 ) }
328368 </ div >
0 commit comments