fix: address all PR review comments
- HTTPClient: replace isRefreshing bool with shared Task to safely coalesce concurrent 401 refresh attempts; surface JSON serialization error instead of silently dropping request body - AuthService.logout: always clear Keychain tokens via defer, even when refresh token is absent, preventing stale access token - NotificationsAPIService: remove updateAppBadge (UIKit call moved to @MainActor NotificationsViewModel); drop unused UIKit import - NotificationsViewModel: guard startPolling() against duplicate tasks; update badge directly on @MainActor instead of hopping to actor - VerifyEmailView: replace Timer (never invalidated) with async Task cancelled in .onDisappear - NotificationsView: use Text(date, style: .relative) — auto-updates without custom formatter; remove duplicate Date extension - SettingsView: handle logoutAll errors explicitly with alert instead of silently proceeding with local logout - MaydayLiveActivity/Info.plist: add NSExtensionPrincipalClass so the widget extension is discoverable by the system - Live Activity widget: replace frozen duration(from:) with Text(date, style: .timer); replace frozen relativeFormatted with Text(date, style: .relative); localize status badge to Russian Co-authored-by: robonen <26167508+robonen@users.noreply.github.com>
This commit is contained in:
@@ -7,7 +7,7 @@ struct VerifyEmailView: View {
|
||||
@State private var codeDigits: [String] = Array(repeating: "", count: 6)
|
||||
@State private var resendCooldown = 0
|
||||
@FocusState private var focusedIndex: Int?
|
||||
@State private var resendTimer: Timer?
|
||||
@State private var cooldownTask: Task<Void, Never>?
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 32) {
|
||||
@@ -64,6 +64,7 @@ struct VerifyEmailView: View {
|
||||
.navigationTitle("Подтверждение")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.onAppear { focusedIndex = 0 }
|
||||
.onDisappear { cooldownTask?.cancel() }
|
||||
}
|
||||
|
||||
private func handleDigitChange(index: Int, value: String) {
|
||||
@@ -99,21 +100,22 @@ struct VerifyEmailView: View {
|
||||
private func resendCode() async {
|
||||
do {
|
||||
try await AuthService.shared.resendCode(email: email)
|
||||
resendCooldown = 60
|
||||
startCooldownTimer()
|
||||
startCooldown()
|
||||
} catch {
|
||||
authViewModel.error = error.localizedDescription
|
||||
}
|
||||
}
|
||||
|
||||
private func startCooldownTimer() {
|
||||
resendTimer?.invalidate()
|
||||
resendTimer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
|
||||
if resendCooldown > 0 {
|
||||
resendCooldown -= 1
|
||||
} else {
|
||||
resendTimer?.invalidate()
|
||||
private func startCooldown() {
|
||||
cooldownTask?.cancel()
|
||||
cooldownTask = Task {
|
||||
for remaining in stride(from: 60, through: 1, by: -1) {
|
||||
guard !Task.isCancelled else { return }
|
||||
resendCooldown = remaining
|
||||
try? await Task.sleep(for: .seconds(1))
|
||||
}
|
||||
guard !Task.isCancelled else { return }
|
||||
resendCooldown = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user