@@ -45,7 +45,7 @@ function detectAndSyncTheme() {
45
45
isDarkTheme : leetcodeTheme === 'dark'
46
46
} ) ;
47
47
48
- console . log ( `Theme auto-detected: ${ leetcodeTheme } ` ) ;
48
+ // console.log(`Theme auto-detected: ${leetcodeTheme}`);
49
49
50
50
// Set up observer for future theme changes
51
51
observeThemeChanges ( ) ;
@@ -70,7 +70,7 @@ function observeThemeChanges() {
70
70
chrome . storage . local . set ( {
71
71
isDarkTheme : leetcodeTheme === 'dark'
72
72
} ) ;
73
- console . log ( `Theme changed to: ${ leetcodeTheme } ` ) ;
73
+ // console.log(`Theme changed to: ${leetcodeTheme}`);
74
74
}
75
75
} ) ;
76
76
} ) ;
@@ -162,16 +162,21 @@ function showRating(problemTitle: string) {
162
162
// show the company tags if the user has enabled it in the settings
163
163
function showCompanyTags ( problemTitle : string ) {
164
164
chrome . storage . local . get ( [ 'showCompanyTags' ] , ( result ) => {
165
- if ( ! result . showCompanyTags ) {
166
- return ;
167
- }
168
-
169
165
// Check if we're on the description tab before proceeding
170
166
const isDescriptionPage = ! window . location . href . includes ( '/solutions' ) ;
171
167
if ( ! isDescriptionPage ) {
172
168
return ;
173
169
}
174
170
171
+ // Remove existing container if setting is disabled
172
+ const existingContainer = document . getElementById ( 'companyTagContainer' ) ;
173
+ if ( ! result . showCompanyTags ) {
174
+ if ( existingContainer ) {
175
+ existingContainer . remove ( ) ;
176
+ }
177
+ return ;
178
+ }
179
+
175
180
// Try to find the description element with retries
176
181
const maxRetries = 10 ;
177
182
const baseDelay = 300 ;
@@ -209,13 +214,11 @@ function showCompanyTags(problemTitle: string) {
209
214
// Use exponential backoff for retry delay
210
215
const delay = baseDelay * Math . pow ( 1.5 , retryCount ) ;
211
216
retryCount ++ ;
212
- console . log ( `Attempt ${ retryCount } : Waiting for description element to load... Retrying in ${ delay } ms` ) ;
213
217
setTimeout ( tryInsertCompanyTags , delay ) ;
214
218
return ;
215
219
}
216
220
217
221
if ( ! description ) {
218
- console . log ( 'Failed to find description element after all retries' ) ;
219
222
220
223
// If still not found, set up a MutationObserver to watch for DOM changes
221
224
const observer = new MutationObserver ( ( mutations , obs ) => {
@@ -373,10 +376,16 @@ function setupDescriptionThemeListener() {
373
376
374
377
chrome . runtime . onMessage . addListener ( ( request , sender , sendResponse ) => {
375
378
if ( request . action === 'updateDescription' ) {
379
+ // For settings updates, bypass the state checks
380
+ if ( request . isSettingsUpdate ) {
381
+ console . log ( 'Updating description tab due to settings change...' ) ;
382
+ updatePageContent ( ) ;
383
+ return true ;
384
+ }
385
+
376
386
// Only detect theme on first load, problem change, or refresh
377
387
if ( ! request . isProblemChange && ! request . isRefresh ) {
378
- console . log ( 'Skipping theme detection for internal navigation' ) ;
379
- return ;
388
+ return true ;
380
389
}
381
390
382
391
console . log ( 'Updating description tab...' ) ;
@@ -412,38 +421,93 @@ function initializeDescriptionTab() {
412
421
// Set up theme detection and synchronization
413
422
setupDescriptionThemeListener ( ) ;
414
423
415
- // Get the problem title from the page
416
- const problemTitle = document . title . replace ( ' - LeetCode' , '' ) ;
417
-
418
- // Apply all enhancements
419
- showDifficulty ( ) ;
420
- showRating ( problemTitle ) ;
421
- showCompanyTags ( problemTitle ) ;
422
- showExamples ( ) ;
424
+ // Initial load of enhancements
425
+ updatePageContent ( ) ;
423
426
424
- // Set up a MutationObserver to detect tab changes
427
+ // Set up URL change detection using History API
428
+ const originalPushState = history . pushState ;
429
+ const originalReplaceState = history . replaceState ;
430
+
431
+ history . pushState = function ( data : any , unused : string , url ?: string | URL ) {
432
+ originalPushState . call ( this , data , unused , url ) ;
433
+ handleUrlChange ( ) ;
434
+ } ;
435
+
436
+ history . replaceState = function ( data : any , unused : string , url ?: string | URL ) {
437
+ originalReplaceState . call ( this , data , unused , url ) ;
438
+ handleUrlChange ( ) ;
439
+ } ;
440
+
441
+ window . addEventListener ( 'popstate' , handleUrlChange ) ;
442
+
443
+ // Set up a MutationObserver to detect tab and content changes
425
444
const observer = new MutationObserver ( ( mutations ) => {
445
+ let shouldUpdate = false ;
446
+
426
447
mutations . forEach ( ( mutation ) => {
427
- if ( mutation . type === 'childList' && mutation . addedNodes . length > 0 ) {
428
- // Check if we're on the description tab
429
- const descriptionTab = document . querySelector ( '[data-cy="description-tab"]' ) ;
430
- if ( descriptionTab && descriptionTab . classList . contains ( 'active' ) ) {
431
- // Re-apply company tags when switching to description tab
432
- const problemTitle = document . title . replace ( ' - LeetCode' , '' ) ;
433
- showCompanyTags ( problemTitle ) ;
448
+ // Check for tab changes
449
+ if ( mutation . target instanceof HTMLElement ) {
450
+ const isTabChange = mutation . target . getAttribute ( 'role' ) === 'tab' ||
451
+ mutation . target . closest ( '[role="tab"]' ) ;
452
+ if ( isTabChange ) {
453
+ shouldUpdate = true ;
434
454
}
435
455
}
456
+
457
+ // Check for content changes in the main container
458
+ if ( mutation . type === 'childList' &&
459
+ ( ( mutation . target instanceof HTMLElement && mutation . target . classList ?. contains ( 'elfjS' ) ) ||
460
+ mutation . addedNodes . length > 0 ) ) {
461
+ shouldUpdate = true ;
462
+ }
436
463
} ) ;
464
+
465
+ if ( shouldUpdate ) {
466
+ // Small delay to ensure DOM is fully updated
467
+ setTimeout ( updatePageContent , 100 ) ;
468
+ }
437
469
} ) ;
438
470
439
- // Start observing the tab container
440
- const tabContainer = document . querySelector ( '[role="tablist"]' ) ;
441
- if ( tabContainer ) {
442
- observer . observe ( tabContainer , { childList : true , subtree : true } ) ;
443
- }
471
+ // Observe both the tab container and the main content area
472
+ observer . observe ( document . body , {
473
+ childList : true ,
474
+ subtree : true ,
475
+ attributes : true ,
476
+ attributeFilter : [ 'class' , 'data-cy' ]
477
+ } ) ;
478
+ }
479
+ }
480
+
481
+ // Update all page content
482
+ function updatePageContent ( ) {
483
+ const problemTitle = document . title . replace ( ' - LeetCode' , '' ) . split ( '-' ) [ 0 ] . trim ( ) ;
484
+ const isDescriptionTab = isOnDescriptionTab ( ) ;
485
+
486
+ if ( isDescriptionTab ) {
487
+ showCompanyTags ( problemTitle ) ;
488
+ showDifficulty ( ) ;
489
+ showRating ( problemTitle ) ;
490
+ showExamples ( ) ;
444
491
}
445
492
}
446
493
494
+ // Check if we're on the description tab
495
+ function isOnDescriptionTab ( ) {
496
+ // Check multiple conditions to determine if we're on the description tab
497
+ const descriptionTab = document . querySelector ( '[data-cy="description-tab"]' ) ;
498
+ const isDescriptionActive = descriptionTab ?. classList . contains ( 'active' ) ;
499
+ const notOnSolutions = ! window . location . href . includes ( '/solutions' ) ;
500
+ const hasDescriptionContent = ! ! document . getElementsByClassName ( 'elfjS' ) [ 0 ] ;
501
+
502
+ return ( isDescriptionActive || notOnSolutions ) && hasDescriptionContent ;
503
+ }
504
+
505
+ // Handle URL changes
506
+ function handleUrlChange ( ) {
507
+ // Small delay to ensure DOM is updated
508
+ setTimeout ( updatePageContent , 200 ) ;
509
+ }
510
+
447
511
// Initialize the content script
448
512
initializeDescriptionTab ( ) ;
449
513
0 commit comments