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:
parent
1999f7c137
commit
815b91f6ca
163
AGENTS.md
163
AGENTS.md
@ -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.
|
||||
|
||||
@ -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
158
README.md
@ -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)*
|
||||
|
||||
@ -762,10 +762,20 @@ struct SettingsView: View {
|
||||
}
|
||||
|
||||
// MARK: - Branding Debug Section
|
||||
|
||||
|
||||
#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")
|
||||
|
||||
@ -25,16 +25,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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user