diff --git a/ConversationsClassic/Resources/Strings/Localizable.strings b/ConversationsClassic/Resources/Strings/Localizable.strings index 35b879b..730872d 100644 --- a/ConversationsClassic/Resources/Strings/Localizable.strings +++ b/ConversationsClassic/Resources/Strings/Localizable.strings @@ -65,4 +65,5 @@ "Attachment.Tab.files" = "Files"; "Attachment.Tab.location" = "Location"; "Attachment.Tab.contacts" = "Contacts"; +"Attachment.Send.media" = "Send media"; diff --git a/ConversationsClassic/View/Screens/Attachments/AttachmentMediaPickerView.swift b/ConversationsClassic/View/Screens/Attachments/AttachmentMediaPickerView.swift index 05d1173..14264a1 100644 --- a/ConversationsClassic/View/Screens/Attachments/AttachmentMediaPickerView.swift +++ b/ConversationsClassic/View/Screens/Attachments/AttachmentMediaPickerView.swift @@ -3,7 +3,7 @@ import Photos import SwiftUI struct SelectedMedia { - let path: String + let id: String } struct AttachmentMediaPickerView: View { @@ -18,73 +18,98 @@ struct AttachmentMediaPickerView: View { var body: some View { let columns = Array(repeating: GridItem(.flexible(), spacing: 0), count: 3) - ScrollView(showsIndicators: false) { - LazyVGrid(columns: columns, spacing: 0) { - // For camera - if isCameraAccessGranted { - ZStack { - CameraView() - .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: { + VStack(spacing: 0) { + // List of media + ScrollView(showsIndicators: false) { + LazyVGrid(columns: columns, spacing: 0) { + // For camera + if isCameraAccessGranted { 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) + CameraView() + .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 { + 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 - if isGalleryAccessGranted { - ForEach(thumbnails) { photo in - photo - } - } 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) + // For gallery + if isGalleryAccessGranted { + ForEach(thumbnails) { photo in + photo + } + } 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) + .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 { 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 if let image { 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 if let image { 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 { - let id = UUID() + let id: String let gridSize: CGFloat let duration: String? @@ -210,7 +235,8 @@ private struct ThumbnailView: Identifiable, View { @State private var selected = false @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.gridSize = gridSize _selectedMedia = selected @@ -246,10 +272,6 @@ private struct ThumbnailView: Identifiable, View { .frame(width: 30, height: 30) .shadow(color: .black, radius: 2) .foregroundColor(.Material.Shape.white) - // Circle() - // .fill(Color.Material.Shape.white) - // .frame(width: 30, height: 30) - // .shadow(color: .black, radius: 2) .overlay { Image(systemName: "checkmark") .foregroundColor(.Material.Elements.active) @@ -265,9 +287,9 @@ private struct ThumbnailView: Identifiable, View { withAnimation { selected.toggle() if selected { - selectedMedia.append(SelectedMedia(path: id.uuidString)) + selectedMedia.append(SelectedMedia(id: id)) } else { - selectedMedia.removeAll { $0.path == id.uuidString } + selectedMedia.removeAll { $0.id == id } } } }