Inverse hellthread_notifications_enabled to be hellthread_notifications_disabled and add hellthread_notifications_max_pubkeys setting
Signed-off-by: Terry Yiu <git@tyiu.xyz>
This commit is contained in:
@@ -41,7 +41,7 @@ func should_display_notification(state: HeadlessDamusState, event ev: NostrEvent
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if !state.settings.hellthread_notification && ev.is_hellthread {
|
if state.settings.hellthread_notifications_disabled && ev.is_hellthread(max_pubkeys: state.settings.hellthread_notification_max_pubkeys) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,12 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
// Minimum threshold the hellthread pubkey tag count setting can go down to.
|
||||||
|
let HELLTHREAD_MIN_PUBKEYS: Int = 6
|
||||||
|
|
||||||
|
// Maximum threshold the hellthread pubkey tag count setting can go up to.
|
||||||
|
let HELLTHREAD_MAX_PUBKEYS: Int = 24
|
||||||
|
|
||||||
struct PushNotificationClient {
|
struct PushNotificationClient {
|
||||||
let keypair: Keypair
|
let keypair: Keypair
|
||||||
let settings: UserSettingsStore
|
let settings: UserSettingsStore
|
||||||
@@ -181,10 +187,27 @@ extension PushNotificationClient {
|
|||||||
let reaction_notifications_enabled: Bool?
|
let reaction_notifications_enabled: Bool?
|
||||||
let dm_notifications_enabled: Bool?
|
let dm_notifications_enabled: Bool?
|
||||||
let only_notifications_from_following_enabled: Bool?
|
let only_notifications_from_following_enabled: Bool?
|
||||||
let hellthread_notifications_enabled: Bool?
|
let hellthread_notifications_disabled: Bool?
|
||||||
|
let hellthread_notifications_max_pubkeys: Int?
|
||||||
|
|
||||||
static func from(json_data: Data) -> Self? {
|
static func from(json_data: Data) -> Self? {
|
||||||
guard let decoded = try? JSONDecoder().decode(Self.self, from: json_data) else { return nil }
|
guard let decoded = try? JSONDecoder().decode(Self.self, from: json_data) else { return nil }
|
||||||
|
|
||||||
|
// Normalize hellthread_notifications_max_pubkeys in case
|
||||||
|
// it goes beyond the expected range supported on the client.
|
||||||
|
if let max_pubkeys = decoded.hellthread_notifications_max_pubkeys, max_pubkeys < HELLTHREAD_MIN_PUBKEYS || max_pubkeys > HELLTHREAD_MAX_PUBKEYS {
|
||||||
|
return NotificationSettings(
|
||||||
|
zap_notifications_enabled: decoded.zap_notifications_enabled,
|
||||||
|
mention_notifications_enabled: decoded.mention_notifications_enabled,
|
||||||
|
repost_notifications_enabled: decoded.repost_notifications_enabled,
|
||||||
|
reaction_notifications_enabled: decoded.reaction_notifications_enabled,
|
||||||
|
dm_notifications_enabled: decoded.dm_notifications_enabled,
|
||||||
|
only_notifications_from_following_enabled: decoded.only_notifications_from_following_enabled,
|
||||||
|
hellthread_notifications_disabled: decoded.hellthread_notifications_disabled,
|
||||||
|
hellthread_notifications_max_pubkeys: max(min(HELLTHREAD_MAX_PUBKEYS, max_pubkeys), HELLTHREAD_MIN_PUBKEYS)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return decoded
|
return decoded
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,7 +219,8 @@ extension PushNotificationClient {
|
|||||||
reaction_notifications_enabled: settings.like_notification,
|
reaction_notifications_enabled: settings.like_notification,
|
||||||
dm_notifications_enabled: settings.dm_notification,
|
dm_notifications_enabled: settings.dm_notification,
|
||||||
only_notifications_from_following_enabled: settings.notification_only_from_following,
|
only_notifications_from_following_enabled: settings.notification_only_from_following,
|
||||||
hellthread_notifications_enabled: settings.hellthread_notification
|
hellthread_notifications_disabled: settings.hellthread_notifications_disabled,
|
||||||
|
hellthread_notifications_max_pubkeys: settings.hellthread_notification_max_pubkeys
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -161,8 +161,11 @@ class UserSettingsStore: ObservableObject {
|
|||||||
@Setting(key: "notification_only_from_following", default_value: false)
|
@Setting(key: "notification_only_from_following", default_value: false)
|
||||||
var notification_only_from_following: Bool
|
var notification_only_from_following: Bool
|
||||||
|
|
||||||
@Setting(key: "hellthread_notification", default_value: false)
|
@Setting(key: "hellthread_notifications_disabled", default_value: false)
|
||||||
var hellthread_notification: Bool
|
var hellthread_notifications_disabled: Bool
|
||||||
|
|
||||||
|
@Setting(key: "hellthread_notification_max_pubkeys", default_value: DEFAULT_HELLTHREAD_MAX_PUBKEYS)
|
||||||
|
var hellthread_notification_max_pubkeys: Int
|
||||||
|
|
||||||
@Setting(key: "translate_dms", default_value: false)
|
@Setting(key: "translate_dms", default_value: false)
|
||||||
var translate_dms: Bool
|
var translate_dms: Bool
|
||||||
|
|||||||
@@ -10,16 +10,26 @@ import SwiftUI
|
|||||||
class NotificationFilter: ObservableObject, Equatable {
|
class NotificationFilter: ObservableObject, Equatable {
|
||||||
@Published var state: NotificationFilterState
|
@Published var state: NotificationFilterState
|
||||||
@Published var friend_filter: FriendFilter
|
@Published var friend_filter: FriendFilter
|
||||||
@Published var show_hellthreads: Bool = false
|
@Published var hellthread_notifications_disabled: Bool
|
||||||
|
@Published var hellthread_notification_max_pubkeys: Int
|
||||||
|
|
||||||
static func == (lhs: NotificationFilter, rhs: NotificationFilter) -> Bool {
|
static func == (lhs: NotificationFilter, rhs: NotificationFilter) -> Bool {
|
||||||
return lhs.state == rhs.state && lhs.friend_filter == rhs.friend_filter && lhs.show_hellthreads == rhs.show_hellthreads
|
return lhs.state == rhs.state
|
||||||
|
&& lhs.friend_filter == rhs.friend_filter
|
||||||
|
&& lhs.hellthread_notifications_disabled == rhs.hellthread_notifications_disabled
|
||||||
|
&& lhs.hellthread_notification_max_pubkeys == rhs.hellthread_notification_max_pubkeys
|
||||||
}
|
}
|
||||||
|
|
||||||
init(state: NotificationFilterState = .all, friend_filter: FriendFilter = .all, show_hellthreads: Bool = false) {
|
init(
|
||||||
|
state: NotificationFilterState = .all,
|
||||||
|
friend_filter: FriendFilter = .all,
|
||||||
|
hellthread_notifications_disabled: Bool = false,
|
||||||
|
hellthread_notification_max_pubkeys: Int = DEFAULT_HELLTHREAD_MAX_PUBKEYS
|
||||||
|
) {
|
||||||
self.state = state
|
self.state = state
|
||||||
self.friend_filter = friend_filter
|
self.friend_filter = friend_filter
|
||||||
self.show_hellthreads = show_hellthreads
|
self.hellthread_notifications_disabled = hellthread_notifications_disabled
|
||||||
|
self.hellthread_notification_max_pubkeys = hellthread_notification_max_pubkeys
|
||||||
}
|
}
|
||||||
|
|
||||||
func filter(contacts: Contacts, items: [NotificationItem]) -> [NotificationItem] {
|
func filter(contacts: Contacts, items: [NotificationItem]) -> [NotificationItem] {
|
||||||
@@ -31,7 +41,7 @@ class NotificationFilter: ObservableObject, Equatable {
|
|||||||
|
|
||||||
if let item = item.filter({ ev in
|
if let item = item.filter({ ev in
|
||||||
self.friend_filter.filter(contacts: contacts, pubkey: ev.pubkey) &&
|
self.friend_filter.filter(contacts: contacts, pubkey: ev.pubkey) &&
|
||||||
(show_hellthreads || !ev.is_hellthread)
|
(!hellthread_notifications_disabled || !ev.is_hellthread(max_pubkeys: hellthread_notification_max_pubkeys))
|
||||||
}) {
|
}) {
|
||||||
acc.append(item)
|
acc.append(item)
|
||||||
}
|
}
|
||||||
@@ -71,7 +81,8 @@ struct NotificationsView: View {
|
|||||||
NotificationFilter(
|
NotificationFilter(
|
||||||
state: .all,
|
state: .all,
|
||||||
friend_filter: filter.friend_filter,
|
friend_filter: filter.friend_filter,
|
||||||
show_hellthreads: state.settings.hellthread_notification
|
hellthread_notifications_disabled: state.settings.hellthread_notifications_disabled,
|
||||||
|
hellthread_notification_max_pubkeys: state.settings.hellthread_notification_max_pubkeys
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.tag(NotificationFilterState.all)
|
.tag(NotificationFilterState.all)
|
||||||
@@ -80,7 +91,8 @@ struct NotificationsView: View {
|
|||||||
NotificationFilter(
|
NotificationFilter(
|
||||||
state: .zaps,
|
state: .zaps,
|
||||||
friend_filter: filter.friend_filter,
|
friend_filter: filter.friend_filter,
|
||||||
show_hellthreads: state.settings.hellthread_notification
|
hellthread_notifications_disabled: state.settings.hellthread_notifications_disabled,
|
||||||
|
hellthread_notification_max_pubkeys: state.settings.hellthread_notification_max_pubkeys
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.tag(NotificationFilterState.zaps)
|
.tag(NotificationFilterState.zaps)
|
||||||
@@ -89,7 +101,8 @@ struct NotificationsView: View {
|
|||||||
NotificationFilter(
|
NotificationFilter(
|
||||||
state: .replies,
|
state: .replies,
|
||||||
friend_filter: filter.friend_filter,
|
friend_filter: filter.friend_filter,
|
||||||
show_hellthreads: state.settings.hellthread_notification
|
hellthread_notifications_disabled: state.settings.hellthread_notifications_disabled,
|
||||||
|
hellthread_notification_max_pubkeys: state.settings.hellthread_notification_max_pubkeys
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.tag(NotificationFilterState.replies)
|
.tag(NotificationFilterState.replies)
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ struct NotificationSettingsView: View {
|
|||||||
|
|
||||||
@Environment(\.dismiss) var dismiss
|
@Environment(\.dismiss) var dismiss
|
||||||
|
|
||||||
let hellthread_notification_settings_text = pluralizedString(key: "hellthread_notification_settings", count: MIN_HELLTHREAD_PUBKEYS - 1)
|
|
||||||
|
|
||||||
func indicator_binding(_ val: NewEventsBits) -> Binding<Bool> {
|
func indicator_binding(_ val: NewEventsBits) -> Binding<Bool> {
|
||||||
return Binding.init(get: {
|
return Binding.init(get: {
|
||||||
(settings.notification_indicators & val.rawValue) > 0
|
(settings.notification_indicators & val.rawValue) > 0
|
||||||
@@ -31,6 +29,14 @@ struct NotificationSettingsView: View {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var hellthread_notification_max_pubkeys_binding: Binding<Double> {
|
||||||
|
Binding<Double>(get: {
|
||||||
|
return Double(settings.hellthread_notification_max_pubkeys)
|
||||||
|
}, set: {
|
||||||
|
settings.hellthread_notification_max_pubkeys = Int($0)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func try_to_set_notifications_mode(new_value: UserSettingsStore.NotificationsMode) {
|
func try_to_set_notifications_mode(new_value: UserSettingsStore.NotificationsMode) {
|
||||||
notification_mode_setting_error = nil
|
notification_mode_setting_error = nil
|
||||||
if new_value == .push {
|
if new_value == .push {
|
||||||
@@ -114,6 +120,23 @@ struct NotificationSettingsView: View {
|
|||||||
|
|
||||||
// MARK: - View layout
|
// MARK: - View layout
|
||||||
|
|
||||||
|
func hellthread_notification_settings_text() -> String {
|
||||||
|
if !settings.hellthread_notifications_disabled {
|
||||||
|
return NSLocalizedString("Hide notifications that tag many profiles", comment: "Label for notification settings toggle that hides notifications that tag many people.")
|
||||||
|
}
|
||||||
|
return pluralizedString(key: "hellthread_notifications_disabled", count: $settings.hellthread_notification_max_pubkeys.wrappedValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
var hellthread_notifications_max_pubkeys_view: some View {
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
Slider(
|
||||||
|
value: self.notification_preference_binding(hellthread_notification_max_pubkeys_binding),
|
||||||
|
in: Double(HELLTHREAD_MIN_PUBKEYS)...Double(HELLTHREAD_MAX_PUBKEYS),
|
||||||
|
step: 1
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Form {
|
Form {
|
||||||
if settings.enable_push_notifications {
|
if settings.enable_push_notifications {
|
||||||
@@ -177,8 +200,13 @@ struct NotificationSettingsView: View {
|
|||||||
.toggleStyle(.switch)
|
.toggleStyle(.switch)
|
||||||
Toggle(NSLocalizedString("Show only from users you follow", comment: "Setting to Show notifications only associated to users your follow"), isOn: self.notification_preference_binding($settings.notification_only_from_following))
|
Toggle(NSLocalizedString("Show only from users you follow", comment: "Setting to Show notifications only associated to users your follow"), isOn: self.notification_preference_binding($settings.notification_only_from_following))
|
||||||
.toggleStyle(.switch)
|
.toggleStyle(.switch)
|
||||||
Toggle(hellthread_notification_settings_text, isOn: $settings.hellthread_notification)
|
VStack {
|
||||||
.toggleStyle(.switch)
|
Toggle(hellthread_notification_settings_text(), isOn: self.notification_preference_binding($settings.hellthread_notifications_disabled))
|
||||||
|
.toggleStyle(.switch)
|
||||||
|
if settings.hellthread_notifications_disabled {
|
||||||
|
hellthread_notifications_max_pubkeys_view
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Section(
|
Section(
|
||||||
|
|||||||
@@ -50,6 +50,22 @@
|
|||||||
<string>Following</string>
|
<string>Following</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
|
<key>hellthread_notifications_disabled</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
<string>%#@HELLTHREAD_PROFILES@</string>
|
||||||
|
<key>HELLTHREAD_PROFILES</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
|
<string>NSStringPluralRuleType</string>
|
||||||
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
|
<string>d</string>
|
||||||
|
<key>one</key>
|
||||||
|
<string>Hide notifications that tag more than %d profile</string>
|
||||||
|
<key>other</key>
|
||||||
|
<string>Hide notifications that tag more than %d profiles</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
<key>imports_count</key>
|
<key>imports_count</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
@@ -82,22 +98,6 @@
|
|||||||
<string>%2$@ and %1$d others reposted</string>
|
<string>%2$@ and %1$d others reposted</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>hellthread_notification_settings</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
|
||||||
<string>%#@HELLTHREAD_PROFILES@</string>
|
|
||||||
<key>HELLTHREAD_PROFILES</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringFormatSpecTypeKey</key>
|
|
||||||
<string>NSStringPluralRuleType</string>
|
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
|
||||||
<string>d</string>
|
|
||||||
<key>one</key>
|
|
||||||
<string>Show notifications that mention more than %d profile</string>
|
|
||||||
<key>other</key>
|
|
||||||
<string>Show notifications that mention more than %d profiles</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>quoted_reposts_count</key>
|
<key>quoted_reposts_count</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ final class LargeEventTests: XCTestCase {
|
|||||||
|
|
||||||
XCTAssertEqual(subid, "subid")
|
XCTAssertEqual(subid, "subid")
|
||||||
XCTAssertTrue(ev.should_show_event)
|
XCTAssertTrue(ev.should_show_event)
|
||||||
XCTAssertTrue(ev.is_hellthread)
|
XCTAssertTrue(ev.is_hellthread(max_pubkeys: 10))
|
||||||
XCTAssertTrue(validate_event(ev: ev) == .ok)
|
XCTAssertTrue(validate_event(ev: ev) == .ok)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ final class LocalizationUtilTests: XCTestCase {
|
|||||||
let keys = [
|
let keys = [
|
||||||
["followers_count", "Followers", "Follower", "Followers"],
|
["followers_count", "Followers", "Follower", "Followers"],
|
||||||
["following_count", "Following", "Following", "Following"],
|
["following_count", "Following", "Following", "Following"],
|
||||||
|
["hellthread_notifications_disabled", "Hide notifications that tag more than 0 profiles", "Hide notifications that tag more than 1 profile", "Hide notifications that tag more than 2 profiles"],
|
||||||
["imports_count", "Imports", "Import", "Imports"],
|
["imports_count", "Imports", "Import", "Imports"],
|
||||||
["hellthread_notification_settings", "Show notifications that mention more than 0 profiles", "Show notifications that mention more than 1 profile", "Show notifications that mention more than 2 profiles"],
|
|
||||||
["quoted_reposts_count", "Quotes", "Quote", "Quotes"],
|
["quoted_reposts_count", "Quotes", "Quote", "Quotes"],
|
||||||
["reactions_count", "Reactions", "Reaction", "Reactions"],
|
["reactions_count", "Reactions", "Reaction", "Reactions"],
|
||||||
["relays_count", "Relays", "Relay", "Relays"],
|
["relays_count", "Relays", "Relay", "Relays"],
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ import secp256k1_implementation
|
|||||||
import CryptoKit
|
import CryptoKit
|
||||||
|
|
||||||
let MAX_NOTE_SIZE: Int = 2 << 18
|
let MAX_NOTE_SIZE: Int = 2 << 18
|
||||||
let MIN_HELLTHREAD_PUBKEYS = 11
|
|
||||||
|
// Default threshold of the hellthread pubkey tag count setting if it is not set.
|
||||||
|
let DEFAULT_HELLTHREAD_MAX_PUBKEYS: Int = 10
|
||||||
|
|
||||||
struct NdbStr {
|
struct NdbStr {
|
||||||
let note: NdbNote
|
let note: NdbNote
|
||||||
@@ -300,10 +302,10 @@ extension NdbNote {
|
|||||||
return !too_big
|
return !too_big
|
||||||
}
|
}
|
||||||
|
|
||||||
var is_hellthread: Bool {
|
func is_hellthread(max_pubkeys: Int) -> Bool {
|
||||||
switch known_kind {
|
switch known_kind {
|
||||||
case .text, .boost, .like, .zap:
|
case .text, .boost, .like, .zap:
|
||||||
Set(referenced_pubkeys).count >= MIN_HELLTHREAD_PUBKEYS
|
Set(referenced_pubkeys).count > max_pubkeys
|
||||||
default:
|
default:
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user