Charts: fix selección iPad/charts bloqueadas, filtro Rolling 12M, KPIs específicos y botón compartir
Bugs: - Charts bloqueadas (intermitente) y tiles que no responden: el observer Combine registraba el estado como actualizado ANTES de llamar a updateChartData, cuyo guard de reentrada descartaba la llamada en silencio — reintentarlo era no-op permanente. Ahora el bookkeeping vive dentro de updateChartData, las llamadas reentrantes se colean en vez de descartarse, y selectChart computa en síncrono (pulsar un tile es determinista y re-pulsar actúa de retry). - Paywall sheet: movida del Group que cambia con el size class a cada layout — en NavigationSplitView no llegaba a presentarse (tiles premium 'no hacían nada'). - Rolling 12M: el filtro de periodo no filtraba — el cálculo necesita histórico completo para el lookback, pero ahora la salida respeta selectedTimeRange. KPIs: - El header de iPad muestra KPIs específicos del chart activo (los mismos que su stats row) en vez de las 5 métricas de cartera fijas; las stats rows dentro de las cards se ocultan en regular width para no duplicar (YoY opta por quedarse al no tener equivalente en el header). Compartir: - Botón de compartir por chart (toolbar iPad + navbar iPhone): renderiza la gráfica en una card con branding (BrandMark, KPIs, tagline, QR al App Store con ct=chart_share) vía ImageRenderer y abre el share sheet con imagen + link. - drawingGroup() se desactiva durante el export (ImageRenderer no rasteriza capas Metal — salían en blanco). Strings nuevas en 7 idiomas. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WoScpmHdVj1aUf4rAp6hbe
This commit is contained in:
@@ -10,23 +10,31 @@ struct ChartStat {
|
||||
// MARK: - Stats summary row (horizontal scroll of chips)
|
||||
struct ChartStatsRow: View {
|
||||
let stats: [ChartStat]
|
||||
/// On regular width the charts container surfaces these stats in the KPI
|
||||
/// header above the chart — hide the in-card duplicate row. Charts without a
|
||||
/// header equivalent (e.g. Year vs Year) opt back in.
|
||||
var showsOnRegularWidth = false
|
||||
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
|
||||
|
||||
var body: some View {
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
HStack(spacing: 10) {
|
||||
ForEach(stats.indices, id: \.self) { i in
|
||||
VStack(alignment: .center, spacing: 3) {
|
||||
Text(stats[i].label)
|
||||
.font(.caption2)
|
||||
.foregroundColor(.secondary)
|
||||
Text(stats[i].value)
|
||||
.font(.subheadline.weight(.semibold))
|
||||
.foregroundColor(stats[i].color)
|
||||
if horizontalSizeClass != .regular || showsOnRegularWidth {
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
HStack(spacing: 10) {
|
||||
ForEach(stats.indices, id: \.self) { i in
|
||||
VStack(alignment: .center, spacing: 3) {
|
||||
Text(stats[i].label)
|
||||
.font(.caption2)
|
||||
.foregroundColor(.secondary)
|
||||
Text(stats[i].value)
|
||||
.font(.subheadline.weight(.semibold))
|
||||
.foregroundColor(stats[i].color)
|
||||
}
|
||||
.frame(minWidth: 60)
|
||||
.padding(.horizontal, 12)
|
||||
.padding(.vertical, 8)
|
||||
.background(Color(.systemGray6))
|
||||
.cornerRadius(8)
|
||||
}
|
||||
.frame(minWidth: 60)
|
||||
.padding(.horizontal, 12)
|
||||
.padding(.vertical, 8)
|
||||
.background(Color(.systemGray6))
|
||||
.cornerRadius(8)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user