TimeView.swift (2128B)
1 /* 2 * This file is part of GNU Taler, ©2022-26 Taler Systems S.A. 3 * See LICENSE.md 4 */ 5 /** 6 * @author Marc Stibane 7 */ 8 import SwiftUI 9 10 struct TimeView: View { 11 let title: String 12 let seconds: Int 13 let trailer: String 14 @Binding var isFinished: Bool? 15 16 init(_ title: String, seconds: Int,_ trailer: String? = nil, isFinished: Binding<Bool?> = .constant(nil)) { 17 self.title = title 18 self.seconds = seconds 19 self.trailer = trailer ?? String(localized: "seconds") 20 self._isFinished = isFinished 21 } 22 23 func remainingTime(_ elapsed: Int) -> Int { 24 let remaining = seconds - elapsed 25 if remaining <= 0 { 26 if isFinished != nil { 27 DispatchQueue.main.async { 28 withAnimation { 29 isFinished = true 30 } 31 // print("❗️❗️❗️ retrying…") 32 DispatchQueue.main.asyncAfter(deadline: .now() + 1.2) { 33 withAnimation { 34 isFinished = nil 35 } 36 // print("❗️❗️❗️ waiting for response…") 37 } 38 } 39 } 40 } 41 return remaining 42 } 43 44 var body: some View { 45 let startDate = Date() 46 HStack { 47 Text(title) 48 TimelineView(.animation) { context in 49 let elapsed = Int(context.date.timeIntervalSince(startDate)) 50 let remaining = remainingTime(elapsed) 51 let text = Text(verbatim: "\(remaining)") 52 if #available(iOS 17.0, *) { 53 text 54 .contentTransition(.numericText(countsDown: true)) 55 .animation(.default, value: elapsed) 56 } else if #available(iOS 16.4, *) { 57 text 58 .animation(.default, value: elapsed) 59 } else { 60 text 61 } 62 }.monospacedDigit() 63 Text(trailer) 64 }.accessibilityElement(children: .combine) 65 } 66 }