Created
October 12, 2022 00:54
-
-
Save AdamWhitcroft/0e1a57066ebd3f5c7547a680fd9f9ac6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// AppearanceSheet.swift | |
// PeePooBoobRelease | |
// | |
// Created by Adam Whitcroft on 2022-10-07. | |
// | |
import SwiftUI | |
struct AppearanceSheet: View { | |
// MARK: Dismiss | |
// Is this view visible or not | |
@Environment(\.dismiss) private var dismiss | |
@StateObject var viewModel = ChangeAppIconViewModel() | |
var body: some View { | |
ScrollView { | |
VStack(spacing: 16) { | |
// Section title | |
SectionTitleView(title: "App icon") | |
// App icon selector | |
InsetContentCard { | |
ForEach(ChangeAppIconViewModel.AppIcon.allCases) { appIcon in | |
HStack(spacing: 16) { | |
Image(uiImage: appIcon.preview) | |
.resizable() | |
.aspectRatio(contentMode: .fit) | |
.frame(width: 60, height: 60) | |
.cornerRadius(12) | |
Text(appIcon.description) | |
} | |
.onTapGesture { | |
withAnimation { | |
viewModel.updateAppIcon(to: appIcon) | |
} | |
} | |
} | |
} | |
} | |
.padding() | |
} | |
.navigationTitle("") | |
.navigationBarTitleDisplayMode(.inline) | |
.navigationBarBackButtonHidden(true) | |
.toolbar { | |
ToolbarItem(placement: .navigationBarLeading) { | |
Button { | |
dismiss() | |
} label: {} | |
.buttonStyle(RoundButtonStyleSmall(iconName: "chevron.left", iconColor: .secondary)) | |
} | |
ToolbarItem(placement: .principal) { | |
Text(Strings.SheetTitleAppearance) | |
.font(.system(.body, design: .rounded).weight(.bold)) | |
} | |
} | |
} | |
} | |
enum AppIcon: String, CaseIterable, Identifiable { | |
case primary = "AppIcon" | |
case primaryInverted = "AppIcon-Inverted" | |
case red = "AppIcon-Red" | |
case redInverted = "AppIcon-Red-Inverted" | |
// etc... | |
var id: String { rawValue } | |
var iconName: String? { | |
switch self { | |
case .primary: | |
// `nil` resets back to the primary `AppIcon` icon | |
return nil | |
default: | |
return rawValue | |
} | |
} | |
var description: String { | |
switch self { | |
case .primary: | |
return "Default" | |
case .primaryInverted: | |
return "Something about primary inverted here..." | |
case .red: | |
return "Something about red here..." | |
case .redInverted: | |
return "Something about red inverted here..." | |
} | |
} | |
var preview: UIImage { | |
UIImage(named: rawValue + "-Preview") ?? UIImage() | |
} | |
} | |
final class ChangeAppIconViewModel: ObservableObject { | |
@Published private(set) var selectedAppIcon: AppIcon | |
init() { | |
if let iconName = UIApplication.shared.alternateIconName, let appIcon = AppIcon(rawValue: iconName) { | |
selectedAppIcon = appIcon | |
} else { | |
selectedAppIcon = .primary | |
} | |
} | |
func updateAppIcon(to icon: AppIcon) { | |
let previousAppIcon = selectedAppIcon | |
selectedAppIcon = icon | |
Task { @MainActor in | |
guard UIApplication.shared.alternateIconName != icon.iconName else { | |
// No need to update since we're already using this icon. | |
return | |
} | |
do { | |
try await UIApplication.shared.setAlternateIconName(icon.iconName) | |
} catch { | |
// We're only logging the error here and not actively handling the app icon failure | |
// since it's very unlikely to fail. | |
print("Updating icon to \(String(describing: icon.iconName)) failed.") | |
// Restore previous app icon | |
selectedAppIcon = previousAppIcon | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment