damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | README | LICENSE

commit 444f76a233085480764a96e218d466ca40c2c599
parent 49082683473108b8211e991830750240bb014707
Author: Thomas <31560900+0xtlt@users.noreply.github.com>
Date:   Fri, 23 Dec 2022 18:27:39 +0100

MetadataView -> EditMetadataView

Diffstat:
Mdamus.xcodeproj/project.pbxproj | 8++++----
Mdamus/Views/ConfigView.swift | 2+-
Adamus/Views/EditMetadataView.swift | 174+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ddamus/Views/MetadataView.swift | 174-------------------------------------------------------------------------------
Mdamus/Views/ProfileView.swift | 2+-
5 files changed, 180 insertions(+), 180 deletions(-)

diff --git a/damus.xcodeproj/project.pbxproj b/damus.xcodeproj/project.pbxproj @@ -129,7 +129,7 @@ 4CEE2AF7280B2DEA00AB5EEF /* ProfileName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CEE2AF6280B2DEA00AB5EEF /* ProfileName.swift */; }; 4CEE2AF9280B2EAC00AB5EEF /* PowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CEE2AF8280B2EAC00AB5EEF /* PowView.swift */; }; 4CEE2B02280B39E800AB5EEF /* EventActionBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CEE2B01280B39E800AB5EEF /* EventActionBar.swift */; }; - E990020F2955F837003BBC5A /* MetadataView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E990020E2955F837003BBC5A /* MetadataView.swift */; }; + E990020F2955F837003BBC5A /* EditMetadataView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E990020E2955F837003BBC5A /* EditMetadataView.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -307,7 +307,7 @@ 4CEE2AF6280B2DEA00AB5EEF /* ProfileName.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileName.swift; sourceTree = "<group>"; }; 4CEE2AF8280B2EAC00AB5EEF /* PowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PowView.swift; sourceTree = "<group>"; }; 4CEE2B01280B39E800AB5EEF /* EventActionBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventActionBar.swift; sourceTree = "<group>"; }; - E990020E2955F837003BBC5A /* MetadataView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MetadataView.swift; sourceTree = "<group>"; }; + E990020E2955F837003BBC5A /* EditMetadataView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditMetadataView.swift; sourceTree = "<group>"; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -475,7 +475,7 @@ 4C216F31286E388800040376 /* DMChatView.swift */, 4C216F33286F5ACD00040376 /* DMView.swift */, 4C06670028FC7C5900038D2A /* RelayView.swift */, - E990020E2955F837003BBC5A /* MetadataView.swift */, + E990020E2955F837003BBC5A /* EditMetadataView.swift */, ); path = Views; sourceTree = "<group>"; @@ -848,7 +848,7 @@ 4C3EA67D28FFBBA300C48A62 /* InvoicesView.swift in Sources */, 4C363A8E28236FE4006E126D /* NoteContentView.swift in Sources */, 4C90BD1A283AA67F008EE7EF /* Bech32.swift in Sources */, - E990020F2955F837003BBC5A /* MetadataView.swift in Sources */, + E990020F2955F837003BBC5A /* EditMetadataView.swift in Sources */, 4CACA9D5280C31E100D9BBE8 /* ReplyView.swift in Sources */, 4C0A3F97280F8E02000448DE /* ThreadView.swift in Sources */, 4C06670B28FDE64700038D2A /* damus.c in Sources */, diff --git a/damus/Views/ConfigView.swift b/damus/Views/ConfigView.swift @@ -80,7 +80,7 @@ struct ConfigView: View { Section("Account settings") { NavigationLink { - MetadataView(damus_state: state, profileModel: ProfileModel(pubkey: state.pubkey, damus: state)) + EditMetadataView(damus_state: state, profileModel: ProfileModel(pubkey: state.pubkey, damus: state)) } label: { Text("Profile metadata") } diff --git a/damus/Views/EditMetadataView.swift b/damus/Views/EditMetadataView.swift @@ -0,0 +1,174 @@ +// +// EditMetadataView.swift +// damus +// +// Created by Thomas Tastet on 23/12/2022. +// + +import SwiftUI + +let PPM_SIZE: CGFloat = 80.0 + +func isHttpsUrl(_ string: String) -> Bool { + let urlRegEx = "^https://.*$" + let urlTest = NSPredicate(format:"SELF MATCHES %@", urlRegEx) + return urlTest.evaluate(with: string) +} + +func isImage(_ urlString: String) -> Bool { + let imageTypes = ["image/jpg", "image/jpeg", "image/png", "image/gif", "image/tiff", "image/bmp"] + + guard let url = URL(string: urlString) else { + return false + } + + var result = false + let semaphore = DispatchSemaphore(value: 0) + + let task = URLSession.shared.dataTask(with: url) { data, response, error in + if let error = error { + print(error) + semaphore.signal() + return + } + + guard let httpResponse = response as? HTTPURLResponse, + let contentType = httpResponse.allHeaderFields["Content-Type"] as? String else { + semaphore.signal() + return + } + + if imageTypes.contains(contentType.lowercased()) { + result = true + } + + semaphore.signal() + } + + task.resume() + semaphore.wait() + + return result +} + +struct EditMetadataView: View { + let damus_state: DamusState + @State var name: String = "" + @State var about: String = "" + @State var picture: String = "" + @State var nip05: String = "" + @State var nickname: String = "" + @State var lud06: String = "" + @State var lud16: String = "" + @State private var showAlert = false + + // Image preview + @State var profiles = Profiles() + @State private var timer: Timer? + + @StateObject var profileModel: ProfileModel + + func save() { + let metadata = NostrMetadata( + display_name: name, + name: nickname, + about: about, + website: nil, + nip05: nip05.isEmpty ? nil : nip05, + picture: picture.isEmpty ? nil : picture, + lud06: lud06.isEmpty ? nil : lud06, + lud16: lud16.isEmpty ? nil : lud16 + ); + + let m_metadata_ev = make_metadata_event(keypair: damus_state.keypair, metadata: metadata) + + if let metadata_ev = m_metadata_ev { + damus_state.pool.send(.event(metadata_ev)) + } + } + + var body: some View { + VStack(alignment: .leading) { + Form { + HStack { + Spacer() + ProfilePicView(pubkey: "0", size: PPM_SIZE, highlight: .none, profiles: profiles) + Spacer() + } + Section("Your Nostr Profile") { + TextField("Your username", text: $name) + .textInputAutocapitalization(.never) + TextField("Your @", text: $nickname) + .textInputAutocapitalization(.never) + TextField("Profile Picture Url", text: $picture) + .autocorrectionDisabled(true) + .textInputAutocapitalization(.never) + .onChange(of: picture) { newValue in + self.timer?.invalidate() + self.timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { _ in + profiles = Profiles() + let tmp_profile = Profile(name: "0", display_name: "0", about: "0", picture: isHttpsUrl(picture) && isImage(picture) ? picture : nil, website: nil, lud06: "", lud16: nil, nip05: nil) + let ts_profile = TimestampedProfile(profile: tmp_profile, timestamp: 0) + profiles.add(id: "0", profile: ts_profile) + } + } + TextField("NIP-05 Verification Domain (eg: example.com)", text: $nip05) + .autocorrectionDisabled(true) + .textInputAutocapitalization(.never) + } + + Section("Description") { + ZStack(alignment: .topLeading) { + TextEditor(text: $about) + .textInputAutocapitalization(.sentences) + if about.isEmpty { + Text("Type your description here...") + .offset(x: 0, y: 7) + .foregroundColor(Color(uiColor: .placeholderText)) + } + } + } + + Section("Advanced") { + TextField("LNURL", text: $lud06) + .autocorrectionDisabled(true) + .textInputAutocapitalization(.never) + TextField("LN Address", text: $lud16) + .autocorrectionDisabled(true) + .textInputAutocapitalization(.never) + } + + Button("Save") { + save() + showAlert = true + }.alert(isPresented: $showAlert) { + Alert(title: Text("Saved"), message: Text("Your metadata has been saved."), dismissButton: .default(Text("OK"))) + } + } + } + .onAppear() { + profileModel.subscribe() + + let data = damus_state.profiles.lookup(id: profileModel.pubkey) + + name = data?.display_name ?? name + nickname = data?.name ?? name + about = data?.about ?? about + picture = data?.picture ?? picture + nip05 = data?.nip05 ?? nip05 + lud06 = data?.lud06 ?? lud06 + lud16 = data?.lud16 ?? lud16 + } + .onDisappear { + profileModel.unsubscribe() + } + } +} + +struct EditMetadataView_Previews: PreviewProvider { + static var previews: some View { + let ds = test_damus_state() + let profile_model = ProfileModel(pubkey: ds.pubkey, damus: ds) + EditMetadataView(damus_state: ds, profileModel: profile_model) + } +} diff --git a/damus/Views/MetadataView.swift b/damus/Views/MetadataView.swift @@ -1,174 +0,0 @@ -// -// MetadataView.swift -// damus -// -// Created by Thomas Tastet on 23/12/2022. -// - -import SwiftUI - -let PPM_SIZE: CGFloat = 80.0 - -func isHttpsUrl(_ string: String) -> Bool { - let urlRegEx = "^https://.*$" - let urlTest = NSPredicate(format:"SELF MATCHES %@", urlRegEx) - return urlTest.evaluate(with: string) -} - -func isImage(_ urlString: String) -> Bool { - let imageTypes = ["image/jpg", "image/jpeg", "image/png", "image/gif", "image/tiff", "image/bmp"] - - guard let url = URL(string: urlString) else { - return false - } - - var result = false - let semaphore = DispatchSemaphore(value: 0) - - let task = URLSession.shared.dataTask(with: url) { data, response, error in - if let error = error { - print(error) - semaphore.signal() - return - } - - guard let httpResponse = response as? HTTPURLResponse, - let contentType = httpResponse.allHeaderFields["Content-Type"] as? String else { - semaphore.signal() - return - } - - if imageTypes.contains(contentType.lowercased()) { - result = true - } - - semaphore.signal() - } - - task.resume() - semaphore.wait() - - return result -} - -struct MetadataView: View { - let damus_state: DamusState - @State var name: String = "" - @State var about: String = "" - @State var picture: String = "" - @State var nip05: String = "" - @State var nickname: String = "" - @State var lud06: String = "" - @State var lud16: String = "" - @State private var showAlert = false - - // Image preview - @State var profiles = Profiles() - @State private var timer: Timer? - - @StateObject var profileModel: ProfileModel - - func save() { - let metadata = NostrMetadata( - display_name: name, - name: nickname, - about: about, - website: nil, - nip05: nip05.isEmpty ? nil : nip05, - picture: picture.isEmpty ? nil : picture, - lud06: lud06.isEmpty ? nil : lud06, - lud16: lud16.isEmpty ? nil : lud16 - ); - - let m_metadata_ev = make_metadata_event(keypair: damus_state.keypair, metadata: metadata) - - if let metadata_ev = m_metadata_ev { - damus_state.pool.send(.event(metadata_ev)) - } - } - - var body: some View { - VStack(alignment: .leading) { - Form { - HStack { - Spacer() - ProfilePicView(pubkey: "0", size: PPM_SIZE, highlight: .none, profiles: profiles) - Spacer() - } - Section("Your Nostr Profile") { - TextField("Your username", text: $name) - .textInputAutocapitalization(.never) - TextField("Your @", text: $nickname) - .textInputAutocapitalization(.never) - TextField("Profile Picture Url", text: $picture) - .autocorrectionDisabled(true) - .textInputAutocapitalization(.never) - .onChange(of: picture) { newValue in - self.timer?.invalidate() - self.timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { _ in - profiles = Profiles() - let tmp_profile = Profile(name: "0", display_name: "0", about: "0", picture: isHttpsUrl(picture) && isImage(picture) ? picture : nil, website: nil, lud06: "", lud16: nil, nip05: nil) - let ts_profile = TimestampedProfile(profile: tmp_profile, timestamp: 0) - profiles.add(id: "0", profile: ts_profile) - } - } - TextField("NIP-05 Verification Domain (eg: example.com)", text: $nip05) - .autocorrectionDisabled(true) - .textInputAutocapitalization(.never) - } - - Section("Description") { - ZStack(alignment: .topLeading) { - TextEditor(text: $about) - .textInputAutocapitalization(.sentences) - if about.isEmpty { - Text("Type your description here...") - .offset(x: 0, y: 7) - .foregroundColor(Color(uiColor: .placeholderText)) - } - } - } - - Section("Advanced") { - TextField("LNURL", text: $lud06) - .autocorrectionDisabled(true) - .textInputAutocapitalization(.never) - TextField("LN Address", text: $lud16) - .autocorrectionDisabled(true) - .textInputAutocapitalization(.never) - } - - Button("Save") { - save() - showAlert = true - }.alert(isPresented: $showAlert) { - Alert(title: Text("Saved"), message: Text("Your metadata has been saved."), dismissButton: .default(Text("OK"))) - } - } - } - .onAppear() { - profileModel.subscribe() - - let data = damus_state.profiles.lookup(id: profileModel.pubkey) - - name = data?.display_name ?? name - nickname = data?.name ?? name - about = data?.about ?? about - picture = data?.picture ?? picture - nip05 = data?.nip05 ?? nip05 - lud06 = data?.lud06 ?? lud06 - lud16 = data?.lud16 ?? lud16 - } - .onDisappear { - profileModel.unsubscribe() - } - } -} - -struct MetadataView_Previews: PreviewProvider { - static var previews: some View { - let ds = test_damus_state() - let profile_model = ProfileModel(pubkey: ds.pubkey, damus: ds) - MetadataView(damus_state: ds, profileModel: profile_model) - } -} diff --git a/damus/Views/ProfileView.swift b/damus/Views/ProfileView.swift @@ -141,7 +141,7 @@ struct ProfileView: View { ) }.sheet(isPresented: $showingEditProfile) { - MetadataView(damus_state: damus_state, profileModel: profile) + EditMetadataView(damus_state: damus_state, profileModel: profile) } ProfileNameView(pubkey: profile.pubkey, profile: data, contacts: damus_state.contacts)