← All repositories

listless

A simple list app for Apple platforms

git clone https://code.inqk.net/listless.git


ListlessiOS/Views/PullToClear.swift (1799B)

1import SwiftUI
2
3/// Pull distance at which the indicator signals readiness and completed item clearing triggers.
4let pullClearThreshold: CGFloat = 50
5
6struct PullToClearIndicator: View {
7    let pullOffset: CGFloat
8
9    private var progress: CGFloat { min(1, pullOffset / pullClearThreshold) }
10    private var isReady: Bool { pullOffset >= pullClearThreshold }
11    private let textSlideDistance: CGFloat = 22
12
13    var body: some View {
14        HStack(spacing: 6) {
15            ZStack {
16                Image(systemName: "checkmark")
17                    .offset(y: isReady ? 0 : textSlideDistance)
18                Image(systemName: "tray")
19                    .offset(y: isReady ? -textSlideDistance : 0)
20            }
21            .frame(width: 26, height: textSlideDistance, alignment: .leading)
22            .clipped()
23            .foregroundStyle(.secondary)
24            .font(.system(size: 17))
25            .fontWeight(.semibold)
26            .animation(.easeInOut(duration: 0.15), value: isReady)
27            ZStack(alignment: .leading) {
28                Text("Release to clear")
29                    .offset(y: isReady ? 0 : textSlideDistance)
30                Text("Clear completed")
31                    .offset(y: isReady ? -textSlideDistance : 0)
32            }
33            .foregroundStyle(.secondary)
34            .font(ItemRowMetrics.hintSUI)
35            .frame(height: textSlideDistance, alignment: .topLeading)
36            .clipped()
37            .animation(.easeInOut(duration: 0.15), value: isReady)
38        }
39        .frame(maxWidth: .infinity)
40        .frame(height: 56)
41        // Reveal from the bottom upward as the user pulls
42        .frame(height: min(pullOffset, 56), alignment: .bottom)
43        .clipped()
44        .opacity(Double(progress))
45        .allowsHitTesting(false)
46    }
47}