This change includes several source files related to NostrDB into the extension target as well, so that we can use it from that context (and thus enable more advanced push notification formatting and suppression)
To make this change possible, I had to split some source files as well as to move some functions to different files, to ensure we don't have to pull too much unnecessary code into the extension.
Testing
-------
PASS
Device: iPhone 15 Pro simulator
iOS: 17.0.1
Damus: This commit
Test steps:
1. Build DamusNotificationService. Should succeed. PASS
2. Build Damus (the app). PASS
3. Run app, scroll around some notes, go to a few different views, post a note. Should work as normal. PASS
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>
This commit adds a new setting that can be used by developers to test onboarding suggestions without having to make local changes to code or reinstall the app.
Testing
-------
Device: iPhone 15 Pro (Simulator)
iOS: 17.0.1
Damus: This commit
Coverage:
1. Starting the existing app under the default setting does not show onboarding suggestions
2. Turning the setting ON causes the app to show onboarding suggestions on every app restart
3. Turning the setting back OFF causes the app to no longer show onboarding suggestions
Changelog-Added: Add "Always show onboarding suggestions" developer setting
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
This is useful to see where the load_profiles request is coming from
We may need to switch to a central dispatch for profile loading, I
suspect there is a lot of redundancy between requests.
Tested on iOS 17.0.1 on an iPhone 15 Pro simulator.
Closes: https://github.com/damus-io/damus/issues/1641
Changelog-Added: Add setting that allows users to optionally disable the new profile action sheet feature
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
This commit implements a single-tap zap on the profile action sheet and fixes an issue where zapping would silently fail on default settings if the user had no lightning wallet installed in their system.
Testing
-------
Configurations:
- iPhone 13 Mini (physical device) on iOS 17.0.2 with NWC wallet attached
- iPhone 15 Pro (simulator) on iOS 17.0.1 with no lightning wallet nor NWC
Damus: This commit
Coverage:
- Zapping using NWC connected wallet: PASS (Zaps and shows UX feedback of the completed action)
- Zapping under default settings and no lightning wallet: PASS (Shows the wallet selector invoice view)
- Long press on zap button brings custom zap view
Regression testing
------------------
Preconditions: iPhone 15 Pro (simulator) on iOS 17.0.1 with no lightning wallet nor NWC
Coverage:
- Zapping user on their full profile shows wallet selector. PASS
- On-post invoice shows wallet selector. PASS
Closes: https://github.com/damus-io/damus/issues/1634
Changelog-Changed: Zap button on profile action sheet now zaps with a single click, while a long press brings custom zap view
Changelog-Fixed: Fixed an issue where zapping would silently fail on default settings if the user does not have a lightning wallet preinstalled on their device.
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
In 7c98489, routes are compared to the stack top before push.
Problem is, search comparison is not looking at the NostrFilter.
Instead, hash value involves two UUID-based fields (sub_id,
profiles_subid), so equality will always fail and result in a
"duplicated push".
As I do not know the context of such fields to deliberately
drop them, this patch is sent as a draft.
The basic idea is using the filter for comparison, so I added
a Hashable extension to NostrFilter where the subject of the
comparison may be fine-tuned.
Adding `hashtag` resolves#1367 but it's only a starting point.
Signed-off-by: Davide De Rosa <keeshux@gmail.com>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
This commit adds a suggested hashtag section to the universe view tab. The method for suggesting hashtags is currently simple:
1. It contains a list of many possible hashtags that we could recommend
2. It calculates how many users have been talking about it in the events fetched by the Universe tab
3. It selects the Top-N most mentioned suggested hashtags in the Universe tab
This has the following properties:
1. It has some spam resistance as it ranks by unique users mentioning the tag (instead of events)
2. It is a simple way to curate good hashtags
3. It shows the ones with the most amount of people talking about it among the notes fecthed in the Universe view
Testing
-------
PASS
Device: iPhone 14 Pro simulator
iOS: 17.0
Damus: This commit
Coverage:
1. Suggested hashtags are displayed
2. Layout looks similar to Figma
3. User count goes up (does not stay at zero)
4. Clicking on a suggested hashtag takes you to that hashtag view
5. Only the top 5 hashtags are displayed
Notes: The counts seem low, probably because there are not enough notes loaded in Universe View
Changelog-Added: Add suggested hashtags to universe view
Closes: https://github.com/damus-io/damus/issues/1569
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Signed-off-by: William Casarin <jb55@jb55.com>
Testing of standard flow
------------------------
PASS
Device: iPhone 14 Pro simulator
iOS: 17.0
Damus: This commit
Steps:
1. Delete and reinstall Damus
2. Go through onboarding until suggested users appear
3. Click "continue". Should slide into the post view. PASS
4. Post view should look similar to the Figma design file, but with examples as placeholders. PASS
5. Examples should switch every 3 seconds. PASS
6. Typing a first character causes the #introductions hashtag to be automatically added. PASS
7. Uploading an image makes progress view show up and not break layout. PASS
8. Clicking on "post" should post this note and dismiss onboarding view. PASS
Testing of other flows
----------------------
PASS
Device: iPhone 14 Pro simulator
iOS: 17.0
Damus: This commit
Special remark: Made local change to always show the onboarding suggestions, and speed up testing
Coverage:
1. Clicking "skip" on suggested users view will skip into the post view. PASS
2. Clicking "cancel" on post view and then going to the normal post view reveals a blank draft. PASS
3. Clicking "cancel" dismisses onboarding view and does not post anything. PASS
4. Normal post view looks normal (not broken). PASS
5. Changing initial suggested post during onboarding, cancelling the post, and then re-entering normal post view reveals the draft with user modifications. PASS
Changelog-Added: Suggest first post during onboarding
Closes: https://github.com/damus-io/damus/issues/1338
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Signed-off-by: William Casarin <jb55@jb55.com>
This patch improves clear cache functionality by:
- Reducing kingfisher cache removal to one command (The two commands running async was leading to warning logs. One was a subset of the other)
- Removing all files under the cache folder where not currently used by other processes
Full Functionality test
-----------------------
PASS
Device: iPhone 13 mini (Physical device)
iOS: 17.0.3
Damus: This commit
Special remarks:
- I had to locally delete other unit tests to be able to build the test target
- Unit test run on an earlier version of the patch. Test coverage should still apply since this newer patch is a subset of the previous.
Setup: Run Damus with debugger connection to Xcode
Test steps:
1. Follow multiple active accounts (Skip if local Damus is already filled up with GBs of data)
2. Scroll down on the feed for a couple of minutes (or until you have seen at least a few images, a few videos, and link previews) (Skip if local Damus is filled up with GBs of data)
3. In Xcode, download a storage container (Window > Devices and Simulators > Select the device > Select Damus > click on (...) > Download container)
- Note: Even though you see the file, it does not download instantly. Monitor the file size until it roughly reaches the size reported in iOS storage settings, as the download may still be in progress. This may take a few minutes in some cases.
- Also take note of storage usage in iOS settings
4. Open the app data package using terminal
5. Run `du -h . | sort -hr`
6. Clear cache and check logs. Logs should indicate the caches being cleared, and there should be no storage-related warning/error logs. PASS
7. Download a new storage container. Remember to wait until it completes download.
8. Run `du -h . | sort -hr` on it.
9. Compare. There should be much less data. Also check iOS settings storage usage. PASS
10. Go back to the home feed and start scrolling, browsing, follow some other people, etc. Look at your own profile as well. Everything should appear to be working as expected with no crashes or important data loss
11. Check bookmarks are still present. PASS
12. Run `DamusCacheManagerTests`. Should pass. PASS* (*See special remarks)
Results:
- Storage usage goes from 3.9GB to 394.7MB
- Damus works as normal after clearing cache, and after restarting the app as well. It becomes slower for a moment, but after a bit it loads as normal again.
- No warning or error logs pertaining to clearing cache
- Unit test passes
My storage container disk usage stats after clearing cache:
```
% du -h | sort -hr
359M ./AppData
359M .
336M ./AppData/Documents
23M ./AppData/Library
20M ./AppData/Library/Caches
7.9M ./AppData/Library/Caches/com.jb55.damus2
2.4M ./AppData/Library/SplashBoard/Snapshots
2.4M ./AppData/Library/SplashBoard
1.8M ./AppData/Library/SplashBoard/Snapshots/com.jb55.damus2 - {DEFAULT GROUP}
1.6M ./AppData/Library/Caches/com.jb55.damus2/fsCachedData
636K ./AppData/Library/SplashBoard/Snapshots/sceneID:com.jb55.damus2-ecc156b1-eb9c-4439-b219-e1eebf2b4c36
596K ./AppData/Library/Caches/com.apple.WebKit.GPU/com.apple.metal
596K ./AppData/Library/Caches/com.apple.WebKit.GPU
452K ./AppData/Library/Caches/com.jb55.damus2/com.apple.metal
296K ./AppData/Library/SplashBoard/Snapshots/sceneID:com.jb55.damus2-ecc156b1-eb9c-4439-b219-e1eebf2b4c36/downscaled
224K ./AppData/Library/HTTPStorages/com.jb55.damus2
224K ./AppData/Library/HTTPStorages
164K ./AppData/Library/Caches/com.onevcat.Kingfisher.ImageCache.default
156K ./AppData/Library/Caches/RelayLogs
112K ./AppData/Library/Caches/com.apple.dyld
92K ./AppData/Library/Preferences
60K ./AppData/Library/Caches/com.jb55.damus2/com.apple.metal/archiveUsage.db
12K ./AppData/Library/Saved Application State/com.jb55.damus2.savedState
12K ./AppData/Library/Saved Application State
8.0K ./AppData/StoreKit
8.0K ./AppData/Library/Saved Application State/com.jb55.damus2.savedState/ecc156b1-eb9c-4439-b219-e1eebf2b4c36
4.0K ./AppData/Library/Saved Application State/com.jb55.damus2.savedState/KnownSceneSessions
4.0K ./AppData/Library/LanguageModeling/en-dynamic.lm
4.0K ./AppData/Library/LanguageModeling
4.0K ./AppData/Library/Cookies
0B ./AppData/SystemData/com.apple.SafariViewService/Library/WebKit/WebsiteData
0B ./AppData/SystemData/com.apple.SafariViewService/Library/WebKit
0B ./AppData/SystemData/com.apple.SafariViewService/Library
0B ./AppData/SystemData/com.apple.SafariViewService
```
Biggest storage used remaining is in the Documents folder where NostrDB is stored. However, we do not want to clear NostrDB, so this is expected behavior.
Changelog-Changed: Improve clear cache functionality
Closes: https://github.com/damus-io/damus/issues/1472
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Signed-off-by: William Casarin <jb55@jb55.com>
Summary
-------
This fixes the issue at Github #1531 where relays with trailing slashes cannot be removed.
The root cause (Identified by @fishcakeday) was that for a relay to be removed, a certain dictionary entry containing the relay url needed to be removed prior to sending the updated relay list. However those dictionary keys used `String` objects, which cannot tell that two URLs are the same with or without a trailing slash.
To fix the issue, I have used a dictionary with the type `[RelayURL: RelayInfo]`, and made the necessary protocol conformance implementations for RelayURL. This way, URLs are handled with higher accuracy (e.g. Trailing slashes do not matter, URLs that resolve to the same location will match no matter what).
This allows us to leverage the existing parsing and handling logic that comes with the `URL` type, instead of manually handling URL strings.
Generally speaking it is preferrable to work with higher level `URL` or `RelayURL` objects than handle URLs via `String`. There is an opportunity to refactor more code, but I intentionally kept the changes to `RelayURL` limited to the functionality in this issue, because otherwise the changeset becomes very big and risky.
Issue reproduction
------------------
**Device:** iPhone 14 Pro simulator
**iOS:** 17.0
**Damus:** Local build from `476f52562` with the following local change:
``` diff
Signed-off-by: William Casarin <jb55@jb55.com>
Issue reproduction
------------------
**Device:** iPhone 14 Pro simulator
**iOS:** 17.0
**Damus:** `bb2eb904cc`
**Steps:**
1. Repost a note from another account (Account "B")
2. Mute user "B"
3. Check home page and your own profile page. Repost shows up with a muted box.
Fix
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
Testing
-------
**PASS**
**Device:** iPhone 14 Pro simulator
**iOS:** 17.0
**Damus:** This commit
**Steps:**
1. Setup accounts "A" and "B" that you control. Account "A" will be on our device under test.
2. Post something
3. Make a reply using Account A (Reply 1)
4. Make a reply using Account B (Reply 2)
5. Make another reply using account A (Reply 3)
6. Order of replies should be (top to bottom): 1, 2, 3
7. Mute user B
8. Order of replies should be: 1, 3, 2
Performance check
-----------------
**Device:** iPhone 14 Pro simulator
**iOS:** 17.0
**Damus:** This commit
**Steps:**
1. Locally change the code and add a print statement right before the sorting begins. In that print statement, include the number of events that will be sorted
2. Run Damus and go to a busy thread (I found one with 45 replies)
3. Go to the thread, and monitor the logs.
4. Navigate a bit between replies and monitor logs.
**Results:** I only saw a few print statements being printed with each navigation action, which indicates that we are not constantly re-sorting this object (which would be inefficient). Therefore, it seems like performance/efficiency would not be a problem.
Changelog-Changed: Show muted thread replies at the bottom of the thread view (#1522)
Closes: https://github.com/damus-io/damus/issues/1522
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
This adds profiles to nostrdb
- Remove in-memory Profiles caches, nostrdb is as fast as an in-memory cache
- Remove ProfileDatabase and just use nostrdb directly
Changelog-Changed: Use nostrdb for profiles
When users view who a certain person follows, now they will see an extra
tab to see the hashtags that they follow.
This new tab contains a list of followed hashtags, each of which
includes an option to follow/unfollow the hashtag, as well as the
ability to visit the hashtag timeline
Testing
**iOS:** 17.0 (iPhone 14 Pro Simulator)
**Damus:** (This commit)
**Test steps:**
1. Go to search view, search for a couple of hashtags: #apple, #orange, #kiwi
2. Go to the test accounts own profile via the drawer menu
3. Click on "Following". Make sure there are two tabs now.
4. Scroll down, switch tabs between "People" and "Hashtags". Make sure that scrolling and switching tabs work
5. Unfollow and follow a user. Make sure that this still works
6. Make sure that #apple, #orange, #kiwi hashtags are visible under the "Hashtags" tab
7. Unfollow "#kiwi". Check that the button label now switches from "Unfollow" to "Follow"
8. Click on "#kiwi". Make sure that it takes you to the page where posts with that hashtag appears
9. Go to @jb55's profile
10. Click on "Following"
11. Ensure that there is a "Hashtags" tab
12. Check that @jb55's followed hashtags are shown (not your own)
13. Follow one of the same hashtags as @jb55's
14. Go back to your own profile and go to your own following view again.
15. Make sure that this newly added tag is present on the list, and that #kiwi is not.
Closes: https://github.com/damus-io/damus/issues/606
Changelog-Added: Add followed hashtags to your following list
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
This simplifies our content filters so that it is a bit more flexible
for future additions.
Fixes: 0957cc896cc8 ("Add "Do not show #nsfw tagged posts" setting")
This commit adds a setting where the user can choose to hide notes with
a #nsfw hashtag. This setting was implemented to allow users to filter
out adult or other unsafe content.
I moved the code logic for content filtering into a new file, and
defined a protocol for content filters. Although the logic is still
simple, this might help in developing a flexible API in case we have
more complex filtering needs in the future.
I also modified the name of the "Appearance" setting to "Appearance and
filters", to make it easier for users to intuitively find this setting.
(Note: Re-translations of this string might be necessary)
**PASS**
**iOS:**
- iOS 17.0 (iPhone 14 Pro)
**Damus:** (This commit)
**Steps:**
1. Follow another account that you control (Account B)
2. On account B, post a note saying "#test this is a test". This note should show up on the home feed.
3. On account B, post a note saying "#nsfw this is a test". This note should NOT show up on the home feed
4. Go to settings and disable the NSFW filter. Go back to the home view. The #nsfw post should now show up.
5. Close app and reopen. NSFW post should still show up (i.e. Setting should be persistent)
6. Unfollow account B
7. Close app and reopen.
8. Follow the "#grownostr" hashtag
9. Turn on the NSFW filter
10. On account B, post a note saying "#grownostr this is a test". This note should show up on the home view.
11. On account B, post a note saying "#grownostr #nsfw this is a test". This note should NOT show up.
12. Double-check the "notes and replies" tab. Note should NOT show up there either.
12. Turn off NSFW filter
13. Note from step 11 should now show up.
14. Go to Universe view and find a post with a hashtag. Remember where the post is.
14. Locally change the tag keyword from "nsfw" to that hashtag (Note: I had to test this way because my posts were not showing up in the Universe view)
15. Turn off the filter. Check post is there, in the Universe view.
16. Turn on the filter. Check post is no longer there in the Universe view. (Check the neighboring posts are the same, to make sure)
17. Bring back the code to its normal state.
18. Search for "#nsfw". Make sure that #nsfw appears (I believe this is ok, because it means the person is purposefully searching for it)
Closes: https://github.com/damus-io/damus/issues/1412
Changelog-Added: Add "Do not show #nsfw tagged posts" setting
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Signed-off-by: William Casarin <jb55@jb55.com>
Move the "Follow you" badge into the profile header he profile header
out-of-line with the often long and already space-constrained
username/display name text
Changelog-Changed: Move the "Follow you" badge into the profile header
Closes: https://github.com/damus-io/damus/pull/1529
Signed-off-by: William Casarin <jb55@jb55.com>
Collapse the various standalone functions for parsing block data, and
refactor consumers to initialize a Block with given data and access its
members as needed.
Closes: https://github.com/damus-io/damus/pull/1496
Signed-off-by: William Casarin <jb55@jb55.com>
Revert "home: debounce last notified"
This is technically incorrect, as debouncing can prevent saving
important events.
The proper way to do this is to save it locally in memory, and then
debouncing the saving itself. Will do this soon.
Reverts: a9b4cfd424
Fixes: https://github.com/damus-io/damus/issues/1439
Changelog-Fixed: Fixed old notifications always appearing on first start
Fixes a crash when the user mutes a thread. UserDefaults didn't know how
to serialize a NoteId for storage, so we'll convert it to the hex id
first.
Changelog-Fixed: Crash when muting threads
Signed-off-by: Bryan Montz <bryanmontz@me.com>
Signed-off-by: William Casarin <jb55@jb55.com>