@@ -571,55 +571,133 @@ function updateAllElements(isDark: boolean) {
571571 } ) ;
572572}
573573
574- chrome . runtime . onMessage . addListener ( ( request ) => {
575- if ( request . action === 'updateSolutions' ) {
576- chrome . storage . local . get ( [ 'leetcodeProblems' ] , ( result ) => {
574+ // Function to update the solutions tab content
575+ function updateSolutionsTab ( title : string ) {
576+ chrome . storage . local . get ( [ 'leetcodeProblems' ] , ( result ) => {
577+ // Try to find the search bar with retries
578+ const maxRetries = 10 ;
579+ const baseDelay = 300 ;
580+ let retryCount = 0 ;
581+ 582+ const tryInsertContent = ( ) => {
577583 const searchBar = document . querySelectorAll ( 'input.block' ) [ 0 ] ?. parentElement ?. parentElement ?. parentElement ;
578- if ( ! searchBar ) return ;
579- 580- const title = request . title . split ( '-' ) [ 0 ] . trim ( ) ;
581- const problem = result . leetcodeProblems . questions . find ( ( problem : { title : string } ) => problem . title === title ) ;
582- 583- // If no solution code or videos exist, don't do anything
584- if ( ! problem ?. videos && ! problem ?. languages ) return ;
585- if ( problem . videos ?. length === 0 && problem . languages ?. length === 0 ) return ;
586- 587- // Remove any existing containers
588- const existingWrapper = document . querySelector ( '.leetcode-explained-wrapper' ) ;
589- if ( existingWrapper ) existingWrapper . remove ( ) ;
590- 591- // Create wrapper for all our custom content
592- const wrapper = createCustomContentWrapper ( ) ;
593584
594- // Create and add nav container
595- const navContainer = createNavContainer ( problem ) ;
596- wrapper . appendChild ( navContainer ) ;
597- 598- // Add video container if videos exist
599- if ( problem . videos ?. length > 0 ) {
600- const videoContainer = createVideoContainer ( problem ) ;
601- wrapper . appendChild ( videoContainer ) ;
585+ if ( ! searchBar && retryCount < maxRetries ) {
586+ // Use exponential backoff for retry delay
587+ const delay = baseDelay * Math . pow ( 1.5 , retryCount ) ;
588+ retryCount ++ ;
589+ console . log ( `Attempt ${ retryCount } : Waiting for search bar element to load... Retrying in ${ delay } ms` ) ;
590+ setTimeout ( tryInsertContent , delay ) ;
591+ return ;
602592 }
603593
604- // Add code container and language buttons if languages exist
605- if ( problem . languages ?. length > 0 ) {
606- const codeContainer = createCodeContainer ( ) ;
607- const languageButtonsContainer = createLanguageButtons ( problem ) ;
608- languageButtonsContainer . classList . add ( 'language-buttons-container' ) ;
609- languageButtonsContainer . style . display = 'none' ;
594+ if ( ! searchBar ) {
595+ console . log ( 'Failed to find search bar element after all retries' ) ;
596+ 597+ // If still not found, set up a MutationObserver to watch for DOM changes
598+ const observer = new MutationObserver ( ( mutations , obs ) => {
599+ const searchBar = document . querySelectorAll ( 'input.block' ) [ 0 ] ?. parentElement ?. parentElement ?. parentElement ;
600+ if ( searchBar ) {
601+ obs . disconnect ( ) ; // Stop observing once we find the element
602+ insertContent ( searchBar , title , result ) ;
603+ }
604+ } ) ;
605+ 606+ // Start observing the document with the configured parameters
607+ observer . observe ( document . body , {
608+ childList : true ,
609+ subtree : true
610+ } ) ;
610611
611- wrapper . appendChild ( languageButtonsContainer ) ;
612- wrapper . appendChild ( codeContainer ) ;
612+ return ;
613613 }
614614
615- // Insert the wrapper at the top of the solutions tab
616- searchBar . insertBefore ( wrapper , searchBar . firstChild ) ;
615+ insertContent ( searchBar , title , result ) ;
616+ } ;
617617
618- // Show discussion by default
619- showContent ( 'Discussion' ) ;
618+ tryInsertContent ( ) ;
619+ } ) ;
620+ }
620621
621- // Set up theme change listener
622- setupThemeChangeListener ( ) ;
623- } ) ;
622+ // Helper function to insert the content
623+ function insertContent ( searchBar : Element , title : string , result : any ) {
624+ const problemTitle = title . split ( '-' ) [ 0 ] . trim ( ) ;
625+ const problem = result . leetcodeProblems . questions . find ( ( problem : { title : string } ) => problem . title === problemTitle ) ;
626+ 627+ // If no solution code or videos exist, don't do anything
628+ if ( ! problem ?. videos && ! problem ?. languages ) return ;
629+ if ( problem . videos ?. length === 0 && problem . languages ?. length === 0 ) return ;
630+ 631+ // Remove any existing containers
632+ const existingWrapper = document . querySelector ( '.leetcode-explained-wrapper' ) ;
633+ if ( existingWrapper ) existingWrapper . remove ( ) ;
634+ 635+ // Create wrapper for all our custom content
636+ const wrapper = createCustomContentWrapper ( ) ;
637+ 638+ // Create and add nav container
639+ const navContainer = createNavContainer ( problem ) ;
640+ wrapper . appendChild ( navContainer ) ;
641+ 642+ // Add video container if videos exist
643+ if ( problem . videos ?. length > 0 ) {
644+ const videoContainer = createVideoContainer ( problem ) ;
645+ wrapper . appendChild ( videoContainer ) ;
646+ }
647+ 648+ // Add code container and language buttons if languages exist
649+ if ( problem . languages ?. length > 0 ) {
650+ const codeContainer = createCodeContainer ( ) ;
651+ const languageButtonsContainer = createLanguageButtons ( problem ) ;
652+ languageButtonsContainer . classList . add ( 'language-buttons-container' ) ;
653+ languageButtonsContainer . style . display = 'none' ;
654+ 655+ wrapper . appendChild ( languageButtonsContainer ) ;
656+ wrapper . appendChild ( codeContainer ) ;
657+ }
658+ 659+ // Insert the wrapper at the top of the solutions tab
660+ searchBar . insertBefore ( wrapper , searchBar . firstChild ) ;
661+ 662+ // Show discussion by default
663+ showContent ( 'Discussion' ) ;
664+ 665+ // Set up theme change listener
666+ setupThemeChangeListener ( ) ;
667+ }
668+ 669+ // Self-initialization function that runs when the content script loads
670+ function initializeContentScript ( ) {
671+ // Wait for the DOM to be fully loaded
672+ if ( document . readyState === 'loading' ) {
673+ document . addEventListener ( 'DOMContentLoaded' , onDOMReady ) ;
674+ } else {
675+ onDOMReady ( ) ;
676+ }
677+ 678+ function onDOMReady ( ) {
679+ // Check if we're on a LeetCode problem's solutions page
680+ const isSolutionsPage = / ^ h t t p s : \/ \/ l e e t c o d e \. c o m \/ p r o b l e m s \/ .* \/ s o l u t i o n s \/ ? / . test ( window . location . href ) ;
681+ 682+ if ( isSolutionsPage ) {
683+ console . log ( 'LeetCode solutions page detected, initializing content script...' ) ;
684+ 685+ // Extract the problem title from the page title
686+ const pageTitle = document . title ;
687+ 688+ // Update the solutions tab
689+ updateSolutionsTab ( pageTitle ) ;
690+ 691+ console . log ( 'Solutions tab content script initialized for problem:' , pageTitle ) ;
692+ }
693+ }
694+ }
695+ 696+ // Run the initialization
697+ initializeContentScript ( ) ;
698+ 699+ chrome . runtime . onMessage . addListener ( ( request ) => {
700+ if ( request . action === 'updateSolutions' ) {
701+ updateSolutionsTab ( request . title ) ;
624702 }
625703} ) ;
0 commit comments