Browse Source

Profile Editor

Changelog-Added: Added profile edit view
Changelog-Changed: Don't fetch followers right away
post-button-style
William Casarin 2 years ago
parent
commit
79f4223977
  1. 55
      damus/Views/EditMetadataView.swift
  2. 18
      damus/Views/FollowButtonView.swift
  3. 8
      damus/Views/FollowingView.swift
  4. 42
      damus/Views/ProfilePicView.swift
  5. 60
      damus/Views/ProfileView.swift

55
damus/Views/EditMetadataView.swift

@ -58,21 +58,22 @@ struct EditMetadataView: View {
@State var picture: String @State var picture: String
@State var nip05: String @State var nip05: String
@State var name: String @State var name: String
@State var lud06: String @State var ln: String
@State var lud16: String @State var website: String
@State private var showAlert = false
@Environment(\.dismiss) var dismiss
init (damus_state: DamusState) { init (damus_state: DamusState) {
self.damus_state = damus_state self.damus_state = damus_state
let data = damus_state.profiles.lookup(id: damus_state.pubkey) let data = damus_state.profiles.lookup(id: damus_state.pubkey)
name = data?.name ?? "" _name = State(initialValue: data?.name ?? "")
display_name = data?.display_name ?? "" _display_name = State(initialValue: data?.display_name ?? "")
about = data?.about ?? "" _about = State(initialValue: data?.about ?? "")
picture = data?.picture ?? "" _website = State(initialValue: data?.website ?? "")
nip05 = data?.nip05 ?? "" _picture = State(initialValue: data?.picture ?? "")
lud06 = data?.lud06 ?? "" _nip05 = State(initialValue: data?.nip05 ?? "")
lud16 = data?.lud16 ?? "" _ln = State(initialValue: data?.lud16 ?? data?.lud06 ?? "")
} }
func save() { func save() {
@ -80,11 +81,11 @@ struct EditMetadataView: View {
display_name: display_name, display_name: display_name,
name: name, name: name,
about: about, about: about,
website: nil, website: website,
nip05: nip05.isEmpty ? nil : nip05, nip05: nip05.isEmpty ? nil : nip05,
picture: picture.isEmpty ? nil : picture, picture: picture.isEmpty ? nil : picture,
lud06: lud06.isEmpty ? nil : lud06, lud06: ln.contains("@") ? ln : nil,
lud16: lud16.isEmpty ? nil : lud16 lud16: ln.contains("@") ? nil : ln
); );
let m_metadata_ev = make_metadata_event(keypair: damus_state.keypair, metadata: metadata) let m_metadata_ev = make_metadata_event(keypair: damus_state.keypair, metadata: metadata)
@ -98,10 +99,9 @@ struct EditMetadataView: View {
VStack(alignment: .leading) { VStack(alignment: .leading) {
HStack { HStack {
Spacer() Spacer()
ProfilePicView(pubkey: damus_state.pubkey, size: PPM_SIZE, highlight: .none, profiles: damus_state.profiles, picture: picture) InnerProfilePicView(url: URL(string: picture), pubkey: damus_state.pubkey, size: PPM_SIZE, highlight: .none)
Spacer() Spacer()
} }
.padding([.top], 30)
Form { Form {
Section("Your Name") { Section("Your Name") {
TextField("Satoshi Nakamoto", text: $display_name) TextField("Satoshi Nakamoto", text: $display_name)
@ -120,7 +120,12 @@ struct EditMetadataView: View {
TextField("https://example.com/pic.jpg", text: $picture) TextField("https://example.com/pic.jpg", text: $picture)
.autocorrectionDisabled(true) .autocorrectionDisabled(true)
.textInputAutocapitalization(.never) .textInputAutocapitalization(.never)
}
Section("Website") {
TextField("https://jb55.com", text: $website)
.autocorrectionDisabled(true)
.textInputAutocapitalization(.never)
} }
Section("About Me") { Section("About Me") {
@ -135,18 +140,11 @@ struct EditMetadataView: View {
} }
} }
Section(content: { Section("Bitcoin Lightning Tips") {
TextField("Lightning Address", text: $lud16) TextField("Lightning Address or LNURL", text: $ln)
.autocorrectionDisabled(true) .autocorrectionDisabled(true)
.textInputAutocapitalization(.never) .textInputAutocapitalization(.never)
TextField("LNURL", text: $lud06) }
.autocorrectionDisabled(true)
.textInputAutocapitalization(.never)
}, header: {
Text("Bitcoin Lightning Tips")
}, footer: {
Text("Only one needs to be set")
})
Section(content: { Section(content: {
TextField("example.com", text: $nip05) TextField("example.com", text: $nip05)
@ -160,12 +158,11 @@ struct EditMetadataView: View {
Button("Save") { Button("Save") {
save() save()
showAlert = true dismiss()
}.alert(isPresented: $showAlert) {
Alert(title: Text("Saved"), message: Text("Your metadata has been saved."), dismissButton: .default(Text("OK")))
} }
} }
} }
.navigationTitle("Edit Profile")
} }
} }

18
damus/Views/FollowButtonView.swift

@ -13,14 +13,9 @@ struct FollowButtonView: View {
let target: FollowTarget let target: FollowTarget
@State var follow_state: FollowState @State var follow_state: FollowState
let perform: (() -> Void)?
var body: some View { var body: some View {
Button { Button {
if perform != nil {
perform!()
}
follow_state = perform_follow_btn_action(follow_state, target: target) follow_state = perform_follow_btn_action(follow_state, target: target)
} label: { } label: {
Text(follow_btn_txt(follow_state)) Text(follow_btn_txt(follow_state))
@ -71,19 +66,16 @@ struct FollowButtonPreviews: View {
var body: some View { var body: some View {
VStack { VStack {
Text("Unfollows") Text("Unfollows")
FollowButtonView(target: target, follow_state: .unfollows, perform: nil) FollowButtonView(target: target, follow_state: .unfollows)
Text("Following") Text("Following")
FollowButtonView(target: target, follow_state: .following, perform: nil) FollowButtonView(target: target, follow_state: .following)
Text("Follows") Text("Follows")
FollowButtonView(target: target, follow_state: .follows, perform: nil) FollowButtonView(target: target, follow_state: .follows)
Text("Unfollowing") Text("Unfollowing")
FollowButtonView(target: target, follow_state: .unfollowing, perform: nil) FollowButtonView(target: target, follow_state: .unfollowing)
Text("Edit")
FollowButtonView(target: target, follow_state: .edit, perform: nil)
} }
} }
} }
@ -106,8 +98,6 @@ func perform_follow_btn_action(_ fs: FollowState, target: FollowTarget) -> Follo
case .unfollows: case .unfollows:
notify(.follow, target) notify(.follow, target)
return .unfollowing return .unfollowing
case .edit:
return .edit
} }
} }

8
damus/Views/FollowingView.swift

@ -32,7 +32,7 @@ struct FollowUserView: View {
} }
.buttonStyle(PlainButtonStyle()) .buttonStyle(PlainButtonStyle())
FollowButtonView(target: target, follow_state: damus_state.contacts.follow_state(target.pubkey), perform: nil) FollowButtonView(target: target, follow_state: damus_state.contacts.follow_state(target.pubkey))
} }
} }
} }
@ -53,6 +53,12 @@ struct FollowersView: View {
} }
} }
.navigationBarTitle("\(Profile.displayName(profile: profile, pubkey: whos))'s Followers") .navigationBarTitle("\(Profile.displayName(profile: profile, pubkey: whos))'s Followers")
.onAppear {
followers.subscribe()
}
.onDisappear {
followers.unsubscribe()
}
} }
} }

42
damus/Views/ProfilePicView.swift

@ -32,17 +32,13 @@ func pfp_line_width(_ h: Highlight) -> CGFloat {
} }
} }
struct ProfilePicView: View { struct InnerProfilePicView: View {
@Environment(\.redactionReasons) private var reasons @Environment(\.redactionReasons) private var reasons
let url: URL?
let pubkey: String let pubkey: String
let size: CGFloat let size: CGFloat
let highlight: Highlight let highlight: Highlight
let profiles: Profiles
let isPlaceholder: Bool = false
@State var picture: String? = nil
var PlaceholderColor: Color { var PlaceholderColor: Color {
return id_to_color(pubkey) return id_to_color(pubkey)
@ -56,11 +52,8 @@ struct ProfilePicView: View {
.padding(2) .padding(2)
} }
var MainContent: some View { var body: some View {
Group { Group {
let pic = picture ?? profiles.lookup(id: pubkey)?.picture ?? robohash(pubkey)
let url = URL(string: pic)
if reasons.isEmpty { if reasons.isEmpty {
KFAnimatedImage(url) KFAnimatedImage(url)
.configure { view in .configure { view in
@ -82,8 +75,27 @@ struct ProfilePicView: View {
.overlay(Circle().stroke(highlight_color(highlight), lineWidth: pfp_line_width(highlight))) .overlay(Circle().stroke(highlight_color(highlight), lineWidth: pfp_line_width(highlight)))
} }
}
struct ProfilePicView: View {
let pubkey: String
let size: CGFloat
let highlight: Highlight
let profiles: Profiles
@State var picture: String?
init (pubkey: String, size: CGFloat, highlight: Highlight, profiles: Profiles, picture: String? = nil) {
self.pubkey = pubkey
self.profiles = profiles
self.size = size
self.highlight = highlight
self._picture = State(initialValue: picture)
}
var body: some View { var body: some View {
MainContent InnerProfilePicView(url: get_profile_url(picture: picture, pubkey: pubkey, profiles: profiles), pubkey: pubkey, size: size, highlight: highlight)
.onReceive(handle_notify(.profile_updated)) { notif in .onReceive(handle_notify(.profile_updated)) { notif in
let updated = notif.object as! ProfileUpdate let updated = notif.object as! ProfileUpdate
@ -98,6 +110,14 @@ struct ProfilePicView: View {
} }
} }
func get_profile_url(picture: String?, pubkey: String, profiles: Profiles) -> URL {
let pic = picture ?? profiles.lookup(id: pubkey)?.picture ?? robohash(pubkey)
if let url = URL(string: pic) {
return url
}
return URL(string: robohash(pubkey))!
}
func make_preview_profiles(_ pubkey: String) -> Profiles { func make_preview_profiles(_ pubkey: String) -> Profiles {
let profiles = Profiles() let profiles = Profiles()
let picture = "http://cdn.jb55.com/img/red-me.jpg" let picture = "http://cdn.jb55.com/img/red-me.jpg"

60
damus/Views/ProfileView.swift

@ -17,7 +17,6 @@ enum FollowState {
case following case following
case unfollowing case unfollowing
case unfollows case unfollows
case edit
} }
func follow_btn_txt(_ fs: FollowState) -> String { func follow_btn_txt(_ fs: FollowState) -> String {
@ -30,8 +29,6 @@ func follow_btn_txt(_ fs: FollowState) -> String {
return "Unfollowing..." return "Unfollowing..."
case .unfollows: case .unfollows:
return "Follow" return "Follow"
case .edit:
return "Edit"
} }
} }
@ -45,8 +42,6 @@ func follow_btn_enabled_state(_ fs: FollowState) -> Bool {
return false return false
case .unfollows: case .unfollows:
return true return true
case .edit:
return true
} }
} }
@ -82,6 +77,40 @@ struct ProfileNameView: View {
} }
} }
struct EditButton: View {
let damus_state: DamusState
@Environment(\.colorScheme) var colorScheme
var body: some View {
NavigationLink(destination: EditMetadataView(damus_state: damus_state)) {
Text("Edit")
.padding(.horizontal, 25)
.padding(.vertical, 10)
.font(.caption.weight(.bold))
.foregroundColor(fillColor())
.background(emptyColor())
.cornerRadius(20)
.overlay {
RoundedRectangle(cornerRadius: 16)
.stroke(borderColor(), lineWidth: 1)
}
}
}
func fillColor() -> Color {
colorScheme == .light ? .black : .white
}
func emptyColor() -> Color {
colorScheme == .light ? .white : .black
}
func borderColor() -> Color {
colorScheme == .light ? .black.opacity(0.1) : .white.opacity(0.2)
}
}
struct ProfileView: View { struct ProfileView: View {
let damus_state: DamusState let damus_state: DamusState
@ -134,14 +163,17 @@ struct ProfileView: View {
DMButton DMButton
FollowButtonView( if profile.pubkey != damus_state.pubkey {
target: profile.get_follow_target(), FollowButtonView(
follow_state: profile.pubkey == damus_state.pubkey ? .edit : damus_state.contacts.follow_state(profile.pubkey), target: profile.get_follow_target(),
perform: profile.pubkey == damus_state.pubkey ? { showingEditProfile.toggle() } : nil follow_state: damus_state.contacts.follow_state(profile.pubkey)
) )
} else {
NavigationLink(destination: EditMetadataView(damus_state: damus_state)) {
EditButton(damus_state: damus_state)
}
}
}.sheet(isPresented: $showingEditProfile) {
EditMetadataView(damus_state: damus_state)
} }
ProfileNameView(pubkey: profile.pubkey, profile: data, contacts: damus_state.contacts) ProfileNameView(pubkey: profile.pubkey, profile: data, contacts: damus_state.contacts)
@ -201,11 +233,11 @@ struct ProfileView: View {
} }
.onAppear() { .onAppear() {
profile.subscribe() profile.subscribe()
followers.subscribe() //followers.subscribe()
} }
.onDisappear { .onDisappear {
profile.unsubscribe() profile.unsubscribe()
followers.unsubscribe() //followers.unsubscribe()
// our profilemodel needs a bit more help // our profilemodel needs a bit more help
} }
} }

Loading…
Cancel
Save