# PATCH 1: Add Pin Icon Caching System # Location: Add to class properties (after line 120) # ADD AFTER: private clickDebounceTimer: any = null; private readonly CLICK_DEBOUNCE_MS = 50; private lastClickTime: number = 0; # INSERT: // ============================================ // PERFORMANCE: PIN ICON CACHE // ============================================ /** Cache for generated pin icons (color+size → data URL) */ private pinIconCache = new Map(); # ============================================ # PATCH 2: Add Debounced Change Detection System # Location: Add to imports (line 1-20) # ADD TO IMPORTS: import { Subject } from 'rxjs'; import { debounceTime, takeUntil } from 'rxjs/operators'; # ============================ # PATCH 3: Add Change Detection Properties # Location: Add to class properties (after pinIconCache) # INSERT: /** Debounced change detection subject */ private changeDetectionSubject = new Subject(); /** Cleanup subscriptions */ private destroy$ = new Subject(); # ============================================ # PATCH 4: Setup Debounced Change Detection # Location: Inside constructor (before closing brace) # FIND: constructor( private locationsService: LocationsService, private mapService: MapService, private i18nService: I18nService, private sectorService: SectorService, private dialog: MatDialog, private route: ActivatedRoute, private http: HttpClient, private cdr: ChangeDetectorRef ) {} # REPLACE WITH: constructor( private locationsService: LocationsService, private mapService: MapService, private i18nService: I18nService, private sectorService: SectorService, private dialog: MatDialog, private route: ActivatedRoute, private http: HttpClient, private cdr: ChangeDetectorRef ) { // Setup debounced change detection (batch UI updates at ~60fps) this.changeDetectionSubject .pipe( debounceTime(16), // ~60fps takeUntil(this.destroy$) ) .subscribe(() => { this.cdr.detectChanges(); }); } # ============================================ # PATCH 5: Add ngOnDestroy for Cleanup # Location: Add after ngAfterViewInit method (around line 280) # INSERT: ngOnDestroy() { this.destroy$.next(); this.destroy$.complete(); this.pinIconCache.clear(); } # ============================================ # PATCH 6: Add Helper Methods # Location: Add after constructor # INSERT: /** * Trigger debounced change detection (batches UI updates) */ private scheduleChangeDetection() { this.changeDetectionSubject.next(); } /** * Get or create a diamond pin icon with caching * ✅ OPTIMIZED: Creates canvas only once per color+size combination */ private getCachedDiamondPin(color: string, size: number = 56): string { const cacheKey = `diamond_${color}_${size}`; if (this.pinIconCache.has(cacheKey)) { return this.pinIconCache.get(cacheKey)!; } const pinIcon = this.createDiamondPinIcon(color, size); this.pinIconCache.set(cacheKey, pinIcon); return pinIcon; } # ============================================