Skip to content

Commit 2d4f60c

Browse files
authoredMar 11, 2024
fix(comments): handle lack of access to inline comments (#5925)
* fix(comments): display upsell UI for inline comments * chore(core): export `UpsellDialogViewedInfo` interface * dev(comments): update `CommentsUpsellDialogStory` * fix(comments): change inline comment telemetry source name
1 parent c531a6b commit 2d4f60c

File tree

6 files changed

+59
-25
lines changed

6 files changed

+59
-25
lines changed
 

‎packages/sanity/src/core/studio/upsell/__telemetry__/upsell.telemetry.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ interface UpsellDialogActionsInfo {
44
feature: 'comments' | 'scheduled_publishing' | 'ai_assist'
55
type: 'modal' | 'inspector'
66
}
7-
interface UpsellDialogViewedInfo extends UpsellDialogActionsInfo {
8-
source: 'field_action' | 'document_toolbar' | 'document_action' | 'navbar' | 'link'
7+
8+
/** @internal */
9+
export interface UpsellDialogViewedInfo extends UpsellDialogActionsInfo {
10+
source: 'field_action' | 'document_toolbar' | 'document_action' | 'navbar' | 'link' | 'pte'
911
}
1012

1113
/**

‎packages/sanity/src/structure/comments/plugin/field/CommentsField.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ function CommentFieldInner(
186186

187187
if (mode === 'upsell') {
188188
if (upsellData) {
189-
handleOpenDialog()
189+
handleOpenDialog('field_action')
190190
} else {
191191
// Open the comments inspector
192192
onCommentsOpen?.()

‎packages/sanity/src/structure/comments/plugin/input/components/CommentsPortableTextInput.tsx

+35-10
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@ import {
2222
CommentInlineHighlightSpan,
2323
type CommentMessage,
2424
type CommentsTextSelectionItem,
25+
type CommentsUIMode,
2526
type CommentUpdatePayload,
2627
isTextSelectionComment,
2728
useComments,
2829
useCommentsEnabled,
2930
useCommentsScroll,
3031
useCommentsSelectedPath,
32+
useCommentsUpsell,
3133
} from '../../../src'
3234
import {getSelectionBoundingRect, useAuthoringReferenceElement} from '../helpers'
3335
import {FloatingButtonPopover} from './FloatingButtonPopover'
@@ -47,22 +49,25 @@ export function CommentsPortableTextInput(props: PortableTextInputProps) {
4749
// Therefore we disable the comments for the AI assist type.
4850
const isAiAssist = props.schemaType.name === AI_ASSIST_TYPE
4951

50-
if (!enabled || mode === 'upsell' || isAiAssist) {
52+
if (!enabled || isAiAssist) {
5153
return props.renderDefault(props)
5254
}
5355

54-
return <CommentsPortableTextInputInner {...props} />
56+
return <CommentsPortableTextInputInner {...props} mode={mode} />
5557
}
5658

5759
export const CommentsPortableTextInputInner = React.memo(function CommentsPortableTextInputInner(
58-
props: PortableTextInputProps,
60+
props: PortableTextInputProps & {mode: CommentsUIMode},
5961
) {
62+
const {mode} = props
6063
const currentUser = useCurrentUser()
6164
const portal = usePortal()
6265

63-
const {mentionOptions, comments, operation, onCommentsOpen, getComment} = useComments()
66+
const {mentionOptions, comments, operation, onCommentsOpen, getComment, setStatus, status} =
67+
useComments()
6468
const {setSelectedPath, selectedPath} = useCommentsSelectedPath()
6569
const {scrollToComment, scrollToGroup} = useCommentsScroll()
70+
const {handleOpenDialog} = useCommentsUpsell()
6671

6772
const editorRef = useRef<PortableTextEditor | null>(null)
6873
const mouseDownRef = useRef<boolean>(false)
@@ -100,8 +105,15 @@ export const CommentsPortableTextInputInner = React.memo(function CommentsPortab
100105
// Set the next comment selection to the current selection so that we can
101106
// render the comment input popover on the current selection using a range decoration.
102107
const handleSelectCurrentSelection = useCallback(() => {
108+
// When trying to add a comment in "upsell" mode, we want to
109+
// display the upsell dialog instead of the comment input popover.
110+
if (mode === 'upsell') {
111+
handleOpenDialog('pte')
112+
return
113+
}
114+
103115
setNextCommentSelection(currentSelection)
104-
}, [currentSelection])
116+
}, [currentSelection, handleOpenDialog, mode])
105117

106118
// Clear the selection and close the popover when discarding the comment
107119
const handleCommentDiscardConfirm = useCallback(() => {
@@ -125,12 +137,15 @@ export const CommentsPortableTextInputInner = React.memo(function CommentsPortab
125137

126138
const fragment = getFragment() || EMPTY_ARRAY
127139
const editorValue = PortableTextEditor.getValue(editorRef.current)
140+
128141
if (!editorValue) return
142+
129143
const textSelection = buildTextSelectionFromFragment({
130144
fragment,
131145
selection: nextCommentSelection,
132146
value: editorValue,
133147
})
148+
134149
const threadId = uuid()
135150

136151
operation.create({
@@ -145,27 +160,37 @@ export const CommentsPortableTextInputInner = React.memo(function CommentsPortab
145160
threadId,
146161
})
147162

163+
// Open the inspector when a new comment is added
148164
onCommentsOpen?.()
149165

166+
// Set the status to 'open' so that the comment is visible
167+
if (status === 'resolved') {
168+
setStatus('open')
169+
}
170+
171+
// Set the selected path to the new comment
150172
setSelectedPath({
151173
fieldPath: stringFieldPath,
152174
threadId,
153175
origin: 'form',
154176
})
155177

178+
// Scroll to the comment
156179
scrollToGroup(threadId)
157180

158181
resetStates()
159182
}, [
160-
resetStates,
161-
getFragment,
162183
nextCommentSelection,
184+
getFragment,
185+
operation,
186+
stringFieldPath,
163187
nextCommentValue,
164188
onCommentsOpen,
165-
operation,
166-
scrollToGroup,
189+
status,
167190
setSelectedPath,
168-
stringFieldPath,
191+
scrollToGroup,
192+
resetStates,
193+
setStatus,
169194
])
170195

171196
const handleDecoratorClick = useCallback(

‎packages/sanity/src/structure/comments/src/components/upsell/__workshop__/CommentsUpsellDialogStory.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ import {useCommentsUpsell} from '../../../hooks'
88
const CommentsUpsellDialogStoryInner = () => {
99
const {upsellData, handleOpenDialog} = useCommentsUpsell()
1010
const handleOpen = useCallback(() => {
11-
handleOpenDialog()
11+
handleOpenDialog('field_action')
1212
}, [handleOpenDialog])
1313

1414
useEffect(() => {
15-
handleOpenDialog()
15+
handleOpenDialog('field_action')
1616
}, [handleOpenDialog])
1717

1818
if (!upsellData) return null

‎packages/sanity/src/structure/comments/src/context/upsell/CommentsUpsellProvider.tsx

+13-8
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
UpsellDialogLearnMoreCtaClicked,
99
UpsellDialogUpgradeCtaClicked,
1010
UpsellDialogViewed,
11+
type UpsellDialogViewedInfo,
1112
useClient,
1213
useProjectId,
1314
} from 'sanity'
@@ -123,14 +124,18 @@ export function CommentsUpsellProvider(props: {children: React.ReactNode}) {
123124
}
124125
}, [client, projectId])
125126

126-
const handleOpenDialog = useCallback(() => {
127-
setUpsellDialogOpen(true)
128-
telemetry.log(UpsellDialogViewed, {
129-
feature: FEATURE,
130-
type: 'modal',
131-
source: 'field_action',
132-
})
133-
}, [telemetry])
127+
const handleOpenDialog = useCallback(
128+
(source: UpsellDialogViewedInfo['source']) => {
129+
setUpsellDialogOpen(true)
130+
131+
telemetry.log(UpsellDialogViewed, {
132+
feature: FEATURE,
133+
type: 'modal',
134+
source,
135+
})
136+
},
137+
[telemetry],
138+
)
134139

135140
const ctxValue = useMemo<CommentsUpsellContextValue>(
136141
() => ({

‎packages/sanity/src/structure/comments/src/context/upsell/types.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1+
import {type UpsellDialogViewedInfo} from 'sanity'
2+
13
import {type CommentsUpsellData} from '../../types'
24

35
export interface CommentsUpsellContextValue {
46
upsellDialogOpen: boolean
5-
handleOpenDialog: () => void
7+
handleOpenDialog: (source: UpsellDialogViewedInfo['source']) => void
68
upsellData: CommentsUpsellData | null
79
telemetryLogs: {
810
dialogSecondaryClicked: () => void
911
dialogPrimaryClicked: () => void
10-
panelViewed: (source: 'document_action' | 'field_action' | 'link') => void
12+
panelViewed: (source: UpsellDialogViewedInfo['source']) => void
1113
panelDismissed: () => void
1214
panelPrimaryClicked: () => void
1315
panelSecondaryClicked: () => void

0 commit comments

Comments
 (0)
Please sign in to comment.