Merge branch 'release_1.10'
This commit is contained in:
@@ -55,6 +55,9 @@ struct NotificationFormatter {
|
|||||||
var identifier = ""
|
var identifier = ""
|
||||||
|
|
||||||
switch notify.type {
|
switch notify.type {
|
||||||
|
case .tagged:
|
||||||
|
title = String(format: NSLocalizedString("Tagged by %@", comment: "Tagged by heading in local notification"), displayName)
|
||||||
|
identifier = "myMentionNotification"
|
||||||
case .mention:
|
case .mention:
|
||||||
title = String(format: NSLocalizedString("Mentioned by %@", comment: "Mentioned by heading in local notification"), displayName)
|
title = String(format: NSLocalizedString("Mentioned by %@", comment: "Mentioned by heading in local notification"), displayName)
|
||||||
identifier = "myMentionNotification"
|
identifier = "myMentionNotification"
|
||||||
@@ -90,10 +93,11 @@ struct NotificationFormatter {
|
|||||||
|
|
||||||
// If it does not work, try async formatting methods
|
// If it does not work, try async formatting methods
|
||||||
let content = UNMutableNotificationContent()
|
let content = UNMutableNotificationContent()
|
||||||
|
|
||||||
switch notify.type {
|
switch notify.type {
|
||||||
case .zap, .profile_zap:
|
case .zap, .profile_zap:
|
||||||
guard let zap = await get_zap(from: notify.event, state: state) else {
|
guard let zap = await get_zap(from: notify.event, state: state) else {
|
||||||
|
Log.debug("format_message: async get_zap failed", for: .push_notifications)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
content.title = Self.zap_notification_title(zap)
|
content.title = Self.zap_notification_title(zap)
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ class NotificationService: UNNotificationServiceExtension {
|
|||||||
// Log that we got a push notification
|
// Log that we got a push notification
|
||||||
Log.debug("Got nostr event push notification from pubkey %s", for: .push_notifications, nostr_event.pubkey.hex())
|
Log.debug("Got nostr event push notification from pubkey %s", for: .push_notifications, nostr_event.pubkey.hex())
|
||||||
|
|
||||||
guard let state = NotificationExtensionState(),
|
guard let state = NotificationExtensionState() else {
|
||||||
let display_name = state.ndb.lookup_profile(nostr_event.pubkey)?.unsafeUnownedValue?.profile?.display_name // We are not holding the txn here.
|
Log.debug("Failed to open nostrdb", for: .push_notifications)
|
||||||
else {
|
|
||||||
// Something failed to initialize so let's go for the next best thing
|
// Something failed to initialize so let's go for the next best thing
|
||||||
guard let improved_content = NotificationFormatter.shared.format_message(event: nostr_event) else {
|
guard let improved_content = NotificationFormatter.shared.format_message(event: nostr_event) else {
|
||||||
// We cannot format this nostr event. Suppress notification.
|
// We cannot format this nostr event. Suppress notification.
|
||||||
@@ -39,7 +39,11 @@ class NotificationService: UNNotificationServiceExtension {
|
|||||||
contentHandler(improved_content)
|
contentHandler(improved_content)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let txn = state.ndb.lookup_profile(nostr_event.pubkey)
|
||||||
|
let profile = txn?.unsafeUnownedValue?.profile
|
||||||
|
let name = Profile.displayName(profile: profile, pubkey: nostr_event.pubkey).displayName
|
||||||
|
|
||||||
// Don't show notification details that match mute list.
|
// Don't show notification details that match mute list.
|
||||||
// TODO: Remove this code block once we get notification suppression entitlement from Apple. It will be covered by the `guard should_display_notification` block
|
// TODO: Remove this code block once we get notification suppression entitlement from Apple. It will be covered by the `guard should_display_notification` block
|
||||||
if state.mutelist_manager.is_event_muted(nostr_event) {
|
if state.mutelist_manager.is_event_muted(nostr_event) {
|
||||||
@@ -54,6 +58,7 @@ class NotificationService: UNNotificationServiceExtension {
|
|||||||
}
|
}
|
||||||
|
|
||||||
guard should_display_notification(state: state, event: nostr_event, mode: .push) else {
|
guard should_display_notification(state: state, event: nostr_event, mode: .push) else {
|
||||||
|
Log.debug("should_display_notification failed", for: .push_notifications)
|
||||||
// We should not display notification for this event. Suppress notification.
|
// We should not display notification for this event. Suppress notification.
|
||||||
// contentHandler(UNNotificationContent())
|
// contentHandler(UNNotificationContent())
|
||||||
// TODO: We cannot really suppress until we have the notification supression entitlement. Show the raw notification
|
// TODO: We cannot really suppress until we have the notification supression entitlement. Show the raw notification
|
||||||
@@ -62,6 +67,7 @@ class NotificationService: UNNotificationServiceExtension {
|
|||||||
}
|
}
|
||||||
|
|
||||||
guard let notification_object = generate_local_notification_object(from: nostr_event, state: state) else {
|
guard let notification_object = generate_local_notification_object(from: nostr_event, state: state) else {
|
||||||
|
Log.debug("generate_local_notification_object failed", for: .push_notifications)
|
||||||
// We could not process this notification. Probably an unsupported nostr event kind. Suppress.
|
// We could not process this notification. Probably an unsupported nostr event kind. Suppress.
|
||||||
// contentHandler(UNNotificationContent())
|
// contentHandler(UNNotificationContent())
|
||||||
// TODO: We cannot really suppress until we have the notification supression entitlement. Show the raw notification
|
// TODO: We cannot really suppress until we have the notification supression entitlement. Show the raw notification
|
||||||
@@ -70,9 +76,13 @@ class NotificationService: UNNotificationServiceExtension {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Task {
|
Task {
|
||||||
if let (improvedContent, _) = await NotificationFormatter.shared.format_message(displayName: display_name, notify: notification_object, state: state) {
|
guard let (improvedContent, _) = await NotificationFormatter.shared.format_message(displayName: name, notify: notification_object, state: state) else {
|
||||||
contentHandler(improvedContent)
|
|
||||||
|
Log.debug("NotificationFormatter.format_message failed", for: .push_notifications)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
contentHandler(improvedContent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -722,7 +722,7 @@ struct ContentView: View {
|
|||||||
selected_timeline = .dms
|
selected_timeline = .dms
|
||||||
damus_state.dms.set_active_dm(target.pubkey)
|
damus_state.dms.set_active_dm(target.pubkey)
|
||||||
navigationCoordinator.push(route: Route.DMChat(dms: damus_state.dms.active_model))
|
navigationCoordinator.push(route: Route.DMChat(dms: damus_state.dms.active_model))
|
||||||
case .like, .zap, .mention, .repost, .reply:
|
case .like, .zap, .mention, .repost, .reply, .tagged:
|
||||||
open_event(ev: target)
|
open_event(ev: target)
|
||||||
case .profile_zap:
|
case .profile_zap:
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -61,13 +61,15 @@ func generate_local_notification_object(from ev: NostrEvent, state: HeadlessDamu
|
|||||||
|
|
||||||
if type == .text, state.settings.mention_notification {
|
if type == .text, state.settings.mention_notification {
|
||||||
let blocks = ev.blocks(state.keypair).blocks
|
let blocks = ev.blocks(state.keypair).blocks
|
||||||
|
|
||||||
for case .mention(let mention) in blocks {
|
for case .mention(let mention) in blocks {
|
||||||
guard case .pubkey(let pk) = mention.ref, pk == state.keypair.pubkey else {
|
guard case .pubkey(let pk) = mention.ref, pk == state.keypair.pubkey else {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
let content_preview = render_notification_content_preview(ev: ev, profiles: state.profiles, keypair: state.keypair)
|
let content_preview = render_notification_content_preview(ev: ev, profiles: state.profiles, keypair: state.keypair)
|
||||||
return LocalNotification(type: .mention, event: ev, target: ev, content: content_preview)
|
return LocalNotification(type: .mention, event: ev, target: .note(ev), content: content_preview)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ev.referenced_ids.contains(where: { note_id in
|
if ev.referenced_ids.contains(where: { note_id in
|
||||||
guard let note_author: Pubkey = state.ndb.lookup_note(note_id)?.unsafeUnownedValue?.pubkey else { return false }
|
guard let note_author: Pubkey = state.ndb.lookup_note(note_id)?.unsafeUnownedValue?.pubkey else { return false }
|
||||||
guard note_author == state.keypair.pubkey else { return false }
|
guard note_author == state.keypair.pubkey else { return false }
|
||||||
@@ -75,31 +77,39 @@ func generate_local_notification_object(from ev: NostrEvent, state: HeadlessDamu
|
|||||||
}) {
|
}) {
|
||||||
// This is a reply to one of our posts
|
// This is a reply to one of our posts
|
||||||
let content_preview = render_notification_content_preview(ev: ev, profiles: state.profiles, keypair: state.keypair)
|
let content_preview = render_notification_content_preview(ev: ev, profiles: state.profiles, keypair: state.keypair)
|
||||||
return LocalNotification(type: .reply, event: ev, target: ev, content: content_preview)
|
return LocalNotification(type: .reply, event: ev, target: .note(ev), content: content_preview)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ev.referenced_pubkeys.contains(state.keypair.pubkey) {
|
||||||
|
// not mentioned or replied to, just tagged
|
||||||
|
let content_preview = render_notification_content_preview(ev: ev, profiles: state.profiles, keypair: state.keypair)
|
||||||
|
return LocalNotification(type: .tagged, event: ev, target: .note(ev), content: content_preview)
|
||||||
|
}
|
||||||
|
|
||||||
} else if type == .boost,
|
} else if type == .boost,
|
||||||
state.settings.repost_notification,
|
state.settings.repost_notification,
|
||||||
let inner_ev = ev.get_inner_event()
|
let inner_ev = ev.get_inner_event()
|
||||||
{
|
{
|
||||||
let content_preview = render_notification_content_preview(ev: inner_ev, profiles: state.profiles, keypair: state.keypair)
|
let content_preview = render_notification_content_preview(ev: inner_ev, profiles: state.profiles, keypair: state.keypair)
|
||||||
return LocalNotification(type: .repost, event: ev, target: inner_ev, content: content_preview)
|
return LocalNotification(type: .repost, event: ev, target: .note(inner_ev), content: content_preview)
|
||||||
} else if type == .like,
|
} else if type == .like, state.settings.like_notification, let evid = ev.referenced_ids.last {
|
||||||
state.settings.like_notification,
|
if let txn = state.ndb.lookup_note(evid, txn_name: "local_notification_like"),
|
||||||
let evid = ev.referenced_ids.last,
|
let liked_event = txn.unsafeUnownedValue
|
||||||
let txn = state.ndb.lookup_note(evid, txn_name: "local_notification_like"),
|
{
|
||||||
let liked_event = txn.unsafeUnownedValue?.to_owned()
|
let content_preview = render_notification_content_preview(ev: liked_event, profiles: state.profiles, keypair: state.keypair)
|
||||||
{
|
return LocalNotification(type: .like, event: ev, target: .note(liked_event), content: content_preview)
|
||||||
let content_preview = render_notification_content_preview(ev: liked_event, profiles: state.profiles, keypair: state.keypair)
|
} else {
|
||||||
return LocalNotification(type: .like, event: ev, target: liked_event, content: content_preview)
|
return LocalNotification(type: .like, event: ev, target: .note_id(evid), content: "")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if type == .dm,
|
else if type == .dm,
|
||||||
state.settings.dm_notification {
|
state.settings.dm_notification {
|
||||||
let convo = ev.decrypted(keypair: state.keypair) ?? NSLocalizedString("New encrypted direct message", comment: "Notification that the user has received a new direct message")
|
let convo = ev.decrypted(keypair: state.keypair) ?? NSLocalizedString("New encrypted direct message", comment: "Notification that the user has received a new direct message")
|
||||||
return LocalNotification(type: .dm, event: ev, target: ev, content: convo)
|
return LocalNotification(type: .dm, event: ev, target: .note(ev), content: convo)
|
||||||
}
|
}
|
||||||
else if type == .zap,
|
else if type == .zap,
|
||||||
state.settings.zap_notification {
|
state.settings.zap_notification {
|
||||||
return LocalNotification(type: .zap, event: ev, target: ev, content: ev.content)
|
return LocalNotification(type: .zap, event: ev, target: .note(ev), content: ev.content)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -48,10 +48,24 @@ struct LossyLocalNotification {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum NotificationTarget {
|
||||||
|
case note(NostrEvent)
|
||||||
|
case note_id(NoteId)
|
||||||
|
|
||||||
|
var id: NoteId {
|
||||||
|
switch self {
|
||||||
|
case .note(let note):
|
||||||
|
return note.id
|
||||||
|
case .note_id(let id):
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct LocalNotification {
|
struct LocalNotification {
|
||||||
let type: LocalNotificationType
|
let type: LocalNotificationType
|
||||||
let event: NostrEvent
|
let event: NostrEvent
|
||||||
let target: NostrEvent
|
let target: NotificationTarget
|
||||||
let content: String
|
let content: String
|
||||||
|
|
||||||
func to_lossy() -> LossyLocalNotification {
|
func to_lossy() -> LossyLocalNotification {
|
||||||
@@ -64,6 +78,7 @@ enum LocalNotificationType: String {
|
|||||||
case like
|
case like
|
||||||
case mention
|
case mention
|
||||||
case reply
|
case reply
|
||||||
|
case tagged
|
||||||
case repost
|
case repost
|
||||||
case zap
|
case zap
|
||||||
case profile_zap
|
case profile_zap
|
||||||
|
|||||||
@@ -111,8 +111,10 @@ class Ndb {
|
|||||||
var ok = false
|
var ok = false
|
||||||
while !ok && mapsize > 1024 * 1024 * 700 {
|
while !ok && mapsize > 1024 * 1024 * 700 {
|
||||||
var cfg = ndb_config(flags: 0, ingester_threads: ingest_threads, mapsize: mapsize, filter_context: nil, ingest_filter: nil)
|
var cfg = ndb_config(flags: 0, ingester_threads: ingest_threads, mapsize: mapsize, filter_context: nil, ingest_filter: nil)
|
||||||
ok = ndb_init(&ndb_p, testdir, &cfg) != 0
|
let res = ndb_init(&ndb_p, testdir, &cfg)
|
||||||
|
ok = res != 0;
|
||||||
if !ok {
|
if !ok {
|
||||||
|
Log.error("ndb_init failed: %d, reducing mapsize from %d to %d", for: .storage, res, mapsize, mapsize / 2)
|
||||||
mapsize /= 2
|
mapsize /= 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user