Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>

This commit is contained in:
Matt Bruce 2026-02-03 09:12:23 -06:00
parent ab8ef49ddb
commit fb9a810262
6 changed files with 33 additions and 29 deletions

View File

@ -12,6 +12,15 @@ import Bedrock
struct SelfieCamApp: App {
init() {
Design.showDebugLogs = true
// Register SelfieCam theme with Bedrock
Theme.register(
text: AppTextColors.self,
surface: AppSurface.self,
accent: AppAccent.self,
status: AppStatus.self
)
Theme.register(border: AppBorder.self)
}
var body: some Scene {

View File

@ -195,9 +195,9 @@ struct CameraContainerView: View, Equatable {
let cameraPosition: CameraPosition
let onImageCaptured: (UIImage) -> Void
// Only compare sessionKey and cameraPosition for equality
// Only compare sessionKey for equality - we want to handle position changes via runtime setCameraPosition
static func == (lhs: CameraContainerView, rhs: CameraContainerView) -> Bool {
lhs.sessionKey == rhs.sessionKey && lhs.cameraPosition == rhs.cameraPosition
lhs.sessionKey == rhs.sessionKey
}
var body: some View {

View File

@ -320,17 +320,17 @@ struct CustomCameraScreen: MCameraScreen {
// Initial haptic for countdown start
triggerHaptic(.light)
Task { @MainActor in
while countdownSeconds > 0 {
try? await Task.sleep(for: .seconds(1))
countdownSeconds -= 1
// Haptic tick for each countdown second
triggerHaptic(.light)
// Use a Timer to ensure we update on the main thread every second
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in
if self.countdownSeconds > 1 {
self.countdownSeconds -= 1
self.triggerHaptic(.light)
} else {
timer.invalidate()
self.countdownSeconds = 0
self.isCountdownActive = false
self.performActualCapture()
}
// Countdown finished, perform capture
isCountdownActive = false
performActualCapture()
}
}
@ -542,16 +542,8 @@ struct CustomCameraScreen: MCameraScreen {
let newPosition: CameraPosition = cameraPosition == .front ? .back : .front
Design.debugLog("Double-tap: flipping camera to \(newPosition)")
Task {
do {
try await setCameraPosition(newPosition)
// Update settings to persist the change
// Update settings to persist the change - this will trigger the onChange in CustomCameraScreen
cameraSettings.cameraPosition = newPosition
currentCameraPosition = newPosition
} catch {
Design.debugLog("Failed to flip camera: \(error)")
}
}
}
// MARK: - Haptic Feedback

View File

@ -22,14 +22,14 @@ extension SettingsViewModel {
var cameraPosition: CameraPosition {
get {
// Access the data through cloudSync to ensure observation is tracked
let raw = cloudSync.data.cameraPositionRaw
let position: CameraPosition = raw == "front" ? .front : .back
Design.debugLog("cameraPosition getter: raw='\(raw)' -> \(position)")
return position
return raw == "back" ? .back : .front
}
set {
let rawValue = newValue == .front ? "front" : "back"
Design.debugLog("cameraPosition setter: \(newValue) -> raw='\(rawValue)'")
let rawValue = newValue == .back ? "back" : "front"
// Use updateSettings to ensure modificationCount is incremented and observers are notified
updateSettings { $0.cameraPositionRaw = rawValue }
}
}

View File

@ -137,6 +137,9 @@ final class SettingsViewModel: RingLightConfigurable {
/// Updates settings and saves to cloud immediately
func updateSettings(_ transform: (inout SyncedSettings) -> Void) {
// Since we are using @Observable, we need to ensure the property access is tracked
// The cloudSync.update call modifies the data, but we need to trigger the observation
// We wrap the update in a way that SwiftUI's observation system can see the change
cloudSync.update { settings in
transform(&settings)
settings.modificationCount += 1

View File

@ -27,7 +27,7 @@ struct AppLicensesView: View {
var body: some View {
LicensesView(
licenses: Self.licenses,
backgroundColor: AppSurface.overlay,
backgroundColor: AppSurface.primary,
cardBackgroundColor: AppSurface.card,
cardBorderColor: AppBorder.subtle,
accentColor: AppAccent.primary