Commit Graph

15 Commits

Author SHA1 Message Date
489318b220 Add Open Source Licenses section in Settings
Apache 2.0 license requires attribution for MijickCamera.
Added:
- 'About' section in Settings with 'Open Source Licenses' link
- LicensesView showing all third-party libraries:
  - MijickCamera (Apache 2.0)
  - RevenueCat (MIT)
- Links to GitHub repositories
- License type badges

This fulfills the attribution requirement for Apache 2.0 licensed
libraries used in the app.
2026-01-02 16:18:07 -06:00
829770b6b7 Integrate MijickCamera library, remove custom camera code
Major refactor: Replace custom camera implementation with MijickCamera

Added:
- MijickCamera Swift package (v3.0.3)
- MijickTimer dependency (required by MijickCamera)

Changed:
- ContentView now uses MCamera() from MijickCamera
- Ring light wraps around MijickCamera view with padding
- MijickCamera handles all camera logic:
  - Permissions
  - Capture (photo/video)
  - Camera switching
  - Orientation/rotation
  - Zoom/focus gestures
  - Flash

Removed:
- CameraViewModel.swift (replaced by MijickCamera)
- CameraPreview.swift (replaced by MijickCamera)

Kept:
- Ring light background (settings.lightColor)
- Ring size control (settings.ringSize)
- Grid overlay
- Post-capture preview workflow
- Settings view
- Premium features and paywall
- iCloud sync

Benefits:
- Less code to maintain
- Battle-tested camera implementation
- Better rotation handling built-in
- More camera features available (filters, exposure, etc.)
2026-01-02 16:16:31 -06:00
d93625b2a4 Add manual rotation button for camera preview
New feature: Rotate preview independent of device orientation
- Rotate button in top control bar (next to Center Stage)
- Cycles through: 0° → 90° → 180° → 270° → 0°
- Yellow highlight when rotation is active
- Icon changes to show current rotation state

Ring light integration:
- Preview background color now matches ring light color
- Letterbox areas (from aspect ratio differences) show ring light
- Placeholder during permission request also uses ring light color

Visual feedback:
- rotate.right (outline) = no rotation
- rotate.right.fill = 90° right
- arrow.up.arrow.down = 180°
- rotate.left.fill = 270° (90° left)

Full accessibility support with labels and hints.
2026-01-02 16:06:39 -06:00
6fb3c4e212 Fix camera stuck in landscape - improve orientation detection
Issues fixed:
1. On app launch, UIDevice.current.orientation may be .unknown or .faceUp
   causing no orientation to be set (defaulting to landscape)

2. When phone is flat, orientation was being skipped

Solution:
- Track lastValidOrientation as fallback
- When device orientation is invalid, get from windowScene.interfaceOrientation
- Use last known good orientation if all else fails
- Default to portrait (90°) if nothing else works

This ensures the camera preview starts in the correct orientation
and stays properly rotated during use.
2026-01-02 16:03:13 -06:00
e66487cabf Fix preview to show actual capture aspect ratio
Changes:
1. Preview layer now uses .resizeAspect instead of .resizeAspectFill
   - Shows exactly what will be in the captured photo
   - No cropping - what you see is what you get
   - Ring light naturally fills any letterbox areas

2. Session preset changed from .high to .photo
   - Optimized for photo capture
   - Consistent 4:3 aspect ratio
   - Better quality for selfies

This ensures the preview accurately represents the final photo,
eliminating surprise cropping in captured images.
2026-01-02 16:01:43 -06:00
80976c61d1 Fix camera preview not rotating with device orientation
The preview layer's connection needs its own rotation update, separate
from the capture output connections.

Changes:
- CameraPreviewUIView now listens to UIDevice.orientationDidChangeNotification
- updatePreviewOrientation() updates the preview layer's connection
- Called on layoutSubviews and orientation changes
- Handles faceUp/faceDown/unknown by keeping current orientation
- Uses modern videoRotationAngle API (iOS 17+)
2026-01-02 16:00:03 -06:00
0f2655593f Add premium gating UX for color presets
Visual feedback for non-premium users:
- Premium colors show lock overlay with darkened circle
- Crown icon is hollow (outline) when locked, filled when unlocked
- Text is dimmed for locked colors
- Custom color shows rainbow gradient with lock overlay

Interaction behavior:
- Tapping locked premium color opens paywall
- Tapping locked custom color opens paywall
- Non-premium presets (Pure White, Warm Cream) remain fully accessible
- Premium users see unlocked UI with filled crown icons

This helps users:
1. See what premium features are available
2. Easily distinguish free vs premium colors
3. Test both states by toggling ENABLE_DEBUG_PREMIUM env var
2026-01-02 15:58:46 -06:00
a384db1c84 Fix ring light color always showing white
Bug: The ring light background was gated behind premium check:
  premiumManager.isPremiumUnlocked ? settings.lightColor : white

This blocked ALL colors (even non-premium ones like Warm Cream)
from displaying unless the user was premium.

