SelfieRingLight/SelfieRingLight/Shared/Storage/SyncedSettings.swift
Matt Bruce 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

133 lines
4.1 KiB
Swift

import Foundation
import SwiftUI
import Bedrock
// MARK: - Synced Settings Data
/// Settings data structure that syncs across all devices via iCloud.
/// Conforms to `PersistableData` for use with Bedrock's `CloudSyncManager`.
struct SyncedSettings: PersistableData, Sendable {
// MARK: - PersistableData Requirements
static var dataIdentifier: String { "selfieRingLightSettings" }
static var empty: SyncedSettings {
SyncedSettings()
}
/// Sync priority based on modification count - higher means more changes made.
/// This ensures the most actively used device's settings win in conflicts.
var syncPriority: Int {
modificationCount
}
var lastModified: Date = .now
// MARK: - Settings Properties
/// How many times settings have been modified (for sync priority)
var modificationCount: Int = 0
/// Ring border size in points (stored as Double for Codable compatibility)
var ringSizeValue: Double = 40
/// ID of the selected light color preset
var lightColorId: String = "pureWhite"
/// Whether front flash is enabled (hides preview during capture)
var isFrontFlashEnabled: Bool = true
/// Whether the camera preview is flipped to show a true mirror
var isMirrorFlipped: Bool = false
/// Whether skin smoothing filter is enabled
var isSkinSmoothingEnabled: Bool = true
/// Selected self-timer option raw value
var selectedTimerRaw: String = "off"
/// Whether the grid overlay is visible
var isGridVisible: Bool = false
/// Current camera zoom factor
var currentZoomFactor: Double = 1.0
/// Selected capture mode raw value
var selectedCaptureModeRaw: String = "photo"
/// Whether captures are auto-saved to Photo Library
var isAutoSaveEnabled: Bool = true
// MARK: - Computed Properties
/// Ring size as CGFloat (convenience accessor)
var ringSize: CGFloat {
get { CGFloat(ringSizeValue) }
set { ringSizeValue = Double(newValue) }
}
// MARK: - Initialization
init() {}
init(
ringSize: CGFloat,
lightColorId: String,
isFrontFlashEnabled: Bool,
isMirrorFlipped: Bool,
isSkinSmoothingEnabled: Bool,
selectedTimerRaw: String,
isGridVisible: Bool,
currentZoomFactor: Double,
selectedCaptureModeRaw: String,
modificationCount: Int = 0
) {
self.ringSizeValue = Double(ringSize)
self.lightColorId = lightColorId
self.isFrontFlashEnabled = isFrontFlashEnabled
self.isMirrorFlipped = isMirrorFlipped
self.isSkinSmoothingEnabled = isSkinSmoothingEnabled
self.selectedTimerRaw = selectedTimerRaw
self.isGridVisible = isGridVisible
self.currentZoomFactor = currentZoomFactor
self.selectedCaptureModeRaw = selectedCaptureModeRaw
self.modificationCount = modificationCount
self.lastModified = .now
}
// MARK: - Codable
enum CodingKeys: String, CodingKey {
case modificationCount
case lastModified
case ringSizeValue
case lightColorId
case isFrontFlashEnabled
case isMirrorFlipped
case isSkinSmoothingEnabled
case selectedTimerRaw
case isGridVisible
case currentZoomFactor
case selectedCaptureModeRaw
case isAutoSaveEnabled
}
}
// MARK: - Equatable
extension SyncedSettings: Equatable {
static func == (lhs: SyncedSettings, rhs: SyncedSettings) -> Bool {
lhs.ringSizeValue == rhs.ringSizeValue &&
lhs.lightColorId == rhs.lightColorId &&
lhs.isFrontFlashEnabled == rhs.isFrontFlashEnabled &&
lhs.isMirrorFlipped == rhs.isMirrorFlipped &&
lhs.isSkinSmoothingEnabled == rhs.isSkinSmoothingEnabled &&
lhs.selectedTimerRaw == rhs.selectedTimerRaw &&
lhs.isGridVisible == rhs.isGridVisible &&
lhs.currentZoomFactor == rhs.currentZoomFactor &&
lhs.selectedCaptureModeRaw == rhs.selectedCaptureModeRaw &&
lhs.isAutoSaveEnabled == rhs.isAutoSaveEnabled
}
}