fix: reduce memory footprint — Canvas for dot grid, scope PreferenceKey
DotGridProgress replaced GeometryReader + 200+ Circle view nodes with a single Canvas draw call. Canvas receives its own size parameter so no GeometryReader is needed; SwiftUI interpolates the progress value through the .animation modifier for smooth fill transitions. FloatingTabState ScrollYKey made private to TabBarScrollModifier to limit its PreferenceKey scope and prevent unintended propagation across unrelated subtrees.
This commit is contained in:
@@ -1107,39 +1107,29 @@ struct DotGridProgress: View {
|
||||
private let rows = 7
|
||||
|
||||
var body: some View {
|
||||
GeometryReader { geo in
|
||||
let cols = max(1, Int((geo.size.width + gap) / (dotSize + gap)))
|
||||
Canvas { ctx, size in
|
||||
let step = dotSize + gap
|
||||
let cols = max(1, Int((size.width + gap) / step))
|
||||
let total = cols * rows
|
||||
let filled = Int(Double(total) * min(max(progress, 0), 1))
|
||||
|
||||
VStack(alignment: .leading, spacing: gap) {
|
||||
ForEach(0..<rows, id: \.self) { row in
|
||||
DotRow(cols: cols, rowStart: row * cols, filled: filled,
|
||||
dotSize: dotSize, gap: gap, cs: cs)
|
||||
}
|
||||
}
|
||||
.animation(KisaniSpring.entrance, value: filled)
|
||||
}
|
||||
.frame(height: CGFloat(rows) * dotSize + CGFloat(rows - 1) * gap)
|
||||
}
|
||||
}
|
||||
|
||||
struct DotRow: View {
|
||||
let cols: Int
|
||||
let rowStart: Int
|
||||
let filled: Int
|
||||
let dotSize: CGFloat
|
||||
let gap: CGFloat
|
||||
let cs: ColorScheme
|
||||
|
||||
var body: some View {
|
||||
HStack(spacing: gap) {
|
||||
ForEach(0..<cols, id: \.self) { col in
|
||||
let isFilled = (rowStart + col) < filled
|
||||
Circle()
|
||||
.fill(isFilled ? AppColors.green : AppColors.green.opacity(0.12))
|
||||
.frame(width: dotSize, height: dotSize)
|
||||
for row in 0..<rows {
|
||||
for col in 0..<cols {
|
||||
let idx = row * cols + col
|
||||
let rect = CGRect(
|
||||
x: CGFloat(col) * step,
|
||||
y: CGFloat(row) * step,
|
||||
width: dotSize, height: dotSize
|
||||
)
|
||||
ctx.fill(
|
||||
Path(ellipseIn: rect),
|
||||
with: .color(idx < filled ? AppColors.green : AppColors.green.opacity(0.12))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
.frame(height: CGFloat(rows) * (dotSize + gap) - gap)
|
||||
.animation(KisaniSpring.entrance, value: progress)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user