@@ -887,6 +887,10 @@ struct FloatingOverlayView: View {
887887
888888 @State private var appeared = false
889889
890+ // Auto-advance countdown for follow-cursor mode (where buttons can't be clicked)
891+ @State private var countdownRemaining : Int = 0
892+ @State private var countdownTimer : Timer ? = nil
893+
890894 // Timer-based scroll for classic & silence-paused modes
891895 @State private var timerWordProgress : Double = 0
892896 @State private var isPaused : Bool = false
@@ -995,6 +999,9 @@ struct FloatingOverlayView: View {
995999 DispatchQueue . main. asyncAfter ( deadline: . now( ) + 1.0 ) {
9961000 speechRecognizer. shouldDismiss = true
9971001 }
1002+ } else if followingCursor {
1003+ // Start 3-second countdown to auto-advance (button can't be clicked in follow-cursor mode)
1004+ startCountdown ( )
9981005 }
9991006 }
10001007 }
@@ -1117,26 +1124,55 @@ struct FloatingOverlayView: View {
11171124 }
11181125 }
11191126
1127+ private func startCountdown( ) {
1128+ countdownTimer? . invalidate ( )
1129+ countdownRemaining = 3
1130+ countdownTimer = Timer . scheduledTimer ( withTimeInterval: 1.0 , repeats: true ) { timer in
1131+ DispatchQueue . main. async {
1132+ countdownRemaining -= 1
1133+ if countdownRemaining <= 0 {
1134+ timer. invalidate ( )
1135+ countdownTimer = nil
1136+ speechRecognizer. shouldAdvancePage = true
1137+ }
1138+ }
1139+ }
1140+ }
1141+
11201142 private var floatingDoneView : some View {
11211143 VStack {
11221144 Spacer ( )
11231145 if hasNextPage {
1124- Button {
1125- speechRecognizer. shouldAdvancePage = true
1126- } label: {
1127- HStack ( spacing: 8 ) {
1128- Image ( systemName: " play.fill " )
1129- . font ( . system( size: 14 , weight: . bold) )
1146+ if followingCursor {
1147+ // Auto-advance countdown (buttons can't be clicked in follow-cursor mode)
1148+ VStack ( spacing: 6 ) {
11301149 Text ( " Next Page " )
11311150 . font ( . system( size: 14 , weight: . bold) )
1151+ . foregroundStyle ( . white)
1152+ Text ( " \( countdownRemaining) " )
1153+ . font ( . system( size: 28 , weight: . heavy, design: . rounded) )
1154+ . foregroundStyle ( . white)
1155+ . contentTransition ( . numericText( ) )
1156+ . animation ( . easeInOut( duration: 0.3 ) , value: countdownRemaining)
11321157 }
1133- . foregroundStyle ( . white)
1134- . padding ( . horizontal, 20 )
1135- . padding ( . vertical, 10 )
1136- . background ( Color . accentColor)
1137- . clipShape ( Capsule ( ) )
1158+ } else {
1159+ Button {
1160+ speechRecognizer. shouldAdvancePage = true
1161+ } label: {
1162+ HStack ( spacing: 8 ) {
1163+ Image ( systemName: " play.fill " )
1164+ . font ( . system( size: 14 , weight: . bold) )
1165+ Text ( " Next Page " )
1166+ . font ( . system( size: 14 , weight: . bold) )
1167+ }
1168+ . foregroundStyle ( . white)
1169+ . padding ( . horizontal, 20 )
1170+ . padding ( . vertical, 10 )
1171+ . background ( Color . accentColor)
1172+ . clipShape ( Capsule ( ) )
1173+ }
1174+ . buttonStyle ( . plain)
11381175 }
1139- . buttonStyle ( . plain)
11401176 } else {
11411177 HStack ( spacing: 6 ) {
11421178 Image ( systemName: " checkmark.circle.fill " )
0 commit comments