Compare commits
1 Commits
tyiu/relay
...
tyiu/swap-
| Author | SHA1 | Date | |
|---|---|---|---|
|
cc95402581
|
31
.github/workflows/run-tests.yaml
vendored
@@ -1,31 +0,0 @@
|
||||
name: Run Test Suite
|
||||
run-name: Testing ${{ github.ref }} by @${{ github.actor }}
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
pull_request:
|
||||
branches:
|
||||
- "*"
|
||||
|
||||
|
||||
jobs:
|
||||
run_tests:
|
||||
runs-on: macos-12
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- xcode: "14.2"
|
||||
ios: "16.2"
|
||||
|
||||
name: Test iOS (${{ matrix.ios }})
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v1
|
||||
- name: Select Xcode
|
||||
uses: maxim-lobanov/setup-xcode@v1
|
||||
with:
|
||||
xcode-version: ${{ matrix.xcode }}
|
||||
- name: Run Tests
|
||||
run: xcodebuild test -scheme damus -project damus.xcodeproj -destination 'platform=iOS Simulator,name=iPhone 14,OS=${{ matrix.ios }}' | xcpretty && exit ${PIPESTATUS[0]}
|
||||
351
CHANGELOG.md
@@ -1,353 +1,3 @@
|
||||
## [1.0.0-13] - 2023-01-30
|
||||
|
||||
### Added
|
||||
|
||||
- LibreTranslate note translations (Terry Yiu)
|
||||
- Added support for account deletion (William Casarin)
|
||||
- User tagging and autocompletion in posts (Swift)
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Remove redundant logout button from settings (Jonathan Milligan)
|
||||
- Moved relay config to its own sidebar entry (William Casarin)
|
||||
- New stylized tabs (ericholguin)
|
||||
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix hidden profile action sheet when clicking ... (William Casarin)
|
||||
- Fixed height of DM input (Terry Yiu)
|
||||
- Fixed bug where copying pubkey from context menu only copied your own pubkey (Terry Yiu)
|
||||
|
||||
|
||||
|
||||
[1.0.0-13]: https://github.com/damus-io/damus/releases/tag/v1.0.0-13
|
||||
## [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
|
||||
|
||||
### Added
|
||||
|
||||
- Show website on profiles (William Casarin)
|
||||
- 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)
|
||||
- Add DM Message Requests (William Casarin)
|
||||
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix commands and emojis getting included in hashtags (William Casarin)
|
||||
- Fix duplicate post buttons when swiping tabs (Thomas Rademaker)
|
||||
- Show embedded note references (William Casarin)
|
||||
|
||||
|
||||
[1.0.0-8]: https://github.com/damus-io/damus/releases/tag/v1.0.0-8
|
||||
|
||||
|
||||
## [1.0.0-7] - 2023-01-20
|
||||
|
||||
### Added
|
||||
|
||||
- Drastically improved image viewer (OlegAba)
|
||||
- Added pinch to zoom on images (Swift)
|
||||
- Add Latin American Spanish translations (Nicolás Valencia)
|
||||
- Added SVG profile picture support (OlegAba)
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Makes both name and username clickable in sidebar to go to profile (Zach Hendel)
|
||||
- Clicking pfp in sidebar opens profile as well (radixrat)
|
||||
- Don't blur images if your friend boosted it (ericholguin)
|
||||
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix ... when too many likes/reposts (Joel Klabo)
|
||||
- Don't show report alert if logged in as a pubkey (Swift)
|
||||
- Fix padding issue at top of home timeline (Ben Weeks)
|
||||
- Fix absurdly large sidebar on Mac/iPad (John Bethancourt)
|
||||
- Fix tab views moving after selecting from search result (OlegAba)
|
||||
- Make follow/unfollow button a consistent width (OlegAba)
|
||||
- Don't add events to notifications from buggy relays (William Casarin)
|
||||
- Fixed some crashes with large images (OlegAba)
|
||||
- Fix DM sorting on incoming messages (William Casarin)
|
||||
- Fix text getting truncated next to link previews (William Casarin)
|
||||
|
||||
|
||||
[1.0.0-7]: https://github.com/damus-io/damus/releases/tag/v1.0.0-7
|
||||
|
||||
|
||||
## [1.0.0-6] - 2023-01-13
|
||||
|
||||
### Added
|
||||
|
||||
- Profile banner images (Jason Jōb)
|
||||
- Added Reactions View (William Casarin)
|
||||
- Left hand option for post button (Jonathan Milligan)
|
||||
- Damus icon at the top (Ben Weeks)
|
||||
- Make purple badges on profile page tappable (Joel Klabo)
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Make Shaka button purple when liked (Joel Klabo)
|
||||
- Move counts to right side like Birdsite (Joel Klabo)
|
||||
- Use custom icon for shaka button (Joel Klabo)
|
||||
- Renamed boost to repost (William Casarin)
|
||||
- Removed nip05 domain from boosts/reposts (William Casarin)
|
||||
- Make DMs only take up 80% of screen width (Jonathan Milligan)
|
||||
- Hide Recommended Relays Section if Empty (Joel Klabo)
|
||||
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed shaka moving when you press it (Joel Klabo)
|
||||
- Fixed issue with relays not keeping in sync when adding (Fredrik Olofsson)
|
||||
|
||||
|
||||
|
||||
[1.0.0-6]: https://github.com/damus-io/damus/releases/tag/v1.0.0-6
|
||||
|
||||
|
||||
## [1.0.0-5] - 2023-01-06
|
||||
|
||||
### Added
|
||||
|
||||
- Added share button to profile (William Casarin)
|
||||
- Added universal link sharing of notes (William Casarin)
|
||||
- Added clear cache button to wipe pfp/image cache (OlegAba)
|
||||
- Allow Adding Relay Without wss:// Prefix (Joel Klabo)
|
||||
- Allow Saving Images to Library (Joel Klabo)
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Added damus gradient to post button (Ben Weeks)
|
||||
- Center the Post Button (Thomas)
|
||||
- Switch yellow nip05 check to gray (William Casarin)
|
||||
- Switch from bluecheck to purplecheck (William Casarin)
|
||||
|
||||
|
||||
### Fixed
|
||||
|
||||
- Add system background color to profile pics (OlegAba)
|
||||
- High res color pubkey on profile page (William Casarin)
|
||||
- Don't spin forever if we're temporarily disconnected (William Casarin)
|
||||
- Fixed a few issues with avatars not animating (OlegAba)
|
||||
- Scroll to bottom when new DM received (Aidan O'Loan)
|
||||
- Make reply view scrollable (Joel Klabo)
|
||||
- Hide profile edit button when logged in with pubkey (Swift)
|
||||
|
||||
|
||||
[1.0.0-5]: https://github.com/damus-io/damus/releases/tag/v1.0.0-5
|
||||
|
||||
## [1.0.0-4] - 2023-01-04
|
||||
|
||||
### Added
|
||||
|
||||
- Added NIP05 Verification (William Casarin)
|
||||
- Downscale images if they are unreasonably large (OlegAba)
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Revert to old style ln/dm buttons (William Casarin)
|
||||
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix ascii shrug guy (Lionello Lunesu)
|
||||
- Fix navigation popping in threads (William Casarin)
|
||||
|
||||
|
||||
[1.0.0-4]: https://github.com/damus-io/damus/releases/tag/v1.0.0-4
|
||||
|
||||
## [1.0.0-2] - 2023-01-03
|
||||
|
||||
### Added
|
||||
|
||||
- Cache link previews (William Casarin)
|
||||
- Added brb.io to recommended relay list (William Casarin)
|
||||
- Add Blixt Wallet to Wallet Selector (Benjamin Hakes)
|
||||
- Add River Wallet to Wallet Selector (Benjamin Hakes)
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Added muted shaka images instead of thumbs up (CutClout)
|
||||
- Updated profile page look and feel (Ben Weeks)
|
||||
- Filter replies from global feed (Nitesh Balusu)
|
||||
- Show non-image links inline (William Casarin)
|
||||
- Add swipe gesture to switch between tabs (Thomas Rademaker)
|
||||
- Parse links in profiles (Lionello Lunesu) (Lio李歐)
|
||||
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix detection of email addresses in profiles (Lionello Lunesu)
|
||||
- Fix padding on search results view (OlegAba)
|
||||
- Fix home view moving after selecting from search result (OlegAba)
|
||||
- Fix bug where boost event is loaded in the thread instead of the boosted event (William Casarin)
|
||||
- Hide edit button on profile page when no private key (Swift)
|
||||
- Fixed follows and relays getting out of sync on profile pages (William Casarin)
|
||||
|
||||
|
||||
|
||||
[1.0.0-2]: https://github.com/damus-io/damus/releases/tag/v1.0.0-2
|
||||
## [1.0.0] - 2023-01-01
|
||||
|
||||
### Added
|
||||
|
||||
- Parse links in profiles (Lionello Lunesu)
|
||||
- Added Breez wallet to wallet selector (Lee Salminen)
|
||||
- Added Bitcoin Beach wallet to wallet selector (Lee Salminen)
|
||||
- Added ability to copy relay urls (Matt Ward)
|
||||
- Added option to choose default wallet (Suhail Saqan)
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Switch like from ❤️ to 🤙 (William Casarin)
|
||||
- Internationalize relative dates (Terry Yiu)
|
||||
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix but where text was not showing after invoices (William Casarin)
|
||||
- Load profiles in DMs and notifications (William Casarin)
|
||||
- Fix expanding profile picture (nosestr bug) (Joel Klabo)
|
||||
- Fix padding on threads and search results views (OlegAba)
|
||||
- Don't badge DMs if sent by you (Joel Klabo)
|
||||
- Reset relay in Add Relay view after adding (Joel Klabo)
|
||||
|
||||
|
||||
[1.0.0]: https://github.com/damus-io/damus/releases/tag/v1.0.0
|
||||
|
||||
## [0.1.8-9] - 2022-12-29
|
||||
|
||||
### Added
|
||||
|
||||
- Relay list on user profiles
|
||||
|
||||
### Changed
|
||||
|
||||
- Show recommended relays in config. Currently just a fixed set. (William Casarin)
|
||||
- Ensure contact relay list is kept in sync with internal relay pool (William Casarin)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed issue where contact list would sometimes revert to an older version (William Casarin)
|
||||
- Don't show boosts in threads (Thomas)
|
||||
|
||||
|
||||
[0.1.8-9]: https://github.com/damus-io/damus/releases/tag/v0.1.8-9
|
||||
|
||||
## [0.1.8-6] - 2022-12-28
|
||||
|
||||
### Added
|
||||
|
||||
- Lightning wallet selector (Suhail Saqan)
|
||||
- Cmd-{1,2,3,4} to switch between tabs on MacOS (Jonathan Milligan)
|
||||
- Shift-Cmd-N to create a post on MacOS (Jonathan Milligan)
|
||||
- Link Previews! (Sam DuBois)
|
||||
- Added paste and delete buttons to add relay field (Suhail Saqan)
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Blur and opaque non-friend images rather than only display the link (Sam DuBois)
|
||||
- Remove URLs in content text when image is displayed (Sam DuBois)
|
||||
- Show non-image URLs as clickable link views (Sam DuBois)
|
||||
- Adjusted Pay button on invoices. (Sam DuBois)
|
||||
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix crash with @ sign in some posts (Pablo Fernandez)
|
||||
- Swapped order of Logout and Cancel alert buttons (Terry Yiu)
|
||||
- Fixed padding issue on tabbar on some devices (Sam DuBois)
|
||||
- Fix post button moving after selecting from search result (OlegAba)
|
||||
- Don't show white background on images in dark mode (William Casarin)
|
||||
|
||||
|
||||
|
||||
[0.1.8-6]: https://github.com/damus-io/damus/releases/tag/v0.1.8-6
|
||||
## [0.1.8-5] - 2022-12-27
|
||||
|
||||
### Added
|
||||
|
||||
- Added the ability to zoom profile pic on profile page
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- Improve visual composition of threads
|
||||
- Show npub abbreviations instead of old-style hex
|
||||
- Added search placeholder and larger cancel button
|
||||
- Swap order of Boost and Cancel alert buttons
|
||||
- Rename "Copy Note" to "Copy Note JSON"
|
||||
|
||||
|
||||
### Fixed
|
||||
|
||||
- Don't cutoff gifs
|
||||
- Fixed bug where booster's names are not displayed
|
||||
|
||||
|
||||
|
||||
[0.1.8-5]: https://github.com/damus-io/damus/releases/tag/v0.1.8-5
|
||||
## [0.1.8-4] - 2022-12-26
|
||||
|
||||
### Added
|
||||
@@ -515,4 +165,3 @@
|
||||
[0.1.2]: https://github.com/damus-io/damus/releases/tag/v0.1.2
|
||||
|
||||
|
||||
|
||||
|
||||
47
README.md
@@ -1,4 +1,3 @@
|
||||
[](https://github.com/damus-io/damus/actions/workflows/run-tests.yaml)
|
||||
|
||||
# damus
|
||||
|
||||
@@ -26,7 +25,7 @@ damus implements the following [Nostr Implementation Possibilities][nips]
|
||||
## Getting Started on Damus
|
||||
|
||||
### Damus iOS
|
||||
1) Get the Damus app on the iOS App Store: https://apps.apple.com/ca/app/damus/id1628663131
|
||||
1) Get the Damus app on Testflight: https://testflight.apple.com/join/CLwjLxWl
|
||||
|
||||
#### ⚙️ Settings (gear icon, top right)
|
||||
- Relays: You can add more relays to send your notes to by tapping the "+".
|
||||
@@ -49,7 +48,7 @@ damus implements the following [Nostr Implementation Possibilities][nips]
|
||||
4. Add @ direcly followed by the pubkey (e.g., `@npub1xtscya34g58tk0z605fvr788k263gsu6cy9x0mhnm87echrgufzsevkk5s`)
|
||||
- You can also long-press a Note to grab their User ID aka pubkey or Note ID to link directly to a Note.
|
||||
- Currently you can't delete your Notes in the iOS app
|
||||
- Share images by pasting the image url which you can grab from imgbb, imgur, etc. (i.e., `https://i.ibb.co/2SHZbwm/alpha60.jpg`). Currently images only load for people you follow in the 🏠 Personal Feed. Images are not automatically loaded in 🔍 Global Feed
|
||||
- Share images by pasting the image url which you can grab from imgbb, imgur, etc. (i.e., `(https://i.ibb.co/2SHZbwm/alpha60.jpg)`). Currently images only load for people you follow in the 🏠 Personal Feed. Images are not automatically loaded in 🔍 Global Feed
|
||||
- Engaging with Notes
|
||||
- 💬 Replying to a Note: Tap the chat icon underneath the note. This will show up in the users’ notifications and in your 🏠 Personal and 🔍 Global Feeds
|
||||
- ♺ Reposts: Tap the repost icon which will show up in your 🏠 Personal and 🔍 Global Feeds
|
||||
@@ -57,8 +56,8 @@ damus implements the following [Nostr Implementation Possibilities][nips]
|
||||
- Formatting Notes (may not format as intended in other web clients)
|
||||
- Italics: 1 asterisk `*italic*`
|
||||
- Bold: 2 asterisk `**bold**`
|
||||
- Strikethrough: 1 tildes `~strikethrough~`
|
||||
- Code: 1 back-tick `` `code` ``
|
||||
- Strikethrough: 2 tildes `~~strikethrough~~`
|
||||
- Code: 1 back-tick ``code``
|
||||
|
||||
#### 💬 Encrypted DMs (chat app, bottom navigation)
|
||||
- Tap the chat icon and you'll notice there's nothing to see at first. Go to a user profile and tap the 💬 chat icon next to the follow button to begin a DM
|
||||
@@ -92,41 +91,15 @@ damus implements the following [Nostr Implementation Possibilities][nips]
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributors welcome!
|
||||
|
||||
### Code
|
||||
|
||||
[Email patches][git-send-email] to jb55@jb55.com are preferred, but I accept PRs on GitHub as well.
|
||||
Contributors welcome! [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
|
||||
|
||||
### 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
|
||||
|
||||
There may be nostr badges awarded for contributors in the future... :)
|
||||
|
||||
@@ -134,7 +107,3 @@ First contributors:
|
||||
|
||||
1. @randymcmillan
|
||||
2. @jcarucci27
|
||||
|
||||
### git log bot
|
||||
|
||||
npub1fjtdwclt9lspjy8huu3qklr7eklp5uq90u6yh8mec290pqxraccqlufnas
|
||||
|
||||
@@ -151,7 +151,7 @@ static bool from_numbers(u64 *res,
|
||||
return false;
|
||||
|
||||
if (!from_number(&p1, s1, len1, tens_factor)
|
||||
|| !from_number(&p2, s2, len2, tens_factor - (int)len2))
|
||||
|| !from_number(&p2, s2, len2, tens_factor - len2))
|
||||
return false;
|
||||
|
||||
if (add_overflows_u64(p1, p2))
|
||||
@@ -453,7 +453,7 @@ bool amount_msat_to_u32(struct amount_msat msat, u32 *millisatoshis)
|
||||
{
|
||||
if (amount_msat_greater_eq(msat, AMOUNT_MSAT(0x100000000)))
|
||||
return false;
|
||||
*millisatoshis = (u32)msat.millisatoshis;
|
||||
*millisatoshis = msat.millisatoshis;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -297,7 +297,7 @@ static char *decode_c(struct bolt11 *b11,
|
||||
if (!pull_uint(hu5, data, data_len, &c, data_length * 5))
|
||||
return tal_fmt(b11, "c: length %zu chars is excessive",
|
||||
*data_len);
|
||||
b11->min_final_cltv_expiry = (u32)c;
|
||||
b11->min_final_cltv_expiry = c;
|
||||
/* Can overflow, since c is 64 bits but value must be < 32 bits */
|
||||
if (b11->min_final_cltv_expiry != c)
|
||||
return tal_fmt(b11, "c: %"PRIu64" is too large", c);
|
||||
|
||||
@@ -22,10 +22,6 @@ static inline int is_whitespace(char c) {
|
||||
return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r';
|
||||
}
|
||||
|
||||
static inline int is_boundary(char c) {
|
||||
return !isalnum(c);
|
||||
}
|
||||
|
||||
static void make_cursor(struct cursor *c, const u8 *content, size_t len)
|
||||
{
|
||||
c->start = content;
|
||||
@@ -33,33 +29,16 @@ static void make_cursor(struct cursor *c, const u8 *content, size_t len)
|
||||
c->p = content;
|
||||
}
|
||||
|
||||
static int consume_until_boundary(struct cursor *cur) {
|
||||
char c;
|
||||
|
||||
while (cur->p < cur->end) {
|
||||
c = *cur->p;
|
||||
|
||||
if (is_boundary(c))
|
||||
return 1;
|
||||
|
||||
cur->p++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int consume_until_whitespace(struct cursor *cur, int or_end) {
|
||||
char c;
|
||||
bool consumedAtLeastOne = false;
|
||||
|
||||
while (cur->p < cur->end) {
|
||||
c = *cur->p;
|
||||
|
||||
if (is_whitespace(c) && consumedAtLeastOne)
|
||||
if (is_whitespace(c))
|
||||
return 1;
|
||||
|
||||
cur->p++;
|
||||
consumedAtLeastOne = true;
|
||||
}
|
||||
|
||||
return or_end;
|
||||
@@ -166,7 +145,7 @@ static int parse_hashtag(struct cursor *cur, struct block *block) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
consume_until_boundary(cur);
|
||||
consume_until_whitespace(cur, 1);
|
||||
|
||||
block->type = BLOCK_HASHTAG;
|
||||
block->block.str.start = (const char*)(start + 1);
|
||||
@@ -262,7 +241,7 @@ static int parse_invoice(struct cursor *cur, struct block *block) {
|
||||
block->block.invoice.invstr.end = (const char*)end;
|
||||
block->block.invoice.bolt11 = bolt11;
|
||||
|
||||
cur->p = end;
|
||||
cur->p += end - start;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ void hash_u5(struct hash_u5 *hu5, const u8 *u5, size_t len)
|
||||
u5++;
|
||||
|
||||
if (hu5->num_bits >= 32) {
|
||||
be32 be32 = cpu_to_be32((u32)(hu5->buf >> (hu5->num_bits-32)));
|
||||
be32 be32 = cpu_to_be32(hu5->buf >> (hu5->num_bits-32));
|
||||
sha256_update(&hu5->hash, &be32, sizeof(be32));
|
||||
hu5->num_bits -= 32;
|
||||
}
|
||||
@@ -40,7 +40,7 @@ void hash_u5(struct hash_u5 *hu5, const u8 *u5, size_t len)
|
||||
void hash_u5_done(struct hash_u5 *hu5, struct sha256 *res)
|
||||
{
|
||||
if (hu5->num_bits) {
|
||||
be32 be32 = cpu_to_be32((u32)(hu5->buf << (32 - hu5->num_bits)));
|
||||
be32 be32 = cpu_to_be32(hu5->buf << (32 - hu5->num_bits));
|
||||
|
||||
sha256_update(&hu5->hash, &be32, (hu5->num_bits + 7) / 8);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ static inline bool assign_overflow_u16(u16 *dst, uint64_t v)
|
||||
|
||||
static inline bool assign_overflow_u32(u32 *dst, uint64_t v)
|
||||
{
|
||||
*dst = (u32)v;
|
||||
*dst = v;
|
||||
return *dst == v;
|
||||
}
|
||||
#endif /* LIGHTNING_COMMON_OVERFLOWS_H */
|
||||
|
||||
@@ -7,18 +7,9 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
3165648B295B70D500C64604 /* LinkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3165648A295B70D500C64604 /* LinkView.swift */; };
|
||||
3169CAE6294E69C000EE4006 /* EmptyTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3169CAE5294E69C000EE4006 /* EmptyTimelineView.swift */; };
|
||||
3169CAED294FCCFC00EE4006 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3169CAEC294FCCFC00EE4006 /* Constants.swift */; };
|
||||
31D2E847295218AF006D67F8 /* Shimmer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31D2E846295218AF006D67F8 /* Shimmer.swift */; };
|
||||
3A4325A82961E11400BFCD9D /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 3A4325AA2961E11400BFCD9D /* Localizable.stringsdict */; };
|
||||
3AA247FD297E3CFF0090C62D /* RepostsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA247FC297E3CFF0090C62D /* RepostsModel.swift */; };
|
||||
3AA247FF297E3D900090C62D /* RepostsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA247FE297E3D900090C62D /* RepostsView.swift */; };
|
||||
3AA24802297E3DC20090C62D /* RepostView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA24801297E3DC20090C62D /* RepostView.swift */; };
|
||||
3ACB685C297633BC00C46468 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3ACB685A297633BC00C46468 /* InfoPlist.strings */; };
|
||||
3ACB685F297633BC00C46468 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3ACB685D297633BC00C46468 /* Localizable.strings */; };
|
||||
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 */; };
|
||||
4C06670428FC7EC500038D2A /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 4C06670328FC7EC500038D2A /* Kingfisher */; };
|
||||
4C06670628FCB08600038D2A /* ImageCarousel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C06670528FCB08600038D2A /* ImageCarousel.swift */; };
|
||||
@@ -28,6 +19,7 @@
|
||||
4C0A3F8F280F640A000448DE /* ThreadModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C0A3F8E280F640A000448DE /* ThreadModel.swift */; };
|
||||
4C0A3F91280F6528000448DE /* ChatView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C0A3F90280F6528000448DE /* ChatView.swift */; };
|
||||
4C0A3F93280F66F5000448DE /* ReplyMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C0A3F92280F66F5000448DE /* ReplyMap.swift */; };
|
||||
4C0A3F95280F6C78000448DE /* ReplyQuoteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C0A3F94280F6C78000448DE /* ReplyQuoteView.swift */; };
|
||||
4C0A3F97280F8E02000448DE /* ThreadView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C0A3F96280F8E02000448DE /* ThreadView.swift */; };
|
||||
4C216F32286E388800040376 /* DMChatView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C216F31286E388800040376 /* DMChatView.swift */; };
|
||||
4C216F34286F5ACD00040376 /* DMView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C216F33286F5ACD00040376 /* DMView.swift */; };
|
||||
@@ -55,8 +47,6 @@
|
||||
4C363AA228296A7E006E126D /* SearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C363AA128296A7E006E126D /* SearchView.swift */; };
|
||||
4C363AA428296DEE006E126D /* SearchModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C363AA328296DEE006E126D /* SearchModel.swift */; };
|
||||
4C363AA828297703006E126D /* InsertSort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C363AA728297703006E126D /* InsertSort.swift */; };
|
||||
4C3A1D332960DB0500558C0F /* Markdown.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3A1D322960DB0500558C0F /* Markdown.swift */; };
|
||||
4C3A1D3729637E0500558C0F /* PreviewCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3A1D3629637E0500558C0F /* PreviewCache.swift */; };
|
||||
4C3AC79B28306D7B00E1F516 /* Contacts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3AC79A28306D7B00E1F516 /* Contacts.swift */; };
|
||||
4C3AC79D2833036D00E1F516 /* FollowingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3AC79C2833036D00E1F516 /* FollowingView.swift */; };
|
||||
4C3AC79F2833115300E1F516 /* FollowButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3AC79E2833115300E1F516 /* FollowButtonView.swift */; };
|
||||
@@ -69,8 +59,6 @@
|
||||
4C3BEFDA281DCA1400B3DE84 /* LikeCounter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3BEFD9281DCA1400B3DE84 /* LikeCounter.swift */; };
|
||||
4C3BEFDC281DCE6100B3DE84 /* Liked.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3BEFDB281DCE6100B3DE84 /* Liked.swift */; };
|
||||
4C3BEFE0281DE1ED00B3DE84 /* DamusState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3BEFDF281DE1ED00B3DE84 /* DamusState.swift */; };
|
||||
4C3D52B6298DB4E6001C5831 /* ZapEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3D52B5298DB4E6001C5831 /* ZapEvent.swift */; };
|
||||
4C3D52B8298DB5C6001C5831 /* TextEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3D52B7298DB5C6001C5831 /* TextEvent.swift */; };
|
||||
4C3EA63D28FF52D600C48A62 /* bolt11.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C3EA63C28FF52D600C48A62 /* bolt11.c */; };
|
||||
4C3EA64128FF553900C48A62 /* hash_u5.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C3EA64028FF553900C48A62 /* hash_u5.c */; };
|
||||
4C3EA64428FF558100C48A62 /* sha256.c in Sources */ = {isa = PBXBuildFile; fileRef = 4C3EA64328FF558100C48A62 /* sha256.c */; };
|
||||
@@ -87,7 +75,6 @@
|
||||
4C3EA67B28FF7B3900C48A62 /* InvoiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3EA67A28FF7B3900C48A62 /* InvoiceTests.swift */; };
|
||||
4C3EA67D28FFBBA300C48A62 /* InvoicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3EA67C28FFBBA200C48A62 /* InvoicesView.swift */; };
|
||||
4C3EA67F28FFC01D00C48A62 /* InvoiceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3EA67E28FFC01D00C48A62 /* InvoiceView.swift */; };
|
||||
4C42812C298C848200DBF26F /* TranslateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C42812B298C848200DBF26F /* TranslateView.swift */; };
|
||||
4C477C9E282C3A4800033AA3 /* TipCounter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C477C9D282C3A4800033AA3 /* TipCounter.swift */; };
|
||||
4C5C7E68284ED36500A22DF5 /* SearchHomeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C5C7E67284ED36500A22DF5 /* SearchHomeModel.swift */; };
|
||||
4C5C7E6A284EDE2E00A22DF5 /* SearchResultsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C5C7E69284EDE2E00A22DF5 /* SearchResultsView.swift */; };
|
||||
@@ -119,36 +106,8 @@
|
||||
4C987B57283FD07F0042CE38 /* FollowersModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C987B56283FD07F0042CE38 /* FollowersModel.swift */; };
|
||||
4C99737B28C92A9200E53835 /* ChatroomMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C99737A28C92A9200E53835 /* ChatroomMetadata.swift */; };
|
||||
4CA2EFA0280E37AC0044ACD8 /* TimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CA2EF9F280E37AC0044ACD8 /* TimelineView.swift */; };
|
||||
4CAAD8AD298851D000060CEA /* AccountDeletion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CAAD8AC298851D000060CEA /* AccountDeletion.swift */; };
|
||||
4CAAD8B029888AD200060CEA /* RelayConfigView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CAAD8AF29888AD200060CEA /* RelayConfigView.swift */; };
|
||||
4CACA9D5280C31E100D9BBE8 /* ReplyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CACA9D4280C31E100D9BBE8 /* ReplyView.swift */; };
|
||||
4CACA9DC280C38C000D9BBE8 /* Profiles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CACA9DB280C38C000D9BBE8 /* Profiles.swift */; };
|
||||
4CB55EF3295E5D59007FD187 /* RecommendedRelayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB55EF2295E5D59007FD187 /* RecommendedRelayView.swift */; };
|
||||
4CB55EF5295E679D007FD187 /* UserRelaysView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB55EF4295E679D007FD187 /* UserRelaysView.swift */; };
|
||||
4CB8838629656C8B00DC99E7 /* NIP05.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB8838529656C8B00DC99E7 /* NIP05.swift */; };
|
||||
4CB88389296AF99A00DC99E7 /* EventDetailBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB88388296AF99A00DC99E7 /* EventDetailBar.swift */; };
|
||||
4CB8838B296F6E1E00DC99E7 /* NIP05Badge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB8838A296F6E1E00DC99E7 /* NIP05Badge.swift */; };
|
||||
4CB8838D296F710400DC99E7 /* Reposted.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB8838C296F710400DC99E7 /* Reposted.swift */; };
|
||||
4CB8838F296F781C00DC99E7 /* ReactionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB8838E296F781C00DC99E7 /* ReactionsView.swift */; };
|
||||
4CB88393296F798300DC99E7 /* ReactionsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB88392296F798300DC99E7 /* ReactionsModel.swift */; };
|
||||
4CB88396296F7F8B00DC99E7 /* ReactionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB88395296F7F8B00DC99E7 /* ReactionView.swift */; };
|
||||
4CB8839A297322D200DC99E7 /* DMTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB88399297322D200DC99E7 /* DMTests.swift */; };
|
||||
4CB883A62975F83C00DC99E7 /* LNUrlPayRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB883A52975F83C00DC99E7 /* LNUrlPayRequest.swift */; };
|
||||
4CB883A82975FC1800DC99E7 /* Zaps.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB883A72975FC1800DC99E7 /* Zaps.swift */; };
|
||||
4CB883AA297612FF00DC99E7 /* ZapTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB883A9297612FF00DC99E7 /* ZapTests.swift */; };
|
||||
4CB883AE2976FA9300DC99E7 /* FormatTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB883AD2976FA9300DC99E7 /* FormatTests.swift */; };
|
||||
4CB883B0297705DD00DC99E7 /* ZapButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB883AF297705DD00DC99E7 /* ZapButton.swift */; };
|
||||
4CB883B6297730E400DC99E7 /* LNUrls.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CB883B5297730E400DC99E7 /* LNUrls.swift */; };
|
||||
4CBCA930297DB57F00EC6B2F /* WebsiteLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CBCA92F297DB57F00EC6B2F /* WebsiteLink.swift */; };
|
||||
4CC7AAE7297EFA7B00430951 /* Zap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7AAE6297EFA7B00430951 /* Zap.swift */; };
|
||||
4CC7AAEB297F0AEC00430951 /* BuilderEventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7AAEA297F0AEC00430951 /* BuilderEventView.swift */; };
|
||||
4CC7AAED297F0B9E00430951 /* Highlight.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7AAEC297F0B9E00430951 /* Highlight.swift */; };
|
||||
4CC7AAF0297F11C700430951 /* SelectedEventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7AAEF297F11C700430951 /* SelectedEventView.swift */; };
|
||||
4CC7AAF2297F129C00430951 /* EmbeddedEventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7AAF1297F129C00430951 /* EmbeddedEventView.swift */; };
|
||||
4CC7AAF4297F18B400430951 /* ReplyDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7AAF3297F18B400430951 /* ReplyDescription.swift */; };
|
||||
4CC7AAF6297F1A6A00430951 /* EventBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7AAF5297F1A6A00430951 /* EventBody.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 */; };
|
||||
4CE4F8CD281352B30009DFBB /* Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE4F8CC281352B30009DFBB /* Notifications.swift */; };
|
||||
4CE4F9DE2852768D00C00DD9 /* ConfigView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE4F9DD2852768D00C00DD9 /* ConfigView.swift */; };
|
||||
@@ -170,38 +129,8 @@
|
||||
4CEE2AF7280B2DEA00AB5EEF /* ProfileName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CEE2AF6280B2DEA00AB5EEF /* ProfileName.swift */; };
|
||||
4CEE2AF9280B2EAC00AB5EEF /* PowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CEE2AF8280B2EAC00AB5EEF /* PowView.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 */; };
|
||||
5C513FBA297F72980072348F /* CustomPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C513FB9297F72980072348F /* CustomPicker.swift */; };
|
||||
5C513FCC2984ACA60072348F /* QRCodeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C513FCB2984ACA60072348F /* QRCodeView.swift */; };
|
||||
6439E014296790CF0020672B /* ProfileZoomView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6439E013296790CF0020672B /* ProfileZoomView.swift */; };
|
||||
647D9A8D2968520300A295DE /* SideMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 647D9A8C2968520300A295DE /* SideMenuView.swift */; };
|
||||
64FBD06F296255C400D9D3B2 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64FBD06E296255C400D9D3B2 /* Theme.swift */; };
|
||||
6C7DE41F2955169800E66263 /* Vault in Frameworks */ = {isa = PBXBuildFile; productRef = 6C7DE41E2955169800E66263 /* Vault */; };
|
||||
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 */; };
|
||||
BA693074295D649800ADDB87 /* UserSettingsStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA693073295D649800ADDB87 /* UserSettingsStore.swift */; };
|
||||
BAB68BED29543FA3007BA466 /* SelectWalletView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAB68BEC29543FA3007BA466 /* SelectWalletView.swift */; };
|
||||
DD597CBD2963D85A00C64D32 /* MarkdownTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD597CBC2963D85A00C64D32 /* MarkdownTests.swift */; };
|
||||
E990020F2955F837003BBC5A /* EditMetadataView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E990020E2955F837003BBC5A /* EditMetadataView.swift */; };
|
||||
E9E4ED0B295867B900DD7078 /* ThreadV2View.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E4ED0A295867B900DD7078 /* ThreadV2View.swift */; };
|
||||
F7F0BA25297892BD009531F3 /* SwipeToDismiss.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F0BA24297892BD009531F3 /* SwipeToDismiss.swift */; };
|
||||
F7F0BA272978E54D009531F3 /* ParicipantsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7F0BA262978E54D009531F3 /* ParicipantsView.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@@ -222,49 +151,9 @@
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
3165648A295B70D500C64604 /* LinkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkView.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; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
3A4F3322297CCFEE004B5F72 /* fr-FR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "fr-FR"; path = "fr-FR.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
|
||||
3A5C4575296A879E0032D398 /* es-419 */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "es-419"; path = "es-419.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
|
||||
3A5CAE1D298DC0DB00B5334F /* zh-CN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-CN"; path = "zh-CN.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
||||
3A5CAE1E298DC0DB00B5334F /* zh-CN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-CN"; path = "zh-CN.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||
3A5CAE1F298DC0DB00B5334F /* zh-CN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "zh-CN"; path = "zh-CN.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>"; };
|
||||
3A93342929884CA600D6A8F3 /* pl-PL */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pl-PL"; path = "pl-PL.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
||||
3A93342A29884CA600D6A8F3 /* pl-PL */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pl-PL"; path = "pl-PL.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||
3A93342B29884CA600D6A8F3 /* pl-PL */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "pl-PL"; path = "pl-PL.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
|
||||
3A96D41A298DA94500388A2A /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
3A96D41B298DA94500388A2A /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
3A96D41C298DA94500388A2A /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = nl; path = nl.lproj/Localizable.stringsdict; 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>"; };
|
||||
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>"; };
|
||||
3AC524EE298C000B00693EBF /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
3AC524EF298C000B00693EBF /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
3AC524F0298C000B00693EBF /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ar; path = ar.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>"; };
|
||||
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>"; };
|
||||
3AE45AF5297BB2E700C1D842 /* LibreTranslateServer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibreTranslateServer.swift; 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>"; };
|
||||
3AEB8005297CCEA900713A25 /* tr-TR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "tr-TR"; path = "tr-TR.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
|
||||
3AF6336829884C6B0005672A /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
||||
3AF6336929884C6B0005672A /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||
3AF6336A29884C6B0005672A /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "pt-PT"; path = "pt-PT.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
|
||||
4C06670028FC7C5900038D2A /* RelayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayView.swift; sourceTree = "<group>"; };
|
||||
4C06670528FCB08600038D2A /* ImageCarousel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCarousel.swift; sourceTree = "<group>"; };
|
||||
4C06670828FDE64700038D2A /* damus-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "damus-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
@@ -276,6 +165,7 @@
|
||||
4C0A3F8E280F640A000448DE /* ThreadModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadModel.swift; sourceTree = "<group>"; };
|
||||
4C0A3F90280F6528000448DE /* ChatView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatView.swift; sourceTree = "<group>"; };
|
||||
4C0A3F92280F66F5000448DE /* ReplyMap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReplyMap.swift; sourceTree = "<group>"; };
|
||||
4C0A3F94280F6C78000448DE /* ReplyQuoteView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReplyQuoteView.swift; sourceTree = "<group>"; };
|
||||
4C0A3F96280F8E02000448DE /* ThreadView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadView.swift; sourceTree = "<group>"; };
|
||||
4C216F31286E388800040376 /* DMChatView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DMChatView.swift; sourceTree = "<group>"; };
|
||||
4C216F33286F5ACD00040376 /* DMView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DMView.swift; sourceTree = "<group>"; };
|
||||
@@ -303,8 +193,6 @@
|
||||
4C363AA128296A7E006E126D /* SearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchView.swift; sourceTree = "<group>"; };
|
||||
4C363AA328296DEE006E126D /* SearchModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchModel.swift; sourceTree = "<group>"; };
|
||||
4C363AA728297703006E126D /* InsertSort.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InsertSort.swift; sourceTree = "<group>"; };
|
||||
4C3A1D322960DB0500558C0F /* Markdown.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Markdown.swift; sourceTree = "<group>"; };
|
||||
4C3A1D3629637E0500558C0F /* PreviewCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreviewCache.swift; sourceTree = "<group>"; };
|
||||
4C3AC79A28306D7B00E1F516 /* Contacts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Contacts.swift; sourceTree = "<group>"; };
|
||||
4C3AC79C2833036D00E1F516 /* FollowingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowingView.swift; sourceTree = "<group>"; };
|
||||
4C3AC79E2833115300E1F516 /* FollowButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowButtonView.swift; sourceTree = "<group>"; };
|
||||
@@ -317,8 +205,6 @@
|
||||
4C3BEFD9281DCA1400B3DE84 /* LikeCounter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LikeCounter.swift; sourceTree = "<group>"; };
|
||||
4C3BEFDB281DCE6100B3DE84 /* Liked.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Liked.swift; sourceTree = "<group>"; };
|
||||
4C3BEFDF281DE1ED00B3DE84 /* DamusState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DamusState.swift; sourceTree = "<group>"; };
|
||||
4C3D52B5298DB4E6001C5831 /* ZapEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZapEvent.swift; sourceTree = "<group>"; };
|
||||
4C3D52B7298DB5C6001C5831 /* TextEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextEvent.swift; sourceTree = "<group>"; };
|
||||
4C3EA63B28FF52D600C48A62 /* bolt11.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bolt11.h; sourceTree = "<group>"; };
|
||||
4C3EA63C28FF52D600C48A62 /* bolt11.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = bolt11.c; sourceTree = "<group>"; };
|
||||
4C3EA63E28FF54BD00C48A62 /* short_types.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = short_types.h; sourceTree = "<group>"; };
|
||||
@@ -364,7 +250,6 @@
|
||||
4C3EA67A28FF7B3900C48A62 /* InvoiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvoiceTests.swift; sourceTree = "<group>"; };
|
||||
4C3EA67C28FFBBA200C48A62 /* InvoicesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvoicesView.swift; sourceTree = "<group>"; };
|
||||
4C3EA67E28FFC01D00C48A62 /* InvoiceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvoiceView.swift; sourceTree = "<group>"; };
|
||||
4C42812B298C848200DBF26F /* TranslateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslateView.swift; sourceTree = "<group>"; };
|
||||
4C477C9D282C3A4800033AA3 /* TipCounter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TipCounter.swift; sourceTree = "<group>"; };
|
||||
4C4A3A5A288A1B2200453788 /* damus.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = damus.entitlements; sourceTree = "<group>"; };
|
||||
4C5C7E67284ED36500A22DF5 /* SearchHomeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchHomeModel.swift; sourceTree = "<group>"; };
|
||||
@@ -397,36 +282,8 @@
|
||||
4C987B56283FD07F0042CE38 /* FollowersModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowersModel.swift; sourceTree = "<group>"; };
|
||||
4C99737A28C92A9200E53835 /* ChatroomMetadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatroomMetadata.swift; sourceTree = "<group>"; };
|
||||
4CA2EF9F280E37AC0044ACD8 /* TimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineView.swift; sourceTree = "<group>"; };
|
||||
4CAAD8AC298851D000060CEA /* AccountDeletion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountDeletion.swift; sourceTree = "<group>"; };
|
||||
4CAAD8AF29888AD200060CEA /* RelayConfigView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayConfigView.swift; sourceTree = "<group>"; };
|
||||
4CACA9D4280C31E100D9BBE8 /* ReplyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReplyView.swift; sourceTree = "<group>"; };
|
||||
4CACA9DB280C38C000D9BBE8 /* Profiles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Profiles.swift; sourceTree = "<group>"; };
|
||||
4CB55EF2295E5D59007FD187 /* RecommendedRelayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecommendedRelayView.swift; sourceTree = "<group>"; };
|
||||
4CB55EF4295E679D007FD187 /* UserRelaysView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserRelaysView.swift; sourceTree = "<group>"; };
|
||||
4CB8838529656C8B00DC99E7 /* NIP05.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NIP05.swift; sourceTree = "<group>"; };
|
||||
4CB88388296AF99A00DC99E7 /* EventDetailBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventDetailBar.swift; sourceTree = "<group>"; };
|
||||
4CB8838A296F6E1E00DC99E7 /* NIP05Badge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NIP05Badge.swift; sourceTree = "<group>"; };
|
||||
4CB8838C296F710400DC99E7 /* Reposted.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Reposted.swift; sourceTree = "<group>"; };
|
||||
4CB8838E296F781C00DC99E7 /* ReactionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactionsView.swift; sourceTree = "<group>"; };
|
||||
4CB88392296F798300DC99E7 /* ReactionsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactionsModel.swift; sourceTree = "<group>"; };
|
||||
4CB88395296F7F8B00DC99E7 /* ReactionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactionView.swift; sourceTree = "<group>"; };
|
||||
4CB88399297322D200DC99E7 /* DMTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DMTests.swift; sourceTree = "<group>"; };
|
||||
4CB883A52975F83C00DC99E7 /* LNUrlPayRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LNUrlPayRequest.swift; sourceTree = "<group>"; };
|
||||
4CB883A72975FC1800DC99E7 /* Zaps.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Zaps.swift; sourceTree = "<group>"; };
|
||||
4CB883A9297612FF00DC99E7 /* ZapTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZapTests.swift; sourceTree = "<group>"; };
|
||||
4CB883AD2976FA9300DC99E7 /* FormatTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormatTests.swift; sourceTree = "<group>"; };
|
||||
4CB883AF297705DD00DC99E7 /* ZapButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZapButton.swift; sourceTree = "<group>"; };
|
||||
4CB883B5297730E400DC99E7 /* LNUrls.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LNUrls.swift; sourceTree = "<group>"; };
|
||||
4CBCA92F297DB57F00EC6B2F /* WebsiteLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebsiteLink.swift; sourceTree = "<group>"; };
|
||||
4CC7AAE6297EFA7B00430951 /* Zap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Zap.swift; sourceTree = "<group>"; };
|
||||
4CC7AAEA297F0AEC00430951 /* BuilderEventView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuilderEventView.swift; sourceTree = "<group>"; };
|
||||
4CC7AAEC297F0B9E00430951 /* Highlight.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Highlight.swift; sourceTree = "<group>"; };
|
||||
4CC7AAEF297F11C700430951 /* SelectedEventView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectedEventView.swift; sourceTree = "<group>"; };
|
||||
4CC7AAF1297F129C00430951 /* EmbeddedEventView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmbeddedEventView.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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@@ -451,37 +308,7 @@
|
||||
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>"; };
|
||||
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>"; };
|
||||
5C513FB9297F72980072348F /* CustomPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomPicker.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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
DD597CBC2963D85A00C64D32 /* MarkdownTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarkdownTests.swift; sourceTree = "<group>"; };
|
||||
E990020E2955F837003BBC5A /* EditMetadataView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditMetadataView.swift; sourceTree = "<group>"; };
|
||||
E9E4ED0A295867B900DD7078 /* ThreadV2View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadV2View.swift; sourceTree = "<group>"; };
|
||||
F7F0BA24297892BD009531F3 /* SwipeToDismiss.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwipeToDismiss.swift; sourceTree = "<group>"; };
|
||||
F7F0BA262978E54D009531F3 /* ParicipantsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParicipantsView.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@@ -521,14 +348,6 @@
|
||||
path = "Empty Views";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
3AA24800297E3DAE0090C62D /* Reposts */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3AA24801297E3DC20090C62D /* RepostView.swift */,
|
||||
);
|
||||
path = Reposts;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4C06670728FDE62900038D2A /* damus-c */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -586,7 +405,6 @@
|
||||
4C0A3F8D280F63FF000448DE /* Models */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3AA247FC297E3CFF0090C62D /* RepostsModel.swift */,
|
||||
4C0A3F8E280F640A000448DE /* ThreadModel.swift */,
|
||||
4C0A3F92280F66F5000448DE /* ReplyMap.swift */,
|
||||
4C3BEFD12819DB9B00B3DE84 /* ProfileModel.swift */,
|
||||
@@ -614,13 +432,6 @@
|
||||
4C64987D286D082C00EAE2B3 /* DirectMessagesModel.swift */,
|
||||
4C216F372871EDE300040376 /* DirectMessageModel.swift */,
|
||||
4C99737A28C92A9200E53835 /* ChatroomMetadata.swift */,
|
||||
BA693073295D649800ADDB87 /* UserSettingsStore.swift */,
|
||||
4FE60CDC295E1C5E00105A1F /* Wallet.swift */,
|
||||
4CB88392296F798300DC99E7 /* ReactionsModel.swift */,
|
||||
7C45AE70297353390031D7BC /* KFImageModel.swift */,
|
||||
4CF0ABD32980996B00D66079 /* Report.swift */,
|
||||
4CF0ABDD2981A69500D66079 /* MutelistModel.swift */,
|
||||
3AE45AF5297BB2E700C1D842 /* LibreTranslateServer.swift */,
|
||||
);
|
||||
path = Models;
|
||||
sourceTree = "<group>";
|
||||
@@ -628,61 +439,45 @@
|
||||
4C75EFA227FA576C0006080F /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4CAAD8AE29888A9B00060CEA /* Relays */,
|
||||
4CF0ABF42985CD4200D66079 /* Posting */,
|
||||
4CF0ABDF2981A83000D66079 /* Muting */,
|
||||
4CC7AAEE297F11B300430951 /* Events */,
|
||||
3AA24800297E3DAE0090C62D /* Reposts */,
|
||||
4CB88394296F7F8100DC99E7 /* Reactions */,
|
||||
4CB88387296AF97C00DC99E7 /* ActionBar */,
|
||||
4CE4F9E228528C5200C00DD9 /* AddRelayView.swift */,
|
||||
4C363A8728236948006E126D /* BlocksView.swift */,
|
||||
4C285C8128385570008A31F1 /* CarouselView.swift */,
|
||||
3169CAE4294E699400EE4006 /* Empty Views */,
|
||||
4C75EFA327FA577B0006080F /* PostView.swift */,
|
||||
4C75EFAC28049CFB0006080F /* PostButton.swift */,
|
||||
4C75EFB82804A2740006080F /* EventView.swift */,
|
||||
4CEE2AF0280B216B00AB5EEF /* EventDetailView.swift */,
|
||||
4CEE2AF2280B25C500AB5EEF /* ProfilePicView.swift */,
|
||||
4CEE2AF6280B2DEA00AB5EEF /* ProfileName.swift */,
|
||||
4CEE2AF8280B2EAC00AB5EEF /* PowView.swift */,
|
||||
4CEE2B01280B39E800AB5EEF /* EventActionBar.swift */,
|
||||
4CACA9D4280C31E100D9BBE8 /* ReplyView.swift */,
|
||||
4CA2EF9F280E37AC0044ACD8 /* TimelineView.swift */,
|
||||
4C0A3F8B280F5FCA000448DE /* ChatroomView.swift */,
|
||||
4C0A3F90280F6528000448DE /* ChatView.swift */,
|
||||
4CE4F9DD2852768D00C00DD9 /* ConfigView.swift */,
|
||||
4C0A3F94280F6C78000448DE /* ReplyQuoteView.swift */,
|
||||
4C0A3F96280F8E02000448DE /* ThreadView.swift */,
|
||||
4C8682862814DE470026224F /* ProfileView.swift */,
|
||||
4C363A8728236948006E126D /* BlocksView.swift */,
|
||||
4C363A8928236B57006E126D /* MentionView.swift */,
|
||||
4C363A8B28236B92006E126D /* PubkeyView.swift */,
|
||||
4C363A8D28236FE4006E126D /* NoteContentView.swift */,
|
||||
4C363AA128296A7E006E126D /* SearchView.swift */,
|
||||
4C3AC79C2833036D00E1F516 /* FollowingView.swift */,
|
||||
4C3AC79E2833115300E1F516 /* FollowButtonView.swift */,
|
||||
4C3AC7A02835A81400E1F516 /* SetupView.swift */,
|
||||
4C3AC7A42836987600E1F516 /* MainTabView.swift */,
|
||||
4C3AC7A628369BA200E1F516 /* SearchHomeView.swift */,
|
||||
4C285C8128385570008A31F1 /* CarouselView.swift */,
|
||||
4C285C8328385690008A31F1 /* CreateAccountView.swift */,
|
||||
4C285C892838B985008A31F1 /* ProfilePictureSelector.swift */,
|
||||
4C285C8D28399BFD008A31F1 /* SaveKeysView.swift */,
|
||||
4C90BD17283A9EE5008EE7EF /* LoginView.swift */,
|
||||
4C5C7E69284EDE2E00A22DF5 /* SearchResultsView.swift */,
|
||||
4CE4F9DD2852768D00C00DD9 /* ConfigView.swift */,
|
||||
4CE4F9E228528C5200C00DD9 /* AddRelayView.swift */,
|
||||
4C64987B286D03E000EAE2B3 /* DirectMessagesView.swift */,
|
||||
4C216F31286E388800040376 /* DMChatView.swift */,
|
||||
4C216F33286F5ACD00040376 /* DMView.swift */,
|
||||
4C06670028FC7C5900038D2A /* RelayView.swift */,
|
||||
E990020E2955F837003BBC5A /* EditMetadataView.swift */,
|
||||
3169CAE4294E699400EE4006 /* Empty Views */,
|
||||
4C75EFB82804A2740006080F /* EventView.swift */,
|
||||
4CEE2AF0280B216B00AB5EEF /* EventDetailView.swift */,
|
||||
4C3AC79E2833115300E1F516 /* FollowButtonView.swift */,
|
||||
4C3AC79C2833036D00E1F516 /* FollowingView.swift */,
|
||||
4C90BD17283A9EE5008EE7EF /* LoginView.swift */,
|
||||
4C363A8928236B57006E126D /* MentionView.swift */,
|
||||
4C363A8D28236FE4006E126D /* NoteContentView.swift */,
|
||||
4C75EFAC28049CFB0006080F /* PostButton.swift */,
|
||||
4C75EFA327FA577B0006080F /* PostView.swift */,
|
||||
4CEE2AF8280B2EAC00AB5EEF /* PowView.swift */,
|
||||
4CEE2AF6280B2DEA00AB5EEF /* ProfileName.swift */,
|
||||
4C285C892838B985008A31F1 /* ProfilePictureSelector.swift */,
|
||||
4CEE2AF2280B25C500AB5EEF /* ProfilePicView.swift */,
|
||||
4C8682862814DE470026224F /* ProfileView.swift */,
|
||||
4C3AC7A42836987600E1F516 /* MainTabView.swift */,
|
||||
4C363A8B28236B92006E126D /* PubkeyView.swift */,
|
||||
4CACA9D4280C31E100D9BBE8 /* ReplyView.swift */,
|
||||
F7F0BA262978E54D009531F3 /* ParicipantsView.swift */,
|
||||
4C285C8D28399BFD008A31F1 /* SaveKeysView.swift */,
|
||||
4C3AC7A628369BA200E1F516 /* SearchHomeView.swift */,
|
||||
4C5C7E69284EDE2E00A22DF5 /* SearchResultsView.swift */,
|
||||
4C363AA128296A7E006E126D /* SearchView.swift */,
|
||||
BAB68BEC29543FA3007BA466 /* SelectWalletView.swift */,
|
||||
4C3AC7A02835A81400E1F516 /* SetupView.swift */,
|
||||
E9E4ED0A295867B900DD7078 /* ThreadV2View.swift */,
|
||||
4C0A3F96280F8E02000448DE /* ThreadView.swift */,
|
||||
4CA2EF9F280E37AC0044ACD8 /* TimelineView.swift */,
|
||||
4CB55EF4295E679D007FD187 /* UserRelaysView.swift */,
|
||||
647D9A8C2968520300A295DE /* SideMenuView.swift */,
|
||||
9609F057296E220800069BF3 /* BannerImageView.swift */,
|
||||
4CB8838E296F781C00DC99E7 /* ReactionsView.swift */,
|
||||
6439E013296790CF0020672B /* ProfileZoomView.swift */,
|
||||
4CF0ABD529817F5B00D66079 /* ReportView.swift */,
|
||||
4CF0ABE42981EE0C00D66079 /* EULAView.swift */,
|
||||
3AA247FE297E3D900090C62D /* RepostsView.swift */,
|
||||
5C513FCB2984ACA60072348F /* QRCodeView.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
@@ -710,9 +505,6 @@
|
||||
4C7FF7D628233637009601DB /* Util */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4CF0ABEA29844B2F00D66079 /* AnyCodable */,
|
||||
4CC7AAE6297EFA7B00430951 /* Zap.swift */,
|
||||
4C3A1D322960DB0500558C0F /* Markdown.swift */,
|
||||
4CEE2AF4280B29E600AB5EEF /* TimeAgo.swift */,
|
||||
4CE4F8CC281352B30009DFBB /* Notifications.swift */,
|
||||
4C363A8328233689006E126D /* Parser.swift */,
|
||||
@@ -722,65 +514,10 @@
|
||||
4C90BD19283AA67F008EE7EF /* Bech32.swift */,
|
||||
4C216F352870A9A700040376 /* InputDismissKeyboard.swift */,
|
||||
3169CAEC294FCCFC00EE4006 /* Constants.swift */,
|
||||
3165648A295B70D500C64604 /* LinkView.swift */,
|
||||
4C3A1D3629637E0500558C0F /* PreviewCache.swift */,
|
||||
64FBD06E296255C400D9D3B2 /* Theme.swift */,
|
||||
4CB8838529656C8B00DC99E7 /* NIP05.swift */,
|
||||
4CF0ABD72981980C00D66079 /* Lists.swift */,
|
||||
4CF0ABEF29857E9200D66079 /* Bech32Object.swift */,
|
||||
7C60CAEE298471A1009C80D6 /* CoreSVG.swift */,
|
||||
4CAAD8AC298851D000060CEA /* AccountDeletion.swift */,
|
||||
4CB883A52975F83C00DC99E7 /* LNUrlPayRequest.swift */,
|
||||
4CB883A72975FC1800DC99E7 /* Zaps.swift */,
|
||||
4CB883B5297730E400DC99E7 /* LNUrls.swift */,
|
||||
);
|
||||
path = Util;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4CAAD8AE29888A9B00060CEA /* Relays */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4CB55EF2295E5D59007FD187 /* RecommendedRelayView.swift */,
|
||||
4C06670028FC7C5900038D2A /* RelayView.swift */,
|
||||
4CAAD8AF29888AD200060CEA /* RelayConfigView.swift */,
|
||||
);
|
||||
path = Relays;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4CB88387296AF97C00DC99E7 /* ActionBar */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4CEE2B01280B39E800AB5EEF /* EventActionBar.swift */,
|
||||
4CB88388296AF99A00DC99E7 /* EventDetailBar.swift */,
|
||||
);
|
||||
path = ActionBar;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4CB88394296F7F8100DC99E7 /* Reactions */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4CB88395296F7F8B00DC99E7 /* ReactionView.swift */,
|
||||
);
|
||||
path = Reactions;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4CC7AAEE297F11B300430951 /* Events */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4CC7AAEF297F11C700430951 /* SelectedEventView.swift */,
|
||||
4CC7AAF1297F129C00430951 /* EmbeddedEventView.swift */,
|
||||
4CC7AAF3297F18B400430951 /* ReplyDescription.swift */,
|
||||
4CC7AAF5297F1A6A00430951 /* EventBody.swift */,
|
||||
4CC7AAEA297F0AEC00430951 /* BuilderEventView.swift */,
|
||||
4CC7AAF7297F1CEE00430951 /* EventProfile.swift */,
|
||||
4CC7AAF9297F64AC00430951 /* EventMenu.swift */,
|
||||
4CF0ABE6298444FC00D66079 /* MutedEventView.swift */,
|
||||
4C3D52B5298DB4E6001C5831 /* ZapEvent.swift */,
|
||||
4C3D52B7298DB5C6001C5831 /* TextEvent.swift */,
|
||||
);
|
||||
path = Events;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4CE4F9DF285287A000C00DD9 /* Components */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -790,15 +527,6 @@
|
||||
4C06670528FCB08600038D2A /* ImageCarousel.swift */,
|
||||
4C3EA67C28FFBBA200C48A62 /* InvoicesView.swift */,
|
||||
4C3EA67E28FFC01D00C48A62 /* InvoiceView.swift */,
|
||||
4CB8838A296F6E1E00DC99E7 /* NIP05Badge.swift */,
|
||||
4CB8838C296F710400DC99E7 /* Reposted.swift */,
|
||||
4CBCA92F297DB57F00EC6B2F /* WebsiteLink.swift */,
|
||||
4CC7AAEC297F0B9E00430951 /* Highlight.swift */,
|
||||
5C513FB9297F72980072348F /* CustomPicker.swift */,
|
||||
4CF0ABE22981BC7D00D66079 /* UserView.swift */,
|
||||
7C902AE22981D55B002AB16E /* ZoomableScrollView.swift */,
|
||||
4CB883AF297705DD00DC99E7 /* ZapButton.swift */,
|
||||
4C42812B298C848200DBF26F /* TranslateView.swift */,
|
||||
);
|
||||
path = Components;
|
||||
sourceTree = "<group>";
|
||||
@@ -828,21 +556,17 @@
|
||||
4CE6DEE527F7A08100C66700 /* damus */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F7F0BA23297892AE009531F3 /* Modifiers */,
|
||||
4C4A3A5A288A1B2200453788 /* damus.entitlements */,
|
||||
4CE4F9DF285287A000C00DD9 /* Components */,
|
||||
4C7FF7D628233637009601DB /* Util */,
|
||||
4C0A3F8D280F63FF000448DE /* Models */,
|
||||
4C75EFAB28049CC80006080F /* Nostr */,
|
||||
4C75EFA72804823E0006080F /* Info.plist */,
|
||||
3ACB685D297633BC00C46468 /* Localizable.strings */,
|
||||
3ACB685A297633BC00C46468 /* InfoPlist.strings */,
|
||||
4C75EFA227FA576C0006080F /* Views */,
|
||||
4CE6DEE627F7A08100C66700 /* damusApp.swift */,
|
||||
4CE6DEE827F7A08100C66700 /* ContentView.swift */,
|
||||
4CE6DEEA27F7A08200C66700 /* Assets.xcassets */,
|
||||
4CE6DEEC27F7A08200C66700 /* Preview Content */,
|
||||
3A4325AA2961E11400BFCD9D /* Localizable.stringsdict */,
|
||||
);
|
||||
path = damus;
|
||||
sourceTree = "<group>";
|
||||
@@ -858,17 +582,11 @@
|
||||
4CE6DEF627F7A08200C66700 /* damusTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DD597CBC2963D85A00C64D32 /* MarkdownTests.swift */,
|
||||
4C90BD1B283AC38E008EE7EF /* Bech32Tests.swift */,
|
||||
4C363A9F2828A8DD006E126D /* LikeTests.swift */,
|
||||
4C363A9D2828A822006E126D /* ReplyTests.swift */,
|
||||
4CE6DEF727F7A08200C66700 /* damusTests.swift */,
|
||||
4C3EA67A28FF7B3900C48A62 /* InvoiceTests.swift */,
|
||||
3ACBCB77295FE5C70037388A /* TimeAgoTests.swift */,
|
||||
4CB88399297322D200DC99E7 /* DMTests.swift */,
|
||||
4CF0ABDB2981A19E00D66079 /* ListTests.swift */,
|
||||
4CB883A9297612FF00DC99E7 /* ZapTests.swift */,
|
||||
4CB883AD2976FA9300DC99E7 /* FormatTests.swift */,
|
||||
);
|
||||
path = damusTests;
|
||||
sourceTree = "<group>";
|
||||
@@ -890,40 +608,6 @@
|
||||
name = Frameworks;
|
||||
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 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F7F0BA24297892BD009531F3 /* SwipeToDismiss.swift */,
|
||||
);
|
||||
path = Modifiers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
@@ -1012,28 +696,18 @@
|
||||
};
|
||||
buildConfigurationList = 4CE6DEDE27F7A08100C66700 /* Build configuration list for PBXProject "damus" */;
|
||||
compatibilityVersion = "Xcode 13.0";
|
||||
developmentRegion = "en-US";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
"es-419",
|
||||
"en-US",
|
||||
"tr-TR",
|
||||
"fr-FR",
|
||||
"lv-LV",
|
||||
"it-IT",
|
||||
de,
|
||||
"pt-PT",
|
||||
"pl-PL",
|
||||
ar,
|
||||
nl,
|
||||
"zh-CN",
|
||||
);
|
||||
mainGroup = 4CE6DEDA27F7A08100C66700;
|
||||
packageReferences = (
|
||||
4CE6DF1027F7A2B300C66700 /* XCRemoteSwiftPackageReference "Starscream" */,
|
||||
4C64987F286E0EE300EAE2B3 /* XCRemoteSwiftPackageReference "secp256k1" */,
|
||||
4C06670228FC7EC500038D2A /* XCRemoteSwiftPackageReference "Kingfisher" */,
|
||||
3169CAE9294FCABA00EE4006 /* XCRemoteSwiftPackageReference "Shimmer" */,
|
||||
6C7DE41D2955169800E66263 /* XCRemoteSwiftPackageReference "Vault" */,
|
||||
);
|
||||
productRefGroup = 4CE6DEE427F7A08100C66700 /* Products */;
|
||||
@@ -1052,11 +726,8 @@
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
3ACB685F297633BC00C46468 /* Localizable.strings in Resources */,
|
||||
4CE6DEEE27F7A08200C66700 /* Preview Assets.xcassets in Resources */,
|
||||
3ACB685C297633BC00C46468 /* InfoPlist.strings in Resources */,
|
||||
4CE6DEEB27F7A08200C66700 /* Assets.xcassets in Resources */,
|
||||
3A4325A82961E11400BFCD9D /* Localizable.stringsdict in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -1088,131 +759,81 @@
|
||||
4C216F34286F5ACD00040376 /* DMView.swift in Sources */,
|
||||
4C3EA64428FF558100C48A62 /* sha256.c in Sources */,
|
||||
4CE4F9E1285287B800C00DD9 /* TextFieldAlert.swift in Sources */,
|
||||
4CF0ABF62985CD5500D66079 /* UserSearch.swift in Sources */,
|
||||
4C363AA828297703006E126D /* InsertSort.swift in Sources */,
|
||||
4C285C86283892E7008A31F1 /* CreateAccountModel.swift in Sources */,
|
||||
4C64987C286D03E000EAE2B3 /* DirectMessagesView.swift in Sources */,
|
||||
7C902AE32981D55B002AB16E /* ZoomableScrollView.swift in Sources */,
|
||||
4C363A8C28236B92006E126D /* PubkeyView.swift in Sources */,
|
||||
4C5C7E68284ED36500A22DF5 /* SearchHomeModel.swift in Sources */,
|
||||
4C75EFB728049D990006080F /* RelayPool.swift in Sources */,
|
||||
4CF0ABEE29844B5500D66079 /* AnyEncodable.swift in Sources */,
|
||||
4CB8838D296F710400DC99E7 /* Reposted.swift in Sources */,
|
||||
4C3EA67728FF7A9800C48A62 /* talstr.c in Sources */,
|
||||
4CE6DEE927F7A08100C66700 /* ContentView.swift in Sources */,
|
||||
4CEE2AF5280B29E600AB5EEF /* TimeAgo.swift in Sources */,
|
||||
4C75EFAD28049CFB0006080F /* PostButton.swift in Sources */,
|
||||
4CB55EF5295E679D007FD187 /* UserRelaysView.swift in Sources */,
|
||||
4C363AA228296A7E006E126D /* SearchView.swift in Sources */,
|
||||
4CC7AAED297F0B9E00430951 /* Highlight.swift in Sources */,
|
||||
4C285C8A2838B985008A31F1 /* ProfilePictureSelector.swift in Sources */,
|
||||
4C75EFB92804A2740006080F /* EventView.swift in Sources */,
|
||||
3AA247FD297E3CFF0090C62D /* RepostsModel.swift in Sources */,
|
||||
4CB883B6297730E400DC99E7 /* LNUrls.swift in Sources */,
|
||||
4C7FF7D52823313F009601DB /* Mentions.swift in Sources */,
|
||||
4C633350283D40E500B1C9C3 /* HomeModel.swift in Sources */,
|
||||
4C987B57283FD07F0042CE38 /* FollowersModel.swift in Sources */,
|
||||
4C363A9028247A1D006E126D /* NostrLink.swift in Sources */,
|
||||
4C0A3F8C280F5FCA000448DE /* ChatroomView.swift in Sources */,
|
||||
4C477C9E282C3A4800033AA3 /* TipCounter.swift in Sources */,
|
||||
4C3D52B6298DB4E6001C5831 /* ZapEvent.swift in Sources */,
|
||||
647D9A8D2968520300A295DE /* SideMenuView.swift in Sources */,
|
||||
F7F0BA272978E54D009531F3 /* ParicipantsView.swift in Sources */,
|
||||
4C0A3F91280F6528000448DE /* ChatView.swift in Sources */,
|
||||
4CF0ABE32981BC7D00D66079 /* UserView.swift in Sources */,
|
||||
4CF0ABF029857E9200D66079 /* Bech32Object.swift in Sources */,
|
||||
4C3D52B8298DB5C6001C5831 /* TextEvent.swift in Sources */,
|
||||
4C216F362870A9A700040376 /* InputDismissKeyboard.swift in Sources */,
|
||||
4C216F382871EDE300040376 /* DirectMessageModel.swift in Sources */,
|
||||
4C75EFA627FF87A20006080F /* Nostr.swift in Sources */,
|
||||
4CB883A62975F83C00DC99E7 /* LNUrlPayRequest.swift in Sources */,
|
||||
4CE4F9DE2852768D00C00DD9 /* ConfigView.swift in Sources */,
|
||||
4C285C8E28399BFE008A31F1 /* SaveKeysView.swift in Sources */,
|
||||
F7F0BA25297892BD009531F3 /* SwipeToDismiss.swift in Sources */,
|
||||
4CB8838F296F781C00DC99E7 /* ReactionsView.swift in Sources */,
|
||||
4C649844285A952100EAE2B3 /* LocalUserConfig.swift in Sources */,
|
||||
4C75EFB328049D640006080F /* NostrEvent.swift in Sources */,
|
||||
4CA2EFA0280E37AC0044ACD8 /* TimelineView.swift in Sources */,
|
||||
4C363A8428233689006E126D /* Parser.swift in Sources */,
|
||||
4CE4F9E328528C5200C00DD9 /* AddRelayView.swift in Sources */,
|
||||
4C363A9A28283854006E126D /* Reply.swift in Sources */,
|
||||
BA693074295D649800ADDB87 /* UserSettingsStore.swift in Sources */,
|
||||
4C90BD18283A9EE5008EE7EF /* LoginView.swift in Sources */,
|
||||
4CB8838B296F6E1E00DC99E7 /* NIP05Badge.swift in Sources */,
|
||||
4C3EA66828FF5F9900C48A62 /* hex.c in Sources */,
|
||||
E9E4ED0B295867B900DD7078 /* ThreadV2View.swift in Sources */,
|
||||
4C3BEFDC281DCE6100B3DE84 /* Liked.swift in Sources */,
|
||||
4CF0ABE7298444FD00D66079 /* MutedEventView.swift in Sources */,
|
||||
4CF0ABE12981A83900D66079 /* MutelistView.swift in Sources */,
|
||||
4CB883A82975FC1800DC99E7 /* Zaps.swift in Sources */,
|
||||
4C75EFB128049D510006080F /* NostrResponse.swift in Sources */,
|
||||
4CEE2AF7280B2DEA00AB5EEF /* ProfileName.swift in Sources */,
|
||||
4CC7AAEB297F0AEC00430951 /* BuilderEventView.swift in Sources */,
|
||||
31D2E847295218AF006D67F8 /* Shimmer.swift in Sources */,
|
||||
4C285C8228385570008A31F1 /* CarouselView.swift in Sources */,
|
||||
4C3EA67F28FFC01D00C48A62 /* InvoiceView.swift in Sources */,
|
||||
4CEE2B02280B39E800AB5EEF /* EventActionBar.swift in Sources */,
|
||||
4C3BEFE0281DE1ED00B3DE84 /* DamusState.swift in Sources */,
|
||||
7C45AE71297353390031D7BC /* KFImageModel.swift in Sources */,
|
||||
4CF0ABE929844AF100D66079 /* AnyCodable.swift in Sources */,
|
||||
4C0A3F8F280F640A000448DE /* ThreadModel.swift in Sources */,
|
||||
4CC7AAF2297F129C00430951 /* EmbeddedEventView.swift in Sources */,
|
||||
4C3AC79F2833115300E1F516 /* FollowButtonView.swift in Sources */,
|
||||
4CC7AAE7297EFA7B00430951 /* Zap.swift in Sources */,
|
||||
4C3BEFD22819DB9B00B3DE84 /* ProfileModel.swift in Sources */,
|
||||
4C0A3F93280F66F5000448DE /* ReplyMap.swift in Sources */,
|
||||
BAB68BED29543FA3007BA466 /* SelectWalletView.swift in Sources */,
|
||||
3169CAE6294E69C000EE4006 /* EmptyTimelineView.swift in Sources */,
|
||||
4CC7AAF0297F11C700430951 /* SelectedEventView.swift in Sources */,
|
||||
4CC7AAF8297F1CEE00430951 /* EventProfile.swift in Sources */,
|
||||
64FBD06F296255C400D9D3B2 /* Theme.swift in Sources */,
|
||||
4C3EA64928FF597700C48A62 /* bech32.c in Sources */,
|
||||
4C90BD162839DB54008EE7EF /* NostrMetadata.swift in Sources */,
|
||||
4C3A1D3729637E0500558C0F /* PreviewCache.swift in Sources */,
|
||||
4C3EA67528FF7A5A00C48A62 /* take.c in Sources */,
|
||||
4C3AC7A12835A81400E1F516 /* SetupView.swift in Sources */,
|
||||
4C06670128FC7C5900038D2A /* RelayView.swift in Sources */,
|
||||
4C285C8C28398BC7008A31F1 /* Keys.swift in Sources */,
|
||||
4CACA9DC280C38C000D9BBE8 /* Profiles.swift in Sources */,
|
||||
4C633352283D419F00B1C9C3 /* SignalModel.swift in Sources */,
|
||||
9609F058296E220800069BF3 /* BannerImageView.swift in Sources */,
|
||||
4C363A94282704FA006E126D /* Post.swift in Sources */,
|
||||
4C216F32286E388800040376 /* DMChatView.swift in Sources */,
|
||||
4CAAD8AD298851D000060CEA /* AccountDeletion.swift in Sources */,
|
||||
4C3EA67928FF7ABF00C48A62 /* list.c in Sources */,
|
||||
4C64987E286D082C00EAE2B3 /* DirectMessagesModel.swift in Sources */,
|
||||
4C363A8828236948006E126D /* BlocksView.swift in Sources */,
|
||||
4C06670628FCB08600038D2A /* ImageCarousel.swift in Sources */,
|
||||
4C75EFAF28049D350006080F /* NostrFilter.swift in Sources */,
|
||||
4C3EA64C28FF59AC00C48A62 /* bech32_util.c in Sources */,
|
||||
4C42812C298C848200DBF26F /* TranslateView.swift in Sources */,
|
||||
4C363A9C282838B9006E126D /* EventRef.swift in Sources */,
|
||||
3AA24802297E3DC20090C62D /* RepostView.swift in Sources */,
|
||||
4CD7641B28A1641400B6928F /* EndBlock.swift in Sources */,
|
||||
4C3EA66528FF5F6800C48A62 /* mem.c in Sources */,
|
||||
4CF0ABE52981EE0C00D66079 /* EULAView.swift in Sources */,
|
||||
4CBCA930297DB57F00EC6B2F /* WebsiteLink.swift in Sources */,
|
||||
4CAAD8B029888AD200060CEA /* RelayConfigView.swift in Sources */,
|
||||
4C3EA64128FF553900C48A62 /* hash_u5.c in Sources */,
|
||||
5C513FCC2984ACA60072348F /* QRCodeView.swift in Sources */,
|
||||
4C3EA64F28FF59F200C48A62 /* tal.c in Sources */,
|
||||
4CB88393296F798300DC99E7 /* ReactionsModel.swift in Sources */,
|
||||
4CB88396296F7F8B00DC99E7 /* ReactionView.swift in Sources */,
|
||||
4C8682872814DE470026224F /* ProfileView.swift in Sources */,
|
||||
4C5F9114283D694D0052CD1C /* FollowTarget.swift in Sources */,
|
||||
4CF0ABD629817F5B00D66079 /* ReportView.swift in Sources */,
|
||||
4CB8838629656C8B00DC99E7 /* NIP05.swift in Sources */,
|
||||
4CF0ABD82981980C00D66079 /* Lists.swift in Sources */,
|
||||
4C5C7E6A284EDE2E00A22DF5 /* SearchResultsView.swift in Sources */,
|
||||
7C60CAEF298471A1009C80D6 /* CoreSVG.swift in Sources */,
|
||||
6439E014296790CF0020672B /* ProfileZoomView.swift in Sources */,
|
||||
4CE6DF1627F8DEBF00C66700 /* RelayConnection.swift in Sources */,
|
||||
4C3BEFD6281D995700B3DE84 /* ActionBarModel.swift in Sources */,
|
||||
4C363AA428296DEE006E126D /* SearchModel.swift in Sources */,
|
||||
4CEE2AF3280B25C500AB5EEF /* ProfilePicView.swift in Sources */,
|
||||
4CC7AAF6297F1A6A00430951 /* EventBody.swift in Sources */,
|
||||
4CEE2AF9280B2EAC00AB5EEF /* PowView.swift in Sources */,
|
||||
3165648B295B70D500C64604 /* LinkView.swift in Sources */,
|
||||
4C3BEFD42819DE8F00B3DE84 /* NostrKind.swift in Sources */,
|
||||
4C3EA66028FF5E7700C48A62 /* node_id.c in Sources */,
|
||||
4CE6DEE727F7A08100C66700 /* damusApp.swift in Sources */,
|
||||
@@ -1222,35 +843,23 @@
|
||||
4C06670E28FDEAA000038D2A /* utf8.c in Sources */,
|
||||
4C3EA66D28FF782800C48A62 /* amount.c in Sources */,
|
||||
4C3AC7A728369BA200E1F516 /* SearchHomeView.swift in Sources */,
|
||||
4CB883B0297705DD00DC99E7 /* ZapButton.swift in Sources */,
|
||||
4C363A922825FCF2006E126D /* ProfileUpdate.swift in Sources */,
|
||||
4C0A3F95280F6C78000448DE /* ReplyQuoteView.swift in Sources */,
|
||||
4C3BEFDA281DCA1400B3DE84 /* LikeCounter.swift in Sources */,
|
||||
4CB88389296AF99A00DC99E7 /* EventDetailBar.swift in Sources */,
|
||||
4CF0ABDE2981A69500D66079 /* MutelistModel.swift in Sources */,
|
||||
4C3AC79B28306D7B00E1F516 /* Contacts.swift in Sources */,
|
||||
4C3EA63D28FF52D600C48A62 /* bolt11.c in Sources */,
|
||||
4CB55EF3295E5D59007FD187 /* RecommendedRelayView.swift in Sources */,
|
||||
4CF0ABEC29844B4700D66079 /* AnyDecodable.swift in Sources */,
|
||||
4C5F9118283D88E40052CD1C /* FollowingModel.swift in Sources */,
|
||||
4C3EA67D28FFBBA300C48A62 /* InvoicesView.swift in Sources */,
|
||||
4C363A8E28236FE4006E126D /* NoteContentView.swift in Sources */,
|
||||
4C90BD1A283AA67F008EE7EF /* Bech32.swift in Sources */,
|
||||
E990020F2955F837003BBC5A /* EditMetadataView.swift in Sources */,
|
||||
5C513FBA297F72980072348F /* CustomPicker.swift in Sources */,
|
||||
4CACA9D5280C31E100D9BBE8 /* ReplyView.swift in Sources */,
|
||||
4C3A1D332960DB0500558C0F /* Markdown.swift in Sources */,
|
||||
4CF0ABD42980996B00D66079 /* Report.swift in Sources */,
|
||||
4C0A3F97280F8E02000448DE /* ThreadView.swift in Sources */,
|
||||
4C06670B28FDE64700038D2A /* damus.c in Sources */,
|
||||
4FE60CDD295E1C5E00105A1F /* Wallet.swift in Sources */,
|
||||
3AA247FF297E3D900090C62D /* RepostsView.swift in Sources */,
|
||||
3AE45AF6297BB2E700C1D842 /* LibreTranslateServer.swift in Sources */,
|
||||
4C99737B28C92A9200E53835 /* ChatroomMetadata.swift in Sources */,
|
||||
4CC7AAF4297F18B400430951 /* ReplyDescription.swift in Sources */,
|
||||
4C75EFA427FA577B0006080F /* PostView.swift in Sources */,
|
||||
4C75EFB528049D790006080F /* Relay.swift in Sources */,
|
||||
4CEE2AF1280B216B00AB5EEF /* EventDetailView.swift in Sources */,
|
||||
4CC7AAFA297F64AC00430951 /* EventMenu.swift in Sources */,
|
||||
4C75EFBB2804A34C0006080F /* ProofOfWork.swift in Sources */,
|
||||
4C3AC7A52836987600E1F516 /* MainTabView.swift in Sources */,
|
||||
3169CAED294FCCFC00EE4006 /* Constants.swift in Sources */,
|
||||
@@ -1261,17 +870,11 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
3ACBCB78295FE5C70037388A /* TimeAgoTests.swift in Sources */,
|
||||
DD597CBD2963D85A00C64D32 /* MarkdownTests.swift in Sources */,
|
||||
4C3EA67B28FF7B3900C48A62 /* InvoiceTests.swift in Sources */,
|
||||
4C363A9E2828A822006E126D /* ReplyTests.swift in Sources */,
|
||||
4CB883AA297612FF00DC99E7 /* ZapTests.swift in Sources */,
|
||||
4CB8839A297322D200DC99E7 /* DMTests.swift in Sources */,
|
||||
4CB883AE2976FA9300DC99E7 /* FormatTests.swift in Sources */,
|
||||
4C363AA02828A8DD006E126D /* LikeTests.swift in Sources */,
|
||||
4C90BD1C283AC38E008EE7EF /* Bech32Tests.swift in Sources */,
|
||||
4CE6DEF827F7A08200C66700 /* damusTests.swift in Sources */,
|
||||
4CF0ABDC2981A19E00D66079 /* ListTests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -1299,70 +902,11 @@
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
3A4325AA2961E11400BFCD9D /* Localizable.stringsdict */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
3A5C4575296A879E0032D398 /* es-419 */,
|
||||
3A2B8B0A296A8982009CC16D /* en-US */,
|
||||
3AEB8005297CCEA900713A25 /* tr-TR */,
|
||||
3A4F3322297CCFEE004B5F72 /* fr-FR */,
|
||||
3A185A06297F2C3800F4BDC0 /* lv-LV */,
|
||||
3A929C22297F2CF80090925E /* it-IT */,
|
||||
3AB5B86C2986D8A3006599D2 /* de */,
|
||||
3AF6336A29884C6B0005672A /* pt-PT */,
|
||||
3A93342B29884CA600D6A8F3 /* pl-PL */,
|
||||
3AC524F0298C000B00693EBF /* ar */,
|
||||
3A96D41C298DA94500388A2A /* nl */,
|
||||
3A5CAE1F298DC0DB00B5334F /* zh-CN */,
|
||||
);
|
||||
name = Localizable.stringsdict;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
3ACB685A297633BC00C46468 /* InfoPlist.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
3ACB685B297633BC00C46468 /* es-419 */,
|
||||
3AEB8003297CCEA800713A25 /* tr-TR */,
|
||||
3A4F3320297CCFEE004B5F72 /* fr-FR */,
|
||||
3A185A04297F2C3800F4BDC0 /* lv-LV */,
|
||||
3A929C20297F2CF80090925E /* it-IT */,
|
||||
3AB5B86A2986D8A3006599D2 /* de */,
|
||||
3AF6336829884C6B0005672A /* pt-PT */,
|
||||
3A93342929884CA600D6A8F3 /* pl-PL */,
|
||||
3AC524EE298C000B00693EBF /* ar */,
|
||||
3A96D41A298DA94500388A2A /* nl */,
|
||||
3A5CAE1D298DC0DB00B5334F /* zh-CN */,
|
||||
);
|
||||
name = InfoPlist.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
3ACB685D297633BC00C46468 /* Localizable.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
3ACB685E297633BC00C46468 /* es-419 */,
|
||||
3AEB8004297CCEA800713A25 /* tr-TR */,
|
||||
3A4F3321297CCFEE004B5F72 /* fr-FR */,
|
||||
3A185A05297F2C3800F4BDC0 /* lv-LV */,
|
||||
3A929C21297F2CF80090925E /* it-IT */,
|
||||
3AB5B86B2986D8A3006599D2 /* de */,
|
||||
3AF6336929884C6B0005672A /* pt-PT */,
|
||||
3A93342A29884CA600D6A8F3 /* pl-PL */,
|
||||
3AC524EF298C000B00693EBF /* ar */,
|
||||
3A96D41B298DA94500388A2A /* nl */,
|
||||
3A5CAE1E298DC0DB00B5334F /* zh-CN */,
|
||||
);
|
||||
name = Localizable.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
4CE6DF0527F7A08200C66700 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
||||
@@ -1409,14 +953,13 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.3;
|
||||
MACOSX_DEPLOYMENT_TARGET = 12.3;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
@@ -1425,7 +968,6 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
||||
@@ -1466,13 +1008,12 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.3;
|
||||
MACOSX_DEPLOYMENT_TARGET = 12.3;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
@@ -1486,15 +1027,13 @@
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = damus/damus.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 13;
|
||||
CURRENT_PROJECT_VERSION = 4;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"damus/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = XK7H4JAB3D;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = damus/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = Damus;
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
||||
INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = "Granting Damus access to your photos allows you to save images.";
|
||||
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
||||
@@ -1508,7 +1047,7 @@
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.0;
|
||||
MARKETING_VERSION = 0.1.8;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.jb55.damus2;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
@@ -1527,15 +1066,13 @@
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = damus/damus.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 13;
|
||||
CURRENT_PROJECT_VERSION = 4;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"damus/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = XK7H4JAB3D;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = damus/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = Damus;
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
||||
INFOPLIST_KEY_NSPhotoLibraryAddUsageDescription = "Granting Damus access to your photos allows you to save images.";
|
||||
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
||||
@@ -1549,7 +1086,7 @@
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.0;
|
||||
MARKETING_VERSION = 0.1.8;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.jb55.damus2;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
@@ -1677,6 +1214,14 @@
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCRemoteSwiftPackageReference section */
|
||||
3169CAE9294FCABA00EE4006 /* XCRemoteSwiftPackageReference "Shimmer" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/joshuajhomann/Shimmer";
|
||||
requirement = {
|
||||
branch = master;
|
||||
kind = branch;
|
||||
};
|
||||
};
|
||||
4C06670228FC7EC500038D2A /* XCRemoteSwiftPackageReference "Kingfisher" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/onevcat/Kingfisher";
|
||||
|
||||
@@ -17,6 +17,15 @@
|
||||
"revision" : "40b4b38b3b1c83f7088c76189a742870e0ca06a9"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "shimmer",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/joshuajhomann/Shimmer",
|
||||
"state" : {
|
||||
"branch" : "master",
|
||||
"revision" : "2fde687b3f1d9c5409c53da095d3686361e41343"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "starscream",
|
||||
"kind" : "remoteSourceControl",
|
||||
@@ -31,8 +40,8 @@
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/SparrowTek/Vault",
|
||||
"state" : {
|
||||
"revision" : "87db56c3c8b6421c65b0745f73e08b0dc56f79d4",
|
||||
"version" : "1.0.3"
|
||||
"revision" : "f5707fac23f4a17b3e5ed32dd444f502773615ae",
|
||||
"version" : "1.0.2"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
@@ -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>
|
||||
@@ -1,33 +1,6 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xC5",
|
||||
"green" : "0x43",
|
||||
"red" : "0xCC"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xC5",
|
||||
"green" : "0x43",
|
||||
"red" : "0xCC"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x00",
|
||||
"green" : "0x00",
|
||||
"red" : "0x00"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x00",
|
||||
"green" : "0x00",
|
||||
"red" : "0x00"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xFF",
|
||||
"green" : "0x4D",
|
||||
"red" : "0x4B"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xFF",
|
||||
"green" : "0x4D",
|
||||
"red" : "0x4B"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x1E",
|
||||
"green" : "0x1C",
|
||||
"red" : "0x1C"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x1E",
|
||||
"green" : "0x1C",
|
||||
"red" : "0x1C"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x4F",
|
||||
"green" : "0xC3",
|
||||
"red" : "0x66"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x4F",
|
||||
"green" : "0xC3",
|
||||
"red" : "0x66"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xF4",
|
||||
"green" : "0xEE",
|
||||
"red" : "0xEE"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xF4",
|
||||
"green" : "0xEE",
|
||||
"red" : "0xEE"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x5F",
|
||||
"green" : "0x5F",
|
||||
"red" : "0x5F"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x5F",
|
||||
"green" : "0x5F",
|
||||
"red" : "0x5F"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xC5",
|
||||
"green" : "0x43",
|
||||
"red" : "0xCC"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xC5",
|
||||
"green" : "0x43",
|
||||
"red" : "0xCC"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xFF",
|
||||
"green" : "0xFF",
|
||||
"red" : "0xFF"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xFF",
|
||||
"green" : "0xFF",
|
||||
"red" : "0xFF"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ic-copy.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 354 B |
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ic-key.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 400 B |
@@ -1,52 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ic-message-black.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"filename" : "ic-message-white 1.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 321 B |
|
Before Width: | Height: | Size: 341 B |
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ic-nipverified.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 950 B |
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ic-qr.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 252 B |
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "profile-banner.jpeg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 290 KiB |
21
damus/Assets.xcassets/bbw.imageset/Contents.json
vendored
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "bbw.jpg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
damus/Assets.xcassets/bbw.imageset/bbw.jpg
vendored
|
Before Width: | Height: | Size: 14 KiB |
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "blixt-wallet.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 215 KiB |
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "bluewallet.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 61 KiB |
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "breez.jpg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
damus/Assets.xcassets/breez.imageset/breez.jpg
vendored
|
Before Width: | Height: | Size: 21 KiB |
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "cashapp.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
damus/Assets.xcassets/cashapp.imageset/cashapp.png
vendored
|
Before Width: | Height: | Size: 44 KiB |
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "damus-home@1x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "damus-home@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "damus-home@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 8.0 KiB |
|
Before Width: | Height: | Size: 12 KiB |
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ic-lightning.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 458 B |
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ic-tick.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
damus/Assets.xcassets/ic-tick.imageset/ic-tick.png
vendored
|
Before Width: | Height: | Size: 671 B |
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "lnlink.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
damus/Assets.xcassets/lnlink.imageset/lnlink.png
vendored
|
Before Width: | Height: | Size: 547 KiB |
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "muun.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
damus/Assets.xcassets/muun.imageset/muun.png
vendored
|
Before Width: | Height: | Size: 25 KiB |
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "phoenix.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
damus/Assets.xcassets/phoenix.imageset/phoenix.png
vendored
|
Before Width: | Height: | Size: 2.9 KiB |
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "river.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
damus/Assets.xcassets/river.imageset/river.png
vendored
|
Before Width: | Height: | Size: 26 KiB |
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "shaka-full.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
%PDF-1.7
|
||||
|
||||
1 0 obj
|
||||
<< >>
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
<< /Length 3 0 R >>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 0.000000 -0.073975 cm
|
||||
1.000000 1.000000 1.000000 scn
|
||||
1.295334 8.661732 m
|
||||
3.613694 8.367855 l
|
||||
4.475733 8.733568 5.268113 9.771931 5.474915 10.327032 c
|
||||
6.083156 11.959681 5.507567 14.604573 5.474915 15.061715 c
|
||||
5.448792 15.427428 6.008246 15.693006 6.291239 15.780080 c
|
||||
7.571236 15.858447 8.508359 14.876789 8.642253 13.984165 c
|
||||
8.740212 13.331103 8.576948 11.752880 8.381030 10.849482 c
|
||||
8.979668 10.936556 10.980525 10.901726 11.868687 10.849482 c
|
||||
12.756847 10.797236 13.474895 10.196423 14.193260 9.412750 c
|
||||
14.767952 8.237244 13.953805 7.725680 13.474895 7.616838 c
|
||||
13.834077 7.257654 l
|
||||
14.781013 5.918882 13.649043 5.178749 13.115711 5.004600 c
|
||||
13.474895 4.743376 l
|
||||
14.487136 3.763786 13.246323 2.751544 13.017752 2.882155 c
|
||||
11.058574 3.176033 l
|
||||
15.499378 1.673996 l
|
||||
16.054478 0.400530 15.074889 0.073999 14.781013 0.073999 c
|
||||
8.576947 1.673996 l
|
||||
6.291239 1.673996 5.311650 1.869914 4.299407 2.163791 c
|
||||
4.157911 2.131138 3.659409 1.987464 2.797370 1.673996 c
|
||||
1.935332 1.360527 1.219143 2.087601 0.968804 2.490320 c
|
||||
-0.285071 4.083785 -0.467927 7.257655 1.295334 8.661732 c
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
1149
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
<< /Annots []
|
||||
/Type /Page
|
||||
/MediaBox [ 0.000000 0.000000 15.666626 15.710510 ]
|
||||
/Resources 1 0 R
|
||||
/Contents 2 0 R
|
||||
/Parent 5 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
5 0 obj
|
||||
<< /Kids [ 4 0 R ]
|
||||
/Count 1
|
||||
/Type /Pages
|
||||
>>
|
||||
endobj
|
||||
|
||||
6 0 obj
|
||||
<< /Pages 5 0 R
|
||||
/Type /Catalog
|
||||
>>
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 7
|
||||
0000000000 65535 f
|
||||
0000000010 00000 n
|
||||
0000000034 00000 n
|
||||
0000001239 00000 n
|
||||
0000001262 00000 n
|
||||
0000001435 00000 n
|
||||
0000001509 00000 n
|
||||
trailer
|
||||
<< /ID [ (some) (id) ]
|
||||
/Root 6 0 R
|
||||
/Size 7
|
||||
>>
|
||||
startxref
|
||||
1568
|
||||
%%EOF
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "shaka-line.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
||||
@@ -1,323 +0,0 @@
|
||||
%PDF-1.7
|
||||
|
||||
1 0 obj
|
||||
<< >>
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
<< /Length 3 0 R >>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 0.474731 -0.563965 cm
|
||||
1.000000 1.000000 1.000000 scn
|
||||
3.613694 9.332577 m
|
||||
3.553993 8.861599 l
|
||||
3.637261 8.851044 3.721838 8.862753 3.799107 8.895533 c
|
||||
3.613694 9.332577 l
|
||||
h
|
||||
1.295334 9.626453 m
|
||||
1.355035 10.097433 l
|
||||
1.227973 10.113539 1.099794 10.077623 0.999601 9.997839 c
|
||||
1.295334 9.626453 l
|
||||
h
|
||||
0.968804 3.455042 m
|
||||
1.372000 3.705677 l
|
||||
1.362764 3.720535 1.352713 3.734872 1.341894 3.748621 c
|
||||
0.968804 3.455042 l
|
||||
h
|
||||
4.299407 3.128512 m
|
||||
4.431771 3.584435 l
|
||||
4.353942 3.607030 4.271623 3.609325 4.192656 3.591103 c
|
||||
4.299407 3.128512 l
|
||||
h
|
||||
8.576947 2.638718 m
|
||||
8.695503 3.098424 l
|
||||
8.656776 3.108411 8.616942 3.113465 8.576947 3.113465 c
|
||||
8.576947 2.638718 l
|
||||
h
|
||||
14.781013 1.038721 m
|
||||
14.662457 0.579016 l
|
||||
14.701184 0.569027 14.741018 0.563974 14.781013 0.563974 c
|
||||
14.781013 1.038721 l
|
||||
h
|
||||
15.499378 2.638718 m
|
||||
15.934578 2.828420 l
|
||||
15.881091 2.951125 15.778289 3.045548 15.651489 3.088437 c
|
||||
15.499378 2.638718 l
|
||||
h
|
||||
11.058574 4.140755 m
|
||||
11.128998 4.610250 l
|
||||
10.885809 4.646729 10.655017 4.491467 10.597156 4.252461 c
|
||||
10.539293 4.013455 10.673516 3.769826 10.906463 3.691035 c
|
||||
11.058574 4.140755 l
|
||||
h
|
||||
13.017752 3.846877 m
|
||||
13.253292 4.259073 l
|
||||
13.202273 4.288227 13.146286 4.307655 13.088176 4.316372 c
|
||||
13.017752 3.846877 l
|
||||
h
|
||||
13.474895 5.708097 m
|
||||
13.805044 6.049252 l
|
||||
13.789093 6.064689 13.772079 6.078987 13.754128 6.092043 c
|
||||
13.474895 5.708097 l
|
||||
h
|
||||
13.115711 5.969321 m
|
||||
12.968349 6.420619 l
|
||||
12.798800 6.365256 12.674588 6.219535 12.646772 6.043359 c
|
||||
12.618958 5.867183 12.692234 5.690281 12.836478 5.585376 c
|
||||
13.115711 5.969321 l
|
||||
h
|
||||
13.834077 8.222376 m
|
||||
14.221668 8.496526 l
|
||||
14.206144 8.518474 14.188784 8.539063 14.169774 8.558073 c
|
||||
13.834077 8.222376 l
|
||||
h
|
||||
13.474895 8.581559 m
|
||||
13.369680 9.044500 l
|
||||
13.201114 9.006190 13.066693 8.879284 13.018762 8.713197 c
|
||||
12.970830 8.547110 13.016963 8.368095 13.139197 8.245862 c
|
||||
13.474895 8.581559 l
|
||||
h
|
||||
14.193260 10.377472 m
|
||||
14.619765 10.585986 l
|
||||
14.599768 10.626891 14.573989 10.664707 14.543221 10.698271 c
|
||||
14.193260 10.377472 l
|
||||
h
|
||||
8.381030 11.814203 m
|
||||
7.917068 11.914822 l
|
||||
7.884080 11.762714 7.927746 11.604099 8.033934 11.490305 c
|
||||
8.140121 11.376513 8.295343 11.321997 8.449365 11.344399 c
|
||||
8.381030 11.814203 l
|
||||
h
|
||||
8.642253 14.948887 m
|
||||
9.111748 15.019311 l
|
||||
8.642253 14.948887 l
|
||||
h
|
||||
6.291239 16.744801 m
|
||||
6.262227 17.218662 l
|
||||
6.224693 17.216364 6.187564 17.209614 6.151623 17.198555 c
|
||||
6.291239 16.744801 l
|
||||
h
|
||||
5.474915 16.026436 m
|
||||
5.948456 16.060261 l
|
||||
5.474915 16.026436 l
|
||||
h
|
||||
5.474915 11.291754 m
|
||||
5.030037 11.457493 l
|
||||
5.474915 11.291754 l
|
||||
h
|
||||
3.673396 9.803555 m
|
||||
1.355035 10.097433 l
|
||||
1.235632 9.155476 l
|
||||
3.553993 8.861599 l
|
||||
3.673396 9.803555 l
|
||||
h
|
||||
0.999601 9.997839 m
|
||||
-0.029049 9.178730 -0.454726 7.875908 -0.474048 6.619066 c
|
||||
-0.493367 5.362488 -0.110331 4.058727 0.595713 3.161463 c
|
||||
1.341894 3.748621 l
|
||||
0.794064 4.444821 0.458734 5.524729 0.475334 6.604470 c
|
||||
0.491930 7.683949 0.856455 8.670100 1.591066 9.255068 c
|
||||
0.999601 9.997839 l
|
||||
h
|
||||
0.565608 3.204407 m
|
||||
0.721970 2.952868 1.013515 2.611341 1.407507 2.372385 c
|
||||
1.811404 2.127421 2.357187 1.973489 2.959612 2.192553 c
|
||||
2.635129 3.084882 l
|
||||
2.375515 2.990478 2.132184 3.043347 1.899893 3.184233 c
|
||||
1.657696 3.331126 1.465977 3.554496 1.372000 3.705677 c
|
||||
0.565608 3.204407 l
|
||||
h
|
||||
2.959612 2.192553 m
|
||||
3.816493 2.504146 4.293336 2.639887 4.406158 2.665923 c
|
||||
4.192656 3.591103 l
|
||||
4.022485 3.551832 3.502325 3.400227 2.635129 3.084882 c
|
||||
2.959612 2.192553 l
|
||||
h
|
||||
4.167043 2.672591 m
|
||||
5.229115 2.364247 6.254152 2.163970 8.576947 2.163970 c
|
||||
8.576947 3.113465 l
|
||||
6.328326 3.113465 5.394184 3.305025 4.431771 3.584435 c
|
||||
4.167043 2.672591 l
|
||||
h
|
||||
8.458392 2.179011 m
|
||||
14.662457 0.579016 l
|
||||
14.899569 1.498427 l
|
||||
8.695503 3.098424 l
|
||||
8.458392 2.179011 l
|
||||
h
|
||||
14.781013 0.563974 m
|
||||
15.036198 0.563974 15.495326 0.684875 15.814721 1.047266 c
|
||||
16.180891 1.462728 16.264221 2.072176 15.934578 2.828420 c
|
||||
15.064179 2.449016 l
|
||||
15.289635 1.931793 15.160722 1.741243 15.102402 1.675073 c
|
||||
15.055794 1.622190 14.990156 1.579316 14.916806 1.549556 c
|
||||
14.881134 1.535082 14.847747 1.525430 14.820526 1.519657 c
|
||||
14.791491 1.513498 14.777695 1.513469 14.781013 1.513469 c
|
||||
14.781013 0.563974 l
|
||||
h
|
||||
15.651489 3.088437 m
|
||||
11.210685 4.590474 l
|
||||
10.906463 3.691035 l
|
||||
15.347267 2.188998 l
|
||||
15.651489 3.088437 l
|
||||
h
|
||||
10.988150 3.671260 m
|
||||
12.947328 3.377382 l
|
||||
13.088176 4.316372 l
|
||||
11.128998 4.610250 l
|
||||
10.988150 3.671260 l
|
||||
h
|
||||
12.782211 3.434681 m
|
||||
12.991495 3.315090 13.204453 3.370091 13.288217 3.396689 c
|
||||
13.400116 3.432221 13.506123 3.490767 13.598186 3.554502 c
|
||||
13.783985 3.683133 13.977411 3.877748 14.120350 4.119644 c
|
||||
14.264680 4.363894 14.369576 4.678114 14.335162 5.031647 c
|
||||
14.300108 5.391746 14.125634 5.739002 13.805044 6.049252 c
|
||||
13.144745 5.366943 l
|
||||
13.330275 5.187398 13.380290 5.040778 13.390134 4.939653 c
|
||||
13.400617 4.831963 13.370820 4.717613 13.302905 4.602680 c
|
||||
13.233600 4.485394 13.137231 4.390213 13.057724 4.335170 c
|
||||
13.017135 4.307070 12.996612 4.300308 13.000857 4.301657 c
|
||||
13.003194 4.302399 13.024761 4.309311 13.061064 4.310122 c
|
||||
13.095938 4.310902 13.170414 4.306433 13.253292 4.259073 c
|
||||
12.782211 3.434681 l
|
||||
h
|
||||
13.754128 6.092043 m
|
||||
13.394944 6.353267 l
|
||||
12.836478 5.585376 l
|
||||
13.195662 5.324152 l
|
||||
13.754128 6.092043 l
|
||||
h
|
||||
13.263074 5.518023 m
|
||||
13.593105 5.625790 14.123367 5.907292 14.433812 6.409482 c
|
||||
14.595931 6.671733 14.696482 6.993351 14.669847 7.364054 c
|
||||
14.643518 7.730516 14.495621 8.109214 14.221668 8.496526 c
|
||||
13.446486 7.948226 l
|
||||
13.646002 7.666152 13.711709 7.450294 13.722795 7.296009 c
|
||||
13.733575 7.145966 13.695351 7.020646 13.626177 6.908748 c
|
||||
13.474038 6.662641 13.171650 6.487002 12.968349 6.420619 c
|
||||
13.263074 5.518023 l
|
||||
h
|
||||
14.169774 8.558073 m
|
||||
13.810592 8.917255 l
|
||||
13.139197 8.245862 l
|
||||
13.498380 7.886679 l
|
||||
14.169774 8.558073 l
|
||||
h
|
||||
13.580109 8.118617 m
|
||||
13.896242 8.190466 14.344993 8.395787 14.624650 8.816864 c
|
||||
14.929440 9.275781 14.963785 9.882310 14.619765 10.585986 c
|
||||
13.766754 10.168959 l
|
||||
13.997427 9.697128 13.912044 9.460121 13.833706 9.342171 c
|
||||
13.730235 9.186377 13.532457 9.081495 13.369680 9.044500 c
|
||||
13.580109 8.118617 l
|
||||
h
|
||||
14.543221 10.698271 m
|
||||
13.820906 11.486253 12.989320 12.223852 11.896564 12.288132 c
|
||||
11.840808 11.340275 l
|
||||
12.524374 11.300065 13.128883 10.836036 13.843298 10.056674 c
|
||||
14.543221 10.698271 l
|
||||
h
|
||||
11.896564 12.288132 m
|
||||
11.441970 12.314873 10.711069 12.336796 10.019300 12.341186 c
|
||||
9.341933 12.345484 8.654247 12.333687 8.312695 12.284006 c
|
||||
8.449365 11.344399 l
|
||||
8.706450 11.381794 9.318512 11.396118 10.013274 11.391710 c
|
||||
10.693633 11.387392 11.407242 11.365778 11.840808 11.340275 c
|
||||
11.896564 12.288132 l
|
||||
h
|
||||
8.844993 11.713585 m
|
||||
8.948084 12.188952 9.040332 12.829445 9.094679 13.432834 c
|
||||
9.147870 14.023395 9.169946 14.631327 9.111748 15.019311 c
|
||||
8.172758 14.878462 l
|
||||
8.212520 14.613384 8.201942 14.105675 8.149012 13.518009 c
|
||||
8.097237 12.943172 8.009893 12.342852 7.917068 11.914822 c
|
||||
8.844993 11.713585 l
|
||||
h
|
||||
9.111748 15.019311 m
|
||||
8.944062 16.137217 7.805658 17.313158 6.262227 17.218662 c
|
||||
6.320251 16.270941 l
|
||||
7.336813 16.333179 8.072657 15.545805 8.172758 14.878462 c
|
||||
9.111748 15.019311 l
|
||||
h
|
||||
6.151623 17.198555 m
|
||||
5.976391 17.144638 5.715709 17.036982 5.490986 16.876261 c
|
||||
5.292936 16.734617 4.969444 16.439627 5.001374 15.992612 c
|
||||
5.948456 16.060261 l
|
||||
5.951383 16.019283 5.934667 15.999795 5.943361 16.012491 c
|
||||
5.954769 16.029152 5.984430 16.061831 6.043331 16.103956 c
|
||||
6.162553 16.189222 6.323094 16.257891 6.430855 16.291048 c
|
||||
6.151623 17.198555 l
|
||||
h
|
||||
5.001374 15.992612 m
|
||||
5.011176 15.855374 5.059216 15.566318 5.104405 15.255149 c
|
||||
5.152757 14.922197 5.207128 14.509316 5.241940 14.062993 c
|
||||
5.312967 13.152368 5.295928 12.171200 5.030037 11.457493 c
|
||||
5.919792 11.126015 l
|
||||
6.262142 12.044956 6.261431 13.202559 6.188560 14.136827 c
|
||||
6.151423 14.612950 6.093790 15.049047 6.044043 15.391605 c
|
||||
5.991133 15.755945 5.954979 15.968927 5.948456 16.060261 c
|
||||
5.001374 15.992612 l
|
||||
h
|
||||
5.030037 11.457493 m
|
||||
4.953650 11.252455 4.742510 10.903708 4.434547 10.555828 c
|
||||
4.127778 10.209298 3.769400 9.914337 3.428282 9.769621 c
|
||||
3.799107 8.895533 l
|
||||
4.320028 9.116529 4.788858 9.523607 5.145489 9.926461 c
|
||||
5.500926 10.327968 5.789377 10.775953 5.919792 11.126015 c
|
||||
5.030037 11.457493 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
7995
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
<< /Annots []
|
||||
/Type /Page
|
||||
/MediaBox [ 0.000000 0.000000 16.615845 16.660034 ]
|
||||
/Resources 1 0 R
|
||||
/Contents 2 0 R
|
||||
/Parent 5 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
5 0 obj
|
||||
<< /Kids [ 4 0 R ]
|
||||
/Count 1
|
||||
/Type /Pages
|
||||
>>
|
||||
endobj
|
||||
|
||||
6 0 obj
|
||||
<< /Pages 5 0 R
|
||||
/Type /Catalog
|
||||
>>
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 7
|
||||
0000000000 65535 f
|
||||
0000000010 00000 n
|
||||
0000000034 00000 n
|
||||
0000008085 00000 n
|
||||
0000008108 00000 n
|
||||
0000008281 00000 n
|
||||
0000008355 00000 n
|
||||
trailer
|
||||
<< /ID [ (some) (id) ]
|
||||
/Root 6 0 R
|
||||
/Size 7
|
||||
>>
|
||||
startxref
|
||||
8414
|
||||
%%EOF
|
||||
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "strike.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
damus/Assets.xcassets/strike.imageset/strike.png
vendored
|
Before Width: | Height: | Size: 23 KiB |
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "walletofsatoshi.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 42 KiB |
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "zebedee.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
damus/Assets.xcassets/zebedee.imageset/zebedee.png
vendored
|
Before Width: | Height: | Size: 78 KiB |
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "zeus.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
damus/Assets.xcassets/zeusln.imageset/zeus.png
vendored
|
Before Width: | Height: | Size: 109 KiB |
@@ -1,60 +0,0 @@
|
||||
//
|
||||
// CustomPicker.swift
|
||||
// damus
|
||||
//
|
||||
// Created by Eric Holguin on 1/22/23.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
let RECTANGLE_GRADIENT = LinearGradient(gradient: Gradient(colors: [
|
||||
Color("DamusPurple"),
|
||||
Color("DamusBlue")
|
||||
]), startPoint: .leading, endPoint: .trailing)
|
||||
|
||||
struct CustomPicker<SelectionValue: Hashable, Content: View>: View {
|
||||
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
|
||||
@Namespace var picker
|
||||
@Binding var selection: SelectionValue
|
||||
@ViewBuilder let content: Content
|
||||
|
||||
public var body: some View {
|
||||
let contentMirror = Mirror(reflecting: content)
|
||||
let blocksCount = Mirror(reflecting: contentMirror.descendant("value")!).children.count
|
||||
HStack {
|
||||
ForEach(0..<blocksCount, id: \.self) { index in
|
||||
let tupleBlock = contentMirror.descendant("value", ".\(index)")
|
||||
let text = Mirror(reflecting: tupleBlock!).descendant("content") as! Text
|
||||
let tag = Mirror(reflecting: tupleBlock!).descendant("modifier", "value", "tagged") as! SelectionValue
|
||||
|
||||
Button {
|
||||
withAnimation(.spring()) {
|
||||
selection = tag
|
||||
}
|
||||
} label: {
|
||||
text
|
||||
.padding(EdgeInsets(top: 15, leading: 0, bottom: 10, trailing: 0))
|
||||
.font(.system(size: 14, weight: .heavy))
|
||||
}
|
||||
.background(
|
||||
Group {
|
||||
if tag == selection {
|
||||
Rectangle().fill(RECTANGLE_GRADIENT).frame(height: 2.5)
|
||||
.matchedGeometryEffect(id: "selector", in: picker)
|
||||
.cornerRadius(2.5)
|
||||
}
|
||||
},
|
||||
alignment: .bottom
|
||||
)
|
||||
.frame(maxWidth: .infinity)
|
||||
.accentColor(tag == selection ? textColor() : .gray)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func textColor() -> Color {
|
||||
colorScheme == .light ? Color("DamusBlack") : Color("DamusWhite")
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
//
|
||||
// Highlight.swift
|
||||
// damus
|
||||
//
|
||||
// Created by William Casarin on 2023-01-23.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
|
||||
enum Highlight {
|
||||
case none
|
||||
case main
|
||||
case reply
|
||||
case custom(Color, Float)
|
||||
|
||||
var is_main: Bool {
|
||||
if case .main = self {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var is_none: Bool {
|
||||
if case .none = self {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var is_replied_to: Bool {
|
||||
switch self {
|
||||
case .reply: return true
|
||||
default: return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,14 +12,14 @@ import Kingfisher
|
||||
struct ShareSheet: UIViewControllerRepresentable {
|
||||
typealias Callback = (_ activityType: UIActivity.ActivityType?, _ completed: Bool, _ returnedItems: [Any]?, _ error: Error?) -> Void
|
||||
|
||||
let activityItems: [URL?]
|
||||
let activityItems: [URL]
|
||||
let callback: Callback? = nil
|
||||
let applicationActivities: [UIActivity]? = nil
|
||||
let excludedActivityTypes: [UIActivity.ActivityType]? = nil
|
||||
|
||||
func makeUIViewController(context: Context) -> UIActivityViewController {
|
||||
let controller = UIActivityViewController(
|
||||
activityItems: activityItems as [Any],
|
||||
activityItems: activityItems,
|
||||
applicationActivities: applicationActivities)
|
||||
controller.excludedActivityTypes = excludedActivityTypes
|
||||
controller.completionWithItemsHandler = callback
|
||||
@@ -32,7 +32,7 @@ struct ShareSheet: UIViewControllerRepresentable {
|
||||
}
|
||||
|
||||
struct ImageContextMenuModifier: ViewModifier {
|
||||
let url: URL?
|
||||
let url: URL
|
||||
let image: UIImage?
|
||||
@Binding var showShareSheet: Bool
|
||||
|
||||
@@ -41,44 +41,26 @@ struct ImageContextMenuModifier: ViewModifier {
|
||||
Button {
|
||||
UIPasteboard.general.url = url
|
||||
} label: {
|
||||
Label(NSLocalizedString("Copy Image URL", comment: "Context menu option to copy the URL of an image into clipboard."), systemImage: "doc.on.doc")
|
||||
Label("Copy Image URL", systemImage: "doc.on.doc")
|
||||
}
|
||||
if let someImage = image {
|
||||
Button {
|
||||
UIPasteboard.general.image = someImage
|
||||
} label: {
|
||||
Label(NSLocalizedString("Copy Image", comment: "Context menu option to copy an image into clipboard."), systemImage: "photo.on.rectangle")
|
||||
}
|
||||
Button {
|
||||
UIImageWriteToSavedPhotosAlbum(someImage, nil, nil, nil)
|
||||
} label: {
|
||||
Label(NSLocalizedString("Save Image", comment: "Context menu option to save an image."), systemImage: "square.and.arrow.down")
|
||||
Label("Copy Image", systemImage: "photo.on.rectangle")
|
||||
}
|
||||
}
|
||||
Button {
|
||||
showShareSheet = true
|
||||
} label: {
|
||||
Label(NSLocalizedString("Share", comment: "Button to share an image."), systemImage: "square.and.arrow.up")
|
||||
Label("Share", systemImage: "square.and.arrow.up")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct ImageContainerView: View {
|
||||
|
||||
@ObservedObject var imageModel: KFImageModel
|
||||
|
||||
@State private var image: UIImage?
|
||||
@State private var showShareSheet = false
|
||||
|
||||
init(url: URL?) {
|
||||
self.imageModel = KFImageModel(
|
||||
url: url,
|
||||
fallbackUrl: nil,
|
||||
maxByteSize: 2000000, // 2 MB
|
||||
downsampleSize: CGSize(width: 400, height: 400)
|
||||
)
|
||||
}
|
||||
struct ImageViewer: View {
|
||||
let urls: [URL]
|
||||
|
||||
private struct ImageHandler: ImageModifier {
|
||||
@Binding var handler: UIImage?
|
||||
@@ -88,131 +70,45 @@ private struct ImageContainerView: View {
|
||||
return image
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
|
||||
KFAnimatedImage(imageModel.url)
|
||||
.callbackQueue(.dispatch(.global(qos: .background)))
|
||||
.processingQueue(.dispatch(.global(qos: .background)))
|
||||
.cacheOriginalImage()
|
||||
.configure { view in
|
||||
view.framePreloadCount = 1
|
||||
}
|
||||
.scaleFactor(UIScreen.main.scale)
|
||||
.loadDiskFileSynchronously()
|
||||
.fade(duration: 0.1)
|
||||
.imageModifier(ImageHandler(handler: $image))
|
||||
.onFailure { _ in
|
||||
imageModel.downloadFailed()
|
||||
}
|
||||
.id(imageModel.refreshID)
|
||||
.clipped()
|
||||
.modifier(ImageContextMenuModifier(url: imageModel.url, image: image, showShareSheet: $showShareSheet))
|
||||
.sheet(isPresented: $showShareSheet) {
|
||||
ShareSheet(activityItems: [imageModel.url])
|
||||
}
|
||||
|
||||
// TODO: Update ImageCarousel with serializer and processor
|
||||
// .serialize(by: imageModel.serializer)
|
||||
// .setProcessor(imageModel.processor)
|
||||
}
|
||||
}
|
||||
|
||||
struct ImageView: View {
|
||||
@State private var image: UIImage?
|
||||
@State private var showShareSheet = false
|
||||
|
||||
let urls: [URL?]
|
||||
|
||||
@Environment(\.presentationMode) var presentationMode
|
||||
|
||||
@State private var selectedIndex = 0
|
||||
@State var showMenu = true
|
||||
|
||||
var safeAreaInsets: UIEdgeInsets? {
|
||||
return UIApplication
|
||||
.shared
|
||||
.connectedScenes
|
||||
.flatMap { ($0 as? UIWindowScene)?.windows ?? [] }
|
||||
.first { $0.isKeyWindow }?.safeAreaInsets
|
||||
}
|
||||
|
||||
var navBarView: some View {
|
||||
VStack {
|
||||
HStack {
|
||||
Text(urls[selectedIndex]?.lastPathComponent ?? "")
|
||||
.bold()
|
||||
|
||||
Spacer()
|
||||
|
||||
Button(action: {
|
||||
presentationMode.wrappedValue.dismiss()
|
||||
}, label: {
|
||||
Image(systemName: "xmark")
|
||||
})
|
||||
}
|
||||
.padding()
|
||||
|
||||
Divider()
|
||||
.ignoresSafeArea()
|
||||
func onShared(completed: Bool) -> Void {
|
||||
if (completed) {
|
||||
showShareSheet = false
|
||||
}
|
||||
.background(.regularMaterial)
|
||||
}
|
||||
|
||||
var tabViewIndicator: some View {
|
||||
HStack(spacing: 10) {
|
||||
ForEach(urls.indices, id: \.self) { index in
|
||||
Capsule()
|
||||
.fill(index == selectedIndex ? Color(UIColor.label) : Color.secondary)
|
||||
.frame(width: 7, height: 7)
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
.background(.regularMaterial)
|
||||
.clipShape(Capsule())
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
Color(.systemBackground)
|
||||
.ignoresSafeArea()
|
||||
|
||||
TabView(selection: $selectedIndex) {
|
||||
ForEach(urls.indices, id: \.self) { index in
|
||||
ZoomableScrollView {
|
||||
ImageContainerView(url: urls[index])
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.padding(.top, safeAreaInsets?.top)
|
||||
.padding(.bottom, safeAreaInsets?.bottom)
|
||||
}
|
||||
.modifier(SwipeToDismissModifier(minDistance: 50, onDismiss: {
|
||||
presentationMode.wrappedValue.dismiss()
|
||||
}))
|
||||
.ignoresSafeArea()
|
||||
.tag(index)
|
||||
TabView {
|
||||
ForEach(urls, id: \.absoluteString) { url in
|
||||
VStack{
|
||||
Text(url.lastPathComponent)
|
||||
|
||||
KFAnimatedImage(url)
|
||||
.configure { view in
|
||||
view.framePreloadCount = 3
|
||||
}
|
||||
.cacheOriginalImage()
|
||||
.imageModifier(ImageHandler(handler: $image))
|
||||
.loadDiskFileSynchronously()
|
||||
.scaleFactor(UIScreen.main.scale)
|
||||
.fade(duration: 0.1)
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.tabItem {
|
||||
Text(url.absoluteString)
|
||||
}
|
||||
.id(url.absoluteString)
|
||||
.modifier(ImageContextMenuModifier(url: url, image: image, showShareSheet: $showShareSheet))
|
||||
.sheet(isPresented: $showShareSheet) {
|
||||
ShareSheet(activityItems: [url])
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
.ignoresSafeArea()
|
||||
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
|
||||
.gesture(TapGesture(count: 2).onEnded {
|
||||
// Prevents menu from hiding on double tap
|
||||
})
|
||||
.gesture(TapGesture(count: 1).onEnded {
|
||||
showMenu.toggle()
|
||||
})
|
||||
.overlay(
|
||||
VStack {
|
||||
if showMenu {
|
||||
navBarView
|
||||
Spacer()
|
||||
|
||||
if (urls.count > 1) {
|
||||
tabViewIndicator
|
||||
}
|
||||
}
|
||||
}
|
||||
.animation(.easeInOut, value: showMenu)
|
||||
.padding(.bottom, safeAreaInsets?.bottom)
|
||||
)
|
||||
}
|
||||
.tabViewStyle(PageTabViewStyle())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,34 +122,26 @@ struct ImageCarousel: View {
|
||||
TabView {
|
||||
ForEach(urls, id: \.absoluteString) { url in
|
||||
Rectangle()
|
||||
.foregroundColor(Color.clear)
|
||||
.overlay {
|
||||
KFAnimatedImage(url)
|
||||
.callbackQueue(.dispatch(.global(qos: .background)))
|
||||
.processingQueue(.dispatch(.global(qos: .background)))
|
||||
.configure { view in
|
||||
view.framePreloadCount = 3
|
||||
}
|
||||
.cacheOriginalImage()
|
||||
.loadDiskFileSynchronously()
|
||||
.scaleFactor(UIScreen.main.scale)
|
||||
.fade(duration: 0.1)
|
||||
.configure { view in
|
||||
view.framePreloadCount = 3
|
||||
}
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.tabItem {
|
||||
Text(url.absoluteString)
|
||||
}
|
||||
.id(url.absoluteString)
|
||||
.contextMenu {
|
||||
Button(NSLocalizedString("Copy Image", comment: "Context menu option to copy an image to clipboard.")) {
|
||||
UIPasteboard.general.string = url.absoluteString
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.cornerRadius(10)
|
||||
.fullScreenCover(isPresented: $open_sheet) {
|
||||
ImageView(urls: urls)
|
||||
.sheet(isPresented: $open_sheet) {
|
||||
ImageViewer(urls: urls)
|
||||
}
|
||||
.frame(height: 200)
|
||||
.onTapGesture {
|
||||
@@ -265,6 +153,6 @@ struct ImageCarousel: View {
|
||||
|
||||
struct ImageCarousel_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
ImageCarousel(urls: [URL(string: "https://jb55.com/red-me.jpg")!,URL(string: "https://jb55.com/red-me.jpg")!])
|
||||
ImageCarousel(urls: [URL(string: "https://jb55.com/red-me.jpg")!])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,110 +8,46 @@
|
||||
import SwiftUI
|
||||
|
||||
struct InvoiceView: View {
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
@Environment(\.openURL) private var openURL
|
||||
let our_pubkey: String
|
||||
let invoice: Invoice
|
||||
@State var showing_select_wallet: Bool = false
|
||||
@State var copied = false
|
||||
|
||||
var CopyButton: some View {
|
||||
Button {
|
||||
copied = true
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
|
||||
copied = false
|
||||
}
|
||||
UIImpactFeedbackGenerator(style: .medium).impactOccurred()
|
||||
UIPasteboard.general.string = invoice.string
|
||||
} label: {
|
||||
if !copied {
|
||||
Image(systemName: "doc.on.clipboard")
|
||||
.foregroundColor(.gray)
|
||||
} else {
|
||||
Image(systemName: "checkmark.circle")
|
||||
.foregroundColor(Color("DamusGreen"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var PayButton: some View {
|
||||
Button {
|
||||
if should_show_wallet_selector(our_pubkey) {
|
||||
showing_select_wallet = true
|
||||
} else {
|
||||
open_with_wallet(wallet: get_default_wallet(our_pubkey).model, invoice: invoice.string)
|
||||
Button("Pay") {
|
||||
guard let url = URL(string: "lightning:" + invoice.string) else {
|
||||
return
|
||||
}
|
||||
} label: {
|
||||
RoundedRectangle(cornerRadius: 20, style: .circular)
|
||||
.foregroundColor(colorScheme == .light ? .black : .white)
|
||||
.overlay {
|
||||
Text("Pay", comment: "Button to pay a Lightning invoice.")
|
||||
.fontWeight(.medium)
|
||||
.foregroundColor(colorScheme == .light ? .white : .black)
|
||||
}
|
||||
}
|
||||
.onTapGesture {
|
||||
// Temporary solution so that the "pay" button can be clicked (Yes we need an empty tap gesture)
|
||||
print("pay button tap")
|
||||
UIApplication.shared.open(url)
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
RoundedRectangle(cornerRadius: 10)
|
||||
RoundedRectangle(cornerRadius: 20)
|
||||
.foregroundColor(.secondary.opacity(0.1))
|
||||
|
||||
VStack(alignment: .leading, spacing: 12) {
|
||||
VStack(alignment: .trailing, spacing: 12) {
|
||||
HStack {
|
||||
Label("", systemImage: "bolt.fill")
|
||||
.foregroundColor(.orange)
|
||||
Text("Lightning Invoice", comment: "Indicates that the view is for paying a Lightning invoice.")
|
||||
Spacer()
|
||||
CopyButton
|
||||
Text("Lightning Invoice")
|
||||
}
|
||||
Divider()
|
||||
Text(invoice.description_string)
|
||||
Text(invoice.amount.amount_sats_str())
|
||||
Text(invoice.description)
|
||||
Text("\(invoice.amount / 1000) sats")
|
||||
.font(.title)
|
||||
PayButton
|
||||
.frame(height: 50)
|
||||
.zIndex(10.0)
|
||||
.zIndex(5.0)
|
||||
}
|
||||
.padding(30)
|
||||
}
|
||||
.sheet(isPresented: $showing_select_wallet, onDismiss: {showing_select_wallet = false}) {
|
||||
SelectWalletView(showingSelectWallet: $showing_select_wallet, our_pubkey: our_pubkey, invoice: invoice.string)
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func open_with_wallet(wallet: Wallet.Model, invoice: String) {
|
||||
if let url = URL(string: "\(wallet.link)\(invoice)"), UIApplication.shared.canOpenURL(url) {
|
||||
UIApplication.shared.open(url)
|
||||
} else {
|
||||
guard let store_link = wallet.appStoreLink else {
|
||||
// TODO: do something here if we don't have an appstore link
|
||||
return
|
||||
}
|
||||
|
||||
guard let url = URL(string: store_link) else {
|
||||
return
|
||||
}
|
||||
|
||||
guard UIApplication.shared.canOpenURL(url) else {
|
||||
return
|
||||
}
|
||||
|
||||
UIApplication.shared.open(url)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let test_invoice = Invoice(description: .description("this is a description"), amount: .specific(10000), string: "lnbc100n1p357sl0sp5t9n56wdztun39lgdqlr30xqwksg3k69q4q2rkr52aplujw0esn0qpp5mrqgljk62z20q4nvgr6lzcyn6fhylzccwdvu4k77apg3zmrkujjqdpzw35xjueqd9ejqcfqv3jhxcmjd9c8g6t0dcxqyjw5qcqpjrzjqt56h4gvp5yx36u2uzqa6qwcsk3e2duunfxppzj9vhypc3wfe2wswz607uqq3xqqqsqqqqqqqqqqqlqqyg9qyysgqagx5h20aeulj3gdwx3kxs8u9f4mcakdkwuakasamm9562ffyr9en8yg20lg0ygnr9zpwp68524kmda0t5xp2wytex35pu8hapyjajxqpsql29r", expiry: 604800, payment_hash: Data(), created_at: 1666139119)
|
||||
let test_invoice = Invoice(description: "this is a description", amount: 10000, string: "lnbc100n1p357sl0sp5t9n56wdztun39lgdqlr30xqwksg3k69q4q2rkr52aplujw0esn0qpp5mrqgljk62z20q4nvgr6lzcyn6fhylzccwdvu4k77apg3zmrkujjqdpzw35xjueqd9ejqcfqv3jhxcmjd9c8g6t0dcxqyjw5qcqpjrzjqt56h4gvp5yx36u2uzqa6qwcsk3e2duunfxppzj9vhypc3wfe2wswz607uqq3xqqqsqqqqqqqqqqqlqqyg9qyysgqagx5h20aeulj3gdwx3kxs8u9f4mcakdkwuakasamm9562ffyr9en8yg20lg0ygnr9zpwp68524kmda0t5xp2wytex35pu8hapyjajxqpsql29r", expiry: 604800, payment_hash: Data(), created_at: 1666139119)
|
||||
|
||||
struct InvoiceView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
InvoiceView(our_pubkey: "", invoice: test_invoice)
|
||||
.frame(width: 300, height: 200)
|
||||
InvoiceView(invoice: test_invoice)
|
||||
.frame(width: 200, height: 200)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
import SwiftUI
|
||||
|
||||
struct InvoicesView: View {
|
||||
let our_pubkey: String
|
||||
var invoices: [Invoice]
|
||||
|
||||
@State var open_sheet: Bool = false
|
||||
@@ -17,21 +16,20 @@ struct InvoicesView: View {
|
||||
var body: some View {
|
||||
TabView {
|
||||
ForEach(invoices, id: \.string) { invoice in
|
||||
InvoiceView(our_pubkey: our_pubkey, invoice: invoice)
|
||||
InvoiceView(invoice: invoice)
|
||||
.tabItem {
|
||||
Text(invoice.string)
|
||||
}
|
||||
.id(invoice.string)
|
||||
}
|
||||
}
|
||||
.frame(height: 240)
|
||||
.frame(height: 200)
|
||||
.tabViewStyle(PageTabViewStyle())
|
||||
}
|
||||
}
|
||||
|
||||
struct InvoicesView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
InvoicesView(our_pubkey: "", invoices: [Invoice.init(description: .description("description"), amount: .specific(10000), string: "invstr", expiry: 100000, payment_hash: Data(), created_at: 1000000)])
|
||||
.frame(width: 300)
|
||||
InvoicesView(invoices: [Invoice.init(description: "description", amount: 10000, string: "invstr", expiry: 100000, payment_hash: Data(), created_at: 1000000)])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
//
|
||||
// NIP05Badge.swift
|
||||
// damus
|
||||
//
|
||||
// Created by William Casarin on 2023-01-11.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct NIP05Badge: View {
|
||||
let nip05: NIP05
|
||||
let pubkey: String
|
||||
let contacts: Contacts
|
||||
let show_domain: Bool
|
||||
let clickable: Bool
|
||||
|
||||
@Environment(\.openURL) var openURL
|
||||
|
||||
init (nip05: NIP05, pubkey: String, contacts: Contacts, show_domain: Bool, clickable: Bool) {
|
||||
self.nip05 = nip05
|
||||
self.pubkey = pubkey
|
||||
self.contacts = contacts
|
||||
self.show_domain = show_domain
|
||||
self.clickable = clickable
|
||||
}
|
||||
|
||||
var nip05_color: Color {
|
||||
return get_nip05_color(pubkey: pubkey, contacts: contacts)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
HStack(spacing: 2) {
|
||||
Image(systemName: "checkmark.seal.fill")
|
||||
.font(.footnote)
|
||||
.foregroundColor(nip05_color)
|
||||
if show_domain {
|
||||
if clickable {
|
||||
Text(nip05.host)
|
||||
.foregroundColor(nip05_color)
|
||||
.onTapGesture {
|
||||
if let nip5url = nip05.siteUrl {
|
||||
openURL(nip5url)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Text(nip05.host)
|
||||
.foregroundColor(nip05_color)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func get_nip05_color(pubkey: String, contacts: Contacts) -> Color {
|
||||
return contacts.is_friend_or_self(pubkey) ? .accentColor : .gray
|
||||
}
|
||||
|
||||
struct NIP05Badge_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
let test_state = test_damus_state()
|
||||
NIP05Badge(nip05: NIP05(username: "jb55", host: "jb55.com"), pubkey: test_state.pubkey, contacts: test_state.contacts, show_domain: true, clickable: false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
//
|
||||
// Reposted.swift
|
||||
// damus
|
||||
//
|
||||
// Created by William Casarin on 2023-01-11.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct Reposted: View {
|
||||
let damus: DamusState
|
||||
let pubkey: String
|
||||
let profile: Profile?
|
||||
|
||||
var body: some View {
|
||||
HStack(alignment: .center) {
|
||||
Image(systemName: "arrow.2.squarepath")
|
||||
.font(.footnote)
|
||||
.foregroundColor(Color.gray)
|
||||
ProfileName(pubkey: pubkey, profile: profile, damus: damus, show_friend_confirmed: true, show_nip5_domain: false)
|
||||
.foregroundColor(Color.gray)
|
||||
Text("Reposted", comment: "Text indicating that the post was reposted (i.e. re-shared).")
|
||||
.font(.footnote)
|
||||
.foregroundColor(Color.gray)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Reposted_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
let test_state = test_damus_state()
|
||||
Reposted(damus: test_state, pubkey: test_state.pubkey, profile: make_test_profile())
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ struct TextFieldAlert<Presenting>: View where Presenting: View {
|
||||
.disabled(isShowing)
|
||||
VStack {
|
||||
Text(self.title)
|
||||
TextField(NSLocalizedString("Relay", comment: "Text field for relay server. Used for testing purposes."), text: self.$text)
|
||||
TextField("Relay", text: self.$text)
|
||||
Divider()
|
||||
HStack {
|
||||
Button(action: {
|
||||
@@ -28,7 +28,7 @@ struct TextFieldAlert<Presenting>: View where Presenting: View {
|
||||
self.isShowing.toggle()
|
||||
}
|
||||
}) {
|
||||
Text("Dismiss", comment: "Button to dismiss a text field alert.")
|
||||
Text("Dismiss")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,138 +0,0 @@
|
||||
//
|
||||
// TranslateButton.swift
|
||||
// damus
|
||||
//
|
||||
// Created by William Casarin on 2023-02-02.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import NaturalLanguage
|
||||
|
||||
struct TranslateView: View {
|
||||
let damus_state: DamusState
|
||||
let event: NostrEvent
|
||||
let size: EventViewKind
|
||||
|
||||
@State var checkingTranslationStatus: Bool = false
|
||||
@State var currentLanguage: String = "en"
|
||||
@State var noteLanguage: String? = nil
|
||||
@State var translated_note: String? = nil
|
||||
@State var show_translated_note: Bool = false
|
||||
@State var translated_artifacts: NoteArtifacts? = nil
|
||||
|
||||
var TranslateButton: some View {
|
||||
Button(NSLocalizedString("Translate Note", comment: "Button to translate note from different language.")) {
|
||||
show_translated_note = true
|
||||
}
|
||||
.translate_button_style()
|
||||
}
|
||||
|
||||
func Translated(lang: String, artifacts: NoteArtifacts) -> some View {
|
||||
return Group {
|
||||
Button(NSLocalizedString("Translated from \(lang)", comment: "Button to indicate that the note has been translated from a different language.")) {
|
||||
show_translated_note = false
|
||||
}
|
||||
.translate_button_style()
|
||||
|
||||
Text(artifacts.content)
|
||||
.font(eventviewsize_to_font(size))
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
}
|
||||
|
||||
func CheckingStatus(lang: String) -> some View {
|
||||
return Button(NSLocalizedString("Translating from \(lang)...", comment: "Button to indicate that the note is in the process of being translated from a different language.")) {
|
||||
show_translated_note = false
|
||||
}
|
||||
.translate_button_style()
|
||||
}
|
||||
|
||||
func MainContent(note_lang: String) -> some View {
|
||||
return Group {
|
||||
let languageName = Locale.current.localizedString(forLanguageCode: note_lang)
|
||||
if let lang = languageName, show_translated_note {
|
||||
if checkingTranslationStatus {
|
||||
CheckingStatus(lang: lang)
|
||||
} else if let artifacts = translated_artifacts {
|
||||
Translated(lang: lang, artifacts: artifacts)
|
||||
}
|
||||
} else {
|
||||
TranslateButton
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
Group {
|
||||
if let note_lang = noteLanguage, noteLanguage != currentLanguage {
|
||||
MainContent(note_lang: note_lang)
|
||||
} else {
|
||||
Text("")
|
||||
}
|
||||
}
|
||||
.task {
|
||||
let translate_url = damus_state.settings.libretranslate_url
|
||||
let api_key = damus_state.settings.libretranslate_api_key
|
||||
|
||||
guard noteLanguage == nil && !checkingTranslationStatus && translate_url != "" else {
|
||||
return
|
||||
}
|
||||
|
||||
checkingTranslationStatus = true
|
||||
|
||||
if #available(iOS 16, *) {
|
||||
currentLanguage = Locale.current.language.languageCode?.identifier ?? "en"
|
||||
} else {
|
||||
currentLanguage = Locale.current.languageCode ?? "en"
|
||||
}
|
||||
|
||||
// Rely on Apple's NLLanguageRecognizer to tell us which language it thinks the note is in.
|
||||
let content = event.get_content(damus_state.keypair.privkey)
|
||||
noteLanguage = NLLanguageRecognizer.dominantLanguage(for: content)?.rawValue ?? currentLanguage
|
||||
|
||||
if let lang = noteLanguage, noteLanguage != currentLanguage {
|
||||
// If the detected dominant language is a variant, remove the variant component and just take the language part as LibreTranslate typically only supports the variant-less language.
|
||||
if #available(iOS 16, *) {
|
||||
noteLanguage = Locale.LanguageCode(stringLiteral: lang).identifier(.alpha2)
|
||||
} else {
|
||||
noteLanguage = Locale.canonicalLanguageIdentifier(from: lang)
|
||||
}
|
||||
}
|
||||
|
||||
guard let note_lang = noteLanguage else {
|
||||
noteLanguage = currentLanguage
|
||||
translated_note = nil
|
||||
checkingTranslationStatus = false
|
||||
return
|
||||
}
|
||||
|
||||
if note_lang != currentLanguage {
|
||||
do {
|
||||
// If the note language is different from our language, send a translation request.
|
||||
let translator = Translator(translate_url, apiKey: api_key)
|
||||
translated_note = try await translator.translate(content, from: note_lang, to: currentLanguage)
|
||||
} 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.
|
||||
noteLanguage = currentLanguage
|
||||
translated_note = nil
|
||||
}
|
||||
}
|
||||
|
||||
if let translated = translated_note {
|
||||
// Render translated note.
|
||||
let blocks = event.get_blocks(content: translated)
|
||||
translated_artifacts = render_blocks(blocks: blocks, profiles: damus_state.profiles, privkey: damus_state.keypair.privkey)
|
||||
}
|
||||
|
||||
checkingTranslationStatus = false
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct TranslateView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
let ds = test_damus_state()
|
||||
TranslateView(damus_state: ds, event: test_event, size: .selected)
|
||||
}
|
||||
}
|
||||
@@ -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,38 +0,0 @@
|
||||
//
|
||||
// WebsiteLink.swift
|
||||
// damus
|
||||
//
|
||||
// Created by William Casarin on 2023-01-22.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct WebsiteLink: View {
|
||||
let url: URL
|
||||
@Environment(\.openURL) var openURL
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
Image(systemName: "link")
|
||||
.foregroundColor(.gray)
|
||||
.font(.footnote)
|
||||
|
||||
Button(action: {
|
||||
openURL(url)
|
||||
}, label: {
|
||||
Text(link_text)
|
||||
.font(.footnote)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var link_text: String {
|
||||
url.host ?? url.absoluteString
|
||||
}
|
||||
}
|
||||
|
||||
struct WebsiteLink_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
WebsiteLink(url: URL(string: "https://jb55.com")!)
|
||||
}
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
//
|
||||
// ZapButton.swift
|
||||
// damus
|
||||
//
|
||||
// Created by William Casarin on 2023-01-17.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ZapButton: View {
|
||||
let damus_state: DamusState
|
||||
let event: NostrEvent
|
||||
let lnurl: String
|
||||
|
||||
@ObservedObject var bar: ActionBarModel
|
||||
|
||||
@State var zapping: Bool = false
|
||||
@State var invoice: String = ""
|
||||
@State var slider_value: Double = 0.0
|
||||
@State var slider_visible: Bool = false
|
||||
@State var showing_select_wallet: Bool = false
|
||||
|
||||
func send_zap() {
|
||||
guard let privkey = damus_state.keypair.privkey else {
|
||||
return
|
||||
}
|
||||
|
||||
// Only take the first 10 because reasons
|
||||
let relays = Array(damus_state.pool.descriptors.prefix(10))
|
||||
let target = ZapTarget.note(id: event.id, author: event.pubkey)
|
||||
// TODO: gather comment?
|
||||
let content = ""
|
||||
let zapreq = make_zap_request_event(pubkey: damus_state.pubkey, privkey: privkey, content: content, relays: relays, target: target)
|
||||
|
||||
zapping = true
|
||||
|
||||
Task {
|
||||
var mpayreq = damus_state.lnurls.lookup(target.pubkey)
|
||||
if mpayreq == nil {
|
||||
mpayreq = await fetch_static_payreq(lnurl)
|
||||
}
|
||||
|
||||
guard let payreq = mpayreq else {
|
||||
// TODO: show error
|
||||
DispatchQueue.main.async {
|
||||
zapping = false
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
damus_state.lnurls.endpoints[target.pubkey] = payreq
|
||||
}
|
||||
|
||||
guard let inv = await fetch_zap_invoice(payreq, zapreq: zapreq, amount: 1000000) else {
|
||||
DispatchQueue.main.async {
|
||||
zapping = false
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
zapping = false
|
||||
|
||||
if should_show_wallet_selector(damus_state.pubkey) {
|
||||
self.invoice = inv
|
||||
self.showing_select_wallet = true
|
||||
} else {
|
||||
open_with_wallet(wallet: get_default_wallet(damus_state.pubkey).model, invoice: inv)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//damus_state.pool.send(.event(zapreq))
|
||||
}
|
||||
|
||||
var zap_img: String {
|
||||
if bar.zapped {
|
||||
return "bolt.fill"
|
||||
}
|
||||
|
||||
if !zapping {
|
||||
return "bolt"
|
||||
}
|
||||
|
||||
return "bolt.horizontal.fill"
|
||||
}
|
||||
|
||||
var zap_color: Color? {
|
||||
if bar.zapped {
|
||||
return Color.orange
|
||||
}
|
||||
|
||||
if !zapping {
|
||||
return nil
|
||||
}
|
||||
|
||||
return Color.yellow
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
EventActionButton(img: zap_img, col: zap_color) {
|
||||
if bar.zapped {
|
||||
//notify(.delete, bar.our_tip)
|
||||
} else if !zapping {
|
||||
send_zap()
|
||||
}
|
||||
}
|
||||
|
||||
Text("\(bar.zap_total > 0 ? "\(format_msats_abbrev(bar.zap_total))" : "")")
|
||||
.offset(x: 22)
|
||||
.font(.footnote)
|
||||
.foregroundColor(bar.zapped ? Color.orange : Color.gray)
|
||||
}
|
||||
.sheet(isPresented: $showing_select_wallet, onDismiss: {showing_select_wallet = false}) {
|
||||
SelectWalletView(showingSelectWallet: $showing_select_wallet, our_pubkey: damus_state.pubkey, invoice: invoice)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct ZapButton_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
let bar = ActionBarModel(likes: 0, boosts: 0, zaps: 10, zap_total: 15623414, our_like: nil, our_boost: nil, our_zap: nil)
|
||||
ZapButton(damus_state: test_damus_state(), event: test_event, lnurl: "lnurl", bar: bar)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,12 +11,9 @@ import Kingfisher
|
||||
|
||||
var BOOTSTRAP_RELAYS = [
|
||||
"wss://relay.damus.io",
|
||||
"wss://eden.nostr.land",
|
||||
"wss://relay.snort.social",
|
||||
"wss://nostr.bitcoiner.social",
|
||||
"wss://nos.lol",
|
||||
"wss://relay.current.fyi",
|
||||
"wss://brb.io",
|
||||
"wss://nostr-relay.wlvs.space",
|
||||
"wss://nostr.fmt.wiz.biz",
|
||||
"wss://nostr.oxtr.dev",
|
||||
]
|
||||
|
||||
struct TimestampedProfile {
|
||||
@@ -26,12 +23,10 @@ struct TimestampedProfile {
|
||||
|
||||
enum Sheets: Identifiable {
|
||||
case post
|
||||
case report(ReportTarget)
|
||||
case reply(NostrEvent)
|
||||
|
||||
var id: String {
|
||||
switch self {
|
||||
case .report: return "report"
|
||||
case .post: return "post"
|
||||
case .reply(let ev): return "reply-" + ev.id
|
||||
}
|
||||
@@ -46,15 +41,6 @@ enum ThreadState {
|
||||
enum FilterState : Int {
|
||||
case posts_and_replies = 1
|
||||
case posts = 0
|
||||
|
||||
func filter(ev: NostrEvent) -> Bool {
|
||||
switch self {
|
||||
case .posts:
|
||||
return !ev.is_reply(nil)
|
||||
case .posts_and_replies:
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ContentView: View {
|
||||
@@ -73,7 +59,6 @@ struct ContentView: View {
|
||||
@State var damus_state: DamusState? = nil
|
||||
@State var selected_timeline: Timeline? = .home
|
||||
@State var is_thread_open: Bool = false
|
||||
@State var is_deleted_account: Bool = false
|
||||
@State var is_profile_open: Bool = false
|
||||
@State var event: NostrEvent? = nil
|
||||
@State var active_profile: String? = nil
|
||||
@@ -82,12 +67,7 @@ struct ContentView: View {
|
||||
@State var profile_open: Bool = false
|
||||
@State var thread_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 private var isSideBarOpened = false
|
||||
@StateObject var home: HomeModel = HomeModel()
|
||||
|
||||
// connect retry timer
|
||||
@@ -98,31 +78,23 @@ struct ContentView: View {
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
|
||||
var PostingTimelineView: some View {
|
||||
VStack {
|
||||
VStack{
|
||||
ZStack {
|
||||
TabView(selection: $filter_state) {
|
||||
contentTimelineView(filter: FilterState.posts.filter)
|
||||
.tag(FilterState.posts)
|
||||
.id(FilterState.posts)
|
||||
contentTimelineView(filter: FilterState.posts_and_replies.filter)
|
||||
.tag(FilterState.posts_and_replies)
|
||||
.id(FilterState.posts_and_replies)
|
||||
if let damus = self.damus_state {
|
||||
TimelineView(events: $home.events, loading: $home.loading, damus: damus, show_friend_icon: false, filter: filter_event)
|
||||
}
|
||||
.tabViewStyle(.page(indexDisplayMode: .never))
|
||||
|
||||
if privkey != nil {
|
||||
PostButtonContainer(is_left_handed: damus_state?.settings.left_handed ?? false) {
|
||||
PostButtonContainer {
|
||||
self.active_sheet = .post
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.safeAreaInset(edge: .top, spacing: 0) {
|
||||
.safeAreaInset(edge: .top) {
|
||||
VStack(spacing: 0) {
|
||||
CustomPicker(selection: $filter_state, content: {
|
||||
Text("Posts", comment: "Label for filter for seeing only posts (instead of posts and replies).").tag(FilterState.posts)
|
||||
Text("Posts & Replies", comment: "Label for filter for seeing posts and replies (instead of only posts).").tag(FilterState.posts_and_replies)
|
||||
})
|
||||
FiltersView
|
||||
//.frame(maxWidth: 275)
|
||||
.padding()
|
||||
Divider()
|
||||
.frame(height: 1)
|
||||
}
|
||||
@@ -130,14 +102,24 @@ struct ContentView: View {
|
||||
}
|
||||
}
|
||||
|
||||
func contentTimelineView(filter: (@escaping (NostrEvent) -> Bool)) -> some View {
|
||||
ZStack {
|
||||
if let damus = self.damus_state {
|
||||
TimelineView(events: $home.events, loading: $home.loading, damus: damus, show_friend_icon: false, filter: filter)
|
||||
var FiltersView: some View {
|
||||
VStack{
|
||||
Picker("Filter State", selection: $filter_state) {
|
||||
Text("Posts").tag(FilterState.posts)
|
||||
Text("Posts & Replies").tag(FilterState.posts_and_replies)
|
||||
}
|
||||
.pickerStyle(.segmented)
|
||||
}
|
||||
}
|
||||
|
||||
func filter_event(_ ev: NostrEvent) -> Bool {
|
||||
if self.filter_state == .posts {
|
||||
return !ev.is_reply(nil)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func MainContent(damus: DamusState) -> some View {
|
||||
VStack {
|
||||
NavigationLink(destination: MaybeProfileView, isActive: $profile_open) {
|
||||
@@ -158,7 +140,7 @@ struct ContentView: View {
|
||||
|
||||
case .notifications:
|
||||
TimelineView(events: $home.notifications, loading: $home.loading, damus: damus, show_friend_icon: true, filter: { _ in true })
|
||||
.navigationTitle(NSLocalizedString("Notifications", comment: "Navigation title for notifications."))
|
||||
.navigationTitle("Notifications")
|
||||
|
||||
case .dms:
|
||||
DirectMessagesView(damus_state: damus_state!)
|
||||
@@ -168,36 +150,13 @@ struct ContentView: View {
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
.navigationBarTitle(selected_timeline == .home ? NSLocalizedString("Home", comment: "Navigation bar title for Home view where posts and replies appear from those who the user is following.") : NSLocalizedString("Global", comment: "Navigation bar title for Global view where posts from all connected relay servers appear."), displayMode: .inline)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .principal) {
|
||||
switch selected_timeline {
|
||||
case .home:
|
||||
Image("damus-home")
|
||||
.resizable()
|
||||
.frame(width:30,height:30)
|
||||
.shadow(color: Color("DamusPurple"), radius: 2)
|
||||
case .dms:
|
||||
Text("DMs", comment: "Toolbar label for DMs view, where DM is the English abbreviation for Direct Message.")
|
||||
.bold()
|
||||
case .notifications:
|
||||
Text("Notifications", comment: "Toolbar label for Notifications view.")
|
||||
.bold()
|
||||
case .search:
|
||||
Text("Global", comment: "Toolbar label for Global view where posts from all connected relay servers appear.")
|
||||
.bold()
|
||||
case .none:
|
||||
Text("", comment: "Toolbar label for unknown views. This label would be displayed only if a new timeline view is added but a toolbar label was not explicitly assigned to it yet.")
|
||||
}
|
||||
}
|
||||
}
|
||||
.ignoresSafeArea(.keyboard)
|
||||
.navigationBarTitle(selected_timeline == .home ? "Home" : "Global", displayMode: .inline)
|
||||
}
|
||||
|
||||
var MaybeSearchView: some View {
|
||||
Group {
|
||||
if let search = self.active_search {
|
||||
SearchView(appstate: damus_state!, search: SearchModel(contacts: damus_state!.contacts, pool: damus_state!.pool, search: search))
|
||||
SearchView(appstate: damus_state!, search: SearchModel(pool: damus_state!.pool, search: search))
|
||||
} else {
|
||||
EmptyView()
|
||||
}
|
||||
@@ -207,7 +166,8 @@ struct ContentView: View {
|
||||
var MaybeThreadView: some View {
|
||||
Group {
|
||||
if let evid = self.active_event_id {
|
||||
BuildThreadV2View(damus: damus_state!, event_id: evid)
|
||||
let thread_model = ThreadModel(evid: evid, damus_state: damus_state!)
|
||||
ThreadView(thread: thread_model, damus: damus_state!, is_chatroom: false)
|
||||
} else {
|
||||
EmptyView()
|
||||
}
|
||||
@@ -225,65 +185,50 @@ 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 {
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
if let damus = self.damus_state {
|
||||
NavigationView {
|
||||
ZStack {
|
||||
VStack {
|
||||
MainContent(damus: damus)
|
||||
.toolbar() {
|
||||
ToolbarItem(placement: .navigationBarLeading) {
|
||||
Button {
|
||||
isSideBarOpened.toggle()
|
||||
} label: {
|
||||
ProfilePicView(pubkey: damus_state!.pubkey, size: 32, highlight: .none, profiles: damus_state!.profiles)
|
||||
}
|
||||
}
|
||||
|
||||
ToolbarItem(placement: .navigationBarTrailing) {
|
||||
HStack(alignment: .center) {
|
||||
if home.signal.signal != home.signal.max_signal {
|
||||
NavigationLink(destination: RelayConfigView(state: damus_state!)) {
|
||||
Text("\(home.signal.signal)/\(home.signal.max_signal)", comment: "Fraction of how many of the user's relay servers that are operational.")
|
||||
.font(.callout)
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
}
|
||||
MainContent(damus: damus)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .navigationBarLeading) {
|
||||
let profile_model = ProfileModel(pubkey: damus_state!.pubkey, damus: damus_state!)
|
||||
let followers_model = FollowersModel(damus_state: damus_state!, target: damus_state!.pubkey)
|
||||
let prof_dest = ProfileView(damus_state: damus_state!, profile: profile_model, followers: followers_model)
|
||||
|
||||
}
|
||||
NavigationLink(destination: prof_dest) {
|
||||
/// Verify that the user has a profile picture, if not display a generic SF Symbol
|
||||
/// (Resolves an in-app error where ``Robohash`` pictures are not generated so the button dissapears
|
||||
if let picture = damus_state?.profiles.lookup(id: pubkey)?.picture {
|
||||
ProfilePicView(pubkey: damus_state!.pubkey, size: 32, highlight: .none, profiles: damus_state!.profiles, picture: picture)
|
||||
} else {
|
||||
Image(systemName: "person.fill")
|
||||
}
|
||||
}
|
||||
.buttonStyle(PlainButtonStyle())
|
||||
}
|
||||
|
||||
ToolbarItem(placement: .navigationBarTrailing) {
|
||||
HStack(alignment: .center) {
|
||||
if home.signal.signal != home.signal.max_signal {
|
||||
Text("\(home.signal.signal)/\(home.signal.max_signal)")
|
||||
.font(.callout)
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
|
||||
NavigationLink(destination: ConfigView(state: damus_state!)) {
|
||||
Label("", systemImage: "gear")
|
||||
}
|
||||
.buttonStyle(PlainButtonStyle())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Color.clear
|
||||
.overlay(
|
||||
SideMenuView(damus_state: damus, isSidebarVisible: $isSideBarOpened)
|
||||
)
|
||||
}
|
||||
.navigationBarHidden(isSideBarOpened ? true: false) // Would prefer a different way of doing this.
|
||||
}
|
||||
.navigationViewStyle(.stack)
|
||||
|
||||
TabBar(new_events: $home.new_events, selected: $selected_timeline, isSidebarVisible: $isSideBarOpened, action: switch_timeline)
|
||||
.padding([.bottom], 8)
|
||||
}
|
||||
|
||||
TabBar(new_events: $home.new_events, selected: $selected_timeline, action: switch_timeline)
|
||||
}
|
||||
.onAppear() {
|
||||
self.connect()
|
||||
@@ -292,10 +237,8 @@ struct ContentView: View {
|
||||
}
|
||||
.sheet(item: $active_sheet) { item in
|
||||
switch item {
|
||||
case .report(let target):
|
||||
MaybeReportView(target: target)
|
||||
case .post:
|
||||
PostView(replying_to: nil, references: [], damus_state: damus_state!)
|
||||
PostView(replying_to: nil, references: [])
|
||||
case .reply(let event):
|
||||
ReplyView(replying_to: event, damus: damus_state!)
|
||||
}
|
||||
@@ -326,6 +269,7 @@ struct ContentView: View {
|
||||
guard let privkey = self.privkey else {
|
||||
return
|
||||
}
|
||||
|
||||
let ev = notif.object as! NostrEvent
|
||||
let boost = make_boost_event(pubkey: pubkey, privkey: privkey, boosted: ev)
|
||||
self.damus_state?.pool.send(.event(boost))
|
||||
@@ -341,18 +285,6 @@ struct ContentView: View {
|
||||
}
|
||||
.onReceive(handle_notify(.like)) { like in
|
||||
}
|
||||
.onReceive(handle_notify(.deleted_account)) { notif in
|
||||
self.is_deleted_account = true
|
||||
}
|
||||
.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
|
||||
let ev = obj.object as! NostrEvent
|
||||
self.damus_state?.pool.send(.event(ev))
|
||||
@@ -370,10 +302,10 @@ struct ContentView: View {
|
||||
let pk = target.pubkey
|
||||
|
||||
if let ev = unfollow_user(pool: damus.pool,
|
||||
our_contacts: damus.contacts.event,
|
||||
pubkey: damus.pubkey,
|
||||
privkey: privkey,
|
||||
unfollow: pk) {
|
||||
our_contacts: damus.contacts.event,
|
||||
pubkey: damus.pubkey,
|
||||
privkey: privkey,
|
||||
unfollow: pk) {
|
||||
notify(.unfollowed, pk)
|
||||
|
||||
damus.contacts.event = ev
|
||||
@@ -392,10 +324,10 @@ struct ContentView: View {
|
||||
}
|
||||
|
||||
if let ev = follow_user(pool: damus.pool,
|
||||
our_contacts: damus.contacts.event,
|
||||
pubkey: damus.pubkey,
|
||||
privkey: privkey,
|
||||
follow: ReferencedId(ref_id: fnotify.pubkey, relay_id: nil, key: "p")) {
|
||||
our_contacts: damus.contacts.event,
|
||||
pubkey: damus.pubkey,
|
||||
privkey: privkey,
|
||||
follow: ReferencedId(ref_id: fnotify.pubkey, relay_id: nil, key: "p")) {
|
||||
notify(.followed, fnotify.pubkey)
|
||||
|
||||
damus_state?.contacts.event = ev
|
||||
@@ -427,96 +359,6 @@ struct ContentView: View {
|
||||
.onReceive(timer) { n in
|
||||
self.damus_state?.pool.connect_to_disconnected()
|
||||
}
|
||||
.onReceive(handle_notify(.new_mutes)) { notif in
|
||||
home.filter_muted()
|
||||
}
|
||||
.alert(NSLocalizedString("Deleted Account", comment: "Alert message to indicate this is a deleted account"), isPresented: $is_deleted_account) {
|
||||
Button(NSLocalizedString("Logout", comment: "Button to close the alert that informs that the current account has been deleted.")) {
|
||||
is_deleted_account = false
|
||||
notify(.logout, ())
|
||||
}
|
||||
}
|
||||
.alert(NSLocalizedString("User blocked", comment: "Alert message to indicate the user has been blocked"), 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) {
|
||||
@@ -555,14 +397,10 @@ struct ContentView: View {
|
||||
self.damus_state = DamusState(pool: pool, keypair: keypair,
|
||||
likes: EventCounter(our_pubkey: pubkey),
|
||||
boosts: EventCounter(our_pubkey: pubkey),
|
||||
contacts: Contacts(our_pubkey: pubkey),
|
||||
contacts: Contacts(),
|
||||
tips: TipCounter(our_pubkey: pubkey),
|
||||
profiles: Profiles(),
|
||||
dms: home.dms,
|
||||
previews: PreviewCache(),
|
||||
zaps: Zaps(our_pubkey: pubkey),
|
||||
lnurls: LNUrls(),
|
||||
settings: UserSettingsStore()
|
||||
dms: home.dms
|
||||
)
|
||||
home.damus_state = self.damus_state!
|
||||
|
||||
@@ -578,6 +416,7 @@ struct ContentView_Previews: PreviewProvider {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func get_since_time(last_event: NostrEvent?) -> Int64? {
|
||||
if let last_event = last_event {
|
||||
return last_event.created_at - 60 * 10
|
||||
|
||||
@@ -15,22 +15,6 @@
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>LSApplicationQueriesSchemes</key>
|
||||
<array>
|
||||
<string>river</string>
|
||||
<string>bitcoinbeach</string>
|
||||
<string>breez</string>
|
||||
<string>muun</string>
|
||||
<string>zeusln</string>
|
||||
<string>zebedee</string>
|
||||
<string>lightning</string>
|
||||
<string>phoenix</string>
|
||||
<string>lnlink</string>
|
||||
<string>strike</string>
|
||||
<string>bluewallet</string>
|
||||
<string>walletofsatoshi</string>
|
||||
<string>blixtwallet</string>
|
||||
</array>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
|
||||
@@ -11,32 +11,22 @@ import Foundation
|
||||
class ActionBarModel: ObservableObject {
|
||||
@Published var our_like: NostrEvent?
|
||||
@Published var our_boost: NostrEvent?
|
||||
@Published var our_zap: Zap?
|
||||
@Published var our_tip: NostrEvent?
|
||||
@Published var likes: Int
|
||||
@Published var boosts: Int
|
||||
@Published var zaps: Int
|
||||
@Published var zap_total: Int64
|
||||
@Published var tips: Int64
|
||||
|
||||
static func empty() -> ActionBarModel {
|
||||
return ActionBarModel(likes: 0, boosts: 0, zaps: 0, zap_total: 0, our_like: nil, our_boost: nil, our_zap: nil)
|
||||
}
|
||||
|
||||
init(likes: Int, boosts: Int, zaps: Int, zap_total: Int64, our_like: NostrEvent?, our_boost: NostrEvent?, our_zap: Zap?) {
|
||||
init(likes: Int, boosts: Int, tips: Int64, our_like: NostrEvent?, our_boost: NostrEvent?, our_tip: NostrEvent?) {
|
||||
self.likes = likes
|
||||
self.boosts = boosts
|
||||
self.zaps = zaps
|
||||
self.zap_total = zap_total
|
||||
self.tips = tips
|
||||
self.our_like = our_like
|
||||
self.our_boost = our_boost
|
||||
self.our_zap = our_zap
|
||||
self.our_tip = our_tip
|
||||
}
|
||||
|
||||
var is_empty: Bool {
|
||||
return likes == 0 && boosts == 0 && zaps == 0
|
||||
}
|
||||
|
||||
var zapped: Bool {
|
||||
return our_zap != nil
|
||||
var tipped: Bool {
|
||||
return our_tip != nil
|
||||
}
|
||||
|
||||
var liked: Bool {
|
||||
|
||||
@@ -11,50 +11,7 @@ import Foundation
|
||||
class Contacts {
|
||||
private var friends: Set<String> = Set()
|
||||
private var friend_of_friends: Set<String> = Set()
|
||||
private var muted: Set<String> = Set()
|
||||
|
||||
let our_pubkey: String
|
||||
var event: NostrEvent?
|
||||
var mutelist: NostrEvent?
|
||||
|
||||
init(our_pubkey: String) {
|
||||
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] {
|
||||
var fs = get_friend_list()
|
||||
@@ -99,10 +56,6 @@ class Contacts {
|
||||
return friends.contains(pubkey)
|
||||
}
|
||||
|
||||
func is_friend_or_self(_ pubkey: String) -> Bool {
|
||||
return pubkey == our_pubkey || is_friend(pubkey)
|
||||
}
|
||||
|
||||
func follow_state(_ pubkey: String) -> FollowState {
|
||||
return is_friend(pubkey) ? .follows : .unfollows
|
||||
}
|
||||
@@ -186,12 +139,16 @@ func decode_json_relays(_ content: String) -> [String: RelayInfo]? {
|
||||
return decode_json(content)
|
||||
}
|
||||
|
||||
func remove_relay(ev: NostrEvent, current_relays: [RelayDescriptor], privkey: String, relay: String) -> NostrEvent? {
|
||||
var relays = ensure_relay_info(relays: current_relays, content: ev.content)
|
||||
func remove_relay(ev: NostrEvent, privkey: String, relay: String) -> NostrEvent? {
|
||||
let damus_relay = RelayDescriptor(url: URL(string: "wss://relay.damus.io")!, info: .rw)
|
||||
|
||||
var relays = ensure_relay_info(relays: [damus_relay], content: ev.content)
|
||||
guard relays.index(forKey: relay) != nil else {
|
||||
return nil
|
||||
}
|
||||
|
||||
relays.removeValue(forKey: relay)
|
||||
|
||||
print("remove_relay \(relays)")
|
||||
guard let content = encode_json(relays) else {
|
||||
return nil
|
||||
}
|
||||
@@ -202,9 +159,10 @@ func remove_relay(ev: NostrEvent, current_relays: [RelayDescriptor], privkey: St
|
||||
return new_ev
|
||||
}
|
||||
|
||||
func add_relay(ev: NostrEvent, privkey: String, current_relays: [RelayDescriptor], relay: String, info: RelayInfo) -> NostrEvent? {
|
||||
var relays = ensure_relay_info(relays: current_relays, content: ev.content)
|
||||
func add_relay(ev: NostrEvent, privkey: String, relay: String, info: RelayInfo) -> NostrEvent? {
|
||||
let damus_relay = RelayDescriptor(url: URL(string: "wss://relay.damus.io")!, info: .rw)
|
||||
|
||||
var relays = ensure_relay_info(relays: [damus_relay], content: ev.content)
|
||||
guard relays.index(forKey: relay) == nil else {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import LinkPresentation
|
||||
|
||||
struct DamusState {
|
||||
let pool: RelayPool
|
||||
@@ -17,21 +16,12 @@ struct DamusState {
|
||||
let tips: TipCounter
|
||||
let profiles: Profiles
|
||||
let dms: DirectMessagesModel
|
||||
let previews: PreviewCache
|
||||
let zaps: Zaps
|
||||
let lnurls: LNUrls
|
||||
let settings: UserSettingsStore
|
||||
|
||||
var pubkey: String {
|
||||
return keypair.pubkey
|
||||
}
|
||||
|
||||
var is_privkey_user: Bool {
|
||||
keypair.privkey != nil
|
||||
}
|
||||
|
||||
|
||||
static var empty: DamusState {
|
||||
return DamusState.init(pool: RelayPool(), keypair: Keypair(pubkey: "", privkey: ""), likes: EventCounter(our_pubkey: ""), boosts: EventCounter(our_pubkey: ""), contacts: Contacts(our_pubkey: ""), tips: TipCounter(our_pubkey: ""), profiles: Profiles(), dms: DirectMessagesModel(our_pubkey: ""), previews: PreviewCache(), zaps: Zaps(our_pubkey: ""), lnurls: LNUrls(), settings: UserSettingsStore())
|
||||
return DamusState.init(pool: RelayPool(), keypair: Keypair(pubkey: "", privkey: ""), likes: EventCounter(our_pubkey: ""), boosts: EventCounter(our_pubkey: ""), contacts: Contacts(), tips: TipCounter(our_pubkey: ""), profiles: Profiles(), dms: DirectMessagesModel())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,34 +8,13 @@
|
||||
import Foundation
|
||||
|
||||
class DirectMessageModel: ObservableObject {
|
||||
@Published var events: [NostrEvent] {
|
||||
didSet {
|
||||
is_request = determine_is_request()
|
||||
}
|
||||
}
|
||||
@Published var events: [NostrEvent]
|
||||
|
||||
var is_request: Bool
|
||||
var our_pubkey: String
|
||||
|
||||
func determine_is_request() -> Bool {
|
||||
for event in events {
|
||||
if event.pubkey == our_pubkey {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
init(events: [NostrEvent], our_pubkey: String) {
|
||||
init(events: [NostrEvent]) {
|
||||
self.events = events
|
||||
self.is_request = false
|
||||
self.our_pubkey = our_pubkey
|
||||
}
|
||||
|
||||
init(our_pubkey: String) {
|
||||
init() {
|
||||
self.events = []
|
||||
self.is_request = false
|
||||
self.our_pubkey = our_pubkey
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,26 +10,13 @@ import Foundation
|
||||
class DirectMessagesModel: ObservableObject {
|
||||
@Published var dms: [(String, DirectMessageModel)] = []
|
||||
@Published var loading: Bool = false
|
||||
let our_pubkey: String
|
||||
|
||||
init(our_pubkey: String) {
|
||||
self.our_pubkey = our_pubkey
|
||||
}
|
||||
|
||||
var message_requests: [(String, DirectMessageModel)] {
|
||||
return dms.filter { dm in dm.1.is_request }
|
||||
}
|
||||
|
||||
var friend_dms: [(String, DirectMessageModel)] {
|
||||
return dms.filter { dm in !dm.1.is_request }
|
||||
}
|
||||
|
||||
func lookup_or_create(_ pubkey: String) -> DirectMessageModel {
|
||||
if let dm = lookup(pubkey) {
|
||||
return dm
|
||||
}
|
||||
|
||||
let new = DirectMessageModel(our_pubkey: our_pubkey)
|
||||
let new = DirectMessageModel()
|
||||
dms.append((pubkey, new))
|
||||
return new
|
||||
}
|
||||
|
||||
@@ -18,11 +18,11 @@ class FollowersModel: ObservableObject {
|
||||
let sub_id: String = UUID().description
|
||||
let profiles_id: String = UUID().description
|
||||
|
||||
var count: Int? {
|
||||
var count_display: String {
|
||||
guard let contacts = self.contacts else {
|
||||
return nil
|
||||
return "?"
|
||||
}
|
||||
return contacts.count
|
||||
return "\(contacts.count)";
|
||||
}
|
||||
|
||||
init(damus_state: DamusState, target: String) {
|
||||
@@ -73,30 +73,31 @@ class FollowersModel: ObservableObject {
|
||||
}
|
||||
|
||||
func handle_event(relay_id: String, ev: NostrConnectionEvent) {
|
||||
guard case .nostr_event(let nev) = ev else {
|
||||
return
|
||||
}
|
||||
|
||||
switch nev {
|
||||
case .event(let sub_id, let ev):
|
||||
guard sub_id == self.sub_id || sub_id == self.profiles_id else {
|
||||
return
|
||||
}
|
||||
|
||||
if ev.known_kind == .contacts {
|
||||
handle_contact_event(ev)
|
||||
} else if ev.known_kind == .metadata {
|
||||
process_metadata_event(our_pubkey: damus_state.pubkey, profiles: damus_state.profiles, ev: ev)
|
||||
}
|
||||
|
||||
case .notice(let msg):
|
||||
print("followingmodel notice: \(msg)")
|
||||
|
||||
case .eose(let sub_id):
|
||||
if sub_id == self.sub_id {
|
||||
load_profiles(relay_id: relay_id)
|
||||
} else if sub_id == self.profiles_id {
|
||||
damus_state.pool.unsubscribe(sub_id: profiles_id, to: [relay_id])
|
||||
switch ev {
|
||||
case .ws_event:
|
||||
break
|
||||
case .nostr_event(let nev):
|
||||
switch nev {
|
||||
case .event(let sub_id, let ev):
|
||||
guard sub_id == self.sub_id || sub_id == self.profiles_id else {
|
||||
return
|
||||
}
|
||||
|
||||
if ev.known_kind == .contacts {
|
||||
handle_contact_event(ev)
|
||||
} else if ev.known_kind == .metadata {
|
||||
process_metadata_event(profiles: damus_state.profiles, ev: ev)
|
||||
}
|
||||
|
||||
case .notice(let msg):
|
||||
print("followingmodel notice: \(msg)")
|
||||
|
||||
case .eose(let sub_id):
|
||||
if sub_id == self.sub_id {
|
||||
load_profiles(relay_id: relay_id)
|
||||
} else if sub_id == self.profiles_id {
|
||||
damus_state.pool.unsubscribe(sub_id: profiles_id, to: [relay_id])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ class FollowingModel {
|
||||
switch nev {
|
||||
case .event(_, let ev):
|
||||
if ev.kind == 0 {
|
||||
process_metadata_event(our_pubkey: damus_state.pubkey, profiles: damus_state.profiles, ev: ev)
|
||||
process_metadata_event(profiles: damus_state.profiles, ev: ev)
|
||||
}
|
||||
case .notice(let msg):
|
||||
print("followingmodel notice: \(msg)")
|
||||
|
||||
@@ -44,23 +44,20 @@ class HomeModel: ObservableObject {
|
||||
let notifications_subid = UUID().description
|
||||
let dms_subid = UUID().description
|
||||
let init_subid = UUID().description
|
||||
let profiles_subid = UUID().description
|
||||
|
||||
@Published var new_events: NewEventsBits = NewEventsBits()
|
||||
@Published var notifications: [NostrEvent] = []
|
||||
@Published var dms: DirectMessagesModel
|
||||
@Published var dms: DirectMessagesModel = DirectMessagesModel()
|
||||
@Published var events: [NostrEvent] = []
|
||||
@Published var loading: Bool = false
|
||||
@Published var signal: SignalModel = SignalModel()
|
||||
|
||||
init() {
|
||||
self.damus_state = DamusState.empty
|
||||
self.dms = DirectMessagesModel(our_pubkey: damus_state.pubkey)
|
||||
}
|
||||
|
||||
init(damus_state: DamusState) {
|
||||
self.damus_state = damus_state
|
||||
self.dms = DirectMessagesModel(our_pubkey: damus_state.pubkey)
|
||||
}
|
||||
|
||||
var pool: RelayPool {
|
||||
@@ -98,8 +95,6 @@ class HomeModel: ObservableObject {
|
||||
handle_contact_event(sub_id: sub_id, relay_id: relay_id, ev: ev)
|
||||
case .metadata:
|
||||
handle_metadata_event(ev)
|
||||
case .list:
|
||||
handle_list_event(ev)
|
||||
case .boost:
|
||||
handle_boost_event(sub_id: sub_id, ev)
|
||||
case .like:
|
||||
@@ -112,61 +107,9 @@ class HomeModel: ObservableObject {
|
||||
handle_channel_create(ev)
|
||||
case .channel_meta:
|
||||
handle_channel_meta(ev)
|
||||
case .zap:
|
||||
handle_zap_event(ev)
|
||||
}
|
||||
}
|
||||
|
||||
func handle_zap_event_with_zapper(_ ev: NostrEvent, zapper: String) {
|
||||
guard let zap = Zap.from_zap_event(zap_ev: ev, zapper: zapper) else {
|
||||
return
|
||||
}
|
||||
|
||||
damus_state.zaps.add_zap(zap: zap)
|
||||
|
||||
if !insert_uniq_sorted_event(events: ¬ifications, new_ev: ev, cmp: { $0.created_at > $1.created_at }) {
|
||||
return
|
||||
}
|
||||
|
||||
handle_last_event(ev: ev, timeline: .notifications)
|
||||
return
|
||||
}
|
||||
|
||||
func handle_zap_event(_ ev: NostrEvent) {
|
||||
// These are zap notifications
|
||||
guard let ptag = event_tag(ev, name: "p") else {
|
||||
return
|
||||
}
|
||||
|
||||
guard ptag == damus_state.pubkey else {
|
||||
return
|
||||
}
|
||||
|
||||
if let local_zapper = damus_state.profiles.lookup_zapper(pubkey: damus_state.pubkey) {
|
||||
handle_zap_event_with_zapper(ev, zapper: local_zapper)
|
||||
return
|
||||
}
|
||||
|
||||
guard let profile = damus_state.profiles.lookup(id: damus_state.pubkey) else {
|
||||
return
|
||||
}
|
||||
|
||||
guard let lnurl = profile.lnurl else {
|
||||
return
|
||||
}
|
||||
|
||||
Task {
|
||||
guard let zapper = await fetch_zapper_from_lnurl(lnurl) else {
|
||||
return
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.handle_zap_event_with_zapper(ev, zapper: zapper)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func handle_channel_create(_ ev: NostrEvent) {
|
||||
guard ev.is_valid else {
|
||||
return
|
||||
@@ -178,12 +121,6 @@ class HomeModel: ObservableObject {
|
||||
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) {
|
||||
guard ev.is_valid else {
|
||||
return
|
||||
@@ -286,7 +223,7 @@ class HomeModel: ObservableObject {
|
||||
switch ev {
|
||||
case .event(let sub_id, let ev):
|
||||
// globally handle likes
|
||||
let always_process = sub_id == notifications_subid || sub_id == contacts_subid || sub_id == home_subid || sub_id == dms_subid || sub_id == init_subid || ev.known_kind == .like || ev.known_kind == .zap || ev.known_kind == .contacts || ev.known_kind == .metadata
|
||||
let always_process = sub_id == notifications_subid || sub_id == contacts_subid || sub_id == home_subid || sub_id == dms_subid || sub_id == init_subid || ev.known_kind == .like || ev.known_kind == .contacts || ev.known_kind == .metadata
|
||||
if !always_process {
|
||||
// TODO: other views like threads might have their own sub ids, so ignore those events... or should we?
|
||||
return
|
||||
@@ -297,15 +234,7 @@ class HomeModel: ObservableObject {
|
||||
//self.events.insert(NostrEvent(content: "NOTICE from \(relay_id): \(msg)", pubkey: "system"), at: 0)
|
||||
print(msg)
|
||||
|
||||
case .eose(let sub_id):
|
||||
|
||||
if sub_id == dms_subid {
|
||||
let dms = dms.dms.flatMap { $0.1.events }
|
||||
load_profiles(profiles_subid: profiles_subid, relay_id: relay_id, events: dms, damus_state: damus_state)
|
||||
} else if sub_id == notifications_subid {
|
||||
load_profiles(profiles_subid: profiles_subid, relay_id: relay_id, events: notifications, damus_state: damus_state)
|
||||
}
|
||||
|
||||
case .eose:
|
||||
self.loading = false
|
||||
break
|
||||
}
|
||||
@@ -331,14 +260,7 @@ class HomeModel: ObservableObject {
|
||||
|
||||
var contacts_filter = NostrFilter.filter_kinds([0])
|
||||
contacts_filter.authors = friends
|
||||
|
||||
var our_contacts_filter = NostrFilter.filter_kinds([3, 0])
|
||||
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([
|
||||
NostrKind.dm.rawValue,
|
||||
])
|
||||
@@ -369,14 +291,13 @@ class HomeModel: ObservableObject {
|
||||
NostrKind.chat.rawValue,
|
||||
NostrKind.like.rawValue,
|
||||
NostrKind.boost.rawValue,
|
||||
NostrKind.zap.rawValue,
|
||||
])
|
||||
notifications_filter.pubkeys = [damus_state.pubkey]
|
||||
notifications_filter.limit = 100
|
||||
|
||||
var home_filters = [home_filter]
|
||||
var notifications_filters = [notifications_filter]
|
||||
var contacts_filters = [contacts_filter, our_contacts_filter, our_blocklist_filter]
|
||||
var contacts_filters = [contacts_filter]
|
||||
var dms_filters = [dms_filter, our_dms_filter]
|
||||
|
||||
let last_of_kind = relay_id.flatMap { last_event_of_kind[$0] } ?? [:]
|
||||
@@ -400,32 +321,9 @@ class HomeModel: ObservableObject {
|
||||
pool.send(.subscribe(.init(filters: dms_filters, sub_id: dms_subid)))
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
process_metadata_event(our_pubkey: damus_state.pubkey, profiles: damus_state.profiles, ev: ev)
|
||||
process_metadata_event(profiles: damus_state.profiles, ev: ev)
|
||||
}
|
||||
|
||||
func get_last_event_of_kind(relay_id: String, kind: Int) -> NostrEvent? {
|
||||
@@ -437,23 +335,22 @@ class HomeModel: ObservableObject {
|
||||
return m[kind]
|
||||
}
|
||||
|
||||
func handle_notification(ev: NostrEvent) {
|
||||
guard event_has_our_pubkey(ev, our_pubkey: self.damus_state.pubkey) else {
|
||||
return
|
||||
func handle_last_event(ev: NostrEvent, timeline: Timeline) {
|
||||
let last_ev = get_last_event(timeline)
|
||||
|
||||
if last_ev == nil || last_ev!.created_at < ev.created_at {
|
||||
save_last_event(ev, timeline: timeline)
|
||||
new_events = NewEventsBits(prev: new_events, setting: timeline)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func handle_notification(ev: NostrEvent) {
|
||||
if !insert_uniq_sorted_event(events: ¬ifications, new_ev: ev, cmp: { $0.created_at > $1.created_at }) {
|
||||
return
|
||||
}
|
||||
|
||||
handle_last_event(ev: ev, timeline: .notifications)
|
||||
}
|
||||
|
||||
func handle_last_event(ev: NostrEvent, timeline: Timeline, shouldNotify: Bool = true) {
|
||||
if let new_bits = handle_last_events(new_events: self.new_events, ev: ev, timeline: timeline, shouldNotify: shouldNotify) {
|
||||
new_events = new_bits
|
||||
}
|
||||
}
|
||||
|
||||
func insert_home_event(_ ev: NostrEvent) -> Bool {
|
||||
let ok = insert_uniq_sorted_event(events: &self.events, new_ev: ev, cmp: { $0.created_at > $1.created_at })
|
||||
@@ -463,8 +360,12 @@ class HomeModel: ObservableObject {
|
||||
return ok
|
||||
}
|
||||
|
||||
func should_hide_event(_ ev: NostrEvent) -> Bool {
|
||||
return !ev.should_show_event
|
||||
}
|
||||
|
||||
func handle_text_event(sub_id: String, _ ev: NostrEvent) {
|
||||
guard should_show_event(contacts: damus_state.contacts, ev: ev) else {
|
||||
if should_hide_event(ev) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -476,8 +377,49 @@ class HomeModel: ObservableObject {
|
||||
}
|
||||
|
||||
func handle_dm(_ ev: NostrEvent) {
|
||||
if let notifs = handle_incoming_dm(contacts: damus_state.contacts, prev_events: self.new_events, dms: self.dms, our_pubkey: self.damus_state.pubkey, ev: ev) {
|
||||
self.new_events = notifs
|
||||
|
||||
var inserted = false
|
||||
var found = false
|
||||
let ours = ev.pubkey == self.damus_state.pubkey
|
||||
var i = 0
|
||||
|
||||
var the_pk = ev.pubkey
|
||||
if ours {
|
||||
if let ref_pk = ev.referenced_pubkeys.first {
|
||||
the_pk = ref_pk.ref_id
|
||||
} else {
|
||||
// self dm!?
|
||||
print("TODO: handle self dm?")
|
||||
}
|
||||
}
|
||||
|
||||
for (pk, _) in dms.dms {
|
||||
if pk == the_pk {
|
||||
found = true
|
||||
inserted = insert_uniq_sorted_event(events: &(dms.dms[i].1.events), new_ev: ev) {
|
||||
$0.created_at < $1.created_at
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
|
||||
if !found {
|
||||
inserted = true
|
||||
let model = DirectMessageModel(events: [ev])
|
||||
dms.dms.append((the_pk, model))
|
||||
}
|
||||
|
||||
if inserted {
|
||||
handle_last_event(ev: ev, timeline: .dms)
|
||||
|
||||
dms.dms = dms.dms.sorted { a, b in
|
||||
if a.1.events.count > 0 && b.1.events.count > 0 {
|
||||
return a.1.events.last!.created_at > b.1.events.last!.created_at
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -501,33 +443,18 @@ func add_contact_if_friend(contacts: Contacts, ev: NostrEvent) {
|
||||
contacts.add_friend_contact(ev)
|
||||
}
|
||||
|
||||
func load_our_contacts(contacts: Contacts, our_pubkey: String, m_old_ev: NostrEvent?, ev: NostrEvent) {
|
||||
var new_pks = Set<String>()
|
||||
func load_our_contacts(contacts: Contacts, our_pubkey: String, ev: NostrEvent) {
|
||||
guard ev.pubkey == our_pubkey else {
|
||||
return
|
||||
}
|
||||
|
||||
contacts.event = ev
|
||||
|
||||
// our contacts
|
||||
for tag in ev.tags {
|
||||
if tag.count >= 2 && tag[0] == "p" {
|
||||
new_pks.insert(tag[1])
|
||||
}
|
||||
}
|
||||
|
||||
var old_pks = Set<String>()
|
||||
// find removed contacts
|
||||
if let old_ev = m_old_ev {
|
||||
for tag in old_ev.tags {
|
||||
if tag.count >= 2 && tag[0] == "p" {
|
||||
old_pks.insert(tag[1])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let diff = new_pks.symmetricDifference(old_pks)
|
||||
for pk in diff {
|
||||
if new_pks.contains(pk) {
|
||||
notify(.followed, pk)
|
||||
contacts.add_friend_pubkey(pk)
|
||||
} else {
|
||||
notify(.unfollowed, pk)
|
||||
contacts.remove_friend(pk)
|
||||
if tag.count > 1 && tag[0] == "p" {
|
||||
// TODO: validate pubkey?
|
||||
contacts.add_friend_pubkey(tag[1])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -583,21 +510,12 @@ func print_filters(relay_id: String?, filters groups: [[NostrFilter]]) {
|
||||
print("-----")
|
||||
}
|
||||
|
||||
func process_metadata_event(our_pubkey: String, profiles: Profiles, ev: NostrEvent) {
|
||||
func process_metadata_event(profiles: Profiles, ev: NostrEvent) {
|
||||
guard let profile: Profile = decode_data(Data(ev.content.utf8)) else {
|
||||
return
|
||||
}
|
||||
|
||||
if our_pubkey == ev.pubkey && (profile.deleted ?? false) {
|
||||
DispatchQueue.main.async {
|
||||
notify(.deleted_account, ())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var old_nip05: String? = nil
|
||||
if let mprof = profiles.lookup_with_timestamp(id: ev.pubkey) {
|
||||
old_nip05 = mprof.profile.nip05
|
||||
if mprof.timestamp > ev.created_at {
|
||||
// skip if we already have an newer profile
|
||||
return
|
||||
@@ -607,20 +525,6 @@ func process_metadata_event(our_pubkey: String, profiles: Profiles, ev: NostrEve
|
||||
let tprof = TimestampedProfile(profile: profile, timestamp: ev.created_at)
|
||||
profiles.add(id: ev.pubkey, profile: tprof)
|
||||
|
||||
if let nip05 = profile.nip05, old_nip05 != profile.nip05 {
|
||||
Task.detached(priority: .background) {
|
||||
let validated = await validate_nip05(pubkey: ev.pubkey, nip05_str: nip05)
|
||||
if validated != nil {
|
||||
print("validated nip05 for '\(nip05)'")
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
profiles.validated[ev.pubkey] = validated
|
||||
notify(.profile_updated, ProfileUpdate(pubkey: ev.pubkey, profile: profile))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// load pfps asap
|
||||
let picture = tprof.profile.picture ?? robohash(ev.pubkey)
|
||||
if let _ = URL(string: picture) {
|
||||
@@ -629,13 +533,6 @@ func process_metadata_event(our_pubkey: String, profiles: Profiles, ev: NostrEve
|
||||
}
|
||||
}
|
||||
|
||||
let banner = tprof.profile.banner ?? ""
|
||||
if let _ = URL(string: banner) {
|
||||
DispatchQueue.main.async {
|
||||
notify(.profile_updated, ProfileUpdate(pubkey: ev.pubkey, profile: profile))
|
||||
}
|
||||
}
|
||||
|
||||
notify(.profile_updated, ProfileUpdate(pubkey: ev.pubkey, profile: profile))
|
||||
}
|
||||
|
||||
@@ -643,153 +540,51 @@ func robohash(_ pk: String) -> String {
|
||||
return "https://robohash.org/" + pk
|
||||
}
|
||||
|
||||
func load_our_stuff(pool: RelayPool, contacts: Contacts, pubkey: String, ev: NostrEvent) {
|
||||
guard ev.pubkey == pubkey else {
|
||||
return
|
||||
}
|
||||
|
||||
// only use new stuff
|
||||
if let current_ev = contacts.event {
|
||||
guard ev.created_at > current_ev.created_at else {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
let m_old_ev = contacts.event
|
||||
contacts.event = ev
|
||||
|
||||
load_our_contacts(contacts: contacts, our_pubkey: pubkey, m_old_ev: m_old_ev, ev: ev)
|
||||
load_our_relays(contacts: contacts, our_pubkey: pubkey, pool: pool, m_old_ev: m_old_ev, ev: ev)
|
||||
}
|
||||
|
||||
func process_contact_event(pool: RelayPool, contacts: Contacts, pubkey: String, ev: NostrEvent) {
|
||||
load_our_stuff(pool: pool, contacts: contacts, pubkey: pubkey, ev: ev)
|
||||
load_our_contacts(contacts: contacts, our_pubkey: pubkey, ev: ev)
|
||||
load_our_relays(our_pubkey: pubkey, pool: pool, ev: ev)
|
||||
add_contact_if_friend(contacts: contacts, ev: ev)
|
||||
}
|
||||
|
||||
func load_our_relays(contacts: Contacts, our_pubkey: String, pool: RelayPool, m_old_ev: NostrEvent?, ev: NostrEvent) {
|
||||
let bootstrap_dict: [String: RelayInfo] = [:]
|
||||
let old_decoded = m_old_ev.flatMap { decode_json_relays($0.content) } ?? BOOTSTRAP_RELAYS.reduce(into: bootstrap_dict) { (d, r) in
|
||||
d[r] = .rw
|
||||
func load_our_relays(our_pubkey: String, pool: RelayPool, ev: NostrEvent) {
|
||||
guard ev.pubkey == our_pubkey else {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
guard let decoded = decode_json_relays(ev.content) else {
|
||||
return
|
||||
}
|
||||
|
||||
var changed = false
|
||||
|
||||
var new = Set<String>()
|
||||
|
||||
for key in decoded.keys {
|
||||
new.insert(key)
|
||||
}
|
||||
|
||||
var old = Set<String>()
|
||||
for key in old_decoded.keys {
|
||||
old.insert(key)
|
||||
}
|
||||
|
||||
let diff = old.symmetricDifference(new)
|
||||
|
||||
for d in diff {
|
||||
changed = true
|
||||
if new.contains(d) {
|
||||
if let url = URL(string: d) {
|
||||
try? pool.add_relay(url, info: decoded[d] ?? .rw)
|
||||
if let url = URL(string: key) {
|
||||
if let _ = try? pool.add_relay(url, info: decoded[key]!) {
|
||||
pool.connect(to: [key])
|
||||
}
|
||||
} else {
|
||||
pool.remove_relay(d)
|
||||
}
|
||||
}
|
||||
|
||||
if changed {
|
||||
notify(.relays_changed, ())
|
||||
}
|
||||
}
|
||||
|
||||
func handle_incoming_dm(contacts: Contacts, prev_events: NewEventsBits, dms: DirectMessagesModel, our_pubkey: String, ev: NostrEvent) -> NewEventsBits? {
|
||||
// hide blocked users
|
||||
guard should_show_event(contacts: contacts, ev: ev) else {
|
||||
return prev_events
|
||||
}
|
||||
|
||||
var inserted = false
|
||||
var found = false
|
||||
let ours = ev.pubkey == our_pubkey
|
||||
var i = 0
|
||||
|
||||
var the_pk = ev.pubkey
|
||||
if ours {
|
||||
if let ref_pk = ev.referenced_pubkeys.first {
|
||||
the_pk = ref_pk.ref_id
|
||||
} else {
|
||||
// self dm!?
|
||||
print("TODO: handle self dm?")
|
||||
func remove_bootstrap_nodes(_ damus_state: DamusState) {
|
||||
guard let contacts = damus_state.contacts.event else {
|
||||
return
|
||||
}
|
||||
|
||||
guard let relays = decode_json_relays(contacts.content) else {
|
||||
return
|
||||
}
|
||||
|
||||
let descriptors = relays.reduce(into: []) { arr, kv in
|
||||
guard let url = URL(string: kv.key) else {
|
||||
return
|
||||
}
|
||||
arr.append(RelayDescriptor(url: url, info: kv.value))
|
||||
}
|
||||
|
||||
for relay in BOOTSTRAP_RELAYS {
|
||||
if !(descriptors.contains { ($0 as! RelayDescriptor).url.absoluteString == relay }) {
|
||||
damus_state.pool.remove_relay(relay)
|
||||
}
|
||||
}
|
||||
|
||||
for (pk, _) in dms.dms {
|
||||
if pk == the_pk {
|
||||
found = true
|
||||
inserted = insert_uniq_sorted_event(events: &(dms.dms[i].1.events), new_ev: ev) {
|
||||
$0.created_at < $1.created_at
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
|
||||
if !found {
|
||||
inserted = true
|
||||
let model = DirectMessageModel(events: [ev], our_pubkey: our_pubkey)
|
||||
dms.dms.append((the_pk, model))
|
||||
}
|
||||
|
||||
var new_events: NewEventsBits? = nil
|
||||
if inserted {
|
||||
new_events = handle_last_events(new_events: prev_events, ev: ev, timeline: .dms, shouldNotify: !ours)
|
||||
|
||||
dms.dms = dms.dms.filter({ $0.1.events.count > 0 }).sorted { a, b in
|
||||
return a.1.events.last!.created_at > b.1.events.last!.created_at
|
||||
}
|
||||
}
|
||||
|
||||
return new_events
|
||||
}
|
||||
|
||||
|
||||
/// A helper to determine if we need to notify the user of new events
|
||||
func handle_last_events(new_events: NewEventsBits, ev: NostrEvent, timeline: Timeline, shouldNotify: Bool = true) -> NewEventsBits? {
|
||||
let last_ev = get_last_event(timeline)
|
||||
|
||||
if last_ev == nil || last_ev!.created_at < ev.created_at {
|
||||
save_last_event(ev, timeline: timeline)
|
||||
if shouldNotify {
|
||||
return NewEventsBits(prev: new_events, setting: timeline)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
/// Sometimes we get garbage in our notifications. Ensure we have our pubkey on this event
|
||||
func event_has_our_pubkey(_ ev: NostrEvent, our_pubkey: String) -> Bool {
|
||||
for tag in ev.tags {
|
||||
if tag.count >= 2 && tag[0] == "p" && tag[1] == our_pubkey {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
func should_show_event(contacts: Contacts, ev: NostrEvent) -> Bool {
|
||||
if contacts.is_muted(ev.pubkey) {
|
||||
return false
|
||||
}
|
||||
return ev.should_show_event
|
||||
}
|
||||
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
//
|
||||
// KFImageModel.swift
|
||||
// damus
|
||||
//
|
||||
// Created by Oleg Abalonski on 1/11/23.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Kingfisher
|
||||
|
||||
class KFImageModel: ObservableObject {
|
||||
|
||||
let url: URL?
|
||||
let fallbackUrl: URL?
|
||||
let processor: ImageProcessor
|
||||
let serializer: CacheSerializer
|
||||
|
||||
@Published var refreshID = ""
|
||||
|
||||
init(url: URL?, fallbackUrl: URL?, maxByteSize: Int, downsampleSize: CGSize) {
|
||||
self.url = url
|
||||
self.fallbackUrl = fallbackUrl
|
||||
self.processor = CustomImageProcessor(maxSize: maxByteSize, downsampleSize: downsampleSize)
|
||||
self.serializer = CustomCacheSerializer(maxSize: maxByteSize, downsampleSize: downsampleSize)
|
||||
}
|
||||
|
||||
func refresh() -> Void {
|
||||
DispatchQueue.main.async {
|
||||
self.refreshID = UUID().uuidString
|
||||
}
|
||||
}
|
||||
|
||||
func cache(_ image: UIImage, forKey key: String) -> Void {
|
||||
KingfisherManager.shared.cache.store(image, forKey: key, processorIdentifier: processor.identifier) { _ in
|
||||
self.refresh()
|
||||
}
|
||||
}
|
||||
|
||||
func downloadFailed() -> Void {
|
||||
guard let url = url, let fallbackUrl = fallbackUrl else { return }
|
||||
|
||||
DispatchQueue.global(qos: .background).async {
|
||||
KingfisherManager.shared.downloader.downloadImage(with: fallbackUrl) { result in
|
||||
|
||||
var fallbackImage: UIImage {
|
||||
switch result {
|
||||
case .success(let imageLoadingResult):
|
||||
return imageLoadingResult.image
|
||||
case .failure(let error):
|
||||
print(error)
|
||||
return UIImage()
|
||||
}
|
||||
}
|
||||
|
||||
self.cache(fallbackImage, forKey: url.absoluteString)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct CustomImageProcessor: ImageProcessor {
|
||||
|
||||
let maxSize: Int
|
||||
let downsampleSize: CGSize
|
||||
|
||||
let identifier = "com.damus.customimageprocessor"
|
||||
|
||||
func process(item: ImageProcessItem, options: KingfisherParsedOptionsInfo) -> KFCrossPlatformImage? {
|
||||
|
||||
switch item {
|
||||
case .image(_):
|
||||
// This case will never run
|
||||
return DefaultImageProcessor.default.process(item: item, options: options)
|
||||
case .data(let data):
|
||||
|
||||
// Handle large image size
|
||||
if data.count > maxSize {
|
||||
return KingfisherWrapper.downsampledImage(data: data, to: downsampleSize, scale: options.scaleFactor)
|
||||
}
|
||||
|
||||
// Handle SVG image
|
||||
if let dataString = String(data: data, encoding: .utf8),
|
||||
let svg = SVG(dataString) {
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct CustomCacheSerializer: CacheSerializer {
|
||||
|
||||
let maxSize: Int
|
||||
let downsampleSize: CGSize
|
||||
|
||||
func data(with image: Kingfisher.KFCrossPlatformImage, original: Data?) -> Data? {
|
||||
return DefaultCacheSerializer.default.data(with: image, original: original)
|
||||
}
|
||||
|
||||
func image(with data: Data, options: Kingfisher.KingfisherParsedOptionsInfo) -> Kingfisher.KFCrossPlatformImage? {
|
||||
if data.count > maxSize {
|
||||
return KingfisherWrapper.downsampledImage(data: data, to: downsampleSize, scale: options.scaleFactor)
|
||||
}
|
||||
|
||||
return DefaultCacheSerializer.default.image(with: data, 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 }
|
||||
}
|
||||
}
|
||||
@@ -7,10 +7,6 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
enum CountResult {
|
||||
case already_counted
|
||||
case success(Int)
|
||||
}
|
||||
|
||||
class EventCounter {
|
||||
var counts: [String: Int] = [:]
|
||||
@@ -18,6 +14,11 @@ class EventCounter {
|
||||
var our_events: [String: NostrEvent] = [:]
|
||||
var our_pubkey: String
|
||||
|
||||
enum CountResult {
|
||||
case already_counted
|
||||
case success(Int)
|
||||
}
|
||||
|
||||
init (our_pubkey: String) {
|
||||
self.our_pubkey = our_pubkey
|
||||
}
|
||||
|
||||
@@ -32,30 +32,13 @@ struct IdBlock: Identifiable {
|
||||
let block: Block
|
||||
}
|
||||
|
||||
typealias Invoice = LightningInvoice<Amount>
|
||||
typealias ZapInvoice = LightningInvoice<Int64>
|
||||
|
||||
enum InvoiceDescription {
|
||||
case description(String)
|
||||
case description_hash(Data)
|
||||
}
|
||||
|
||||
struct LightningInvoice<T> {
|
||||
let description: InvoiceDescription
|
||||
let amount: T
|
||||
struct Invoice {
|
||||
let description: String
|
||||
let amount: Int64
|
||||
let string: String
|
||||
let expiry: UInt64
|
||||
let payment_hash: Data
|
||||
let created_at: UInt64
|
||||
|
||||
var description_string: String {
|
||||
switch description {
|
||||
case .description(let string):
|
||||
return string
|
||||
case .description_hash:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum Block {
|
||||
@@ -132,7 +115,7 @@ func parse_mentions(content: String, tags: [[String]]) -> [Block] {
|
||||
blocks_init(&bs)
|
||||
|
||||
let bytes = content.utf8CString
|
||||
let _ = bytes.withUnsafeBufferPointer { p in
|
||||
bytes.withUnsafeBufferPointer { p in
|
||||
damus_parse_content(&bs, p.baseAddress)
|
||||
}
|
||||
|
||||
@@ -197,59 +180,6 @@ func maybe_pointee<T>(_ p: UnsafeMutablePointer<T>!) -> T? {
|
||||
return p.pointee
|
||||
}
|
||||
|
||||
enum Amount: Equatable {
|
||||
case any
|
||||
case specific(Int64)
|
||||
|
||||
func amount_sats_str() -> String {
|
||||
switch self {
|
||||
case .any:
|
||||
return NSLocalizedString("Any", comment: "Any amount of sats")
|
||||
case .specific(let amt):
|
||||
return format_msats(amt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func format_msats_abbrev(_ msats: Int64) -> String {
|
||||
let formatter = NumberFormatter()
|
||||
formatter.numberStyle = .decimal
|
||||
formatter.positiveSuffix = "m"
|
||||
formatter.positivePrefix = ""
|
||||
formatter.minimumFractionDigits = 0
|
||||
formatter.maximumFractionDigits = 3
|
||||
formatter.roundingMode = .down
|
||||
formatter.roundingIncrement = 0.1
|
||||
formatter.multiplier = 1
|
||||
|
||||
let sats = NSNumber(value: (Double(msats) / 1000.0))
|
||||
|
||||
if msats >= 1_000_000*1000 {
|
||||
formatter.positiveSuffix = "m"
|
||||
formatter.multiplier = 0.000001
|
||||
} else if msats >= 1000*1000 {
|
||||
formatter.positiveSuffix = "k"
|
||||
formatter.multiplier = 0.001
|
||||
} else {
|
||||
return sats.stringValue
|
||||
}
|
||||
|
||||
return formatter.string(from: sats) ?? sats.stringValue
|
||||
}
|
||||
|
||||
func format_msats(_ msat: Int64) -> String {
|
||||
let numberFormatter = NumberFormatter()
|
||||
numberFormatter.numberStyle = .decimal
|
||||
numberFormatter.minimumFractionDigits = 0
|
||||
numberFormatter.maximumFractionDigits = 3
|
||||
numberFormatter.roundingMode = .down
|
||||
|
||||
let sats = NSNumber(value: (Double(msat) / 1000.0))
|
||||
let formattedSats = numberFormatter.string(from: sats) ?? sats.stringValue
|
||||
|
||||
return String(format: NSLocalizedString("sats_count", comment: "Amount of sats."), sats.decimalValue as NSDecimalNumber, formattedSats)
|
||||
}
|
||||
|
||||
func convert_invoice_block(_ b: invoice_block) -> Block? {
|
||||
guard let invstr = strblock_to_string(b.invstr) else {
|
||||
return nil
|
||||
@@ -259,30 +189,23 @@ func convert_invoice_block(_ b: invoice_block) -> Block? {
|
||||
return nil
|
||||
}
|
||||
|
||||
guard let description = convert_invoice_description(b11: b11) else {
|
||||
return nil
|
||||
var description = ""
|
||||
if b11.description != nil {
|
||||
description = String(cString: b11.description)
|
||||
}
|
||||
|
||||
let amount: Amount = maybe_pointee(b11.msat).map { .specific(Int64($0.millisatoshis)) } ?? .any
|
||||
guard let msat = maybe_pointee(b11.msat) else {
|
||||
return nil
|
||||
}
|
||||
let amount = Int64(msat.millisatoshis)
|
||||
let payment_hash = Data(bytes: &b11.payment_hash, count: 32)
|
||||
let hex = hex_encode(payment_hash)
|
||||
let created_at = b11.timestamp
|
||||
|
||||
tal_free(b.bolt11)
|
||||
return .invoice(Invoice(description: description, amount: amount, string: invstr, expiry: b11.expiry, payment_hash: payment_hash, created_at: created_at))
|
||||
}
|
||||
|
||||
func convert_invoice_description(b11: bolt11) -> InvoiceDescription? {
|
||||
if let desc = b11.description {
|
||||
return .description(String(cString: desc))
|
||||
}
|
||||
|
||||
if var deschash = maybe_pointee(b11.description_hash) {
|
||||
return .description_hash(Data(bytes: &deschash, count: 32))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func convert_mention_block(ind: Int32, tags: [[String]]) -> Block?
|
||||
{
|
||||
let ind = Int(ind)
|
||||
|
||||