Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Swift 6 support #27

Merged
merged 4 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Demo/Demo/Alerts/CustomAlerts.swift
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ struct CustomContent: View {
}

extension CustomAlertConfiguration {
static var myConfig: CustomAlertConfiguration = .create { configuration in
static let myConfig: CustomAlertConfiguration = .create { configuration in
configuration.background = .blurEffect(.dark)
configuration.padding = EdgeInsets()
configuration.alert = .create { alert in
Expand Down
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import PackageDescription
let package = Package(
name: "CustomAlert",
platforms: [
.iOS(.v14)
.iOS(.v15)
],
products: [
.library(
Expand Down
34 changes: 12 additions & 22 deletions Sources/CustomAlert/AlertButtonStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public struct AlertButtonStyle: ButtonStyle {
@Environment(\.customAlertConfiguration.button) private var buttonConfiguration
@Environment(\.alertDismiss) private var alertDismiss
@Environment(\.alertButtonHeight) private var maxHeight
@Environment(\.customDynamicTypeSize) private var dynamicTypeSize
@Environment(\.dynamicTypeSize) private var dynamicTypeSize

@Environment(\.isEnabled) private var isEnabled
@Environment(\.colorScheme) private var colorScheme
Expand Down Expand Up @@ -57,22 +57,16 @@ public struct AlertButtonStyle: ButtonStyle {
}

@ViewBuilder func label(configuration: Configuration) -> some View {
if #available(iOS 15, *) {
switch configuration.role {
case .some(.destructive):
configuration.label
.font(resolvedFont(role: .destructive))
.foregroundColor(resolvedColor(role: .destructive, isPressed: configuration.isPressed))
case .some(.cancel):
configuration.label
.font(resolvedFont(role: .cancel))
.foregroundColor(resolvedColor(role: .cancel, isPressed: configuration.isPressed))
default:
configuration.label
.font(resolvedFont())
.foregroundColor(resolvedColor(isPressed: configuration.isPressed))
}
} else {
switch configuration.role {
case .some(.destructive):
configuration.label
.font(resolvedFont(role: .destructive))
.foregroundColor(resolvedColor(role: .destructive, isPressed: configuration.isPressed))
case .some(.cancel):
configuration.label
.font(resolvedFont(role: .cancel))
.foregroundColor(resolvedColor(role: .cancel, isPressed: configuration.isPressed))
default:
configuration.label
.font(resolvedFont())
.foregroundColor(resolvedColor(isPressed: configuration.isPressed))
Expand Down Expand Up @@ -102,11 +96,7 @@ public struct AlertButtonStyle: ButtonStyle {
return .accentColor
}

if #available(iOS 15.0, *) {
return Color(uiColor: color)
} else {
return Color(color)
}
return Color(uiColor: color)
} else {
return Color("Disabled", bundle: .module)
}
Expand Down
24 changes: 20 additions & 4 deletions Sources/CustomAlert/Configuration/CustomAlertBackground.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import SwiftUI
import UIKit

/// Wrapped background of the alert
public enum CustomAlertBackground {
public enum CustomAlertBackground: Sendable {
/// A `UIBlurEffect` as background
case blurEffect(UIBlurEffect.Style)
/// A `Color` as background
Expand All @@ -19,11 +19,27 @@ public enum CustomAlertBackground {
case colorBlurEffect(Color, UIBlurEffect.Style)
case anyView(AnyView)

public static func view<Content>(@ViewBuilder builder: () -> Content) -> CustomAlertBackground where Content: View {
CustomAlertBackground.anyView(AnyView(builder()))
@MainActor public static func view<Content>(@ViewBuilder builder: () -> Content) -> CustomAlertBackground where Content: View {
CustomAlertBackground.anyView(AnyView(builder: builder))
}

public static func view<Content>(_ view: Content) -> CustomAlertBackground where Content: View {
@MainActor public static func view<Content>(_ view: Content) -> CustomAlertBackground where Content: View {
CustomAlertBackground.anyView(AnyView(view))
}

@MainActor public struct AnyView: View, Sendable {
let wrappedView: SwiftUI.AnyView

init<Content>(@ViewBuilder builder: () -> Content) where Content: View {
self.wrappedView = SwiftUI.AnyView(builder())
}

init<Content>(_ view: Content) where Content: View {
self.wrappedView = SwiftUI.AnyView(view)
}

public var body: some View {
wrappedView
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,40 @@ import SwiftUI

extension CustomAlertConfiguration {
/// The custom alert configuration
public struct Alert {
public struct Alert: Sendable {
/// The background of the alert view
public var background: CustomAlertBackground = .blurEffect(.systemMaterial)
public var background: CustomAlertBackground
/// The corner radius of the alert view
public var cornerRadius: CGFloat = 13.3333
public var cornerRadius: CGFloat
/// The padding of the content of the alert view
public var padding: EdgeInsets = EdgeInsets(top: 20, leading: 8, bottom: 20, trailing: 8)
public var padding: EdgeInsets
/// The padding of the content of the alert view when using accessibility scaling
public var accessibilityPadding: EdgeInsets = EdgeInsets(top: 37.5, leading: 12, bottom: 37.5, trailing: 12)
public var accessibilityPadding: EdgeInsets
/// The minimum width of the alert view
public var minWidth: CGFloat = 270
public var minWidth: CGFloat
/// The minimum width of the alert view when using accessibility scaling
public var accessibilityMinWidth: CGFloat = 329
public var accessibilityMinWidth: CGFloat
/// The default font of the title of the alert view
public var titleFont: Font = .headline
public var titleFont: Font
/// The default font of the content of the alert view
public var contentFont: Font = .footnote
public var contentFont: Font
/// The spacing of the content of the alert view
public var spacing: CGFloat = 4
public var spacing: CGFloat
/// The alignment of the content of the alert view
public var alignment: CustomAlertAlignment = .center
public var alignment: CustomAlertAlignment

init() {
self.background = .blurEffect(.systemMaterial)
self.cornerRadius = 13.3333
self.padding = EdgeInsets(top: 20, leading: 8, bottom: 20, trailing: 8)
self.accessibilityPadding = EdgeInsets(top: 37.5, leading: 12, bottom: 37.5, trailing: 12)
self.minWidth = 270
self.accessibilityMinWidth = 329
self.titleFont = .headline
self.contentFont = .footnote
self.spacing = 4
self.alignment = .center
}

/// Create a custom configuration
///
Expand All @@ -44,7 +57,7 @@ extension CustomAlertConfiguration {
}

/// The default configuration
public static var `default`: CustomAlertConfiguration {
@MainActor public static var `default`: CustomAlertConfiguration {
CustomAlertConfiguration()
}

Expand Down Expand Up @@ -84,7 +97,7 @@ extension CustomAlertConfiguration {
}

/// The alignment of the content of the custom alert
public enum CustomAlertAlignment {
public enum CustomAlertAlignment: Sendable {
/// The content is aligned in the center
case center
/// The content is aligned on the leading edge
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,45 @@ import Foundation
import SwiftUI

extension CustomAlertConfiguration {
public struct Button {
public struct Button: Sendable {
/// Configuration values of a custom alert button
/// The tint color of the alert button
public var tintColor: Color?
/// The pressed tint color of the alert button
public var pressedTintColor: Color?
internal var roleColor: [ButtonType: Color] = [.destructive: .red]
internal var roleColor: [ButtonType: Color]
/// The padding of the alert button
public var padding: EdgeInsets = EdgeInsets(top: 12, leading: 12, bottom: 12, trailing: 12)
public var padding: EdgeInsets
/// The padding of the alert button when using accessibility scaling
public var accessibilityPadding: EdgeInsets = EdgeInsets(top: 20, leading: 12, bottom: 20, trailing: 12)
public var accessibilityPadding: EdgeInsets
/// The font of the alert button
public var font: Font = .body
internal var roleFont: [ButtonType: Font] = [.cancel: .headline]
public var font: Font
internal var roleFont: [ButtonType: Font]
/// Whether to hide the dividers between the buttons
public var hideDivider: Bool = false
public var hideDivider: Bool
/// The background of the alert button
public var background: CustomAlertBackground = .color(.almostClear)
public var background: CustomAlertBackground
/// The pressed background of the alert button
public var pressedBackground: CustomAlertBackground = .color(Color(.customAlertBackgroundColor))
public var pressedBackground: CustomAlertBackground

init() {
self.tintColor = nil
self.pressedTintColor = nil
self.roleColor = [.destructive: .red]
self.padding = EdgeInsets(top: 12, leading: 12, bottom: 12, trailing: 12)
self.accessibilityPadding = EdgeInsets(top: 20, leading: 12, bottom: 20, trailing: 12)
self.font = .body
self.roleFont = [.cancel: .headline]
self.hideDivider = false
self.background = .color(.almostClear)
self.pressedBackground = .color(Color(.customAlertBackgroundColor))
}

@available(iOS 15.0, *)
public mutating func font(_ font: Font, for role: ButtonRole) {
guard let type = ButtonType(from: role) else { return }
self.roleFont[type] = font
}

@available(iOS 15.0, *)
public mutating func color(_ color: Color, for role: ButtonRole) {
guard let type = ButtonType(from: role) else { return }
self.roleColor[type] = color
Expand All @@ -60,12 +71,11 @@ extension CustomAlertConfiguration {
}
}

/// Internal button type because `ButtonRole` is iOS 15+
/// Internal button type because `ButtonRole` is not `Hashable`
enum ButtonType: Hashable {
case destructive
case cancel

@available(iOS 15.0, *)
init?(from role: ButtonRole) {
switch role {
case .destructive:
Expand All @@ -81,15 +91,7 @@ enum ButtonType: Hashable {
private extension UIColor {
static var customAlertColor: UIColor {
let traitCollection = UITraitCollection(activeAppearance: .active)
if #available(iOS 15.0, *) {
return .tintColor.resolvedColor(with: traitCollection)
} else {
return UIColor(
named: "AccentColor",
in: .main,
compatibleWith: traitCollection
) ?? .systemBlue
}
return .tintColor.resolvedColor(with: traitCollection)
}

static var customAlertBackgroundColor: UIColor {
Expand Down
35 changes: 24 additions & 11 deletions Sources/CustomAlert/Configuration/CustomAlertConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,34 @@ import Foundation
import SwiftUI

/// Configuration values for custom alerts
public struct CustomAlertConfiguration {
@MainActor public struct CustomAlertConfiguration: Sendable {
/// The configuration of the alert view
public var alert: Alert = .init()
public var alert: Alert
/// The configuration of the alert buttons
public var button: Button = .init()
public var button: Button
/// The window background behind the alert
public var background: CustomAlertBackground = .color(Color.black.opacity(0.2))
public var background: CustomAlertBackground
/// The padding around the alert
public var padding: EdgeInsets = EdgeInsets(top: 30, leading: 30, bottom: 30, trailing: 30)
public var padding: EdgeInsets
/// The transition the alert appears with
public var transition: AnyTransition = .opacity.combined(with: .scale(scale: 1.1))
public var transition: AnyTransition
/// Animate the alert appearance
public var animateTransition: Bool = true
public var animateTransition: Bool
/// The vertical alginment of the alert
public var alignment: VerticalAlignment = .center
public var alignment: VerticalAlignment
/// Allow dismissing the alert when tapping on the background
public var dismissOnBackgroundTap: Bool = false
public var dismissOnBackgroundTap: Bool

public init() {
self.alert = .init()
self.button = .init()
self.background = .color(Color.black.opacity(0.2))
self.padding = EdgeInsets(top: 30, leading: 30, bottom: 30, trailing: 30)
self.transition = .opacity.combined(with: .scale(scale: 1.1))
self.animateTransition = true
self.alignment = .center
self.dismissOnBackgroundTap = false
}

/// Create a custom configuration
///
Expand All @@ -39,7 +50,9 @@ public struct CustomAlertConfiguration {
}

/// The default configuration
public static var `default`: CustomAlertConfiguration {
CustomAlertConfiguration()
public static nonisolated var `default`: CustomAlertConfiguration {
MainActor.runSync {
CustomAlertConfiguration()
}
}
}
12 changes: 2 additions & 10 deletions Sources/CustomAlert/CustomAlertHandler+Item.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import SwiftUI
import Combine
import WindowKit

struct CustomAlertItemHandler<AlertItem, AlertContent, AlertActions>: ViewModifier where AlertItem: Identifiable, AlertContent: View, AlertActions: View {
@MainActor struct CustomAlertItemHandler<AlertItem, AlertContent, AlertActions>: ViewModifier where AlertItem: Identifiable, AlertContent: View, AlertActions: View {
@Environment(\.customAlertConfiguration) private var configuration

@Binding var item: AlertItem?
Expand Down Expand Up @@ -103,14 +103,6 @@ struct CustomAlertItemHandler<AlertItem, AlertContent, AlertActions>: ViewModifi
private extension UIColor {
static var customAlertColor: UIColor {
let traitCollection = UITraitCollection(activeAppearance: .active)
if #available(iOS 15.0, *) {
return .tintColor.resolvedColor(with: traitCollection)
} else {
return UIColor(
named: "AccentColor",
in: .main,
compatibleWith: traitCollection
) ?? .systemBlue
}
return .tintColor.resolvedColor(with: traitCollection)
}
}
12 changes: 2 additions & 10 deletions Sources/CustomAlert/CustomAlertHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import SwiftUI
import Combine
import WindowKit

struct CustomAlertHandler<AlertContent, AlertActions>: ViewModifier where AlertContent: View, AlertActions: View {
@MainActor struct CustomAlertHandler<AlertContent, AlertActions>: ViewModifier where AlertContent: View, AlertActions: View {
@Environment(\.customAlertConfiguration) private var configuration

@Binding var isPresented: Bool
Expand Down Expand Up @@ -91,14 +91,6 @@ struct CustomAlertHandler<AlertContent, AlertActions>: ViewModifier where AlertC
private extension UIColor {
static var customAlertColor: UIColor {
let traitCollection = UITraitCollection(activeAppearance: .active)
if #available(iOS 15.0, *) {
return .tintColor.resolvedColor(with: traitCollection)
} else {
return UIColor(
named: "AccentColor",
in: .main,
compatibleWith: traitCollection
) ?? .systemBlue
}
return .tintColor.resolvedColor(with: traitCollection)
}
}
11 changes: 0 additions & 11 deletions Sources/CustomAlert/Deprecations.swift

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import SwiftUI

private struct CustomAlertConfigurationKey: EnvironmentKey {
static var defaultValue: CustomAlertConfiguration {
CustomAlertConfiguration()
CustomAlertConfiguration.default
}
}

Expand Down
Loading