Files
aliasvault/apps/mobile-app/ios/VaultUI/Components/LoadingOverlayView.swift

90 lines
3.4 KiB
Swift

import SwiftUI
/// Loading overlay component with AliasVault branding
public struct LoadingOverlayView: View {
let message: String
@Environment(\.colorScheme) private var colorScheme
@State private var animatingDots: [Bool] = [false, false, false, false]
@State private var textDots = ""
@State private var timer: Timer?
public init(message: String) {
self.message = message
}
public var body: some View {
GeometryReader { geometry in
VStack(spacing: 0) {
// Position content at 20% from top to avoid Face ID prompt obstruction
Spacer()
.frame(height: geometry.size.height * 0.15)
VStack(spacing: 0) {
// AliasVault logo animation - four pulsing dots
HStack(spacing: 10) {
ForEach(0..<4) { index in
Circle()
.fill(ColorConstants.Light.tertiary)
.frame(width: 8, height: 8)
.opacity(animatingDots[index] ? 1.0 : 0.3)
.animation(
Animation.easeInOut(duration: 0.7)
.repeatForever(autoreverses: true)
.delay(Double(index) * 0.2),
value: animatingDots[index]
)
}
}
.padding(12)
.padding(.horizontal, 12)
.background(
RoundedRectangle(cornerRadius: 20)
.fill(colorScheme == .dark ? Color.clear : Color.white)
.overlay(
RoundedRectangle(cornerRadius: 20)
.stroke(ColorConstants.Light.tertiary, lineWidth: 5)
)
.shadow(color: Color.black.opacity(0.05), radius: 2, x: 0, y: 1)
)
// Loading message with animated dots
if !message.isEmpty {
Text(message + textDots)
.font(.body)
.foregroundColor(colorScheme == .dark ? ColorConstants.Dark.text : ColorConstants.Light.text)
.multilineTextAlignment(.center)
.padding(.horizontal)
.padding(.top, 16)
}
}
.padding(20)
.frame(maxWidth: .infinity) // Ensure horizontal centering
Spacer()
}
.frame(maxWidth: .infinity) // Ensure horizontal centering for entire VStack
}
.onAppear {
// Start dot animations
for index in 0..<4 {
animatingDots[index] = true
}
// Start text dots animation
let textTimer = Timer.scheduledTimer(withTimeInterval: 0.4, repeats: true) { _ in
if textDots.count >= 3 {
textDots = ""
} else {
textDots += "."
}
}
timer = textTimer
}
.onDisappear {
timer?.invalidate()
timer = nil
}
}
}