diff --git a/V2er/View/Widget/Updatable/HeadIndicatorView.swift b/V2er/View/Widget/Updatable/HeadIndicatorView.swift index 58b56e8..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 { @@ -37,9 +42,27 @@ 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) + + 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 + } + } } } .frame(height: height) 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 + } } } }