# Issue: UIObservationTrackingFeedbackLoop on "Designed for iPad" macOS with NavigationBarContentView

## Description
- Aplicația USB Meter (SwiftUI "Designed for iPad") se bloaca instant la deschiderea `MeterView` pe macOS Apple Silicon, cu eroare repetata `UIObservationTrackingFeedbackLoopDetected` in `NavigationBarContentView.updateProperties`.
- Freezeul apare **inainte** ca datele BLE să ajunga (instant la deschidere), diferit de problema Catalyst (care era blocata pe navigare).
- Condiții: macOS Apple Silicon cu "Designed for iPad" mode (UIKit hosted SwiftUI). Pe Catalyst, NU apare (AppKit toolbar remplace NavigationBarContentView).

## Impact
- Imposibil de deschis meter view pe "Designed for iPad" macOS
- Aplicatia devine complet neresponsiva, CPU la 100%
- Error stack: `NavigationBarContentView` intra in ciclu infinit de observare SwiftUI (sa se schimbe ceva constant)

## Root Cause Analysis

### Ipoteza initiala (INCORECTA): Update frequency pe model
- Prim diagnostic: "poate BLE packet-uri (~1Hz) cu 15+ @Published pe Meter triggerez body re-evaluate, care triggerez NavigationBar update, care cicleaza la infinit"
- **CONCLUZIUNE incorecta**: problema nu este frecventa datelor; eroarea apare instant, inainte ca Bluetooth sa se conecteze

### Adevarat root cause (GASIT): UIKit NavigationBarContentView bug
- NavigationBarContentView (UIKit hosted component) are implement basata pe @Observable tracking
- Cand SwiftUI seteaza `.navigationBarTitle()` + `.toolbar {}` pe o view push-uit in split NavigationView, UIKit intra in infinite feedback loop pe observation changes
- Bug specific la "Designed for iPad" pe macOS; pe Catalyst NU apare (AppKit toolbar inlocuieste NavigationBarContentView)
- Eroarea apare **inainte** ca bind pe meter data; doar configurarea vue modifiers triggerez loop-ul

## Investigatie si attempts

### 1. Model-layer deduplication (PARTIAL, nu era fix principal)
Implemented:
- `BluetoothSerial.swift`: RSSI averaging (sliding window 3 = ~9s), singura @Published ramasa
- `Meter.swift`: Eliminat @Published de la ~20 proprietati per-packet (voltage, current, power, temps, etc.). Adaugat `setIfChanged()` helper cu dedup. Singur `objectWillChange.send()` la final de `parseData()` doar daca ceva s-a schimbat. Guard pe `operationalState` oscillation
- `Measurements.swift`: `objectWillChange.send()` doar cand punct e adaugat (nu pe accumulation)
- **Rezultat**: Zero improvement pe problema Designed-for-iPad. Insa sunt optimizari bune pentru defense-in-depth.

### 2. Toolbar migration (DEPRECATED API FIX, nu era problema)
- Inlocuit `.navigationBarItems(trailing:)` cu `.toolbar { ToolbarItemGroup }` in MeterView
- Adaugat @State buffers (`navBarTitle`, `navBarShowRSSI`, `navBarRSSI`) ca shield
- **Rezultat**: Zero improvement. Nu era problema API veche; problema era conceptuala (UIKit nav bar pe Mac).

### 3. UIKit NavigationBarContentView bypass (SOLUTIE FINALA)
- Runtime detection: `ProcessInfo.processInfo.isiOSAppOnMac` (true doar pe "Designed for iPad" pe Mac)
- **MeterView.swift**:
  - Adaugat `static let isMacIPadApp: Bool = ProcessInfo.processInfo.isiOSAppOnMac`
  - Body rewritten: VStack cu conditional `macNavigationHeader` (custom back button via `dismiss()`, title, RSSI, settings)
  - `.navigationBarHidden(true)` cand `isMacIPadApp || landscape`
  - Creat `IOSOnlyNavBar` ViewModifier (@ViewBuilder if/else): applies `.navigationBarTitle()` + `.toolbar {}` DOAR cand `!isMacIPadApp`, passeaza content nemodificat pe Mac
- **MeterSettingsView.swift**: Acelasi pattern
  - Custom `macSettingsHeader` cu back button, title, RSSI
  - `IOSOnlySettingsNavBar` ViewModifier pentru conditional nav bar modifiers
- Pe real iPad: toti modifiers se aplica normal (nav bar standard UIKit)

## Solutie finala aplicata

### Fișiere modificate
1. **MeterView.swift** (728 → 765 lines)
   - Adaugat `@Environment(\.dismiss)` si `isMacIPadApp` static const
   - Rewritten body cu conditional `macNavigationHeader` (HStack cu back button, title, RSSI, settings NavigationLink)
   - Adaugat `IOSOnlyNavBar` ViewModifier private struct cu @ViewBuilder if/else

2. **MeterSettingsView.swift**
   - Adaugat `@Environment(\.dismiss)` si `isMacIPadApp` static const
   - Body rewritten cu VStack + conditional `macSettingsHeader`
   - Adaugat `IOSOnlySettingsNavBar` ViewModifier private struct

3. **Model layer** (executat anterior, nu direct pentru fix), dar relevant:
   - BluetoothSerial.swift: RSSI averaging
   - Meter.swift: @Published dedup
   - Measurements.swift: objectWillChange fix

## Test status
- ✅ Compileaza fara erori
- ✅ "Designed for iPad" mode pe macOS: MeterView si MeterSettingsView deschid fara blocaj
- ⚠️ Real iPad: NU am iPad disponibil sa verific ca problema nu apare (nu am device pentru test)
  - UIKit nav bar modifiers se aplica normal pe real iPad (path aplicarii e diferit din UIKit sandbox)
  - Expect sa fie OK dar nu am certitudine

## Commit-uri
- [recent] - UIKit NavBar bypass pe "Designed for iPad", MeterView + MeterSettingsView custom headers

## Verificare
- pe macOS Apple Silicon + "Designed for iPad": deschide app, selecteaza meter, apasa sa o deschizi
  - MeterView trebuie sa deschida fara freeze
  - MeterSettingsView (pe gear icon) trebuie sa deschida fara freeze
  - Back button sa revina la lista

## Lessons learned
- Nu toate feedback loop-urile ObservableObject sunt cauzate de frecventa datelor
- UIKit pe macOS "Designed for iPad" are bugs nedocumentate in observation tracking cand SwiftUI configureaza nav bar
- Catalyst (AppKit) nu are problema (toolbar separat)
- Workaround: bypass-ul ca sa nu setam nav bar modifiers pe Mac

## Notes pentru viitor
- Aceasta solutie functioneaza pe "Designed for iPad" + Catalyst
- Nu am testat pe real iPad (nu am device); expect sa fie OK din arhitectura (modifiers se aplica)
- Daca problema apare pe real iPad in viitor: mai multi custom headers nu scala; s-ar putea reveni la NavigationView + sheet-based nav (cum am facut pe Catalyst in issue #001)
