TimeView.swift (1996B)
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 isFinished = true 29 // print("❗️❗️❗️ retrying…") 30 DispatchQueue.main.asyncAfter(deadline: .now() + 1.2) { 31 isFinished = nil 32 // print("❗️❗️❗️ waiting for response…") 33 } 34 } 35 } 36 } 37 return remaining 38 } 39 40 var body: some View { 41 let startDate = Date() 42 HStack { 43 Text(title) 44 TimelineView(.animation) { context in 45 let elapsed = Int(context.date.timeIntervalSince(startDate)) 46 let remaining = remainingTime(elapsed) 47 let text = Text(verbatim: "\(remaining)") 48 if #available(iOS 17.0, *) { 49 text 50 .contentTransition(.numericText(countsDown: true)) 51 .animation(.default, value: elapsed) 52 } else if #available(iOS 16.4, *) { 53 text 54 .animation(.default, value: elapsed) 55 } else { 56 text 57 } 58 }.monospacedDigit() 59 Text(trailer) 60 }.accessibilityElement(children: .combine) 61 } 62 }