Compare commits
1 Commits
nprofile-q
...
pinned-not
| Author | SHA1 | Date | |
|---|---|---|---|
|
e5c82ec64b
|
@@ -14,6 +14,12 @@
|
||||
31D2E847295218AF006D67F8 /* Shimmer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31D2E846295218AF006D67F8 /* Shimmer.swift */; };
|
||||
3A0A30BB2C21397A00F8C9BC /* EmojiPicker in Frameworks */ = {isa = PBXBuildFile; productRef = 3A0A30BA2C21397A00F8C9BC /* EmojiPicker */; };
|
||||
3A23838E2A297DD200E5AA2E /* ZapButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A23838D2A297DD200E5AA2E /* ZapButtonModel.swift */; };
|
||||
3A28D3A12E2F3FB5003C6F82 /* PinnedEventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A28D3A02E2F3FB5003C6F82 /* PinnedEventView.swift */; };
|
||||
3A28D3A22E2F3FB5003C6F82 /* PinnedEventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A28D3A02E2F3FB5003C6F82 /* PinnedEventView.swift */; };
|
||||
3A28D3A32E2F3FB5003C6F82 /* PinnedEventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A28D3A02E2F3FB5003C6F82 /* PinnedEventView.swift */; };
|
||||
3A28D3A62E2F4082003C6F82 /* PinnedHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A28D3A52E2F4082003C6F82 /* PinnedHeaderView.swift */; };
|
||||
3A28D3A72E2F4082003C6F82 /* PinnedHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A28D3A52E2F4082003C6F82 /* PinnedHeaderView.swift */; };
|
||||
3A28D3A82E2F4082003C6F82 /* PinnedHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A28D3A52E2F4082003C6F82 /* PinnedHeaderView.swift */; };
|
||||
3A2BAC5A2DD7E4C400EBB4CC /* NIP05DomainTimelineHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A2BAC592DD7E4C400EBB4CC /* NIP05DomainTimelineHeaderView.swift */; };
|
||||
3A2BAC5B2DD7E4C400EBB4CC /* NIP05DomainTimelineHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A2BAC592DD7E4C400EBB4CC /* NIP05DomainTimelineHeaderView.swift */; };
|
||||
3A2BAC5C2DD7E4C400EBB4CC /* NIP05DomainTimelineHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A2BAC592DD7E4C400EBB4CC /* NIP05DomainTimelineHeaderView.swift */; };
|
||||
@@ -1869,6 +1875,8 @@
|
||||
3A25EF132992DA5D008ABE69 /* el-GR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "el-GR"; path = "el-GR.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
||||
3A25EF142992DA5D008ABE69 /* el-GR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "el-GR"; path = "el-GR.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||
3A25EF152992DA5D008ABE69 /* el-GR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "el-GR"; path = "el-GR.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
|
||||
3A28D3A02E2F3FB5003C6F82 /* PinnedEventView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedEventView.swift; sourceTree = "<group>"; };
|
||||
3A28D3A52E2F4082003C6F82 /* PinnedHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedHeaderView.swift; sourceTree = "<group>"; };
|
||||
3A2B8B0A296A8982009CC16D /* en-US */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "en-US"; path = "en-US.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
|
||||
3A2BAC592DD7E4C400EBB4CC /* NIP05DomainTimelineHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NIP05DomainTimelineHeaderView.swift; sourceTree = "<group>"; };
|
||||
3A2BAC5D2DE02E8600EBB4CC /* NIP05DomainPubkeysView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NIP05DomainPubkeysView.swift; sourceTree = "<group>"; };
|
||||
@@ -2784,6 +2792,15 @@
|
||||
path = "Empty Views";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
3A28D3A42E2F4053003C6F82 /* Pinned */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3A28D3A02E2F3FB5003C6F82 /* PinnedEventView.swift */,
|
||||
3A28D3A52E2F4082003C6F82 /* PinnedHeaderView.swift */,
|
||||
);
|
||||
path = Pinned;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
3A515C4E2DF4E0E6002D3B34 /* Tips */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -3685,6 +3702,7 @@
|
||||
4CC7AAEE297F11B300430951 /* Events */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3A28D3A42E2F4053003C6F82 /* Pinned */,
|
||||
5C4FA7FA2DC29C3800CE658C /* FollowPack */,
|
||||
5CC852A02BDED9970039FFC5 /* Highlight */,
|
||||
4CA927682A290F8F0098A105 /* Components */,
|
||||
@@ -4698,6 +4716,7 @@
|
||||
4C75EFAD28049CFB0006080F /* PostButton.swift in Sources */,
|
||||
D7EDED1E2B11797D0018B19C /* LongformEvent.swift in Sources */,
|
||||
504323A92A3495B6006AE6DC /* RelayModelCache.swift in Sources */,
|
||||
3A28D3A32E2F3FB5003C6F82 /* PinnedEventView.swift in Sources */,
|
||||
5C4D9EA72C042FA5005EA0F7 /* HighlightDraftContentView.swift in Sources */,
|
||||
3A8CC6CC2A2CFEF900940F5F /* StringUtil.swift in Sources */,
|
||||
D7FD12262BD345A700CF195B /* FirstAidSettingsView.swift in Sources */,
|
||||
@@ -5002,6 +5021,7 @@
|
||||
4CC14FF92A741939007AEB17 /* Referenced.swift in Sources */,
|
||||
4C5C7E6A284EDE2E00A22DF5 /* SearchResultsView.swift in Sources */,
|
||||
4CE1399429F0669900AC6A0B /* BigButton.swift in Sources */,
|
||||
3A28D3A62E2F4082003C6F82 /* PinnedHeaderView.swift in Sources */,
|
||||
D7EFBA372CC322F300F45588 /* DamusVideoControlsView.swift in Sources */,
|
||||
7C60CAEF298471A1009C80D6 /* CoreSVG.swift in Sources */,
|
||||
D706C5AF2D5D31C20027C627 /* AutoSaveIndicatorView.swift in Sources */,
|
||||
@@ -5332,6 +5352,7 @@
|
||||
82D6FB012CD99F7900C925F4 /* Block.swift in Sources */,
|
||||
82D6FB022CD99F7900C925F4 /* MigratedTypes.swift in Sources */,
|
||||
82D6FB032CD99F7900C925F4 /* DamusDuration.swift in Sources */,
|
||||
3A28D3A22E2F3FB5003C6F82 /* PinnedEventView.swift in Sources */,
|
||||
82D6FB042CD99F7900C925F4 /* SwipeToDismiss.swift in Sources */,
|
||||
82D6FB052CD99F7900C925F4 /* MusicController.swift in Sources */,
|
||||
82D6FB062CD99F7900C925F4 /* UserStatusView.swift in Sources */,
|
||||
@@ -5490,6 +5511,7 @@
|
||||
D74EA08E2D2E271E002290DD /* ErrorView.swift in Sources */,
|
||||
82D6FB952CD99F7900C925F4 /* TranslationService.swift in Sources */,
|
||||
82D6FB962CD99F7900C925F4 /* DeepLPlan.swift in Sources */,
|
||||
3A28D3A72E2F4082003C6F82 /* PinnedHeaderView.swift in Sources */,
|
||||
82D6FB972CD99F7900C925F4 /* ZapsModel.swift in Sources */,
|
||||
82D6FB982CD99F7900C925F4 /* DraftsModel.swift in Sources */,
|
||||
82D6FB992CD99F7900C925F4 /* NotificationsModel.swift in Sources */,
|
||||
@@ -5754,6 +5776,7 @@
|
||||
D73E5F8B2C6AA6A2007EB227 /* UserStatusSheet.swift in Sources */,
|
||||
D73E5E282C6A97F4007EB227 /* LoginNotify.swift in Sources */,
|
||||
D73E5E292C6A97F4007EB227 /* LogoutNotify.swift in Sources */,
|
||||
3A28D3A12E2F3FB5003C6F82 /* PinnedEventView.swift in Sources */,
|
||||
D73E5E2A2C6A97F4007EB227 /* OnlyZapsNotify.swift in Sources */,
|
||||
D73E5E2B2C6A97F4007EB227 /* PostNotify.swift in Sources */,
|
||||
D73E5E2C2C6A97F4007EB227 /* PresentSheetNotify.swift in Sources */,
|
||||
@@ -5776,6 +5799,7 @@
|
||||
D73E5E3A2C6A97F4007EB227 /* SwipeToDismiss.swift in Sources */,
|
||||
D73E5E3B2C6A97F4007EB227 /* MusicController.swift in Sources */,
|
||||
D73E5E3C2C6A97F4007EB227 /* UserStatusView.swift in Sources */,
|
||||
3A28D3A82E2F4082003C6F82 /* PinnedHeaderView.swift in Sources */,
|
||||
D74EA08F2D2E271E002290DD /* ErrorView.swift in Sources */,
|
||||
D73E5E3E2C6A97F4007EB227 /* SearchHeaderView.swift in Sources */,
|
||||
D73E5E3F2C6A97F4007EB227 /* DamusGradient.swift in Sources */,
|
||||
|
||||
@@ -231,6 +231,8 @@ class HomeModel: ContactsDelegate {
|
||||
break
|
||||
case .interest_list:
|
||||
break // Don't care for now
|
||||
case .pinned_notes:
|
||||
break // FIXME(tyiu)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,17 @@ class ProfileModel: ObservableObject, Equatable {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@Published var pinned_notes_list: NostrEvent? = nil
|
||||
var pinned_note_ids: Set<NoteId> {
|
||||
if let pinned_notes_list {
|
||||
return Set(pinned_notes_list.referenced_noterefs.map { $0.note_id })
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
var events: EventHolder
|
||||
var pinned_events: EventHolder
|
||||
let pubkey: Pubkey
|
||||
let damus: DamusState
|
||||
|
||||
@@ -32,6 +41,7 @@ class ProfileModel: ObservableObject, Equatable {
|
||||
var prof_subid = UUID().description
|
||||
var conversations_subid = UUID().description
|
||||
var findRelay_subid = UUID().description
|
||||
var pinned_subid = UUID().description
|
||||
var conversation_events: Set<NoteId> = Set()
|
||||
|
||||
init(pubkey: Pubkey, damus: DamusState) {
|
||||
@@ -40,6 +50,9 @@ class ProfileModel: ObservableObject, Equatable {
|
||||
self.events = EventHolder(on_queue: { ev in
|
||||
preload_events(state: damus, events: [ev])
|
||||
})
|
||||
self.pinned_events = EventHolder(on_queue: { ev in
|
||||
preload_events(state: damus, events: [ev])
|
||||
})
|
||||
}
|
||||
|
||||
func follows(pubkey: Pubkey) -> Bool {
|
||||
@@ -74,20 +87,18 @@ class ProfileModel: ObservableObject, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
func subscribe() {
|
||||
var text_filter = NostrFilter(kinds: [.text, .longform, .highlight])
|
||||
var profile_filter = NostrFilter(kinds: [.contacts, .metadata, .boost])
|
||||
var relay_list_filter = NostrFilter(kinds: [.relay_list], authors: [pubkey])
|
||||
let textKinds: [NostrKind] = [.text, .longform, .highlight]
|
||||
|
||||
profile_filter.authors = [pubkey]
|
||||
|
||||
text_filter.authors = [pubkey]
|
||||
text_filter.limit = 500
|
||||
func subscribe() {
|
||||
let text_filter = NostrFilter(kinds: textKinds, limit: 500, authors: [pubkey])
|
||||
let profile_filter = NostrFilter(kinds: [.contacts, .metadata, .boost], authors: [pubkey])
|
||||
let relay_list_filter = NostrFilter(kinds: [.relay_list], authors: [pubkey])
|
||||
let pinned_notes_filter = NostrFilter(kinds: [.pinned_notes], authors: [pubkey])
|
||||
|
||||
print("subscribing to textlike events from profile \(pubkey) with sub_id \(sub_id)")
|
||||
//print_filters(relay_id: "profile", filters: [[text_filter], [profile_filter]])
|
||||
damus.nostrNetwork.pool.subscribe(sub_id: sub_id, filters: [text_filter], handler: handle_event)
|
||||
damus.nostrNetwork.pool.subscribe(sub_id: prof_subid, filters: [profile_filter, relay_list_filter], handler: handle_event)
|
||||
damus.nostrNetwork.pool.subscribe(sub_id: prof_subid, filters: [profile_filter, relay_list_filter, pinned_notes_filter], handler: handle_event)
|
||||
|
||||
subscribe_to_conversations()
|
||||
}
|
||||
@@ -98,7 +109,7 @@ class ProfileModel: ObservableObject, Equatable {
|
||||
return
|
||||
}
|
||||
|
||||
let conversation_kinds: [NostrKind] = [.text, .longform, .highlight]
|
||||
let conversation_kinds: [NostrKind] = textKinds
|
||||
let limit: UInt32 = 500
|
||||
let conversations_filter_them = NostrFilter(kinds: conversation_kinds, pubkeys: [damus.pubkey], limit: limit, authors: [pubkey])
|
||||
let conversations_filter_us = NostrFilter(kinds: conversation_kinds, pubkeys: [pubkey], limit: limit, authors: [damus.pubkey])
|
||||
@@ -106,6 +117,15 @@ class ProfileModel: ObservableObject, Equatable {
|
||||
damus.nostrNetwork.pool.subscribe(sub_id: conversations_subid, filters: [conversations_filter_them, conversations_filter_us], handler: handle_event)
|
||||
}
|
||||
|
||||
private func subscribe_to_pinned_notes() {
|
||||
guard let pinned_notes_list, pinned_notes_list.referenced_noterefs.first != nil else {
|
||||
return
|
||||
}
|
||||
|
||||
let pinned_filter = NostrFilter(ids: Array(pinned_note_ids), kinds: [.text], authors: [pubkey])
|
||||
damus.nostrNetwork.pool.subscribe(sub_id: pinned_subid, filters: [pinned_filter], handler: handle_event)
|
||||
}
|
||||
|
||||
func handle_profile_contact_event(_ ev: NostrEvent) {
|
||||
process_contact_event(state: damus, ev: ev)
|
||||
|
||||
@@ -126,11 +146,24 @@ class ProfileModel: ObservableObject, Equatable {
|
||||
if self.events.insert(ev) {
|
||||
self.objectWillChange.send()
|
||||
}
|
||||
if pinned_note_ids.contains(ev.id) && self.pinned_events.insert(ev) {
|
||||
self.objectWillChange.send()
|
||||
}
|
||||
} else if ev.known_kind == .contacts {
|
||||
handle_profile_contact_event(ev)
|
||||
}
|
||||
else if ev.known_kind == .relay_list {
|
||||
} else if ev.known_kind == .relay_list {
|
||||
self.relay_list = try? NIP65.RelayList(event: ev) // Whether another user's list is malformatted is something beyond our control. Probably best to suppress errors
|
||||
} else if ev.known_kind == .pinned_notes {
|
||||
if let current_ev = self.pinned_notes_list {
|
||||
guard ev.created_at > current_ev.created_at else {
|
||||
return
|
||||
}
|
||||
pinned_events.incoming.removeAll()
|
||||
pinned_events.events.removeAll()
|
||||
}
|
||||
|
||||
self.pinned_notes_list = ev
|
||||
subscribe_to_pinned_notes()
|
||||
}
|
||||
seen_event.insert(ev.id)
|
||||
}
|
||||
@@ -148,6 +181,8 @@ class ProfileModel: ObservableObject, Equatable {
|
||||
default:
|
||||
return false
|
||||
}
|
||||
} else if sub_id == self.pinned_subid {
|
||||
return self.pubkey == ev.pubkey && pinned_note_ids.contains(ev.id)
|
||||
}
|
||||
|
||||
return self.pubkey == ev.pubkey
|
||||
@@ -158,7 +193,7 @@ class ProfileModel: ObservableObject, Equatable {
|
||||
case .ws_event:
|
||||
return
|
||||
case .nostr_event(let resp):
|
||||
guard resp.subid == self.sub_id || resp.subid == self.prof_subid || resp.subid == self.conversations_subid else {
|
||||
guard [self.sub_id, self.prof_subid, self.conversations_subid, self.pinned_subid].contains(resp.subid) else {
|
||||
return
|
||||
}
|
||||
switch resp {
|
||||
@@ -179,12 +214,24 @@ class ProfileModel: ObservableObject, Equatable {
|
||||
if resp.subid == self.conversations_subid {
|
||||
conversation_events.insert(ev.id)
|
||||
}
|
||||
|
||||
if resp.subid == self.pinned_subid, self.pinned_events.insert(ev) {
|
||||
self.objectWillChange.send()
|
||||
}
|
||||
} else if resp.subid == self.conversations_subid && !conversation_events.contains(ev.id) {
|
||||
guard relay_filtered_correctly(ev, subid: resp.subid) else {
|
||||
break
|
||||
}
|
||||
|
||||
conversation_events.insert(ev.id)
|
||||
} else if resp.subid == self.pinned_subid {
|
||||
guard relay_filtered_correctly(ev, subid: resp.subid) else {
|
||||
break
|
||||
}
|
||||
|
||||
if resp.subid == self.pinned_subid, self.pinned_events.insert(ev) {
|
||||
self.objectWillChange.send()
|
||||
}
|
||||
}
|
||||
case .notice:
|
||||
break
|
||||
|
||||
@@ -19,6 +19,7 @@ enum NostrKind: UInt32, Codable {
|
||||
case like = 7
|
||||
case chat = 42
|
||||
case mute_list = 10000
|
||||
case pinned_notes = 10001
|
||||
case relay_list = 10002
|
||||
case interest_list = 10015
|
||||
case list_deprecated = 30000
|
||||
|
||||
@@ -37,7 +37,7 @@ struct BookmarksView: View {
|
||||
}
|
||||
} else {
|
||||
ScrollView {
|
||||
InnerTimelineView(events: EventHolder(events: bookmarks, incoming: []), damus: state, filter: noneFilter)
|
||||
InnerTimelineView(events: EventHolder(events: bookmarks, incoming: []), pinned_events: EventHolder(), damus: state, filter: noneFilter)
|
||||
}
|
||||
.padding(.bottom, 10 + tabHeight + getSafeAreaBottom())
|
||||
}
|
||||
|
||||
@@ -21,17 +21,21 @@ struct EventView: View {
|
||||
let options: EventViewOptions
|
||||
let damus: DamusState
|
||||
let pubkey: Pubkey
|
||||
let pinned: Set<NoteId>
|
||||
|
||||
init(damus: DamusState, event: NostrEvent, pubkey: Pubkey? = nil, options: EventViewOptions = []) {
|
||||
init(damus: DamusState, event: NostrEvent, pubkey: Pubkey? = nil, pinned: Set<NoteId> = [], options: EventViewOptions = []) {
|
||||
self.event = event
|
||||
self.options = options
|
||||
self.damus = damus
|
||||
self.pubkey = pubkey ?? event.pubkey
|
||||
self.pinned = pinned
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
if event.known_kind == .boost {
|
||||
if pinned.contains(event.id) {
|
||||
PinnedEventView(damus: damus, event: event, options: options)
|
||||
} else if event.known_kind == .boost {
|
||||
if let inner_ev = event.get_inner_event(cache: damus.events) {
|
||||
RepostedEvent(damus: damus, event: event, inner_ev: inner_ev, options: options)
|
||||
} else {
|
||||
|
||||
@@ -98,7 +98,7 @@ struct FollowPackView: View {
|
||||
}
|
||||
|
||||
if tab_selection == FollowPackTabSelection.posts {
|
||||
InnerTimelineView(events: model.events, damus: state, filter: content_filter(event.publicKeys))
|
||||
InnerTimelineView(events: model.events, pinned_events: EventHolder(), damus: state, filter: content_filter(event.publicKeys))
|
||||
}
|
||||
}
|
||||
.onAppear() {
|
||||
|
||||
28
damus/Views/Events/Pinned/PinnedEventView.swift
Normal file
28
damus/Views/Events/Pinned/PinnedEventView.swift
Normal file
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// PinnedEventView.swift
|
||||
// damus
|
||||
//
|
||||
// Created by Terry Yiu on 7/21/25.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct PinnedEventView: View {
|
||||
let damus: DamusState
|
||||
let event: NostrEvent
|
||||
let options: EventViewOptions
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
PinnedHeaderView(damus: damus, pubkey: event.pubkey)
|
||||
.padding(.horizontal)
|
||||
.buttonStyle(PlainButtonStyle())
|
||||
|
||||
TextEvent(damus: damus, event: event, pubkey: event.pubkey, options: options)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
PinnedEventView(damus: test_damus_state, event: test_note, options: [])
|
||||
}
|
||||
33
damus/Views/Events/Pinned/PinnedHeaderView.swift
Normal file
33
damus/Views/Events/Pinned/PinnedHeaderView.swift
Normal file
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// PinnedHeaderView.swift
|
||||
// damus
|
||||
//
|
||||
// Created by Terry Yiu on 7/21/25.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct PinnedHeaderView: View {
|
||||
let damus: DamusState
|
||||
let pubkey: Pubkey
|
||||
|
||||
init(damus: DamusState, pubkey: Pubkey) {
|
||||
self.damus = damus
|
||||
self.pubkey = pubkey
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
HStack(alignment: .center) {
|
||||
Image("pin")
|
||||
.foregroundColor(Color.gray)
|
||||
|
||||
Text("Pinned", comment: "FIXME")
|
||||
.font(.subheadline)
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
PinnedHeaderView(damus: test_damus_state, pubkey: test_pubkey)
|
||||
}
|
||||
@@ -74,7 +74,7 @@ class LoadableNostrEventViewModel: ObservableObject {
|
||||
case .zap, .zap_request:
|
||||
guard let zap = await get_zap(from: ev, state: damus_state) else { return .not_found }
|
||||
return .loaded(route: Route.Zaps(target: zap.target))
|
||||
case .contacts, .metadata, .delete, .boost, .chat, .mute_list, .list_deprecated, .draft, .longform, .nwc_request, .nwc_response, .http_auth, .status, .relay_list, .follow_list, .interest_list:
|
||||
case .contacts, .metadata, .delete, .boost, .chat, .mute_list, .list_deprecated, .draft, .longform, .nwc_request, .nwc_response, .http_auth, .status, .relay_list, .follow_list, .interest_list, .pinned_notes:
|
||||
return .unknown_or_unsupported_kind
|
||||
}
|
||||
case .naddr(let naddr):
|
||||
|
||||
@@ -464,13 +464,13 @@ struct ProfileView: View {
|
||||
.background(colorScheme == .dark ? Color.black : Color.white)
|
||||
|
||||
if filter_state == FilterState.posts {
|
||||
InnerTimelineView(events: profile.events, damus: damus_state, filter: content_filter(FilterState.posts))
|
||||
InnerTimelineView(events: profile.events, pinned_events: profile.pinned_events, damus: damus_state, filter: content_filter(FilterState.posts))
|
||||
}
|
||||
if filter_state == FilterState.posts_and_replies {
|
||||
InnerTimelineView(events: profile.events, damus: damus_state, filter: content_filter(FilterState.posts_and_replies))
|
||||
InnerTimelineView(events: profile.events, pinned_events: profile.pinned_events, damus: damus_state, filter: content_filter(FilterState.posts_and_replies))
|
||||
}
|
||||
if filter_state == FilterState.conversations && !profile.conversation_events.isEmpty {
|
||||
InnerTimelineView(events: profile.events, damus: damus_state, filter: content_filter(FilterState.conversations))
|
||||
InnerTimelineView(events: profile.events, pinned_events: EventHolder(), damus: damus_state, filter: content_filter(FilterState.conversations))
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, Theme.safeAreaInsets?.left)
|
||||
|
||||
@@ -10,11 +10,13 @@ import SwiftUI
|
||||
|
||||
struct InnerTimelineView: View {
|
||||
@ObservedObject var events: EventHolder
|
||||
@ObservedObject var pinned_events: EventHolder
|
||||
let state: DamusState
|
||||
let filter: (NostrEvent) -> Bool
|
||||
|
||||
init(events: EventHolder, damus: DamusState, filter: @escaping (NostrEvent) -> Bool, apply_mute_rules: Bool = true) {
|
||||
init(events: EventHolder, pinned_events: EventHolder, damus: DamusState, filter: @escaping (NostrEvent) -> Bool, apply_mute_rules: Bool = true) {
|
||||
self.events = events
|
||||
self.pinned_events = pinned_events
|
||||
self.state = damus
|
||||
self.filter = apply_mute_rules ? { filter($0) && !damus.mutelist_manager.is_event_muted($0) } : filter
|
||||
}
|
||||
@@ -29,7 +31,7 @@ struct InnerTimelineView: View {
|
||||
|
||||
var body: some View {
|
||||
LazyVStack(spacing: 0) {
|
||||
let events = self.events.events
|
||||
let events = self.pinned_events.events + self.events.events
|
||||
if events.isEmpty {
|
||||
EmptyTimelineView()
|
||||
} else {
|
||||
@@ -38,7 +40,7 @@ struct InnerTimelineView: View {
|
||||
ForEach(indexed, id: \.0.id) { tup in
|
||||
let ev = tup.0
|
||||
let ind = tup.1
|
||||
EventView(damus: state, event: ev, options: event_options)
|
||||
EventView(damus: state, event: ev, pinned: Set(self.pinned_events.events.map { $0.id }), options: event_options)
|
||||
.onTapGesture {
|
||||
let event = ev.get_inner_event(cache: state.events) ?? ev
|
||||
let thread = ThreadModel(event: event, damus_state: state)
|
||||
@@ -69,7 +71,7 @@ struct InnerTimelineView: View {
|
||||
|
||||
struct InnerTimelineView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
InnerTimelineView(events: test_event_holder, damus: test_damus_state, filter: { _ in true })
|
||||
InnerTimelineView(events: test_event_holder, pinned_events: EventHolder(), damus: test_damus_state, filter: { _ in true })
|
||||
.frame(width: 300, height: 500)
|
||||
.border(Color.red)
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ struct TimelineView<Content: View>: View {
|
||||
.id("startblock")
|
||||
.frame(height: 0)
|
||||
|
||||
InnerTimelineView(events: events, damus: damus, filter: loading ? { _ in true } : filter, apply_mute_rules: self.apply_mute_rules)
|
||||
InnerTimelineView(events: events, pinned_events: EventHolder(), damus: damus, filter: loading ? { _ in true } : filter, apply_mute_rules: self.apply_mute_rules)
|
||||
.redacted(reason: loading ? .placeholder : [])
|
||||
.shimmer(loading)
|
||||
.disabled(loading)
|
||||
|
||||
Reference in New Issue
Block a user