diff --git a/damus/Features/Timeline/Views/InnerTimelineView.swift b/damus/Features/Timeline/Views/InnerTimelineView.swift index 0e572f8f..51c8f82d 100644 --- a/damus/Features/Timeline/Views/InnerTimelineView.swift +++ b/damus/Features/Timeline/Views/InnerTimelineView.swift @@ -9,14 +9,18 @@ import SwiftUI struct InnerTimelineView: View { - @ObservedObject var events: EventHolder + var events: EventHolder + @ObservedObject var filteredEvents: EventHolder.FilteredHolder + var filteredEventHolderId: UUID let state: DamusState - let filter: (NostrEvent) -> Bool init(events: EventHolder, damus: DamusState, filter: @escaping (NostrEvent) -> Bool, apply_mute_rules: Bool = true) { self.events = events self.state = damus - self.filter = apply_mute_rules ? { filter($0) && !damus.mutelist_manager.is_event_muted($0) } : filter + let filter = apply_mute_rules ? { filter($0) && !damus.mutelist_manager.is_event_muted($0) } : filter + let filteredEvents = EventHolder.FilteredHolder(filter: filter) + self.filteredEvents = filteredEvents + self.filteredEventHolderId = events.add(filteredHolder: filteredEvents) } var event_options: EventViewOptions { @@ -29,12 +33,11 @@ struct InnerTimelineView: View { var body: some View { LazyVStack(spacing: 0) { - let events = self.events.events + let events = self.filteredEvents.events if events.isEmpty { EmptyTimelineView() } else { - let evs = events.filter(filter) - let indexed = Array(zip(evs, 0...)) + let indexed = Array(zip(events, 0...)) ForEach(indexed, id: \.0.id) { tup in let ev = tup.0 let ind = tup.1 @@ -62,6 +65,9 @@ struct InnerTimelineView: View { } } } + .onDisappear { + self.events.removeFilteredHolder(id: self.filteredEventHolderId) + } //.padding(.horizontal) } diff --git a/damus/Shared/Utilities/EventHolder.swift b/damus/Shared/Utilities/EventHolder.swift index 995a6c6e..24026167 100644 --- a/damus/Shared/Utilities/EventHolder.swift +++ b/damus/Shared/Utilities/EventHolder.swift @@ -11,6 +11,7 @@ import Foundation class EventHolder: ObservableObject, ScrollQueue { private var has_event = Set() @Published var events: [NostrEvent] + var filteredHolders: [UUID: FilteredHolder] = [:] var incoming: [NostrEvent] private(set) var should_queue = false var on_queue: ((NostrEvent) -> Void)? @@ -58,6 +59,9 @@ class EventHolder: ObservableObject, ScrollQueue { if insert_uniq_sorted_event_created(events: &self.events, new_ev: ev) { return true } + for (id, filteredView) in self.filteredHolders { + filteredView.insert(event: ev) + } return false } @@ -85,6 +89,9 @@ class EventHolder: ObservableObject, ScrollQueue { if insert_uniq_sorted_event_created(events: &events, new_ev: event) { changed = true } + for (id, filteredHolder) in self.filteredHolders { + filteredHolder.insert(event: event) + } } if changed { @@ -100,5 +107,46 @@ class EventHolder: ObservableObject, ScrollQueue { func reset() { self.incoming = [] self.events = [] + for (id, filteredHolder) in filteredHolders { + filteredHolder.update(events: []) + } + } + + @MainActor + func add(filteredHolder: FilteredHolder) -> UUID { + let id = UUID() + self.filteredHolders[id] = filteredHolder + filteredHolder.update(events: self.events) + return id + } + + @MainActor + func removeFilteredHolder(id: UUID) { + self.filteredHolders[id] = nil + } + + class FilteredHolder: ObservableObject { + @Published private(set) var events: [NostrEvent] + let filter: (NostrEvent) -> Bool + + init(filter: @escaping (NostrEvent) -> Bool) { + self.events = [] + self.filter = filter + } + + func update(events: [NostrEvent]) { + self.events = events.filter(self.filter) + } + + func insert(event: NostrEvent) { + guard self.filter(event) else { return } + var changed = false + if insert_uniq_sorted_event_created(events: &events, new_ev: event) { + changed = true + } + if changed { + self.objectWillChange.send() + } + } } }