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)
.callbackQueue(.dispatch(.global(qos: .background)))
.processingQueue(.dispatch(.global(qos: .background)))
.cacheOriginalImage()
.configure { view in
view.framePreloadCount = 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])
}
}
}
struct ProfileZoomView: View {
let pubkey: String
let profiles: Profiles
@Environment(\.presentationMode) var presentationMode
var navBarView: some View {
HStack {
Button(action: {
presentationMode.wrappedValue.dismiss() presentationMode.wrappedValue.dismiss()
} label: { }, label: {
Image(systemName: "xmark") Image(systemName: "xmark")
.foregroundColor(.white) .frame(width: 33, height: 33)
.font(.subheadline) .background(.regularMaterial)
.padding(.leading, 20) .clipShape(Circle())
} })
.zIndex(1)
VStack(alignment: .center) { Spacer()
Spacer()
ProfilePicView(pubkey: pubkey, size: 200.0, highlight: .none, profiles: profiles)
.padding(100)
.scaledToFit()
.scaleEffect(self.scale * scaleState)
.offset(x: offset.width + offsetState.width, y: offset.height + offsetState.height)
.gesture(SimultaneousGesture(zoomGesture, dragGesture))
.gesture(doubleTapGesture)
.modifier(SwipeToDismissModifier(minDistance: nil, onDismiss: {
presentationMode.wrappedValue.dismiss()
}))
Spacer()
}
} }
.padding()
}
var body: some View {
ZStack {
Color(.systemBackground)
.ignoresSafeArea()
ZoomableScrollView {
ImageContainerView(url: get_profile_url(picture: nil, pubkey: pubkey, profiles: profiles))
.aspectRatio(contentMode: .fit)
.padding(.top, Theme.safeAreaInsets?.top)
.padding(.bottom, Theme.safeAreaInsets?.bottom)
.padding(.horizontal)
}
.ignoresSafeArea()
.modifier(SwipeToDismissModifier(minDistance: 50, onDismiss: {
presentationMode.wrappedValue.dismiss()
}))
}
.overlay(navBarView, alignment: .top)
} }
} }