Skip to content

Cache Invalidation for Layer Mappings #119

@malpern

Description

@malpern

Problem

When rule collections are toggled on/off in the UI, the in-memory layer mapping cache is not invalidated. This causes stale labels to appear on the overlay keyboard until the app is restarted.

Example Reproduction

  1. Enable Window Snapping rule collection (targets "window" layer)
  2. Press Space to enter Nav layer
  3. Window Snapping labels incorrectly appear on Nav layer keys
  4. Toggle Window Snapping off
  5. Bug: Labels still appear until app restart
  6. Restart app → labels correctly disappear

Root Cause

LayerKeyMapper caches layer mappings in memory, but the cache is not invalidated when:

  • Rule collections are enabled/disabled
  • Custom rules are added/removed/modified
  • Rule collection mappings are changed
  • Layer targets are changed

Proposed Solution

Implement cache invalidation mechanism that triggers when rule configuration changes:

Option 1: Notification-Based Invalidation

Listen to NotificationCenter events for:

  • Rule collection toggle
  • Custom rule changes
  • Mapping modifications
NotificationCenter.default.addObserver(
    forName: .ruleCollectionDidChange,
    object: nil,
    queue: .main
) { [weak self] _ in
    self?.layerKeyMapper.invalidateCache()
    self?.rebuildLayerMapping()
}

Option 2: Explicit Invalidation

Add explicit cache invalidation calls in RuleCollectionsManager:

func toggleRuleCollection(_ id: UUID) {
    // ... existing toggle logic ...
    NotificationCenter.default.post(name: .layerCacheInvalidated, object: nil)
}

Option 3: Smart Cache Keys

Use hash of rule configuration as cache key:

struct CacheKey: Hashable {
    let layerName: String
    let ruleConfigHash: String // Hash of enabled collections + custom rules
}

Affected Components

  • LayerKeyMapper: Needs invalidation API
  • KeyboardVisualizationViewModel: Needs to listen for invalidation events
  • RuleCollectionsManager: Needs to trigger invalidation
  • OverlayKeyboardView: Needs to rebuild when cache invalidated

Acceptance Criteria

  • Toggling rule collections updates overlay labels immediately (no restart)
  • Adding/removing custom rules updates labels immediately
  • Modifying rule mappings updates labels immediately
  • Changing rule target layers updates labels immediately
  • No performance regression (cache still effective for unchanged config)
  • Thread-safe cache invalidation (UI thread)

Related Work

  • Layer filtering fix in augmentWithPushMsgActions() (completed)
  • This issue discovered while testing contextual help feature

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions