Friends filter for notifications
Changelog-Added: Friends filter for notifications
This commit is contained in:
@@ -143,6 +143,7 @@
|
|||||||
4C8D00CF29E38B950036AF10 /* nostr_bech32.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C8D00CE29E38B950036AF10 /* nostr_bech32.c */; };
|
4C8D00CF29E38B950036AF10 /* nostr_bech32.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C8D00CE29E38B950036AF10 /* nostr_bech32.c */; };
|
||||||
4C8D00D429E3C5D40036AF10 /* NIP19Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8D00D329E3C5D40036AF10 /* NIP19Tests.swift */; };
|
4C8D00D429E3C5D40036AF10 /* NIP19Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8D00D329E3C5D40036AF10 /* NIP19Tests.swift */; };
|
||||||
4C8D1A6C29F1DFC200ACDF75 /* FriendIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8D1A6B29F1DFC200ACDF75 /* FriendIcon.swift */; };
|
4C8D1A6C29F1DFC200ACDF75 /* FriendIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8D1A6B29F1DFC200ACDF75 /* FriendIcon.swift */; };
|
||||||
|
4C8D1A6F29F31E5000ACDF75 /* FriendsButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8D1A6E29F31E5000ACDF75 /* FriendsButton.swift */; };
|
||||||
4C8EC52529D1FA6C0085D9A8 /* DamusColors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8EC52429D1FA6C0085D9A8 /* DamusColors.swift */; };
|
4C8EC52529D1FA6C0085D9A8 /* DamusColors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C8EC52429D1FA6C0085D9A8 /* DamusColors.swift */; };
|
||||||
4C90BD18283A9EE5008EE7EF /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C90BD17283A9EE5008EE7EF /* LoginView.swift */; };
|
4C90BD18283A9EE5008EE7EF /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C90BD17283A9EE5008EE7EF /* LoginView.swift */; };
|
||||||
4C90BD1A283AA67F008EE7EF /* Bech32.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C90BD19283AA67F008EE7EF /* Bech32.swift */; };
|
4C90BD1A283AA67F008EE7EF /* Bech32.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C90BD19283AA67F008EE7EF /* Bech32.swift */; };
|
||||||
@@ -550,6 +551,7 @@
|
|||||||
4C8D00D229E3C19F0036AF10 /* str_block.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = str_block.h; sourceTree = "<group>"; };
|
4C8D00D229E3C19F0036AF10 /* str_block.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = str_block.h; sourceTree = "<group>"; };
|
||||||
4C8D00D329E3C5D40036AF10 /* NIP19Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NIP19Tests.swift; sourceTree = "<group>"; };
|
4C8D00D329E3C5D40036AF10 /* NIP19Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NIP19Tests.swift; sourceTree = "<group>"; };
|
||||||
4C8D1A6B29F1DFC200ACDF75 /* FriendIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FriendIcon.swift; sourceTree = "<group>"; };
|
4C8D1A6B29F1DFC200ACDF75 /* FriendIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FriendIcon.swift; sourceTree = "<group>"; };
|
||||||
|
4C8D1A6E29F31E5000ACDF75 /* FriendsButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FriendsButton.swift; sourceTree = "<group>"; };
|
||||||
4C8EC52429D1FA6C0085D9A8 /* DamusColors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusColors.swift; sourceTree = "<group>"; };
|
4C8EC52429D1FA6C0085D9A8 /* DamusColors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusColors.swift; sourceTree = "<group>"; };
|
||||||
4C90BD17283A9EE5008EE7EF /* LoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginView.swift; sourceTree = "<group>"; };
|
4C90BD17283A9EE5008EE7EF /* LoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginView.swift; sourceTree = "<group>"; };
|
||||||
4C90BD19283AA67F008EE7EF /* Bech32.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bech32.swift; sourceTree = "<group>"; };
|
4C90BD19283AA67F008EE7EF /* Bech32.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bech32.swift; sourceTree = "<group>"; };
|
||||||
@@ -881,6 +883,7 @@
|
|||||||
4C75EFA227FA576C0006080F /* Views */ = {
|
4C75EFA227FA576C0006080F /* Views */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
4C8D1A6D29F31E4100ACDF75 /* Buttons */,
|
||||||
4C1A9A1B29DDCF8B00516EAC /* Settings */,
|
4C1A9A1B29DDCF8B00516EAC /* Settings */,
|
||||||
4CFF8F6129CC9A80008DB934 /* Images */,
|
4CFF8F6129CC9A80008DB934 /* Images */,
|
||||||
4CCEB7AC29B53D180078AA28 /* Search */,
|
4CCEB7AC29B53D180078AA28 /* Search */,
|
||||||
@@ -1009,6 +1012,14 @@
|
|||||||
path = Util;
|
path = Util;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
4C8D1A6D29F31E4100ACDF75 /* Buttons */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
4C8D1A6E29F31E5000ACDF75 /* FriendsButton.swift */,
|
||||||
|
);
|
||||||
|
path = Buttons;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
4CAAD8AE29888A9B00060CEA /* Relays */ = {
|
4CAAD8AE29888A9B00060CEA /* Relays */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -1535,6 +1546,7 @@
|
|||||||
4CF0ABF029857E9200D66079 /* Bech32Object.swift in Sources */,
|
4CF0ABF029857E9200D66079 /* Bech32Object.swift in Sources */,
|
||||||
4C3D52B8298DB5C6001C5831 /* TextEvent.swift in Sources */,
|
4C3D52B8298DB5C6001C5831 /* TextEvent.swift in Sources */,
|
||||||
4C216F362870A9A700040376 /* InputDismissKeyboard.swift in Sources */,
|
4C216F362870A9A700040376 /* InputDismissKeyboard.swift in Sources */,
|
||||||
|
4C8D1A6F29F31E5000ACDF75 /* FriendsButton.swift in Sources */,
|
||||||
4C216F382871EDE300040376 /* DirectMessageModel.swift in Sources */,
|
4C216F382871EDE300040376 /* DirectMessageModel.swift in Sources */,
|
||||||
4C75EFA627FF87A20006080F /* Nostr.swift in Sources */,
|
4C75EFA627FF87A20006080F /* Nostr.swift in Sources */,
|
||||||
4CB883A62975F83C00DC99E7 /* LNUrlPayRequest.swift in Sources */,
|
4CB883A62975F83C00DC99E7 /* LNUrlPayRequest.swift in Sources */,
|
||||||
|
|||||||
@@ -29,4 +29,22 @@ class EventGroup {
|
|||||||
func insert(_ ev: NostrEvent) -> Bool {
|
func insert(_ ev: NostrEvent) -> Bool {
|
||||||
return insert_uniq_sorted_event_created(events: &events, new_ev: ev)
|
return insert_uniq_sorted_event_created(events: &events, new_ev: ev)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func would_filter(_ isIncluded: (NostrEvent) -> Bool) -> Bool {
|
||||||
|
for ev in events {
|
||||||
|
if !isIncluded(ev) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func filter(_ isIncluded: (NostrEvent) -> Bool) -> EventGroup? {
|
||||||
|
let new_evs = events.filter(isIncluded)
|
||||||
|
guard new_evs.count > 0 else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return EventGroup(events: new_evs)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,10 +30,26 @@ class ZapGroup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init(zaps: [Zap]) {
|
func would_filter(_ isIncluded: (NostrEvent) -> Bool) -> Bool {
|
||||||
self.zaps = zaps
|
for zap in zaps {
|
||||||
self.msat_total = 0
|
if !isIncluded(zap.request_ev) {
|
||||||
self.zappers = Set()
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func filter(_ isIncluded: (NostrEvent) -> Bool) -> ZapGroup? {
|
||||||
|
let new_zaps = zaps.filter { isIncluded($0.request_ev) }
|
||||||
|
guard new_zaps.count > 0 else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
let grp = ZapGroup()
|
||||||
|
for zap in new_zaps {
|
||||||
|
grp.insert(zap)
|
||||||
|
}
|
||||||
|
return grp
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
@@ -42,6 +58,7 @@ class ZapGroup {
|
|||||||
self.zappers = Set()
|
self.zappers = Set()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
func insert(_ zap: Zap) -> Bool {
|
func insert(_ zap: Zap) -> Bool {
|
||||||
if !insert_uniq_sorted_zap_by_created(zaps: &zaps, new_zap: zap) {
|
if !insert_uniq_sorted_zap_by_created(zaps: &zaps, new_zap: zap) {
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -65,6 +65,37 @@ enum NotificationItem {
|
|||||||
return reply.created_at
|
return reply.created_at
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func would_filter(_ isIncluded: (NostrEvent) -> Bool) -> Bool {
|
||||||
|
switch self {
|
||||||
|
case .repost(_, let evgrp):
|
||||||
|
return evgrp.would_filter(isIncluded)
|
||||||
|
case .reaction(_, let evgrp):
|
||||||
|
return evgrp.would_filter(isIncluded)
|
||||||
|
case .profile_zap(let zapgrp):
|
||||||
|
return zapgrp.would_filter(isIncluded)
|
||||||
|
case .event_zap(_, let zapgrp):
|
||||||
|
return zapgrp.would_filter(isIncluded)
|
||||||
|
case .reply(let ev):
|
||||||
|
return !isIncluded(ev)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func filter(_ isIncluded: (NostrEvent) -> Bool) -> NotificationItem? {
|
||||||
|
switch self {
|
||||||
|
case .repost(let evid, let evgrp):
|
||||||
|
return evgrp.filter(isIncluded).map { .repost(evid, $0) }
|
||||||
|
case .reaction(let evid, let evgrp):
|
||||||
|
return evgrp.filter(isIncluded).map { .reaction(evid, $0) }
|
||||||
|
case .profile_zap(let zapgrp):
|
||||||
|
return zapgrp.filter(isIncluded).map { .profile_zap($0) }
|
||||||
|
case .event_zap(let evid, let zapgrp):
|
||||||
|
return zapgrp.filter(isIncluded).map { .event_zap(evid, $0) }
|
||||||
|
case .reply(let ev):
|
||||||
|
if isIncluded(ev) { return .reply(ev) }
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class NotificationsModel: ObservableObject, ScrollQueue {
|
class NotificationsModel: ObservableObject, ScrollQueue {
|
||||||
|
|||||||
@@ -52,6 +52,10 @@ struct Zap {
|
|||||||
public let is_anon: Bool
|
public let is_anon: Bool
|
||||||
public let private_request: NostrEvent?
|
public let private_request: NostrEvent?
|
||||||
|
|
||||||
|
var request_ev: NostrEvent {
|
||||||
|
return private_request ?? self.request.ev
|
||||||
|
}
|
||||||
|
|
||||||
public static func from_zap_event(zap_ev: NostrEvent, zapper: String, our_privkey: String?) -> Zap? {
|
public static func from_zap_event(zap_ev: NostrEvent, zapper: String, our_privkey: String?) -> Zap? {
|
||||||
/// Make sure that we only create a zap event if it is authorized by the profile or event
|
/// Make sure that we only create a zap event if it is authorized by the profile or event
|
||||||
guard zapper == zap_ev.pubkey else {
|
guard zapper == zap_ev.pubkey else {
|
||||||
|
|||||||
39
damus/Views/Buttons/FriendsButton.swift
Normal file
39
damus/Views/Buttons/FriendsButton.swift
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
//
|
||||||
|
// FriendsButton.swift
|
||||||
|
// damus
|
||||||
|
//
|
||||||
|
// Created by William Casarin on 2023-04-21.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct FriendsButton: View {
|
||||||
|
@Binding var enabled: Bool
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
Button(action: {
|
||||||
|
self.enabled.toggle()
|
||||||
|
}) {
|
||||||
|
if enabled {
|
||||||
|
LINEAR_GRADIENT
|
||||||
|
.mask(Image(systemName: "person.2.fill")
|
||||||
|
.resizable()
|
||||||
|
).frame(width: 30, height: 20)
|
||||||
|
} else {
|
||||||
|
Image(systemName: "person.2.fill")
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 30, height: 20)
|
||||||
|
.foregroundColor(DamusColors.adaptableGrey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.buttonStyle(.plain)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FriendsButton_Previews: PreviewProvider {
|
||||||
|
@State static var enabled: Bool = false
|
||||||
|
|
||||||
|
static var previews: some View {
|
||||||
|
FriendsButton(enabled: $enabled)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,69 @@
|
|||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
|
enum FineNotificationFilter: String {
|
||||||
|
case all
|
||||||
|
case friends
|
||||||
|
|
||||||
|
func filter(contacts: Contacts, pubkey: String) -> Bool {
|
||||||
|
switch self {
|
||||||
|
case .all:
|
||||||
|
return true
|
||||||
|
case .friends:
|
||||||
|
return contacts.is_in_friendosphere(pubkey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NotificationFilter: ObservableObject, Equatable {
|
||||||
|
@Published var state: NotificationFilterState
|
||||||
|
@Published var fine_filter: FineNotificationFilter
|
||||||
|
|
||||||
|
static func == (lhs: NotificationFilter, rhs: NotificationFilter) -> Bool {
|
||||||
|
return lhs.state == rhs.state && lhs.fine_filter == rhs.fine_filter
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
self.state = .all
|
||||||
|
self.fine_filter = .all
|
||||||
|
}
|
||||||
|
|
||||||
|
init(state: NotificationFilterState, fine_filter: FineNotificationFilter) {
|
||||||
|
self.state = state
|
||||||
|
self.fine_filter = fine_filter
|
||||||
|
}
|
||||||
|
|
||||||
|
func toggle_fine_filter() {
|
||||||
|
switch self.fine_filter {
|
||||||
|
case .all:
|
||||||
|
self.fine_filter = .friends
|
||||||
|
case .friends:
|
||||||
|
self.fine_filter = .all
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var fine_filter_binding: Binding<Bool> {
|
||||||
|
Binding(get: {
|
||||||
|
return self.fine_filter == .friends
|
||||||
|
}, set: { v in
|
||||||
|
self.fine_filter = v ? .friends : .all
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func filter(contacts: Contacts, items: [NotificationItem]) -> [NotificationItem] {
|
||||||
|
|
||||||
|
return items.reduce(into: []) { acc, item in
|
||||||
|
if !self.state.filter(item) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if let item = item.filter({ self.fine_filter.filter(contacts: contacts, pubkey: $0.pubkey) }) {
|
||||||
|
acc.append(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum NotificationFilterState: String {
|
enum NotificationFilterState: String {
|
||||||
case all
|
case all
|
||||||
case zaps
|
case zaps
|
||||||
@@ -31,7 +94,7 @@ enum NotificationFilterState: String {
|
|||||||
struct NotificationsView: View {
|
struct NotificationsView: View {
|
||||||
let state: DamusState
|
let state: DamusState
|
||||||
@ObservedObject var notifications: NotificationsModel
|
@ObservedObject var notifications: NotificationsModel
|
||||||
@State var filter_state: NotificationFilterState = .all
|
@StateObject var filter_state: NotificationFilter = NotificationFilter()
|
||||||
|
|
||||||
@Environment(\.colorScheme) var colorScheme
|
@Environment(\.colorScheme) var colorScheme
|
||||||
|
|
||||||
@@ -44,28 +107,55 @@ struct NotificationsView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
TabView(selection: $filter_state) {
|
TabView(selection: $filter_state.state) {
|
||||||
|
// This is needed or else there is a bug when switching from the 3rd or 2nd tab to first. no idea why.
|
||||||
mystery
|
mystery
|
||||||
|
|
||||||
// This is needed or else there is a bug when switching from the 3rd or 2nd tab to first. no idea why.
|
NotificationTab(
|
||||||
NotificationTab(NotificationFilterState.all)
|
NotificationFilter(
|
||||||
.tag(NotificationFilterState.all)
|
state: .all,
|
||||||
|
fine_filter: filter_state.fine_filter
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.tag(NotificationFilterState.all)
|
||||||
|
|
||||||
NotificationTab(NotificationFilterState.zaps)
|
NotificationTab(
|
||||||
.tag(NotificationFilterState.zaps)
|
NotificationFilter(
|
||||||
|
state: .zaps,
|
||||||
|
fine_filter: filter_state.fine_filter
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.tag(NotificationFilterState.zaps)
|
||||||
|
|
||||||
NotificationTab(NotificationFilterState.replies)
|
NotificationTab(
|
||||||
.tag(NotificationFilterState.replies)
|
NotificationFilter(
|
||||||
|
state: .replies,
|
||||||
|
fine_filter: filter_state.fine_filter
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.tag(NotificationFilterState.replies)
|
||||||
}
|
}
|
||||||
.onChange(of: filter_state) { val in
|
.toolbar {
|
||||||
|
ToolbarItem(placement: .navigationBarTrailing) {
|
||||||
|
if would_filter_non_friends_from_notifications(contacts: state.contacts, state: self.filter_state.state, items: self.notifications.notifications) {
|
||||||
|
FriendsButton(enabled: self.filter_state.fine_filter_binding)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onChange(of: filter_state.fine_filter) { val in
|
||||||
|
save_friend_filter(pubkey: state.pubkey, filter: val)
|
||||||
|
}
|
||||||
|
.onChange(of: filter_state.state) { val in
|
||||||
save_notification_filter_state(pubkey: state.pubkey, state: val)
|
save_notification_filter_state(pubkey: state.pubkey, state: val)
|
||||||
}
|
}
|
||||||
.onAppear {
|
.onAppear {
|
||||||
self.filter_state = load_notification_filter_state(pubkey: state.pubkey)
|
let state = load_notification_filter_state(pubkey: state.pubkey)
|
||||||
|
self.filter_state.fine_filter = state.fine_filter
|
||||||
|
self.filter_state.state = state.state
|
||||||
}
|
}
|
||||||
.safeAreaInset(edge: .top, spacing: 0) {
|
.safeAreaInset(edge: .top, spacing: 0) {
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
CustomPicker(selection: $filter_state, content: {
|
CustomPicker(selection: $filter_state.state, content: {
|
||||||
Text("All", comment: "Label for filter for all notifications.")
|
Text("All", comment: "Label for filter for all notifications.")
|
||||||
.tag(NotificationFilterState.all)
|
.tag(NotificationFilterState.all)
|
||||||
|
|
||||||
@@ -83,14 +173,14 @@ struct NotificationsView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NotificationTab(_ filter: NotificationFilterState) -> some View {
|
func NotificationTab(_ filter: NotificationFilter) -> some View {
|
||||||
ScrollViewReader { scroller in
|
ScrollViewReader { scroller in
|
||||||
ScrollView {
|
ScrollView {
|
||||||
LazyVStack(alignment: .leading) {
|
LazyVStack(alignment: .leading) {
|
||||||
Color.white.opacity(0)
|
Color.white.opacity(0)
|
||||||
.id("startblock")
|
.id("startblock")
|
||||||
.frame(height: 5)
|
.frame(height: 5)
|
||||||
ForEach(notifications.notifications.filter(filter.filter), id: \.id) { item in
|
ForEach(filter.filter(contacts: state.contacts, items: notifications.notifications), id: \.id) { item in
|
||||||
NotificationItemView(state: state, item: item)
|
NotificationItemView(state: state, item: item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,7 +206,7 @@ struct NotificationsView: View {
|
|||||||
|
|
||||||
struct NotificationsView_Previews: PreviewProvider {
|
struct NotificationsView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
NotificationsView(state: test_damus_state(), notifications: NotificationsModel(), filter_state: NotificationFilterState.all)
|
NotificationsView(state: test_damus_state(), notifications: NotificationsModel(), filter_state: NotificationFilter())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,22 +214,48 @@ func notification_filter_state_key(pubkey: String) -> String {
|
|||||||
return pk_setting_key(pubkey, key: "notification_filter_state")
|
return pk_setting_key(pubkey, key: "notification_filter_state")
|
||||||
}
|
}
|
||||||
|
|
||||||
func load_notification_filter_state(pubkey: String) -> NotificationFilterState {
|
func friend_filter_key(pubkey: String) -> String {
|
||||||
|
return pk_setting_key(pubkey, key: "friend_filter")
|
||||||
|
}
|
||||||
|
|
||||||
|
func load_notification_filter_state(pubkey: String) -> NotificationFilter {
|
||||||
let key = notification_filter_state_key(pubkey: pubkey)
|
let key = notification_filter_state_key(pubkey: pubkey)
|
||||||
|
let fine_key = friend_filter_key(pubkey: pubkey)
|
||||||
|
|
||||||
guard let state_str = UserDefaults.standard.string(forKey: key) else {
|
let state_str = UserDefaults.standard.string(forKey: key)
|
||||||
return .all
|
let state = (state_str.flatMap { NotificationFilterState(rawValue: $0) }) ?? .all
|
||||||
}
|
|
||||||
|
|
||||||
guard let state = NotificationFilterState(rawValue: state_str) else {
|
let filter_str = UserDefaults.standard.string(forKey: fine_key)
|
||||||
return .all
|
let filter = (filter_str.flatMap { FineNotificationFilter(rawValue: $0) } ) ?? .all
|
||||||
}
|
|
||||||
|
|
||||||
return state
|
return NotificationFilter(state: state, fine_filter: filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func save_notification_filter_state(pubkey: String, state: NotificationFilterState) {
|
func save_notification_filter_state(pubkey: String, state: NotificationFilterState) {
|
||||||
let key = notification_filter_state_key(pubkey: pubkey)
|
let key = notification_filter_state_key(pubkey: pubkey)
|
||||||
|
|
||||||
UserDefaults.standard.set(state.rawValue, forKey: key)
|
UserDefaults.standard.set(state.rawValue, forKey: key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func save_friend_filter(pubkey: String, filter: FineNotificationFilter) {
|
||||||
|
let key = friend_filter_key(pubkey: pubkey)
|
||||||
|
|
||||||
|
UserDefaults.standard.set(filter.rawValue, forKey: key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func would_filter_non_friends_from_notifications(contacts: Contacts, state: NotificationFilterState, items: [NotificationItem]) -> Bool {
|
||||||
|
for item in items {
|
||||||
|
// this is only valid depending on which tab we're looking at
|
||||||
|
if !state.filter(item) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if item.would_filter({ ev in FineNotificationFilter.friends.filter(contacts: contacts, pubkey: ev.pubkey) }) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user