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 { struct SelfieCamApp: App {
init() { init() {
Design.showDebugLogs = true 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 { var body: some Scene {

View File

@ -195,9 +195,9 @@ struct CameraContainerView: View, Equatable {
let cameraPosition: CameraPosition let cameraPosition: CameraPosition
let onImageCaptured: (UIImage) -> Void 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 { static func == (lhs: CameraContainerView, rhs: CameraContainerView) -> Bool {
lhs.sessionKey == rhs.sessionKey && lhs.cameraPosition == rhs.cameraPosition lhs.sessionKey == rhs.sessionKey
} }
var body: some View { var body: some View {

View File

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

View File

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

View File

@ -137,6 +137,9 @@ final class SettingsViewModel: RingLightConfigurable {
/// Updates settings and saves to cloud immediately /// Updates settings and saves to cloud immediately
func updateSettings(_ transform: (inout SyncedSettings) -> Void) { 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 cloudSync.update { settings in
transform(&settings) transform(&settings)
settings.modificationCount += 1 settings.modificationCount += 1

View File

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