@@ -14,7 +14,6 @@ import PinIcon from "~common/pin"
14
14
15
15
import "~styles.css"
16
16
17
- import { cp } from "fs"
18
17
import { useCallback , useEffect , useState } from "react"
19
18
20
19
import LogoIcon from "~common/logo"
@@ -26,38 +25,40 @@ export const config: PlasmoCSConfig = {
26
25
matches : [ "https://chat.openai.com/*" , "https://chatgpt.com/*" ]
27
26
}
28
27
28
+ /**
29
+ * Previously this was querying for the <markdown> tag.
30
+ * The ChatGPT DOM uses a div with a "markdown" class.
31
+ */
29
32
export const getInlineAnchorList : PlasmoGetInlineAnchorList = async ( ) =>
30
- document . querySelectorAll ( "div > .pt-0 " )
33
+ document . querySelectorAll ( ".markdown " )
31
34
32
35
export const render : PlasmoRender < Element > = async ( {
33
36
anchor, // the observed anchor, OR document.body.
34
- createRootContainer // This creates the default root container
37
+ createRootContainer // Creates the default root container
35
38
} ) => {
36
39
if ( ! anchor || ! createRootContainer ) return
37
- // const parentElement = anchor?.element.parentElement?.parentElement
38
- // if (!parentElement) return
39
- // const parentAnchor = {
40
- // element: parentElement,
41
- // type: anchor.type
42
- // }
43
-
44
- // console.log({ anchor, parentAnchor })
45
- const rootContainer = await createRootContainer ( anchor )
46
40
47
- const root = createRoot ( rootContainer ) // Any root
48
- const parent =
49
- anchor ?. element ?. parentElement ?. parentElement ?. parentElement ?. parentElement
41
+ const rootContainer = await createRootContainer ( anchor )
42
+ // Instead of multiple parentElement calls, use closest() to grab the container
43
+ // that represents the whole assistant turn.
44
+ const parent = anchor . element . closest ( ".agent-turn" )
50
45
parent ?. classList . add ( "pin" )
46
+ parent ?. insertBefore ( rootContainer , parent . firstChild )
47
+
48
+ const root = createRoot ( rootContainer )
49
+ rootContainer . classList . add ( "relative" )
50
+
51
51
root . render (
52
52
< >
53
- < Content
54
- // @ts -ignore
55
- parent = { parent }
56
- />
53
+ < Content parent = { parent } />
57
54
</ >
58
55
)
59
56
}
60
57
58
+ type Props = {
59
+ parent : Element | null
60
+ }
61
+
61
62
const Content = ( { parent } : Props ) => {
62
63
const [ toBeSaved , setToBeSaved ] = useStorage < ToBeSaved > (
63
64
STORAGE_KEYS . toBeSaved
@@ -81,11 +82,19 @@ const Content = ({ parent }: Props) => {
81
82
const [ pinIndex , setPinIndex ] = useState ( - 1 )
82
83
83
84
useEffect ( ( ) => {
84
- if ( parent . parentElement ?. querySelector ( ".agent-turn" ) ) setShowPin ( true )
85
- else parent . classList . remove ( "pin" )
85
+ console . log ( parent )
86
+ } , [ parent ] )
87
+
88
+ useEffect ( ( ) => {
89
+ // Only show the pin if a sibling agent-turn exists
90
+ if ( parent ?. parentElement ?. querySelector ( ".agent-turn" ) ) {
91
+ setShowPin ( true )
92
+ } else {
93
+ parent ?. classList . remove ( "pin" )
94
+ }
86
95
const index = getPinIndex ( parent )
87
96
setPinIndex ( index )
88
- } , [ ] )
97
+ } , [ parent ] )
89
98
90
99
useEffect ( ( ) => {
91
100
if ( ! ( isPremium || activeTrial ) || ! chatID ) return
@@ -101,17 +110,13 @@ const Content = ({ parent }: Props) => {
101
110
const pins = document . querySelectorAll ( ".pin" )
102
111
const lastPin = pins [ pins . length - 1 ]
103
112
if ( ! lastPin ) return false
104
- // Unelegant way to get the node of an element
105
- const parentNode = parent . firstChild ?. parentNode
113
+ // A somewhat inelegant way to compare nodes:
114
+ const parentNode = parent ? .firstChild ?. parentNode
106
115
if ( ! parentNode ) return false
107
- return (
108
- lastPin . firstChild ?. parentNode ?. isSameNode (
109
- parent . firstChild ?. parentNode
110
- ) ?? false
111
- )
116
+ return lastPin . firstChild ?. parentNode ?. isSameNode ( parentNode ) ?? false
112
117
} ) ( )
113
118
)
114
- } , [ chatID , status ] )
119
+ } , [ chatID , status , isPremium , activeTrial , parent ] )
115
120
116
121
const LastMessageIcon = useCallback ( ( ) => {
117
122
switch ( status ) {
@@ -125,28 +130,31 @@ const Content = ({ parent }: Props) => {
125
130
return < LogoIcon error />
126
131
case "saved" :
127
132
return < LogoIcon />
133
+ default :
134
+ return < LogoIcon />
128
135
}
129
- } , [ chatID , status ] )
136
+ } , [ status ] )
130
137
131
138
const handleClick = async ( ) => {
132
139
if ( ! authenticated ) {
133
140
alert ( i18n ( "errConnect" ) )
134
141
return
135
142
}
136
143
137
- const images = Array . from ( parent . querySelectorAll ( "img" ) || [ ] )
138
- const text = Array . from ( parent . querySelectorAll ( ".markdown" ) ) . map ( ( el ) =>
139
- el . parentElement ?. classList . contains ( "mt-3" )
140
- ? "%%CHATGPT_TO_NOTION_WORK1%%" + el . innerHTML
141
- : el . innerHTML
144
+ const images = Array . from ( parent ?. querySelectorAll ( "img" ) || [ ] )
145
+ const text = Array . from ( parent ?. querySelectorAll ( ".markdown" ) || [ ] ) . map (
146
+ ( el ) =>
147
+ el . parentElement ?. classList . contains ( "mt-3" )
148
+ ? "%%CHATGPT_TO_NOTION_WORK1%%" + el . innerHTML
149
+ : el . innerHTML
142
150
)
143
151
144
152
console . log ( text )
145
153
146
154
let uncompressedAnswer = text [ 0 ]
147
155
if ( text . length > 1 ) {
148
156
uncompressedAnswer = text . reduce ( ( acc , curr , i , arr ) => {
149
- if ( i == 0 ) return curr
157
+ if ( i === 0 ) return curr
150
158
151
159
const prev = arr [ i - 1 ]
152
160
const joint = ( curr + prev ) . includes ( "%%CHATGPT_TO_NOTION_WORK2%%" )
@@ -162,12 +170,13 @@ const Content = ({ parent }: Props) => {
162
170
: uncompressedAnswer
163
171
const answer = await compress ( preCompressionAnswer )
164
172
165
- const prompt = await compress (
166
- // @ts -ignore
167
- parent . parentElement . previousElementSibling . querySelector (
173
+ // Find the prompt in the previous sibling element:
174
+ const promptElement =
175
+ parent ? .parentElement ? .previousElementSibling ? .querySelector (
168
176
".whitespace-pre-wrap"
169
- ) . textContent
170
- )
177
+ )
178
+ const promptText = promptElement ? promptElement . textContent : ""
179
+ const prompt = await compress ( promptText || "" )
171
180
const title = document . title
172
181
const url = window . location . href
173
182
@@ -201,7 +210,6 @@ const Content = ({ parent }: Props) => {
201
210
background : "transparent" ,
202
211
border : "none" ,
203
212
marginTop : 10 ,
204
- width : "100%" ,
205
213
cursor : status !== "generating" ? "pointer" : "default"
206
214
} } >
207
215
{ isLastMessage ? < LastMessageIcon /> : < LogoIcon /> }
@@ -218,7 +226,9 @@ const Content = ({ parent }: Props) => {
218
226
marginTop : 10 ,
219
227
padding : 4 ,
220
228
borderRadius : 4 ,
221
- width : "100%" ,
229
+ position : "absolute" ,
230
+ top : 32 ,
231
+ left : - 42 ,
222
232
cursor : "pointer"
223
233
} } >
224
234
< PinIcon />
@@ -228,11 +238,9 @@ const Content = ({ parent }: Props) => {
228
238
229
239
export default Content
230
240
231
- const getPinIndex = ( parent : Element ) => {
241
+ const getPinIndex = ( parent : Element | null ) => {
232
242
const pins = document . querySelectorAll ( ".pin" )
233
- return Array . from ( pins ) . findIndex ( ( pin ) => pin . isSameNode ( parent ) )
234
- }
235
-
236
- type Props = {
237
- parent : Element
243
+ return Array . from ( pins ) . findIndex ( ( pin ) =>
244
+ parent ? pin . isSameNode ( parent ) : false
245
+ )
238
246
}
0 commit comments