commit c100c6db47d62e7155a622528ee6acb30d5dde5c
parent 8d3fb397f7943087ada0326ab4edf2ee37909ed6
Author: OlegAba <mail@olegaba.com>
Date: Wed, 15 Feb 2023 12:31:50 -0800
Merge remote-tracking branch 'oleg/custom-profile-navbar'
Changelog-Added: Improved profile navbar
Diffstat:
5 files changed, 289 insertions(+), 239 deletions(-)
diff --git a/damus/Components/ImageCarousel.swift b/damus/Components/ImageCarousel.swift
@@ -127,14 +127,6 @@ struct ImageView: View {
@State private var selectedIndex = 0
@State var showMenu = true
- var safeAreaInsets: UIEdgeInsets? {
- return UIApplication
- .shared
- .connectedScenes
- .flatMap { ($0 as? UIWindowScene)?.windows ?? [] }
- .first { $0.isKeyWindow }?.safeAreaInsets
- }
-
var navBarView: some View {
VStack {
HStack {
@@ -180,8 +172,8 @@ struct ImageView: View {
ZoomableScrollView {
ImageContainerView(url: urls[index])
.aspectRatio(contentMode: .fit)
- .padding(.top, safeAreaInsets?.top)
- .padding(.bottom, safeAreaInsets?.bottom)
+ .padding(.top, Theme.safeAreaInsets?.top)
+ .padding(.bottom, Theme.safeAreaInsets?.bottom)
}
.modifier(SwipeToDismissModifier(minDistance: 50, onDismiss: {
presentationMode.wrappedValue.dismiss()
@@ -210,7 +202,7 @@ struct ImageView: View {
}
}
.animation(.easeInOut, value: showMenu)
- .padding(.bottom, safeAreaInsets?.bottom)
+ .padding(.bottom, Theme.safeAreaInsets?.bottom)
)
}
}
diff --git a/damus/Util/Theme.swift b/damus/Util/Theme.swift
@@ -25,4 +25,12 @@ class Theme {
UINavigationBar.appearance().tintColor = tintColor ?? titleColor ?? .black
}
+
+ static var safeAreaInsets: UIEdgeInsets? {
+ return UIApplication
+ .shared
+ .connectedScenes
+ .flatMap { ($0 as? UIWindowScene)?.windows ?? [] }
+ .first { $0.isKeyWindow }?.safeAreaInsets
+ }
}
diff --git a/damus/Views/Profile/ProfileNameView.swift b/damus/Views/Profile/ProfileNameView.swift
@@ -18,7 +18,7 @@ struct ProfileNameView: View {
var body: some View {
Group {
if let real_name = profile?.display_name {
- VStack(alignment: .leading) {
+ VStack(alignment: .leading, spacing: 0) {
Text(real_name)
.font(.title3.weight(.bold))
HStack(alignment: .center, spacing: spacing) {
@@ -30,6 +30,7 @@ struct ProfileNameView: View {
FollowsYou()
}
}
+ Spacer()
KeyView(pubkey: pubkey)
.pubkey_context_menu(bech32_pubkey: pubkey)
}
diff --git a/damus/Views/ProfileView.swift b/damus/Views/ProfileView.swift
@@ -80,9 +80,24 @@ struct EditButton: View {
}
}
+struct VisualEffectView: UIViewRepresentable {
+ var effect: UIVisualEffect?
+
+ func makeUIView(context: UIViewRepresentableContext<Self>) -> UIVisualEffectView {
+ UIVisualEffectView()
+ }
+
+ func updateUIView(_ uiView: UIVisualEffectView, context: UIViewRepresentableContext<Self>) {
+ uiView.effect = effect
+ }
+}
+
struct ProfileView: View {
let damus_state: DamusState
- let zoom_size: CGFloat = 350
+ let pfp_size: CGFloat = 90.0
+ let bannerHeight: CGFloat = 150.0
+
+ static let markdown = Markdown()
@State private var selected_tab: ProfileTab = .posts
@StateObject var profile: ProfileModel
@@ -92,20 +107,12 @@ struct ProfileView: View {
@State var is_zoomed: Bool = false
@State var show_share_sheet: Bool = false
@State var action_sheet_presented: Bool = false
+ @State var yOffset: CGFloat = 0
@Environment(\.dismiss) var dismiss
@Environment(\.colorScheme) var colorScheme
@Environment(\.openURL) var openURL
-
- // We just want to have a white "< Home" text here, however,
- // setting the initialiser is causing issues, and it's late.
- // Ref: https://blog.techchee.com/navigation-bar-title-style-color-and-custom-back-button-in-swiftui/
- /*
- init(damus_state: DamusState, zoom_size: CGFloat = 350) {
- self.damus_state = damus_state
- self.zoom_size = zoom_size
- Theme.navigationBarColors(background: nil, titleColor: .white, tintColor: nil)
- }*/
+ @Environment(\.presentationMode) var presentationMode
func fillColor() -> Color {
colorScheme == .light ? Color("DamusLightGrey") : Color("DamusDarkGrey")
@@ -115,39 +122,66 @@ struct ProfileView: View {
colorScheme == .light ? Color("DamusWhite") : Color("DamusBlack")
}
- func LNButton(lnurl: String, profile: Profile) -> some View {
- Button(action: {
- if damus_state.settings.show_wallet_selector {
- showing_select_wallet = true
- } else {
- open_with_wallet(wallet: damus_state.settings.default_wallet.model, invoice: lnurl)
+ func bannerBlurViewOpacity() -> Double {
+ let progress = -(yOffset + navbarHeight) / 100
+ return Double(-yOffset > navbarHeight ? progress : 0)
+ }
+
+ var bannerSection: some View {
+ GeometryReader { proxy -> AnyView in
+
+ let minY = proxy.frame(in: .global).minY
+
+ DispatchQueue.main.async {
+ self.yOffset = minY
}
- }) {
- Image(systemName: "bolt.circle")
- .profile_button_style(scheme: colorScheme)
- .contextMenu {
- Button {
- UIPasteboard.general.string = profile.lnurl ?? ""
- } label: {
- Label(NSLocalizedString("Copy LNURL", comment: "Context menu option for copying a user's Lightning URL."), systemImage: "doc.on.doc")
+
+ return AnyView(
+ VStack(spacing: 0) {
+ ZStack {
+ BannerImageView(pubkey: profile.pubkey, profiles: damus_state.profiles)
+ .aspectRatio(contentMode: .fill)
+ .frame(width: proxy.size.width, height: minY > 0 ? bannerHeight + minY : bannerHeight)
+ .clipped()
+
+ VisualEffectView(effect: UIBlurEffect(style: .systemUltraThinMaterial)).opacity(bannerBlurViewOpacity())
}
+
+ Divider().opacity(bannerBlurViewOpacity())
}
-
+ .frame(height: minY > 0 ? bannerHeight + minY : nil)
+ .offset(y: minY > 0 ? -minY : -minY < navbarHeight ? 0 : -minY - navbarHeight)
+ )
+
}
- .cornerRadius(24)
- .sheet(isPresented: $showing_select_wallet, onDismiss: {showing_select_wallet = false}) {
- SelectWalletView(showingSelectWallet: $showing_select_wallet, our_pubkey: damus_state.pubkey, invoice: lnurl)
+ .frame(height: bannerHeight)
+ }
+
+ var navbarHeight: CGFloat {
+ return 100.0 - (Theme.safeAreaInsets?.top ?? 0)
+ }
+
+ @ViewBuilder
+ func navImage(systemImage: String) -> some View {
+ Image(systemName: systemImage)
+ .frame(width: 33, height: 33)
+ .background(Color.black.opacity(0.6))
+ .clipShape(Circle())
+ }
+
+ var navBackButton: some View {
+ Button {
+ presentationMode.wrappedValue.dismiss()
+ } label: {
+ navImage(systemImage: "chevron.left")
}
}
-
- static let markdown = Markdown()
- var ActionSheetButton: some View {
+ var navActionSheetButton: some View {
Button(action: {
action_sheet_presented = true
}) {
- Image(systemName: "ellipsis.circle")
- .profile_button_style(scheme: colorScheme)
+ navImage(systemImage: "ellipsis")
}
.confirmationDialog(NSLocalizedString("Actions", comment: "Title for confirmation dialog to either share, report, or block a profile."), isPresented: $action_sheet_presented) {
Button(NSLocalizedString("Share", comment: "Button to share the link to a profile.")) {
@@ -166,19 +200,45 @@ struct ProfileView: View {
}
}
}
-
}
- var ShareButton: some View {
+ var customNavbar: some View {
+ HStack {
+ navBackButton
+ Spacer()
+ navActionSheetButton
+ }
+ .padding(.top, 5)
+ .padding(.horizontal)
+ .accentColor(Color("DamusWhite"))
+ }
+
+ func lnButton(lnurl: String, profile: Profile) -> some View {
Button(action: {
- show_share_sheet = true
+ if damus_state.settings.show_wallet_selector {
+ showing_select_wallet = true
+ } else {
+ open_with_wallet(wallet: damus_state.settings.default_wallet.model, invoice: lnurl)
+ }
}) {
- Image(systemName: "square.and.arrow.up.circle")
+ Image(systemName: "bolt.circle")
.profile_button_style(scheme: colorScheme)
+ .contextMenu {
+ Button {
+ UIPasteboard.general.string = profile.lnurl ?? ""
+ } label: {
+ Label(NSLocalizedString("Copy LNURL", comment: "Context menu option for copying a user's Lightning URL."), systemImage: "doc.on.doc")
+ }
+ }
+
+ }
+ .cornerRadius(24)
+ .sheet(isPresented: $showing_select_wallet, onDismiss: {showing_select_wallet = false}) {
+ SelectWalletView(showingSelectWallet: $showing_select_wallet, our_pubkey: damus_state.pubkey, invoice: lnurl)
}
}
- var DMButton: some View {
+ var dmButton: some View {
let dm_model = damus_state.dms.lookup_or_create(profile.pubkey)
let dmview = DMChatView(damus_state: damus_state, pubkey: profile.pubkey)
.environmentObject(dm_model)
@@ -187,44 +247,17 @@ struct ProfileView: View {
.profile_button_style(scheme: colorScheme)
}
}
-
- private func getScrollOffset(_ geometry: GeometryProxy) -> CGFloat {
- geometry.frame(in: .global).minY
- }
-
- private func getHeightForHeaderImage(_ geometry: GeometryProxy) -> CGFloat {
- let offset = getScrollOffset(geometry)
- let imageHeight = 150.0
-
- if offset > 0 {
- return imageHeight + offset
- }
-
- return imageHeight
- }
-
- private func getOffsetForHeaderImage(_ geometry: GeometryProxy) -> CGFloat {
- let offset = getScrollOffset(geometry)
-
- // Image was pulled down
- if offset > 0 {
- return -offset
- }
-
- return 0
- }
- func ActionSection(profile_data: Profile?) -> some View {
+ func actionSection(profile_data: Profile?) -> some View {
return Group {
- ActionSheetButton
if let profile = profile_data {
if let lnurl = profile.lnurl, lnurl != "" {
- LNButton(lnurl: lnurl, profile: profile)
+ lnButton(lnurl: lnurl, profile: profile)
}
}
- DMButton
+ dmButton
if profile.pubkey != damus_state.pubkey {
FollowButtonView(
@@ -241,136 +274,139 @@ struct ProfileView: View {
}
}
- func NameSection(profile_data: Profile?) -> some View {
+ func pfpOffset() -> CGFloat {
+ let progress = -yOffset / navbarHeight
+ let offset = (pfp_size / 4.0) * (progress < 1.0 ? progress : 1)
+ return offset > 0 ? offset : 0
+ }
+
+ func pfpScale() -> CGFloat {
+ let progress = -yOffset / navbarHeight
+ let scale = 1.0 - (0.5 * (progress < 1.0 ? progress : 1))
+ return scale < 1 ? scale : 1
+ }
+
+ func nameSection(profile_data: Profile?) -> some View {
return Group {
HStack(alignment: .center) {
ProfilePicView(pubkey: profile.pubkey, size: pfp_size, highlight: .custom(imageBorderColor(), 4.0), profiles: damus_state.profiles)
+ .padding(.top, -(pfp_size / 2.0))
+ .offset(y: pfpOffset())
+ .scaleEffect(pfpScale())
.onTapGesture {
is_zoomed.toggle()
}
.fullScreenCover(isPresented: $is_zoomed) {
ProfileZoomView(pubkey: profile.pubkey, profiles: damus_state.profiles) }
- .offset(y: -(pfp_size/2.0)) // Increase if set a frame
Spacer()
- ActionSection(profile_data: profile_data)
- .offset(y: -15.0) // Increase if set a frame
+ actionSection(profile_data: profile_data)
}
let follows_you = profile.follows(pubkey: damus_state.pubkey)
ProfileNameView(pubkey: profile.pubkey, profile: profile_data, follows_you: follows_you, damus: damus_state)
- //.padding(.bottom)
- .padding(.top,-(pfp_size/2.0))
}
}
- var pfp_size: CGFloat {
- return 90.0
+ var followersCount: some View {
+ HStack {
+ if followers.count == nil {
+ Image(systemName: "square.and.arrow.down")
+ Text("Followers", comment: "Label describing followers of a user.")
+ .font(.subheadline)
+ .foregroundColor(.gray)
+ } else {
+ let followerCount = followers.count!
+ Text("\(Text(String("\(followerCount)")).font(.subheadline.weight(.medium))) \(Text(String(format: NSLocalizedString("followers_count", comment: "Part of a larger sentence to describe how many people are following a user."), followerCount)).font(.subheadline).foregroundColor(.gray))", comment: "Sentence composed of 2 variables to describe how many people are following a user. In source English, the first variable is the number of followers, and the second variable is 'Follower' or 'Followers'.")
+ }
+ }
}
- var TopSection: some View {
- ZStack(alignment: .top) {
- GeometryReader { geometry in
- BannerImageView(pubkey: profile.pubkey, profiles: damus_state.profiles)
- .aspectRatio(contentMode: .fill)
- .frame(width: geometry.size.width, height: self.getHeightForHeaderImage(geometry))
- .clipped()
- .offset(x: 0, y: self.getOffsetForHeaderImage(geometry))
-
- }.frame(height: BANNER_HEIGHT)
+ var aboutSection: some View {
+ VStack(alignment: .leading, spacing: 8.0) {
+ let profile_data = damus_state.profiles.lookup(id: profile.pubkey)
- VStack(alignment: .leading, spacing: 8.0) {
- let profile_data = damus_state.profiles.lookup(id: profile.pubkey)
-
- NameSection(profile_data: profile_data)
-
- Text(ProfileView.markdown.process(profile_data?.about ?? ""))
- .font(.subheadline).textSelection(.enabled)
-
- if let url = profile_data?.website_url {
- WebsiteLink(url: url)
- }
-
- Divider()
-
- HStack {
- if let contact = profile.contacts {
- let contacts = contact.referenced_pubkeys.map { $0.ref_id }
- let following_model = FollowingModel(damus_state: damus_state, contacts: contacts)
- NavigationLink(destination: FollowingView(damus_state: damus_state, following: following_model, whos: profile.pubkey)) {
- HStack {
- Text("\(Text(String("\(profile.following)")).font(.subheadline.weight(.medium))) \(Text("Following", comment: "Part of a larger sentence to describe how many profiles a user is following.").font(.subheadline).foregroundColor(.gray))", comment: "Sentence composed of 2 variables to describe how many profiles a user is following. In source English, the first variable is the number of profiles being followed, and the second variable is 'Following'.")
- }
+ nameSection(profile_data: profile_data)
+
+ Text(ProfileView.markdown.process(profile_data?.about ?? ""))
+ .font(.subheadline).textSelection(.enabled)
+
+ if let url = profile_data?.website_url {
+ WebsiteLink(url: url)
+ }
+
+ Divider()
+
+ HStack {
+ if let contact = profile.contacts {
+ let contacts = contact.referenced_pubkeys.map { $0.ref_id }
+ let following_model = FollowingModel(damus_state: damus_state, contacts: contacts)
+ NavigationLink(destination: FollowingView(damus_state: damus_state, following: following_model, whos: profile.pubkey)) {
+ HStack {
+ Text("\(Text("\(profile.following)", comment: "Number of profiles a user is following.").font(.subheadline.weight(.medium))) \(Text("Following", comment: "Part of a larger sentence to describe how many profiles a user is following.").font(.subheadline).foregroundColor(.gray))", comment: "Sentence composed of 2 variables to describe how many profiles a user is following. In source English, the first variable is the number of profiles being followed, and the second variable is 'Following'.")
}
- .buttonStyle(PlainButtonStyle())
}
- let fview = FollowersView(damus_state: damus_state, whos: profile.pubkey)
- .environmentObject(followers)
- if followers.contacts != nil {
- NavigationLink(destination: fview) {
- FollowersCount
+ .buttonStyle(PlainButtonStyle())
+ }
+ let fview = FollowersView(damus_state: damus_state, whos: profile.pubkey)
+ .environmentObject(followers)
+ if followers.contacts != nil {
+ NavigationLink(destination: fview) {
+ followersCount
+ }
+ .buttonStyle(PlainButtonStyle())
+ } else {
+ followersCount
+ .onTapGesture {
+ UIImpactFeedbackGenerator(style: .light).impactOccurred()
+ followers.contacts = []
+ followers.subscribe()
+ }
+ }
+
+ if let relays = profile.relays {
+ // Only open relay config view if the user is logged in with private key and they are looking at their own profile.
+ let relay_text = Text("\(Text("\(relays.keys.count)", comment: "Number of relay servers a user is connected.").font(.subheadline.weight(.medium))) \(Text(String(format: NSLocalizedString("relays_count", comment: "Part of a larger sentence to describe how many relay servers a user is connected."), relays.keys.count)).font(.subheadline).foregroundColor(.gray))", comment: "Sentence composed of 2 variables to describe how many relay servers a user is connected. In source English, the first variable is the number of relay servers, and the second variable is 'Relay' or 'Relays'.")
+ if profile.pubkey == damus_state.pubkey && damus_state.is_privkey_user {
+ NavigationLink(destination: RelayConfigView(state: damus_state)) {
+ relay_text
}
.buttonStyle(PlainButtonStyle())
} else {
- FollowersCount
- .onTapGesture {
- UIImpactFeedbackGenerator(style: .light).impactOccurred()
- followers.contacts = []
- followers.subscribe()
- }
- }
-
- if let relays = profile.relays {
- // Only open relay config view if the user is logged in with private key and they are looking at their own profile.
- let relay_text = Text("\(Text(String("\(relays.keys.count)")).font(.subheadline.weight(.medium))) \(Text(String(format: NSLocalizedString("relays_count", comment: "Part of a larger sentence to describe how many relay servers a user is connected."), relays.keys.count)).font(.subheadline).foregroundColor(.gray))", comment: "Sentence composed of 2 variables to describe how many relay servers a user is connected. In source English, the first variable is the number of relay servers, and the second variable is 'Relay' or 'Relays'.")
- if profile.pubkey == damus_state.pubkey && damus_state.is_privkey_user {
- NavigationLink(destination: RelayConfigView(state: damus_state)) {
- relay_text
- }
- .buttonStyle(PlainButtonStyle())
- } else {
- NavigationLink(destination: UserRelaysView(state: damus_state, pubkey: profile.pubkey, relays: Array(relays.keys).sorted())) {
- relay_text
- }
- .buttonStyle(PlainButtonStyle())
+ NavigationLink(destination: UserRelaysView(state: damus_state, pubkey: profile.pubkey, relays: Array(relays.keys).sorted())) {
+ relay_text
}
+ .buttonStyle(PlainButtonStyle())
}
}
}
- .padding(.horizontal,18)
- //.offset(y:120)
- .padding(.top,150)
- }
- }
-
- var FollowersCount: some View {
- HStack {
- if followers.count == nil {
- Image(systemName: "square.and.arrow.down")
- Text("Followers", comment: "Label describing followers of a user.")
- .font(.subheadline)
- .foregroundColor(.gray)
- } else {
- let followerCount = followers.count!
- Text("\(Text(String("\(followerCount)")).font(.subheadline.weight(.medium))) \(Text(String(format: NSLocalizedString("followers_count", comment: "Part of a larger sentence to describe how many people are following a user."), followerCount)).font(.subheadline).foregroundColor(.gray))", comment: "Sentence composed of 2 variables to describe how many people are following a user. In source English, the first variable is the number of followers, and the second variable is 'Follower' or 'Followers'.")
- }
}
+ .padding(.horizontal)
}
var body: some View {
- VStack(alignment: .leading) {
- ScrollView {
- TopSection
-
- Divider()
+ ScrollView(.vertical) {
+ VStack(spacing: 0) {
+ bannerSection
+ .zIndex(1)
- InnerTimelineView(events: $profile.events, damus: damus_state, show_friend_icon: false, filter: { _ in true })
+ VStack() {
+ aboutSection
+
+ Divider()
+
+ InnerTimelineView(events: $profile.events, damus: damus_state, show_friend_icon: false, filter: { _ in true })
+ }
+ .padding(.horizontal, Theme.safeAreaInsets?.left)
+ .zIndex(-yOffset > navbarHeight ? 0 : 1)
}
- .frame(maxHeight: .infinity, alignment: .topLeading)
}
- .frame(maxWidth: .infinity, alignment: .topLeading)
+ .ignoresSafeArea()
+ .navigationTitle("")
+ .navigationBarHidden(true)
+ .overlay(customNavbar, alignment: .top)
.onReceive(handle_notify(.switched_timeline)) { _ in
dismiss()
}
@@ -390,7 +426,6 @@ struct ProfileView: View {
}
}
}
- .ignoresSafeArea()
}
}
@@ -403,7 +438,6 @@ struct ProfileView_Previews: PreviewProvider {
}
}
-
func test_damus_state() -> DamusState {
let pubkey = "3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681"
let damus = DamusState.empty
diff --git a/damus/Views/ProfileZoomView.swift b/damus/Views/ProfileZoomView.swift
@@ -5,84 +5,99 @@
// Created by scoder1747 on 12/27/22.
//
import SwiftUI
+import Kingfisher
-struct ProfileZoomView: View {
-
- @Environment(\.presentationMode) var presentationMode
- let pubkey: String
- let profiles: Profiles
-
- @GestureState private var scaleState: CGFloat = 1
- @GestureState private var offsetState = CGSize.zero
-
- @State private var offset = CGSize.zero
- @State private var scale: CGFloat = 1
-
- func resetStatus(){
- self.offset = CGSize.zero
- self.scale = 1
+private struct ImageContainerView: View {
+
+ @ObservedObject var imageModel: KFImageModel
+
+ @State private var image: UIImage?
+ @State private var showShareSheet = false
+
+ init(url: URL?) {
+ self.imageModel = KFImageModel(
+ url: url,
+ fallbackUrl: nil,
+ maxByteSize: 2000000, // 2 MB
+ downsampleSize: CGSize(width: 400, height: 400)
+ )
}
-
- var zoomGesture: some Gesture {
- MagnificationGesture()
- .updating($scaleState) { currentState, gestureState, _ in
- gestureState = currentState
+
+ private struct ImageHandler: ImageModifier {
+ @Binding var handler: UIImage?
+
+ func modify(_ image: UIImage) -> UIImage {
+ handler = image
+ return image
+ }
+ }
+
+ var body: some View {
+
+ KFAnimatedImage(imageModel.url)
+ .callbackQueue(.dispatch(.global(qos: .background)))
+ .processingQueue(.dispatch(.global(qos: .background)))
+ .cacheOriginalImage()
+ .configure { view in
+ view.framePreloadCount = 1
}
- .onEnded { value in
- scale *= value
+ .scaleFactor(UIScreen.main.scale)
+ .loadDiskFileSynchronously()
+ .fade(duration: 0.1)
+ .imageModifier(ImageHandler(handler: $image))
+ .onFailure { _ in
+ imageModel.downloadFailed()
}
- }
-
- var dragGesture: some Gesture {
- DragGesture()
- .updating($offsetState) { currentState, gestureState, _ in
- gestureState = currentState.translation
- }.onEnded { value in
- offset.height += value.translation.height
- offset.width += value.translation.width
+ .id(imageModel.refreshID)
+ .clipShape(Circle())
+ .modifier(ImageContextMenuModifier(url: imageModel.url, image: image, showShareSheet: $showShareSheet))
+ .sheet(isPresented: $showShareSheet) {
+ ShareSheet(activityItems: [imageModel.url])
}
}
+}
- var doubleTapGesture : some Gesture {
- TapGesture(count: 2).onEnded { value in
- resetStatus()
+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()
}
+ .padding()
}
var body: some View {
- ZStack(alignment: .topLeading) {
- Color("DamusDarkGrey") // Or Color("DamusBlack")
- .edgesIgnoringSafeArea(.all)
+ ZStack {
+ Color(.systemBackground)
+ .ignoresSafeArea()
- Button {
- presentationMode.wrappedValue.dismiss()
- } label: {
- Image(systemName: "xmark")
- .foregroundColor(.white)
- .font(.subheadline)
- .padding(.leading, 20)
- }
- .zIndex(1)
-
- VStack(alignment: .center) {
-
- 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()
-
+ 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)
}
}