Removed existing progress view bar at the top of post view
Added separate stack in PVImageCarouselView for media undergoing the upload process
Changelog-Added: Display uploading indicator in post view
Signed-off-by: Swift Coder <scoder1747@gmail.com>
Soon after tightening error handling around NWC, it was noticed that
Damus was trying to process NWC responses meant for other people,
which caused a failure around the decryption process and a spam of
errors.
This commit modifies the relay filter to include only responses destined
to the user, and also guards the NWC response processing logic to ignore
responses meant for other users.
Changelog-Changed: Improved handling around NWC responses
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Changelog-Changed: Added more human visible errors on NWC wallets to aid with troubleshooting
Changelog-Added: Added copy technical info button to user visible errors, so that users can more easily share errors with developers
Closes: https://github.com/damus-io/damus/issues/3010
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit moves Kingfisher data to Apple's designated caches folder
to avoid it from being backed up to iCloud.
Closes: https://github.com/damus-io/damus/issues/2993
Changelog-Fixed: Fixed issue where cached images would be backed up to iCloud
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This is a minor refactor on the way wallet invoice URLs are handled, in
order to better fit the interface, enforce the design pattern, and avoid
side-effects in a particular function that handles opening URLs.
This design pattern was introduced to prevent issues on the previous
pattern, where URL handling was done with side-effects inside multiple
levels of nested logic and separate function calls, which would make
debugging very difficult, and cause the app to fail silently.
Closes: https://github.com/damus-io/damus/issues/3023
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This PR allows users to tap on a profile picture from the wallet
transaction list to go to that user's profile page.
Closes: #2997
Changelog-Added: Added route to profile page from wallet tx list
Signed-off-by: ericholguin <ericholguin@apache.org>
This is a palliative fix for an issue where videos become unplayable
after a long user session.
The fix works by detecting the error state anytime the video gets
played, and reinitializes the video and corresponding player views in
order to clear the error.
Changelog-Fixed: Fixed issue where some videos would become unplayable after some time using the app
Closes: https://github.com/damus-io/damus/issues/2878
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit adds a reminder to users who hold more than 100K sats in
their NWC wallet, reminding them to learn about self-custody.
Changelog-Added: Added safety reminder to wallets with higher balance
Closes: https://github.com/damus-io/damus/issues/2984
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit fixes a regression on the highlighter and share extensions,
which was caused by a change in the code's architecture, which required
the network manager to be initialized.
Fixes: 8d48f77d95138c93ed93989989fa930b61c2d6fb
Closes: https://github.com/damus-io/damus/issues/2955
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit implements a one-click Coinos wallet setup.
This was implemented using the Coinos API, and using account details
that are deterministically generated from the user's private key.
Closes: https://github.com/damus-io/damus/issues/2961
Changelog-Added: Added one-click Coinos wallet setup
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This adds a First aid tool to repair the NIP-65 relay list
Changelog-Added: Added separated first aid option for relay lists that does not need a contact list reset
Closes: https://github.com/damus-io/damus/issues/2120
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit implements a new layer called NostrNetworkManager,
responsible for managing interactions with the Nostr network, and
providing a higher level API that is easier and more secure to use for
the layer above it.
It also integrates it with the rest of the app, by moving RelayPool and PostBox
into NostrNetworkManager, along with all their usages.
Changelog-Added: Added NIP-65 relay list support
Changelog-Changed: Improved robustness of relay list handling
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit introduces a new interface that makes it easier and safer to
handle unowned NostrDB notes, by leveraging new non-copyable and borrow
features from modern Swift.
Changelog-None
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit adds the base models needed for the NIP-65 relay list support.
This introduces no user-facing changes.
Changelog-None
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This is a non-functional refactor that organizes some classes and
structs used by RelayPool under the same namespace.
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit introduces two minor improvements:
1. It ensures better consistency between ThreadModel and EventCache
2. It avoids unnecessary recursion calls on `add_event`
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This fixes a regression where ThreadModel would no longer look at
NostrDB saved notes for parent events, causing some instability on
thread loading — especially in poor networking conditions.
This was fixed by adding a call that searches for parent events in
EventCache/NostrDB each time an event is added to the ThreadModel.
That `add_event` function is the ideal spot to place the call because it
is the only interface used for all information updates incoming to the
ThreadModel, including:
- anytime an event is loaded from the network into the thread model.
- when the ThreadModel is first initialized, with an initial event.
Fixes: 74d5bee1f6
Changelog-Fixed: Fixed an issue where threads would not load properly
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This PR redesigns the NWC wallet view. A new view is added to introduce zaps to users. The set up wallet view is simplified, with new and existing wallet setup separated.
This also adds new NWC features such as getBalance and listTransactions allowing users to see their balance and previous transactions made.
Changelog-Added: Added view introducing users to Zaps
Changelog-Added: Added new wallet view with balance and transactions list
Changelog-Changed: Improved integration with Nostr Wallet Connect wallets
Closes: https://github.com/damus-io/damus/issues/2900
Signed-off-by: ericholguin <ericholguin@apache.org>
Co-Authored-By: Daniel D’Aquino <daniel@daquino.me>
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Changelog-Changed: Changed spaces to newlines in new posts to provide cleaner separation between text, uploaded media, and quoted notes
Signed-off-by: Terry Yiu <git@tyiu.xyz>
Changelog-Fixed: Fix bug where profile view was showing more than just the notes and replies on the notes / notes & replies tabs
Fixes: caa4bfe864 ("Fix bug where profile view was showing more than just the notes and replies on the notes / notes & replies tabs")
Signed-off-by: Terry Yiu <git@tyiu.xyz>
I've tested these and they seem to be working!
Terry Yiu (3):
Fix reposts banner to be localizable
Add Conversations tab to profiles
Remove mystery tabs meant to fix tab switching bug that no longer exists
Push notifications were not opened reliably. To improve robustness, the
following changes were introduced:
1. The notification opening logic was updated to become more similar to
URL handling, in a way that uses better defined interfaces and
functions that provide better result guarantees, by separating
complex handling logic, and the side-effects/mutations that
are made after computing the open action — instead of relying on a
complex logic function that produces side-effects as a result, which
obfuscates the actual behavior of the function.
2. The LoadableThreadView was expanded and renamed to
LoadableNostrEventView, to reflect that it can also handle non-thread
nostr events, such as DMs, which is a necessity for handling push
notifications.
3. A new type of Notify object, the `QueueableNotify` was introduced, to
address issues where the listener/handler is not instantiated at the
time the app notifies that there is a push notification to be opened.
This was implemented using async streams, which simplifies the usage
of this down to a simple "for-in" loop.
Closes: https://github.com/damus-io/damus/issues/2825
Changelog-Fixed: Fixed issue where some push notifications would not open in the app and leave users confused
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Daniel D’Aquino (4):
Reduce swipe sensitivity on thread chat view
Fix issue where a NWC connection would not work unless restarting the app
Implement developer feature to avoid distractions
Fix issue where note persisted after note publication
replaced deprecated noteID with neventID in EventMenu.swift. NoteID currently appears in bubble/context menu of each note (top right three dots ellipsis).
This commit implements an optional developer feature to scramble text
and blur images to prevent distractions during development and testing.
It is not perfect (It breaks some mentions and rich text objects, and
does not scramble non-alphanumeric languages such as Japanese), but
good enough to avoid distractions while working on most features.
No changelog entry is needed because this is not meant for the final
user.
Changelog-None
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit fixes an issue where the post view would scroll to the text
cursor at seemingly random times.
This was done by detaching the save view and its logic, so that we have
3 components:
1. The `PostView`
2. An auto-save view model (which is an Observable object)
3. A separate SwiftUI view for the auto-save indicator
The auto-save view model is shared between the `PostView` and the new
indicator view to ensure proper signaling and communication across
views.
However, this view model is only observed by the indicator view,
ensuring it updates its own view, while not causing any re-renders on
the rest of the `PostView`.
This refactor had the side-effect of making the auto-save logic and view
more reusable. It is now a separate collection of elements that can be
used anywhere else.
Beyond the scroll issue, this commit also prevents empty drafts from
being saved, by introducing the new save state called `.nothingToSave`
Note: No changelog item is needed because the new drafts feature was never
publicly released.
Changelog-None
Closes: https://github.com/damus-io/damus/issues/2826
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit removes rust-nostr dependency, and replaces the NIP-44 logic
with a new NIP-44 module based on the Swift NostrSDK implementation.
The decision to move away from rust-nostr and the Swift NostrSDK was
made for the following reasons:
1. `rust-nostr` caused the app size to double
2. We only need NIP44 functionality, and we don't need to bring
everything else
3. The Swift NostrSDK caused conflicts around the secp256k1 dependency
that is hard to address
4. The way we do things in the codebase is far different from the Swift
NostrSDK, and we optimize it for use with NostrDB. Bringing it an
outside library causes significant complexity in integration with
NostrDB, and would effectively cause the codebase to be split into
two different ways of achieving the same results. Therefore it is
cleaner if we stick to our own Nostr structures and functions and
focus on maintaining them.
However, the library CryptoSwift was added as a dependency, to bring in
ChaCha20 which is not supported by CryptoKit (CryptoKit supports the
ChaCha20-Poly1305 cipher, but NIP-44 uses ChaCha20 with HMAC-SHA256
instead)
Closes: https://github.com/damus-io/damus/issues/2849
Changelog-Changed: Made internal changes to reduce the app binary size
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Changelog-Changed: Improved clarity of the mute button to indicate it can be used for blocking a user
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This makes the microphone access request contain a message that is more
clear to the user
Changelog-Changed: Made the microphone access request message more clear to users
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit adds a special badge for purple members who have been active
for more than one entire year.
Closes: https://github.com/damus-io/damus/issues/2831
Changelog-Added: Purple members who have been active for more than a year now get a special badge
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit makes drafts persistent.
It does so by:
1. Converting `DraftsArtifacts` into Nostr events
2. Wrapping those Nostr events into NIP-37 notes
3. Saving those NIP-37 notes into NostrDB
4. Loading those same notes at startup
5. Unwrapping NIP-37 notes into Nostr events
6. Parsing that into `DraftsArtifacts`, loaded into DamusState
7. PostView can then load these drafts
Furthermore, a UX indicator was added to show when a draft has been
saved.
Limitations:
1. No encoding/decoding roundtrip guarantees. That would require
extensive and heavy refactoring which is out of the scope of this
commit.
2. We rely on `UserSettings` to keep track of note ids, while we do not
have Ndb query capabilities
3. No NIP-37 relay sync support has been added yet, as that adds
important privacy and sync conflict considerations which are out of
the scope of this ticket, which is ensuring people don't lose their
progress while writing notes.
4. The main use cases and scenarios have been tested. Because of (1),
there may be some small inconsistencies on the stored version of the
draft, but care was taken to keep the substantial portions of the
content intact.
Closes: https://github.com/damus-io/damus/issues/1862
Changelog-Added: Added local persistence of note drafts
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit fixes an issue where events in threads would occasionally
disappear.
Previously, the computation of parent events and reply events depended
on EventCache and had to be manually computed upon event selection
change. This may lead to inconsistencies if the computation is not
re-done after a new event that leads to a change in the model, or if certain
events are not yet on the cache. Instead, these are now computed
properties inside ThreadModel, and relies exclusively on the events
already in the ThreadModel.
Several other smaller improvements were made around the affected class,
including:
- Removing unused code for simplicity
- Configuring the class external interface with more intent, avoiding
misusage
- Adding more documentation on the usage of things, as well as
implementation notes on why certain design decisions were taken.
- Moving things to explicit actors, to integrate more structured concurrency
- Improving code efficiency to lower computational overhead on the main
actor
- Splitting concerns between objects with more intent and thoughful
design.
Changelog-Fixed: Fixed an issue where events on a thread view would occasionally disappear
Closes: https://github.com/damus-io/damus/issues/2791
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit improves reliability on the handling of
external URLs.
This was achieved through the following improvements:
1. The URL handler interface is now well-defined, with more clear inputs
and outputs, to avoid silent failures and error paths that are hard to see
within convoluted logic paths
2. Side effects during URL parsing were almost completely removed for
more predictable behavior
3. Error handling logic was added to present errors to the user in a user-friendly manner,
instead of silently failing
4. Event loading logic was moved into a special new thread view, which
makes its own internal state evident to the user (i.e. whether
the note is loading, loaded, or if the note could not be found)
These changes make the URL opening logic more predictable, easy to
refactor, and helps ensure the user always gets some outcome from
opening a URL, even if it means showing a "not found" or "error" screen,
to eliminate cases where nothing seems to happen.
Closes: https://github.com/damus-io/damus/issues/2429
Changelog-Fixed: Improved robustness of the URL handler
Changelog-Added: Added user-friendly error view for errors around the app that would not fit in other places
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Changelog-Fixed: Translate notes even if they are in a preferred language but not the current language as that is what users expect
Signed-off-by: Terry Yiu <git@tyiu.xyz>
This PR adds a button to allow users to easily connect to Coinos
Also cleans up and organizes assets.
Changelog-Added: Coinos connection button in Wallet view
Signed-off-by: ericholguin <ericholguin@apache.org>
1] Cancel ongoing uploading operations after the user has pressed "cancel post"
2] Don't generate haptic feedback in this error case because user has already dismissed the Post View
Changelog-Fixed: Cancel ongoing uploading operations after the user cancels the post
Signed-off-by: Swift Coder <scoder1747@gmail.com>
This commit improves accessibility of EditPictureControl, by adding
better accessibility labels and hints.
Changelog-Added: Minor accessibility improvements around picture editing and onboarding
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit implements profile image cropping and optimization, as well
as a major refactor on EditPictureControl.
It now employs the following techniques:
- Users can now crop their profile pictures to fit a square aspect
ratio nicely and avoid issues with automatic resizing/cropping
- Profile images are resized to a 400px by 400px image before sending it
over the wire for better bandwidth usage
- Profile pictures are now tagged as such to the media uploaders, to
enable media optimization or special care on their end.
Integrating the cropping step was very difficult with the previous
structures, so `EditPictureControl` was heavily refactored to have
improved state handling and better testability:
1. Enums with associated values are being used to capture all of the
state in the picture selection process, as that helps ensure the
needed info in each step is there and more clearly delianeate
different steps — all at compile-time
2. The view was split into a view-model architecture, with almost all of
the view logic ported to the new view-model class, making the view
and the logic more clear to read as concerns are separated. This also
enables better testabilty
Several automated tests were added to cover EditPictureControl logic and
looks.
Closes: https://github.com/damus-io/damus/issues/2643
Changelog-Added: Profile image cropping tools
Changelog-Changed: Improved profile image bandwidth optimization
Changelog-Changed: Improved reliability of picture selector
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit adds the SwiftyCrop dependency, to provide users with a way
to crop their profile images prior to upload
- Dependency version is commit-hash-locked for extra security and
reproducibility
- Reviewed code contents of the library to check for any user tracking
code. None was found
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit fixes an issue where the "next" button is hidden behind the
software keyboard in the account creation view, where it is very hard to
press.
The fix was done by dynamically shrinking the profile picture size when
keyboard appears in smartphone screens, so that there is enough space
for all content to appear.
Changelog-Fixed: Fixed issue where the "next" button would appear hidden and hard to click on the create account view
Closes: https://github.com/damus-io/damus/issues/2771
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Changelog-Fixed: Fixed AddMuteItemView to trim leading and trailing whitespaces from mute text and disallow adding text with only whitespaces
Signed-off-by: Terry Yiu <git@tyiu.xyz>
This fixes an issue where a user would have to input a profile npub
twice in order to get a result.
The fix is composed of the following constituents:
1. The removal of the dependency on NostrDB having profile information.
Previously the function relied on NostrDB having profile information
about a freshly downloaded profile, which it sometimes does not. The
function does not require the profile to be on NostrDB at the time
the profile is found on the relay.
2. The increase in allowed relay attempts to all relays. Previously it
would only look for about half of the relays, which could cause
certain events to not be found
3. The closing of relay subscription on EOSE. Previously, the
subscription would only be closed if an event was found, which could
lead to a "leak" of open subscriptions if an event is not found.
Closes: https://github.com/damus-io/damus/issues/2635
Changelog-Fixed: Fixed an issue where a profile would need to be input twice in the search to be found
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Turn on strict concurrency checks on the compiler to make potential
concurrency issues more visible and aid during debugging, as well as to
start preparing us for Swift 6.
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit change will allow users to paste GIF file in the Post by copying from other apps (previously similar to pasting Jpeg and PNG image functionality)
Changelog-Added: Paste Gif image similar to jpeg and png files
Signed-off-by: Swift Coder <scoder1747@gmail.com>
Changelog-Fixed: Replace non-breaking spaces with regular spaces as Apple's NSLocalizedString macro does not seem to work with it
Signed-off-by: Terry Yiu <963907+tyiu@users.noreply.github.com>
1. While sharing images/videos from Apple's Message app, the file will be treated as a Link with file-url. The if-else ordering will help to fix the issue.
2. While sharing image from Signal and Facebook app, the file being received is an UIImage and error is being sent. This PR fixes the issue.
Changelog-Fixed: Fix damus sharing issues
Signed-off-by: Swift Coder <scoder1747@gmail.com>
This commit adds a new script to devtools that can be used to help
identify duplicate changelog entries.
It works by identifying duplicate lines in CHANGELOG.md, and then
searching whether each one of those duplicate lines are present in a
separate text file (which can be a subset of the changelog that the user
is interested in analyzing)
No user-facing changes
Changelog-None
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit adds an automated UI test to check if the edit banner button
UI is clickable and not hidden behind a top bar or another invisible
element.
It also improves accessibility support for some elements on login and
top bar.
Changelog-Changed: Improved accessibility support on some elements
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
In some conditions, it was found that the banner edit button was
obscured behind a top nav bar.
This commit fixes that by introspecting on the safe area margins and
applying them to the button
Closes: https://github.com/damus-io/damus/issues/2636
Changelog-Fixed: Fixed issue where banner edit button is unclickable
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit fixes the following issues with the new Share extension:
- Typo on user-facing label
- Misconfigured Info.plist that caused the build to be rejected by AppStore Connect
This extension was never shipped to users, so no changelog entry is needed.
Changelog-None
Fixes: eeb6547d3e
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit fixes build errors caused by logical merge issues from
changes that worked in isolation but not when combined.
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This PR change adds Damus Share feature to the app that allows the users to share Photos and URLs from foreign apps.
Changelog-Added: Add Damus Share Feature
Signed-off-by: Swift Coder <scoder1747@gmail.com>
1. Removed the dependency on finding the profile event for displaying actions to the user, even if the full profile couldn't be loaded. This allowed showing useful options such as the option to follow that pubkey.
2. Opened a profile preview sheet instead of navigating to the full profile page, enabling quick actions and saving bandwidth by not loading their timeline immediately.
3. Refactored most of that view to simplify state management and make it less prone to errors.
4. Improved error handling and management.
5. Ensured the view truly reflected the internal state of the scanner to the user.
Changelog-Fixed: Fixed some issues where QR code would not work, and improved UX
Closes: https://github.com/damus-io/damus/issues/2032
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Previously, the ImageCarousel needed to directly set a video size
binding to the video player view, in order to communicate and listen to
video size changes, and it used that to calculate the carousel image fill.
However, in the new video coordination architecture, the video size is
not owned by the ImageCarousel, but instead it is owned by the video
player itself, which in turn is owned by the video coordinator.
Therefore, this is incompatible with several logic elements of
ImageCarousel.
This commit updates the image carousel to integrate with the new video
coordinator architecture, and it also refactors the image fill logic
almost completely — with a focus on reducing stateful behavior by
carefully employing some state management patterns.
Furthermore, the new CarouselModel was heavily documented to explain its
design decisions and inner workings.
Note: There used to be some caching on the ImageFill calculations, but
after using this new refactored version without caching, I have not
noticed any noticeable performance regressions, so I have decided not to
add them back — applying Occam's razor
Changelog-Changed: Improved image carousel image fill behavior
Closes: https://github.com/damus-io/damus/issues/2458
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit makes several improvements to video coordination,
and implements a new video control view.
The video support stack in Damus has been re-architected to achieve
this.
The new architecture can be summarized as follows:
1. `DamusVideoCoordinator` is a singleton object in `DamusState`, and it
is responsible for deciding which video should have the "main stage"
focus, based on main stage requests that video player views make when
they become visible.
Having "main stage" focus means that the coordinator will auto-play
that video and pause others, and is used throughout the app to
determine which video to talk to or control, in the case of app-wide
controls (analogous to how Apple Music needs to know which song is
playing for displaying playback controls on the iOS home screen)
Having a singleton take care of this establishes
clear ownership and prevents conflicts such as double-playing video.
This coordinator also holds a pool of video media items (`DamusVideoPlayer`),
with exactly ONE `DamusVideoPlayer` per URL, to reduce
bandwidth and ensure perfect syncing of the same video in different
contexts.
2. `DamusVideoPlayer` objects hold the actual media item (video data, playback state),
much like `AVPlayer`.
In fact, `DamusVideoPlayer` can be described as a wrapper for `AVPlayer`,
except it has an interface that is much more SwiftUI friendly,
enabling playback state syncing with minimal effort.
`DamusVideoPlayer` is NOT a view. And there is only ONE `DamusVideoPlayer`
per URL — held by the coordinator.
However, when the app needs to display that same video in multiple
places, the app can instantiate multiple video player VIEWS of the
same `DamusVideoPlayer`
3. `DamusVideoPlayer.BaseView` is the most basic video player view for a
`DamusVideoPlayer` item. It has basically no features other than
showing the video itself.
4. `DamusVideoPlayerView` is the standard, batteries-included, video
player view for `DamusVideoPlayer` items, that is used throughout the
app.
It also tries to detect its own visibility, and makes requests to
`DamusVideoCoordinator` to take over the main stage when it becomes
visible.
5. `DamusVideoControlsView` is a view that presents video playback
controls (play/pause, mute, scrubbing) for a `DamusVideoPlayer`
object.
How a `DamusVideoPlayerView` gains and loses main stage focus:
1. `DamusVideoPlayerView` uses `VisibilityTracker` to find out when it
becomes visible or not
2. When it becomes visible, it makes a request to the video coordinator
to take main stage focus. The request also specifies which layer the
video view is in (Full screen layer? Normal app layer?), which the
video player view gets from the `\.view_layer_context` environment
variable set by `damus_full_screen_cover`
3. The coordinator (`DamusVideoCoordinator`) keeps all of these
requests, and uses its own internal logic and info to determine which
video should get the main stage.
The logic also depends on whether or not the app finds itself in full
screen mode.
Once the main stage is given to a different video, the previous video
is paused, the main-staged-video is played, and the requestor
receives a callback.
4. Once the video disappears from view, it tells the coordinator that it
is giving up the main stage, and the coordinator then picks another
main stage request again.
On top of this, several of other small changes and improvements were made,
such as video gesture improvements
Note: This commit causes some breakage over the image carousel sizing
logic, which will be addressed separately in the next commit.
Changelog-Fixed: Fixed iOS 18 gesture issues that would take user to the thread view when clicking on a video or unmuting it
Changelog-Fixed: Fixed several issues that would cause video to automatically play or pause incorrectly
Changelog-Fixed: Fixed issue where full screen video would disappear when going to landscape mode
Changelog-Added: Added new easy to use video controls for full screen video
Changelog-Changed: Improved video syncing and bandwidth usage when switching between timeline video and full screen mode
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit moves all logic related to visibility tracking into a single
view modifier for better code reusability.
Furthermore, the modified VisibilityTracker component was more
extensively documented, for better awareness of its limitations and
usage.
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit introduces new mechanisms to solve some issues with full screen support:
1. Full screen covers disappear when its caller disappears (e.g. when it
is an event in a lazy stack, and an orientation change causes the
view to disappear along with the full screen cover)
2. There are no mechanisms for views to determine whether they are being
presented under a full screen cover or not, and whether the device is
in full screen mode or not.
The commit overcomes the above limitations through the following:
1. A full screen cover on `ContentView` that can be accessed by any view
when calling `present(fullScreenItem)`
2. A new `damus_full_screen_cover` view modifier that automatically
tracks whether a device is in full screen mode or not, and allows
any descendant view in its hierarchy to introspect on which view
layer it is being presented in.
This commit lays a foundation that will later become important for
improving video coordination.
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit adds an opacity transition when swiping to dismiss an item,
to make it clear that the user is about to dismiss it.
Changelog-Changed: Swipe to dismiss on full screen carousel now shows an opacity effect for improved UX
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit renames this class to better represent what it does.
This reduces some of the term overloading between this class and other video
controller classes/structs. (Such as AVPlayerController)
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Add share button in Full screen image carousel view images
The ellipsis (share button) allows you to share the current image being displayed in the full screen carousel viewer.
Changelog-Changed: Add share button for images on full screen image carousel view
Signed-off-by: Swift Coder <scoder1747@gmail.com>
Add Edit button that navigates onto Profile Page
Add ShareLink button that allows us to Share actual image
Add Tap gesture in profile pic image viewer
Changelog-Added: Add Edit, Share, and Tap-gesture in Profile pic image viewer
Signed-off-by: Swift Coder <scoder1747@gmail.com>
There was a nostr.build auth issue when uploading banner images. This
fixes that.
Closes: #2614
Changelog-Fixed: Fix banner image uploa
Signed-off-by: Swift Coder <scoder1747@gmail.com>
This PR simply reduces the bold font in the side menu labels.
Changelog-Changed: Changed boldness of font in side menu labels.
Signed-off-by: ericholguin <ericholguin@apache.org>
This PR replaces the search notes button with the searched word.
This also removes the magnifying glass image from the search buttons.
Closes: #2601
Changelog-Changed: Changed search notes button with searched keyword
Signed-off-by: ericholguin <ericholguin@apache.org>
Terry Yiu (1):
Fix localization issues and export strings
Transifex (5):
Translate Localizable.strings in th
Translate Localizable.strings in ja
Translate Localizable.strings in ja
Translate Localizable.strings in nl
Translate Localizable.strings in hu_HU
This updates the dismiss button on the fullscreen carousel
so that it is more visible in some scenarios.
Changelog-Fixed: Fix dismiss button visibility
Signed-off-by: Swift Coder <scoder1747@gmail.com>
It looks like some refactor broke q tags on quote reposts. This drops
the gather_quote_tags entirely and just relies on the logic in
build_post.
The references field wasn't being used for anything other than pubkeys,
so we switch to pubkeys directly.
Changelog-Fixed: Fix quote repost counting
Signed-off-by: William Casarin <jb55@jb55.com>
This PR simply increases the opacity of the tabbar and post button.
The increase in opacity makes the post button active.
Closes: #2598Closes: #2599
Changelog-Changed: Changed opacity of tabbar and post button
Signed-off-by: ericholguin <ericholguin@apache.org>
This PR fixes the overlapping text in the Universe View.
Changelog-Fixed: Fixed overlapping text in Universe View
Signed-off-by: ericholguin <ericholguin@apache.org>
This PR redesigns the side menu to more closely match Roberto's design
Changelog-Changed: Changed side menu design
Signed-off-by: ericholguin <ericholguin@apache.org>
This commit fixes an issue with the chat bubble view where it would
unexpectedly trigger the reaction emoji keyboard when scrolling or
swiping, which became specially sensitive on iOS 18.
The fix consists of 2 parts:
- Changing the long press gesture logic to better adhere to Apple's API specs
- Modify the SwipeActions library to allow the gesture priority to be
configurable, and demote the swiping gesture to have normal priority
(it was found that having a high-priority drag gesture prevents
long-presses from being activated)
Closes: https://github.com/damus-io/damus/issues/2577
Changelog-Fixed: Fix sensitive long-press gesture on event chat bubble in iOS 18
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This PR fixes the bottom padding on views to account for the bottom tabbar,
now that the tabbar is an overlay we must account for it.
Changelog-Fixed: Fixed bottom padding for tabbar
Signed-off-by: ericholguin <ericholguin@apache.org>
This PR fixes the issue with the placement of the back navigation button in the profile edit view for iOS 18 devices:
Changelog-Fixed: Fixed back nav button placement in profile edit view
Signed-off-by: ericholguin <ericholguin@apache.org>
This PR is a ux change to make the header, tabbar, and post button disappear when the user scrolls.
The main tabbar is now an overlay which means it will display over views, this was needed in
order to get the timeline to extend behind it. However, this mean we must add bottom padding to any
view where the main tabbar is present to account for the overlap.
Changelog-Added: Disappearing header, tabbar, and post button on scroll
Signed-off-by: ericholguin <ericholguin@apache.org>
Transifex (11):
Translate Localizable.strings in th
Translate Localizable.strings in th
Translate Localizable.strings in th
Translate Localizable.strings in de
Translate Localizable.strings in zh_CN
Translate Localizable.strings in zh_HK
Translate Localizable.strings in zh_HK
Translate Localizable.strings in zh_TW
Translate Localizable.strings in de
Translate Localizable.strings in de
Translate Localizable.strings in de
This should be plenty
Fixes: https://github.com/damus-io/damus/issues/2547
Changelog-Changed: Expanded profile search results to 128
Changelog-Fixed: Friend profiles will now more likely show up in profile search
Signed-off-by: William Casarin <jb55@jb55.com>
This continues our hack due to the way the compiler bridges to static
sized arrays. yes its horrible. no i don't care.
Changelog-Changed: Expand nostrdb text search results to 128 items
Signed-off-by: William Casarin <jb55@jb55.com>
we're gonna need this when expanding search results
Changelog-Changed: Use LazyVStack in text search results
Signed-off-by: William Casarin <jb55@jb55.com>
This adds a PR template that will be applied to every new pull request,
to help both contributors and reviewers make sure that the contribution
guidelines are being met.
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This is needed because we already have a 1.10 build approved by Apple,
and they require a version number bump
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Pull some things from the 1.10 release branch into master:
Daniel D’Aquino (1):
Fix unclickable elements
William Casarin (4):
relays: add some ping/pong and connection logs
relay: don't reconnect when we don't have to
Merge some additional ios18 fixes
Daniel D’Aquino (1):
Fix unclickable elements
William Casarin (3):
relays: add some ping/pong and connection logs
relay: don't reconnect when we don't have to
We are reconnecting multiple times for two separate reasons:
1. On a cancellation "error" which does not warrant a reconnect
2. In our reconnection backoff it doesn't check If we are already
connecting or connected. We check this so we don't reconnect multiple
times.
This fixes many reconnection issues and makes Damus feel wayyy snappier.
Signed-off-by: William Casarin <jb55@jb55.com>
The introduction of iOS 18 brought a new bug that made `KFAnimatedImage`
not recognize tap gestures and become unclickable. (https://github.com/onevcat/Kingfisher/issues/2295)
This commit addresses the issue with a workaround found here:
https://github.com/onevcat/Kingfisher/issues/2046#issuecomment-1554068070
The workaround was suggested by the author of the library to fix a
slightly different issue, but that property seems to work for our
purposes.
The issue is addressed by adding a `contentShape` property to usages
of `KFAnimatedImage`, in order to make them clickable. A custom modifier
was created to make the solution less obscure and more obvious.
Furthermore, one empty tap gesture handler was removed as it was
preventing other tap gesture handlers on the image carousel from being
triggered on iOS 18
Testing
-------
PASS
Configurations:
- iPhone 13 mini on iOS 18.0
- iPhone SE simulator on iOS 17.5
Damus: This commit
Coverage:
- Check that the following views are clickable:
- Images in the carousel
- Profile picture on notes
- Profile picture on thread comments
- Profile picture on profile page
Changelog-Fixed: Fix items that became unclickable on iOS 18
Closes: https://github.com/damus-io/damus/issues/2342
Closes: https://github.com/damus-io/damus/issues/2370
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
- Add subtitle below the toolbar title to indicate the state of the filter
- Add settings icon to take user to the notification settings page, and
thus make that more discoverable
Testing
-------
PASS
Device: iPhone 13 mini
iOS: 17.6.1
Coverage:
1. Switching back and forth between the notifications tab and other tabs
causes subtitle to show/hide as expected in both filter options
(all, friends)
2. Subtitle follows the friends filter
3. Subtitle shows after restarting the app
4. Settings icon appears and takes user to the notification setting view
5. Notification settings can be updated from that view.
Changelog-Changed: Improve notification view filtering UX
Closes: https://github.com/damus-io/damus/issues/2480
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit changes the appearance of the friends filter button to make it more visible
Testing:
- Checked appearance in both light mode and dark mode
- Checked appearance in all usages (notifications view and DM view)
- Checked consistency against the filter button in Universe view
Changelog-Changed: Improve visibility of friends filter button
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Removed line which forces preferred colour scheme to dark on iOS 18, and
made adjustments to the styling to maintain text legibility
Changelog-Fixed: Fixed issue where theme would be changed to black and can't be switched back on iOS 18
Closes: https://github.com/damus-io/damus/issues/2373
Co-authored-by: Daniel D’Aquino <daniel@daquino.me>
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Unless the user signed up after changes from Github issue #2057, the contact list delegate would never be set due to a logic error, which means latest_contact_event_changed would never get called and the app would never save a local contact list reference to pull from — which caused issues when switching to different relays.
Testing
--------
PASS
Device: iPhone 15 simulator
iOS: 17.5
Setup: Manually removed UserSettingsStore::latest_contact_event_id_hex value to replicate the entry condition for the bug
Steps:
1. Add new relay (relay.zap.store)
2. Remove all other relays
3. Attempt to add relay. Ensure new relay can be added
4. Remove all relays
5. Add the `wss://notify-staging.damus.io` relay (which will not save any events)
6. Restart app
7. Try to add a new relay. Ensure a new relay can be added
8. Make a test post. Ensure the new test post is posted successfully.
Changelog-Fixed: Fixed some scenarios where the contact list would never be saved locally and cause issues when switching relays.
Closes: https://github.com/damus-io/damus/issues/2293
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
A change around the NostrPost interfaces caused unit tests to fail
compilation. This commit fixes that.
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This PR adds the NDB search functionality from the pull down search in the
posting timeline to the universe view.
Changelog-Added: Added NDB search functionality to the universe view
Signed-off-by: ericholguin <ericholguin@apache.org>
Unless the user signed up after changes from Github issue #2057, the contact list delegate would never be set due to a logic error, which means latest_contact_event_changed would never get called and the app would never save a local contact list reference to pull from — which caused issues when switching to different relays.
Testing
--------
PASS
Device: iPhone 15 simulator
iOS: 17.5
Setup: Manually removed UserSettingsStore::latest_contact_event_id_hex value to replicate the entry condition for the bug
Steps:
1. Add new relay (relay.zap.store)
2. Remove all other relays
3. Attempt to add relay. Ensure new relay can be added
4. Remove all relays
5. Add the `wss://notify-staging.damus.io` relay (which will not save any events)
6. Restart app
7. Try to add a new relay. Ensure a new relay can be added
8. Make a test post. Ensure the new test post is posted successfully.
Changelog-Fixed: Fixed some scenarios where the contact list would never be saved locally and cause issues when switching relays.
Closes: https://github.com/damus-io/damus/issues/2293
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit hardcodes the push notification feature flag to true, in
preparation for purple testflight release.
It also changes the notification mode setting string, to ensure that we
won't have issues with people being stuck with local notification mode.
Testing
-------
Steps:
1. Run app
2. Ensure push notification flag is gone from developer Settings
3. Ensure notification mode is set to push, and that the push option is available
4. Ensure push notification settings appear as "synced successfully"
Conditions:
- iPhone 13 mini, iOS 17.6.1, on a device that was already under testing
- iPad simulator, iOS 17.5, brand new account
Changelog-Added: Push notification support
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit links localization data to the extension targets so that
those targets can successfully localize data
Testing
-------
PASS
Device: iPhone 13 Mini
Damus: This commit
iOS: 17.6.1
Setup:
- Staging environment
- Push notifications enabled and configured
Steps:
1. Send a zap without message to the device with push notifications setup
2. Ensure message appears localized, not a localization key (`zap_notification_no_message`)
3. Change language to Portuguese
4. Make a highlight via the extension. Ensure some or all of the UI elements are localized into Portuguese
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Closes: https://github.com/damus-io/damus/issues/2419
This commit reapplies the "ux: Mute selected text" commit, with some
manual rework to solve logical conflicts during merge.
Rework testing
--------------
PASS
Device: iPhone 13 Mini
iOS: 17.6.1
Steps:
1. Go to a note
2. Select text and click on the "highlight" button. Ensure that highlight sheet appears with the correct text
3. Select text and click on the "mute" button. Ensure that mute sheet appears with the correct text
Original commit: d663155941
Original author: ericholguin <ericholguin@apache.org>
Reworked-by: Daniel D’Aquino <daniel@daquino.me>
Retested-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
This commit adds an option that allows a user to choose a custom push
notification server, as well as the staging notify server, to help with testing
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This brings Daniel's highlighter safari extension to master/testflight.
Previously we only had it on the 1.10 release branch. This also includes
some extended virtual addressing fixes to fix push notifications, we
also update the push notification server address since that seems to
have been missed.
Daniel D’Aquino (8):
Update push notification server address
Add convenience functions
Simplify SelectableText state management
Add support for rendering highlights with comments
Add support for adding comments when creating a highlight
Add highlighter extension
Fix highlight tag ambiguity with specifiers
Improve handling of NostrDB when switching apps
William Casarin (5):
lmdb: patch semaphore names to use shared group container prefix
Revert "ux: Mute selected text"
notifications: add extended virtual addressing entitlement
highlighter: add extended virtual addressing entitlement
It looks like our push notification service was missing the extended
virtual memory entitlement. This is required to open nostrdb databases.
Signed-off-by: William Casarin <jb55@jb55.com>
There was an issue where profiles on Damus would not load when switching
back and forth between the extension and Damus.
This commit fixes that by closing NostrDB when the extension is backgrounded
Testing
-------
PASS
Device: iPhone 13 Mini
iOS: 17.6.1
Damus: This commit
Steps:
1. Go to a webpage in safari, and open the highlight extension
2. With the highlight extension open, switch apps to Damus (without closing the extension)
3. Make sure profiles can be loaded on Damus
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit fixes the ambiguity in tags used in highlights with comments, by adding specifiers to help clients understand:
- If a URL reference is the source of the highlight or just a URL mentioned in the comment
- If a pubkey reference is the author of the highlighted content, or just a generic mention in the comment
This tries to be backwards compatible with previous versions of NIP-84.
Testing
--------
PASS
Device: iPhone 15 simulator
iOS: 17.5
Damus: This commit
Steps:
1. Create a new highlight from a webpage using the extension. Tag a user and attach an image
2. Check the newly-created highlight:
1. Highlight description line should just say "Highlighted", not "Highlighted <username>"
2. Highlight source link preview should present the URL of the highlighted page, NOT the image URL
3. Inspect the JSON for the newly-created highlight:
1. "r" tags should include specifiers in the 3rd slot, such as "source" or "mention"
2. "p" tags should include specifiers in the 3rd slot, such as "mention"
4. Go to an older, generic highlight (without comment) to another nostr event and check the view.
1. Highlight description line should say "Highlighted <author_name_of_other_event>"
2. Clicking on the highlight should lead to the highlighted event itself.
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit adds a highlighting extension for web pages. This works on
Safari, and can be used by selecting a text on a page and hitting the
share button at the bottom of the Safari UI
To make this possible, some refactoring was necessary:
1. Several sources were included in the extension bundle to provide access to DamusState, PostView, and the postbox
2. UIApplication.shared was replaced with `this_app`, which routes to UIApplication.shared on the main app bundle,
and routes to a bogus UIApplication() in the extension. This is needed because UIApplication.shared cannot be used on an extension.
3. Some items were moved to different files to facilitate the transition.
The extension itself uses PostView, and implements views for several edge cases, and tries to handle the note publishing process gracefully.
Changelog-Added: Add highlighter for web pages
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit implements rendering comments from the `["comment",
<COMMENT_TEXT>]` tag in a highlight note.
Comment contents get rendered like a kind 1 note's "content" field
This commit also adds the `r` "reference" tag as a standard tag reference type
Changelog-Added: Add support for rendering highlights with comments
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit simplifies the state management and information flow for SelectableText.
This also fixes issues and inconsistencies with the selected text for a highlight action,
which often appeared in some scenarios with the symptom of a highlight
action showing the incorrect or outdated selected text.
Previously, the state of the selected text and highlight action was
tracked in two independent state/binding variables which caused
re-renders when they were modified, often leading to inconsistencies as
those two independent variables would not be changed atomically across
renders leading to inconsistent, undefined behavior
The commit addresses this by using a single state object instead of two,
and a direct callback interface when the highlight button is pressed,
which eliminates the need of relying on view re-renders to apply.
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit adds a convenience initializer for DamusState that is
simpler than the normal initializer, to allow extensions to more easily
use it.
It also includes a new convenience function for `should_blur_images`
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
I had to revert this for now because it conflicts too heavily
with the highlighter feature which we definitely want in master.
Let's rework this using Daniel's refactor
This reverts commit d663155941.
Daniel D’Aquino (7):
Add convenience functions
Simplify SelectableText state management
Add support for rendering highlights with comments
Add support for adding comments when creating a highlight
Add highlighter extension
Fix highlight tag ambiguity with specifiers
Improve handling of NostrDB when switching apps
William Casarin (4):
lmdb: patch semaphore names to use group container prefix
notifications: add extended virtual addressing entitlement
highlighter: add extended virtual addressing entitlement
It looks like our push notification service was missing the extended
virtual memory entitlement. This is required to open nostrdb databases.
Signed-off-by: William Casarin <jb55@jb55.com>
This is an attempt to fix various issues when acquiring a IPC
semaphore on iOS
See: https://github.com/damus-io/damus/issues/2323#issuecomment-2323181204
Running this patch gives us these names:
mdb_env_setup_locks: using semnames
'group.com.damus/MDBrwDDi_FHxD' (29),
'group.com.damus/MDBwwDDi_FHxD' (29)
From old Apple docs:
> IPC and POSIX Semaphores and Shared Memory
>
> Normally, sandboxed apps cannot use Mach IPC, POSIX semaphores and
> shared memory, or UNIX domain sockets (usefully). However, by specifying
> an entitlement that requests membership in an application group, an app
> can use these technologies to communicate with other members of that
> application group.
>
> Note: System V semaphores are not supported in sandboxed apps.
>
> UNIX domain sockets are straightforward; they work just like any other
> file.
>
> Any semaphore or Mach port that you wish to access within a sandboxed
> app must be named according to a special convention:
>
> POSIX semaphores and shared memory names must begin with the application
> group identifier, followed by a slash (/), followed by a name of your
> choosing.
>
> Mach port names must begin with the application group identifier,
> followed by a period (.), followed by a name of your choosing.
>
> For example, if your application group’s name is
> Z123456789.com.example.app-group, you might create two semaphores named
> Z123456789.myappgroup/rdyllwflg and Z123456789.myappgroup/bluwhtflg. You
> might create a Mach port named
> Z123456789.com.example.app-group.Port_of_Kobe.
>
> Note: The maximum length of a POSIX semaphore name is only 31 bytes, so
> if you need to use POSIX semaphores, you should keep your app group
> names short.
Link: https://github.com/damus-io/damus/issues/2323#issuecomment-2323305949
Signed-off-by: William Casarin <jb55@jb55.com>
mdb_env_setup_locks: using semnames
'group.com.damus/MDBrwDDi_FHxD' (29),
'group.com.damus/MDBwwDDi_FHxD' (29)
From old Apple docs:
> IPC and POSIX Semaphores and Shared Memory
>
> Normally, sandboxed apps cannot use Mach IPC, POSIX semaphores and
> shared memory, or UNIX domain sockets (usefully). However, by specifying
> an entitlement that requests membership in an application group, an app
> can use these technologies to communicate with other members of that
> application group.
>
> Note: System V semaphores are not supported in sandboxed apps.
>
> UNIX domain sockets are straightforward; they work just like any other
> file.
>
> Any semaphore or Mach port that you wish to access within a sandboxed
> app must be named according to a special convention:
>
> POSIX semaphores and shared memory names must begin with the application
> group identifier, followed by a slash (/), followed by a name of your
> choosing.
>
> Mach port names must begin with the application group identifier,
> followed by a period (.), followed by a name of your choosing.
>
> For example, if your application group’s name is
> Z123456789.com.example.app-group, you might create two semaphores named
> Z123456789.myappgroup/rdyllwflg and Z123456789.myappgroup/bluwhtflg. You
> might create a Mach port named
> Z123456789.com.example.app-group.Port_of_Kobe.
>
> Note: The maximum length of a POSIX semaphore name is only 31 bytes, so
> if you need to use POSIX semaphores, you should keep your app group
> names short.
Link: https://github.com/damus-io/damus/issues/2323#issuecomment-2323305949
Signed-off-by: William Casarin <jb55@jb55.com>
There was an issue where profiles on Damus would not load when switching
back and forth between the extension and Damus.
This commit fixes that by closing NostrDB when the extension is backgrounded
Testing
-------
PASS
Device: iPhone 13 Mini
iOS: 17.6.1
Damus: This commit
Steps:
1. Go to a webpage in safari, and open the highlight extension
2. With the highlight extension open, switch apps to Damus (without closing the extension)
3. Make sure profiles can be loaded on Damus
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
AlbyHub does not use description hash invoices. We had some code that
looked for zap request invoices inside the description which albyhub
does not do.
Change our code to always get the zap_request from the description.
Changelog-Fixed: Fix albyhub zaps not appearing
Signed-off-by: William Casarin <jb55@jb55.com>
It was noticed that adding a space inadvertently escapes the user
mention suggestion menu (even though several users have an escape
character in their name)
This commit fixes that issue, and improves overall handling of user
mention escape sequences, by allowing those sequences to be made up of
multiple characters instead of a single one.
Testing
-------
Device: iPhone 13 Mini
iOS: 17.6.1
Damus: This commit
Steps:
1. Type normally. Make sure Text editing works normally
2. Try to type a mention with a long name with spaces. Make sure typing
spaces does not cause the mention suggestions menu to be dismissed.
3. Select a user, make sure mention suggestions menu gets dismissed
4. Try to type a mention with a long name with spaces, but this time
instead of selecting a user, just add a punctuation mark. Make sure
the mention suggestions menu gets dismissed
5. Repeat the step above with the following escape sequences:
1. Newline
2. Another "@"
3. ", "
4. " " (double-space)
5. ". "
6. Delete characters all the way back to an existing mention. Make sure
mention gets broken with a backspace, showing the mention suggestions
menu once again.
7. Type a mention and select a user
8. Right after the new user mention, with a single space, start typing something
else ("e.g. @daniel blah"). Make sure that the mention menu does NOT show up when cursor is at the end of "blah"
9. Right after the new user mention, with a single space, start typing a
mention ("e.g. @daniel @jb"). Make sure the mention menu DOES show
up, and suggests "@jb55"
Changelog-Fixed: Fix inadvertent escape from mention suggestion menu when typing a space character
Closes: https://github.com/damus-io/damus/issues/2008
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
AlbyHub does not use description hash invoices. We had some code that
looked for zap request invoices inside the description which albyhub
does not do.
Change our code to always get the zap_request from the description.
Fixes: https://github.com/damus-io/damus/issues/2363
Changelog-Fixed: Fix albyhub zaps not appearing
Signed-off-by: William Casarin <jb55@jb55.com>
This commit fixes an issue where DM contents would not be displayed on a
push notification, by giving the notification extension access to the
keychain group which contains the user's private key
Testing
--------
PASS
Device: iPhone 13 mini
iOS: 17.6.1
Damus: This commit
Setup:
- Make sure that device is setup with push notifications
- DM notifications enabled
- Device registered with push notification server
Steps:
1. Send a DM push notification to yourself
2. Ensure DM contents can be decrypted on the push notification body
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Closes: https://github.com/damus-io/damus/issues/2388
This commit fixes an issue where DM contents would not be displayed on a
push notification, by giving the notification extension access to the
keychain group which contains the user's private key
Testing
--------
PASS
Device: iPhone 13 mini
iOS: 17.6.1
Damus: This commit
Setup:
- Make sure that device is setup with push notifications
- DM notifications enabled
- Device registered with push notification server
Steps:
1. Send a DM push notification to yourself
2. Ensure DM contents can be decrypted on the push notification body
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Closes: https://github.com/damus-io/damus/issues/2388
This commit fixes the ambiguity in tags used in highlights with comments, by adding specifiers to help clients understand:
- If a URL reference is the source of the highlight or just a URL mentioned in the comment
- If a pubkey reference is the author of the highlighted content, or just a generic mention in the comment
This tries to be backwards compatible with previous versions of NIP-84.
Testing
--------
PASS
Device: iPhone 15 simulator
iOS: 17.5
Damus: This commit
Steps:
1. Create a new highlight from a webpage using the extension. Tag a user and attach an image
2. Check the newly-created highlight:
1. Highlight description line should just say "Highlighted", not "Highlighted <username>"
2. Highlight source link preview should present the URL of the highlighted page, NOT the image URL
3. Inspect the JSON for the newly-created highlight:
1. "r" tags should include specifiers in the 3rd slot, such as "source" or "mention"
2. "p" tags should include specifiers in the 3rd slot, such as "mention"
4. Go to an older, generic highlight (without comment) to another nostr event and check the view.
1. Highlight description line should say "Highlighted <author_name_of_other_event>"
2. Clicking on the highlight should lead to the highlighted event itself.
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
It was noticed that adding a space inadvertently escapes the user
mention suggestion menu (even though several users have an escape
character in their name)
This commit fixes that issue, and improves overall handling of user
mention escape sequences, by allowing those sequences to be made up of
multiple characters instead of a single one.
Testing
-------
Device: iPhone 13 Mini
iOS: 17.6.1
Damus: This commit
Steps:
1. Type normally. Make sure Text editing works normally
2. Try to type a mention with a long name with spaces. Make sure typing
spaces does not cause the mention suggestions menu to be dismissed.
3. Select a user, make sure mention suggestions menu gets dismissed
4. Try to type a mention with a long name with spaces, but this time
instead of selecting a user, just add a punctuation mark. Make sure
the mention suggestions menu gets dismissed
5. Repeat the step above with the following escape sequences:
1. Newline
2. Another "@"
3. ", "
4. " " (double-space)
5. ". "
6. Delete characters all the way back to an existing mention. Make sure
mention gets broken with a backspace, showing the mention suggestions
menu once again.
7. Type a mention and select a user
8. Right after the new user mention, with a single space, start typing something
else ("e.g. @daniel blah"). Make sure that the mention menu does NOT show up when cursor is at the end of "blah"
9. Right after the new user mention, with a single space, start typing a
mention ("e.g. @daniel @jb"). Make sure the mention menu DOES show
up, and suggests "@jb55"
Changelog-Fixed: Fix inadvertent escape from mention suggestion menu when typing a space character
Closes: https://github.com/damus-io/damus/issues/2008
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This PR adds mute button to ProfileActionSheet, allowing user to quick mute npubs/bots
Changelog-Added: Added mute button to ProfileActionSheet
Signed-off-by: chungwwei <chungwwei223@gmail.com>
This PR adds the Mute action to the selected text menu. Pressing the mute
action will pop up a sheet which allows users to confirm their selection and
choose for how long they would like to mute the selected text for.
Changelog-Added: Added mute action to selected text menu
Signed-off-by: ericholguin <ericholguin@apache.org>
This PR adds improvements to the profile edit view. The banner image is
changed from the old ostrich image to the fresh new damoose. The image and
banner url text entries have been removed from the edit form and now live under
the image selector menu. Selecting the Image URL menu option presents a sheet
where a user can update the image URL. There are now safe guards in place for
users who update their profile, if they make any changes and try to navigate
back to home they will get an alert asking if they want to discard changes. The
Save button is also more prominent.
Changelog-Changed: Changed the default banner from ostriches to damoose
Changelog-Added: Added profile edit safe guards
Changelog-Changed: Changed image and banner url text fields to new sheet view
Signed-off-by: ericholguin <ericholguin@apache.org>
This PR just adds the tor icon to relays ending with .onion
Changelog-Added: Tor relay icon
Closes: #2318
Signed-off-by: ericholguin <ericholguin@apache.org>
This commit implements push notification preferences with the push
notifications server, as well as updates itself to the new push
notifications API.
Testing
-------
Device: iPhone 15 simulator
iOS: 17.5
Damus: this commit
notepush: 3ca3a8325707535fdbc98d681d5e4a47dc313c67
Steps:
1. Enable push notifications. Settings should get synced and success message should appear
2. Disable push notifications. Sync message should disappear as it no longer applies
3. Enable push notifications again, and tweak notifications. Settings should sync with no errors
4. Leave settings screen and come back. Settings should be declared as synced
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Closes: https://github.com/damus-io/damus/issues/2360
This commit adds a highlighting extension for web pages. This works on
Safari, and can be used by selecting a text on a page and hitting the
share button at the bottom of the Safari UI
To make this possible, some refactoring was necessary:
1. Several sources were included in the extension bundle to provide access to DamusState, PostView, and the postbox
2. UIApplication.shared was replaced with `this_app`, which routes to UIApplication.shared on the main app bundle,
and routes to a bogus UIApplication() in the extension. This is needed because UIApplication.shared cannot be used on an extension.
3. Some items were moved to different files to facilitate the transition.
The extension itself uses PostView, and implements views for several edge cases, and tries to handle the note publishing process gracefully.
Changelog-Added: Add highlighter for web pages
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit implements rendering comments from the `["comment",
<COMMENT_TEXT>]` tag in a highlight note.
Comment contents get rendered like a kind 1 note's "content" field
This commit also adds the `r` "reference" tag as a standard tag reference type
Changelog-Added: Add support for rendering highlights with comments
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit simplifies the state management and information flow for SelectableText.
This also fixes issues and inconsistencies with the selected text for a highlight action,
which often appeared in some scenarios with the symptom of a highlight
action showing the incorrect or outdated selected text.
Previously, the state of the selected text and highlight action was
tracked in two independent state/binding variables which caused
re-renders when they were modified, often leading to inconsistencies as
those two independent variables would not be changed atomically across
renders leading to inconsistent, undefined behavior
The commit addresses this by using a single state object instead of two,
and a direct callback interface when the highlight button is pressed,
which eliminates the need of relying on view re-renders to apply.
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit adds a convenience initializer for DamusState that is
simpler than the normal initializer, to allow extensions to more easily
use it.
It also includes a new convenience function for `should_blur_images`
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit fixes a consistent crash noticed when visiting a particular
profile.
The crash was occuring when trying to display the blurhash of a specific Event, where the metadata claimed the image dimensions were 0px x 0px.
The null dimensions caused a division by zero to occur when scaling the image down, yielding a NaN (Not a Number) size value, which crashed the app when trying to cast that CGFloat value down to an integer.
The crash was fixed by modifying the down-scaling computations to check for invalid dimensions, and return nil. The callers were then updated to fallback to a default display dimension.
Issue repro
-------
Device: iPhone 15 simulator
iOS: 17.5
Damus: dba1799df0
Steps:
1. Visit the profile npub1gujeqakgt7fyp6zjggxhyy7ft623qtcaay5lkc8n8gkry4cvnrzqd3f67z
2. Check accessing the profile does not crash Damus.
3. Visit the event that had invalid 0x0 dimensions on the metadata (note1qmqdualjezamcjun23l4d9xw7529m7fee6hklgtnhack2fwznxysuzuuyz)
4. Check that Damus does not crash.
Results: Steps 2 and 4 crash 100% of the time (3/3)
Testing
--------
PASS
Device: iPhone 15 simulator
iOS: 17.5
Damus: This commit
Steps: Same as repro
Results:
1. Crash no longer occurs
2. Blurhash looks ok
Closes: https://github.com/damus-io/damus/issues/2341
Changelog-Fixed: Fix crash when viewing notes with invalid image dimension metadata
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This PR adds improvements to the profile edit view. The banner image is
changed from the old ostrich image to the fresh new damoose. The image and
banner url text entries have been removed from the edit form and now live under
the image selector menu. Selecting the Image URL menu option presents a sheet
where a user can update the image URL. There are now safe guards in place for
users who update their profile, if they make any changes and try to navigate
back to home they will get an alert asking if they want to discard changes. The
Save button is also more prominent.
Changelog-Changed: Changed the default banner from ostriches to damoose
Changelog-Added: Added profile edit safe guards
Changelog-Changed: Changed image and banner url text fields to new sheet view
Signed-off-by: ericholguin <ericholguin@apache.org>
This commit fixes a consistent crash noticed when visiting a particular
profile.
The crash was occuring when trying to display the blurhash of a specific Event, where the metadata claimed the image dimensions were 0px x 0px.
The null dimensions caused a division by zero to occur when scaling the image down, yielding a NaN (Not a Number) size value, which crashed the app when trying to cast that CGFloat value down to an integer.
The crash was fixed by modifying the down-scaling computations to check for invalid dimensions, and return nil. The callers were then updated to fallback to a default display dimension.
Issue repro
-------
Device: iPhone 15 simulator
iOS: 17.5
Damus: dba1799df0
Steps:
1. Visit the profile npub1gujeqakgt7fyp6zjggxhyy7ft623qtcaay5lkc8n8gkry4cvnrzqd3f67z
2. Check accessing the profile does not crash Damus.
3. Visit the event that had invalid 0x0 dimensions on the metadata (note1qmqdualjezamcjun23l4d9xw7529m7fee6hklgtnhack2fwznxysuzuuyz)
4. Check that Damus does not crash.
Results: Steps 2 and 4 crash 100% of the time (3/3)
Testing
--------
PASS
Device: iPhone 15 simulator
iOS: 17.5
Damus: This commit
Steps: Same as repro
Results:
1. Crash no longer occurs
2. Blurhash looks ok
Closes: https://github.com/damus-io/damus/issues/2341
Changelog-Fixed: Fix crash when viewing notes with invalid image dimension metadata
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit implements push notification preferences with the push
notifications server, as well as updates itself to the new push
notifications API.
Testing
-------
Device: iPhone 15 simulator
iOS: 17.5
Damus: this commit
notepush: 3ca3a8325707535fdbc98d681d5e4a47dc313c67
Steps:
1. Enable push notifications. Settings should get synced and success message should appear
2. Disable push notifications. Sync message should disappear as it no longer applies
3. Enable push notifications again, and tweak notifications. Settings should sync with no errors
4. Leave settings screen and come back. Settings should be declared as synced
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Closes: https://github.com/damus-io/damus/issues/2360
This PR just adds the tor icon to relays ending with .onion
Changelog-Added: Tor relay icon
Closes: #2318
Signed-off-by: ericholguin <ericholguin@apache.org>
This patch allows highlights to be included in posts as well as removes context
when creating a highlight. Highlights now route as the root and selecting the
highlight in root routes to the highlighted event.
Signed-off-by: ericholguin <ericholguin@apache.org>
This patch allows highlights to be included in posts as well as removes context
when creating a highlight. Highlights now route as the root and selecting the
highlight in root routes to the highlighted event.
Signed-off-by: ericholguin <ericholguin@apache.org>
With this commit, long-presses on chat bubbles will now reveal a zap
sheet if they are on OnlyZaps mode and have zaps unlocked.
Users without OnlyZaps or with Zaps blocked will continue to see the
emoji reaction sheet
Closes: https://github.com/damus-io/damus/issues/2327
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit adds event mentions to the chat bubbles.
Testing
-------
PASS
Damus: This commit
Device: iPhone 15 simulator
iOS: 17.5
Coverage:
- Tested referencing an event on a thread reply. Thread reply shows up as expected
- Checked appearance on light and dark mode
- Tapping on the mentioned event takes the user to that event
Closes: https://github.com/damus-io/damus/issues/2309
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Very large messages on the chat event view cause issues with swipe and
long-press interactions, and they might be a nuisance during scrolling.
This commit adds text truncation to the chat event view. The "show
more" button causes the user to navigate to the message, which is
reasonable to avoid overloading too many interactions on the same view
and having a huge text bubble that is difficult to interact with.
Closes: https://github.com/damus-io/damus/issues/2326
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Some users have reported that there is unwanted horizontal padding on
small messages. This was due to the minimum chat event view width. To
address this feedback, the minimum width has been reduced to a very
small amount, so that small messages with no other content can more
tightly hug the inner content.
Closes: https://github.com/damus-io/damus/issues/2312
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Some japanese user profiles are breaking the flatbuffer profile
builder for some reason
Changelog-Fixed: Fix pretty bad crash when building flatbuffer profiles
Signed-off-by: William Casarin <jb55@jb55.com>
This commit sets up the correct server address to send device token
notifications to.
Testing
-------
PASS
Device: iPhone 13 Mini
iOS: 17.5
Damus: This commit
strfry-push-notify: 6c52129ab52f37f6686b1a3d1d0d8b478de9e60f
Setup:
- strfry-push-notify and notification device token server setup on the real damus server
- APNS environment setup to development on the server (temporarily)
- Developer settings turned on
- Experimental push notifications support turned ON
- "Send device tokens to localhost" setting turned OFF
- Notification mode in notification settings set to PUSH notifications
Steps:
1. Get a simulator up and running and connected to the Damus relay
2. Send a DM to the main device under test.
3. Check if push notification arrives even with Damus closed. PASS
Closes: https://github.com/damus-io/damus/issues/1733
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
This patch simplifies the onboarding flow based on Jeroen's suggestions.
Setup view:
- Removes extra nostr information
- Only shows two buttons, create account and sign in.
Create Account view:
- When a user uploads a photo it is now displayed
- Name is now required
- Public key is now hidden
- Create account model has been updated to match metadata
Save Keys view:
- Removes the requirement to copy the nsec
- Simplified explanation
- Only shows two buttons, save and not now
Testing
——
iPhone 15 Pro Max (17.0) Light Mode:
https://v.nostr.build/3P75x.mp4
iPhone SE (3rd generation) (16.4) Dark Mode:
https://v.nostr.build/wGBQL.mp4
——
Changelog-Fixed: Create Account model now uses correct metadata
Changelog-Changed: Onboarding design
Changed the interface of SelectableText to allow highlighting to be
disabled in places where it is not applicable (For example, on the
AboutView).
This prevents the need for adding dummy events in places where
highlighting is not applicable, preventing the user from making bad
highlights.
Testing
-------
PASS
Device: iPhone 13 mini
iOS: 17.5
Damus: This version
Steps:
1. Go to a user profile and select some text in their bio. The "highlight" option should not be present.
2. Go to a note and select some text. The "highlight" option should be available
This patch allows users to create a highlight in Damus.
This is done by modifying the menu options when text is selected, including a custom highlight option.
This option presents a sheet to the user of what they are highlighting with a cancel or post button.
If they press Post the sheet will dismiss and their highlight will be posted.
Testing
——
iPhone 15 Pro Max (17.3.1) Dark Mode:
https://v.nostr.build/wGDnx.mp4
iPhone SE (3rd generation) (16.4) Light Mode:
https://v.nostr.build/xEK0e.mp4
——
Changelog-Added: Ability to create highlights
Signed-off-by: ericholguin <ericholguin@apache.org>
This commit changes the thread view to a new UX concept where children views of the selected view are now presented as chat bubbles, and the entire tree of conversation is shown flattened. New interactions, layout, and design changes have been introduced to revamp the user experience.
Testing
-------
Device: A mix of iPhone physical devices and simulator
iOS: A mix of iOS 17 versions
Damus: A mix of versions leading up to this one.
Coverage:
1. Unit tests are passing
2. A select few users have been using prototypes versions of this as their daily driver
3. Layout tested with an eclectic mix of threads
4. Posting new notes to the thread works
5. Clicking on reply quote view takes user to the mentioned message with a momentary visible highlight
6. Swipe actions work
7. Long press on chat bubbles works and shows emoji selector. Adding emoji sends the reaction
8. Clicking on notes selects them with an easy to follow transition
Known issues:
1. The text on the reply quote view occasionally appears to be off-center (in about 10% of occurrences). The cause is still unknown
2. Long press will still show the emoji keyboard even if user is on "onlyzaps" mode
3. Quoted events are not rendered on chat bubbles. When user posts a quoted event with no text, that could lead to confusion
Closes: https://github.com/damus-io/damus/issues/1126
Changelog-Added: Completely new threads experience that is easier and more pleasant to use
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This patch simply disconects the wallet connection when a user logs out.
Changelog-Fixed: Fixed wallet not disconnecting when a user logs out
Signed-off-by: ericholguin <ericholguin@apache.org>
Signed-off-by: William Casarin <jb55@jb55.com>
Changing the notification mode setting requires successfully sending or
revoking the device token to the server. As this is an action that might
fail, it is important to have a clear UX feedback in case this fails.
Testing
--------
PASS
Device: iPhone 15 simulator
iOS: 17.4
Damus: This commit
strfry-push-notify: d6c2ff289c80e0a90874a7499ed6408394659fc9
Coverage:
1. Checked that push notification mode setting is invisible when experimental push notifications mode is disabled
2. Checked that push notification mode setting is visible when experimental push notifications mode is enabled
3. Checked that switching between push and local notifications sends requests to the server
4. Checked that switching to push notification mode will cause local notifications to be suppressed and push notifications will be sent to the APNS server
5. Checked that switching back to local notification mode will cause local notifications to be displayed, and push notifications will NOT be sent to APNS
6. Checked that if the API server is off, switching from local to push notification modes is not possible and shows an error to the user.
7. Checked that sending APNS payload to Apple's test APNS page will actually deliver the push notification successfully.
Closes: https://github.com/damus-io/damus/issues/1704
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
This commit moves the device token logic to a new
PushNotificationClient, to move complexity from this specific feature
away from damusApp.swift
This commit also slightly improves the handling of device tokens, by
caching it on the client struct even if the user is using local
notifications, so that the device token can be sent to the server immediately after
switching to push notifications mode.
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
This allows the user to switch between local and push notifications
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
We do not have the ability to suppress push notifications yet (we are
waiting to receive the entitlement from Apple)
In the meantime, attempt to fallback gracefully where possible
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
When a user is following several accounts, they may get a stale feed
caused by the subscription request being rejected by relays (due to max filter item limits).
This commit implements a fix that gets around the issue by
creating several chunked filters for the home feed event and contact
metadata subscriptions.
This is a short to medium-term practical fix, where we get around the
practical limitations imposed by most relays. In the future we should
work on longer-term solutions, which will likely require protocol improvements
Main Test
---------
Procedure:
1. Login with Elsat's npub (Or some account that follows about 2K people)
2. Check the home feed. There should be fresh notes.
REPRO:
Device: iPhone 15 simulator
iOS: 17.4
Damus: 1.9 (3) (0d9954290a)
Results:
- No fresh notes, most recent post is from several hours ago (Feed is stale)
FIX TEST:
Device: iPhone 15 simulator
iOS: 17.4
Damus: This commit
Results:
- Fresh notes appear, most recent post is from a few seconds ago.
Other testing:
--------------
- New automated test passing
- All other automated tests passing
- Tested scrolling down the feed on these conditions:
- Device: iPhone 13 Mini
- iOS: 17.4.1
- Accounts:
- One with about 160 contacts and 10 relays (Daniel D’Aquino)
- One with about 1K+ contacts and 9 relays (Freedom Smuggler)
- One with about 981 contacts and 6 relays (jb55)
- Elsat's account (2K+ accounts and 8 relays)
- Result: None of those were stale
Changelog-Fixed: Fix stale feed issue when follow list is too big
Closes: https://github.com/damus-io/damus/issues/2194
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
This removes EventRefs alltogether and uses the form we use in Damus
Android.
This simplifies our ThreadReply logic and fixes a reply-to-root bug
Reported-by: NotBiebs <justinbieber@stemstr.app>
Changelog-Fixed: Fix thread bug where a quote isn't picked up as a reply
Signed-off-by: William Casarin <jb55@jb55.com>
Our nip10 logic looks for notes only in the in-memory cache. This means
sometimes threads don't get fully loaded if for whatever reason it's in
the nostrdb cache but not in-memory.
Ideally we would just remove our in-memory cache, but for now let's just
hack it so it falls back to nostrdb and makes an owned note.
Changelog-Fixed: Fixed threads not loading sometimes
Signed-off-by: William Casarin <jb55@jb55.com>
This should drastically increase compatibility for damus replies in
other clients.
Also filter non-pubkey references when replying so we don't run into the
q-tag bug.
Changelog-Added: Added nip10 marker replies
Changelog-Fixed: Fixed issue where some replies were including the q tag
Fixes: https://github.com/damus-io/damus/issues/2239
Fixes: https://github.com/damus-io/damus/issues/2233
Signed-off-by: William Casarin <jb55@jb55.com>
This perf change was experimental and probably minor anyways
This reverts commit d49cf5a505.
Fixes: https://github.com/damus-io/damus/issues/2235
Changelog-Fixed: Fixed issue where timeline was scrolling when it isn't supposed to
Signed-off-by: William Casarin <jb55@jb55.com>
To filter muted events on a timeline, we need to check if an event is
muted. However, we need to do so in a very efficient manner, to avoid performance degradation.
This commit improves performance by caching mute statuses for as long as
the mutelist stays the same.
Testing
--------
PASS
Device: iPhone 13 Mini
iOS: 17.4.1
Damus: This commit
Damus baseline: bb8dba6df6e2534dfb193402399b31a4fae8052d
Steps:
1. Downgrade to baseline version, Run SwiftUI profiler on Xcode instruments
2. Scroll down home feed. Try to notice hangs and microhangs on the UI
3. Upgrade to version under test. Start the same profiler test.
4. Check that hangs/microhangs frequency and severity are roughly the same.
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
Mute rules were not applied in all timeline views. This commit adds code
to filter out muted events on timelines. It also provides an opt-out
parameter if there is ever a need to a timeline without mute filters
Testing
--------
PASS
Device: iPhone 13 Mini
iOS: 17.4.1
Damus: This commit
Coverage:
1. Add a muted keyword
2. Go to home view, check that events with that keyword are now not showing up
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Signed-off-by: William Casarin <jb55@jb55.com>
The user keypair is necessary to determine whether or not a given event
is muted or not. Previously, the user keypair had to be passed on each
function call as an optional parameter, and word filtering would not
work unless the caller remembered to add the keypair parameter.
All usages of MutelistManager functions indicate that the desired base
keypair is always the same as the DamusState's keypair that owns the
MutelistManager. Therefore, it is simpler and less error prone to simply
pass the keypair to MutelistManager during its initialization.
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Signed-off-by: William Casarin <jb55@jb55.com>
We still need to add these when writing notes.
Changelog-Added: Add marker nip10 support when reading notes
Signed-off-by: William Casarin <jb55@jb55.com>
This commit fixes an issue where the Damus relay (Or other bootstrap relays) would be added to the user's relay list even though they explicitly removed it.
The root cause of the issue lies in the way we load bootstrap relays. The default bootstrap relays would be initially loaded even though the user already has a bootstrap list stored, just in case all the relays on the user list fails. This would cause the app to inadvertently connect to relays that the user did not select whenever there is a connectivity issue with all their listed relays.
The fix is to simply not add the default bootstrap list when the user already has a list stored. We do not need to use bootstrap relays in order to get our relay list, because that list is already stored in both UserDefaults as well as on NostrDB through the user's contact list event. (A contact list which is also locally loaded on startup since the fix related to https://github.com/damus-io/damus/issues/2057)
Issue reproduction + Testing
----------------------------
Procedure:
1. Disconnect from all relays, and disconnect from the Damus relay last.
2. Connect to a local relay (that you control). Connection should be successful.
3. Quit the app completely.
4. Stop the local relay.
5. Restart the app.
6. Go to the relay list view.
7. Check the relay list. It should list the one local relay selected by the user
Issue reproduction:
- Device: iPhone 15 simulator
- iOS: 17.4
- Damus: 1.8 (`97169f4fa276723bfab28ca304953ec206c904d2`)
- Result: ISSUE REPRODUCED
- Details: On step 7, the relay list only lists the Damus relay
Fix test:
- Device: iPhone 15 simulator
- iOS: 17.4
- Damus: This commit
- Result: PASS
- Details: On step 7, the local relay is listed even though connection is unsuccessful. No notes are loaded since no relays were able to connect successfully
Quick regression check
----------------------
PASS
Device: iPhone 15 simulator
iOS: 17.4
Damus: This commit
Steps:
1. Reinstall app from scratch
2. Create a new account, go through onboarding
3. Make sure that new account connects to bootstrap relays. PASS
4. Sign out
5. Sign in with previously existing account (The one from the previous test) (Notice no UserDefaults exists for this user at that point)
6. Make sure relay list is loaded to the latest relay list known to the bootstrap relays (i.e. connects only to the Damus relay) (It cannot recover the latest relay list pointing only to the local relay, since the bootstrap relays have no knowledge about that relay or the contact lists stored there.). PASS
Note: The behavior on step 6 is not a bug, it is an expected limitation. In fact, this behavior is privacy protecting, as the user may not want those public relays from knowing about its connection preference to the local relay (and its address)
Other information
------------------
Q: How is this test using local relays related or equivalent to Tor relay list described in #2186?
A: Those Tor relays need dedicated software (such as Orbot VPN) to be running successfully in order for Damus to make a successful connection to them. If at any moment that VPN stops working, it would trigger the same situation as described in the test above, where all relay connections fail at once.
Q: In #2186, the user reports that the Damus relay is added, but does not describe the Damus relay replacing existing relays. What is the difference?
A: I believe the difference is in the order in which relays are added or removed. We have to remember that the relay we just disconnected from will likely still have version N-1 of our contact list event, where it still includes itself on that list.
Changelog-Fixed: Fix issue where bootstrap relays would inadvertently be added to the user's list on connectivity issues
Closes: https://github.com/damus-io/damus/issues/2186
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
This commit fixes GIF uploads and improves GIF support:
- MediaPicker will now skip location data removal processing, as it is not needed on GIF images and causes them to be converted to JPEG images
- The uploader now sets more accurate MIME types on the upload request
Issue Repro
-----------
Device: iPhone 13 Mini
iOS: 17.4.1
Damus: `ada99418f6fcdb1354bc5c1c3f3cc3b4db994ce6`
Steps:
1. Download a GIF from GIPHY to the iOS photo gallery
2. Upload that and attach into a post in Damus
3. Check if GIF is animated.
Results: GIF is not animated. Issue is reproduced.
Testing
-------
PASS
Device: iPhone 13 Mini
iOS: 17.4.1
Damus: this commit
Steps:
1. Create a new post
2. Upload the same GIF as the repro and post
3. Make sure GIF is animated. PASS
4. Create a new post
5. Upload a new GIF image (that has never been uploaded by the user on the app) and post
6. Make sure the GIF is animated on the post. PASS
7. Make sure that JPEGs can still be successfully uploaded. PASS
8. Make sure that MP4s can be uploaded.
9. Make a new post that contains 1 JPEG, 1 MP4 file, and 2 GIF files. Make sure they are all uploaded correctly and all GIF files are animated. PASS
Closes: https://github.com/damus-io/damus/issues/2157
Changelog-Fixed: Fix broken GIF uploads
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
This commit fixes GIF uploads and improves GIF support:
- MediaPicker will now skip location data removal processing, as it is not needed on GIF images and causes them to be converted to JPEG images
- The uploader now sets more accurate MIME types on the upload request
Issue Repro
-----------
Device: iPhone 13 Mini
iOS: 17.4.1
Damus: `ada99418f6fcdb1354bc5c1c3f3cc3b4db994ce6`
Steps:
1. Download a GIF from GIPHY to the iOS photo gallery
2. Upload that and attach into a post in Damus
3. Check if GIF is animated.
Results: GIF is not animated. Issue is reproduced.
Testing
-------
PASS
Device: iPhone 13 Mini
iOS: 17.4.1
Damus: this commit
Steps:
1. Create a new post
2. Upload the same GIF as the repro and post
3. Make sure GIF is animated. PASS
4. Create a new post
5. Upload a new GIF image (that has never been uploaded by the user on the app) and post
6. Make sure the GIF is animated on the post. PASS
7. Make sure that JPEGs can still be successfully uploaded. PASS
8. Make sure that MP4s can be uploaded.
9. Make a new post that contains 1 JPEG, 1 MP4 file, and 2 GIF files. Make sure they are all uploaded correctly and all GIF files are animated. PASS
Closes: https://github.com/damus-io/damus/issues/2157
Changelog-Fixed: Fix broken GIF uploads
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
This commit fixes the "ghost notifications" experienced by Purple users
whose membership has expired (or about to expire).
It does that by using a similar mechanism as other notifications to keep
track of the last event date seen on the notifications tab in a
persistent way.
Testing
--------
iOS: 17.4
Device: iPhone 15 simulator
damus-api: bfe6c4240a0b3729724162896f0024a963586f7c
Damus: This commit
Setup:
1. Local Purple server
2. Damus running on local testing mode for Purple
3. An existing but expired Purple account (on the local server)
Steps:
1. Reopen app after pointing to the new server and setting things up.
2. Check that the bell icon shows there is a new notification. PASS
3. Check that purple expiration notifications are visible. PASS
4. Restart app.
5. Check the bell icon. This time there should be no new notifications. PASS
6. Using another account, engage with the primary test account to cause a new notification to appear.
7. After a second or two, the bell icon should indicate there is a new notification from the other user. PASS
8. Switch out and into the app. Check that the bell icon does not indicate any new notifications. PASS
9. Restart the app again. The bell icon should once again NOT indicate any new notifications. PASS
Changelog-Fixed: Fix ghost notifications caused by Purple impending expiration notifications
Closes: https://github.com/damus-io/damus/issues/2158
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
also create the contact list reset First Aid action
Automatically detecting whether or not to create a blank contact list
when we could not find any is very tricky. It could mean that no contact
list exists, but it could also mean that a temporary network or relay
outage occurred.
Since resetting the contact list when one already exists is a
destructive action, we should make no assumptions. Instead, we should
provide users the tool to fix it based on their own judgement.
For that reason, the first aid view was created. It detects if no
contact list was found, and in those cases, it gives them an option to
reset (with appropriate warning messages).
Testing 1: Contact list creation robustness
-----------------------------
Setup:
1. Network Link Conditioner installed and configured to this profile:
- DNS delay: 400 ms
- Downlink bandwidth: 100 kbps
- Uplink bandwidth: 50 kbps
- Packets dropped: 50% (On both uplink and downlink)
- Delay: 1000 ms (Both uplink and downlink)
Procedure:
1. Turn Network Link conditioner ON
2. Go through the account creation steps
3. At the moment the onboarding follow suggestions screen shows up, quit the app
3. Turn Network Link conditioner OFF
4. Start the app again
5. Verify the home screen. It should present notes from the Damus account (the default follow)
6. Follow someone and wait for 5 seconds
7. Restart app
8. Look at the home feed. Notes from user from step 6 should appear, and that user should appear as being followed by you.
- Repro details:
- Damus version: ada99418f6
- Device: iPhone 15 simulator
- iOS: 17.4
- Number of runs: 3 times
- Result: FAILS (issue is reproduced) 3 out of 3 times
- Test details:
- Damus version: This commit
- Device: iPhone 15 simulator
- iOS: 17.4
- Number of runs: 3 times
- Result: PASSES all criteria 3 out of 3 times
Testing 2: Contact list First Aid
------------------------------
Setup:
1. Reproduce the issue with the old version as outlined in "Testing 1" above
2. Upgrade to the version in this commit
Steps:
1. Go to Settings > First Aid
2. A button to reset the contact list (and some text for context) should appear. PASS
3. Click on the button. A warning message should appear. PASS
4. Click "cancel". The action should be cancelled and nothing should have changed. PASS
5. Click on the reset button again.
6. Click "Continue" on the warning prompt. The reset button will now show "Contact list has been reset" with a green checkmark. PASS
5. Go back to the home tab. Notes from the Damus account should immediately appear. PASS
6. Try to follow someone and restart the app. Follows should now stick persistently. PASS
7. Go to the First Aid screen again. The reset option should no longer be present. PASS
Changelog-Added: Add First Aid solution for users who do not have a contact list created for their account
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
Link: 20240422230912.65056-4-daniel@daquino.me
Signed-off-by: William Casarin <jb55@jb55.com>
... to a persistent setting, and try to load it from NostrDB on app start.
This commit causes the user's contact list event ID to be saved
persistently as a user-specific setting, and to be loaded immediately
after startup from the local NostrDB instance.
This helps improve reliability around contact lists, since we previously
relied on fetching that contact list from other relays.
Eventually we will not need the event ID to be stored at all, as we will
be able to query NostrDB, but for now having the latest event ID
persistently stored will allow us to get around this limitation in the
cleanest possible way (i.e. without having to store the event itself
into another mechanism, and migrating it later to NostrDB)
Other notes:
- It uses a mechanism similar to other user settings, so it is
pubkey-specific and should handle login/logout cases
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
Link: 20240422230912.65056-2-daniel@daquino.me
Signed-off-by: William Casarin <jb55@jb55.com>
This commit fixes the "ghost notifications" experienced by Purple users
whose membership has expired (or about to expire).
It does that by using a similar mechanism as other notifications to keep
track of the last event date seen on the notifications tab in a
persistent way.
Testing
--------
iOS: 17.4
Device: iPhone 15 simulator
damus-api: bfe6c4240a0b3729724162896f0024a963586f7c
Damus: This commit
Setup:
1. Local Purple server
2. Damus running on local testing mode for Purple
3. An existing but expired Purple account (on the local server)
Steps:
1. Reopen app after pointing to the new server and setting things up.
2. Check that the bell icon shows there is a new notification. PASS
3. Check that purple expiration notifications are visible. PASS
4. Restart app.
5. Check the bell icon. This time there should be no new notifications. PASS
6. Using another account, engage with the primary test account to cause a new notification to appear.
7. After a second or two, the bell icon should indicate there is a new notification from the other user. PASS
8. Switch out and into the app. Check that the bell icon does not indicate any new notifications. PASS
9. Restart the app again. The bell icon should once again NOT indicate any new notifications. PASS
Changelog-Fixed: Fix ghost notifications caused by Purple impending expiration notifications
Closes: https://github.com/damus-io/damus/issues/2158
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
also create the contact list reset First Aid action
Automatically detecting whether or not to create a blank contact list
when we could not find any is very tricky. It could mean that no contact
list exists, but it could also mean that a temporary network or relay
outage occurred.
Since resetting the contact list when one already exists is a
destructive action, we should make no assumptions. Instead, we should
provide users the tool to fix it based on their own judgement.
For that reason, the first aid view was created. It detects if no
contact list was found, and in those cases, it gives them an option to
reset (with appropriate warning messages).
Testing 1: Contact list creation robustness
-----------------------------
Setup:
1. Network Link Conditioner installed and configured to this profile:
- DNS delay: 400 ms
- Downlink bandwidth: 100 kbps
- Uplink bandwidth: 50 kbps
- Packets dropped: 50% (On both uplink and downlink)
- Delay: 1000 ms (Both uplink and downlink)
Procedure:
1. Turn Network Link conditioner ON
2. Go through the account creation steps
3. At the moment the onboarding follow suggestions screen shows up, quit the app
3. Turn Network Link conditioner OFF
4. Start the app again
5. Verify the home screen. It should present notes from the Damus account (the default follow)
6. Follow someone and wait for 5 seconds
7. Restart app
8. Look at the home feed. Notes from user from step 6 should appear, and that user should appear as being followed by you.
- Repro details:
- Damus version: ada99418f6
- Device: iPhone 15 simulator
- iOS: 17.4
- Number of runs: 3 times
- Result: FAILS (issue is reproduced) 3 out of 3 times
- Test details:
- Damus version: This commit
- Device: iPhone 15 simulator
- iOS: 17.4
- Number of runs: 3 times
- Result: PASSES all criteria 3 out of 3 times
Testing 2: Contact list First Aid
------------------------------
Setup:
1. Reproduce the issue with the old version as outlined in "Testing 1" above
2. Upgrade to the version in this commit
Steps:
1. Go to Settings > First Aid
2. A button to reset the contact list (and some text for context) should appear. PASS
3. Click on the button. A warning message should appear. PASS
4. Click "cancel". The action should be cancelled and nothing should have changed. PASS
5. Click on the reset button again.
6. Click "Continue" on the warning prompt. The reset button will now show "Contact list has been reset" with a green checkmark. PASS
5. Go back to the home tab. Notes from the Damus account should immediately appear. PASS
6. Try to follow someone and restart the app. Follows should now stick persistently. PASS
7. Go to the First Aid screen again. The reset option should no longer be present. PASS
Changelog-Added: Add First Aid solution for users who do not have a contact list created for their account
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
Link: 20240422230912.65056-4-daniel@daquino.me
Signed-off-by: William Casarin <jb55@jb55.com>
... to a persistent setting, and try to load it from NostrDB on app start.
This commit causes the user's contact list event ID to be saved
persistently as a user-specific setting, and to be loaded immediately
after startup from the local NostrDB instance.
This helps improve reliability around contact lists, since we previously
relied on fetching that contact list from other relays.
Eventually we will not need the event ID to be stored at all, as we will
be able to query NostrDB, but for now having the latest event ID
persistently stored will allow us to get around this limitation in the
cleanest possible way (i.e. without having to store the event itself
into another mechanism, and migrating it later to NostrDB)
Other notes:
- It uses a mechanism similar to other user settings, so it is
pubkey-specific and should handle login/logout cases
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
Link: 20240422230912.65056-2-daniel@daquino.me
Signed-off-by: William Casarin <jb55@jb55.com>
seems like most clients don't do this and apparently simplfies some
zapper implementations. It's not a huge deal for us since people can
fake bolt11s anyways.
Suggested-by: bumi, calle
Link: 20240418230321.1907519-1-jb55@jb55.com
Signed-off-by: William Casarin <jb55@jb55.com>
This commit brings significant improvements to the video cache feature.
Previously, the cache would merely download the video when requested, in
parallel with AVPlayer which also triggers a video download.
The video cache has been updated to tap into the AVPlayer loading
process, removing the download duplication.
Here is how that works:
1. The player requests an AVAsset from the cache.
2. The cache will return a cached asset if possible, or a special AVURLAsset with a custom `AVAssetResourceLoaderDelegate`.
3. The video player will start sending loading requests to this loader delegate.
4. Upon receiving the first request, the loader delegate begins to download the video data on the background.
5. Upon receiving these requests, the loader delegate will also record the requests, so that it can serve them once possible
6. The loader delegate keeps track of all video data chunks as it receives them from the download task, through the `URLSessionDataDelegate` and `URLSessionTaskDelegate` protocols
7. As it receives data, it checks all pending loading requests from the AVPlayer, and fulfills them as soon as possible
8. If the download fails (e.g. timeout errors, loss of connection), it attempts to restart the download.
9. If the download succeeds, it saves the video to the cache on disk.
Closes: https://github.com/damus-io/damus/issues/1717
Changelog-Added: Add video cache to save network bandwidth
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Link: 20240411004129.84436-4-daniel@daquino.me
Signed-off-by: William Casarin <jb55@jb55.com>
This commit implements a simple but functional video cache.
It works by providing a method called `maybe_cached_url`, where a video
URL can be passed in, and this method will either return the URL of a
cached version of this video if available, or the original URL if not. It also
downloads new video URLs on the background into the cache folder for use
next time.
Functional testing
-------------------
PASS
Device: iPhone 15 simulator
iOS: 17.4
Damus: Approximately this commit
Setup:
- Debug connection
- Expiry time locally changed to 5 minutes
Steps:
1. Basic functionality
1. Go to a profile with lots of videos
2. Scroll down
3. Filter logs to only logs that start with "Loading video with URL"
4. Check that most videos are being loaded from external URLs. PASS
5. Now restart the app and go to that same profile
6. Scroll down and watch logs. Videos should now be loaded with an internal file URL. PASS
2. Automatic cache refresh after expiry
1. Go to the video-heavy profile, make note of the external URL.
2. Go to a different screen and then come back to that video. Make sure the file was loaded from cache. PASS
3. Now go to a different screen and wait 5 minutes.
4. Come back to the same video. It should be loaded from the external URL. PASS
3. "Clear cache" button functionality
1. Go to the video-heavy profile, make note of the external URL.
2. Go to a different screen and then come back to that video. Make sure the file was loaded from cache. PASS
3. Now quit the app (to ensure file is not in use when trying to delete it)
4. Clear cache in settings
5. Go back to the same video. It should now be loaded from the external URL. PASS
Performance testing
-----------------------
Device: iPhone 13 mini
iOS: 17.3.1
Damus: This commit
Baseline: 87de88861adb3b41d73998452e7c876ab5ee06bf
Setup:
- Debug connection
- Expiry time locally changed to 5 minutes
- Running on Profile mode, with XCode Instruments
Steps:
1. Start recording network activity with XCode Instruments
2. Go to a video-heavy profile (e.g. Julian Figueroa)
3. Scroll down to a specific video (Make sure to scroll through at least 5 videos)
4. Stop recording and measure the "Bytes In" from "Network connections"
5. Repeat this for all test configurations
Results:
- Baseline (No caching support): 26.74 MiB
- This commit (First run, cleared cache): 40.52 MiB
- This commit (Second run, cache filled with videos): 8.13 MiB
Automated test coverage
------------------------
PASS
Device: iPhone 15 simulator
iOS: 17.4
Damus: This commit
Coverage:
- Ran new automated tests multiple times. PASS 3/3 times
- Ran all other automated tests. PASS
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Link: 20240411004129.84436-3-daniel@daquino.me
Signed-off-by: William Casarin <jb55@jb55.com>
This patch redesigns the relay detail view. The first step needed to
further improve how relays are viewed. In addition, Fees are added to
the relay metadata to present to the user the admission, subscription,
or publication fees a relay may have.
There are various changes made, but mainly several relay details are
moved outside of the main RelayDetail view for easier tracking and
updates.
With this design we will be able to add ratings and relay previews, as
this patch is large enough I will submit that improvement in the future.
iPhone 15 Pro Max (17.3.1) Dark Mode:
https://i.nostr.build/VwVvq.pnghttps://i.nostr.build/KGO0v.png
iPhone SE (3rd generation) (16.4) Light Mode:
https://i.nostr.build/M5V26.pnghttps://i.nostr.build/gZKw3.png
Changelog-Added: Relay fees metadata
Changelog-Changed: Relay detail design
Signed-off-by: ericholguin <ericholguin@apache.org>
Signed-off-by: William Casarin <jb55@jb55.com>
We already have the full relay URL under the name, we don't need to
repeat it and this is a bit cleaner.
Before:
wss://damus.io
wss://damus.io
After:
damus.io
wss://damus.io
Signed-off-by: William Casarin <jb55@jb55.com>
This commit tries to replace all usage of `String` to represent relay
URLs and use `RelayURL` which automatically converts strings to a
canonical relay URL format that is more reliable and avoids issues related to
trailing slashes.
Test 1: Main issue fix
-----------------------
PASS
Device: iPhone 15 Simulator
iOS: 17.4
Damus: This commit
Steps:
1. Delete all connected relays
2. Add `wss://relay.damus.io/` (with the trailing slash) to the relay list
3. Try to post. Post should succeed. PASS
4. Try removing this newly added relay. Relay should be removed successfully. PASS
Test 2: Persistent relay list after upgrade
--------------------------------------------
PASS
Device: iPhone 15 Simulator
iOS: 17.4
Damus: 1.8 (1) `247f313b` + This commit
Steps:
1. Downgrade to old version
2. Add some relays to the list, some without a trailing slash, some with
3. Upgrade to this commit
4. All relays added in step 2 should still be there, and ones with a trailing slash should have been corrected to remove the trailing slash
Test 3: Miscellaneous regression tests
--------------------------------------
Device: iPhone 15 Simulator
iOS: 17.4
Damus: This commit
Coverage:
1. Posting works
2. Search works
3. Relay connection status works
4. Adding relays work
5. Removing relays work
6. Adding relay with trailing slashes works (it fixes itself to remove the trailing slash)
7. Adding relays with different paths works (e.g. wss://yabu.me/v1 and wss://yabu.me/v2)
8. Adding duplicate relay (but with trailing slash) gets rejected as expected
9. Relay details page works. All items on that view loads correctly
10. Relay logs work
11. Getting follower counts and seeing follow lists on profiles still work
12. Relay list changes persist after app restart
13. Notifications view still work
14. Copying the user's pubkey and profile link works
15. Share note + copy link button still works
16. Connecting NWC wallet works
17. One-tap zaps work
18. Onboarding works
19. Unit tests all passing
Closes: https://github.com/damus-io/damus/issues/2072
Changelog-Fixed: Fix bug that would cause connection issues with relays defined with a trailing slash URL, and an inability to delete them.
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Signed-off-by: William Casarin <jb55@jb55.com>
Changelog-Added: Added callbackuri for a better ux when connecting mutiny wallet nwc
Signed-off-by: ericholguin <ericholguin@apache.org>
Signed-off-by: William Casarin <jb55@jb55.com>
Date: Fri, 22 Mar 2024 10:02:00 +0100
From: William Casarin <jb55@jb55.com>
To: dev@damus.io
Subject: Moving away from email code submissions
Hey there,
Since there are more people joining these days and the idea of training
everyone on how to do email code review is effectively impossible in
2024, I've decided to move away from them. I have scripts that can
convert github pull requests to do offline review on my end, so I no
longer need people to directly email them to me.
You of course can, but if you prefer to use github PRs then that is now
perfectly fine. I still may not use GitHub's code review interface, but
that is just me.
I want to encourage more code review from people other than me, if noone
is set up to do that via email then I would rather not encourage it.
Cheers,
Will
Signed-off-by: William Casarin <jb55@jb55.com>
The DamusAVPlayerView (along with other classes) play or pause based on
their Y position relative to the user's viewport. This is ideal for a
vertical feed of notes.
However, this does not work well on a horizontal carousel, such as when
viewing videos on the full-screen carousel and swiping left/right.
This commit adds a new tracking method based on onAppear/onDisappear
triggers from a lazy stack (which only loads when it is visible), and
applied it to videos shown on a full screen carousel, so that videos
pause when we swipe away from the video.
Incidentally, this also fixes an issue I was seeing where a full screen
video would disappear as soon as I rotated the phone to landscape mode.
Testing
--------
Device: iPhone 13 Mini
iOS: 17.3.1
Damus: This version
Coverage:
1. Scroll down a feed full of videos and make sure videos still autoplay when passing through them. PASS
2. Check videos on the feed are muted by default. PASS
3. Check mute button on the video still works. PASS
4. Check clicking on the video brings it to a full-screen carousel view. PASS
5. Check that videos play unmuted by default on full-screen carousel view. PASS
6. Check that all playback controls work on the full-screen carousel view. PASS
7. Check that clicking outside the video shows/hides the carousel overlays. PASS
8. Check that a summary of the note shows up. PASS
9. Check that clicking on that note takes the user to the thread view. PASS
10. Check that changing phone orientation between portrait and landscape on both full-screen carousel AND full-screen video modes will work as expected. PASS
11. Check close button on full-screen carousel works. PASS
12. Check that swiping the video away exits full-screen carousel. PASS
13. Check that full-screen carousel works with images. PASS
14. Check that a carousel with multiple images/videos can be swiped left and right. PASS
15. Check that swiping away from a video on a full-screen carousel will pause it. PASS
16. Check that clicking on an unmuted video on the feed won't cause double-audio issues. PASS
17. Check that full-screen carousel view looks good on both dark and light modes. PASS
Closes: https://github.com/damus-io/damus/issues/1530
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Link: 20240318222048.14226-6-daniel@daquino.me
Signed-off-by: William Casarin <jb55@jb55.com>
The full screen carousel looks quite empty. When viewing videos, it
looks like the video is being played full screen, when it is really not.
Alas, SwiftUI/UIKit does not provide an API for programmatically
bringing a video player full screen. The closest we can do is show the
system native playback controls.
This can cause confusion to users, and is not the best UX. To get around
these limitations and improve UX, event information and content is added to the full
screen carousel overlay, so that:
- Users can see a piece of the post while they are browsing images and videos
- Users can more clearly tell when the video is being displayed on the full screen carousel or on full screen
- Users have a way to directly go to the thread view within the full screen carousel
Changelog-Added: Add event content preview to the full screen carousel
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Link: 20240318222048.14226-4-daniel@daquino.me
Signed-off-by: William Casarin <jb55@jb55.com>
This commit includes several UX changes to give users better control
over video playback. It also, by design, work arounds a SwiftUI quirk*
Here are the changes to the UX:
1. Videos on the feed only have a mute/unmute button
2. When the user clicks on the video, they are taken to a full screen carousel view (similar to when you click on an image)
3. The full-screen carousel view shows all video playback controls (through a specific SwiftUI hack)
4. If the carousel has multiple videos/images, the user can swipe between them normally as expected
Other UI changes that were made:
- The full screen carousel now uses dark mode (black background, white close button)
* The SwiftUI quirk is that when video views are placed within a TabView with ".page" tab view style, the tabview consumes most of the user gestures, making the video playback controls unusable.
Changelog-Changed: Improve UX around video playback
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Link: 20240318222048.14226-3-daniel@daquino.me
Signed-off-by: William Casarin <jb55@jb55.com>
This adds quote reposts as an additional detail view on threads. It will
list quoted reposts that have the `q` tag. Not all clients have updated
to this yet (like primal), but hopefully they will soon.
Changelog-Added: Show list of quoted reposts in threads
Signed-off-by: William Casarin <jb55@jb55.com>
We also switch to using an eventholder because that is a bit nicer
when it comes to rendering quotes in timelines.
Signed-off-by: William Casarin <jb55@jb55.com>
Simplify with new EventsModel constructors. This is slightly less
typesafe but its not a big deal, I hate inheritence more.
Signed-off-by: William Casarin <jb55@jb55.com>
This adds the initial support code for counting and handling
quote reposts.
Eventually we are going to replace all of the event counts by stats
within nostrdb, but we do this in the meantime now.
Signed-off-by: William Casarin <jb55@jb55.com>
This adds the recommended parameter to the relay view used in Wallet view.
Signed-off-by: ericholguin <ericholguin@apache.org>
Signed-off-by: William Casarin <jb55@jb55.com>
This patch redesigns the wallet view to more closely match Rob's design.
In addition this patch allows users to connect to Mutiny Wallet by clicking a button.
iPhone SE (3rd generation) Dark Mode:
https://v.nostr.build/K9lk.mp4
iPhone 15 Pro Max Light Mode:
https://v.nostr.build/9mKA.mp4
Connected Alby Wallet:
https://i.nostr.build/kyd5.png
Changelog-Added: Connect to Mutiny Wallet Button
Changelog-Changed: Moved paste nwc button to main wallet view
Changelog-Changed: Errors with an NWC will show as an alert
Changelog-Fixed: Issue where NWC Scanner view would not dismiss after a failed scan/paste
Signed-off-by: ericholguin <ericholguin@apache.org>
Reviewed-by: William Casarin <jb55@jb55.com>
Link: 20240310223713.4541-1-ericholguin@apache.org
Signed-off-by: William Casarin <jb55@jb55.com>
This patch removes the Recommended Relay View and the old representation of recommended relays.
Adds a tab view style to the Relay Config View allowing the user to switch between their connected relays
and recommended relays. They can add and remove from the recommended view as well. For users logged in with
a pubkey the add button will no longer be displayed.
Testing
——
iPhone 15 Pro Max (17.0) Light Mode:
https://v.nostr.build/QGMZ.mp4
iPhone SE (3rd generation) (16.4) Dark Mode:
https://v.nostr.build/Wlw3.mp4
——
Changelog-Changed: Relay config view user interface
Signed-off-by: ericholguin <ericholguin@apache.org>
Link: 20240307152808.47929-1-ericholguin@apache.org
Signed-off-by: William Casarin <jb55@jb55.com>
It was observed that sending the receipt to the server right after
performing the StoreKit purchase caused issues due to the receipt not
being completely ready when it got sent, causing rejections by the
server.
This commit, in conjuction with backend changes, implements purchase
verification through transaction IDs directly.
Testing
--------
PASS
Device: iPhone 13 Mini (physical device)
iOS: 17.3.1
Damus: This commit
damus-api: `a878da5598a9344a4d351f9a9da16712ce0615b7`
Setup:
- Local server Setup
- Local testing mode on Damus developer settings
- Clean Sandbox account (Create new sandbox account if clearing purchase history does not work)
- Fresh DB
- App is closed before starting.
- Run app on release target
- MOCK_VERIFY=false on server, with all IAP environment correctly setup
Steps:
1. Make Purple IAP purchase. Make sure that:
- Server logs indicate `/apple-iap/transaction-id` is being hit and returning HTTP 200. PASS
- No errors appear on the iOS side. After purchase the welcome sheet should appear, and then the account info. PASS
Part of: https://github.com/damus-io/damus/issues/2036
Changelog-Fixed: Fix in-app purchase issue that would trigger an error on purchase before confirming the account information.
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Signed-off-by: William Casarin <jb55@jb55.com>
Reverting due to CI error:
```
damus file:///Volumes/workspace/repository/damus/cs.lproj/Localizable.stringsdict
validation failed: Couldn't parse property list because the input data
was in an invalid format (1)
```
This reverts commit fa738c4303, reversing
changes made to 9511ba767a.
034f31797e Translate Localizable.strings in de
adb6f66a4f Translate Localizable.strings in zh_TW
a5f438b9c7 Translate Localizable.strings in zh_HK
d7f04d9ab9 Translate Localizable.strings in zh_HK
0b2ea46ef4 Translate Localizable.strings in zh_HK
331ed96d57 Translate Localizable.strings in zh_CN
701a747ed6 Translate Localizable.strings in cs
118c2bf2b2 Translate Localizable.stringsdict in cs
7a4f82c97b Translate Localizable.strings in de
d1e3a06cc6 Translate Localizable.strings in de
b9d960b54b Translate InfoPlist.strings in cs
* branch `translations` of https://github.com/damus-io/damus:
Translate Localizable.strings in de
Translate Localizable.strings in zh_TW
Translate Localizable.strings in zh_HK
Translate Localizable.strings in zh_HK
Translate Localizable.strings in zh_HK
Translate Localizable.strings in zh_CN
Translate Localizable.strings in cs
Translate Localizable.stringsdict in cs
Translate Localizable.strings in de
Translate Localizable.strings in de
Translate InfoPlist.strings in cs
Nothing has changed, but we need to submit a new minor version with
the subscription products since we missed those in the 1.7 appstore
release.
Signed-off-by: William Casarin <jb55@jb55.com>
This should not be visible to end-users on normal circumstances, but we
should regardless show an error message if something goes wrong with the
IAP receipt verification, to prompt them to contact support.
Testing
-------
PASS
Device: iPhone simulator
iOS: 17.2
Damus: This commit
damus-api: d3801376fa204433661be6de8b7974f12b0ad25f
Setup:
- Local Testing server
- Xcode StoreKit environment
Steps:
1. Set MOCK_VERIFY to false on the server (that means receipt verification will fail on Xcode environment)
2. Try to make IAP purchase. Error should appear on UI
3. Set MOCK_VERIFY to true on the server and restart StoreKit environment (Receipt validation will always work)
5. Try to make IAP purchase. Onboarding flow should go as normal with no error messages. PASS
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit changes when the Damus Purple onboarding gets triggered. Now
it only shows the onboarding if it is the first time they are purchasing
Damus Purple for a Nostr account. If it is not the first they see the
onboarding, they are directed to a sheet that displays their new account
info (e.g. a renewal)
However, if the website links to `damus:purple:welcome` links, the app
will still show the onboarding. This will be addressed on the
website-side by taking them to `damus:purple:landing` instead when it is
a renewal.
Testing
---------
PASS
Device: iPhone 13 mini (Physical device)
iOS: 17.3.1
Damus: This commit
damus-api: d3801376fa204433661be6de8b7974f12b0ad25f
damus-website: 6bb425e324c318ca474417cbd2b2f8bb74f9505f
Setup:
- iOS configured to use a local test environment
- Local damus-api server and local damus-website server setup and properly configured
- Fresh db (i.e. Delete mdb files before starting)
Coverage:
1. LN flow with switching to the app instead of clicking "continue". PASS
a. Ensure that first purchase will result in onboarding being shown. PASS
b. Ensure that second purchase will result in onboarding NOT being shown (User should be taken to the account info screen). PASS
c. Restart app completely. Ensure third purchase will result in onboarding NOT being shown (only account info screen). PASS
2. LN flow with clicking continue (Since website changes are not ready, we will simulate them by manually generally appropriate "continue" URL QR codes)
a. Note: Clear DB again before starting this portion, and completely restart app.
b. Ensure that first purchase will result in onboarding being shown. PASS
c. Ensure that second purchase (with continue URL manually hard-coded to `damus:purple:landing`) results in account info being shown with updated info. PASS
d. Restart app completely and repeat test 2(c). PASS
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit adds Damus Purple expiry notification support.
How it works: Whenever the app initiates or enters the foreground, it
checks the user's account expiry, and calculates what notifications to
display (It is functional, not imperative, to better match how
the notifications view works)
The notification handlers work the same as every other notification
handler for Nostr events. However, local iOS notifications were not
implemented to maintain these reminders more discreet.
Current limitations:
- Notifications cannot be dismissed
- Notifications are dismissed only when Damus Purple is extended
- After making a purchase, notifications are not dismissed right away
- Bell icon with purple badge shows up on every app restart if user's account is expired
Testing
-------
Device: iPhone 13 Mini
iOS: 17.3.1
Damus: This commit
damus-api: d3801376fa204433661be6de8b7974f12b0ad25f
Setup:
- Local servers Setup
- Debug endpoints enabled for changing expiry date on the fly
Coverage:
1. Expired account
1. Starting the app on home screen shows bell icon with purple badge. PASS
2. 4 notifications appear on notifications view (7,3,1,0 days to expiry). PASS
3. Notifications appear in correct chronological order. PASS
4. Notifications look consistent in appearance. PASS
5. Expiry notifications' text size follows text size settings. PASS
6. Clicking on notification CTA takes user to account info page. PASS
2. Non-expired account (set expiry, restart app)
1. No expiry notifications, no bell icon. PASS
3. Expiry in 6 days (set expiry, restart app)
1. Starting the app on home screen shows bell icon with purple badge. PASS
2. Starting the app on the notification screen renders notifications the same way. PASS
3. Only one notification (7 days remaining) appears. PASS
4. Expiry in 2 days. PASS
5. General
1. Clicking bell icon clears away "new notifications" badge. PASS
2. Performance of notifications view does not seem affected. PASS
3. Performance of app on startup does not seem affected. PASS
6. IAP
1. Active IAP + expiry date in 2 days does not trigger reminder notification (Because it is auto-renewed). PASS
Closes: https://github.com/damus-io/damus/issues/1973
Changelog-Added: Notification reminders for Damus Purple impending expiration
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This merge adds a bunch of new features from charlie's work on the new
mutelist changes:
- Muted words
- Mute performance optimizations
- New mute list UI
I needed to make a few changes to fix the tests in this merge. Otherwise
it seems to work ok!
Thank to Charlie for getting all of this working after many rounds of
review!
* branch `mute` of https://github.com/damus-io/damus:
mute: fix bug with duplicate Indefinite items in MuteDurationMenu
mute: fix mute hashtag from search view if no existing mutelist
mute: integrate new MutelistManager
mute: adding MutelistManager.swift
mute: add maybe_get_content function to NdbNote
mute: fix bug where mutes can't be added without existing mutelist
mute: fix issue with not being able to change mute duration
mute: don't mutate string when adding hashtag
mute: implement fast MuteItem decoder
tags: add u64 decoding function
mute: migrating muted_threads to new mute list
mute: adding ability to mute hashtag from SearchView
mute: updating UI to support new mute list
mute: adding filtering support for MuteItem events
mute: receiving New Mute List Type
mute: migrate Lists.swift to use new MuteItem
mute: add new UI views for new mute list
mute: adding new structs/enums for new mute list
Changelog-Added: Add ability to mute words, add new mutelist interface (Charlie)
This patch is slightly large (I think still within the guidelines tho) ,
but also pretty straightforward. I thought for a while about how I could
split this up in a straightforward way, and I couldn’t come up with
anything without breaking intermediate builds.
- Deleted a lot of old/unnecessary code (ie. the Collection extension
for MuteItem, since we’re now using the MutelistManager sets)
- Changed damus_state.contacts to damus_state.mutelist_manager for all
mute list manager work
- Updated MutelistView to take advantage of new code (this is probably
the largest change in this patch)
Lighting-Address: fishcharlie@strike.me
Signed-off-by: Charlie Fish <contact@charlie.fish>
Reviewed-by: William Casarin <jb55@jb55.com>
Link: 20240210163650.42884-4-contact@charlie.fish
Signed-off-by: William Casarin <jb55@jb55.com>
This patch adds MutelistManager which contains separate sets for each
type of muted item.
Whenever we receive a new event we parse it into those sets.
When checking to see if an event is muted, we simply check in each of
those sets if it contains the given mute. For words/phrases we have to
loop through each item in the set to see if the event contains the given
word.
In future patches I will be implementing and integrating this new
MutelistManager.
Lighting-Address: fishcharlie@strike.me
Signed-off-by: Charlie Fish <contact@charlie.fish>
Reviewed-by: William Casarin <jb55@jb55.com>
Link: 20240210163650.42884-3-contact@charlie.fish
Signed-off-by: William Casarin <jb55@jb55.com>
This patch adds a maybe_get_content method to NdbNote which returns an
optional string instead of “*failed to decrypt content*” on DM
decryption failure.
This method will be used by the MutelistManager in future patches.
Lighting-Address: fishcharlie@strike.me
Signed-off-by: Charlie Fish <contact@charlie.fish>
Reviewed-by: William Casarin <jb55@jb55.com>
Link: 20240210163650.42884-2-contact@charlie.fish
Signed-off-by: William Casarin <jb55@jb55.com>
Automatically show welcome sheet for people who completed a Lightning
checkout but did not click on the "Continue" button
Some people get confused in the last step of the lightning checkout and
they do not click on the "Continue in app", which causes the welcome
screen to not show up and the translation setting to not be setup.
This ticket addresses this issue to ensure they get the welcome screen
in such cases.
This is how it works:
- When they go through the mandatory checkout verification step, the
verify screen registers that there is a checkout in progress (and
which checkout is in progress) on the DamusPurple struct
- Every time the app enters the foreground, it checks for that flag:
- If there are no checkouts in progress, it does nothing
- If there is one or multiple checkouts in progress, it checks the
checkout status for those. If any checkout is freshly completed and
successful, and the account is now active, it shows the welcome
screen and onboarding
- Once the welcome screen is shown, those checkouts are marked
internally as handled (so that we only show it once)
===========
Testing
===========
PASS
Damus: This commit
Device: iPhone 13 Mini (real physical device)
iOS: 17.3.1
damus-api: 044150fedddc5ba4135a80579e41e9c1c5743fc0
damus-website: af8089128159e25df31141be624b4090c66d6ddf
Setup:
- Local test Setup
- Clean db before starting
PART 1: LN flow without clicking on the link
---------------------------------------------
Steps:
1. Go through the normal LN flow, EXCEPT at the last step. On the last
step, instead of clicking "continue in the app", just switch to the
app.
2. Ensure the welcome screen and onboarding shows up, and the purple
screen updates to show account info. PASS
3. Switch out and into the app again. Welcome screen should NOT show up
again. PASS
4. Close the app completely and open the app again. Purple welcome
screen should NOT show up again. PASS
PART 2: Normal LN flow
---------------------------------------------
Steps:
1. Reset the entire test setup
2. Go through the normal LN flow (this time click on "continue in app").
The welcome screen should show up without issues or glitches. PASS
PART 3: Crazy flow with multiple incomplete checkouts
---------------------------------------------
(This is to simulate a confused user who accidentally opens multiple new
checkouts, but in the end only completes one of them)
Steps:
1. Reset the entire test setup
2. Open 5 LN checkouts and verify npub with all of them.
3. Only pay one of those checkouts (to make it more confusing, don't pay
the first or last one, but a random one in between)
4. Go to the app directly (Do not use the link, just go directly to the app)
Related: https://github.com/damus-io/damus/issues/1892
Changelog-Fixed: Fix welcome screen not showing if the user enters the app directly after a successful checkout without going through the link
Closes: https://github.com/damus-io/damus/issues/2021
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Link: 20240223212945.37384-2-daniel@daquino.me
Signed-off-by: William Casarin <jb55@jb55.com>
Apple In-app purchases do not respond immediately. This commit adds a
loading spinner element, to improve the UX and avoid the appearance of a
broken/unresponsive element.
Testing
--------
Device: iPhone 15 simulator
iOS: 17.2
Damus: This commit
Setup:
- Using the sandbox environment
- No tx to start with
- IAP experimental support enabled on developer settings in Damus
Steps:
1. Click "purchase" in any option on the damus purple screen
2. It should show a loading spinner while the purchase action is loading. PASS
3. On the confirmation screen, cancel the purchase.
4. Purchase buttons should show again. PASS
Closes: https://github.com/damus-io/damus/issues/2020
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Link: 20240223212945.37384-1-daniel@daquino.me
Signed-off-by: William Casarin <jb55@jb55.com>
The responsibility of MediaPicker is to 'pick' all sorts of media, not
just images.
Lightning-address: kernelkind@getalby.com
Signed-off-by: kernelkind <kernelkind@gmail.com>
Signed-off-by: William Casarin <jb55@jb55.com>
Images selected from the photo library will automatically have their
gps data stripped regardless of whether the user toggles the 'Location'
button in the system level photo library view.
Changelog-Changed: Always strip GPS data from images
Closes: https://github.com/damus-io/damus/issues/1990
Lightning-address: kernelkind@getalby.com
Signed-off-by: kernelkind <kernelkind@gmail.com>
Signed-off-by: William Casarin <jb55@jb55.com>
Upgrade the ImagePicker to use PHPickerViewController instead of
UIImagePickerController for the photo library since the
PHPickerViewController allows for more options for how the user
shares their media, such as whether location data should be
included.
Create a CameraController since PHPickerViewController is only used for
the photo library. After capturing media with the camera, it will be
saved to the user's photo library and the photo library view will
appear for the user to select the media they captured. The user can then
toggle whether they would like apple to strip their media of location
data before handing it off to Damus.
Lightning-address: kernelkind@getalby.com
Signed-off-by: kernelkind <kernelkind@gmail.com>
Signed-off-by: William Casarin <jb55@jb55.com>
This patch adds a new ProxyView which is added to the Event Shell
whenever an event has the proxy tag. It includes images of the protocol
logos that are listed in the NIP docs.
Reviewed-by: William Casarin <jb55@jb55>.com
Link: 20240205032400.7069-1-ericholguin@apache.org
Signed-off-by: William Casarin <jb55@jb55.com>
This commit adapts the functionality around login/logout with relation
to Damus Purple In-App purchases (IAP). Due to (apparent) limitations on
Renewable subscription In-app purchases (It seems that there can only be
one active IAP subscription per device or Apple ID), these changes add
support for only one IAP subscription at a time.
To prevent confusion, a customer who logs out and logs into a separate
account will see a message indicating the limitation. Any other Nostr
account won't be able to manage IAP on a device that contains an IAP
registered to a different user.
To make this feature possible, the following changes were made to the
code:
1. IAP purchases are now associated with an account UUID. This account
UUID is generated by the server. Each npub gets one and only one UUID
for this purpose.
2. This UUID is used to determine which npub owns the IAP on the device.
It is used as the source of truth when determining whether a
particular Purple account is manageable on a device or not
3. `DamusPurple` was changed to adhere to a new IAP flow API design
changes. Previously, the client would create an (inactive) account,
and then send the IAP receipt to the server for activation. Now, the
client fetches the npub's UUID from the server, associates it with an
IAP during purchase, and sends the IAP receipt to the server. The
server will then bump the expiry (if it's a renewal) or create a new
active account (if it's the first time).
4. Several changes were made to the StoreKit handling code to improve
handling:
a. The `DamusPurple.StoreKitManager` class now records all purchased
product updates, and sends them to the delegate each time the
delegate is updated. This helps ensure we do not miss purchased
product updates regardless of when and if `DamusPurpleView` is ever
instantiated.
b. `DamusPurple.StoreKitManager` is now used by `DamusPurple` in a
singleton pattern via `DamusPurple.StoreKitManager.standard`. This
helps maintain the local purchase history consistent (and avoid
losing such data) after `DamusState` or its `DamusPurple` are
destroyed and re-initialized.
c. Added logs (using the logger) to help us debug/troubleshoot
problems in the future
5. Changed the views around DamusPurple, to only show IAP
purchase/management options if applicable to a particular account. It
also shows instructive messages in other scenarios.
Testing
-------
damus: This commit
damus-api: d3956ee004a358a39c8570fdbd481d2f5f6f94ab
Device: iPhone 15 simulator
iOS: 17.2
Setup:
- Xcode (local) StoreKit environment
- All StoreKit transactions deleted before starting
- Running `damus` app target (which contains test StoreKit products)
- Local damus-api server running with `npm run dev` and
`MOCK_VERIFY=true` to disable real receipt verification
- Damus setup with experimental IAP support enabled, and Purple
environment set to "Test (local)" (localhost)
- Two `nsecs` readily available for account switching
- Clean DB (Delete db files before starting)
Steps:
1. Open the app and sign in to the first account
2. Go to Damus Purple screen. Marketing screen with buttons to purchase
products should be visible. PASS
3. Buy a product and monitor server logs as well as the screen.
a. IAP confirmation dialog should appear. PASS
b. After confirmation, server logs should show a receipt was sent
IMMEDIATELY and the response should be an HTTP 200. PASS
c. The welcome and onboarding screens should appear as normal. PASS
d. Once the onboarding sheet goes away, the Purple screen should now
show the account information. PASS
e. The account information should be correct. PASS
f. Under the account information, there should be a "manage" button. PASS
4. Click on "manage" and verify that the iOS subscription management
screen appears. PASS
5. Now log out and sign in to the second account
6. Go to Damus Purple screen.
a. Marketing screen should be visible. PASS
b. There should be no purchase buttons. instead, there should be a
message indicating that there can only be one active subscription
at a time, and that the app is unable to manage subscription for
this second acocunt. PASS
7. Log out and sign in to the first account. Go to the Purple screen.
a. Account info with the manage button should be visible like before. PASS
8. Through Xcode, delete transactions, and restart the app. This will
simulate the case where the user bought the subscription externally.
9. Go to the Purple screen.
a. Account info should be visible and correct. PASS
b. Below the account info, there should be a small note telling the
user to visit the website to manage their billing. PASS
Closes: https://github.com/damus-io/damus/issues/1815
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 moves most of StoreKit-specific logic that was embedded into
DamusPurpleView and places it into a new PurpleStoreKitManager struct,
to make code more reusable and readable by separating view concerns from
StoreKit-specific concerns.
Most of the code here should be in feature parity with the previous
behavior. However, a few logical improvements were made alongside this
refactoring:
- Improved StoreKit transaction update monitoring logic: Previously the
view would stop listening for purchase updates after the first update.
However, I made the program continuously listen for purchase updates,
as recommended by Apple's documentation
(https://developer.apple.com/documentation/storekit/transaction/3851206-updates)
- Improved/simplified logic around getting extra information from the
products: Information and the handling of product information was
spread in a few separate places. I incorporated those bits of
information into central and uniform interfaces on DamusPurpleType, to
simplify logic and future changes.
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 refactoring commit splits several view blocks from DamusPurpleView
into separate files.
- New view structs were defined within the DamusPurpleView namespace, to
avoid polluting the global namespace
- No logical changes were made. The functionality should have stayed
equivalent
- Changes were made conservatively, and as semantically as possible, to
make the code easier to work with.
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Signed-off-by: William Casarin <jb55@jb55.com>
This refactoring commit moves primitive, low complexity, helper views
from DamusPurpleView into a separate file, to reduce complexity on
DamusPurpleView.swift.
Although functions were changed into View structs, no logical changes
were made. (New version is functionally equivalent)
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 a purely non-functional refactor of DamusPurpleView consisting
only of code mark section comments, and re-ordering for better
organization and to facilitate further refactoring.
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Signed-off-by: William Casarin <jb55@jb55.com>
This commit adds a developer setting that allows the use of a custom
host for testing. This was added to allow testing on real devices
without the need for pushing changes into staging.
========
Testing
========
Test 1: Production not affected
-------------------------------
PASS
Device: iPhone 13 Mini
iOS: 17.3
Damus: This version
Steps:
1. Run app on a device logged into a real Damus Purple account
2. Scroll down the home feed. Make sure that other Purple members still show up with a star next to their profile. PASS
3. Go to the Damus Purple screen. Ensure that account info shows up and is correct. PASS
4. Ensure auto-translations appear. PASS
Test 2: Check custom test URL
-----------------------------
PASS
(Continued from test 1)
1. Run local damus-api and damus-website on the same computer
2. Change developer purple env setting to local test
3. Set the host url to the local IP address of the test server
4. Go through LN purchase flow. Ensure it works correctly. PASS
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 was broken by the recent nip19 changes, let's fix it again
Fixes: cb4adf06f1 ("nip19: added swift enums")
Changelog-Fixed: Fix nostrscripts not loading
Signed-off-by: William Casarin <jb55@jb55.com>
otherwise there is contention and tends to crash
Fixes: f06b882139 ("purple: consolidate UserBadgeInfo with Account")
Changelog-Fixed: Fix crash when accessing cached purple accounts
Signed-off-by: William Casarin <jb55@jb55.com>
Also doing this so I can add a changelog entry
Changelog-Changed: Disable inline text suggestions on 17.0 as they interfere with mention generation
Signed-off-by: William Casarin <jb55@jb55.com>
The purple membership badge should be displayed as compact view
everywhere except the user's profile.
Lightning-address: kernelkind@getalby.com
Changelog-Fixed: Hide member signup date on reposts
Signed-off-by: kernelkind <kernelkind@gmail.com>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
Rename get_account to fetch_account to make it clear that it is always a
call to the server.
Add get_maybe_cached_account method that checks cached before calling
fetch_account.
Signed-off-by: William Casarin <jb55@jb55.com>
The URL shown to the user before they click the 'Load Media' button can
take up a large portion of the screen, and doesn't offer any value to
the user.
This patch features a naive approach to truncate the URL to be a certain
number of characters if it is greater than the specified value. Right
now the maximum number of characters is set to 80.
Closes: https://github.com/damus-io/damus/issues/1950
Lightning-address: kernelkind@getalby.com
Signed-off-by: kernelkind <kernelkind@gmail.com>
Link: 20240130183525.50446-1-kernelkind@gmail.com
Signed-off-by: William Casarin <jb55@jb55.com>
Previously, if the user had the DamusPurpleView open and bought the
subscription, the DamusPurpleView would not change. It would stay in the
marketing pitch screen.
This commit makes sure that this view is automatically updated as soon
as the user sees the welcome screen, so that they can see their account
info in case they have DamusPurpleView open.
Testing
--------
PASS
iOS: 17.2
Damus: This commit
damus-api: Varying versions around `9a6af62`
Coverage:
1. Checked the entire LN flow through the local test environment using the simulator
2. Checked all LN flow views on both light and dark mode to ensure it looks good
3. Checked the entire LN flow using the staging environment using a physical iOS device
Closes: https://github.com/damus-io/damus/issues/1899
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
Some views appeared broken when iOS was in dark mode, with a white
background. This commit fixes that and makes sure the background is
always dark.
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 changes the welcome view into a multi-step onboarding
process, where it makes it more clear that translations are unlocked,
and provides the user with some choices to set it up or not.
This flow also makes the translation setup possible on the LN flow
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
We do not have Apple In-app purchases ready for the upcoming release.
This commit hides IAP UI/UX behind a developer feature flag which is off
by default, and shows a link inviting the user to visit the website to
learn more.
It also makes the link go to the normal Damus website.
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
Originally the Damus Purple feature was gated behind a setting which
served as a feature flag.
However, when we release, we need to enable Purple features for all
users running on a particular version.
This commit improves feature flag management by replacing the setting
with a computed property (which still points to the setting, but can be
very easily replaced)
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 improves the handling of different Purple environments:
- 3 environments were added (test, staging, production) to fulfill all
testing needs
- Damus website constants were also added (This will become important
for the next few commits)
- Toggle settings were replaced with a picker, where the user can select
one of the 3 environments (test, staging, production)
- Damus purple page and website address links can now be obtained
directly from the DamusPurple struct, which improves flexibility and
reduces complexity for code that consumes these constants.
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
On small screens, specifically the iPhone 12 Mini in this case, the
'Load Media' has a minimum width which is too high so it causes
formatting problems when viewing replies.
The minimum width of the frame was arbitrarily decreased from 300 to
200.
Changelog-Fixed: Fix load media formatting on small screens
Closes: https://github.com/damus-io/damus/issues/1944
Lightning-address: kernelkind@getalby.com
Signed-off-by: kernelkind <kernelkind@gmail.com>
Signed-off-by: William Casarin <jb55@jb55.com>
When creating an NostrEvent with an nevent1 mention, don't include the
nevent mentions in the event's tags. This matches the behavior for
note1 mentions.
Tests for content with npub1 and note1 mentions were added to confirm
tag generation behavior. Test for nevent mention tag generation was
modified to be the same as note1.
Closes: https://github.com/damus-io/damus/issues/1941
Lightning-address: kernelkind@getalby.com
Signed-off-by: kernelkind <kernelkind@gmail.com>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
There comes a point when the sharing a Nip19 mention becomes unwieldy
when there is too much TLV data. This patch features a naive approach to
making sure the relay portion of the TLV data doesn't contribute too
much data to the mention.
It adds a maximum number of relays that should be shared in the mention,
right now it is set to four.
Changelog-Fixed: Fix shared nevents that are too long
Lightning-address: kernelkind@getalby.com
Signed-off-by: kernelkind <kernelkind@gmail.com>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
This change adds an subscriber number to the supporter badge.
Testing
--------
PASS
Device: iPhone 15 simulator
iOS: 17.2
Damus: This commit
damus-api: `53fd7fef1c8c0bbf82bb28d1d776e45379433d23`
Setup:
- `damus-api` running on `npm run dev` mode
- Damus configured to enable experimental Purple support + localhost mode
Test steps:
1. Wipe local database and rerun server
2. Purchase purple using In-app purchase (Xcode environment) flow
3. Make sure that badge to the side of the user's name on the event shows a golden star without any ordinal numbers
4. Make sure that the badge to the side of the user's name on the profile page shows a golden star with the text "1st"
5. Repeat steps 2–4 and make sure the text says "2nd"
6. Look at the SupporterBadge view previews. Ordinals should show up correctly for all previews (They should always show up, no matter the number)
Closes: https://github.com/damus-io/damus/issues/1873
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
There is currently an issue where if a user doesn’t have an existing
mutelist it won’t let the user add new mute items. This patch fixes that
by not including the existing mutelist variable in the guard statement.
Lighting-address: fishcharlie@strike.me
Signed-off-by: Charlie Fish <contact@charlie.fish>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
This patch fixes an issue where the user can’t change the mute duration
when adding a new mute item.
The problem was that `expiration` was nil for indefinite which isn’t
really allowed for a Picker.
I fixed this by adding an indefinite case to DamusDuration.
Closes: https://github.com/damus-io/damus/issues/1907
Lighting-address: fishcharlie@strike.me
Signed-off-by: Charlie Fish <contact@charlie.fish>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
Currently there is an issue where if you try to mute a hashtag, it will
mutate the `new_text` variable. This patch fixes that so that we aren’t
mutating `new_text`.
Lighting-address: fishcharlie@strike.me
Signed-off-by: Charlie Fish <contact@charlie.fish>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
This fixes subtle bugs with transaction inheritence. Since we were not
passing the inherited state to moved value, we were sometimes committing
transactions more than once.
Changelog-Fixed: Fix many nostrdb transaction related crashes
Previously, when a post is being sent, the next character after a
mention was checked. If it wasn't a space, a space was added. This
implementation was insufficient because there are times where a
character immediately following a mention is desired, especially for
punctuation.
This was possible in the past because the C code counts anything non
alphanumeric as being part of the mention if it starts with 'nostr:'.
The fix included follows similar logic. If the character following the
mention is non alphanumeric, it allows it. Otherwise, a space is added
so that the C code can correctly parse the mention.
A test was added which verifies non alphanumeric characters after
mentions don't get whitespace added before them.
Fixes: af75eed ("mention: fix broken mentions when there is text is directly after")
Closes: https://github.com/damus-io/damus/issues/1915
Signed-off-by: kernelkind <kernelkind@gmail.com>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
Just using strings is really bad performance wise, and is not the
proper way to implement a TagConvertible. The whole point of this
protocol is to parse tags efficiently.
This patch depends on: Adding new structs/enums for new mute list
- Rewrites Lists.swift to use new mute list option
- This leads to a lot of changes for changing the type from RefId to the new MuteItem
- Update & relay new mute list in AddMuteItemView.swift (fixing previous patch TODO)
- Renames `list` to `list_deprecated`
- We need to keep this since existing users might have an old mute list
Related: https://github.com/damus-io/damus/issues/1718
Related: https://github.com/damus-io/damus/issues/856
Lighting Address: fishcharlie@strike.me
Signed-off-by: Charlie Fish <contact@charlie.fish>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
This is a potential fix for some of the crash reports that have been
streaming in. They all seem to be crashing within ndb_close_txn. I
suspect this means that the transactions are trying to get closed when
ndb is already closed. Closing Ndb will close the transactions
automatically, so it looks like we might be trying to close twice.
This patch depends on: Adding new structs/enums for new mute list
- Rewrites Lists.swift to use new mute list option
- This leads to a lot of changes for changing the type from RefId to the new MuteItem
- Update & relay new mute list in AddMuteItemView.swift (fixing previous patch TODO)
- Renames `list` to `list_deprecated`
- We need to keep this since existing users might have an old mute list
Related: https://github.com/damus-io/damus/issues/1718
Related: https://github.com/damus-io/damus/issues/856
Lighting Address: fishcharlie@strike.me
Signed-off-by: Charlie Fish <contact@charlie.fish>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
In the ellipsis menu, when the user selects the 'Copy user public key',
an nprofile Bech32 entity will be generated which will include TLV data
with the user's public key and entire relay list, if available.
The nprofile will be added to the user's copy clipboard.
When the user presses the share menu on an event and clicks the 'copy
link' button, a damus link with the nevent for the note will be
generated and copied to the user's clipboard.
Closes: https://github.com/damus-io/damus/issues/1844
Changelog-Changed: Generate nprofile/nevent links in share menus
Lightning-url: LNURL1DP68GURN8GHJ7EM9W3SKCCNE9E3K7MF0D3H82UNVWQHKWUN9V4HXGCTHDC6RZVGR8SW3G
Signed-off-by: kernelkind <kernelkind@gmail.com>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
The user is able to search for naddr, nprofile & nevent bech32 entities.
Additionally, these entities and others are able to have prefixes such
as damus:nostr: and damus.io links.
Closes: https://github.com/damus-io/damus/issues/1841
Closes: https://github.com/damus-io/damus/issues/1650
Changelog-Added: Add ability to search for naddr, nprofiles, nevents
Lightning-url: LNURL1DP68GURN8GHJ7EM9W3SKCCNE9E3K7MF0D3H82UNVWQHKWUN9V4HXGCTHDC6RZVGR8SW3G
Signed-off-by: kernelkind <kernelkind@gmail.com>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
Add functionality for when user taps on naddr link they get redirected
to the proper note.
Closes: https://github.com/damus-io/damus/issues/1806
Changelog-Added: Add naddr link support
Lightning-url: LNURL1DP68GURN8GHJ7EM9W3SKCCNE9E3K7MF0D3H82UNVWQHKWUN9V4HXGCTHDC6RZVGR8SW3G
Signed-off-by: kernelkind <kernelkind@gmail.com>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
Allow nevent mentions to be loaded in the MentionView since they are
just a note with extra metadata.
Lightning-url: LNURL1DP68GURN8GHJ7EM9W3SKCCNE9E3K7MF0D3H82UNVWQHKWUN9V4HXGCTHDC6RZVGR8SW3G
Signed-off-by: kernelkind <kernelkind@gmail.com>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
Create shortened URLs for bech32 with TLV data strings. Additionally,
upon clicking on an nevent URL the user is directed to the note.
Lightning-url: LNURL1DP68GURN8GHJ7EM9W3SKCCNE9E3K7MF0D3H82UNVWQHKWUN9V4HXGCTHDC6RZVGR8SW3G
Signed-off-by: kernelkind <kernelkind@gmail.com>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
If a user adds text right after a mention without a space, a space gets
added so the mention can be parsed correctly after posting.
Closes: https://github.com/damus-io/damus/issues/1872
Changelog-Fixed: Fix broken mentions when there is text is directly after
Lightning-url: LNURL1DP68GURN8GHJ7EM9W3SKCCNE9E3K7MF0D3H82UNVWQHKWUN9V4HXGCTHDC6RZVGR8SW3G
Signed-off-by: kernelkind <kernelkind@gmail.com>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
Contributes to closing https://github.com/damus-io/damus/issues/1847.
- Fixes (1), the black bar at the top of the view is removed.
- Fixes (2), Scrolling down does not reveal an unappealing navigation bar
- Fixes (3), After the user presses 'continue', the user is taken back to
DamusPurpleView. If the user is shown a confirmation dialog, it waits
for user interaction, and after it dismisses DamusPurpleView to go back
to the home screen. If the user isn't shown the confirmation dialog, the
user is brought to the home screen straight away.
- May or may not fix (4)
- Fixes (5), the theme persists in light and dark mode
Lightning-url: LNURL1DP68GURN8GHJ7EM9W3SKCCNE9E3K7MF0D3H82UNVWQHKWUN9V4HXGCTHDC6RZVGR8SW3G
Signed-off-by: kernelkind <kernelkind@gmail.com>
Signed-off-by: William Casarin <jb55@jb55.com>
When scrolling through the media carousel, the currently viewed media
should persist between fullscreen and carousel view instead of resetting
to the first index.
Closes: https://github.com/damus-io/damus/issues/1329
Changelog-Fixed: Save current viewed image index when switching to fullscreen
Lightning-url: LNURL1DP68GURN8GHJ7EM9W3SKCCNE9E3K7MF0D3H82UNVWQHKWUN9V4HXGCTHDC6RZVGR8SW3G
Signed-off-by: kernelkind <kernelkind@gmail.com>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
Finds the range of characters which represents a mention the user is
typing in PostView. Previously the tokenizer used the standard
granularity UITextGranularity.word, but this is insufficient for our use
case for detecting when a mention ends.
The criteria is simple: a mention starts with the '@' character and ends
when there is a space, line break, or @, instead of when there is a new
word.
Closes: https://github.com/damus-io/damus/issues/1721
Changelog-Fixed: Allow mentioning users with punctuation characters in their names
Lightning-url: LNURL1DP68GURN8GHJ7EM9W3SKCCNE9E3K7MF0D3H82UNVWQHKWUN9V4HXGCTHDC6RZVGR8SW3G
Signed-off-by: kernelkind <kernelkind@gmail.com>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
This commit adds support for the LN checkout flow, and the Purple
landing page:
1. It adds a "learn more" button on the Damus Purple view, where the
user can learn more
2. It adds new `damus:purple` urls to enable the LN checkout flow
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
Add encode method for converting Bech32Object to a bech32 encoded
string. This will be useful for generalized conversion of Bech32Objects
to its string representation.
Lightning-url: LNURL1DP68GURN8GHJ7EM9W3SKCCNE9E3K7MF0D3H82UNVWQHKWUN9V4HXGCTHDC6RZVGR8SW3G
Signed-off-by: kernelkind <kernelkind@gmail.com>
Signed-off-by: William Casarin <jb55@jb55.com>
Add enums to reflect Bech32 with TLV encoded data. Update parse method
to call C library for generalized parsing of bech32 data.
Lightning-url: LNURL1DP68GURN8GHJ7EM9W3SKCCNE9E3K7MF0D3H82UNVWQHKWUN9V4HXGCTHDC6RZVGR8SW3G
Signed-off-by: kernelkind <kernelkind@gmail.com>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
Add support for type KIND for bech32-encoded entities naddr and nevent
as specified in NIP-19.
LNURL1DP68GURN8GHJ7EM9W3SKCCNE9E3K7MF0D3H82UNVWQHKWUN9V4HXGCTHDC6RZVGR8SW3G
Signed-off-by: kernelkind <kernelkind@gmail.com>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
This was causing crashing and corruption issues. This should have been
handled by the garbage collector, but for some reason old references
still hang around.
Add a "close" method to DamusState which disconnects from relays and
closes nostrdb.
Changelog-Fixed: Fix crash when logging out and switching accounts
Changelog-Fixed: Fix persistent local notifications even after logout
Signed-off-by: William Casarin <jb55@jb55.com>
It's never safe to return an unsafeUnownedValue
Fixes: c4f0e833ff ("Reuse local notification logic with push notifications")
Cc: Daniel DAquino <daniel@daquino.me>
Signed-off-by: William Casarin <jb55@jb55.com>
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")
... to shared container instead of migrating
This commit is a reimplementation of DamusUserDefaults that mirrors
settings from the app to the shared container (instead of migrating
values over).
This new implementation brings the benefit of being backwards compatible
with the user's settings. That is, even if the user upgrades or
downgrades between various versions and changes settings along the way,
the main settings in the app will stay consistent between Damus versions
— that is, changes to the settings would not be lost between
downgrades/upgrades
General settings test
----------------------
PASS
Device: iPhone 15 Pro simulator
iOS: 17.0.1
Damus: This commit
Setup: A device with non-standard settings
Steps:
1. Flash Damus on the device
2. Check any non-default settings that were there before. Ensure that settings remained the same. PASS
3. Change one setting (any setting) to a non-default value
4. Restart Damus
5. Ensure settings change in step 3 persisted on the device
Notification settings 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. Use the secondary phone to generate a push notification
2. Trigger the push notification (Send push notification from test tool)
3. Ensure that the notification is received on the other device
4. Turn off notifications for that notification type on settings
5. Trigger the same push notification (Resend push notification from test tool)
6. Ensure that the notification is not received on the other device
7. Turn on notifications for that notification type on settings
8. Trigger the same push notification (Resend from test tool)
9. Ensure that notification appears on the device
Result: PASS (notifications are received when enabled and not received when disabled)
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Signed-off-by: William Casarin <jb55@jb55.com>
Unit tests
-----------
Device: iPhone 15 Pro simulator
iOS: 17.0.1
Damus: This commit
Steps: Run unit tests
Result: No regressions found (Tests either pass or they were already failing before the patches)
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Signed-off-by: William Casarin <jb55@jb55.com>
Muted users + unfollowed users 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
Steps:
1. Unfollow the user who is the author of the saved notifications
2. Disable notifications for people you don't follow
3. Trigger a push notification (Resend push notification from test tool)
4. Ensure that the notification is not received on the other device
5. Enable notifications for people you don't follow
6. Trigger a push notification (Resend push notification from test tool)
7. Ensure that the notification is received on the other device
8. Mute the user who is the author of the saved notifications
9. Trigger a push notification (Resend push notification from test tool)
10. Ensure that the notification is not received on the other device
11. Unmute the user who is the author of the saved notifications
12. Trigger a push notification (Resend push notification from test tool)
13. Ensure that the notification is received on the other device
Result: PASS
Closes: https://github.com/damus-io/damus/issues/1705
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Signed-off-by: William Casarin <jb55@jb55.com>
Notification settings 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 push notification (Resend push notification from test tool)
2. Ensure that the notification is received on the other device
3. Turn off notifications for that type on settings
4. Trigger a push notification (Resend push notification from test tool)
5. Ensure that the notification is not received on the other device
Result: PASS (notifications are received when enabled and not received when disabled)
Closes: https://github.com/damus-io/damus/issues/1764
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Signed-off-by: William Casarin <jb55@jb55.com>
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 is needed to allow the notification extension to process push notifications, respect user's notification settings, and decrypt DMs on the push notification
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Signed-off-by: William Casarin <jb55@jb55.com>
This commit brings key local notification logic into the notification
extension target to allow the extension to reuse much of the
functionality surrounding the processing and formatting of
notifications. More specifically, the functions
`process_local_notification` and `create_local_notification` were
brought into the extension target.
This will enable us to reuse much of the pre-existing notification logic
(and avoid having to reimplement all of that)
However, those functions had high dependencies on other parts of the
code, so significant refactorings were needed to make this happen:
- `create_local_notification` and `process_local_notification` had its
function signatures changed to avoid the need to `DamusState` (which
pulls too many other dependecies)
- Other necessary dependencies, such as `Profiles`, `UserSettingsStore`
had to be pulled into the extension target. Subsequently,
sub-dependencies of those items had to be pulled in as well
- In several cases, files were split to avoid pulling too many
dependencies (e.g. Some Model files depended on some functions in View
files, so in those cases I moved those functions into their own
separate file to avoid pulling in view logic into the extension
target)
- Notification processing logic was changed a bit to remove dependency
on `EventCache` in favor of using ndb directly (As instructed in a
TODO comment in EventCache, and because EventCache has too many other
dependencies)
tldr: A LOT of things were moved around, a bit of logic was changed
around local notifications to avoid using `EventCache`, but otherwise
this commit is meant to be a no-op without any new features or
user-facing functional changes.
Testing
-------
Device: iPhone 15 Pro
iOS: 17.0.1
Damus: This commit
Coverage:
1. Ran unit tests to check for regressions (none detected)
2. Launched the app and navigated around and did some interactions to
perform a quick functional smoke test (no regressions found)
3. Sent a few push notifications to check they still work as expected (PASS)
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 realized we didn't have this in the contributor docs. Noone will read
it, but at least we'll have something to point to for future contributors.
Cc: kernelkind <kernelkind@gmail.com>
Signed-off-by: William Casarin <jb55@jb55.com>
Signed-off-by: Terry Yiu <git@tyiu.xyz>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
Changelog-Fixed: Add workaround to fix note language recognition and reduce wasteful translation requests
Lightning-Invoice: lnbc1pjcpaakpp5gjs4f626hf8w6slx84xz3wwhlf309z503rjutckdxv6wwg5ldavsdqqcqzpgxqrrs0fppqjaxxw43p7em4g59vedv7pzl76kt0qyjfsp5qcp9de7a7t8h6zs5mcssfaqp4exrnkehqtg2hf0ary3z5cjnasvs9qyyssq55523e4h3cazhkv7f8jqf5qp0n8spykls49crsu5t3m636u3yj4qdqjkdl2nxf6jet5t2r2pfrxmm8rjpqjd3ylrzqq89m4gqt5l6ycqf92c7h
Closes: https://github.com/damus-io/damus/issues/940
Signed-off-by: Charlie Fish <contact@charlie.fish>
Signed-off-by: William Casarin <jb55@jb55.com>
Changelog-Added: Add NIP-42 relay auth support
Closes: https://github.com/damus-io/damus/issues/1846
Lightning-Invoice: lnbc1pjef2gupp5ffv0he47r6s6us9s2pfxy023mx8lutwlh3sq365rzgmmj6efl8nsdqqcqzpgxqrrs0fppq65gwnyvf5pn5zj5ryx9s4n7y58clk7yqsp5v7pa2ges4rgvtt0nh6lnt4cevm8n2ql9p7kqstwfp4wutf8faa8q9qyyssqwx8t9kk0m3jj6vu0kvftl3nc8zqyfl5l8ne058q5dnqyad3cqfz8vdnna5g0vy9f2ttwugc0sr20p0hsem84g8xd85ptnwgmryrf4lqqmygv34
Signed-off-by: Charlie Fish <contact@charlie.fish>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
Changelog-Fixed: Fixed bug where sometimes notes from other profiles appear on profile pages
Do not include comma as part of a URL if it is followed by whitespace.
This allows users to make lists of URLs.
Closes: https://github.com/damus-io/damus/issues/1833
LNURL1DP68GURN8GHJ7EM9W3SKCCNE9E3K7MF0D3H82UNVWQHKWUN9V4HXGCTHDC6RZVGR8SW3G
Signed-off-by: kernelkind <kernelkind@gmail.com>
Signed-off-by: William Casarin <jb55@jb55.com>
This commit integrates the Damus Purple translation service:
- Automatically handles translation settings change after purchase
- Asks for permission to override translation settings if the user already has translation setup
- Translation settings can be changed with Damus Purple, if desired
- Translation requests working with the Damus API server
Testing
--------
PASS
Device: iPhone 15 simulator
iOS: 17.2
Damus: This commit
Damus Purple API server: `9397201d7d55ddcec4c18fcd337f759b61dce697` running on Ubuntu 22.04 LTS VM (npm run dev)
iOS setting: English set as the only preferred language.
Steps:
1. Enable Damus Purple feature flag on developer settings, set purple localhost mode, and restart app
2. Set translation setting to something other than none (e.g. DeepL)
3. Simulate Damus Purple purchase
4. Check that when dismissing welcome view, a confirmation prompt will ask the user whether they want to switch translator to Damus Purple. PASS
5. Click "Yes".
6. Go to translation settings. Check that translation settings are set to "Purple". PASS
7. Go to a non-English profile. Check that translations appear with "Mock translation" (Which is the translation text provided by the mock translation server). PASS
8. Reinstall app
9. Repeat the test, but this time starting with no translation settings. Make sure that translation settings will automatically switch to Damus Purple. PASS
Feature flag testing
--------------------
PASS
Preconditions: Same as above
Steps:
1. Turn off translation
2. Turn off Damus Purple feature flag
3. Go to translation settings. Make sure that Damus Purple is not an option. PASS
Closes: https://github.com/damus-io/damus/issues/1836
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
these changes were made to adapt the client-side to the new improvements
done to the Purple API server (See
https://github.com/damus-io/api/issues/1)
Testing
-------
PASS
Device: iPhone 15 Pro simulator
iOS: 17.2
Damus: This commit
damus-api: bda56590be7eb47e21dfd61ab94b17f6a8595d0c
Server: Ubuntu 22.04 (VM)
Setup:
1. On the server, delete the `mdb` database files to start from scratch
2. Enable subscriptions support via developer settings with localhost
test mode and restart app
3. Get Damus Purple (Purchase it via Xcode test environment)
4. Start server with mock parameters (Run `npm run dev`)
5. Restart app
Steps
-----
1. Post something
2. Gold star should appear beside your name
3. Look at the server logs. There should be some requests to create the
account (POST), to send the receipt (POST), and to get account
status. Those three requests should have returned HTTP status 200.
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
Testing
---------
PASS
Device: iPhone 15 Pro simulator
iOS: 17.2
Damus: This commit
damus-api: 626fb9665d8d6c576dd635d5224869cd9b69d190
Server: Ubuntu 22.04 (VM)
Setup:
1. On the server, delete the `mdb` database files to start from scratch
2. In iOS, reinstall the app if necessary to make sure there are no in-app purchases
3. Enable subscriptions support via developer settings with localhost test mode and restart app
4. Start server with mock parameters (Run `npm run dev`)
Steps:
1. Open top bar and click on "Purple"
2. Purple screen should appear and show both benefits and the purchase options. PASS
3. Click on "monthly". An Apple screen to confirm purchase should appear. PASS
4. Welcome screen with animation should appear. PASS
5. Click continue and restart app (Due to known issue tracked at damus-io#1814)
6. Post something
7. Gold star should appear beside your name
8. Look at the server logs. There should be some requests to create the account (POST), to send the receipt (POST), and to get account status
9. Go to purple view. There should be some information about the subscription, as well as a "manage" button. PASS
10. Click on "manage" button. An iOS sheet should appear allow the user to unsubscribe or manage their subscription to Damus Purple.
Closes: https://github.com/damus-io/damus/issues/1809
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Signed-off-by: William Casarin <jb55@jb55.com>
This commit includes various code changes necessary to get a basic proof of concept of the feature working.
This is NOT a full working feature yet, only a preliminary prototype/PoC. It includes:
- [X] Basic Storekit configuration
- [X] Basic purchase mechanism
- [X] Basic layout and copywriting
- [X] Basic design
- [X] Manage button (To help user cancel their subscription)
- [X] Thank you confirmation + special welcome view
- [X] Star badge on profile (by checking the Damus Purple API)
- [X] Connection to Damus purple API for fetching account info, registering for an account and sending over the App Store receipt data
The feature sits behind a feature flag which is OFF by default (it can be turned ON via Settings --> Developer settings --> Enable experimental Purple API and restarting the app)
Testing
---------
PASS
Device: iPhone 15 Pro simulator
iOS: 17.0.1
Damus: This commit
damus-api: 59ce44a92cff1c1aaed9886f9befbd5f1053821d
Server: Ubuntu 22.04 (VM)
Setup:
1. On the server, delete the `mdb` database files to start from scratch
2. In iOS, reinstall the app if necessary to make sure there are no in-app purchases
3. Enable subscriptions support via developer settings with localhost test mode and restart app
4. Start server with mock parameters (Run `npm run dev`)
Steps:
1. Open top bar and click on "Purple"
2. Purple screen should appear and show both benefits and the purchase options. PASS
3. Click on "monthly". An Apple screen to confirm purchase should appear. PASS
4. Welcome screen with animation should appear. PASS
5. Click continue and restart app (Due to known issue tracked at https://github.com/damus-io/damus/issues/1814)
6. Post something
7. Gold star should appear beside your name
8. Look at the server logs. There should be some requests to create the account (POST), to send the receipt (POST), and to get account status
9. Go to purple view. There should be some information about the subscription, as well as a "manage" button. PASS
10. Click on "manage" button. An iOS sheet should appear allow the user to unsubscribe or manage their subscription to Damus Purple.
Feature flag testing
--------------------
PASS
Preconditions: Continue from above test
Steps:
1. Disable Damus Purple experiment support on developer settings. Restart the app.
2. Check your post. There should be no star beside your profile name. PASS
3. Check side menu. There should be no "Damus Purple" option. PASS
4. Check server logs. There should be no new requests being done to the server. PASS
Closes: https://github.com/damus-io/damus/issues/1422
This commit fixes a crash that occured on large notes with several artifacts.
The crash was caused by an empirically observed limitation on the amount
of `Text` objects that can be added together. Adding several `Text`
objects together causes a infinite recursion and subsequent stack
overflow.
The fix applied changes the `CompatibleText` class to store several
items in a list, which concatenates attributed strings when possible to
reducethe amount of `Text` objects used.
This commit also:
- Changes the structure to avoid storing SwiftUI objects on a variable,
but making it into a computed property instead.
- Renders a nice error message when the note is too large to be rendered
(instead of crashing)
With this new commit, we can render much larger notes, and the only ones
that will not be displayed are those containing more than 50 custom
hashtags.
Since we do not even have 50 custom hashtag types, the only notes that
won't be rendered are spammy notes that repeat the same hashtags over
and over again.
Testing
-------
PASS
Device: iPhone 13 Mini (Physical device)
iOS: 17.2
Damus: This commit
Setup:
- Local test relay and a test account running on a simulator to post
those long test notes.
- Local web page server to serve a link to the problematic note.
(nostr:note1ttfgneka3lt6yuutmr0uls5xd6z975fgdzpfkxwwf40dd38pjcqqvzvxaj)
Steps
-----
1. Click on the link to open the note
2. Check that no crash occurs and that the note is rendered correctly. PASS
3. Click on the note to render the SelectableText view (Different code
path). Make sure that no crash occurs and that it is rendered
correctly. PASS
4. On the simulator, post a note with 50 "#bitcoin" hashtags displayed
(100 items).
5. Open the note on the physical iPhone. Make sure that no crash occurs
and that the note is rendered correctly. PASS
6. Ensure that the hashtag and hashtag icons are rendered. PASS
7. Click on the note and make sure that the SelectableText view is
rendered correctly. PASS[1]
8. On the simulator, post a note with 51 "#bitcoin" hashtags displayed
(102 items).
9. Open the note on the physical iPhone. Make sure that a nice error
message is displayed. PASS
10. Click on the note and make sure that the SelectableText view is
rendered correctly. PASS[1]
Notes
[1] On the SelectableText view, special hashtags always render with the
purple color. This behavior was already present before the changes, so
it is not a regression.
Changelog-Fixed: Fix crash on very large notes
Closes: https://github.com/damus-io/damus/issues/1826
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
Fix parsing URL when encountering a period at the end of the url by
setting it as disallowed from being present at the end of a
URL.
Some characters are disallowed to be present at the end of URLs.
Presently, the period character is the only disallowed character.
A character is the last character in the URL if it is followed by
is_whitespace() or if it's the last character in the string.
Closes: https://github.com/damus-io/damus/issues/1638
LNURL1DP68GURN8GHJ7EM9W3SKCCNE9E3K7MF0D3H82UNVWQHKWUN9V4HXGCTHDC6RZVGR8SW3G
Signed-off-by: kernelkind <kernelkind@gmail.com>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
This reverts commit da2bdad18d.
This commit was reverted because it was causing crashes (Occasional `EXC_BAD_ACCESS` errors when accessing database transactions), and because the push notification extension uses Ndb in a read-only manner, which means we no longer need these changes
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Remove the private key leak warning in the DMChatView and PostView since
they are no longer needed since nsec is automatically converted into
npub.
Changelog-Removed: Removed old nsec key warning, nsec automatically convert to npub when posting
Signed-off-by: kernelkind <kernelkind@gmail.com>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
This patch makes sure that regional relays (e.g. Japan relays) are suggested to the relevant users on the Relay configuration view.
It also makes some small improvements to the recommended relays view layout, to allow it to comfortably show more than 4 relay suggestions without "squeezing" items.
Testing
-------
PASS
Devices:
- iPhone 15 Pro simulator running iOS 17.0.1
- iPad Air 5th generation running iOS 16.4
Damus: This commit
Configuration: No relays selected, region set to Canada
Steps:
1. Go to Relay Config view
2. Check that recommended relays are: Damus, nos.lol, nostr.wine, nostr.land. PASS
3. Change region to Japan on settings
4. Open relay config view again
5. Check that Japan relays are suggested on top of the list presented in step 2. PASS
6. Check that layout looks ok, not broken. PASS
7. Check that it is possible to scroll horizontally to see all the options. PASS
8. Add some relays. Check that it is possible to add relays. PASS
9. Check that borders of the recommended relay view fades away nicely (not just clip). PASS
10. Remove some relays. Check that they return to the suggested relays list. PASS
Real device smoke test
----------------------
Device: iPhone 13 mini running iOS 17.1
Damus: This commit
Configuration: Several relays selected. Region set to Canada.
Steps:
1. Check relay config view does not look broken. PASS
2. Remove some recommended relays. Check that they display nicely on the recommended view. PASS
3. Scroll horizontally. Scrolling should work and layout should not be broken. PASS
4. Add those recommended relays again. Should work. PASS
Closes: https://github.com/damus-io/damus/issues/1730
Changelog-Added: Add regional relay recommendations to Relay configuration view (currently for Japanese users only)
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
Reviewed-by: William Casarin <jb55@jb55.com>
Signed-off-by: William Casarin <jb55@jb55.com>
Otherwise iOS gets mad because we are holding onto a lockfile in a
shared container which is apparently not allowed.
Fixes: a1e6be214e ("Migrate NostrDB files to shared app group file container")
_[Please provide a summary of the changes in this PR.]_
## Checklist
- [ ] I have read (or I am familiar with) the [Contribution Guidelines](../docs/CONTRIBUTING.md)
- [ ] I have tested the changes in this PR
- [ ] I have opened or referred to an existing github issue related to this change.
- [ ] My PR is either small, or I have split it into smaller logical commits that are easier to review
- [ ] I have added the signoff line to all my commits. See [Signing off your work](../docs/CONTRIBUTING.md#sign-your-work---the-developers-certificate-of-origin)
- [ ] I have added appropriate changelog entries for the changes in this PR. See [Adding changelog entries](../docs/CONTRIBUTING.md#add-changelog-changed-changelog-fixed-etc)
- [ ] I do not need to add a changelog entry. Reason: _[Please provide a reason]_
- [ ] I have added appropriate `Closes:` or `Fixes:` tags in the commit messages wherever applicable, or made sure those are not needed. See [Submitting patches](https://github.com/damus-io/damus/blob/master/docs/CONTRIBUTING.md#submitting-patches)
## Test report
_Please provide a test report for the changes in this PR. You can use the template below, but feel free to modify it as needed._
**Device:**_[Please specify the device you used for testing]_
**iOS:**_[Please specify the iOS version you used for testing]_
**Damus:**_[Please specify the Damus version or commit hash you used for testing]_
**Setup:**_[Please provide a brief description of the setup you used for testing, if applicable]_
**Steps:**_[Please provide a list of steps you took to test the changes in this PR]_
**Results:**
- [ ] PASS
- [ ] Partial PASS
- Details: _[Please provide details of the partial pass]_
## Other notes
_[Please provide any other information that you think is relevant to this PR.]_
1. This product contains code derived from [Nostr SDK iOS](https://github.com/nostr-sdk/nostr-sdk-ios). [License](https://github.com/nostr-sdk/nostr-sdk-ios/blob/40df800c6749d7ce0b6fd7328e76cbc0dc71c87b/LICENSE)
2. This product includes software developed by the "Marcin Krzyzanowski" (http://krzyzanowskim.com/). [License](https://github.com/krzyzanowskim/CryptoSwift/blob/e74bbbfbef939224b242ae7c342a90e60b88b5ce/LICENSE)
content.title=NSLocalizedString("Someone posted a note",comment:"Title label for push notification where someone posted a note")
content.body=event.content
@@ -30,7 +31,7 @@ struct NotificationFormatter {
content.body=NSLocalizedString("(Contents are encrypted)",comment:"Label on push notification indicating that the contents of the message are encrypted")
content.title=NSLocalizedString("Someone reacted to your note",comment:"Generic title label for push notifications where someone reacted to the user's post")
title=String(format:NSLocalizedString("Tagged by %@",comment:"Tagged by heading in local notification"),displayName)
identifier="myMentionNotification"
case.mention:
title=String(format:NSLocalizedString("Mentioned by %@",comment:"Mentioned by heading in local notification"),displayName)
identifier="myMentionNotification"
case.repost:
title=String(format:NSLocalizedString("Reposted by %@",comment:"Reposted by heading in local notification"),displayName)
identifier="myBoostNotification"
case.like:
title=String(format:NSLocalizedString("%@ reacted with %@",comment:"Reacted by heading in local notification"),displayName,to_reaction_emoji(ev:notify.event)??"")
content.title=NSLocalizedString("Muted event",comment:"Title for a push notification which has been muted")
content.body=NSLocalizedString("This is an event that has been muted according to your mute list rules. We cannot suppress this notification, but we obscured the details to respect your preferences",comment:"Description for a push notification which has been muted, and explanation that we cannot suppress it")
A twitter-like [nostr][nostr] client for iPhone, iPad and MacOS.
A twitter-like [nostr][nostr] client for iPhone, iPad and MacOS.
<img src="./ss.png" width="50%" height="50%" />
[nostr]: https://github.com/fiatjaf/nostr
## How is Damus better than X/Twitter?
There are no toxic algorithms.\
You can send or receive zaps (satoshis) without asking for permission.\
[There is no central database](https://fiatjaf.com/nostr.html). Therefore, Damus is censorship resistant.\
There are no ads.\
You don't have to reveal sensitive personal information to sign up.\
No email is required. \
No phone number is required. \
Damus is free and open source software. \
There is no Big Tech moat. Therefore, seamless interoperability with thousands or millions of other nostr apps is possible, and is how [Damus and nostr win](https://www.youtube.com/watch?v=qTixqS-W1yo).
## If there are no ads, how is Damus funded?
Damus offers a paid subscription 🟣 purple 🟣 https://damus.io/purple/. \
Initial benefits include a unique subscriber number, subscriber badge, and auto-translate powered by DeepL.
Damus has also graciously received donations or grants from hundreds of Damus users, [Opensats](https://opensats.org/), and the [Human Rights Foundation](https://hrf.org/).
## Spec Compliance
damus implements the following [Nostr Implementation Possibilities][nips]
- [NIP-01: Basic protocol flow][nip01]
- [NIP-04: Encrypted direct message][nip04]
- [NIP-08: Mentions][nip08]
- [NIP-10: Reply conventions][nip10]
- [NIP-12: Generic tag queries (hashtags)][nip12]
- [NIP-19: bech32-encoded entities][NIP19]
- [NIP-21: nostr: URI scheme][NIP21]
- [NIP-25: Reactions][NIP25]
- [NIP-42: Authentication of clients to relays][nip42]
@@ -32,7 +62,7 @@ damus implements the following [Nostr Implementation Possibilities][nips]
- Relays: You can add more relays to send your notes to by tapping the "+".
- Find more relays to add: https://nostr.info/relays/
- Public Key (pubkey): Your public, personal address and how people can find and tag you
- Secret Key: Your *private* key unique to you. Never share your private key publically and share with other clients at your own risk!
- Secret Key: Your *private* key unique to you. Never share your private key publicly and share with other clients at your own risk!
- Save your keys somewhere safe
- Log out
@@ -46,19 +76,15 @@ damus implements the following [Nostr Implementation Possibilities][nips]
1. Search their username in the search bar at the top of the 🔍 Global Feed and click their profile
2. Tap the 🔑 icon which will copy their pubkey to your clipboard
3. Go back to your 🏠 Personal Feed and tap the blue + button to compose your Note
4. Add @ direcly followed by the pubkey (e.g., `@npub1xtscya34g58tk0z605fvr788k263gsu6cy9x0mhnm87echrgufzsevkk5s`)
- You can also long-press a Note to grab their User ID aka pubkey or Note ID to link directly to a Note.
4. Add @ directly followed by the pubkey (e.g., `@npub1xtscya34g58tk0z605fvr788k263gsu6cy9x0mhnm87echrgufzsevkk5s`)
- You can also tap the ellipsis menu of a Note (three dots in top right of note) to grab their User ID aka pubkey or Note ID to link directly to a Note.
- Currently you can't delete your Notes in the iOS app
- Share images by pasting the image url which you can grab from imgbb, imgur, etc. (i.e., `https://i.ibb.co/2SHZbwm/alpha60.jpg`). Currently images only load for people you follow in the 🏠 Personal Feed. Images are not automatically loaded in 🔍 Global Feed
- Share images by pasting the image url which you can grab from nostr.build, imgbb, imgur, etc. (i.e., `https://i.ibb.co/2SHZbwm/alpha60.jpg`). Currently images only load for people you follow in the 🏠 Personal Feed. Images are not automatically loaded in 🔍 Global Feed
- Engaging with Notes
- 💬 Replying to a Note: Tap the chat icon underneath the note. This will show up in the users’ notifications and in your 🏠 Personal and 🔍 Global Feeds
- ♺ Reposts: Tap the repost icon which will show up in your 🏠 Personal and 🔍 Global Feeds
- ♡ Likes: Tap the heart icon. Users will not get a notification, and cannot see who liked their note (currently, web clients can see your pfp only)
- Formatting Notes (may not format as intended in other web clients)
- Tap the chat icon and you'll notice there's nothing to see at first. Go to a user profile and tap the 💬 chat icon next to the follow button to begin a DM
@@ -76,7 +102,9 @@ damus implements the following [Nostr Implementation Possibilities][nips]
4. For PFP, insert a URL containing your image (support video: https://cdn.jb55.com/vid/pfp-editor.mp4)
5. Save
#### ⚡️ Request Sats
Paste an invoice from your favorite LN wallet.
(Sats or Satoshis are the smallest denomination of bitcoin)
**Alby (browser extension)**
@@ -117,6 +145,8 @@ Your internet protocol (IP) address is exposed to the relays you connect to, and
The relay also learns which public keys you are requesting, meaning your public key will be tied to your IP address.
It is public information which other profiles (npubs) you are exchanging DMs with. The content of the DMs is encrypted.
### Translations
Translators welcome! Join the [Transifex][transifex] project.
@@ -127,8 +157,10 @@ All user-facing strings must have a comment in order to provide context to trans
### Awards
Damus lead dev and founder Will awards developers with satoshis!
There may be nostr badges awarded for contributors in the future... :)
d="M 49.097656,-504.56641 0,-476.2207 v 11.33789 l 39.277344,-22.67578 v 45.35351 l 9.820312,5.66992 z m -19.638672,34.01563 -19.6406246,11.33789 19.6406246,11.33789 z"
d="m 263.22656,34.349609 c -1.66644,0 -2.95278,0.477436 -3.85742,1.429688 -0.90464,0.904639 -1.35742,2.069669 -1.35742,3.498047 0,1.428378 0.45278,2.59536 1.35742,3.5 0.90464,0.857027 2.19098,1.285156 3.85742,1.285156 1.66644,0 2.99818,-0.428129 3.99805,-1.285156 0.99986,-0.857027 1.5,-2.024009 1.5,-3.5 0,-1.475991 -0.50014,-2.665673 -1.5,-3.570313 -0.99987,-0.904639 -2.33161,-1.357422 -3.99805,-1.357422 z m 43.95117,0 c -1.66644,0 -2.95082,0.477436 -3.85546,1.429688 -0.90464,0.904639 -1.35743,2.069669 -1.35743,3.498047 0,1.428378 0.45279,2.59536 1.35743,3.5 0.90464,0.857027 2.18902,1.285156 3.85546,1.285156 1.66645,0 3.00014,-0.428129 4,-1.285156 0.99987,-0.857027 1.5,-2.024009 1.5,-3.5 0,-1.475991 -0.50013,-2.665673 -1.5,-3.570313 -0.99986,-0.904639 -2.33355,-1.357422 -4,-1.357422 z m -118.46166,0.357422 -14.49805,50.351563 h 8.92774 l 2.92773,-11.285156 h 11.78516 l 3.07031,11.285156 h 9.42773 L 195.78638,34.707031 Z m 58.71166,5.285157 -8.49804,2.642578 v 6.71289 h -3.92774 v 7.570313 h 3.92774 v 18.71289 c 0,3.713784 0.66684,6.356519 2,7.927735 1.38076,1.571216 3.42866,2.355468 6.14258,2.355468 1.5236,0 2.9747,-0.189411 4.35546,-0.570312 1.38077,-0.333288 2.59511,-0.761418 3.64258,-1.285156 L 254,77.273438 c -0.66658,0.285675 -1.28607,0.49974 -1.85742,0.642578 -0.57135,0.142837 -1.2155,0.214843 -1.92969,0.214843 -1.04748,0 -1.78438,-0.430082 -2.21289,-1.287109 -0.3809,-0.857027 -0.57227,-2.308127 -0.57227,-4.355469 V 56.917969 h 6.92774 v -7.570313 h -6.92774 z m 80.23243,0 -8.49805,2.642578 v 6.71289 h -3.92969 v 7.570313 h 3.92969 v 18.71289 c 0,3.713784 0.66489,6.356519 1.99805,7.927735 1.38076,1.571216 3.42866,2.355468 6.14257,2.355468 1.52361,0 2.97666,-0.189411 4.35743,-0.570312 1.38076,-0.333288 2.5951,-0.761418 3.64257,-1.285156 l -1.07226,-6.785156 c -0.66658,0.285675 -1.28607,0.49974 -1.85742,0.642578 -0.57135,0.142837 -1.21355,0.214843 -1.92774,0.214843 -1.04747,0 -1.78437,-0.430082 -2.21289,-1.287109 -0.3809,-0.857027 -0.57226,-2.308127 -0.57226,-4.355469 V 56.917969 h 6.92773 v -7.570313 h -6.92773 z m -135.65894,6.855468 h 0.28516 l 1.14453,7.857422 2.85547,11.640625 h -8.2832 l 2.78515,-11.570312 z m 31.94605,1.572266 c -4.33275,0 -7.61963,1.570458 -9.85743,4.71289 -2.23779,3.142433 -3.35546,7.833061 -3.35546,14.070313 0,2.856756 0.21406,5.452139 0.64257,7.785156 0.47613,2.285405 1.23768,4.261293 2.28516,5.927735 1.04748,1.618828 2.38117,2.880516 4,3.785156 1.66644,0.857027 3.71238,1.285156 6.14062,1.285156 1.66645,0 3.33356,-0.238718 5,-0.714844 1.66645,-0.476126 3.09485,-1.190326 4.28516,-2.142578 l -1.78516,-6.570312 c -0.71418,0.476126 -1.50039,0.881555 -2.35742,1.214844 -0.80941,0.285675 -1.80968,0.427734 -3,0.427734 -2.23779,0 -3.88025,-1.022971 -4.92773,-3.070313 -0.99987,-2.047342 -1.5,-4.690077 -1.5,-7.927734 0,-3.856621 0.50013,-6.641415 1.5,-8.355469 0.99986,-1.761666 2.50027,-2.642578 4.5,-2.642578 1.09509,0 2.02335,0.117406 2.78515,0.355469 0.80942,0.19045 1.64298,0.501174 2.5,0.929687 l 2,-7.070312 c -1.04747,-0.571351 -2.26181,-1.048787 -3.64257,-1.429688 -1.33316,-0.3809 -3.07033,-0.570312 -5.21289,-0.570312 z m 35.06445,0.927734 v 35.710938 h 8.5 V 49.347656 Z m 11.05469,0 12.64257,36.066406 h 5.7129 l 11.99804,-36.066406 h -9.14062 l -4.42774,18.570313 -0.78711,5.71289 h -0.28515 l -0.85742,-5.642578 -4.92774,-18.640625 z m 32.89843,0 v 35.710938 h 8.49805 V 49.347656 Z m 33.53125,0 12.42774,35.710938 c -0.28568,1.571216 -0.64375,2.832904 -1.07227,3.785156 -0.42851,0.952252 -0.92865,1.641799 -1.5,2.070312 -0.52374,0.476127 -1.11858,0.714844 -1.78515,0.714844 -0.61897,0.04761 -1.23846,-0.04905 -1.85743,-0.287109 l -1.42773,7.285156 c 0.66658,0.380901 1.45278,0.642319 2.35742,0.785156 0.95225,0.190451 1.92787,0.28711 2.92774,0.28711 1.42837,0 2.64271,-0.430083 3.64257,-1.28711 1.04748,-0.809414 1.97575,-1.999096 2.78516,-3.570312 0.80941,-1.571216 1.57097,-3.475098 2.28516,-5.712891 0.71419,-2.237792 1.47574,-4.761168 2.28515,-7.570312 l 8.92774,-32.210938 h -8.71289 l -4.14258,19.998047 -0.64258,5.642578 h -0.35742 l -0.92774,-5.572265 -5,-20.06836 z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:8.52205467px;line-height:2.53632545px;font-family:'PT Sans Narrow';-inkscape-font-specification:'PT Sans Narrow Bold Condensed';letter-spacing:0.22319667px;word-spacing:2.60024095px;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:url(#linearGradient4523);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.27365798px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"/>
d="m 386.9082,34.349609 c -2.04734,0 -4.09523,0.119359 -6.14258,0.357422 -2.04734,0.190451 -3.92657,0.476521 -5.64062,0.857422 v 49.494141 h 8.99805 V 67.845703 c 0.19045,0.04761 0.49922,0.09497 0.92773,0.142578 l 1.42969,0.142578 h 1.35742 0.92773 c 2.04735,0 4.02324,-0.30877 5.92774,-0.927734 1.95212,-0.618964 3.66659,-1.619234 5.14258,-3 1.47599,-1.380766 2.64102,-3.165289 3.49804,-5.355469 0.90464,-2.19018 1.35743,-4.857568 1.35743,-8 0,-3.47572 -0.52284,-6.285167 -1.57032,-8.427734 -1.04747,-2.19018 -2.40582,-3.879997 -4.07226,-5.070313 -1.66644,-1.190315 -3.57033,-1.976521 -5.71289,-2.357421 -2.09496,-0.428514 -4.23756,-0.642579 -6.42774,-0.642579 z m 51.72461,0.714844 v 48.564453 c 1.14271,0.571352 2.76052,1.09614 4.85547,1.572266 2.14257,0.476126 4.47653,0.71289 7,0.71289 4.61842,0 8.25948,-1.570458 10.92578,-4.71289 2.66631,-3.190045 4,-8.164791 4,-14.925781 0,-6.237252 -0.95292,-10.761169 -2.85742,-13.570313 -1.85689,-2.809144 -4.47497,-4.214844 -7.85547,-4.214844 -3.19004,0 -5.64141,1.047624 -7.35547,3.142578 h -0.21484 V 35.064453 Z m -50.86719,7.285156 c 0.99987,0 1.95279,0.142059 2.85743,0.427735 0.90464,0.285675 1.68889,0.761158 2.35547,1.427734 0.71418,0.618964 1.26167,1.477176 1.64257,2.572266 0.42852,1.09509 0.64258,2.428784 0.64258,4 0,1.856891 -0.21406,3.402697 -0.64258,4.640625 -0.42851,1.190315 -1.02335,2.143233 -1.78515,2.857422 -0.71419,0.666576 -1.54775,1.142058 -2.5,1.427734 -0.95225,0.285676 -1.95057,0.429687 -2.99805,0.429687 -0.28568,10e-7 -0.83316,-0.02465 -1.64258,-0.07227 -0.7618,-0.09522 -1.28659,-0.189931 -1.57226,-0.285156 v -17.06836 c 0.95225,-0.238063 2.16658,-0.357422 3.64257,-0.357422 z m 20.31836,6.998047 v 23.210938 c 0,2.666306 0.21407,4.880911 0.64258,6.642578 0.42852,1.714054 1.04606,3.070448 1.85547,4.070312 0.80942,0.999865 1.78699,1.691365 2.92969,2.072266 1.1427,0.428513 2.45174,0.642578 3.92773,0.642578 2.28541,0 4.18929,-0.547488 5.71289,-1.642578 1.57122,-1.09509 2.81021,-2.476137 3.71485,-4.142578 h 0.21289 l 1.5,4.857422 h 6.42773 c -0.3809,-1.523604 -0.64232,-3.215374 -0.78515,-5.072266 -0.14284,-1.904504 -0.21485,-3.833039 -0.21485,-5.785156 V 49.347656 h -8.49804 v 23.853516 c -0.38091,1.380765 -1.02505,2.572401 -1.92969,3.572266 -0.90464,0.952252 -2.02232,1.427734 -3.35547,1.427734 -1.38077,0 -2.33368,-0.547488 -2.85742,-1.642578 -0.52374,-1.09509 -0.78516,-3.046325 -0.78516,-5.855469 V 49.347656 Z m 43.83204,6.927735 c 1.61882,0 2.80851,0.858211 3.57031,2.572265 0.7618,1.666441 1.14258,4.307223 1.14258,7.925782 0,4.094684 -0.47549,7.023489 -1.42774,8.785156 -0.95225,1.714054 -2.3333,2.572265 -4.14258,2.572265 -1.61882,0 -2.92787,-0.26337 -3.92773,-0.787109 V 59.990234 c 0.80941,-2.475855 2.40453,-3.714843 4.78516,-3.714843 z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:8.52205467px;line-height:2.53632545px;font-family:'PT Sans Narrow';-inkscape-font-specification:'PT Sans Narrow Bold Condensed';letter-spacing:0.22319667px;word-spacing:2.60024095px;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:url(#linearGradient4526);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.24196777px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.