From 2ebc58d48766dc78bec8ec4d1f47cd3067db4af9 Mon Sep 17 00:00:00 2001 From: Gray Zhang Date: Sat, 18 Oct 2025 13:22:11 +0800 Subject: [PATCH 1/2] feat: Add green indicator dot to online user count MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a small green dot (#52bf1c) to the left of the online user count text in the pull-to-refresh indicator for better visual indication. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- V2er/View/Widget/Updatable/HeadIndicatorView.swift | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/V2er/View/Widget/Updatable/HeadIndicatorView.swift b/V2er/View/Widget/Updatable/HeadIndicatorView.swift index 58b56e8..2fd9f45 100644 --- a/V2er/View/Widget/Updatable/HeadIndicatorView.swift +++ b/V2er/View/Widget/Updatable/HeadIndicatorView.swift @@ -37,9 +37,14 @@ struct HeadIndicatorView: View { } if let stats = onlineStats, stats.isValid() { - Text("\(stats.onlineCount) 人在线") - .font(.caption) - .foregroundColor(.secondaryText) + HStack(spacing: 4) { + Circle() + .fill(Color.hex(0x52bf1c)) + .frame(width: 6, height: 6) + Text("\(stats.onlineCount) 人在线") + .font(.caption) + .foregroundColor(.secondaryText) + } } } .frame(height: height) From 38f4eada395616fef2da85df7c54299ee049b930 Mon Sep 17 00:00:00 2001 From: Gray Zhang Date: Sat, 18 Oct 2025 14:59:23 +0800 Subject: [PATCH 2/2] feat: Add numeric animation and smart delay for online count MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .../Widget/Updatable/HeadIndicatorView.swift | 24 ++++++++++++++++--- .../View/Widget/Updatable/UpdatableView.swift | 24 +++++++++++++++++-- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/V2er/View/Widget/Updatable/HeadIndicatorView.swift b/V2er/View/Widget/Updatable/HeadIndicatorView.swift index 2fd9f45..5053af1 100644 --- a/V2er/View/Widget/Updatable/HeadIndicatorView.swift +++ b/V2er/View/Widget/Updatable/HeadIndicatorView.swift @@ -15,6 +15,8 @@ struct HeadIndicatorView: View { @Binding var isRefreshing: Bool var onlineStats: OnlineStatsInfo? + @State private var animatedOnlineCount: Int = 0 + var offset: CGFloat { return isRefreshing ? (0 - scrollY) : -height } @@ -25,6 +27,9 @@ struct HeadIndicatorView: View { self._progress = progress self._isRefreshing = isRefreshing self.onlineStats = onlineStats + if let stats = onlineStats { + self._animatedOnlineCount = State(initialValue: stats.onlineCount) + } } var body: some View { @@ -41,9 +46,22 @@ struct HeadIndicatorView: View { Circle() .fill(Color.hex(0x52bf1c)) .frame(width: 6, height: 6) - Text("\(stats.onlineCount) 人在线") - .font(.caption) - .foregroundColor(.secondaryText) + + if #available(iOS 16.0, *) { + Text("\(animatedOnlineCount) 人在线") + .font(.caption) + .foregroundColor(.secondaryText) + .contentTransition(.numericText()) + } else { + Text("\(animatedOnlineCount) 人在线") + .font(.caption) + .foregroundColor(.secondaryText) + } + } + .onChange(of: stats.onlineCount) { newValue in + withAnimation(.easeInOut(duration: 0.3)) { + animatedOnlineCount = newValue + } } } } diff --git a/V2er/View/Widget/Updatable/UpdatableView.swift b/V2er/View/Widget/Updatable/UpdatableView.swift index 790d040..a645510 100644 --- a/V2er/View/Widget/Updatable/UpdatableView.swift +++ b/V2er/View/Widget/Updatable/UpdatableView.swift @@ -31,6 +31,7 @@ struct UpdatableView: View { @State var hapticed = false let state: UpdatableState let onlineStats: OnlineStatsInfo? + @State private var previousOnlineCount: Int? = nil private var refreshable: Bool { return onRefresh != nil @@ -123,11 +124,30 @@ struct UpdatableView: View { && lastScrollY > threshold { isRefreshing = true hapticed = false + // Record current online count before refresh + previousOnlineCount = onlineStats?.onlineCount + Task { await onRefresh?() runInMain { - withAnimation { - isRefreshing = false + // Check if online count changed + let currentCount = onlineStats?.onlineCount + let onlineCountChanged = previousOnlineCount != nil && currentCount != nil && previousOnlineCount != currentCount + + if onlineCountChanged { + // Delay hiding if online count changed + Task { + try? await Task.sleep(nanoseconds: 300_000_000) // 300ms + runInMain { + withAnimation { + isRefreshing = false + } + } + } + } else { + withAnimation { + isRefreshing = false + } } } }