diff --git a/damus.xcodeproj/project.pbxproj b/damus.xcodeproj/project.pbxproj index 4a923257..10c89777 100644 --- a/damus.xcodeproj/project.pbxproj +++ b/damus.xcodeproj/project.pbxproj @@ -329,7 +329,7 @@ F75BA12F29A18EF500E10810 /* BookmarksView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F75BA12E29A18EF500E10810 /* BookmarksView.swift */; }; F7908E92298B0F0700AB113A /* RelayDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7908E91298B0F0700AB113A /* RelayDetailView.swift */; }; F7908E97298B1FDF00AB113A /* NIPURLBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7908E96298B1FDF00AB113A /* NIPURLBuilder.swift */; }; - F79C7FAD29D5E9620000F946 /* EditProfilePictureControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = F79C7FAC29D5E9620000F946 /* EditProfilePictureControl.swift */; }; + F79C7FAD29D5E9620000F946 /* EditPictureControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = F79C7FAC29D5E9620000F946 /* EditPictureControl.swift */; }; F7F0BA25297892BD009531F3 /* SwipeToDismiss.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F0BA24297892BD009531F3 /* SwipeToDismiss.swift */; }; F7F0BA272978E54D009531F3 /* ParticipantsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F0BA262978E54D009531F3 /* ParticipantsView.swift */; }; F944F56E29EA9CCC0067B3BF /* DamusParseContentTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F944F56D29EA9CCC0067B3BF /* DamusParseContentTests.swift */; }; @@ -804,7 +804,7 @@ F75BA12E29A18EF500E10810 /* BookmarksView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarksView.swift; sourceTree = ""; }; F7908E91298B0F0700AB113A /* RelayDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayDetailView.swift; sourceTree = ""; }; F7908E96298B1FDF00AB113A /* NIPURLBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NIPURLBuilder.swift; sourceTree = ""; }; - F79C7FAC29D5E9620000F946 /* EditProfilePictureControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditProfilePictureControl.swift; sourceTree = ""; }; + F79C7FAC29D5E9620000F946 /* EditPictureControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditPictureControl.swift; sourceTree = ""; }; F7F0BA24297892BD009531F3 /* SwipeToDismiss.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwipeToDismiss.swift; sourceTree = ""; }; F7F0BA262978E54D009531F3 /* ParticipantsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParticipantsView.swift; sourceTree = ""; }; F944F56D29EA9CCC0067B3BF /* DamusParseContentTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusParseContentTests.swift; sourceTree = ""; }; @@ -1312,6 +1312,7 @@ 4C285C892838B985008A31F1 /* ProfilePictureSelector.swift */, F79C7FAC29D5E9620000F946 /* EditProfilePictureControl.swift */, E990020E2955F837003BBC5A /* EditMetadataView.swift */, + F79C7FAC29D5E9620000F946 /* EditPictureControl.swift */, 4CEE2AF2280B25C500AB5EEF /* ProfilePicView.swift */, 4C8682862814DE470026224F /* ProfileView.swift */, 4CB9D4A62992D02B00A9A7E4 /* ProfileNameView.swift */, @@ -1930,6 +1931,7 @@ 3A23838E2A297DD200E5AA2E /* ZapButtonModel.swift in Sources */, 5053ACA72A56DF3B00851AE3 /* DeveloperSettingsView.swift in Sources */, F79C7FAD29D5E9620000F946 /* EditProfilePictureControl.swift in Sources */, + F79C7FAD29D5E9620000F946 /* EditPictureControl.swift in Sources */, 4C9F18E229AA9B6C008C55EC /* CustomizeZapView.swift in Sources */, 4C2859602A12A2BE004746F7 /* SupporterBadge.swift in Sources */, 4C1A9A2A29DDF54400516EAC /* DamusVideoPlayer.swift in Sources */, diff --git a/damus/Views/BannerImageView.swift b/damus/Views/BannerImageView.swift index d4d720ed..f3a0754b 100644 --- a/damus/Views/BannerImageView.swift +++ b/damus/Views/BannerImageView.swift @@ -8,6 +8,33 @@ import SwiftUI import Kingfisher +struct EditBannerImageView: View { + + var damus_state: DamusState + @ObservedObject var viewModel: ImageUploadingObserver + let callback: (URL?) -> Void + let defaultImage = UIImage(named: "profile-banner") ?? UIImage() + + @State var banner_image: URL? = nil + + var body: some View { + ZStack { + Color(uiColor: .systemBackground) + KFAnimatedImage(get_banner_url(banner: banner_image?.absoluteString, pubkey: damus_state.pubkey, profiles: damus_state.profiles)) + .imageContext(.banner, disable_animation: damus_state.settings.disable_animation) + .configure { view in + view.framePreloadCount = 3 + } + .placeholder { _ in + Color(uiColor: .secondarySystemBackground) + } + .onFailureImage(defaultImage) + + EditPictureControl(uploader: damus_state.settings.default_media_uploader, pubkey: damus_state.pubkey, image_url: $banner_image, uploadObserver: viewModel, callback: callback) + } + } +} + struct InnerBannerImageView: View { let disable_animation: Bool let url: URL? diff --git a/damus/Views/Profile/EditMetadataView.swift b/damus/Views/Profile/EditMetadataView.swift index ebad598d..4deb8515 100644 --- a/damus/Views/Profile/EditMetadataView.swift +++ b/damus/Views/Profile/EditMetadataView.swift @@ -25,7 +25,9 @@ struct EditMetadataView: View { @Environment(\.dismiss) var dismiss @State var confirm_ln_address: Bool = false - @StateObject var profileUploadViewModel = ProfileUploadingViewModel() + + @StateObject var profileUploadObserver = ImageUploadingObserver() + @StateObject var bannerUploadObserver = ImageUploadingObserver() init (damus_state: DamusState) { self.damus_state = damus_state @@ -78,7 +80,7 @@ struct EditMetadataView: View { var TopSection: some View { ZStack(alignment: .top) { GeometryReader { geo in - BannerImageView(pubkey: damus_state.pubkey, profiles: damus_state.profiles, disable_animation: damus_state.settings.disable_animation) + EditBannerImageView(damus_state: damus_state, viewModel: bannerUploadObserver, callback: uploadedBanner(image_url:)) .aspectRatio(contentMode: .fill) .frame(width: geo.size.width, height: BANNER_HEIGHT) .clipped() @@ -87,7 +89,7 @@ struct EditMetadataView: View { let pfp_size: CGFloat = 90.0 HStack(alignment: .center) { - ProfilePictureSelector(pubkey: damus_state.pubkey, damus_state: damus_state, viewModel: profileUploadViewModel, callback: uploadedProfilePicture(image_url:)) + ProfilePictureSelector(pubkey: damus_state.pubkey, damus_state: damus_state, uploadObserver: profileUploadObserver, callback: uploadedProfilePicture(image_url:)) .offset(y: -(pfp_size/2.0)) // Increase if set a frame Spacer() @@ -182,7 +184,7 @@ struct EditMetadataView: View { dismiss() } } - .disabled(profileUploadViewModel.isLoading) + .disabled(profileUploadObserver.isLoading || bannerUploadObserver.isLoading) .alert(NSLocalizedString("Invalid Tip Address", comment: "Title of alerting as invalid tip address."), isPresented: $confirm_ln_address) { Button(NSLocalizedString("Ok", comment: "Button to dismiss the alert.")) { } @@ -198,6 +200,10 @@ struct EditMetadataView: View { func uploadedProfilePicture(image_url: URL?) { picture = image_url?.absoluteString ?? "" } + + func uploadedBanner(image_url: URL?) { + banner = image_url?.absoluteString ?? "" + } } struct EditMetadataView_Previews: PreviewProvider { diff --git a/damus/Views/Profile/EditProfilePictureControl.swift b/damus/Views/Profile/EditPictureControl.swift similarity index 92% rename from damus/Views/Profile/EditProfilePictureControl.swift rename to damus/Views/Profile/EditPictureControl.swift index 8aa6e4b0..22f199bb 100644 --- a/damus/Views/Profile/EditProfilePictureControl.swift +++ b/damus/Views/Profile/EditPictureControl.swift @@ -1,5 +1,5 @@ // -// ProfilePictureEditView.swift +// EditPictureControl.swift // damus // // Created by Joel Klabo on 3/30/23. @@ -7,11 +7,11 @@ import SwiftUI -struct EditProfilePictureControl: View { +struct EditPictureControl: View { let uploader: MediaUploader let pubkey: String - @Binding var profile_image: URL? - @ObservedObject var viewModel: ProfileUploadingViewModel + @Binding var image_url: URL? + @ObservedObject var uploadObserver: ImageUploadingObserver let callback: (URL?) -> Void @StateObject var image_upload: ImageUploadModel = ImageUploadModel() @@ -36,7 +36,7 @@ struct EditProfilePictureControl: View { Text("Take Photo", comment: "Option to take a photo with the camera") } } label: { - if viewModel.isLoading { + if uploadObserver.isLoading { ProgressView() } else { Image("camera") @@ -83,14 +83,14 @@ struct EditProfilePictureControl: View { } private func handle_upload(media: MediaUpload) { - viewModel.isLoading = true + uploadObserver.isLoading = true Task { let res = await image_upload.start(media: media, uploader: uploader) switch res { case .success(let urlString): let url = URL(string: urlString) - profile_image = url + image_url = url callback(url) case .failed(let error): if let error { @@ -100,7 +100,7 @@ struct EditProfilePictureControl: View { } callback(nil) } - viewModel.isLoading = false + uploadObserver.isLoading = false } } } diff --git a/damus/Views/Profile/ProfilePictureSelector.swift b/damus/Views/Profile/ProfilePictureSelector.swift index 6455710e..8aa2d853 100644 --- a/damus/Views/Profile/ProfilePictureSelector.swift +++ b/damus/Views/Profile/ProfilePictureSelector.swift @@ -9,7 +9,7 @@ import SwiftUI import Combine -class ProfileUploadingViewModel: ObservableObject { +class ImageUploadingObserver: ObservableObject { @Published var isLoading: Bool = false } @@ -18,7 +18,7 @@ struct ProfilePictureSelector: View { let pubkey: String var size: CGFloat = 80.0 var damus_state: DamusState? - @ObservedObject var viewModel: ProfileUploadingViewModel + @ObservedObject var uploadObserver: ImageUploadingObserver let callback: (URL?) -> Void @State var profile_image: URL? = nil @@ -31,7 +31,7 @@ struct ProfilePictureSelector: View { let highlight: Highlight = .custom(Color.white, 2.0) ZStack { EditProfilePictureView(url: $profile_image, pubkey: pubkey, size: size, highlight: highlight, damus_state: damus_state) - EditProfilePictureControl(uploader: uploader, pubkey: pubkey, profile_image: $profile_image, viewModel: viewModel, callback: callback) + EditPictureControl(pubkey: pubkey, image_url: $profile_image, uploadObserver: uploadObserver, callback: callback) } } } @@ -39,7 +39,7 @@ struct ProfilePictureSelector: View { struct ProfilePictureSelector_Previews: PreviewProvider { static var previews: some View { let test_pubkey = "ff48854ac6555fed8e439ebb4fa2d928410e0eef13fa41164ec45aaaa132d846" - ProfilePictureSelector(pubkey: test_pubkey, viewModel: ProfileUploadingViewModel()) { _ in + ProfilePictureSelector(pubkey: test_pubkey, uploadObserver: ImageUploadingObserver()) { _ in // } }