mv-experiment #1
|
@ -1,13 +1,17 @@
|
|||
import AVFoundation
|
||||
import Combine
|
||||
import Foundation
|
||||
import GRDB
|
||||
import Photos
|
||||
|
||||
@MainActor
|
||||
final class ConversationStore: ObservableObject {
|
||||
@Published private(set) var messages: [Message] = []
|
||||
@Published var replyText = ""
|
||||
private(set) var roster: Roster
|
||||
@Published var cameraAccessGranted = false
|
||||
@Published var galleryAccessGranted = false
|
||||
|
||||
private(set) var roster: Roster
|
||||
private let client: Client
|
||||
private let blockSize = Const.messagesPageSize
|
||||
private let messagesMax = Const.messagesMaxSize
|
||||
|
@ -49,6 +53,27 @@ extension ConversationStore {
|
|||
}
|
||||
}
|
||||
|
||||
extension ConversationStore {
|
||||
func checkCameraAuthorization() async {
|
||||
let status = AVCaptureDevice.authorizationStatus(for: .video)
|
||||
var isAuthorized = status == .authorized
|
||||
if status == .notDetermined {
|
||||
isAuthorized = await AVCaptureDevice.requestAccess(for: .video)
|
||||
}
|
||||
cameraAccessGranted = isAuthorized
|
||||
}
|
||||
|
||||
func checkGalleryAuthorization() async {
|
||||
let status = PHPhotoLibrary.authorizationStatus()
|
||||
var isAuthorized = status == .authorized
|
||||
if status == .notDetermined {
|
||||
let req = await PHPhotoLibrary.requestAuthorization(for: .readWrite)
|
||||
isAuthorized = (req == .authorized) || (req == .limited)
|
||||
}
|
||||
galleryAccessGranted = isAuthorized
|
||||
}
|
||||
}
|
||||
|
||||
private extension ConversationStore {
|
||||
func subscribe() {
|
||||
messagesCancellable = ValueObservation.tracking(Message
|
||||
|
@ -67,26 +92,3 @@ private extension ConversationStore {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// var isAuthorized: Bool {
|
||||
// get async {
|
||||
// let status = AVCaptureDevice.authorizationStatus(for: .video)
|
||||
//
|
||||
// // Determine if the user previously authorized camera access.
|
||||
// var isAuthorized = status == .authorized
|
||||
//
|
||||
// // If the system hasn't determined the user's authorization status,
|
||||
// // explicitly prompt them for approval.
|
||||
// if status == .notDetermined {
|
||||
// isAuthorized = await AVCaptureDevice.requestAccess(for: .video)
|
||||
// }
|
||||
//
|
||||
// return isAuthorized
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// func setUpCaptureSession() async {
|
||||
// guard await isAuthorized else { return }
|
||||
// // Set up the capture session.
|
||||
// }
|
||||
|
|
|
@ -3,11 +3,11 @@ import SwiftUI
|
|||
|
||||
struct CameraCellPreview: View {
|
||||
@Environment(\.router) var router
|
||||
@State private var cameraAuthorized = false
|
||||
@EnvironmentObject var store: ConversationStore
|
||||
|
||||
var body: some View {
|
||||
Group {
|
||||
if cameraAuthorized {
|
||||
if store.cameraAccessGranted {
|
||||
ZStack {
|
||||
CameraView()
|
||||
.aspectRatio(1, contentMode: .fit)
|
||||
|
@ -51,16 +51,7 @@ struct CameraCellPreview: View {
|
|||
}
|
||||
}
|
||||
.task {
|
||||
await checkAuthorization()
|
||||
await store.checkCameraAuthorization()
|
||||
}
|
||||
}
|
||||
|
||||
private func checkAuthorization() async {
|
||||
let status = AVCaptureDevice.authorizationStatus(for: .video)
|
||||
var isAuthorized = status == .authorized
|
||||
if status == .notDetermined {
|
||||
isAuthorized = await AVCaptureDevice.requestAccess(for: .video)
|
||||
}
|
||||
cameraAuthorized = isAuthorized
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
import SwiftUI
|
||||
|
||||
struct GalleryView: View {
|
||||
// @State private var selectedItems: [String] = []
|
||||
|
||||
var body: some View {
|
||||
Text("test")
|
||||
// Group {
|
||||
// if store.state.sharingState.isGalleryAccessGranted {
|
||||
// ForEach(store.state.sharingState.galleryItems) { item in
|
||||
// GridViewItem(item: item, selected: $selectedItems)
|
||||
// }
|
||||
// } else {
|
||||
// Button {
|
||||
// openAppSettings()
|
||||
// } label: {
|
||||
// ZStack {
|
||||
// Rectangle()
|
||||
// .fill(Color.Material.Background.light)
|
||||
// .overlay {
|
||||
// VStack {
|
||||
// Image(systemName: "photo")
|
||||
// .foregroundColor(.Material.Elements.active)
|
||||
// .font(.system(size: 30))
|
||||
// Text("Allow gallery access")
|
||||
// .foregroundColor(.Material.Text.main)
|
||||
// .font(.body3)
|
||||
// }
|
||||
// }
|
||||
// .frame(height: 100)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
private struct GridViewItem: View {
|
||||
// let item: SharingGalleryItem
|
||||
@Binding var selected: [String]
|
||||
@State var isSelected = false
|
||||
|
||||
var body: some View {
|
||||
Text("Test")
|
||||
// if let data = item.thumbnail {
|
||||
// ZStack {
|
||||
// Image(uiImage: UIImage(data: data) ?? UIImage())
|
||||
// .resizable()
|
||||
// .aspectRatio(contentMode: .fill)
|
||||
// .frame(width: Const.galleryGridSize, height: Const.galleryGridSize)
|
||||
// .clipped()
|
||||
// if let duration = item.duration {
|
||||
// VStack {
|
||||
// Spacer()
|
||||
// HStack {
|
||||
// Spacer()
|
||||
// Text(duration)
|
||||
// .foregroundColor(.Material.Text.white)
|
||||
// .font(.sub1)
|
||||
// .shadow(color: .black, radius: 2)
|
||||
// .padding(4)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if isSelected {
|
||||
// VStack {
|
||||
// HStack {
|
||||
// Spacer()
|
||||
// Circle()
|
||||
// .frame(width: 30, height: 30)
|
||||
// .shadow(color: .black, radius: 2)
|
||||
// .foregroundColor(.Material.Shape.white)
|
||||
// .overlay {
|
||||
// Image(systemName: "checkmark")
|
||||
// .foregroundColor(.Material.Elements.active)
|
||||
// .font(.body3)
|
||||
// }
|
||||
// .padding(4)
|
||||
// }
|
||||
// Spacer()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// .onTapGesture {
|
||||
// isSelected.toggle()
|
||||
// if isSelected {
|
||||
// selected.append(item.id)
|
||||
// } else {
|
||||
// selected.removeAll { $0 == item.id }
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// ZStack {
|
||||
// Rectangle()
|
||||
// .fill(Color.Material.Background.light)
|
||||
// .overlay {
|
||||
// ProgressView()
|
||||
// .foregroundColor(.Material.Elements.active)
|
||||
// }
|
||||
// .frame(width: Const.galleryGridSize, height: Const.galleryGridSize)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
|
@ -4,9 +4,6 @@ import Photos
|
|||
import SwiftUI
|
||||
|
||||
struct MediaPickerView: View {
|
||||
// @State private var showCameraPicker = false
|
||||
// @State private var cameraReady = false
|
||||
|
||||
@State private var selectedItems: [String] = []
|
||||
|
||||
var body: some View {
|
||||
|
@ -20,41 +17,9 @@ struct MediaPickerView: View {
|
|||
CameraCellPreview()
|
||||
|
||||
// For gallery
|
||||
// if store.state.sharingState.isGalleryAccessGranted {
|
||||
// ForEach(store.state.sharingState.galleryItems) { item in
|
||||
// GridViewItem(item: item, selected: $selectedItems)
|
||||
// }
|
||||
// } else {
|
||||
// Button {
|
||||
// openAppSettings()
|
||||
// } label: {
|
||||
// ZStack {
|
||||
// Rectangle()
|
||||
// .fill(Color.Material.Background.light)
|
||||
// .overlay {
|
||||
// VStack {
|
||||
// Image(systemName: "photo")
|
||||
// .foregroundColor(.Material.Elements.active)
|
||||
// .font(.system(size: 30))
|
||||
// Text("Allow gallery access")
|
||||
// .foregroundColor(.Material.Text.main)
|
||||
// .font(.body3)
|
||||
// }
|
||||
// }
|
||||
// .frame(height: 100)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
GalleryView()
|
||||
}
|
||||
}
|
||||
// .fullScreenCover(isPresented: $showCameraPicker) {
|
||||
// CameraPicker(sourceType: .camera) { data, type in
|
||||
// store.dispatch(.sharingAction(.cameraCaptured(media: data, type: type)))
|
||||
// showCameraPicker = false
|
||||
// store.dispatch(.sharingAction(.showSharing(false)))
|
||||
// }
|
||||
// .edgesIgnoringSafeArea(.all)
|
||||
// }
|
||||
|
||||
// Send panel
|
||||
Rectangle()
|
||||
|
@ -79,82 +44,5 @@ struct MediaPickerView: View {
|
|||
// store.dispatch(.sharingAction(.showSharing(false)))
|
||||
}
|
||||
}
|
||||
// .onAppear {
|
||||
// store.dispatch(.sharingAction(.checkCameraAccess))
|
||||
// store.dispatch(.sharingAction(.checkGalleryAccess))
|
||||
// }
|
||||
// .onChange(of: store.state.sharingState.isGalleryAccessGranted) { granted in
|
||||
// if granted {
|
||||
// store.dispatch(.fileAction(.fetchItemsFromGallery))
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
private struct GridViewItem: View {
|
||||
// let item: SharingGalleryItem
|
||||
@Binding var selected: [String]
|
||||
@State var isSelected = false
|
||||
|
||||
var body: some View {
|
||||
Text("Test")
|
||||
// if let data = item.thumbnail {
|
||||
// ZStack {
|
||||
// Image(uiImage: UIImage(data: data) ?? UIImage())
|
||||
// .resizable()
|
||||
// .aspectRatio(contentMode: .fill)
|
||||
// .frame(width: Const.galleryGridSize, height: Const.galleryGridSize)
|
||||
// .clipped()
|
||||
// if let duration = item.duration {
|
||||
// VStack {
|
||||
// Spacer()
|
||||
// HStack {
|
||||
// Spacer()
|
||||
// Text(duration)
|
||||
// .foregroundColor(.Material.Text.white)
|
||||
// .font(.sub1)
|
||||
// .shadow(color: .black, radius: 2)
|
||||
// .padding(4)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if isSelected {
|
||||
// VStack {
|
||||
// HStack {
|
||||
// Spacer()
|
||||
// Circle()
|
||||
// .frame(width: 30, height: 30)
|
||||
// .shadow(color: .black, radius: 2)
|
||||
// .foregroundColor(.Material.Shape.white)
|
||||
// .overlay {
|
||||
// Image(systemName: "checkmark")
|
||||
// .foregroundColor(.Material.Elements.active)
|
||||
// .font(.body3)
|
||||
// }
|
||||
// .padding(4)
|
||||
// }
|
||||
// Spacer()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// .onTapGesture {
|
||||
// isSelected.toggle()
|
||||
// if isSelected {
|
||||
// selected.append(item.id)
|
||||
// } else {
|
||||
// selected.removeAll { $0 == item.id }
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// ZStack {
|
||||
// Rectangle()
|
||||
// .fill(Color.Material.Background.light)
|
||||
// .overlay {
|
||||
// ProgressView()
|
||||
// .foregroundColor(.Material.Elements.active)
|
||||
// }
|
||||
// .frame(width: Const.galleryGridSize, height: Const.galleryGridSize)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@ struct ConversationTextInput: View {
|
|||
.tappablePadding(.symmetric(8)) {
|
||||
router.showScreen(.fullScreenCover) { _ in
|
||||
AttachmentPickerScreen()
|
||||
.environmentObject(conversation)
|
||||
}
|
||||
}
|
||||
TextField("", text: $messageStr, prompt: Text(L10n.Chat.textfieldPrompt).foregroundColor(.Material.Shape.separator))
|
||||
|
|
Loading…
Reference in a new issue