Atoll/logic.md
Hariharan Mudaliar 471fb6723e Update README
2025-08-01 23:08:40 +05:30

6.2 KiB

Dynamic Island Alignment Logic Analysis

Problem Statement

The Dynamic Island window sometimes gets misaligned (moves to the left) when switching between tabs, especially when going from stats tab (with 4+ graphs that make the window wider) back to other tabs.

Current Implementation Analysis

When Window is Created

  1. createDynamicIslandWindow() creates window with openNotchSize (fixed size)
  2. positionWindow() centers it using current window width
  3. Window is perfectly centered initially

When User Switches to Stats Tab (4+ graphs)

  1. coordinator.$currentView triggers updateWindowSizeIfNeeded()
  2. calculateRequiredNotchSize() returns larger size (openNotchSize.width + extraWidth)
  3. updateWindowSizeIfNeeded() resizes window and re-centers using new width
  4. Window should stay centered with new larger size

When User Switches Away from Stats Tab

  1. coordinator.$currentView triggers updateWindowSizeIfNeeded() again
  2. calculateRequiredNotchSize() returns normal openNotchSize
  3. updateWindowSizeIfNeeded() resizes window back and re-centers using normal width
  4. THIS IS WHERE THE PROBLEM OCCURS

Root Cause Analysis

The Issue: Timing and State Mismatch

The problem is likely that coordinator.currentView and the actual UI state are not perfectly synchronized. Here's what probably happens:

  1. User clicks another tab
  2. coordinator.$currentView fires immediately
  3. updateWindowSizeIfNeeded() calculates size as if we're NOT on stats tab
  4. BUT the ContentView might still be showing stats content (transition not complete)
  5. Window gets resized to small size while content is still large
  6. This causes misalignment because content and window size don't match

Why It Sometimes Works

  • When the UI transition is fast enough, everything stays in sync
  • When there's any delay or animation, they get out of sync

Potential Solutions

Option 1: Delay the Window Resize

Add a small delay to ensure UI transition is complete before resizing window.

Option 2: Remove Window Resizing, Use Content Clipping

Let the window stay large and let the content handle its own sizing internally.

Option 3: Better State Synchronization

Make sure window resizing only happens when we're 100% sure the content has updated.

Option 4: Use ContentView's dynamicNotchSize Instead

The ContentView already has dynamicNotchSize logic. Maybe the window should use that instead of having its own calculation.

Option 2 seems safest: Remove dynamic window resizing entirely and let the content handle sizing.

The ContentView already has:

var dynamicNotchSize: CGSize {
    // calculation logic
}

And uses it in:

.frame(maxWidth: dynamicNotchSize.width, maxHeight: dynamicNotchSize.height)

This means the content already knows how to size itself. The window can stay at the maximum possible size, and the content will center itself within that space.

Test Plan

  1. Remove all dynamic window resizing logic
  2. Set window to maximum possible size (openNotchSize.width + max extra width)
  3. Let ContentView handle all dynamic sizing internally
  4. Test alignment stays perfect

This eliminates the timing issue completely because the window never changes size after initial creation.

CRITICAL DISCOVERY - Clipboard is NOT a Tab View

Major Finding

The .clipboard case doesn't exist in NotchViews enum!

public enum NotchViews {
    case home
    case shelf
    case timer
    case stats
}

What This Means

  • All my protective logic for coordinator.currentView == .clipboard is ineffective
  • Clipboard functionality works differently - likely as a popover or overlay, not a tab
  • The hover collapse issue is NOT about tab transitions but about popover interactions

Investigation Results

  1. ContentView switch statement only handles: .home, .shelf, .timer, .stats
  2. No clipboard tab content rendering in the main view switch
  3. Clipboard must be implemented as popover/overlay system

New Hypothesis

The clipboard "area" the user refers to is likely:

  1. ClipboardHistoryPopover - a popover that opens over the Dynamic Island
  2. ClipboardManager integration - clipboard content shown in existing tabs
  3. Overlay system - clipboard UI overlaid on top of main content

Critical Issue Identified

My previous fix added protections for .clipboard view that DOESN'T EXIST, meaning:

  • Protections are not working
  • Hover collapse still happening during clipboard interactions
  • Need to find actual clipboard interaction boundaries

Next Steps

  1. Find real clipboard implementation - how is clipboard content actually shown?
  2. Identify clipboard hover boundaries - what UI element represents "clipboard area"?
  3. Fix actual interaction conflicts - coordinate between clipboard popover and main hover logic

When This Caused Problems:

  1. "Show on all displays" toggle: Creates new window with default openNotchSize, losing dynamic sizing
  2. Screen changes: adjustWindowPosition() creates new windows with wrong size
  3. App restarts/other events: Any time a new window is created, it ignores current dynamic sizing needs

The Wrong Code:

// OLD - ALWAYS used openNotchSize
let window = DynamicIslandWindow(
    contentRect: NSRect(x: 0, y: 0, width: openNotchSize.width, height: openNotchSize.height),
    ...

The Fix:

// NEW - Uses current required size
let requiredSize = calculateRequiredNotchSize()
let window = DynamicIslandWindow(
    contentRect: NSRect(x: 0, y: 0, width: requiredSize.width, height: requiredSize.height),
    ...

Why This Fixes Everything:

✅ "Show on all displays" toggle: New windows created with correct size
✅ Tab switching: No more size mismatch when repositioning
✅ Screen changes: New windows respect current graph settings
✅ Consistent behavior: All window creation uses same sizing logic

The Real Issue Was:

  • Windows created with wrong size, then positioned correctly = misalignment
  • Content expecting larger window, but window is small = positioning errors
  • Dynamic sizing only worked if you never triggered window recreation

Result:

Perfect alignment in ALL scenarios - no more window size/content size mismatches!