Skip to content

Commit 20c0fc5

Browse files
FoodFinder camera: native-style overlay with library thumbnail
Polish the in-app camera so it feels like the iOS native Camera app and consolidates the two-button "Take a Photo / Choose from Library" entry point into a single capture surface. Camera overlay (FoodFinder_CameraOverlay): - Library-thumbnail button on the bottom-left auto-loads the user's most recent photo via PhotoKit (with the new NSPhotoLibraryUsageDescription prompt; falls back to a generic SF Symbol if denied). Tap flips the picker into .photoLibrary mode in place. - Flip-camera button bottom-right uses the iOS-native circular-arrows glyph (arrow.triangle.2.circlepath) in a circular chip. - Shutter unchanged in position; thumb + flip dropped to the bottom of the translucent band (the native camera does the same — auxiliary controls sit at the floor while the shutter stays elevated). - Semi-transparent black band behind the controls. - Camera preview scales + translates to fill the entire screen via cameraViewTransform so the translucent band shows actual preview content through it, not picker.view's solid black background. The captured frame is unaffected (still the full 4:3 sensor image). - All positioning happens in layoutSubviews against self.bounds — fixed shutter / thumbnail / flip being clipped off-screen when the overlay's rendered bounds differed from UIScreen.main.bounds. - showsCameraControls and cameraOverlayView are only touched when sourceType == .camera. Setting them on a .photoLibrary picker froze the OS picker. Image crop view (FoodFinder_ImageCropView): - Drop the inner NavigationView. The host AICameraView's outer nav bar now holds both Cancel (left) and a conditional "Reset Crop" (right) on the same row instead of two stacked toolbars. - Reset is driven by an integer `resetTrigger` binding the host increments — the crop view observes via .onChange. AI Food Analysis host (AICameraView): - "AI Food Analysis" title removed. - "Choose from Library" button removed; library entry is now the overlay's thumbnail. - Conditional Reset Crop ToolbarItem renders Button vs EmptyView inside the ToolbarItem body — `if` directly inside `.toolbar` needs ToolbarContentBuilder.buildIf which is iOS 16+. Strings: Info.plist gains NSPhotoLibraryUsageDescription. xcstrings catalogs auto-synced by Xcode.
1 parent 6921e37 commit 20c0fc5

5 files changed

Lines changed: 312 additions & 117 deletions

File tree

Loop/Info.plist

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@
6767
<string>AutoPresets reads your calendar to automatically activate presets before scheduled activities like gym sessions or runs. Calendar data stays on your device.</string>
6868
<key>NSCameraUsageDescription</key>
6969
<string>Camera is used to scan barcodes of devices.</string>
70+
<key>NSPhotoLibraryUsageDescription</key>
71+
<string>FoodFinder previews your most recent photo on the camera screen so you can pick a photo for analysis without leaving the capture view.</string>
7072
<key>NSLocationWhenInUseUsageDescription</key>
7173
<string>FoodFinder uses your location to tag meals with where you ate. AutoPresets uses location to activate presets when you arrive at or leave saved places like the gym.</string>
7274
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>

Loop/InfoPlist.xcstrings

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,6 +1146,18 @@
11461146
}
11471147
}
11481148
},
1149+
"NSPhotoLibraryUsageDescription" : {
1150+
"comment" : "Privacy - Photo Library Usage Description",
1151+
"extractionState" : "extracted_with_value",
1152+
"localizations" : {
1153+
"en" : {
1154+
"stringUnit" : {
1155+
"state" : "new",
1156+
"value" : "FoodFinder previews your most recent photo on the camera screen so you can pick a photo for analysis without leaving the capture view."
1157+
}
1158+
}
1159+
}
1160+
},
11491161
"NSSiriUsageDescription" : {
11501162
"comment" : "Privacy - Siri Usage Description",
11511163
"extractionState" : "extracted_with_value",

Loop/Localizable.xcstrings

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6569,9 +6569,6 @@
65696569
},
65706570
"AI food analysis" : {
65716571
"comment" : "Accessibility label for AI camera button"
6572-
},
6573-
"AI Food Analysis" : {
6574-
65756572
},
65766573
"AI Meal Debrief" : {
65776574
"comment" : "LoopInsights debrief header\nLoopInsights meal debrief toggle"
@@ -11152,7 +11149,7 @@
1115211149
"comment" : "Error message when camera permission is denied"
1115311150
},
1115411151
"Cancel" : {
11155-
"comment" : "Button label for cancel\nButton text to cancel\nCancel\nCancel button\nCancel button for reset loop alert\nCancel export button title\nLoopInsights pre-fill cancel button\nThe title of the cancel action in an action sheet",
11152+
"comment" : "Button label for cancel\nButton text to cancel\nCamera cancel button\nCancel\nCancel button\nCancel button for reset loop alert\nCancel export button title\nLoopInsights pre-fill cancel button\nThe title of the cancel action in an action sheet",
1115611153
"localizations" : {
1115711154
"ar" : {
1115811155
"stringUnit" : {
@@ -13328,9 +13325,6 @@
1332813325
}
1332913326
}
1333013327
}
13331-
},
13332-
"Choose from Library" : {
13333-
1333413328
},
1333513329
"Choose which types of data you want to share. Each category can be enabled or disabled independently." : {
1333613330
"comment" : "DataLayer categories description"
@@ -15399,10 +15393,6 @@
1539915393
"comment" : "A button that crops and analyzes an image.",
1540015394
"isCommentAutoGenerated" : true
1540115395
},
15402-
"Crop Image" : {
15403-
"comment" : "The title of the crop image view.",
15404-
"isCommentAutoGenerated" : true
15405-
},
1540615396
"Current" : {
1540715397
"comment" : "LoopInsights current value label\nLoopInsights pre-fill current label"
1540815398
},
@@ -35631,6 +35621,9 @@
3563135621
"Reset BolusPro tunables?" : {
3563235622
"comment" : "A confirmation alert asking the user to reset all BolusPro tunables to their default values.",
3563335623
"isCommentAutoGenerated" : true
35624+
},
35625+
"Reset Crop" : {
35626+
3563435627
},
3563535628
"Reset to defaults" : {
3563635629
"comment" : "A button that resets all settings to their default values.",

0 commit comments

Comments
 (0)