// // IconGeneratorView.swift // Blackjack // // Development tool to generate and export app icon images. // Run this view, tap the button, then find the icons in the Files app. // import SwiftUI import CasinoKit /// A development view that generates and saves app icon images. /// After running, find the icons in Files app → On My iPhone → Blackjack struct IconGeneratorView: View { @State private var status: String = "Tap the button to generate icons" @State private var isGenerating = false @State private var generatedIcons: [GeneratedIcon] = [] // Development view: hardcoded sizes acceptable private let previewSize: CGFloat = 200 private let iconCornerRadiusRatio: CGFloat = 0.22 var body: some View { NavigationStack { ScrollView { VStack(spacing: Design.Spacing.xxLarge) { // Preview AppIconView(config: .blackjack, size: previewSize) .clipShape(.rect(cornerRadius: previewSize * iconCornerRadiusRatio)) .shadow(radius: 10) Text("App Icon Preview") .font(.headline) // Generate button Button { Task { await generateIcons() } } label: { HStack { if isGenerating { ProgressView() .tint(.white) } Text(isGenerating ? "Generating..." : "Generate & Save Icons") } .font(.headline) .foregroundStyle(.white) .frame(maxWidth: .infinity) .padding() .background(isGenerating ? Color.gray : Color.blue) .clipShape(.rect(cornerRadius: 12)) } .disabled(isGenerating) .padding(.horizontal) // Status Text(status) .font(.callout) .foregroundStyle(.secondary) .multilineTextAlignment(.center) .padding(.horizontal) // Generated icons if !generatedIcons.isEmpty { VStack(alignment: .leading, spacing: 12) { Text("Generated Icons:") .font(.headline) ForEach(generatedIcons) { icon in HStack { Image(systemName: "checkmark.circle.fill") .foregroundStyle(.green) Text(icon.filename) .font(.caption.monospaced()) Spacer() Text("\(Int(icon.size))px") .font(.caption) .foregroundStyle(.secondary) } } } .padding() .background(Color.green.opacity(Design.Opacity.subtle)) .clipShape(.rect(cornerRadius: Design.CornerRadius.medium)) .padding(.horizontal) } // Instructions instructionsSection } .padding(.vertical) } .navigationTitle("Icon Generator") } } private var instructionsSection: some View { VStack(alignment: .leading, spacing: 12) { Text("After generating:") .font(.headline) VStack(alignment: .leading, spacing: Design.Spacing.small) { instructionRow(number: 1, text: "Open Files app on your device/simulator") instructionRow(number: 2, text: "Navigate to: On My iPhone → Blackjack") instructionRow(number: 3, text: "Find the AppIcon-1024.png file") instructionRow(number: 4, text: "AirDrop or share to your Mac") instructionRow(number: 5, text: "Drag into Xcode's Assets.xcassets/AppIcon") } Divider() Text("Alternative: Use an online tool") .font(.subheadline.bold()) Text("Upload the 1024px icon to appicon.co or makeappicon.com to generate all sizes automatically.") .font(.caption) .foregroundStyle(.secondary) } .padding() .background(Color.gray.opacity(Design.Opacity.subtle)) .clipShape(.rect(cornerRadius: Design.CornerRadius.medium)) .padding(.horizontal) } private func instructionRow(number: Int, text: String) -> some View { HStack(alignment: .top, spacing: 8) { Text("\(number).") .font(.callout.bold()) .foregroundStyle(.blue) Text(text) .font(.callout) } } @MainActor private func generateIcons() async { isGenerating = true generatedIcons = [] status = "Generating icons..." let sizes: [(CGFloat, String)] = [ (1024, "AppIcon-1024"), (180, "AppIcon-180"), (120, "AppIcon-120"), (87, "AppIcon-87"), (80, "AppIcon-80"), (60, "AppIcon-60"), (40, "AppIcon-40") ] let documentsPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] for (size, name) in sizes { // Render the icon let view = AppIconView(config: .blackjack, size: size) let renderer = ImageRenderer(content: view) renderer.scale = 1.0 if let uiImage = renderer.uiImage, let data = uiImage.pngData() { let filename = "\(name).png" let fileURL = documentsPath.appending(path: filename) do { try data.write(to: fileURL) generatedIcons.append(GeneratedIcon(filename: filename, size: size)) } catch { status = "Error saving \(filename): \(error.localizedDescription)" } } // Small delay for UI feedback try? await Task.sleep(for: .milliseconds(100)) } if generatedIcons.count == sizes.count { status = "✅ All icons saved to Documents folder!\nOpen Files app to find them." } else { status = "⚠️ Some icons failed to generate" } isGenerating = false } } struct GeneratedIcon: Identifiable { let id = UUID() let filename: String let size: CGFloat } #Preview { IconGeneratorView() }