Created
September 28, 2024 18:09
-
-
Save maxhand/f49fac47443d0f312b50f1f87c66651a to your computer and use it in GitHub Desktop.
App Tint Settings
This file contains 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
import UIKit | |
enum AccentViewSection: Hashable, CaseIterable { case main } | |
enum AppAccent: Int, Hashable, CaseIterable { | |
case blue = 0 | |
case orange = 1 | |
case red = 2 | |
case purple = 3 | |
var name: String { | |
switch self { | |
case .blue: | |
return "Blue" | |
case .orange: | |
return "Orange" | |
case .red: | |
return "Red" | |
case .purple: | |
return "Purple" | |
} | |
} | |
var color: UIColor { | |
switch self { | |
case .blue: | |
return .systemBlue | |
case .red: | |
return .systemRed | |
case .orange: | |
return .systemOrange | |
case .purple: | |
return .systemPurple | |
} | |
} | |
} | |
private class AccentViewDataSource: UICollectionViewDiffableDataSource<AccentViewSection, AppAccent> { } | |
private typealias AccentViewSnapshot = NSDiffableDataSourceSnapshot<AccentViewSection, AppAccent> | |
class AccentPickerViewController: UIViewController { | |
private var dataSource: AccentViewDataSource? | |
private var collectionView: UICollectionView! | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
setupView() | |
makeDataSource() | |
applySnapshot() | |
} | |
private func setupView() { | |
title = "Accent" | |
collectionView = .init(frame: .zero, collectionViewLayout: makeLayout()) | |
collectionView.delegate = self | |
view = collectionView | |
} | |
private func makeLayout() -> UICollectionViewCompositionalLayout { | |
.list(using: .init(appearance: .insetGrouped)) | |
} | |
private func makeDataSource() { | |
dataSource = .init(collectionView: collectionView, cellProvider: { [unowned self] collectionView, indexPath, itemIdentifier in | |
collectionView.dequeueConfiguredReusableCell(using: accentCellRegistration, for: indexPath, item: itemIdentifier) | |
}) | |
} | |
private func applySnapshot(animatingDifferences: Bool = false) { | |
var snapshot = AccentViewSnapshot() | |
snapshot.appendSections(AccentViewSection.allCases) | |
snapshot.appendItems(AppAccent.allCases, toSection: .main) | |
dataSource?.apply(snapshot, animatingDifferences: animatingDifferences) | |
} | |
private let accentCellRegistration: UICollectionView.CellRegistration<UICollectionViewListCell, AppAccent> = { | |
.init { cell, indexPath, itemIdentifier in | |
var contentConfiguration = cell.defaultContentConfiguration() | |
contentConfiguration.text = itemIdentifier.name | |
contentConfiguration.image = UIImage( | |
systemName: "circle.fill")? | |
.withConfiguration( | |
UIImage.SymbolConfiguration( | |
paletteColors: [itemIdentifier.color] | |
) | |
.applying(UIImage.SymbolConfiguration(scale: .medium)) | |
) | |
cell.contentConfiguration = contentConfiguration | |
} | |
}() | |
} | |
extension AccentPickerViewController: UICollectionViewDelegate { | |
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { | |
collectionView.deselectItem(at: indexPath, animated: true) | |
guard let itemIdentifier = dataSource?.itemIdentifier(for: indexPath) else { return } | |
setAccent(itemIdentifier) | |
} | |
} | |
extension AccentPickerViewController { | |
private func setAccent(_ accent: AppAccent) { | |
UIApplication.keyWindow?.tintColor = accent.color | |
UserDefaults.appGroup.appTintColorRawValue = accent.rawValue | |
} | |
} | |
extension UIApplication { | |
static var keyWindow: UIWindow? { | |
let allScenes = UIApplication.shared.connectedScenes | |
for scene in allScenes { | |
guard let windowScene = scene as? UIWindowScene else { continue } | |
for window in windowScene.windows where window.isKeyWindow { | |
return window | |
} | |
} | |
return nil | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment