import DesignSystem import SwiftUI @MainActor struct IconSelectorView: View { enum Icon: Int, CaseIterable, Identifiable { var id: String { "\(rawValue)" } init(string: String) { if string == "AppIcon" { self = .primary } else { self = .init(rawValue: Int(String(string.replacing("AppIconAlternate", with: "")))!)! } } case primary = 0 case alt1, alt2, alt3, alt4, alt5, alt6, alt7, alt8, alt9, alt10, alt11, alt12, alt13, alt14, alt15 case alt16, alt17, alt18, alt19, alt20, alt21 case alt22, alt23, alt24, alt25, alt26 case alt27, alt28, alt29 case alt30, alt31, alt32, alt33, alt34, alt35, alt36 case alt37 case alt38 case alt39, alt40, alt41, alt42, alt43 case alt44, alt45 case alt46 var appIconName: String { return "AppIconAlternate\(rawValue)" } } struct IconSelector: Identifiable { var id = UUID() let title: String let icons: [Icon] static let items = [ IconSelector(title: "settings.app.icon.official".localized, icons: [ .primary, .alt46, .alt1, .alt2, .alt3, .alt4, .alt5, .alt6, .alt7, .alt8, .alt9, .alt10, .alt11, .alt12, .alt13, .alt14, .alt15, .alt16, .alt17, .alt18, .alt19, .alt20, .alt21]), IconSelector(title: "\("settings.app.icon.designed-by".localized) Louie Mantia, Jr.", icons: []), IconSelector(title: "\("settings.app.icon.designed-by".localized) Albert Kinng", icons: [.alt22, .alt23, .alt24, .alt25, .alt26]), IconSelector(title: "\("settings.app.icon.designed-by".localized) Dan van Moll", icons: [.alt27, .alt28, .alt29]), IconSelector(title: "\("settings.app.icon.designed-by".localized) Chanhwi Joo (GitHub @te6-in)", icons: [.alt30, .alt31, .alt32, .alt33, .alt34, .alt35, .alt36]), IconSelector(title: "\("settings.app.icon.designed-by".localized) W. Kovács Ágnes (@wildgica)", icons: [.alt37]), IconSelector(title: "\("settings.app.icon.designed-by".localized) Duncan Horne", icons: [.alt38]), IconSelector(title: "\("settings.app.icon.designed-by".localized) BeAware@social.beaware.live", icons: [.alt39, .alt40, .alt41, .alt42, .alt43]), IconSelector(title: "\("settings.app.icon.designed-by".localized) Simone Margio", icons: [.alt44, .alt45]), ] } @Environment(Theme.self) private var theme @State private var currentIcon = UIApplication.shared.alternateIconName ?? Icon.primary.appIconName private let columns = [GridItem(.adaptive(minimum: 125, maximum: 1024))] var body: some View { ScrollView { VStack(alignment: .leading) { ForEach(IconSelector.items) { item in Section { makeIconGridView(icons: item.icons) } header: { Text(item.title) .font(.scaledHeadline) } } } .padding(6) .navigationTitle("settings.app.icon.navigation-title") } #if !os(visionOS) .background(theme.primaryBackgroundColor) #endif } private func makeIconGridView(icons: [Icon]) -> some View { LazyVGrid(columns: columns, spacing: 6) { ForEach(icons) { icon in Button { currentIcon = icon.appIconName if icon.rawValue == Icon.primary.rawValue { UIApplication.shared.setAlternateIconName(nil) } else { UIApplication.shared.setAlternateIconName(icon.appIconName) { err in guard let err else { return } assertionFailure("\(err.localizedDescription) - Icon name: \(icon.appIconName)") } } } label: { ZStack(alignment: .bottomTrailing) { Image(uiImage: .init(named: icon.appIconName) ?? .init()) .resizable() .aspectRatio(contentMode: .fit) .frame(minHeight: 125, maxHeight: 1024) .cornerRadius(6) .shadow(radius: 3) if icon.appIconName == currentIcon { Image(systemName: "checkmark.seal.fill") .padding(4) .tint(.green) } } } .buttonStyle(.plain) } } } } extension String { var localized: String { NSLocalizedString(self, comment: "") } }