Update documentation and add branding system integration

Documentation:
- Update README.md with complete feature list and SelfieCam branding
- Update AI_Implementation.md with current architecture and branding details
- Add SelfieCam-specific sections to AGENTS.md (premium, branding, camera)

Features:
- Add branding debug section to SettingsView (icon generator, preview)
- Add BrandingConfig.swift with app colors and launch screen config
- Add LaunchBackground.colorset for seamless launch experience
- Wrap app in AppLaunchView for animated launch screen
This commit is contained in:
Matt Bruce 2026-01-04 14:43:53 -06:00
parent 1999f7c137
commit 815b91f6ca
5 changed files with 555 additions and 91 deletions

163
AGENTS.md
View File

@ -497,3 +497,166 @@ Color.Primary.background
- If installed, make sure SwiftLint returns no warnings or errors before committing.
- Verify that documentation reflects any new functionality or behavioral changes.
---
# SelfieCam-Specific Guidelines
The following sections are specific to this app's architecture and features.
## App Architecture
SelfieCam uses the following architectural patterns:
### Dependencies
- **Bedrock**: Local Swift package for design system, branding, and cloud sync
- **MijickCamera**: SwiftUI camera framework for capture and preview
- **RevenueCat**: Subscription management for premium features
### Key Protocols
| Protocol | Purpose | Conforming Types |
|----------|---------|------------------|
| `RingLightConfigurable` | Ring light settings (size, color, opacity) | `SettingsViewModel` |
| `CaptureControlling` | Capture actions (timer, flash, shutter) | `SettingsViewModel` |
| `PremiumManaging` | Subscription state and purchases | `PremiumManager` |
## Premium Features
### Adding a New Premium Feature
1. **Add setting to `SyncedSettings`** with an appropriate default value
2. **Use `PremiumGate.get()`** in the getter:
```swift
var myPremiumFeature: Bool {
get { PremiumGate.get(cloudSync.data.myFeature, default: false, isPremium: isPremiumUnlocked) }
set {
guard PremiumGate.canSet(isPremium: isPremiumUnlocked) else { return }
updateSettings { $0.myFeature = newValue }
}
}
```
3. **Add crown icon** in the UI to indicate premium status
4. **Wire up paywall** trigger when non-premium users tap the control
### Current Premium Features
- Custom ring light colors
- Premium color presets (Ice Blue, Soft Pink, Warm Amber, Cool Lavender)
- Flash sync with ring light color
- HDR mode
- High quality photos
- True mirror mode
- Skin smoothing
- Center Stage
- Extended timers (5s, 10s)
- Video and Boomerang capture modes
## Settings & iCloud Sync
### How Settings Work
1. All settings are stored in `SyncedSettings` struct
2. `CloudSyncManager<SyncedSettings>` handles iCloud synchronization
3. `SettingsViewModel` exposes properties that read/write through the sync manager
4. Slider values use debounced saves (300ms) to prevent excessive writes
### Adding a New Setting
1. Add property to `SyncedSettings` with default value
2. Add corresponding property in `SettingsViewModel`
3. For premium settings, use `PremiumGate` utilities
4. Add UI in `SettingsView`
## Branding System
### Overview
The app uses Bedrock's branding system for:
- Animated launch screen
- App icon generation
- Consistent color scheme
### Key Files
- `Shared/BrandingConfig.swift` - App icon and launch screen configuration
- `Resources/Assets.xcassets/LaunchBackground.colorset/` - Launch screen background color
- `App/SelfieCamApp.swift` - Wraps ContentView with AppLaunchView
### Modifying Branding
1. Update colors in `BrandingConfig.swift``Color.Branding`
2. Update `LaunchBackground.colorset` to match primary color
3. Adjust icon/launch screen config as needed
4. Use Icon Generator in Settings → Debug to create new app icon
### Documentation
See `Bedrock/Sources/Bedrock/Branding/BRANDING_GUIDE.md` for complete branding documentation.
## Camera Integration
### MijickCamera
The app uses MijickCamera for camera functionality:
```swift
import MijickCamera
// Camera position
var cameraPosition: CameraPosition // .front or .back
// Flash modes
var flashMode: CameraFlashMode // .off, .on, .auto
```
### Camera Features
- Front/back camera switching
- Pinch-to-zoom
- Photo capture with quality settings
- Video recording (premium)
- HDR mode (premium)
## Ring Light System
### How It Works
The ring light is a colored overlay (`RingLightOverlay`) that surrounds the camera preview:
- **Size**: Adjustable border width (10-120pt)
- **Color**: Preset colors or custom color picker
- **Opacity**: Adjustable brightness (10%-100%)
- **Toggle**: Can be enabled/disabled
### Color Presets
| Color | ID | Premium |
|-------|-----|---------|
| Pure White | `pureWhite` | No |
| Warm Cream | `warmCream` | No |
| Ice Blue | `iceBlue` | Yes |
| Soft Pink | `softPink` | Yes |
| Warm Amber | `warmAmber` | Yes |
| Cool Lavender | `coolLavender` | Yes |
| Custom | `custom` | Yes |
## Documentation Files
When making changes, update the appropriate documentation:
| File | Purpose |
|------|---------|
| `README.md` | User-facing app overview, setup instructions |
| `AI_Implementation.md` | Technical architecture, implementation details |
| `AGENTS.md` | Development guidelines (this file) |
Always commit documentation updates with the related code changes.

