Skip to content

Commit 38f4ead

Browse files
graycreateclaude
andcommitted
feat: Add numeric animation and smart delay for online count
Improvements to the online user count display: 1. Apply SwiftUI numericText animation when count changes (iOS 16+) 2. Add 300ms delay before hiding refresh indicator when count changes 3. Record previous count to detect changes during refresh This creates a smoother UX by: - Animating number transitions instead of instant changes - Keeping the indicator visible longer when data updates - Allowing users to see the count change before it disappears 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 2ebc58d commit 38f4ead

File tree

2 files changed

+43
-5
lines changed

2 files changed

+43
-5
lines changed

V2er/View/Widget/Updatable/HeadIndicatorView.swift

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ struct HeadIndicatorView: View {
1515
@Binding var isRefreshing: Bool
1616
var onlineStats: OnlineStatsInfo?
1717

18+
@State private var animatedOnlineCount: Int = 0
19+
1820
var offset: CGFloat {
1921
return isRefreshing ? (0 - scrollY) : -height
2022
}
@@ -25,6 +27,9 @@ struct HeadIndicatorView: View {
2527
self._progress = progress
2628
self._isRefreshing = isRefreshing
2729
self.onlineStats = onlineStats
30+
if let stats = onlineStats {
31+
self._animatedOnlineCount = State(initialValue: stats.onlineCount)
32+
}
2833
}
2934

3035
var body: some View {
@@ -41,9 +46,22 @@ struct HeadIndicatorView: View {
4146
Circle()
4247
.fill(Color.hex(0x52bf1c))
4348
.frame(width: 6, height: 6)
44-
Text("\(stats.onlineCount) 人在线")
45-
.font(.caption)
46-
.foregroundColor(.secondaryText)
49+
50+
if #available(iOS 16.0, *) {
51+
Text("\(animatedOnlineCount) 人在线")
52+
.font(.caption)
53+
.foregroundColor(.secondaryText)
54+
.contentTransition(.numericText())
55+
} else {
56+
Text("\(animatedOnlineCount) 人在线")
57+
.font(.caption)
58+
.foregroundColor(.secondaryText)
59+
}
60+
}
61+
.onChange(of: stats.onlineCount) { newValue in
62+
withAnimation(.easeInOut(duration: 0.3)) {
63+
animatedOnlineCount = newValue
64+
}
4765
}
4866
}
4967
}

V2er/View/Widget/Updatable/UpdatableView.swift

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ struct UpdatableView<Content: View>: View {
3131
@State var hapticed = false
3232
let state: UpdatableState
3333
let onlineStats: OnlineStatsInfo?
34+
@State private var previousOnlineCount: Int? = nil
3435

3536
private var refreshable: Bool {
3637
return onRefresh != nil
@@ -123,11 +124,30 @@ struct UpdatableView<Content: View>: View {
123124
&& lastScrollY > threshold {
124125
isRefreshing = true
125126
hapticed = false
127+
// Record current online count before refresh
128+
previousOnlineCount = onlineStats?.onlineCount
129+
126130
Task {
127131
await onRefresh?()
128132
runInMain {
129-
withAnimation {
130-
isRefreshing = false
133+
// Check if online count changed
134+
let currentCount = onlineStats?.onlineCount
135+
let onlineCountChanged = previousOnlineCount != nil && currentCount != nil && previousOnlineCount != currentCount
136+
137+
if onlineCountChanged {
138+
// Delay hiding if online count changed
139+
Task {
140+
try? await Task.sleep(nanoseconds: 300_000_000) // 300ms
141+
runInMain {
142+
withAnimation {
143+
isRefreshing = false
144+
}
145+
}
146+
}
147+
} else {
148+
withAnimation {
149+
isRefreshing = false
150+
}
131151
}
132152
}
133153
}

0 commit comments

Comments
 (0)