This commit is contained in:
fmodf 2024-07-04 11:53:45 +02:00
parent 8aa1ed6b75
commit c2fb21f932
2 changed files with 91 additions and 68 deletions

View file

@ -65,4 +65,5 @@
"Attachment.Tab.files" = "Files"; "Attachment.Tab.files" = "Files";
"Attachment.Tab.location" = "Location"; "Attachment.Tab.location" = "Location";
"Attachment.Tab.contacts" = "Contacts"; "Attachment.Tab.contacts" = "Contacts";
"Attachment.Send.media" = "Send media";

View file

@ -3,7 +3,7 @@ import Photos
import SwiftUI import SwiftUI
struct SelectedMedia { struct SelectedMedia {
let path: String let id: String
} }
struct AttachmentMediaPickerView: View { struct AttachmentMediaPickerView: View {
@ -18,73 +18,98 @@ struct AttachmentMediaPickerView: View {
var body: some View { var body: some View {
let columns = Array(repeating: GridItem(.flexible(), spacing: 0), count: 3) let columns = Array(repeating: GridItem(.flexible(), spacing: 0), count: 3)
ScrollView(showsIndicators: false) { VStack(spacing: 0) {
LazyVGrid(columns: columns, spacing: 0) { // List of media
// For camera ScrollView(showsIndicators: false) {
if isCameraAccessGranted { LazyVGrid(columns: columns, spacing: 0) {
ZStack { // For camera
CameraView() if isCameraAccessGranted {
.aspectRatio(1, contentMode: .fit)
.frame(maxWidth: .infinity)
Image(systemName: "camera")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 40, height: 40)
.foregroundColor(.white)
.padding(8)
.background(Color.black.opacity(0.5))
.clipShape(Circle())
.padding(8)
}
} else {
Button {
openAppSettings()
} label: {
ZStack { ZStack {
Rectangle() CameraView()
.fill(Color.Material.Background.light) .aspectRatio(1, contentMode: .fit)
.overlay { .frame(maxWidth: .infinity)
VStack { Image(systemName: "camera")
Image(systemName: "camera") .resizable()
.foregroundColor(.Material.Elements.active) .aspectRatio(contentMode: .fit)
.font(.system(size: 30)) .frame(width: 40, height: 40)
Text("Allow camera access") .foregroundColor(.white)
.foregroundColor(.Material.Text.main) .padding(8)
.font(.body3) .background(Color.black.opacity(0.5))
.clipShape(Circle())
.padding(8)
}
} else {
Button {
openAppSettings()
} label: {
ZStack {
Rectangle()
.fill(Color.Material.Background.light)
.overlay {
VStack {
Image(systemName: "camera")
.foregroundColor(.Material.Elements.active)
.font(.system(size: 30))
Text("Allow camera access")
.foregroundColor(.Material.Text.main)
.font(.body3)
}
} }
} .frame(height: 100)
.frame(height: 100) }
} }
} }
}
// For pictures // For gallery
if isGalleryAccessGranted { if isGalleryAccessGranted {
ForEach(thumbnails) { photo in ForEach(thumbnails) { photo in
photo photo
} }
} else { } else {
Button { Button {
openAppSettings() openAppSettings()
} label: { } label: {
ZStack { ZStack {
Rectangle() Rectangle()
.fill(Color.Material.Background.light) .fill(Color.Material.Background.light)
.overlay { .overlay {
VStack { VStack {
Image(systemName: "photo") Image(systemName: "photo")
.foregroundColor(.Material.Elements.active) .foregroundColor(.Material.Elements.active)
.font(.system(size: 30)) .font(.system(size: 30))
Text("Allow gallery access") Text("Allow gallery access")
.foregroundColor(.Material.Text.main) .foregroundColor(.Material.Text.main)
.font(.body3) .font(.body3)
}
} }
} .frame(height: 100)
.frame(height: 100) }
} }
} }
} }
} }
// Send panel
Rectangle()
.foregroundColor(.Material.Shape.black)
.frame(maxWidth: .infinity)
.frame(height: self.selectedMedia.isEmpty ? 0 : 50)
.overlay {
HStack {
Text(L10n.Attachment.Send.media)
.foregroundColor(.Material.Text.white)
.font(.body1)
Image(systemName: "arrow.up.circle")
.foregroundColor(.Material.Text.white)
.font(.body1)
.padding(.leading, 8)
}
.padding()
}
.clipped()
.onTapGesture {
print("Send media files")
}
} }
.onAppear { .onAppear {
DispatchQueue.global(qos: .background).asyncAfter(deadline: .now() + 0.2) { DispatchQueue.global(qos: .background).asyncAfter(deadline: .now() + 0.2) {
@ -160,7 +185,7 @@ struct AttachmentMediaPickerView: View {
image?.scaleAndCropImage(toExampleSize: CGSize(width: gridSize, height: gridSize), completion: { image in image?.scaleAndCropImage(toExampleSize: CGSize(width: gridSize, height: gridSize), completion: { image in
if let image { if let image {
DispatchQueue.main.async { DispatchQueue.main.async {
self.thumbnails.append(ThumbnailView(image: image, gridSize: gridSize, selected: $selectedMedia)) self.thumbnails.append(ThumbnailView(id: asset.localIdentifier, image: image, gridSize: gridSize, selected: $selectedMedia))
} }
} }
}) })
@ -177,7 +202,7 @@ struct AttachmentMediaPickerView: View {
thumbnail.scaleAndCropImage(toExampleSize: CGSize(width: gridSize, height: gridSize), completion: { image in thumbnail.scaleAndCropImage(toExampleSize: CGSize(width: gridSize, height: gridSize), completion: { image in
if let image { if let image {
DispatchQueue.main.async { DispatchQueue.main.async {
self.thumbnails.append(ThumbnailView(image: image, gridSize: gridSize, selected: $selectedMedia, duration: asset.duration.minAndSec)) self.thumbnails.append(ThumbnailView(id: asset.localIdentifier, image: image, gridSize: gridSize, selected: $selectedMedia, duration: asset.duration.minAndSec))
} }
} }
}) })
@ -201,7 +226,7 @@ struct AttachmentMediaPickerView: View {
} }
private struct ThumbnailView: Identifiable, View { private struct ThumbnailView: Identifiable, View {
let id = UUID() let id: String
let gridSize: CGFloat let gridSize: CGFloat
let duration: String? let duration: String?
@ -210,7 +235,8 @@ private struct ThumbnailView: Identifiable, View {
@State private var selected = false @State private var selected = false
@Binding var selectedMedia: [SelectedMedia] @Binding var selectedMedia: [SelectedMedia]
init(image: UIImage, gridSize: CGFloat, selected: Binding<[SelectedMedia]>, duration: String? = nil) { init(id: String, image: UIImage, gridSize: CGFloat, selected: Binding<[SelectedMedia]>, duration: String? = nil) {
self.id = id
self.image = image self.image = image
self.gridSize = gridSize self.gridSize = gridSize
_selectedMedia = selected _selectedMedia = selected
@ -246,10 +272,6 @@ private struct ThumbnailView: Identifiable, View {
.frame(width: 30, height: 30) .frame(width: 30, height: 30)
.shadow(color: .black, radius: 2) .shadow(color: .black, radius: 2)
.foregroundColor(.Material.Shape.white) .foregroundColor(.Material.Shape.white)
// Circle()
// .fill(Color.Material.Shape.white)
// .frame(width: 30, height: 30)
// .shadow(color: .black, radius: 2)
.overlay { .overlay {
Image(systemName: "checkmark") Image(systemName: "checkmark")
.foregroundColor(.Material.Elements.active) .foregroundColor(.Material.Elements.active)
@ -265,9 +287,9 @@ private struct ThumbnailView: Identifiable, View {
withAnimation { withAnimation {
selected.toggle() selected.toggle()
if selected { if selected {
selectedMedia.append(SelectedMedia(path: id.uuidString)) selectedMedia.append(SelectedMedia(id: id))
} else { } else {
selectedMedia.removeAll { $0.path == id.uuidString } selectedMedia.removeAll { $0.id == id }
} }
} }
} }