View File

@ -1,68 +1,272 @@
# AI_Implementation.md
# AI Implementation Guide
## How This App Was Architected & Built
This project was developed following strict senior-level iOS engineering standards, with guidance from an AI assistant (Grok) acting as a Senior iOS Engineer specializing in SwiftUI and modern Apple frameworks.
This project was developed following strict senior-level iOS engineering standards, with guidance from AI assistants acting as Senior iOS Engineers specializing in SwiftUI and modern Apple frameworks.
---
## Guiding Principles (from AGENTS.md)
### Guiding Principles (from AGENTS.md)
- **Protocol-Oriented Programming (POP) first**: All shared capabilities defined via protocols before concrete types
- **MVVM-lite**: Views are "dumb" — all logic lives in `@Observable` view models
- **No third-party dependencies**: Pure Apple frameworks only (SwiftUI, AVFoundation, StoreKit 2, CoreImage)
- **No magic numbers**: All dimensions, opacities, durations from centralized `Design` constants
- **Bedrock Design System**: Centralized design tokens, no magic numbers
- **Full accessibility**: Dynamic Type, VoiceOver labels/hints/traits/announcements
- **Modern Swift & SwiftUI**: Swift 6 concurrency, `@MainActor`, `foregroundStyle`, `clipShape(.rect)`, `NavigationStack`
- **Testable & reusable design**: Protocols enable mocking and future SPM package extraction
- **Testable & reusable design**: Protocols enable mocking and future package extraction
### Architecture Overview
---
## Architecture Overview
```
Shared/
├── DesignConstants.swift → Semantic design tokens (spacing, radii, sizes, etc.)
├── Color+Extensions.swift → Ring light color presets
├── DesignConstants.swift → Uses Bedrock design tokens
├── BrandingConfig.swift → App icon & launch screen config
├── Color+Extensions.swift → Ring light color presets
├── Models/
│ ├── CameraFlashMode.swift → Flash mode enum
│ ├── CameraHDRMode.swift → HDR mode enum
│ ├── PhotoQuality.swift → Photo quality settings
│ └── CapturedPhoto.swift → Photo data model
├── Protocols/
│ ├── RingLightConfigurable.swift → Border, color, brightness, mirror, smoothing
│ ├── CaptureControlling.swift → Timer, grid, zoom, capture mode
│ └── PremiumManaging.swift → Subscription state & purchase handling
└── Premium/
└── PremiumManager.swift → Native StoreKit 2 implementation
│ ├── RingLightConfigurable.swift → Border, color, brightness
│ ├── CaptureControlling.swift → Timer, grid, zoom, capture
│ └── PremiumManaging.swift → Subscription state
├── Premium/
│ └── PremiumManager.swift → RevenueCat integration
├── Services/
│ └── PhotoLibraryService.swift → Photo saving service
└── Storage/
└── SyncedSettings.swift → iCloud-synced settings
Features/
├── Camera/ → Main UI, preview, capture logic
├── Settings/ → Configuration screens
└── Paywall/ → Pro subscription flow
├── Camera/ → Main camera UI
│ ├── ContentView.swift → Screen coordinator
│ ├── Views/ → UI components
│ └── GridOverlay.swift → Rule of thirds
├── Settings/ → Configuration
│ ├── SettingsView.swift → Settings UI
│ └── SettingsViewModel.swift → Settings logic + sync
└── Paywall/ → Pro subscription flow
```
---
### Key Implementation Decisions
## Key Implementation Decisions
1. **Ring Light Effect**
- Achieved by coloring the safe area background and leaving a centered rectangular window for camera preview
- Border width controlled via user setting
- Gradient support added for directional "portrait lighting"
### 1. Ring Light Effect
- Achieved using `RingLightOverlay` view that creates a colored border around the camera preview
- Border width controlled via user setting (10-120pt range)
- Multiple preset colors with premium custom color picker
- Adjustable opacity/brightness (10%-100%)
- Enabled/disabled toggle for quick access
2. **Camera System**
- `AVCaptureSession` with front camera default
- `UIViewRepresentable` wrapper for preview with pinch-to-zoom
- Video data output delegate for future real-time filters (skin smoothing placeholder)
### 2. Camera System
- Uses **MijickCamera** framework for SwiftUI-native camera handling
- Supports front and back camera switching
- Pinch-to-zoom with smooth interpolation
- Flash modes: Off, On, Auto (with premium flash sync)
- HDR mode support (premium feature)
- Photo quality settings (medium free, high premium)
3. **Capture Enhancements**
- Timer with async countdown and accessibility announcements
- Volume button observation via KVO on `AVAudioSession.outputVolume`
- Flash burst: temporarily sets brightness to 1.0 on capture
### 3. Capture Enhancements
- Self-timer with countdown (3s free, 5s/10s premium)
- Post-capture preview with share functionality
- Auto-save option to Photo Library
- Front flash using screen brightness
- Support for photo, video, and boomerang modes
4. **Freemium Model**
- Built with pure StoreKit 2 (no RevenueCat)
- `PremiumManaging` protocol enables easy testing/mocking
- Clean paywall with benefit list and native purchase flow
### 4. Freemium Model
- Built with **RevenueCat** for subscription management
- `PremiumManager` wraps RevenueCat SDK
- `PremiumGate` utility for clean premium feature access
- Settings automatically fall back to free defaults when not premium
5. **Reusability Focus**
- All shared logic extracted to protocols
- Ready for future extraction into SPM packages:
- `SelfieCameraKit`
- `SelfieRingLightKit`
- `SelfiePremiumKit`
### 5. iCloud Sync
- Uses **Bedrock's CloudSyncManager** for settings synchronization
- `SyncedSettings` model contains all user preferences
- Debounced saves for slider values (300ms delay)
- Real-time sync status display in Settings
- Available to all users (not a premium feature)
### Development Process
- Iterative feature additions guided by competitive analysis of top App Store selfie apps
- Each new capability (timer, boomerang, gradient, subscriptions) added with protocol-first design
- Strict adherence to no magic numbers, full accessibility, and clean separation
- Final structure optimized for maintainability and future library extraction
### 6. Branding System
- Uses **Bedrock's Branding** module for launch screen and app icon
- `BrandingConfig.swift` defines app-specific colors and symbols
- `LaunchBackground.colorset` matches launch screen primary color
- Animated launch with configurable duration and pattern style
- Icon generator available in DEBUG builds
This app demonstrates production-quality SwiftUI architecture while delivering a delightful, competitive user experience.
---
## Premium Feature Implementation
### How Premium Gating Works
The app uses a centralized `PremiumGate` utility for consistent premium feature handling:
```swift
// In SettingsViewModel
var isMirrorFlipped: Bool {
get { PremiumGate.get(cloudSync.data.isMirrorFlipped, default: false, isPremium: isPremiumUnlocked) }
set {
guard PremiumGate.canSet(isPremium: isPremiumUnlocked) else { return }
updateSettings { $0.isMirrorFlipped = newValue }
}
}
```
### Premium Features List
| Feature | Free Value | Premium Value |
|---------|-----------|---------------|
| Ring light colors | Pure White, Warm Cream | All presets + custom |
| Timer options | Off, 3s | Off, 3s, 5s, 10s |
| Photo quality | Medium | Medium, High |
| HDR mode | Off | Off, On, Auto |
| True mirror | Off | Configurable |
| Skin smoothing | Off | Configurable |
| Flash sync | Off | Configurable |
| Center stage | Off | Configurable |
| Capture modes | Photo | Photo, Video, Boomerang |
---
## Settings & Persistence
### SyncedSettings Model
All user preferences are stored in a single `SyncedSettings` struct that syncs via iCloud:
- Ring light: size, color ID, custom color RGB, opacity, enabled
- Camera: position, flash mode, HDR mode, photo quality
- Display: mirror flip, skin smoothing, grid visible
- Capture: timer, capture mode, auto-save
- Premium features: flash sync, center stage
### Debounced Saves
Slider values (ring size, opacity) use debounced saving to prevent excessive iCloud writes:
```swift
private func debouncedSave(key: String, action: @escaping () -> Void) {
debounceTask?.cancel()
debounceTask = Task {
try? await Task.sleep(for: .milliseconds(300))
guard !Task.isCancelled else { return }
action()
}
}
```
---
## Branding Implementation
### Files Involved
1. **BrandingConfig.swift** - Defines app icon and launch screen configurations
2. **LaunchBackground.colorset** - Asset catalog color matching primary brand color
3. **SelfieCamApp.swift** - Wraps ContentView with AppLaunchView
### Color Scheme
```swift
extension Color {
enum Branding {
static let primary = Color(red: 0.85, green: 0.25, blue: 0.45) // Vibrant magenta
static let secondary = Color(red: 0.45, green: 0.12, blue: 0.35) // Deep purple
static let accent = Color.white
}
}
```
### Launch Screen Configuration
```swift
static let selfieCam = LaunchScreenConfig(
title: "SELFIE CAM",
tagline: "Look Your Best",
iconSymbols: ["camera.fill", "sparkles"],
cornerSymbol: "sparkle",
patternStyle: .radial,
// ... colors and sizing
)
```
---
## Development Workflow
### Adding a New Feature
1. **Define the protocol** (if shared behavior)
2. **Add to SyncedSettings** (if needs persistence)
3. **Implement in SettingsViewModel** (with premium gating if applicable)
4. **Add UI in SettingsView**
5. **Update documentation** (README, this file)
### Adding a Premium Feature
1. Add setting to `SyncedSettings` with appropriate default
2. Use `PremiumGate.get()` for the getter with free default
3. Use `PremiumGate.canSet()` guard for the setter
4. Add premium indicator (crown icon) in UI
5. Wire up paywall trigger for non-premium users
### Testing Premium Features
Set environment variable in scheme:
- **Name:** `ENABLE_DEBUG_PREMIUM`
- **Value:** `1`
---
## Reusability & Extraction
The codebase is structured for future extraction into reusable packages:
| Potential Package | Contents |
|-------------------|----------|
| **SelfieCameraKit** | Camera views, capture logic, preview components |
| **RingLightKit** | Ring light overlay, color presets, configuration |
| **PremiumKit** | Premium manager, gating utilities, paywall |
| **SyncedSettingsKit** | CloudSyncManager, settings model pattern |
---
## Key Dependencies
| Dependency | Purpose | Integration |
|------------|---------|-------------|
| **Bedrock** | Design system, branding, cloud sync | Local Swift package |
| **MijickCamera** | Camera capture and preview | SPM dependency |
| **RevenueCat** | Subscription management | SPM dependency |
---
## Code Quality Standards
- **No magic numbers**: All values from Design constants
- **Full accessibility**: Every interactive element has VoiceOver support
- **Protocol-first**: Shared behavior defined via protocols
- **Separation of concerns**: Views are dumb, ViewModels contain logic
- **Modern APIs**: Swift 6, async/await, @Observable
- **Documentation**: Code comments, README, implementation guides
---
## Future Enhancements
Potential areas for expansion:
- [ ] Real-time filters (beauty, color grading)
- [ ] Gesture-based capture (smile detection)
- [ ] Widget for quick camera access
- [ ] Apple Watch remote trigger
- [ ] Export presets (aspect ratios, watermarks)
- [ ] Social sharing integrations
---
This architecture demonstrates production-quality SwiftUI development while delivering a polished, competitive user experience.

