@@ -7,33 +7,6 @@ import styles from './comment.module.css'
7
7
8
8
const POLL_INTERVAL = 1000 * 10 // 10 seconds
9
9
10
- // the item query is used to update the item's newComments field
11
- function itemUpdateQuery ( client , id , sort , fn ) {
12
- client . cache . updateQuery ( {
13
- query : ITEM_FULL ,
14
- variables : sort === 'top' ? { id } : { id, sort }
15
- } , ( data ) => {
16
- if ( ! data ) return data
17
- return { item : fn ( data . item ) }
18
- } )
19
- }
20
-
21
- function commentUpdateFragment ( client , id , fn ) {
22
- client . cache . updateFragment ( {
23
- id : `Item:${ id } ` ,
24
- fragment : COMMENT_WITH_NEW ,
25
- fragmentName : 'CommentWithNew'
26
- } , ( data ) => {
27
- if ( ! data ) return data
28
- return { ...data , ...fn ( data ) }
29
- } )
30
- }
31
-
32
- function dedupeComments ( existing = [ ] , incoming = [ ] ) {
33
- const existingIds = new Set ( existing . map ( c => c . id ) )
34
- return [ ...incoming . filter ( c => ! existingIds . has ( c . id ) ) , ...existing ]
35
- }
36
-
37
10
export default function useLiveComments ( rootId , after , sort ) {
38
11
const client = useApolloClient ( )
39
12
const [ latest , setLatest ] = useState ( after )
@@ -62,17 +35,37 @@ export default function useLiveComments (rootId, after, sort) {
62
35
} , [ data , client , rootId , sort ] )
63
36
}
64
37
38
+ // the item query is used to update the item's newComments field
39
+ function itemUpdateQuery ( client , id , sort , fn ) {
40
+ client . cache . updateQuery ( {
41
+ query : ITEM_FULL ,
42
+ variables : sort === 'top' ? { id } : { id, sort }
43
+ } , ( data ) => {
44
+ if ( ! data ) return data
45
+ return { item : fn ( data . item ) }
46
+ } )
47
+ }
48
+
49
+ function commentUpdateFragment ( client , id , fn ) {
50
+ client . cache . updateFragment ( {
51
+ id : `Item:${ id } ` ,
52
+ fragment : COMMENT_WITH_NEW ,
53
+ fragmentName : 'CommentWithNew'
54
+ } , ( data ) => {
55
+ if ( ! data ) return data
56
+ return fn ( data )
57
+ } )
58
+ }
59
+
65
60
function cacheNewComments ( client , rootId , newComments , sort ) {
66
61
const queuedComments = [ ]
67
62
68
63
for ( const newComment of newComments ) {
69
- console . log ( 'newComment' , newComment )
70
64
const { parentId } = newComment
71
65
const topLevel = Number ( parentId ) === Number ( rootId )
72
66
73
67
// if the comment is a top level comment, update the item
74
68
if ( topLevel ) {
75
- console . log ( 'topLevel' , topLevel )
76
69
itemUpdateQuery ( client , rootId , sort , ( data ) => mergeNewComment ( data , newComment ) )
77
70
} else {
78
71
// check if parent exists in cache before attempting update
@@ -84,7 +77,6 @@ function cacheNewComments (client, rootId, newComments, sort) {
84
77
85
78
if ( parentExists ) {
86
79
// if the comment is a reply, update the parent comment
87
- console . log ( 'reply' , parentId )
88
80
commentUpdateFragment ( client , parentId , ( data ) => mergeNewComment ( data , newComment ) )
89
81
} else {
90
82
// parent not in cache, queue for retry
@@ -99,17 +91,23 @@ function cacheNewComments (client, rootId, newComments, sort) {
99
91
// merge new comment into item's newComments
100
92
// if the new comment is already in item's newComments or existing comments, do nothing
101
93
function mergeNewComment ( item , newComment ) {
102
- console . log ( 'mergeNewComment' , item , newComment )
103
94
const existingNewComments = item . newComments || [ ]
104
95
const existingComments = item . comments ?. comments || [ ]
105
96
106
97
// is the incoming new comment already in item's new comments or existing comments?
107
98
if ( existingNewComments . some ( c => c . id === newComment . id ) || existingComments . some ( c => c . id === newComment . id ) ) {
108
99
return item
109
100
}
101
+
110
102
return { ...item , newComments : [ ...existingNewComments , newComment ] }
111
103
}
112
104
105
+ // dedupe comments by id
106
+ function dedupeComments ( existing = [ ] , incoming = [ ] ) {
107
+ const existingIds = new Set ( existing . map ( c => c . id ) )
108
+ return [ ...incoming . filter ( c => ! existingIds . has ( c . id ) ) , ...existing ]
109
+ }
110
+
113
111
function getLatestCommentCreatedAt ( comments , latest ) {
114
112
if ( comments . length === 0 ) return latest
115
113
@@ -127,19 +125,22 @@ export function ShowNewComments ({ newComments = [], itemId, topLevel = false, s
127
125
128
126
const showNewComments = useCallback ( ( ) => {
129
127
const payload = ( data ) => {
130
- if ( ! data ) return data
128
+ // fresh newComments
129
+ const freshNewComments = newComments . map ( c => client . cache . readFragment ( {
130
+ id : `Item:${ c . id } ` ,
131
+ fragment : COMMENT_WITH_NEW ,
132
+ fragmentName : 'CommentWithNew'
133
+ } ) )
131
134
return {
132
135
...data ,
133
- comments : { ...data . comments , comments : dedupeComments ( data . comments . comments , newComments ) } ,
136
+ comments : { ...data . comments , comments : dedupeComments ( data . comments . comments , freshNewComments ) } ,
134
137
newComments : [ ]
135
138
}
136
139
}
137
140
138
141
if ( topLevel ) {
139
- console . log ( 'topLevel' , topLevel )
140
142
itemUpdateQuery ( client , itemId , sort , payload )
141
143
} else {
142
- console . log ( 'reply' , itemId )
143
144
commentUpdateFragment ( client , itemId , payload )
144
145
}
145
146
} , [ client , itemId , newComments , topLevel , sort ] )
@@ -149,7 +150,7 @@ export function ShowNewComments ({ newComments = [], itemId, topLevel = false, s
149
150
onClick = { showNewComments }
150
151
className = { `${ topLevel && `d-block fw-bold ${ styles . comment } pb-2` } d-flex align-items-center gap-2 px-3 pointer` }
151
152
>
152
- load new comments
153
+ show ( { newComments . length } ) new comments
153
154
< div className = { styles . newCommentDot } />
154
155
</ div >
155
156
)
0 commit comments