Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
ae81575386
|
+2
-54
@@ -1,62 +1,10 @@
|
|||||||
## [1.0.0-12] - 2023-01-28
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Added Arabic and Portuguese translations (Barodane, Antonio Chagas)
|
|
||||||
- Add QRCode view for sharing your pubkey (ericholguin)
|
|
||||||
- Added nostr: uri handling (William Casarin)
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Remove markdown link support from posts (Joel Klabo)
|
|
||||||
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Fixed crash on some SVG profile pictures (OlegAba)
|
|
||||||
- Localization fixes
|
|
||||||
- Don't allow blocking yourself (Terry)
|
|
||||||
- Hide muted users from global (William Casarin)
|
|
||||||
- Fixed profiles sometimes not loading from other clients (William Casarin)
|
|
||||||
- Fixed bug where `spam` was always the report type (William Casarin)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[1.0.0-12]: https://github.com/damus-io/damus/releases/tag/v1.0.0-12
|
|
||||||
|
|
||||||
## [1.0.0-11] - 2023-01-25
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Reposts view (Terry Yiu)
|
|
||||||
- Translations for it_IT, it_CH, fr_FR, de_DE, de_AT and lv_LV (Nicolò Carcagnì, Solobalbo, Gregor, Peter Gerstbach, SYX)
|
|
||||||
- Added ability to block users (William Casarin)
|
|
||||||
- Added a way to report content (William Casarin)
|
|
||||||
- Stretchable profile cover header (Swift)
|
|
||||||
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Bump pfp/banner animated fize size limit to 5MiB/20MiB (William Casarin)
|
|
||||||
- Updated default boostrap relays (Ricardo Arturo Cabral Mejía)
|
|
||||||
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- allow ws:// relays again (Steven Briscoe)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[1.0.0-11]: https://github.com/damus-io/damus/releases/tag/v1.0.0-11
|
|
||||||
|
|
||||||
|
|
||||||
## [1.0.0-8] - 2023-01-22
|
## [1.0.0-8] - 2023-01-22
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Show website on profiles (William Casarin)
|
- Show website on profiles (William Casarin)
|
||||||
- Add the ability to choose participants when replying (Joel Klabo)
|
- Add the ability to choose participants when replying (Joel Klabo)
|
||||||
- Translations for de_AT, de_DE, tr_TR, fr_FR (Gregor, Peter Gerstbach, Taylan Benli, Solobalbo)
|
- Translations for de_AT, de_DE, tr_TR, fr_FR (William Casarin)
|
||||||
- Add DM Message Requests (William Casarin)
|
- Add DM Message Requests (William Casarin)
|
||||||
|
|
||||||
|
|
||||||
@@ -76,7 +24,7 @@
|
|||||||
|
|
||||||
- Drastically improved image viewer (OlegAba)
|
- Drastically improved image viewer (OlegAba)
|
||||||
- Added pinch to zoom on images (Swift)
|
- Added pinch to zoom on images (Swift)
|
||||||
- Add Latin American Spanish translations (Nicolás Valencia)
|
- Add Latin American Spanish translations (William Casarin)
|
||||||
- Added SVG profile picture support (OlegAba)
|
- Added SVG profile picture support (OlegAba)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -91,39 +91,13 @@ damus implements the following [Nostr Implementation Possibilities][nips]
|
|||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
Contributors welcome!
|
Contributors welcome! [Email patches][git-send-email] to jb55@jb55.com are preferred, but I accept PRs on github as well.
|
||||||
|
|
||||||
### Code
|
|
||||||
|
|
||||||
[Email patches][git-send-email] to jb55@jb55.com are preferred, but I accept PRs on GitHub as well.
|
|
||||||
|
|
||||||
[git-send-email]: http://git-send-email.io
|
[git-send-email]: http://git-send-email.io
|
||||||
|
|
||||||
### Translations
|
## git log bot
|
||||||
|
|
||||||
Translators welcome! Join the [Transifex][transifex] project.
|
npub1fjtdwclt9lspjy8huu3qklr7eklp5uq90u6yh8mec290pqxraccqlufnas
|
||||||
|
|
||||||
All user-facing strings must have a comment in order to provide context to translators. If a SwiftUI component has a `comment` parameter, use that. Otherwise, wrap your string with `NSLocalizedString` with the `comment` field populated.
|
|
||||||
|
|
||||||
[transifex]: https://explore.transifex.com/damus/damus-ios/
|
|
||||||
|
|
||||||
#### Export Source Translations
|
|
||||||
|
|
||||||
If user-facing strings have been added or changed, please export them for translation as part of your pull request or commit by running:
|
|
||||||
|
|
||||||
```zsh
|
|
||||||
./devtools/export-source-translation.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
This command will export source translations to `translations/en-US.xcloc/Localized Contents/en-US.xliff`, which the Transifex integration will read from the `master` branch and allow translators to translate those strings.
|
|
||||||
|
|
||||||
#### Import Translations
|
|
||||||
|
|
||||||
Once 100% of strings have been translated for a given locale, Transifex will open up a pull request with the `translations/<locale>.xliff` file changed. Currently, it must be manually imported into the project before merging the pull request by running:
|
|
||||||
|
|
||||||
```zsh
|
|
||||||
./devtools/import-translation.sh <locale_code_in_snake_case>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Awards
|
### Awards
|
||||||
|
|
||||||
@@ -133,7 +107,3 @@ First contributors:
|
|||||||
|
|
||||||
1. @randymcmillan
|
1. @randymcmillan
|
||||||
2. @jcarucci27
|
2. @jcarucci27
|
||||||
|
|
||||||
### git log bot
|
|
||||||
|
|
||||||
npub1fjtdwclt9lspjy8huu3qklr7eklp5uq90u6yh8mec290pqxraccqlufnas
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+29
-217
@@ -45,15 +45,9 @@ Abbreviated version of a nostr public key.</note>
|
|||||||
<source>%@ %@</source>
|
<source>%@ %@</source>
|
||||||
<target>%@ %@</target>
|
<target>%@ %@</target>
|
||||||
|
|
||||||
<note>Sentence composed of 2 variables to describe how many tip payments there are on a post. In source English, the first variable is the number of tip payments, and the second variable is 'Tip' or 'Tips'.
|
<note>Sentence composed of 2 variables to describe how many reposts. In source English, the first variable is the number of reposts, and the second variable is 'Repost' or 'Reposts'.
|
||||||
Sentence composed of 2 variables to describe how many profiles a user is following. In source English, the first variable is the number of profiles being followed, and the second variable is 'Following'.</note>
|
Sentence composed of 2 variables to describe how many profiles a user is following. In source English, the first variable is the number of profiles being followed, and the second variable is 'Following'.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%@ has been blocked" xml:space="preserve">
|
|
||||||
<source>%@ has been blocked</source>
|
|
||||||
<target>%@ wurde blockiert</target>
|
|
||||||
|
|
||||||
<note>Alert message that informs a user was blocked.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="%@. Creating an account doesn't require a phone number, email or name. Get started right away with zero friction." xml:space="preserve">
|
<trans-unit id="%@. Creating an account doesn't require a phone number, email or name. Get started right away with zero friction." xml:space="preserve">
|
||||||
<source>%@. Creating an account doesn't require a phone number, email or name. Get started right away with zero friction.</source>
|
<source>%@. Creating an account doesn't require a phone number, email or name. Get started right away with zero friction.</source>
|
||||||
<target>%@. Ein Konto zu erstellen benötigt keine Telefonnummer, Emailadresse oder Namen. Fang jetzt gleich ganz reibungslos an.</target>
|
<target>%@. Ein Konto zu erstellen benötigt keine Telefonnummer, Emailadresse oder Namen. Fang jetzt gleich ganz reibungslos an.</target>
|
||||||
@@ -76,7 +70,7 @@ Sentence composed of 2 variables to describe how many profiles a user is followi
|
|||||||
<source>%lld</source>
|
<source>%lld</source>
|
||||||
<target>%lld</target>
|
<target>%lld</target>
|
||||||
|
|
||||||
<note>Number of tip payments on a post.
|
<note>Number of reposts.
|
||||||
Number of profiles a user is following.</note>
|
Number of profiles a user is following.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%lld/%lld" xml:space="preserve">
|
<trans-unit id="%lld/%lld" xml:space="preserve">
|
||||||
@@ -99,7 +93,7 @@ Number of profiles a user is following.</note>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="(Profile.displayName(profile: profile, pubkey: whos))'s Followers" xml:space="preserve">
|
<trans-unit id="(Profile.displayName(profile: profile, pubkey: whos))'s Followers" xml:space="preserve">
|
||||||
<source>(Profile.displayName(profile: profile, pubkey: whos))'s Followers</source>
|
<source>(Profile.displayName(profile: profile, pubkey: whos))'s Followers</source>
|
||||||
<target>(Profile.displayName(profile: profile, pubkey: whos)) Gefolgte</target>
|
<target>(Profile.displayName(profile: profile, pubkey: whos)) Follower</target>
|
||||||
|
|
||||||
<note>Navigation bar title for view that shows who is following a user.</note>
|
<note>Navigation bar title for view that shows who is following a user.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@@ -139,24 +133,12 @@ Number of profiles a user is following.</note>
|
|||||||
|
|
||||||
<note>Placeholder text for About Me description.</note>
|
<note>Placeholder text for About Me description.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Accept" xml:space="preserve">
|
|
||||||
<source>Accept</source>
|
|
||||||
<target>Zustimmen</target>
|
|
||||||
|
|
||||||
<note>Button to accept the end user license agreement before being allowed into the app.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Account ID" xml:space="preserve">
|
<trans-unit id="Account ID" xml:space="preserve">
|
||||||
<source>Account ID</source>
|
<source>Account ID</source>
|
||||||
<target>Konto ID</target>
|
<target>Konto ID</target>
|
||||||
|
|
||||||
<note>Label to indicate the public ID of the account.</note>
|
<note>Label to indicate the public ID of the account.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Actions" xml:space="preserve">
|
|
||||||
<source>Actions</source>
|
|
||||||
<target>Aktionen</target>
|
|
||||||
|
|
||||||
<note>Title for confirmation dialog to either share, report, or block a profile.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Add" xml:space="preserve">
|
<trans-unit id="Add" xml:space="preserve">
|
||||||
<source>Add</source>
|
<source>Add</source>
|
||||||
<target>Hinzufügen</target>
|
<target>Hinzufügen</target>
|
||||||
@@ -170,12 +152,6 @@ Number of profiles a user is following.</note>
|
|||||||
|
|
||||||
<note>Label for section for adding a relay server.</note>
|
<note>Label for section for adding a relay server.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Add all" xml:space="preserve">
|
|
||||||
<source>Add all</source>
|
|
||||||
<target>Alle hinzufügen</target>
|
|
||||||
|
|
||||||
<note>Button label to re-add all original participants as profiles to reply to in a note</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Any" xml:space="preserve">
|
<trans-unit id="Any" xml:space="preserve">
|
||||||
<source>Any</source>
|
<source>Any</source>
|
||||||
<target>beliebig</target>
|
<target>beliebig</target>
|
||||||
@@ -218,38 +194,6 @@ Number of profiles a user is following.</note>
|
|||||||
|
|
||||||
<note>Dropdown option label for Lightning wallet, Blixt Wallet</note>
|
<note>Dropdown option label for Lightning wallet, Blixt Wallet</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Block" xml:space="preserve">
|
|
||||||
<source>Block</source>
|
|
||||||
<target>Blockieren</target>
|
|
||||||
|
|
||||||
<note>Alert button to block a user.
|
|
||||||
Button to block a profile.
|
|
||||||
Context menu option for blocking users.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Block %@?" xml:space="preserve">
|
|
||||||
<source>Block %@?</source>
|
|
||||||
<target>%@ blockieren?</target>
|
|
||||||
|
|
||||||
<note>Alert message prompt to ask if a user should be blocked.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Block User" xml:space="preserve">
|
|
||||||
<source>Block User</source>
|
|
||||||
<target>Benutzer blockieren</target>
|
|
||||||
|
|
||||||
<note>Title of alert for blocking a user.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Blocked" xml:space="preserve">
|
|
||||||
<source>Blocked</source>
|
|
||||||
<target>Blockiert</target>
|
|
||||||
|
|
||||||
<note>Sidebar menu label for Profile view.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Blocked Users" xml:space="preserve">
|
|
||||||
<source>Blocked Users</source>
|
|
||||||
<target>Blockierte Benutzer</target>
|
|
||||||
|
|
||||||
<note>Navigation title of view to see list of blocked users.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Blue Wallet" xml:space="preserve">
|
<trans-unit id="Blue Wallet" xml:space="preserve">
|
||||||
<source>Blue Wallet</source>
|
<source>Blue Wallet</source>
|
||||||
<target>Blue Wallet</target>
|
<target>Blue Wallet</target>
|
||||||
@@ -272,9 +216,7 @@ Number of profiles a user is following.</note>
|
|||||||
<source>Cancel</source>
|
<source>Cancel</source>
|
||||||
<target>Abbrechen</target>
|
<target>Abbrechen</target>
|
||||||
|
|
||||||
<note>Alert button to cancel out of alert for blocking a user.
|
<note>Button to cancel out of posting a note.
|
||||||
Button to cancel out of alert that creates a new mutelist.
|
|
||||||
Button to cancel out of posting a note.
|
|
||||||
Button to cancel out of reposting a post.
|
Button to cancel out of reposting a post.
|
||||||
Button to cancel out of view adding user inputted relay.
|
Button to cancel out of view adding user inputted relay.
|
||||||
Cancel out of logging out the user.</note>
|
Cancel out of logging out the user.</note>
|
||||||
@@ -352,21 +294,15 @@ Number of profiles a user is following.</note>
|
|||||||
|
|
||||||
<note>Context menu option for copying the JSON text from the note.</note>
|
<note>Context menu option for copying the JSON text from the note.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Copy Report ID" xml:space="preserve">
|
|
||||||
<source>Copy Report ID</source>
|
|
||||||
<target>Meldungs-ID kopieren</target>
|
|
||||||
|
|
||||||
<note>Button to copy report ID.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Copy Text" xml:space="preserve">
|
<trans-unit id="Copy Text" xml:space="preserve">
|
||||||
<source>Copy Text</source>
|
<source>Copy Text</source>
|
||||||
<target>Text kopieren</target>
|
<target>Text kopieren</target>
|
||||||
|
|
||||||
<note>Context menu option for copying the text from an note.</note>
|
<note>Context menu option for copying the text from an note.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Copy User Pubkey" xml:space="preserve">
|
<trans-unit id="Copy User ID" xml:space="preserve">
|
||||||
<source>Copy User Pubkey</source>
|
<source>Copy User ID</source>
|
||||||
<target>Öffentlichen Schlüssel des Benutzers kopieren</target>
|
<target>Benutzer ID kopieren</target>
|
||||||
|
|
||||||
<note>Context menu option for copying the ID of the user who created the note.</note>
|
<note>Context menu option for copying the ID of the user who created the note.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@@ -376,12 +312,6 @@ Number of profiles a user is following.</note>
|
|||||||
|
|
||||||
<note>Title of section for copying a Lightning invoice identifier.</note>
|
<note>Title of section for copying a Lightning invoice identifier.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Could not find user to block..." xml:space="preserve">
|
|
||||||
<source>Could not find user to block...</source>
|
|
||||||
<target>Der zu blockierende Benutzer konnte nicht gefunden werden...</target>
|
|
||||||
|
|
||||||
<note>Alert message to indicate that the blocked user could not be found.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Create" xml:space="preserve">
|
<trans-unit id="Create" xml:space="preserve">
|
||||||
<source>Create</source>
|
<source>Create</source>
|
||||||
<target>Erstellen</target>
|
<target>Erstellen</target>
|
||||||
@@ -394,30 +324,29 @@ Number of profiles a user is following.</note>
|
|||||||
|
|
||||||
<note>Button to create an account.</note>
|
<note>Button to create an account.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Create new mutelist" xml:space="preserve">
|
|
||||||
<source>Create new mutelist</source>
|
|
||||||
<target>Neue Stummschaltungsliste</target>
|
|
||||||
|
|
||||||
<note>Title of alert prompting the user to create a new mutelist.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Creator(s) of Bitcoin. Absolute legend." xml:space="preserve">
|
<trans-unit id="Creator(s) of Bitcoin. Absolute legend." xml:space="preserve">
|
||||||
<source>Creator(s) of Bitcoin. Absolute legend.</source>
|
<source>Creator(s) of Bitcoin. Absolute legend.</source>
|
||||||
<target>Erfinder von Bitcoin. Absolute Legende(n).</target>
|
<target>Erfinder von Bitcoin. Absolute Legende(n).</target>
|
||||||
|
|
||||||
<note>Example description about Bitcoin creator(s), Satoshi Nakamoto.</note>
|
<note>Example description about Bitcoin creator(s), Satoshi Nakamoto.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="DM" xml:space="preserve">
|
||||||
|
<source>DM</source>
|
||||||
|
<target>PN</target>
|
||||||
|
|
||||||
|
<note>Navigation title for DM view, which is the English abbreviation for Direct Message.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="DM Type" xml:space="preserve">
|
<trans-unit id="DM Type" xml:space="preserve">
|
||||||
<source>DM Type</source>
|
<source>DM Type</source>
|
||||||
<target>PN Typ</target>
|
<target>PN Typ</target>
|
||||||
|
|
||||||
<note>DM selector for seeing either DMs or message requests, which are messages that have not been responded to yet. DM is the English abbreviation for Direct Message.</note>
|
<note>DM selector for seeing either DMs or message requests, which are messages that have not been responded to yet.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="DMs" xml:space="preserve">
|
<trans-unit id="DMs" xml:space="preserve">
|
||||||
<source>DMs</source>
|
<source>DMs</source>
|
||||||
<target>PNs</target>
|
<target>PNs</target>
|
||||||
|
|
||||||
<note>Navigation title for DMs view, where DM is the English abbreviation for Direct Message.
|
<note>No comment provided by engineer.</note>
|
||||||
Navigation title for view of DMs, where DM is an English abbreviation for Direct Message.</note>
|
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Damus" xml:space="preserve">
|
<trans-unit id="Damus" xml:space="preserve">
|
||||||
<source>Damus</source>
|
<source>Damus</source>
|
||||||
@@ -435,8 +364,7 @@ Number of profiles a user is following.</note>
|
|||||||
<source>Delete</source>
|
<source>Delete</source>
|
||||||
<target>Löschen</target>
|
<target>Löschen</target>
|
||||||
|
|
||||||
<note>Button to delete a relay server that the user connects to.
|
<note>Button to delete a relay server that the user connects to.</note>
|
||||||
Button to remove a user from their blocklist.</note>
|
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Dismiss" xml:space="preserve">
|
<trans-unit id="Dismiss" xml:space="preserve">
|
||||||
<source>Dismiss</source>
|
<source>Dismiss</source>
|
||||||
@@ -456,12 +384,6 @@ Number of profiles a user is following.</note>
|
|||||||
|
|
||||||
<note>Button to dismiss wallet selection view for paying Lightning invoice.</note>
|
<note>Button to dismiss wallet selection view for paying Lightning invoice.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="EULA" xml:space="preserve">
|
|
||||||
<source>EULA</source>
|
|
||||||
<target>Endbenutzer-Lizenzvereinbarung</target>
|
|
||||||
|
|
||||||
<note>Label indicating that the below text is the EULA, an acronym for End User License Agreement.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Earn Money" xml:space="preserve">
|
<trans-unit id="Earn Money" xml:space="preserve">
|
||||||
<source>Earn Money</source>
|
<source>Earn Money</source>
|
||||||
<target>Verdiene Geld</target>
|
<target>Verdiene Geld</target>
|
||||||
@@ -474,18 +396,18 @@ Number of profiles a user is following.</note>
|
|||||||
|
|
||||||
<note>Button to edit user's profile.</note>
|
<note>Button to edit user's profile.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Edit participants" xml:space="preserve">
|
|
||||||
<source>Edit participants</source>
|
|
||||||
<target>Teilnehmer editieren</target>
|
|
||||||
|
|
||||||
<note>Text indicating that the view is used for editing which participants are replied to in a note.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Encrypted" xml:space="preserve">
|
<trans-unit id="Encrypted" xml:space="preserve">
|
||||||
<source>Encrypted</source>
|
<source>Encrypted</source>
|
||||||
<target>Verschlüsselt</target>
|
<target>Verschlüsselt</target>
|
||||||
|
|
||||||
<note>Heading indicating that this application keeps private messaging end-to-end encrypted.</note>
|
<note>Heading indicating that this application keeps private messaging end-to-end encrypted.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Encrypted DMs" xml:space="preserve">
|
||||||
|
<source>Encrypted DMs</source>
|
||||||
|
<target>Verschlüsselte PNs</target>
|
||||||
|
|
||||||
|
<note>Navigation title for view of encrypted DMs, where DM is an English abbreviation for Direct Message.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Enter your account key to login:" xml:space="preserve">
|
<trans-unit id="Enter your account key to login:" xml:space="preserve">
|
||||||
<source>Enter your account key to login:</source>
|
<source>Enter your account key to login:</source>
|
||||||
<target>Gib deinen Kontoschlüssel ein um dich anzumelden:</target>
|
<target>Gib deinen Kontoschlüssel ein um dich anzumelden:</target>
|
||||||
@@ -512,13 +434,13 @@ Number of profiles a user is following.</note>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Followers" xml:space="preserve">
|
<trans-unit id="Followers" xml:space="preserve">
|
||||||
<source>Followers</source>
|
<source>Followers</source>
|
||||||
<target>Gefolgte:r</target>
|
<target>Follower</target>
|
||||||
|
|
||||||
<note>Label describing followers of a user.</note>
|
<note>Label describing followers of a user.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Following" xml:space="preserve">
|
<trans-unit id="Following" xml:space="preserve">
|
||||||
<source>Following</source>
|
<source>Following</source>
|
||||||
<target>Gefolgt</target>
|
<target>Folgt</target>
|
||||||
|
|
||||||
<note>Text to indicate that the button next to it is in a state that indicates that it is in the process of following a profile.
|
<note>Text to indicate that the button next to it is in a state that indicates that it is in the process of following a profile.
|
||||||
Part of a larger sentence to describe how many profiles a user is following.</note>
|
Part of a larger sentence to describe how many profiles a user is following.</note>
|
||||||
@@ -537,7 +459,7 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Global" xml:space="preserve">
|
<trans-unit id="Global" xml:space="preserve">
|
||||||
<source>Global</source>
|
<source>Global</source>
|
||||||
<target>Allgemein</target>
|
<target>Weltweit</target>
|
||||||
|
|
||||||
<note>Navigation bar title for Global view where posts from all connected relay servers appear.</note>
|
<note>Navigation bar title for Global view where posts from all connected relay servers appear.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@@ -559,24 +481,12 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
|
|
||||||
<note>Navigation bar title for Home view where posts and replies appear from those who the user is following.</note>
|
<note>Navigation bar title for Home view where posts and replies appear from those who the user is following.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Illegal content" xml:space="preserve">
|
|
||||||
<source>Illegal content</source>
|
|
||||||
<target>Illegaler Inhalt</target>
|
|
||||||
|
|
||||||
<note>Button for user to report that the account or content has illegal content.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Invalid key" xml:space="preserve">
|
<trans-unit id="Invalid key" xml:space="preserve">
|
||||||
<source>Invalid key</source>
|
<source>Invalid key</source>
|
||||||
<target>Ungültiger Schlüssel</target>
|
<target>Ungültiger Schlüssel</target>
|
||||||
|
|
||||||
<note>Error message indicating that an invalid account key was entered for login.</note>
|
<note>Error message indicating that an invalid account key was entered for login.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="It's spam" xml:space="preserve">
|
|
||||||
<source>It's spam</source>
|
|
||||||
<target>Es ist Spam</target>
|
|
||||||
|
|
||||||
<note>Button for user to report that the account or content has spam.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="LNLink" xml:space="preserve">
|
<trans-unit id="LNLink" xml:space="preserve">
|
||||||
<source>LNLink</source>
|
<source>LNLink</source>
|
||||||
<target>LNLink</target>
|
<target>LNLink</target>
|
||||||
@@ -646,12 +556,6 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
|
|
||||||
<note>Label for NIP-05 Verification section of user profile form.</note>
|
<note>Label for NIP-05 Verification section of user profile form.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="No block list found, create a new one? This will overwrite any previous block lists." xml:space="preserve">
|
|
||||||
<source>No block list found, create a new one? This will overwrite any previous block lists.</source>
|
|
||||||
<target>Es wurde keine Blockier-Liste gefunden, soll eine neue erzeugt werden? Dies wird eine frühere Blockier-Liste überschreiben.</target>
|
|
||||||
|
|
||||||
<note>Alert message prompt that asks if the user wants to create a new block list, overwriting previous block lists.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Nothing to see here. Check back later!" xml:space="preserve">
|
<trans-unit id="Nothing to see here. Check back later!" xml:space="preserve">
|
||||||
<source>Nothing to see here. Check back later!</source>
|
<source>Nothing to see here. Check back later!</source>
|
||||||
<target>Hier gibt es nichts zu sehen. Komm später wieder vorbei!</target>
|
<target>Hier gibt es nichts zu sehen. Komm später wieder vorbei!</target>
|
||||||
@@ -664,12 +568,6 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
|
|
||||||
<note>Navigation title for notifications.</note>
|
<note>Navigation title for notifications.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Nudity or explicit content" xml:space="preserve">
|
|
||||||
<source>Nudity or explicit content</source>
|
|
||||||
<target>Nacktheit oder anstößige Inhalte</target>
|
|
||||||
|
|
||||||
<note>Button for user to report that the account or content has nudity or explicit content.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Pay" xml:space="preserve">
|
<trans-unit id="Pay" xml:space="preserve">
|
||||||
<source>Pay</source>
|
<source>Pay</source>
|
||||||
<target>Bezahlen</target>
|
<target>Bezahlen</target>
|
||||||
@@ -766,12 +664,6 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
|
|
||||||
<note>Section title for recommend relay servers that could be added as part of configuration</note>
|
<note>Section title for recommend relay servers that could be added as part of configuration</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Reject" xml:space="preserve">
|
|
||||||
<source>Reject</source>
|
|
||||||
<target>Ablehnen</target>
|
|
||||||
|
|
||||||
<note>Button to reject the end user license agreement, which disallows the user from being let into the app.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Relay" xml:space="preserve">
|
<trans-unit id="Relay" xml:space="preserve">
|
||||||
<source>Relay</source>
|
<source>Relay</source>
|
||||||
<target>Relay</target>
|
<target>Relay</target>
|
||||||
@@ -784,18 +676,6 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
|
|
||||||
<note>Sidebar menu label for Relay servers view</note>
|
<note>Sidebar menu label for Relay servers view</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Relays have been notified and clients will be able to use this information to filter content. Thank you!" xml:space="preserve">
|
|
||||||
<source>Relays have been notified and clients will be able to use this information to filter content. Thank you!</source>
|
|
||||||
<target>Relays wurden benachrichtigt und Anwendungen können diese Information nutzen, um Inhalte zu filtern. Vielen Dank!</target>
|
|
||||||
|
|
||||||
<note>Description of what was done as a result of sending a report to relay servers.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Remove all" xml:space="preserve">
|
|
||||||
<source>Remove all</source>
|
|
||||||
<target>Alle entfernen</target>
|
|
||||||
|
|
||||||
<note>Button label to remove all participants from a note reply.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Reply to self" xml:space="preserve">
|
<trans-unit id="Reply to self" xml:space="preserve">
|
||||||
<source>Reply to self</source>
|
<source>Reply to self</source>
|
||||||
<target>Antwort an sich selbst</target>
|
<target>Antwort an sich selbst</target>
|
||||||
@@ -814,25 +694,6 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
|
|
||||||
<note>Indicating that the user is replying to the following listed people.</note>
|
<note>Indicating that the user is replying to the following listed people.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Report" xml:space="preserve">
|
|
||||||
<source>Report</source>
|
|
||||||
<target>Melden</target>
|
|
||||||
|
|
||||||
<note>Button to report a profile.
|
|
||||||
Context menu option for reporting content.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Report ID:" xml:space="preserve">
|
|
||||||
<source>Report ID:</source>
|
|
||||||
<target>Meldungs-ID</target>
|
|
||||||
|
|
||||||
<note>Label indicating that the text underneath is the identifier of the report that was sent to relay servers.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Report sent!" xml:space="preserve">
|
|
||||||
<source>Report sent!</source>
|
|
||||||
<target>Meldung versandt!</target>
|
|
||||||
|
|
||||||
<note>Message indicating that a report was successfully sent to relay servers.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Repost" xml:space="preserve">
|
<trans-unit id="Repost" xml:space="preserve">
|
||||||
<source>Repost</source>
|
<source>Repost</source>
|
||||||
<target>Selbst teilen</target>
|
<target>Selbst teilen</target>
|
||||||
@@ -846,17 +707,11 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
|
|
||||||
<note>Text indicating that the post was reposted (i.e. re-shared).</note>
|
<note>Text indicating that the post was reposted (i.e. re-shared).</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Reposts" xml:space="preserve">
|
|
||||||
<source>Reposts</source>
|
|
||||||
<target>Geteilte Beiträge</target>
|
|
||||||
|
|
||||||
<note>Navigation bar title for Reposts view.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Requests" xml:space="preserve">
|
<trans-unit id="Requests" xml:space="preserve">
|
||||||
<source>Requests</source>
|
<source>Requests</source>
|
||||||
<target>Anfragen</target>
|
<target>Anfragen</target>
|
||||||
|
|
||||||
<note>Picker option for DM selector for seeing only message requests (DMs that someone else sent the user which has not been responded to yet). DM is the English abbreviation for Direct Message.</note>
|
<note>No comment provided by engineer.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Reset" xml:space="preserve">
|
<trans-unit id="Reset" xml:space="preserve">
|
||||||
<source>Reset</source>
|
<source>Reset</source>
|
||||||
@@ -941,8 +796,7 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
<source>Share</source>
|
<source>Share</source>
|
||||||
<target>Teilen</target>
|
<target>Teilen</target>
|
||||||
|
|
||||||
<note>Button to share an image.
|
<note>Button to share an image.</note>
|
||||||
Button to share the link to a profile.</note>
|
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Show" xml:space="preserve">
|
<trans-unit id="Show" xml:space="preserve">
|
||||||
<source>Show</source>
|
<source>Show</source>
|
||||||
@@ -968,18 +822,6 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
|
|
||||||
<note>Dropdown option label for Lightning wallet, Strike.</note>
|
<note>Dropdown option label for Lightning wallet, Strike.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Thanks!" xml:space="preserve">
|
|
||||||
<source>Thanks!</source>
|
|
||||||
<target>Danke!</target>
|
|
||||||
|
|
||||||
<note>Button to close out of alert that informs that the action to block a user was successful.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="They are impersonating someone" xml:space="preserve">
|
|
||||||
<source>They are impersonating someone</source>
|
|
||||||
<target>Sie gibt sich für jemand anderen aus</target>
|
|
||||||
|
|
||||||
<note>Button for user to report that the account is impersonating someone.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="This is a public key, you will not be able to make posts or interact in any way. This is used for viewing accounts from their perspective." xml:space="preserve">
|
<trans-unit id="This is a public key, you will not be able to make posts or interact in any way. This is used for viewing accounts from their perspective." xml:space="preserve">
|
||||||
<source>This is a public key, you will not be able to make posts or interact in any way. This is used for viewing accounts from their perspective.</source>
|
<source>This is a public key, you will not be able to make posts or interact in any way. This is used for viewing accounts from their perspective.</source>
|
||||||
<target>Dies ist ein öffentlicher Schlüssel, mit dem Sie keine Beiträge verfassen oder in irgendeiner Weise interagieren können. Er wird verwendet, um Konten aus deren Perspektive zu betrachten.</target>
|
<target>Dies ist ein öffentlicher Schlüssel, mit dem Sie keine Beiträge verfassen oder in irgendeiner Weise interagieren können. Er wird verwendet, um Konten aus deren Perspektive zu betrachten.</target>
|
||||||
@@ -1041,18 +883,6 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
|
|
||||||
<note>Text to indicate that the button next to it is in a state that will unfollow a profile when tapped.</note>
|
<note>Text to indicate that the button next to it is in a state that will unfollow a profile when tapped.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="User blocked" xml:space="preserve">
|
|
||||||
<source>User blocked</source>
|
|
||||||
<target>Benutzer blockiert</target>
|
|
||||||
|
|
||||||
<note>Alert message to indicate</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="User has been blocked" xml:space="preserve">
|
|
||||||
<source>User has been blocked</source>
|
|
||||||
<target>Der Benutzer wurde blockiert</target>
|
|
||||||
|
|
||||||
<note>Alert message that informs a user was blocked.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Username" xml:space="preserve">
|
<trans-unit id="Username" xml:space="preserve">
|
||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<target>Benutzername</target>
|
<target>Benutzername</target>
|
||||||
@@ -1096,30 +926,12 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
|
|
||||||
<note>Text to welcome user.</note>
|
<note>Text to welcome user.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="What do you want to report?" xml:space="preserve">
|
|
||||||
<source>What do you want to report?</source>
|
|
||||||
<target>Was möchtest du melden?</target>
|
|
||||||
|
|
||||||
<note>Header text to prompt user what issue they want to report.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Yes, Overwrite" xml:space="preserve">
|
|
||||||
<source>Yes, Overwrite</source>
|
|
||||||
<target>Ja, überschreiben</target>
|
|
||||||
|
|
||||||
<note>Text of button that confirms to overwrite the existing mutelist.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Your Name" xml:space="preserve">
|
<trans-unit id="Your Name" xml:space="preserve">
|
||||||
<source>Your Name</source>
|
<source>Your Name</source>
|
||||||
<target>Dein Name</target>
|
<target>Dein Name</target>
|
||||||
|
|
||||||
<note>Label for Your Name section of user profile form.</note>
|
<note>Label for Your Name section of user profile form.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your report will be sent to the relays you are connected to" xml:space="preserve">
|
|
||||||
<source>Your report will be sent to the relays you are connected to</source>
|
|
||||||
<target>Die Meldung wird an Relays versendet, mit denen du verbunden bist</target>
|
|
||||||
|
|
||||||
<note>Footer text to inform user what will happen when the report is submitted.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Zebedee" xml:space="preserve">
|
<trans-unit id="Zebedee" xml:space="preserve">
|
||||||
<source>Zebedee</source>
|
<source>Zebedee</source>
|
||||||
<target>Zebedee</target>
|
<target>Zebedee</target>
|
||||||
@@ -1279,13 +1091,13 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="/followers_count:dict/FOLLOWERS:dict/one:dict/:string" xml:space="preserve">
|
<trans-unit id="/followers_count:dict/FOLLOWERS:dict/one:dict/:string" xml:space="preserve">
|
||||||
<source>Follower</source>
|
<source>Follower</source>
|
||||||
<target>Gefolgte:r</target>
|
<target>Follower</target>
|
||||||
|
|
||||||
<note>Part of a larger sentence to describe how many people are following a user.</note>
|
<note>Part of a larger sentence to describe how many people are following a user.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="/followers_count:dict/FOLLOWERS:dict/other:dict/:string" xml:space="preserve">
|
<trans-unit id="/followers_count:dict/FOLLOWERS:dict/other:dict/:string" xml:space="preserve">
|
||||||
<source>Followers</source>
|
<source>Followers</source>
|
||||||
<target>Gefolgte</target>
|
<target>Follower</target>
|
||||||
|
|
||||||
<note>Part of a larger sentence to describe how many people are following a user.</note>
|
<note>Part of a larger sentence to describe how many people are following a user.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
+175
-182
File diff suppressed because it is too large
Load Diff
+8
-220
@@ -41,14 +41,9 @@ Abbreviated version of a nostr public key.</note>
|
|||||||
<trans-unit id="%@ %@" xml:space="preserve">
|
<trans-unit id="%@ %@" xml:space="preserve">
|
||||||
<source>%@ %@</source>
|
<source>%@ %@</source>
|
||||||
<target>%@ %@</target>
|
<target>%@ %@</target>
|
||||||
<note>Sentence composed of 2 variables to describe how many tip payments there are on a post. In source English, the first variable is the number of tip payments, and the second variable is 'Tip' or 'Tips'.
|
<note>Sentence composed of 2 variables to describe how many reposts. In source English, the first variable is the number of reposts, and the second variable is 'Repost' or 'Reposts'.
|
||||||
Sentence composed of 2 variables to describe how many profiles a user is following. In source English, the first variable is the number of profiles being followed, and the second variable is 'Following'.</note>
|
Sentence composed of 2 variables to describe how many profiles a user is following. In source English, the first variable is the number of profiles being followed, and the second variable is 'Following'.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%@ has been blocked" xml:space="preserve">
|
|
||||||
<source>%@ has been blocked</source>
|
|
||||||
<target>%@ has been blocked</target>
|
|
||||||
<note>Alert message that informs a user was blocked.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="%@. Creating an account doesn't require a phone number, email or name. Get started right away with zero friction." xml:space="preserve">
|
<trans-unit id="%@. Creating an account doesn't require a phone number, email or name. Get started right away with zero friction." xml:space="preserve">
|
||||||
<source>%@. Creating an account doesn't require a phone number, email or name. Get started right away with zero friction.</source>
|
<source>%@. Creating an account doesn't require a phone number, email or name. Get started right away with zero friction.</source>
|
||||||
<target>%@. Creating an account doesn't require a phone number, email or name. Get started right away with zero friction.</target>
|
<target>%@. Creating an account doesn't require a phone number, email or name. Get started right away with zero friction.</target>
|
||||||
@@ -67,7 +62,7 @@ Sentence composed of 2 variables to describe how many profiles a user is followi
|
|||||||
<trans-unit id="%lld" xml:space="preserve">
|
<trans-unit id="%lld" xml:space="preserve">
|
||||||
<source>%lld</source>
|
<source>%lld</source>
|
||||||
<target>%lld</target>
|
<target>%lld</target>
|
||||||
<note>Number of tip payments on a post.
|
<note>Number of reposts.
|
||||||
Number of profiles a user is following.</note>
|
Number of profiles a user is following.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%lld/%lld" xml:space="preserve">
|
<trans-unit id="%lld/%lld" xml:space="preserve">
|
||||||
@@ -105,11 +100,6 @@ Number of profiles a user is following.</note>
|
|||||||
<target>@</target>
|
<target>@</target>
|
||||||
<note>Prefix character to username.</note>
|
<note>Prefix character to username.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="API Key (optional)" xml:space="preserve">
|
|
||||||
<source>API Key (optional)</source>
|
|
||||||
<target>API Key (optional)</target>
|
|
||||||
<note>Example URL to LibreTranslate server</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="About" xml:space="preserve">
|
<trans-unit id="About" xml:space="preserve">
|
||||||
<source>About</source>
|
<source>About</source>
|
||||||
<target>About</target>
|
<target>About</target>
|
||||||
@@ -125,21 +115,11 @@ Number of profiles a user is following.</note>
|
|||||||
<target>Absolute Boss</target>
|
<target>Absolute Boss</target>
|
||||||
<note>Placeholder text for About Me description.</note>
|
<note>Placeholder text for About Me description.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Accept" xml:space="preserve">
|
|
||||||
<source>Accept</source>
|
|
||||||
<target>Accept</target>
|
|
||||||
<note>Button to accept the end user license agreement before being allowed into the app.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Account ID" xml:space="preserve">
|
<trans-unit id="Account ID" xml:space="preserve">
|
||||||
<source>Account ID</source>
|
<source>Account ID</source>
|
||||||
<target>Account ID</target>
|
<target>Account ID</target>
|
||||||
<note>Label to indicate the public ID of the account.</note>
|
<note>Label to indicate the public ID of the account.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Actions" xml:space="preserve">
|
|
||||||
<source>Actions</source>
|
|
||||||
<target>Actions</target>
|
|
||||||
<note>Title for confirmation dialog to either share, report, or block a profile.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Add" xml:space="preserve">
|
<trans-unit id="Add" xml:space="preserve">
|
||||||
<source>Add</source>
|
<source>Add</source>
|
||||||
<target>Add</target>
|
<target>Add</target>
|
||||||
@@ -191,33 +171,6 @@ Number of profiles a user is following.</note>
|
|||||||
<target>Blixt Wallet</target>
|
<target>Blixt Wallet</target>
|
||||||
<note>Dropdown option label for Lightning wallet, Blixt Wallet</note>
|
<note>Dropdown option label for Lightning wallet, Blixt Wallet</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Block" xml:space="preserve">
|
|
||||||
<source>Block</source>
|
|
||||||
<target>Block</target>
|
|
||||||
<note>Alert button to block a user.
|
|
||||||
Button to block a profile.
|
|
||||||
Context menu option for blocking users.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Block %@?" xml:space="preserve">
|
|
||||||
<source>Block %@?</source>
|
|
||||||
<target>Block %@?</target>
|
|
||||||
<note>Alert message prompt to ask if a user should be blocked.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Block User" xml:space="preserve">
|
|
||||||
<source>Block User</source>
|
|
||||||
<target>Block User</target>
|
|
||||||
<note>Title of alert for blocking a user.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Blocked" xml:space="preserve">
|
|
||||||
<source>Blocked</source>
|
|
||||||
<target>Blocked</target>
|
|
||||||
<note>Sidebar menu label for Profile view.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Blocked Users" xml:space="preserve">
|
|
||||||
<source>Blocked Users</source>
|
|
||||||
<target>Blocked Users</target>
|
|
||||||
<note>Navigation title of view to see list of blocked users.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Blue Wallet" xml:space="preserve">
|
<trans-unit id="Blue Wallet" xml:space="preserve">
|
||||||
<source>Blue Wallet</source>
|
<source>Blue Wallet</source>
|
||||||
<target>Blue Wallet</target>
|
<target>Blue Wallet</target>
|
||||||
@@ -236,9 +189,7 @@ Number of profiles a user is following.</note>
|
|||||||
<trans-unit id="Cancel" xml:space="preserve">
|
<trans-unit id="Cancel" xml:space="preserve">
|
||||||
<source>Cancel</source>
|
<source>Cancel</source>
|
||||||
<target>Cancel</target>
|
<target>Cancel</target>
|
||||||
<note>Alert button to cancel out of alert for blocking a user.
|
<note>Button to cancel out of posting a note.
|
||||||
Button to cancel out of alert that creates a new mutelist.
|
|
||||||
Button to cancel out of posting a note.
|
|
||||||
Button to cancel out of reposting a post.
|
Button to cancel out of reposting a post.
|
||||||
Button to cancel out of view adding user inputted relay.
|
Button to cancel out of view adding user inputted relay.
|
||||||
Cancel out of logging out the user.</note>
|
Cancel out of logging out the user.</note>
|
||||||
@@ -304,19 +255,14 @@ Number of profiles a user is following.</note>
|
|||||||
<target>Copy Note JSON</target>
|
<target>Copy Note JSON</target>
|
||||||
<note>Context menu option for copying the JSON text from the note.</note>
|
<note>Context menu option for copying the JSON text from the note.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Copy Report ID" xml:space="preserve">
|
|
||||||
<source>Copy Report ID</source>
|
|
||||||
<target>Copy Report ID</target>
|
|
||||||
<note>Button to copy report ID.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Copy Text" xml:space="preserve">
|
<trans-unit id="Copy Text" xml:space="preserve">
|
||||||
<source>Copy Text</source>
|
<source>Copy Text</source>
|
||||||
<target>Copy Text</target>
|
<target>Copy Text</target>
|
||||||
<note>Context menu option for copying the text from an note.</note>
|
<note>Context menu option for copying the text from an note.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Copy User Pubkey" xml:space="preserve">
|
<trans-unit id="Copy User ID" xml:space="preserve">
|
||||||
<source>Copy User Pubkey</source>
|
<source>Copy User ID</source>
|
||||||
<target>Copy User Pubkey</target>
|
<target>Copy User ID</target>
|
||||||
<note>Context menu option for copying the ID of the user who created the note.</note>
|
<note>Context menu option for copying the ID of the user who created the note.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Copy invoice" xml:space="preserve">
|
<trans-unit id="Copy invoice" xml:space="preserve">
|
||||||
@@ -324,11 +270,6 @@ Number of profiles a user is following.</note>
|
|||||||
<target>Copy invoice</target>
|
<target>Copy invoice</target>
|
||||||
<note>Title of section for copying a Lightning invoice identifier.</note>
|
<note>Title of section for copying a Lightning invoice identifier.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Could not find user to block..." xml:space="preserve">
|
|
||||||
<source>Could not find user to block...</source>
|
|
||||||
<target>Could not find user to block...</target>
|
|
||||||
<note>Alert message to indicate that the blocked user could not be found.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Create" xml:space="preserve">
|
<trans-unit id="Create" xml:space="preserve">
|
||||||
<source>Create</source>
|
<source>Create</source>
|
||||||
<target>Create</target>
|
<target>Create</target>
|
||||||
@@ -339,21 +280,11 @@ Number of profiles a user is following.</note>
|
|||||||
<target>Create Account</target>
|
<target>Create Account</target>
|
||||||
<note>Button to create an account.</note>
|
<note>Button to create an account.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Create new mutelist" xml:space="preserve">
|
|
||||||
<source>Create new mutelist</source>
|
|
||||||
<target>Create new mutelist</target>
|
|
||||||
<note>Title of alert prompting the user to create a new mutelist.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Creator(s) of Bitcoin. Absolute legend." xml:space="preserve">
|
<trans-unit id="Creator(s) of Bitcoin. Absolute legend." xml:space="preserve">
|
||||||
<source>Creator(s) of Bitcoin. Absolute legend.</source>
|
<source>Creator(s) of Bitcoin. Absolute legend.</source>
|
||||||
<target>Creator(s) of Bitcoin. Absolute legend.</target>
|
<target>Creator(s) of Bitcoin. Absolute legend.</target>
|
||||||
<note>Example description about Bitcoin creator(s), Satoshi Nakamoto.</note>
|
<note>Example description about Bitcoin creator(s), Satoshi Nakamoto.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Custom" xml:space="preserve">
|
|
||||||
<source>Custom</source>
|
|
||||||
<target>Custom</target>
|
|
||||||
<note>Dropdown option for selecting a custom translation server.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="DM Type" xml:space="preserve">
|
<trans-unit id="DM Type" xml:space="preserve">
|
||||||
<source>DM Type</source>
|
<source>DM Type</source>
|
||||||
<target>DM Type</target>
|
<target>DM Type</target>
|
||||||
@@ -378,8 +309,7 @@ Number of profiles a user is following.</note>
|
|||||||
<trans-unit id="Delete" xml:space="preserve">
|
<trans-unit id="Delete" xml:space="preserve">
|
||||||
<source>Delete</source>
|
<source>Delete</source>
|
||||||
<target>Delete</target>
|
<target>Delete</target>
|
||||||
<note>Button to delete a relay server that the user connects to.
|
<note>Button to delete a relay server that the user connects to.</note>
|
||||||
Button to remove a user from their blocklist.</note>
|
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Dismiss" xml:space="preserve">
|
<trans-unit id="Dismiss" xml:space="preserve">
|
||||||
<source>Dismiss</source>
|
<source>Dismiss</source>
|
||||||
@@ -396,11 +326,6 @@ Number of profiles a user is following.</note>
|
|||||||
<target>Done</target>
|
<target>Done</target>
|
||||||
<note>Button to dismiss wallet selection view for paying Lightning invoice.</note>
|
<note>Button to dismiss wallet selection view for paying Lightning invoice.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="EULA" xml:space="preserve">
|
|
||||||
<source>EULA</source>
|
|
||||||
<target>EULA</target>
|
|
||||||
<note>Label indicating that the below text is the EULA, an acronym for End User License Agreement.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Earn Money" xml:space="preserve">
|
<trans-unit id="Earn Money" xml:space="preserve">
|
||||||
<source>Earn Money</source>
|
<source>Earn Money</source>
|
||||||
<target>Earn Money</target>
|
<target>Earn Money</target>
|
||||||
@@ -477,36 +402,16 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
<target>Goto profile %@</target>
|
<target>Goto profile %@</target>
|
||||||
<note>Navigation link to go to profile.</note>
|
<note>Navigation link to go to profile.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Hide" xml:space="preserve">
|
|
||||||
<source>Hide</source>
|
|
||||||
<target>Hide</target>
|
|
||||||
<note>No comment provided by engineer.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Hide API Key" xml:space="preserve">
|
|
||||||
<source>Hide API Key</source>
|
|
||||||
<target>Hide API Key</target>
|
|
||||||
<note>Button to hide the LibreTranslate server API key.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Home" xml:space="preserve">
|
<trans-unit id="Home" xml:space="preserve">
|
||||||
<source>Home</source>
|
<source>Home</source>
|
||||||
<target>Home</target>
|
<target>Home</target>
|
||||||
<note>Navigation bar title for Home view where posts and replies appear from those who the user is following.</note>
|
<note>Navigation bar title for Home view where posts and replies appear from those who the user is following.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Illegal content" xml:space="preserve">
|
|
||||||
<source>Illegal content</source>
|
|
||||||
<target>Illegal content</target>
|
|
||||||
<note>Button for user to report that the account or content has illegal content.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Invalid key" xml:space="preserve">
|
<trans-unit id="Invalid key" xml:space="preserve">
|
||||||
<source>Invalid key</source>
|
<source>Invalid key</source>
|
||||||
<target>Invalid key</target>
|
<target>Invalid key</target>
|
||||||
<note>Error message indicating that an invalid account key was entered for login.</note>
|
<note>Error message indicating that an invalid account key was entered for login.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="It's spam" xml:space="preserve">
|
|
||||||
<source>It's spam</source>
|
|
||||||
<target>It's spam</target>
|
|
||||||
<note>Button for user to report that the account or content has spam.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="LNLink" xml:space="preserve">
|
<trans-unit id="LNLink" xml:space="preserve">
|
||||||
<source>LNLink</source>
|
<source>LNLink</source>
|
||||||
<target>LNLink</target>
|
<target>LNLink</target>
|
||||||
@@ -522,11 +427,6 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
<target>Let's go!</target>
|
<target>Let's go!</target>
|
||||||
<note>Button to complete account creation and start using the app.</note>
|
<note>Button to complete account creation and start using the app.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="LibreTranslate Translations" xml:space="preserve">
|
|
||||||
<source>LibreTranslate Translations</source>
|
|
||||||
<target>LibreTranslate Translations</target>
|
|
||||||
<note>Section title for selecting the server that hosts the LibreTranslate machine translation API.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Lightning Address or LNURL" xml:space="preserve">
|
<trans-unit id="Lightning Address or LNURL" xml:space="preserve">
|
||||||
<source>Lightning Address or LNURL</source>
|
<source>Lightning Address or LNURL</source>
|
||||||
<target>Lightning Address or LNURL</target>
|
<target>Lightning Address or LNURL</target>
|
||||||
@@ -570,16 +470,6 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
<target>NIP-05 Verification</target>
|
<target>NIP-05 Verification</target>
|
||||||
<note>Label for NIP-05 Verification section of user profile form.</note>
|
<note>Label for NIP-05 Verification section of user profile form.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="No block list found, create a new one? This will overwrite any previous block lists." xml:space="preserve">
|
|
||||||
<source>No block list found, create a new one? This will overwrite any previous block lists.</source>
|
|
||||||
<target>No block list found, create a new one? This will overwrite any previous block lists.</target>
|
|
||||||
<note>Alert message prompt that asks if the user wants to create a new block list, overwriting previous block lists.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="None" xml:space="preserve">
|
|
||||||
<source>None</source>
|
|
||||||
<target>None</target>
|
|
||||||
<note>Dropdown option for selecting no translation server.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Nothing to see here. Check back later!" xml:space="preserve">
|
<trans-unit id="Nothing to see here. Check back later!" xml:space="preserve">
|
||||||
<source>Nothing to see here. Check back later!</source>
|
<source>Nothing to see here. Check back later!</source>
|
||||||
<target>Nothing to see here. Check back later!</target>
|
<target>Nothing to see here. Check back later!</target>
|
||||||
@@ -590,11 +480,6 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
<target>Notifications</target>
|
<target>Notifications</target>
|
||||||
<note>Navigation title for notifications.</note>
|
<note>Navigation title for notifications.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Nudity or explicit content" xml:space="preserve">
|
|
||||||
<source>Nudity or explicit content</source>
|
|
||||||
<target>Nudity or explicit content</target>
|
|
||||||
<note>Button for user to report that the account or content has nudity or explicit content.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Pay" xml:space="preserve">
|
<trans-unit id="Pay" xml:space="preserve">
|
||||||
<source>Pay</source>
|
<source>Pay</source>
|
||||||
<target>Pay</target>
|
<target>Pay</target>
|
||||||
@@ -615,11 +500,6 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
<target>Post</target>
|
<target>Post</target>
|
||||||
<note>Button to post a note.</note>
|
<note>Button to post a note.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Post from a user you've blocked" xml:space="preserve">
|
|
||||||
<source>Post from a user you've blocked</source>
|
|
||||||
<target>Post from a user you've blocked</target>
|
|
||||||
<note>No comment provided by engineer.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Posts" xml:space="preserve">
|
<trans-unit id="Posts" xml:space="preserve">
|
||||||
<source>Posts</source>
|
<source>Posts</source>
|
||||||
<target>Posts</target>
|
<target>Posts</target>
|
||||||
@@ -680,11 +560,6 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
<target>Recommended Relays</target>
|
<target>Recommended Relays</target>
|
||||||
<note>Section title for recommend relay servers that could be added as part of configuration</note>
|
<note>Section title for recommend relay servers that could be added as part of configuration</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Reject" xml:space="preserve">
|
|
||||||
<source>Reject</source>
|
|
||||||
<target>Reject</target>
|
|
||||||
<note>Button to reject the end user license agreement, which disallows the user from being let into the app.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Relay" xml:space="preserve">
|
<trans-unit id="Relay" xml:space="preserve">
|
||||||
<source>Relay</source>
|
<source>Relay</source>
|
||||||
<target>Relay</target>
|
<target>Relay</target>
|
||||||
@@ -695,11 +570,6 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
<target>Relays</target>
|
<target>Relays</target>
|
||||||
<note>Sidebar menu label for Relay servers view</note>
|
<note>Sidebar menu label for Relay servers view</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Relays have been notified and clients will be able to use this information to filter content. Thank you!" xml:space="preserve">
|
|
||||||
<source>Relays have been notified and clients will be able to use this information to filter content. Thank you!</source>
|
|
||||||
<target>Relays have been notified and clients will be able to use this information to filter content. Thank you!</target>
|
|
||||||
<note>Description of what was done as a result of sending a report to relay servers.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Remove all" xml:space="preserve">
|
<trans-unit id="Remove all" xml:space="preserve">
|
||||||
<source>Remove all</source>
|
<source>Remove all</source>
|
||||||
<target>Remove all</target>
|
<target>Remove all</target>
|
||||||
@@ -720,22 +590,6 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
<target>Replying to:</target>
|
<target>Replying to:</target>
|
||||||
<note>Indicating that the user is replying to the following listed people.</note>
|
<note>Indicating that the user is replying to the following listed people.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Report" xml:space="preserve">
|
|
||||||
<source>Report</source>
|
|
||||||
<target>Report</target>
|
|
||||||
<note>Button to report a profile.
|
|
||||||
Context menu option for reporting content.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Report ID:" xml:space="preserve">
|
|
||||||
<source>Report ID:</source>
|
|
||||||
<target>Report ID:</target>
|
|
||||||
<note>Label indicating that the text underneath is the identifier of the report that was sent to relay servers.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Report sent!" xml:space="preserve">
|
|
||||||
<source>Report sent!</source>
|
|
||||||
<target>Report sent!</target>
|
|
||||||
<note>Message indicating that a report was successfully sent to relay servers.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Repost" xml:space="preserve">
|
<trans-unit id="Repost" xml:space="preserve">
|
||||||
<source>Repost</source>
|
<source>Repost</source>
|
||||||
<target>Repost</target>
|
<target>Repost</target>
|
||||||
@@ -747,11 +601,6 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
<target>Reposted</target>
|
<target>Reposted</target>
|
||||||
<note>Text indicating that the post was reposted (i.e. re-shared).</note>
|
<note>Text indicating that the post was reposted (i.e. re-shared).</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Reposts" xml:space="preserve">
|
|
||||||
<source>Reposts</source>
|
|
||||||
<target>Reposts</target>
|
|
||||||
<note>Navigation bar title for Reposts view.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Requests" xml:space="preserve">
|
<trans-unit id="Requests" xml:space="preserve">
|
||||||
<source>Requests</source>
|
<source>Requests</source>
|
||||||
<target>Requests</target>
|
<target>Requests</target>
|
||||||
@@ -817,11 +666,6 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
<target>Send a message to start the conversation...</target>
|
<target>Send a message to start the conversation...</target>
|
||||||
<note>Text prompt for user to send a message to the other user.</note>
|
<note>Text prompt for user to send a message to the other user.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Server" xml:space="preserve">
|
|
||||||
<source>Server</source>
|
|
||||||
<target>Server</target>
|
|
||||||
<note>Prompt selection of LibreTranslate server to perform machine translations on notes</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Settings" xml:space="preserve">
|
<trans-unit id="Settings" xml:space="preserve">
|
||||||
<source>Settings</source>
|
<source>Settings</source>
|
||||||
<target>Settings</target>
|
<target>Settings</target>
|
||||||
@@ -831,19 +675,13 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
<trans-unit id="Share" xml:space="preserve">
|
<trans-unit id="Share" xml:space="preserve">
|
||||||
<source>Share</source>
|
<source>Share</source>
|
||||||
<target>Share</target>
|
<target>Share</target>
|
||||||
<note>Button to share an image.
|
<note>Button to share an image.</note>
|
||||||
Button to share the link to a profile.</note>
|
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Show" xml:space="preserve">
|
<trans-unit id="Show" xml:space="preserve">
|
||||||
<source>Show</source>
|
<source>Show</source>
|
||||||
<target>Show</target>
|
<target>Show</target>
|
||||||
<note>Toggle to show or hide user's secret account login key.</note>
|
<note>Toggle to show or hide user's secret account login key.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Show API Key" xml:space="preserve">
|
|
||||||
<source>Show API Key</source>
|
|
||||||
<target>Show API Key</target>
|
|
||||||
<note>Button to hide the LibreTranslate server API key.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Show wallet selector" xml:space="preserve">
|
<trans-unit id="Show wallet selector" xml:space="preserve">
|
||||||
<source>Show wallet selector</source>
|
<source>Show wallet selector</source>
|
||||||
<target>Show wallet selector</target>
|
<target>Show wallet selector</target>
|
||||||
@@ -859,16 +697,6 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
<target>Strike</target>
|
<target>Strike</target>
|
||||||
<note>Dropdown option label for Lightning wallet, Strike.</note>
|
<note>Dropdown option label for Lightning wallet, Strike.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Thanks!" xml:space="preserve">
|
|
||||||
<source>Thanks!</source>
|
|
||||||
<target>Thanks!</target>
|
|
||||||
<note>Button to close out of alert that informs that the action to block a user was successful.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="They are impersonating someone" xml:space="preserve">
|
|
||||||
<source>They are impersonating someone</source>
|
|
||||||
<target>They are impersonating someone</target>
|
|
||||||
<note>Button for user to report that the account is impersonating someone.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="This is a public key, you will not be able to make posts or interact in any way. This is used for viewing accounts from their perspective." xml:space="preserve">
|
<trans-unit id="This is a public key, you will not be able to make posts or interact in any way. This is used for viewing accounts from their perspective." xml:space="preserve">
|
||||||
<source>This is a public key, you will not be able to make posts or interact in any way. This is used for viewing accounts from their perspective.</source>
|
<source>This is a public key, you will not be able to make posts or interact in any way. This is used for viewing accounts from their perspective.</source>
|
||||||
<target>This is a public key, you will not be able to make posts or interact in any way. This is used for viewing accounts from their perspective.</target>
|
<target>This is a public key, you will not be able to make posts or interact in any way. This is used for viewing accounts from their perspective.</target>
|
||||||
@@ -895,26 +723,11 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
<note>Navigation bar title for note thread.
|
<note>Navigation bar title for note thread.
|
||||||
Navigation bar title for threaded event detail view.</note>
|
Navigation bar title for threaded event detail view.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Translate Note" xml:space="preserve">
|
|
||||||
<source>Translate Note</source>
|
|
||||||
<target>Translate Note</target>
|
|
||||||
<note>Button to translate note from different language.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Translated from (languageName!)" xml:space="preserve">
|
|
||||||
<source>Translated from (languageName!)</source>
|
|
||||||
<target>Translated from (languageName!)</target>
|
|
||||||
<note>Button to indicate that the note has been translated from a different language.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Type your post here..." xml:space="preserve">
|
<trans-unit id="Type your post here..." xml:space="preserve">
|
||||||
<source>Type your post here...</source>
|
<source>Type your post here...</source>
|
||||||
<target>Type your post here...</target>
|
<target>Type your post here...</target>
|
||||||
<note>Text box prompt to ask user to type their post.</note>
|
<note>Text box prompt to ask user to type their post.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="URL" xml:space="preserve">
|
|
||||||
<source>URL</source>
|
|
||||||
<target>URL</target>
|
|
||||||
<note>Example URL to LibreTranslate server</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Unfollow" xml:space="preserve">
|
<trans-unit id="Unfollow" xml:space="preserve">
|
||||||
<source>Unfollow</source>
|
<source>Unfollow</source>
|
||||||
<target>Unfollow</target>
|
<target>Unfollow</target>
|
||||||
@@ -935,16 +748,6 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
<target>Unfollows</target>
|
<target>Unfollows</target>
|
||||||
<note>Text to indicate that the button next to it is in a state that will unfollow a profile when tapped.</note>
|
<note>Text to indicate that the button next to it is in a state that will unfollow a profile when tapped.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="User blocked" xml:space="preserve">
|
|
||||||
<source>User blocked</source>
|
|
||||||
<target>User blocked</target>
|
|
||||||
<note>Alert message to indicate</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="User has been blocked" xml:space="preserve">
|
|
||||||
<source>User has been blocked</source>
|
|
||||||
<target>User has been blocked</target>
|
|
||||||
<note>Alert message that informs a user was blocked.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Username" xml:space="preserve">
|
<trans-unit id="Username" xml:space="preserve">
|
||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<target>Username</target>
|
<target>Username</target>
|
||||||
@@ -981,26 +784,11 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
<target>Welcome, %@!</target>
|
<target>Welcome, %@!</target>
|
||||||
<note>Text to welcome user.</note>
|
<note>Text to welcome user.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="What do you want to report?" xml:space="preserve">
|
|
||||||
<source>What do you want to report?</source>
|
|
||||||
<target>What do you want to report?</target>
|
|
||||||
<note>Header text to prompt user what issue they want to report.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Yes, Overwrite" xml:space="preserve">
|
|
||||||
<source>Yes, Overwrite</source>
|
|
||||||
<target>Yes, Overwrite</target>
|
|
||||||
<note>Text of button that confirms to overwrite the existing mutelist.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Your Name" xml:space="preserve">
|
<trans-unit id="Your Name" xml:space="preserve">
|
||||||
<source>Your Name</source>
|
<source>Your Name</source>
|
||||||
<target>Your Name</target>
|
<target>Your Name</target>
|
||||||
<note>Label for Your Name section of user profile form.</note>
|
<note>Label for Your Name section of user profile form.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Your report will be sent to the relays you are connected to" xml:space="preserve">
|
|
||||||
<source>Your report will be sent to the relays you are connected to</source>
|
|
||||||
<target>Your report will be sent to the relays you are connected to</target>
|
|
||||||
<note>Footer text to inform user what will happen when the report is submitted.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Zebedee" xml:space="preserve">
|
<trans-unit id="Zebedee" xml:space="preserve">
|
||||||
<source>Zebedee</source>
|
<source>Zebedee</source>
|
||||||
<target>Zebedee</target>
|
<target>Zebedee</target>
|
||||||
BIN
Binary file not shown.
+50
-69
@@ -17,8 +17,8 @@
|
|||||||
<note>Bundle name</note>
|
<note>Bundle name</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="NSPhotoLibraryAddUsageDescription" xml:space="preserve">
|
<trans-unit id="NSPhotoLibraryAddUsageDescription" xml:space="preserve">
|
||||||
<source>Granting Damus access to your photos allows you to save images.</source>
|
<source>"Granting Damus access to your photo library allows you to save photos.</source>
|
||||||
<target>Donner accès à Damus à vos photos vous permet d'enregistrer des images</target>
|
<target>"Accorder à Damus l'accès à votre galerie photos vous permet d'enregistrer des photos.</target>
|
||||||
|
|
||||||
<note>Privacy - Photo Library Additions Usage Description</note>
|
<note>Privacy - Photo Library Additions Usage Description</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@@ -75,7 +75,7 @@ Number of profiles a user is following.</note>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="%lld/%lld" xml:space="preserve">
|
<trans-unit id="%lld/%lld" xml:space="preserve">
|
||||||
<source>%lld/%lld</source>
|
<source>%lld/%lld</source>
|
||||||
<target>%lld/%lld</target>
|
<target>%lld/%lld<br data-mce-bogus="1"></target>
|
||||||
|
|
||||||
<note>Fraction of how many of the user's relay servers that are operational.</note>
|
<note>Fraction of how many of the user's relay servers that are operational.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@@ -93,13 +93,13 @@ Number of profiles a user is following.</note>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="(Profile.displayName(profile: profile, pubkey: whos))'s Followers" xml:space="preserve">
|
<trans-unit id="(Profile.displayName(profile: profile, pubkey: whos))'s Followers" xml:space="preserve">
|
||||||
<source>(Profile.displayName(profile: profile, pubkey: whos))'s Followers</source>
|
<source>(Profile.displayName(profile: profile, pubkey: whos))'s Followers</source>
|
||||||
<target>Abonnés de (Profile.displayName(profile: profile, pubkey: whos))</target>
|
<target>(Profile.displayName(profile: profile, pubkey: whos))'s Followers</target>
|
||||||
|
|
||||||
<note>Navigation bar title for view that shows who is following a user.</note>
|
<note>Navigation bar title for view that shows who is following a user.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="(who) following" xml:space="preserve">
|
<trans-unit id="(who) following" xml:space="preserve">
|
||||||
<source>(who) following</source>
|
<source>(who) following</source>
|
||||||
<target>(who) suit</target>
|
<target>(who) following</target>
|
||||||
|
|
||||||
<note>Navigation bar title for view that shows who a user is following.</note>
|
<note>Navigation bar title for view that shows who a user is following.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@@ -152,12 +152,6 @@ Number of profiles a user is following.</note>
|
|||||||
|
|
||||||
<note>Label for section for adding a relay server.</note>
|
<note>Label for section for adding a relay server.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Add all" xml:space="preserve">
|
|
||||||
<source>Add all</source>
|
|
||||||
<target>Tout ajouter</target>
|
|
||||||
|
|
||||||
<note>Button label to re-add all original participants as profiles to reply to in a note</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Any" xml:space="preserve">
|
<trans-unit id="Any" xml:space="preserve">
|
||||||
<source>Any</source>
|
<source>Any</source>
|
||||||
<target>N'importe Lequel</target>
|
<target>N'importe Lequel</target>
|
||||||
@@ -166,7 +160,7 @@ Number of profiles a user is following.</note>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Are you sure you want to repost this?" xml:space="preserve">
|
<trans-unit id="Are you sure you want to repost this?" xml:space="preserve">
|
||||||
<source>Are you sure you want to repost this?</source>
|
<source>Are you sure you want to repost this?</source>
|
||||||
<target>Êtes-vous sûr de vouloir republier ceci ?</target>
|
<target>Êtes-vous sûr de vouloir republier ceci ?</target>
|
||||||
|
|
||||||
<note>Alert message to ask if user wants to repost a post.</note>
|
<note>Alert message to ask if user wants to repost a post.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@@ -196,13 +190,13 @@ Number of profiles a user is following.</note>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Blixt Wallet" xml:space="preserve">
|
<trans-unit id="Blixt Wallet" xml:space="preserve">
|
||||||
<source>Blixt Wallet</source>
|
<source>Blixt Wallet</source>
|
||||||
<target>Blixt Wallet</target>
|
<target>Portefeuille Blixt</target>
|
||||||
|
|
||||||
<note>Dropdown option label for Lightning wallet, Blixt Wallet</note>
|
<note>Dropdown option label for Lightning wallet, Blixt Wallet</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Blue Wallet" xml:space="preserve">
|
<trans-unit id="Blue Wallet" xml:space="preserve">
|
||||||
<source>Blue Wallet</source>
|
<source>Blue Wallet</source>
|
||||||
<target>Blue Wallet</target>
|
<target>Portefeuille Blue</target>
|
||||||
|
|
||||||
<note>Dropdown option label for Lightning wallet, Blue Wallet.</note>
|
<note>Dropdown option label for Lightning wallet, Blue Wallet.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@@ -241,7 +235,7 @@ Number of profiles a user is following.</note>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Clear" xml:space="preserve">
|
<trans-unit id="Clear" xml:space="preserve">
|
||||||
<source>Clear</source>
|
<source>Clear</source>
|
||||||
<target>Vider</target>
|
<target><br>Vider</target>
|
||||||
|
|
||||||
<note>Button for clearing cached data.</note>
|
<note>Button for clearing cached data.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@@ -336,18 +330,11 @@ Number of profiles a user is following.</note>
|
|||||||
|
|
||||||
<note>Example description about Bitcoin creator(s), Satoshi Nakamoto.</note>
|
<note>Example description about Bitcoin creator(s), Satoshi Nakamoto.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="DM Type" xml:space="preserve">
|
<trans-unit id="DM" xml:space="preserve">
|
||||||
<source>DM Type</source>
|
<source>DM</source>
|
||||||
<target>Type de message privé</target>
|
<target>DM</target>
|
||||||
|
|
||||||
<note>DM selector for seeing either DMs or message requests, which are messages that have not been responded to yet. DM is the English abbreviation for Direct Message.</note>
|
<note>Navigation title for DM view, which is the English abbreviation for Direct Message.</note>
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="DMs" xml:space="preserve">
|
|
||||||
<source>DMs</source>
|
|
||||||
<target>Messages privés</target>
|
|
||||||
|
|
||||||
<note>Navigation title for DMs view, where DM is the English abbreviation for Direct Message.
|
|
||||||
Navigation title for view of DMs, where DM is an English abbreviation for Direct Message.</note>
|
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Damus" xml:space="preserve">
|
<trans-unit id="Damus" xml:space="preserve">
|
||||||
<source>Damus</source>
|
<source>Damus</source>
|
||||||
@@ -363,7 +350,7 @@ Number of profiles a user is following.</note>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Delete" xml:space="preserve">
|
<trans-unit id="Delete" xml:space="preserve">
|
||||||
<source>Delete</source>
|
<source>Delete</source>
|
||||||
<target>Effacer</target>
|
<target><br>Effacer</target>
|
||||||
|
|
||||||
<note>Button to delete a relay server that the user connects to.</note>
|
<note>Button to delete a relay server that the user connects to.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@@ -397,18 +384,18 @@ Number of profiles a user is following.</note>
|
|||||||
|
|
||||||
<note>Button to edit user's profile.</note>
|
<note>Button to edit user's profile.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Edit participants" xml:space="preserve">
|
|
||||||
<source>Edit participants</source>
|
|
||||||
<target>Modifier les participants</target>
|
|
||||||
|
|
||||||
<note>Text indicating that the view is used for editing which participants are replied to in a note.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Encrypted" xml:space="preserve">
|
<trans-unit id="Encrypted" xml:space="preserve">
|
||||||
<source>Encrypted</source>
|
<source>Encrypted</source>
|
||||||
<target>Crypté</target>
|
<target>Crypté</target>
|
||||||
|
|
||||||
<note>Heading indicating that this application keeps private messaging end-to-end encrypted.</note>
|
<note>Heading indicating that this application keeps private messaging end-to-end encrypted.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="Encrypted DMs" xml:space="preserve">
|
||||||
|
<source>Encrypted DMs</source>
|
||||||
|
<target>DMs cryptés</target>
|
||||||
|
|
||||||
|
<note>Navigation title for view of encrypted DMs, where DM is an English abbreviation for Direct Message.</note>
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="Enter your account key to login:" xml:space="preserve">
|
<trans-unit id="Enter your account key to login:" xml:space="preserve">
|
||||||
<source>Enter your account key to login:</source>
|
<source>Enter your account key to login:</source>
|
||||||
<target>Entrez votre clé de compte pour vous connecter:</target>
|
<target>Entrez votre clé de compte pour vous connecter:</target>
|
||||||
@@ -417,7 +404,7 @@ Number of profiles a user is following.</note>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Error: %@" xml:space="preserve">
|
<trans-unit id="Error: %@" xml:space="preserve">
|
||||||
<source>Error: %@</source>
|
<source>Error: %@</source>
|
||||||
<target>Erreur: %@</target>
|
<target>Error: %@</target>
|
||||||
|
|
||||||
<note>Error message indicating why saving keys failed.</note>
|
<note>Error message indicating why saving keys failed.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@@ -429,7 +416,7 @@ Number of profiles a user is following.</note>
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Follow" xml:space="preserve">
|
<trans-unit id="Follow" xml:space="preserve">
|
||||||
<source>Follow</source>
|
<source>Follow</source>
|
||||||
<target>S'abonner</target>
|
<target>S'abonner<br></target>
|
||||||
|
|
||||||
<note>Button to follow a user.</note>
|
<note>Button to follow a user.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@@ -454,7 +441,7 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Follows" xml:space="preserve">
|
<trans-unit id="Follows" xml:space="preserve">
|
||||||
<source>Follows</source>
|
<source>Follows</source>
|
||||||
<target>Suit</target>
|
<target>Follow<br></target>
|
||||||
|
|
||||||
<note>Text to indicate that button next to it is in a state that will follow a profile when tapped.</note>
|
<note>Text to indicate that button next to it is in a state that will follow a profile when tapped.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@@ -466,13 +453,13 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Goto post %@" xml:space="preserve">
|
<trans-unit id="Goto post %@" xml:space="preserve">
|
||||||
<source>Goto post %@</source>
|
<source>Goto post %@</source>
|
||||||
<target>Aller au post %@</target>
|
<target>Goto post %@</target>
|
||||||
|
|
||||||
<note>Navigation link to go to post referenced by hex code.</note>
|
<note>Navigation link to go to post referenced by hex code.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Goto profile %@" xml:space="preserve">
|
<trans-unit id="Goto profile %@" xml:space="preserve">
|
||||||
<source>Goto profile %@</source>
|
<source>Goto profile %@</source>
|
||||||
<target>Aller au profil %@</target>
|
<target>Goto profile %@</target>
|
||||||
|
|
||||||
<note>Navigation link to go to profile.</note>
|
<note>Navigation link to go to profile.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@@ -490,7 +477,7 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="LNLink" xml:space="preserve">
|
<trans-unit id="LNLink" xml:space="preserve">
|
||||||
<source>LNLink</source>
|
<source>LNLink</source>
|
||||||
<target>LNLink</target>
|
<target>Lien LN</target>
|
||||||
|
|
||||||
<note>Dropdown option label for Lightning wallet, LNLink.</note>
|
<note>Dropdown option label for Lightning wallet, LNLink.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@@ -615,6 +602,12 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
<source>Private Key</source>
|
<source>Private Key</source>
|
||||||
<target>Clé Privée</target>
|
<target>Clé Privée</target>
|
||||||
|
|
||||||
|
<note>Label to indicate that the text below is the user's private key used by only the user themself as a secret to login to access their account.</note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="PrivateKey" xml:space="preserve">
|
||||||
|
<source>PrivateKey</source>
|
||||||
|
<target>PrivateKey</target>
|
||||||
|
|
||||||
<note>Title of the secure field that holds the user's private key.</note>
|
<note>Title of the secure field that holds the user's private key.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Profile" xml:space="preserve">
|
<trans-unit id="Profile" xml:space="preserve">
|
||||||
@@ -677,15 +670,9 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
|
|
||||||
<note>Sidebar menu label for Relay servers view</note>
|
<note>Sidebar menu label for Relay servers view</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Remove all" xml:space="preserve">
|
|
||||||
<source>Remove all</source>
|
|
||||||
<target>Tout supprimer</target>
|
|
||||||
|
|
||||||
<note>Button label to remove all participants from a note reply.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Reply to self" xml:space="preserve">
|
<trans-unit id="Reply to self" xml:space="preserve">
|
||||||
<source>Reply to self</source>
|
<source>Reply to self</source>
|
||||||
<target>Réponse à soi-même</target>
|
<target>Répondre à soi-même</target>
|
||||||
|
|
||||||
<note>Label to indicate that the user is replying to themself.</note>
|
<note>Label to indicate that the user is replying to themself.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@@ -714,12 +701,6 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
|
|
||||||
<note>Text indicating that the post was reposted (i.e. re-shared).</note>
|
<note>Text indicating that the post was reposted (i.e. re-shared).</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Requests" xml:space="preserve">
|
|
||||||
<source>Requests</source>
|
|
||||||
<target>Demandes</target>
|
|
||||||
|
|
||||||
<note>Picker option for DM selector for seeing only message requests (DMs that someone else sent the user which has not been responded to yet). DM is the English abbreviation for Direct Message.</note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="Reset" xml:space="preserve">
|
<trans-unit id="Reset" xml:space="preserve">
|
||||||
<source>Reset</source>
|
<source>Reset</source>
|
||||||
<target>Réinitialiser</target>
|
<target>Réinitialiser</target>
|
||||||
@@ -807,7 +788,7 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Show" xml:space="preserve">
|
<trans-unit id="Show" xml:space="preserve">
|
||||||
<source>Show</source>
|
<source>Show</source>
|
||||||
<target>Afficher</target>
|
<target>Afficher<br></target>
|
||||||
|
|
||||||
<note>Toggle to show or hide user's secret account login key.</note>
|
<note>Toggle to show or hide user's secret account login key.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@@ -880,7 +861,7 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Unfollowing..." xml:space="preserve">
|
<trans-unit id="Unfollowing..." xml:space="preserve">
|
||||||
<source>Unfollowing...</source>
|
<source>Unfollowing...</source>
|
||||||
<target>Ne plus suivre...</target>
|
<target>Ne plus suivre...<br></target>
|
||||||
|
|
||||||
<note>Label to indicate that the user is in the process of unfollowing another user.</note>
|
<note>Label to indicate that the user is in the process of unfollowing another user.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@@ -905,7 +886,7 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Wallet Of Satoshi" xml:space="preserve">
|
<trans-unit id="Wallet Of Satoshi" xml:space="preserve">
|
||||||
<source>Wallet Of Satoshi</source>
|
<source>Wallet Of Satoshi</source>
|
||||||
<target>Wallet Of Satoshi</target>
|
<target>Portefeuille de Satoshi</target>
|
||||||
|
|
||||||
<note>Dropdown option label for Lightning wallet, Wallet Of Satoshi.</note>
|
<note>Dropdown option label for Lightning wallet, Wallet Of Satoshi.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@@ -947,7 +928,7 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="Zeus LN" xml:space="preserve">
|
<trans-unit id="Zeus LN" xml:space="preserve">
|
||||||
<source>Zeus LN</source>
|
<source>Zeus LN</source>
|
||||||
<target>Zeus LN</target>
|
<target>LN de Zeus</target>
|
||||||
|
|
||||||
<note>Dropdown option label for Lightning wallet, Zeus LN.</note>
|
<note>Dropdown option label for Lightning wallet, Zeus LN.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@@ -965,7 +946,7 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="https://example.com/pic.jpg" xml:space="preserve">
|
<trans-unit id="https://example.com/pic.jpg" xml:space="preserve">
|
||||||
<source>https://example.com/pic.jpg</source>
|
<source>https://example.com/pic.jpg</source>
|
||||||
<target>https://exemple.com/pic.jpg</target>
|
<target>https://example.com/pic.jpg</target>
|
||||||
|
|
||||||
<note>Placeholder example text for profile picture URL.</note>
|
<note>Placeholder example text for profile picture URL.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@@ -983,13 +964,13 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="none" xml:space="preserve">
|
<trans-unit id="none" xml:space="preserve">
|
||||||
<source>none</source>
|
<source>none</source>
|
||||||
<target>aucun</target>
|
<target>none</target>
|
||||||
|
|
||||||
<note>No search results.</note>
|
<note>No search results.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="now" xml:space="preserve">
|
<trans-unit id="now" xml:space="preserve">
|
||||||
<source>now</source>
|
<source>now</source>
|
||||||
<target>maintenant</target>
|
<target>now</target>
|
||||||
|
|
||||||
<note>String indicating that a given timestamp just occurred</note>
|
<note>String indicating that a given timestamp just occurred</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@@ -1001,7 +982,7 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="optional" xml:space="preserve">
|
<trans-unit id="optional" xml:space="preserve">
|
||||||
<source>optional</source>
|
<source>optional</source>
|
||||||
<target>optionnel</target>
|
<target>optional</target>
|
||||||
|
|
||||||
<note>Label indicating that a form input is optional.</note>
|
<note>Label indicating that a form input is optional.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@@ -1061,13 +1042,13 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="wss://some.relay.com" xml:space="preserve">
|
<trans-unit id="wss://some.relay.com" xml:space="preserve">
|
||||||
<source>wss://some.relay.com</source>
|
<source>wss://some.relay.com</source>
|
||||||
<target>wss://un.relais.com</target>
|
<target>wss://some.relay.com</target>
|
||||||
|
|
||||||
<note>Placeholder example for relay server address.</note>
|
<note>Placeholder example for relay server address.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="you" xml:space="preserve">
|
<trans-unit id="you" xml:space="preserve">
|
||||||
<source>you</source>
|
<source>you</source>
|
||||||
<target>vous</target>
|
<target>you</target>
|
||||||
|
|
||||||
<note>You, in this context, is the person who controls their own social network. You is used in the context of a larger sentence that welcomes the reader to the social network that they control themself.</note>
|
<note>You, in this context, is the person who controls their own social network. You is used in the context of a larger sentence that welcomes the reader to the social network that they control themself.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@@ -1080,13 +1061,13 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
<body>
|
<body>
|
||||||
<trans-unit id="/collapsed_event_view_other_notes:dict/NOTES:dict/one:dict/:string" xml:space="preserve">
|
<trans-unit id="/collapsed_event_view_other_notes:dict/NOTES:dict/one:dict/:string" xml:space="preserve">
|
||||||
<source>%d other note</source>
|
<source>%d other note</source>
|
||||||
<target>%d autre note</target>
|
<target>%d other note</target>
|
||||||
|
|
||||||
<note>Text to indicate that the thread was collapsed and that there are other notes to view if tapped.</note>
|
<note>Text to indicate that the thread was collapsed and that there are other notes to view if tapped.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="/collapsed_event_view_other_notes:dict/NOTES:dict/other:dict/:string" xml:space="preserve">
|
<trans-unit id="/collapsed_event_view_other_notes:dict/NOTES:dict/other:dict/:string" xml:space="preserve">
|
||||||
<source>%d other notes</source>
|
<source>%d other notes</source>
|
||||||
<target>%d autres notes</target>
|
<target>%d other notes</target>
|
||||||
|
|
||||||
<note>Text to indicate that the thread was collapsed and that there are other notes to view if tapped.</note>
|
<note>Text to indicate that the thread was collapsed and that there are other notes to view if tapped.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@@ -1152,19 +1133,19 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="/replying_to_one_and_others:dict/NSStringLocalizedFormatKey:dict/:string" xml:space="preserve">
|
<trans-unit id="/replying_to_one_and_others:dict/NSStringLocalizedFormatKey:dict/:string" xml:space="preserve">
|
||||||
<source>Replying to %@%#@OTHERS@</source>
|
<source>Replying to %@%#@OTHERS@</source>
|
||||||
<target>Réponse à %@%#@OTHERS@</target>
|
<target>Répondre à %@%#@OTHERS@</target>
|
||||||
|
|
||||||
<note>Label to indicate that the user is replying to 1 user and others.</note>
|
<note>Label to indicate that the user is replying to 1 user and others.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="/replying_to_one_and_others:dict/OTHERS:dict/one:dict/:string" xml:space="preserve">
|
<trans-unit id="/replying_to_one_and_others:dict/OTHERS:dict/one:dict/:string" xml:space="preserve">
|
||||||
<source> & %d other</source>
|
<source> & %d other</source>
|
||||||
<target>& %d autre</target>
|
<target>& %d other</target>
|
||||||
|
|
||||||
<note>Label to indicate that the user is replying to 1 user and others.</note>
|
<note>Label to indicate that the user is replying to 1 user and others.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="/replying_to_one_and_others:dict/OTHERS:dict/other:dict/:string" xml:space="preserve">
|
<trans-unit id="/replying_to_one_and_others:dict/OTHERS:dict/other:dict/:string" xml:space="preserve">
|
||||||
<source> & %d others</source>
|
<source> & %d others</source>
|
||||||
<target>& %d autres</target>
|
<target>& %d others</target>
|
||||||
|
|
||||||
<note>Label to indicate that the user is replying to 1 user and others.</note>
|
<note>Label to indicate that the user is replying to 1 user and others.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@@ -1180,13 +1161,13 @@ Part of a larger sentence to describe how many profiles a user is following.</no
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="/replying_to_two_and_others:dict/OTHERS:dict/one:dict/:string" xml:space="preserve">
|
<trans-unit id="/replying_to_two_and_others:dict/OTHERS:dict/one:dict/:string" xml:space="preserve">
|
||||||
<source> & %d other</source>
|
<source> & %d other</source>
|
||||||
<target>& %d autre</target>
|
<target>& %d other</target>
|
||||||
|
|
||||||
<note>Label to indicate that the user is replying to 2 users and others.</note>
|
<note>Label to indicate that the user is replying to 2 users and others.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="/replying_to_two_and_others:dict/OTHERS:dict/other:dict/:string" xml:space="preserve">
|
<trans-unit id="/replying_to_two_and_others:dict/OTHERS:dict/other:dict/:string" xml:space="preserve">
|
||||||
<source> & %d others</source>
|
<source> & %d others</source>
|
||||||
<target>& %d autres</target>
|
<target>& %d others</target>
|
||||||
|
|
||||||
<note>Label to indicate that the user is replying to 2 users and others.</note>
|
<note>Label to indicate that the user is replying to 2 users and others.</note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
File diff suppressed because it is too large
Load Diff
+34
-123
@@ -18,7 +18,6 @@
|
|||||||
3ACB685C297633BC00C46468 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3ACB685A297633BC00C46468 /* InfoPlist.strings */; };
|
3ACB685C297633BC00C46468 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3ACB685A297633BC00C46468 /* InfoPlist.strings */; };
|
||||||
3ACB685F297633BC00C46468 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3ACB685D297633BC00C46468 /* Localizable.strings */; };
|
3ACB685F297633BC00C46468 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3ACB685D297633BC00C46468 /* Localizable.strings */; };
|
||||||
3ACBCB78295FE5C70037388A /* TimeAgoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ACBCB77295FE5C70037388A /* TimeAgoTests.swift */; };
|
3ACBCB78295FE5C70037388A /* TimeAgoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ACBCB77295FE5C70037388A /* TimeAgoTests.swift */; };
|
||||||
3AE45AF6297BB2E700C1D842 /* LibreTranslateServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AE45AF5297BB2E700C1D842 /* LibreTranslateServer.swift */; };
|
|
||||||
4C06670128FC7C5900038D2A /* RelayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C06670028FC7C5900038D2A /* RelayView.swift */; };
|
4C06670128FC7C5900038D2A /* RelayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C06670028FC7C5900038D2A /* RelayView.swift */; };
|
||||||
4C06670428FC7EC500038D2A /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 4C06670328FC7EC500038D2A /* Kingfisher */; };
|
4C06670428FC7EC500038D2A /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 4C06670328FC7EC500038D2A /* Kingfisher */; };
|
||||||
4C06670628FCB08600038D2A /* ImageCarousel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C06670528FCB08600038D2A /* ImageCarousel.swift */; };
|
4C06670628FCB08600038D2A /* ImageCarousel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C06670528FCB08600038D2A /* ImageCarousel.swift */; };
|
||||||
@@ -137,7 +136,6 @@
|
|||||||
4CC7AAF4297F18B400430951 /* ReplyDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7AAF3297F18B400430951 /* ReplyDescription.swift */; };
|
4CC7AAF4297F18B400430951 /* ReplyDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7AAF3297F18B400430951 /* ReplyDescription.swift */; };
|
||||||
4CC7AAF6297F1A6A00430951 /* EventBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7AAF5297F1A6A00430951 /* EventBody.swift */; };
|
4CC7AAF6297F1A6A00430951 /* EventBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7AAF5297F1A6A00430951 /* EventBody.swift */; };
|
||||||
4CC7AAF8297F1CEE00430951 /* EventProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7AAF7297F1CEE00430951 /* EventProfile.swift */; };
|
4CC7AAF8297F1CEE00430951 /* EventProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7AAF7297F1CEE00430951 /* EventProfile.swift */; };
|
||||||
4CC7AAFA297F64AC00430951 /* EventMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7AAF9297F64AC00430951 /* EventMenu.swift */; };
|
|
||||||
4CD7641B28A1641400B6928F /* EndBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CD7641A28A1641400B6928F /* EndBlock.swift */; };
|
4CD7641B28A1641400B6928F /* EndBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CD7641A28A1641400B6928F /* EndBlock.swift */; };
|
||||||
4CE4F8CD281352B30009DFBB /* Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE4F8CC281352B30009DFBB /* Notifications.swift */; };
|
4CE4F8CD281352B30009DFBB /* Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE4F8CC281352B30009DFBB /* Notifications.swift */; };
|
||||||
4CE4F9DE2852768D00C00DD9 /* ConfigView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE4F9DD2852768D00C00DD9 /* ConfigView.swift */; };
|
4CE4F9DE2852768D00C00DD9 /* ConfigView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE4F9DD2852768D00C00DD9 /* ConfigView.swift */; };
|
||||||
@@ -159,29 +157,14 @@
|
|||||||
4CEE2AF7280B2DEA00AB5EEF /* ProfileName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CEE2AF6280B2DEA00AB5EEF /* ProfileName.swift */; };
|
4CEE2AF7280B2DEA00AB5EEF /* ProfileName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CEE2AF6280B2DEA00AB5EEF /* ProfileName.swift */; };
|
||||||
4CEE2AF9280B2EAC00AB5EEF /* PowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CEE2AF8280B2EAC00AB5EEF /* PowView.swift */; };
|
4CEE2AF9280B2EAC00AB5EEF /* PowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CEE2AF8280B2EAC00AB5EEF /* PowView.swift */; };
|
||||||
4CEE2B02280B39E800AB5EEF /* EventActionBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CEE2B01280B39E800AB5EEF /* EventActionBar.swift */; };
|
4CEE2B02280B39E800AB5EEF /* EventActionBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CEE2B01280B39E800AB5EEF /* EventActionBar.swift */; };
|
||||||
4CF0ABD42980996B00D66079 /* Report.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CF0ABD32980996B00D66079 /* Report.swift */; };
|
|
||||||
4CF0ABD629817F5B00D66079 /* ReportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CF0ABD529817F5B00D66079 /* ReportView.swift */; };
|
|
||||||
4CF0ABD82981980C00D66079 /* Lists.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CF0ABD72981980C00D66079 /* Lists.swift */; };
|
|
||||||
4CF0ABDC2981A19E00D66079 /* ListTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CF0ABDB2981A19E00D66079 /* ListTests.swift */; };
|
|
||||||
4CF0ABDE2981A69500D66079 /* MutelistModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CF0ABDD2981A69500D66079 /* MutelistModel.swift */; };
|
|
||||||
4CF0ABE12981A83900D66079 /* MutelistView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CF0ABE02981A83900D66079 /* MutelistView.swift */; };
|
|
||||||
4CF0ABE32981BC7D00D66079 /* UserView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CF0ABE22981BC7D00D66079 /* UserView.swift */; };
|
|
||||||
4CF0ABE52981EE0C00D66079 /* EULAView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CF0ABE42981EE0C00D66079 /* EULAView.swift */; };
|
|
||||||
4CF0ABE7298444FD00D66079 /* MutedEventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CF0ABE6298444FC00D66079 /* MutedEventView.swift */; };
|
|
||||||
4CF0ABE929844AF100D66079 /* AnyCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CF0ABE829844AF100D66079 /* AnyCodable.swift */; };
|
|
||||||
4CF0ABEC29844B4700D66079 /* AnyDecodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CF0ABEB29844B4700D66079 /* AnyDecodable.swift */; };
|
|
||||||
4CF0ABEE29844B5500D66079 /* AnyEncodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CF0ABED29844B5500D66079 /* AnyEncodable.swift */; };
|
|
||||||
4CF0ABF029857E9200D66079 /* Bech32Object.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CF0ABEF29857E9200D66079 /* Bech32Object.swift */; };
|
|
||||||
4CF0ABF62985CD5500D66079 /* UserSearch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CF0ABF52985CD5500D66079 /* UserSearch.swift */; };
|
|
||||||
4FE60CDD295E1C5E00105A1F /* Wallet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FE60CDC295E1C5E00105A1F /* Wallet.swift */; };
|
4FE60CDD295E1C5E00105A1F /* Wallet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FE60CDC295E1C5E00105A1F /* Wallet.swift */; };
|
||||||
5C513FCC2984ACA60072348F /* QRCodeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C513FCB2984ACA60072348F /* QRCodeView.swift */; };
|
|
||||||
6439E014296790CF0020672B /* ProfileZoomView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6439E013296790CF0020672B /* ProfileZoomView.swift */; };
|
6439E014296790CF0020672B /* ProfileZoomView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6439E013296790CF0020672B /* ProfileZoomView.swift */; };
|
||||||
647D9A8D2968520300A295DE /* SideMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 647D9A8C2968520300A295DE /* SideMenuView.swift */; };
|
647D9A8D2968520300A295DE /* SideMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 647D9A8C2968520300A295DE /* SideMenuView.swift */; };
|
||||||
64FBD06F296255C400D9D3B2 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64FBD06E296255C400D9D3B2 /* Theme.swift */; };
|
64FBD06F296255C400D9D3B2 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64FBD06E296255C400D9D3B2 /* Theme.swift */; };
|
||||||
6C7DE41F2955169800E66263 /* Vault in Frameworks */ = {isa = PBXBuildFile; productRef = 6C7DE41E2955169800E66263 /* Vault */; };
|
6C7DE41F2955169800E66263 /* Vault in Frameworks */ = {isa = PBXBuildFile; productRef = 6C7DE41E2955169800E66263 /* Vault */; };
|
||||||
|
7C45AE6D297352F90031D7BC /* SVGKit in Frameworks */ = {isa = PBXBuildFile; productRef = 7C45AE6C297352F90031D7BC /* SVGKit */; };
|
||||||
|
7C45AE6F297352F90031D7BC /* SVGKitSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 7C45AE6E297352F90031D7BC /* SVGKitSwift */; };
|
||||||
7C45AE71297353390031D7BC /* KFImageModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C45AE70297353390031D7BC /* KFImageModel.swift */; };
|
7C45AE71297353390031D7BC /* KFImageModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C45AE70297353390031D7BC /* KFImageModel.swift */; };
|
||||||
7C60CAEF298471A1009C80D6 /* CoreSVG.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C60CAEE298471A1009C80D6 /* CoreSVG.swift */; };
|
|
||||||
7C902AE32981D55B002AB16E /* ZoomableScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C902AE22981D55B002AB16E /* ZoomableScrollView.swift */; };
|
|
||||||
9609F058296E220800069BF3 /* BannerImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9609F057296E220800069BF3 /* BannerImageView.swift */; };
|
9609F058296E220800069BF3 /* BannerImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9609F057296E220800069BF3 /* BannerImageView.swift */; };
|
||||||
BA693074295D649800ADDB87 /* UserSettingsStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA693073295D649800ADDB87 /* UserSettingsStore.swift */; };
|
BA693074295D649800ADDB87 /* UserSettingsStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA693073295D649800ADDB87 /* UserSettingsStore.swift */; };
|
||||||
BAB68BED29543FA3007BA466 /* SelectWalletView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAB68BEC29543FA3007BA466 /* SelectWalletView.swift */; };
|
BAB68BED29543FA3007BA466 /* SelectWalletView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAB68BEC29543FA3007BA466 /* SelectWalletView.swift */; };
|
||||||
@@ -214,9 +197,6 @@
|
|||||||
3169CAE5294E69C000EE4006 /* EmptyTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyTimelineView.swift; sourceTree = "<group>"; };
|
3169CAE5294E69C000EE4006 /* EmptyTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyTimelineView.swift; sourceTree = "<group>"; };
|
||||||
3169CAEC294FCCFC00EE4006 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Constants.swift; path = damus/Util/Constants.swift; sourceTree = SOURCE_ROOT; };
|
3169CAEC294FCCFC00EE4006 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Constants.swift; path = damus/Util/Constants.swift; sourceTree = SOURCE_ROOT; };
|
||||||
31D2E846295218AF006D67F8 /* Shimmer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Shimmer.swift; sourceTree = "<group>"; };
|
31D2E846295218AF006D67F8 /* Shimmer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Shimmer.swift; sourceTree = "<group>"; };
|
||||||
3A185A04297F2C3800F4BDC0 /* lv-LV */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "lv-LV"; path = "lv-LV.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
|
||||||
3A185A05297F2C3800F4BDC0 /* lv-LV */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "lv-LV"; path = "lv-LV.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
|
||||||
3A185A06297F2C3800F4BDC0 /* lv-LV */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "lv-LV"; path = "lv-LV.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
|
|
||||||
3A2B8B0A296A8982009CC16D /* en-US */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "en-US"; path = "en-US.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
|
3A2B8B0A296A8982009CC16D /* en-US */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "en-US"; path = "en-US.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
|
||||||
3A4F3320297CCFEE004B5F72 /* fr-FR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "fr-FR"; path = "fr-FR.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
3A4F3320297CCFEE004B5F72 /* fr-FR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "fr-FR"; path = "fr-FR.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
||||||
3A4F3321297CCFEE004B5F72 /* fr-FR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "fr-FR"; path = "fr-FR.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
3A4F3321297CCFEE004B5F72 /* fr-FR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "fr-FR"; path = "fr-FR.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||||
@@ -225,19 +205,15 @@
|
|||||||
3A5EA10F297CCF6C00569477 /* de-AT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "de-AT"; path = "de-AT.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
3A5EA10F297CCF6C00569477 /* de-AT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "de-AT"; path = "de-AT.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
||||||
3A5EA110297CCF6C00569477 /* de-AT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "de-AT"; path = "de-AT.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
3A5EA110297CCF6C00569477 /* de-AT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "de-AT"; path = "de-AT.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||||
3A5EA111297CCF6C00569477 /* de-AT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "de-AT"; path = "de-AT.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
|
3A5EA111297CCF6C00569477 /* de-AT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "de-AT"; path = "de-AT.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
|
||||||
3A929C20297F2CF80090925E /* it-IT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "it-IT"; path = "it-IT.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
|
||||||
3A929C21297F2CF80090925E /* it-IT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "it-IT"; path = "it-IT.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
|
||||||
3A929C22297F2CF80090925E /* it-IT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "it-IT"; path = "it-IT.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
|
|
||||||
3AA247FC297E3CFF0090C62D /* RepostsModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RepostsModel.swift; sourceTree = "<group>"; };
|
3AA247FC297E3CFF0090C62D /* RepostsModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RepostsModel.swift; sourceTree = "<group>"; };
|
||||||
3AA247FE297E3D900090C62D /* RepostsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepostsView.swift; sourceTree = "<group>"; };
|
3AA247FE297E3D900090C62D /* RepostsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepostsView.swift; sourceTree = "<group>"; };
|
||||||
3AA24801297E3DC20090C62D /* RepostView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepostView.swift; sourceTree = "<group>"; };
|
3AA24801297E3DC20090C62D /* RepostView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepostView.swift; sourceTree = "<group>"; };
|
||||||
3AB5B86A2986D8A3006599D2 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
|
||||||
3AB5B86B2986D8A3006599D2 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; };
|
|
||||||
3AB5B86C2986D8A3006599D2 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = de; path = de.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
|
||||||
3ACB685B297633BC00C46468 /* es-419 */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-419"; path = "es-419.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
3ACB685B297633BC00C46468 /* es-419 */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-419"; path = "es-419.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
||||||
3ACB685E297633BC00C46468 /* es-419 */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-419"; path = "es-419.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
3ACB685E297633BC00C46468 /* es-419 */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-419"; path = "es-419.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||||
3ACBCB77295FE5C70037388A /* TimeAgoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeAgoTests.swift; sourceTree = "<group>"; };
|
3ACBCB77295FE5C70037388A /* TimeAgoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeAgoTests.swift; sourceTree = "<group>"; };
|
||||||
3AE45AF5297BB2E700C1D842 /* LibreTranslateServer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibreTranslateServer.swift; sourceTree = "<group>"; };
|
3AEABD20297CCFA8003F2975 /* de-DE */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "de-DE"; path = "de-DE.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
||||||
|
3AEABD21297CCFA8003F2975 /* de-DE */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "de-DE"; path = "de-DE.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||||
|
3AEABD22297CCFA8003F2975 /* de-DE */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "de-DE"; path = "de-DE.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
|
||||||
3AEB8003297CCEA800713A25 /* tr-TR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "tr-TR"; path = "tr-TR.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
3AEB8003297CCEA800713A25 /* tr-TR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "tr-TR"; path = "tr-TR.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
||||||
3AEB8004297CCEA800713A25 /* tr-TR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "tr-TR"; path = "tr-TR.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
3AEB8004297CCEA800713A25 /* tr-TR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "tr-TR"; path = "tr-TR.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||||
3AEB8005297CCEA900713A25 /* tr-TR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "tr-TR"; path = "tr-TR.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
|
3AEB8005297CCEA900713A25 /* tr-TR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "tr-TR"; path = "tr-TR.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
|
||||||
@@ -391,7 +367,6 @@
|
|||||||
4CC7AAF3297F18B400430951 /* ReplyDescription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReplyDescription.swift; sourceTree = "<group>"; };
|
4CC7AAF3297F18B400430951 /* ReplyDescription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReplyDescription.swift; sourceTree = "<group>"; };
|
||||||
4CC7AAF5297F1A6A00430951 /* EventBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventBody.swift; sourceTree = "<group>"; };
|
4CC7AAF5297F1A6A00430951 /* EventBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventBody.swift; sourceTree = "<group>"; };
|
||||||
4CC7AAF7297F1CEE00430951 /* EventProfile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventProfile.swift; sourceTree = "<group>"; };
|
4CC7AAF7297F1CEE00430951 /* EventProfile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventProfile.swift; sourceTree = "<group>"; };
|
||||||
4CC7AAF9297F64AC00430951 /* EventMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventMenu.swift; sourceTree = "<group>"; };
|
|
||||||
4CD7641A28A1641400B6928F /* EndBlock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EndBlock.swift; sourceTree = "<group>"; };
|
4CD7641A28A1641400B6928F /* EndBlock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EndBlock.swift; sourceTree = "<group>"; };
|
||||||
4CE4F8CC281352B30009DFBB /* Notifications.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notifications.swift; sourceTree = "<group>"; };
|
4CE4F8CC281352B30009DFBB /* Notifications.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notifications.swift; sourceTree = "<group>"; };
|
||||||
4CE4F9DD2852768D00C00DD9 /* ConfigView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigView.swift; sourceTree = "<group>"; };
|
4CE4F9DD2852768D00C00DD9 /* ConfigView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigView.swift; sourceTree = "<group>"; };
|
||||||
@@ -416,28 +391,11 @@
|
|||||||
4CEE2AF6280B2DEA00AB5EEF /* ProfileName.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileName.swift; sourceTree = "<group>"; };
|
4CEE2AF6280B2DEA00AB5EEF /* ProfileName.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileName.swift; sourceTree = "<group>"; };
|
||||||
4CEE2AF8280B2EAC00AB5EEF /* PowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PowView.swift; sourceTree = "<group>"; };
|
4CEE2AF8280B2EAC00AB5EEF /* PowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PowView.swift; sourceTree = "<group>"; };
|
||||||
4CEE2B01280B39E800AB5EEF /* EventActionBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventActionBar.swift; sourceTree = "<group>"; };
|
4CEE2B01280B39E800AB5EEF /* EventActionBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventActionBar.swift; sourceTree = "<group>"; };
|
||||||
4CF0ABD32980996B00D66079 /* Report.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Report.swift; sourceTree = "<group>"; };
|
|
||||||
4CF0ABD529817F5B00D66079 /* ReportView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportView.swift; sourceTree = "<group>"; };
|
|
||||||
4CF0ABD72981980C00D66079 /* Lists.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Lists.swift; sourceTree = "<group>"; };
|
|
||||||
4CF0ABDB2981A19E00D66079 /* ListTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTests.swift; sourceTree = "<group>"; };
|
|
||||||
4CF0ABDD2981A69500D66079 /* MutelistModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MutelistModel.swift; sourceTree = "<group>"; };
|
|
||||||
4CF0ABE02981A83900D66079 /* MutelistView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MutelistView.swift; sourceTree = "<group>"; };
|
|
||||||
4CF0ABE22981BC7D00D66079 /* UserView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserView.swift; sourceTree = "<group>"; };
|
|
||||||
4CF0ABE42981EE0C00D66079 /* EULAView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EULAView.swift; sourceTree = "<group>"; };
|
|
||||||
4CF0ABE6298444FC00D66079 /* MutedEventView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MutedEventView.swift; sourceTree = "<group>"; };
|
|
||||||
4CF0ABE829844AF100D66079 /* AnyCodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyCodable.swift; sourceTree = "<group>"; };
|
|
||||||
4CF0ABEB29844B4700D66079 /* AnyDecodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyDecodable.swift; sourceTree = "<group>"; };
|
|
||||||
4CF0ABED29844B5500D66079 /* AnyEncodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyEncodable.swift; sourceTree = "<group>"; };
|
|
||||||
4CF0ABEF29857E9200D66079 /* Bech32Object.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bech32Object.swift; sourceTree = "<group>"; };
|
|
||||||
4CF0ABF52985CD5500D66079 /* UserSearch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSearch.swift; sourceTree = "<group>"; };
|
|
||||||
4FE60CDC295E1C5E00105A1F /* Wallet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Wallet.swift; sourceTree = "<group>"; };
|
4FE60CDC295E1C5E00105A1F /* Wallet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Wallet.swift; sourceTree = "<group>"; };
|
||||||
5C513FCB2984ACA60072348F /* QRCodeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeView.swift; sourceTree = "<group>"; };
|
|
||||||
6439E013296790CF0020672B /* ProfileZoomView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileZoomView.swift; sourceTree = "<group>"; };
|
6439E013296790CF0020672B /* ProfileZoomView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileZoomView.swift; sourceTree = "<group>"; };
|
||||||
647D9A8C2968520300A295DE /* SideMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SideMenuView.swift; sourceTree = "<group>"; };
|
647D9A8C2968520300A295DE /* SideMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SideMenuView.swift; sourceTree = "<group>"; };
|
||||||
64FBD06E296255C400D9D3B2 /* Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = "<group>"; };
|
64FBD06E296255C400D9D3B2 /* Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = "<group>"; };
|
||||||
7C45AE70297353390031D7BC /* KFImageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KFImageModel.swift; sourceTree = "<group>"; };
|
7C45AE70297353390031D7BC /* KFImageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KFImageModel.swift; sourceTree = "<group>"; };
|
||||||
7C60CAEE298471A1009C80D6 /* CoreSVG.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreSVG.swift; sourceTree = "<group>"; };
|
|
||||||
7C902AE22981D55B002AB16E /* ZoomableScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZoomableScrollView.swift; sourceTree = "<group>"; };
|
|
||||||
9609F057296E220800069BF3 /* BannerImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BannerImageView.swift; sourceTree = "<group>"; };
|
9609F057296E220800069BF3 /* BannerImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BannerImageView.swift; sourceTree = "<group>"; };
|
||||||
BA693073295D649800ADDB87 /* UserSettingsStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSettingsStore.swift; sourceTree = "<group>"; };
|
BA693073295D649800ADDB87 /* UserSettingsStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSettingsStore.swift; sourceTree = "<group>"; };
|
||||||
BAB68BEC29543FA3007BA466 /* SelectWalletView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectWalletView.swift; sourceTree = "<group>"; };
|
BAB68BEC29543FA3007BA466 /* SelectWalletView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectWalletView.swift; sourceTree = "<group>"; };
|
||||||
@@ -453,6 +411,8 @@
|
|||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
7C45AE6F297352F90031D7BC /* SVGKitSwift in Frameworks */,
|
||||||
|
7C45AE6D297352F90031D7BC /* SVGKit in Frameworks */,
|
||||||
4C06670428FC7EC500038D2A /* Kingfisher in Frameworks */,
|
4C06670428FC7EC500038D2A /* Kingfisher in Frameworks */,
|
||||||
6C7DE41F2955169800E66263 /* Vault in Frameworks */,
|
6C7DE41F2955169800E66263 /* Vault in Frameworks */,
|
||||||
4CE6DF1227F7A2B300C66700 /* Starscream in Frameworks */,
|
4CE6DF1227F7A2B300C66700 /* Starscream in Frameworks */,
|
||||||
@@ -582,9 +542,6 @@
|
|||||||
4FE60CDC295E1C5E00105A1F /* Wallet.swift */,
|
4FE60CDC295E1C5E00105A1F /* Wallet.swift */,
|
||||||
4CB88392296F798300DC99E7 /* ReactionsModel.swift */,
|
4CB88392296F798300DC99E7 /* ReactionsModel.swift */,
|
||||||
7C45AE70297353390031D7BC /* KFImageModel.swift */,
|
7C45AE70297353390031D7BC /* KFImageModel.swift */,
|
||||||
4CF0ABD32980996B00D66079 /* Report.swift */,
|
|
||||||
4CF0ABDD2981A69500D66079 /* MutelistModel.swift */,
|
|
||||||
3AE45AF5297BB2E700C1D842 /* LibreTranslateServer.swift */,
|
|
||||||
);
|
);
|
||||||
path = Models;
|
path = Models;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -592,8 +549,6 @@
|
|||||||
4C75EFA227FA576C0006080F /* Views */ = {
|
4C75EFA227FA576C0006080F /* Views */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
4CF0ABF42985CD4200D66079 /* Posting */,
|
|
||||||
4CF0ABDF2981A83000D66079 /* Muting */,
|
|
||||||
4CC7AAEE297F11B300430951 /* Events */,
|
4CC7AAEE297F11B300430951 /* Events */,
|
||||||
3AA24800297E3DAE0090C62D /* Reposts */,
|
3AA24800297E3DAE0090C62D /* Reposts */,
|
||||||
4CB88394296F7F8100DC99E7 /* Reactions */,
|
4CB88394296F7F8100DC99E7 /* Reactions */,
|
||||||
@@ -645,10 +600,7 @@
|
|||||||
9609F057296E220800069BF3 /* BannerImageView.swift */,
|
9609F057296E220800069BF3 /* BannerImageView.swift */,
|
||||||
4CB8838E296F781C00DC99E7 /* ReactionsView.swift */,
|
4CB8838E296F781C00DC99E7 /* ReactionsView.swift */,
|
||||||
6439E013296790CF0020672B /* ProfileZoomView.swift */,
|
6439E013296790CF0020672B /* ProfileZoomView.swift */,
|
||||||
4CF0ABD529817F5B00D66079 /* ReportView.swift */,
|
|
||||||
4CF0ABE42981EE0C00D66079 /* EULAView.swift */,
|
|
||||||
3AA247FE297E3D900090C62D /* RepostsView.swift */,
|
3AA247FE297E3D900090C62D /* RepostsView.swift */,
|
||||||
5C513FCB2984ACA60072348F /* QRCodeView.swift */,
|
|
||||||
);
|
);
|
||||||
path = Views;
|
path = Views;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -676,7 +628,6 @@
|
|||||||
4C7FF7D628233637009601DB /* Util */ = {
|
4C7FF7D628233637009601DB /* Util */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
4CF0ABEA29844B2F00D66079 /* AnyCodable */,
|
|
||||||
4C3A1D322960DB0500558C0F /* Markdown.swift */,
|
4C3A1D322960DB0500558C0F /* Markdown.swift */,
|
||||||
4CEE2AF4280B29E600AB5EEF /* TimeAgo.swift */,
|
4CEE2AF4280B29E600AB5EEF /* TimeAgo.swift */,
|
||||||
4CE4F8CC281352B30009DFBB /* Notifications.swift */,
|
4CE4F8CC281352B30009DFBB /* Notifications.swift */,
|
||||||
@@ -691,9 +642,6 @@
|
|||||||
4C3A1D3629637E0500558C0F /* PreviewCache.swift */,
|
4C3A1D3629637E0500558C0F /* PreviewCache.swift */,
|
||||||
64FBD06E296255C400D9D3B2 /* Theme.swift */,
|
64FBD06E296255C400D9D3B2 /* Theme.swift */,
|
||||||
4CB8838529656C8B00DC99E7 /* NIP05.swift */,
|
4CB8838529656C8B00DC99E7 /* NIP05.swift */,
|
||||||
4CF0ABD72981980C00D66079 /* Lists.swift */,
|
|
||||||
4CF0ABEF29857E9200D66079 /* Bech32Object.swift */,
|
|
||||||
7C60CAEE298471A1009C80D6 /* CoreSVG.swift */,
|
|
||||||
);
|
);
|
||||||
path = Util;
|
path = Util;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -724,8 +672,6 @@
|
|||||||
4CC7AAF5297F1A6A00430951 /* EventBody.swift */,
|
4CC7AAF5297F1A6A00430951 /* EventBody.swift */,
|
||||||
4CC7AAEA297F0AEC00430951 /* BuilderEventView.swift */,
|
4CC7AAEA297F0AEC00430951 /* BuilderEventView.swift */,
|
||||||
4CC7AAF7297F1CEE00430951 /* EventProfile.swift */,
|
4CC7AAF7297F1CEE00430951 /* EventProfile.swift */,
|
||||||
4CC7AAF9297F64AC00430951 /* EventMenu.swift */,
|
|
||||||
4CF0ABE6298444FC00D66079 /* MutedEventView.swift */,
|
|
||||||
);
|
);
|
||||||
path = Events;
|
path = Events;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -743,8 +689,6 @@
|
|||||||
4CB8838C296F710400DC99E7 /* Reposted.swift */,
|
4CB8838C296F710400DC99E7 /* Reposted.swift */,
|
||||||
4CBCA92F297DB57F00EC6B2F /* WebsiteLink.swift */,
|
4CBCA92F297DB57F00EC6B2F /* WebsiteLink.swift */,
|
||||||
4CC7AAEC297F0B9E00430951 /* Highlight.swift */,
|
4CC7AAEC297F0B9E00430951 /* Highlight.swift */,
|
||||||
4CF0ABE22981BC7D00D66079 /* UserView.swift */,
|
|
||||||
7C902AE22981D55B002AB16E /* ZoomableScrollView.swift */,
|
|
||||||
);
|
);
|
||||||
path = Components;
|
path = Components;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -812,7 +756,6 @@
|
|||||||
4C3EA67A28FF7B3900C48A62 /* InvoiceTests.swift */,
|
4C3EA67A28FF7B3900C48A62 /* InvoiceTests.swift */,
|
||||||
3ACBCB77295FE5C70037388A /* TimeAgoTests.swift */,
|
3ACBCB77295FE5C70037388A /* TimeAgoTests.swift */,
|
||||||
4CB88399297322D200DC99E7 /* DMTests.swift */,
|
4CB88399297322D200DC99E7 /* DMTests.swift */,
|
||||||
4CF0ABDB2981A19E00D66079 /* ListTests.swift */,
|
|
||||||
);
|
);
|
||||||
path = damusTests;
|
path = damusTests;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -834,32 +777,6 @@
|
|||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
4CF0ABDF2981A83000D66079 /* Muting */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
4CF0ABE02981A83900D66079 /* MutelistView.swift */,
|
|
||||||
);
|
|
||||||
path = Muting;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
4CF0ABEA29844B2F00D66079 /* AnyCodable */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
4CF0ABE829844AF100D66079 /* AnyCodable.swift */,
|
|
||||||
4CF0ABEB29844B4700D66079 /* AnyDecodable.swift */,
|
|
||||||
4CF0ABED29844B5500D66079 /* AnyEncodable.swift */,
|
|
||||||
);
|
|
||||||
path = AnyCodable;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
4CF0ABF42985CD4200D66079 /* Posting */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
4CF0ABF52985CD5500D66079 /* UserSearch.swift */,
|
|
||||||
);
|
|
||||||
path = Posting;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
F7F0BA23297892AE009531F3 /* Modifiers */ = {
|
F7F0BA23297892AE009531F3 /* Modifiers */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -889,6 +806,8 @@
|
|||||||
4C649880286E0EE300EAE2B3 /* secp256k1 */,
|
4C649880286E0EE300EAE2B3 /* secp256k1 */,
|
||||||
4C06670328FC7EC500038D2A /* Kingfisher */,
|
4C06670328FC7EC500038D2A /* Kingfisher */,
|
||||||
6C7DE41E2955169800E66263 /* Vault */,
|
6C7DE41E2955169800E66263 /* Vault */,
|
||||||
|
7C45AE6C297352F90031D7BC /* SVGKit */,
|
||||||
|
7C45AE6E297352F90031D7BC /* SVGKitSwift */,
|
||||||
);
|
);
|
||||||
productName = damus;
|
productName = damus;
|
||||||
productReference = 4CE6DEE327F7A08100C66700 /* damus.app */;
|
productReference = 4CE6DEE327F7A08100C66700 /* damus.app */;
|
||||||
@@ -963,11 +882,9 @@
|
|||||||
"es-419",
|
"es-419",
|
||||||
"en-US",
|
"en-US",
|
||||||
"de-AT",
|
"de-AT",
|
||||||
|
"de-DE",
|
||||||
"tr-TR",
|
"tr-TR",
|
||||||
"fr-FR",
|
"fr-FR",
|
||||||
"lv-LV",
|
|
||||||
"it-IT",
|
|
||||||
de,
|
|
||||||
);
|
);
|
||||||
mainGroup = 4CE6DEDA27F7A08100C66700;
|
mainGroup = 4CE6DEDA27F7A08100C66700;
|
||||||
packageReferences = (
|
packageReferences = (
|
||||||
@@ -975,6 +892,7 @@
|
|||||||
4C64987F286E0EE300EAE2B3 /* XCRemoteSwiftPackageReference "secp256k1" */,
|
4C64987F286E0EE300EAE2B3 /* XCRemoteSwiftPackageReference "secp256k1" */,
|
||||||
4C06670228FC7EC500038D2A /* XCRemoteSwiftPackageReference "Kingfisher" */,
|
4C06670228FC7EC500038D2A /* XCRemoteSwiftPackageReference "Kingfisher" */,
|
||||||
6C7DE41D2955169800E66263 /* XCRemoteSwiftPackageReference "Vault" */,
|
6C7DE41D2955169800E66263 /* XCRemoteSwiftPackageReference "Vault" */,
|
||||||
|
7C45AE6B297352F90031D7BC /* XCRemoteSwiftPackageReference "SVGKit" */,
|
||||||
);
|
);
|
||||||
productRefGroup = 4CE6DEE427F7A08100C66700 /* Products */;
|
productRefGroup = 4CE6DEE427F7A08100C66700 /* Products */;
|
||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
@@ -1028,15 +946,12 @@
|
|||||||
4C216F34286F5ACD00040376 /* DMView.swift in Sources */,
|
4C216F34286F5ACD00040376 /* DMView.swift in Sources */,
|
||||||
4C3EA64428FF558100C48A62 /* sha256.c in Sources */,
|
4C3EA64428FF558100C48A62 /* sha256.c in Sources */,
|
||||||
4CE4F9E1285287B800C00DD9 /* TextFieldAlert.swift in Sources */,
|
4CE4F9E1285287B800C00DD9 /* TextFieldAlert.swift in Sources */,
|
||||||
4CF0ABF62985CD5500D66079 /* UserSearch.swift in Sources */,
|
|
||||||
4C363AA828297703006E126D /* InsertSort.swift in Sources */,
|
4C363AA828297703006E126D /* InsertSort.swift in Sources */,
|
||||||
4C285C86283892E7008A31F1 /* CreateAccountModel.swift in Sources */,
|
4C285C86283892E7008A31F1 /* CreateAccountModel.swift in Sources */,
|
||||||
4C64987C286D03E000EAE2B3 /* DirectMessagesView.swift in Sources */,
|
4C64987C286D03E000EAE2B3 /* DirectMessagesView.swift in Sources */,
|
||||||
7C902AE32981D55B002AB16E /* ZoomableScrollView.swift in Sources */,
|
|
||||||
4C363A8C28236B92006E126D /* PubkeyView.swift in Sources */,
|
4C363A8C28236B92006E126D /* PubkeyView.swift in Sources */,
|
||||||
4C5C7E68284ED36500A22DF5 /* SearchHomeModel.swift in Sources */,
|
4C5C7E68284ED36500A22DF5 /* SearchHomeModel.swift in Sources */,
|
||||||
4C75EFB728049D990006080F /* RelayPool.swift in Sources */,
|
4C75EFB728049D990006080F /* RelayPool.swift in Sources */,
|
||||||
4CF0ABEE29844B5500D66079 /* AnyEncodable.swift in Sources */,
|
|
||||||
4CB8838D296F710400DC99E7 /* Reposted.swift in Sources */,
|
4CB8838D296F710400DC99E7 /* Reposted.swift in Sources */,
|
||||||
4C3EA67728FF7A9800C48A62 /* talstr.c in Sources */,
|
4C3EA67728FF7A9800C48A62 /* talstr.c in Sources */,
|
||||||
4CE6DEE927F7A08100C66700 /* ContentView.swift in Sources */,
|
4CE6DEE927F7A08100C66700 /* ContentView.swift in Sources */,
|
||||||
@@ -1057,8 +972,6 @@
|
|||||||
647D9A8D2968520300A295DE /* SideMenuView.swift in Sources */,
|
647D9A8D2968520300A295DE /* SideMenuView.swift in Sources */,
|
||||||
F7F0BA272978E54D009531F3 /* ParicipantsView.swift in Sources */,
|
F7F0BA272978E54D009531F3 /* ParicipantsView.swift in Sources */,
|
||||||
4C0A3F91280F6528000448DE /* ChatView.swift in Sources */,
|
4C0A3F91280F6528000448DE /* ChatView.swift in Sources */,
|
||||||
4CF0ABE32981BC7D00D66079 /* UserView.swift in Sources */,
|
|
||||||
4CF0ABF029857E9200D66079 /* Bech32Object.swift in Sources */,
|
|
||||||
4C216F362870A9A700040376 /* InputDismissKeyboard.swift in Sources */,
|
4C216F362870A9A700040376 /* InputDismissKeyboard.swift in Sources */,
|
||||||
4C216F382871EDE300040376 /* DirectMessageModel.swift in Sources */,
|
4C216F382871EDE300040376 /* DirectMessageModel.swift in Sources */,
|
||||||
4C75EFA627FF87A20006080F /* Nostr.swift in Sources */,
|
4C75EFA627FF87A20006080F /* Nostr.swift in Sources */,
|
||||||
@@ -1078,8 +991,6 @@
|
|||||||
4C3EA66828FF5F9900C48A62 /* hex.c in Sources */,
|
4C3EA66828FF5F9900C48A62 /* hex.c in Sources */,
|
||||||
E9E4ED0B295867B900DD7078 /* ThreadV2View.swift in Sources */,
|
E9E4ED0B295867B900DD7078 /* ThreadV2View.swift in Sources */,
|
||||||
4C3BEFDC281DCE6100B3DE84 /* Liked.swift in Sources */,
|
4C3BEFDC281DCE6100B3DE84 /* Liked.swift in Sources */,
|
||||||
4CF0ABE7298444FD00D66079 /* MutedEventView.swift in Sources */,
|
|
||||||
4CF0ABE12981A83900D66079 /* MutelistView.swift in Sources */,
|
|
||||||
4C75EFB128049D510006080F /* NostrResponse.swift in Sources */,
|
4C75EFB128049D510006080F /* NostrResponse.swift in Sources */,
|
||||||
4CEE2AF7280B2DEA00AB5EEF /* ProfileName.swift in Sources */,
|
4CEE2AF7280B2DEA00AB5EEF /* ProfileName.swift in Sources */,
|
||||||
4CC7AAEB297F0AEC00430951 /* BuilderEventView.swift in Sources */,
|
4CC7AAEB297F0AEC00430951 /* BuilderEventView.swift in Sources */,
|
||||||
@@ -1089,7 +1000,6 @@
|
|||||||
4CEE2B02280B39E800AB5EEF /* EventActionBar.swift in Sources */,
|
4CEE2B02280B39E800AB5EEF /* EventActionBar.swift in Sources */,
|
||||||
4C3BEFE0281DE1ED00B3DE84 /* DamusState.swift in Sources */,
|
4C3BEFE0281DE1ED00B3DE84 /* DamusState.swift in Sources */,
|
||||||
7C45AE71297353390031D7BC /* KFImageModel.swift in Sources */,
|
7C45AE71297353390031D7BC /* KFImageModel.swift in Sources */,
|
||||||
4CF0ABE929844AF100D66079 /* AnyCodable.swift in Sources */,
|
|
||||||
4C0A3F8F280F640A000448DE /* ThreadModel.swift in Sources */,
|
4C0A3F8F280F640A000448DE /* ThreadModel.swift in Sources */,
|
||||||
4CC7AAF2297F129C00430951 /* EmbeddedEventView.swift in Sources */,
|
4CC7AAF2297F129C00430951 /* EmbeddedEventView.swift in Sources */,
|
||||||
4C3AC79F2833115300E1F516 /* FollowButtonView.swift in Sources */,
|
4C3AC79F2833115300E1F516 /* FollowButtonView.swift in Sources */,
|
||||||
@@ -1122,20 +1032,15 @@
|
|||||||
3AA24802297E3DC20090C62D /* RepostView.swift in Sources */,
|
3AA24802297E3DC20090C62D /* RepostView.swift in Sources */,
|
||||||
4CD7641B28A1641400B6928F /* EndBlock.swift in Sources */,
|
4CD7641B28A1641400B6928F /* EndBlock.swift in Sources */,
|
||||||
4C3EA66528FF5F6800C48A62 /* mem.c in Sources */,
|
4C3EA66528FF5F6800C48A62 /* mem.c in Sources */,
|
||||||
4CF0ABE52981EE0C00D66079 /* EULAView.swift in Sources */,
|
|
||||||
4CBCA930297DB57F00EC6B2F /* WebsiteLink.swift in Sources */,
|
4CBCA930297DB57F00EC6B2F /* WebsiteLink.swift in Sources */,
|
||||||
4C3EA64128FF553900C48A62 /* hash_u5.c in Sources */,
|
4C3EA64128FF553900C48A62 /* hash_u5.c in Sources */,
|
||||||
5C513FCC2984ACA60072348F /* QRCodeView.swift in Sources */,
|
|
||||||
4C3EA64F28FF59F200C48A62 /* tal.c in Sources */,
|
4C3EA64F28FF59F200C48A62 /* tal.c in Sources */,
|
||||||
4CB88393296F798300DC99E7 /* ReactionsModel.swift in Sources */,
|
4CB88393296F798300DC99E7 /* ReactionsModel.swift in Sources */,
|
||||||
4CB88396296F7F8B00DC99E7 /* ReactionView.swift in Sources */,
|
4CB88396296F7F8B00DC99E7 /* ReactionView.swift in Sources */,
|
||||||
4C8682872814DE470026224F /* ProfileView.swift in Sources */,
|
4C8682872814DE470026224F /* ProfileView.swift in Sources */,
|
||||||
4C5F9114283D694D0052CD1C /* FollowTarget.swift in Sources */,
|
4C5F9114283D694D0052CD1C /* FollowTarget.swift in Sources */,
|
||||||
4CF0ABD629817F5B00D66079 /* ReportView.swift in Sources */,
|
|
||||||
4CB8838629656C8B00DC99E7 /* NIP05.swift in Sources */,
|
4CB8838629656C8B00DC99E7 /* NIP05.swift in Sources */,
|
||||||
4CF0ABD82981980C00D66079 /* Lists.swift in Sources */,
|
|
||||||
4C5C7E6A284EDE2E00A22DF5 /* SearchResultsView.swift in Sources */,
|
4C5C7E6A284EDE2E00A22DF5 /* SearchResultsView.swift in Sources */,
|
||||||
7C60CAEF298471A1009C80D6 /* CoreSVG.swift in Sources */,
|
|
||||||
6439E014296790CF0020672B /* ProfileZoomView.swift in Sources */,
|
6439E014296790CF0020672B /* ProfileZoomView.swift in Sources */,
|
||||||
4CE6DF1627F8DEBF00C66700 /* RelayConnection.swift in Sources */,
|
4CE6DF1627F8DEBF00C66700 /* RelayConnection.swift in Sources */,
|
||||||
4C3BEFD6281D995700B3DE84 /* ActionBarModel.swift in Sources */,
|
4C3BEFD6281D995700B3DE84 /* ActionBarModel.swift in Sources */,
|
||||||
@@ -1157,11 +1062,9 @@
|
|||||||
4C0A3F95280F6C78000448DE /* ReplyQuoteView.swift in Sources */,
|
4C0A3F95280F6C78000448DE /* ReplyQuoteView.swift in Sources */,
|
||||||
4C3BEFDA281DCA1400B3DE84 /* LikeCounter.swift in Sources */,
|
4C3BEFDA281DCA1400B3DE84 /* LikeCounter.swift in Sources */,
|
||||||
4CB88389296AF99A00DC99E7 /* EventDetailBar.swift in Sources */,
|
4CB88389296AF99A00DC99E7 /* EventDetailBar.swift in Sources */,
|
||||||
4CF0ABDE2981A69500D66079 /* MutelistModel.swift in Sources */,
|
|
||||||
4C3AC79B28306D7B00E1F516 /* Contacts.swift in Sources */,
|
4C3AC79B28306D7B00E1F516 /* Contacts.swift in Sources */,
|
||||||
4C3EA63D28FF52D600C48A62 /* bolt11.c in Sources */,
|
4C3EA63D28FF52D600C48A62 /* bolt11.c in Sources */,
|
||||||
4CB55EF3295E5D59007FD187 /* RecommendedRelayView.swift in Sources */,
|
4CB55EF3295E5D59007FD187 /* RecommendedRelayView.swift in Sources */,
|
||||||
4CF0ABEC29844B4700D66079 /* AnyDecodable.swift in Sources */,
|
|
||||||
4C5F9118283D88E40052CD1C /* FollowingModel.swift in Sources */,
|
4C5F9118283D88E40052CD1C /* FollowingModel.swift in Sources */,
|
||||||
4C3EA67D28FFBBA300C48A62 /* InvoicesView.swift in Sources */,
|
4C3EA67D28FFBBA300C48A62 /* InvoicesView.swift in Sources */,
|
||||||
4C363A8E28236FE4006E126D /* NoteContentView.swift in Sources */,
|
4C363A8E28236FE4006E126D /* NoteContentView.swift in Sources */,
|
||||||
@@ -1169,18 +1072,15 @@
|
|||||||
E990020F2955F837003BBC5A /* EditMetadataView.swift in Sources */,
|
E990020F2955F837003BBC5A /* EditMetadataView.swift in Sources */,
|
||||||
4CACA9D5280C31E100D9BBE8 /* ReplyView.swift in Sources */,
|
4CACA9D5280C31E100D9BBE8 /* ReplyView.swift in Sources */,
|
||||||
4C3A1D332960DB0500558C0F /* Markdown.swift in Sources */,
|
4C3A1D332960DB0500558C0F /* Markdown.swift in Sources */,
|
||||||
4CF0ABD42980996B00D66079 /* Report.swift in Sources */,
|
|
||||||
4C0A3F97280F8E02000448DE /* ThreadView.swift in Sources */,
|
4C0A3F97280F8E02000448DE /* ThreadView.swift in Sources */,
|
||||||
4C06670B28FDE64700038D2A /* damus.c in Sources */,
|
4C06670B28FDE64700038D2A /* damus.c in Sources */,
|
||||||
4FE60CDD295E1C5E00105A1F /* Wallet.swift in Sources */,
|
4FE60CDD295E1C5E00105A1F /* Wallet.swift in Sources */,
|
||||||
3AA247FF297E3D900090C62D /* RepostsView.swift in Sources */,
|
3AA247FF297E3D900090C62D /* RepostsView.swift in Sources */,
|
||||||
3AE45AF6297BB2E700C1D842 /* LibreTranslateServer.swift in Sources */,
|
|
||||||
4C99737B28C92A9200E53835 /* ChatroomMetadata.swift in Sources */,
|
4C99737B28C92A9200E53835 /* ChatroomMetadata.swift in Sources */,
|
||||||
4CC7AAF4297F18B400430951 /* ReplyDescription.swift in Sources */,
|
4CC7AAF4297F18B400430951 /* ReplyDescription.swift in Sources */,
|
||||||
4C75EFA427FA577B0006080F /* PostView.swift in Sources */,
|
4C75EFA427FA577B0006080F /* PostView.swift in Sources */,
|
||||||
4C75EFB528049D790006080F /* Relay.swift in Sources */,
|
4C75EFB528049D790006080F /* Relay.swift in Sources */,
|
||||||
4CEE2AF1280B216B00AB5EEF /* EventDetailView.swift in Sources */,
|
4CEE2AF1280B216B00AB5EEF /* EventDetailView.swift in Sources */,
|
||||||
4CC7AAFA297F64AC00430951 /* EventMenu.swift in Sources */,
|
|
||||||
4C75EFBB2804A34C0006080F /* ProofOfWork.swift in Sources */,
|
4C75EFBB2804A34C0006080F /* ProofOfWork.swift in Sources */,
|
||||||
4C3AC7A52836987600E1F516 /* MainTabView.swift in Sources */,
|
4C3AC7A52836987600E1F516 /* MainTabView.swift in Sources */,
|
||||||
3169CAED294FCCFC00EE4006 /* Constants.swift in Sources */,
|
3169CAED294FCCFC00EE4006 /* Constants.swift in Sources */,
|
||||||
@@ -1199,7 +1099,6 @@
|
|||||||
4C363AA02828A8DD006E126D /* LikeTests.swift in Sources */,
|
4C363AA02828A8DD006E126D /* LikeTests.swift in Sources */,
|
||||||
4C90BD1C283AC38E008EE7EF /* Bech32Tests.swift in Sources */,
|
4C90BD1C283AC38E008EE7EF /* Bech32Tests.swift in Sources */,
|
||||||
4CE6DEF827F7A08200C66700 /* damusTests.swift in Sources */,
|
4CE6DEF827F7A08200C66700 /* damusTests.swift in Sources */,
|
||||||
4CF0ABDC2981A19E00D66079 /* ListTests.swift in Sources */,
|
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -1234,11 +1133,9 @@
|
|||||||
3A5C4575296A879E0032D398 /* es-419 */,
|
3A5C4575296A879E0032D398 /* es-419 */,
|
||||||
3A2B8B0A296A8982009CC16D /* en-US */,
|
3A2B8B0A296A8982009CC16D /* en-US */,
|
||||||
3A5EA111297CCF6C00569477 /* de-AT */,
|
3A5EA111297CCF6C00569477 /* de-AT */,
|
||||||
|
3AEABD22297CCFA8003F2975 /* de-DE */,
|
||||||
3AEB8005297CCEA900713A25 /* tr-TR */,
|
3AEB8005297CCEA900713A25 /* tr-TR */,
|
||||||
3A4F3322297CCFEE004B5F72 /* fr-FR */,
|
3A4F3322297CCFEE004B5F72 /* fr-FR */,
|
||||||
3A185A06297F2C3800F4BDC0 /* lv-LV */,
|
|
||||||
3A929C22297F2CF80090925E /* it-IT */,
|
|
||||||
3AB5B86C2986D8A3006599D2 /* de */,
|
|
||||||
);
|
);
|
||||||
name = Localizable.stringsdict;
|
name = Localizable.stringsdict;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -1248,11 +1145,9 @@
|
|||||||
children = (
|
children = (
|
||||||
3ACB685B297633BC00C46468 /* es-419 */,
|
3ACB685B297633BC00C46468 /* es-419 */,
|
||||||
3A5EA10F297CCF6C00569477 /* de-AT */,
|
3A5EA10F297CCF6C00569477 /* de-AT */,
|
||||||
|
3AEABD20297CCFA8003F2975 /* de-DE */,
|
||||||
3AEB8003297CCEA800713A25 /* tr-TR */,
|
3AEB8003297CCEA800713A25 /* tr-TR */,
|
||||||
3A4F3320297CCFEE004B5F72 /* fr-FR */,
|
3A4F3320297CCFEE004B5F72 /* fr-FR */,
|
||||||
3A185A04297F2C3800F4BDC0 /* lv-LV */,
|
|
||||||
3A929C20297F2CF80090925E /* it-IT */,
|
|
||||||
3AB5B86A2986D8A3006599D2 /* de */,
|
|
||||||
);
|
);
|
||||||
name = InfoPlist.strings;
|
name = InfoPlist.strings;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -1262,11 +1157,9 @@
|
|||||||
children = (
|
children = (
|
||||||
3ACB685E297633BC00C46468 /* es-419 */,
|
3ACB685E297633BC00C46468 /* es-419 */,
|
||||||
3A5EA110297CCF6C00569477 /* de-AT */,
|
3A5EA110297CCF6C00569477 /* de-AT */,
|
||||||
|
3AEABD21297CCFA8003F2975 /* de-DE */,
|
||||||
3AEB8004297CCEA800713A25 /* tr-TR */,
|
3AEB8004297CCEA800713A25 /* tr-TR */,
|
||||||
3A4F3321297CCFEE004B5F72 /* fr-FR */,
|
3A4F3321297CCFEE004B5F72 /* fr-FR */,
|
||||||
3A185A05297F2C3800F4BDC0 /* lv-LV */,
|
|
||||||
3A929C21297F2CF80090925E /* it-IT */,
|
|
||||||
3AB5B86B2986D8A3006599D2 /* de */,
|
|
||||||
);
|
);
|
||||||
name = Localizable.strings;
|
name = Localizable.strings;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -1402,7 +1295,7 @@
|
|||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = damus/damus.entitlements;
|
CODE_SIGN_ENTITLEMENTS = damus/damus.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 12;
|
CURRENT_PROJECT_VERSION = 9;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"damus/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"damus/Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = XK7H4JAB3D;
|
DEVELOPMENT_TEAM = XK7H4JAB3D;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
@@ -1443,7 +1336,7 @@
|
|||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = damus/damus.entitlements;
|
CODE_SIGN_ENTITLEMENTS = damus/damus.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 12;
|
CURRENT_PROJECT_VERSION = 9;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"damus/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"damus/Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = XK7H4JAB3D;
|
DEVELOPMENT_TEAM = XK7H4JAB3D;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
@@ -1625,6 +1518,14 @@
|
|||||||
minimumVersion = 1.0.0;
|
minimumVersion = 1.0.0;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
7C45AE6B297352F90031D7BC /* XCRemoteSwiftPackageReference "SVGKit" */ = {
|
||||||
|
isa = XCRemoteSwiftPackageReference;
|
||||||
|
repositoryURL = "https://github.com/SVGKit/SVGKit";
|
||||||
|
requirement = {
|
||||||
|
kind = revision;
|
||||||
|
revision = e1f13e27b1e4c0ffe20e7d8d3984bf49c2a584d0;
|
||||||
|
};
|
||||||
|
};
|
||||||
/* End XCRemoteSwiftPackageReference section */
|
/* End XCRemoteSwiftPackageReference section */
|
||||||
|
|
||||||
/* Begin XCSwiftPackageProductDependency section */
|
/* Begin XCSwiftPackageProductDependency section */
|
||||||
@@ -1648,6 +1549,16 @@
|
|||||||
package = 6C7DE41D2955169800E66263 /* XCRemoteSwiftPackageReference "Vault" */;
|
package = 6C7DE41D2955169800E66263 /* XCRemoteSwiftPackageReference "Vault" */;
|
||||||
productName = Vault;
|
productName = Vault;
|
||||||
};
|
};
|
||||||
|
7C45AE6C297352F90031D7BC /* SVGKit */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = 7C45AE6B297352F90031D7BC /* XCRemoteSwiftPackageReference "SVGKit" */;
|
||||||
|
productName = SVGKit;
|
||||||
|
};
|
||||||
|
7C45AE6E297352F90031D7BC /* SVGKitSwift */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = 7C45AE6B297352F90031D7BC /* XCRemoteSwiftPackageReference "SVGKit" */;
|
||||||
|
productName = SVGKitSwift;
|
||||||
|
};
|
||||||
/* End XCSwiftPackageProductDependency section */
|
/* End XCSwiftPackageProductDependency section */
|
||||||
};
|
};
|
||||||
rootObject = 4CE6DEDB27F7A08100C66700 /* Project object */;
|
rootObject = 4CE6DEDB27F7A08100C66700 /* Project object */;
|
||||||
|
|||||||
@@ -26,6 +26,14 @@
|
|||||||
"version" : "4.0.4"
|
"version" : "4.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"identity" : "svgkit",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/SVGKit/SVGKit",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "e1f13e27b1e4c0ffe20e7d8d3984bf49c2a584d0"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"identity" : "vault",
|
"identity" : "vault",
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
|
|||||||
@@ -1,98 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<Scheme
|
|
||||||
LastUpgradeVersion = "1420"
|
|
||||||
version = "1.3">
|
|
||||||
<BuildAction
|
|
||||||
parallelizeBuildables = "YES"
|
|
||||||
buildImplicitDependencies = "YES">
|
|
||||||
<BuildActionEntries>
|
|
||||||
<BuildActionEntry
|
|
||||||
buildForTesting = "YES"
|
|
||||||
buildForRunning = "YES"
|
|
||||||
buildForProfiling = "YES"
|
|
||||||
buildForArchiving = "YES"
|
|
||||||
buildForAnalyzing = "YES">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "4CE6DEE227F7A08100C66700"
|
|
||||||
BuildableName = "damus.app"
|
|
||||||
BlueprintName = "damus"
|
|
||||||
ReferencedContainer = "container:damus.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildActionEntry>
|
|
||||||
</BuildActionEntries>
|
|
||||||
</BuildAction>
|
|
||||||
<TestAction
|
|
||||||
buildConfiguration = "Debug"
|
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
|
||||||
<Testables>
|
|
||||||
<TestableReference
|
|
||||||
skipped = "NO">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "4CE6DEF227F7A08200C66700"
|
|
||||||
BuildableName = "damusTests.xctest"
|
|
||||||
BlueprintName = "damusTests"
|
|
||||||
ReferencedContainer = "container:damus.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</TestableReference>
|
|
||||||
<TestableReference
|
|
||||||
skipped = "YES">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "4CE6DEFC27F7A08200C66700"
|
|
||||||
BuildableName = "damusUITests.xctest"
|
|
||||||
BlueprintName = "damusUITests"
|
|
||||||
ReferencedContainer = "container:damus.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</TestableReference>
|
|
||||||
</Testables>
|
|
||||||
</TestAction>
|
|
||||||
<LaunchAction
|
|
||||||
buildConfiguration = "Debug"
|
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
|
||||||
launchStyle = "0"
|
|
||||||
useCustomWorkingDirectory = "NO"
|
|
||||||
ignoresPersistentStateOnLaunch = "NO"
|
|
||||||
debugDocumentVersioning = "YES"
|
|
||||||
debugServiceExtension = "internal"
|
|
||||||
allowLocationSimulation = "YES">
|
|
||||||
<BuildableProductRunnable
|
|
||||||
runnableDebuggingMode = "0">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "4CE6DEE227F7A08100C66700"
|
|
||||||
BuildableName = "damus.app"
|
|
||||||
BlueprintName = "damus"
|
|
||||||
ReferencedContainer = "container:damus.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildableProductRunnable>
|
|
||||||
</LaunchAction>
|
|
||||||
<ProfileAction
|
|
||||||
buildConfiguration = "Release"
|
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
|
||||||
savedToolIdentifier = ""
|
|
||||||
useCustomWorkingDirectory = "NO"
|
|
||||||
debugDocumentVersioning = "YES">
|
|
||||||
<BuildableProductRunnable
|
|
||||||
runnableDebuggingMode = "0">
|
|
||||||
<BuildableReference
|
|
||||||
BuildableIdentifier = "primary"
|
|
||||||
BlueprintIdentifier = "4CE6DEE227F7A08100C66700"
|
|
||||||
BuildableName = "damus.app"
|
|
||||||
BlueprintName = "damus"
|
|
||||||
ReferencedContainer = "container:damus.xcodeproj">
|
|
||||||
</BuildableReference>
|
|
||||||
</BuildableProductRunnable>
|
|
||||||
</ProfileAction>
|
|
||||||
<AnalyzeAction
|
|
||||||
buildConfiguration = "Debug">
|
|
||||||
</AnalyzeAction>
|
|
||||||
<ArchiveAction
|
|
||||||
buildConfiguration = "Release"
|
|
||||||
revealArchiveInOrganizer = "YES">
|
|
||||||
</ArchiveAction>
|
|
||||||
</Scheme>
|
|
||||||
@@ -115,6 +115,56 @@ private struct ImageContainerView: View {
|
|||||||
// TODO: Update ImageCarousel with serializer and processor
|
// TODO: Update ImageCarousel with serializer and processor
|
||||||
// .serialize(by: imageModel.serializer)
|
// .serialize(by: imageModel.serializer)
|
||||||
// .setProcessor(imageModel.processor)
|
// .setProcessor(imageModel.processor)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ZoomableScrollView<Content: View>: UIViewRepresentable {
|
||||||
|
|
||||||
|
private var content: Content
|
||||||
|
|
||||||
|
init(@ViewBuilder content: () -> Content) {
|
||||||
|
self.content = content()
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeUIView(context: Context) -> UIScrollView {
|
||||||
|
let scrollView = UIScrollView()
|
||||||
|
scrollView.delegate = context.coordinator
|
||||||
|
scrollView.maximumZoomScale = 20
|
||||||
|
scrollView.minimumZoomScale = 1
|
||||||
|
scrollView.bouncesZoom = true
|
||||||
|
scrollView.showsVerticalScrollIndicator = false
|
||||||
|
scrollView.showsHorizontalScrollIndicator = false
|
||||||
|
|
||||||
|
let hostedView = context.coordinator.hostingController.view!
|
||||||
|
hostedView.translatesAutoresizingMaskIntoConstraints = true
|
||||||
|
hostedView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||||
|
hostedView.frame = scrollView.bounds
|
||||||
|
hostedView.backgroundColor = .clear
|
||||||
|
scrollView.addSubview(hostedView)
|
||||||
|
|
||||||
|
return scrollView
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeCoordinator() -> Coordinator {
|
||||||
|
return Coordinator(hostingController: UIHostingController(rootView: self.content))
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateUIView(_ uiView: UIScrollView, context: Context) {
|
||||||
|
context.coordinator.hostingController.rootView = self.content
|
||||||
|
assert(context.coordinator.hostingController.view.superview == uiView)
|
||||||
|
}
|
||||||
|
|
||||||
|
class Coordinator: NSObject, UIScrollViewDelegate {
|
||||||
|
var hostingController: UIHostingController<Content>
|
||||||
|
|
||||||
|
init(hostingController: UIHostingController<Content>) {
|
||||||
|
self.hostingController = hostingController
|
||||||
|
}
|
||||||
|
|
||||||
|
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
|
||||||
|
return hostingController.view
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,14 +177,6 @@ struct ImageView: View {
|
|||||||
@State private var selectedIndex = 0
|
@State private var selectedIndex = 0
|
||||||
@State var showMenu = true
|
@State var showMenu = true
|
||||||
|
|
||||||
var safeAreaInsets: UIEdgeInsets? {
|
|
||||||
return UIApplication
|
|
||||||
.shared
|
|
||||||
.connectedScenes
|
|
||||||
.flatMap { ($0 as? UIWindowScene)?.windows ?? [] }
|
|
||||||
.first { $0.isKeyWindow }?.safeAreaInsets
|
|
||||||
}
|
|
||||||
|
|
||||||
var navBarView: some View {
|
var navBarView: some View {
|
||||||
VStack {
|
VStack {
|
||||||
HStack {
|
HStack {
|
||||||
@@ -180,24 +222,22 @@ struct ImageView: View {
|
|||||||
ZoomableScrollView {
|
ZoomableScrollView {
|
||||||
ImageContainerView(url: urls[index])
|
ImageContainerView(url: urls[index])
|
||||||
.aspectRatio(contentMode: .fit)
|
.aspectRatio(contentMode: .fit)
|
||||||
.padding(.top, safeAreaInsets?.top)
|
|
||||||
.padding(.bottom, safeAreaInsets?.bottom)
|
|
||||||
}
|
}
|
||||||
|
.ignoresSafeArea()
|
||||||
|
.tag(index)
|
||||||
.modifier(SwipeToDismissModifier(minDistance: 50, onDismiss: {
|
.modifier(SwipeToDismissModifier(minDistance: 50, onDismiss: {
|
||||||
presentationMode.wrappedValue.dismiss()
|
presentationMode.wrappedValue.dismiss()
|
||||||
}))
|
}))
|
||||||
.ignoresSafeArea()
|
|
||||||
.tag(index)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.ignoresSafeArea()
|
.ignoresSafeArea()
|
||||||
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
|
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
|
||||||
.gesture(TapGesture(count: 2).onEnded {
|
.onChange(of: selectedIndex, perform: { _ in
|
||||||
// Prevents menu from hiding on double tap
|
showMenu = true
|
||||||
})
|
})
|
||||||
.gesture(TapGesture(count: 1).onEnded {
|
.onTapGesture {
|
||||||
showMenu.toggle()
|
showMenu.toggle()
|
||||||
})
|
}
|
||||||
.overlay(
|
.overlay(
|
||||||
VStack {
|
VStack {
|
||||||
if showMenu {
|
if showMenu {
|
||||||
@@ -210,7 +250,14 @@ struct ImageView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.animation(.easeInOut, value: showMenu)
|
.animation(.easeInOut, value: showMenu)
|
||||||
.padding(.bottom, safeAreaInsets?.bottom)
|
.padding(
|
||||||
|
.bottom,
|
||||||
|
UIApplication
|
||||||
|
.shared
|
||||||
|
.connectedScenes
|
||||||
|
.flatMap { ($0 as? UIWindowScene)?.windows ?? [] }
|
||||||
|
.first { $0.isKeyWindow }?.safeAreaInsets.bottom
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ struct InvoiceView: View {
|
|||||||
|
|
||||||
let invoice: Invoice
|
let invoice: Invoice
|
||||||
@State var showing_select_wallet: Bool = false
|
@State var showing_select_wallet: Bool = false
|
||||||
@EnvironmentObject var user_settings: UserSettingsStore
|
@ObservedObject var user_settings = UserSettingsStore()
|
||||||
|
|
||||||
var PayButton: some View {
|
var PayButton: some View {
|
||||||
Button {
|
Button {
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
//
|
|
||||||
// UserView.swift
|
|
||||||
// damus
|
|
||||||
//
|
|
||||||
// Created by William Casarin on 2023-01-25.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct UserView: View {
|
|
||||||
let damus_state: DamusState
|
|
||||||
let pubkey: String
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
let pmodel = ProfileModel(pubkey: pubkey, damus: damus_state)
|
|
||||||
let followers = FollowersModel(damus_state: damus_state, target: pubkey)
|
|
||||||
let pv = ProfileView(damus_state: damus_state, profile: pmodel, followers: followers)
|
|
||||||
|
|
||||||
NavigationLink(destination: pv) {
|
|
||||||
ProfilePicView(pubkey: pubkey, size: PFP_SIZE, highlight: .none, profiles: damus_state.profiles)
|
|
||||||
|
|
||||||
VStack(alignment: .leading) {
|
|
||||||
let profile = damus_state.profiles.lookup(id: pubkey)
|
|
||||||
ProfileName(pubkey: pubkey, profile: profile, damus: damus_state, show_friend_confirmed: false, show_nip5_domain: false)
|
|
||||||
if let about = profile?.about {
|
|
||||||
Text(about)
|
|
||||||
.lineLimit(3)
|
|
||||||
.font(.footnote)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
}
|
|
||||||
.buttonStyle(PlainButtonStyle())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct UserView_Previews: PreviewProvider {
|
|
||||||
static var previews: some View {
|
|
||||||
UserView(damus_state: test_damus_state(), pubkey: "pk")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,152 +0,0 @@
|
|||||||
//
|
|
||||||
// ZoomableScrollView.swift
|
|
||||||
// damus
|
|
||||||
//
|
|
||||||
// Created by Oleg Abalonski on 1/25/23.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct ZoomableScrollView<Content: View>: UIViewRepresentable {
|
|
||||||
|
|
||||||
private var content: Content
|
|
||||||
|
|
||||||
init(@ViewBuilder content: () -> Content) {
|
|
||||||
self.content = content()
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeUIView(context: Context) -> UIScrollView {
|
|
||||||
let scrollView = GesturedScrollView()
|
|
||||||
scrollView.delegate = context.coordinator
|
|
||||||
scrollView.maximumZoomScale = 20
|
|
||||||
scrollView.minimumZoomScale = 1
|
|
||||||
scrollView.bouncesZoom = true
|
|
||||||
scrollView.showsVerticalScrollIndicator = false
|
|
||||||
scrollView.showsHorizontalScrollIndicator = false
|
|
||||||
|
|
||||||
let hostedView = context.coordinator.hostingController.view!
|
|
||||||
hostedView.translatesAutoresizingMaskIntoConstraints = true
|
|
||||||
hostedView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
|
||||||
hostedView.frame = scrollView.bounds
|
|
||||||
hostedView.backgroundColor = .clear
|
|
||||||
scrollView.addSubview(hostedView)
|
|
||||||
|
|
||||||
return scrollView
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeCoordinator() -> Coordinator {
|
|
||||||
return Coordinator(hostingController: UIHostingController(rootView: self.content, ignoreSafeArea: true))
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateUIView(_ uiView: UIScrollView, context: Context) {
|
|
||||||
context.coordinator.hostingController.rootView = self.content
|
|
||||||
assert(context.coordinator.hostingController.view.superview == uiView)
|
|
||||||
}
|
|
||||||
|
|
||||||
class Coordinator: NSObject, UIScrollViewDelegate {
|
|
||||||
var hostingController: UIHostingController<Content>
|
|
||||||
|
|
||||||
init(hostingController: UIHostingController<Content>) {
|
|
||||||
self.hostingController = hostingController
|
|
||||||
}
|
|
||||||
|
|
||||||
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
|
|
||||||
return hostingController.view
|
|
||||||
}
|
|
||||||
|
|
||||||
func scrollViewDidZoom(_ scrollView: UIScrollView) {
|
|
||||||
let viewSize = hostingController.view.frame.size
|
|
||||||
guard let imageSize = scrollView.subviews[0].subviews.last?.frame.size else { return }
|
|
||||||
|
|
||||||
if scrollView.zoomScale > 1 {
|
|
||||||
|
|
||||||
let ratioW = viewSize.width / imageSize.width
|
|
||||||
let ratioH = viewSize.height / imageSize.height
|
|
||||||
|
|
||||||
let ratio = ratioW < ratioH ? ratioW:ratioH
|
|
||||||
|
|
||||||
let newWidth = imageSize.width * ratio
|
|
||||||
let newHeight = imageSize.height * ratio
|
|
||||||
|
|
||||||
let left = 0.5 * (newWidth * scrollView.zoomScale > viewSize.width ? (newWidth - viewSize.width) : (scrollView.frame.width - scrollView.contentSize.width))
|
|
||||||
let top = 0.5 * (newHeight * scrollView.zoomScale > viewSize.height ? (newHeight - viewSize.height) : (scrollView.frame.height - scrollView.contentSize.height))
|
|
||||||
|
|
||||||
scrollView.contentInset = UIEdgeInsets(top: top, left: left, bottom: top, right: left)
|
|
||||||
} else {
|
|
||||||
scrollView.contentInset = .zero
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fileprivate class GesturedScrollView: UIScrollView, UIGestureRecognizerDelegate {
|
|
||||||
|
|
||||||
let doubleTapGesture: UITapGestureRecognizer
|
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
|
||||||
doubleTapGesture = UITapGestureRecognizer()
|
|
||||||
super.init(frame: frame)
|
|
||||||
doubleTapGesture.addTarget(self, action: #selector(handleDoubleTap))
|
|
||||||
doubleTapGesture.numberOfTapsRequired = 2
|
|
||||||
addGestureRecognizer(doubleTapGesture)
|
|
||||||
doubleTapGesture.delegate = self
|
|
||||||
}
|
|
||||||
|
|
||||||
required init?(coder: NSCoder) {
|
|
||||||
fatalError("init(coder:) has not been implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func handleDoubleTap(_ gesture: UITapGestureRecognizer) {
|
|
||||||
if self.zoomScale == 1 {
|
|
||||||
let pointInView = gesture.location(in: self.subviews.first)
|
|
||||||
let newZoomScale = self.maximumZoomScale / 4.0
|
|
||||||
let scrollViewSize = self.bounds.size
|
|
||||||
let width = scrollViewSize.width / newZoomScale
|
|
||||||
let height = scrollViewSize.height / newZoomScale
|
|
||||||
let originX = pointInView.x - (width / 2.0)
|
|
||||||
let originY = pointInView.y - (height / 2.0)
|
|
||||||
let zoomRect = CGRect(x: originX, y: originY, width: width, height: height)
|
|
||||||
self.zoom(to: zoomRect, animated: true)
|
|
||||||
} else {
|
|
||||||
self.setZoomScale(self.minimumZoomScale, animated: true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
|
||||||
return gestureRecognizer == doubleTapGesture
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fileprivate extension UIHostingController {
|
|
||||||
|
|
||||||
convenience init(rootView: Content, ignoreSafeArea: Bool) {
|
|
||||||
self.init(rootView: rootView)
|
|
||||||
|
|
||||||
if ignoreSafeArea {
|
|
||||||
disableSafeArea()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func disableSafeArea() {
|
|
||||||
guard let viewClass = object_getClass(view) else { return }
|
|
||||||
|
|
||||||
let viewSubclassName = String(cString: class_getName(viewClass)).appending("_IgnoreSafeArea")
|
|
||||||
if let viewSubclass = NSClassFromString(viewSubclassName) {
|
|
||||||
object_setClass(view, viewSubclass)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
guard let viewClassNameUtf8 = (viewSubclassName as NSString).utf8String else { return }
|
|
||||||
guard let viewSubclass = objc_allocateClassPair(viewClass, viewClassNameUtf8, 0) else { return }
|
|
||||||
|
|
||||||
if let method = class_getInstanceMethod(UIView.self, #selector(getter: UIView.safeAreaInsets)) {
|
|
||||||
let safeAreaInsets: @convention(block) (AnyObject) -> UIEdgeInsets = { _ in
|
|
||||||
return .zero
|
|
||||||
}
|
|
||||||
class_addMethod(viewSubclass, #selector(getter: UIView.safeAreaInsets), imp_implementationWithBlock(safeAreaInsets), method_getTypeEncoding(method))
|
|
||||||
}
|
|
||||||
|
|
||||||
objc_registerClassPair(viewSubclass)
|
|
||||||
object_setClass(view, viewSubclass)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+3
-119
@@ -11,11 +11,11 @@ import Kingfisher
|
|||||||
|
|
||||||
var BOOTSTRAP_RELAYS = [
|
var BOOTSTRAP_RELAYS = [
|
||||||
"wss://relay.damus.io",
|
"wss://relay.damus.io",
|
||||||
"wss://eden.nostr.land",
|
"wss://nostr-relay.wlvs.space",
|
||||||
"wss://nostr.fmt.wiz.biz",
|
"wss://nostr.fmt.wiz.biz",
|
||||||
"wss://relay.nostr.bg",
|
"wss://relay.nostr.bg",
|
||||||
"wss://nostr.oxtr.dev",
|
"wss://nostr.oxtr.dev",
|
||||||
"wss://relay.snort.social",
|
"wss://nostr.v0l.io",
|
||||||
"wss://brb.io",
|
"wss://brb.io",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -26,12 +26,10 @@ struct TimestampedProfile {
|
|||||||
|
|
||||||
enum Sheets: Identifiable {
|
enum Sheets: Identifiable {
|
||||||
case post
|
case post
|
||||||
case report(ReportTarget)
|
|
||||||
case reply(NostrEvent)
|
case reply(NostrEvent)
|
||||||
|
|
||||||
var id: String {
|
var id: String {
|
||||||
switch self {
|
switch self {
|
||||||
case .report: return "report"
|
|
||||||
case .post: return "post"
|
case .post: return "post"
|
||||||
case .reply(let ev): return "reply-" + ev.id
|
case .reply(let ev): return "reply-" + ev.id
|
||||||
}
|
}
|
||||||
@@ -81,10 +79,6 @@ struct ContentView: View {
|
|||||||
@State var profile_open: Bool = false
|
@State var profile_open: Bool = false
|
||||||
@State var thread_open: Bool = false
|
@State var thread_open: Bool = false
|
||||||
@State var search_open: Bool = false
|
@State var search_open: Bool = false
|
||||||
@State var blocking: String? = nil
|
|
||||||
@State var confirm_block: Bool = false
|
|
||||||
@State var user_blocked_confirm: Bool = false
|
|
||||||
@State var confirm_overwrite_mutelist: Bool = false
|
|
||||||
@State var filter_state : FilterState = .posts_and_replies
|
@State var filter_state : FilterState = .posts_and_replies
|
||||||
@State private var isSideBarOpened = false
|
@State private var isSideBarOpened = false
|
||||||
@StateObject var home: HomeModel = HomeModel()
|
@StateObject var home: HomeModel = HomeModel()
|
||||||
@@ -235,20 +229,6 @@ struct ContentView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func MaybeReportView(target: ReportTarget) -> some View {
|
|
||||||
Group {
|
|
||||||
if let ds = damus_state {
|
|
||||||
if let sec = ds.keypair.privkey {
|
|
||||||
ReportView(pool: ds.pool, target: target, privkey: sec)
|
|
||||||
} else {
|
|
||||||
EmptyView()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
EmptyView()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(alignment: .leading, spacing: 0) {
|
VStack(alignment: .leading, spacing: 0) {
|
||||||
if let damus = self.damus_state {
|
if let damus = self.damus_state {
|
||||||
@@ -292,7 +272,6 @@ struct ContentView: View {
|
|||||||
.padding([.bottom], 8)
|
.padding([.bottom], 8)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.environmentObject(user_settings)
|
|
||||||
.onAppear() {
|
.onAppear() {
|
||||||
self.connect()
|
self.connect()
|
||||||
//KingfisherManager.shared.cache.clearDiskCache()
|
//KingfisherManager.shared.cache.clearDiskCache()
|
||||||
@@ -300,10 +279,8 @@ struct ContentView: View {
|
|||||||
}
|
}
|
||||||
.sheet(item: $active_sheet) { item in
|
.sheet(item: $active_sheet) { item in
|
||||||
switch item {
|
switch item {
|
||||||
case .report(let target):
|
|
||||||
MaybeReportView(target: target)
|
|
||||||
case .post:
|
case .post:
|
||||||
PostView(replying_to: nil, references: [], damus_state: damus_state!)
|
PostView(replying_to: nil, references: [])
|
||||||
case .reply(let event):
|
case .reply(let event):
|
||||||
ReplyView(replying_to: event, damus: damus_state!)
|
ReplyView(replying_to: event, damus: damus_state!)
|
||||||
}
|
}
|
||||||
@@ -349,15 +326,6 @@ struct ContentView: View {
|
|||||||
}
|
}
|
||||||
.onReceive(handle_notify(.like)) { like in
|
.onReceive(handle_notify(.like)) { like in
|
||||||
}
|
}
|
||||||
.onReceive(handle_notify(.report)) { notif in
|
|
||||||
let target = notif.object as! ReportTarget
|
|
||||||
self.active_sheet = .report(target)
|
|
||||||
}
|
|
||||||
.onReceive(handle_notify(.block)) { notif in
|
|
||||||
let pubkey = notif.object as! String
|
|
||||||
self.blocking = pubkey
|
|
||||||
self.confirm_block = true
|
|
||||||
}
|
|
||||||
.onReceive(handle_notify(.broadcast_event)) { obj in
|
.onReceive(handle_notify(.broadcast_event)) { obj in
|
||||||
let ev = obj.object as! NostrEvent
|
let ev = obj.object as! NostrEvent
|
||||||
self.damus_state?.pool.send(.event(ev))
|
self.damus_state?.pool.send(.event(ev))
|
||||||
@@ -432,90 +400,6 @@ struct ContentView: View {
|
|||||||
.onReceive(timer) { n in
|
.onReceive(timer) { n in
|
||||||
self.damus_state?.pool.connect_to_disconnected()
|
self.damus_state?.pool.connect_to_disconnected()
|
||||||
}
|
}
|
||||||
.onReceive(handle_notify(.new_mutes)) { notif in
|
|
||||||
home.filter_muted()
|
|
||||||
}
|
|
||||||
.alert(NSLocalizedString("User blocked", comment: "Alert message to indicate "), isPresented: $user_blocked_confirm, actions: {
|
|
||||||
Button(NSLocalizedString("Thanks!", comment: "Button to close out of alert that informs that the action to block a user was successful.")) {
|
|
||||||
user_blocked_confirm = false
|
|
||||||
}
|
|
||||||
}, message: {
|
|
||||||
if let pubkey = self.blocking {
|
|
||||||
let profile = damus_state!.profiles.lookup(id: pubkey)
|
|
||||||
let name = Profile.displayName(profile: profile, pubkey: pubkey)
|
|
||||||
Text("\(name) has been blocked", comment: "Alert message that informs a user was blocked.")
|
|
||||||
} else {
|
|
||||||
Text("User has been blocked", comment: "Alert message that informs a user was blocked.")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.alert(NSLocalizedString("Create new mutelist", comment: "Title of alert prompting the user to create a new mutelist."), isPresented: $confirm_overwrite_mutelist, actions: {
|
|
||||||
Button(NSLocalizedString("Cancel", comment: "Button to cancel out of alert that creates a new mutelist.")) {
|
|
||||||
confirm_overwrite_mutelist = false
|
|
||||||
confirm_block = false
|
|
||||||
}
|
|
||||||
|
|
||||||
Button(NSLocalizedString("Yes, Overwrite", comment: "Text of button that confirms to overwrite the existing mutelist.")) {
|
|
||||||
guard let ds = damus_state else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let keypair = ds.keypair.to_full() else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let pubkey = blocking else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let mutelist = create_or_update_mutelist(keypair: keypair, mprev: nil, to_add: pubkey) else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
damus_state?.contacts.set_mutelist(mutelist)
|
|
||||||
ds.pool.send(.event(mutelist))
|
|
||||||
|
|
||||||
confirm_overwrite_mutelist = false
|
|
||||||
confirm_block = false
|
|
||||||
user_blocked_confirm = true
|
|
||||||
}
|
|
||||||
}, message: {
|
|
||||||
Text("No block list found, create a new one? This will overwrite any previous block lists.", comment: "Alert message prompt that asks if the user wants to create a new block list, overwriting previous block lists.")
|
|
||||||
})
|
|
||||||
.alert(NSLocalizedString("Block User", comment: "Title of alert for blocking a user."), isPresented: $confirm_block, actions: {
|
|
||||||
Button(NSLocalizedString("Cancel", comment: "Alert button to cancel out of alert for blocking a user."), role: .cancel) {
|
|
||||||
confirm_block = false
|
|
||||||
}
|
|
||||||
Button(NSLocalizedString("Block", comment: "Alert button to block a user."), role: .destructive) {
|
|
||||||
guard let ds = damus_state else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if ds.contacts.mutelist == nil {
|
|
||||||
confirm_overwrite_mutelist = true
|
|
||||||
} else {
|
|
||||||
guard let keypair = ds.keypair.to_full() else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
guard let pubkey = blocking else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let ev = create_or_update_mutelist(keypair: keypair, mprev: ds.contacts.mutelist, to_add: pubkey) else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
damus_state?.contacts.set_mutelist(ev)
|
|
||||||
ds.pool.send(.event(ev))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, message: {
|
|
||||||
if let pubkey = blocking {
|
|
||||||
let profile = damus_state?.profiles.lookup(id: pubkey)
|
|
||||||
let name = Profile.displayName(profile: profile, pubkey: pubkey)
|
|
||||||
Text("Block \(name)?", comment: "Alert message prompt to ask if a user should be blocked.")
|
|
||||||
} else {
|
|
||||||
Text("Could not find user to block...", comment: "Alert message to indicate that the blocked user could not be found.")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func switch_timeline(_ timeline: Timeline) {
|
func switch_timeline(_ timeline: Timeline) {
|
||||||
|
|||||||
@@ -11,51 +11,13 @@ import Foundation
|
|||||||
class Contacts {
|
class Contacts {
|
||||||
private var friends: Set<String> = Set()
|
private var friends: Set<String> = Set()
|
||||||
private var friend_of_friends: Set<String> = Set()
|
private var friend_of_friends: Set<String> = Set()
|
||||||
private var muted: Set<String> = Set()
|
|
||||||
|
|
||||||
let our_pubkey: String
|
let our_pubkey: String
|
||||||
var event: NostrEvent?
|
var event: NostrEvent?
|
||||||
var mutelist: NostrEvent?
|
|
||||||
|
|
||||||
init(our_pubkey: String) {
|
init(our_pubkey: String) {
|
||||||
self.our_pubkey = our_pubkey
|
self.our_pubkey = our_pubkey
|
||||||
}
|
}
|
||||||
|
|
||||||
func is_muted(_ pk: String) -> Bool {
|
|
||||||
return muted.contains(pk)
|
|
||||||
}
|
|
||||||
|
|
||||||
func set_mutelist(_ ev: NostrEvent) {
|
|
||||||
let oldlist = self.mutelist
|
|
||||||
self.mutelist = ev
|
|
||||||
|
|
||||||
let old = Set(oldlist?.referenced_pubkeys.map({ $0.ref_id }) ?? [])
|
|
||||||
let new = Set(ev.referenced_pubkeys.map({ $0.ref_id }))
|
|
||||||
let diff = old.symmetricDifference(new)
|
|
||||||
|
|
||||||
var new_mutes = Array<String>()
|
|
||||||
var new_unmutes = Array<String>()
|
|
||||||
|
|
||||||
for d in diff {
|
|
||||||
if new.contains(d) {
|
|
||||||
new_mutes.append(d)
|
|
||||||
} else {
|
|
||||||
new_unmutes.append(d)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: set local mutelist here
|
|
||||||
self.muted = Set(ev.referenced_pubkeys.map({ $0.ref_id }))
|
|
||||||
|
|
||||||
if new_mutes.count > 0 {
|
|
||||||
notify(.new_mutes, new_mutes)
|
|
||||||
}
|
|
||||||
|
|
||||||
if new_unmutes.count > 0 {
|
|
||||||
notify(.new_unmutes, new_unmutes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func get_friendosphere() -> [String] {
|
func get_friendosphere() -> [String] {
|
||||||
var fs = get_friend_list()
|
var fs = get_friend_list()
|
||||||
fs.append(contentsOf: get_friend_of_friend_list())
|
fs.append(contentsOf: get_friend_of_friend_list())
|
||||||
|
|||||||
@@ -98,8 +98,6 @@ class HomeModel: ObservableObject {
|
|||||||
handle_contact_event(sub_id: sub_id, relay_id: relay_id, ev: ev)
|
handle_contact_event(sub_id: sub_id, relay_id: relay_id, ev: ev)
|
||||||
case .metadata:
|
case .metadata:
|
||||||
handle_metadata_event(ev)
|
handle_metadata_event(ev)
|
||||||
case .list:
|
|
||||||
handle_list_event(ev)
|
|
||||||
case .boost:
|
case .boost:
|
||||||
handle_boost_event(sub_id: sub_id, ev)
|
handle_boost_event(sub_id: sub_id, ev)
|
||||||
case .like:
|
case .like:
|
||||||
@@ -126,12 +124,6 @@ class HomeModel: ObservableObject {
|
|||||||
func handle_channel_meta(_ ev: NostrEvent) {
|
func handle_channel_meta(_ ev: NostrEvent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func filter_muted() {
|
|
||||||
self.events = events.filter { !damus_state.contacts.is_muted($0.pubkey) }
|
|
||||||
self.dms.dms = dms.dms.filter { !damus_state.contacts.is_muted($0.0) }
|
|
||||||
self.notifications = notifications.filter { !damus_state.contacts.is_muted($0.pubkey) }
|
|
||||||
}
|
|
||||||
|
|
||||||
func handle_delete_event(_ ev: NostrEvent) {
|
func handle_delete_event(_ ev: NostrEvent) {
|
||||||
guard ev.is_valid else {
|
guard ev.is_valid else {
|
||||||
return
|
return
|
||||||
@@ -283,10 +275,6 @@ class HomeModel: ObservableObject {
|
|||||||
var our_contacts_filter = NostrFilter.filter_kinds([3, 0])
|
var our_contacts_filter = NostrFilter.filter_kinds([3, 0])
|
||||||
our_contacts_filter.authors = [damus_state.pubkey]
|
our_contacts_filter.authors = [damus_state.pubkey]
|
||||||
|
|
||||||
var our_blocklist_filter = NostrFilter.filter_kinds([30000])
|
|
||||||
our_blocklist_filter.parameter = ["mute"]
|
|
||||||
our_blocklist_filter.authors = [damus_state.pubkey]
|
|
||||||
|
|
||||||
var dms_filter = NostrFilter.filter_kinds([
|
var dms_filter = NostrFilter.filter_kinds([
|
||||||
NostrKind.dm.rawValue,
|
NostrKind.dm.rawValue,
|
||||||
])
|
])
|
||||||
@@ -323,7 +311,7 @@ class HomeModel: ObservableObject {
|
|||||||
|
|
||||||
var home_filters = [home_filter]
|
var home_filters = [home_filter]
|
||||||
var notifications_filters = [notifications_filter]
|
var notifications_filters = [notifications_filter]
|
||||||
var contacts_filters = [contacts_filter, our_contacts_filter, our_blocklist_filter]
|
var contacts_filters = [contacts_filter, our_contacts_filter]
|
||||||
var dms_filters = [dms_filter, our_dms_filter]
|
var dms_filters = [dms_filter, our_dms_filter]
|
||||||
|
|
||||||
let last_of_kind = relay_id.flatMap { last_event_of_kind[$0] } ?? [:]
|
let last_of_kind = relay_id.flatMap { last_event_of_kind[$0] } ?? [:]
|
||||||
@@ -348,29 +336,6 @@ class HomeModel: ObservableObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handle_list_event(_ ev: NostrEvent) {
|
|
||||||
// we only care about our lists
|
|
||||||
guard ev.pubkey == damus_state.pubkey else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if let mutelist = damus_state.contacts.mutelist {
|
|
||||||
if ev.created_at <= mutelist.created_at {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let name = get_referenced_ids(tags: ev.tags, key: "d").first else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
guard name.ref_id == "mute" else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
damus_state.contacts.set_mutelist(ev)
|
|
||||||
}
|
|
||||||
|
|
||||||
func handle_metadata_event(_ ev: NostrEvent) {
|
func handle_metadata_event(_ ev: NostrEvent) {
|
||||||
process_metadata_event(profiles: damus_state.profiles, ev: ev)
|
process_metadata_event(profiles: damus_state.profiles, ev: ev)
|
||||||
}
|
}
|
||||||
@@ -410,8 +375,12 @@ class HomeModel: ObservableObject {
|
|||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func should_hide_event(_ ev: NostrEvent) -> Bool {
|
||||||
|
return !ev.should_show_event
|
||||||
|
}
|
||||||
|
|
||||||
func handle_text_event(sub_id: String, _ ev: NostrEvent) {
|
func handle_text_event(sub_id: String, _ ev: NostrEvent) {
|
||||||
if should_hide_event(contacts: damus_state.contacts, ev: ev) {
|
if should_hide_event(ev) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -719,11 +688,3 @@ func event_has_our_pubkey(_ ev: NostrEvent, our_pubkey: String) -> Bool {
|
|||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func should_hide_event(contacts: Contacts, ev: NostrEvent) -> Bool {
|
|
||||||
if contacts.is_muted(ev.pubkey) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return !ev.should_show_event
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,8 +5,9 @@
|
|||||||
// Created by Oleg Abalonski on 1/11/23.
|
// Created by Oleg Abalonski on 1/11/23.
|
||||||
//
|
//
|
||||||
|
|
||||||
import UIKit
|
import Foundation
|
||||||
import Kingfisher
|
import Kingfisher
|
||||||
|
import SVGKit
|
||||||
|
|
||||||
class KFImageModel: ObservableObject {
|
class KFImageModel: ObservableObject {
|
||||||
|
|
||||||
@@ -79,15 +80,8 @@ struct CustomImageProcessor: ImageProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle SVG image
|
// Handle SVG image
|
||||||
if let dataString = String(data: data, encoding: .utf8),
|
if let svgImage = SVGKImage(data: data), let image = svgImage.uiImage {
|
||||||
let svg = SVG(dataString) {
|
return image.kf.scaled(to: options.scaleFactor)
|
||||||
|
|
||||||
let render = UIGraphicsImageRenderer(size: svg.size)
|
|
||||||
let image = render.image { context in
|
|
||||||
svg.draw(in: context.cgContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
return image.kf.scaled(to: options.scaleFactor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return DefaultImageProcessor.default.process(item: item, options: options)
|
return DefaultImageProcessor.default.process(item: item, options: options)
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
//
|
|
||||||
// LibreTranslateServer.swift
|
|
||||||
// damus
|
|
||||||
//
|
|
||||||
// Created by Terry Yiu on 1/21/23.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
enum LibreTranslateServer: String, CaseIterable, Identifiable {
|
|
||||||
var id: String { self.rawValue }
|
|
||||||
|
|
||||||
struct Model: Identifiable, Hashable {
|
|
||||||
var id: String { self.tag }
|
|
||||||
var tag: String
|
|
||||||
var displayName: String
|
|
||||||
var url: String?
|
|
||||||
}
|
|
||||||
|
|
||||||
case none
|
|
||||||
case argosopentech
|
|
||||||
case terraprint
|
|
||||||
case vern
|
|
||||||
case custom
|
|
||||||
|
|
||||||
var model: Model {
|
|
||||||
switch self {
|
|
||||||
case .none:
|
|
||||||
return .init(tag: self.rawValue, displayName: NSLocalizedString("None", comment: "Dropdown option for selecting no translation server."), url: nil)
|
|
||||||
case .argosopentech:
|
|
||||||
return .init(tag: self.rawValue, displayName: "translate.argosopentech.com", url: "https://translate.argosopentech.com")
|
|
||||||
case .terraprint:
|
|
||||||
return .init(tag: self.rawValue, displayName: "translate.terraprint.co", url: "https://translate.terraprint.co")
|
|
||||||
case .vern:
|
|
||||||
return .init(tag: self.rawValue, displayName: "lt.vern.cc", url: "https://lt.vern.cc")
|
|
||||||
case .custom:
|
|
||||||
return .init(tag: self.rawValue, displayName: NSLocalizedString("Custom", comment: "Dropdown option for selecting a custom translation server."), url: nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static var allModels: [Model] {
|
|
||||||
return Self.allCases.map { $0.model }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
//
|
|
||||||
// ListModel.swift
|
|
||||||
// damus
|
|
||||||
//
|
|
||||||
// Created by William Casarin on 2023-01-25.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
class MutelistModel: ObservableObject {
|
|
||||||
let contacts: Contacts
|
|
||||||
|
|
||||||
@Published var users: [String]
|
|
||||||
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
//
|
|
||||||
// Report.swift
|
|
||||||
// damus
|
|
||||||
//
|
|
||||||
// Created by William Casarin on 2023-01-24.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
enum ReportType: String {
|
|
||||||
case explicit
|
|
||||||
case illegal
|
|
||||||
case spam
|
|
||||||
case impersonation
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ReportNoteTarget {
|
|
||||||
let pubkey: String
|
|
||||||
let note_id: String
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ReportTarget {
|
|
||||||
case user(String)
|
|
||||||
case note(ReportNoteTarget)
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Report {
|
|
||||||
let type: ReportType
|
|
||||||
let target: ReportTarget
|
|
||||||
let message: String
|
|
||||||
}
|
|
||||||
|
|
||||||
func create_report_tags(target: ReportTarget, type: ReportType) -> [[String]] {
|
|
||||||
var tags: [[String]]
|
|
||||||
switch target {
|
|
||||||
case .user(let pubkey):
|
|
||||||
tags = [["p", pubkey]]
|
|
||||||
case .note(let notet):
|
|
||||||
tags = [["e", notet.note_id], ["p", notet.pubkey]]
|
|
||||||
}
|
|
||||||
|
|
||||||
tags.append(["report", type.rawValue])
|
|
||||||
return tags
|
|
||||||
}
|
|
||||||
|
|
||||||
func create_report_event(privkey: String, report: Report) -> NostrEvent? {
|
|
||||||
guard let pubkey = privkey_to_pubkey(privkey: privkey) else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
let kind = 1984
|
|
||||||
let tags = create_report_tags(target: report.target, type: report.type)
|
|
||||||
let ev = NostrEvent(content: report.message, pubkey: pubkey, kind: kind, tags: tags)
|
|
||||||
|
|
||||||
ev.id = calculate_event_id(ev: ev)
|
|
||||||
ev.sig = sign_event(privkey: privkey, ev: ev)
|
|
||||||
|
|
||||||
return ev
|
|
||||||
}
|
|
||||||
@@ -30,10 +30,6 @@ class SearchHomeModel: ObservableObject {
|
|||||||
return filter
|
return filter
|
||||||
}
|
}
|
||||||
|
|
||||||
func filter_muted() {
|
|
||||||
events = events.filter { !should_hide_event(contacts: damus_state.contacts, ev: $0) }
|
|
||||||
}
|
|
||||||
|
|
||||||
func subscribe() {
|
func subscribe() {
|
||||||
loading = true
|
loading = true
|
||||||
damus_state.pool.subscribe(sub_id: base_subid, filters: [get_base_filter()], handler: handle_event)
|
damus_state.pool.subscribe(sub_id: base_subid, filters: [get_base_filter()], handler: handle_event)
|
||||||
@@ -54,7 +50,7 @@ class SearchHomeModel: ObservableObject {
|
|||||||
guard sub_id == self.base_subid || sub_id == self.profiles_subid else {
|
guard sub_id == self.base_subid || sub_id == self.profiles_subid else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if ev.is_textlike && !should_hide_event(contacts: damus_state.contacts, ev: ev) && !ev.is_reply(nil) {
|
if ev.is_textlike && ev.should_show_event && !ev.is_reply(nil) {
|
||||||
if seen_pubkey.contains(ev.pubkey) {
|
if seen_pubkey.contains(ev.pubkey) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import Vault
|
|
||||||
|
|
||||||
class UserSettingsStore: ObservableObject {
|
class UserSettingsStore: ObservableObject {
|
||||||
@Published var default_wallet: Wallet {
|
@Published var default_wallet: Wallet {
|
||||||
@@ -27,44 +26,6 @@ class UserSettingsStore: ObservableObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Published var libretranslate_server: LibreTranslateServer {
|
|
||||||
didSet {
|
|
||||||
if oldValue == libretranslate_server {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
UserDefaults.standard.set(libretranslate_server.rawValue, forKey: "libretranslate_server")
|
|
||||||
|
|
||||||
libretranslate_api_key = ""
|
|
||||||
|
|
||||||
if libretranslate_server == .custom || libretranslate_server == .none {
|
|
||||||
libretranslate_url = ""
|
|
||||||
} else {
|
|
||||||
libretranslate_url = libretranslate_server.model.url!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Published var libretranslate_url: String {
|
|
||||||
didSet {
|
|
||||||
UserDefaults.standard.set(libretranslate_url, forKey: "libretranslate_url")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Published var libretranslate_api_key: String {
|
|
||||||
didSet {
|
|
||||||
do {
|
|
||||||
if libretranslate_api_key == "" {
|
|
||||||
try clearLibreTranslateApiKey()
|
|
||||||
} else {
|
|
||||||
try saveLibreTranslateApiKey(libretranslate_api_key)
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
// No-op.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
if let defaultWalletName = UserDefaults.standard.string(forKey: "default_wallet"),
|
if let defaultWalletName = UserDefaults.standard.string(forKey: "default_wallet"),
|
||||||
let default_wallet = Wallet(rawValue: defaultWalletName)
|
let default_wallet = Wallet(rawValue: defaultWalletName)
|
||||||
@@ -76,40 +37,5 @@ class UserSettingsStore: ObservableObject {
|
|||||||
show_wallet_selector = UserDefaults.standard.object(forKey: "show_wallet_selector") as? Bool ?? true
|
show_wallet_selector = UserDefaults.standard.object(forKey: "show_wallet_selector") as? Bool ?? true
|
||||||
|
|
||||||
left_handed = UserDefaults.standard.object(forKey: "left_handed") as? Bool ?? false
|
left_handed = UserDefaults.standard.object(forKey: "left_handed") as? Bool ?? false
|
||||||
|
|
||||||
if let translationServerName = UserDefaults.standard.string(forKey: "libretranslate_server"),
|
|
||||||
let translationServer = LibreTranslateServer(rawValue: translationServerName) {
|
|
||||||
self.libretranslate_server = translationServer
|
|
||||||
libretranslate_url = translationServer.model.url ?? UserDefaults.standard.object(forKey: "libretranslate_url") as? String ?? ""
|
|
||||||
} else {
|
|
||||||
// Note from @tyiu:
|
|
||||||
// Default server is disabled by default for now until we gain some confidence that it is working well in production.
|
|
||||||
// Instead of throwing all Damus users onto feature immediately, allow for discovery of feature organically.
|
|
||||||
// Also, we are connecting to servers listed as mirrors on the official LibreTranslate GitHub README that do not require API keys.
|
|
||||||
// However, we have not asked them for permission to use, so we're trying to be good neighbors for now.
|
|
||||||
// Opportunity: spin up dedicated trusted LibreTranslate server that requires an API key for any access (or higher rate limit access).
|
|
||||||
libretranslate_server = .none
|
|
||||||
libretranslate_url = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
libretranslate_api_key = try Vault.getPrivateKey(keychainConfiguration: DamusLibreTranslateKeychainConfiguration())
|
|
||||||
} catch {
|
|
||||||
libretranslate_api_key = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func saveLibreTranslateApiKey(_ apiKey: String) throws {
|
|
||||||
try Vault.savePrivateKey(apiKey, keychainConfiguration: DamusLibreTranslateKeychainConfiguration())
|
|
||||||
}
|
|
||||||
|
|
||||||
func clearLibreTranslateApiKey() throws {
|
|
||||||
try Vault.deletePrivateKey(keychainConfiguration: DamusLibreTranslateKeychainConfiguration())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DamusLibreTranslateKeychainConfiguration: KeychainConfiguration {
|
|
||||||
var serviceName = "damus"
|
|
||||||
var accessGroup: String? = nil
|
|
||||||
var accountName = "libretranslate_apikey"
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -11,17 +11,13 @@ struct SwipeToDismissModifier: ViewModifier {
|
|||||||
let minDistance: CGFloat?
|
let minDistance: CGFloat?
|
||||||
var onDismiss: () -> Void
|
var onDismiss: () -> Void
|
||||||
@State private var offset: CGSize = .zero
|
@State private var offset: CGSize = .zero
|
||||||
@GestureState private var viewOffset: CGSize = .zero
|
|
||||||
|
|
||||||
func body(content: Content) -> some View {
|
func body(content: Content) -> some View {
|
||||||
content
|
content
|
||||||
.offset(y: viewOffset.height)
|
.offset(y: offset.height)
|
||||||
.animation(.interactiveSpring(), value: viewOffset)
|
.animation(.interactiveSpring(), value: offset)
|
||||||
.simultaneousGesture(
|
.simultaneousGesture(
|
||||||
DragGesture(minimumDistance: minDistance ?? 10)
|
DragGesture(minimumDistance: minDistance ?? 10)
|
||||||
.updating($viewOffset, body: { value, gestureState, transaction in
|
|
||||||
gestureState = CGSize(width: value.location.x - value.startLocation.x, height: value.location.y - value.startLocation.y)
|
|
||||||
})
|
|
||||||
.onChanged { gesture in
|
.onChanged { gesture in
|
||||||
if gesture.translation.width < 50 {
|
if gesture.translation.width < 50 {
|
||||||
offset = gesture.translation
|
offset = gesture.translation
|
||||||
|
|||||||
+26
-47
@@ -8,7 +8,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct Profile: Codable {
|
struct Profile: Codable {
|
||||||
var value: [String: AnyCodable]
|
var value: [String: String]
|
||||||
|
|
||||||
init (name: String?, display_name: String?, about: String?, picture: String?, banner: String?, website: String?, lud06: String?, lud16: String?, nip05: String?) {
|
init (name: String?, display_name: String?, about: String?, picture: String?, banner: String?, website: String?, lud06: String?, lud16: String?, nip05: String?) {
|
||||||
self.value = [:]
|
self.value = [:]
|
||||||
@@ -23,71 +23,50 @@ struct Profile: Codable {
|
|||||||
self.nip05 = nip05
|
self.nip05 = nip05
|
||||||
}
|
}
|
||||||
|
|
||||||
private func str(_ str: String) -> String? {
|
|
||||||
guard let val = self.value[str] else{
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let s = val.value as? String else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
private mutating func set_str(_ key: String, _ val: String?) {
|
|
||||||
if val == nil {
|
|
||||||
self.value.removeValue(forKey: key)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
self.value[key] = AnyCodable.init(val)
|
|
||||||
}
|
|
||||||
|
|
||||||
var display_name: String? {
|
var display_name: String? {
|
||||||
get { return str("display_name"); }
|
get { return value["display_name"]; }
|
||||||
set(s) { set_str("display_name", s) }
|
set(s) { value["display_name"] = s }
|
||||||
}
|
}
|
||||||
|
|
||||||
var name: String? {
|
var name: String? {
|
||||||
get { return str("name"); }
|
get { return value["name"]; }
|
||||||
set(s) { set_str("name", s) }
|
set(s) { value["name"] = s }
|
||||||
}
|
}
|
||||||
|
|
||||||
var about: String? {
|
var about: String? {
|
||||||
get { return str("about"); }
|
get { return value["about"]; }
|
||||||
set(s) { set_str("about", s) }
|
set(s) { value["about"] = s }
|
||||||
}
|
}
|
||||||
|
|
||||||
var picture: String? {
|
var picture: String? {
|
||||||
get { return str("picture"); }
|
get { return value["picture"]; }
|
||||||
set(s) { set_str("picture", s) }
|
set(s) { value["picture"] = s }
|
||||||
}
|
}
|
||||||
|
|
||||||
var banner: String? {
|
var banner: String? {
|
||||||
get { return str("banner"); }
|
get { return value["banner"]; }
|
||||||
set(s) { set_str("banner", s) }
|
set(s) { value["banner"] = s }
|
||||||
}
|
}
|
||||||
|
|
||||||
var website: String? {
|
var website: String? {
|
||||||
get { return str("website"); }
|
get { return value["website"]; }
|
||||||
set(s) { set_str("website", s) }
|
set(s) { value["website"] = s }
|
||||||
}
|
|
||||||
|
|
||||||
var lud06: String? {
|
|
||||||
get { return str("lud06"); }
|
|
||||||
set(s) { set_str("lud06", s) }
|
|
||||||
}
|
|
||||||
|
|
||||||
var lud16: String? {
|
|
||||||
get { return str("lud16"); }
|
|
||||||
set(s) { set_str("lud16", s) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var website_url: URL? {
|
var website_url: URL? {
|
||||||
return self.website.flatMap { URL(string: $0) }
|
return self.website.flatMap { URL(string: $0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var lud06: String? {
|
||||||
|
get { return value["lud06"]; }
|
||||||
|
set(s) { value["lud06"] = s }
|
||||||
|
}
|
||||||
|
|
||||||
|
var lud16: String? {
|
||||||
|
get { return value["lud16"]; }
|
||||||
|
set(s) { value["lud16"] = s }
|
||||||
|
}
|
||||||
|
|
||||||
var lnurl: String? {
|
var lnurl: String? {
|
||||||
guard let addr = lud06 ?? lud16 else {
|
guard let addr = lud06 ?? lud16 else {
|
||||||
return nil;
|
return nil;
|
||||||
@@ -101,8 +80,8 @@ struct Profile: Codable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var nip05: String? {
|
var nip05: String? {
|
||||||
get { return str("nip05"); }
|
get { return value["nip05"]; }
|
||||||
set(s) { set_str("nip05", s) }
|
set(s) { value["nip05"] = s }
|
||||||
}
|
}
|
||||||
|
|
||||||
var lightning_uri: URL? {
|
var lightning_uri: URL? {
|
||||||
@@ -111,7 +90,7 @@ struct Profile: Codable {
|
|||||||
|
|
||||||
init(from decoder: Decoder) throws {
|
init(from decoder: Decoder) throws {
|
||||||
let container = try decoder.singleValueContainer()
|
let container = try decoder.singleValueContainer()
|
||||||
self.value = try container.decode([String: AnyCodable].self)
|
self.value = try container.decode([String: String].self)
|
||||||
}
|
}
|
||||||
|
|
||||||
func encode(to encoder: Encoder) throws {
|
func encode(to encoder: Encoder) throws {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ struct KeyEvent {
|
|||||||
let relay_url: String
|
let relay_url: String
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ReferencedId: Identifiable, Hashable, Equatable {
|
struct ReferencedId: Identifiable, Hashable {
|
||||||
let ref_id: String
|
let ref_id: String
|
||||||
let relay_id: String?
|
let relay_id: String?
|
||||||
let key: String
|
let key: String
|
||||||
@@ -103,15 +103,11 @@ class NostrEvent: Codable, Identifiable, CustomStringConvertible, Equatable, Has
|
|||||||
if let bs = _blocks {
|
if let bs = _blocks {
|
||||||
return bs
|
return bs
|
||||||
}
|
}
|
||||||
let blocks = get_blocks(content: self.get_content(privkey))
|
let blocks = parse_mentions(content: self.get_content(privkey), tags: self.tags)
|
||||||
self._blocks = blocks
|
self._blocks = blocks
|
||||||
return blocks
|
return blocks
|
||||||
}
|
}
|
||||||
|
|
||||||
func get_blocks(content: String) -> [Block] {
|
|
||||||
return parse_mentions(content: content, tags: self.tags)
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy var inner_event: NostrEvent? = {
|
lazy var inner_event: NostrEvent? = {
|
||||||
// don't try to deserialize an inner event if we know there won't be one
|
// don't try to deserialize an inner event if we know there won't be one
|
||||||
if self.known_kind == .boost {
|
if self.known_kind == .boost {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct NostrFilter: Codable, Equatable {
|
struct NostrFilter: Codable {
|
||||||
var ids: [String]?
|
var ids: [String]?
|
||||||
var kinds: [Int]?
|
var kinds: [Int]?
|
||||||
var referenced_ids: [String]?
|
var referenced_ids: [String]?
|
||||||
@@ -17,7 +17,6 @@ struct NostrFilter: Codable, Equatable {
|
|||||||
var limit: UInt32?
|
var limit: UInt32?
|
||||||
var authors: [String]?
|
var authors: [String]?
|
||||||
var hashtag: [String]? = nil
|
var hashtag: [String]? = nil
|
||||||
var parameter: [String]? = nil
|
|
||||||
|
|
||||||
private enum CodingKeys : String, CodingKey {
|
private enum CodingKeys : String, CodingKey {
|
||||||
case ids
|
case ids
|
||||||
@@ -25,7 +24,6 @@ struct NostrFilter: Codable, Equatable {
|
|||||||
case referenced_ids = "#e"
|
case referenced_ids = "#e"
|
||||||
case pubkeys = "#p"
|
case pubkeys = "#p"
|
||||||
case hashtag = "#t"
|
case hashtag = "#t"
|
||||||
case parameter = "#d"
|
|
||||||
case since
|
case since
|
||||||
case until
|
case until
|
||||||
case authors
|
case authors
|
||||||
|
|||||||
@@ -19,5 +19,4 @@ enum NostrKind: Int {
|
|||||||
case channel_create = 40
|
case channel_create = 40
|
||||||
case channel_meta = 41
|
case channel_meta = 41
|
||||||
case chat = 42
|
case chat = 42
|
||||||
case list = 30000
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
|
||||||
enum NostrLink: Equatable {
|
enum NostrLink {
|
||||||
case ref(ReferencedId)
|
case ref(ReferencedId)
|
||||||
case filter(NostrFilter)
|
case filter(NostrFilter)
|
||||||
}
|
}
|
||||||
@@ -101,24 +101,6 @@ func decode_universal_link(_ s: String) -> NostrLink? {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decode_nostr_bech32_uri(_ s: String) -> NostrLink? {
|
|
||||||
guard let obj = Bech32Object.parse(s) else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
switch obj {
|
|
||||||
case .nsec(let privkey):
|
|
||||||
guard let pubkey = privkey_to_pubkey(privkey: privkey) else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return .ref(ReferencedId(ref_id: pubkey, relay_id: nil, key: "p"))
|
|
||||||
case .npub(let pubkey):
|
|
||||||
return .ref(ReferencedId(ref_id: pubkey, relay_id: nil, key: "p"))
|
|
||||||
case .note(let id):
|
|
||||||
return .ref(ReferencedId(ref_id: id, relay_id: nil, key: "e"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func decode_nostr_uri(_ s: String) -> NostrLink? {
|
func decode_nostr_uri(_ s: String) -> NostrLink? {
|
||||||
if s.starts(with: "https://damus.io/") {
|
if s.starts(with: "https://damus.io/") {
|
||||||
return decode_universal_link(s)
|
return decode_universal_link(s)
|
||||||
@@ -140,15 +122,5 @@ func decode_nostr_uri(_ s: String) -> NostrLink? {
|
|||||||
return .filter(NostrFilter.filter_hashtag([parts[1].lowercased()]))
|
return .filter(NostrFilter.filter_hashtag([parts[1].lowercased()]))
|
||||||
}
|
}
|
||||||
|
|
||||||
if let rid = tag_to_refid(parts) {
|
return tag_to_refid(parts).map { .ref($0) }
|
||||||
return .ref(rid)
|
|
||||||
}
|
|
||||||
|
|
||||||
guard parts.count == 1 else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
let part = parts[0]
|
|
||||||
|
|
||||||
return decode_nostr_bech32_uri(part)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,147 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
/**
|
|
||||||
A type-erased `Codable` value.
|
|
||||||
|
|
||||||
The `AnyCodable` type forwards encoding and decoding responsibilities
|
|
||||||
to an underlying value, hiding its specific underlying type.
|
|
||||||
|
|
||||||
You can encode or decode mixed-type values in dictionaries
|
|
||||||
and other collections that require `Encodable` or `Decodable` conformance
|
|
||||||
by declaring their contained type to be `AnyCodable`.
|
|
||||||
|
|
||||||
- SeeAlso: `AnyEncodable`
|
|
||||||
- SeeAlso: `AnyDecodable`
|
|
||||||
*/
|
|
||||||
@frozen public struct AnyCodable: Codable {
|
|
||||||
public let value: Any
|
|
||||||
|
|
||||||
public init<T>(_ value: T?) {
|
|
||||||
self.value = value ?? ()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension AnyCodable: _AnyEncodable, _AnyDecodable {}
|
|
||||||
|
|
||||||
extension AnyCodable: Equatable {
|
|
||||||
public static func == (lhs: AnyCodable, rhs: AnyCodable) -> Bool {
|
|
||||||
switch (lhs.value, rhs.value) {
|
|
||||||
case is (Void, Void):
|
|
||||||
return true
|
|
||||||
case let (lhs as Bool, rhs as Bool):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as Int, rhs as Int):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as Int8, rhs as Int8):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as Int16, rhs as Int16):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as Int32, rhs as Int32):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as Int64, rhs as Int64):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as UInt, rhs as UInt):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as UInt8, rhs as UInt8):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as UInt16, rhs as UInt16):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as UInt32, rhs as UInt32):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as UInt64, rhs as UInt64):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as Float, rhs as Float):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as Double, rhs as Double):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as String, rhs as String):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as [String: AnyCodable], rhs as [String: AnyCodable]):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as [AnyCodable], rhs as [AnyCodable]):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as [String: Any], rhs as [String: Any]):
|
|
||||||
return NSDictionary(dictionary: lhs) == NSDictionary(dictionary: rhs)
|
|
||||||
case let (lhs as [Any], rhs as [Any]):
|
|
||||||
return NSArray(array: lhs) == NSArray(array: rhs)
|
|
||||||
case is (NSNull, NSNull):
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension AnyCodable: CustomStringConvertible {
|
|
||||||
public var description: String {
|
|
||||||
switch value {
|
|
||||||
case is Void:
|
|
||||||
return String(describing: nil as Any?)
|
|
||||||
case let value as CustomStringConvertible:
|
|
||||||
return value.description
|
|
||||||
default:
|
|
||||||
return String(describing: value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension AnyCodable: CustomDebugStringConvertible {
|
|
||||||
public var debugDescription: String {
|
|
||||||
switch value {
|
|
||||||
case let value as CustomDebugStringConvertible:
|
|
||||||
return "AnyCodable(\(value.debugDescription))"
|
|
||||||
default:
|
|
||||||
return "AnyCodable(\(description))"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension AnyCodable: ExpressibleByNilLiteral {}
|
|
||||||
extension AnyCodable: ExpressibleByBooleanLiteral {}
|
|
||||||
extension AnyCodable: ExpressibleByIntegerLiteral {}
|
|
||||||
extension AnyCodable: ExpressibleByFloatLiteral {}
|
|
||||||
extension AnyCodable: ExpressibleByStringLiteral {}
|
|
||||||
extension AnyCodable: ExpressibleByStringInterpolation {}
|
|
||||||
extension AnyCodable: ExpressibleByArrayLiteral {}
|
|
||||||
extension AnyCodable: ExpressibleByDictionaryLiteral {}
|
|
||||||
|
|
||||||
|
|
||||||
extension AnyCodable: Hashable {
|
|
||||||
public func hash(into hasher: inout Hasher) {
|
|
||||||
switch value {
|
|
||||||
case let value as Bool:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as Int:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as Int8:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as Int16:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as Int32:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as Int64:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as UInt:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as UInt8:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as UInt16:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as UInt32:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as UInt64:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as Float:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as Double:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as String:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as [String: AnyCodable]:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as [AnyCodable]:
|
|
||||||
hasher.combine(value)
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,188 +0,0 @@
|
|||||||
#if canImport(Foundation)
|
|
||||||
import Foundation
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
A type-erased `Decodable` value.
|
|
||||||
|
|
||||||
The `AnyDecodable` type forwards decoding responsibilities
|
|
||||||
to an underlying value, hiding its specific underlying type.
|
|
||||||
|
|
||||||
You can decode mixed-type values in dictionaries
|
|
||||||
and other collections that require `Decodable` conformance
|
|
||||||
by declaring their contained type to be `AnyDecodable`:
|
|
||||||
|
|
||||||
let json = """
|
|
||||||
{
|
|
||||||
"boolean": true,
|
|
||||||
"integer": 42,
|
|
||||||
"double": 3.141592653589793,
|
|
||||||
"string": "string",
|
|
||||||
"array": [1, 2, 3],
|
|
||||||
"nested": {
|
|
||||||
"a": "alpha",
|
|
||||||
"b": "bravo",
|
|
||||||
"c": "charlie"
|
|
||||||
},
|
|
||||||
"null": null
|
|
||||||
}
|
|
||||||
""".data(using: .utf8)!
|
|
||||||
|
|
||||||
let decoder = JSONDecoder()
|
|
||||||
let dictionary = try! decoder.decode([String: AnyDecodable].self, from: json)
|
|
||||||
*/
|
|
||||||
@frozen public struct AnyDecodable: Decodable {
|
|
||||||
public let value: Any
|
|
||||||
|
|
||||||
public init<T>(_ value: T?) {
|
|
||||||
self.value = value ?? ()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@usableFromInline
|
|
||||||
protocol _AnyDecodable {
|
|
||||||
var value: Any { get }
|
|
||||||
init<T>(_ value: T?)
|
|
||||||
}
|
|
||||||
|
|
||||||
extension AnyDecodable: _AnyDecodable {}
|
|
||||||
|
|
||||||
extension _AnyDecodable {
|
|
||||||
public init(from decoder: Decoder) throws {
|
|
||||||
let container = try decoder.singleValueContainer()
|
|
||||||
|
|
||||||
if container.decodeNil() {
|
|
||||||
#if canImport(Foundation)
|
|
||||||
self.init(NSNull())
|
|
||||||
#else
|
|
||||||
self.init(Optional<Self>.none)
|
|
||||||
#endif
|
|
||||||
} else if let bool = try? container.decode(Bool.self) {
|
|
||||||
self.init(bool)
|
|
||||||
} else if let int = try? container.decode(Int.self) {
|
|
||||||
self.init(int)
|
|
||||||
} else if let uint = try? container.decode(UInt.self) {
|
|
||||||
self.init(uint)
|
|
||||||
} else if let double = try? container.decode(Double.self) {
|
|
||||||
self.init(double)
|
|
||||||
} else if let string = try? container.decode(String.self) {
|
|
||||||
self.init(string)
|
|
||||||
} else if let array = try? container.decode([AnyDecodable].self) {
|
|
||||||
self.init(array.map { $0.value })
|
|
||||||
} else if let dictionary = try? container.decode([String: AnyDecodable].self) {
|
|
||||||
self.init(dictionary.mapValues { $0.value })
|
|
||||||
} else {
|
|
||||||
throw DecodingError.dataCorruptedError(in: container, debugDescription: "AnyDecodable value cannot be decoded")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension AnyDecodable: Equatable {
|
|
||||||
public static func == (lhs: AnyDecodable, rhs: AnyDecodable) -> Bool {
|
|
||||||
switch (lhs.value, rhs.value) {
|
|
||||||
#if canImport(Foundation)
|
|
||||||
case is (NSNull, NSNull), is (Void, Void):
|
|
||||||
return true
|
|
||||||
#endif
|
|
||||||
case let (lhs as Bool, rhs as Bool):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as Int, rhs as Int):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as Int8, rhs as Int8):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as Int16, rhs as Int16):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as Int32, rhs as Int32):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as Int64, rhs as Int64):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as UInt, rhs as UInt):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as UInt8, rhs as UInt8):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as UInt16, rhs as UInt16):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as UInt32, rhs as UInt32):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as UInt64, rhs as UInt64):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as Float, rhs as Float):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as Double, rhs as Double):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as String, rhs as String):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as [String: AnyDecodable], rhs as [String: AnyDecodable]):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as [AnyDecodable], rhs as [AnyDecodable]):
|
|
||||||
return lhs == rhs
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension AnyDecodable: CustomStringConvertible {
|
|
||||||
public var description: String {
|
|
||||||
switch value {
|
|
||||||
case is Void:
|
|
||||||
return String(describing: nil as Any?)
|
|
||||||
case let value as CustomStringConvertible:
|
|
||||||
return value.description
|
|
||||||
default:
|
|
||||||
return String(describing: value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension AnyDecodable: CustomDebugStringConvertible {
|
|
||||||
public var debugDescription: String {
|
|
||||||
switch value {
|
|
||||||
case let value as CustomDebugStringConvertible:
|
|
||||||
return "AnyDecodable(\(value.debugDescription))"
|
|
||||||
default:
|
|
||||||
return "AnyDecodable(\(description))"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension AnyDecodable: Hashable {
|
|
||||||
public func hash(into hasher: inout Hasher) {
|
|
||||||
switch value {
|
|
||||||
case let value as Bool:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as Int:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as Int8:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as Int16:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as Int32:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as Int64:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as UInt:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as UInt8:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as UInt16:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as UInt32:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as UInt64:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as Float:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as Double:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as String:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as [String: AnyDecodable]:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as [AnyDecodable]:
|
|
||||||
hasher.combine(value)
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,291 +0,0 @@
|
|||||||
#if canImport(Foundation)
|
|
||||||
import Foundation
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
A type-erased `Encodable` value.
|
|
||||||
|
|
||||||
The `AnyEncodable` type forwards encoding responsibilities
|
|
||||||
to an underlying value, hiding its specific underlying type.
|
|
||||||
|
|
||||||
You can encode mixed-type values in dictionaries
|
|
||||||
and other collections that require `Encodable` conformance
|
|
||||||
by declaring their contained type to be `AnyEncodable`:
|
|
||||||
|
|
||||||
let dictionary: [String: AnyEncodable] = [
|
|
||||||
"boolean": true,
|
|
||||||
"integer": 42,
|
|
||||||
"double": 3.141592653589793,
|
|
||||||
"string": "string",
|
|
||||||
"array": [1, 2, 3],
|
|
||||||
"nested": [
|
|
||||||
"a": "alpha",
|
|
||||||
"b": "bravo",
|
|
||||||
"c": "charlie"
|
|
||||||
],
|
|
||||||
"null": nil
|
|
||||||
]
|
|
||||||
|
|
||||||
let encoder = JSONEncoder()
|
|
||||||
let json = try! encoder.encode(dictionary)
|
|
||||||
*/
|
|
||||||
@frozen public struct AnyEncodable: Encodable {
|
|
||||||
public let value: Any
|
|
||||||
|
|
||||||
public init<T>(_ value: T?) {
|
|
||||||
self.value = value ?? ()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@usableFromInline
|
|
||||||
protocol _AnyEncodable {
|
|
||||||
var value: Any { get }
|
|
||||||
init<T>(_ value: T?)
|
|
||||||
}
|
|
||||||
|
|
||||||
extension AnyEncodable: _AnyEncodable {}
|
|
||||||
|
|
||||||
// MARK: - Encodable
|
|
||||||
|
|
||||||
extension _AnyEncodable {
|
|
||||||
public func encode(to encoder: Encoder) throws {
|
|
||||||
var container = encoder.singleValueContainer()
|
|
||||||
|
|
||||||
switch value {
|
|
||||||
#if canImport(Foundation)
|
|
||||||
case is NSNull:
|
|
||||||
try container.encodeNil()
|
|
||||||
#endif
|
|
||||||
case is Void:
|
|
||||||
try container.encodeNil()
|
|
||||||
case let bool as Bool:
|
|
||||||
try container.encode(bool)
|
|
||||||
case let int as Int:
|
|
||||||
try container.encode(int)
|
|
||||||
case let int8 as Int8:
|
|
||||||
try container.encode(int8)
|
|
||||||
case let int16 as Int16:
|
|
||||||
try container.encode(int16)
|
|
||||||
case let int32 as Int32:
|
|
||||||
try container.encode(int32)
|
|
||||||
case let int64 as Int64:
|
|
||||||
try container.encode(int64)
|
|
||||||
case let uint as UInt:
|
|
||||||
try container.encode(uint)
|
|
||||||
case let uint8 as UInt8:
|
|
||||||
try container.encode(uint8)
|
|
||||||
case let uint16 as UInt16:
|
|
||||||
try container.encode(uint16)
|
|
||||||
case let uint32 as UInt32:
|
|
||||||
try container.encode(uint32)
|
|
||||||
case let uint64 as UInt64:
|
|
||||||
try container.encode(uint64)
|
|
||||||
case let float as Float:
|
|
||||||
try container.encode(float)
|
|
||||||
case let double as Double:
|
|
||||||
try container.encode(double)
|
|
||||||
case let string as String:
|
|
||||||
try container.encode(string)
|
|
||||||
#if canImport(Foundation)
|
|
||||||
case let number as NSNumber:
|
|
||||||
try encode(nsnumber: number, into: &container)
|
|
||||||
case let date as Date:
|
|
||||||
try container.encode(date)
|
|
||||||
case let url as URL:
|
|
||||||
try container.encode(url)
|
|
||||||
#endif
|
|
||||||
case let array as [Any?]:
|
|
||||||
try container.encode(array.map { AnyEncodable($0) })
|
|
||||||
case let dictionary as [String: Any?]:
|
|
||||||
try container.encode(dictionary.mapValues { AnyEncodable($0) })
|
|
||||||
case let encodable as Encodable:
|
|
||||||
try encodable.encode(to: encoder)
|
|
||||||
default:
|
|
||||||
let context = EncodingError.Context(codingPath: container.codingPath, debugDescription: "AnyEncodable value cannot be encoded")
|
|
||||||
throw EncodingError.invalidValue(value, context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if canImport(Foundation)
|
|
||||||
private func encode(nsnumber: NSNumber, into container: inout SingleValueEncodingContainer) throws {
|
|
||||||
switch Character(Unicode.Scalar(UInt8(nsnumber.objCType.pointee))) {
|
|
||||||
case "B":
|
|
||||||
try container.encode(nsnumber.boolValue)
|
|
||||||
case "c":
|
|
||||||
try container.encode(nsnumber.int8Value)
|
|
||||||
case "s":
|
|
||||||
try container.encode(nsnumber.int16Value)
|
|
||||||
case "i", "l":
|
|
||||||
try container.encode(nsnumber.int32Value)
|
|
||||||
case "q":
|
|
||||||
try container.encode(nsnumber.int64Value)
|
|
||||||
case "C":
|
|
||||||
try container.encode(nsnumber.uint8Value)
|
|
||||||
case "S":
|
|
||||||
try container.encode(nsnumber.uint16Value)
|
|
||||||
case "I", "L":
|
|
||||||
try container.encode(nsnumber.uint32Value)
|
|
||||||
case "Q":
|
|
||||||
try container.encode(nsnumber.uint64Value)
|
|
||||||
case "f":
|
|
||||||
try container.encode(nsnumber.floatValue)
|
|
||||||
case "d":
|
|
||||||
try container.encode(nsnumber.doubleValue)
|
|
||||||
default:
|
|
||||||
let context = EncodingError.Context(codingPath: container.codingPath, debugDescription: "NSNumber cannot be encoded because its type is not handled")
|
|
||||||
throw EncodingError.invalidValue(nsnumber, context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
extension AnyEncodable: Equatable {
|
|
||||||
public static func == (lhs: AnyEncodable, rhs: AnyEncodable) -> Bool {
|
|
||||||
switch (lhs.value, rhs.value) {
|
|
||||||
case is (Void, Void):
|
|
||||||
return true
|
|
||||||
case let (lhs as Bool, rhs as Bool):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as Int, rhs as Int):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as Int8, rhs as Int8):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as Int16, rhs as Int16):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as Int32, rhs as Int32):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as Int64, rhs as Int64):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as UInt, rhs as UInt):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as UInt8, rhs as UInt8):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as UInt16, rhs as UInt16):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as UInt32, rhs as UInt32):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as UInt64, rhs as UInt64):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as Float, rhs as Float):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as Double, rhs as Double):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as String, rhs as String):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as [String: AnyEncodable], rhs as [String: AnyEncodable]):
|
|
||||||
return lhs == rhs
|
|
||||||
case let (lhs as [AnyEncodable], rhs as [AnyEncodable]):
|
|
||||||
return lhs == rhs
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension AnyEncodable: CustomStringConvertible {
|
|
||||||
public var description: String {
|
|
||||||
switch value {
|
|
||||||
case is Void:
|
|
||||||
return String(describing: nil as Any?)
|
|
||||||
case let value as CustomStringConvertible:
|
|
||||||
return value.description
|
|
||||||
default:
|
|
||||||
return String(describing: value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension AnyEncodable: CustomDebugStringConvertible {
|
|
||||||
public var debugDescription: String {
|
|
||||||
switch value {
|
|
||||||
case let value as CustomDebugStringConvertible:
|
|
||||||
return "AnyEncodable(\(value.debugDescription))"
|
|
||||||
default:
|
|
||||||
return "AnyEncodable(\(description))"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension AnyEncodable: ExpressibleByNilLiteral {}
|
|
||||||
extension AnyEncodable: ExpressibleByBooleanLiteral {}
|
|
||||||
extension AnyEncodable: ExpressibleByIntegerLiteral {}
|
|
||||||
extension AnyEncodable: ExpressibleByFloatLiteral {}
|
|
||||||
extension AnyEncodable: ExpressibleByStringLiteral {}
|
|
||||||
extension AnyEncodable: ExpressibleByStringInterpolation {}
|
|
||||||
extension AnyEncodable: ExpressibleByArrayLiteral {}
|
|
||||||
extension AnyEncodable: ExpressibleByDictionaryLiteral {}
|
|
||||||
|
|
||||||
extension _AnyEncodable {
|
|
||||||
public init(nilLiteral _: ()) {
|
|
||||||
self.init(nil as Any?)
|
|
||||||
}
|
|
||||||
|
|
||||||
public init(booleanLiteral value: Bool) {
|
|
||||||
self.init(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
public init(integerLiteral value: Int) {
|
|
||||||
self.init(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
public init(floatLiteral value: Double) {
|
|
||||||
self.init(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
public init(extendedGraphemeClusterLiteral value: String) {
|
|
||||||
self.init(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
public init(stringLiteral value: String) {
|
|
||||||
self.init(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
public init(arrayLiteral elements: Any...) {
|
|
||||||
self.init(elements)
|
|
||||||
}
|
|
||||||
|
|
||||||
public init(dictionaryLiteral elements: (AnyHashable, Any)...) {
|
|
||||||
self.init([AnyHashable: Any](elements, uniquingKeysWith: { first, _ in first }))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension AnyEncodable: Hashable {
|
|
||||||
public func hash(into hasher: inout Hasher) {
|
|
||||||
switch value {
|
|
||||||
case let value as Bool:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as Int:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as Int8:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as Int16:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as Int32:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as Int64:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as UInt:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as UInt8:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as UInt16:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as UInt32:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as UInt64:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as Float:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as Double:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as String:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as [String: AnyEncodable]:
|
|
||||||
hasher.combine(value)
|
|
||||||
case let value as [AnyEncodable]:
|
|
||||||
hasher.combine(value)
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
//
|
|
||||||
// Bech32Object.swift
|
|
||||||
// damus
|
|
||||||
//
|
|
||||||
// Created by William Casarin on 2023-01-28.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
|
|
||||||
enum Bech32Object {
|
|
||||||
case nsec(String)
|
|
||||||
case npub(String)
|
|
||||||
case note(String)
|
|
||||||
|
|
||||||
static func parse(_ str: String) -> Bech32Object? {
|
|
||||||
guard let decoded = try? bech32_decode(str) else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if decoded.hrp == "npub" {
|
|
||||||
return .npub(hex_encode(decoded.data))
|
|
||||||
} else if decoded.hrp == "nsec" {
|
|
||||||
return .nsec(hex_encode(decoded.data))
|
|
||||||
} else if decoded.hrp == "note" {
|
|
||||||
return .note(hex_encode(decoded.data))
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
//
|
|
||||||
// CoreSVG.swift
|
|
||||||
// damus
|
|
||||||
//
|
|
||||||
// Created by Oleg Abalonski on 1/27/23.
|
|
||||||
// Ref: https://gist.github.com/ollieatkinson/eb87a82fcb5500d5561fed8b0900a9f7
|
|
||||||
|
|
||||||
import Darwin
|
|
||||||
import Foundation
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
@objc
|
|
||||||
class CGSVGDocument: NSObject { }
|
|
||||||
|
|
||||||
var CGSVGDocumentRetain: (@convention(c) (CGSVGDocument?) -> Unmanaged<CGSVGDocument>?) = load("CGSVGDocumentRetain")
|
|
||||||
var CGSVGDocumentRelease: (@convention(c) (CGSVGDocument?) -> Void) = load("CGSVGDocumentRelease")
|
|
||||||
var CGSVGDocumentCreateFromData: (@convention(c) (CFData?, CFDictionary?) -> Unmanaged<CGSVGDocument>?) = load("CGSVGDocumentCreateFromData")
|
|
||||||
var CGContextDrawSVGDocument: (@convention(c) (CGContext?, CGSVGDocument?) -> Void) = load("CGContextDrawSVGDocument")
|
|
||||||
var CGSVGDocumentGetCanvasSize: (@convention(c) (CGSVGDocument?) -> CGSize) = load("CGSVGDocumentGetCanvasSize")
|
|
||||||
|
|
||||||
typealias ImageWithCGSVGDocument = @convention(c) (AnyObject, Selector, CGSVGDocument) -> UIImage
|
|
||||||
var ImageWithCGSVGDocumentSEL: Selector = NSSelectorFromString("_imageWithCGSVGDocument:")
|
|
||||||
|
|
||||||
let CoreSVG = dlopen("/System/Library/PrivateFrameworks/CoreSVG.framework/CoreSVG", RTLD_NOW)
|
|
||||||
|
|
||||||
func load<T>(_ name: String) -> T {
|
|
||||||
unsafeBitCast(dlsym(CoreSVG, name), to: T.self)
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SVG {
|
|
||||||
|
|
||||||
deinit { CGSVGDocumentRelease(document) }
|
|
||||||
|
|
||||||
let document: CGSVGDocument
|
|
||||||
|
|
||||||
public convenience init?(_ value: String) {
|
|
||||||
guard let data = value.data(using: .utf8) else { return nil }
|
|
||||||
self.init(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
public init?(_ data: Data) {
|
|
||||||
guard let document = CGSVGDocumentCreateFromData(data as CFData, nil)?.takeUnretainedValue() else { return nil }
|
|
||||||
guard CGSVGDocumentGetCanvasSize(document) != .zero else { return nil }
|
|
||||||
self.document = document
|
|
||||||
}
|
|
||||||
|
|
||||||
public var size: CGSize {
|
|
||||||
CGSVGDocumentGetCanvasSize(document)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func image() -> UIImage? {
|
|
||||||
let ImageWithCGSVGDocument = unsafeBitCast(UIImage.self.method(for: ImageWithCGSVGDocumentSEL), to: ImageWithCGSVGDocument.self)
|
|
||||||
let image = ImageWithCGSVGDocument(UIImage.self, ImageWithCGSVGDocumentSEL, document)
|
|
||||||
return image
|
|
||||||
}
|
|
||||||
|
|
||||||
public func draw(in context: CGContext) {
|
|
||||||
draw(in: context, size: size)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func draw(in context: CGContext, size target: CGSize) {
|
|
||||||
|
|
||||||
var target = target
|
|
||||||
|
|
||||||
let ratio = (
|
|
||||||
x: target.width / size.width,
|
|
||||||
y: target.height / size.height
|
|
||||||
)
|
|
||||||
|
|
||||||
let rect = (
|
|
||||||
document: CGRect(origin: .zero, size: size), ()
|
|
||||||
)
|
|
||||||
|
|
||||||
let scale: (x: CGFloat, y: CGFloat)
|
|
||||||
|
|
||||||
if target.width <= 0 {
|
|
||||||
scale = (ratio.y, ratio.y)
|
|
||||||
target.width = size.width * scale.x
|
|
||||||
} else if target.height <= 0 {
|
|
||||||
scale = (ratio.x, ratio.x)
|
|
||||||
target.width = size.width * scale.y
|
|
||||||
} else {
|
|
||||||
let min = min(ratio.x, ratio.y)
|
|
||||||
scale = (min, min)
|
|
||||||
target.width = size.width * scale.x
|
|
||||||
target.height = size.height * scale.y
|
|
||||||
}
|
|
||||||
|
|
||||||
let transform = (
|
|
||||||
scale: CGAffineTransform(scaleX: scale.x, y: scale.y),
|
|
||||||
aspect: CGAffineTransform(translationX: (target.width / scale.x - rect.document.width) / 2, y: (target.height / scale.y - rect.document.height) / 2)
|
|
||||||
)
|
|
||||||
|
|
||||||
context.translateBy(x: 0, y: target.height)
|
|
||||||
context.scaleBy(x: 1, y: -1)
|
|
||||||
context.concatenate(transform.scale)
|
|
||||||
context.concatenate(transform.aspect)
|
|
||||||
|
|
||||||
CGContextDrawSVGDocument(context, document)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -12,25 +12,12 @@ import Vault
|
|||||||
let PUBKEY_HRP = "npub"
|
let PUBKEY_HRP = "npub"
|
||||||
let PRIVKEY_HRP = "nsec"
|
let PRIVKEY_HRP = "nsec"
|
||||||
|
|
||||||
struct FullKeypair {
|
|
||||||
let pubkey: String
|
|
||||||
let privkey: String
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Keypair {
|
struct Keypair {
|
||||||
let pubkey: String
|
let pubkey: String
|
||||||
let privkey: String?
|
let privkey: String?
|
||||||
let pubkey_bech32: String
|
let pubkey_bech32: String
|
||||||
let privkey_bech32: String?
|
let privkey_bech32: String?
|
||||||
|
|
||||||
func to_full() -> FullKeypair? {
|
|
||||||
guard let privkey = self.privkey else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return FullKeypair(pubkey: pubkey, privkey: privkey)
|
|
||||||
}
|
|
||||||
|
|
||||||
init(pubkey: String, privkey: String?) {
|
init(pubkey: String, privkey: String?) {
|
||||||
self.pubkey = pubkey
|
self.pubkey = pubkey
|
||||||
self.privkey = privkey
|
self.privkey = privkey
|
||||||
|
|||||||
@@ -1,91 +0,0 @@
|
|||||||
//
|
|
||||||
// Mute.swift
|
|
||||||
// damus
|
|
||||||
//
|
|
||||||
// Created by William Casarin on 2023-01-25.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
func create_or_update_mutelist(keypair: FullKeypair, mprev: NostrEvent?, to_add: String) -> NostrEvent? {
|
|
||||||
return create_or_update_list_event(keypair: keypair, mprev: mprev, to_add: to_add, list_name: "mute", list_type: "p")
|
|
||||||
}
|
|
||||||
|
|
||||||
func remove_from_mutelist(keypair: FullKeypair, prev: NostrEvent, to_remove: String) -> NostrEvent? {
|
|
||||||
return remove_from_list_event(keypair: keypair, prev: prev, to_remove: to_remove, tag_type: "p")
|
|
||||||
}
|
|
||||||
|
|
||||||
func create_or_update_list_event(keypair: FullKeypair, mprev: NostrEvent?, to_add: String, list_name: String, list_type: String) -> NostrEvent? {
|
|
||||||
let pubkey = keypair.pubkey
|
|
||||||
|
|
||||||
if let prev = mprev {
|
|
||||||
if let okprev = ensure_list_name(list: prev, name: list_name), prev.pubkey == keypair.pubkey {
|
|
||||||
return add_to_list_event(keypair: keypair, prev: okprev, to_add: to_add, tag_type: list_type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let tags = [["d", list_name], [list_type, to_add]]
|
|
||||||
let ev = NostrEvent(content: "", pubkey: pubkey, kind: 30000, tags: tags)
|
|
||||||
|
|
||||||
ev.tags = tags
|
|
||||||
ev.id = calculate_event_id(ev: ev)
|
|
||||||
ev.sig = sign_event(privkey: keypair.privkey, ev: ev)
|
|
||||||
|
|
||||||
return ev
|
|
||||||
}
|
|
||||||
|
|
||||||
func remove_from_list_event(keypair: FullKeypair, prev: NostrEvent, to_remove: String, tag_type: String) -> NostrEvent? {
|
|
||||||
var exists = false
|
|
||||||
for tag in prev.tags {
|
|
||||||
if tag.count >= 2 && tag[0] == tag_type && tag[1] == to_remove {
|
|
||||||
exists = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure we actually have the pubkey to remove
|
|
||||||
guard exists else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
let new_tags = prev.tags.filter { tag in
|
|
||||||
!(tag.count >= 2 && tag[0] == tag_type && tag[1] == to_remove)
|
|
||||||
}
|
|
||||||
|
|
||||||
let ev = NostrEvent(content: prev.content, pubkey: keypair.pubkey, kind: 30000, tags: new_tags)
|
|
||||||
ev.id = calculate_event_id(ev: ev)
|
|
||||||
ev.sig = sign_event(privkey: keypair.privkey, ev: ev)
|
|
||||||
|
|
||||||
return ev
|
|
||||||
}
|
|
||||||
|
|
||||||
func add_to_list_event(keypair: FullKeypair, prev: NostrEvent, to_add: String, tag_type: String) -> NostrEvent? {
|
|
||||||
for tag in prev.tags {
|
|
||||||
// we are already muting this user
|
|
||||||
if tag.count >= 2 && tag[0] == tag_type && tag[1] == to_add {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let new = NostrEvent(content: prev.content, pubkey: keypair.pubkey, kind: 30000, tags: prev.tags)
|
|
||||||
new.tags.append([tag_type, to_add])
|
|
||||||
new.id = calculate_event_id(ev: new)
|
|
||||||
new.sig = sign_event(privkey: keypair.privkey, ev: new)
|
|
||||||
|
|
||||||
return new
|
|
||||||
}
|
|
||||||
|
|
||||||
func ensure_list_name(list: NostrEvent, name: String) -> NostrEvent? {
|
|
||||||
for tag in list.tags {
|
|
||||||
if tag.count >= 2 && tag[0] == "d" {
|
|
||||||
if tag[1] != name {
|
|
||||||
return nil
|
|
||||||
} else {
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
list.tags.insert(["d", name], at: 0)
|
|
||||||
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
@@ -11,90 +11,150 @@ extension Notification.Name {
|
|||||||
static var thread_focus: Notification.Name {
|
static var thread_focus: Notification.Name {
|
||||||
return Notification.Name("thread focus")
|
return Notification.Name("thread focus")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Notification.Name {
|
||||||
static var relays_changed: Notification.Name {
|
static var relays_changed: Notification.Name {
|
||||||
return Notification.Name("relays_changed")
|
return Notification.Name("relays_changed")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Notification.Name {
|
||||||
static var select_event: Notification.Name {
|
static var select_event: Notification.Name {
|
||||||
return Notification.Name("select_event")
|
return Notification.Name("select_event")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Notification.Name {
|
||||||
static var select_quote: Notification.Name {
|
static var select_quote: Notification.Name {
|
||||||
return Notification.Name("select quote")
|
return Notification.Name("select quote")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Notification.Name {
|
||||||
static var reply: Notification.Name {
|
static var reply: Notification.Name {
|
||||||
return Notification.Name("reply")
|
return Notification.Name("reply")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Notification.Name {
|
||||||
static var profile_updated: Notification.Name {
|
static var profile_updated: Notification.Name {
|
||||||
return Notification.Name("profile_updated")
|
return Notification.Name("profile_updated")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Notification.Name {
|
||||||
static var switched_timeline: Notification.Name {
|
static var switched_timeline: Notification.Name {
|
||||||
return Notification.Name("switched_timeline")
|
return Notification.Name("switched_timeline")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Notification.Name {
|
||||||
static var liked: Notification.Name {
|
static var liked: Notification.Name {
|
||||||
return Notification.Name("liked")
|
return Notification.Name("liked")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Notification.Name {
|
||||||
static var open_profile: Notification.Name {
|
static var open_profile: Notification.Name {
|
||||||
return Notification.Name("open_profile")
|
return Notification.Name("open_profile")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Notification.Name {
|
||||||
static var scroll_to_top: Notification.Name {
|
static var scroll_to_top: Notification.Name {
|
||||||
return Notification.Name("scroll_to_to")
|
return Notification.Name("scroll_to_to")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Notification.Name {
|
||||||
static var broadcast_event: Notification.Name {
|
static var broadcast_event: Notification.Name {
|
||||||
return Notification.Name("broadcast event")
|
return Notification.Name("broadcast event")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Notification.Name {
|
||||||
static var open_thread: Notification.Name {
|
static var open_thread: Notification.Name {
|
||||||
return Notification.Name("open thread")
|
return Notification.Name("open thread")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Notification.Name {
|
||||||
static var notice: Notification.Name {
|
static var notice: Notification.Name {
|
||||||
return Notification.Name("notice")
|
return Notification.Name("notice")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Notification.Name {
|
||||||
static var like: Notification.Name {
|
static var like: Notification.Name {
|
||||||
return Notification.Name("like note")
|
return Notification.Name("like note")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Notification.Name {
|
||||||
static var delete: Notification.Name {
|
static var delete: Notification.Name {
|
||||||
return Notification.Name("delete note")
|
return Notification.Name("delete note")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Notification.Name {
|
||||||
static var post: Notification.Name {
|
static var post: Notification.Name {
|
||||||
return Notification.Name("send post")
|
return Notification.Name("send post")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Notification.Name {
|
||||||
static var boost: Notification.Name {
|
static var boost: Notification.Name {
|
||||||
return Notification.Name("boost")
|
return Notification.Name("boost")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Notification.Name {
|
||||||
static var boosted: Notification.Name {
|
static var boosted: Notification.Name {
|
||||||
return Notification.Name("boosted")
|
return Notification.Name("boosted")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Notification.Name {
|
||||||
static var follow: Notification.Name {
|
static var follow: Notification.Name {
|
||||||
return Notification.Name("follow")
|
return Notification.Name("follow")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Notification.Name {
|
||||||
static var unfollow: Notification.Name {
|
static var unfollow: Notification.Name {
|
||||||
return Notification.Name("unfollow")
|
return Notification.Name("unfollow")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Notification.Name {
|
||||||
static var login: Notification.Name {
|
static var login: Notification.Name {
|
||||||
return Notification.Name("login")
|
return Notification.Name("login")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Notification.Name {
|
||||||
static var logout: Notification.Name {
|
static var logout: Notification.Name {
|
||||||
return Notification.Name("logout")
|
return Notification.Name("logout")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Notification.Name {
|
||||||
static var followed: Notification.Name {
|
static var followed: Notification.Name {
|
||||||
return Notification.Name("followed")
|
return Notification.Name("followed")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Notification.Name {
|
||||||
static var chatroom_meta: Notification.Name {
|
static var chatroom_meta: Notification.Name {
|
||||||
return Notification.Name("chatroom_meta")
|
return Notification.Name("chatroom_meta")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Notification.Name {
|
||||||
static var unfollowed: Notification.Name {
|
static var unfollowed: Notification.Name {
|
||||||
return Notification.Name("unfollowed")
|
return Notification.Name("unfollowed")
|
||||||
}
|
}
|
||||||
static var report: Notification.Name {
|
|
||||||
return Notification.Name("report")
|
|
||||||
}
|
|
||||||
static var block: Notification.Name {
|
|
||||||
return Notification.Name("block")
|
|
||||||
}
|
|
||||||
static var new_mutes: Notification.Name {
|
|
||||||
return Notification.Name("new_mutes")
|
|
||||||
}
|
|
||||||
static var new_unmutes: Notification.Name {
|
|
||||||
return Notification.Name("new_unmutes")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func handle_notify(_ name: Notification.Name) -> NotificationCenter.Publisher {
|
func handle_notify(_ name: Notification.Name) -> NotificationCenter.Publisher {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ struct InnerBannerImageView: View {
|
|||||||
self.imageModel = KFImageModel(
|
self.imageModel = KFImageModel(
|
||||||
url: url,
|
url: url,
|
||||||
fallbackUrl: nil,
|
fallbackUrl: nil,
|
||||||
maxByteSize: 20_971_520, // 20 MiB
|
maxByteSize: 5000000,
|
||||||
downsampleSize: CGSize(width: 750, height: 250)
|
downsampleSize: CGSize(width: 750, height: 250)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ struct ChatroomView: View {
|
|||||||
next_ev: ind == count-1 ? nil : thread.events[ind+1],
|
next_ev: ind == count-1 ? nil : thread.events[ind+1],
|
||||||
damus_state: damus
|
damus_state: damus
|
||||||
)
|
)
|
||||||
.event_context_menu(ev, privkey: damus.keypair.privkey, pubkey: ev.pubkey)
|
.event_context_menu(ev, pubkey: ev.pubkey, privkey: damus.keypair.privkey)
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
if thread.initial_event.id == ev.id {
|
if thread.initial_event.id == ev.id {
|
||||||
//dismiss()
|
//dismiss()
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ struct ConfigView: View {
|
|||||||
@State var confirm_logout: Bool = false
|
@State var confirm_logout: Bool = false
|
||||||
@State var new_relay: String = ""
|
@State var new_relay: String = ""
|
||||||
@State var show_privkey: Bool = false
|
@State var show_privkey: Bool = false
|
||||||
@State var show_libretranslate_api_key: Bool = false
|
|
||||||
@State var privkey: String
|
@State var privkey: String
|
||||||
@State var privkey_copied: Bool = false
|
@State var privkey_copied: Bool = false
|
||||||
@State var pubkey_copied: Bool = false
|
@State var pubkey_copied: Bool = false
|
||||||
@@ -117,39 +116,6 @@ struct ConfigView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Section(NSLocalizedString("LibreTranslate Translations", comment: "Section title for selecting the server that hosts the LibreTranslate machine translation API.")) {
|
|
||||||
Picker(NSLocalizedString("Server", comment: "Prompt selection of LibreTranslate server to perform machine translations on notes"), selection: $user_settings.libretranslate_server) {
|
|
||||||
ForEach(LibreTranslateServer.allCases, id: \.self) { server in
|
|
||||||
Text(server.model.displayName)
|
|
||||||
.tag(server.model.tag)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if user_settings.libretranslate_server != .none {
|
|
||||||
TextField(NSLocalizedString("URL", comment: "Example URL to LibreTranslate server"), text: $user_settings.libretranslate_url)
|
|
||||||
.disableAutocorrection(true)
|
|
||||||
.disabled(user_settings.libretranslate_server != .custom)
|
|
||||||
.autocapitalization(UITextAutocapitalizationType.none)
|
|
||||||
HStack {
|
|
||||||
if show_libretranslate_api_key {
|
|
||||||
TextField(NSLocalizedString("API Key (optional)", comment: "Example URL to LibreTranslate server"), text: $user_settings.libretranslate_api_key)
|
|
||||||
.disableAutocorrection(true)
|
|
||||||
.autocapitalization(UITextAutocapitalizationType.none)
|
|
||||||
Button(NSLocalizedString("Hide API Key", comment: "Button to hide the LibreTranslate server API key.")) {
|
|
||||||
show_libretranslate_api_key = false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
SecureField(NSLocalizedString("API Key (optional)", comment: "Example URL to LibreTranslate server"), text: $user_settings.libretranslate_api_key)
|
|
||||||
.disableAutocorrection(true)
|
|
||||||
.autocapitalization(UITextAutocapitalizationType.none)
|
|
||||||
Button(NSLocalizedString("Show API Key", comment: "Button to hide the LibreTranslate server API key.")) {
|
|
||||||
show_libretranslate_api_key = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Section(NSLocalizedString("Left Handed", comment: "Moves the post button to the left side of the screen")) {
|
Section(NSLocalizedString("Left Handed", comment: "Moves the post button to the left side of the screen")) {
|
||||||
Toggle(NSLocalizedString("Left Handed", comment: "Moves the post button to the left side of the screen"), isOn: $user_settings.left_handed)
|
Toggle(NSLocalizedString("Left Handed", comment: "Moves the post button to the left side of the screen"), isOn: $user_settings.left_handed)
|
||||||
.toggleStyle(.switch)
|
.toggleStyle(.switch)
|
||||||
@@ -173,10 +139,10 @@ struct ConfigView: View {
|
|||||||
.navigationTitle(NSLocalizedString("Settings", comment: "Navigation title for Settings view."))
|
.navigationTitle(NSLocalizedString("Settings", comment: "Navigation title for Settings view."))
|
||||||
.navigationBarTitleDisplayMode(.large)
|
.navigationBarTitleDisplayMode(.large)
|
||||||
.alert(NSLocalizedString("Logout", comment: "Alert for logging out the user."), isPresented: $confirm_logout) {
|
.alert(NSLocalizedString("Logout", comment: "Alert for logging out the user."), isPresented: $confirm_logout) {
|
||||||
Button(NSLocalizedString("Cancel", comment: "Cancel out of logging out the user."), role: .cancel) {
|
Button(NSLocalizedString("Cancel", comment: "Cancel out of logging out the user.")) {
|
||||||
confirm_logout = false
|
confirm_logout = false
|
||||||
}
|
}
|
||||||
Button(NSLocalizedString("Logout", comment: "Button for logging out the user."), role: .destructive) {
|
Button(NSLocalizedString("Logout", comment: "Button for logging out the user.")) {
|
||||||
notify(.logout, ())
|
notify(.logout, ())
|
||||||
}
|
}
|
||||||
} message: {
|
} message: {
|
||||||
@@ -188,7 +154,7 @@ struct ConfigView: View {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if relay.starts(with: "wss://") == false && relay.starts(with: "ws://") == false {
|
if relay.starts(with: "wss://") == false {
|
||||||
relay = "wss://" + relay
|
relay = "wss://" + relay
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ struct CreateAccountView: View {
|
|||||||
@StateObject var account: CreateAccountModel = CreateAccountModel()
|
@StateObject var account: CreateAccountModel = CreateAccountModel()
|
||||||
@State var is_light: Bool = false
|
@State var is_light: Bool = false
|
||||||
@State var is_done: Bool = false
|
@State var is_done: Bool = false
|
||||||
@State var reading_eula: Bool = false
|
|
||||||
|
|
||||||
func SignupForm<FormContent: View>(@ViewBuilder content: () -> FormContent) -> some View {
|
func SignupForm<FormContent: View>(@ViewBuilder content: () -> FormContent) -> some View {
|
||||||
return VStack(alignment: .leading, spacing: 10.0, content: content)
|
return VStack(alignment: .leading, spacing: 10.0, content: content)
|
||||||
@@ -76,7 +75,6 @@ struct CreateAccountView: View {
|
|||||||
NavigationLink(destination: SaveKeysView(account: account), isActive: $is_done) {
|
NavigationLink(destination: SaveKeysView(account: account), isActive: $is_done) {
|
||||||
EmptyView()
|
EmptyView()
|
||||||
}
|
}
|
||||||
|
|
||||||
DamusWhiteButton(NSLocalizedString("Create", comment: "Button to create account.")) {
|
DamusWhiteButton(NSLocalizedString("Create", comment: "Button to create account.")) {
|
||||||
self.is_done = true
|
self.is_done = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ struct DMChatView: View {
|
|||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
ForEach(Array(zip(dms.events, dms.events.indices)), id: \.0.id) { (ev, ind) in
|
ForEach(Array(zip(dms.events, dms.events.indices)), id: \.0.id) { (ev, ind) in
|
||||||
DMView(event: dms.events[ind], damus_state: damus_state)
|
DMView(event: dms.events[ind], damus_state: damus_state)
|
||||||
.event_context_menu(ev, privkey: damus_state.keypair.privkey, pubkey: ev.pubkey)
|
.event_context_menu(ev, pubkey: ev.pubkey, privkey: damus_state.keypair.privkey)
|
||||||
}
|
}
|
||||||
EndBlock(height: 80)
|
EndBlock(height: 80)
|
||||||
}
|
}
|
||||||
@@ -63,8 +63,6 @@ struct DMChatView: View {
|
|||||||
)
|
)
|
||||||
.padding(16)
|
.padding(16)
|
||||||
.foregroundColor(Color.primary)
|
.foregroundColor(Color.primary)
|
||||||
.frame(minHeight: 70, maxHeight: 150, alignment: .bottom)
|
|
||||||
.fixedSize(horizontal: false, vertical: true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Environment(\.colorScheme) var colorScheme
|
@Environment(\.colorScheme) var colorScheme
|
||||||
@@ -99,15 +97,22 @@ struct DMChatView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.fixedSize(horizontal: false, vertical: true)
|
|
||||||
.frame(minHeight: 70, maxHeight: 150, alignment: .bottom)
|
|
||||||
|
|
||||||
Text(message).opacity(0).padding(.all, 8)
|
|
||||||
.fixedSize(horizontal: false, vertical: true)
|
|
||||||
.frame(minHeight: 70, maxHeight: 150, alignment: .bottom)
|
|
||||||
}
|
}
|
||||||
.fixedSize(horizontal: false, vertical: true)
|
.frame(height: 50 + 20 * CGFloat(text_lines))
|
||||||
.frame(minHeight: 70, maxHeight: 150, alignment: .bottom)
|
}
|
||||||
|
|
||||||
|
var text_lines: Int {
|
||||||
|
var lines = 1
|
||||||
|
for c in message {
|
||||||
|
if lines > 4 {
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
if c.isNewline {
|
||||||
|
lines += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines
|
||||||
}
|
}
|
||||||
|
|
||||||
func send_message() {
|
func send_message() {
|
||||||
@@ -137,13 +142,12 @@ struct DMChatView: View {
|
|||||||
|
|
||||||
Footer
|
Footer
|
||||||
}
|
}
|
||||||
|
|
||||||
Text("Send a message to start the conversation...", comment: "Text prompt for user to send a message to the other user.")
|
Text("Send a message to start the conversation...", comment: "Text prompt for user to send a message to the other user.")
|
||||||
.lineLimit(nil)
|
.lineLimit(nil)
|
||||||
.multilineTextAlignment(.center)
|
.multilineTextAlignment(.center)
|
||||||
.padding(.horizontal, 40)
|
.padding(.horizontal, 40)
|
||||||
.opacity(((dms.events.count == 0) ? 1.0 : 0.0))
|
.opacity(((dms.events.count == 0) ? 1.0 : 0.0))
|
||||||
.foregroundColor(.gray)
|
.foregroundColor(.gray)
|
||||||
}
|
}
|
||||||
.navigationTitle(NSLocalizedString("DMs", comment: "Navigation title for DMs view, where DM is the English abbreviation for Direct Message."))
|
.navigationTitle(NSLocalizedString("DMs", comment: "Navigation title for DMs view, where DM is the English abbreviation for Direct Message."))
|
||||||
.toolbar { Header }
|
.toolbar { Header }
|
||||||
|
|||||||
@@ -1,96 +0,0 @@
|
|||||||
//
|
|
||||||
// EULAView.swift
|
|
||||||
// damus
|
|
||||||
//
|
|
||||||
// Created by William Casarin on 2023-01-25.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct EULAView: View {
|
|
||||||
@Environment(\.dismiss) var dismiss
|
|
||||||
@State var creating_account = false
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
ZStack {
|
|
||||||
DamusGradient()
|
|
||||||
|
|
||||||
ScrollView {
|
|
||||||
Text("EULA", comment: "Label indicating that the below text is the EULA, an acronym for End User License Agreement.")
|
|
||||||
.font(.title.bold())
|
|
||||||
.foregroundColor(.white)
|
|
||||||
|
|
||||||
Text(Markdown.parse(content: """
|
|
||||||
End User License Agreement
|
|
||||||
|
|
||||||
## Introduction
|
|
||||||
|
|
||||||
This End User License Agreement ("EULA") is a legal agreement between you and Damus Nostr Inc. for the use of our mobile application Damus. By installing, accessing, or using our application, you agree to be bound by the terms and conditions of this EULA.
|
|
||||||
|
|
||||||
## Prohibited Content and Conduct
|
|
||||||
|
|
||||||
You agree not to use our application to create, upload, post, send, or store any content that:
|
|
||||||
|
|
||||||
* Is illegal, infringing, or fraudulent
|
|
||||||
* Is defamatory, libelous, or threatening
|
|
||||||
* Is pornographic, obscene, or offensive
|
|
||||||
* Is discriminatory or promotes hate speech
|
|
||||||
* Is harmful to minors
|
|
||||||
* Is intended to harass or bully others
|
|
||||||
* Is intended to impersonate others
|
|
||||||
|
|
||||||
## You also agree not to engage in any conduct that:
|
|
||||||
|
|
||||||
* Harasses or bullies others
|
|
||||||
* Impersonates others
|
|
||||||
* Is intended to intimidate or threaten others
|
|
||||||
* Is intended to promote or incite violence
|
|
||||||
|
|
||||||
## Consequences of Violation
|
|
||||||
|
|
||||||
Any violation of this EULA, including the prohibited content and conduct outlined above, may result in the termination of your access to our application.
|
|
||||||
|
|
||||||
## Disclaimer of Warranties and Limitation of Liability
|
|
||||||
|
|
||||||
Our application is provided "as is" and "as available" without warranty of any kind, either express or implied, including but not limited to the implied warranties of merchantability and fitness for a particular purpose. We do not guarantee that our application will be uninterrupted or error-free. In no event shall Damus Nostr Inc. be liable for any damages whatsoever, including but not limited to direct, indirect, special, incidental, or consequential damages, arising out of or in connection with the use or inability to use our application.
|
|
||||||
|
|
||||||
## Changes to EULA
|
|
||||||
|
|
||||||
We reserve the right to update or modify this EULA at any time and without prior notice. Your continued use of our application following any changes to this EULA will be deemed to be your acceptance of such changes.
|
|
||||||
|
|
||||||
## Contact Information
|
|
||||||
|
|
||||||
If you have any questions about this EULA, please contact us at damus@jb55.com
|
|
||||||
|
|
||||||
## Acceptance of Terms
|
|
||||||
|
|
||||||
By using our Application, you signify your acceptance of this EULA. If you do not agree to this EULA, you may not use our Application.
|
|
||||||
|
|
||||||
"""))
|
|
||||||
.padding()
|
|
||||||
|
|
||||||
NavigationLink(destination: CreateAccountView(), isActive: $creating_account) {
|
|
||||||
EmptyView()
|
|
||||||
}
|
|
||||||
DamusWhiteButton(NSLocalizedString("Accept", comment: "Button to accept the end user license agreement before being allowed into the app.")) {
|
|
||||||
creating_account = true
|
|
||||||
}
|
|
||||||
|
|
||||||
DamusWhiteButton(NSLocalizedString("Reject", comment: "Button to reject the end user license agreement, which disallows the user from being let into the app.")) {
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.padding()
|
|
||||||
}
|
|
||||||
.navigationBarTitleDisplayMode(.inline)
|
|
||||||
.navigationBarBackButtonHidden(true)
|
|
||||||
.navigationBarItems(leading: BackNav())
|
|
||||||
.foregroundColor(.white)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct EULAView_Previews: PreviewProvider {
|
|
||||||
static var previews: some View {
|
|
||||||
EULAView()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -71,8 +71,8 @@ struct EventDetailView: View {
|
|||||||
}
|
}
|
||||||
toggle_thread_view()
|
toggle_thread_view()
|
||||||
}
|
}
|
||||||
case .event(let ev, _):
|
case .event(let ev, let highlight):
|
||||||
EventView(damus: damus, event: ev, has_action_bar: true)
|
EventView(event: ev, has_action_bar: true, damus: damus)
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
if thread.initial_event.id == ev.id {
|
if thread.initial_event.id == ev.id {
|
||||||
toggle_thread_view()
|
toggle_thread_view()
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ struct EventView: View {
|
|||||||
|
|
||||||
@EnvironmentObject var action_bar: ActionBarModel
|
@EnvironmentObject var action_bar: ActionBarModel
|
||||||
|
|
||||||
init(damus: DamusState, event: NostrEvent, has_action_bar: Bool) {
|
init(event: NostrEvent, has_action_bar: Bool, damus: DamusState) {
|
||||||
self.event = event
|
self.event = event
|
||||||
self.has_action_bar = has_action_bar
|
self.has_action_bar = has_action_bar
|
||||||
self.damus = damus
|
self.damus = damus
|
||||||
@@ -100,8 +100,6 @@ struct EventView: View {
|
|||||||
|
|
||||||
Text("\(format_relative_time(event.created_at))")
|
Text("\(format_relative_time(event.created_at))")
|
||||||
.foregroundColor(.gray)
|
.foregroundColor(.gray)
|
||||||
|
|
||||||
Spacer()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EventBody(damus_state: damus, event: event, size: .normal)
|
EventBody(damus_state: damus, event: event, size: .normal)
|
||||||
@@ -129,7 +127,7 @@ struct EventView: View {
|
|||||||
.id(event.id)
|
.id(event.id)
|
||||||
.frame(maxWidth: .infinity, minHeight: PFP_SIZE)
|
.frame(maxWidth: .infinity, minHeight: PFP_SIZE)
|
||||||
.padding([.bottom], 2)
|
.padding([.bottom], 2)
|
||||||
.event_context_menu(event, privkey: damus.keypair.privkey, pubkey: pubkey)
|
.event_context_menu(event, pubkey: pubkey, privkey: damus.keypair.privkey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,9 +169,37 @@ extension View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func event_context_menu(_ event: NostrEvent, privkey: String?, pubkey: String) -> some View {
|
func event_context_menu(_ event: NostrEvent, pubkey: String, privkey: String?) -> some View {
|
||||||
return self.contextMenu {
|
return self.contextMenu {
|
||||||
EventMenuContext(event: event, privkey: privkey, pubkey: pubkey)
|
Button {
|
||||||
|
UIPasteboard.general.string = event.get_content(privkey)
|
||||||
|
} label: {
|
||||||
|
Label(NSLocalizedString("Copy Text", comment: "Context menu option for copying the text from an note."), systemImage: "doc.on.doc")
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
UIPasteboard.general.string = bech32_pubkey(pubkey) ?? pubkey
|
||||||
|
} label: {
|
||||||
|
Label(NSLocalizedString("Copy User ID", comment: "Context menu option for copying the ID of the user who created the note."), systemImage: "person")
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
UIPasteboard.general.string = bech32_note_id(event.id) ?? event.id
|
||||||
|
} label: {
|
||||||
|
Label(NSLocalizedString("Copy Note ID", comment: "Context menu option for copying the ID of the note."), systemImage: "note.text")
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
UIPasteboard.general.string = event_to_json(ev: event)
|
||||||
|
} label: {
|
||||||
|
Label(NSLocalizedString("Copy Note JSON", comment: "Context menu option for copying the JSON text from the note."), systemImage: "j.square.on.square")
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
NotificationCenter.default.post(name: .broadcast_event, object: event)
|
||||||
|
} label: {
|
||||||
|
Label(NSLocalizedString("Broadcast", comment: "Context menu option for broadcasting the user's note to all of the user's connected relay servers."), systemImage: "globe")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -222,9 +248,9 @@ struct EventView_Previews: PreviewProvider {
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
EventView(
|
EventView(
|
||||||
damus: test_damus_state(),
|
|
||||||
event: test_event,
|
event: test_event,
|
||||||
has_action_bar: true
|
has_action_bar: true,
|
||||||
|
damus: test_damus_state()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ struct EmbeddedEventView: View {
|
|||||||
|
|
||||||
EventBody(damus_state: damus_state, event: event, size: .small)
|
EventBody(damus_state: damus_state, event: event, size: .small)
|
||||||
}
|
}
|
||||||
.event_context_menu(event, privkey: damus_state.keypair.privkey, pubkey: pubkey)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,102 +0,0 @@
|
|||||||
//
|
|
||||||
// EventMenu.swift
|
|
||||||
// damus
|
|
||||||
//
|
|
||||||
// Created by William Casarin on 2023-01-23.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct EventMenuContext: View {
|
|
||||||
let event: NostrEvent
|
|
||||||
let privkey: String?
|
|
||||||
let pubkey: String
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
|
|
||||||
Button {
|
|
||||||
UIPasteboard.general.string = event.get_content(privkey)
|
|
||||||
} label: {
|
|
||||||
Label(NSLocalizedString("Copy Text", comment: "Context menu option for copying the text from an note."), systemImage: "doc.on.doc")
|
|
||||||
}
|
|
||||||
|
|
||||||
Button {
|
|
||||||
UIPasteboard.general.string = bech32_pubkey(event.pubkey)
|
|
||||||
} label: {
|
|
||||||
Label(NSLocalizedString("Copy User Pubkey", comment: "Context menu option for copying the ID of the user who created the note."), systemImage: "person")
|
|
||||||
}
|
|
||||||
|
|
||||||
Button {
|
|
||||||
UIPasteboard.general.string = bech32_note_id(event.id) ?? event.id
|
|
||||||
} label: {
|
|
||||||
Label(NSLocalizedString("Copy Note ID", comment: "Context menu option for copying the ID of the note."), systemImage: "note.text")
|
|
||||||
}
|
|
||||||
|
|
||||||
Button {
|
|
||||||
UIPasteboard.general.string = event_to_json(ev: event)
|
|
||||||
} label: {
|
|
||||||
Label(NSLocalizedString("Copy Note JSON", comment: "Context menu option for copying the JSON text from the note."), systemImage: "square.on.square")
|
|
||||||
}
|
|
||||||
|
|
||||||
Button {
|
|
||||||
NotificationCenter.default.post(name: .broadcast_event, object: event)
|
|
||||||
} label: {
|
|
||||||
Label(NSLocalizedString("Broadcast", comment: "Context menu option for broadcasting the user's note to all of the user's connected relay servers."), systemImage: "globe")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only allow reporting if logged in with private key and the currently viewed profile is not the logged in profile.
|
|
||||||
if pubkey != event.pubkey && privkey != nil {
|
|
||||||
Button(role: .destructive) {
|
|
||||||
let target: ReportTarget = .note(ReportNoteTarget(pubkey: event.pubkey, note_id: event.id))
|
|
||||||
notify(.report, target)
|
|
||||||
} label: {
|
|
||||||
Label(NSLocalizedString("Report", comment: "Context menu option for reporting content."), systemImage: "exclamationmark.bubble")
|
|
||||||
}
|
|
||||||
|
|
||||||
Button(role: .destructive) {
|
|
||||||
notify(.block, event.pubkey)
|
|
||||||
} label: {
|
|
||||||
Label(NSLocalizedString("Block", comment: "Context menu option for blocking users."), systemImage: "exclamationmark.octagon")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
struct EventMenu: UIViewRepresentable {
|
|
||||||
|
|
||||||
typealias UIViewType = UIButton
|
|
||||||
|
|
||||||
let saveAction = UIAction(title: "") { action in }
|
|
||||||
let saveMenu = UIMenu(title: "", children: [
|
|
||||||
UIAction(title: "First Menu Item", image: UIImage(systemName: "nameOfSFSymbol")) { action in
|
|
||||||
//code action for menu item
|
|
||||||
},
|
|
||||||
UIAction(title: "First Menu Item", image: UIImage(systemName: "nameOfSFSymbol")) { action in
|
|
||||||
//code action for menu item
|
|
||||||
},
|
|
||||||
UIAction(title: "First Menu Item", image: UIImage(systemName: "nameOfSFSymbol")) { action in
|
|
||||||
//code action for menu item
|
|
||||||
},
|
|
||||||
])
|
|
||||||
|
|
||||||
func makeUIView(context: Context) -> UIButton {
|
|
||||||
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 20, height: 20))
|
|
||||||
button.showsMenuAsPrimaryAction = true
|
|
||||||
button.menu = saveMenu
|
|
||||||
|
|
||||||
return button
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateUIView(_ uiView: UIButton, context: Context) {
|
|
||||||
uiView.setImage(UIImage(systemName: "plus"), for: .normal)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct EventMenu_Previews: PreviewProvider {
|
|
||||||
static var previews: some View {
|
|
||||||
EventMenu(event: test_event, privkey: nil, pubkey: test_event.pubkey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
//
|
|
||||||
// MutedEventView.swift
|
|
||||||
// damus
|
|
||||||
//
|
|
||||||
// Created by William Casarin on 2023-01-27.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct MutedEventView: View {
|
|
||||||
let damus_state: DamusState
|
|
||||||
let event: NostrEvent
|
|
||||||
let scroller: ScrollViewProxy?
|
|
||||||
|
|
||||||
let selected: Bool
|
|
||||||
@Binding var nav_target: String?
|
|
||||||
@Binding var navigating: Bool
|
|
||||||
@State var shown: Bool
|
|
||||||
@Environment(\.colorScheme) var colorScheme
|
|
||||||
|
|
||||||
init(damus_state: DamusState, event: NostrEvent, scroller: ScrollViewProxy?, nav_target: Binding<String?>, navigating: Binding<Bool>, selected: Bool) {
|
|
||||||
self.damus_state = damus_state
|
|
||||||
self.event = event
|
|
||||||
self.scroller = scroller
|
|
||||||
self.selected = selected
|
|
||||||
self._nav_target = nav_target
|
|
||||||
self._navigating = navigating
|
|
||||||
self._shown = State(initialValue: !should_hide_event(contacts: damus_state.contacts, ev: event))
|
|
||||||
}
|
|
||||||
|
|
||||||
var should_mute: Bool {
|
|
||||||
return should_hide_event(contacts: damus_state.contacts, ev: event)
|
|
||||||
}
|
|
||||||
|
|
||||||
var FillColor: Color {
|
|
||||||
colorScheme == .light ? Color("DamusLightGrey") : Color("DamusDarkGrey")
|
|
||||||
}
|
|
||||||
|
|
||||||
var MutedBox: some View {
|
|
||||||
ZStack {
|
|
||||||
RoundedRectangle(cornerRadius: 20)
|
|
||||||
.foregroundColor(FillColor)
|
|
||||||
|
|
||||||
HStack {
|
|
||||||
Text("Post from a user you've blocked")
|
|
||||||
Spacer()
|
|
||||||
Button(shown ? "Hide" : "Show") {
|
|
||||||
shown.toggle()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.padding(10)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var Event: some View {
|
|
||||||
Group {
|
|
||||||
if selected {
|
|
||||||
SelectedEventView(damus: damus_state, event: event)
|
|
||||||
} else {
|
|
||||||
EventView(damus: damus_state, event: event, has_action_bar: true)
|
|
||||||
.onTapGesture {
|
|
||||||
nav_target = event.id
|
|
||||||
navigating = true
|
|
||||||
}
|
|
||||||
.onAppear {
|
|
||||||
// TODO: find another solution to prevent layout shifting and layout blocking on large responses
|
|
||||||
scroller?.scrollTo("main", anchor: .bottom)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
Group {
|
|
||||||
if should_mute {
|
|
||||||
MutedBox
|
|
||||||
}
|
|
||||||
if shown {
|
|
||||||
Event
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.onReceive(handle_notify(.new_mutes)) { notif in
|
|
||||||
guard let mutes = notif.object as? [String] else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if mutes.contains(event.pubkey) {
|
|
||||||
shown = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.onReceive(handle_notify(.new_unmutes)) { notif in
|
|
||||||
guard let unmutes = notif.object as? [String] else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if unmutes.contains(event.pubkey) {
|
|
||||||
shown = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MutedEventView_Previews: PreviewProvider {
|
|
||||||
@State static var nav_target: String? = nil
|
|
||||||
@State static var navigating: Bool = false
|
|
||||||
|
|
||||||
static var previews: some View {
|
|
||||||
|
|
||||||
MutedEventView(damus_state: test_damus_state(), event: test_event, scroller: nil, nav_target: $nav_target, navigating: $navigating, selected: false)
|
|
||||||
.frame(width: .infinity, height: 50)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -49,7 +49,6 @@ struct SelectedEventView: View {
|
|||||||
.padding([.top], 4)
|
.padding([.top], 4)
|
||||||
}
|
}
|
||||||
.padding([.leading], 2)
|
.padding([.leading], 2)
|
||||||
.event_context_menu(event, privkey: damus.keypair.privkey, pubkey: event.pubkey)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,26 @@ struct FollowUserView: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
HStack {
|
HStack {
|
||||||
UserView(damus_state: damus_state, pubkey: target.pubkey)
|
let pmodel = ProfileModel(pubkey: target.pubkey, damus: damus_state)
|
||||||
|
let followers = FollowersModel(damus_state: damus_state, target: target.pubkey)
|
||||||
|
let pv = ProfileView(damus_state: damus_state, profile: pmodel, followers: followers)
|
||||||
|
|
||||||
|
NavigationLink(destination: pv) {
|
||||||
|
ProfilePicView(pubkey: target.pubkey, size: PFP_SIZE, highlight: .none, profiles: damus_state.profiles)
|
||||||
|
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
let profile = damus_state.profiles.lookup(id: target.pubkey)
|
||||||
|
ProfileName(pubkey: target.pubkey, profile: profile, damus: damus_state, show_friend_confirmed: false, show_nip5_domain: false)
|
||||||
|
if let about = profile?.about {
|
||||||
|
Text(FollowUserView.markdown.process(about))
|
||||||
|
.lineLimit(3)
|
||||||
|
.font(.footnote)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.buttonStyle(PlainButtonStyle())
|
||||||
|
|
||||||
FollowButtonView(target: target, follow_state: damus_state.contacts.follow_state(target.pubkey))
|
FollowButtonView(target: target, follow_state: damus_state.contacts.follow_state(target.pubkey))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,67 +0,0 @@
|
|||||||
//
|
|
||||||
// MutelistView.swift
|
|
||||||
// damus
|
|
||||||
//
|
|
||||||
// Created by William Casarin on 2023-01-25.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct MutelistView: View {
|
|
||||||
let damus_state: DamusState
|
|
||||||
@State var users: [String]
|
|
||||||
|
|
||||||
func RemoveAction(pubkey: String) -> some View {
|
|
||||||
Button {
|
|
||||||
guard let mutelist = damus_state.contacts.mutelist else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let keypair = damus_state.keypair.to_full() else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let new_ev = remove_from_mutelist(keypair: keypair, prev: mutelist, to_remove: pubkey) else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
damus_state.contacts.set_mutelist(new_ev)
|
|
||||||
damus_state.pool.send(.event(new_ev))
|
|
||||||
users = get_mutelist_users(new_ev)
|
|
||||||
} label: {
|
|
||||||
Label(NSLocalizedString("Delete", comment: "Button to remove a user from their blocklist."), systemImage: "trash")
|
|
||||||
}
|
|
||||||
.tint(.red)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
List(users, id: \.self) { pubkey in
|
|
||||||
UserView(damus_state: damus_state, pubkey: pubkey)
|
|
||||||
.id(pubkey)
|
|
||||||
.swipeActions {
|
|
||||||
RemoveAction(pubkey: pubkey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.navigationTitle(NSLocalizedString("Blocked Users", comment: "Navigation title of view to see list of blocked users."))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func get_mutelist_users(_ mlist: NostrEvent?) -> [String] {
|
|
||||||
guard let mutelist = mlist else {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
return mutelist.tags.reduce(into: Array<String>()) { pks, tag in
|
|
||||||
if tag.count >= 2 && tag[0] == "p" {
|
|
||||||
pks.append(tag[1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MutelistView_Previews: PreviewProvider {
|
|
||||||
static var previews: some View {
|
|
||||||
MutelistView(damus_state: test_damus_state(), users: [test_event.pubkey, test_event.pubkey+"hi"])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -8,42 +8,35 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import LinkPresentation
|
import LinkPresentation
|
||||||
|
|
||||||
#if canImport(FoundationNetworking)
|
|
||||||
import FoundationNetworking
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct NoteArtifacts {
|
struct NoteArtifacts {
|
||||||
let content: AttributedString
|
let content: String
|
||||||
let images: [URL]
|
let images: [URL]
|
||||||
let invoices: [Invoice]
|
let invoices: [Invoice]
|
||||||
let links: [URL]
|
let links: [URL]
|
||||||
|
|
||||||
static func just_content(_ content: String) -> NoteArtifacts {
|
static func just_content(_ content: String) -> NoteArtifacts {
|
||||||
NoteArtifacts(content: AttributedString(stringLiteral: content), images: [], invoices: [], links: [])
|
NoteArtifacts(content: content, images: [], invoices: [], links: [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func render_note_content(ev: NostrEvent, profiles: Profiles, privkey: String?) -> NoteArtifacts {
|
func render_note_content(ev: NostrEvent, profiles: Profiles, privkey: String?) -> NoteArtifacts {
|
||||||
let blocks = ev.blocks(privkey)
|
let blocks = ev.blocks(privkey)
|
||||||
return render_blocks(blocks: blocks, profiles: profiles, privkey: privkey)
|
|
||||||
}
|
|
||||||
|
|
||||||
func render_blocks(blocks: [Block], profiles: Profiles, privkey: String?) -> NoteArtifacts {
|
|
||||||
var invoices: [Invoice] = []
|
var invoices: [Invoice] = []
|
||||||
var img_urls: [URL] = []
|
var img_urls: [URL] = []
|
||||||
var link_urls: [URL] = []
|
var link_urls: [URL] = []
|
||||||
let txt: AttributedString = blocks.reduce("") { str, block in
|
let txt = blocks.reduce("") { str, block in
|
||||||
switch block {
|
switch block {
|
||||||
case .mention(let m):
|
case .mention(let m):
|
||||||
return str + mention_str(m, profiles: profiles)
|
return str + mention_str(m, profiles: profiles)
|
||||||
case .text(let txt):
|
case .text(let txt):
|
||||||
return str + AttributedString(stringLiteral: txt)
|
return str + txt
|
||||||
case .hashtag(let htag):
|
case .hashtag(let htag):
|
||||||
return str + hashtag_str(htag)
|
return str + hashtag_str(htag)
|
||||||
case .invoice(let invoice):
|
case .invoice(let invoice):
|
||||||
invoices.append(invoice)
|
invoices.append(invoice)
|
||||||
return str
|
return str
|
||||||
case .url(let url):
|
case .url(let url):
|
||||||
|
|
||||||
// Handle Image URLs
|
// Handle Image URLs
|
||||||
if is_image_url(url) {
|
if is_image_url(url) {
|
||||||
// Append Image
|
// Append Image
|
||||||
@@ -51,7 +44,7 @@ func render_blocks(blocks: [Block], profiles: Profiles, privkey: String?) -> Not
|
|||||||
return str
|
return str
|
||||||
} else {
|
} else {
|
||||||
link_urls.append(url)
|
link_urls.append(url)
|
||||||
return str + url_str(url)
|
return str + url.absoluteString
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,48 +65,17 @@ struct NoteContentView: View {
|
|||||||
|
|
||||||
let show_images: Bool
|
let show_images: Bool
|
||||||
|
|
||||||
@State var checkingTranslationStatus: Bool = false
|
|
||||||
@State var language: String? = nil
|
|
||||||
@State var translated_note: String? = nil
|
|
||||||
@State var show_translated_note: Bool = false
|
|
||||||
@State var translated_artifacts: NoteArtifacts? = nil
|
|
||||||
|
|
||||||
@State var artifacts: NoteArtifacts
|
@State var artifacts: NoteArtifacts
|
||||||
|
|
||||||
@State var preview: LinkViewRepresentable? = nil
|
@State var preview: LinkViewRepresentable? = nil
|
||||||
let size: EventViewKind
|
let size: EventViewKind
|
||||||
|
|
||||||
@EnvironmentObject var user_settings: UserSettingsStore
|
|
||||||
|
|
||||||
func MainContent() -> some View {
|
func MainContent() -> some View {
|
||||||
return VStack(alignment: .leading) {
|
return VStack(alignment: .leading) {
|
||||||
Text(artifacts.content)
|
Text(Markdown.parse(content: artifacts.content))
|
||||||
.font(eventviewsize_to_font(size))
|
.font(eventviewsize_to_font(size))
|
||||||
.fixedSize(horizontal: false, vertical: true)
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
|
|
||||||
if size == .selected && language != nil && translated_artifacts != nil {
|
|
||||||
let languageName = Locale.current.localizedString(forLanguageCode: language!)
|
|
||||||
if show_translated_note {
|
|
||||||
Button(NSLocalizedString("Translated from \(languageName!)", comment: "Button to indicate that the note has been translated from a different language.")) {
|
|
||||||
show_translated_note = false
|
|
||||||
}
|
|
||||||
.font(.footnote)
|
|
||||||
.contentShape(Rectangle())
|
|
||||||
.padding(.top, 10)
|
|
||||||
|
|
||||||
Text(translated_artifacts!.content)
|
|
||||||
.font(eventviewsize_to_font(size))
|
|
||||||
.fixedSize(horizontal: false, vertical: true)
|
|
||||||
} else {
|
|
||||||
Button(NSLocalizedString("Translate Note", comment: "Button to translate note from different language.")) {
|
|
||||||
show_translated_note = true
|
|
||||||
}
|
|
||||||
.font(.footnote)
|
|
||||||
.contentShape(Rectangle())
|
|
||||||
.padding(.top, 10)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if show_images && artifacts.images.count > 0 {
|
if show_images && artifacts.images.count > 0 {
|
||||||
ImageCarousel(urls: artifacts.images)
|
ImageCarousel(urls: artifacts.images)
|
||||||
} else if !show_images && artifacts.images.count > 0 {
|
} else if !show_images && artifacts.images.count > 0 {
|
||||||
@@ -181,35 +143,6 @@ struct NoteContentView: View {
|
|||||||
previews.store(evid: self.event.id, preview: view)
|
previews.store(evid: self.event.id, preview: view)
|
||||||
self.preview = view
|
self.preview = view
|
||||||
}
|
}
|
||||||
|
|
||||||
if size == .selected && language == nil && !checkingTranslationStatus && user_settings.libretranslate_url != "" {
|
|
||||||
checkingTranslationStatus = true
|
|
||||||
|
|
||||||
let currentLanguage = Locale.current.languageCode ?? "en"
|
|
||||||
let translator = Translator(user_settings.libretranslate_url, apiKey: user_settings.libretranslate_api_key)
|
|
||||||
|
|
||||||
do {
|
|
||||||
language = try await translator.detect(event.content)
|
|
||||||
|
|
||||||
if language == nil {
|
|
||||||
language = currentLanguage
|
|
||||||
translated_note = nil
|
|
||||||
} else if language != currentLanguage {
|
|
||||||
translated_note = try await translator.translate(event.content, from: language!, to: currentLanguage)
|
|
||||||
|
|
||||||
if translated_note != nil {
|
|
||||||
let blocks = event.get_blocks(content: translated_note!)
|
|
||||||
translated_artifacts = render_blocks(blocks: blocks, profiles: profiles, privkey: privkey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
// If for whatever reason we're not able to figure out the language of the note, or translate the note, fail gracefully and do not retry. It's not the end of the world. Don't want to take down someone's translation server with an accidental denial of service attack.
|
|
||||||
language = currentLanguage
|
|
||||||
translated_note = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
checkingTranslationStatus = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,142 +163,20 @@ struct NoteContentView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func hashtag_str(_ htag: String) -> AttributedString {
|
func hashtag_str(_ htag: String) -> String {
|
||||||
var attributedString = AttributedString(stringLiteral: "#\(htag)")
|
return "[#\(htag)](nostr:t:\(htag))"
|
||||||
attributedString.link = URL(string: "nostr:t:\(htag)")
|
}
|
||||||
attributedString.foregroundColor = .purple
|
|
||||||
return attributedString
|
|
||||||
}
|
|
||||||
|
|
||||||
func url_str(_ url: URL) -> AttributedString {
|
func mention_str(_ m: Mention, profiles: Profiles) -> String {
|
||||||
var attributedString = AttributedString(stringLiteral: url.absoluteString)
|
|
||||||
attributedString.link = url
|
|
||||||
attributedString.foregroundColor = .purple
|
|
||||||
return attributedString
|
|
||||||
}
|
|
||||||
|
|
||||||
func mention_str(_ m: Mention, profiles: Profiles) -> AttributedString {
|
|
||||||
switch m.type {
|
switch m.type {
|
||||||
case .pubkey:
|
case .pubkey:
|
||||||
let pk = m.ref.ref_id
|
let pk = m.ref.ref_id
|
||||||
let profile = profiles.lookup(id: pk)
|
let profile = profiles.lookup(id: pk)
|
||||||
let disp = Profile.displayName(profile: profile, pubkey: pk)
|
let disp = Profile.displayName(profile: profile, pubkey: pk)
|
||||||
var attributedString = AttributedString(stringLiteral: "@\(disp)")
|
return "[@\(disp)](nostr:\(encode_pubkey_uri(m.ref)))"
|
||||||
attributedString.link = URL(string: "nostr:\(encode_pubkey_uri(m.ref))")
|
|
||||||
attributedString.foregroundColor = .purple
|
|
||||||
return attributedString
|
|
||||||
case .event:
|
case .event:
|
||||||
let bevid = bech32_note_id(m.ref.ref_id) ?? m.ref.ref_id
|
let bevid = bech32_note_id(m.ref.ref_id) ?? m.ref.ref_id
|
||||||
var attributedString = AttributedString(stringLiteral: "@\(abbrev_pubkey(bevid))")
|
return "[@\(abbrev_pubkey(bevid))](nostr:\(encode_event_id_uri(m.ref)))"
|
||||||
attributedString.link = URL(string: "nostr:\(encode_event_id_uri(m.ref))")
|
|
||||||
attributedString.foregroundColor = .purple
|
|
||||||
return attributedString
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public struct Translator {
|
|
||||||
private let url: String
|
|
||||||
private let apiKey: String?
|
|
||||||
private let session = URLSession.shared
|
|
||||||
private let encoder = JSONEncoder()
|
|
||||||
private let decoder = JSONDecoder()
|
|
||||||
|
|
||||||
public init(_ url: String, apiKey: String? = nil) {
|
|
||||||
self.url = url
|
|
||||||
self.apiKey = apiKey
|
|
||||||
}
|
|
||||||
|
|
||||||
public func detect(_ text: String) async throws -> String? {
|
|
||||||
let url = try makeURL(path: "/detect")
|
|
||||||
|
|
||||||
var request = URLRequest(url: url)
|
|
||||||
request.httpMethod = "POST"
|
|
||||||
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
|
||||||
|
|
||||||
struct RequestBody: Encodable {
|
|
||||||
let q: String
|
|
||||||
let api_key: String?
|
|
||||||
}
|
|
||||||
let body = RequestBody(q: text, api_key: apiKey)
|
|
||||||
request.httpBody = try encoder.encode(body)
|
|
||||||
|
|
||||||
struct Response: Decodable {
|
|
||||||
let confidence: Double
|
|
||||||
let language: String
|
|
||||||
}
|
|
||||||
|
|
||||||
let data = try await session.data(for: request)
|
|
||||||
let response = try decoder.decode([Response].self, from: data)
|
|
||||||
let language = response.first!
|
|
||||||
|
|
||||||
if language.confidence >= 80 {
|
|
||||||
return language.language
|
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public func translate(_ text: String, from sourceLanguage: String, to targetLanguage: String) async throws -> String {
|
|
||||||
let url = try makeURL(path: "/translate")
|
|
||||||
|
|
||||||
var request = URLRequest(url: url)
|
|
||||||
request.httpMethod = "POST"
|
|
||||||
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
|
||||||
|
|
||||||
struct RequestBody: Encodable {
|
|
||||||
let q: String
|
|
||||||
let source: String
|
|
||||||
let target: String
|
|
||||||
let api_key: String?
|
|
||||||
}
|
|
||||||
let body = RequestBody(q: text, source: sourceLanguage, target: targetLanguage, api_key: apiKey)
|
|
||||||
request.httpBody = try encoder.encode(body)
|
|
||||||
|
|
||||||
struct Response: Decodable {
|
|
||||||
let translatedText: String
|
|
||||||
}
|
|
||||||
let response: Response = try await decodedData(for: request)
|
|
||||||
return response.translatedText
|
|
||||||
}
|
|
||||||
|
|
||||||
private func makeURL(path: String) throws -> URL {
|
|
||||||
guard var components = URLComponents(string: url) else {
|
|
||||||
throw URLError(.badURL)
|
|
||||||
}
|
|
||||||
components.path = path
|
|
||||||
guard let url = components.url else {
|
|
||||||
throw URLError(.badURL)
|
|
||||||
}
|
|
||||||
return url
|
|
||||||
}
|
|
||||||
|
|
||||||
private func decodedData<Output: Decodable>(for request: URLRequest) async throws -> Output {
|
|
||||||
let data = try await session.data(for: request)
|
|
||||||
let result = try decoder.decode(Output.self, from: data)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private extension URLSession {
|
|
||||||
func data(for request: URLRequest) async throws -> Data {
|
|
||||||
var task: URLSessionDataTask?
|
|
||||||
let onCancel = { task?.cancel() }
|
|
||||||
return try await withTaskCancellationHandler(
|
|
||||||
operation: {
|
|
||||||
try await withCheckedThrowingContinuation { continuation in
|
|
||||||
task = dataTask(with: request) { data, _, error in
|
|
||||||
guard let data = data else {
|
|
||||||
let error = error ?? URLError(.badServerResponse)
|
|
||||||
return continuation.resume(throwing: error)
|
|
||||||
}
|
|
||||||
continuation.resume(returning: data)
|
|
||||||
}
|
|
||||||
task?.resume()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onCancel: { onCancel() }
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,7 +185,7 @@ struct NoteContentView_Previews: PreviewProvider {
|
|||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
let state = test_damus_state()
|
let state = test_damus_state()
|
||||||
let content = "hi there ¯\\_(ツ)_/¯ https://jb55.com/s/Oct12-150217.png 5739a762ef6124dd.jpg"
|
let content = "hi there ¯\\_(ツ)_/¯ https://jb55.com/s/Oct12-150217.png 5739a762ef6124dd.jpg"
|
||||||
let artifacts = NoteArtifacts(content: AttributedString(stringLiteral: content), images: [], invoices: [], links: [])
|
let artifacts = NoteArtifacts(content: content, images: [], invoices: [], links: [])
|
||||||
NoteContentView(privkey: "", event: NostrEvent(content: content, pubkey: "pk"), profiles: state.profiles, previews: PreviewCache(), show_images: true, artifacts: artifacts, size: .normal)
|
NoteContentView(privkey: "", event: NostrEvent(content: content, pubkey: "pk"), profiles: state.profiles, previews: PreviewCache(), show_images: true, artifacts: artifacts, size: .normal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,11 +16,10 @@ let POST_PLACEHOLDER = NSLocalizedString("Type your post here...", comment: "Tex
|
|||||||
|
|
||||||
struct PostView: View {
|
struct PostView: View {
|
||||||
@State var post: String = ""
|
@State var post: String = ""
|
||||||
@FocusState var focus: Bool
|
|
||||||
|
|
||||||
let replying_to: NostrEvent?
|
let replying_to: NostrEvent?
|
||||||
|
@FocusState var focus: Bool
|
||||||
let references: [ReferencedId]
|
let references: [ReferencedId]
|
||||||
let damus_state: DamusState
|
|
||||||
|
|
||||||
@Environment(\.presentationMode) var presentationMode
|
@Environment(\.presentationMode) var presentationMode
|
||||||
|
|
||||||
@@ -75,7 +74,6 @@ struct PostView: View {
|
|||||||
TextEditor(text: $post)
|
TextEditor(text: $post)
|
||||||
.focused($focus)
|
.focused($focus)
|
||||||
.textInputAutocapitalization(.sentences)
|
.textInputAutocapitalization(.sentences)
|
||||||
|
|
||||||
if post.isEmpty {
|
if post.isEmpty {
|
||||||
Text(POST_PLACEHOLDER)
|
Text(POST_PLACEHOLDER)
|
||||||
.padding(.top, 8)
|
.padding(.top, 8)
|
||||||
@@ -84,14 +82,6 @@ struct PostView: View {
|
|||||||
.allowsHitTesting(false)
|
.allowsHitTesting(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This if-block observes @ for tagging
|
|
||||||
if let searching = get_searching_string(post) {
|
|
||||||
VStack {
|
|
||||||
Spacer()
|
|
||||||
UserSearch(damus_state: damus_state, search: searching, post: $post)
|
|
||||||
}.zIndex(1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.onAppear() {
|
.onAppear() {
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||||
@@ -102,23 +92,3 @@ struct PostView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func get_searching_string(_ post: String) -> String? {
|
|
||||||
guard let last_word = post.components(separatedBy: .whitespacesAndNewlines).last else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
guard last_word.count >= 2 else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
guard last_word.first! == "@" else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// don't include @npub... strings
|
|
||||||
guard last_word.count != 64 else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return String(last_word.dropFirst())
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,87 +0,0 @@
|
|||||||
//
|
|
||||||
// UserAutocompletion.swift
|
|
||||||
// damus
|
|
||||||
//
|
|
||||||
// Created by William Casarin on 2023-01-28.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct SearchedUser: Identifiable {
|
|
||||||
let petname: String?
|
|
||||||
let profile: Profile?
|
|
||||||
let pubkey: String
|
|
||||||
|
|
||||||
var id: String {
|
|
||||||
return pubkey
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct UserSearch: View {
|
|
||||||
let damus_state: DamusState
|
|
||||||
let search: String
|
|
||||||
@Binding var post: String
|
|
||||||
|
|
||||||
var users: [SearchedUser] {
|
|
||||||
guard let contacts = damus_state.contacts.event else {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
return search_users(profiles: damus_state.profiles, tags: contacts.tags, search: search)
|
|
||||||
}
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
ScrollView {
|
|
||||||
LazyVStack {
|
|
||||||
ForEach(users) { user in
|
|
||||||
UserView(damus_state: damus_state, pubkey: user.pubkey)
|
|
||||||
.onTapGesture {
|
|
||||||
guard let pk = bech32_pubkey(user.pubkey) else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
post = post.replacingOccurrences(of: "@"+search, with: "@"+pk+" ")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct UserSearch_Previews: PreviewProvider {
|
|
||||||
static let search: String = "jb55"
|
|
||||||
@State static var post: String = "some @jb55"
|
|
||||||
|
|
||||||
static var previews: some View {
|
|
||||||
UserSearch(damus_state: test_damus_state(), search: search, post: $post)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func search_users(profiles: Profiles, tags: [[String]], search: String) -> [SearchedUser] {
|
|
||||||
var seen_user = Set<String>()
|
|
||||||
return tags.reduce(into: Array<SearchedUser>()) { arr, tag in
|
|
||||||
guard tag.count >= 2 && tag[0] == "p" else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let pubkey = tag[1]
|
|
||||||
guard !seen_user.contains(pubkey) else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
seen_user.insert(pubkey)
|
|
||||||
|
|
||||||
var petname: String? = nil
|
|
||||||
if tag.count >= 4 {
|
|
||||||
petname = tag[3]
|
|
||||||
}
|
|
||||||
|
|
||||||
let profile = profiles.lookup(id: pubkey)
|
|
||||||
|
|
||||||
guard ((petname?.hasPrefix(search) ?? false) || (profile?.name?.hasPrefix(search) ?? false)) else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let searched_user = SearchedUser(petname: petname, profile: profile, pubkey: pubkey)
|
|
||||||
arr.append(searched_user)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -46,7 +46,7 @@ struct InnerProfilePicView: View {
|
|||||||
self.imageModel = KFImageModel(
|
self.imageModel = KFImageModel(
|
||||||
url: url,
|
url: url,
|
||||||
fallbackUrl: fallbackUrl,
|
fallbackUrl: fallbackUrl,
|
||||||
maxByteSize: 5_242_880, // 5Mib
|
maxByteSize: 1000000,
|
||||||
downsampleSize: CGSize(width: 200, height: 200)
|
downsampleSize: CGSize(width: 200, height: 200)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -114,8 +114,7 @@ struct ProfileView: View {
|
|||||||
@State var showing_select_wallet: Bool = false
|
@State var showing_select_wallet: Bool = false
|
||||||
@State var is_zoomed: Bool = false
|
@State var is_zoomed: Bool = false
|
||||||
@State var show_share_sheet: Bool = false
|
@State var show_share_sheet: Bool = false
|
||||||
@State var action_sheet_presented: Bool = false
|
@StateObject var user_settings = UserSettingsStore()
|
||||||
@EnvironmentObject var user_settings: UserSettingsStore
|
|
||||||
|
|
||||||
@Environment(\.dismiss) var dismiss
|
@Environment(\.dismiss) var dismiss
|
||||||
@Environment(\.colorScheme) var colorScheme
|
@Environment(\.colorScheme) var colorScheme
|
||||||
@@ -148,7 +147,9 @@ struct ProfileView: View {
|
|||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
Image(systemName: "bolt.circle")
|
Image(systemName: "bolt.circle")
|
||||||
.profile_button_style(scheme: colorScheme)
|
.symbolRenderingMode(.palette)
|
||||||
|
.foregroundStyle(colorScheme == .dark ? .white : .black, colorScheme == .dark ? .white : .black)
|
||||||
|
.font(.system(size: 32).weight(.thin))
|
||||||
.contextMenu {
|
.contextMenu {
|
||||||
Button {
|
Button {
|
||||||
UIPasteboard.general.string = profile.lnurl ?? ""
|
UIPasteboard.general.string = profile.lnurl ?? ""
|
||||||
@@ -167,21 +168,15 @@ struct ProfileView: View {
|
|||||||
|
|
||||||
static let markdown = Markdown()
|
static let markdown = Markdown()
|
||||||
|
|
||||||
var ActionSheetButton: some View {
|
|
||||||
Button(action: {
|
|
||||||
action_sheet_presented = true
|
|
||||||
}) {
|
|
||||||
Image(systemName: "ellipsis.circle")
|
|
||||||
.profile_button_style(scheme: colorScheme)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var ShareButton: some View {
|
var ShareButton: some View {
|
||||||
Button(action: {
|
Button(action: {
|
||||||
show_share_sheet = true
|
show_share_sheet = true
|
||||||
}) {
|
}) {
|
||||||
Image(systemName: "square.and.arrow.up.circle")
|
Image(systemName: "square.and.arrow.up.circle.fill")
|
||||||
.profile_button_style(scheme: colorScheme)
|
.symbolRenderingMode(.palette)
|
||||||
|
.font(.system(size: 32))
|
||||||
|
.padding()
|
||||||
|
.foregroundStyle(.white, .black, .black.opacity(0.8))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +186,9 @@ struct ProfileView: View {
|
|||||||
.environmentObject(dm_model)
|
.environmentObject(dm_model)
|
||||||
return NavigationLink(destination: dmview) {
|
return NavigationLink(destination: dmview) {
|
||||||
Image(systemName: "bubble.left.circle")
|
Image(systemName: "bubble.left.circle")
|
||||||
.profile_button_style(scheme: colorScheme)
|
.symbolRenderingMode(.palette)
|
||||||
|
.font(.system(size: 32).weight(.thin))
|
||||||
|
.foregroundStyle(colorScheme == .dark ? .white : .black, colorScheme == .dark ? .white : .black)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,6 +227,9 @@ struct ProfileView: View {
|
|||||||
.clipped()
|
.clipped()
|
||||||
.offset(x: 0, y: self.getOffsetForHeaderImage(geometry))
|
.offset(x: 0, y: self.getOffsetForHeaderImage(geometry))
|
||||||
|
|
||||||
|
ShareButton
|
||||||
|
.offset(x: geometry.size.width - 80.0, y: 50.0 )
|
||||||
|
|
||||||
}.frame(height: BANNER_HEIGHT)
|
}.frame(height: BANNER_HEIGHT)
|
||||||
|
|
||||||
VStack(alignment: .leading, spacing: 8.0) {
|
VStack(alignment: .leading, spacing: 8.0) {
|
||||||
@@ -248,7 +248,6 @@ struct ProfileView: View {
|
|||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
Group {
|
Group {
|
||||||
ActionSheetButton
|
|
||||||
|
|
||||||
if let profile = data {
|
if let profile = data {
|
||||||
if let lnurl = profile.lnurl, lnurl != "" {
|
if let lnurl = profile.lnurl, lnurl != "" {
|
||||||
@@ -374,23 +373,6 @@ struct ProfileView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.confirmationDialog(NSLocalizedString("Actions", comment: "Title for confirmation dialog to either share, report, or block a profile."), isPresented: $action_sheet_presented) {
|
|
||||||
Button(NSLocalizedString("Share", comment: "Button to share the link to a profile.")) {
|
|
||||||
show_share_sheet = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only allow reporting if logged in with private key and the currently viewed profile is not the logged in profile.
|
|
||||||
if profile.pubkey != damus_state.pubkey && damus_state.is_privkey_user {
|
|
||||||
Button(NSLocalizedString("Report", comment: "Button to report a profile."), role: .destructive) {
|
|
||||||
let target: ReportTarget = .user(profile.pubkey)
|
|
||||||
notify(.report, target)
|
|
||||||
}
|
|
||||||
|
|
||||||
Button(NSLocalizedString("Block", comment: "Button to block a profile."), role: .destructive) {
|
|
||||||
notify(.block, profile.pubkey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.ignoresSafeArea()
|
.ignoresSafeArea()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -491,11 +473,3 @@ struct KeyView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension View {
|
|
||||||
func profile_button_style(scheme: ColorScheme) -> some View {
|
|
||||||
self.symbolRenderingMode(.palette)
|
|
||||||
.font(.system(size: 32).weight(.thin))
|
|
||||||
.foregroundStyle(scheme == .dark ? .white : .black, scheme == .dark ? .white : .black)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,90 +0,0 @@
|
|||||||
//
|
|
||||||
// QRCodeView.swift
|
|
||||||
// damus
|
|
||||||
//
|
|
||||||
// Created by eric on 1/27/23.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
import CoreImage.CIFilterBuiltins
|
|
||||||
|
|
||||||
struct QRCodeView: View {
|
|
||||||
let damus_state: DamusState
|
|
||||||
|
|
||||||
@Environment(\.dismiss) var dismiss
|
|
||||||
@Environment(\.presentationMode) var presentationMode
|
|
||||||
|
|
||||||
var maybe_key: String? {
|
|
||||||
guard let key = bech32_pubkey(damus_state.pubkey) else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return key
|
|
||||||
}
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
ZStack(alignment: .topLeading) {
|
|
||||||
DamusGradient()
|
|
||||||
Button {
|
|
||||||
presentationMode.wrappedValue.dismiss()
|
|
||||||
} label: {
|
|
||||||
Image(systemName: "xmark")
|
|
||||||
.foregroundColor(.white)
|
|
||||||
.font(.subheadline)
|
|
||||||
.padding(.leading, 20)
|
|
||||||
}
|
|
||||||
.zIndex(1)
|
|
||||||
|
|
||||||
VStack(alignment: .center) {
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
if let key = maybe_key {
|
|
||||||
Image(uiImage: generateQRCode(pubkey: "nostr:" + key))
|
|
||||||
.interpolation(.none)
|
|
||||||
.resizable()
|
|
||||||
.scaledToFit()
|
|
||||||
.frame(width: 200, height: 200)
|
|
||||||
.padding()
|
|
||||||
|
|
||||||
Text(key)
|
|
||||||
.font(.headline)
|
|
||||||
.foregroundColor(Color(.white))
|
|
||||||
.padding()
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
.modifier(SwipeToDismissModifier(minDistance: nil, onDismiss: {
|
|
||||||
presentationMode.wrappedValue.dismiss()
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
func generateQRCode(pubkey: String) -> UIImage {
|
|
||||||
let data = pubkey.data(using: String.Encoding.ascii)
|
|
||||||
let qrFilter = CIFilter(name: "CIQRCodeGenerator")
|
|
||||||
qrFilter?.setValue(data, forKey: "inputMessage")
|
|
||||||
let qrImage = qrFilter?.outputImage
|
|
||||||
|
|
||||||
let colorInvertFilter = CIFilter(name: "CIColorInvert")
|
|
||||||
colorInvertFilter?.setValue(qrImage, forKey: "inputImage")
|
|
||||||
let outputInvertedImage = colorInvertFilter?.outputImage
|
|
||||||
|
|
||||||
let maskToAlphaFilter = CIFilter(name: "CIMaskToAlpha")
|
|
||||||
maskToAlphaFilter?.setValue(outputInvertedImage, forKey: "inputImage")
|
|
||||||
let outputCIImage = maskToAlphaFilter?.outputImage
|
|
||||||
|
|
||||||
let context = CIContext()
|
|
||||||
let cgImage = context.createCGImage(outputCIImage!, from: outputCIImage!.extent)!
|
|
||||||
return UIImage(cgImage: cgImage)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct QRCodeView_Previews: PreviewProvider {
|
|
||||||
static var previews: some View {
|
|
||||||
QRCodeView(damus_state: test_damus_state())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -45,9 +45,9 @@ struct ReplyView: View {
|
|||||||
ParticipantsView(damus_state: damus, references: $references, originalReferences: $originalReferences)
|
ParticipantsView(damus_state: damus, references: $references, originalReferences: $originalReferences)
|
||||||
}
|
}
|
||||||
ScrollView {
|
ScrollView {
|
||||||
EventView(damus: damus, event: replying_to, has_action_bar: false)
|
EventView(event: replying_to, has_action_bar: false, damus: damus)
|
||||||
}
|
}
|
||||||
PostView(replying_to: replying_to, references: references, damus_state: damus)
|
PostView(replying_to: replying_to, references: references)
|
||||||
}
|
}
|
||||||
.onAppear {
|
.onAppear {
|
||||||
references = gather_reply_ids(our_pubkey: damus.pubkey, from: replying_to)
|
references = gather_reply_ids(our_pubkey: damus.pubkey, from: replying_to)
|
||||||
|
|||||||
@@ -1,115 +0,0 @@
|
|||||||
//
|
|
||||||
// ReportView.swift
|
|
||||||
// damus
|
|
||||||
//
|
|
||||||
// Created by William Casarin on 2023-01-25.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct ReportView: View {
|
|
||||||
let pool: RelayPool
|
|
||||||
let target: ReportTarget
|
|
||||||
let privkey: String
|
|
||||||
|
|
||||||
@State var report_sent: Bool = false
|
|
||||||
@State var report_id: String = ""
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
if report_sent {
|
|
||||||
Success
|
|
||||||
} else {
|
|
||||||
MainForm
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var Success: some View {
|
|
||||||
VStack(alignment: .center, spacing: 20) {
|
|
||||||
Text("Report sent!", comment: "Message indicating that a report was successfully sent to relay servers.")
|
|
||||||
.font(.headline)
|
|
||||||
|
|
||||||
Text("Relays have been notified and clients will be able to use this information to filter content. Thank you!", comment: "Description of what was done as a result of sending a report to relay servers.")
|
|
||||||
|
|
||||||
Text("Report ID:", comment: "Label indicating that the text underneath is the identifier of the report that was sent to relay servers.")
|
|
||||||
|
|
||||||
Text(report_id)
|
|
||||||
|
|
||||||
Button(NSLocalizedString("Copy Report ID", comment: "Button to copy report ID.")) {
|
|
||||||
UIPasteboard.general.string = report_id
|
|
||||||
let g = UIImpactFeedbackGenerator(style: .medium)
|
|
||||||
g.impactOccurred()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.padding()
|
|
||||||
}
|
|
||||||
|
|
||||||
func do_send_report(type: ReportType) {
|
|
||||||
guard let ev = send_report(privkey: privkey, pool: pool, target: target, type: type) else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let note_id = bech32_note_id(ev.id) else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
report_sent = true
|
|
||||||
report_id = note_id
|
|
||||||
}
|
|
||||||
|
|
||||||
var MainForm: some View {
|
|
||||||
VStack {
|
|
||||||
|
|
||||||
Text("Report", comment: "Label indicating that the current view is for the user to report content.")
|
|
||||||
.font(.headline)
|
|
||||||
.padding()
|
|
||||||
|
|
||||||
Form {
|
|
||||||
Section(content: {
|
|
||||||
Button(NSLocalizedString("It's spam", comment: "Button for user to report that the account or content has spam.")) {
|
|
||||||
do_send_report(type: .spam)
|
|
||||||
}
|
|
||||||
|
|
||||||
Button(NSLocalizedString("Nudity or explicit content", comment: "Button for user to report that the account or content has nudity or explicit content.")) {
|
|
||||||
do_send_report(type: .explicit)
|
|
||||||
}
|
|
||||||
|
|
||||||
Button(NSLocalizedString("Illegal content", comment: "Button for user to report that the account or content has illegal content.")) {
|
|
||||||
do_send_report(type: .illegal)
|
|
||||||
}
|
|
||||||
|
|
||||||
if case .user = target {
|
|
||||||
Button(NSLocalizedString("They are impersonating someone", comment: "Button for user to report that the account is impersonating someone.")) {
|
|
||||||
do_send_report(type: .impersonation)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, header: {
|
|
||||||
Text("What do you want to report?", comment: "Header text to prompt user what issue they want to report.")
|
|
||||||
}, footer: {
|
|
||||||
Text("Your report will be sent to the relays you are connected to", comment: "Footer text to inform user what will happen when the report is submitted.")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func send_report(privkey: String, pool: RelayPool, target: ReportTarget, type: ReportType) -> NostrEvent? {
|
|
||||||
let report = Report(type: type, target: target, message: "")
|
|
||||||
guard let ev = create_report_event(privkey: privkey, report: report) else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
pool.send(.event(ev))
|
|
||||||
return ev
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ReportView_Previews: PreviewProvider {
|
|
||||||
static var previews: some View {
|
|
||||||
let ds = test_damus_state()
|
|
||||||
VStack {
|
|
||||||
|
|
||||||
ReportView(pool: ds.pool, target: ReportTarget.user(""), privkey: "")
|
|
||||||
|
|
||||||
ReportView(pool: ds.pool, target: ReportTarget.user(""), privkey: "", report_sent: true, report_id: "report_id")
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -87,9 +87,6 @@ struct SearchHomeView: View {
|
|||||||
.onChange(of: search) { s in
|
.onChange(of: search) { s in
|
||||||
print("search change 1")
|
print("search change 1")
|
||||||
}
|
}
|
||||||
.onReceive(handle_notify(.new_mutes)) { _ in
|
|
||||||
self.model.filter_muted()
|
|
||||||
}
|
|
||||||
.onAppear {
|
.onAppear {
|
||||||
if model.events.isEmpty {
|
if model.events.isEmpty {
|
||||||
model.subscribe()
|
model.subscribe()
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ struct SetupView: View {
|
|||||||
DamusGradient()
|
DamusGradient()
|
||||||
|
|
||||||
VStack(alignment: .center) {
|
VStack(alignment: .center) {
|
||||||
NavigationLink(destination: EULAView(), tag: .create_account, selection: $state ) {
|
NavigationLink(destination: CreateAccountView(), tag: .create_account, selection: $state ) {
|
||||||
EmptyView()
|
EmptyView()
|
||||||
}
|
}
|
||||||
NavigationLink(destination: LoginView(), tag: .login, selection: $state ) {
|
NavigationLink(destination: LoginView(), tag: .login, selection: $state ) {
|
||||||
|
|||||||
@@ -12,9 +12,7 @@ struct SideMenuView: View {
|
|||||||
@Binding var isSidebarVisible: Bool
|
@Binding var isSidebarVisible: Bool
|
||||||
|
|
||||||
@State var confirm_logout: Bool = false
|
@State var confirm_logout: Bool = false
|
||||||
@EnvironmentObject var user_settings: UserSettingsStore
|
@StateObject var user_settings = UserSettingsStore()
|
||||||
|
|
||||||
@State private var showQRCode = false
|
|
||||||
|
|
||||||
@Environment(\.colorScheme) var colorScheme
|
@Environment(\.colorScheme) var colorScheme
|
||||||
|
|
||||||
@@ -78,6 +76,22 @@ struct SideMenuView: View {
|
|||||||
Divider()
|
Divider()
|
||||||
.padding(.trailing,40)
|
.padding(.trailing,40)
|
||||||
|
|
||||||
|
/*
|
||||||
|
HStack(alignment: .bottom) {
|
||||||
|
Text("69,420")
|
||||||
|
.foregroundColor(.accentColor)
|
||||||
|
.font(.largeTitle)
|
||||||
|
Text("SATS")
|
||||||
|
.font(.caption)
|
||||||
|
.padding(.bottom,6)
|
||||||
|
}
|
||||||
|
|
||||||
|
Divider()
|
||||||
|
.padding(.trailing,40)
|
||||||
|
*/
|
||||||
|
|
||||||
|
// THERE IS A LIMIT OF 10 NAVIGATIONLINKS!!! (Consider some in other views)
|
||||||
|
|
||||||
NavigationLink(destination: ProfileView(damus_state: damus_state, profile: profile_model, followers: followers)) {
|
NavigationLink(destination: ProfileView(damus_state: damus_state, profile: profile_model, followers: followers)) {
|
||||||
Label(NSLocalizedString("Profile", comment: "Sidebar menu label for Profile view."), systemImage: "person")
|
Label(NSLocalizedString("Profile", comment: "Sidebar menu label for Profile view."), systemImage: "person")
|
||||||
.font(.title2)
|
.font(.title2)
|
||||||
@@ -109,12 +123,6 @@ struct SideMenuView: View {
|
|||||||
})
|
})
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NavigationLink(destination: MutelistView(damus_state: damus_state, users: get_mutelist_users(damus_state.contacts.mutelist) )) {
|
|
||||||
Label(NSLocalizedString("Blocked", comment: "Sidebar menu label for Profile view."), systemImage: "exclamationmark.octagon")
|
|
||||||
.font(.title2)
|
|
||||||
.foregroundColor(textColor())
|
|
||||||
}
|
|
||||||
|
|
||||||
NavigationLink(destination: ConfigView(state: damus_state).environmentObject(user_settings)) {
|
NavigationLink(destination: ConfigView(state: damus_state).environmentObject(user_settings)) {
|
||||||
Label(NSLocalizedString("Settings", comment: "Sidebar menu label for accessing the app settings"), systemImage: "gear")
|
Label(NSLocalizedString("Settings", comment: "Sidebar menu label for accessing the app settings"), systemImage: "gear")
|
||||||
.font(.title2)
|
.font(.title2)
|
||||||
@@ -126,33 +134,18 @@ struct SideMenuView: View {
|
|||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
HStack(alignment: .center) {
|
Button(action: {
|
||||||
Button(action: {
|
//ConfigView(state: damus_state)
|
||||||
//ConfigView(state: damus_state)
|
if damus_state.keypair.privkey == nil {
|
||||||
if damus_state.keypair.privkey == nil {
|
notify(.logout, ())
|
||||||
notify(.logout, ())
|
} else {
|
||||||
} else {
|
confirm_logout = true
|
||||||
confirm_logout = true
|
|
||||||
}
|
|
||||||
}, label: {
|
|
||||||
Label(NSLocalizedString("Sign out", comment: "Sidebar menu label to sign out of the account."), systemImage: "pip.exit")
|
|
||||||
.font(.title3)
|
|
||||||
.foregroundColor(textColor())
|
|
||||||
})
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
Button(action: {
|
|
||||||
showQRCode.toggle()
|
|
||||||
}, label: {
|
|
||||||
Label(NSLocalizedString("", comment: "Sidebar menu label for accessing QRCode view"), systemImage: "qrcode")
|
|
||||||
.font(.title)
|
|
||||||
.foregroundColor(textColor())
|
|
||||||
.padding(.trailing, 20)
|
|
||||||
}).fullScreenCover(isPresented: $showQRCode) {
|
|
||||||
QRCodeView(damus_state: damus_state)
|
|
||||||
}
|
}
|
||||||
}
|
}, label: {
|
||||||
|
Label(NSLocalizedString("Sign out", comment: "Sidebar menu label to sign out of the account."), systemImage: "pip.exit")
|
||||||
|
.font(.title3)
|
||||||
|
.foregroundColor(textColor())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
.padding(.top, 60)
|
.padding(.top, 60)
|
||||||
.padding(.bottom, 40)
|
.padding(.bottom, 40)
|
||||||
@@ -165,10 +158,10 @@ struct SideMenuView: View {
|
|||||||
isSidebarVisible.toggle()
|
isSidebarVisible.toggle()
|
||||||
}
|
}
|
||||||
.alert("Logout", isPresented: $confirm_logout) {
|
.alert("Logout", isPresented: $confirm_logout) {
|
||||||
Button(NSLocalizedString("Cancel", comment: "Cancel out of logging out the user."), role: .cancel) {
|
Button(NSLocalizedString("Cancel", comment: "Cancel out of logging out the user.")) {
|
||||||
confirm_logout = false
|
confirm_logout = false
|
||||||
}
|
}
|
||||||
Button(NSLocalizedString("Logout", comment: "Button for logging out the user."), role: .destructive) {
|
Button(NSLocalizedString("Logout", comment: "Button for logging out the user.")) {
|
||||||
notify(.logout, ())
|
notify(.logout, ())
|
||||||
}
|
}
|
||||||
} message: {
|
} message: {
|
||||||
|
|||||||
@@ -255,13 +255,15 @@ struct ThreadV2View: View {
|
|||||||
// MARK: - Parents events view
|
// MARK: - Parents events view
|
||||||
VStack {
|
VStack {
|
||||||
ForEach(thread.parentEvents, id: \.id) { event in
|
ForEach(thread.parentEvents, id: \.id) { event in
|
||||||
MutedEventView(damus_state: damus,
|
EventView(event: event, has_action_bar: true, damus: damus)
|
||||||
event: event,
|
.onTapGesture {
|
||||||
scroller: reader,
|
nav_target = event.id
|
||||||
nav_target: $nav_target,
|
navigating = true
|
||||||
navigating: $navigating,
|
}
|
||||||
selected: false
|
.onAppear {
|
||||||
)
|
// TODO: find another solution to prevent layout shifting and layout blocking on large responses
|
||||||
|
reader.scrollTo("main", anchor: .bottom)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}.background(GeometryReader { geometry in
|
}.background(GeometryReader { geometry in
|
||||||
// get the height and width of the EventView view
|
// get the height and width of the EventView view
|
||||||
@@ -276,25 +278,22 @@ struct ThreadV2View: View {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// MARK: - Actual event view
|
// MARK: - Actual event view
|
||||||
MutedEventView(
|
SelectedEventView(
|
||||||
damus_state: damus,
|
damus: damus,
|
||||||
event: thread.current,
|
event: thread.current
|
||||||
scroller: reader,
|
|
||||||
nav_target: $nav_target,
|
|
||||||
navigating: $navigating,
|
|
||||||
selected: true
|
|
||||||
).id("main")
|
).id("main")
|
||||||
|
|
||||||
// MARK: - Responses of the actual event view
|
// MARK: - Responses of the actual event view
|
||||||
ForEach(thread.childEvents, id: \.id) { event in
|
ForEach(thread.childEvents, id: \.id) { event in
|
||||||
MutedEventView(
|
EventView(
|
||||||
damus_state: damus,
|
|
||||||
event: event,
|
event: event,
|
||||||
scroller: reader,
|
has_action_bar: true,
|
||||||
nav_target: $nav_target,
|
damus: damus
|
||||||
navigating: $navigating,
|
|
||||||
selected: false
|
|
||||||
)
|
)
|
||||||
|
.onTapGesture {
|
||||||
|
nav_target = event.id
|
||||||
|
navigating = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}.padding()
|
}.padding()
|
||||||
}.navigationBarTitle(NSLocalizedString("Thread", comment: "Navigation bar title for note thread."))
|
}.navigationBarTitle(NSLocalizedString("Thread", comment: "Navigation bar title for note thread."))
|
||||||
|
|||||||
@@ -39,7 +39,11 @@ struct InnerTimelineView: View {
|
|||||||
EmptyTimelineView()
|
EmptyTimelineView()
|
||||||
} else {
|
} else {
|
||||||
ForEach(events.filter(filter), id: \.id) { (ev: NostrEvent) in
|
ForEach(events.filter(filter), id: \.id) { (ev: NostrEvent) in
|
||||||
EventView(damus: damus, event: ev, has_action_bar: true)
|
//let tm = ThreadModel(event: inner_event_or_self(ev: ev), damus_state: damus)
|
||||||
|
//let is_chatroom = should_show_chatroom(ev)
|
||||||
|
//let tv = ThreadView(thread: tm, damus: damus, is_chatroom: is_chatroom)
|
||||||
|
|
||||||
|
EventView(event: ev, has_action_bar: true, damus: damus)
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
nav_target = ev
|
nav_target = ev
|
||||||
navigating = true
|
navigating = true
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
"'%@' is an invalid nip05 identifier. It should look like an email." = "'%@' ist eine ungültige nip05 Kennzeichnung. Diese sollte wie eine Emailadresse aussehen. ";
|
"'%@' is an invalid nip05 identifier. It should look like an email." = "'%@' ist eine ungültige nip05 Kennzeichnung. Diese sollte wie eine Emailadresse aussehen. ";
|
||||||
|
|
||||||
/* Navigation bar title for view that shows who is following a user. */
|
/* Navigation bar title for view that shows who is following a user. */
|
||||||
"(Profile.displayName(profile: profile, pubkey: whos))'s Followers" = "(Profile.displayName(profile: profile, pubkey: whos)) Gefolgte";
|
"(Profile.displayName(profile: profile, pubkey: whos))'s Followers" = "(Profile.displayName(profile: profile, pubkey: whos)) Follower";
|
||||||
|
|
||||||
/* Navigation bar title for view that shows who a user is following. */
|
/* Navigation bar title for view that shows who a user is following. */
|
||||||
"(who) following" = "(who) folgt";
|
"(who) following" = "(who) folgt";
|
||||||
@@ -20,13 +20,10 @@
|
|||||||
Abbreviated version of a nostr public key. */
|
Abbreviated version of a nostr public key. */
|
||||||
"%@" = "%@";
|
"%@" = "%@";
|
||||||
|
|
||||||
/* Sentence composed of 2 variables to describe how many tip payments there are on a post. In source English, the first variable is the number of tip payments, and the second variable is 'Tip' or 'Tips'.
|
/* Sentence composed of 2 variables to describe how many reposts. In source English, the first variable is the number of reposts, and the second variable is 'Repost' or 'Reposts'.
|
||||||
Sentence composed of 2 variables to describe how many profiles a user is following. In source English, the first variable is the number of profiles being followed, and the second variable is 'Following'. */
|
Sentence composed of 2 variables to describe how many profiles a user is following. In source English, the first variable is the number of profiles being followed, and the second variable is 'Following'. */
|
||||||
"%@ %@" = "%@ %@";
|
"%@ %@" = "%@ %@";
|
||||||
|
|
||||||
/* Alert message that informs a user was blocked. */
|
|
||||||
"%@ has been blocked" = "%@ wurde blockiert";
|
|
||||||
|
|
||||||
/* Explanation of what is done to keep personally identifiable information private. There is a heading that precedes this explanation which is a variable to this string. */
|
/* Explanation of what is done to keep personally identifiable information private. There is a heading that precedes this explanation which is a variable to this string. */
|
||||||
"%@. Creating an account doesn't require a phone number, email or name. Get started right away with zero friction." = "%@. Ein Konto zu erstellen benötigt keine Telefonnummer, Emailadresse oder Namen. Fang jetzt gleich ganz reibungslos an.";
|
"%@. Creating an account doesn't require a phone number, email or name. Get started right away with zero friction." = "%@. Ein Konto zu erstellen benötigt keine Telefonnummer, Emailadresse oder Namen. Fang jetzt gleich ganz reibungslos an.";
|
||||||
|
|
||||||
@@ -36,7 +33,7 @@ Sentence composed of 2 variables to describe how many profiles a user is followi
|
|||||||
/* Explanation of what can be done by users to earn money. There is a heading that precedes this explanation which is a variable to this string. */
|
/* Explanation of what can be done by users to earn money. There is a heading that precedes this explanation which is a variable to this string. */
|
||||||
"%@. Tip your friend's posts and stack sats with Bitcoin⚡️, the native currency of the internet." = "%@. Belohne Beiträge deiner Freunde und sammle Sats mit Bitcoin⚡️, der eigenen Währung des Internets.";
|
"%@. Tip your friend's posts and stack sats with Bitcoin⚡️, the native currency of the internet." = "%@. Belohne Beiträge deiner Freunde und sammle Sats mit Bitcoin⚡️, der eigenen Währung des Internets.";
|
||||||
|
|
||||||
/* Number of tip payments on a post.
|
/* Number of reposts.
|
||||||
Number of profiles a user is following. */
|
Number of profiles a user is following. */
|
||||||
"%lld" = "%lld";
|
"%lld" = "%lld";
|
||||||
|
|
||||||
@@ -55,22 +52,13 @@ Number of profiles a user is following. */
|
|||||||
/* Placeholder text for About Me description. */
|
/* Placeholder text for About Me description. */
|
||||||
"Absolute Boss" = "Absoluter Macher";
|
"Absolute Boss" = "Absoluter Macher";
|
||||||
|
|
||||||
/* Button to accept the end user license agreement before being allowed into the app. */
|
|
||||||
"Accept" = "Zustimmen";
|
|
||||||
|
|
||||||
/* Label to indicate the public ID of the account. */
|
/* Label to indicate the public ID of the account. */
|
||||||
"Account ID" = "Konto ID";
|
"Account ID" = "Konto ID";
|
||||||
|
|
||||||
/* Title for confirmation dialog to either share, report, or block a profile. */
|
|
||||||
"Actions" = "Aktionen";
|
|
||||||
|
|
||||||
/* Button to add recommended relay server.
|
/* Button to add recommended relay server.
|
||||||
Button to confirm adding user inputted relay. */
|
Button to confirm adding user inputted relay. */
|
||||||
"Add" = "Hinzufügen";
|
"Add" = "Hinzufügen";
|
||||||
|
|
||||||
/* Button label to re-add all original participants as profiles to reply to in a note */
|
|
||||||
"Add all" = "Alle hinzufügen";
|
|
||||||
|
|
||||||
/* Label for section for adding a relay server. */
|
/* Label for section for adding a relay server. */
|
||||||
"Add Relay" = "Relay hinzufügen";
|
"Add Relay" = "Relay hinzufügen";
|
||||||
|
|
||||||
@@ -95,23 +83,6 @@ Number of profiles a user is following. */
|
|||||||
/* Dropdown option label for Lightning wallet, Blixt Wallet */
|
/* Dropdown option label for Lightning wallet, Blixt Wallet */
|
||||||
"Blixt Wallet" = "Blixt Wallet";
|
"Blixt Wallet" = "Blixt Wallet";
|
||||||
|
|
||||||
/* Alert button to block a user.
|
|
||||||
Button to block a profile.
|
|
||||||
Context menu option for blocking users. */
|
|
||||||
"Block" = "Blockieren";
|
|
||||||
|
|
||||||
/* Alert message prompt to ask if a user should be blocked. */
|
|
||||||
"Block %@?" = "%@ blockieren?";
|
|
||||||
|
|
||||||
/* Title of alert for blocking a user. */
|
|
||||||
"Block User" = "Benutzer blockieren";
|
|
||||||
|
|
||||||
/* Sidebar menu label for Profile view. */
|
|
||||||
"Blocked" = "Blockiert";
|
|
||||||
|
|
||||||
/* Navigation title of view to see list of blocked users. */
|
|
||||||
"Blocked Users" = "Blockierte Benutzer";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Blue Wallet. */
|
/* Dropdown option label for Lightning wallet, Blue Wallet. */
|
||||||
"Blue Wallet" = "Blue Wallet";
|
"Blue Wallet" = "Blue Wallet";
|
||||||
|
|
||||||
@@ -121,9 +92,7 @@ Number of profiles a user is following. */
|
|||||||
/* Context menu option for broadcasting the user's note to all of the user's connected relay servers. */
|
/* Context menu option for broadcasting the user's note to all of the user's connected relay servers. */
|
||||||
"Broadcast" = "Senden";
|
"Broadcast" = "Senden";
|
||||||
|
|
||||||
/* Alert button to cancel out of alert for blocking a user.
|
/* Button to cancel out of posting a note.
|
||||||
Button to cancel out of alert that creates a new mutelist.
|
|
||||||
Button to cancel out of posting a note.
|
|
||||||
Button to cancel out of reposting a post.
|
Button to cancel out of reposting a post.
|
||||||
Button to cancel out of view adding user inputted relay.
|
Button to cancel out of view adding user inputted relay.
|
||||||
Cancel out of logging out the user. */
|
Cancel out of logging out the user. */
|
||||||
@@ -169,17 +138,11 @@ Number of profiles a user is following. */
|
|||||||
/* Context menu option for copying the JSON text from the note. */
|
/* Context menu option for copying the JSON text from the note. */
|
||||||
"Copy Note JSON" = "Notiz JSON kopieren";
|
"Copy Note JSON" = "Notiz JSON kopieren";
|
||||||
|
|
||||||
/* Button to copy report ID. */
|
|
||||||
"Copy Report ID" = "Meldungs-ID kopieren";
|
|
||||||
|
|
||||||
/* Context menu option for copying the text from an note. */
|
/* Context menu option for copying the text from an note. */
|
||||||
"Copy Text" = "Text kopieren";
|
"Copy Text" = "Text kopieren";
|
||||||
|
|
||||||
/* Context menu option for copying the ID of the user who created the note. */
|
/* Context menu option for copying the ID of the user who created the note. */
|
||||||
"Copy User Pubkey" = "Öffentlichen Schlüssel des Benutzers kopieren";
|
"Copy User ID" = "Benutzer ID kopieren";
|
||||||
|
|
||||||
/* Alert message to indicate that the blocked user could not be found. */
|
|
||||||
"Could not find user to block..." = "Der zu blockierende Benutzer konnte nicht gefunden werden...";
|
|
||||||
|
|
||||||
/* Button to create account. */
|
/* Button to create account. */
|
||||||
"Create" = "Erstellen";
|
"Create" = "Erstellen";
|
||||||
@@ -187,9 +150,6 @@ Number of profiles a user is following. */
|
|||||||
/* Button to create an account. */
|
/* Button to create an account. */
|
||||||
"Create Account" = "Konto erstellen";
|
"Create Account" = "Konto erstellen";
|
||||||
|
|
||||||
/* Title of alert prompting the user to create a new mutelist. */
|
|
||||||
"Create new mutelist" = "Neue Stummschaltungsliste";
|
|
||||||
|
|
||||||
/* Example description about Bitcoin creator(s), Satoshi Nakamoto. */
|
/* Example description about Bitcoin creator(s), Satoshi Nakamoto. */
|
||||||
"Creator(s) of Bitcoin. Absolute legend." = "Erfinder von Bitcoin. Absolute Legende(n).";
|
"Creator(s) of Bitcoin. Absolute legend." = "Erfinder von Bitcoin. Absolute Legende(n).";
|
||||||
|
|
||||||
@@ -199,8 +159,7 @@ Number of profiles a user is following. */
|
|||||||
/* Button to pay a Lightning invoice with the user's default Lightning wallet. */
|
/* Button to pay a Lightning invoice with the user's default Lightning wallet. */
|
||||||
"Default Wallet" = "Voreingestelltes Wallet";
|
"Default Wallet" = "Voreingestelltes Wallet";
|
||||||
|
|
||||||
/* Button to delete a relay server that the user connects to.
|
/* Button to delete a relay server that the user connects to. */
|
||||||
Button to remove a user from their blocklist. */
|
|
||||||
"Delete" = "Löschen";
|
"Delete" = "Löschen";
|
||||||
|
|
||||||
/* Button to dismiss a text field alert. */
|
/* Button to dismiss a text field alert. */
|
||||||
@@ -209,11 +168,13 @@ Number of profiles a user is following. */
|
|||||||
/* Label to prompt display name entry. */
|
/* Label to prompt display name entry. */
|
||||||
"Display Name" = "Profilname";
|
"Display Name" = "Profilname";
|
||||||
|
|
||||||
/* DM selector for seeing either DMs or message requests, which are messages that have not been responded to yet. DM is the English abbreviation for Direct Message. */
|
/* Navigation title for DM view, which is the English abbreviation for Direct Message. */
|
||||||
|
"DM" = "PN";
|
||||||
|
|
||||||
|
/* DM selector for seeing either DMs or message requests, which are messages that have not been responded to yet. */
|
||||||
"DM Type" = "PN Typ";
|
"DM Type" = "PN Typ";
|
||||||
|
|
||||||
/* Navigation title for DMs view, where DM is the English abbreviation for Direct Message.
|
/* No comment provided by engineer. */
|
||||||
Navigation title for view of DMs, where DM is an English abbreviation for Direct Message. */
|
|
||||||
"DMs" = "PNs";
|
"DMs" = "PNs";
|
||||||
|
|
||||||
/* Button to dismiss wallet selection view for paying Lightning invoice. */
|
/* Button to dismiss wallet selection view for paying Lightning invoice. */
|
||||||
@@ -225,21 +186,18 @@ Number of profiles a user is following. */
|
|||||||
/* Button to edit user's profile. */
|
/* Button to edit user's profile. */
|
||||||
"Edit" = "Bearbeiten";
|
"Edit" = "Bearbeiten";
|
||||||
|
|
||||||
/* Text indicating that the view is used for editing which participants are replied to in a note. */
|
|
||||||
"Edit participants" = "Teilnehmer editieren";
|
|
||||||
|
|
||||||
/* Heading indicating that this application keeps private messaging end-to-end encrypted. */
|
/* Heading indicating that this application keeps private messaging end-to-end encrypted. */
|
||||||
"Encrypted" = "Verschlüsselt";
|
"Encrypted" = "Verschlüsselt";
|
||||||
|
|
||||||
|
/* Navigation title for view of encrypted DMs, where DM is an English abbreviation for Direct Message. */
|
||||||
|
"Encrypted DMs" = "Verschlüsselte PNs";
|
||||||
|
|
||||||
/* Prompt for user to enter an account key to login. */
|
/* Prompt for user to enter an account key to login. */
|
||||||
"Enter your account key to login:" = "Gib deinen Kontoschlüssel ein um dich anzumelden:";
|
"Enter your account key to login:" = "Gib deinen Kontoschlüssel ein um dich anzumelden:";
|
||||||
|
|
||||||
/* Error message indicating why saving keys failed. */
|
/* Error message indicating why saving keys failed. */
|
||||||
"Error: %@" = "Fehler: %@";
|
"Error: %@" = "Fehler: %@";
|
||||||
|
|
||||||
/* Label indicating that the below text is the EULA, an acronym for End User License Agreement. */
|
|
||||||
"EULA" = "Endbenutzer-Lizenzvereinbarung";
|
|
||||||
|
|
||||||
/* Filter state for seeing either only posts, or posts & replies. */
|
/* Filter state for seeing either only posts, or posts & replies. */
|
||||||
"Filter State" = "Filter Einstellung";
|
"Filter State" = "Filter Einstellung";
|
||||||
|
|
||||||
@@ -247,11 +205,11 @@ Number of profiles a user is following. */
|
|||||||
"Follow" = "Folgen";
|
"Follow" = "Folgen";
|
||||||
|
|
||||||
/* Label describing followers of a user. */
|
/* Label describing followers of a user. */
|
||||||
"Followers" = "Gefolgte:r";
|
"Followers" = "Follower";
|
||||||
|
|
||||||
/* Text to indicate that the button next to it is in a state that indicates that it is in the process of following a profile.
|
/* Text to indicate that the button next to it is in a state that indicates that it is in the process of following a profile.
|
||||||
Part of a larger sentence to describe how many profiles a user is following. */
|
Part of a larger sentence to describe how many profiles a user is following. */
|
||||||
"Following" = "Gefolgt";
|
"Following" = "Folgt";
|
||||||
|
|
||||||
/* Label to indicate that the user is in the process of following another user. */
|
/* Label to indicate that the user is in the process of following another user. */
|
||||||
"Following..." = "Folge…";
|
"Following..." = "Folge…";
|
||||||
@@ -260,7 +218,7 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
"Follows" = "Folgt";
|
"Follows" = "Folgt";
|
||||||
|
|
||||||
/* Navigation bar title for Global view where posts from all connected relay servers appear. */
|
/* Navigation bar title for Global view where posts from all connected relay servers appear. */
|
||||||
"Global" = "Allgemein";
|
"Global" = "Weltweit";
|
||||||
|
|
||||||
/* Navigation link to go to post referenced by hex code. */
|
/* Navigation link to go to post referenced by hex code. */
|
||||||
"Goto post %@" = "Gehe zum Beitrag %@";
|
"Goto post %@" = "Gehe zum Beitrag %@";
|
||||||
@@ -277,15 +235,9 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
/* Placeholder example text for website URL for user profile. */
|
/* Placeholder example text for website URL for user profile. */
|
||||||
"https://jb55.com" = "https://jb55.com";
|
"https://jb55.com" = "https://jb55.com";
|
||||||
|
|
||||||
/* Button for user to report that the account or content has illegal content. */
|
|
||||||
"Illegal content" = "Illegaler Inhalt";
|
|
||||||
|
|
||||||
/* Error message indicating that an invalid account key was entered for login. */
|
/* Error message indicating that an invalid account key was entered for login. */
|
||||||
"Invalid key" = "Ungültiger Schlüssel";
|
"Invalid key" = "Ungültiger Schlüssel";
|
||||||
|
|
||||||
/* Button for user to report that the account or content has spam. */
|
|
||||||
"It's spam" = "Es ist Spam";
|
|
||||||
|
|
||||||
/* Placeholder example text for identifier used for NIP-05 verification. */
|
/* Placeholder example text for identifier used for NIP-05 verification. */
|
||||||
"jb55@jb55.com" = "jb55@jb55.com";
|
"jb55@jb55.com" = "jb55@jb55.com";
|
||||||
|
|
||||||
@@ -325,9 +277,6 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
/* Label for NIP-05 Verification section of user profile form. */
|
/* Label for NIP-05 Verification section of user profile form. */
|
||||||
"NIP-05 Verification" = "NIP-05-Verifizierung";
|
"NIP-05 Verification" = "NIP-05-Verifizierung";
|
||||||
|
|
||||||
/* Alert message prompt that asks if the user wants to create a new block list, overwriting previous block lists. */
|
|
||||||
"No block list found, create a new one? This will overwrite any previous block lists." = "Es wurde keine Blockier-Liste gefunden, soll eine neue erzeugt werden? Dies wird eine frühere Blockier-Liste überschreiben.";
|
|
||||||
|
|
||||||
/* No search results. */
|
/* No search results. */
|
||||||
"none" = "keine";
|
"none" = "keine";
|
||||||
|
|
||||||
@@ -343,9 +292,6 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
/* Prompt for user to enter in an account key to login. This text shows the characters the key could start with if it was a private key. */
|
/* Prompt for user to enter in an account key to login. This text shows the characters the key could start with if it was a private key. */
|
||||||
"nsec1..." = "nsec1...";
|
"nsec1..." = "nsec1...";
|
||||||
|
|
||||||
/* Button for user to report that the account or content has nudity or explicit content. */
|
|
||||||
"Nudity or explicit content" = "Nacktheit oder anstößige Inhalte";
|
|
||||||
|
|
||||||
/* Label indicating that a form input is optional. */
|
/* Label indicating that a form input is optional. */
|
||||||
"optional" = "optional";
|
"optional" = "optional";
|
||||||
|
|
||||||
@@ -397,21 +343,12 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
/* Section title for recommend relay servers that could be added as part of configuration */
|
/* Section title for recommend relay servers that could be added as part of configuration */
|
||||||
"Recommended Relays" = "Empfohlene Relays";
|
"Recommended Relays" = "Empfohlene Relays";
|
||||||
|
|
||||||
/* Button to reject the end user license agreement, which disallows the user from being let into the app. */
|
|
||||||
"Reject" = "Ablehnen";
|
|
||||||
|
|
||||||
/* Text field for relay server. Used for testing purposes. */
|
/* Text field for relay server. Used for testing purposes. */
|
||||||
"Relay" = "Relay";
|
"Relay" = "Relay";
|
||||||
|
|
||||||
/* Sidebar menu label for Relay servers view */
|
/* Sidebar menu label for Relay servers view */
|
||||||
"Relays" = "Relays";
|
"Relays" = "Relays";
|
||||||
|
|
||||||
/* Description of what was done as a result of sending a report to relay servers. */
|
|
||||||
"Relays have been notified and clients will be able to use this information to filter content. Thank you!" = "Relays wurden benachrichtigt und Anwendungen können diese Information nutzen, um Inhalte zu filtern. Vielen Dank!";
|
|
||||||
|
|
||||||
/* Button label to remove all participants from a note reply. */
|
|
||||||
"Remove all" = "Alle entfernen";
|
|
||||||
|
|
||||||
/* Label to indicate that the user is replying to themself. */
|
/* Label to indicate that the user is replying to themself. */
|
||||||
"Reply to self" = "Antwort an sich selbst";
|
"Reply to self" = "Antwort an sich selbst";
|
||||||
|
|
||||||
@@ -421,16 +358,6 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
/* Indicating that the user is replying to the following listed people. */
|
/* Indicating that the user is replying to the following listed people. */
|
||||||
"Replying to:" = "Antwort an:";
|
"Replying to:" = "Antwort an:";
|
||||||
|
|
||||||
/* Button to report a profile.
|
|
||||||
Context menu option for reporting content. */
|
|
||||||
"Report" = "Melden";
|
|
||||||
|
|
||||||
/* Label indicating that the text underneath is the identifier of the report that was sent to relay servers. */
|
|
||||||
"Report ID:" = "Meldungs-ID";
|
|
||||||
|
|
||||||
/* Message indicating that a report was successfully sent to relay servers. */
|
|
||||||
"Report sent!" = "Meldung versandt!";
|
|
||||||
|
|
||||||
/* Button to confirm reposting a post.
|
/* Button to confirm reposting a post.
|
||||||
Title of alert for confirming to repost a post. */
|
Title of alert for confirming to repost a post. */
|
||||||
"Repost" = "Selbst teilen";
|
"Repost" = "Selbst teilen";
|
||||||
@@ -438,10 +365,7 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
/* Text indicating that the post was reposted (i.e. re-shared). */
|
/* Text indicating that the post was reposted (i.e. re-shared). */
|
||||||
"Reposted" = "Selbst geteilt";
|
"Reposted" = "Selbst geteilt";
|
||||||
|
|
||||||
/* Navigation bar title for Reposts view. */
|
/* No comment provided by engineer. */
|
||||||
"Reposts" = "Geteilte Beiträge";
|
|
||||||
|
|
||||||
/* Picker option for DM selector for seeing only message requests (DMs that someone else sent the user which has not been responded to yet). DM is the English abbreviation for Direct Message. */
|
|
||||||
"Requests" = "Anfragen";
|
"Requests" = "Anfragen";
|
||||||
|
|
||||||
/* Section title for resetting the user */
|
/* Section title for resetting the user */
|
||||||
@@ -487,8 +411,7 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
Sidebar menu label for accessing the app settings */
|
Sidebar menu label for accessing the app settings */
|
||||||
"Settings" = "Einstellungen";
|
"Settings" = "Einstellungen";
|
||||||
|
|
||||||
/* Button to share an image.
|
/* Button to share an image. */
|
||||||
Button to share the link to a profile. */
|
|
||||||
"Share" = "Teilen";
|
"Share" = "Teilen";
|
||||||
|
|
||||||
/* Toggle to show or hide user's secret account login key. */
|
/* Toggle to show or hide user's secret account login key. */
|
||||||
@@ -503,12 +426,6 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
/* Dropdown option label for Lightning wallet, Strike. */
|
/* Dropdown option label for Lightning wallet, Strike. */
|
||||||
"Strike" = "Strike";
|
"Strike" = "Strike";
|
||||||
|
|
||||||
/* Button to close out of alert that informs that the action to block a user was successful. */
|
|
||||||
"Thanks!" = "Danke!";
|
|
||||||
|
|
||||||
/* Button for user to report that the account is impersonating someone. */
|
|
||||||
"They are impersonating someone" = "Sie gibt sich für jemand anderen aus";
|
|
||||||
|
|
||||||
/* Warning that the inputted account key is a public key and the result of what happens because of it. */
|
/* Warning that the inputted account key is a public key and the result of what happens because of it. */
|
||||||
"This is a public key, you will not be able to make posts or interact in any way. This is used for viewing accounts from their perspective." = "Dies ist ein öffentlicher Schlüssel, mit dem Sie keine Beiträge verfassen oder in irgendeiner Weise interagieren können. Er wird verwendet, um Konten aus deren Perspektive zu betrachten.";
|
"This is a public key, you will not be able to make posts or interact in any way. This is used for viewing accounts from their perspective." = "Dies ist ein öffentlicher Schlüssel, mit dem Sie keine Beiträge verfassen oder in irgendeiner Weise interagieren können. Er wird verwendet, um Konten aus deren Perspektive zu betrachten.";
|
||||||
|
|
||||||
@@ -543,12 +460,6 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
/* Text to indicate that the button next to it is in a state that will unfollow a profile when tapped. */
|
/* Text to indicate that the button next to it is in a state that will unfollow a profile when tapped. */
|
||||||
"Unfollows" = "Entfolgen";
|
"Unfollows" = "Entfolgen";
|
||||||
|
|
||||||
/* Alert message to indicate */
|
|
||||||
"User blocked" = "Benutzer blockiert";
|
|
||||||
|
|
||||||
/* Alert message that informs a user was blocked. */
|
|
||||||
"User has been blocked" = "Der Benutzer wurde blockiert";
|
|
||||||
|
|
||||||
/* Label for Username section of user profile form.
|
/* Label for Username section of user profile form.
|
||||||
Label to prompt username entry. */
|
Label to prompt username entry. */
|
||||||
"Username" = "Benutzername";
|
"Username" = "Benutzername";
|
||||||
@@ -571,24 +482,15 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
/* Text to welcome user. */
|
/* Text to welcome user. */
|
||||||
"Welcome, %@!" = "Willkommen, %@!";
|
"Welcome, %@!" = "Willkommen, %@!";
|
||||||
|
|
||||||
/* Header text to prompt user what issue they want to report. */
|
|
||||||
"What do you want to report?" = "Was möchtest du melden?";
|
|
||||||
|
|
||||||
/* Placeholder example for relay server address. */
|
/* Placeholder example for relay server address. */
|
||||||
"wss://some.relay.com" = "wss://ein.relay.at";
|
"wss://some.relay.com" = "wss://ein.relay.at";
|
||||||
|
|
||||||
/* Text of button that confirms to overwrite the existing mutelist. */
|
|
||||||
"Yes, Overwrite" = "Ja, überschreiben";
|
|
||||||
|
|
||||||
/* You, in this context, is the person who controls their own social network. You is used in the context of a larger sentence that welcomes the reader to the social network that they control themself. */
|
/* You, in this context, is the person who controls their own social network. You is used in the context of a larger sentence that welcomes the reader to the social network that they control themself. */
|
||||||
"you" = "Du";
|
"you" = "Du";
|
||||||
|
|
||||||
/* Label for Your Name section of user profile form. */
|
/* Label for Your Name section of user profile form. */
|
||||||
"Your Name" = "Dein Name";
|
"Your Name" = "Dein Name";
|
||||||
|
|
||||||
/* Footer text to inform user what will happen when the report is submitted. */
|
|
||||||
"Your report will be sent to the relays you are connected to" = "Die Meldung wird an Relays versendet, mit denen du verbunden bist";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Zebedee. */
|
/* Dropdown option label for Lightning wallet, Zebedee. */
|
||||||
"Zebedee" = "Zebedee";
|
"Zebedee" = "Zebedee";
|
||||||
|
|
||||||
|
|||||||
@@ -27,9 +27,9 @@
|
|||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>d</string>
|
<string>d</string>
|
||||||
<key>one</key>
|
<key>one</key>
|
||||||
<string>Gefolgte:r</string>
|
<string>Follower</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>Gefolgte</string>
|
<string>Follower</string>
|
||||||
</dict>
|
</dict>
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
<string>%#@FOLLOWERS@</string>
|
<string>%#@FOLLOWERS@</string>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
"'%@' is an invalid nip05 identifier. It should look like an email." = "'%@' ist eine ungültige nip05 Kennzeichnung. Diese sollte wie eine Emailadresse aussehen. ";
|
"'%@' is an invalid nip05 identifier. It should look like an email." = "'%@' ist eine ungültige nip05 Kennzeichnung. Diese sollte wie eine Emailadresse aussehen. ";
|
||||||
|
|
||||||
/* Navigation bar title for view that shows who is following a user. */
|
/* Navigation bar title for view that shows who is following a user. */
|
||||||
"(Profile.displayName(profile: profile, pubkey: whos))'s Followers" = "(Profile.displayName(profile: profile, pubkey: whos)) Gefolgte";
|
"(Profile.displayName(profile: profile, pubkey: whos))'s Followers" = "(Profile.displayName(profile: profile, pubkey: whos)) Follower";
|
||||||
|
|
||||||
/* Navigation bar title for view that shows who a user is following. */
|
/* Navigation bar title for view that shows who a user is following. */
|
||||||
"(who) following" = "(who) folgt";
|
"(who) following" = "(who) folgt";
|
||||||
@@ -20,23 +20,20 @@
|
|||||||
Abbreviated version of a nostr public key. */
|
Abbreviated version of a nostr public key. */
|
||||||
"%@" = "%@";
|
"%@" = "%@";
|
||||||
|
|
||||||
/* Sentence composed of 2 variables to describe how many tip payments there are on a post. In source English, the first variable is the number of tip payments, and the second variable is 'Tip' or 'Tips'.
|
/* Sentence composed of 2 variables to describe how many reposts. In source English, the first variable is the number of reposts, and the second variable is 'Repost' or 'Reposts'.
|
||||||
Sentence composed of 2 variables to describe how many profiles a user is following. In source English, the first variable is the number of profiles being followed, and the second variable is 'Following'. */
|
Sentence composed of 2 variables to describe how many profiles a user is following. In source English, the first variable is the number of profiles being followed, and the second variable is 'Following'. */
|
||||||
"%@ %@" = "%@ %@";
|
"%@ %@" = "%@ %@";
|
||||||
|
|
||||||
/* Alert message that informs a user was blocked. */
|
|
||||||
"%@ has been blocked" = "%@ wurde blockiert";
|
|
||||||
|
|
||||||
/* Explanation of what is done to keep personally identifiable information private. There is a heading that precedes this explanation which is a variable to this string. */
|
/* Explanation of what is done to keep personally identifiable information private. There is a heading that precedes this explanation which is a variable to this string. */
|
||||||
"%@. Creating an account doesn't require a phone number, email or name. Get started right away with zero friction." = "%@. Ein Konto zu erstellen benötigt keine Telefonnummer, Emailadresse oder Namen. Fang jetzt gleich ganz reibungslos an.";
|
"%@. Creating an account doesn't require a phone number, email or name. Get started right away with zero friction." = "Für das Erstellen eines Accounts ist keine Telefonnumer, E-Mail-Adresse und kein Name notwendig. Lege direkt los!";
|
||||||
|
|
||||||
/* Explanation of what is done to keep private data encrypted. There is a heading that precedes this explanation which is a variable to this string. */
|
/* Explanation of what is done to keep private data encrypted. There is a heading that precedes this explanation which is a variable to this string. */
|
||||||
"%@. End-to-End encrypted private messaging. Keep Big Tech out of your DMs" = "%@. End-zu-End verschlüsselter privater Nachrichtenaustausch. Halte Tech-Riesen aus deinen PNs heraus";
|
"%@. End-to-End encrypted private messaging. Keep Big Tech out of your DMs" = "%@. Ende-zu-Ende verschlüsselte private Nachrichten. Halte „Big Tech“ aus deinen Direktnachrichten heraus.";
|
||||||
|
|
||||||
/* Explanation of what can be done by users to earn money. There is a heading that precedes this explanation which is a variable to this string. */
|
/* Explanation of what can be done by users to earn money. There is a heading that precedes this explanation which is a variable to this string. */
|
||||||
"%@. Tip your friend's posts and stack sats with Bitcoin⚡️, the native currency of the internet." = "%@. Belohne Beiträge deiner Freunde und sammle Sats mit Bitcoin⚡️, der eigenen Währung des Internets.";
|
"%@. Tip your friend's posts and stack sats with Bitcoin⚡️, the native currency of the internet." = "%@. Belohne Beiträge deiner Freunde und sammle Sats mit Bitcoin⚡️, der eigenen Währung des Internets.";
|
||||||
|
|
||||||
/* Number of tip payments on a post.
|
/* Number of reposts.
|
||||||
Number of profiles a user is following. */
|
Number of profiles a user is following. */
|
||||||
"%lld" = "%lld";
|
"%lld" = "%lld";
|
||||||
|
|
||||||
@@ -55,22 +52,13 @@ Number of profiles a user is following. */
|
|||||||
/* Placeholder text for About Me description. */
|
/* Placeholder text for About Me description. */
|
||||||
"Absolute Boss" = "Absoluter Macher";
|
"Absolute Boss" = "Absoluter Macher";
|
||||||
|
|
||||||
/* Button to accept the end user license agreement before being allowed into the app. */
|
|
||||||
"Accept" = "Zustimmen";
|
|
||||||
|
|
||||||
/* Label to indicate the public ID of the account. */
|
/* Label to indicate the public ID of the account. */
|
||||||
"Account ID" = "Konto-ID";
|
"Account ID" = "Konto-ID";
|
||||||
|
|
||||||
/* Title for confirmation dialog to either share, report, or block a profile. */
|
|
||||||
"Actions" = "Aktionen";
|
|
||||||
|
|
||||||
/* Button to add recommended relay server.
|
/* Button to add recommended relay server.
|
||||||
Button to confirm adding user inputted relay. */
|
Button to confirm adding user inputted relay. */
|
||||||
"Add" = "Hinzufügen";
|
"Add" = "Hinzufügen";
|
||||||
|
|
||||||
/* Button label to re-add all original participants as profiles to reply to in a note */
|
|
||||||
"Add all" = "Alle hinzufügen";
|
|
||||||
|
|
||||||
/* Label for section for adding a relay server. */
|
/* Label for section for adding a relay server. */
|
||||||
"Add Relay" = "Relay hinzufügen";
|
"Add Relay" = "Relay hinzufügen";
|
||||||
|
|
||||||
@@ -81,7 +69,7 @@ Number of profiles a user is following. */
|
|||||||
"Are you sure you want to repost this?" = "Bist du sicher dass Du den Beitrag auf deinem Profil teilen möchtest?";
|
"Are you sure you want to repost this?" = "Bist du sicher dass Du den Beitrag auf deinem Profil teilen möchtest?";
|
||||||
|
|
||||||
/* Label for Banner Image section of user profile form. */
|
/* Label for Banner Image section of user profile form. */
|
||||||
"Banner Image" = "Bannerbild";
|
"Banner Image" = "Banner Bild";
|
||||||
|
|
||||||
/* Reminder to user that they should save their account information. */
|
/* Reminder to user that they should save their account information. */
|
||||||
"Before we get started, you'll need to save your account info, otherwise you won't be able to login in the future if you ever uninstall Damus." = "Bevor wir anfangen, musst du deine Kontodaten sichern, sonst kannst du dich in Zukunft nicht mehr anmelden, wenn du Damus jemals deinstallierst.";
|
"Before we get started, you'll need to save your account info, otherwise you won't be able to login in the future if you ever uninstall Damus." = "Bevor wir anfangen, musst du deine Kontodaten sichern, sonst kannst du dich in Zukunft nicht mehr anmelden, wenn du Damus jemals deinstallierst.";
|
||||||
@@ -95,23 +83,6 @@ Number of profiles a user is following. */
|
|||||||
/* Dropdown option label for Lightning wallet, Blixt Wallet */
|
/* Dropdown option label for Lightning wallet, Blixt Wallet */
|
||||||
"Blixt Wallet" = "Blixt Wallet";
|
"Blixt Wallet" = "Blixt Wallet";
|
||||||
|
|
||||||
/* Alert button to block a user.
|
|
||||||
Button to block a profile.
|
|
||||||
Context menu option for blocking users. */
|
|
||||||
"Block" = "Blockieren";
|
|
||||||
|
|
||||||
/* Alert message prompt to ask if a user should be blocked. */
|
|
||||||
"Block %@?" = "%@ blockieren?";
|
|
||||||
|
|
||||||
/* Title of alert for blocking a user. */
|
|
||||||
"Block User" = "Benutzer blockieren";
|
|
||||||
|
|
||||||
/* Sidebar menu label for Profile view. */
|
|
||||||
"Blocked" = "Blockiert";
|
|
||||||
|
|
||||||
/* Navigation title of view to see list of blocked users. */
|
|
||||||
"Blocked Users" = "Blockierte Benutzer";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Blue Wallet. */
|
/* Dropdown option label for Lightning wallet, Blue Wallet. */
|
||||||
"Blue Wallet" = "Blue Wallet";
|
"Blue Wallet" = "Blue Wallet";
|
||||||
|
|
||||||
@@ -121,9 +92,7 @@ Number of profiles a user is following. */
|
|||||||
/* Context menu option for broadcasting the user's note to all of the user's connected relay servers. */
|
/* Context menu option for broadcasting the user's note to all of the user's connected relay servers. */
|
||||||
"Broadcast" = "Senden";
|
"Broadcast" = "Senden";
|
||||||
|
|
||||||
/* Alert button to cancel out of alert for blocking a user.
|
/* Button to cancel out of posting a note.
|
||||||
Button to cancel out of alert that creates a new mutelist.
|
|
||||||
Button to cancel out of posting a note.
|
|
||||||
Button to cancel out of reposting a post.
|
Button to cancel out of reposting a post.
|
||||||
Button to cancel out of view adding user inputted relay.
|
Button to cancel out of view adding user inputted relay.
|
||||||
Cancel out of logging out the user. */
|
Cancel out of logging out the user. */
|
||||||
@@ -133,7 +102,7 @@ Number of profiles a user is following. */
|
|||||||
"Cash App" = "Cash App";
|
"Cash App" = "Cash App";
|
||||||
|
|
||||||
/* Navigation bar title for Chatroom view. */
|
/* Navigation bar title for Chatroom view. */
|
||||||
"Chat" = "Unterhaltungen";
|
"Chat" = "Unterhaltung";
|
||||||
|
|
||||||
/* Button for clearing cached data. */
|
/* Button for clearing cached data. */
|
||||||
"Clear" = "Löschen";
|
"Clear" = "Löschen";
|
||||||
@@ -158,7 +127,7 @@ Number of profiles a user is following. */
|
|||||||
"Copy Image URL" = "Bild-URL kopieren";
|
"Copy Image URL" = "Bild-URL kopieren";
|
||||||
|
|
||||||
/* Title of section for copying a Lightning invoice identifier. */
|
/* Title of section for copying a Lightning invoice identifier. */
|
||||||
"Copy invoice" = "Zahlungsdaten kopieren";
|
"Copy invoice" = "Rechnung kopieren";
|
||||||
|
|
||||||
/* Context menu option for copying a user's Lightning URL. */
|
/* Context menu option for copying a user's Lightning URL. */
|
||||||
"Copy LNURL" = "LNURL kopieren";
|
"Copy LNURL" = "LNURL kopieren";
|
||||||
@@ -169,17 +138,11 @@ Number of profiles a user is following. */
|
|||||||
/* Context menu option for copying the JSON text from the note. */
|
/* Context menu option for copying the JSON text from the note. */
|
||||||
"Copy Note JSON" = "Notiz-JSON kopieren";
|
"Copy Note JSON" = "Notiz-JSON kopieren";
|
||||||
|
|
||||||
/* Button to copy report ID. */
|
|
||||||
"Copy Report ID" = "Meldungs-ID kopieren";
|
|
||||||
|
|
||||||
/* Context menu option for copying the text from an note. */
|
/* Context menu option for copying the text from an note. */
|
||||||
"Copy Text" = "Text kopieren";
|
"Copy Text" = "Text kopieren";
|
||||||
|
|
||||||
/* Context menu option for copying the ID of the user who created the note. */
|
/* Context menu option for copying the ID of the user who created the note. */
|
||||||
"Copy User Pubkey" = "Öffentlichen Schlüssel des Benutzers kopieren";
|
"Copy User ID" = "Benutzer-ID kopieren";
|
||||||
|
|
||||||
/* Alert message to indicate that the blocked user could not be found. */
|
|
||||||
"Could not find user to block..." = "Der zu blockierende Benutzer konnte nicht gefunden werden...";
|
|
||||||
|
|
||||||
/* Button to create account. */
|
/* Button to create account. */
|
||||||
"Create" = "Erstellen";
|
"Create" = "Erstellen";
|
||||||
@@ -187,9 +150,6 @@ Number of profiles a user is following. */
|
|||||||
/* Button to create an account. */
|
/* Button to create an account. */
|
||||||
"Create Account" = "Konto erstellen";
|
"Create Account" = "Konto erstellen";
|
||||||
|
|
||||||
/* Title of alert prompting the user to create a new mutelist. */
|
|
||||||
"Create new mutelist" = "Neue Stummschaltungsliste";
|
|
||||||
|
|
||||||
/* Example description about Bitcoin creator(s), Satoshi Nakamoto. */
|
/* Example description about Bitcoin creator(s), Satoshi Nakamoto. */
|
||||||
"Creator(s) of Bitcoin. Absolute legend." = "Erfinder von Bitcoin. Absolute Legende(n).";
|
"Creator(s) of Bitcoin. Absolute legend." = "Erfinder von Bitcoin. Absolute Legende(n).";
|
||||||
|
|
||||||
@@ -199,8 +159,7 @@ Number of profiles a user is following. */
|
|||||||
/* Button to pay a Lightning invoice with the user's default Lightning wallet. */
|
/* Button to pay a Lightning invoice with the user's default Lightning wallet. */
|
||||||
"Default Wallet" = "Voreingestellte Wallet";
|
"Default Wallet" = "Voreingestellte Wallet";
|
||||||
|
|
||||||
/* Button to delete a relay server that the user connects to.
|
/* Button to delete a relay server that the user connects to. */
|
||||||
Button to remove a user from their blocklist. */
|
|
||||||
"Delete" = "Löschen";
|
"Delete" = "Löschen";
|
||||||
|
|
||||||
/* Button to dismiss a text field alert. */
|
/* Button to dismiss a text field alert. */
|
||||||
@@ -209,11 +168,13 @@ Number of profiles a user is following. */
|
|||||||
/* Label to prompt display name entry. */
|
/* Label to prompt display name entry. */
|
||||||
"Display Name" = "Profilname";
|
"Display Name" = "Profilname";
|
||||||
|
|
||||||
/* DM selector for seeing either DMs or message requests, which are messages that have not been responded to yet. DM is the English abbreviation for Direct Message. */
|
/* Navigation title for DM view, which is the English abbreviation for Direct Message. */
|
||||||
"DM Type" = "PN Typ";
|
"DM" = "PN";
|
||||||
|
|
||||||
/* Navigation title for DMs view, where DM is the English abbreviation for Direct Message.
|
/* DM selector for seeing either DMs or message requests, which are messages that have not been responded to yet. */
|
||||||
Navigation title for view of DMs, where DM is an English abbreviation for Direct Message. */
|
"DM Type" = "PN Art";
|
||||||
|
|
||||||
|
/* No comment provided by engineer. */
|
||||||
"DMs" = "PNs";
|
"DMs" = "PNs";
|
||||||
|
|
||||||
/* Button to dismiss wallet selection view for paying Lightning invoice. */
|
/* Button to dismiss wallet selection view for paying Lightning invoice. */
|
||||||
@@ -225,21 +186,18 @@ Number of profiles a user is following. */
|
|||||||
/* Button to edit user's profile. */
|
/* Button to edit user's profile. */
|
||||||
"Edit" = "Bearbeiten";
|
"Edit" = "Bearbeiten";
|
||||||
|
|
||||||
/* Text indicating that the view is used for editing which participants are replied to in a note. */
|
|
||||||
"Edit participants" = "Teilnehmer editieren";
|
|
||||||
|
|
||||||
/* Heading indicating that this application keeps private messaging end-to-end encrypted. */
|
/* Heading indicating that this application keeps private messaging end-to-end encrypted. */
|
||||||
"Encrypted" = "Verschlüsselt";
|
"Encrypted" = "Verschlüsselt";
|
||||||
|
|
||||||
|
/* Navigation title for view of encrypted DMs, where DM is an English abbreviation for Direct Message. */
|
||||||
|
"Encrypted DMs" = "Verschlüsselte PNs";
|
||||||
|
|
||||||
/* Prompt for user to enter an account key to login. */
|
/* Prompt for user to enter an account key to login. */
|
||||||
"Enter your account key to login:" = "Gib deinen Kontoschlüssel ein um dich anzumelden:";
|
"Enter your account key to login:" = "Gib deinen Kontoschlüssel ein um dich anzumelden:";
|
||||||
|
|
||||||
/* Error message indicating why saving keys failed. */
|
/* Error message indicating why saving keys failed. */
|
||||||
"Error: %@" = "Fehler: %@";
|
"Error: %@" = "Fehler: %@";
|
||||||
|
|
||||||
/* Label indicating that the below text is the EULA, an acronym for End User License Agreement. */
|
|
||||||
"EULA" = "Endbenutzer-Lizenzvereinbarung";
|
|
||||||
|
|
||||||
/* Filter state for seeing either only posts, or posts & replies. */
|
/* Filter state for seeing either only posts, or posts & replies. */
|
||||||
"Filter State" = "Filter Einstellung";
|
"Filter State" = "Filter Einstellung";
|
||||||
|
|
||||||
@@ -247,11 +205,11 @@ Number of profiles a user is following. */
|
|||||||
"Follow" = "Folgen";
|
"Follow" = "Folgen";
|
||||||
|
|
||||||
/* Label describing followers of a user. */
|
/* Label describing followers of a user. */
|
||||||
"Followers" = "Gefolgte:r";
|
"Followers" = "Follower";
|
||||||
|
|
||||||
/* Text to indicate that the button next to it is in a state that indicates that it is in the process of following a profile.
|
/* Text to indicate that the button next to it is in a state that indicates that it is in the process of following a profile.
|
||||||
Part of a larger sentence to describe how many profiles a user is following. */
|
Part of a larger sentence to describe how many profiles a user is following. */
|
||||||
"Following" = "Gefolgt";
|
"Following" = "Folgt";
|
||||||
|
|
||||||
/* Label to indicate that the user is in the process of following another user. */
|
/* Label to indicate that the user is in the process of following another user. */
|
||||||
"Following..." = "Folge…";
|
"Following..." = "Folge…";
|
||||||
@@ -260,7 +218,7 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
"Follows" = "Folgt";
|
"Follows" = "Folgt";
|
||||||
|
|
||||||
/* Navigation bar title for Global view where posts from all connected relay servers appear. */
|
/* Navigation bar title for Global view where posts from all connected relay servers appear. */
|
||||||
"Global" = "Allgemein";
|
"Global" = "Weltweit";
|
||||||
|
|
||||||
/* Navigation link to go to post referenced by hex code. */
|
/* Navigation link to go to post referenced by hex code. */
|
||||||
"Goto post %@" = "Gehe zum Beitrag %@";
|
"Goto post %@" = "Gehe zum Beitrag %@";
|
||||||
@@ -272,20 +230,14 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
"Home" = "Heim";
|
"Home" = "Heim";
|
||||||
|
|
||||||
/* Placeholder example text for profile picture URL. */
|
/* Placeholder example text for profile picture URL. */
|
||||||
"https://example.com/pic.jpg" = "https://beispiel.at/bild.jpg";
|
"https://example.com/pic.jpg" = "https://beispiel.de/bild.jpg";
|
||||||
|
|
||||||
/* Placeholder example text for website URL for user profile. */
|
/* Placeholder example text for website URL for user profile. */
|
||||||
"https://jb55.com" = "https://jb55.com";
|
"https://jb55.com" = "https://jb55.com";
|
||||||
|
|
||||||
/* Button for user to report that the account or content has illegal content. */
|
|
||||||
"Illegal content" = "Illegaler Inhalt";
|
|
||||||
|
|
||||||
/* Error message indicating that an invalid account key was entered for login. */
|
/* Error message indicating that an invalid account key was entered for login. */
|
||||||
"Invalid key" = "Ungültiger Schlüssel";
|
"Invalid key" = "Ungültiger Schlüssel";
|
||||||
|
|
||||||
/* Button for user to report that the account or content has spam. */
|
|
||||||
"It's spam" = "Es ist Spam";
|
|
||||||
|
|
||||||
/* Placeholder example text for identifier used for NIP-05 verification. */
|
/* Placeholder example text for identifier used for NIP-05 verification. */
|
||||||
"jb55@jb55.com" = "jb55@jb55.com";
|
"jb55@jb55.com" = "jb55@jb55.com";
|
||||||
|
|
||||||
@@ -325,9 +277,6 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
/* Label for NIP-05 Verification section of user profile form. */
|
/* Label for NIP-05 Verification section of user profile form. */
|
||||||
"NIP-05 Verification" = "NIP-05-Verifizierung";
|
"NIP-05 Verification" = "NIP-05-Verifizierung";
|
||||||
|
|
||||||
/* Alert message prompt that asks if the user wants to create a new block list, overwriting previous block lists. */
|
|
||||||
"No block list found, create a new one? This will overwrite any previous block lists." = "Es wurde keine Blockier-Liste gefunden, soll eine neue erzeugt werden? Dies wird eine frühere Blockier-Liste überschreiben.";
|
|
||||||
|
|
||||||
/* No search results. */
|
/* No search results. */
|
||||||
"none" = "keine";
|
"none" = "keine";
|
||||||
|
|
||||||
@@ -343,9 +292,6 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
/* Prompt for user to enter in an account key to login. This text shows the characters the key could start with if it was a private key. */
|
/* Prompt for user to enter in an account key to login. This text shows the characters the key could start with if it was a private key. */
|
||||||
"nsec1..." = "nsec1...";
|
"nsec1..." = "nsec1...";
|
||||||
|
|
||||||
/* Button for user to report that the account or content has nudity or explicit content. */
|
|
||||||
"Nudity or explicit content" = "Nacktheit oder anstößige Inhalte";
|
|
||||||
|
|
||||||
/* Label indicating that a form input is optional. */
|
/* Label indicating that a form input is optional. */
|
||||||
"optional" = "optional";
|
"optional" = "optional";
|
||||||
|
|
||||||
@@ -397,21 +343,12 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
/* Section title for recommend relay servers that could be added as part of configuration */
|
/* Section title for recommend relay servers that could be added as part of configuration */
|
||||||
"Recommended Relays" = "Empfohlene Relays";
|
"Recommended Relays" = "Empfohlene Relays";
|
||||||
|
|
||||||
/* Button to reject the end user license agreement, which disallows the user from being let into the app. */
|
|
||||||
"Reject" = "Ablehnen";
|
|
||||||
|
|
||||||
/* Text field for relay server. Used for testing purposes. */
|
/* Text field for relay server. Used for testing purposes. */
|
||||||
"Relay" = "Relay";
|
"Relay" = "Relay";
|
||||||
|
|
||||||
/* Sidebar menu label for Relay servers view */
|
/* Sidebar menu label for Relay servers view */
|
||||||
"Relays" = "Relays";
|
"Relays" = "Relays";
|
||||||
|
|
||||||
/* Description of what was done as a result of sending a report to relay servers. */
|
|
||||||
"Relays have been notified and clients will be able to use this information to filter content. Thank you!" = "Relays wurden benachrichtigt und Anwendungen können diese Information nutzen, um Inhalte zu filtern. Vielen Dank!";
|
|
||||||
|
|
||||||
/* Button label to remove all participants from a note reply. */
|
|
||||||
"Remove all" = "Alle entfernen";
|
|
||||||
|
|
||||||
/* Label to indicate that the user is replying to themself. */
|
/* Label to indicate that the user is replying to themself. */
|
||||||
"Reply to self" = "Antwort an dich selbst";
|
"Reply to self" = "Antwort an dich selbst";
|
||||||
|
|
||||||
@@ -421,34 +358,21 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
/* Indicating that the user is replying to the following listed people. */
|
/* Indicating that the user is replying to the following listed people. */
|
||||||
"Replying to:" = "Du antwortest:";
|
"Replying to:" = "Du antwortest:";
|
||||||
|
|
||||||
/* Button to report a profile.
|
|
||||||
Context menu option for reporting content. */
|
|
||||||
"Report" = "Melden";
|
|
||||||
|
|
||||||
/* Label indicating that the text underneath is the identifier of the report that was sent to relay servers. */
|
|
||||||
"Report ID:" = "Meldungs-ID";
|
|
||||||
|
|
||||||
/* Message indicating that a report was successfully sent to relay servers. */
|
|
||||||
"Report sent!" = "Meldung versandt!";
|
|
||||||
|
|
||||||
/* Button to confirm reposting a post.
|
/* Button to confirm reposting a post.
|
||||||
Title of alert for confirming to repost a post. */
|
Title of alert for confirming to repost a post. */
|
||||||
"Repost" = "Selbst teilen";
|
"Repost" = "Teilen";
|
||||||
|
|
||||||
/* Text indicating that the post was reposted (i.e. re-shared). */
|
/* Text indicating that the post was reposted (i.e. re-shared). */
|
||||||
"Reposted" = "Selbst geteilt";
|
"Reposted" = "Geteilt";
|
||||||
|
|
||||||
/* Navigation bar title for Reposts view. */
|
/* No comment provided by engineer. */
|
||||||
"Reposts" = "Geteilte Beiträge";
|
|
||||||
|
|
||||||
/* Picker option for DM selector for seeing only message requests (DMs that someone else sent the user which has not been responded to yet). DM is the English abbreviation for Direct Message. */
|
|
||||||
"Requests" = "Anfragen";
|
"Requests" = "Anfragen";
|
||||||
|
|
||||||
/* Section title for resetting the user */
|
/* Section title for resetting the user */
|
||||||
"Reset" = "Zurücksetzen";
|
"Reset" = "Zurücksetzen";
|
||||||
|
|
||||||
/* Button to retry completing account creation after an error occurred. */
|
/* Button to retry completing account creation after an error occurred. */
|
||||||
"Retry" = "Erneut versuchen";
|
"Retry" = "Wiederholung";
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, River */
|
/* Dropdown option label for Lightning wallet, River */
|
||||||
"River" = "River";
|
"River" = "River";
|
||||||
@@ -463,7 +387,7 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
"Save" = "Speichern";
|
"Save" = "Speichern";
|
||||||
|
|
||||||
/* Context menu option to save an image. */
|
/* Context menu option to save an image. */
|
||||||
"Save Image" = "Bild sichern";
|
"Save Image" = "Bild speichern";
|
||||||
|
|
||||||
/* Navigation link to search hashtag. */
|
/* Navigation link to search hashtag. */
|
||||||
"Search hashtag: #%@" = "Hashtag suchen: #%@";
|
"Search hashtag: #%@" = "Hashtag suchen: #%@";
|
||||||
@@ -475,7 +399,7 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
"Secret Account Login Key" = "Geheimer Konto-Anmeldeschlüssel";
|
"Secret Account Login Key" = "Geheimer Konto-Anmeldeschlüssel";
|
||||||
|
|
||||||
/* Title of section for selecting a Lightning wallet to pay a Lightning invoice. */
|
/* Title of section for selecting a Lightning wallet to pay a Lightning invoice. */
|
||||||
"Select a Lightning wallet" = "Wähle ein Lightning Wallet";
|
"Select a Lightning wallet" = "Wähle eine Lightning-Wallet";
|
||||||
|
|
||||||
/* Prompt selection of user's default wallet */
|
/* Prompt selection of user's default wallet */
|
||||||
"Select default wallet" = "Wähle ein voreingestelltes Wallet";
|
"Select default wallet" = "Wähle ein voreingestelltes Wallet";
|
||||||
@@ -487,8 +411,7 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
Sidebar menu label for accessing the app settings */
|
Sidebar menu label for accessing the app settings */
|
||||||
"Settings" = "Einstellungen";
|
"Settings" = "Einstellungen";
|
||||||
|
|
||||||
/* Button to share an image.
|
/* Button to share an image. */
|
||||||
Button to share the link to a profile. */
|
|
||||||
"Share" = "Teilen";
|
"Share" = "Teilen";
|
||||||
|
|
||||||
/* Toggle to show or hide user's secret account login key. */
|
/* Toggle to show or hide user's secret account login key. */
|
||||||
@@ -503,12 +426,6 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
/* Dropdown option label for Lightning wallet, Strike. */
|
/* Dropdown option label for Lightning wallet, Strike. */
|
||||||
"Strike" = "Strike";
|
"Strike" = "Strike";
|
||||||
|
|
||||||
/* Button to close out of alert that informs that the action to block a user was successful. */
|
|
||||||
"Thanks!" = "Danke!";
|
|
||||||
|
|
||||||
/* Button for user to report that the account is impersonating someone. */
|
|
||||||
"They are impersonating someone" = "Sie gibt sich für jemand anderen aus";
|
|
||||||
|
|
||||||
/* Warning that the inputted account key is a public key and the result of what happens because of it. */
|
/* Warning that the inputted account key is a public key and the result of what happens because of it. */
|
||||||
"This is a public key, you will not be able to make posts or interact in any way. This is used for viewing accounts from their perspective." = "Dies ist ein öffentlicher Schlüssel, Du wirst keine Beiträge teilen oder oder auf irgendeine Weise interagieren können. Dies wird genutzt um Kontos aus deren Perspektive zu sehen.";
|
"This is a public key, you will not be able to make posts or interact in any way. This is used for viewing accounts from their perspective." = "Dies ist ein öffentlicher Schlüssel, Du wirst keine Beiträge teilen oder oder auf irgendeine Weise interagieren können. Dies wird genutzt um Kontos aus deren Perspektive zu sehen.";
|
||||||
|
|
||||||
@@ -543,12 +460,6 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
/* Text to indicate that the button next to it is in a state that will unfollow a profile when tapped. */
|
/* Text to indicate that the button next to it is in a state that will unfollow a profile when tapped. */
|
||||||
"Unfollows" = "Entfolgen";
|
"Unfollows" = "Entfolgen";
|
||||||
|
|
||||||
/* Alert message to indicate */
|
|
||||||
"User blocked" = "Benutzer blockiert";
|
|
||||||
|
|
||||||
/* Alert message that informs a user was blocked. */
|
|
||||||
"User has been blocked" = "Der Benutzer wurde blockiert";
|
|
||||||
|
|
||||||
/* Label for Username section of user profile form.
|
/* Label for Username section of user profile form.
|
||||||
Label to prompt username entry. */
|
Label to prompt username entry. */
|
||||||
"Username" = "Benutzername";
|
"Username" = "Benutzername";
|
||||||
@@ -571,14 +482,8 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
/* Text to welcome user. */
|
/* Text to welcome user. */
|
||||||
"Welcome, %@!" = "Willkommen, %@!";
|
"Welcome, %@!" = "Willkommen, %@!";
|
||||||
|
|
||||||
/* Header text to prompt user what issue they want to report. */
|
|
||||||
"What do you want to report?" = "Was möchtest du melden?";
|
|
||||||
|
|
||||||
/* Placeholder example for relay server address. */
|
/* Placeholder example for relay server address. */
|
||||||
"wss://some.relay.com" = "wss://ein.relay.at";
|
"wss://some.relay.com" = "wss://irgendein.relay.de";
|
||||||
|
|
||||||
/* Text of button that confirms to overwrite the existing mutelist. */
|
|
||||||
"Yes, Overwrite" = "Ja, überschreiben";
|
|
||||||
|
|
||||||
/* You, in this context, is the person who controls their own social network. You is used in the context of a larger sentence that welcomes the reader to the social network that they control themself. */
|
/* You, in this context, is the person who controls their own social network. You is used in the context of a larger sentence that welcomes the reader to the social network that they control themself. */
|
||||||
"you" = "Du";
|
"you" = "Du";
|
||||||
@@ -586,9 +491,6 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
/* Label for Your Name section of user profile form. */
|
/* Label for Your Name section of user profile form. */
|
||||||
"Your Name" = "Dein Name";
|
"Your Name" = "Dein Name";
|
||||||
|
|
||||||
/* Footer text to inform user what will happen when the report is submitted. */
|
|
||||||
"Your report will be sent to the relays you are connected to" = "Die Meldung wird an Relays versendet, mit denen du verbunden bist";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Zebedee. */
|
/* Dropdown option label for Lightning wallet, Zebedee. */
|
||||||
"Zebedee" = "Zebedee";
|
"Zebedee" = "Zebedee";
|
||||||
|
|
||||||
@@ -27,9 +27,9 @@
|
|||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>d</string>
|
<string>d</string>
|
||||||
<key>one</key>
|
<key>one</key>
|
||||||
<string>Gefolgte:r</string>
|
<string>Follower</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>Gefolgte</string>
|
<string>Follower</string>
|
||||||
</dict>
|
</dict>
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
<string>%#@FOLLOWERS@</string>
|
<string>%#@FOLLOWERS@</string>
|
||||||
@@ -77,9 +77,9 @@
|
|||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>d</string>
|
<string>d</string>
|
||||||
<key>one</key>
|
<key>one</key>
|
||||||
<string> & %d andere</string>
|
<string>& %d andere</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string> & %d andere</string>
|
<string>& %d andere</string>
|
||||||
<key>zero</key>
|
<key>zero</key>
|
||||||
<string></string>
|
<string></string>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -95,9 +95,9 @@
|
|||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>d</string>
|
<string>d</string>
|
||||||
<key>one</key>
|
<key>one</key>
|
||||||
<string> & %d andere</string>
|
<string>& %d andere</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string> & %d andere</string>
|
<string>& %d andere</string>
|
||||||
<key>zero</key>
|
<key>zero</key>
|
||||||
<string></string>
|
<string></string>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -113,9 +113,9 @@
|
|||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>d</string>
|
<string>d</string>
|
||||||
<key>one</key>
|
<key>one</key>
|
||||||
<string>geteilter Beitrag</string>
|
<string>Mal geteilt</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>geteilte Beiträge</string>
|
<string>Mal geteilt</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
<key>sats_count</key>
|
<key>sats_count</key>
|
||||||
@@ -5,5 +5,5 @@
|
|||||||
"CFBundleName" = "damus";
|
"CFBundleName" = "damus";
|
||||||
|
|
||||||
/* Privacy - Photo Library Additions Usage Description */
|
/* Privacy - Photo Library Additions Usage Description */
|
||||||
"NSPhotoLibraryAddUsageDescription" = "Donner accès à Damus à vos photos vous permet d'enregistrer des images";
|
"NSPhotoLibraryAddUsageDescription" = "\"Accorder à Damus l'accès à votre galerie photos vous permet d'enregistrer des photos.";
|
||||||
|
|
||||||
|
|||||||
@@ -8,10 +8,10 @@
|
|||||||
"'%@' is an invalid nip05 identifier. It should look like an email." = "'@' est un identifiant nip05 invalide. Cela devrait ressembler à une adresse e-mail.";
|
"'%@' is an invalid nip05 identifier. It should look like an email." = "'@' est un identifiant nip05 invalide. Cela devrait ressembler à une adresse e-mail.";
|
||||||
|
|
||||||
/* Navigation bar title for view that shows who is following a user. */
|
/* Navigation bar title for view that shows who is following a user. */
|
||||||
"(Profile.displayName(profile: profile, pubkey: whos))'s Followers" = "Abonnés de (Profile.displayName(profile: profile, pubkey: whos))";
|
"(Profile.displayName(profile: profile, pubkey: whos))'s Followers" = "(Profile.displayName(profile: profile, pubkey: whos))'s Followers";
|
||||||
|
|
||||||
/* Navigation bar title for view that shows who a user is following. */
|
/* Navigation bar title for view that shows who a user is following. */
|
||||||
"(who) following" = "(who) suit";
|
"(who) following" = "(who) following";
|
||||||
|
|
||||||
/* Prefix character to username. */
|
/* Prefix character to username. */
|
||||||
"@" = "@";
|
"@" = "@";
|
||||||
@@ -38,7 +38,7 @@ Number of profiles a user is following. */
|
|||||||
"%lld" = "%lld";
|
"%lld" = "%lld";
|
||||||
|
|
||||||
/* Fraction of how many of the user's relay servers that are operational. */
|
/* Fraction of how many of the user's relay servers that are operational. */
|
||||||
"%lld/%lld" = "%lld/%lld";
|
"%lld/%lld" = "%lld/%lld<br data-mce-bogus=\"1\">";
|
||||||
|
|
||||||
/* Placeholder for event mention. */
|
/* Placeholder for event mention. */
|
||||||
"< e >" = "< e >";
|
"< e >" = "< e >";
|
||||||
@@ -59,9 +59,6 @@ Number of profiles a user is following. */
|
|||||||
Button to confirm adding user inputted relay. */
|
Button to confirm adding user inputted relay. */
|
||||||
"Add" = "Ajouter";
|
"Add" = "Ajouter";
|
||||||
|
|
||||||
/* Button label to re-add all original participants as profiles to reply to in a note */
|
|
||||||
"Add all" = "Tout ajouter";
|
|
||||||
|
|
||||||
/* Label for section for adding a relay server. */
|
/* Label for section for adding a relay server. */
|
||||||
"Add Relay" = "Ajouter un Relais";
|
"Add Relay" = "Ajouter un Relais";
|
||||||
|
|
||||||
@@ -69,7 +66,7 @@ Number of profiles a user is following. */
|
|||||||
"Any" = "N'importe Lequel";
|
"Any" = "N'importe Lequel";
|
||||||
|
|
||||||
/* Alert message to ask if user wants to repost a post. */
|
/* Alert message to ask if user wants to repost a post. */
|
||||||
"Are you sure you want to repost this?" = "Êtes-vous sûr de vouloir republier ceci ?";
|
"Are you sure you want to repost this?" = "Êtes-vous sûr de vouloir republier ceci ?";
|
||||||
|
|
||||||
/* Label for Banner Image section of user profile form. */
|
/* Label for Banner Image section of user profile form. */
|
||||||
"Banner Image" = "Image Bannière";
|
"Banner Image" = "Image Bannière";
|
||||||
@@ -84,10 +81,10 @@ Number of profiles a user is following. */
|
|||||||
"Bitcoin Lightning Tips" = "Pourboires de Bitcoin Lightning";
|
"Bitcoin Lightning Tips" = "Pourboires de Bitcoin Lightning";
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Blixt Wallet */
|
/* Dropdown option label for Lightning wallet, Blixt Wallet */
|
||||||
"Blixt Wallet" = "Blixt Wallet";
|
"Blixt Wallet" = "Portefeuille Blixt";
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Blue Wallet. */
|
/* Dropdown option label for Lightning wallet, Blue Wallet. */
|
||||||
"Blue Wallet" = "Blue Wallet";
|
"Blue Wallet" = "Portefeuille Blue";
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Breez. */
|
/* Dropdown option label for Lightning wallet, Breez. */
|
||||||
"Breez" = "Breez";
|
"Breez" = "Breez";
|
||||||
@@ -108,7 +105,7 @@ Number of profiles a user is following. */
|
|||||||
"Chat" = "Chatter";
|
"Chat" = "Chatter";
|
||||||
|
|
||||||
/* Button for clearing cached data. */
|
/* Button for clearing cached data. */
|
||||||
"Clear" = "Vider";
|
"Clear" = "<br>Vider";
|
||||||
|
|
||||||
/* Section title for clearing cached data. */
|
/* Section title for clearing cached data. */
|
||||||
"Clear Cache" = "Vider le Cache";
|
"Clear Cache" = "Vider le Cache";
|
||||||
@@ -163,7 +160,7 @@ Number of profiles a user is following. */
|
|||||||
"Default Wallet" = "Portefeuille par défaut";
|
"Default Wallet" = "Portefeuille par défaut";
|
||||||
|
|
||||||
/* Button to delete a relay server that the user connects to. */
|
/* Button to delete a relay server that the user connects to. */
|
||||||
"Delete" = "Effacer";
|
"Delete" = "<br>Effacer";
|
||||||
|
|
||||||
/* Button to dismiss a text field alert. */
|
/* Button to dismiss a text field alert. */
|
||||||
"Dismiss" = "Rejeter";
|
"Dismiss" = "Rejeter";
|
||||||
@@ -171,12 +168,8 @@ Number of profiles a user is following. */
|
|||||||
/* Label to prompt display name entry. */
|
/* Label to prompt display name entry. */
|
||||||
"Display Name" = "Afficher Nom";
|
"Display Name" = "Afficher Nom";
|
||||||
|
|
||||||
/* DM selector for seeing either DMs or message requests, which are messages that have not been responded to yet. DM is the English abbreviation for Direct Message. */
|
/* Navigation title for DM view, which is the English abbreviation for Direct Message. */
|
||||||
"DM Type" = "Type de message privé";
|
"DM" = "DM";
|
||||||
|
|
||||||
/* Navigation title for DMs view, where DM is the English abbreviation for Direct Message.
|
|
||||||
Navigation title for view of DMs, where DM is an English abbreviation for Direct Message. */
|
|
||||||
"DMs" = "Messages privés";
|
|
||||||
|
|
||||||
/* Button to dismiss wallet selection view for paying Lightning invoice. */
|
/* Button to dismiss wallet selection view for paying Lightning invoice. */
|
||||||
"Done" = "Fini";
|
"Done" = "Fini";
|
||||||
@@ -187,23 +180,23 @@ Number of profiles a user is following. */
|
|||||||
/* Button to edit user's profile. */
|
/* Button to edit user's profile. */
|
||||||
"Edit" = "Modifier";
|
"Edit" = "Modifier";
|
||||||
|
|
||||||
/* Text indicating that the view is used for editing which participants are replied to in a note. */
|
|
||||||
"Edit participants" = "Modifier les participants";
|
|
||||||
|
|
||||||
/* Heading indicating that this application keeps private messaging end-to-end encrypted. */
|
/* Heading indicating that this application keeps private messaging end-to-end encrypted. */
|
||||||
"Encrypted" = "Crypté";
|
"Encrypted" = "Crypté";
|
||||||
|
|
||||||
|
/* Navigation title for view of encrypted DMs, where DM is an English abbreviation for Direct Message. */
|
||||||
|
"Encrypted DMs" = "DMs cryptés";
|
||||||
|
|
||||||
/* Prompt for user to enter an account key to login. */
|
/* Prompt for user to enter an account key to login. */
|
||||||
"Enter your account key to login:" = "Entrez votre clé de compte pour vous connecter:";
|
"Enter your account key to login:" = "Entrez votre clé de compte pour vous connecter:";
|
||||||
|
|
||||||
/* Error message indicating why saving keys failed. */
|
/* Error message indicating why saving keys failed. */
|
||||||
"Error: %@" = "Erreur: %@";
|
"Error: %@" = "Error: %@";
|
||||||
|
|
||||||
/* Filter state for seeing either only posts, or posts & replies. */
|
/* Filter state for seeing either only posts, or posts & replies. */
|
||||||
"Filter State" = "État du filtre";
|
"Filter State" = "État du filtre";
|
||||||
|
|
||||||
/* Button to follow a user. */
|
/* Button to follow a user. */
|
||||||
"Follow" = "S'abonner";
|
"Follow" = "S'abonner<br>";
|
||||||
|
|
||||||
/* Label describing followers of a user. */
|
/* Label describing followers of a user. */
|
||||||
"Followers" = "Abonnés";
|
"Followers" = "Abonnés";
|
||||||
@@ -216,22 +209,22 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
"Following..." = "Abonnements...";
|
"Following..." = "Abonnements...";
|
||||||
|
|
||||||
/* Text to indicate that button next to it is in a state that will follow a profile when tapped. */
|
/* Text to indicate that button next to it is in a state that will follow a profile when tapped. */
|
||||||
"Follows" = "Suit";
|
"Follows" = "Follow<br>";
|
||||||
|
|
||||||
/* Navigation bar title for Global view where posts from all connected relay servers appear. */
|
/* Navigation bar title for Global view where posts from all connected relay servers appear. */
|
||||||
"Global" = "Global";
|
"Global" = "Global";
|
||||||
|
|
||||||
/* Navigation link to go to post referenced by hex code. */
|
/* Navigation link to go to post referenced by hex code. */
|
||||||
"Goto post %@" = "Aller au post %@";
|
"Goto post %@" = "Goto post %@";
|
||||||
|
|
||||||
/* Navigation link to go to profile. */
|
/* Navigation link to go to profile. */
|
||||||
"Goto profile %@" = "Aller au profil %@";
|
"Goto profile %@" = "Goto profile %@";
|
||||||
|
|
||||||
/* Navigation bar title for Home view where posts and replies appear from those who the user is following. */
|
/* Navigation bar title for Home view where posts and replies appear from those who the user is following. */
|
||||||
"Home" = "Accueil";
|
"Home" = "Accueil";
|
||||||
|
|
||||||
/* Placeholder example text for profile picture URL. */
|
/* Placeholder example text for profile picture URL. */
|
||||||
"https://example.com/pic.jpg" = "https://exemple.com/pic.jpg";
|
"https://example.com/pic.jpg" = "https://example.com/pic.jpg";
|
||||||
|
|
||||||
/* Placeholder example text for website URL for user profile. */
|
/* Placeholder example text for website URL for user profile. */
|
||||||
"https://jb55.com" = "https://jb55.com";
|
"https://jb55.com" = "https://jb55.com";
|
||||||
@@ -255,7 +248,7 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
"Lightning Invoice" = "Facture Lightning";
|
"Lightning Invoice" = "Facture Lightning";
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, LNLink. */
|
/* Dropdown option label for Lightning wallet, LNLink. */
|
||||||
"LNLink" = "LNLink";
|
"LNLink" = "Lien LN";
|
||||||
|
|
||||||
/* Dropdown option label for system default for Lightning wallet. */
|
/* Dropdown option label for system default for Lightning wallet. */
|
||||||
"Local default" = "Valeur locale par défaut";
|
"Local default" = "Valeur locale par défaut";
|
||||||
@@ -279,7 +272,7 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
"NIP-05 Verification" = "Vérification NIP-05";
|
"NIP-05 Verification" = "Vérification NIP-05";
|
||||||
|
|
||||||
/* No search results. */
|
/* No search results. */
|
||||||
"none" = "aucun";
|
"none" = "none";
|
||||||
|
|
||||||
/* Indicates that there are no notes in the timeline to view. */
|
/* Indicates that there are no notes in the timeline to view. */
|
||||||
"Nothing to see here. Check back later!" = "Rien à voir ici. Revenez plus tard!";
|
"Nothing to see here. Check back later!" = "Rien à voir ici. Revenez plus tard!";
|
||||||
@@ -288,13 +281,13 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
"Notifications" = "Notifications";
|
"Notifications" = "Notifications";
|
||||||
|
|
||||||
/* String indicating that a given timestamp just occurred */
|
/* String indicating that a given timestamp just occurred */
|
||||||
"now" = "maintenant";
|
"now" = "now";
|
||||||
|
|
||||||
/* Prompt for user to enter in an account key to login. This text shows the characters the key could start with if it was a private key. */
|
/* Prompt for user to enter in an account key to login. This text shows the characters the key could start with if it was a private key. */
|
||||||
"nsec1..." = "nsec1...";
|
"nsec1..." = "nsec1...";
|
||||||
|
|
||||||
/* Label indicating that a form input is optional. */
|
/* Label indicating that a form input is optional. */
|
||||||
"optional" = "optionnel";
|
"optional" = "optional";
|
||||||
|
|
||||||
/* Button to pay a Lightning invoice. */
|
/* Button to pay a Lightning invoice. */
|
||||||
"Pay" = "Payer";
|
"Pay" = "Payer";
|
||||||
@@ -317,9 +310,12 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
/* Heading indicating that this application keeps personally identifiable information private. A sentence describing what is done to keep data private comes after this heading. */
|
/* Heading indicating that this application keeps personally identifiable information private. A sentence describing what is done to keep data private comes after this heading. */
|
||||||
"Private" = "Privé";
|
"Private" = "Privé";
|
||||||
|
|
||||||
/* Title of the secure field that holds the user's private key. */
|
/* Label to indicate that the text below is the user's private key used by only the user themself as a secret to login to access their account. */
|
||||||
"Private Key" = "Clé Privée";
|
"Private Key" = "Clé Privée";
|
||||||
|
|
||||||
|
/* Title of the secure field that holds the user's private key. */
|
||||||
|
"PrivateKey" = "PrivateKey";
|
||||||
|
|
||||||
/* Sidebar menu label for Profile view. */
|
/* Sidebar menu label for Profile view. */
|
||||||
"Profile" = "Profil";
|
"Profile" = "Profil";
|
||||||
|
|
||||||
@@ -350,11 +346,8 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
/* Sidebar menu label for Relay servers view */
|
/* Sidebar menu label for Relay servers view */
|
||||||
"Relays" = "Relais";
|
"Relays" = "Relais";
|
||||||
|
|
||||||
/* Button label to remove all participants from a note reply. */
|
|
||||||
"Remove all" = "Tout supprimer";
|
|
||||||
|
|
||||||
/* Label to indicate that the user is replying to themself. */
|
/* Label to indicate that the user is replying to themself. */
|
||||||
"Reply to self" = "Réponse à soi-même";
|
"Reply to self" = "Répondre à soi-même";
|
||||||
|
|
||||||
/* Label to indicate that the user is replying to 2 users. */
|
/* Label to indicate that the user is replying to 2 users. */
|
||||||
"Replying to %@ & %@" = "Répondre à %1$@ & %2$@";
|
"Replying to %@ & %@" = "Répondre à %1$@ & %2$@";
|
||||||
@@ -369,9 +362,6 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
/* Text indicating that the post was reposted (i.e. re-shared). */
|
/* Text indicating that the post was reposted (i.e. re-shared). */
|
||||||
"Reposted" = "A republié";
|
"Reposted" = "A republié";
|
||||||
|
|
||||||
/* Picker option for DM selector for seeing only message requests (DMs that someone else sent the user which has not been responded to yet). DM is the English abbreviation for Direct Message. */
|
|
||||||
"Requests" = "Demandes";
|
|
||||||
|
|
||||||
/* Section title for resetting the user */
|
/* Section title for resetting the user */
|
||||||
"Reset" = "Réinitialiser";
|
"Reset" = "Réinitialiser";
|
||||||
|
|
||||||
@@ -419,7 +409,7 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
"Share" = "Partager";
|
"Share" = "Partager";
|
||||||
|
|
||||||
/* Toggle to show or hide user's secret account login key. */
|
/* Toggle to show or hide user's secret account login key. */
|
||||||
"Show" = "Afficher";
|
"Show" = "Afficher<br>";
|
||||||
|
|
||||||
/* Toggle to show or hide selection of wallet. */
|
/* Toggle to show or hide selection of wallet. */
|
||||||
"Show wallet selector" = "Afficher le sélecteur de portefeuille";
|
"Show wallet selector" = "Afficher le sélecteur de portefeuille";
|
||||||
@@ -459,7 +449,7 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
"Unfollowing" = "Ne plus suivre";
|
"Unfollowing" = "Ne plus suivre";
|
||||||
|
|
||||||
/* Label to indicate that the user is in the process of unfollowing another user. */
|
/* Label to indicate that the user is in the process of unfollowing another user. */
|
||||||
"Unfollowing..." = "Ne plus suivre...";
|
"Unfollowing..." = "Ne plus suivre...<br>";
|
||||||
|
|
||||||
/* Text to indicate that the button next to it is in a state that will unfollow a profile when tapped. */
|
/* Text to indicate that the button next to it is in a state that will unfollow a profile when tapped. */
|
||||||
"Unfollows" = "Se désabonne de";
|
"Unfollows" = "Se désabonne de";
|
||||||
@@ -472,7 +462,7 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
"Wallet" = "Portefeuille";
|
"Wallet" = "Portefeuille";
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Wallet Of Satoshi. */
|
/* Dropdown option label for Lightning wallet, Wallet Of Satoshi. */
|
||||||
"Wallet Of Satoshi" = "Wallet Of Satoshi";
|
"Wallet Of Satoshi" = "Portefeuille de Satoshi";
|
||||||
|
|
||||||
/* Section title for selection of wallet. */
|
/* Section title for selection of wallet. */
|
||||||
"Wallet Selector" = "Sélecteur de portefeuille";
|
"Wallet Selector" = "Sélecteur de portefeuille";
|
||||||
@@ -487,10 +477,10 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
"Welcome, %@!" = "Bienvenue, %@!";
|
"Welcome, %@!" = "Bienvenue, %@!";
|
||||||
|
|
||||||
/* Placeholder example for relay server address. */
|
/* Placeholder example for relay server address. */
|
||||||
"wss://some.relay.com" = "wss://un.relais.com";
|
"wss://some.relay.com" = "wss://some.relay.com";
|
||||||
|
|
||||||
/* You, in this context, is the person who controls their own social network. You is used in the context of a larger sentence that welcomes the reader to the social network that they control themself. */
|
/* You, in this context, is the person who controls their own social network. You is used in the context of a larger sentence that welcomes the reader to the social network that they control themself. */
|
||||||
"you" = "vous";
|
"you" = "you";
|
||||||
|
|
||||||
/* Label for Your Name section of user profile form. */
|
/* Label for Your Name section of user profile form. */
|
||||||
"Your Name" = "Votre Nom";
|
"Your Name" = "Votre Nom";
|
||||||
@@ -499,5 +489,5 @@ Part of a larger sentence to describe how many profiles a user is following. */
|
|||||||
"Zebedee" = "Zebedee";
|
"Zebedee" = "Zebedee";
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Zeus LN. */
|
/* Dropdown option label for Lightning wallet, Zeus LN. */
|
||||||
"Zeus LN" = "Zeus LN";
|
"Zeus LN" = "LN de Zeus";
|
||||||
|
|
||||||
|
|||||||
@@ -11,9 +11,9 @@
|
|||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>d</string>
|
<string>d</string>
|
||||||
<key>one</key>
|
<key>one</key>
|
||||||
<string>%d autre note</string>
|
<string>%d other note</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>%d autres notes</string>
|
<string>%d other notes</string>
|
||||||
</dict>
|
</dict>
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
<string>··· %#@NOTES@ ···</string>
|
<string>··· %#@NOTES@ ···</string>
|
||||||
@@ -69,7 +69,7 @@
|
|||||||
<key>replying_to_one_and_others</key>
|
<key>replying_to_one_and_others</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
<key>NSStringLocalizedFormatKey</key>
|
||||||
<string>Réponse à %@%#@OTHERS@</string>
|
<string>Répondre à %@%#@OTHERS@</string>
|
||||||
<key>OTHERS</key>
|
<key>OTHERS</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSStringFormatSpecTypeKey</key>
|
<key>NSStringFormatSpecTypeKey</key>
|
||||||
@@ -77,9 +77,9 @@
|
|||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>d</string>
|
<string>d</string>
|
||||||
<key>one</key>
|
<key>one</key>
|
||||||
<string>& %d autre</string>
|
<string>& %d other</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>& %d autres</string>
|
<string>& %d others</string>
|
||||||
<key>zero</key>
|
<key>zero</key>
|
||||||
<string></string>
|
<string></string>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -95,9 +95,9 @@
|
|||||||
<key>NSStringFormatValueTypeKey</key>
|
<key>NSStringFormatValueTypeKey</key>
|
||||||
<string>d</string>
|
<string>d</string>
|
||||||
<key>one</key>
|
<key>one</key>
|
||||||
<string>& %d autre</string>
|
<string>& %d other</string>
|
||||||
<key>other</key>
|
<key>other</key>
|
||||||
<string>& %d autres</string>
|
<string>& %d others</string>
|
||||||
<key>zero</key>
|
<key>zero</key>
|
||||||
<string></string>
|
<string></string>
|
||||||
</dict>
|
</dict>
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
/* Bundle display name */
|
|
||||||
"CFBundleDisplayName" = "Damus";
|
|
||||||
|
|
||||||
/* Bundle name */
|
|
||||||
"CFBundleName" = "damus";
|
|
||||||
|
|
||||||
/* Privacy - Photo Library Additions Usage Description */
|
|
||||||
"NSPhotoLibraryAddUsageDescription" = "Dai il permesso a Damus di accedere alle tue Foto per salvare immagini";
|
|
||||||
|
|
||||||
@@ -1,503 +0,0 @@
|
|||||||
/* Blank space to separate profile picture from profile editor form. */
|
|
||||||
" " = "61b6edf1108e6f396680a33b02486a70_tr";
|
|
||||||
|
|
||||||
/* Description of how the nip05 identifier would be used for verification. */
|
|
||||||
"'%@' at '%@' will be used for verification" = "'%@' at '%@' sarà usato per la verifica";
|
|
||||||
|
|
||||||
/* Description of why the nip05 identifier is invalid. */
|
|
||||||
"'%@' is an invalid nip05 identifier. It should look like an email." = "'%@' non è un identificatore NIP05 valido. Dovrebbe essere simile ad un indirizzo email.";
|
|
||||||
|
|
||||||
/* Navigation bar title for view that shows who is following a user. */
|
|
||||||
"(Profile.displayName(profile: profile, pubkey: whos))'s Followers" = "Seguaci di (Profile.displayName(profile: profile, pubkey: whos))'";
|
|
||||||
|
|
||||||
/* Navigation bar title for view that shows who a user is following. */
|
|
||||||
"(who) following" = "(who) segui già";
|
|
||||||
|
|
||||||
/* Prefix character to username. */
|
|
||||||
"@" = "@";
|
|
||||||
|
|
||||||
/* Amount of time that has passed since reply quote event occurred.
|
|
||||||
Abbreviated version of a nostr public key. */
|
|
||||||
"%@" = "%@";
|
|
||||||
|
|
||||||
/* Sentence composed of 2 variables to describe how many reposts. In source English, the first variable is the number of reposts, and the second variable is 'Repost' or 'Reposts'.
|
|
||||||
Sentence composed of 2 variables to describe how many profiles a user is following. In source English, the first variable is the number of profiles being followed, and the second variable is 'Following'. */
|
|
||||||
"%@ %@" = "%@ %@";
|
|
||||||
|
|
||||||
/* Explanation of what is done to keep personally identifiable information private. There is a heading that precedes this explanation which is a variable to this string. */
|
|
||||||
"%@. Creating an account doesn't require a phone number, email or name. Get started right away with zero friction." = "%@. Per creare un account non hai bisogno di un numero di telefono, un indirizzo email o del tuo nome. Inizia ora senza impegni.";
|
|
||||||
|
|
||||||
/* Explanation of what is done to keep private data encrypted. There is a heading that precedes this explanation which is a variable to this string. */
|
|
||||||
"%@. End-to-End encrypted private messaging. Keep Big Tech out of your DMs" = "%@. I messaggi sono criptati utilizzando la crittografia end-to-end. Mantieni i colossi della tecnologia lontani dai tuoi messaggi";
|
|
||||||
|
|
||||||
/* Explanation of what can be done by users to earn money. There is a heading that precedes this explanation which is a variable to this string. */
|
|
||||||
"%@. Tip your friend's posts and stack sats with Bitcoin⚡️, the native currency of the internet." = "%@. Paga i tuoi amici e accumula sats con Bitcoin⚡️, la moneta di internet.";
|
|
||||||
|
|
||||||
/* Number of reposts.
|
|
||||||
Number of profiles a user is following. */
|
|
||||||
"%lld" = "%lld";
|
|
||||||
|
|
||||||
/* Fraction of how many of the user's relay servers that are operational. */
|
|
||||||
"%lld/%lld" = "%lld/%lld";
|
|
||||||
|
|
||||||
/* Placeholder for event mention. */
|
|
||||||
"< e >" = "< e >";
|
|
||||||
|
|
||||||
/* Label to prompt for about text entry for user to describe about themself. */
|
|
||||||
"About" = "Informazioni";
|
|
||||||
|
|
||||||
/* Label for About Me section of user profile form. */
|
|
||||||
"About Me" = "Io";
|
|
||||||
|
|
||||||
/* Placeholder text for About Me description. */
|
|
||||||
"Absolute Boss" = "Capo supremo";
|
|
||||||
|
|
||||||
/* Label to indicate the public ID of the account. */
|
|
||||||
"Account ID" = "ID dell'account";
|
|
||||||
|
|
||||||
/* Button to add recommended relay server.
|
|
||||||
Button to confirm adding user inputted relay. */
|
|
||||||
"Add" = "Aggiungi";
|
|
||||||
|
|
||||||
/* Button label to re-add all original participants as profiles to reply to in a note */
|
|
||||||
"Add all" = "Aggiungi tutto";
|
|
||||||
|
|
||||||
/* Label for section for adding a relay server. */
|
|
||||||
"Add Relay" = "Aggiungi relè";
|
|
||||||
|
|
||||||
/* Any amount of sats */
|
|
||||||
"Any" = "Qualsiasi";
|
|
||||||
|
|
||||||
/* Alert message to ask if user wants to repost a post. */
|
|
||||||
"Are you sure you want to repost this?" = "Sei sicuro di voler segnalare questo post?";
|
|
||||||
|
|
||||||
/* Label for Banner Image section of user profile form. */
|
|
||||||
"Banner Image" = "Immagine banner";
|
|
||||||
|
|
||||||
/* Reminder to user that they should save their account information. */
|
|
||||||
"Before we get started, you'll need to save your account info, otherwise you won't be able to login in the future if you ever uninstall Damus." = "Prima di iniziare, dovrai salvare le informazioni del tuo account altrimenti non sarai in grado di accedere in futuro se dovessi disinstallare Damus.";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Bitcoin Beach. */
|
|
||||||
"Bitcoin Beach" = "Bitcoin Beach";
|
|
||||||
|
|
||||||
/* Label for Bitcoin Lightning Tips section of user profile form. */
|
|
||||||
"Bitcoin Lightning Tips" = "Mancia con Bitcoin Lightning";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Blixt Wallet */
|
|
||||||
"Blixt Wallet" = "Blixt Wallet";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Blue Wallet. */
|
|
||||||
"Blue Wallet" = "Blue Wallet";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Breez. */
|
|
||||||
"Breez" = "Breez";
|
|
||||||
|
|
||||||
/* Context menu option for broadcasting the user's note to all of the user's connected relay servers. */
|
|
||||||
"Broadcast" = "Trasmetti";
|
|
||||||
|
|
||||||
/* Button to cancel out of posting a note.
|
|
||||||
Button to cancel out of reposting a post.
|
|
||||||
Button to cancel out of view adding user inputted relay.
|
|
||||||
Cancel out of logging out the user. */
|
|
||||||
"Cancel" = "Annulla";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Cash App. */
|
|
||||||
"Cash App" = "Cash App";
|
|
||||||
|
|
||||||
/* Navigation bar title for Chatroom view. */
|
|
||||||
"Chat" = "Chat";
|
|
||||||
|
|
||||||
/* Button for clearing cached data. */
|
|
||||||
"Clear" = "Cancella";
|
|
||||||
|
|
||||||
/* Section title for clearing cached data. */
|
|
||||||
"Clear Cache" = "Cancella cache";
|
|
||||||
|
|
||||||
/* Label indicating that a user's key was copied. */
|
|
||||||
"Copied" = "Copiato";
|
|
||||||
|
|
||||||
/* Button to copy a relay server address. */
|
|
||||||
"Copy" = "Copia";
|
|
||||||
|
|
||||||
/* Context menu option for copying the ID of the account that created the note. */
|
|
||||||
"Copy Account ID" = "Copia ID dell'Account";
|
|
||||||
|
|
||||||
/* Context menu option to copy an image into clipboard.
|
|
||||||
Context menu option to copy an image to clipboard. */
|
|
||||||
"Copy Image" = "Copia Immagine";
|
|
||||||
|
|
||||||
/* Context menu option to copy the URL of an image into clipboard. */
|
|
||||||
"Copy Image URL" = "Copia URL dell'Immagine";
|
|
||||||
|
|
||||||
/* Title of section for copying a Lightning invoice identifier. */
|
|
||||||
"Copy invoice" = "Copia fattura";
|
|
||||||
|
|
||||||
/* Context menu option for copying a user's Lightning URL. */
|
|
||||||
"Copy LNURL" = "Copia LNURL";
|
|
||||||
|
|
||||||
/* Context menu option for copying the ID of the note. */
|
|
||||||
"Copy Note ID" = "Copia ID della Nota";
|
|
||||||
|
|
||||||
/* Context menu option for copying the JSON text from the note. */
|
|
||||||
"Copy Note JSON" = "Copia JSON della Nota";
|
|
||||||
|
|
||||||
/* Context menu option for copying the text from an note. */
|
|
||||||
"Copy Text" = "Copia Testo";
|
|
||||||
|
|
||||||
/* Context menu option for copying the ID of the user who created the note. */
|
|
||||||
"Copy User ID" = "Copia ID dell'Utente";
|
|
||||||
|
|
||||||
/* Button to create account. */
|
|
||||||
"Create" = "Crea";
|
|
||||||
|
|
||||||
/* Button to create an account. */
|
|
||||||
"Create Account" = "Crea Account";
|
|
||||||
|
|
||||||
/* Example description about Bitcoin creator(s), Satoshi Nakamoto. */
|
|
||||||
"Creator(s) of Bitcoin. Absolute legend." = "Creatore/i di Bitcoin. Leggenda assoluta";
|
|
||||||
|
|
||||||
/* Name of the app, shown on the first screen when user is not logged in. */
|
|
||||||
"Damus" = "Damus";
|
|
||||||
|
|
||||||
/* Button to pay a Lightning invoice with the user's default Lightning wallet. */
|
|
||||||
"Default Wallet" = "Portafoglio Principale";
|
|
||||||
|
|
||||||
/* Button to delete a relay server that the user connects to. */
|
|
||||||
"Delete" = "Cancella";
|
|
||||||
|
|
||||||
/* Button to dismiss a text field alert. */
|
|
||||||
"Dismiss" = "Lascia stare";
|
|
||||||
|
|
||||||
/* Label to prompt display name entry. */
|
|
||||||
"Display Name" = "Nome visualizzato";
|
|
||||||
|
|
||||||
/* DM selector for seeing either DMs or message requests, which are messages that have not been responded to yet. DM is the English abbreviation for Direct Message. */
|
|
||||||
"DM Type" = "Tipo DM";
|
|
||||||
|
|
||||||
/* Navigation title for DMs view, where DM is the English abbreviation for Direct Message.
|
|
||||||
Navigation title for view of DMs, where DM is an English abbreviation for Direct Message. */
|
|
||||||
"DMs" = "DM";
|
|
||||||
|
|
||||||
/* Button to dismiss wallet selection view for paying Lightning invoice. */
|
|
||||||
"Done" = "Finito";
|
|
||||||
|
|
||||||
/* Heading indicating that this application allows users to earn money. */
|
|
||||||
"Earn Money" = "Guadagna Soldi";
|
|
||||||
|
|
||||||
/* Button to edit user's profile. */
|
|
||||||
"Edit" = "Modifica";
|
|
||||||
|
|
||||||
/* Text indicating that the view is used for editing which participants are replied to in a note. */
|
|
||||||
"Edit participants" = "Modifica partecipanti";
|
|
||||||
|
|
||||||
/* Heading indicating that this application keeps private messaging end-to-end encrypted. */
|
|
||||||
"Encrypted" = "Criptato";
|
|
||||||
|
|
||||||
/* Prompt for user to enter an account key to login. */
|
|
||||||
"Enter your account key to login:" = "Inserisci la chiave del tuo account per accedere";
|
|
||||||
|
|
||||||
/* Error message indicating why saving keys failed. */
|
|
||||||
"Error: %@" = "Errore: %@";
|
|
||||||
|
|
||||||
/* Filter state for seeing either only posts, or posts & replies. */
|
|
||||||
"Filter State" = "Filtra";
|
|
||||||
|
|
||||||
/* Button to follow a user. */
|
|
||||||
"Follow" = "Segui";
|
|
||||||
|
|
||||||
/* Label describing followers of a user. */
|
|
||||||
"Followers" = "Seguaci";
|
|
||||||
|
|
||||||
/* Text to indicate that the button next to it is in a state that indicates that it is in the process of following a profile.
|
|
||||||
Part of a larger sentence to describe how many profiles a user is following. */
|
|
||||||
"Following" = "Seguiti";
|
|
||||||
|
|
||||||
/* Label to indicate that the user is in the process of following another user. */
|
|
||||||
"Following..." = "Segui già...";
|
|
||||||
|
|
||||||
/* Text to indicate that button next to it is in a state that will follow a profile when tapped. */
|
|
||||||
"Follows" = "Segui";
|
|
||||||
|
|
||||||
/* Navigation bar title for Global view where posts from all connected relay servers appear. */
|
|
||||||
"Global" = "Globale";
|
|
||||||
|
|
||||||
/* Navigation link to go to post referenced by hex code. */
|
|
||||||
"Goto post %@" = "Vai al post %@";
|
|
||||||
|
|
||||||
/* Navigation link to go to profile. */
|
|
||||||
"Goto profile %@" = "Vai al profilo %@";
|
|
||||||
|
|
||||||
/* Navigation bar title for Home view where posts and replies appear from those who the user is following. */
|
|
||||||
"Home" = "Home";
|
|
||||||
|
|
||||||
/* Placeholder example text for profile picture URL. */
|
|
||||||
"https://example.com/pic.jpg" = "https://esempio.com/foto.jpg";
|
|
||||||
|
|
||||||
/* Placeholder example text for website URL for user profile. */
|
|
||||||
"https://jb55.com" = "https://jb55.com";
|
|
||||||
|
|
||||||
/* Error message indicating that an invalid account key was entered for login. */
|
|
||||||
"Invalid key" = "Chiave non valida";
|
|
||||||
|
|
||||||
/* Placeholder example text for identifier used for NIP-05 verification. */
|
|
||||||
"jb55@jb55.com" = "jb55@jb55.com";
|
|
||||||
|
|
||||||
/* Moves the post button to the left side of the screen */
|
|
||||||
"Left Handed" = "Mancino";
|
|
||||||
|
|
||||||
/* Button to complete account creation and start using the app. */
|
|
||||||
"Let's go!" = "Andiamo!";
|
|
||||||
|
|
||||||
/* Placeholder text for entry of Lightning Address or LNURL. */
|
|
||||||
"Lightning Address or LNURL" = "Indirizzo Lightning o LNURL";
|
|
||||||
|
|
||||||
/* Indicates that the view is for paying a Lightning invoice. */
|
|
||||||
"Lightning Invoice" = "Fattura Lightning";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, LNLink. */
|
|
||||||
"LNLink" = "LNLink";
|
|
||||||
|
|
||||||
/* Dropdown option label for system default for Lightning wallet. */
|
|
||||||
"Local default" = "Predefinito";
|
|
||||||
|
|
||||||
/* Button to log into account.
|
|
||||||
Button to log into an account. */
|
|
||||||
"Login" = "Entra";
|
|
||||||
|
|
||||||
/* Alert for logging out the user.
|
|
||||||
Button for logging out the user.
|
|
||||||
Button to logout the user. */
|
|
||||||
"Logout" = "Esci";
|
|
||||||
|
|
||||||
/* Reminder message in alert to get customer to verify that their private security account key is saved saved before logging out. */
|
|
||||||
"Make sure your nsec account key is saved before you logout or you will lose access to this account" = "Assicurati di aver salvato la chiave privata (nSEC) prima di uscire o perderai l'accesso a questo account";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Muun. */
|
|
||||||
"Muun" = "Muun";
|
|
||||||
|
|
||||||
/* Label for NIP-05 Verification section of user profile form. */
|
|
||||||
"NIP-05 Verification" = "Verifica NIP-05";
|
|
||||||
|
|
||||||
/* No search results. */
|
|
||||||
"none" = "Nessun risultato";
|
|
||||||
|
|
||||||
/* Indicates that there are no notes in the timeline to view. */
|
|
||||||
"Nothing to see here. Check back later!" = "Niente da vedere qui. Controlla dopo!";
|
|
||||||
|
|
||||||
/* Navigation title for notifications. */
|
|
||||||
"Notifications" = "Notifiche";
|
|
||||||
|
|
||||||
/* String indicating that a given timestamp just occurred */
|
|
||||||
"now" = "ora";
|
|
||||||
|
|
||||||
/* Prompt for user to enter in an account key to login. This text shows the characters the key could start with if it was a private key. */
|
|
||||||
"nsec1..." = "nsec1...";
|
|
||||||
|
|
||||||
/* Label indicating that a form input is optional. */
|
|
||||||
"optional" = "opzione1";
|
|
||||||
|
|
||||||
/* Button to pay a Lightning invoice. */
|
|
||||||
"Pay" = "Paga";
|
|
||||||
|
|
||||||
/* Navigation bar title for view to pay Lightning invoice. */
|
|
||||||
"Pay the Lightning invoice" = "Paga la fattura Lightning";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Phoenix. */
|
|
||||||
"Phoenix" = "Phoenix";
|
|
||||||
|
|
||||||
/* Button to post a note. */
|
|
||||||
"Post" = "Post";
|
|
||||||
|
|
||||||
/* Label for filter for seeing only posts (instead of posts and replies). */
|
|
||||||
"Posts" = "Post";
|
|
||||||
|
|
||||||
/* Label for filter for seeing posts and replies (instead of only posts). */
|
|
||||||
"Posts & Replies" = "Post & Risposte";
|
|
||||||
|
|
||||||
/* Heading indicating that this application keeps personally identifiable information private. A sentence describing what is done to keep data private comes after this heading. */
|
|
||||||
"Private" = "Privato";
|
|
||||||
|
|
||||||
/* Title of the secure field that holds the user's private key. */
|
|
||||||
"Private Key" = "Chiave Privata";
|
|
||||||
|
|
||||||
/* Sidebar menu label for Profile view. */
|
|
||||||
"Profile" = "Profilo1";
|
|
||||||
|
|
||||||
/* Label for Profile Picture section of user profile form. */
|
|
||||||
"Profile Picture" = "Foto Profilo";
|
|
||||||
|
|
||||||
/* Section title for the user's public account ID. */
|
|
||||||
"Public Account ID" = "ID Pubblico dell'Account";
|
|
||||||
|
|
||||||
/* Label indicating that the text is a user's public account key. */
|
|
||||||
"Public key" = "Chiave Pubblica";
|
|
||||||
|
|
||||||
/* Label indicating that the text is a user's public account key. */
|
|
||||||
"Public Key" = "Chiave Pubblica";
|
|
||||||
|
|
||||||
/* Prompt to ask user if the key they entered is a public key. */
|
|
||||||
"Public Key?" = "È la chiave pubblica?";
|
|
||||||
|
|
||||||
/* Navigation bar title for Reactions view. */
|
|
||||||
"Reactions" = "Reazioni";
|
|
||||||
|
|
||||||
/* Section title for recommend relay servers that could be added as part of configuration */
|
|
||||||
"Recommended Relays" = "Relè consigliati";
|
|
||||||
|
|
||||||
/* Text field for relay server. Used for testing purposes. */
|
|
||||||
"Relay" = "Relè";
|
|
||||||
|
|
||||||
/* Sidebar menu label for Relay servers view */
|
|
||||||
"Relays" = "Relè";
|
|
||||||
|
|
||||||
/* Button label to remove all participants from a note reply. */
|
|
||||||
"Remove all" = "Rimuovi tutto";
|
|
||||||
|
|
||||||
/* Label to indicate that the user is replying to themself. */
|
|
||||||
"Reply to self" = "Rispondi a te stesso";
|
|
||||||
|
|
||||||
/* Label to indicate that the user is replying to 2 users. */
|
|
||||||
"Replying to %@ & %@" = "Rispondi a %1$@ e %2$@";
|
|
||||||
|
|
||||||
/* Indicating that the user is replying to the following listed people. */
|
|
||||||
"Replying to:" = "Rispondi a:";
|
|
||||||
|
|
||||||
/* Button to confirm reposting a post.
|
|
||||||
Title of alert for confirming to repost a post. */
|
|
||||||
"Repost" = "Reposta";
|
|
||||||
|
|
||||||
/* Text indicating that the post was reposted (i.e. re-shared). */
|
|
||||||
"Reposted" = "Repostato";
|
|
||||||
|
|
||||||
/* Picker option for DM selector for seeing only message requests (DMs that someone else sent the user which has not been responded to yet). DM is the English abbreviation for Direct Message. */
|
|
||||||
"Requests" = "Richiesta";
|
|
||||||
|
|
||||||
/* Section title for resetting the user */
|
|
||||||
"Reset" = "Ricomincia";
|
|
||||||
|
|
||||||
/* Button to retry completing account creation after an error occurred. */
|
|
||||||
"Retry" = "Riprova";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, River */
|
|
||||||
"River" = "River";
|
|
||||||
|
|
||||||
/* Example username of Bitcoin creator(s), Satoshi Nakamoto. */
|
|
||||||
"satoshi" = "satoshi";
|
|
||||||
|
|
||||||
/* Name of Bitcoin creator(s). */
|
|
||||||
"Satoshi Nakamoto" = "Satoshi Nakamoto";
|
|
||||||
|
|
||||||
/* Button for saving profile. */
|
|
||||||
"Save" = "Salva";
|
|
||||||
|
|
||||||
/* Context menu option to save an image. */
|
|
||||||
"Save Image" = "Salva Immagine";
|
|
||||||
|
|
||||||
/* Navigation link to search hashtag. */
|
|
||||||
"Search hashtag: #%@" = "Cerca hashtag: #%@";
|
|
||||||
|
|
||||||
/* Placeholder text to prompt entry of search query. */
|
|
||||||
"Search..." = "Cerca...";
|
|
||||||
|
|
||||||
/* Section title for user's secret account login key. */
|
|
||||||
"Secret Account Login Key" = "Chiave login segreta dell'Account";
|
|
||||||
|
|
||||||
/* Title of section for selecting a Lightning wallet to pay a Lightning invoice. */
|
|
||||||
"Select a Lightning wallet" = "Seleziona un portafoglio Lightning";
|
|
||||||
|
|
||||||
/* Prompt selection of user's default wallet */
|
|
||||||
"Select default wallet" = "Seleziona un wallet predefinito";
|
|
||||||
|
|
||||||
/* Text prompt for user to send a message to the other user. */
|
|
||||||
"Send a message to start the conversation..." = "Invia un messaggio e inizia la conversazione...";
|
|
||||||
|
|
||||||
/* Navigation title for Settings view.
|
|
||||||
Sidebar menu label for accessing the app settings */
|
|
||||||
"Settings" = "Impostazioni";
|
|
||||||
|
|
||||||
/* Button to share an image. */
|
|
||||||
"Share" = "Condividi";
|
|
||||||
|
|
||||||
/* Toggle to show or hide user's secret account login key. */
|
|
||||||
"Show" = "Mostra";
|
|
||||||
|
|
||||||
/* Toggle to show or hide selection of wallet. */
|
|
||||||
"Show wallet selector" = "Mostra wallet disponibili";
|
|
||||||
|
|
||||||
/* Sidebar menu label to sign out of the account. */
|
|
||||||
"Sign out" = "Esci";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Strike. */
|
|
||||||
"Strike" = "Strike";
|
|
||||||
|
|
||||||
/* Warning that the inputted account key is a public key and the result of what happens because of it. */
|
|
||||||
"This is a public key, you will not be able to make posts or interact in any way. This is used for viewing accounts from their perspective." = "Questa è una chiave pubblica, non potrai postare o interagire in alcun modo. Puoi utilizzarla solo per vedere gli account";
|
|
||||||
|
|
||||||
/* Warning that the inputted account key for login is an old-style and asking user to verify if it is a public key. */
|
|
||||||
"This is an old-style nostr key. We're not sure if it's a pubkey or private key. Please toggle the button below if this a public key." = "Questa è una chiave di vecchio tipo. Non siamo sicuri se si tratti di una chiave pubblica o privata. Utilizza il pulsante sottostante se si tratta di una chiave pubblica.";
|
|
||||||
|
|
||||||
/* Label to describe that a public key is the user's account ID and what they can do with it. */
|
|
||||||
"This is your account ID, you can give this to your friends so that they can follow you. Click to copy." = "Questo è l'ID del tuo account. Condividilo con i tuoi amici per farti seguire. Clicca per copiare";
|
|
||||||
|
|
||||||
/* Label to describe that a private key is the user's secret account key and what they should do with it. */
|
|
||||||
"This is your secret account key. You need this to access your account. Don't share this with anyone! Save it in a password manager and keep it safe!" = "Questa è la tua chiave privata. Ti serve ad accedere al tuo account. Non condividerla con nessuno! Salvala in un gestore password e tienila al sicuro";
|
|
||||||
|
|
||||||
/* Navigation bar title for note thread.
|
|
||||||
Navigation bar title for threaded event detail view. */
|
|
||||||
"Thread" = "Thread";
|
|
||||||
|
|
||||||
/* Text box prompt to ask user to type their post. */
|
|
||||||
"Type your post here..." = "Scrivi il tuo post qui...";
|
|
||||||
|
|
||||||
/* Non-breaking space character to fill in blank space next to event action button icons. */
|
|
||||||
"u{00A0}" = "u{00A0}";
|
|
||||||
|
|
||||||
/* Button to unfollow a user. */
|
|
||||||
"Unfollow" = "Smetti di seguire";
|
|
||||||
|
|
||||||
/* Text to indicate that the button next to it is in a state that indicates that it is in the process of unfollowing a profile. */
|
|
||||||
"Unfollowing" = "Smetti di seguire";
|
|
||||||
|
|
||||||
/* Label to indicate that the user is in the process of unfollowing another user. */
|
|
||||||
"Unfollowing..." = "Togliendo il segui...";
|
|
||||||
|
|
||||||
/* Text to indicate that the button next to it is in a state that will unfollow a profile when tapped. */
|
|
||||||
"Unfollows" = "Smetti di seguire";
|
|
||||||
|
|
||||||
/* Label for Username section of user profile form.
|
|
||||||
Label to prompt username entry. */
|
|
||||||
"Username" = "Nome utente";
|
|
||||||
|
|
||||||
/* Sidebar menu label for Wallet view. */
|
|
||||||
"Wallet" = "Portafoglio";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Wallet Of Satoshi. */
|
|
||||||
"Wallet Of Satoshi" = "Wallet Of Satoshi";
|
|
||||||
|
|
||||||
/* Section title for selection of wallet. */
|
|
||||||
"Wallet Selector" = "Seleziona un portafoglio";
|
|
||||||
|
|
||||||
/* Label for Website section of user profile form. */
|
|
||||||
"Website" = "Sito web";
|
|
||||||
|
|
||||||
/* Welcoming message to the reader. The variable is 'you', the reader. */
|
|
||||||
"Welcome to the social network %@ control." = "Benvenuto nel social network %@ controlla.";
|
|
||||||
|
|
||||||
/* Text to welcome user. */
|
|
||||||
"Welcome, %@!" = "Benvenuto, %@!";
|
|
||||||
|
|
||||||
/* Placeholder example for relay server address. */
|
|
||||||
"wss://some.relay.com" = "wss://un.relè.com";
|
|
||||||
|
|
||||||
/* You, in this context, is the person who controls their own social network. You is used in the context of a larger sentence that welcomes the reader to the social network that they control themself. */
|
|
||||||
"you" = "tu";
|
|
||||||
|
|
||||||
/* Label for Your Name section of user profile form. */
|
|
||||||
"Your Name" = "Nome";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Zebedee. */
|
|
||||||
"Zebedee" = "Zebedee";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Zeus LN. */
|
|
||||||
"Zeus LN" = "Zeus LN";
|
|
||||||
|
|
||||||
@@ -1,154 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>collapsed_event_view_other_notes</key>
|
|
||||||
<dict>
|
|
||||||
<key>NOTES</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringFormatSpecTypeKey</key>
|
|
||||||
<string>NSStringPluralRuleType</string>
|
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
|
||||||
<string>d</string>
|
|
||||||
<key>one</key>
|
|
||||||
<string>%d other note</string>
|
|
||||||
<key>other</key>
|
|
||||||
<string>%d other notes</string>
|
|
||||||
</dict>
|
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
|
||||||
<string>··· %#@NOTES@ ···</string>
|
|
||||||
</dict>
|
|
||||||
<key>followers_count</key>
|
|
||||||
<dict>
|
|
||||||
<key>FOLLOWERS</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringFormatSpecTypeKey</key>
|
|
||||||
<string>NSStringPluralRuleType</string>
|
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
|
||||||
<string>d</string>
|
|
||||||
<key>one</key>
|
|
||||||
<string>Follower</string>
|
|
||||||
<key>other</key>
|
|
||||||
<string>Followers</string>
|
|
||||||
</dict>
|
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
|
||||||
<string>%#@FOLLOWERS@</string>
|
|
||||||
</dict>
|
|
||||||
<key>reactions_count</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
|
||||||
<string>%#@REACTIONS@</string>
|
|
||||||
<key>REACTIONS</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringFormatSpecTypeKey</key>
|
|
||||||
<string>NSStringPluralRuleType</string>
|
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
|
||||||
<string>d</string>
|
|
||||||
<key>one</key>
|
|
||||||
<string>Reaction</string>
|
|
||||||
<key>other</key>
|
|
||||||
<string>Reactions</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>relays_count</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
|
||||||
<string>%#@RELAYS@</string>
|
|
||||||
<key>RELAYS</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringFormatSpecTypeKey</key>
|
|
||||||
<string>NSStringPluralRuleType</string>
|
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
|
||||||
<string>d</string>
|
|
||||||
<key>one</key>
|
|
||||||
<string>Relay</string>
|
|
||||||
<key>other</key>
|
|
||||||
<string>Relays</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>replying_to_one_and_others</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
|
||||||
<string>Replying to %@%#@OTHERS@</string>
|
|
||||||
<key>OTHERS</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringFormatSpecTypeKey</key>
|
|
||||||
<string>NSStringPluralRuleType</string>
|
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
|
||||||
<string>d</string>
|
|
||||||
<key>one</key>
|
|
||||||
<string> & %d other</string>
|
|
||||||
<key>other</key>
|
|
||||||
<string> & %d others</string>
|
|
||||||
<key>zero</key>
|
|
||||||
<string></string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>replying_to_two_and_others</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
|
||||||
<string>Replying to %@, %@%#@OTHERS@</string>
|
|
||||||
<key>OTHERS</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringFormatSpecTypeKey</key>
|
|
||||||
<string>NSStringPluralRuleType</string>
|
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
|
||||||
<string>d</string>
|
|
||||||
<key>one</key>
|
|
||||||
<string> & %d other</string>
|
|
||||||
<key>other</key>
|
|
||||||
<string> & %d others</string>
|
|
||||||
<key>zero</key>
|
|
||||||
<string></string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>reposts_count</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
|
||||||
<string>%#@REPOSTS@</string>
|
|
||||||
<key>REPOSTS</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringFormatSpecTypeKey</key>
|
|
||||||
<string>NSStringPluralRuleType</string>
|
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
|
||||||
<string>d</string>
|
|
||||||
<key>one</key>
|
|
||||||
<string>Repost</string>
|
|
||||||
<key>other</key>
|
|
||||||
<string>Reposts</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>sats_count</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
|
||||||
<string>%1$#@SATS@</string>
|
|
||||||
<key>SATS</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringFormatSpecTypeKey</key>
|
|
||||||
<string>NSStringPluralRuleType</string>
|
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
|
||||||
<string>@</string>
|
|
||||||
<key>one</key>
|
|
||||||
<string>%2$@ sat</string>
|
|
||||||
<key>other</key>
|
|
||||||
<string>%2$@ sats</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>tips_count</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
|
||||||
<string>%#@TIPS@</string>
|
|
||||||
<key>TIPS</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringFormatSpecTypeKey</key>
|
|
||||||
<string>NSStringPluralRuleType</string>
|
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
|
||||||
<string>d</string>
|
|
||||||
<key>one</key>
|
|
||||||
<string>Tip</string>
|
|
||||||
<key>other</key>
|
|
||||||
<string>Tips</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
/* Bundle display name */
|
|
||||||
"CFBundleDisplayName" = "Damus";
|
|
||||||
|
|
||||||
/* Bundle name */
|
|
||||||
"CFBundleName" = "damus";
|
|
||||||
|
|
||||||
/* Privacy - Photo Library Additions Usage Description */
|
|
||||||
"NSPhotoLibraryAddUsageDescription" = "Piešķir Damus piekļuvi saviem fotoattēliem, lai varat saglabāt attēlus.";
|
|
||||||
|
|
||||||
@@ -1,503 +0,0 @@
|
|||||||
/* Blank space to separate profile picture from profile editor form. */
|
|
||||||
" " = "61b6edf1108e6f396680a33b02486a70_tr";
|
|
||||||
|
|
||||||
/* Description of how the nip05 identifier would be used for verification. */
|
|
||||||
"'%@' at '%@' will be used for verification" = "'%@' pie '%@' tiks izmantota priekš verifikācijas.";
|
|
||||||
|
|
||||||
/* Description of why the nip05 identifier is invalid. */
|
|
||||||
"'%@' is an invalid nip05 identifier. It should look like an email." = "'%@' ir nederīgs nip05 identifikators. Tam vajadzētu būt kā e-pasta adresei.";
|
|
||||||
|
|
||||||
/* Navigation bar title for view that shows who is following a user. */
|
|
||||||
"(Profile.displayName(profile: profile, pubkey: whos))'s Followers" = "(Profils.ParādāmaisVārds(profils: profils, kopAtslēga: kurš))'am Sekotāji";
|
|
||||||
|
|
||||||
/* Navigation bar title for view that shows who a user is following. */
|
|
||||||
"(who) following" = "(kurš) seko";
|
|
||||||
|
|
||||||
/* Prefix character to username. */
|
|
||||||
"@" = "@";
|
|
||||||
|
|
||||||
/* Amount of time that has passed since reply quote event occurred.
|
|
||||||
Abbreviated version of a nostr public key. */
|
|
||||||
"%@" = "%@";
|
|
||||||
|
|
||||||
/* Sentence composed of 2 variables to describe how many reposts. In source English, the first variable is the number of reposts, and the second variable is 'Repost' or 'Reposts'.
|
|
||||||
Sentence composed of 2 variables to describe how many profiles a user is following. In source English, the first variable is the number of profiles being followed, and the second variable is 'Following'. */
|
|
||||||
"%@ %@" = "%@ %@";
|
|
||||||
|
|
||||||
/* Explanation of what is done to keep personally identifiable information private. There is a heading that precedes this explanation which is a variable to this string. */
|
|
||||||
"%@. Creating an account doesn't require a phone number, email or name. Get started right away with zero friction." = "Lai izveidotu kontu, nav nepieciešams tālruņa numurs, e-pasts vai vārds. Sāciet uzreiz bez aizkaves.";
|
|
||||||
|
|
||||||
/* Explanation of what is done to keep private data encrypted. There is a heading that precedes this explanation which is a variable to this string. */
|
|
||||||
"%@. End-to-End encrypted private messaging. Keep Big Tech out of your DMs" = "%@. Pilnīga šifrēta privātā ziņojumapmaiņa. Esi privātajā iesūtnē bez lielo tekfirmu klātbūtnes.";
|
|
||||||
|
|
||||||
/* Explanation of what can be done by users to earn money. There is a heading that precedes this explanation which is a variable to this string. */
|
|
||||||
"%@. Tip your friend's posts and stack sats with Bitcoin⚡️, the native currency of the internet." = "%@. Sponsorē draugu ziņas un krājiet Satiņus ar BitMonētu⚡️, interneta digitālo valūtu.";
|
|
||||||
|
|
||||||
/* Number of reposts.
|
|
||||||
Number of profiles a user is following. */
|
|
||||||
"%lld" = "%lld";
|
|
||||||
|
|
||||||
/* Fraction of how many of the user's relay servers that are operational. */
|
|
||||||
"%lld/%lld" = "%lld/%lld";
|
|
||||||
|
|
||||||
/* Placeholder for event mention. */
|
|
||||||
"< e >" = "< e >";
|
|
||||||
|
|
||||||
/* Label to prompt for about text entry for user to describe about themself. */
|
|
||||||
"About" = "Par";
|
|
||||||
|
|
||||||
/* Label for About Me section of user profile form. */
|
|
||||||
"About Me" = "Par Mani";
|
|
||||||
|
|
||||||
/* Placeholder text for About Me description. */
|
|
||||||
"Absolute Boss" = "Pilnīgs Priekšnieks";
|
|
||||||
|
|
||||||
/* Label to indicate the public ID of the account. */
|
|
||||||
"Account ID" = "Konta ID";
|
|
||||||
|
|
||||||
/* Button to add recommended relay server.
|
|
||||||
Button to confirm adding user inputted relay. */
|
|
||||||
"Add" = "Pievieno";
|
|
||||||
|
|
||||||
/* Button label to re-add all original participants as profiles to reply to in a note */
|
|
||||||
"Add all" = "Pievienot Visus";
|
|
||||||
|
|
||||||
/* Label for section for adding a relay server. */
|
|
||||||
"Add Relay" = "Pievienot Releju";
|
|
||||||
|
|
||||||
/* Any amount of sats */
|
|
||||||
"Any" = "Jebkurš";
|
|
||||||
|
|
||||||
/* Alert message to ask if user wants to repost a post. */
|
|
||||||
"Are you sure you want to repost this?" = "Vai tiešām vēlies šo ziņu pārpublicēt?";
|
|
||||||
|
|
||||||
/* Label for Banner Image section of user profile form. */
|
|
||||||
"Banner Image" = "Karoga Attēls";
|
|
||||||
|
|
||||||
/* Reminder to user that they should save their account information. */
|
|
||||||
"Before we get started, you'll need to save your account info, otherwise you won't be able to login in the future if you ever uninstall Damus." = "Pirms sākam darbu, jums ir jāsaglabā sava konta informācija, pretējā gadījumā jūs nevarēsiet pieteikties nākamjā reizē, ja kādreiz atinstalēsiet Damus.";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Bitcoin Beach. */
|
|
||||||
"Bitcoin Beach" = "Bitmonētas Pludmale";
|
|
||||||
|
|
||||||
/* Label for Bitcoin Lightning Tips section of user profile form. */
|
|
||||||
"Bitcoin Lightning Tips" = "Bitmonētas Zibens Naudiņa";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Blixt Wallet */
|
|
||||||
"Blixt Wallet" = "Blixt Maciņš";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Blue Wallet. */
|
|
||||||
"Blue Wallet" = "Blue Maciņš";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Breez. */
|
|
||||||
"Breez" = "Breez";
|
|
||||||
|
|
||||||
/* Context menu option for broadcasting the user's note to all of the user's connected relay servers. */
|
|
||||||
"Broadcast" = "Pārraidīt";
|
|
||||||
|
|
||||||
/* Button to cancel out of posting a note.
|
|
||||||
Button to cancel out of reposting a post.
|
|
||||||
Button to cancel out of view adding user inputted relay.
|
|
||||||
Cancel out of logging out the user. */
|
|
||||||
"Cancel" = "Atcelt";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Cash App. */
|
|
||||||
"Cash App" = "Cash App";
|
|
||||||
|
|
||||||
/* Navigation bar title for Chatroom view. */
|
|
||||||
"Chat" = "Čatiņš";
|
|
||||||
|
|
||||||
/* Button for clearing cached data. */
|
|
||||||
"Clear" = "Notīrīt";
|
|
||||||
|
|
||||||
/* Section title for clearing cached data. */
|
|
||||||
"Clear Cache" = "Notīrīt Kešatmiņu";
|
|
||||||
|
|
||||||
/* Label indicating that a user's key was copied. */
|
|
||||||
"Copied" = "Nokopēts";
|
|
||||||
|
|
||||||
/* Button to copy a relay server address. */
|
|
||||||
"Copy" = "Kopēt";
|
|
||||||
|
|
||||||
/* Context menu option for copying the ID of the account that created the note. */
|
|
||||||
"Copy Account ID" = "Nokopēt konta ID";
|
|
||||||
|
|
||||||
/* Context menu option to copy an image into clipboard.
|
|
||||||
Context menu option to copy an image to clipboard. */
|
|
||||||
"Copy Image" = "Nokopēt Attēlu";
|
|
||||||
|
|
||||||
/* Context menu option to copy the URL of an image into clipboard. */
|
|
||||||
"Copy Image URL" = "Nokopēt Attēla Adresi";
|
|
||||||
|
|
||||||
/* Title of section for copying a Lightning invoice identifier. */
|
|
||||||
"Copy invoice" = "Nokopēt Pavadzīmi";
|
|
||||||
|
|
||||||
/* Context menu option for copying a user's Lightning URL. */
|
|
||||||
"Copy LNURL" = "Nokopēt Zibens Adresi";
|
|
||||||
|
|
||||||
/* Context menu option for copying the ID of the note. */
|
|
||||||
"Copy Note ID" = "Nokopēt Ziņas ID";
|
|
||||||
|
|
||||||
/* Context menu option for copying the JSON text from the note. */
|
|
||||||
"Copy Note JSON" = "Nokopēt Ziņas JSON";
|
|
||||||
|
|
||||||
/* Context menu option for copying the text from an note. */
|
|
||||||
"Copy Text" = "Nokopēt Tekstu";
|
|
||||||
|
|
||||||
/* Context menu option for copying the ID of the user who created the note. */
|
|
||||||
"Copy User ID" = "Nokopēt Lietotāja ID";
|
|
||||||
|
|
||||||
/* Button to create account. */
|
|
||||||
"Create" = "Izveidot";
|
|
||||||
|
|
||||||
/* Button to create an account. */
|
|
||||||
"Create Account" = "Izveidot Kontu";
|
|
||||||
|
|
||||||
/* Example description about Bitcoin creator(s), Satoshi Nakamoto. */
|
|
||||||
"Creator(s) of Bitcoin. Absolute legend." = "Bitmonētas Radītājs(i). Pilnīgas Leģendas.";
|
|
||||||
|
|
||||||
/* Name of the app, shown on the first screen when user is not logged in. */
|
|
||||||
"Damus" = "Damus";
|
|
||||||
|
|
||||||
/* Button to pay a Lightning invoice with the user's default Lightning wallet. */
|
|
||||||
"Default Wallet" = "Noklusējuma Maciņš";
|
|
||||||
|
|
||||||
/* Button to delete a relay server that the user connects to. */
|
|
||||||
"Delete" = "Izdzēst";
|
|
||||||
|
|
||||||
/* Button to dismiss a text field alert. */
|
|
||||||
"Dismiss" = "Atmest";
|
|
||||||
|
|
||||||
/* Label to prompt display name entry. */
|
|
||||||
"Display Name" = "Parādāmais Vārds";
|
|
||||||
|
|
||||||
/* DM selector for seeing either DMs or message requests, which are messages that have not been responded to yet. DM is the English abbreviation for Direct Message. */
|
|
||||||
"DM Type" = "Privātās Iesūtnes Tips";
|
|
||||||
|
|
||||||
/* Navigation title for DMs view, where DM is the English abbreviation for Direct Message.
|
|
||||||
Navigation title for view of DMs, where DM is an English abbreviation for Direct Message. */
|
|
||||||
"DMs" = "Privātās Ziņas";
|
|
||||||
|
|
||||||
/* Button to dismiss wallet selection view for paying Lightning invoice. */
|
|
||||||
"Done" = "Pabeigts";
|
|
||||||
|
|
||||||
/* Heading indicating that this application allows users to earn money. */
|
|
||||||
"Earn Money" = "Pelni Naudu";
|
|
||||||
|
|
||||||
/* Button to edit user's profile. */
|
|
||||||
"Edit" = "Rediģēt";
|
|
||||||
|
|
||||||
/* Text indicating that the view is used for editing which participants are replied to in a note. */
|
|
||||||
"Edit participants" = "Rediģēt dalībniekus";
|
|
||||||
|
|
||||||
/* Heading indicating that this application keeps private messaging end-to-end encrypted. */
|
|
||||||
"Encrypted" = "Šifrēts";
|
|
||||||
|
|
||||||
/* Prompt for user to enter an account key to login. */
|
|
||||||
"Enter your account key to login:" = "Ievadi sava konta atslēgu, lai pieteiktos:";
|
|
||||||
|
|
||||||
/* Error message indicating why saving keys failed. */
|
|
||||||
"Error: %@" = "Kļūda: %@";
|
|
||||||
|
|
||||||
/* Filter state for seeing either only posts, or posts & replies. */
|
|
||||||
"Filter State" = "Filtrēt Štatu";
|
|
||||||
|
|
||||||
/* Button to follow a user. */
|
|
||||||
"Follow" = "Sekot";
|
|
||||||
|
|
||||||
/* Label describing followers of a user. */
|
|
||||||
"Followers" = "Sekotāji";
|
|
||||||
|
|
||||||
/* Text to indicate that the button next to it is in a state that indicates that it is in the process of following a profile.
|
|
||||||
Part of a larger sentence to describe how many profiles a user is following. */
|
|
||||||
"Following" = "Sekoju";
|
|
||||||
|
|
||||||
/* Label to indicate that the user is in the process of following another user. */
|
|
||||||
"Following..." = "Sekoju..";
|
|
||||||
|
|
||||||
/* Text to indicate that button next to it is in a state that will follow a profile when tapped. */
|
|
||||||
"Follows" = "Seko";
|
|
||||||
|
|
||||||
/* Navigation bar title for Global view where posts from all connected relay servers appear. */
|
|
||||||
"Global" = "Globāls";
|
|
||||||
|
|
||||||
/* Navigation link to go to post referenced by hex code. */
|
|
||||||
"Goto post %@" = "Ej uz ierakstu %@";
|
|
||||||
|
|
||||||
/* Navigation link to go to profile. */
|
|
||||||
"Goto profile %@" = "Ej uz profilu %@";
|
|
||||||
|
|
||||||
/* Navigation bar title for Home view where posts and replies appear from those who the user is following. */
|
|
||||||
"Home" = "Sākums";
|
|
||||||
|
|
||||||
/* Placeholder example text for profile picture URL. */
|
|
||||||
"https://example.com/pic.jpg" = "https://paraugs.lv/att.jpg";
|
|
||||||
|
|
||||||
/* Placeholder example text for website URL for user profile. */
|
|
||||||
"https://jb55.com" = "https://jb55.com";
|
|
||||||
|
|
||||||
/* Error message indicating that an invalid account key was entered for login. */
|
|
||||||
"Invalid key" = "Nepareiza atslēga";
|
|
||||||
|
|
||||||
/* Placeholder example text for identifier used for NIP-05 verification. */
|
|
||||||
"jb55@jb55.com" = "jb55@jb55.com";
|
|
||||||
|
|
||||||
/* Moves the post button to the left side of the screen */
|
|
||||||
"Left Handed" = "Kreilis";
|
|
||||||
|
|
||||||
/* Button to complete account creation and start using the app. */
|
|
||||||
"Let's go!" = "Uz priekšu!";
|
|
||||||
|
|
||||||
/* Placeholder text for entry of Lightning Address or LNURL. */
|
|
||||||
"Lightning Address or LNURL" = "Zibens Adrese vai ZibSaite";
|
|
||||||
|
|
||||||
/* Indicates that the view is for paying a Lightning invoice. */
|
|
||||||
"Lightning Invoice" = "Zibens Pavadzīme";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, LNLink. */
|
|
||||||
"LNLink" = "ZibSaite";
|
|
||||||
|
|
||||||
/* Dropdown option label for system default for Lightning wallet. */
|
|
||||||
"Local default" = "Vietējais Noklusējums";
|
|
||||||
|
|
||||||
/* Button to log into account.
|
|
||||||
Button to log into an account. */
|
|
||||||
"Login" = "Pieteikties";
|
|
||||||
|
|
||||||
/* Alert for logging out the user.
|
|
||||||
Button for logging out the user.
|
|
||||||
Button to logout the user. */
|
|
||||||
"Logout" = "Iziet";
|
|
||||||
|
|
||||||
/* Reminder message in alert to get customer to verify that their private security account key is saved saved before logging out. */
|
|
||||||
"Make sure your nsec account key is saved before you logout or you will lose access to this account" = "Pirms iziešanas pārliecinieties, vai jūsu nsec konta atslēga ir saglabāta, pretējā gadījumā jūs zaudēsiet piekļuvi šim kontam";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Muun. */
|
|
||||||
"Muun" = "Muun";
|
|
||||||
|
|
||||||
/* Label for NIP-05 Verification section of user profile form. */
|
|
||||||
"NIP-05 Verification" = "NIP-05 Verifikācija";
|
|
||||||
|
|
||||||
/* No search results. */
|
|
||||||
"none" = "neviens";
|
|
||||||
|
|
||||||
/* Indicates that there are no notes in the timeline to view. */
|
|
||||||
"Nothing to see here. Check back later!" = "Nav ko redzēt te. Ienāc šeit vēlāk.";
|
|
||||||
|
|
||||||
/* Navigation title for notifications. */
|
|
||||||
"Notifications" = "Paziņojumi";
|
|
||||||
|
|
||||||
/* String indicating that a given timestamp just occurred */
|
|
||||||
"now" = "tagad";
|
|
||||||
|
|
||||||
/* Prompt for user to enter in an account key to login. This text shows the characters the key could start with if it was a private key. */
|
|
||||||
"nsec1..." = "nsec1...";
|
|
||||||
|
|
||||||
/* Label indicating that a form input is optional. */
|
|
||||||
"optional" = "pēc izvēles";
|
|
||||||
|
|
||||||
/* Button to pay a Lightning invoice. */
|
|
||||||
"Pay" = "Maksāt";
|
|
||||||
|
|
||||||
/* Navigation bar title for view to pay Lightning invoice. */
|
|
||||||
"Pay the Lightning invoice" = "Samaksāt Zibens Pavadzīmi";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Phoenix. */
|
|
||||||
"Phoenix" = "Phoenix";
|
|
||||||
|
|
||||||
/* Button to post a note. */
|
|
||||||
"Post" = "Publicēt";
|
|
||||||
|
|
||||||
/* Label for filter for seeing only posts (instead of posts and replies). */
|
|
||||||
"Posts" = "Ieraksti";
|
|
||||||
|
|
||||||
/* Label for filter for seeing posts and replies (instead of only posts). */
|
|
||||||
"Posts & Replies" = "Ieraksti & Atbildes";
|
|
||||||
|
|
||||||
/* Heading indicating that this application keeps personally identifiable information private. A sentence describing what is done to keep data private comes after this heading. */
|
|
||||||
"Private" = "Privāts";
|
|
||||||
|
|
||||||
/* Title of the secure field that holds the user's private key. */
|
|
||||||
"Private Key" = "Privātā Atslēga";
|
|
||||||
|
|
||||||
/* Sidebar menu label for Profile view. */
|
|
||||||
"Profile" = "Profils";
|
|
||||||
|
|
||||||
/* Label for Profile Picture section of user profile form. */
|
|
||||||
"Profile Picture" = "Profila Attēls";
|
|
||||||
|
|
||||||
/* Section title for the user's public account ID. */
|
|
||||||
"Public Account ID" = "Publiskais Konta ID";
|
|
||||||
|
|
||||||
/* Label indicating that the text is a user's public account key. */
|
|
||||||
"Public key" = "Publiskā atslēga";
|
|
||||||
|
|
||||||
/* Label indicating that the text is a user's public account key. */
|
|
||||||
"Public Key" = "Publiskā Atslēga";
|
|
||||||
|
|
||||||
/* Prompt to ask user if the key they entered is a public key. */
|
|
||||||
"Public Key?" = "Vai Publiskā Atslēga?";
|
|
||||||
|
|
||||||
/* Navigation bar title for Reactions view. */
|
|
||||||
"Reactions" = "Reakcijas";
|
|
||||||
|
|
||||||
/* Section title for recommend relay servers that could be added as part of configuration */
|
|
||||||
"Recommended Relays" = "Ieteicamie Releji";
|
|
||||||
|
|
||||||
/* Text field for relay server. Used for testing purposes. */
|
|
||||||
"Relay" = "Relejs";
|
|
||||||
|
|
||||||
/* Sidebar menu label for Relay servers view */
|
|
||||||
"Relays" = "Releji";
|
|
||||||
|
|
||||||
/* Button label to remove all participants from a note reply. */
|
|
||||||
"Remove all" = "Noņemt visu";
|
|
||||||
|
|
||||||
/* Label to indicate that the user is replying to themself. */
|
|
||||||
"Reply to self" = "Atbildēt sev";
|
|
||||||
|
|
||||||
/* Label to indicate that the user is replying to 2 users. */
|
|
||||||
"Replying to %@ & %@" = "Atbildot %1$@ & %2$@";
|
|
||||||
|
|
||||||
/* Indicating that the user is replying to the following listed people. */
|
|
||||||
"Replying to:" = "Atbildot";
|
|
||||||
|
|
||||||
/* Button to confirm reposting a post.
|
|
||||||
Title of alert for confirming to repost a post. */
|
|
||||||
"Repost" = "Pārpublicēt";
|
|
||||||
|
|
||||||
/* Text indicating that the post was reposted (i.e. re-shared). */
|
|
||||||
"Reposted" = "Pārpublicēts";
|
|
||||||
|
|
||||||
/* Picker option for DM selector for seeing only message requests (DMs that someone else sent the user which has not been responded to yet). DM is the English abbreviation for Direct Message. */
|
|
||||||
"Requests" = "Pieprasījumi";
|
|
||||||
|
|
||||||
/* Section title for resetting the user */
|
|
||||||
"Reset" = "Atiestatīt";
|
|
||||||
|
|
||||||
/* Button to retry completing account creation after an error occurred. */
|
|
||||||
"Retry" = "Mēģiniet vēlreiz";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, River */
|
|
||||||
"River" = "Plūsma";
|
|
||||||
|
|
||||||
/* Example username of Bitcoin creator(s), Satoshi Nakamoto. */
|
|
||||||
"satoshi" = "satoshi";
|
|
||||||
|
|
||||||
/* Name of Bitcoin creator(s). */
|
|
||||||
"Satoshi Nakamoto" = "Satoshi Nakamoto";
|
|
||||||
|
|
||||||
/* Button for saving profile. */
|
|
||||||
"Save" = "Saglabāt";
|
|
||||||
|
|
||||||
/* Context menu option to save an image. */
|
|
||||||
"Save Image" = "Saglabāt Attēlu";
|
|
||||||
|
|
||||||
/* Navigation link to search hashtag. */
|
|
||||||
"Search hashtag: #%@" = "Meklēt Režģbirku #%@";
|
|
||||||
|
|
||||||
/* Placeholder text to prompt entry of search query. */
|
|
||||||
"Search..." = "Meklēt...";
|
|
||||||
|
|
||||||
/* Section title for user's secret account login key. */
|
|
||||||
"Secret Account Login Key" = "Konta Slepenā Pietiekšanās Atslēga";
|
|
||||||
|
|
||||||
/* Title of section for selecting a Lightning wallet to pay a Lightning invoice. */
|
|
||||||
"Select a Lightning wallet" = "Atlasīt Zibens maciņu";
|
|
||||||
|
|
||||||
/* Prompt selection of user's default wallet */
|
|
||||||
"Select default wallet" = "Atlasīt noklusējuma maciņu";
|
|
||||||
|
|
||||||
/* Text prompt for user to send a message to the other user. */
|
|
||||||
"Send a message to start the conversation..." = "Sūti ziņu, lai sāktu sarunu...";
|
|
||||||
|
|
||||||
/* Navigation title for Settings view.
|
|
||||||
Sidebar menu label for accessing the app settings */
|
|
||||||
"Settings" = "Uzstādījumi";
|
|
||||||
|
|
||||||
/* Button to share an image. */
|
|
||||||
"Share" = "Dalīties";
|
|
||||||
|
|
||||||
/* Toggle to show or hide user's secret account login key. */
|
|
||||||
"Show" = "Parādīt";
|
|
||||||
|
|
||||||
/* Toggle to show or hide selection of wallet. */
|
|
||||||
"Show wallet selector" = "Parādīt maciņu atlasītāju";
|
|
||||||
|
|
||||||
/* Sidebar menu label to sign out of the account. */
|
|
||||||
"Sign out" = "Atteikties";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Strike. */
|
|
||||||
"Strike" = "Strike";
|
|
||||||
|
|
||||||
/* Warning that the inputted account key is a public key and the result of what happens because of it. */
|
|
||||||
"This is a public key, you will not be able to make posts or interact in any way. This is used for viewing accounts from their perspective." = "Šī ir publiskā atslēga, jūs nevarēsit rakstīt ziņas vai kādā citā veidā darboties. To izmanto, lai tikai skatītu kontus no to skatpunkta.";
|
|
||||||
|
|
||||||
/* Warning that the inputted account key for login is an old-style and asking user to verify if it is a public key. */
|
|
||||||
"This is an old-style nostr key. We're not sure if it's a pubkey or private key. Please toggle the button below if this a public key." = "Šī ir vecā parauga nostr atslēga. Mēs neesam pārliecināti, vai tā ir kopAtslēga vai slepenā atslēga. Lūdzu, pārslēdziet ar tālāk esošo pogu, ja šī ir publiskā atslēga.";
|
|
||||||
|
|
||||||
/* Label to describe that a public key is the user's account ID and what they can do with it. */
|
|
||||||
"This is your account ID, you can give this to your friends so that they can follow you. Click to copy." = "Šis ir jūsu konta ID. Varat to iedot draugiem, lai viņi varētu jums sekot. Noklikšķiniet, lai nokopētu.";
|
|
||||||
|
|
||||||
/* Label to describe that a private key is the user's secret account key and what they should do with it. */
|
|
||||||
"This is your secret account key. You need this to access your account. Don't share this with anyone! Save it in a password manager and keep it safe!" = "Šī ir jūsu konta slepenā atslēga. Tā ir nepieciešama, lai piekļūtu savam kontam. Nedalies ar to nevienam! Saglabājiet to paroļu pārvaldniekā un glabājiet to drošībā!";
|
|
||||||
|
|
||||||
/* Navigation bar title for note thread.
|
|
||||||
Navigation bar title for threaded event detail view. */
|
|
||||||
"Thread" = "Plūsma";
|
|
||||||
|
|
||||||
/* Text box prompt to ask user to type their post. */
|
|
||||||
"Type your post here..." = "Rakstiet savu ziņu šeit...";
|
|
||||||
|
|
||||||
/* Non-breaking space character to fill in blank space next to event action button icons. */
|
|
||||||
"u{00A0}" = "u{00A0}";
|
|
||||||
|
|
||||||
/* Button to unfollow a user. */
|
|
||||||
"Unfollow" = "Atsekot";
|
|
||||||
|
|
||||||
/* Text to indicate that the button next to it is in a state that indicates that it is in the process of unfollowing a profile. */
|
|
||||||
"Unfollowing" = "Atsekoju";
|
|
||||||
|
|
||||||
/* Label to indicate that the user is in the process of unfollowing another user. */
|
|
||||||
"Unfollowing..." = "Atsekoju...";
|
|
||||||
|
|
||||||
/* Text to indicate that the button next to it is in a state that will unfollow a profile when tapped. */
|
|
||||||
"Unfollows" = "Atsekos";
|
|
||||||
|
|
||||||
/* Label for Username section of user profile form.
|
|
||||||
Label to prompt username entry. */
|
|
||||||
"Username" = "Lietotājvārds";
|
|
||||||
|
|
||||||
/* Sidebar menu label for Wallet view. */
|
|
||||||
"Wallet" = "Maciņš";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Wallet Of Satoshi. */
|
|
||||||
"Wallet Of Satoshi" = "Wallet Of Satoshi";
|
|
||||||
|
|
||||||
/* Section title for selection of wallet. */
|
|
||||||
"Wallet Selector" = "Maciņu Atlasītājs";
|
|
||||||
|
|
||||||
/* Label for Website section of user profile form. */
|
|
||||||
"Website" = "Mājaslapa";
|
|
||||||
|
|
||||||
/* Welcoming message to the reader. The variable is 'you', the reader. */
|
|
||||||
"Welcome to the social network %@ control." = "Esi sveicināts sociālo tīklu %@ vadībā.";
|
|
||||||
|
|
||||||
/* Text to welcome user. */
|
|
||||||
"Welcome, %@!" = "Laipni lūgts, %@!";
|
|
||||||
|
|
||||||
/* Placeholder example for relay server address. */
|
|
||||||
"wss://some.relay.com" = "wss://cits.relejs.lv";
|
|
||||||
|
|
||||||
/* You, in this context, is the person who controls their own social network. You is used in the context of a larger sentence that welcomes the reader to the social network that they control themself. */
|
|
||||||
"you" = "jūs";
|
|
||||||
|
|
||||||
/* Label for Your Name section of user profile form. */
|
|
||||||
"Your Name" = "Tavs Vārds";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Zebedee. */
|
|
||||||
"Zebedee" = "Zebedee";
|
|
||||||
|
|
||||||
/* Dropdown option label for Lightning wallet, Zeus LN. */
|
|
||||||
"Zeus LN" = "Zeus LN";
|
|
||||||
|
|
||||||
@@ -1,168 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>collapsed_event_view_other_notes</key>
|
|
||||||
<dict>
|
|
||||||
<key>NOTES</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringFormatSpecTypeKey</key>
|
|
||||||
<string>NSStringPluralRuleType</string>
|
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
|
||||||
<string>d</string>
|
|
||||||
<key>one</key>
|
|
||||||
<string>%d cita piezīme</string>
|
|
||||||
<key>other</key>
|
|
||||||
<string>%d citas piezīmes</string>
|
|
||||||
<key>zero</key>
|
|
||||||
<string>%d other notes</string>
|
|
||||||
</dict>
|
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
|
||||||
<string>··· %#@PIEZĪMES@ ···</string>
|
|
||||||
</dict>
|
|
||||||
<key>followers_count</key>
|
|
||||||
<dict>
|
|
||||||
<key>FOLLOWERS</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringFormatSpecTypeKey</key>
|
|
||||||
<string>NSStringPluralRuleType</string>
|
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
|
||||||
<string>d</string>
|
|
||||||
<key>one</key>
|
|
||||||
<string>Sekotājs</string>
|
|
||||||
<key>other</key>
|
|
||||||
<string>Sekotāji</string>
|
|
||||||
<key>zero</key>
|
|
||||||
<string>Followers</string>
|
|
||||||
</dict>
|
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
|
||||||
<string>%#@SEKOTĀJI@</string>
|
|
||||||
</dict>
|
|
||||||
<key>reactions_count</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
|
||||||
<string>%#@REAKCIJAS@</string>
|
|
||||||
<key>REACTIONS</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringFormatSpecTypeKey</key>
|
|
||||||
<string>NSStringPluralRuleType</string>
|
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
|
||||||
<string>d</string>
|
|
||||||
<key>one</key>
|
|
||||||
<string>Reakcija</string>
|
|
||||||
<key>other</key>
|
|
||||||
<string>Reakcijas</string>
|
|
||||||
<key>zero</key>
|
|
||||||
<string>Reactions</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>relays_count</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
|
||||||
<string>%#@RELEJI@</string>
|
|
||||||
<key>RELAYS</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringFormatSpecTypeKey</key>
|
|
||||||
<string>NSStringPluralRuleType</string>
|
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
|
||||||
<string>d</string>
|
|
||||||
<key>one</key>
|
|
||||||
<string>Relejs</string>
|
|
||||||
<key>other</key>
|
|
||||||
<string>Releji</string>
|
|
||||||
<key>zero</key>
|
|
||||||
<string>Relays</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>replying_to_one_and_others</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
|
||||||
<string>Atbildot %@%#@CITIEM@</string>
|
|
||||||
<key>OTHERS</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringFormatSpecTypeKey</key>
|
|
||||||
<string>NSStringPluralRuleType</string>
|
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
|
||||||
<string>d</string>
|
|
||||||
<key>one</key>
|
|
||||||
<string> & %d cits</string>
|
|
||||||
<key>other</key>
|
|
||||||
<string> & %d citiem</string>
|
|
||||||
<key>zero</key>
|
|
||||||
<string></string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>replying_to_two_and_others</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
|
||||||
<string>Atbildot %@, %@%#@CITIEM@</string>
|
|
||||||
<key>OTHERS</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringFormatSpecTypeKey</key>
|
|
||||||
<string>NSStringPluralRuleType</string>
|
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
|
||||||
<string>d</string>
|
|
||||||
<key>one</key>
|
|
||||||
<string> & %d cits</string>
|
|
||||||
<key>other</key>
|
|
||||||
<string> & %d citiem</string>
|
|
||||||
<key>zero</key>
|
|
||||||
<string></string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>reposts_count</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
|
||||||
<string>%#@PĀRPUBLICĒJUMI@</string>
|
|
||||||
<key>REPOSTS</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringFormatSpecTypeKey</key>
|
|
||||||
<string>NSStringPluralRuleType</string>
|
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
|
||||||
<string>d</string>
|
|
||||||
<key>one</key>
|
|
||||||
<string>Pārpublicēt</string>
|
|
||||||
<key>other</key>
|
|
||||||
<string>Pārpublicējumi</string>
|
|
||||||
<key>zero</key>
|
|
||||||
<string>Reposts</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>sats_count</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
|
||||||
<string>%1$#@SATIŅI@</string>
|
|
||||||
<key>SATS</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringFormatSpecTypeKey</key>
|
|
||||||
<string>NSStringPluralRuleType</string>
|
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
|
||||||
<string>@</string>
|
|
||||||
<key>one</key>
|
|
||||||
<string>%2$@ satiņš</string>
|
|
||||||
<key>other</key>
|
|
||||||
<string>%2$@ satiņi</string>
|
|
||||||
<key>zero</key>
|
|
||||||
<string>%2$@ sats</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>tips_count</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringLocalizedFormatKey</key>
|
|
||||||
<string>%#@SPONSORĒJUMI@</string>
|
|
||||||
<key>TIPS</key>
|
|
||||||
<dict>
|
|
||||||
<key>NSStringFormatSpecTypeKey</key>
|
|
||||||
<string>NSStringPluralRuleType</string>
|
|
||||||
<key>NSStringFormatValueTypeKey</key>
|
|
||||||
<string>d</string>
|
|
||||||
<key>one</key>
|
|
||||||
<string>Sponsorējums</string>
|
|
||||||
<key>other</key>
|
|
||||||
<string>Sponsorējumi</string>
|
|
||||||
<key>zero</key>
|
|
||||||
<string>Tips</string>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
//
|
|
||||||
// ListTests.swift
|
|
||||||
// damusTests
|
|
||||||
//
|
|
||||||
// Created by William Casarin on 2023-01-25.
|
|
||||||
//
|
|
||||||
|
|
||||||
import XCTest
|
|
||||||
@testable import damus
|
|
||||||
|
|
||||||
final class ListTests: XCTestCase {
|
|
||||||
|
|
||||||
override func setUpWithError() throws {
|
|
||||||
// Put setup code here. This method is called before the invocation of each test method in the class.
|
|
||||||
}
|
|
||||||
|
|
||||||
override func tearDownWithError() throws {
|
|
||||||
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
|
||||||
}
|
|
||||||
|
|
||||||
func testCreateMuteList() throws {
|
|
||||||
let privkey = "87f313b03f2548e6eaf1c188db47078e08e894252949779b639b28db0891937a"
|
|
||||||
let pubkey = "4b0c29bf96496130c1253102f6870c0eee05db38a257315858272aa43fd19685"
|
|
||||||
let to_mute = "2fa2630fea3d2c188c49f2799fcd92f0e9879ea6a36ae60770a5428ed6c19edd"
|
|
||||||
let keypair = FullKeypair(pubkey: pubkey, privkey: privkey)
|
|
||||||
let mutelist = create_or_update_mutelist(keypair: keypair, mprev: nil, to_add: to_mute)!
|
|
||||||
|
|
||||||
XCTAssertEqual(mutelist.pubkey, pubkey)
|
|
||||||
XCTAssertEqual(mutelist.content, "")
|
|
||||||
XCTAssertEqual(mutelist.tags.count, 2)
|
|
||||||
XCTAssertEqual(mutelist.tags[0][0], "d")
|
|
||||||
XCTAssertEqual(mutelist.tags[0][1], "mute")
|
|
||||||
XCTAssertEqual(mutelist.tags[1][0], "p")
|
|
||||||
XCTAssertEqual(mutelist.tags[1][1], to_mute)
|
|
||||||
}
|
|
||||||
|
|
||||||
func testCreateAndRemoveMuteList() throws {
|
|
||||||
let privkey = "87f313b03f2548e6eaf1c188db47078e08e894252949779b639b28db0891937a"
|
|
||||||
let pubkey = "4b0c29bf96496130c1253102f6870c0eee05db38a257315858272aa43fd19685"
|
|
||||||
let to_mute = "2fa2630fea3d2c188c49f2799fcd92f0e9879ea6a36ae60770a5428ed6c19edd"
|
|
||||||
let keypair = FullKeypair(pubkey: pubkey, privkey: privkey)
|
|
||||||
let mutelist = create_or_update_mutelist(keypair: keypair, mprev: nil, to_add: to_mute)!
|
|
||||||
let new = remove_from_mutelist(keypair: keypair, prev: mutelist, to_remove: to_mute)!
|
|
||||||
|
|
||||||
XCTAssertEqual(new.pubkey, pubkey)
|
|
||||||
XCTAssertEqual(new.content, "")
|
|
||||||
XCTAssertEqual(new.tags.count, 1)
|
|
||||||
XCTAssertEqual(new.tags[0][0], "d")
|
|
||||||
XCTAssertEqual(new.tags[0][1], "mute")
|
|
||||||
}
|
|
||||||
|
|
||||||
func testAddToExistingMutelist() throws {
|
|
||||||
let privkey = "87f313b03f2548e6eaf1c188db47078e08e894252949779b639b28db0891937a"
|
|
||||||
let pubkey = "4b0c29bf96496130c1253102f6870c0eee05db38a257315858272aa43fd19685"
|
|
||||||
let to_mute = "2fa2630fea3d2c188c49f2799fcd92f0e9879ea6a36ae60770a5428ed6c19edd"
|
|
||||||
let to_mute_2 = "976b4ab41f8634119b4f21f57ef5836a4bef65d0bf72c7ced67b8b170ba4a38d"
|
|
||||||
let keypair = FullKeypair(pubkey: pubkey, privkey: privkey)
|
|
||||||
let mutelist = create_or_update_mutelist(keypair: keypair, mprev: nil, to_add: to_mute)!
|
|
||||||
let new = create_or_update_mutelist(keypair: keypair, mprev: mutelist, to_add: to_mute_2)!
|
|
||||||
|
|
||||||
XCTAssertEqual(new.pubkey, pubkey)
|
|
||||||
XCTAssertEqual(new.content, "")
|
|
||||||
XCTAssertEqual(new.tags.count, 3)
|
|
||||||
XCTAssertEqual(new.tags[0][0], "d")
|
|
||||||
XCTAssertEqual(new.tags[0][1], "mute")
|
|
||||||
XCTAssertEqual(new.tags[1][0], "p")
|
|
||||||
XCTAssertEqual(new.tags[1][1], to_mute)
|
|
||||||
XCTAssertEqual(new.tags[2][0], "p")
|
|
||||||
XCTAssertEqual(new.tags[2][1], to_mute_2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -79,15 +79,6 @@ class damusTests: XCTestCase {
|
|||||||
XCTAssertEqual(parsed[1].is_url?.absoluteString, "HTTPS://jb55.COM")
|
XCTAssertEqual(parsed[1].is_url?.absoluteString, "HTTPS://jb55.COM")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testBech32Url() {
|
|
||||||
let parsed = decode_nostr_uri("nostr:npub1xtscya34g58tk0z605fvr788k263gsu6cy9x0mhnm87echrgufzsevkk5s")
|
|
||||||
|
|
||||||
let hexpk = "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245"
|
|
||||||
let expected: NostrLink = .ref(ReferencedId(ref_id: hexpk, relay_id: nil, key: "p"))
|
|
||||||
|
|
||||||
XCTAssertEqual(parsed, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
func testParseUrl() {
|
func testParseUrl() {
|
||||||
let parsed = parse_mentions(content: "a https://jb55.com b", tags: [])
|
let parsed = parse_mentions(content: "a https://jb55.com b", tags: [])
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
#!/bin/zsh
|
|
||||||
|
|
||||||
xcodebuild -exportLocalizations -project damus.xcodeproj -localizationPath "translations" -exportLanguage en-US
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#!/bin/zsh
|
|
||||||
|
|
||||||
if [ -z "$*" ]; then
|
|
||||||
echo "Usage: ./devtools/import-translation.sh <locale_code_in_snake_case>"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
find "translations" -name "${1}.xliff" | grep -v "en-US.xliff" | xargs -I % xcodebuild -importLocalizations -project damus.xcodeproj -localizationPath %
|
|
||||||
+2
-2
@@ -3,8 +3,8 @@ git:
|
|||||||
- filter_type: file
|
- filter_type: file
|
||||||
file_format: XLIFF
|
file_format: XLIFF
|
||||||
source_language: en_US
|
source_language: en_US
|
||||||
source_file: translations/en-US.xcloc/Localized Contents/en-US.xliff
|
source_file: damus Localizations/en-US.xcloc/Localized Contents/en-US.xliff
|
||||||
translation_files_expression: translations/<lang>.xliff
|
translation_files_expression: damus Localizations/<lang>.xcloc/Localized Contents/<lang>.xliff
|
||||||
|
|
||||||
settings:
|
settings:
|
||||||
pr_branch_name: transifex/<br_unique_id>
|
pr_branch_name: transifex/<br_unique_id>
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user