BannerImageView.swift (4554B)
1 // 2 // BannerImageView.swift 3 // damus 4 // 5 // Created by Jason Jōb on 2023-01-10. 6 // 7 8 import SwiftUI 9 import Kingfisher 10 11 struct EditBannerImageView: View { 12 13 var damus_state: DamusState 14 @ObservedObject var viewModel: ImageUploadingObserver 15 let callback: (URL?) -> Void 16 let defaultImage = UIImage(named: "damoose") ?? UIImage() 17 let safeAreaInsets: EdgeInsets 18 19 @State var banner_image: URL? = nil 20 21 var body: some View { 22 ZStack { 23 Color(uiColor: .systemBackground) 24 KFAnimatedImage(get_banner_url(banner: banner_image?.absoluteString, pubkey: damus_state.pubkey, profiles: damus_state.profiles)) 25 .imageContext(.banner, disable_animation: damus_state.settings.disable_animation) 26 .configure { view in 27 view.framePreloadCount = .max 28 } 29 .placeholder { _ in 30 Color(uiColor: .secondarySystemBackground) 31 } 32 .onFailureImage(defaultImage) 33 .kfClickable() 34 35 EditPictureControl( 36 uploader: damus_state.settings.default_media_uploader, 37 context: .normal, 38 keypair: damus_state.keypair, 39 pubkey: damus_state.pubkey, 40 current_image_url: $banner_image, 41 upload_observer: viewModel, 42 callback: callback 43 ) 44 .padding(10) 45 .backwardsCompatibleSafeAreaPadding(self.safeAreaInsets) 46 .accessibilityLabel(NSLocalizedString("Edit banner image", comment: "Accessibility label for edit banner image button")) 47 .accessibilityIdentifier(AppAccessibilityIdentifiers.own_profile_banner_image_edit_button.rawValue) 48 } 49 } 50 } 51 52 extension View { 53 fileprivate func backwardsCompatibleSafeAreaPadding(_ insets: EdgeInsets) -> some View { 54 if #available(iOS 17.0, *) { 55 return self.safeAreaPadding(insets) 56 } else { 57 return self.padding(.top, insets.top) 58 } 59 } 60 } 61 62 struct InnerBannerImageView: View { 63 let disable_animation: Bool 64 let url: URL? 65 let defaultImage = UIImage(named: "damoose") ?? UIImage() 66 67 var body: some View { 68 ZStack { 69 Color(uiColor: .systemBackground) 70 71 if (url != nil) { 72 KFAnimatedImage(url) 73 .imageContext(.banner, disable_animation: disable_animation) 74 .configure { view in 75 view.framePreloadCount = 3 76 } 77 .placeholder { _ in 78 Color(uiColor: .secondarySystemBackground) 79 } 80 .onFailureImage(defaultImage) 81 .kfClickable() 82 } else { 83 Image(uiImage: defaultImage).resizable() 84 } 85 } 86 } 87 } 88 89 struct BannerImageView: View { 90 let disable_animation: Bool 91 let pubkey: Pubkey 92 let profiles: Profiles 93 94 @State var banner: String? 95 96 init(pubkey: Pubkey, profiles: Profiles, disable_animation: Bool, banner: String? = nil) { 97 self.pubkey = pubkey 98 self.profiles = profiles 99 self._banner = State(initialValue: banner) 100 self.disable_animation = disable_animation 101 } 102 103 var body: some View { 104 InnerBannerImageView(disable_animation: disable_animation, url: get_banner_url(banner: banner, pubkey: pubkey, profiles: profiles)) 105 .onReceive(handle_notify(.profile_updated)) { updated in 106 guard updated.pubkey == self.pubkey, 107 let profile_txn = profiles.lookup(id: updated.pubkey) 108 else { 109 return 110 } 111 112 let profile = profile_txn.unsafeUnownedValue 113 if let bannerImage = profile?.banner, bannerImage != self.banner { 114 self.banner = bannerImage 115 } 116 } 117 } 118 } 119 120 func get_banner_url(banner: String?, pubkey: Pubkey, profiles: Profiles) -> URL? { 121 let bannerUrlString = banner ?? profiles.lookup(id: pubkey)?.map({ p in p?.banner }).value ?? "" 122 if let url = URL(string: bannerUrlString) { 123 return url 124 } 125 return nil 126 } 127 128 struct BannerImageView_Previews: PreviewProvider { 129 static var previews: some View { 130 BannerImageView( 131 pubkey: test_pubkey, 132 profiles: make_preview_profiles(test_pubkey), 133 disable_animation: false 134 ) 135 } 136 } 137