{"id":32519552,"url":"https://github.com/toddheasley/snap","last_synced_at":"2025-10-28T04:37:04.467Z","repository":{"id":207452416,"uuid":"717536545","full_name":"toddheasley/snap","owner":"toddheasley","description":"Point-and-shoot camera for iOS apps","archived":false,"fork":false,"pushed_at":"2024-01-23T00:50:55.000Z","size":4605,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-01-23T03:02:37.433Z","etag":null,"topics":["camera","ios","swift-package-manager","swiftui","uiimagepickercontroller"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/toddheasley.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-11-11T19:07:17.000Z","updated_at":"2024-01-19T18:27:53.000Z","dependencies_parsed_at":"2023-11-15T22:38:53.844Z","dependency_job_id":null,"html_url":"https://github.com/toddheasley/snap","commit_stats":null,"previous_names":["toddheasley/snap"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/toddheasley/snap","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toddheasley%2Fsnap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toddheasley%2Fsnap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toddheasley%2Fsnap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toddheasley%2Fsnap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/toddheasley","download_url":"https://codeload.github.com/toddheasley/snap/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toddheasley%2Fsnap/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":281386564,"owners_count":26492014,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-28T02:00:06.022Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["camera","ios","swift-package-manager","swiftui","uiimagepickercontroller"],"created_at":"2025-10-28T04:37:01.890Z","updated_at":"2025-10-28T04:37:04.430Z","avatar_url":"https://github.com/toddheasley.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `Snap`\n\n__Point-and-shoot camera for iOS apps__\n\nA single-lens, single-use alternative to `UIImagePickerController`, `Snap` covers the most common in-app picture-taking use case. Zero configuration, unless you want to pick a different lens or enable the flash. Takes one auto-focused JPEG at a time.\n\n### Supported Platforms\n\nWritten in [Swift](https://developer.apple.com/swift) 5.10 for [iOS](https://developer.apple.com/ios) 17. Build with [Xcode](https://developer.apple.com/xcode) 15 or newer.\n\n## Ready to Use\n\n![](docs/camera.png)\n\nPresent `Snap.Camera` using one of two included view modifiers for sheet and full-screen-cover modal presentations:\n\n```swift\nimport SwiftUI\nimport Snap\n\nstruct ContentView: View {\n    @State var isPresented: Bool = false\n    @State var isCapturing: Bool = false\n    @State var image: Camera.Image?\n    \n    var body: some View {\n        VStack {\n            Image(image)\n                .resizable()\n                .aspectRatio(contentMode: .fit)\n            Button(action: { isPresented.toggle() }) {\n                Label(\"Camera\", systemImage: \"camera\")\n            }\n            .sheet($isPresented) {\n                Camera($isCapturing) { image in\n                    self.image = image\n                    isPresented.toggle()\n                }\n            }\n        }\n    }\n}\n```\n\nToggle `$isCapturing` true to trigger the shutter programmatically. Captured still images are delivered as `Data` with `UTType public.jpeg`.\n\n`Snap.Camera` automatically selects the 1x-iest built-in rear camera available. Easily flip that to front-facing camera or pick your own:\n\n```swift\nCamera.device = .default() // .default(.back)\nCamera.device = .default(.front)\nCamera.device = Camera.Device([\n    .builtInDualCamera,\n    .builtInWideAngleCamera // Select first available\n], position: .back)\n\nCamera.quality = .balanced // Default\nCamera.quality = .speed \nCamera.quality = .quality\n\nCamera.flash = .off // Default\nCamera.flash = .auto\n```\n\n⚠️ Add a [privacy description](https://developer.apple.com/documentation/uikit/protecting_the_user_s_privacy/requesting_access_to_protected_resources) for camera usage to the main app target info.\n\n## Kit of Parts\n\n### `Camera`\n\n`Camera` holds the core functionality:\n\n* Interface binding to trigger the camera shutter\n* Handler to deliver a JPEG image of the configured quality, using the configured camera\n* Live video preview that scales to fill its SwiftUI containing view\n* Video preview flashes to indicate shutter release\n\nUse `Camera.shutterToggle(_ alignment: Alignment)` modifier to add a shutter button:\n\n```swift\n@State var isCapturing: Bool = false\n@State var error: Error? = nil\n\nCamera($isCapturing, error: $error) { image in\n    // image.fileType: public.jpeg\n    // image.data: 2901515 bytes\n}\n.shutterToggle() // Default alignment: .bottom\n```\n\n### `DisableIdleTimer`\n\nThe `Snap.Camera` sheet/full-screen presentations use a handy `ViewModifier` to keep the screen awake:\n\n```swift\nimport Snap\n\nEmptyView()\n    .disableIdleTimer() // .disableIdleTimer(300.0)\n    .disableIdleTimer(86400.0) // Lowest value wins\n```\n\n### `ImagePicker`\n\nSwiftUI is gonna get a first-party camera `Picker` of some kind _eventually_. In the meantime, `ImagePicker` wraps [`UIImagePickerController`](https://developer.apple.com/documentation/uikit/uiimagepickercontroller) for when you need features that `Snap.Camera` doesn't cover:\n\n* User-adjustable zoom and flash\n* Review, edit and retake\n* Hardware volume button shutter release\n* Movie recording\n\n![](docs/image-picker.png)\n\nPresent `ImagePicker` with the included view modifier, then handle any captured media:\n\n```swift\nimport Snap\n\n@State private var isPresented: Bool = false\n\nButton(action: { isPresented.toggle() }) {\n    Label(\"Camera\", systemImage: \"camera\")\n}\n.imagePicker($isPresented, media: [.image, .movie]) { info in\n    // info: [UIImagePickerController.InfoKey: Any]\n}\n```\n\n⚠️ `UIImagePickerController` is designed to be locked in portrait orientation only, but `UIViewControllerRepresentable` ignores view controller orientation locking. Hilarity ensues _unless_ your app is portrait only. Otherwise, stick to presenting from UIKit for now.\n\n⚠️ Enabling movie capture in `ImagePicker` or `UIImagePickerController` requires an additional target info privacy description for microphone usage.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftoddheasley%2Fsnap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftoddheasley%2Fsnap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftoddheasley%2Fsnap/lists"}