Refactor pfp image view to use zoomable scroll view

This commit is contained in:
OlegAba
2023-02-10 01:03:55 -05:00
parent 504108da75
commit 9a95967a81
2 changed files with 82 additions and 68 deletions

View File

@@ -94,7 +94,6 @@ struct VisualEffectView: UIViewRepresentable {
struct ProfileView: View { struct ProfileView: View {
let damus_state: DamusState let damus_state: DamusState
let zoom_size: CGFloat = 350.0
let pfp_size: CGFloat = 90.0 let pfp_size: CGFloat = 90.0
let bannerHeight: CGFloat = 150.0 let bannerHeight: CGFloat = 150.0

View File

@@ -5,84 +5,99 @@
// Created by scoder1747 on 12/27/22. // Created by scoder1747 on 12/27/22.
// //
import SwiftUI import SwiftUI
import Kingfisher
struct ProfileZoomView: View { private struct ImageContainerView: View {
@Environment(\.presentationMode) var presentationMode @ObservedObject var imageModel: KFImageModel
let pubkey: String
let profiles: Profiles
@GestureState private var scaleState: CGFloat = 1 @State private var image: UIImage?
@GestureState private var offsetState = CGSize.zero @State private var showShareSheet = false
@State private var offset = CGSize.zero init(url: URL?) {
@State private var scale: CGFloat = 1 self.imageModel = KFImageModel(
url: url,
func resetStatus(){ fallbackUrl: nil,
self.offset = CGSize.zero maxByteSize: 2000000, // 2 MB
self.scale = 1 downsampleSize: CGSize(width: 400, height: 400)
)
} }
var zoomGesture: some Gesture { private struct ImageHandler: ImageModifier {
MagnificationGesture() @Binding var handler: UIImage?
.updating($scaleState) { currentState, gestureState, _ in
gestureState = currentState
}
.onEnded { value in
scale *= value
}
}
var dragGesture: some Gesture { func modify(_ image: UIImage) -> UIImage {
DragGesture() handler = image
.updating($offsetState) { currentState, gestureState, _ in return image
gestureState = currentState.translation
}.onEnded { value in
offset.height += value.translation.height
offset.width += value.translation.width
}
}
var doubleTapGesture : some Gesture {
TapGesture(count: 2).onEnded { value in
resetStatus()
} }
} }
var body: some View { var body: some View {
ZStack(alignment: .topLeading) {
Color("DamusDarkGrey") // Or Color("DamusBlack")
.edgesIgnoringSafeArea(.all)
Button { KFAnimatedImage(imageModel.url)
presentationMode.wrappedValue.dismiss() .callbackQueue(.dispatch(.global(qos: .background)))
} label: { .processingQueue(.dispatch(.global(qos: .background)))
Image(systemName: "xmark") .cacheOriginalImage()
.foregroundColor(.white) .configure { view in
.font(.subheadline) view.framePreloadCount = 1
.padding(.leading, 20)
} }
.zIndex(1) .scaleFactor(UIScreen.main.scale)
.loadDiskFileSynchronously()
.fade(duration: 0.1)
.imageModifier(ImageHandler(handler: $image))
.onFailure { _ in
imageModel.downloadFailed()
}
.id(imageModel.refreshID)
.clipShape(Circle())
.modifier(ImageContextMenuModifier(url: imageModel.url, image: image, showShareSheet: $showShareSheet))
.sheet(isPresented: $showShareSheet) {
ShareSheet(activityItems: [imageModel.url])
}
}
}
VStack(alignment: .center) { struct ProfileZoomView: View {
let pubkey: String
let profiles: Profiles
@Environment(\.presentationMode) var presentationMode
var navBarView: some View {
HStack {
Button(action: {
presentationMode.wrappedValue.dismiss()
}, label: {
Image(systemName: "xmark")
.frame(width: 33, height: 33)
.background(.regularMaterial)
.clipShape(Circle())
})
Spacer() Spacer()
}
.padding()
}
ProfilePicView(pubkey: pubkey, size: 200.0, highlight: .none, profiles: profiles) var body: some View {
.padding(100) ZStack {
.scaledToFit() Color(.systemBackground)
.scaleEffect(self.scale * scaleState) .ignoresSafeArea()
.offset(x: offset.width + offsetState.width, y: offset.height + offsetState.height)
.gesture(SimultaneousGesture(zoomGesture, dragGesture)) ZoomableScrollView {
.gesture(doubleTapGesture) ImageContainerView(url: get_profile_url(picture: nil, pubkey: pubkey, profiles: profiles))
.modifier(SwipeToDismissModifier(minDistance: nil, onDismiss: { .aspectRatio(contentMode: .fit)
.padding(.top, Theme.safeAreaInsets?.top)
.padding(.bottom, Theme.safeAreaInsets?.bottom)
.padding(.horizontal)
}
.ignoresSafeArea()
.modifier(SwipeToDismissModifier(minDistance: 50, onDismiss: {
presentationMode.wrappedValue.dismiss() presentationMode.wrappedValue.dismiss()
})) }))
Spacer()
}
} }
.overlay(navBarView, alignment: .top)
} }
} }