This adds a sync mechanism in Ndb.swift to coordinate certain usage of
nostrdb.c calls and the need to close nostrdb due to app lifecycle
requirements. Furthermore, it fixes the order of operations when
re-opening NostrDB, to avoid race conditions where a query uses an older
Ndb generation.
This sync mechanism allows multiple queries to happen simultaneously
(from the Swift-side), while preventing ndb from simultaneously closing
during such usages. It also does that while keeping the Ndb interface
sync and nonisolated, which keeps the API easy to use from
Swift/SwiftUI and allows for parallel operations to occur.
If Swift Actors were to be used (e.g. creating an NdbActor), the Ndb.swift
interface would change in such a way that it would propagate the need for
several changes throughout the codebase, including loading logic in
some ViewModels. Furthermore, it would likely decrease performance by
forcing Ndb.swift operations to run sequentially when they could run in
parallel.
Changelog-Fixed: Fixed crashes that happened when the app went into background mode
Closes: https://github.com/damus-io/damus/issues/3245
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit redesigns the Ndb.swift interface with a focus on build-time
safety against crashes.
It removes the external usage of NdbTxn and SafeNdbTxn, restricting it
to be used only in NostrDB internal code.
This prevents dangerous and crash prone usages throughout the app, such
as holding transactions in a variable in an async function (which can
cause thread-based reference counting to incorrectly deinit inherited
transactions in use by separate callers), as well as holding unsafe
unowned values longer than the lifetime of their corresponding
transactions.
Closes: https://github.com/damus-io/damus/issues/3364
Changelog-Fixed: Fixed several crashes throughout the app
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit implements support for nicely formatting reply push
notifications.
Testing
-------
PASS
Device: iPhone 15 simulator
notepush: 11568aa6285142e4c19bb0da30977957a92b7d9b
Damus: This commit
Settings: Local push notification setup
Steps:
1. Create a post from account 1
2. On account 2, make a reply to that post
3. Ensure we get a push notification with:
- A title formatted as "<ACCOUNT_2_NAME> replied to your note"
- A body with the contents of that reply
4. Click on that push notification. Ensure you are taken to the reply
5. Now make a post from account 2 and mention account 1 in it
6. Ensure push notification says that account 2 mentioned account 1 (i.e. does not talk about a reply)
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Closes: https://github.com/damus-io/damus/issues/2403
Since there may be situations where we close and re-open the database,
we need to make sure transactions fail when the database is not open.
Make NdbTxn an init?() constructor and check for ndb.closed. If it's
closed, then fail transaction construction.
This fixes crashes during high database activity when switching from
background to foreground and vice-versa.
Fixes: da2bdad18d ("nostrdb: close database when backgrounded")
The code paths for generating zap notifications were very different from
the paths used by most other notifications. In this commit, I include
the logic and data structures necessary for formatting zap notifications
in the same fashion as local notifications.
A good amount of refactoring and moving functions/structures around was
necessary to reuse zap local notification logic. I also attempted to
make the notification generation process more consistent between zaps
and other notifications, without changing too much of existing logic to
avoid even more regression risk.
General push notifications + local notifications test
-----------------------------------------------------
PASS
Device: iPhone 15 Pro simulator
iOS: 17.0.1
Damus: This commit
Setup:
- Two phones running Damus on different accounts
- Local relay with strfry-push-notify test setup
- Apple push notification test tool
Coverage:
1. Mention notifications
2. DM notifications
3. Reaction notifications
4. Repost notifications
Steps for each notification type:
1. Trigger a notification (local and then push)
2. Ensure that the notification is received on the other device
3. Ensure that the notification is formatted correctly
4. Ensure that DMs are decrypted correctly
5. Ensure that profile names are unfurled correctly
6. Click on the notification and ensure that the app opens to the correct screen
Result: PASS (all notifications received and formatted correctly)
Notes:
- For some reason my relay is not receiving zap events, so I could not
test zap notifications yet.
- Reply notifications do not seem to be implemented yet
- These apply to the tests below as well
Changelog-Added: Zap notification support for push notifications
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Signed-off-by: William Casarin <jb55@jb55.com>
Testing
-------
Conditional pass
Device: iPhone 15 Pro simulator
iOS: 17.0.1
Damus: This commit
Coverage:
1. Mention notification works (local and push). PASS
2. Thread replies do not appear (but upon code inspection it seems like
it was not supported before). PASS?
3. DM notification works with decryption (local and push). PASS
4. Zaps not yet implemented. Coming later.
Closes: https://github.com/damus-io/damus/issues/1702
Closes: https://github.com/damus-io/damus/issues/1703
Changelog-Changed: Improve push notification support to match local notification support
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Signed-off-by: William Casarin <jb55@jb55.com>
This commit adds support for the unfurling of author profile names on remote push notifications
It also makes the following changes:
- Notification extension now uses NdbNote
- Some of the logic between push notifications and local notifications was unified
Testing
-------
Device: iPhone 15 Pro simulator
iOS: 17.0.1
Damus: This commit
Coverage:
1. Basic smoke tests on the app by browsing different notes and different tabs
2. Sent test push notifications for mentions and DMs to check the unfurling of profile names
3. Ran unit tests
Closes: https://github.com/damus-io/damus/issues/1703
Changelog-Added: Unfurl profile name on remote push notifications
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Signed-off-by: William Casarin <jb55@jb55.com>
I added support for the experimental push notifications feature. There are many improvements to be made, so this feature is currently opt-in only. If the user does not opt-in, their device tokens will not be sent out and thus they will receive no push notifications.
We should perform more testing on real-life staging environments before fully releasing this feature.
Testing
-------
Testing was done gradually during development.
Device: iOS simulators
iOS: 17
Damus version: A few different but recent prototypes
Rough coverage:
1. Checked that no device tokens are sent out when setting is off
2. Checked that I can successfully receive device tokens when feature is ON and set to localhost.
3. Checked sending test push notifications of types "note" (kind: 1), reaction (kind: 7) and DMs (kind 4) works and shows a generic but reasonable push notification message
4. Checked that clicking on the notifications above take the user to the correct screen
Closes: https://github.com/damus-io/damus/issues/67
Changelog-Added: Add experimental push notification support
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Signed-off-by: William Casarin <jb55@jb55.com>