Feedback iPad: allocation grande + %, Home 2 columnas, YoY KPIs, achievements fix, iCloud calmado (build 58)
Allocation: - Semicírculo responsive que llena su mitad de la fila (grande en iPad, no minúsculo en una esquina) + porcentaje dentro de cada segmento >=7%. SemicircleArc acepta center explícito; labels en el ángulo medio del arco. Home iPad: - Ya no columna única estrecha a 720. Hero + check-in a ancho completo, resto de cards en DOS columnas masonry independientes (sin acoplar alturas → sin gaps del grid). Cap 1100pt. Year vs Year KPIs: - Retorno del año actual + diferencia (pp) vs año anterior + mejor/peor año histórico. Usa forecastEndValue para el año en curso. Fixes: - 'View all achievements' en Journal no hacía nada: NavigationLink inline (frágil según contexto de navegación) → sheet fiable en cualquier sitio. - iCloud: CKErrorPartialFailure tras una sync que funciona ya NO se pinta en rojo alarmante — nota calmada 'Sincronizando con iCloud' + detalle técnico en disclosure. Rojo solo si nunca ha sincronizado y es fallo total. syncErrorIsCritical + strings ×7. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WoScpmHdVj1aUf4rAp6hbe
This commit is contained in:
@@ -425,22 +425,42 @@ struct SettingsView: View {
|
||||
}
|
||||
}
|
||||
|
||||
// CloudKit error (if any)
|
||||
// CloudKit status: only alarm (red) when sync is genuinely
|
||||
// broken. A partial failure while data is syncing is shown as
|
||||
// a calm "still syncing" note, not a scary error.
|
||||
if let error = cloudStack.lastSyncError {
|
||||
let critical = cloudStack.syncErrorIsCritical
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
Label("CloudKit error", systemImage: "exclamationmark.icloud")
|
||||
.font(.caption.weight(.semibold))
|
||||
.foregroundColor(.red)
|
||||
if let hint = cloudStack.lastSyncErrorHint {
|
||||
Label(
|
||||
critical
|
||||
? String(localized: "icloud_status_error")
|
||||
: String(localized: "icloud_status_syncing"),
|
||||
systemImage: critical ? "exclamationmark.icloud" : "arrow.triangle.2.circlepath.icloud"
|
||||
)
|
||||
.font(.caption.weight(.semibold))
|
||||
.foregroundColor(critical ? .red : .secondary)
|
||||
|
||||
if critical, let hint = cloudStack.lastSyncErrorHint {
|
||||
Text(hint)
|
||||
.font(.caption)
|
||||
.foregroundColor(.primary)
|
||||
}
|
||||
Text(error)
|
||||
.font(.caption2)
|
||||
.foregroundColor(.secondary)
|
||||
.lineLimit(6)
|
||||
.textSelection(.enabled)
|
||||
|
||||
// Technical detail is opt-in behind a disclosure, so it
|
||||
// never dominates the screen for a benign partial sync.
|
||||
DisclosureGroup(String(localized: "icloud_show_details")) {
|
||||
if let hint = cloudStack.lastSyncErrorHint, !critical {
|
||||
Text(hint)
|
||||
.font(.caption2)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
Text(error)
|
||||
.font(.caption2)
|
||||
.foregroundColor(.secondary)
|
||||
.textSelection(.enabled)
|
||||
}
|
||||
.font(.caption2)
|
||||
.tint(.secondary)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user