iOS/Sources/Shared/DesignSystem/Components/HAProgressView.swift
Bruno Pantaleão Gonçalves 878f6f9965
Visual improvements for Home Assistant invitation onboarding (#3649)
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->

## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->

## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
![CleanShot 2025-06-12 at 14 11
54@2x](https://github.com/user-attachments/assets/c866d074-fa26-4957-a44e-d669e0625e26)

## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#

## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
2025-06-12 15:25:45 +02:00

87 lines
2.6 KiB
Swift

import SwiftUI
final class HAProgressViewModel: ObservableObject {
@Published var isAnimating = false
@Published var trimEnd: CGFloat = 0.1
}
public struct HAProgressView: View {
public enum Style {
case small
case medium
case large
case extraLarge
var size: CGSize {
switch self {
case .small:
return CGSize(width: 24, height: 24)
case .medium:
return CGSize(width: 28, height: 28)
case .large:
return CGSize(width: 48, height: 48)
case .extraLarge:
return CGSize(width: 68, height: 68)
}
}
var lineWidth: CGFloat {
4
}
}
public enum ColorType {
/// When display in light background
case `default`
/// When displayed on accented background such as haPrimary
case light
}
@StateObject private var viewModel = HAProgressViewModel()
let style: Style
let colorType: ColorType
public init(style: Style = .medium, colorType: ColorType = .default) {
self.style = style
self.colorType = colorType
}
public var body: some View {
ZStack {
Circle()
.stroke(
colorType == .default ? Color.track : Color.white,
style: StrokeStyle(lineWidth: style.lineWidth)
)
.frame(width: style.size.width, height: style.size.height)
Circle()
.trim(from: 0, to: viewModel.trimEnd)
.stroke(
Color.haPrimary.opacity(colorType == .default ? 1 : 0.5),
style: StrokeStyle(lineWidth: style.lineWidth, lineCap: .round)
)
.frame(width: style.size.width, height: style.size.height)
.rotationEffect(Angle(degrees: viewModel.isAnimating ? 360 : 0))
.animation(
Animation.linear(duration: 1).repeatForever(autoreverses: false),
value: viewModel.isAnimating
)
.onAppear {
viewModel.isAnimating = true
withAnimation(.easeInOut(duration: 1.75).repeatForever(autoreverses: true)) {
viewModel.trimEnd = 0.7
}
}
}
}
}
#Preview {
HStack(spacing: Spaces.two) {
HAProgressView(style: .small)
HAProgressView(style: .medium)
HAProgressView(style: .large)
HAProgressView(style: .extraLarge)
}
}