From f2d8c5c47fb48a60247e2b8c8e6e3b0b44153d1c Mon Sep 17 00:00:00 2001 From: Marcin Czachurski Date: Fri, 5 May 2023 18:36:15 +0200 Subject: [PATCH] Initial implementation --- .../Subviews/UserProfileStatusesView.swift | 26 ++++++++++--------- Vernissage/Widgets/ImageRowAsync.swift | 24 +++++++++++++---- Vernissage/Widgets/ImageRowItemAsync.swift | 11 ++++++-- 3 files changed, 42 insertions(+), 19 deletions(-) diff --git a/Vernissage/Views/UserProfileView/Subviews/UserProfileStatusesView.swift b/Vernissage/Views/UserProfileView/Subviews/UserProfileStatusesView.swift index c547edc..5f6843e 100644 --- a/Vernissage/Views/UserProfileView/Subviews/UserProfileStatusesView.swift +++ b/Vernissage/Views/UserProfileView/Subviews/UserProfileStatusesView.swift @@ -26,10 +26,12 @@ struct UserProfileStatusesView: View { private let imagePrefetcher = ImagePrefetcher(destination: .diskCache) var body: some View { - LazyVStack(alignment: .center) { - if firstLoadFinished == true { + // LazyVStack(alignment: .center) { + if firstLoadFinished == true { + LazyVGrid(columns: [GridItem(.flexible(), spacing: 10), GridItem(.flexible(), spacing: 0)], spacing: 5) { ForEach(self.statusViewModels, id: \.id) { item in - ImageRowAsync(statusViewModel: item, withAvatar: false) + ImageRowAsync(statusViewModel: item, withAvatar: false, clipToSquare: true) + .frame(width: UIScreen.main.bounds.width / 2, height: UIScreen.main.bounds.width / 2) } if allItemsLoaded == false && firstLoadFinished == true { @@ -46,16 +48,16 @@ struct UserProfileStatusesView: View { Spacer() } } - } else { - LoadingIndicator() - } - } - .onFirstAppear { - do { - try await self.loadStatuses() - } catch { - ErrorService.shared.handle(error, message: "global.error.errorDuringDownloadStatuses", showToastr: !Task.isCancelled) } + } else { + LoadingIndicator() + .onFirstAppear { + do { + try await self.loadStatuses() + } catch { + ErrorService.shared.handle(error, message: "global.error.errorDuringDownloadStatuses", showToastr: !Task.isCancelled) + } + } } } diff --git a/Vernissage/Widgets/ImageRowAsync.swift b/Vernissage/Widgets/ImageRowAsync.swift index 9e5cf52..12af889 100644 --- a/Vernissage/Widgets/ImageRowAsync.swift +++ b/Vernissage/Widgets/ImageRowAsync.swift @@ -14,13 +14,15 @@ struct ImageRowAsync: View { private let statusViewModel: StatusModel private let firstAttachment: AttachmentModel? private let showAvatar: Bool + private let clipToSquare: Bool @State private var selected: String @State private var imageHeight: Double @State private var imageWidth: Double - init(statusViewModel: StatusModel, withAvatar showAvatar: Bool = true) { + init(statusViewModel: StatusModel, withAvatar showAvatar: Bool = true, clipToSquare: Bool = false) { self.showAvatar = showAvatar + self.clipToSquare = clipToSquare self.statusViewModel = statusViewModel self.firstAttachment = statusViewModel.mediaAttachments.first self.selected = String.empty() @@ -44,7 +46,11 @@ struct ImageRowAsync: View { var body: some View { if statusViewModel.mediaAttachments.count == 1, let firstAttachment = self.firstAttachment { - ImageRowItemAsync(statusViewModel: self.statusViewModel, attachment: firstAttachment, withAvatar: self.showAvatar) { (imageWidth, imageHeight) in + ImageRowItemAsync(statusViewModel: self.statusViewModel, + attachment: firstAttachment, + withAvatar: self.showAvatar, + clipToSquare: self.clipToSquare) { (imageWidth, imageHeight) in + // When we download image and calculate real size we have to change view size. if imageWidth != self.imageWidth || imageHeight != self.imageHeight { withAnimation(.linear(duration: 0.4)) { @@ -53,11 +59,17 @@ struct ImageRowAsync: View { } } } - .frame(width: self.imageWidth, height: self.imageHeight) + .if(self.clipToSquare == false) { + $0.frame(width: self.imageWidth, height: self.imageHeight) + } } else { TabView(selection: $selected) { ForEach(statusViewModel.mediaAttachments, id: \.id) { attachment in - ImageRowItemAsync(statusViewModel: self.statusViewModel, attachment: attachment, withAvatar: self.showAvatar) { (imageWidth, imageHeight) in + ImageRowItemAsync(statusViewModel: self.statusViewModel, + attachment: attachment, + withAvatar: self.showAvatar, + clipToSquare: self.clipToSquare) { (imageWidth, imageHeight) in + // When we download image and calculate real size we have to change view size (only when image is now visible). if attachment.id == self.selected { if imageWidth != self.imageWidth || imageHeight != self.imageHeight { @@ -86,7 +98,9 @@ struct ImageRowAsync: View { } } }) - .frame(width: self.imageWidth, height: self.imageHeight) + .if(self.clipToSquare == false) { + $0.frame(width: self.imageWidth, height: self.imageHeight) + } .tabViewStyle(.page(indexDisplayMode: .never)) .overlay(CustomPageTabViewStyleView(pages: self.statusViewModel.mediaAttachments, currentId: $selected)) } diff --git a/Vernissage/Widgets/ImageRowItemAsync.swift b/Vernissage/Widgets/ImageRowItemAsync.swift index 45a79d3..c99e4d8 100644 --- a/Vernissage/Widgets/ImageRowItemAsync.swift +++ b/Vernissage/Widgets/ImageRowItemAsync.swift @@ -21,6 +21,7 @@ struct ImageRowItemAsync: View { private var statusViewModel: StatusModel private var attachment: AttachmentModel private let showAvatar: Bool + private let clipToSquare: Bool private let imageFromCache: Bool @State private var showThumbImage = false @@ -31,8 +32,11 @@ struct ImageRowItemAsync: View { init(statusViewModel: StatusModel, attachment: AttachmentModel, - withAvatar showAvatar: Bool = true, onImageDownloaded: @escaping (_: Double, _: Double) -> Void) { + withAvatar showAvatar: Bool = true, + clipToSquare: Bool = false, + onImageDownloaded: @escaping (_: Double, _: Double) -> Void) { self.showAvatar = showAvatar + self.clipToSquare = clipToSquare self.statusViewModel = statusViewModel self.attachment = attachment self.onImageDownloaded = onImageDownloaded @@ -149,7 +153,10 @@ struct ImageRowItemAsync: View { private func imageView(image: Image) -> some View { image .resizable() - .aspectRatio(contentMode: .fit) + .scaledToFill() + .if(self.clipToSquare) { + $0.frame(width: UIScreen.main.bounds.width / 2, height: UIScreen.main.bounds.width / 2).clipped() + } .onTapGesture(count: 2) { Task { // Update favourite in Pixelfed server.