Fix: Remove the premium gate from the display - the selected color
always shows. Premium enforcement should happen in Settings when
selecting colors, not in displaying them.
2026-01-02 15:54:11 -06:00
533e428e94 Fix ring light color not updating when changed in settings
Issue: SwiftUI observation wasn't tracking color changes properly

Fixes:
1. Removed intermediate 'settings' computed property in ContentView
   - Was breaking SwiftUI's observation chain
   - Now access viewModel.settings directly everywhere

2. Added cached lightColorId for immediate UI response
   - Similar pattern to ringSize caching
   - Ensures SwiftUI tracks the stored property changes

This ensures the ring light color updates immediately when
selecting a different color preset or custom color in settings.
2026-01-02 15:49:34 -06:00
c442acf464 Fix camera issues: front flash reset, rotation, Center Stage
Fixes:
1. Front flash now properly resets after capture
   - restorePreviewAfterFlash() called in photo delegate
   - Preview no longer stays white after taking photo

2. Device rotation support
   - updateVideoOrientation() updates capture connections
   - Uses modern videoRotationAngle API (iOS 17+)
   - Listens to UIDevice.orientationDidChangeNotification

3. Center Stage support for supported devices
   - Detects Center Stage availability on front camera
   - Toggle button in top control bar (person.crop.rectangle icon)
   - Yellow highlight when enabled
   - Updates availability on camera switch
2026-01-02 15:46:56 -06:00
9066635a4d Fix UI issues: preview sizing, debounce, corners, color picker
Fixes:
1. Camera preview rounded corners - clipShape now applied before padding
   so the preview itself has rounded corners, not the container

2. Debounced slider saves - ringSize and customColor now use debouncing
   - Immediate UI update via cached values
   - 300ms debounce before cloud save
   - Prevents excessive save operations during slider drag

3. Simplified custom color picker to one-step
   - ColorPicker styled as a circle button
   - Shows current custom color always (no rainbow)
   - Tapping opens iOS native color picker directly
   - Color applies immediately on selection
   - No Apply/Cancel sheet needed
2026-01-02 15:43:01 -06:00
95377c5950 Add custom color picker as premium feature
Features:
- Custom color button in Light Color section (rainbow gradient icon)
- Tapping opens color picker sheet with:
  - Live color preview
  - Native iOS ColorPicker
  - Tips for best ring light colors
- Custom color syncs across devices via iCloud
- Premium-gated with crown icon indicator

Storage:
- CustomColorRGB struct for Codable-compatible color storage
- RGB values stored separately in SyncedSettings
- Color converts to/from UIColor for RGB extraction

UI:
- Rainbow gradient when not selected, solid custom color when selected
- Sheet with Apply/Cancel buttons
- Color preview bar at top of picker
2026-01-02 13:26:11 -06:00
bf5853d999 Fix UI issues: full-screen preview, ring size limits, cleaner layout
Changes:
1. Camera preview now fills available space (not forced square)
   - Maintains proper aspect ratio for captured photos
   - Controls overlay on top of preview

2. Ring size now limited based on screen dimensions
   - Maximum is 1/4 of smaller screen dimension
   - Prevents content from shifting off-screen

3. Removed light intensity slider
   - Was causing color changes (opacity approach)
   - Ring light now always at full brightness

4. Removed crown icon from main screen
   - Pro upgrade moved to Settings > Pro section
   - Cleaner camera interface

5. Smaller top icons
   - Grid and settings buttons use .body font
   - Less visual clutter
2026-01-02 13:23:17 -06:00
ef15a8c21a Add post-capture workflow with preview, edit, and share
Features:
- Full-screen PostCapturePreviewView after photo/video capture
- Auto-save to Photo Library (on by default, configurable in Settings)
- Toast notification when saved
- Retake button to discard and return to camera
- Share button with native iOS Share Sheet
- Edit mode with smoothing and glow intensity sliders
- Premium tools teaser in edit view
- Video/boomerang auto-playback with loop support

Settings:
- Added 'Auto-Save' toggle in Capture section
- Syncs across devices via iCloud

Architecture:
- CapturedMedia enum for photo/video/boomerang types
- ShareSheet UIViewControllerRepresentable wrapper
- Toast system in CameraViewModel
2026-01-02 13:05:27 -06:00
74e65829de Initial commit: SelfieRingLight app
Features:
- Camera preview with ring light effect
- Adjustable ring size with slider
- Light color presets (white, warm cream, ice blue, soft pink, warm amber, cool lavender)
- Light intensity control (opacity)
- Front flash (hides preview during capture)
- True mirror mode
- Skin smoothing toggle
- Grid overlay (rule of thirds)
- Self-timer options
- Photo and video capture modes
- iCloud sync for settings across devices

Architecture:
- SwiftUI with @Observable view models
- Protocol-oriented design (RingLightConfigurable, CaptureControlling)
- Bedrock design system integration
- CloudSyncManager for iCloud settings sync
- RevenueCat for premium features
2026-01-02 13:01:24 -06:00