@@ -599,30 +599,29 @@ function updateSolutionsTab(title: string) {
599599 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 ) ;
600600 if ( ! isSolutionsPage ) return ;
601601
602+ // Check if we already have content for this problem
603+ const existingWrapper = document . querySelector ( '.leetcode-explained-wrapper' ) as HTMLElement ;
604+ if ( existingWrapper ) {
605+ const currentTitle = document . title . split ( '-' ) [ 0 ] . trim ( ) ;
606+ const wrapperTitle = existingWrapper . getAttribute ( 'data-problem-title' ) ;
607+ 608+ // If it's the same problem and the wrapper is in the DOM, preserve state
609+ if ( wrapperTitle === currentTitle && document . contains ( existingWrapper ) ) {
610+ console . log ( 'Content exists for current problem, preserving state' ) ;
611+ return ;
612+ }
613+ 614+ // If it's a different problem or wrapper is detached, remove it
615+ existingWrapper . remove ( ) ;
616+ }
617+ 602618 chrome . storage . local . get ( [ 'leetcodeProblems' ] , ( result ) => {
603619 // Try to find the search bar with retries
604620 const maxRetries = 10 ;
605621 const baseDelay = 300 ;
606622 let retryCount = 0 ;
607623
608624 const tryInsertContent = ( ) => {
609- // Check if we already have a wrapper and if it's for the same problem
610- const existingWrapper = document . querySelector ( '.leetcode-explained-wrapper' ) ;
611- if ( existingWrapper ) {
612- const currentTitle = document . title . split ( '-' ) [ 0 ] . trim ( ) ;
613- const wrapperTitle = existingWrapper . getAttribute ( 'data-problem-title' ) ;
614- 615- // If it's the same problem, preserve the state
616- if ( wrapperTitle === currentTitle ) {
617- console . log ( 'Content for same problem exists, preserving state' ) ;
618- return ;
619- }
620- 621- // If it's a different problem, remove the old wrapper
622- console . log ( 'Different problem detected, updating content' ) ;
623- existingWrapper . remove ( ) ;
624- }
625- 626625 const searchBar = document . querySelectorAll ( 'input.block' ) [ 0 ] ?. parentElement ?. parentElement ?. parentElement ;
627626
628627 if ( ! searchBar && retryCount < maxRetries ) {
@@ -642,7 +641,11 @@ function updateSolutionsTab(title: string) {
642641 const searchBar = document . querySelectorAll ( 'input.block' ) [ 0 ] ?. parentElement ?. parentElement ?. parentElement ;
643642 if ( searchBar ) {
644643 obs . disconnect ( ) ; // Stop observing once we find the element
645- insertContent ( searchBar , title , result ) ;
644+ // Only insert if we don't already have content for this problem
645+ const existingWrapper = document . querySelector ( '.leetcode-explained-wrapper' ) ;
646+ if ( ! existingWrapper || ! document . contains ( existingWrapper ) ) {
647+ insertContent ( searchBar , title , result ) ;
648+ }
646649 }
647650 } ) ;
648651
@@ -655,7 +658,11 @@ function updateSolutionsTab(title: string) {
655658 return ;
656659 }
657660
658- insertContent ( searchBar , title , result ) ;
661+ // Only insert if we don't already have content for this problem
662+ const existingWrapper = document . querySelector ( '.leetcode-explained-wrapper' ) ;
663+ if ( ! existingWrapper || ! document . contains ( existingWrapper ) ) {
664+ insertContent ( searchBar , title , result ) ;
665+ }
659666 } ;
660667
661668 tryInsertContent ( ) ;
@@ -708,32 +715,52 @@ function insertContent(searchBar: Element, title: string, result: any) {
708715
709716// Self-initialization function that runs when the content script loads
710717function initializeSolutionsTab ( ) {
711- // Wait for the DOM to be fully loaded
712- if ( document . readyState === 'loading' ) {
713- document . addEventListener ( 'DOMContentLoaded' , onDOMReady ) ;
714- } else {
715- onDOMReady ( ) ;
716- }
717- 718- function onDOMReady ( ) {
718+ // Function to initialize content
719+ const initialize = ( ) => {
719720 // Get the problem title from the page
720721 const problemTitle = document . title . replace ( ' - LeetCode' , '' ) ;
721722
722- // Find the search bar to insert our content before it
723- const searchBar = document . querySelector ( 'div[class*="search"]' ) ;
724- if ( ! searchBar ) return ;
725- 726- // Load problem data and insert content
727- chrome . storage . local . get ( [ 'leetcodeProblems' ] , ( result ) => {
728- if ( ! result . leetcodeProblems ) return ;
729- insertContent ( searchBar , problemTitle , result ) ;
730- } ) ;
723+ // Only update if we don't have content or if it's detached from DOM
724+ const existingWrapper = document . querySelector ( '.leetcode-explained-wrapper' ) ;
725+ if ( ! existingWrapper || ! document . contains ( existingWrapper ) ) {
726+ updateSolutionsTab ( problemTitle ) ;
727+ }
728+ } ;
729+ 730+ // Set up page refresh detection using both URL and history state changes
731+ let lastUrl = location . href ;
732+ let lastState = history . state ;
733+ 734+ const observer = new MutationObserver ( ( ) => {
735+ const currentUrl = location . href ;
736+ const currentState = history . state ;
737+ 738+ // Check if this is a real navigation or just a tab switch
739+ if ( currentUrl !== lastUrl || JSON . stringify ( currentState ) !== JSON . stringify ( lastState ) ) {
740+ lastUrl = currentUrl ;
741+ lastState = currentState ;
742+ 743+ if ( currentUrl . includes ( '/solutions' ) ) {
744+ initialize ( ) ;
745+ }
746+ }
747+ } ) ;
748+ 749+ // Start observing URL changes
750+ observer . observe ( document , { subtree : true , childList : true } ) ;
751+ 752+ // Initial load
753+ if ( document . readyState === 'loading' ) {
754+ document . addEventListener ( 'DOMContentLoaded' , initialize ) ;
755+ } else {
756+ initialize ( ) ;
731757 }
732758}
733759
734760// Initialize the content script
735761initializeSolutionsTab ( ) ;
736762
763+ // Listen for messages from background script
737764chrome . runtime . onMessage . addListener ( ( request ) => {
738765 if ( request . action === 'updateSolutions' ) {
739766 updateSolutionsTab ( request . title ) ;
0 commit comments