1.6.0: auto-rellenar huecos (snapshots estimados) + widgets/lock screen enriquecidos
Auto-relleno (#5): SnapshotRepository.autoFillGap crea snapshots interpolados linealmente entre los dos snapshots que bordean el hueco, marcados isEstimated. deleteEstimatedSnapshots para borrado en bloque. Botón 'Autocompletar N meses' (wand.and.stars) en DataGapsSheet + 'Añadir manualmente'. Idempotente. Strings 7 idiomas. Widgets/Lock Screen (#8, vía agente): familias enriquecidas — systemSmall/Medium/Large con net worth + cambio desde check-in + racha + próximo check-in + progreso de objetivo; lock screen accessoryCircular (gauge objetivo/milestone), accessoryRectangular, accessoryInline. Deep link quickupdate preservado. Solo InvestmentWidget.swift. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L2p3gUZRNWW388rWFRjiU7
This commit is contained in:
@@ -62,6 +62,8 @@ struct DataGapsSheet: View {
|
||||
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
@State private var fillTarget: FillTarget?
|
||||
@State private var filledGapIds: Set<String> = []
|
||||
private let snapshotRepository = SnapshotRepository()
|
||||
|
||||
private struct FillTarget: Identifiable {
|
||||
let source: InvestmentSource
|
||||
@@ -69,15 +71,19 @@ struct DataGapsSheet: View {
|
||||
var id: String { "\(source.id.uuidString)-\(date.timeIntervalSince1970)" }
|
||||
}
|
||||
|
||||
private var visibleGaps: [SnapshotGapDetector.Gap] {
|
||||
gaps.filter { !filledGapIds.contains($0.id) }
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
List {
|
||||
Section {
|
||||
ForEach(gaps) { gap in
|
||||
ForEach(visibleGaps) { gap in
|
||||
gapRow(gap)
|
||||
}
|
||||
} footer: {
|
||||
Text("The chart estimates these months. Add real snapshots to keep your history accurate.")
|
||||
Text("Auto-fill estimates the missing months between two snapshots (marked as estimated). Or add the real values yourself.")
|
||||
}
|
||||
}
|
||||
.navigationTitle("Missing Data")
|
||||
@@ -116,14 +122,34 @@ struct DataGapsSheet: View {
|
||||
|
||||
if let source = sourceProvider(gap.sourceId),
|
||||
let firstMissing = gap.missingMonthDates.first {
|
||||
Button {
|
||||
fillTarget = FillTarget(source: source, date: firstMissing)
|
||||
} label: {
|
||||
Label("Fill Gap", systemImage: "plus.circle.fill")
|
||||
HStack(spacing: 16) {
|
||||
Button {
|
||||
let n = snapshotRepository.autoFillGap(
|
||||
source: source,
|
||||
from: gap.fromMonth,
|
||||
to: gap.toMonth,
|
||||
missingMonthDates: gap.missingMonthDates
|
||||
)
|
||||
if n > 0 { filledGapIds.insert(gap.id) }
|
||||
} label: {
|
||||
Label(
|
||||
String(format: String(localized: "gaps_autofill_cta"), gap.missingMonths),
|
||||
systemImage: "wand.and.stars"
|
||||
)
|
||||
.font(.subheadline.weight(.semibold))
|
||||
}
|
||||
.buttonStyle(.borderless)
|
||||
.tint(.appPrimary)
|
||||
|
||||
Button {
|
||||
fillTarget = FillTarget(source: source, date: firstMissing)
|
||||
} label: {
|
||||
Label("Add manually", systemImage: "plus.circle")
|
||||
.font(.subheadline)
|
||||
}
|
||||
.buttonStyle(.borderless)
|
||||
.tint(.secondary)
|
||||
}
|
||||
.buttonStyle(.borderless)
|
||||
.tint(.appPrimary)
|
||||
}
|
||||
}
|
||||
.padding(.vertical, 4)
|
||||
|
||||
Reference in New Issue
Block a user