wip
This commit is contained in:
parent
024c9d85c8
commit
cdccfb9e3e
|
@ -4,54 +4,61 @@ import SwiftUI
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
class MediaManager: NSObject, ObservableObject {
|
class MediaManager: NSObject, ObservableObject {
|
||||||
@Published var photos: [UIImage] = []
|
// @Published var photos: [UIImage] = []
|
||||||
@Published var cameraFeed: UIImage?
|
@Published var cameraFeed: UIImage?
|
||||||
|
|
||||||
|
// @Published var galleryAccessLevel: PHAuthorizationStatus = .notDetermined
|
||||||
|
@Published var cameraAccessLevel: AVAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: .video)
|
||||||
|
|
||||||
override init() {
|
override init() {
|
||||||
super.init()
|
super.init()
|
||||||
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
|
NotificationCenter.default.addObserver(self, selector: #selector(appDidBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)
|
||||||
self?.fetchPhotos()
|
|
||||||
self?.setupCameraFeed()
|
// DispatchQueue.main.async { [weak self] in
|
||||||
}
|
// // self?.fetchPhotos()
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
private func fetchPhotos() {
|
// private func fetchPhotos() {
|
||||||
let fetchOptions = PHFetchOptions()
|
// galleryAccessLevel = PHPhotoLibrary.authorizationStatus()
|
||||||
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
|
//
|
||||||
let assets = PHAsset.fetchAssets(with: .image, options: fetchOptions)
|
// let fetchOptions = PHFetchOptions()
|
||||||
|
// fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
|
||||||
let manager = PHImageManager.default()
|
// let assets = PHAsset.fetchAssets(with: .image, options: fetchOptions)
|
||||||
let option = PHImageRequestOptions()
|
//
|
||||||
option.isSynchronous = true
|
// let manager = PHImageManager.default()
|
||||||
|
// let option = PHImageRequestOptions()
|
||||||
assets.enumerateObjects { asset, _, _ in
|
// option.isSynchronous = true
|
||||||
manager.requestImage(for: asset, targetSize: CGSize(width: 200, height: 200), contentMode: .aspectFill, options: option) { image, _ in
|
//
|
||||||
if let image = image {
|
// assets.enumerateObjects { asset, _, _ in
|
||||||
DispatchQueue.main.async {
|
// manager.requestImage(for: asset, targetSize: CGSize(width: 200, height: 200), contentMode: .aspectFill, options: option) { image, _ in
|
||||||
self.photos.append(image)
|
// if let image = image {
|
||||||
}
|
// DispatchQueue.main.async {
|
||||||
}
|
// self.photos.append(image)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
private func setupCameraFeed() {
|
private func setupCameraFeed() {
|
||||||
|
cameraAccessLevel = AVCaptureDevice.authorizationStatus(for: .video)
|
||||||
|
|
||||||
let captureSession = AVCaptureSession()
|
let captureSession = AVCaptureSession()
|
||||||
captureSession.sessionPreset = .medium
|
captureSession.sessionPreset = .medium
|
||||||
|
|
||||||
guard let captureDevice = AVCaptureDevice.default(for: .video) else {
|
guard let backCamera = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) else {
|
||||||
|
print("Unable to access the back camera!")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let deviceInput: AVCaptureDeviceInput
|
|
||||||
do {
|
do {
|
||||||
deviceInput = try AVCaptureDeviceInput(device: captureDevice)
|
let input = try AVCaptureDeviceInput(device: backCamera)
|
||||||
|
if captureSession.canAddInput(input) {
|
||||||
|
captureSession.addInput(input)
|
||||||
|
}
|
||||||
} catch {
|
} catch {
|
||||||
return
|
print("Error Unable to initialize back camera: \(error.localizedDescription)")
|
||||||
}
|
|
||||||
|
|
||||||
if captureSession.canAddInput(deviceInput) {
|
|
||||||
captureSession.addInput(deviceInput)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let videoOutput = AVCaptureVideoDataOutput()
|
let videoOutput = AVCaptureVideoDataOutput()
|
||||||
|
@ -66,6 +73,7 @@ class MediaManager: NSObject, ObservableObject {
|
||||||
|
|
||||||
extension MediaManager: AVCaptureVideoDataOutputSampleBufferDelegate {
|
extension MediaManager: AVCaptureVideoDataOutputSampleBufferDelegate {
|
||||||
func captureOutput(_: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from _: AVCaptureConnection) {
|
func captureOutput(_: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from _: AVCaptureConnection) {
|
||||||
|
print("Capturing output started")
|
||||||
guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
|
guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -78,6 +86,25 @@ extension MediaManager: AVCaptureVideoDataOutputSampleBufferDelegate {
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.cameraFeed = UIImage(cgImage: cgImage)
|
self.cameraFeed = UIImage(cgImage: cgImage)
|
||||||
|
print("Updated camera feed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension MediaManager {
|
||||||
|
func openAppSettings() {
|
||||||
|
if
|
||||||
|
let appSettingsUrl = URL(string: UIApplication.openSettingsURLString),
|
||||||
|
UIApplication.shared.canOpenURL(appSettingsUrl)
|
||||||
|
{
|
||||||
|
UIApplication.shared.open(appSettingsUrl, completionHandler: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func appDidBecomeActive() {
|
||||||
|
// Update access levels
|
||||||
|
// galleryAccessLevel = PHPhotoLibrary.authorizationStatus()
|
||||||
|
cameraAccessLevel = AVCaptureDevice.authorizationStatus(for: .video)
|
||||||
|
setupCameraFeed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,52 +1,136 @@
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct AttachmentMediaPickerView: View {
|
struct AttachmentMediaPickerView: View {
|
||||||
// @StateObject private var mediaManager = MediaManager()
|
@StateObject private var mediaManager = MediaManager()
|
||||||
|
|
||||||
var hasCam: Bool = false
|
|
||||||
|
|
||||||
let elements = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"]
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ScrollView {
|
ScrollView {
|
||||||
LazyVGrid(columns: Array(repeating: .init(.flexible()), count: 3)) {
|
LazyVGrid(columns: Array(repeating: .init(.flexible()), count: 3)) {
|
||||||
ForEach(0 ..< 10) { index in
|
ForEach(elements) { element in
|
||||||
if index == 0 {
|
element
|
||||||
VStack {
|
|
||||||
Color.red
|
|
||||||
.frame(height: 100)
|
|
||||||
Color.red
|
|
||||||
.frame(height: 100)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Color.blue
|
|
||||||
.frame(height: 100)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(.horizontal)
|
.padding(.horizontal, 8)
|
||||||
// LazyVGrid(columns: [GridItem(), GridItem(), GridItem()]) {
|
|
||||||
// if let cameraFeed = mediaManager.cameraFeed {
|
|
||||||
// Button(action: {
|
|
||||||
// isPickerPresented = true
|
|
||||||
// }) {
|
|
||||||
// Image(uiImage: cameraFeed)
|
|
||||||
// .resizable()
|
|
||||||
// .aspectRatio(contentMode: .fill)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// ForEach(mediaManager.photos, id: \.self) { photo in
|
|
||||||
// Button(action: {
|
|
||||||
// selectedPhoto = photo
|
|
||||||
// }) {
|
|
||||||
// Image(uiImage: photo)
|
|
||||||
// .resizable()
|
|
||||||
// .aspectRatio(contentMode: .fill)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
.padding(.vertical, 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
private var elements: [GridElement] {
|
||||||
|
print("Creating elements")
|
||||||
|
var result: [GridElement] = []
|
||||||
|
|
||||||
|
// camera
|
||||||
|
if let feed = mediaManager.cameraFeed, mediaManager.cameraAccessLevel == .authorized {
|
||||||
|
result.append(GridElement(id: UUID(), type: .cameraFeed, content: feed) {
|
||||||
|
print("Go to capture???")
|
||||||
|
})
|
||||||
|
print("Added camera feed")
|
||||||
|
} else if mediaManager.cameraAccessLevel == .restricted {
|
||||||
|
result.append(GridElement(id: UUID(), type: .cameraRestricted, content: nil) {
|
||||||
|
print("Show alert")
|
||||||
|
})
|
||||||
|
print("Added camera restricted")
|
||||||
|
} else {
|
||||||
|
result.append(GridElement(id: UUID(), type: .cameraAskButton, content: nil) {
|
||||||
|
mediaManager.openAppSettings()
|
||||||
|
})
|
||||||
|
print("Added camera ask button")
|
||||||
|
}
|
||||||
|
|
||||||
|
// photos
|
||||||
|
// if mediaManager.galleryAccessLevel == .restricted {
|
||||||
|
// result.append(GridElement(id: UUID(), type: .photoRestricted, content: nil))
|
||||||
|
// } else {
|
||||||
|
// for photo in mediaManager.photos {
|
||||||
|
// result.append(GridElement(id: UUID(), type: .photo, content: photo))
|
||||||
|
// }
|
||||||
|
// if mediaManager.galleryAccessLevel != .authorized {
|
||||||
|
// result.append(GridElement(id: UUID(), type: .photoAskButton, content: nil))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum GridElementType {
|
||||||
|
case cameraFeed
|
||||||
|
case cameraAskButton
|
||||||
|
case cameraRestricted
|
||||||
|
case photo
|
||||||
|
case photoAskButton
|
||||||
|
case photoRestricted
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct GridElement: View, Identifiable {
|
||||||
|
let id: UUID
|
||||||
|
let type: GridElementType
|
||||||
|
let content: UIImage?
|
||||||
|
let action: () -> Void
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
switch type {
|
||||||
|
case .cameraFeed:
|
||||||
|
image
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fill)
|
||||||
|
.frame(width: 100, height: 100)
|
||||||
|
.clipped()
|
||||||
|
|
||||||
|
case .cameraAskButton:
|
||||||
|
Button {
|
||||||
|
action()
|
||||||
|
} label: {
|
||||||
|
RoundedRectangle(cornerRadius: 5)
|
||||||
|
.stroke(Color.Main.backgroundDark, lineWidth: 2)
|
||||||
|
.overlay {
|
||||||
|
Image(systemName: "camera")
|
||||||
|
.foregroundColor(.Material.tortoiseLight300)
|
||||||
|
.font(.system(size: 40))
|
||||||
|
}
|
||||||
|
.frame(height: 100)
|
||||||
|
// .resizable()
|
||||||
|
// .aspectRatio(contentMode: .fill)
|
||||||
|
// .frame(width: 100, height: 100)
|
||||||
|
// .clipped()
|
||||||
|
}
|
||||||
|
|
||||||
|
case .photo:
|
||||||
|
image
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fill)
|
||||||
|
.frame(width: 100, height: 100)
|
||||||
|
.clipped()
|
||||||
|
|
||||||
|
case .photoAskButton:
|
||||||
|
Button {
|
||||||
|
action()
|
||||||
|
} label: {
|
||||||
|
Image(systemName: "photo.badge.plus")
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fill)
|
||||||
|
.frame(width: 100, height: 100)
|
||||||
|
.clipped()
|
||||||
|
}
|
||||||
|
|
||||||
|
case .photoRestricted, .cameraRestricted:
|
||||||
|
Button {
|
||||||
|
action()
|
||||||
|
} label: {
|
||||||
|
Image(systemName: "cross")
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fill)
|
||||||
|
.frame(width: 100, height: 100)
|
||||||
|
.clipped()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var image: Image {
|
||||||
|
guard let content = content else {
|
||||||
|
return Image(systemName: "questionmark.square.dashed")
|
||||||
|
}
|
||||||
|
return Image(uiImage: content)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue