metatext/Views/SwiftUI/AppIconPreferencesView.swift
2021-03-03 23:22:32 -08:00

114 lines
3.2 KiB
Swift

// Copyright © 2021 Metabolist. All rights reserved.
import SwiftUI
import ViewModels
struct AppIconPreferencesView: View {
@StateObject var viewModel: PreferencesViewModel
@State var alertItem: AlertItem?
var body: some View {
ScrollView {
LazyVGrid(columns: [
GridItem(.flexible(minimum: .minimumButtonDimension)),
GridItem(.flexible(minimum: .minimumButtonDimension)),
GridItem(.flexible(minimum: .minimumButtonDimension))
]) {
ForEach(AppIcon.allCases) {
cell(appIcon: $0)
}
}
.padding()
}
.alertItem($alertItem)
.navigationTitle("preferences.app-icon")
}
}
private extension AppIconPreferencesView {
@ViewBuilder func cell(appIcon: AppIcon) -> some View {
Button {
set(appIcon: appIcon)
} label: {
VStack {
if let image = appIcon.image {
image
.cornerRadius(.defaultCornerRadius)
.shadow(radius: .defaultShadowRadius)
.padding(.compactSpacing)
.background(appIcon == AppIcon.current ? Color.blue : Color.clear)
.cornerRadius(.defaultCornerRadius)
.padding(.top)
}
Text(appIcon.nameLocalizedStringKey)
.scaledToFill()
.minimumScaleFactor(0.5)
.foregroundColor(.primary)
}
}
}
func set(appIcon: AppIcon) {
UIApplication.shared.setAlternateIconName(appIcon.alternateIconName) { error in
DispatchQueue.main.async {
if let error = error {
alertItem = AlertItem(error: error)
} else {
viewModel.objectWillChange.send()
}
}
}
}
}
enum AppIcon: String, CaseIterable {
case classic = "AppIconClassic"
case rainbow = "AppIconRainbow"
case brutalist = "AppIconBrutalist"
case rainbowBrutalist = "AppIconRainbowBrutalist"
}
extension AppIcon {
static var current: Self? { Self(rawValue: UIApplication.shared.alternateIconName ?? Self.classic.rawValue) }
var nameLocalizedStringKey: LocalizedStringKey {
switch self {
case .classic:
return "app-icon.classic"
case .rainbow:
return "app-icon.rainbow"
case .brutalist:
return "app-icon.brutalist"
case .rainbowBrutalist:
return "app-icon.rainbow-brutalist"
}
}
var alternateIconName: String? {
switch self {
case .classic:
return nil
default:
return rawValue
}
}
var image: Image? {
guard let image = UIImage(named: rawValue) else { return nil }
return Image(uiImage: image)
}
}
extension AppIcon: Identifiable {
var id: Self { self }
}
#if DEBUG
struct AppIconPreferencesView_Previews: PreviewProvider {
static var previews: some View {
AppIconPreferencesView(viewModel: .init(identityContext: .preview))
}
}
#endif