iPhone Duo (fase 1): navegación adaptativa por size class y layouts regular×regular

- ContentView: un único TabView (sidebarAdaptable en iOS 18+) para todas las
  size classes; desaparece el cambio de jerarquía iPhone/iPad, así abrir o
  cerrar el Duo conserva el estado de cada pestaña. @SceneStorage de la tab.
- Fuentes y Diario: NavigationSplitView (lista + detalle a la vez en ancho
  regular, stack colapsable en compacto) con selección nativa de List.
- Dashboard: Quick Update como .inspector (panel lateral junto a los gráficos
  en regular, sheet en compacto).
- Gráficos: chartHeightScale (+35% de alto en regular) vía chartFrame(height:),
  sin ignoresSafeArea en contenido interactivo.
- Liquid Glass (glassEffect) en las etiquetas flotantes del Diario en iOS 26+.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F1u4K16xy7eQVtgsYNZ9Vn
This commit is contained in:
alexandrev-tibco
2026-09-16 11:44:50 +02:00
parent a8a9ad64f3
commit 680255f69d
17 changed files with 485 additions and 547 deletions
@@ -36,10 +36,10 @@ struct PredictionChartView: View {
VStack(alignment: .trailing, spacing: 2) {
Text("Forecast")
.font(.caption)
.foregroundColor(.secondary)
.foregroundStyle(.secondary)
Text(lastPrediction.formattedValue)
.font(.subheadline.weight(.semibold))
.foregroundColor(.appPrimary)
.foregroundStyle(Color.appPrimary)
}
}
}
@@ -47,7 +47,7 @@ struct PredictionChartView: View {
if let algorithm = predictions.first?.algorithm {
Text("Algorithm: \(algorithm.displayName)")
.font(.caption)
.foregroundColor(.secondary)
.foregroundStyle(.secondary)
}
if !predictions.isEmpty && historicalData.count >= 2 {
@@ -185,7 +185,7 @@ struct PredictionChartView: View {
}
}
}
.frame(height: 280)
.chartFrame(height: 280)
// Stats row
if let currentValue = historicalData.last?.value,
@@ -206,7 +206,7 @@ struct PredictionChartView: View {
.frame(width: 20, height: 3)
Text("Historical")
.font(.caption)
.foregroundColor(.secondary)
.foregroundStyle(.secondary)
}
HStack(spacing: 6) {
@@ -223,7 +223,7 @@ struct PredictionChartView: View {
)
Text("Prediction")
.font(.caption)
.foregroundColor(.secondary)
.foregroundStyle(.secondary)
}
HStack(spacing: 6) {
@@ -232,7 +232,7 @@ struct PredictionChartView: View {
.frame(width: 20, height: 10)
Text("Confidence")
.font(.caption)
.foregroundColor(.secondary)
.foregroundStyle(.secondary)
}
HStack(spacing: 6) {
@@ -241,7 +241,7 @@ struct PredictionChartView: View {
.frame(width: 20, height: 2)
Text("Bull")
.font(.caption)
.foregroundColor(.secondary)
.foregroundStyle(.secondary)
}
HStack(spacing: 6) {
@@ -250,7 +250,7 @@ struct PredictionChartView: View {
.frame(width: 20, height: 2)
Text("Bear")
.font(.caption)
.foregroundColor(.secondary)
.foregroundStyle(.secondary)
}
}
@@ -274,7 +274,7 @@ struct PredictionChartView: View {
Spacer()
Text(lastPrediction.formattedConfidenceRange)
.font(.caption)
.foregroundColor(.secondary)
.foregroundStyle(.secondary)
}
if let currentValue = historicalData.last?.value {
@@ -293,7 +293,7 @@ struct PredictionChartView: View {
Text(String(format: "%+.1f%%", changePercent))
.font(.subheadline.weight(.medium))
}
.foregroundColor(change >= 0 ? .positiveGreen : .negativeRed)
.foregroundStyle(change >= 0 ? Color.positiveGreen : Color.negativeRed)
}
}
}
@@ -310,24 +310,24 @@ struct PredictionChartView: View {
VStack(spacing: 12) {
Image(systemName: "wand.and.stars")
.font(.system(size: 40))
.foregroundColor(.secondary)
.foregroundStyle(.secondary)
Text("Not enough data for predictions")
.font(.subheadline)
.foregroundColor(.secondary)
.foregroundStyle(.secondary)
Text("Add at least 3 snapshots to generate predictions")
.font(.caption)
.foregroundColor(.secondary)
.foregroundStyle(.secondary)
.multilineTextAlignment(.center)
}
.frame(height: 280)
.chartFrame(height: 280)
.frame(maxWidth: .infinity)
}
}
.padding()
.background(Color(.systemBackground))
.cornerRadius(AppConstants.UI.cornerRadius)
.clipShape(RoundedRectangle(cornerRadius: AppConstants.UI.cornerRadius))
.shadow(color: .black.opacity(0.05), radius: 8, y: 2)
}