Changelog-Added: Banner Image Upload
This commit is contained in:
committed by
William Casarin
parent
8a8d2ebbc3
commit
95041600dc
@@ -275,7 +275,7 @@
|
|||||||
F75BA12F29A18EF500E10810 /* BookmarksView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F75BA12E29A18EF500E10810 /* BookmarksView.swift */; };
|
F75BA12F29A18EF500E10810 /* BookmarksView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F75BA12E29A18EF500E10810 /* BookmarksView.swift */; };
|
||||||
F7908E92298B0F0700AB113A /* RelayDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7908E91298B0F0700AB113A /* RelayDetailView.swift */; };
|
F7908E92298B0F0700AB113A /* RelayDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7908E91298B0F0700AB113A /* RelayDetailView.swift */; };
|
||||||
F7908E97298B1FDF00AB113A /* NIPURLBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7908E96298B1FDF00AB113A /* NIPURLBuilder.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 */; };
|
F7F0BA25297892BD009531F3 /* SwipeToDismiss.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F0BA24297892BD009531F3 /* SwipeToDismiss.swift */; };
|
||||||
F7F0BA272978E54D009531F3 /* ParicipantsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F0BA262978E54D009531F3 /* ParicipantsView.swift */; };
|
F7F0BA272978E54D009531F3 /* ParicipantsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F0BA262978E54D009531F3 /* ParicipantsView.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
@@ -684,7 +684,7 @@
|
|||||||
F75BA12E29A18EF500E10810 /* BookmarksView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarksView.swift; sourceTree = "<group>"; };
|
F75BA12E29A18EF500E10810 /* BookmarksView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarksView.swift; sourceTree = "<group>"; };
|
||||||
F7908E91298B0F0700AB113A /* RelayDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayDetailView.swift; sourceTree = "<group>"; };
|
F7908E91298B0F0700AB113A /* RelayDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayDetailView.swift; sourceTree = "<group>"; };
|
||||||
F7908E96298B1FDF00AB113A /* NIPURLBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NIPURLBuilder.swift; sourceTree = "<group>"; };
|
F7908E96298B1FDF00AB113A /* NIPURLBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NIPURLBuilder.swift; sourceTree = "<group>"; };
|
||||||
F79C7FAC29D5E9620000F946 /* EditProfilePictureControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditProfilePictureControl.swift; sourceTree = "<group>"; };
|
F79C7FAC29D5E9620000F946 /* EditPictureControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditPictureControl.swift; sourceTree = "<group>"; };
|
||||||
F7F0BA24297892BD009531F3 /* SwipeToDismiss.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwipeToDismiss.swift; sourceTree = "<group>"; };
|
F7F0BA24297892BD009531F3 /* SwipeToDismiss.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwipeToDismiss.swift; sourceTree = "<group>"; };
|
||||||
F7F0BA262978E54D009531F3 /* ParicipantsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParicipantsView.swift; sourceTree = "<group>"; };
|
F7F0BA262978E54D009531F3 /* ParicipantsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParicipantsView.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
@@ -1049,7 +1049,7 @@
|
|||||||
children = (
|
children = (
|
||||||
4CEE2AF6280B2DEA00AB5EEF /* ProfileName.swift */,
|
4CEE2AF6280B2DEA00AB5EEF /* ProfileName.swift */,
|
||||||
4C285C892838B985008A31F1 /* ProfilePictureSelector.swift */,
|
4C285C892838B985008A31F1 /* ProfilePictureSelector.swift */,
|
||||||
F79C7FAC29D5E9620000F946 /* EditProfilePictureControl.swift */,
|
F79C7FAC29D5E9620000F946 /* EditPictureControl.swift */,
|
||||||
4CEE2AF2280B25C500AB5EEF /* ProfilePicView.swift */,
|
4CEE2AF2280B25C500AB5EEF /* ProfilePicView.swift */,
|
||||||
4C8682862814DE470026224F /* ProfileView.swift */,
|
4C8682862814DE470026224F /* ProfileView.swift */,
|
||||||
4CB9D4A62992D02B00A9A7E4 /* ProfileNameView.swift */,
|
4CB9D4A62992D02B00A9A7E4 /* ProfileNameView.swift */,
|
||||||
@@ -1619,7 +1619,7 @@
|
|||||||
4CE0E2B629A3ED5500DB4CA2 /* InnerTimelineView.swift in Sources */,
|
4CE0E2B629A3ED5500DB4CA2 /* InnerTimelineView.swift in Sources */,
|
||||||
4C363A8828236948006E126D /* BlocksView.swift in Sources */,
|
4C363A8828236948006E126D /* BlocksView.swift in Sources */,
|
||||||
4C06670628FCB08600038D2A /* ImageCarousel.swift in Sources */,
|
4C06670628FCB08600038D2A /* ImageCarousel.swift in Sources */,
|
||||||
F79C7FAD29D5E9620000F946 /* EditProfilePictureControl.swift in Sources */,
|
F79C7FAD29D5E9620000F946 /* EditPictureControl.swift in Sources */,
|
||||||
4C9F18E229AA9B6C008C55EC /* CustomizeZapView.swift in Sources */,
|
4C9F18E229AA9B6C008C55EC /* CustomizeZapView.swift in Sources */,
|
||||||
4C75EFAF28049D350006080F /* NostrFilter.swift in Sources */,
|
4C75EFAF28049D350006080F /* NostrFilter.swift in Sources */,
|
||||||
4C3EA64C28FF59AC00C48A62 /* bech32_util.c in Sources */,
|
4C3EA64C28FF59AC00C48A62 /* bech32_util.c in Sources */,
|
||||||
|
|||||||
@@ -91,8 +91,8 @@ extension _AnyEncodable {
|
|||||||
try encode(nsnumber: number, into: &container)
|
try encode(nsnumber: number, into: &container)
|
||||||
case let date as Date:
|
case let date as Date:
|
||||||
try container.encode(date)
|
try container.encode(date)
|
||||||
case let url as URL:
|
case let profile_url as URL:
|
||||||
try container.encode(url)
|
try container.encode(profile_url)
|
||||||
#endif
|
#endif
|
||||||
case let array as [Any?]:
|
case let array as [Any?]:
|
||||||
try container.encode(array.map { AnyEncodable($0) })
|
try container.encode(array.map { AnyEncodable($0) })
|
||||||
|
|||||||
@@ -8,6 +8,33 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import Kingfisher
|
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)
|
||||||
|
.configure { view in
|
||||||
|
view.framePreloadCount = 3
|
||||||
|
}
|
||||||
|
.placeholder { _ in
|
||||||
|
Color(uiColor: .secondarySystemBackground)
|
||||||
|
}
|
||||||
|
.onFailureImage(defaultImage)
|
||||||
|
|
||||||
|
EditPictureControl(pubkey: damus_state.pubkey, image_url: $banner_image, uploadObserver: viewModel, callback: callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct InnerBannerImageView: View {
|
struct InnerBannerImageView: View {
|
||||||
|
|
||||||
let url: URL?
|
let url: URL?
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import SwiftUI
|
|||||||
|
|
||||||
struct CreateAccountView: View {
|
struct CreateAccountView: View {
|
||||||
@StateObject var account: CreateAccountModel = CreateAccountModel()
|
@StateObject var account: CreateAccountModel = CreateAccountModel()
|
||||||
@StateObject var profileUploadViewModel = ProfileUploadingViewModel()
|
@StateObject var profileUploadObserver = ImageUploadingObserver()
|
||||||
|
|
||||||
@State var is_light: Bool = false
|
@State var is_light: Bool = false
|
||||||
@State var is_done: Bool = false
|
@State var is_done: Bool = false
|
||||||
@@ -35,7 +35,7 @@ struct CreateAccountView: View {
|
|||||||
.font(.title.bold())
|
.font(.title.bold())
|
||||||
.foregroundColor(.white)
|
.foregroundColor(.white)
|
||||||
|
|
||||||
ProfilePictureSelector(pubkey: account.pubkey, viewModel: profileUploadViewModel, callback: uploadedProfilePicture(image_url:))
|
EditProfilePictureView(pubkey: account.pubkey, uploadObserver: profileUploadObserver, callback: uploadedProfilePicture(image_url:))
|
||||||
|
|
||||||
HStack(alignment: .top) {
|
HStack(alignment: .top) {
|
||||||
VStack {
|
VStack {
|
||||||
@@ -84,8 +84,8 @@ struct CreateAccountView: View {
|
|||||||
self.is_done = true
|
self.is_done = true
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
.disabled(profileUploadViewModel.isLoading)
|
.disabled(profileUploadObserver.isLoading)
|
||||||
.opacity(profileUploadViewModel.isLoading ? 0.5 : 1)
|
.opacity(profileUploadObserver.isLoading ? 0.5 : 1)
|
||||||
}
|
}
|
||||||
.padding(.leading, 14.0)
|
.padding(.leading, 14.0)
|
||||||
.padding(.trailing, 20.0)
|
.padding(.trailing, 20.0)
|
||||||
|
|||||||
@@ -68,7 +68,9 @@ struct EditMetadataView: View {
|
|||||||
@Environment(\.colorScheme) var colorScheme
|
@Environment(\.colorScheme) var colorScheme
|
||||||
|
|
||||||
@State var confirm_ln_address: Bool = false
|
@State var confirm_ln_address: Bool = false
|
||||||
@StateObject var profileUploadViewModel = ProfileUploadingViewModel()
|
|
||||||
|
@StateObject var profileUploadObserver = ImageUploadingObserver()
|
||||||
|
@StateObject var bannerUploadObserver = ImageUploadingObserver()
|
||||||
|
|
||||||
init (damus_state: DamusState) {
|
init (damus_state: DamusState) {
|
||||||
self.damus_state = damus_state
|
self.damus_state = damus_state
|
||||||
@@ -119,7 +121,7 @@ struct EditMetadataView: View {
|
|||||||
var TopSection: some View {
|
var TopSection: some View {
|
||||||
ZStack(alignment: .top) {
|
ZStack(alignment: .top) {
|
||||||
GeometryReader { geo in
|
GeometryReader { geo in
|
||||||
BannerImageView(pubkey: damus_state.pubkey, profiles: damus_state.profiles)
|
EditBannerImageView(damus_state: damus_state, viewModel: bannerUploadObserver, callback: uploadedBanner(image_url:))
|
||||||
.aspectRatio(contentMode: .fill)
|
.aspectRatio(contentMode: .fill)
|
||||||
.frame(width: geo.size.width, height: BANNER_HEIGHT)
|
.frame(width: geo.size.width, height: BANNER_HEIGHT)
|
||||||
.clipped()
|
.clipped()
|
||||||
@@ -128,7 +130,7 @@ struct EditMetadataView: View {
|
|||||||
let pfp_size: CGFloat = 90.0
|
let pfp_size: CGFloat = 90.0
|
||||||
|
|
||||||
HStack(alignment: .center) {
|
HStack(alignment: .center) {
|
||||||
ProfilePictureSelector(pubkey: damus_state.pubkey, damus_state: damus_state, viewModel: profileUploadViewModel, callback: uploadedProfilePicture(image_url:))
|
EditProfilePictureView(pubkey: damus_state.pubkey, damus_state: damus_state, size: pfp_size, uploadObserver: profileUploadObserver, callback: uploadedProfilePicture(image_url:))
|
||||||
.offset(y: -(pfp_size/2.0)) // Increase if set a frame
|
.offset(y: -(pfp_size/2.0)) // Increase if set a frame
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
@@ -221,7 +223,7 @@ struct EditMetadataView: View {
|
|||||||
dismiss()
|
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) {
|
.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.")) {
|
Button(NSLocalizedString("Ok", comment: "Button to dismiss the alert.")) {
|
||||||
}
|
}
|
||||||
@@ -237,6 +239,10 @@ struct EditMetadataView: View {
|
|||||||
func uploadedProfilePicture(image_url: URL?) {
|
func uploadedProfilePicture(image_url: URL?) {
|
||||||
picture = image_url?.absoluteString ?? ""
|
picture = image_url?.absoluteString ?? ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func uploadedBanner(image_url: URL?) {
|
||||||
|
banner = image_url?.absoluteString ?? ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EditMetadataView_Previews: PreviewProvider {
|
struct EditMetadataView_Previews: PreviewProvider {
|
||||||
|
|||||||
@@ -47,11 +47,13 @@ struct ImagePicker: UIViewControllerRepresentable {
|
|||||||
// Handle the selected image
|
// Handle the selected image
|
||||||
onImagePicked(imageURL)
|
onImagePicked(imageURL)
|
||||||
} else if let cameraImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
|
} else if let cameraImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
|
||||||
if let imageURL = saveImageToTemporaryFolder(image: cameraImage, imageType: "jpeg") {
|
let orientedImage = cameraImage.fixOrientation()
|
||||||
|
if let imageURL = saveImageToTemporaryFolder(image: orientedImage, imageType: "jpeg") {
|
||||||
onImagePicked(imageURL)
|
onImagePicked(imageURL)
|
||||||
}
|
}
|
||||||
} else if let editedImage = info[UIImagePickerController.InfoKey.editedImage] as? UIImage {
|
} else if let editedImage = info[UIImagePickerController.InfoKey.editedImage] as? UIImage {
|
||||||
if let editedImageURL = saveImageToTemporaryFolder(image: editedImage) {
|
let orientedImage = editedImage.fixOrientation()
|
||||||
|
if let editedImageURL = saveImageToTemporaryFolder(image: orientedImage, imageType: "jpeg") {
|
||||||
onImagePicked(editedImageURL)
|
onImagePicked(editedImageURL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,3 +124,16 @@ struct ImagePicker: UIViewControllerRepresentable {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension UIImage {
|
||||||
|
func fixOrientation() -> UIImage {
|
||||||
|
guard imageOrientation != .up else { return self }
|
||||||
|
|
||||||
|
UIGraphicsBeginImageContextWithOptions(size, false, scale)
|
||||||
|
draw(in: CGRect(origin: .zero, size: size))
|
||||||
|
let normalizedImage = UIGraphicsGetImageFromCurrentImageContext()
|
||||||
|
UIGraphicsEndImageContext()
|
||||||
|
|
||||||
|
return normalizedImage ?? self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// ProfilePictureEditView.swift
|
// EditPictureControl.swift
|
||||||
// damus
|
// damus
|
||||||
//
|
//
|
||||||
// Created by Joel Klabo on 3/30/23.
|
// Created by Joel Klabo on 3/30/23.
|
||||||
@@ -7,11 +7,15 @@
|
|||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct EditProfilePictureControl: View {
|
class ImageUploadingObserver: ObservableObject {
|
||||||
|
@Published var isLoading: Bool = false
|
||||||
|
}
|
||||||
|
|
||||||
|
struct EditPictureControl: View {
|
||||||
|
|
||||||
let pubkey: String
|
let pubkey: String
|
||||||
@Binding var profile_image: URL?
|
@Binding var image_url: URL?
|
||||||
@ObservedObject var viewModel: ProfileUploadingViewModel
|
@ObservedObject var uploadObserver: ImageUploadingObserver
|
||||||
let callback: (URL?) -> Void
|
let callback: (URL?) -> Void
|
||||||
|
|
||||||
@StateObject var image_upload: ImageUploadModel = ImageUploadModel()
|
@StateObject var image_upload: ImageUploadModel = ImageUploadModel()
|
||||||
@@ -34,14 +38,23 @@ struct EditProfilePictureControl: View {
|
|||||||
Text("Take Photo", comment: "Option to take a photo with the camera")
|
Text("Take Photo", comment: "Option to take a photo with the camera")
|
||||||
}
|
}
|
||||||
} label: {
|
} label: {
|
||||||
if viewModel.isLoading {
|
if uploadObserver.isLoading {
|
||||||
ProgressView()
|
ProgressView()
|
||||||
|
.progressViewStyle(CircularProgressViewStyle(tint: DamusColors.purple))
|
||||||
|
.padding(10)
|
||||||
|
.background(DamusColors.white.opacity(0.7))
|
||||||
|
.clipShape(Circle())
|
||||||
|
.shadow(color: DamusColors.purple, radius: 15, x: 0, y: 0)
|
||||||
} else {
|
} else {
|
||||||
Image(systemName: "camera")
|
Image(systemName: "camera")
|
||||||
.resizable()
|
.resizable()
|
||||||
.scaledToFit()
|
.scaledToFit()
|
||||||
.frame(width: 25, height: 25)
|
.frame(width: 25, height: 25)
|
||||||
.foregroundColor(DamusColors.white)
|
.foregroundColor(DamusColors.purple)
|
||||||
|
.padding(10)
|
||||||
|
.background(DamusColors.white.opacity(0.7))
|
||||||
|
.clipShape(Circle())
|
||||||
|
.shadow(color: DamusColors.purple, radius: 15, x: 0, y: 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.sheet(isPresented: $show_camera) {
|
.sheet(isPresented: $show_camera) {
|
||||||
@@ -63,7 +76,7 @@ struct EditProfilePictureControl: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func handle_upload(media: MediaUpload) {
|
private func handle_upload(media: MediaUpload) {
|
||||||
viewModel.isLoading = true
|
uploadObserver.isLoading = true
|
||||||
let uploader = get_media_uploader(pubkey)
|
let uploader = get_media_uploader(pubkey)
|
||||||
Task {
|
Task {
|
||||||
let res = await image_upload.start(media: media, uploader: uploader)
|
let res = await image_upload.start(media: media, uploader: uploader)
|
||||||
@@ -71,7 +84,7 @@ struct EditProfilePictureControl: View {
|
|||||||
switch res {
|
switch res {
|
||||||
case .success(let urlString):
|
case .success(let urlString):
|
||||||
let url = URL(string: urlString)
|
let url = URL(string: urlString)
|
||||||
profile_image = url
|
image_url = url
|
||||||
callback(url)
|
callback(url)
|
||||||
case .failed(let error):
|
case .failed(let error):
|
||||||
if let error {
|
if let error {
|
||||||
@@ -81,7 +94,21 @@ struct EditProfilePictureControl: View {
|
|||||||
}
|
}
|
||||||
callback(nil)
|
callback(nil)
|
||||||
}
|
}
|
||||||
viewModel.isLoading = false
|
uploadObserver.isLoading = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct EditPictureControl_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
let pubkey = "123"
|
||||||
|
let url = Binding<URL?>.constant(URL(string: "https://damus.io")!)
|
||||||
|
let observer = ImageUploadingObserver()
|
||||||
|
ZStack {
|
||||||
|
Color.gray
|
||||||
|
EditPictureControl(pubkey: pubkey, image_url: url, uploadObserver: observer) { _ in
|
||||||
|
//
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -32,60 +32,6 @@ func pfp_line_width(_ h: Highlight) -> CGFloat {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EditProfilePictureView: View {
|
|
||||||
|
|
||||||
@Binding var url: URL?
|
|
||||||
|
|
||||||
let pubkey: String
|
|
||||||
let size: CGFloat
|
|
||||||
let highlight: Highlight
|
|
||||||
|
|
||||||
var damus_state: DamusState?
|
|
||||||
|
|
||||||
var PlaceholderColor: Color {
|
|
||||||
return id_to_color(pubkey)
|
|
||||||
}
|
|
||||||
|
|
||||||
var Placeholder: some View {
|
|
||||||
PlaceholderColor
|
|
||||||
.frame(width: size, height: size)
|
|
||||||
.clipShape(Circle())
|
|
||||||
.overlay(Circle().stroke(highlight_color(highlight), lineWidth: pfp_line_width(highlight)))
|
|
||||||
.padding(2)
|
|
||||||
}
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
ZStack {
|
|
||||||
Color(uiColor: .systemBackground)
|
|
||||||
|
|
||||||
KFAnimatedImage(get_profile_url())
|
|
||||||
.imageContext(.pfp)
|
|
||||||
.cancelOnDisappear(true)
|
|
||||||
.configure { view in
|
|
||||||
view.framePreloadCount = 3
|
|
||||||
}
|
|
||||||
.placeholder { _ in
|
|
||||||
Placeholder
|
|
||||||
}
|
|
||||||
.scaledToFill()
|
|
||||||
.opacity(0.5)
|
|
||||||
}
|
|
||||||
.frame(width: size, height: size)
|
|
||||||
.clipShape(Circle())
|
|
||||||
.overlay(Circle().stroke(highlight_color(highlight), lineWidth: pfp_line_width(highlight)))
|
|
||||||
}
|
|
||||||
|
|
||||||
private func get_profile_url() -> URL? {
|
|
||||||
if let url {
|
|
||||||
return url
|
|
||||||
} else if let state = damus_state, let picture = state.profiles.lookup(id: pubkey)?.picture {
|
|
||||||
return URL(string: picture)
|
|
||||||
} else {
|
|
||||||
return url ?? URL(string: robohash(pubkey))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct InnerProfilePicView: View {
|
struct InnerProfilePicView: View {
|
||||||
|
|
||||||
let url: URL?
|
let url: URL?
|
||||||
|
|||||||
@@ -1,33 +1,66 @@
|
|||||||
//
|
//
|
||||||
// ProfilePictureSelector.swift
|
// EditProfilePictureView.swift
|
||||||
// damus
|
// damus
|
||||||
//
|
//
|
||||||
// Created by William Casarin on 2022-05-20.
|
// Created by William Casarin on 2022-05-20.
|
||||||
//
|
//
|
||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
import Kingfisher
|
||||||
import Combine
|
import Combine
|
||||||
|
|
||||||
class ProfileUploadingViewModel: ObservableObject {
|
struct EditProfilePictureView: View {
|
||||||
@Published var isLoading: Bool = false
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ProfilePictureSelector: View {
|
@State var profile_url: URL?
|
||||||
|
|
||||||
let pubkey: String
|
let pubkey: String
|
||||||
var size: CGFloat = 80.0
|
|
||||||
var damus_state: DamusState?
|
var damus_state: DamusState?
|
||||||
@ObservedObject var viewModel: ProfileUploadingViewModel
|
var size: CGFloat = 80.0
|
||||||
|
let highlight: Highlight = .custom(Color.white, 2.0)
|
||||||
|
@ObservedObject var uploadObserver: ImageUploadingObserver
|
||||||
let callback: (URL?) -> Void
|
let callback: (URL?) -> Void
|
||||||
|
|
||||||
@State var profile_image: URL? = nil
|
var PlaceholderColor: Color {
|
||||||
|
return id_to_color(pubkey)
|
||||||
|
}
|
||||||
|
|
||||||
|
var Placeholder: some View {
|
||||||
|
PlaceholderColor
|
||||||
|
.frame(width: size, height: size)
|
||||||
|
.clipShape(Circle())
|
||||||
|
.overlay(Circle().stroke(highlight_color(highlight), lineWidth: pfp_line_width(highlight)))
|
||||||
|
.padding(2)
|
||||||
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
let highlight: Highlight = .custom(Color.white, 2.0)
|
|
||||||
ZStack {
|
ZStack {
|
||||||
EditProfilePictureView(url: $profile_image, pubkey: pubkey, size: size, highlight: highlight, damus_state: damus_state)
|
Color(uiColor: .systemBackground)
|
||||||
EditProfilePictureControl(pubkey: pubkey, profile_image: $profile_image, viewModel: viewModel, callback: callback)
|
|
||||||
|
KFAnimatedImage(get_profile_url())
|
||||||
|
.imageContext(.pfp)
|
||||||
|
.cancelOnDisappear(true)
|
||||||
|
.configure { view in
|
||||||
|
view.framePreloadCount = 3
|
||||||
|
}
|
||||||
|
.placeholder { _ in
|
||||||
|
Placeholder
|
||||||
|
}
|
||||||
|
.scaledToFill()
|
||||||
|
|
||||||
|
EditPictureControl(pubkey: pubkey, image_url: $profile_url, uploadObserver: uploadObserver, callback: callback)
|
||||||
|
}
|
||||||
|
.frame(width: size, height: size)
|
||||||
|
.clipShape(Circle())
|
||||||
|
.overlay(Circle().stroke(highlight_color(highlight), lineWidth: pfp_line_width(highlight)))
|
||||||
|
}
|
||||||
|
|
||||||
|
private func get_profile_url() -> URL? {
|
||||||
|
if let profile_url {
|
||||||
|
return profile_url
|
||||||
|
} else if let state = damus_state, let picture = state.profiles.lookup(id: pubkey)?.picture {
|
||||||
|
return URL(string: picture)
|
||||||
|
} else {
|
||||||
|
return profile_url ?? URL(string: robohash(pubkey))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -35,7 +68,7 @@ struct ProfilePictureSelector: View {
|
|||||||
struct ProfilePictureSelector_Previews: PreviewProvider {
|
struct ProfilePictureSelector_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
let test_pubkey = "ff48854ac6555fed8e439ebb4fa2d928410e0eef13fa41164ec45aaaa132d846"
|
let test_pubkey = "ff48854ac6555fed8e439ebb4fa2d928410e0eef13fa41164ec45aaaa132d846"
|
||||||
ProfilePictureSelector(pubkey: test_pubkey, viewModel: ProfileUploadingViewModel()) { _ in
|
EditProfilePictureView(pubkey: test_pubkey, uploadObserver: ImageUploadingObserver()) { _ in
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user