diff --git a/damus.xcodeproj/project.pbxproj b/damus.xcodeproj/project.pbxproj index 1c788c3..0a45606 100644 --- a/damus.xcodeproj/project.pbxproj +++ b/damus.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 3169CAEB294FCABA00EE4006 /* Shimmer in Frameworks */ = {isa = PBXBuildFile; productRef = 3169CAEA294FCABA00EE4006 /* Shimmer */; }; 3169CAED294FCCFC00EE4006 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3169CAEC294FCCFC00EE4006 /* Constants.swift */; }; 3169CAEF294FD4C400EE4006 /* DamusViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3169CAEE294FD4C400EE4006 /* DamusViewModel.swift */; }; + 3169CAE6294E69C000EE4006 /* EmptyTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3169CAE5294E69C000EE4006 /* EmptyTimelineView.swift */; }; 4C06670128FC7C5900038D2A /* RelayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C06670028FC7C5900038D2A /* RelayView.swift */; }; 4C06670428FC7EC500038D2A /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 4C06670328FC7EC500038D2A /* Kingfisher */; }; 4C06670628FCB08600038D2A /* ImageCarousel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C06670528FCB08600038D2A /* ImageCarousel.swift */; }; @@ -151,6 +152,7 @@ /* Begin PBXFileReference section */ 3169CAEC294FCCFC00EE4006 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Constants.swift; path = damus/Util/Constants.swift; sourceTree = SOURCE_ROOT; }; 3169CAEE294FD4C400EE4006 /* DamusViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusViewModel.swift; sourceTree = ""; }; + 3169CAE5294E69C000EE4006 /* EmptyTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyTimelineView.swift; sourceTree = ""; }; 4C06670028FC7C5900038D2A /* RelayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayView.swift; sourceTree = ""; }; 4C06670528FCB08600038D2A /* ImageCarousel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCarousel.swift; sourceTree = ""; }; 4C06670828FDE64700038D2A /* damus-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "damus-Bridging-Header.h"; sourceTree = ""; }; @@ -336,6 +338,14 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 3169CAE4294E699400EE4006 /* Empty Views */ = { + isa = PBXGroup; + children = ( + 3169CAE5294E69C000EE4006 /* EmptyTimelineView.swift */, + ); + path = "Empty Views"; + sourceTree = ""; + }; 4C06670728FDE62900038D2A /* damus-c */ = { isa = PBXGroup; children = ( @@ -427,6 +437,7 @@ 4C75EFA227FA576C0006080F /* Views */ = { isa = PBXGroup; children = ( + 3169CAE4294E699400EE4006 /* Empty Views */, 4C75EFA327FA577B0006080F /* PostView.swift */, 4C75EFAC28049CFB0006080F /* PostButton.swift */, 4C75EFB82804A2740006080F /* EventView.swift */, @@ -789,6 +800,7 @@ 4C3AC79F2833115300E1F516 /* FollowButtonView.swift in Sources */, 4C3BEFD22819DB9B00B3DE84 /* ProfileModel.swift in Sources */, 4C0A3F93280F66F5000448DE /* ReplyMap.swift in Sources */, + 3169CAE6294E69C000EE4006 /* EmptyTimelineView.swift in Sources */, 4C3EA64928FF597700C48A62 /* bech32.c in Sources */, 4C90BD162839DB54008EE7EF /* NostrMetadata.swift in Sources */, 4C3EA67528FF7A5A00C48A62 /* take.c in Sources */, diff --git a/damus/Models/Mentions.swift b/damus/Models/Mentions.swift index 6a3de58..ecdeb06 100644 --- a/damus/Models/Mentions.swift +++ b/damus/Models/Mentions.swift @@ -189,7 +189,11 @@ func convert_invoice_block(_ b: invoice_block) -> Block? { return nil } - let description = String(cString: b11.description) + var description = "" + if b11.description != nil { + description = String(cString: b11.description) + } + guard let msat = maybe_pointee(b11.msat) else { return nil } diff --git a/damus/Nostr/NostrEvent.swift b/damus/Nostr/NostrEvent.swift index 3aa8008..fe7ce89 100644 --- a/damus/Nostr/NostrEvent.swift +++ b/damus/Nostr/NostrEvent.swift @@ -485,7 +485,10 @@ func make_first_contact_event(keypair: Keypair) -> NostrEvent? { } let rw_relay_info = RelayInfo(read: true, write: true) - let relays: [String: RelayInfo] = ["wss://relay.damus.io": rw_relay_info] + var relays: [String: RelayInfo] = [:] + for relay in BOOTSTRAP_RELAYS { + relays[relay] = rw_relay_info + } let relay_json = encode_json(relays)! let damus_pubkey = "3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681" let tags = [ diff --git a/damus/Views/ChatView.swift b/damus/Views/ChatView.swift index 53e6d90..0902124 100644 --- a/damus/Views/ChatView.swift +++ b/damus/Views/ChatView.swift @@ -106,7 +106,7 @@ struct ChatView: View { } } - NoteContentView(privkey: damus_state.keypair.privkey, event: event, profiles: damus_state.profiles, show_images: true, artifacts: .just_content(event.content)) + NoteContentView(privkey: damus_state.keypair.privkey, event: event, profiles: damus_state.profiles, show_images: should_show_images(contacts: damus_state.contacts, ev: event), artifacts: .just_content(event.content)) if is_active || next_ev == nil || next_ev!.pubkey != event.pubkey { let bar = make_actionbar_model(ev: event, damus: damus_state) diff --git a/damus/Views/CreateAccountView.swift b/damus/Views/CreateAccountView.swift index 3443e17..9521e45 100644 --- a/damus/Views/CreateAccountView.swift +++ b/damus/Views/CreateAccountView.swift @@ -83,6 +83,7 @@ struct CreateAccountView: View { .padding(.trailing, 20.0) } + .dismissKeyboardOnTap() .navigationBarTitleDisplayMode(.inline) .navigationBarBackButtonHidden(true) .navigationBarItems(leading: BackNav()) diff --git a/damus/Views/DMView.swift b/damus/Views/DMView.swift index 18ac2ed..741eb50 100644 --- a/damus/Views/DMView.swift +++ b/damus/Views/DMView.swift @@ -21,7 +21,7 @@ struct DMView: View { Spacer() } - NoteContentView(privkey: damus_state.keypair.privkey, event: event, profiles: damus_state.profiles, show_images: true, artifacts: .just_content(event.get_content(damus_state.keypair.privkey))) + NoteContentView(privkey: damus_state.keypair.privkey, event: event, profiles: damus_state.profiles, show_images: should_show_images(contacts: damus_state.contacts, ev: event), artifacts: .just_content(event.get_content(damus_state.keypair.privkey))) .foregroundColor(is_ours ? Color.white : Color.primary) .padding(10) .background(is_ours ? Color.accentColor : Color.secondary.opacity(0.15)) diff --git a/damus/Views/DirectMessagesView.swift b/damus/Views/DirectMessagesView.swift index 91e5250..97e18ee 100644 --- a/damus/Views/DirectMessagesView.swift +++ b/damus/Views/DirectMessagesView.swift @@ -14,8 +14,12 @@ struct DirectMessagesView: View { var MainContent: some View { ScrollView { LazyVStack { - ForEach(model.dms, id: \.0) { tup in - MaybeEvent(tup) + if model.dms.isEmpty, !model.loading { + EmptyTimelineView() + } else { + ForEach(model.dms, id: \.0) { tup in + MaybeEvent(tup) + } } } .padding(.horizontal) diff --git a/damus/Views/Empty Views/EmptyTimelineView.swift b/damus/Views/Empty Views/EmptyTimelineView.swift new file mode 100644 index 0000000..f4bcda3 --- /dev/null +++ b/damus/Views/Empty Views/EmptyTimelineView.swift @@ -0,0 +1,29 @@ +// +// EmptyNotificationsView.swift +// damus +// +// Created by Sam DuBois on 12/17/22. +// + +import SwiftUI + +struct EmptyTimelineView: View { + var body: some View { + VStack { + Image(systemName: "tray.fill") + .font(.system(size: 35)) + .padding() + Text("Nothing to see here. Check back later!") + .multilineTextAlignment(.center) + .font(.callout.weight(.medium)) + } + .foregroundColor(.gray) + .padding() + } +} + +struct EmptyTimelineView_Previews: PreviewProvider { + static var previews: some View { + EmptyTimelineView() + } +} diff --git a/damus/Views/EventView.swift b/damus/Views/EventView.swift index 5d696c4..863eb9d 100644 --- a/damus/Views/EventView.swift +++ b/damus/Views/EventView.swift @@ -137,7 +137,7 @@ struct EventView: View { .frame(maxWidth: .infinity, alignment: .leading) } - NoteContentView(privkey: damus.keypair.privkey, event: event, profiles: damus.profiles, show_images: true, artifacts: .just_content(content)) + NoteContentView(privkey: damus.keypair.privkey, event: event, profiles: damus.profiles, show_images: should_show_images(contacts: damus.contacts, ev: event), artifacts: .just_content(content)) .frame(maxWidth: .infinity, alignment: .leading) if has_action_bar { @@ -159,6 +159,14 @@ struct EventView: View { } } +// blame the porn bots for this code +func should_show_images(contacts: Contacts, ev: NostrEvent) -> Bool { + if contacts.is_friend(ev.pubkey) { + return true + } + return false +} + func event_validity_color(_ validation: ValidationResult) -> some View { Group { switch validation { diff --git a/damus/Views/SaveKeysView.swift b/damus/Views/SaveKeysView.swift index 61ad197..70d26c0 100644 --- a/damus/Views/SaveKeysView.swift +++ b/damus/Views/SaveKeysView.swift @@ -80,7 +80,10 @@ struct SaveKeysView: View { } func complete_account_creation(_ account: CreateAccountModel) { - add_rw_relay(self.pool, "wss://relay.damus.io") + for relay in BOOTSTRAP_RELAYS { + add_rw_relay(self.pool, relay) + } + self.pool.register_handler(sub_id: "signup", handler: handle_event) self.loading = true diff --git a/damus/Views/TimelineView.swift b/damus/Views/TimelineView.swift index 08f1a5c..5a81d40 100644 --- a/damus/Views/TimelineView.swift +++ b/damus/Views/TimelineView.swift @@ -21,16 +21,20 @@ struct InnerTimelineView: View { var body: some View { LazyVStack { - ForEach(events.filter(filter), id: \.id) { (ev: NostrEvent) in - let tm = ThreadModel(event: inner_event_or_self(ev: ev), damus_state: damus) - let is_chatroom = should_show_chatroom(ev) - let tv = ThreadView(thread: tm, damus: damus, is_chatroom: is_chatroom) - - NavigationLink(destination: tv) { - EventView(event: ev, highlight: .none, has_action_bar: true, damus: damus, show_friend_icon: show_friend_icon) + if events.isEmpty { + EmptyTimelineView() + } else { + ForEach(events.filter(filter), id: \.id) { (ev: NostrEvent) in + let tm = ThreadModel(event: inner_event_or_self(ev: ev), damus_state: damus) + let is_chatroom = should_show_chatroom(ev) + let tv = ThreadView(thread: tm, damus: damus, is_chatroom: is_chatroom) + + NavigationLink(destination: tv) { + EventView(event: ev, highlight: .none, has_action_bar: true, damus: damus, show_friend_icon: show_friend_icon) + } + .isDetailLink(true) + .buttonStyle(PlainButtonStyle()) } - .isDetailLink(true) - .buttonStyle(PlainButtonStyle()) } } .padding(.horizontal) @@ -76,8 +80,11 @@ struct TimelineView: View { ScrollView { if loading { InnerTimelineRedactedView(events: Constants.EXAMPLE_EVENTS, damus: damus, show_friend_icon: true) + ProgressView() + .progressViewStyle(.circular) + } else { + InnerTimelineView(events: $events, damus: damus, show_friend_icon: show_friend_icon, filter: filter) } - InnerTimelineView(events: $events, damus: damus, show_friend_icon: show_friend_icon, filter: filter) } .onReceive(NotificationCenter.default.publisher(for: .scroll_to_top)) { _ in guard let event = events.filter(self.filter).first else {