2021-10-29 05:50:19 -07:00
|
|
|
//
|
|
|
|
// CircularImageFrame.swift
|
|
|
|
// secant-testnet
|
|
|
|
//
|
|
|
|
// Created by Adam Stener on 9/29/21.
|
|
|
|
//
|
|
|
|
|
|
|
|
import SwiftUI
|
2021-11-09 03:59:03 -08:00
|
|
|
import ComposableArchitecture
|
2021-10-29 05:50:19 -07:00
|
|
|
|
2021-11-09 03:59:03 -08:00
|
|
|
enum Badge: Equatable {
|
|
|
|
case shield
|
|
|
|
case list
|
|
|
|
case person
|
2021-12-13 12:50:04 -08:00
|
|
|
case error
|
2021-10-29 05:50:19 -07:00
|
|
|
|
2021-12-13 12:50:04 -08:00
|
|
|
@ViewBuilder var image: some View {
|
2021-11-09 03:59:03 -08:00
|
|
|
switch self {
|
2021-12-13 12:50:04 -08:00
|
|
|
case .shield:
|
|
|
|
Asset.Assets.Icons.shield.image
|
|
|
|
.resizable()
|
|
|
|
.renderingMode(.none)
|
|
|
|
case .list:
|
|
|
|
Asset.Assets.Icons.list.image
|
|
|
|
.resizable()
|
|
|
|
.renderingMode(.none)
|
|
|
|
case .person:
|
|
|
|
Asset.Assets.Icons.profile.image
|
|
|
|
.resizable()
|
|
|
|
.renderingMode(.none)
|
|
|
|
case .error:
|
|
|
|
ErrorBadge()
|
2021-10-29 05:50:19 -07:00
|
|
|
}
|
|
|
|
}
|
2021-11-09 03:59:03 -08:00
|
|
|
}
|
|
|
|
|
2021-12-13 12:50:04 -08:00
|
|
|
struct ErrorBadge: View {
|
|
|
|
var body: some View {
|
|
|
|
Text("X")
|
|
|
|
.font(.custom(FontFamily.Rubik.bold.name, size: 36))
|
|
|
|
.foregroundColor(Asset.Colors.BackgroundColors.red.color)
|
|
|
|
.frame(width: 60, height: 55, alignment: .center)
|
|
|
|
.background(Asset.Colors.BackgroundColors.numberedChip.color)
|
|
|
|
.cornerRadius(10)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-09 03:59:03 -08:00
|
|
|
struct BadgesOverlay: Animatable, ViewModifier {
|
|
|
|
struct ViewState: Equatable {
|
|
|
|
let index: Int
|
|
|
|
let badges: [Badge]
|
|
|
|
}
|
|
|
|
|
|
|
|
let store: Store<ViewState, Never>
|
|
|
|
|
|
|
|
func body(content: Content) -> some View {
|
|
|
|
WithViewStore(self.store) { viewStore in
|
|
|
|
content
|
|
|
|
.overlay(
|
|
|
|
GeometryReader { proxy in
|
|
|
|
VStack {
|
|
|
|
Spacer()
|
|
|
|
|
|
|
|
HStack {
|
|
|
|
Spacer()
|
2021-10-29 05:50:19 -07:00
|
|
|
|
2021-11-09 03:59:03 -08:00
|
|
|
ZStack {
|
|
|
|
ForEach(0..<viewStore.badges.count) { badgeIndex in
|
|
|
|
viewStore.badges[viewStore.index].image
|
|
|
|
.frame(
|
|
|
|
width: proxy.size.width * 0.35,
|
|
|
|
height: proxy.size.height * 0.35,
|
|
|
|
alignment: .center
|
|
|
|
)
|
|
|
|
.offset(
|
|
|
|
x: 4.0,
|
|
|
|
y: proxy.size.height * 0.15
|
|
|
|
)
|
|
|
|
.opacity(badgeIndex == viewStore.index ? 1 : 0)
|
2022-02-21 12:17:49 -08:00
|
|
|
.shadow(color: Asset.Colors.Onboarding.badgeShadow.color, radius: 10, x: 0, y: 0)
|
2021-11-09 03:59:03 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Spacer()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct BadgeOverlay: Animatable, ViewModifier {
|
|
|
|
var badge: Badge
|
2021-10-29 05:50:19 -07:00
|
|
|
|
|
|
|
func body(content: Content) -> some View {
|
|
|
|
content
|
|
|
|
.overlay(
|
|
|
|
GeometryReader { proxy in
|
|
|
|
VStack {
|
|
|
|
Spacer()
|
|
|
|
|
|
|
|
HStack {
|
|
|
|
Spacer()
|
|
|
|
|
|
|
|
badge.image
|
|
|
|
.frame(
|
2021-11-09 03:59:03 -08:00
|
|
|
width: proxy.size.width * 0.35,
|
|
|
|
height: proxy.size.height * 0.35,
|
2021-10-29 05:50:19 -07:00
|
|
|
alignment: .center
|
|
|
|
)
|
|
|
|
.offset(
|
2021-11-09 03:59:03 -08:00
|
|
|
x: 4.0,
|
|
|
|
y: proxy.size.height * 0.15
|
2021-10-29 05:50:19 -07:00
|
|
|
)
|
2021-11-09 03:59:03 -08:00
|
|
|
.transition(.scale(scale: 2))
|
|
|
|
.transition(.opacity)
|
2022-02-21 12:17:49 -08:00
|
|
|
.shadow(color: Asset.Colors.Onboarding.badgeShadow.color, radius: 10, x: 0, y: 0)
|
2021-10-29 05:50:19 -07:00
|
|
|
Spacer()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extension View {
|
2021-11-09 03:59:03 -08:00
|
|
|
func badgeIcon(_ badge: Badge) -> some View {
|
|
|
|
modifier(BadgeOverlay(badge: badge))
|
|
|
|
}
|
|
|
|
|
|
|
|
func badgeIcons(_ store: Store<BadgesOverlay.ViewState, Never>) -> some View {
|
|
|
|
modifier(BadgesOverlay(store: store))
|
2021-10-29 05:50:19 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Badge_Previews: PreviewProvider {
|
|
|
|
static let size: CGFloat = 300
|
|
|
|
|
|
|
|
static var previews: some View {
|
|
|
|
Group {
|
|
|
|
CircularFrame()
|
|
|
|
.frame(width: size, height: size)
|
|
|
|
.badgeIcon(.shield)
|
|
|
|
|
|
|
|
CircularFrame()
|
|
|
|
.frame(width: size, height: size)
|
|
|
|
.badgeIcon(.list)
|
|
|
|
|
|
|
|
CircularFrame()
|
|
|
|
.frame(width: size, height: size)
|
|
|
|
.badgeIcon(.person)
|
2021-12-13 12:50:04 -08:00
|
|
|
|
|
|
|
CircularFrame()
|
|
|
|
.frame(width: size, height: size)
|
|
|
|
.badgeIcon(.error)
|
2021-10-29 05:50:19 -07:00
|
|
|
}
|
|
|
|
.preferredColorScheme(.light)
|
|
|
|
.previewLayout(.fixed(width: size + 50, height: size + 50))
|
|
|
|
}
|
|
|
|
}
|