158
README.md
View File

@ -1,42 +1,60 @@
# SelfieRingLight
# SelfieCam
A modern, professional-grade selfie camera app for iOS that simulates a high-quality ring light using the device's screen. Built entirely with SwiftUI, Swift 6, and AVFoundation.
A modern, professional-grade selfie camera app for iOS featuring a customizable ring light overlay, premium camera controls, and beautiful branding. Built entirely with SwiftUI, Swift 6, and the MijickCamera framework.
Perfect for low-light selfies, video calls, makeup checks, or professional portrait lighting on the go.
Perfect for low-light selfies, content creation, video calls, makeup application, or professional portrait lighting on the go.
## Features
### Core Camera & Lighting
- Full-screen front-camera preview with true mirror option
- Configurable **screen-based ring light** with adjustable border thickness
- Multiple color temperature presets (Pure White, Warm Cream, Ice Blue, Rose Pink, etc.)
- **Directional gradient lighting** for flattering portrait effects
- Real-time screen brightness control (overrides system brightness while in use)
- Flash burst on capture for extra fill light
- Full-screen camera preview with front/back camera switching
- Configurable **screen-based ring light** with adjustable border thickness (10-120pt)
- Multiple color temperature presets (Pure White, Warm Cream, Ice Blue, Soft Pink, Warm Amber, Cool Lavender)
- **Ring light brightness control** with adjustable opacity
- **Flash modes**: Off, On, Auto
- **Front Flash**: Uses screen brightness for front camera flash effect
- Real-time camera preview with smooth performance
### Capture Modes
- Photo capture (saved to Photo Library)
- Video recording
- **Boomerang** mode (3-second looping short video)
- 3-second and 10-second self-timer with countdown overlay and VoiceOver announcements
- Pinch-to-zoom gesture
- Volume button shutter support (photo or video start/stop)
- **Photo capture** with high-quality output
- **Video recording** (Premium)
- **Boomerang mode** for looping short videos (Premium)
- Self-timer with 3-second (free), 5-second, and 10-second (Premium) options
- Pinch-to-zoom gesture support
- Rule-of-thirds grid overlay (toggleable)
- Post-capture preview with share functionality
### Premium Features (Freemium Model)
- All advanced color presets + custom colors
- Gradient and directional lighting
- Advanced beauty filters (coming soon)
- Unlimited boomerang length
- No watermarks
- **Custom ring light colors** with full color picker
- **Premium color presets**: Ice Blue, Soft Pink, Warm Amber, Cool Lavender
- **Flash Sync**: Match flash color with ring light color
- **HDR Mode**: High Dynamic Range photo capture
- **High Quality Photos**: Maximum resolution output
- **True Mirror Mode**: Horizontally flipped preview like a real mirror
- **Skin Smoothing**: Real-time subtle skin smoothing filter
- **Center Stage**: Automatic subject tracking/centering
- **Extended Timers**: 5-second and 10-second self-timer options
- **Video & Boomerang**: Video recording and looping video capture
- Ad-free experience
### iCloud Sync
- Automatic settings synchronization across all devices
- Real-time sync status with last sync timestamp
- Manual "Sync Now" option
- Available to all users (free and premium)
### Branding & Launch
- **Animated launch screen** with customizable design
- **App icon generator** for creating consistent branding
- Seamless transition from launch to main app
- Configurable colors, patterns, and layout styles
### Accessibility & Polish
- Full VoiceOver support with meaningful labels, hints, and announcements
- Dynamic Type and ScaledMetric for readable text
- Dynamic Type and ScaledMetric for readable text at all sizes
- String Catalog localization ready (`.xcstrings`)
- Prevents screen dimming during use
- Restores original brightness on background/app close
- Consistent design system using Bedrock framework
- Prevents screen dimming during camera use
## Screenshots
*(Add App Store-ready screenshots here once built)*
@ -46,12 +64,17 @@ Perfect for low-light selfies, video calls, makeup checks, or professional portr
- Xcode 16+
- Swift 6 language mode
## Dependencies
- **[MijickCamera](https://github.com/Mijick/Camera)** - Modern SwiftUI camera framework
- **[RevenueCat](https://www.revenuecat.com)** - Subscription management
- **Bedrock** - Internal design system and UI components (local package)
## Setup
### 1. Clone the Repository
```bash
git clone https://github.com/yourusername/SelfieRingLight.git
cd SelfieRingLight
git clone https://github.com/yourusername/SelfieCam.git
cd SelfieCam
```
### 2. Configure API Keys
@ -60,7 +83,7 @@ This project uses `.xcconfig` files to securely manage API keys. **Never commit
1. Copy the template file:
```bash
cp SelfieRingLight/Configuration/Secrets.xcconfig.template SelfieRingLight/Configuration/Secrets.xcconfig
cp SelfieCam/Configuration/Secrets.xcconfig.template SelfieCam/Configuration/Secrets.xcconfig
```
2. Edit `Secrets.xcconfig` with your actual API key:
@ -91,7 +114,17 @@ To test premium features without a real subscription during development:
This unlocks all premium features in DEBUG builds only.
### 5. CI/CD Configuration
### 5. Branding Configuration
The app uses the Bedrock branding system for launch screen and app icon:
1. **BrandingConfig.swift** defines colors, icons, and launch screen settings
2. **Launch Screen Background Color** is set in Assets.xcassets and project build settings
3. **Icon Generator** available in Settings → Debug (DEBUG builds only)
See `Bedrock/Sources/Bedrock/Branding/BRANDING_GUIDE.md` for complete documentation.
### 6. CI/CD Configuration
For automated builds, set the `REVENUECAT_API_KEY` environment variable in your CI/CD system:
@ -108,32 +141,77 @@ Add `REVENUECAT_API_KEY` as a secret in your Xcode Cloud workflow.
- Camera access required for preview and capture
- Photo Library access required to save photos/videos
- Microphone access required for video recording
- iCloud access for settings synchronization (optional)
- No data collection, no analytics, no tracking
## Monetization
Freemium model with optional "Pro" subscription:
- Free: Basic ring light, standard colors, photo/video, timer, zoom
- Pro: Full color palette, gradients, advanced features, future updates
- **Free**: Basic ring light, standard colors (Pure White, Warm Cream), photo capture, 3s timer, grid, zoom
- **Pro**: Full color palette, custom colors, HDR, high quality, flash sync, true mirror, skin smoothing, center stage, extended timers, video, boomerang
Implemented with RevenueCat for reliable subscription management.
## Project Structure
```
SelfieRingLight/
├── App/ # App entry point
SelfieCam/
├── App/ # App entry point with launch screen
├── Configuration/ # xcconfig files (API keys)
├── Features/
│ ├── Camera/ # Camera preview, capture, view model
│ ├── Paywall/ # Pro subscription flow
│ └── Settings/ # Configuration screens
│ ├── Camera/ # Main camera UI
│ │ ├── ContentView.swift # Main screen coordinator
│ │ ├── Views/ # Camera UI components
│ │ │ ├── CustomCameraScreen.swift
│ │ │ ├── RingLightOverlay.swift
│ │ │ ├── CaptureButton.swift
│ │ │ ├── ExpandableControlsPanel.swift
│ │ │ └── ...
│ │ ├── GridOverlay.swift # Rule of thirds overlay
│ │ └── PostCapturePreviewView.swift
│ ├── Paywall/ # Pro subscription flow
│ │ └── ProPaywallView.swift
│ └── Settings/ # Configuration screens
│ ├── SettingsView.swift
│ ├── SettingsViewModel.swift
│ └── ...
├── Shared/
│ ├── Configuration/ # xcconfig files (API keys)
│ ├── Premium/ # PremiumManager (RevenueCat)
│ ├── Protocols/ # Shared protocols
│ ├── Color+Extensions.swift # Ring light color presets
│ └── DesignConstants.swift # Design tokens
└── Resources/ # Assets, localization
│ ├── BrandingConfig.swift # App icon & launch screen config
│ ├── DesignConstants.swift # Design tokens (uses Bedrock)
│ ├── Color+Extensions.swift # Ring light color presets
│ ├── Models/ # Data models
│ │ ├── CameraFlashMode.swift
│ │ ├── CameraHDRMode.swift
│ │ ├── PhotoQuality.swift
│ │ └── ...
│ ├── Protocols/ # Shared protocols
│ │ ├── RingLightConfigurable.swift
│ │ ├── CaptureControlling.swift
│ │ └── PremiumManaging.swift
│ ├── Premium/ # Subscription management
│ │ └── PremiumManager.swift
│ ├── Services/ # App services
│ │ └── PhotoLibraryService.swift
│ └── Storage/ # Persistence
│ └── SyncedSettings.swift # iCloud-synced settings model
└── Resources/ # Assets, localization
├── Assets.xcassets/
│ ├── AppIcon.appiconset/
│ ├── LaunchBackground.colorset/
│ └── ...
└── Localizable.xcstrings
```
## Key Technologies
| Technology | Purpose |
|------------|---------|
| SwiftUI | User interface framework |
| Swift 6 | Modern concurrency with strict checking |
| MijickCamera | Camera capture and preview |
| RevenueCat | Subscription management |
| Bedrock | Design system and branding |
| CloudKit | iCloud settings synchronization |
| AVFoundation | Low-level camera access |
## License
*(Add your license here)*

View File

@ -766,6 +766,16 @@ struct SettingsView: View {
#if DEBUG
private var brandingDebugSection: some View {
VStack(spacing: Design.Spacing.small) {
// Debug Premium Toggle
SettingsToggle(
title: "Enable Debug Premium",
subtitle: "Unlock all premium features for testing",
isOn: Binding(
get: { viewModel.premiumManager.isDebugPremiumToggleEnabled },
set: { viewModel.premiumManager.isDebugPremiumToggleEnabled = $0 }
)
)
.tint(Color.Status.warning)
// Icon Generator
NavigationLink {
IconGeneratorView(config: .selfieCam, appName: "SelfieCam")

View File

@ -26,16 +26,25 @@ final class PremiumManager: PremiumManaging {
// MARK: - Debug Override
/// Check if debug premium is enabled via environment variable.
/// Set "ENABLE_DEBUG_PREMIUM" = "1" in your scheme's environment variables to unlock all premium features during debugging.
/// Debug premium toggle stored in UserDefaults (only available in DEBUG builds)
@AppStorage("debugPremiumEnabled") private var debugPremiumEnabled = false
/// Check if debug premium is enabled via UserDefaults toggle or environment variable.
/// The toggle in Settings > Debug takes precedence over environment variables.
private var isDebugPremiumEnabled: Bool {
#if DEBUG
return ProcessInfo.processInfo.environment["ENABLE_DEBUG_PREMIUM"] == "1"
return debugPremiumEnabled || ProcessInfo.processInfo.environment["ENABLE_DEBUG_PREMIUM"] == "1"
#else
return false
#endif
}
/// Public getter/setter for debug premium toggle (DEBUG builds only)
var isDebugPremiumToggleEnabled: Bool {
get { debugPremiumEnabled }
set { debugPremiumEnabled = newValue }
}
var isPremium: Bool {
// Debug override takes precedence
if isDebugPremiumEnabled {