diff --git a/Linphone/GeneratedGit.swift b/Linphone/GeneratedGit.swift index e2e791e55..cffa87656 100644 --- a/Linphone/GeneratedGit.swift +++ b/Linphone/GeneratedGit.swift @@ -2,6 +2,6 @@ import Foundation public enum AppGitInfo { public static let branch = "feature/medias_and_documents_lists" - public static let commit = "cad143172" + public static let commit = "ab47b1ab5" public static let tag = "6.1.0-alpha" } diff --git a/Linphone/UI/Main/Conversations/Fragments/ConversationDocumentsListFragment.swift b/Linphone/UI/Main/Conversations/Fragments/ConversationDocumentsListFragment.swift index 5801b431f..e124216ba 100644 --- a/Linphone/UI/Main/Conversations/Fragments/ConversationDocumentsListFragment.swift +++ b/Linphone/UI/Main/Conversations/Fragments/ConversationDocumentsListFragment.swift @@ -69,10 +69,12 @@ struct ConversationDocumentsListFragment: View { VStack(spacing: 0) { List { ForEach(conversationDocumentsListViewModel.documentsList, id: \.path) { file in - MediaGridItemView(file: file) - .background() + DocumentRow(file: file) + .padding(.vertical, 4) + .padding(.horizontal, 8) .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)) .listRowSeparator(.hidden) + .listRowBackground(Color.clear) } } .safeAreaInset(edge: .top, content: { @@ -82,7 +84,7 @@ struct ConversationDocumentsListFragment: View { .listStyle(.plain) .overlay( VStack { - if true { + if conversationDocumentsListViewModel.documentsList.isEmpty { Spacer() Text("conversation_no_document_found") .multilineTextAlignment(.leading) @@ -90,7 +92,7 @@ struct ConversationDocumentsListFragment: View { Spacer() } } - .padding(.all) + .padding(.all) ) } .frame(maxWidth: .infinity) @@ -111,34 +113,62 @@ struct ConversationDocumentsListFragment: View { } struct DocumentRow: View { - + + @State private var selectedURLAttachment: URL? @ObservedObject var file: FileModel var body: some View { - ZStack(alignment: .bottomTrailing) { - if let previewPath = file.mediaPreview, - let image = UIImage(contentsOfFile: previewPath) { - Image(uiImage: image) - .resizable() - .scaledToFill() - .frame(height: 110) - .clipped() - } else { - Rectangle() - .fill(Color.gray.opacity(0.2)) - .frame(height: 110) + HStack { + VStack { + Image(getImageOfType(filename: file.fileName, type: file.mimeTypeString)) + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.grayMain2c700) + .frame(width: 60, height: 60, alignment: .leading) } - - if let duration = file.audioVideoDuration, file.isVideoPreview { - Text(duration) - .font(.caption2) - .padding(6) - .background(Color.black.opacity(0.6)) - .foregroundColor(.white) - .clipShape(RoundedRectangle(cornerRadius: 6)) - .padding(6) + .frame(width: 100, height: 100) + .background(Color.grayMain2c200) + .onTapGesture { + selectedURLAttachment = URL(fileURLWithPath: file.originalPath) } + + VStack { + Text(file.fileName) + .foregroundStyle(Color.grayMain2c700) + .default_text_style_600(styleSize: 14) + .truncationMode(.middle) + .frame(maxWidth: .infinity, alignment: .leading) + .lineLimit(1) + + if file.fileSize > 0 { + Text(Int(file.fileSize).formatBytes()) + .default_text_style_300(styleSize: 14) + .frame(maxWidth: .infinity, alignment: .leading) + .lineLimit(1) + } + } + .padding(.horizontal, 10) + .frame(maxWidth: .infinity, alignment: .leading) + } + .background(.white) + .clipShape(RoundedRectangle(cornerRadius: 10)) + .onTapGesture { + selectedURLAttachment = URL(fileURLWithPath: file.originalPath) + } + } + + func getImageOfType(filename: String, type: String) -> String { + print("mimemime \(type)") + if type == "audio/mpeg" { + return "file-audio" + } else if type == "application/pdf" + || filename.lowercased().hasSuffix(".pdf") == true { + return "file-pdf" + } else if type.hasPrefix("text/") == true + || ["txt", "md", "json", "xml", "csv", "log"].contains(filename.split(separator: ".").last?.lowercased()) { + return "file-text" + } else { + return "file" } - .cornerRadius(8) } } diff --git a/Linphone/UI/Main/Conversations/Fragments/ConversationMediaListFragment.swift b/Linphone/UI/Main/Conversations/Fragments/ConversationMediaListFragment.swift index 3cc2868db..cd8a7c699 100644 --- a/Linphone/UI/Main/Conversations/Fragments/ConversationMediaListFragment.swift +++ b/Linphone/UI/Main/Conversations/Fragments/ConversationMediaListFragment.swift @@ -86,33 +86,42 @@ struct ConversationMediaListFragment: View { struct ConversationMediaGridView: View { @ObservedObject var viewModel: ConversationMediaListViewModel - - private let columns = [ - GridItem(.flexible(), spacing: 1), - GridItem(.flexible(), spacing: 1), - GridItem(.flexible(), spacing: 1) - ] + @State private var selectedURLAttachment: URL? + private let columns = 4 + private let spacing: CGFloat = 2 var body: some View { VStack(spacing: 0) { if !viewModel.mediaList.isEmpty && !viewModel.operationInProgress { - ScrollView { - LazyVGrid(columns: columns, spacing: 1) { - ForEach(viewModel.mediaList, id: \.path) { file in - MediaGridItemView(file: file) - .onTapGesture { - //viewModel.openMediaEvent.send(file) - } - .onAppear { - if file == viewModel.mediaList.last { - viewModel.loadMoreData(totalItemsCount: viewModel.mediaList.count) + GeometryReader { geometry in + let totalSpacing = spacing * CGFloat(columns - 1) + let itemWidth = (geometry.size.width - totalSpacing) / CGFloat(columns) + + ScrollView { + LazyVGrid( + columns: Array(repeating: GridItem(.fixed(itemWidth), spacing: spacing), count: columns), + spacing: spacing + ) { + ForEach(viewModel.mediaList, id: \.path) { file in + MediaGridItemView(file: file) + .aspectRatio(1, contentMode: .fit) + .frame(width: itemWidth, height: itemWidth) + .clipped() + .onTapGesture { + selectedURLAttachment = URL(fileURLWithPath: file.originalPath) } - } + .onAppear { + if file == viewModel.mediaList.last { + viewModel.loadMoreData(totalItemsCount: viewModel.mediaList.count) + } + } + } } + .padding(.horizontal, spacing) + .padding(.top, spacing) } - .padding(.horizontal, 2) - .padding(.top, 12) } + .quickLookPreview($selectedURLAttachment, in: viewModel.mediaList.compactMap { URL(fileURLWithPath: $0.originalPath) }) } else if viewModel.mediaList.isEmpty && !viewModel.operationInProgress { Spacer() Text("conversation_no_media_found") @@ -125,49 +134,47 @@ struct ConversationMediaGridView: View { } struct MediaGridItemView: View { - @ObservedObject var file: FileModel var body: some View { - ZStack(alignment: .bottomTrailing) { - if let previewPath = file.mediaPreview, - let image = UIImage(contentsOfFile: previewPath) { - Image(uiImage: image) - .resizable() - .scaledToFill() - .frame(width: 120, height: 120) - .clipped() - } else { - Rectangle() - .fill(Color.gray.opacity(0.2)) - .frame(width: 120, height: 120) - } - - if file.isVideoPreview { - VStack { - Spacer() - - Image("play-fill") - .renderingMode(.template) + GeometryReader { geo in + ZStack(alignment: .bottomTrailing) { + if let previewPath = file.mediaPreview, + let image = UIImage(contentsOfFile: previewPath) { + Image(uiImage: image) .resizable() - .foregroundStyle(.white) - .frame(width: 35, height: 35) - - Spacer() + .scaledToFill() + .frame(width: geo.size.width, height: geo.size.height) + .clipped() + } else { + Rectangle() + .fill(Color.gray.opacity(0.2)) + .frame(width: geo.size.width, height: geo.size.height) + } + + if file.isVideoPreview { + Image("play-fill") + .resizable() + .renderingMode(.template) + .scaledToFit() + .frame(width: geo.size.width * 0.3, height: geo.size.height * 0.3) + .foregroundColor(.white) + .shadow(radius: 2) + .position(x: geo.size.width / 2, y: geo.size.height / 2) + } + + if let duration = file.audioVideoDuration, file.isVideoPreview { + Text(duration) + .font(.caption2) + .padding(4) + .background(Color.black.opacity(0.6)) + .foregroundColor(.white) + .clipShape(RoundedRectangle(cornerRadius: 4)) + .padding(6) } - .frame(width: 120, height: 120) - } - - if let duration = file.audioVideoDuration, file.isVideoPreview { - Text(duration) - .font(.caption2) - .padding(6) - .background(Color.black.opacity(0.6)) - .foregroundColor(.white) - .clipShape(RoundedRectangle(cornerRadius: 6)) - .padding(6) } + .cornerRadius(8) } - .cornerRadius(8) + .aspectRatio(1, contentMode: .fit) } }