@@ -29,14 +29,18 @@ function processClaudeCustomSendButtonClick(event, customText, autoSend) {
2929
3030/**
3131 * Handles the send button clicking process for Claude
32- * Uses a promise-based approach to wait for the send button, reducing duplicate code.
3332 */
3433function handleClaudeSend ( ) {
35- const TIMEOUT_DURATION = 5000 ; // 5 seconds
36-
37- // Helper to find a send button using the selectors provided
38- const findClaudeSendButton = ( ) => {
34+ // Add timeout and attempt counter for finding send button
35+ let attempts = 0 ;
36+ const MAX_ATTEMPTS = 50 ;
37+ const TIMEOUT_DURATION = 5000 ;
38+ let timeoutId ;
39+
40+ function findClaudeSendButton ( ) {
41+ // Common selectors for Claude send buttons
3942 const sendButtonSelectors = window . InjectionTargetsOnWebsite . selectors . sendButtons ;
43+
4044 for ( const selector of sendButtonSelectors ) {
4145 const button = document . querySelector ( selector ) ;
4246 if ( button ) {
@@ -45,55 +49,55 @@ function handleClaudeSend() {
4549 }
4650 }
4751 return null ;
48- } ;
52+ }
4953
50- // Promise-based helper to wait for a send button
51- const waitForClaudeSendButton = ( timeout = TIMEOUT_DURATION ) => {
52- return new Promise ( ( resolve , reject ) => {
53- // Try immediately
54- const button = findClaudeSendButton ( ) ;
55- if ( button ) {
56- return resolve ( button ) ;
57- }
54+ // First immediate attempt
55+ const sendButton = findClaudeSendButton ( ) ;
56+ if ( sendButton ) {
57+ logConCgp ( '[Claude] Send button found immediately, delaying click by 200ms' ) ;
58+ setTimeout ( ( ) => {
59+ MaxExtensionUtils . simulateClick ( sendButton ) ;
60+ logConCgp ( '[Claude] Send button clicked after 200ms delay' ) ;
61+ } , 200 ) ;
62+ return ;
63+ }
5864
59- let attempts = 0 ;
60- const observer = new MutationObserver ( ( ) => {
61- attempts ++ ;
62- const btn = findClaudeSendButton ( ) ;
63- if ( btn ) {
64- observer . disconnect ( ) ;
65- logConCgp ( `[Claude] Send button found after ${ attempts } mutation callbacks` ) ;
66- resolve ( btn ) ;
67- } else {
68- logConCgp ( `[Claude] Attempt ${ attempts } : Send button not found yet` ) ;
69- }
70- } ) ;
65+ // If not found, set up observer
66+ logConCgp ( '[Claude] Send button not found immediately, setting up observer' ) ;
7167
72- observer . observe ( document . body , { childList : true , subtree : true } ) ;
68+ const observer = new MutationObserver ( ( mutations , obs ) => {
69+ attempts ++ ;
70+ const sendButton = findClaudeSendButton ( ) ;
7371
74- // Timeout to reject the promise if the button is not found
75- setTimeout ( ( ) => {
76- observer . disconnect ( ) ;
77- reject ( new Error ( 'Timeout reached without finding send button' ) ) ;
78- } , timeout ) ;
79- } ) ;
80- } ;
81-
82- // Use an async IIFE to wait for the send button and then click it
83- ( async ( ) => {
84- try {
85- const sendButton = await waitForClaudeSendButton ( ) ;
86- logConCgp ( '[Claude] Send button found, delaying click by 200ms' ) ;
72+ if ( sendButton ) {
73+ clearTimeout ( timeoutId ) ;
74+ obs . disconnect ( ) ;
75+ logConCgp ( '[Claude] Send button found after observation, delaying click by 200ms' ) ;
8776 setTimeout ( ( ) => {
8877 MaxExtensionUtils . simulateClick ( sendButton ) ;
8978 logConCgp ( '[Claude] Send button clicked after 200ms delay' ) ;
9079 } , 200 ) ;
91- } catch ( error ) {
92- logConCgp ( '[Claude] ' + error . message ) ;
80+ } else if ( attempts >= MAX_ATTEMPTS ) {
81+ clearTimeout ( timeoutId ) ;
82+ obs . disconnect ( ) ;
83+ logConCgp ( '[Claude] Maximum attempts reached without finding send button' ) ;
84+ } else {
85+ logConCgp ( `[Claude] Attempt ${ attempts } /${ MAX_ATTEMPTS } : Send button not found yet` ) ;
9386 }
94- } ) ( ) ;
87+ } ) ;
88+
89+ observer . observe ( document . body , {
90+ childList : true ,
91+ subtree : true
92+ } ) ;
93+
94+ timeoutId = setTimeout ( ( ) => {
95+ observer . disconnect ( ) ;
96+ logConCgp ( '[Claude] Timeout reached without finding send button' ) ;
97+ } , TIMEOUT_DURATION ) ;
9598}
9699
100+
97101/**
98102 * Utility functions for handling text insertion in Claude's editor
99103 * Handles different editor states and element structures
@@ -238,7 +242,7 @@ const ClaudeEditorUtils = {
238242 // Focus the editor
239243 editorElement . focus ( ) ;
240244
241- // If editor has placeholder or is empty, initialize content
245+ // If editor has placeholder, clear it
242246 if ( editorState . hasPlaceholder || editorState . isEmpty ) {
243247 logConCgp ( '[ClaudeEditor] Editor is empty or has placeholder, initializing content' ) ;
244248 editorElement . innerHTML = '<p><br></p>' ;
@@ -285,7 +289,6 @@ const ClaudeEditorUtils = {
285289
286290 /**
287291 * Inserts text into the editor, handling both empty and non-empty cases
288- * Uses modern Range and Selection APIs.
289292 * @param {Element } editorElement - The editor element
290293 * @param {string } textToInsert - The text to insert
291294 * @returns {boolean } - Whether the insertion was successful
@@ -296,9 +299,6 @@ const ClaudeEditorUtils = {
296299 editorElement . focus ( ) ;
297300
298301 const selection = window . getSelection ( ) ;
299- if ( ! selection ) {
300- throw new Error ( 'Selection API not available' ) ;
301- }
302302 selection . removeAllRanges ( ) ;
303303 const range = document . createRange ( ) ;
304304
@@ -309,7 +309,9 @@ const ClaudeEditorUtils = {
309309 editorElement . appendChild ( newParagraph ) ;
310310 range . setStart ( newParagraph , 0 ) ;
311311 } else {
312- // Editor has content, append text to the last paragraph
312+ // Editor has content, append text to last paragraph
313+
314+ // Find the last paragraph element
313315 const paragraphs = editorElement . querySelectorAll ( 'p' ) ;
314316 let lastParagraph ;
315317 if ( paragraphs . length > 0 ) {
@@ -319,6 +321,8 @@ const ClaudeEditorUtils = {
319321 lastParagraph = document . createElement ( 'p' ) ;
320322 editorElement . appendChild ( lastParagraph ) ;
321323 }
324+
325+ // Set the selection to the end of the last paragraph
322326 range . selectNodeContents ( lastParagraph ) ;
323327 range . collapse ( false ) ;
324328 }
0 commit comments