Compare commits

...

4594 Commits

Author SHA1 Message Date
Vitor Pamplona
0fe01696a5 v1.02.0 2025-08-28 17:02:55 -04:00
Vitor Pamplona
624bef21b1 Adds NIP-17 crash report. 2025-08-28 16:59:46 -04:00
Vitor Pamplona
8493c95e07 Fixes the wrong import 2025-08-28 15:54:14 -04:00
Vitor Pamplona
f7eb043aac Avoids comparisons with the torConnection as part of the data class 2025-08-28 14:23:26 -04:00
Vitor Pamplona
b80685dcfb Protects this flow against lots of similar emissions 2025-08-28 14:17:58 -04:00
Vitor Pamplona
0dc18cc98c Reduces the size of log messages 2025-08-28 13:53:22 -04:00
Vitor Pamplona
c366384a83 ignores notebook file 2025-08-28 13:09:08 -04:00
Vitor Pamplona
c298147ad9 updates google services json 2025-08-28 11:18:01 -04:00
Vitor Pamplona
16e9d43da8 Removes DB migration 2025-08-28 11:17:49 -04:00
Vitor Pamplona
da5816a6c6 Fixes crash when pasting an invalid NIP-47 uri into the zap settings 2025-08-28 10:41:22 -04:00
Vitor Pamplona
4be1a143e6 Solving parsing issue with NWC 2025-08-28 10:35:44 -04:00
Vitor Pamplona
85ee48e003 Fixes crash when loading a user without a name 2025-08-28 10:32:29 -04:00
Vitor Pamplona
f536f8e88e Fixes readonly crash on DVMs 2025-08-28 10:32:16 -04:00
Vitor Pamplona
918a575cfd Speeds up first time logins by not waiting for Tor 2025-08-28 10:24:54 -04:00
Vitor Pamplona
56d8a83ebe Fixing a parser benchmark 2025-08-28 08:55:15 -04:00
Vitor Pamplona
5f33fb2cea removes unnecessary native lib 2025-08-27 21:09:42 -04:00
Vitor Pamplona
170b6cfe69 Moves test assets to resources to make it work with kmp 2025-08-27 21:09:21 -04:00
Vitor Pamplona
ce991a8aea - Migrates NIP-49 from java to kotlin for kmp 2025-08-27 21:08:34 -04:00
Vitor Pamplona
bd5b61ee64 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-08-27 18:32:43 -04:00
Vitor Pamplona
494d7edc1f Testing proguard rules on KMP quartz 2025-08-27 18:32:33 -04:00
Vitor Pamplona
8e2d684cb1 Merge pull request #1439 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-08-27 17:38:55 -04:00
Crowdin Bot
e994839468 New Crowdin translations by GitHub Action 2025-08-27 21:36:13 +00:00
Vitor Pamplona
76d97d6d16 Removes nostr.bg from relay options 2025-08-27 17:32:54 -04:00
Vitor Pamplona
442f75fc41 - Migrates Quartz to a KMP project
- Converts OpenTimestamps from java to Kotlin
- Moves OTS OkHttp setup to Quartz
2025-08-27 17:32:39 -04:00
Vitor Pamplona
d2214889b6 Version 1.01.0 2025-08-27 09:10:11 -04:00
Vitor Pamplona
d4da14e4fa Moves draft deletion calculations to the default thread 2025-08-27 08:57:10 -04:00
Vitor Pamplona
56dec11901 Intercepts backhandler to save drafts 2025-08-27 08:56:40 -04:00
Vitor Pamplona
8624dcf2d4 Merge pull request #1437 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-08-27 08:15:39 -04:00
Crowdin Bot
7edccdb236 New Crowdin translations by GitHub Action 2025-08-27 12:02:53 +00:00
Vitor Pamplona
d8fb49bd52 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-08-27 08:00:35 -04:00
Vitor Pamplona
108d8a2e57 Improves draft deletes in the feeds 2025-08-27 08:00:08 -04:00
Vitor Pamplona
7b6bd3579c Merge pull request #1436 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-08-26 20:33:52 -04:00
Crowdin Bot
9f398b5ef8 New Crowdin translations by GitHub Action 2025-08-27 00:20:01 +00:00
Vitor Pamplona
568a175735 fixes fdroid build 2025-08-26 20:18:10 -04:00
Vitor Pamplona
aa80d1b84a - Upgrades NIP-72 communities to NIP-22 comments
- Adds moderation queue feed
- Adds in-app approval procedures
- Adds drafts for community posts
- Redesigns About us section of communities.
2025-08-26 20:10:04 -04:00
Vitor Pamplona
fd752a4997 Adds a restart of the registration once the Post_notification permission changes 2025-08-25 15:43:56 -04:00
Vitor Pamplona
7302d260d9 avoids sending expired events to the cloud 2025-08-25 15:43:12 -04:00
Vitor Pamplona
823540160a Fixes some DM notification issues 2025-08-25 15:42:57 -04:00
Vitor Pamplona
0187529f8d Removes default and bootstrapping lists from the "Trusted Relay set". This should fix the unwanted NOTIFY requests. 2025-08-25 12:16:40 -04:00
Vitor Pamplona
98453c7b65 Fixes unable to delete relays from some lists. 2025-08-25 10:26:39 -04:00
Vitor Pamplona
f43e88eee7 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-08-25 10:10:06 -04:00
Vitor Pamplona
4baa5bf659 Fixes https://github.com/vitorpamplona/amethyst/issues/1070 2025-08-25 10:09:39 -04:00
David Kaspar
ce1db52abb Merge pull request #1433 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-08-25 14:25:14 +01:00
Crowdin Bot
cc6a9f1818 New Crowdin translations by GitHub Action 2025-08-25 13:14:18 +00:00
Vitor Pamplona
f11ab08f92 Merge pull request #1428 from davotoula/1403-accessibility-talkback-issues
accessibility talkback issues
2025-08-25 09:12:41 -04:00
davotoula
c93cc04409 updated imports 2025-08-23 22:58:16 +01:00
davotoula
56f299569e added translations CS, DE, PT, SV 2025-08-23 22:24:48 +01:00
davotoula
4006aebf35 added I18n for new strings 2025-08-23 18:24:10 +01:00
davotoula
b0aa2a8c31 added accessibility Description
TODO: add translations
2025-08-23 17:12:23 +01:00
davotoula
03483c932c reduce warnings:
remove unused nav parameter
remove unnecessary ? operator
replace .filter().first() with .first
2025-08-23 17:08:17 +01:00
David Kaspar
f3f8beeebe Added semantics to the invisible box
contentDescription - provides current state info
TODO: add translations
2025-08-23 17:06:26 +01:00
David Kaspar
0381e22198 Corrected TextSpinner package 2025-08-23 17:06:05 +01:00
Vitor Pamplona
d90618f7f3 Corrected version 1.00.5 2025-08-23 11:06:45 -04:00
Vitor Pamplona
41ca6d281e Revert "Version 1.00.5"
This reverts commit 83870cd06b.
2025-08-23 11:06:11 -04:00
Vitor Pamplona
1f4f1d4822 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-08-23 11:05:50 -04:00
Vitor Pamplona
83870cd06b Version 1.00.5 2025-08-23 11:05:22 -04:00
Vitor Pamplona
0d4689b064 Merge pull request #1427 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-08-23 10:58:18 -04:00
Crowdin Bot
d2e7e171a1 New Crowdin translations by GitHub Action 2025-08-23 14:57:56 +00:00
Vitor Pamplona
aea8573693 Merge pull request #1425 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-08-23 10:56:53 -04:00
Vitor Pamplona
36b14f93cb Removing multiple relays in the same line. 2025-08-23 10:49:40 -04:00
Vitor Pamplona
356a805681 Adds a child safety standards section 2025-08-22 18:15:12 -04:00
Crowdin Bot
c9e5646df2 New Crowdin translations by GitHub Action 2025-08-22 20:46:42 +00:00
Vitor Pamplona
f50a3c5bbb Merge pull request #1424 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-08-22 16:45:32 -04:00
Vitor Pamplona
46fe3c2f4a Merge pull request #1423 from newrizen/New-translation
Update pt_rbr strings.xml
2025-08-22 16:45:08 -04:00
Crowdin Bot
5ed0bf48a6 New Crowdin translations by GitHub Action 2025-08-22 20:31:42 +00:00
Vitor Pamplona
0f59befb03 Version 1.00.4 2025-08-22 16:29:56 -04:00
Vitor Pamplona
c1d8aac030 Fixes https://github.com/vitorpamplona/amethyst/issues/1422 2025-08-22 16:29:49 -04:00
Vitor Pamplona
0d3c60b9c2 Fixes the disappearance of drafts. 2025-08-22 16:11:30 -04:00
Vitor Pamplona
fa80912db2 Uses a separate okhttp for DM relays 2025-08-22 13:50:28 -04:00
Vitor Pamplona
f9ea1270fa creates a separate okhttp for relays 2025-08-22 13:35:46 -04:00
Vitor Pamplona
e0ffa6d4fb In case a user does not have an outbox list, defaults to all hints seen for that user. 2025-08-22 12:42:40 -04:00
Vitor Pamplona
3df7129f00 Deletes unused state class 2025-08-22 12:41:03 -04:00
Neil Rizen
692f77dcd1 Update pt_rbr strings.xml
More compact translation, with corrected spelling (there is no "automaticamente-traduzido" with dash in Portuguese, so I changed it to 'autotraduzido' and moved the dash away to use as a ':' ) and visually more pleasing.
2025-08-22 07:56:00 -03:00
Vitor Pamplona
273186ef35 version 1.00.3 2025-08-21 20:13:52 -04:00
Vitor Pamplona
b64d6c24c8 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-08-21 20:11:54 -04:00
Vitor Pamplona
1f2a153f47 Fixes lack of feed updates for those that didn't follow any communities 2025-08-21 20:11:44 -04:00
Vitor Pamplona
a36f2cc93f Merge pull request #1421 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-08-21 18:29:13 -04:00
Vitor Pamplona
499316687f Avoids parsing bad NIP-28 objects 2025-08-21 17:19:22 -04:00
Vitor Pamplona
693a75b9ec Don't try to decrypt appData unless it is a writeable account 2025-08-21 17:18:47 -04:00
Crowdin Bot
d0b3c9b019 New Crowdin translations by GitHub Action 2025-08-21 21:12:11 +00:00
Vitor Pamplona
d810aaa2d0 streamlines function calls on AccountViewModel 2025-08-21 17:10:10 -04:00
Vitor Pamplona
965db8b91b trying to remove HEAD from the release build name 2025-08-21 15:13:53 -04:00
Vitor Pamplona
5f7088b7bb Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-08-21 14:33:27 -04:00
Vitor Pamplona
d7c80ca138 Merge pull request #1420 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-08-21 14:33:04 -04:00
Vitor Pamplona
75da18a30b Version 1.00.2 2025-08-21 14:32:48 -04:00
Crowdin Bot
897e9d84cb New Crowdin translations by GitHub Action 2025-08-21 18:31:11 +00:00
Vitor Pamplona
fe141d1ee3 Fixes crash when typing a new post without permissions to do a draft post. 2025-08-21 14:29:34 -04:00
Vitor Pamplona
4a7a09c43a Tries to avoid crash when lacking google services in the play version. 2025-08-21 14:20:55 -04:00
Vitor Pamplona
fd26ae5543 Fixes branch name 2025-08-21 14:11:56 -04:00
Vitor Pamplona
631270fc37 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-08-21 14:09:43 -04:00
Vitor Pamplona
816de5bf03 Fixes community join/leave issue 2025-08-21 14:06:47 -04:00
Vitor Pamplona
1ef9902ece Migrates top nav list to hashtag, geohash and community lists 2025-08-21 13:51:33 -04:00
Vitor Pamplona
704a08e7bb Fixes follow/unfollow from hashtags and geohashes 2025-08-21 13:51:10 -04:00
Vitor Pamplona
ffbf2b4024 Merge pull request #1419 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-08-21 12:25:23 -04:00
Crowdin Bot
a33ab5c1e9 New Crowdin translations by GitHub Action 2025-08-21 16:22:29 +00:00
Vitor Pamplona
b699b30954 Version 1.00.1 to fix app name 2025-08-21 12:21:48 -04:00
Vitor Pamplona
1d1ee8670e Fixes app name 2025-08-21 12:20:16 -04:00
Vitor Pamplona
bcdf6e5ff7 Sends only play files to the zap store. 2025-08-21 12:17:31 -04:00
Vitor Pamplona
fbb50f4147 version 1.0.0 2025-08-21 11:08:23 -04:00
Vitor Pamplona
4e13c5ab9c Improves timeouts to download and upload files 2025-08-21 08:49:25 -04:00
Vitor Pamplona
e1a5b9c079 Waits for the player to load and sets the current position of the audio 2025-08-20 21:26:59 -04:00
Vitor Pamplona
a27acd9dc6 YakBak in PictureInPicture mode
New audio player UI for YakBak
2025-08-20 21:00:09 -04:00
Vitor Pamplona
2f82233b25 Higher quality audio recordings 2025-08-20 17:37:44 -04:00
Vitor Pamplona
b232f484bf Saves all NIP-51 lists as nip-44 2025-08-20 17:32:58 -04:00
Vitor Pamplona
679f9b66ed Allows the height of the preview to adjust to the width of the preview image 2025-08-20 17:22:04 -04:00
Vitor Pamplona
da015e3298 Enabling the display for amplitudes in an array of floats for YakBak 2025-08-20 16:00:06 -04:00
Vitor Pamplona
4065adac83 Correctly manages airplane mode changes: reconnects Tor and Relays 2025-08-20 12:16:01 -04:00
Vitor Pamplona
7339f0ea3b Merge pull request #1418 from davotoula/update-n71-video-events
Support updated video events (Kind 21/22)
2025-08-20 08:32:20 -04:00
David Kaspar
1bbc67fed7 Added VideoNormalEvent (21) and VideoShortEvent (22)
Updated Account to post events as new 21 / 22 kinds.
Keep showing old event kinds for backwards compatibility
2025-08-20 11:16:02 +01:00
Vitor Pamplona
64f46a55f9 Because the indexer processes Notes in bulk and after the fact, it could be the case where a new draft and a deletion event happen one after the other. If we don't re-check for deletions, the app will reindex the old draft that was already deleted by the LocalCache, creating a memory leak. 2025-08-19 18:54:28 -04:00
Vitor Pamplona
5662eda54c Finishes the routing for note edits for live, public and ephemeral chats as well as public messages. 2025-08-19 18:21:27 -04:00
Vitor Pamplona
f56d927f72 Adds 90 day expiration to all drafts. 2025-08-19 12:40:53 -04:00
Vitor Pamplona
5685f227f9 Fixes relay hints when they disagree with our findings. 2025-08-19 12:20:49 -04:00
Vitor Pamplona
d539eca8bb Avoids chats going behind the status bar up top 2025-08-19 10:42:42 -04:00
Vitor Pamplona
415bf9f522 Corrects some of the keys for Launched effects 2025-08-19 09:02:15 -04:00
Vitor Pamplona
667c15b3a1 Checks if the relay list in NIP-28 groups is empty and uses default when needed. 2025-08-18 19:24:57 -04:00
Vitor Pamplona
f31fa4a9c6 Adds notes to channels to facilitate their loading. 2025-08-18 19:24:23 -04:00
Vitor Pamplona
3bf6e80650 update kotlin, serialization plugin, tor 2025-08-18 19:22:56 -04:00
Vitor Pamplona
3bf2f858f7 Fixes the unable to recreate user after the GC deletes it. 2025-08-18 17:24:34 -04:00
Vitor Pamplona
5c0d71f034 Avoiding concurrent errors when deleting weak references 2025-08-18 16:52:17 -04:00
Vitor Pamplona
d4d60cb1ff Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-08-18 15:21:06 -04:00
Vitor Pamplona
b2932cd7e3 Updates agp 2025-08-18 15:07:35 -04:00
Vitor Pamplona
9d9b5f03db Merge pull request #1417 from greenart7c3/main
Change BasicOkHttpWebSocket to be like the docs
2025-08-18 13:27:52 -04:00
greenart7c3
e076f97714 Change BasicOkHttpWebSocket to be like the docs 2025-08-18 13:51:40 -03:00
Vitor Pamplona
f5247a5443 Moves reconnections to 1 minute not 10 seconds 2025-08-18 11:37:32 -04:00
Vitor Pamplona
92e9978859 Moves to parcelable.
Fixes: https://github.com/vitorpamplona/amethyst/issues/1413
2025-08-18 11:25:57 -04:00
Vitor Pamplona
3520fe89ae Merge pull request #1414 from davotoula/1413-use-pubkeyhex-for-lazy-column-key
Use pubkeyhex for lazy column key instead of Address
2025-08-18 11:13:23 -04:00
Vitor Pamplona
01ed0f3fc1 Merge pull request #1415 from davotoula/target-field-specifically-for-constructor-params-for-serialization
Use explicit field annotation target for constructor params
2025-08-18 11:13:08 -04:00
David Kaspar
41545a156b Use explicit annotation target for constructor params
See https://youtrack.jetbrains.com/issue/KT-73255 for more details
2025-08-18 10:44:42 +01:00
David Kaspar
b38e9247ce Use pubkeyhex for lazy column key instead of Address 2025-08-17 23:02:25 +01:00
Vitor Pamplona
45ec9e3a62 Merge pull request #1411 from davotoula/reduce-duplications-large-cache
Reduce duplications: large cache
2025-08-16 16:14:13 -04:00
David Kaspar
c1004dc643 Use .get( instead of index to keep to code base coding style 2025-08-16 18:56:48 +01:00
David Kaspar
a72fff5f8f Lifted out collectors from CacheCollectors object 2025-08-16 18:50:01 +01:00
Vitor Pamplona
fca4aee5f5 Adds a user list to each connected relay to know where this is coming from 2025-08-16 13:21:10 -04:00
David Kaspar
a82f4aacbe Use val for references that do not change (eg results) 2025-08-16 18:17:27 +01:00
David Kaspar
f21c7bd258 Lint issues: remove unused methods, use indexing operator instead of .get() 2025-08-16 11:21:19 +01:00
David Kaspar
533d8b18f0 Remove duplicate functionality from Cache implementations and use instead common methods in CacheOperations utility class
Create override for forEach and size as they are needed internally and do slightly different things
2025-08-16 10:45:37 +01:00
David Kaspar
b069f283ac Move common cache operations to new utility class 2025-08-16 10:38:57 +01:00
David Kaspar
eab2f96f02 remove duplicate colletors and Use collectors from new utility class 2025-08-16 10:20:52 +01:00
David Kaspar
c4b71a0aea Move common collectors to new utility class 2025-08-16 10:09:56 +01:00
Vitor Pamplona
88933fba8d Fixes the time to reconnect interval due to an error between seconds and milliseconds. 2025-08-15 18:07:12 -04:00
Vitor Pamplona
ef049e88ba Adds a new mechanism to wake up all connections when movement is made in the app. 2025-08-15 18:06:21 -04:00
Vitor Pamplona
6f27c96aed changes the sendEvent from forcing a connection to waiting for the time to connect. 2025-08-15 18:04:57 -04:00
Vitor Pamplona
5b605700a3 Adds 10 seconds ago 2025-08-15 18:03:57 -04:00
Vitor Pamplona
e867571ea6 Improves version finder 2025-08-15 14:39:53 -04:00
Vitor Pamplona
f4759c283e Adds a basic OkHttp builder to Quartz (new dependency :( )
Adds some instructions to the basic readme.md
2025-08-15 14:33:05 -04:00
Vitor Pamplona
4887e6f3a1 Sends a disconnect signal to the clients 2025-08-15 09:43:37 -04:00
Vitor Pamplona
1392833179 no need for the scope on the cache connector 2025-08-15 09:18:42 -04:00
Vitor Pamplona
529a1f403e Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-08-15 08:41:22 -04:00
Vitor Pamplona
c9b16309e2 Clears the socket from memory upon closing. 2025-08-15 08:40:33 -04:00
Vitor Pamplona
81db455bfb Updates compose and fragment 2025-08-15 08:36:08 -04:00
Vitor Pamplona
c017b9cace Merge pull request #1410 from greenart7c3/main
Fix non ssl connections
2025-08-15 06:57:29 -04:00
greenart7c3
25f5551a98 Fix non ssl connections 2025-08-15 07:35:01 -03:00
Vitor Pamplona
d8461c2a74 Growing the number of possibilities to download profile information from 2025-08-14 19:47:20 -04:00
Vitor Pamplona
25dec49e97 Reactivates event log 2025-08-14 18:58:33 -04:00
Vitor Pamplona
424d5ccc9c Refactoring 2025-08-14 17:32:28 -04:00
Vitor Pamplona
422a018a1f Fixes when posts have published_at in milliseconds. 2025-08-14 17:32:15 -04:00
Vitor Pamplona
5b8afb6f60 Updates logging for auth 2025-08-14 17:06:26 -04:00
Vitor Pamplona
38827a4db6 Uses relays where the event was seen as a source of reactions and replies 2025-08-14 16:20:53 -04:00
Vitor Pamplona
97bad5707f Improves filter by last date of the feed 2025-08-14 16:09:26 -04:00
Vitor Pamplona
58c8ff646f Moves the feed update to 5 seconds. 2025-08-14 16:04:27 -04:00
Vitor Pamplona
613a3b4912 Adds a limit of 1 week to load videos and hashtags on shorts 2025-08-14 16:03:48 -04:00
Vitor Pamplona
a67155ac25 Only loads notifications from random relays after the notification feed is done 2025-08-14 16:03:19 -04:00
Vitor Pamplona
ba27b68c14 Minor refactoring 2025-08-14 15:43:43 -04:00
Vitor Pamplona
dfe5f86a23 Faster PublishedAt providers 2025-08-14 11:28:03 -04:00
Vitor Pamplona
abf0c4fd70 Removes broadcasting relays from the group of relays used to find events. 2025-08-14 10:49:30 -04:00
Vitor Pamplona
ed675a4973 Merge pull request #1408 from davotoula/reduce-duplication-resuable-zap-button
Deduplication of code: ZapTheDevsCard, DvmContentDiscoveryScreen
2025-08-14 09:51:38 -04:00
Vitor Pamplona
6514bacf69 Merge pull request #1409 from davotoula/1406-display-app-picture-when-clicked-on-app-picture
Display app picture when clicked on app picture
2025-08-14 09:51:06 -04:00
David Kaspar
e682a95822 Changed ZoomableImageDialog to show app picture rather than banner
Moved it inside picture?.let to guard against null picture
2025-08-14 14:34:11 +01:00
David Kaspar
d367a1f281 Specify return type as non-nullable asJackson will either return a non-null value or throw an exception. 2025-08-14 11:23:23 +01:00
Vitor Pamplona
f5881d4248 avoids using broadcasting relays to build filters to download home data 2025-08-13 19:11:54 -04:00
Vitor Pamplona
4c0f223673 Draft event refactoring 2025-08-13 19:11:29 -04:00
David Kaspar
aae520d2e4 Created ReusableZapButton with common zap button logic
ZapDVMButton refactored to use ReusableZapButton with DVM-specific configuration
2025-08-13 20:59:56 +01:00
Vitor Pamplona
251e5535d0 Removes hash logs 2025-08-12 18:57:11 -04:00
Vitor Pamplona
a034b495e8 Removes checks 2025-08-12 18:57:01 -04:00
Vitor Pamplona
41c2097f3c reduces logs 2025-08-12 18:55:55 -04:00
Vitor Pamplona
22dc037bf7 Moves to disable tor if on the background 2025-08-12 18:55:47 -04:00
Vitor Pamplona
346fb61507 Small refactoring 2025-08-12 17:55:24 -04:00
Vitor Pamplona
c17d66b7e9 Small optimization 2025-08-12 17:28:22 -04:00
Vitor Pamplona
478b2d12eb Speeding up the parsing of relay urls 2025-08-12 17:16:14 -04:00
Vitor Pamplona
c14d976ad1 Minor refactoring 2025-08-12 17:15:23 -04:00
Vitor Pamplona
d605eb3b0a Fixes lack of update on chats and channels due to the new indexer being decoupled form LocalCache. 2025-08-12 16:37:32 -04:00
Vitor Pamplona
25aaed80b0 Better name for the newestMessage of a chat 2025-08-12 11:43:57 -04:00
Vitor Pamplona
14582fe9b6 Recalculating subject and last message when deletes happen 2025-08-12 11:29:58 -04:00
Vitor Pamplona
7a38269449 removing unused libs 2025-08-12 11:29:34 -04:00
Vitor Pamplona
77bb34eaf8 Updates tor to 16KB-page files and firebase 2025-08-12 08:47:51 -04:00
Vitor Pamplona
d0f3dde08b Migrates to a more obvious open/close subscription model for NostrClient 2025-08-11 10:34:10 -04:00
Vitor Pamplona
d5b9d5e80b Closes subscription when finished by timeout. 2025-08-11 10:33:21 -04:00
Vitor Pamplona
549074ef13 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-08-07 18:04:42 -04:00
Vitor Pamplona
2315051504 - Makes zap calculation a sync routine
- Optimizes the display of the yellow zap when the zap event comes before the pay payment confirmation
- Fixes animations for a new zap over an existing zap.
2025-08-07 18:02:31 -04:00
Vitor Pamplona
8ba96ca527 Simplifies Zap animation sizes 2025-08-07 16:39:44 -04:00
Vitor Pamplona
10c5db8281 Fixes the encryption of NWC 2025-08-07 16:07:15 -04:00
Vitor Pamplona
86b4957067 Removes NWC events from notificatuions 2025-08-07 15:35:59 -04:00
Vitor Pamplona
fe19b8b4af Merge pull request #1405 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-08-07 14:37:59 -04:00
Crowdin Bot
3532a0cadd New Crowdin translations by GitHub Action 2025-08-07 18:27:02 +00:00
Vitor Pamplona
58277d9697 Moves build tools of github actions to 36 2025-08-07 14:24:45 -04:00
Vitor Pamplona
cf76ab9f0e Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-08-07 10:13:18 -04:00
Vitor Pamplona
51d7fa3aac Fixes missing method on build 2025-08-07 10:09:43 -04:00
Vitor Pamplona
10832e10c8 Fixes the background color behind the show more button on light mode 2025-08-07 09:50:20 -04:00
David Kaspar
1fce054c9f Merge pull request #1404 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-08-07 15:27:14 +02:00
Crowdin Bot
f7b3dada05 New Crowdin translations by GitHub Action 2025-08-07 13:25:23 +00:00
Vitor Pamplona
f35376a7da Small refactoring 2025-08-06 19:13:15 -04:00
Vitor Pamplona
d0f3630abb Changes to show the user name before the text on public messages. 2025-08-06 18:26:11 -04:00
Vitor Pamplona
d22fc2874b Don't show public messages on the feed, just on notifications 2025-08-06 18:25:20 -04:00
Vitor Pamplona
23b3ff9fe8 Adds missing methods to display as Public message 2025-08-06 18:09:14 -04:00
Vitor Pamplona
52ac0c184d Passes reply preview to the new Public message screen 2025-08-06 18:07:30 -04:00
Vitor Pamplona
923ddf1c83 Shows all public message events on conversations 2025-08-06 18:05:14 -04:00
Vitor Pamplona
cc186ef91b Fixes route maker 2025-08-06 18:04:44 -04:00
Vitor Pamplona
02def3e0b1 Doesn't pass deleted drafts ahead to the indexer anymore. It's not needed. 2025-08-06 18:02:54 -04:00
Vitor Pamplona
036b385f38 Adds a check for deletion before processing inner posts 2025-08-06 18:02:26 -04:00
Vitor Pamplona
fdff92dff9 New Public Message screen: to field should get focus if it is empty, otherwise the message field should have the focus 2025-08-06 18:01:19 -04:00
Vitor Pamplona
8c854c43be Adds p-tags to the display of public messages so that users know they are being cited 2025-08-06 17:58:51 -04:00
Vitor Pamplona
d707a951c3 Adds an option to pass a request focus parameter to the MessageField in new post screens 2025-08-06 17:58:18 -04:00
Vitor Pamplona
b1566d8f8b Update log descriptions to match the new deleted flow 2025-08-06 17:57:46 -04:00
Vitor Pamplona
481db7ebeb Loads and shows public messages in the user's profile as replies to others 2025-08-06 17:57:06 -04:00
Vitor Pamplona
a18c6c0bc8 Shows public messages in the profile's mutual feed 2025-08-06 17:56:26 -04:00
Vitor Pamplona
4d6f6d0ed5 removes a launch call from an already launched coroutine 2025-08-06 17:55:52 -04:00
Vitor Pamplona
1b043603f9 Adds a method to create nprofiles without creating a relay list first 2025-08-06 17:54:34 -04:00
Vitor Pamplona
dddc9e1346 Simplifies the startWith check 2025-08-06 17:13:37 -04:00
Vitor Pamplona
b5662fd05a normalizes the parameter name across all adaptive filters 2025-08-06 14:09:06 -04:00
Vitor Pamplona
726f9e2f4f Moves target compatibility to java 21 2025-08-06 14:07:51 -04:00
Vitor Pamplona
ca55472010 Increases the limit for notification events to fill up a week's worth of inbox 2025-08-06 13:20:00 -04:00
Vitor Pamplona
71bbae2f9b Simple refactoring 2025-08-06 13:18:45 -04:00
Vitor Pamplona
1971956443 Setting up the boundary for one week ago for notifications 2025-08-06 13:18:13 -04:00
Vitor Pamplona
282935c5f3 Adds search relays as fallback for event finding activities 2025-08-06 08:55:35 -04:00
Vitor Pamplona
d4d7d58378 Maybe separate assemblies work 2025-08-05 17:42:57 -04:00
Vitor Pamplona
5d1e3e804f Trying to see if we can get benchmark flavors out of github actions 2025-08-05 17:20:25 -04:00
Vitor Pamplona
9475978612 Fixes background of transparent posts. 2025-08-05 16:42:13 -04:00
Vitor Pamplona
c32a64fbfe avoids indexing via DraftTags and removes notes from the reply list when they get updated. 2025-08-05 16:30:36 -04:00
Vitor Pamplona
da40de49cd Refactors the DecryptAndIndex to avoid a service class 2025-08-05 16:30:00 -04:00
Vitor Pamplona
e237853a8f Making the new signer work for readonly accounts 2025-08-05 16:06:52 -04:00
Vitor Pamplona
63f62167a4 Simplifying the refactoring of the DecryptAndIndexProcessor 2025-08-05 15:04:23 -04:00
Vitor Pamplona
4675212e1d Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-08-05 12:06:17 -04:00
Vitor Pamplona
f1b15cc3c5 Cleaning up the saving draft concurrency issues. 2025-08-05 11:48:02 -04:00
Vitor Pamplona
a747f25906 Adds exception handlers for managed coroutine scopes 2025-08-05 11:47:03 -04:00
Vitor Pamplona
e72ae565d3 Adds an extra catch in case there is a decryption error 2025-08-05 11:46:29 -04:00
Vitor Pamplona
be41627c2b Fixes geohash cache saving 2025-08-05 10:45:20 -04:00
Vitor Pamplona
426378a7ee Merge pull request #1402 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-08-05 09:55:06 -04:00
Crowdin Bot
f9efc0ae2d New Crowdin translations by GitHub Action 2025-08-05 13:51:50 +00:00
Vitor Pamplona
09dfa79dea Merge pull request #1395 from davotoula/refactor-decrypt-and-index-processor-light
Refactor decrypt and index processor
2025-08-05 09:50:12 -04:00
Vitor Pamplona
8af955ce20 Adds an extra layer on the url normalization cache to avoid recomputing failed attempts before. 2025-08-04 18:18:39 -04:00
Vitor Pamplona
5b0fccb9e0 Merge pull request #1401 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-08-04 11:44:47 -04:00
Crowdin Bot
bef607ec41 New Crowdin translations by GitHub Action 2025-08-04 15:14:07 +00:00
Vitor Pamplona
bfbdc65bef Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-08-04 11:09:24 -04:00
Vitor Pamplona
cfb2f98f66 Merge pull request #1396 from davotoula/dynamic-version-number-based-on-branch-name
Dynamic version number based on branch name
2025-08-03 12:29:56 -04:00
David Kaspar
fb0597b2f4 Merge pull request #1399 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-08-03 18:24:23 +02:00
Crowdin Bot
c663fd0f5a New Crowdin translations by GitHub Action 2025-08-03 16:22:02 +00:00
David Kaspar
2a8b258f80 Merge pull request #1398 from davotoula/update-translations
update DE
2025-08-03 18:20:53 +02:00
David Kaspar
9c0663db69 update DE 2025-08-03 18:16:24 +02:00
David Kaspar
8d8edbaf90 executes a Git command to get the current branch name.
If the branch is "main" or "master", returns the base version unchanged
For feature branches, appends the branch name to the version
2025-08-03 11:47:26 +02:00
David Kaspar
5420ddd338 lets pass LocalCache instead of account.cache, as it was before 2025-08-03 10:35:40 +02:00
David Kaspar
fa80cb297d reduce lint warnings 2025-08-03 10:32:04 +02:00
David Kaspar
cdfb1db253 refactor DecryptAndIndexProcessor
EventProcessor: Orchestrates the processing flow
DecryptionService: Handles all decryption operations
IndexingService: Manages event indexing and relationships
ChatroomService: Manages chatroom operations
2025-08-03 10:29:05 +02:00
David Kaspar
52b87fa17a Merge pull request #1394 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-08-03 10:11:31 +02:00
Crowdin Bot
f209b17811 New Crowdin translations by GitHub Action 2025-08-03 07:36:52 +00:00
David Kaspar
a3d38aab1b Merge pull request #1391 from davotoula/update-translations
Update translations. CZ, SE, PT, DE
2025-08-03 09:35:39 +02:00
Vitor Pamplona
52df3cba02 Updates junit, benchmark, media3, expresso, compose, and crypto 2025-08-01 18:48:31 -04:00
David Kaspar
bb8a71f47b Update translations. CZ, SE, PT, DE 2025-08-01 23:37:14 +02:00
Vitor Pamplona
d78d3aeab3 Merge pull request #1390 from davotoula/upgrade-agp
Upgrade agp to 8.12.0
2025-08-01 17:30:59 -04:00
Vitor Pamplona
7f6435ba57 Updates build tools to java 21 2025-08-01 17:07:31 -04:00
Vitor Pamplona
1a58603477 Merge pull request #1389 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-08-01 16:58:20 -04:00
David Kaspar
4b36da59ec Upgrade agp to 8.12.0 2025-08-01 22:55:28 +02:00
Crowdin Bot
9257305820 New Crowdin translations by GitHub Action 2025-08-01 20:40:51 +00:00
Vitor Pamplona
e414c4be98 Merge pull request #1388 from vitorpamplona/full-outbox
Full outbox
2025-08-01 16:39:30 -04:00
Vitor Pamplona
340760513f Better handling index cleanup when draft events get deleted 2025-08-01 16:11:24 -04:00
Vitor Pamplona
eed4350bca Simplifying badge composables 2025-08-01 16:10:34 -04:00
Vitor Pamplona
6b946a57c2 Moves the exceptions to our own signing exceptions 2025-08-01 16:09:52 -04:00
Vitor Pamplona
26cadfee88 Fixes the index after deletions 2025-08-01 11:40:19 -04:00
Vitor Pamplona
4cd24e5363 No need for not null checks 2025-08-01 09:57:33 -04:00
Vitor Pamplona
e715a74bc4 Better indexes notes in channels and chatrooms 2025-08-01 08:30:44 -04:00
Vitor Pamplona
42738e72f7 fixes test case 2025-07-31 19:14:43 -04:00
Vitor Pamplona
add8f8eba2 Improves the rendering of the node id 2025-07-31 19:12:10 -04:00
Vitor Pamplona
e82c09e1c3 Finishes the migration of adressable ids on the local cache. 2025-07-31 19:11:55 -04:00
Vitor Pamplona
e1b5f0f7b5 Renames chatroom and message fields 2025-07-31 19:11:08 -04:00
Vitor Pamplona
7e9d5d6063 Uses new tag model on the ZapEvent 2025-07-31 19:06:34 -04:00
Vitor Pamplona
141f0ed63b Removes unused items from Node 2025-07-31 19:06:09 -04:00
Vitor Pamplona
c5645b0ae7 Removes suspend of NostrSignerSync-based functions 2025-07-31 17:45:44 -04:00
Vitor Pamplona
fe8f519dbf Correctly logs off from the current account when creating new accounts from inside an existing account. 2025-07-31 17:45:21 -04:00
Vitor Pamplona
14e860928b Improves names of the repost methods 2025-07-31 17:44:04 -04:00
Vitor Pamplona
ba460e011e Adds a lower boundary for inbox from random relays. 2025-07-31 12:22:22 -04:00
Vitor Pamplona
12f793ad51 The gentle shutdown doesn't really work. There could be too many send messages waiting to be processed. 2025-07-31 12:21:44 -04:00
Vitor Pamplona
504d582d54 Tuning limits for Global feeds 2025-07-31 11:31:36 -04:00
Vitor Pamplona
a59cd590bc Deletes these very confusing mocks into account viewmodels for the test 2025-07-30 20:20:56 -04:00
Vitor Pamplona
2e9696745a Avoids sending filters on new connections if the client is not active 2025-07-30 18:23:02 -04:00
Vitor Pamplona
5d4b16641e Fixes count call 2025-07-30 18:11:11 -04:00
Vitor Pamplona
1ddc9c216b Marks which relays have been sending unsupported events. 2025-07-30 18:06:24 -04:00
Vitor Pamplona
349dfe3d42 Slowdown updates to random relay requests. 2025-07-30 18:05:53 -04:00
Vitor Pamplona
521a41d81b avoids logging with sub ms times 2025-07-30 17:50:21 -04:00
Vitor Pamplona
c6e103ff87 Delete unnecessary logs 2025-07-30 17:33:56 -04:00
Vitor Pamplona
e70f1fedc6 Adds a coroutine to the relay class so that we can defer processing events 2025-07-30 17:33:12 -04:00
Vitor Pamplona
651ca9a3ef No need to update status on EOSE 2025-07-30 17:31:38 -04:00
Vitor Pamplona
bd7dba1a31 Fixes more random relay hint errors 2025-07-30 17:31:24 -04:00
Vitor Pamplona
cf1d66bc01 new parameter to only log when a given amount of ms have passed. 2025-07-30 16:50:36 -04:00
Vitor Pamplona
414e933686 Only trigger new filters if this has changed 2025-07-30 16:49:48 -04:00
Vitor Pamplona
fa53ff2c78 Adds an iMeta cache for Picture and Video kinds and speeds up the procedure to verify if a video or picture is supported. 2025-07-30 12:47:31 -04:00
Vitor Pamplona
2c6a084808 Makes sure the NostrClient stays off in the background 2025-07-30 10:37:30 -04:00
Vitor Pamplona
8abba9246c Adds support to reply to Yaks with another voice message. 2025-07-29 20:07:28 -04:00
Vitor Pamplona
c9de32c3fa fixes voice track bugs 2025-07-29 15:08:47 -04:00
Vitor Pamplona
35a0b04020 Adds view support for public messages 2025-07-29 15:03:44 -04:00
Vitor Pamplona
4cc5aaa49d Adds view support for YakBak 2025-07-29 15:02:16 -04:00
Vitor Pamplona
bbf6e02609 Beginnings for the migration to DataStore 2025-07-28 17:13:57 -04:00
Vitor Pamplona
7ba2810423 Quick event store using SQLite directly. 2025-07-28 16:49:39 -04:00
Vitor Pamplona
88f9beafd3 Faster expiration calculation and tag array serialization 2025-07-28 16:48:42 -04:00
Vitor Pamplona
0116bc30e4 Creates a TagArray deserializer that interns all strings to avoid duplicated memory 2025-07-28 10:53:55 -04:00
Vitor Pamplona
a59fe59657 Sending eventDB companion to avoid recreating it all the time 2025-07-27 16:52:28 -04:00
Vitor Pamplona
e6dfa07526 Fixes expiration builder 2025-07-27 16:51:59 -04:00
Vitor Pamplona
8e3594cd75 Adds a way to delete events by address only 2025-07-27 16:25:24 -04:00
Vitor Pamplona
d5bbf4b00b Adds basic events to the seacheable interface 2025-07-27 16:25:09 -04:00
Vitor Pamplona
dc68d6025e Adds support for the Request to Vanish NIP - 62 2025-07-27 16:24:10 -04:00
Vitor Pamplona
f8f59abdf1 Small refactoring 2025-07-25 14:33:14 -04:00
Vitor Pamplona
3a37d5e42d Fixes the benchmark testing cases 2025-07-25 14:29:14 -04:00
Vitor Pamplona
ca9777be83 Creates a kind type alias 2025-07-25 12:42:19 -04:00
Vitor Pamplona
e7a9890eb1 Fixes quartz test cases for the new structure 2025-07-25 12:41:43 -04:00
Vitor Pamplona
39152d4e90 Makes the metadata event and contact list addressables 2025-07-25 12:40:55 -04:00
Vitor Pamplona
96e26cfb7d Adds a parser and assembler for NIP47 2025-07-25 12:39:55 -04:00
Vitor Pamplona
8844bb73ea Defines a searcheable interface for events to implement and provide content for a full text search 2025-07-25 12:39:38 -04:00
Vitor Pamplona
180a1eb1db Refactors the use of Gzip 2025-07-25 12:39:11 -04:00
Vitor Pamplona
b77127df77 Minor adjustment 2025-07-24 11:05:08 -04:00
Vitor Pamplona
803b231aaa Moves firebase to the main module 2025-07-24 10:16:56 -04:00
Vitor Pamplona
b27a12b9b5 Finally solved the issue with @aar in gradle 2025-07-24 10:11:36 -04:00
Vitor Pamplona
e7f04ad38d updates spotless 2025-07-24 10:01:20 -04:00
Vitor Pamplona
25e92666e0 Adjusts the gradle DSL language to the latest deprecations 2025-07-24 09:53:00 -04:00
Vitor Pamplona
e76bffd048 Updates coil, compose, firebase, jackson, lifecyle, mockk, navigation 2025-07-24 09:37:40 -04:00
Vitor Pamplona
558a060994 Merge remote-tracking branch 'origin/HEAD' into full-outbox
# Conflicts:
#	gradle/libs.versions.toml
2025-07-24 09:27:01 -04:00
Vitor Pamplona
14055894dc Refactoring in the relay url normalizer 2025-07-24 09:22:24 -04:00
Vitor Pamplona
a494257a27 Adds Proxy relay list and adds support for fixed list of relays. 2025-07-23 19:09:04 -04:00
Vitor Pamplona
1084d2a063 Adds an indexer relay list 2025-07-23 13:19:46 -04:00
Vitor Pamplona
57e4d76da0 Adds broadcasting relay section 2025-07-23 11:35:25 -04:00
Vitor Pamplona
5ac4314e2a Improvements to the online check 2025-07-23 11:33:43 -04:00
Vitor Pamplona
a7dbd787f4 Creates a garbage collector-friendly note cache. 2025-07-23 10:50:51 -04:00
Vitor Pamplona
3a0d7ddac1 Removes unnecessary spec in Channel 2025-07-23 09:26:07 -04:00
Vitor Pamplona
c221506e78 Fixes square loading image on Follow packs 2025-07-23 08:50:14 -04:00
Vitor Pamplona
064a732ec8 Fixes leaving and joining channels 2025-07-23 08:44:41 -04:00
Vitor Pamplona
95f463b0aa Showing ephemeral chats in the messages list.
Fixing a bug of the last message with unloaded event
2025-07-22 20:12:43 -04:00
Vitor Pamplona
6d4708bbeb Implements a partial page system to load feeds. 2025-07-22 19:02:23 -04:00
Vitor Pamplona
1d9b2cffa2 Filtering Addressable notes from Notification's note stack 2025-07-22 15:05:17 -04:00
Vitor Pamplona
6c77bf94a8 Fixing mark as read 2025-07-22 14:09:47 -04:00
Vitor Pamplona
37ff0070ee Solves the hanging AccountViewModel scope when Amethyst is forced closed. 2025-07-22 13:38:30 -04:00
Vitor Pamplona
0f13202f84 Corrects a bug of not showing the user's own messages on chat 2025-07-22 12:46:05 -04:00
Vitor Pamplona
a3ec4d4260 Completing Intent writing implementation 2025-07-22 10:54:24 -04:00
Vitor Pamplona
e6b5d51cda Fixes NIP-55 return as a list of results on the intent. 2025-07-22 10:34:42 -04:00
Vitor Pamplona
8fe13717dd Fixes trying to parse empty addresses 2025-07-22 10:34:09 -04:00
Vitor Pamplona
c7e81d1378 Refactoring Channel modules 2025-07-22 10:33:50 -04:00
Vitor Pamplona
8e6d71e422 Minimizes the dependency on the Account further by moving Tor settings to a tor Privacy State 2025-07-21 19:09:06 -04:00
Vitor Pamplona
95c6dcce5e Moves Ots to its own state class 2025-07-21 17:34:48 -04:00
Vitor Pamplona
6066c7d06d Removes relay lists from notifications 2025-07-21 17:33:31 -04:00
Vitor Pamplona
1c5acc00f3 More appropriate limits 2025-07-21 10:11:03 -04:00
David Kaspar
d8fd9f127d Merge pull request #1387 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-07-20 16:12:05 +02:00
Crowdin Bot
0037d642b0 New Crowdin translations by GitHub Action 2025-07-20 14:11:35 +00:00
Vitor Pamplona
3b0c1b6d4f Merge pull request #1386 from davotoula/upgrade-agp
Upgrade agp to 8.11.1
2025-07-20 10:10:29 -04:00
David Kaspar
4855e36e4c Upgrade agp to 8.11.1 2025-07-20 11:46:26 +02:00
Vitor Pamplona
8a3bb6e1ae Significantly reduces the limit in our filters to reduce the amount of duplicated events coming from multiple relays. 2025-07-18 18:35:52 -04:00
Vitor Pamplona
13ce0e7311 Breaks down the amount of reactions for each post to download from the amount of reactions to communities and chats themselves (which is much larger) 2025-07-18 18:34:54 -04:00
Vitor Pamplona
ee67f2ded9 Adds a subscription to download notifications from random relays in case users are not outbox ready yet. 2025-07-18 18:33:50 -04:00
Vitor Pamplona
19327b682c Improves external signer logs 2025-07-18 17:51:43 -04:00
Vitor Pamplona
85dd9dd5a4 Fixes screen clean up in Login 2025-07-18 17:47:56 -04:00
Vitor Pamplona
9d9963d324 Fixes saving old version of event in to the cache. 2025-07-18 17:47:11 -04:00
Vitor Pamplona
58e353fb40 Moves NIP-55 calls to be suspending functions.
Moves NIP-55 calls to include an ID per call, not per event.
Adds error handling facilities to the Signer functions.
Moves the indexing of the decrypted objects to outside the LocalCache
Migrates Signers to become suspending functions.
Migrates Decryption caching systems to outside the Events themselves.
Migrates all NIP-51 lists to the new structure.
Migrates Drafts and NIP-04 and NIP-17 DMs to the new structure
Migrates Bookmarks to the new structure.
Changes the Room route to avoid using hashcode.
2025-07-18 17:17:27 -04:00
Vitor Pamplona
7bdb3a1a18 Fixing method name 2025-07-14 11:50:15 -04:00
Vitor Pamplona
850277fdc1 Optimize imports 2025-07-14 11:29:21 -04:00
Vitor Pamplona
597fec5c43 Removes lazy StateFlows due to inconsistent starting values. 2025-07-14 11:19:12 -04:00
Vitor Pamplona
909eb62db6 Moves private zap decryption to async, all at once. 2025-07-14 11:18:56 -04:00
Vitor Pamplona
510583e72e Rewrites NIP-55 to start offering better error handling. 2025-07-14 11:17:59 -04:00
Vitor Pamplona
f93b08a272 Refactors master serializer name from EventMapper to JsonMapper 2025-07-11 17:10:51 -04:00
Vitor Pamplona
bb5ae5d09e Fixes F-droid compilation due to a duplicated class from a unifiedpush crypto bug 2025-07-11 14:55:13 -04:00
Vitor Pamplona
02a9563de6 Updates spotless 2025-07-11 14:33:43 -04:00
Vitor Pamplona
15efd671ec Reorganizes navigation and unifies topbar designs 2025-07-11 14:05:31 -04:00
Vitor Pamplona
e37d6ebd8b Moves media server from Dialog to Screen with full route. 2025-07-11 09:22:27 -04:00
Vitor Pamplona
2ecfeb6e7f Moves subscription management from Ammolite to Quatrz 2025-07-11 08:51:02 -04:00
Vitor Pamplona
a94c8673d5 Fixing Ephemeral Chat interface 2025-07-10 19:42:18 -04:00
Vitor Pamplona
e3acf4c250 Fixes some of the live stream flags when the event doesn't update. 2025-07-10 18:22:38 -04:00
Vitor Pamplona
dc61c5a8e4 Keeps cache of the content inside Public chat forums 2025-07-10 18:08:32 -04:00
Vitor Pamplona
f3e08bd297 No need for this OkHttp log anymore 2025-07-10 18:08:09 -04:00
Vitor Pamplona
62253d8601 Finish the migration to separate channels 2025-07-10 18:07:57 -04:00
Vitor Pamplona
5daaa6364d Fixes issue with unable to parse text-based content in the event. 2025-07-10 18:07:01 -04:00
Vitor Pamplona
a706005cfd Fixes recent label reuse 2025-07-10 18:06:30 -04:00
Vitor Pamplona
4eb348654f Providing a delete fix for empty drafts. 2025-07-10 17:04:19 -04:00
Vitor Pamplona
191f1344db Starts diskcache together with video cache 2025-07-10 17:02:31 -04:00
Vitor Pamplona
a207d80d55 Separating Reports from Metadata watching 2025-07-10 15:51:57 -04:00
Vitor Pamplona
94a7d9cf14 Makes sure the list is not empty before building the filter 2025-07-10 14:52:27 -04:00
Vitor Pamplona
f1d39b8517 Logs the relays used for deletion events and checks if it hasn't sent the deleted event to each relay already 2025-07-10 14:36:31 -04:00
Vitor Pamplona
7a14d95973 Adds more relays to the DVM inbox.
Sends the new EVENT only after the screen updates.
2025-07-10 14:34:09 -04:00
Vitor Pamplona
8dbb1a889e Avoids displaying loading symbol on our cached AsyncImage implementation 2025-07-10 11:49:16 -04:00
Vitor Pamplona
ca41d4e10a Refactoring 2025-07-10 11:13:52 -04:00
Vitor Pamplona
ee8ffcd03d Fixes some borders of preview cards 2025-07-10 11:08:39 -04:00
Vitor Pamplona
f9189e9ec1 Further separates channels by kind in the UI 2025-07-10 10:57:42 -04:00
Vitor Pamplona
ec985d58e7 Fixes matching image borders in the loading step of preview cards 2025-07-10 09:43:36 -04:00
Vitor Pamplona
a2d16c173c Fixing crash when the last : is not present in an address 2025-07-10 09:38:53 -04:00
Vitor Pamplona
123803edd3 Fixes reply count 2025-07-09 17:48:19 -04:00
Vitor Pamplona
35005dddad Adds checks in the filter to highlight issues with empty or invalid filters 2025-07-09 17:20:59 -04:00
Vitor Pamplona
accc8d4439 Brute forces the finding of events. 2025-07-09 16:57:26 -04:00
Vitor Pamplona
267d4c505a Moves OkHttp to the coroutines version and turns all their usage into suspend functions 2025-07-09 15:14:58 -04:00
Vitor Pamplona
b502ab7de8 Fixes issue on saving NIP47 address 2025-07-09 15:14:25 -04:00
Vitor Pamplona
7eb39b3c4c Readjusts relay view on profile 2025-07-09 09:03:56 -04:00
Vitor Pamplona
17e33c61e7 Refactoring base EOSE managers to provide better logging 2025-07-09 09:03:45 -04:00
Vitor Pamplona
6851b1bb51 Only closes after removing the subscriptions to avoid resubscribing while closing. 2025-07-09 08:37:21 -04:00
Vitor Pamplona
b12e675b3a Refactors the name of the simple relay client 2025-07-09 08:36:50 -04:00
Vitor Pamplona
cc02806390 Fixing weird version number on the left drawer 2025-07-08 19:27:43 -04:00
Vitor Pamplona
2ee1285ea1 Removes old follows in Contact lists. 2025-07-08 19:16:28 -04:00
Vitor Pamplona
c5ed0cfa60 Improves Image load screens in the preview cards 2025-07-08 18:43:10 -04:00
Vitor Pamplona
4084a72178 Minor refactoring in Account 2025-07-08 18:17:18 -04:00
Vitor Pamplona
2c3e641639 Merge branch 'full-outbox' of nostr://vitorpamplona.com/relay.ngit.dev/amethyst into full-outbox
# Conflicts:
#	amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt
2025-07-08 18:06:38 -04:00
Vitor Pamplona
8e0b94646a Includes Trusted Relays in all my relays 2025-07-08 18:05:54 -04:00
Vitor Pamplona
8c4ec1dc7d Includes Trusted Relays in all my relays 2025-07-08 17:52:56 -04:00
Vitor Pamplona
e89a04eb56 Makes sure the metadata and the Advertised Relay list goes to every connected relay. 2025-07-08 17:21:59 -04:00
Vitor Pamplona
8d14f3615d Improves Bech32 parser to consider only the 58 chars of nsec1, npub1 and note1. 2025-07-08 15:22:55 -04:00
Vitor Pamplona
dbb9ee5379 Removing all the default since logic 2025-07-08 15:22:31 -04:00
Vitor Pamplona
0be9447bee Reusing the parsed event to reuse cache when computing relay hints. 2025-07-08 15:22:09 -04:00
Vitor Pamplona
0d174aae30 Refining the outbox relay selection with all hints. 2025-07-08 14:34:52 -04:00
Vitor Pamplona
994363602d Turns the relay information dialog into a route 2025-07-08 12:00:17 -04:00
Vitor Pamplona
296fa201f7 Delete Relay Selection dialog from all new post screens. 2025-07-08 11:28:30 -04:00
Vitor Pamplona
a05b2681ad 1. Fixes crash when opening the relay selection dialog
2. Fixes color and size of ping labels on relays
3. Removes delete button for connected relay view.
2025-07-08 10:20:54 -04:00
Vitor Pamplona
1b86c3d85b Fixes the sending of multiple old events back to the relays that send old events to Amethyst. 2025-07-08 09:22:33 -04:00
Vitor Pamplona
2c90aa4b1e Continues the migration to use full parsed Addresses instead of just addressIds on the Local Cache. Moves the community route to take a full address. 2025-07-08 08:54:13 -04:00
Vitor Pamplona
0fe8f6c78c Improves debouncing when changing relays. 2025-07-07 20:40:29 -04:00
Vitor Pamplona
b800b5a664 Early support for Blocked and Trusted Relay Lists 2025-07-07 19:49:23 -04:00
Vitor Pamplona
d084714a21 Avoids logging all REQs by default. 2025-07-07 17:19:37 -04:00
Vitor Pamplona
ed2d7f57c5 Adds the incoming relay as a hint to all related keys, addresses and event ids. 2025-07-07 17:02:42 -04:00
Vitor Pamplona
eb5d113298 new map of set api 2025-07-07 13:48:39 -04:00
Vitor Pamplona
cf48516602 Makes sure Filters are not updated if the since is the only change 2025-07-07 13:37:57 -04:00
Vitor Pamplona
28d182cc55 Updates tor, okhttp and navigation compose 2025-07-03 18:26:57 -04:00
Vitor Pamplona
7eeb2ed66a Fixes count call mistake 2025-07-03 18:26:34 -04:00
Vitor Pamplona
1e8ca6c5f0 Merge remote-tracking branch 'origin/HEAD' into full-outbox 2025-07-03 17:22:38 -04:00
Vitor Pamplona
9e72f5d55e Fixes icon size cache on the User Profile 2025-07-03 17:14:07 -04:00
David Kaspar
1db628719b Merge pull request #1384 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-07-03 22:04:11 +02:00
Vitor Pamplona
e4ebca29f4 Improves RelayHint normalization to make sure the NormalizedRelayUrls are indeed relays 2025-07-03 15:45:46 -04:00
Crowdin Bot
67ae61e5d4 New Crowdin translations by GitHub Action 2025-07-03 19:13:48 +00:00
Vitor Pamplona
64bad2b476 Better logs for the basic relay 2025-07-03 13:08:50 -04:00
Vitor Pamplona
cfbf113910 Fixes crash on lazy flows when uploading images before the relay list is loaded. 2025-07-03 13:08:27 -04:00
Vitor Pamplona
47e69ce045 Improves caching on the allRelays call on the Nostr Client 2025-07-03 10:30:53 -04:00
Vitor Pamplona
da3dbb0321 Fixes the Account switching issue that was calling onDispose AFTER a new user composition was run and thus closing all connections on switching 2025-07-03 10:30:19 -04:00
Vitor Pamplona
1f4ad32d23 Fixes the clearing of the mapping function between users and subscription ids when subscriptions end 2025-07-03 10:29:17 -04:00
Vitor Pamplona
69db9bdcd5 Reviews onDispose calls to make sure the onDispose is disposing the data from the previous composable, since it can happen AFTER a new composition already took place. So the references must match the old composition. 2025-07-03 10:27:47 -04:00
Vitor Pamplona
5bcaf065a3 Fixing logs for the new list of connected relays. 2025-07-03 10:19:33 -04:00
Vitor Pamplona
1fa2592563 Improves the performance and logging structures for the anti-spam filter. 2025-07-02 19:36:33 -04:00
Vitor Pamplona
ad481e1928 Removes another local relay from the list 2025-07-02 17:59:14 -04:00
Vitor Pamplona
5525bc4bd9 Increasing the thread pool for OkHttp in order to sustain more connections. 2025-07-02 17:42:46 -04:00
Vitor Pamplona
0b102df117 Removes local relays from NIP65 lists. 2025-07-02 15:50:50 -04:00
Vitor Pamplona
826718d688 Fixes author id on the outbox loader filter. 2025-07-02 15:35:47 -04:00
Vitor Pamplona
3b260d98ad Marks if it is using Tor in each relay of the list. 2025-07-02 15:15:19 -04:00
Vitor Pamplona
e499410ddb Fixes bug when the string has emojis and is trying to check if it is a hex or not 2025-07-02 15:12:48 -04:00
Vitor Pamplona
11d9af41bd Normalizes the click to open relay info dialog 2025-07-02 14:52:16 -04:00
Vitor Pamplona
67dc396588 Displays all available and connected relays in the relay screen 2025-07-02 14:52:03 -04:00
Vitor Pamplona
d0e66504e4 Improves Relay Icon flow 2025-07-02 14:16:26 -04:00
Vitor Pamplona
8c11ae5c87 Avoids adding local relays to the hint index. 2025-07-02 14:13:36 -04:00
Vitor Pamplona
abd895480d adds local servers to the "local definition" of the Normalized Url 2025-07-02 14:13:09 -04:00
Vitor Pamplona
a1a2e86c94 Reports don't offer hints 2025-07-02 14:12:24 -04:00
Vitor Pamplona
83899bda5a Improves RelayInformation document with an empty one 2025-07-02 14:11:45 -04:00
Vitor Pamplona
29b70a52d4 Improves logs 2025-07-02 14:11:26 -04:00
Vitor Pamplona
dd5c2ca704 Making sure the order of params is right 2025-07-02 13:35:01 -04:00
Vitor Pamplona
ce7965d00e Improves starting value of flows 2025-07-02 12:51:08 -04:00
Vitor Pamplona
bb55aea4a4 Fixing log messages 2025-07-02 12:50:17 -04:00
Vitor Pamplona
546d238db3 Reformats due to new lint 2025-07-02 10:51:13 -04:00
Vitor Pamplona
774ee20a20 Updates all dependencies 2025-07-02 10:51:03 -04:00
Vitor Pamplona
1c4b2e9d1a Recover Send and Wait 2025-07-02 08:59:12 -04:00
Vitor Pamplona
b236938ef5 Simplify the unregistering instead of relying on errors and other states that might come from separate filters to the same relay 2025-07-02 08:59:03 -04:00
Vitor Pamplona
1615337a2c Simplifies new try 2025-07-02 08:58:16 -04:00
Vitor Pamplona
936b17f54a Merge remote-tracking branch 'origin/HEAD' into full-outbox
# Conflicts:
#	ammolite/src/main/java/com/vitorpamplona/ammolite/relays/NostrClient.kt
#	gradle/libs.versions.toml
2025-07-02 08:23:54 -04:00
Vitor Pamplona
0cfcfaf899 3rd large migration to outbox. 2025-07-01 20:38:18 -04:00
Vitor Pamplona
f788d031c9 Merge pull request #1380 from davotoula/684-add-auto-translate-config-to-settings
Add auto translate config to new user specific settings
2025-07-01 08:43:46 -04:00
Vitor Pamplona
ddc50f379d Merge pull request #1381 from greenart7c3/main
Propagate Auth event to `sendAndWaitForResponse`
2025-06-30 08:11:58 -04:00
greenart7c3
bfe5fcf0b1 - Propagate Auth event to sendAndWaitForResponse
- Pass feed types to `sendSingle` when sending signed event
2025-06-30 08:11:10 -03:00
David Kaspar
fb9c070ee6 One more line for description 2025-06-29 18:33:30 +01:00
David Kaspar
285603cc0f added trailing x icon to menu items to clarify removal 2025-06-29 18:28:57 +01:00
David Kaspar
65cca8aa34 Don't show users own languages
TODO:
Add red x to items
Rename Settings to AppSettings (routes, classes)
Add explainer
2025-06-29 17:30:02 +01:00
David Kaspar
6015ea04ce remove selected language from dropdown
TODO:
Rename Settings to AppSettings (routes, classes)
Don't show users own languages
Add explainer
2025-06-26 13:27:32 +02:00
David Kaspar
fdf11d3ca3 revert dropdown
TODO:
Rename Settings to AppSettings (routes, classes)
Don't show users own languages
Remove language from drop down
Add explainer
2025-06-26 09:14:58 +02:00
David Kaspar
5620eb023b added preview for UserSettingsScreen.kt
TODO:
Rename Settings to AppSettings (routes, classes)
Don't show users own languages
Remove language from drop down
Add explainer
2025-06-26 08:56:23 +02:00
David Kaspar
759ef44440 Remove previous implementation
TODO:
Rename Settings to AppSettings (routes, classes)
Don't show users own languages
Remove language from drop down
Add explainer
Change to dropdown with Xs
2025-06-26 08:16:09 +02:00
David Kaspar
f0670971ef Wrap update call in IO scope
TODO:
Don't show users own languages
Remove language from drop down
Add explainer
2025-06-25 20:51:11 +02:00
David Kaspar
c59086068b Move dont translate settings to the dedicated user settings page 2025-06-25 20:42:29 +02:00
David Kaspar
3524f7e412 Added support for multiple icons for a single row (backwards compatible) 2025-06-25 20:18:11 +02:00
David Kaspar
2e2a9bb917 Added user preferences screen 2025-06-25 18:13:43 +02:00
David Kaspar
a5c370133c Change to show excluded languages in dropdown, no rows below
TODO:
Load actually excluded languages
Optimise code
Improve UI
2025-06-25 17:34:14 +02:00
David Kaspar
0495dc88fc Add dropdown with auto translate language excludes to app settings
Persist changes to settings

TODO:
Load actually excluded languages
Optimise code
Improve UI
2025-06-25 17:34:14 +02:00
Vitor Pamplona
f536abb22a Merge pull request #1378 from davotoula/main
Upgrade AGP and Gradle
2025-06-25 11:22:33 -04:00
David Kaspar
0bae8adebc Upgrade AGP to 8.11.0
Upgrade Gradle to 8.13
2025-06-25 17:18:05 +02:00
Vitor Pamplona
3270254f47 Merge pull request #1377 from davotoula/strip-codec-from-mime-type-before-saving-video
bugfix: only user part before ";" in media-type before passing to ContentResolver
2025-06-25 10:53:16 -04:00
David Kaspar
dacc9f236b strip anything after ";" in media-type before passing to ContentResolver 2025-06-25 16:33:28 +02:00
David Kaspar
cd316fb52f Merge pull request #1376 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-06-25 14:20:16 +02:00
Crowdin Bot
bf7638eaa9 New Crowdin translations by GitHub Action 2025-06-25 12:02:19 +00:00
Vitor Pamplona
3f049a0536 Merge pull request #1375 from davotoula/fix-build-issue-android-kotlin-geohash
fix build: change to version b481c6a64e of android-kotlin-geohash
2025-06-25 08:00:55 -04:00
David Kaspar
86bfca99e6 change to version b481c6a64e of android-kotlin-geohash as 1.0 has disappeared from jitpack.io 2025-06-25 11:41:28 +02:00
Vitor Pamplona
e7dec1702d Merge pull request #1369 from alltheseas/patch-2
Update README.md with deepwiki link
2025-06-19 09:48:04 -04:00
Vitor Pamplona
4a848b3296 Merge pull request #1372 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-06-19 09:47:52 -04:00
Crowdin Bot
2d9348b640 New Crowdin translations by GitHub Action 2025-06-19 13:46:40 +00:00
Vitor Pamplona
44108c7410 Merge pull request #1371 from greenart7c3/main
Add a UnsignedEventDeserializer
2025-06-19 09:45:19 -04:00
greenart7c3
9e58c2d3b9 Use EventTemplate instead of Event in BunkerRequestSign 2025-06-18 17:24:43 -03:00
greenart7c3
acf426ccdc Add a UnsignedEventDeserializer 2025-06-18 13:28:43 -03:00
alltheseas
2889c5dae5 Update README.md with deepwiki link
added link to amethyst deepwiki
2025-06-09 17:13:35 -05:00
Vitor Pamplona
8276156f0a Merge pull request #1367 from davotoula/upgrade-agp
Upgrade AGP to 8.10.1
2025-06-05 13:02:06 -04:00
David Kaspar
6a544340cb Upgrade AGP to 8.10.1 2025-06-05 18:52:36 +02:00
Vitor Pamplona
5ee64b31d2 Merge pull request #1366 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-06-02 11:36:03 -04:00
Crowdin Bot
ec1dd3cc6e New Crowdin translations by GitHub Action 2025-06-02 15:28:22 +00:00
Vitor Pamplona
ef6313696d Merge pull request #1365 from davotoula/remove-unused-resource-ids-from-translated-files
remove unused string ids from translations
2025-06-02 11:27:07 -04:00
David Kaspar
ffeeebfe1e remove unused string ids from translations 2025-06-02 16:12:42 +02:00
Vitor Pamplona
fcde05c91e Merge pull request #1363 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-05-30 14:42:48 -04:00
Crowdin Bot
6b1662da24 New Crowdin translations by GitHub Action 2025-05-30 18:40:22 +00:00
Vitor Pamplona
5925a91e62 Merge pull request #1360 from davotoula/update-string-ids
update string ids to force new translations
2025-05-30 14:39:03 -04:00
David Kaspar
d83e8007dc Merge pull request #1362 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-05-28 08:29:43 +02:00
Crowdin Bot
173a27f085 New Crowdin translations by GitHub Action 2025-05-28 06:20:54 +00:00
David Kaspar
a970080478 Merge pull request #1361 from davotoula/remove-unused-imports
remove unused imports amethyst
2025-05-28 08:19:40 +02:00
David Kaspar
293bd2557b remove unused imports amethyst 2025-05-28 07:42:20 +02:00
David Kaspar
dac1c3717a update string ids to force new translations 2025-05-27 18:49:35 +02:00
Vitor Pamplona
e10332c957 - Only saves draft after the first change in the UI.
- Adjusts coroutine scopes to make sure it cannot be cancelled while posting
2025-05-20 18:21:19 -04:00
Vitor Pamplona
de881c23ec Migrates button objects out of the new post screen file 2025-05-20 17:01:55 -04:00
Vitor Pamplona
fcfa2bb05a Making NewPost Screen to be about Kind 1 and polls only 2025-05-20 16:30:35 -04:00
Vitor Pamplona
00048606fa Small refactoring 2025-05-20 15:22:53 -04:00
Vitor Pamplona
65bab50a6d Slight improvements on paddings and spacings 2025-05-20 15:18:32 -04:00
Vitor Pamplona
6d0b05e34d Activates NIP-22 reply for everything but kind 1s. 2025-05-20 15:00:00 -04:00
Vitor Pamplona
195e268865 Normalizes NIP-22 viewmodel to its own entity 2025-05-20 14:23:51 -04:00
Vitor Pamplona
bb1dfee35b Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-05-20 11:54:29 -04:00
Vitor Pamplona
63340d79e2 - Adds support for creating and replying to NIP-22 geo scope posts
- Adds support for creating and replying to NIP-22 hashtag scope posts
- Refactors NIP-73 and NIP-22 on quartz to better support scoped replies
- Creates New post screens for both hashtags and geolocated posts.
2025-05-20 11:54:21 -04:00
Vitor Pamplona
041aa1c461 Fixes hashtag search i18n and padding 2025-05-20 11:50:24 -04:00
Vitor Pamplona
1594971a60 Merge pull request #1359 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-05-19 18:45:48 -04:00
Crowdin Bot
12b7cf410d New Crowdin translations by GitHub Action 2025-05-19 22:16:05 +00:00
Vitor Pamplona
a5e8bdd43a Fixes NIP-22 identifier for geotags 2025-05-19 17:42:16 -04:00
Vitor Pamplona
ba71c95bec Removes youtube links from the video feed 2025-05-19 17:41:50 -04:00
Vitor Pamplona
e5230d734c Merge pull request #1358 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-05-17 08:18:40 -04:00
Crowdin Bot
1a45e26eb8 New Crowdin translations by GitHub Action 2025-05-17 12:17:19 +00:00
Vitor Pamplona
1b81dfd832 Merge pull request #1357 from davotoula/remove-unused-imports
remove unused imports
2025-05-17 08:16:03 -04:00
David Kaspar
7ee2a02227 remove unused imports 2025-05-17 08:50:04 +02:00
Vitor Pamplona
8a59904bfc Fixes local cache strategy to create an option and not verify events from Seals. 2025-05-16 19:27:39 -04:00
Vitor Pamplona
049e1d15ce Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-05-16 17:03:04 -04:00
Vitor Pamplona
203b5e5f39 Align specific inner events with the new verification procedures inside the consume function 2025-05-16 17:02:35 -04:00
David Kaspar
0bb8349a46 Update README.md
Long form content view only
2025-05-16 21:33:05 +02:00
David Kaspar
725fb11ec5 Merge pull request #1356 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-05-16 20:29:04 +02:00
Crowdin Bot
c429a97bb4 New Crowdin translations by GitHub Action 2025-05-16 18:15:50 +00:00
Vitor Pamplona
ad12f80679 Upgrade Media3 to 1.7.1 2025-05-16 14:14:11 -04:00
Vitor Pamplona
d35e3f8daf Removing deprecated functions 2025-05-16 14:11:12 -04:00
Vitor Pamplona
780a1ef65e Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-05-16 14:05:20 -04:00
David Kaspar
c413659c87 Merge pull request #1355 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-05-16 19:48:21 +02:00
Crowdin Bot
23f42a025a New Crowdin translations by GitHub Action 2025-05-16 17:40:35 +00:00
David Kaspar
ef1ac76839 Update strings.xml
Fixed typo
2025-05-16 18:39:14 +01:00
Vitor Pamplona
141713bd35 Minor refactoring 2025-05-16 12:55:29 -04:00
Vitor Pamplona
b5a1b84fa8 Fixes logging of the memory cache usage 2025-05-16 12:48:01 -04:00
Vitor Pamplona
1a681e1b53 Deletes encrypted component of the GiftWrap after unwrapping to avoid consuming memory needlessly 2025-05-16 12:47:35 -04:00
Vitor Pamplona
07434eb4b6 Fixes newStack bug that was only resetting the stack until the home and not to its own route 2025-05-15 17:02:15 -04:00
Vitor Pamplona
ac7084ce84 Removing debug methods from the main binary 2025-05-15 16:40:44 -04:00
Vitor Pamplona
dc6f982ae9 Adds a byte count in the event per second logger 2025-05-15 15:33:53 -04:00
Vitor Pamplona
ea9d25d13b Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-05-15 11:49:34 -04:00
Vitor Pamplona
afe04969ee Improves edge to edge margins and colors for the RelayInfoDialog 2025-05-15 11:49:25 -04:00
Vitor Pamplona
3823acef0b Merge pull request #1354 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-05-15 08:38:34 -04:00
Crowdin Bot
12ac1c48bb New Crowdin translations by GitHub Action 2025-05-15 12:37:54 +00:00
Vitor Pamplona
b345eca8ad Merge pull request #1350 from davotoula/share-media-to-other-apps
Share images to other apps
2025-05-15 08:36:23 -04:00
David Kaspar
c3c8b56a39 Merge branch 'main' into share-media-to-other-apps 2025-05-15 07:41:28 +02:00
Vitor Pamplona
42e20efaa5 removing unused imports 2025-05-14 20:39:01 -04:00
Vitor Pamplona
2ef1cb5fea Merge pull request #1353 from kirpy0x/NostrLinks
Open Njump, Yakihonne and Primal links in Amethyst
2025-05-14 20:33:55 -04:00
Vitor Pamplona
df2f0feef8 Improvement to the logs of RelaySpeedLogger 2025-05-14 20:32:33 -04:00
Vitor Pamplona
700813dab7 Moves LocalCache bundler to the default thread 2025-05-14 19:27:57 -04:00
kirpy
b925b12278 Open Njump, Yakihonne and Primal links in Amethyst
fixes: 1217
2025-05-14 17:23:58 -06:00
Vitor Pamplona
6367e9ddc9 Moving logs from SubscriptionController to the Manager to be able to distinguish between the multiple managers 2025-05-14 19:19:58 -04:00
Vitor Pamplona
dfdee1ae96 - Migrating a mix of tags from the old Tag array methods to the new Tag Object parsers.
- Starting to use fast methods for Tag array loops instead of the native kotlin ones.
2025-05-14 19:19:29 -04:00
Vitor Pamplona
c0ecda94a3 Uses fastAny to avoid creating an iterator 2025-05-14 18:29:03 -04:00
Vitor Pamplona
acf944ebac Avoids item drawing mishandling of multiple incognitos in the same chat screen 2025-05-14 18:28:49 -04:00
Vitor Pamplona
3c5b9dbca6 Fixes an issue with two home screens interfering with flow collections. For some reason it was only a problem because this route matches the starting route. 2025-05-14 17:00:36 -04:00
Vitor Pamplona
e0449a9d44 Adds a list state saver to the messages screen 2025-05-14 16:52:19 -04:00
Vitor Pamplona
4ae86861f8 Removes unnecessary labels 2025-05-14 15:17:31 -04:00
Vitor Pamplona
9e13e88ae9 removes log 2025-05-14 15:00:35 -04:00
Vitor Pamplona
1ed9aa64bf Gets rid of the update bundler for Notes, Users and Channel. 2025-05-14 15:00:06 -04:00
Vitor Pamplona
803decf5ff Move the EOSE cache from Note to the sub assembler 2025-05-14 14:59:27 -04:00
Vitor Pamplona
6a91b68b4b Migrates missing User filter to the new no EOSE cache manager 2025-05-14 14:56:47 -04:00
Vitor Pamplona
0f018140f0 Minor refactoring 2025-05-14 14:56:08 -04:00
Vitor Pamplona
979e02e7fa Migrates event finder and channel finder to the new No Eose cache manager 2025-05-14 14:55:53 -04:00
Vitor Pamplona
4fc2d3a7d1 Adds a new EOSE manager that keeps one sub but no EOSE cache 2025-05-14 14:53:54 -04:00
Vitor Pamplona
d0f138e992 Generalizes the FastEOSE cache for Users 2025-05-14 14:53:30 -04:00
Vitor Pamplona
b7ac32d768 Removes unused since param for missing events in thread assemblers 2025-05-14 14:50:52 -04:00
David Kaspar
3b5d12b477 make helper method suspend, use different scope in View 2025-05-14 19:15:16 +02:00
Vitor Pamplona
6f7f8e296b Removes the time logger for note rendering 2025-05-14 12:53:56 -04:00
David Kaspar
d6ee09ecdb Merge branch 'main' into share-media-to-other-apps 2025-05-14 18:20:57 +02:00
David Kaspar
61970b8ce5 Update README.md
Split video and image capture from phone. Ticket image capture
2025-05-14 17:17:27 +01:00
Vitor Pamplona
b045d0e122 Migrates lint to the newer default version and copyright to 2025 2025-05-14 11:59:15 -04:00
Vitor Pamplona
47de821f6d Updates coil, compose, immutable, lifecycle, navigation and zoomable 2025-05-14 11:14:33 -04:00
Vitor Pamplona
2c06df7e50 Simple refactoring for the name of the subscription cache 2025-05-14 10:43:42 -04:00
Vitor Pamplona
52d31502e6 Migrates the Subscription controller to use filters from the NostrClient instead of the past version in the controller to avoid out of sync comparisons 2025-05-14 10:08:56 -04:00
Vitor Pamplona
d7d8f02a80 Moves Content Sensitivity setting to the Security filter screen 2025-05-13 20:09:14 -04:00
Vitor Pamplona
f3e2327676 Modifies the behavior of new posts to clear the background color after 5 seconds 2025-05-13 17:21:22 -04:00
Vitor Pamplona
dba51acbd5 Merge pull request #1351 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-05-13 15:32:53 -04:00
Crowdin Bot
20c775913a New Crowdin translations by GitHub Action 2025-05-13 19:24:27 +00:00
Vitor Pamplona
a42afdc78b merge 2025-05-13 14:53:00 -04:00
Vitor Pamplona
6ecb25b8e1 - Refactors the entire EOSE caching structure.
- Refactors all Datasource classes into a 3 layer design with composeSubscriptions being registered, passed to a group of EOSE managers that can change eose caching capabilities based on needs, and migrates the old subscription Orchestrator into a simpler controller
- Breaks down all Datasource into multiple filter functions
- Improves EOSE support for many of the base filters like on NIP-04 DMs, notifications, etc
- Moves EOSE cache for public, non-user-dependent items like channels, hashtags, etc to their own caching system.
- Improves the Relay speed logger to better track how many events are being received, and check for duplications
2025-05-13 14:52:26 -04:00
Vitor Pamplona
0e68031227 Removes the need to track EOSE at the base user class 2025-05-13 14:47:20 -04:00
Vitor Pamplona
466f52245b Adds an isDifferent function to avoid resending NormalFilters 2025-05-13 14:46:09 -04:00
Vitor Pamplona
09946c19b9 Turns all base Hint classes into data classes 2025-05-13 14:44:03 -04:00
Vitor Pamplona
4279ad004c Only updates EOSE log if the time is bigger 2025-05-13 14:43:44 -04:00
Vitor Pamplona
50cde1bc3e - Bugfix to mark relay connections as AfterEOSE when the relay client or server closes the subscription
- Adds an arrival time to log the time EOSEs were received in case the listener is running async processes later.
2025-05-13 14:43:28 -04:00
Vitor Pamplona
2d5732bcce Normalizes hashtag transformations for filters. 2025-05-13 14:40:03 -04:00
David Kaspar
a848ea6135 add content param when making call using a MediaPreloadedContent. Just in case 2025-05-13 09:43:23 +02:00
David Kaspar
095d054d62 add support for gifs 2025-05-13 09:39:33 +02:00
David Kaspar
2e4c9f77e6 refactor 2025-05-13 09:39:33 +02:00
David Kaspar
7efec03056 Return file extension from ShareHelper just in case mimetype is null
Use content to determine whether it's an image
2025-05-12 22:26:24 +02:00
David Kaspar
91b6bf6e88 localisation 2025-05-12 21:03:17 +02:00
David Kaspar
35001c0b00 moved sharing intent back to view 2025-05-12 20:56:16 +02:00
David Kaspar
ce96ab873f added todos 2025-05-12 18:42:56 +02:00
David Kaspar
8c1888b4d5 added error handling
.use {} for automatic resource management with snapshots
2025-05-12 17:40:28 +02:00
David Kaspar
0192a4eb20 Add test to only share images. Other media not supported atm 2025-05-12 17:13:29 +02:00
David Kaspar
fee85a6111 remove scope launch 2025-05-12 17:06:05 +02:00
David Kaspar
13ee0a23de Use disk cache reference from app
Detect image type based on magic number
2025-05-12 16:44:31 +02:00
David Kaspar
ebf1571b92 share images from coil cache to other apps 2025-05-08 18:05:06 +02:00
Vitor Pamplona
a5c63dd311 Merge pull request #1349 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-05-08 10:58:07 -04:00
Crowdin Bot
245b767dc8 New Crowdin translations by GitHub Action 2025-05-08 14:56:55 +00:00
Vitor Pamplona
be62d5ad7f Merge pull request #1347 from davotoula/use-updated-markdown-to-sanitise-url-labels
Use new version of Markdown to sanitise url labels from # and @
2025-05-08 10:55:33 -04:00
Vitor Pamplona
dc132de18d Merge pull request #1348 from davotoula/upgrade-agp-to-8.10.0
Upgrade agp to 8.10.0
2025-05-08 10:52:52 -04:00
David Kaspar
5d1515659e remove unused imports 2025-05-08 13:13:02 +02:00
David Kaspar
6206d550e6 Upgrade agp to 8.10.0 2025-05-08 13:09:08 +02:00
David Kaspar
d7055062f3 Use new version of Markdown to sanitise url labels from # and @ 2025-05-08 11:58:02 +02:00
Vitor Pamplona
bddd8914ae Adds an EOSE manager to Channel Filters 2025-05-07 13:54:56 -04:00
Vitor Pamplona
2fc7c37270 Adds a watcher of MetadataChanges for NIP-28 that includes a since parameter for the last metadata time + 1 2025-05-07 13:48:54 -04:00
Vitor Pamplona
bc22b78f19 Refactors EOSE management for Chatroom List 2025-05-07 13:47:34 -04:00
Vitor Pamplona
e6b0b41e80 Adds a Normal Nostr filter as a PerRelay filter 2025-05-07 13:46:39 -04:00
Vitor Pamplona
8a7ce8dc07 Makes EOSE cache per user cleanable 2025-05-07 13:46:14 -04:00
Vitor Pamplona
cb4e57d6f6 remove the filter invalidation after each EOSE 2025-05-06 19:42:23 -04:00
Vitor Pamplona
a54835e4f9 Adds Eose management for the UserProfile Screen 2025-05-06 19:42:09 -04:00
Vitor Pamplona
be0a559b7d Prints better logs for relay subscriptions 2025-05-06 19:38:13 -04:00
Vitor Pamplona
b801125ff5 Builds a speed logger to better understand data usage 2025-05-06 19:37:44 -04:00
Vitor Pamplona
4ea9d2db7d Updates AGP to 8.10 2025-05-06 18:21:15 -04:00
Vitor Pamplona
54532de88a Extending AsyncImage to correctly use pre-loaded aspect ratio and avoid screen jittering 2025-05-06 16:46:25 -04:00
Vitor Pamplona
ba6a7bb07f Fixes missing content alignment on the crossfade API migration 2025-05-06 16:18:21 -04:00
Vitor Pamplona
fcd70001bf Adds a Reads feed to the discovery tab 2025-05-06 15:48:03 -04:00
Vitor Pamplona
80d4971548 - Adds FollowSets to the discovery tabs.
- Refactors discovery screen, creating a package for each feature.
- Fixes Android studio previews
2025-05-06 13:23:43 -04:00
Vitor Pamplona
fbe20029f7 Move to a cache model where we defer the event's verification until the last moment before adding to cache 2025-05-06 09:45:01 -04:00
Vitor Pamplona
a05a465f69 Avoids sending an NWC filter when there are no keys subscribed to it 2025-05-06 08:56:47 -04:00
Vitor Pamplona
49c131a5cd Adding more constraints to the channel filter 2025-05-05 19:11:54 -04:00
Vitor Pamplona
1c23600c57 Assigns the first relay when a gift-wrapped message is received 2025-05-05 18:51:45 -04:00
Vitor Pamplona
7a8766551f unused checks 2025-05-05 18:36:13 -04:00
Vitor Pamplona
7accb5e2b9 Adds onStart calculator for live bubble authors 2025-05-05 18:34:54 -04:00
Vitor Pamplona
504f365ab3 Fixes code to mark messages as received by relays 2025-05-05 18:12:16 -04:00
Vitor Pamplona
d9b784bee5 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-05-05 17:22:53 -04:00
Vitor Pamplona
aff95853d8 Merge pull request #1346 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-05-05 17:21:15 -04:00
Vitor Pamplona
adcbbec5be Removing unnecessary logs 2025-05-05 17:21:03 -04:00
Crowdin Bot
ceabf8184a New Crowdin translations by GitHub Action 2025-05-05 21:10:39 +00:00
Vitor Pamplona
7aa71fad3f Caches app icons as painters 2025-05-05 17:08:47 -04:00
Vitor Pamplona
15dfbb2f31 Fixes the test case for emojis 2025-05-03 16:33:28 -04:00
Vitor Pamplona
0d53a30371 Disable event logger for now 2025-05-03 16:33:08 -04:00
Vitor Pamplona
38bb39a407 Fixes bug when trying to detect the charset of the first 1024 bytes of the page. Since this is an invalid HTML, it was crashing here. 2025-05-03 16:15:20 -04:00
Vitor Pamplona
560a9ba471 Fixes some log messages 2025-05-02 21:23:44 -04:00
Vitor Pamplona
38d3194e87 Merge branch 'main' of https://github.com/vitorpamplona/amethyst
# Conflicts:
#	amethyst/src/main/java/com/vitorpamplona/amethyst/model/Account.kt
2025-05-02 21:19:14 -04:00
Vitor Pamplona
462fda1b5c Updates accompanist, jackson, mockk, secp256, zoomable 2025-05-02 21:18:40 -04:00
Vitor Pamplona
63a009f36d - Adds support for Ephemeral Chats from coolr.chat
- Adds support for following ephemeral chats
- Adds support for live events at the top of the feed.
- Adds support for NIP-51, kind:10005 public chat lists
- Adds support for Channel feeds
- Moves following of NIP-28 chats from the Contact List to kind: 10005
- Disables following of events at the Contact list
- Improves gallery display to slightly override profile pictures when in list
- Starts the Account refactoring by moving custom Emoji, EphemeralList and PublicChat lists to their own packages
- Refactors NIP-51 lists to use common classes of private tags instead of general list classes.
- Starts to separate all Public chats into their own database.
- Removes old account upgrades from the local storage
- Refactors url NIP-11 loading and unifies icon
- Reduces the dependency of Relay classes in the LocalCache, Notes and User classes
2025-05-02 21:18:10 -04:00
David Kaspar
c3dc8104e9 Merge pull request #1340 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-05-02 15:27:21 +02:00
Crowdin Bot
23fbb53c96 New Crowdin translations by GitHub Action 2025-05-02 13:20:35 +00:00
Vitor Pamplona
1fe55ece5d Merge pull request #1339 from davotoula/missing-at-for-profile-links-in-markdown
Missing at for profile links in markdown and fix typo preventing opening of hashtags from markdown notes
2025-05-02 09:19:03 -04:00
David Kaspar
bb9435e637 Remove unused imports 2025-05-02 15:05:20 +02:00
David Kaspar
67e3a92d68 cleanup 2025-05-02 15:00:27 +02:00
David Kaspar
32439b5feb bugfix: fix typo preventing opening of hashtags from markdown notes 2025-05-02 15:00:06 +02:00
David Kaspar
136a4061d7 prepend clickable user with @ sign 2025-05-02 14:59:32 +02:00
Vitor Pamplona
b06e53f59d Fixes lack of update for Discovery filters when resuming 2025-04-30 15:24:00 -04:00
Vitor Pamplona
9c79ef08c7 Moves logging out of quartz Relay class 2025-04-30 14:00:08 -04:00
Vitor Pamplona
43b761c98c Slight improvement in the UI to view follow packs 2025-04-29 17:38:00 -04:00
Vitor Pamplona
626bfc95cb - Adds support for Follow packs
- Enables top filter by pack as well.
2025-04-29 17:24:03 -04:00
Vitor Pamplona
9df0f6c368 Moves Coil's image loader choice to a subscription on account. 2025-04-29 16:04:16 -04:00
Vitor Pamplona
7c68ffaf6e Delete unused flows 2025-04-29 15:55:57 -04:00
Vitor Pamplona
ee1d37dd5b Merge pull request #1338 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-04-29 14:39:17 -04:00
Crowdin Bot
ed6d0f6c0f New Crowdin translations by GitHub Action 2025-04-29 18:37:53 +00:00
Vitor Pamplona
533e7d661f Presubscribe to the bottom navigation items in the start up of the app. 2025-04-29 14:36:01 -04:00
Vitor Pamplona
932664c9f9 Avoids crashes when fetching base64 and blurhash images 2025-04-29 14:33:55 -04:00
David Kaspar
3d89ed567b Merge pull request #1337 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-04-29 06:11:07 +02:00
Crowdin Bot
62e2e2ac65 New Crowdin translations by GitHub Action 2025-04-29 01:16:39 +00:00
Vitor Pamplona
1c8a6d1234 - Separates new Product Screen from the generic new Post screen.
- Adds New product button on the Marketplace tab
- Adds imeta tags for images and urls inside the content of the Classifieds.
- Shows multiple images on the post and thread view.
- Removes the option for NIP-95 images on Classifieds.
- Creates a new route for new products
- Adjusts quarts to process images with iMeta tags
2025-04-28 21:13:41 -04:00
Vitor Pamplona
c07592f399 Migrates Relay selection dialog to full bleed layout 2025-04-28 20:58:23 -04:00
Vitor Pamplona
96b1565de7 Removes duplicated draft save on DM 2025-04-28 20:57:11 -04:00
Vitor Pamplona
ee675d06f6 Merge pull request #1336 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-04-26 11:05:50 -04:00
Crowdin Bot
7c02b5b58f New Crowdin translations by GitHub Action 2025-04-26 15:00:51 +00:00
Vitor Pamplona
4c7ef8ecff Caches the processing of preview urls for the new post screen
Fixes a bug on saving MediaType on Android's stack
2025-04-26 10:58:45 -04:00
Vitor Pamplona
99cef643e1 Improves the visual of multiple previews on the new post screen 2025-04-26 10:58:17 -04:00
Vitor Pamplona
08025f7df7 Adds a special case for loading previews with just 1 item in the new post screen 2025-04-25 17:41:06 -04:00
Vitor Pamplona
92eff02f0a Removes the hack to reduce memory usage by deleting the .content when saving the event to cache. 2025-04-25 17:04:16 -04:00
Vitor Pamplona
539d20b397 Adds an error log for the new on account view model processor 2025-04-25 17:03:26 -04:00
Vitor Pamplona
b51e5f4383 better relay reconnecting logic 2025-04-25 17:02:58 -04:00
Vitor Pamplona
0c54f9aa10 Renders the new comment tag on highlights. 2025-04-25 16:58:41 -04:00
Vitor Pamplona
c98e23add7 Merging 2025-04-25 15:07:52 -04:00
Vitor Pamplona
e4cc65969a Merge pull request #1332 from davotoula/reduce-compiler-warnings-amethyst
Reduce compiler warnings: amethyst module
2025-04-25 12:16:40 -04:00
Vitor Pamplona
aef7d91a6b Moves privacy option from dialog to route 2025-04-25 12:14:44 -04:00
David Kaspar
d874e798c6 remove unused imports 2025-04-25 17:10:25 +02:00
Vitor Pamplona
390e0615d1 Removing these disabled lock behavior code until we get it working 2025-04-25 11:10:04 -04:00
David Kaspar
e40ca09f7c Use default locale for capitalisation in UI strings (use ROOT for IDs/Hashes for consistency) 2025-04-25 17:00:16 +02:00
David Kaspar
96436912bb Safe checked casting 2025-04-25 16:03:16 +02:00
David Kaspar
97290cea48 Replace String.capitalize with replaceFirstChar 2025-04-25 16:02:59 +02:00
David Kaspar
ad2387f8e9 Add @OptIns
Change to auto mirrored icons
Remove unnecessary inline
2025-04-25 15:59:54 +02:00
Vitor Pamplona
d25e89f41d Removes pull to refresh hack since we can now fully migrate 2025-04-24 19:36:47 -04:00
Vitor Pamplona
04712468aa Removing unused nip-05 2025-04-24 19:14:35 -04:00
Vitor Pamplona
354fc34fbb New default banner 2025-04-24 19:08:58 -04:00
Vitor Pamplona
026943439a reverting x 2025-04-24 18:51:34 -04:00
Vitor Pamplona
46cb7eb640 Removes text select icon 2025-04-24 18:50:16 -04:00
Vitor Pamplona
f465844009 Removes old icons and migrates some to the Icons package 2025-04-24 18:49:05 -04:00
Vitor Pamplona
eebbda547d Trying again to fix the hyphen 2025-04-24 18:25:09 -04:00
Vitor Pamplona
122603080e Removed unused function 2025-04-24 18:21:30 -04:00
Vitor Pamplona
aff0369b04 updating firebase 2025-04-24 18:14:02 -04:00
Vitor Pamplona
1c1db6fa1e Removes unused copytext dialog 2025-04-24 18:10:52 -04:00
Vitor Pamplona
187d77c138 Marks GlobalScope as optin 2025-04-24 18:07:22 -04:00
Vitor Pamplona
950d0bcc93 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-04-24 18:06:49 -04:00
Vitor Pamplona
0d66ceb1a4 Merge pull request #1330 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-04-24 18:06:39 -04:00
Vitor Pamplona
8e0563ed3a Migrate animateItemPlacement to new API 2025-04-24 17:46:13 -04:00
Crowdin Bot
02870d0cd3 New Crowdin translations by GitHub Action 2025-04-24 21:41:05 +00:00
Vitor Pamplona
9d3a6d3f1d migrates compose bom and media3 2025-04-24 17:40:38 -04:00
Vitor Pamplona
2c85260ab1 Removes the old ic_verified 2025-04-24 17:39:00 -04:00
Vitor Pamplona
ecebc68e11 avoiding deprecated .put api 2025-04-24 17:36:27 -04:00
Vitor Pamplona
07c3a3ffe5 Fixes unchecked cast and other opt-in tags on observers 2025-04-24 17:35:34 -04:00
Vitor Pamplona
c0f486db82 Hyphen can be replaced with dash 2025-04-24 17:35:11 -04:00
Vitor Pamplona
e0990ae38e Merge pull request #1329 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-04-24 17:22:02 -04:00
Crowdin Bot
7005158821 New Crowdin translations by GitHub Action 2025-04-24 21:19:22 +00:00
Vitor Pamplona
9922fa117f Reverting svg sizes because of app icon issues 2025-04-24 17:16:31 -04:00
Vitor Pamplona
723b4b5e9f Removes dependency on a modifier for SettingsCategory 2025-04-24 16:58:40 -04:00
Vitor Pamplona
2d64eb0cb3 Refactors Add and Remove button to remove dependency on a specific modifier. 2025-04-24 16:58:22 -04:00
Vitor Pamplona
6a91ede54c Fixes the lack of locale when creating percentages on zap split screens. 2025-04-24 16:57:44 -04:00
Vitor Pamplona
8d91b97962 Migrates CircularProgresIndicator to the newer version 2025-04-24 16:57:24 -04:00
Vitor Pamplona
bf47c1b431 No need to check for API version in this function, since we check outside of it 2025-04-24 16:56:46 -04:00
Vitor Pamplona
f5a504077c Keeps the transparency settings for statusbar and navigation for now. 2025-04-24 16:55:21 -04:00
Vitor Pamplona
95afed5045 Only request for notification permissions after API 33 2025-04-24 16:54:52 -04:00
Vitor Pamplona
dcccc1de3a Last Uri.parse fix 2025-04-24 16:54:31 -04:00
Vitor Pamplona
5095c9f480 Migrating from ContextCompat.startActivity to context.startActivity 2025-04-24 16:54:17 -04:00
Vitor Pamplona
30c4e3c646 Fixes deprecated URI parse function warnings 2025-04-24 16:52:25 -04:00
Vitor Pamplona
d04f6c977e Migrates to the new capitalization function 2025-04-24 16:50:48 -04:00
Vitor Pamplona
7d97b73356 Fixes mutable state builders with primitive types warning. 2025-04-24 16:48:56 -04:00
Vitor Pamplona
be3eb4314b Fixes casting warnings on viewmodels 2025-04-24 16:46:34 -04:00
Vitor Pamplona
f7abc6e1ee Suppress modifiers on ColorScheme. 2025-04-24 16:44:30 -04:00
Vitor Pamplona
c16b93c06a Reduces viewport to 200dp for performance 2025-04-24 16:44:10 -04:00
Vitor Pamplona
82af2644a6 Removes unnecessary label to v26 2025-04-24 16:43:50 -04:00
Vitor Pamplona
7d2b2ee674 normalizing strings 2025-04-24 16:43:28 -04:00
Vitor Pamplona
fdc95a656f Ignore permissions to use our services. 2025-04-24 16:42:43 -04:00
Vitor Pamplona
7b040933d5 Merge 2025-04-24 14:35:57 -04:00
Vitor Pamplona
067f353e50 Finish the migration from LiveData to Flow
Moves most of the flow updates away from the Main thread.
Removes the need to use the Main thread to access Account.userProfile
2025-04-24 14:35:22 -04:00
Vitor Pamplona
2f3c282ef5 Merge pull request #1328 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-04-24 08:45:03 -04:00
Crowdin Bot
0c8564157b New Crowdin translations by GitHub Action 2025-04-24 12:43:11 +00:00
Vitor Pamplona
d6160ea6c2 Merge pull request #1327 from davotoula/upgrade-agp
upgrade agp to 8.9.2
2025-04-24 08:41:41 -04:00
David Kaspar
0fc04490fd upgrade agp to 8.9.2 2025-04-24 10:44:11 +02:00
Vitor Pamplona
e375b09a24 Fixes missing gallery of reactions 2025-04-23 18:52:43 -04:00
Vitor Pamplona
802e04445d Adds logging message to hunt down some slow screens 2025-04-23 17:15:21 -04:00
Vitor Pamplona
ca8faa062f Caches translations to avoid blinking text every time the user comes back to an older screen. 2025-04-23 16:44:35 -04:00
Vitor Pamplona
d6d34b2a88 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-04-23 16:24:57 -04:00
Vitor Pamplona
a84371a0b3 - Restructures the old static datasource model into dynamic filter assemblers.
- Moves filter assemblers, viewModels and DAL classes to their own packages.
- Creates Composable observers for Users and Notes
- Deletes most of the secondary LiveData objects in the move to Flow
- Manipulates nostr filters depending on the account of the current screen, not a global account.
- Unifies all FilterAssembly lifecycle watchers to a few classes.
- Prepares to separate The Nostr Client as an Engine of Amethyst.
- Moves the pre-caching processor of new events from the datasource to the accountViewModel
- Reorganizes search to be per-screen basis
- Moves authentication to a fixed Coordinator class for all accounts in all relays.
- Moves NOTIFY command to its own coordinator class for all accounts
- Moves the connection between filters and cache to its own class.
- Significantly reduces the dependency on a single ServiceManager class.
2025-04-23 16:24:41 -04:00
Vitor Pamplona
411b49d68f Merge pull request #1326 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-04-23 16:04:46 -04:00
Crowdin Bot
f8fd935a4e New Crowdin translations by GitHub Action 2025-04-23 19:45:34 +00:00
Vitor Pamplona
62be469cd8 Merge pull request #1325 from greenart7c3/main
Filter special characters when decoding bech32
2025-04-23 15:44:08 -04:00
greenart7c3
b42d05ae7a Filter unicode characters 2025-04-23 16:17:13 -03:00
Vitor Pamplona
e007a02d84 Merge pull request #1320 from davotoula/circle-around-profile-picture-in-drawer
contrasting circle around profile picture
2025-04-13 11:13:03 -04:00
David Kaspar
cbd5a8a7ee contrasting circle around profile picture
remove unused import
2025-04-13 09:59:43 +02:00
Vitor Pamplona
fd1c5d5887 Merge pull request #1319 from davotoula/1318-profile-qr-code-screen-changes
corrected profile picture border colour
2025-04-12 11:18:12 -04:00
David Kaspar
043196be10 Update bug_report.md
Added app flavour field (play vs fdroid)
bump versions
2025-04-12 15:56:51 +01:00
David Kaspar
66927ca70c corrected profile picture border colour 2025-04-12 16:02:35 +02:00
Vitor Pamplona
faf0f6dc1a Updates mockk, coroutines, zoomable and vico 2025-04-10 14:06:25 -04:00
Vitor Pamplona
5abb5f2f80 Merge pull request #1317 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-04-10 10:00:00 -04:00
Crowdin Bot
37b84108a7 New Crowdin translations by GitHub Action 2025-04-10 13:48:08 +00:00
Vitor Pamplona
5edc945341 Updates Compose, CoreKtx and SecurityKtx 2025-04-10 09:45:21 -04:00
Vitor Pamplona
3833f5f822 - Refactoring services to be part of the App Lifecycle,
- Migrated services to Flows that are active while their flows remain subscribed
- Improved OTS Decoupling
- Moved OTS verification procedures from the local cache to the data source
- Migrated the forceProxy options to lambdas that return an OkHttpClient
- Isolated Connectivity services, from Compose to Flow
- Isolated Tor services, from Compose to Tor (only starts if the Tor option is marked as internal)
- Isolated Memory trimming services, from Compose to Flow
- Isolated Image Caching services, from Compose to Flow
- Isolated Video Caching services
- Isolated Logging services
- Isolated NIP-95 Caching services
- Isolated Pokey receiver services
- Improved support for Tor in push notifications
- Isolated OkHttpClient services as flows
- Reduced the coupling of Context objects with singleton objects.
- Migrated UserFeedStates, StringFeedStates and ZapFeedStates to MutableStateFlow, avoiding feed updates on Main
- Forces a reconnect into relays that lost connection if any tor, connectivity or account changes
- Speeds up Base64 parser
2025-04-09 18:51:17 -04:00
Vitor Pamplona
652373bd01 Remove the warning saying the app name is being replaced on benchmark. 2025-04-09 16:28:18 -04:00
Vitor Pamplona
e883a46f53 Fixes deprecated warning 2025-04-09 16:20:14 -04:00
Vitor Pamplona
2b7cfa5560 Better name for the Blurhash class to avoid mistakes with its field. 2025-04-03 20:50:43 -04:00
Vitor Pamplona
ed860454a7 Moves activities to be singleInstance to avoid multiple startups when receiving share events from other apps. 2025-04-03 20:46:39 -04:00
Vitor Pamplona
ed0435061c Moves to cover all classes in the proguard. 2025-04-03 20:45:25 -04:00
Vitor Pamplona
223865827f Fixes tagging issue on new post. 2025-04-03 13:54:23 -04:00
Vitor Pamplona
ec25ef3f82 Adds flowerstr 2025-04-03 09:02:31 -04:00
Vitor Pamplona
7c4911f2dc Converts old ClickableTexts into new Compose Texts with clickable spans 2025-04-02 20:37:14 -04:00
Vitor Pamplona
4ac046fe39 Migrates Navigation to Compose Navigation. 2025-04-02 17:39:16 -04:00
Vitor Pamplona
bfd5845022 Updates Firebase and CBOR 2025-04-01 19:26:10 -04:00
Vitor Pamplona
d288010a83 Move the stringresource setup out of the Activity 2025-04-01 19:13:35 -04:00
Vitor Pamplona
834efe02bc Refactors SharedSettings state to:
- Minimize recompositions
- Improve code quality
2025-04-01 18:59:53 -04:00
Vitor Pamplona
1bd32c854c Makes sure the tryLogin function only runs if it is not already logged in (compostables might call it more times) 2025-04-01 18:58:15 -04:00
Vitor Pamplona
d08998736f Removes unecessary preview items from Cashu components. 2025-04-01 18:57:40 -04:00
Vitor Pamplona
a5f9b865ec Makes ZapAmount viewmodel stable 2025-04-01 18:57:17 -04:00
Vitor Pamplona
375931d4f9 Modernizing the edit access to LocalPreferences. 2025-04-01 18:53:30 -04:00
Vitor Pamplona
7e3f64fc61 Performance: Avoids saving the first collection on login 2025-04-01 18:51:29 -04:00
Vitor Pamplona
09024fbc61 Performance: Avoids creating OkHttp proxies directly on the OnCreate 2025-04-01 18:50:08 -04:00
Vitor Pamplona
a530ced594 Performance: Avoids creating a SharedSettings ViewModel on Galery 2025-04-01 18:49:26 -04:00
Vitor Pamplona
3089524a1f Cleaning up from the previous commit 2025-04-01 16:50:55 -04:00
Vitor Pamplona
5aa2aa4d54 Merge translations 2025-04-01 16:36:03 -04:00
Vitor Pamplona
12235216ff Moves The WIFI/Mobile data connection watcher to the compose.
Moves Relay Connection Manager to the Compose
Adds a 30 second delay to approve events on Amber
2025-04-01 16:35:46 -04:00
Vitor Pamplona
35b9648bab Merge pull request #1316 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-04-01 15:06:31 -04:00
Vitor Pamplona
cf2959d42e Refactors logged in page into its own package 2025-04-01 14:03:17 -04:00
Crowdin Bot
b5164d5dd0 New Crowdin translations by GitHub Action 2025-04-01 18:01:18 +00:00
Vitor Pamplona
05cb055b1d Migrates FDroid's push system to match Play services 2025-04-01 13:58:57 -04:00
Vitor Pamplona
f6bd12058f removes firebase logging 2025-04-01 11:56:55 -04:00
Vitor Pamplona
99ef1fc168 Removes Tor leaks when loading thumbnails for vides automatically from the ExoPlayer 2025-04-01 11:56:47 -04:00
Vitor Pamplona
bd02515209 Moves push registration notification into Compose after login to make sure we use the tor configuration of the active user. 2025-04-01 11:18:15 -04:00
Vitor Pamplona
b3f1b093ed Tor now listens to port changes and restart connections when it does change. 2025-03-31 20:32:15 -04:00
Vitor Pamplona
491d269f75 Merge pull request #1315 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-03-31 11:30:04 -04:00
Crowdin Bot
c79243a912 New Crowdin translations by GitHub Action 2025-03-31 15:11:49 +00:00
Vitor Pamplona
b762907d69 adds a mutex to make sure memory clearing only happens once at a time. 2025-03-31 11:09:23 -04:00
Vitor Pamplona
396831456c - Tor Cleanup:
- Only starts Tor when the "Internal" option is selected on the privacy settings
- Adds a mutex to make sure tor only starts once.
- Fixes bug when setting port before the service is running
- Moves tor start and stop to Compose actions, instead of activity
- Adds a 5 second delay before disconnecting Tor on the App's onPause
2025-03-31 11:09:04 -04:00
Vitor Pamplona
31e961c64f Fixes Video cropping due to rotated Exif metadata. 2025-03-30 10:51:32 -04:00
Vitor Pamplona
8baf9ad914 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-03-29 16:07:19 -04:00
Vitor Pamplona
c2b0154bb5 Fixes mark as seen when drafts are the last post in messages 2025-03-29 16:07:11 -04:00
Vitor Pamplona
c2b19c670b Merge pull request #1314 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-03-29 15:33:38 -04:00
Crowdin Bot
f97cfa81ca New Crowdin translations by GitHub Action 2025-03-29 19:22:34 +00:00
Vitor Pamplona
21643b781c Fixing language codes 2025-03-29 15:02:52 -04:00
Vitor Pamplona
5961db5c77 Testing the removal of generic Arabic translation to a language-country pair 2025-03-29 14:43:23 -04:00
Vitor Pamplona
99d5e9f1f7 Merge pull request #1313 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-03-29 14:38:55 -04:00
Crowdin Bot
818116d57b New Crowdin translations by GitHub Action 2025-03-29 18:36:37 +00:00
Vitor Pamplona
ef1e743fe2 removes language mapping for crowdin 2025-03-29 14:35:28 -04:00
Vitor Pamplona
df9568b667 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-03-29 12:25:54 -04:00
Vitor Pamplona
b5649e2607 Fixes: https://github.com/vitorpamplona/amethyst/issues/1309 2025-03-29 12:25:48 -04:00
Vitor Pamplona
92033b16d2 Updates Media, Camera, Compose and benchmark libs 2025-03-29 12:23:20 -04:00
Vitor Pamplona
9a440513ef Merge pull request #1312 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-03-29 11:11:05 -04:00
Crowdin Bot
89aa4a6f95 New Crowdin translations by GitHub Action 2025-03-29 15:02:23 +00:00
Vitor Pamplona
5ac73bbeba - Retries to reverse geolocate if fails due to the services long startup time.
- Adds support for the new and old ways to use reverse geolocation services.
- Hits all existing providers for location updates instead of just the network ones
- Uses past last known locations to kick start the cache.
- Improves logging to check potential failures in production.
2025-03-29 11:00:37 -04:00
Vitor Pamplona
76eee177a8 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-03-28 13:48:31 -04:00
Vitor Pamplona
4124724fb1 - Creates a new Group DM screen and moves DMs (NIP-17 and NIP-04) away from the New Post Screen.
- Separates all DM attachments as their own objects and holds them in cache until the message is sent.
- Adds previews for any number of urls, events and media uploads on new post screens.
- Adds zap split, zap raiser, geolocation symbols for DMs and channel messages
- Separates each component that can be added to a new post into its own package.
- Unifies processing for User Suggestions, Emoji Suggestions, Url Previews, location, draft versions, among text inputs
2025-03-28 13:48:22 -04:00
Vitor Pamplona
7921745fd9 Merge pull request #1311 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-03-27 17:54:50 -04:00
Crowdin Bot
c24c23f003 New Crowdin translations by GitHub Action 2025-03-27 21:41:53 +00:00
Vitor Pamplona
8a6b71e913 Fixing google services.json for benchmark app 2025-03-27 17:39:10 -04:00
Vitor Pamplona
29d046a094 Updates zoomable, vico, firebase, jackson and jna 2025-03-26 12:36:38 -04:00
Vitor Pamplona
c0423032c3 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-03-26 11:24:17 -04:00
Vitor Pamplona
fd7ff57a37 Merge pull request #1307 from davotoula/1301-use-note-renderer-for-file-header-and-video-events
Use CheckNewAndRenderNote method for FileHeaderEvent, FileStorageHeaderEvent and VideoEvent(s)
2025-03-26 11:23:41 -04:00
Vitor Pamplona
9a0a164ab5 Merge pull request #1308 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-03-26 11:22:51 -04:00
Vitor Pamplona
b35fd24a93 Fixes QR Code screen padding 2025-03-26 11:22:38 -04:00
Vitor Pamplona
aac366c690 - Migrates "Show Anyway" and "Show More" buttons to lighter version (Tonal)
- Improves tonal rendering on Light theme
- Lightens card surfaces
- Adjusts surfaceTint on Dark theme to match the elevation differences on the Light theme
2025-03-26 11:22:27 -04:00
Crowdin Bot
04a161dc47 New Crowdin translations by GitHub Action 2025-03-26 15:20:27 +00:00
David Kaspar
0d623b2ecc Use CheckNewAndRenderNote method for FileHeaderEvent, FileStorageHeaderEvent and VideoEvent(s) 2025-03-26 12:20:59 +00:00
Vitor Pamplona
aa9f1b6c4f Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-03-25 19:36:47 -04:00
Vitor Pamplona
8f77ecd891 Improves the rendering of the channel metadata changes
Redesigns the expandable top bar for NIP-28 chats
2025-03-25 19:36:39 -04:00
Vitor Pamplona
c4ab506c87 Merge pull request #1305 from davotoula/1292-url-decode-text-shared-to-app
use existing helper function that URL decodes message text
2025-03-25 18:06:42 -04:00
Vitor Pamplona
e75b451b79 Merge pull request #1306 from davotoula/remove-fdroid-from-readme
Update README.md
2025-03-25 18:05:44 -04:00
David Kaspar
7ad47bb137 Update README.md
remove fdroid from readme
2025-03-25 21:55:12 +00:00
David Kaspar
5518293813 use existing helper function that URL decodes message text 2025-03-25 20:38:08 +00:00
Vitor Pamplona
a23ad2dde7 Moves relay screens to it's own master package on the UI and reorganizes subpackages 2025-03-25 15:17:59 -04:00
Vitor Pamplona
b74bf44141 - Migrates NIP-28 creation to its own route.
- Adds picture upload for NIP-28 metadata
- Adds support for relay hints on NIP-28
- Improves edit field for chats
- Improves keyboard support for relay lists edit fields
2025-03-25 14:36:12 -04:00
Vitor Pamplona
84f10da006 Forces the root post in a thread to be observed at all times. That guarantees thread loading even if relays are slow and the user is scrolling. 2025-03-24 18:02:55 -04:00
Vitor Pamplona
d2c19cbbb4 Merge pull request #1300 from davotoula/sniff-content-type-from-extension-when-empty-in-response-headers
Sniff content type from extension when empty in response headers
2025-03-24 17:50:22 -04:00
Vitor Pamplona
ef582eceb6 Merge pull request #1303 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-03-24 17:49:27 -04:00
Crowdin Bot
258815d349 New Crowdin translations by GitHub Action 2025-03-24 21:36:42 +00:00
Vitor Pamplona
1b40e70058 Fixing the Notification order for multiple playbacks 2025-03-24 17:33:53 -04:00
Vitor Pamplona
43f1796058 Updates AGP 2025-03-24 17:33:17 -04:00
Vitor Pamplona
53803eb878 Merge pull request #1302 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-03-24 16:13:11 -04:00
Crowdin Bot
7b5a2d1312 New Crowdin translations by GitHub Action 2025-03-24 20:12:36 +00:00
Vitor Pamplona
8f9a4557b5 Enable Picture in Picture videos 2025-03-24 16:10:14 -04:00
David Kaspar
cdf2b10fd2 trim inline meta data to fix sniffing (required for DM messages) 2025-03-18 12:55:31 +00:00
David Kaspar
2f29a21d72 cleaner code saveContentDefault: use apply for clarity 2025-03-18 12:29:03 +00:00
David Kaspar
93ed81dedb cleaner code saveDownloadingIfNeeded: refactor to use when and remove unnecessary null-safe calls 2025-03-18 12:14:57 +00:00
David Kaspar
bcd636b46e sniff content type from extension when empty in response 2025-03-18 11:50:33 +00:00
Vitor Pamplona
6fd5f36ff5 Fix: Removes kind 30078 from search 2025-03-17 20:22:11 -04:00
Vitor Pamplona
4b79122899 Fixes the content type after image compression. 2025-03-17 20:07:25 -04:00
Vitor Pamplona
1df4d1db10 Removes debugging red border for full screen video 2025-03-17 14:30:17 -04:00
Vitor Pamplona
804194c3f5 Opens the fullscreen video playback with the right aspect ratio 2025-03-17 14:27:36 -04:00
Vitor Pamplona
fc159c4d1a Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-03-17 14:27:20 -04:00
Vitor Pamplona
754b648877 Removing unnecessary playback logs 2025-03-17 14:27:13 -04:00
Vitor Pamplona
c1606c54be Merge pull request #1299 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-03-17 14:04:48 -04:00
Crowdin Bot
82864c2069 New Crowdin translations by GitHub Action 2025-03-17 17:58:07 +00:00
Vitor Pamplona
3dc2a4a2d3 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-03-17 13:55:50 -04:00
Vitor Pamplona
7d1a8652cf Merge pull request #1298 from davotoula/1297-trim-inline-meta-data-before-saving-file
Trim meta data from file name before saving file to disk
2025-03-17 13:55:40 -04:00
Vitor Pamplona
96ac674eaa Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-03-17 13:55:18 -04:00
Vitor Pamplona
664ea86e6c Adds tor classes to the proguard exceptions 2025-03-17 13:55:12 -04:00
Vitor Pamplona
5aa2eb4499 Makes the bechmark build its own package name to facilitate testing in real phones. 2025-03-17 13:54:57 -04:00
Vitor Pamplona
0b9a44ab9b adds icon for Android studio 2025-03-17 13:53:42 -04:00
Vitor Pamplona
e3e35fa1eb - Refactoring playback service and its client.
- Created a pool of ExoPlayers to avoid creating new instances when scrolling.
- More accurately tracks MediaSessions
- Splits Caching layers into their own files
- Splits VideoView into multiple files
- Specializes the old Playback Manager into pools.
- Reorganizes video playback dependencies inside a single package.
- Structures callback uris to be per media item as opposed to per controller.
2025-03-17 13:53:26 -04:00
David Kaspar
221c58126c moved the trimming of inline meta-data to where File is created 2025-03-16 21:36:13 +00:00
David Kaspar
2cdf5d6673 trim meta data from file name before saving file to disk 2025-03-16 21:05:09 +00:00
Vitor Pamplona
2d5697cc9a Merge pull request #1296 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-03-15 14:25:09 -04:00
Crowdin Bot
d4ae290364 New Crowdin translations by GitHub Action 2025-03-15 16:46:06 +00:00
Vitor Pamplona
a690359541 Merge pull request #1295 from davotoula/1294-failed-to-save-the-image
Failed to save the image
2025-03-15 12:44:50 -04:00
David Kaspar
b3fa6401f6 Remove accidental import of okio.use 2025-03-15 13:58:04 +00:00
David Kaspar
b58d74138d cleaner code 2025-03-15 13:27:46 +00:00
David Kaspar
e6c413b176 Get mime type from extension if mime type in response header is null for a application/octet-stream content type 2025-03-15 13:13:46 +00:00
Vitor Pamplona
c1399d129e Migrates from old keyboard option interface 2025-03-14 14:20:08 -04:00
Vitor Pamplona
337a5e3cae Adds a flag to avoid new linting warnings 2025-03-14 14:12:12 -04:00
Vitor Pamplona
32b184a9cd Improves lightning error messages 2025-03-14 13:57:44 -04:00
Vitor Pamplona
fd538ebde1 Improves multiple error dialogs appearing when zapping from the reactions bar in the feed. 2025-03-14 13:57:33 -04:00
Vitor Pamplona
d76de0123a Forces aspect ratio of when loading an image to minimize resizing of the UI after the image is loaded. 2025-03-14 10:27:13 -04:00
Vitor Pamplona
de2b1a6c95 Optimizes caching for hidden chars on emoji 2025-03-14 10:24:03 -04:00
Vitor Pamplona
311964ce33 Caches video and image aspect ratios to recompose with the correct size 2025-03-13 19:30:57 -04:00
Vitor Pamplona
4d4c7d5b72 Moves DVM's last announcement restriction from 90 days to 365 days 2025-03-13 17:38:05 -04:00
Vitor Pamplona
66535e11ce - Removes the TAG_SIZE constant on all tags because each parser might use a different size. There is no minimum size for tags.
- Moves the tag parsing checks to use ensure.
- Explicitly writes matching methods to avoid hiding complexity beyond utility functions.
2025-03-13 17:24:20 -04:00
Vitor Pamplona
682dc62703 Updates zoomable, vico and mockk 2025-03-13 10:47:31 -04:00
Vitor Pamplona
ba7bd0bd8a Migrates to AGP 8.9 2025-03-13 09:21:50 -04:00
Vitor Pamplona
64b42ede7c Updates compose, firebase, navigation 2025-03-13 09:04:54 -04:00
Vitor Pamplona
8afe1ae537 Marks PrivateOutbox contents as encrypted 2025-03-13 09:04:39 -04:00
Vitor Pamplona
258a550e15 updating android studio 2025-03-13 09:00:44 -04:00
Vitor Pamplona
1603a7473a Adds support for Harassment reports. 2025-03-12 15:51:17 -04:00
Vitor Pamplona
ba6786cdcf Updates nip70 Protected Tags to the new structure 2025-03-12 14:51:47 -04:00
Vitor Pamplona
b017e03728 Updates NIP-56 to the newest tag structure for Quartz 2025-03-12 14:51:23 -04:00
Vitor Pamplona
5766bb1887 First idea without changing NIP-44 2025-03-12 09:41:18 -04:00
Vitor Pamplona
40bc651860 Making sure iMetas are unique 2025-03-11 14:27:58 -04:00
Vitor Pamplona
8a779e7f3c Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-03-11 14:26:29 -04:00
Vitor Pamplona
350e2a5a90 Fixes loading iMeta from drafts and reset them after use 2025-03-11 14:17:59 -04:00
Vitor Pamplona
a75e268466 Merge pull request #1291 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-03-11 14:00:21 -04:00
Crowdin Bot
2fd456e33d New Crowdin translations by GitHub Action 2025-03-11 17:58:06 +00:00
Vitor Pamplona
64f7401b46 Fixes not including iMeta tags on public chats 2025-03-11 13:57:56 -04:00
Vitor Pamplona
5dcb1350ac Losing the test case for unit tests in CI 2025-03-11 13:57:39 -04:00
Vitor Pamplona
3aa370d746 Fixes bug that the room changes after citing a user on NIP-17 2025-03-11 13:46:55 -04:00
Vitor Pamplona
583855de4f Generalizes the chat upload UI and applies it to channels 2025-03-11 13:46:36 -04:00
Vitor Pamplona
05acc19c9a Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-03-10 20:34:42 -04:00
Vitor Pamplona
71f6fe2375 Merge pull request #1290 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-03-10 20:33:58 -04:00
Vitor Pamplona
286730c50d Adds name to the rendering of people lists in the feed 2025-03-10 20:33:42 -04:00
Crowdin Bot
57d6145677 New Crowdin translations by GitHub Action 2025-03-11 00:06:10 +00:00
Vitor Pamplona
94c78c6327 Minor refactoring of chat screen components. 2025-03-10 20:04:18 -04:00
Vitor Pamplona
7d2b7789d3 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-03-10 19:33:19 -04:00
Vitor Pamplona
fe55ee1818 Starts the migration of public chats to the new structure
Starts the migration of drafts to the new structure
2025-03-10 19:33:12 -04:00
Vitor Pamplona
58b6be73ee as per https://github.com/nostr-protocol/nips/pull/1836 2025-03-10 18:32:43 -04:00
David Kaspar
cd646951cf Merge pull request #1289 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-03-07 20:42:39 +00:00
Crowdin Bot
3789ba6c07 New Crowdin translations by GitHub Action 2025-03-07 20:13:11 +00:00
Vitor Pamplona
429f9f81c4 re organizing the private dm composables 2025-03-07 15:11:17 -05:00
Vitor Pamplona
639e2bb645 Updates our base textfield and moves to it's a more general package 2025-03-07 10:52:28 -05:00
David Kaspar
797bea9e72 Merge pull request #1285 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-03-06 21:40:09 +00:00
Crowdin Bot
1c28aa30f0 New Crowdin translations by GitHub Action 2025-03-06 21:28:31 +00:00
Vitor Pamplona
52e67c9ab6 Uses NIP-22 to reply to Highlights 2025-03-06 16:25:57 -05:00
Vitor Pamplona
fa9ff0c52a Uses NIP-22 to reply to Long form posts. 2025-03-06 16:25:47 -05:00
Vitor Pamplona
9cd73c2663 Adding secret emojis to reactions 2025-03-05 18:24:03 -05:00
Vitor Pamplona
8722f37fa5 Improving the UI of the Custom Emoji page. 2025-03-05 16:56:34 -05:00
Vitor Pamplona
987d8fa5dc Merge branch 'main' of https://github.com/vitorpamplona/amethyst
# Conflicts:
#	quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/tags/RootSceneTag.kt
#	quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/tags/StoryOptionTag.kt
#	quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/addressables/ATag.kt
#	quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/QAddressableTag.kt
#	quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/recommendation/tags/RecommendationTag.kt
2025-03-05 16:14:50 -05:00
Vitor Pamplona
f4d06eee6d Simplifying conditionals for the ATag parser 2025-03-05 16:13:33 -05:00
Vitor Pamplona
e2459e3fbd Simplifying conditionals for the ATag parser 2025-03-05 15:58:55 -05:00
Vitor Pamplona
9adc7a7adf Fixing padding to match the line padding 2025-03-05 15:40:49 -05:00
Vitor Pamplona
d474bb0016 fixes misaligned mute card on notifications 2025-03-05 15:37:57 -05:00
Vitor Pamplona
3942847d16 Refactors chats into public, private and list views for tablets and phones 2025-03-05 15:30:02 -05:00
Vitor Pamplona
2b2b219536 no message 2025-03-05 15:29:16 -05:00
Vitor Pamplona
91c19dc2a1 Adds a wait and display function to make sure the image url doesn't appear while the image is loading from disk 2025-03-05 15:26:52 -05:00
Vitor Pamplona
0536c141b7 Speeding up the loading of emojis 2025-03-05 15:23:37 -05:00
Vitor Pamplona
16331d268d Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-03-05 13:40:59 -05:00
Vitor Pamplona
7e2724ea31 adds support for secret emojis 2025-03-05 13:40:51 -05:00
Vitor Pamplona
8facd02e33 Merge pull request #1284 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-03-04 18:02:13 -05:00
Crowdin Bot
90872b2160 New Crowdin translations by GitHub Action 2025-03-04 23:00:16 +00:00
Vitor Pamplona
0580aef4a2 - Migrates NIP-17 DM new message model to its own model and disable some of the generic behavior from new posts.
- Fixes a bug on edits showing a previous edit.
- Refactors user suggestions and lastword procedures
- Adds a DM inline reply from other parts of the app, like on notification.
- Hides Retweet button from DMs on Notifications
- Fixes colors for drafts in chats.
- Adds a nav function that computes the destination only after the user clicks on it and on a coroutine.
2025-03-04 17:57:47 -05:00
Vitor Pamplona
1a001e7bb3 Moves GeohashPrecision class to Quartz 2025-03-01 18:24:55 -05:00
Vitor Pamplona
4b91cfe809 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-02-28 15:26:58 -05:00
Vitor Pamplona
3d5d7b4987 adds nostr elites as a default global relay 2025-02-27 19:15:55 -05:00
Vitor Pamplona
ca0b6ef2ba Fixing error message on relay notices 2025-02-27 19:15:40 -05:00
Vitor Pamplona
3103b51cf4 Merge pull request #1281 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-02-27 18:45:33 -05:00
Crowdin Bot
8bbc017f91 New Crowdin translations by GitHub Action 2025-02-27 23:37:03 +00:00
Vitor Pamplona
0df07ddfcb - Adds support for https://github.com/nostr-protocol/nips/pull/1770
- Improves signer utils for testing
- Improves test cases for User metadata
2025-02-27 18:34:10 -05:00
Vitor Pamplona
8f0879b8e5 Updates agp, activity compose, accompanist, navigation and zoomable 2025-02-26 15:55:39 -05:00
Vitor Pamplona
f5ac8faa45 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-02-25 19:27:20 -05:00
Vitor Pamplona
40aa469866 Fixes unable to click in the last tab of the profile 2025-02-25 18:26:01 -05:00
Vitor Pamplona
d2590b969b Merge pull request #1280 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-02-25 18:20:05 -05:00
Crowdin Bot
2de3ba82cc New Crowdin translations by GitHub Action 2025-02-25 23:18:41 +00:00
Vitor Pamplona
b3dec691d7 losing up the probability to make tests pass 2025-02-25 18:16:20 -05:00
Vitor Pamplona
b40b37b6ac Adds the logged in user' posts to a user in the user's profile.
Refactors the user profile screen in many packages.
2025-02-25 18:09:04 -05:00
Vitor Pamplona
e6cd3a99c5 Fixes bug on saving Encrypted files on DMs.
Fixes bug when using partial downloads to display videos on DMs.
2025-02-25 16:43:15 -05:00
Vitor Pamplona
d5d289a834 Uses note.toEventUri to make sure the relay hint is correct
Avoids crash when adding an event to gallery without a relay hint.
2025-02-24 20:46:33 -05:00
Vitor Pamplona
a2d9f31a8a Assigning hints to NIPs until NIP-53
Speeding up Bech32 and Hex processing
Updating Boosts and Reposts to the new way of declaring tags
Renaming the SHA256 hash tag from NIP94 to not confuse with # hashtags
2025-02-24 17:09:08 -05:00
Vitor Pamplona
3790325a0f uses const val for faster MurMur 2025-02-22 16:19:01 -05:00
Vitor Pamplona
96f57b2c90 Fixes tag name on ImageTag 2025-02-22 16:18:46 -05:00
Vitor Pamplona
4b10dd58df It's slightly faster to reject params in one line than on many. 2025-02-22 16:17:10 -05:00
Vitor Pamplona
dc4240a8f5 Increasing the amount of addresses 2025-02-20 18:06:17 -05:00
Vitor Pamplona
3220d793b4 Using a linked set for the relayDB is faster to loop through on mightContain 2025-02-20 17:44:36 -05:00
Vitor Pamplona
84a52a1ce0 Speeding MurMur up
Adding more test cases
Mapping out memory used by filter
2025-02-20 17:10:24 -05:00
Vitor Pamplona
aaf86bf53e Adds a Bloom-based hint indexer with MurMur hash 2025-02-20 14:07:10 -05:00
Vitor Pamplona
94e0f4ed02 Performance improvements on the PoW miner 2025-02-18 20:44:24 -05:00
Vitor Pamplona
af29133272 Simplifies the benchmark for PoW 2025-02-18 19:00:05 -05:00
Vitor Pamplona
06240b1f15 Updates libsecp256k 2025-02-18 18:14:52 -05:00
Vitor Pamplona
d47ec06b19 Deleting the experimental serializer test 2025-02-18 17:51:34 -05:00
Vitor Pamplona
9689acb5f3 Deletes experimental serializer on NIP-01
Moves classes to the appropriate packages on NIP-01
Adds a PoW miner to quartz.
Adds a PoW commit evaluator as a bytearray of the ID
2025-02-18 17:47:34 -05:00
Vitor Pamplona
bcb3838e85 Fixes isTagged for events 2025-02-18 12:04:39 -05:00
Vitor Pamplona
4fcf962c71 Fixes r-tag migration 2025-02-18 12:00:22 -05:00
Vitor Pamplona
2de4bb1adc Reverses ATag Generalization (It just made things more complicated) 2025-02-18 11:51:16 -05:00
Vitor Pamplona
9e1a2bb1e4 Removes the notion of generic Address references 2025-02-18 11:29:52 -05:00
Vitor Pamplona
8720b00d4f Separates the random benchmark from the Sign/Verify benchmarks 2025-02-18 10:19:51 -05:00
Vitor Pamplona
9c35008fc4 Moves Sha256 to a pool of digests to double the hashing performance 2025-02-18 09:40:17 -05:00
Vitor Pamplona
fad08830a1 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-02-17 19:13:14 -05:00
Vitor Pamplona
6d9964a1cb Decoupling NIP01 methods from CryptoUtils
Decoupling Encryption and Decryptions from CryptoUtils
Decoupling live instances of JNI bindings for Secp and LibSodium from CryptoUtils
Decoupling key cache from CryptoUtils
Reorganizes NIP-04 to match new package structure
Adjusts test structures to match
2025-02-17 19:13:05 -05:00
Vitor Pamplona
70ced84dc3 Merge pull request #1278 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-02-17 18:59:34 -05:00
Crowdin Bot
50da982b36 New Crowdin translations by GitHub Action 2025-02-17 19:14:58 +00:00
Vitor Pamplona
7ad8b2ce46 Migrates LocalCache from being based on ATags to Addresses, removing the need to use memory space to store relay hints 2025-02-17 14:12:54 -05:00
Vitor Pamplona
94ffe783e9 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-02-17 11:18:47 -05:00
Vitor Pamplona
41e47fa71d Fixes running new events on the main thread. 2025-02-17 11:17:38 -05:00
Vitor Pamplona
08dd634eae Fixes crash when evaluating the isHex function for an emoji 2025-02-17 11:12:47 -05:00
David Kaspar
cb3aa6c329 Merge pull request #1277 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-02-16 19:42:57 +01:00
Crowdin Bot
4e2e24c7ab New Crowdin translations by GitHub Action 2025-02-16 16:55:21 +00:00
Vitor Pamplona
67106e8a11 Renames PoW processor to parser 2025-02-16 11:53:23 -05:00
Vitor Pamplona
06c7ea0123 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-02-14 16:31:33 -05:00
Vitor Pamplona
8022ac525f Makes sure deletions happen in the background thread. 2025-02-14 16:29:10 -05:00
Vitor Pamplona
534f1ed8cd Adds Tim Bourma's test case 2025-02-14 16:28:56 -05:00
Vitor Pamplona
793b3fcd16 Renames PoW Parser to open space for the PoW creator 2025-02-14 16:28:40 -05:00
Vitor Pamplona
a4f84227b6 Merge pull request #1276 from MoonDusk1996/main
fix wrong word
2025-02-14 14:48:26 -05:00
Dusk
e921f26d5f fix wrong word 2025-02-14 13:34:59 -04:00
David Kaspar
0c3a792a84 Merge pull request #1275 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-02-14 17:15:44 +01:00
Crowdin Bot
6481fcbecd New Crowdin translations by GitHub Action 2025-02-14 16:07:00 +00:00
Vitor Pamplona
0f6c3b9a3a Moves to vico chart 2.0 2025-02-14 11:05:00 -05:00
Vitor Pamplona
dcb0e31cd6 Updating activity compose, coil, combosebom, firebasebom, fragmentktx, kotlinserialization, mockk and navigation compose 2025-02-13 19:02:15 -05:00
Vitor Pamplona
09cff7c930 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-02-13 19:01:37 -05:00
Vitor Pamplona
cb121835f5 Stops using vico's forEach custom function (it's going to be deleted in the next version) 2025-02-13 19:01:30 -05:00
Vitor Pamplona
0610416f61 Updates AGP to 8.8.1 2025-02-13 17:59:23 -05:00
Vitor Pamplona
f0116ad06e Merge pull request #1274 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-02-13 17:55:17 -05:00
Crowdin Bot
89664a2813 New Crowdin translations by GitHub Action 2025-02-13 22:49:05 +00:00
Vitor Pamplona
9f465d3296 Merge branch 'main' of https://github.com/vitorpamplona/amethyst
# Conflicts:
#	amethyst/src/main/res/values-uz-rUZ/strings.xml
2025-02-13 17:40:00 -05:00
Vitor Pamplona
9c21a8a7da Massive refactoring of Quartz to:
- Define each tag in their own class.
- Allow extension functions to additional responsibilities to other classes
- Migrate from hardcoded tag filters in events to the Tag's parser and assemble functions.
- Migrate hardcoded event.create to builders that use extension functions
- Restructures threading infrastructure for NIP-10
- Decouple the event signing from the Event building functions via event templates
- Create classes to represent Tags and TagArrays and use extension functions to add domain-related methods to the tag array of each nip.
- Uses external functions on event template builders to better point to which functions and which tags can be used in which event kinds.
- Separates Event kinds in packages inside each nip.
- Improves support for NIP-89
- Correctly establishes which imeta params can be used in each nip (video, picture, files)
- Decouples the iMeta builder from any nip.
- Fixes mute list word and user removal when inserted from a different client.
- Migrates the Account class to avoiding having to build each Event inside of it
2025-02-13 17:39:13 -05:00
Vitor Pamplona
0f3b3c4b2d Adds support for NIP-73 2025-02-13 17:19:09 -05:00
Vitor Pamplona
68d4686424 Adds NostrMedia as a paid blossom relay option 2025-02-13 17:10:51 -05:00
Vitor Pamplona
e2a812a416 Merge pull request #1272 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-02-10 08:48:44 -05:00
Crowdin Bot
2eece49b9b New Crowdin translations by GitHub Action 2025-02-10 13:43:23 +00:00
Vitor Pamplona
c34c107a7c Merge pull request #1270 from believethehype/gallery_options
add option for 2 profile gallery views
2025-02-10 08:41:37 -05:00
dbth
e9861d80f6 add option for 2 profile gallery views 2025-02-01 21:48:26 +01:00
Vitor Pamplona
7b84c81d9c Merge pull request #1267 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-01-30 14:49:30 -05:00
Crowdin Bot
9caf0d28f5 New Crowdin translations by GitHub Action 2025-01-30 19:48:11 +00:00
Vitor Pamplona
78e5f5e277 Merge pull request #1265 from davotoula/1258-exlude-FileHeaderEvent-from-search-results
Exclude file header events from search results
2025-01-30 14:46:55 -05:00
David Kaspar
1bd52f163f extract logical expression for which notes to exclude from search results 2025-01-28 11:55:17 +01:00
David Kaspar
d825995ef4 Exclude FileHeaderEvent from note search results (direct note id search and free text) 2025-01-28 11:39:46 +01:00
Vitor Pamplona
3e1e3e80fb Merge pull request #1264 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-01-25 08:55:44 -05:00
Crowdin Bot
951a3a73d0 New Crowdin translations by GitHub Action 2025-01-25 13:54:41 +00:00
Vitor Pamplona
8a9fdd2c34 Merge pull request #1263 from davotoula/ugrade-gradle-and-agp
upgrade gradle to 8.10.2
2025-01-25 08:53:29 -05:00
David Kaspar
5dbba6d06d upgrade gradle to 8.10.2
upgrade agp to 8.8.0
2025-01-25 09:18:57 +00:00
Vitor Pamplona
5ee754c71a Allows the choice of limits on Count 2025-01-15 13:16:44 -05:00
Vitor Pamplona
a739329ab8 Merge pull request #1257 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-01-15 11:54:44 -05:00
Crowdin Bot
c12febf980 New Crowdin translations by GitHub Action 2025-01-15 16:49:57 +00:00
Vitor Pamplona
c25d64558e - Normalizes the use of ETag
- Creates a BaseReplaceable event to avoid duplicates of empty d tags.
2025-01-15 11:48:01 -05:00
Vitor Pamplona
5a3c821da4 make sure the pow functions are static in java 2025-01-15 10:11:17 -05:00
Vitor Pamplona
b90aac496e Moves PoW tag to the new style of tag builders. 2025-01-15 10:10:10 -05:00
Vitor Pamplona
4b52cdb101 Updates NIP-14 subjects to the new style of extension functions 2025-01-15 10:09:52 -05:00
Vitor Pamplona
4a4f03c12b Refactor proxyTag function names 2025-01-15 09:56:15 -05:00
Vitor Pamplona
1f9aeddb57 Adds support for NIP-48 to Quartz 2025-01-15 09:17:32 -05:00
Vitor Pamplona
f3b049382e Renames Gossip to Rumor to match names on the NIP-59 2025-01-15 08:58:08 -05:00
Vitor Pamplona
d1c64a0d15 Removing additional dependencies in the base Event class 2025-01-15 08:53:13 -05:00
Vitor Pamplona
8e25271bd6 Improves the documentation of the TagArray functions 2025-01-15 08:39:41 -05:00
Vitor Pamplona
0029df4575 Merge pull request #1256 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-01-14 19:44:32 -05:00
Crowdin Bot
b0e029cd59 New Crowdin translations by GitHub Action 2025-01-15 00:37:17 +00:00
Vitor Pamplona
d19ae56afa - Migrates Zap splits, zapraisers, subject, alts and content warning to their own packages.
- Adds protected event tags
2025-01-14 19:35:16 -05:00
Vitor Pamplona
502d39c893 Generalizes the hashtag and index tag parser for the content as well as the way to pass params to build them on create. 2025-01-14 16:59:53 -05:00
Vitor Pamplona
4f774ae3c5 Simple refactoring to avoid empty challenges. 2025-01-14 16:58:16 -05:00
Vitor Pamplona
86a9fb2af5 Moves the relay structure to quartz 2025-01-14 12:09:25 -05:00
Vitor Pamplona
e36e49cc88 Breakes the Command and Message parsers out of the Relay class 2025-01-14 11:47:52 -05:00
Vitor Pamplona
3ac303c724 Starts the work to filter events that return from the relay to make sure they match the subscription submitted 2025-01-13 19:42:43 -05:00
Vitor Pamplona
e3e90229ce Separates Typed Relay class from a SimpleRelay class to prepare to move to Quartz 2025-01-13 19:15:20 -05:00
Vitor Pamplona
9b0f24ba94 Removing duplicated permission for the camera 2025-01-13 13:03:40 -05:00
Vitor Pamplona
7f6b0ef7c2 Fixes package names for filters that moved to quartz 2025-01-13 13:03:22 -05:00
Vitor Pamplona
5c805d7551 Fixes greek name for Backup keys 2025-01-13 12:46:23 -05:00
Vitor Pamplona
57fe3740fc Moves limits and Filters to quartz 2025-01-13 12:46:15 -05:00
Vitor Pamplona
b871954293 Moves NIP96 parsing test to Quartz 2025-01-13 12:23:57 -05:00
Vitor Pamplona
d66e8d4cde refactoring android tests to match refactoring of package names
moving some nip96 stuff to quartz
2025-01-13 12:20:02 -05:00
Vitor Pamplona
103210ade4 Moves pow test to pow package 2025-01-13 10:44:15 -05:00
Vitor Pamplona
0d4936cf4b Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2025-01-13 10:38:53 -05:00
Vitor Pamplona
d2b731e372 Massive refactoring of quartz to prepare for nip-based packages. 2025-01-13 10:38:45 -05:00
Vitor Pamplona
ceba31ec61 Merge pull request #1255 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-01-13 09:51:50 -05:00
Crowdin Bot
9684940265 New Crowdin translations by GitHub Action 2025-01-13 14:49:44 +00:00
Vitor Pamplona
dd7387a3f5 Merge pull request #1254 from greenart7c3/main
Move profile edit dialog to a screen
2025-01-13 09:48:13 -05:00
greenart7c3
020ead3c3f Move profile edit dialog to a screen 2025-01-08 10:47:32 -03:00
Vitor Pamplona
1430ba4745 Moves Event ID hashing to a new class 2025-01-06 15:13:14 -05:00
Vitor Pamplona
5f577df819 Refactors SHA-256 methods to its own class 2025-01-06 12:56:57 -05:00
Vitor Pamplona
0971b716e1 Refactors secure random to extension class 2025-01-06 12:56:29 -05:00
Vitor Pamplona
53458ab484 Avoids showing youtube videos on the feed since we can't play them 2025-01-06 12:54:08 -05:00
Vitor Pamplona
879f70fcbb Merge pull request #1252 from greenart7c3/main
Add some missing functions to NostrClient
2025-01-05 14:23:40 -05:00
greenart7c3
eb93664968 Add getRelay 2025-01-05 14:43:44 -03:00
Vitor Pamplona
9816577f00 v0.94.3 2025-01-05 12:16:06 -05:00
Vitor Pamplona
306ce9a36c Adds iMeta tags to GIF urls 2025-01-05 12:14:28 -05:00
greenart7c3
10459b0a7a Add getAll 2025-01-05 13:58:48 -03:00
Vitor Pamplona
f1d61daa04 Merge pull request #1250 from geovnn/main
Keep note state across LazyColumns recompositions
2025-01-05 11:23:43 -05:00
Vitor Pamplona
1ca0abf30d Minor refactoring: uploaders can do image and videos. 2025-01-05 11:22:40 -05:00
Vitor Pamplona
d0a9c1ccd0 Fixes: Only close the upload screen if the video upload is a success on the Media tab 2025-01-05 11:22:15 -05:00
Vitor Pamplona
617f1ba2a6 Fixes the extra empty kind 20 post when uploading videos. 2025-01-05 11:21:32 -05:00
Giovanni Gatti
f1141e698e Use rememberSaveable to keep note state across LazyColumns recompositions 2025-01-05 00:52:53 +01:00
Vitor Pamplona
f94feebbd7 v0.94.2 2025-01-04 17:47:13 -05:00
Vitor Pamplona
82d006f65e letter change to avoid mixing with other log messages 2025-01-04 17:44:43 -05:00
Vitor Pamplona
3a553fa550 Updates JNA and URI Normalizer 2025-01-04 17:41:47 -05:00
Vitor Pamplona
1e9c3a47a4 Merge pull request #1249 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-01-04 17:40:46 -05:00
Crowdin Bot
3d9b4431ad New Crowdin translations by GitHub Action 2025-01-04 22:37:25 +00:00
Vitor Pamplona
6522d74253 Fixes the Tor leaks for relays and some image content. 2025-01-04 17:35:34 -05:00
Vitor Pamplona
8a8ae4fb8b Merge pull request #1248 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-01-03 20:39:08 -05:00
Crowdin Bot
6cac5fa5e4 New Crowdin translations by GitHub Action 2025-01-04 01:38:36 +00:00
Vitor Pamplona
aa3063acae v0.94.1 2025-01-03 20:36:26 -05:00
Vitor Pamplona
46de90ea65 Removing the unecessary loading of the emoji suggestions when creating the new post view model 2025-01-03 20:36:18 -05:00
Vitor Pamplona
aa44560714 Adds support for Custom Reaction selection on new posts and direct GIF url usage. 2025-01-03 20:29:31 -05:00
Vitor Pamplona
c9a6b63f67 v0.94.0 2025-01-03 11:02:15 -05:00
David Kaspar
47211e9136 Merge pull request #1247 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-01-03 15:29:44 +00:00
Crowdin Bot
cfbcc49940 New Crowdin translations by GitHub Action 2025-01-03 15:28:37 +00:00
Vitor Pamplona
b4a497fd11 Merge pull request #1246 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-01-03 10:27:22 -05:00
Crowdin Bot
9aa287f96a New Crowdin translations by GitHub Action 2025-01-03 15:16:06 +00:00
David Kaspar
a6880f339c Merge pull request #1245 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-01-03 15:14:36 +00:00
Crowdin Bot
43996499ba New Crowdin translations by GitHub Action 2025-01-03 15:13:40 +00:00
Vitor Pamplona
5c0c1acc4a Allowing multiple images on a single event to be displayed in the Profile gallery 2025-01-03 10:11:10 -05:00
Vitor Pamplona
4bfacbc11e Improves the spacing in the layout of the gallery 2025-01-02 19:42:17 -05:00
Vitor Pamplona
633c9e8dcf Merge pull request #1244 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-01-02 19:04:53 -05:00
Crowdin Bot
0f2a4d104c New Crowdin translations by GitHub Action 2025-01-02 23:55:24 +00:00
Vitor Pamplona
fb92d2da2f Merge pull request #1243 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-01-02 18:54:30 -05:00
Vitor Pamplona
d29e90fe8f Adjusts the top bar when uploading media to DMs to match the chat top bar 2025-01-02 18:53:44 -05:00
Crowdin Bot
27329b7a0f New Crowdin translations by GitHub Action 2025-01-02 23:11:04 +00:00
Vitor Pamplona
577ef6437f removes logs 2025-01-02 18:09:27 -05:00
Vitor Pamplona
dbe593db98 Adds a server and compression selection screen when uploading images on DMs 2025-01-02 18:06:41 -05:00
Vitor Pamplona
ff9509b649 Refactors user suggestion views 2025-01-02 17:58:06 -05:00
Vitor Pamplona
2772bdff8b Increases the number of active playbacks on the screen 2025-01-02 10:52:17 -05:00
Vitor Pamplona
c6869eaff6 Merge pull request #1242 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2025-01-02 09:04:49 -05:00
Crowdin Bot
663f5f282e New Crowdin translations by GitHub Action 2025-01-02 13:57:39 +00:00
Vitor Pamplona
9f147f03c7 Fixes https://github.com/vitorpamplona/amethyst/issues/1241 2025-01-02 08:55:42 -05:00
Vitor Pamplona
0ceccb23c6 Avoids cutting off some of the payables in the Pay intent screen 2024-12-31 16:21:35 -05:00
Vitor Pamplona
ee65169896 Final touches of the new error message dashboard 2024-12-31 16:21:14 -05:00
Vitor Pamplona
6ac930c241 Don't show the "message the user" button when the problem is local 2024-12-31 16:20:53 -05:00
Vitor Pamplona
a09b8c5862 Moves to using cancellable coroutines to avoid cancelling the parent group all together. 2024-12-31 16:20:10 -05:00
Vitor Pamplona
160d4722c0 Refactoring Zap Error message screen to allow sending messages directly to each receiver with an error 2024-12-31 15:51:31 -05:00
Vitor Pamplona
497ae937fd Fixes the navigation padding on Samsung devices for the Shorts tab. 2024-12-30 20:32:53 -05:00
Vitor Pamplona
b366aee1a9 Makes sure to keep the chat's input on top of the system nav 2024-12-30 20:13:38 -05:00
Vitor Pamplona
09539ac22a adds new rules for proguard 2024-12-30 19:57:31 -05:00
Vitor Pamplona
e1e3a0e6a0 Expands the Around me filter to 50km 2024-12-30 19:57:20 -05:00
Vitor Pamplona
54e6be8ef3 Fixes notes appearing of replies for some recipes 2024-12-30 16:03:00 -05:00
Vitor Pamplona
e8462fe67f Fully removing the swipe to delete from right to left. 2024-12-30 15:56:24 -05:00
Vitor Pamplona
626daa9967 Refactoring 2024-12-30 15:43:09 -05:00
Vitor Pamplona
266d4cb34f Solves crashing when a p-tag contains only "ffff" 2024-12-30 15:42:54 -05:00
Vitor Pamplona
fc72e20da7 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-12-30 08:51:24 -05:00
Vitor Pamplona
594abd1d7a Updates zoomable 2024-12-30 08:51:14 -05:00
Vitor Pamplona
a0d8a770b7 Merge pull request #1239 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-12-30 08:50:31 -05:00
Crowdin Bot
fc7b44b9d0 New Crowdin translations by GitHub Action 2024-12-30 13:39:56 +00:00
Vitor Pamplona
00eb4e364a Merge pull request #1238 from davotoula/display-toast-on-media-download-start
Display toast on media download start
2024-12-30 08:38:31 -05:00
David Kaspar
e88a36187d added translations 2024-12-30 14:16:30 +01:00
David Kaspar
21d80518c9 strings refactor 2024-12-30 14:07:06 +01:00
David Kaspar
7999608f28 added translatable strings 2024-12-30 14:03:28 +01:00
David Kaspar
ee20508e4b added video download started toast 2024-12-30 13:56:39 +01:00
David Kaspar
1231a1483f Corrected "added to profile gallery" toast text 2024-12-30 13:45:02 +01:00
David Kaspar
f8dd82f592 added a first toast for start of image download 2024-12-30 13:21:11 +01:00
Vitor Pamplona
ca00e6a302 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-12-28 16:43:34 -05:00
Vitor Pamplona
aeba5d1b51 delete unnecessary comment 2024-12-28 16:43:05 -05:00
Vitor Pamplona
3e014e7b0f Merge pull request #1237 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-12-28 15:32:06 -05:00
Crowdin Bot
95cda8ec08 New Crowdin translations by GitHub Action 2024-12-28 20:20:54 +00:00
Vitor Pamplona
1f3a818922 Remove crossfades and double composition on image success 2024-12-28 15:15:52 -05:00
Vitor Pamplona
7fe02fcf2c Disables delete draft from swipe from right to left. Only left to right remains available. 2024-12-27 18:25:24 -05:00
Vitor Pamplona
1c52887e3a Merge pull request #1236 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-12-27 17:02:07 -05:00
Crowdin Bot
62d95e2128 New Crowdin translations by GitHub Action 2024-12-27 21:52:27 +00:00
Vitor Pamplona
d0961d08da Fixes edge to edge issues when the keyboard is shown. 2024-12-27 16:49:43 -05:00
Vitor Pamplona
f38383d4e4 Removes debugging logs 2024-12-25 11:09:20 -05:00
Vitor Pamplona
739a073d4e Updates Vico, mockk, kotlin and adaptive acompanist 2024-12-24 18:22:53 -05:00
Vitor Pamplona
a195167a56 Fixes keyboard overriding the relay settings screen 2024-12-24 17:55:26 -05:00
Vitor Pamplona
72c089858d Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-12-24 16:05:43 -05:00
Vitor Pamplona
92fcf05557 Fixes double quotes on NIP-28 Channel messages 2024-12-24 15:53:45 -05:00
Vitor Pamplona
73d38f6257 Merge pull request #1233 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-12-24 11:31:53 -05:00
Crowdin Bot
48d8e418e8 New Crowdin translations by GitHub Action 2024-12-24 16:30:04 +00:00
Vitor Pamplona
ff427d0fde Fixes image upload testing. 2024-12-24 11:27:44 -05:00
Vitor Pamplona
6807554d1d Merge pull request #1232 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-12-23 20:40:49 -05:00
Crowdin Bot
433a15cf0a New Crowdin translations by GitHub Action 2024-12-24 01:33:04 +00:00
Vitor Pamplona
94c74a1e0c Adds support for encrypted media uploads on NIP-17 DMs 2024-12-23 20:30:22 -05:00
Vitor Pamplona
f839565152 Refactors Ammolite to remove the dependency on OkHttp to prepare for KTor and multiplatform settings.
- This also reduces the Singleton coupling between Client and RelayPool.

To migrate, create a NostrClient instance on your Application class and update your code to access that `client` instance.
2024-12-20 15:36:50 -05:00
Vitor Pamplona
d9c14a78a7 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-12-18 20:55:55 -05:00
Vitor Pamplona
a9d87883d2 Integrates with Pokey's Broadcast receiver. 2024-12-18 20:55:45 -05:00
Vitor Pamplona
66e7559ddb Merge pull request #1231 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-12-18 20:32:34 -05:00
Crowdin Bot
2cd9a7dca6 New Crowdin translations by GitHub Action 2024-12-19 01:10:26 +00:00
Vitor Pamplona
123239443d organize imports 2024-12-18 20:08:27 -05:00
Vitor Pamplona
76ce8f2974 Fixes bug that resets localhost relay settings. 2024-12-18 18:38:26 -05:00
Vitor Pamplona
e002e5c10f Merge pull request #1229 from davotoula/account-backup-qr-code
Account backup qr codes
2024-12-18 18:28:13 -05:00
Vitor Pamplona
d101397166 Merge pull request #1230 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-12-18 17:58:02 -05:00
Crowdin Bot
2fd96da7c7 New Crowdin translations by GitHub Action 2024-12-18 22:48:35 +00:00
Vitor Pamplona
06bc1922cb Fixes tests 2024-12-18 17:27:20 -05:00
David Kaspar
9f1b5a3c1a added content description to QR code icons 2024-12-18 23:23:57 +01:00
David Kaspar
4f4da12aa7 refactor QrCodeButton methods to avoid duplications 2024-12-18 23:06:37 +01:00
Vitor Pamplona
17495631f7 Simplifies a bit of the game controller icon 2024-12-18 17:01:29 -05:00
Vitor Pamplona
0041d87645 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-12-18 16:53:11 -05:00
Vitor Pamplona
579f63935a - Adds support for multiple media uploads at the same time.
- Adds support to display PictureEvents with multiple images at the same time
- Improves Uploading feedback for the NewPost screen
- 10x better performance on Blurhash generation
- Fixes cosine caching on Blurhash
- Removes troublesome dependency on blurhash encoder liberary
- Restructures contentScale for Images and Video dialogs
- Refactors Media Uploaders to improve code reuse
- Refactors iMeta usage on Quartz to move away from NIP-94
2024-12-18 16:52:50 -05:00
David Kaspar
b273e6dd4f rearrange code for easier diff 2024-12-18 22:52:01 +01:00
David Kaspar
eec8212070 added keyguard to qr code encrypted key export 2024-12-18 20:54:14 +01:00
David Kaspar
af5f136e6c added keyguard to qr code key export 2024-12-18 20:18:23 +01:00
David Kaspar
12d646e8a9 Move QR code next to button 2024-12-18 15:08:06 +01:00
David Kaspar
bd26fcfafd Clean up layout 2024-12-18 14:54:09 +01:00
David Kaspar
ca05b768df Added QR code private key export dialog 2024-12-18 14:43:23 +01:00
Vitor Pamplona
b75024e1fb Merge pull request #1227 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-12-16 10:10:44 -05:00
Crowdin Bot
816c598971 New Crowdin translations by GitHub Action 2024-12-16 15:08:47 +00:00
Vitor Pamplona
5636748cf8 Merge pull request #1223 from davotoula/add-custom-hashtag-icon-gamestr
Added Gamestr custom hashtag icon
2024-12-16 10:07:25 -05:00
Vitor Pamplona
3defc4d45b Merge pull request #1226 from greenart7c3/main
Fix download and loading icon not showing when text overflow
2024-12-16 10:06:17 -05:00
greenart7c3
ee16324673 Fix download and loading icon not showing when text overflow 2024-12-16 10:40:18 -03:00
David Kaspar
dfabd7afdd Added Gamestr custom hashtag icon 2024-12-15 21:52:30 +01:00
Vitor Pamplona
728768632c Update Compose Bom, firebase, navigation compose and android camera libs 2024-12-12 14:16:58 -05:00
Vitor Pamplona
c2243c53cf Optimizes user search to account for names that start with the typed prefix 2024-12-10 19:07:37 -05:00
Vitor Pamplona
5aed1cee2c Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-12-10 18:46:08 -05:00
Vitor Pamplona
8809593bbc - adds an account switcher to the notification click
- removes the use of nostr: for notifications
- enables a new screen to be routed when new logins happen
2024-12-10 18:45:59 -05:00
Vitor Pamplona
83e942a7be Fixes lack of notification when a new account is logged into the app and before the app restarts. 2024-12-10 18:39:45 -05:00
Vitor Pamplona
1ee6316e92 Merge pull request #1221 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-12-10 15:28:07 -05:00
Crowdin Bot
357ca9b6eb New Crowdin translations by GitHub Action 2024-12-10 20:16:01 +00:00
Vitor Pamplona
b0f5e77077 Merge pull request #1220 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-12-10 15:14:39 -05:00
Crowdin Bot
1b7b8fa268 New Crowdin translations by GitHub Action 2024-12-10 19:22:17 +00:00
Vitor Pamplona
82d8411ac6 Merge pull request #1219 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-12-10 14:21:00 -05:00
Crowdin Bot
684b78d2df New Crowdin translations by GitHub Action 2024-12-10 19:19:46 +00:00
Vitor Pamplona
8b80ac13db Fixes displaying an old result when coming back to a DVM screen 2024-12-10 14:17:50 -05:00
Vitor Pamplona
83235dab69 Removes contract of the old image picker 2024-12-10 14:17:15 -05:00
Vitor Pamplona
b01f46b2ee Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-12-09 14:59:44 -05:00
Vitor Pamplona
6a787f2774 Moves relayToAdd from the Object to a param in the relay screen 2024-12-09 14:59:35 -05:00
Vitor Pamplona
53206cc0b2 Merge pull request #1218 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-12-09 14:43:09 -05:00
Crowdin Bot
7cb6854489 New Crowdin translations by GitHub Action 2024-12-09 19:32:52 +00:00
Vitor Pamplona
95966e5874 Merge pull request #1214 from greenart7c3/main
Move relay dialog to a route
2024-12-09 14:31:24 -05:00
Vitor Pamplona
723979f185 Merge pull request #1216 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-12-07 18:10:42 -05:00
Crowdin Bot
b989bc0236 New Crowdin translations by GitHub Action 2024-12-07 23:01:56 +00:00
Vitor Pamplona
54ab8f1448 Merge pull request #1215 from davotoula/improve-accessibility-add-content-descriptions
Improve accessibility add content descriptions
2024-12-07 18:00:18 -05:00
David Kaspar
1b0ff52c61 translations 2024-12-07 21:29:34 +01:00
David Kaspar
46b70b719a re-add key to LaunchedEffect 2024-12-07 21:21:47 +01:00
David Kaspar
1972cdeafb Add content description to custom emojis 2024-12-07 21:06:21 +01:00
David Kaspar
39a7d98651 Add content description to icon in app definition 2024-12-07 16:56:24 +01:00
greenart7c3
a93910f8cb Move relay dialog to a route 2024-12-07 11:17:38 -03:00
David Kaspar
314cbe1a32 Add content description to recommended apps icons - refactored 2024-12-07 15:14:46 +01:00
David Kaspar
54d0ec806d Add content description to recommended apps icons 2024-12-07 15:12:27 +01:00
David Kaspar
6faab55a55 Add content description to pushpin icon (just in case) 2024-12-07 14:38:58 +01:00
David Kaspar
8b5366f9e2 Add description to relay list selector in NewMediaView 2024-12-07 14:11:09 +01:00
Vitor Pamplona
15b527c58d Fixes blurhash rendering 2024-12-06 18:13:40 -05:00
Vitor Pamplona
e501101062 Merge pull request #1213 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-12-06 15:57:41 -05:00
Crowdin Bot
15411edfa6 New Crowdin translations by GitHub Action 2024-12-06 20:07:57 +00:00
Vitor Pamplona
e65346d268 Move gallery previews to it's own package. Avoid reusing VideoView 2024-12-06 15:05:59 -05:00
Vitor Pamplona
01b880c4a5 Simplifies the Gallery stack 2024-12-06 13:41:03 -05:00
Vitor Pamplona
0d6760360f Fixes the bugs from migrating video events to imeta tags 2024-12-06 10:19:55 -05:00
Vitor Pamplona
4610519bb3 - Removes pull to refresh from gallery 2024-12-06 10:17:37 -05:00
Vitor Pamplona
905655461d Adds kind picture and video events to the user profile gallery subscription. 2024-12-06 10:16:54 -05:00
Vitor Pamplona
f759acf66e Merge pull request #1210 from believethehype/olas-profile-with-legacy
Extend NIP93 Profile Gallery with Nip68 Events
2024-12-06 08:22:22 -05:00
Vitor Pamplona
8979706a81 Merge pull request #1212 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-12-06 08:21:02 -05:00
Crowdin Bot
0db664fabc New Crowdin translations by GitHub Action 2024-12-06 13:19:06 +00:00
Vitor Pamplona
c33fee59a2 Delete unused constant 2024-12-05 18:03:40 -05:00
Vitor Pamplona
eb36489094 Adds basic support for RelationshipStatus to Quartz 2024-12-05 17:55:59 -05:00
Vitor Pamplona
51ce509928 Simple refactoring to newer versions of the clickable text 2024-12-05 17:55:36 -05:00
Vitor Pamplona
0dd306b7fa Separates event class that manages general lists and abstracts another intermediary class that manages private tag arrays in its content. 2024-12-05 17:55:10 -05:00
Vitor Pamplona
8a6f830e29 Removes invalid import 2024-12-05 17:26:47 -05:00
Vitor Pamplona
bcb9ba26ab Improves search by npubs to use all relays. 2024-12-05 17:14:16 -05:00
Vitor Pamplona
3aa15889c1 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-12-05 17:12:50 -05:00
Vitor Pamplona
b47d9ad4d9 - Migrates Video events to imeta tags
- Removes youtu.be links from the video feed.
- Checks for video file types in uppercase as well as lowercase
2024-12-05 16:41:43 -05:00
David Kaspar
b504a2c0d4 Merge pull request #1211 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-12-05 17:33:30 +01:00
Crowdin Bot
69c9e84dc2 New Crowdin translations by GitHub Action 2024-12-05 15:54:05 +00:00
Vitor Pamplona
81591d6f76 v0.93.1 2024-12-05 10:48:52 -05:00
Believethehype
d2187995b8 Update strings.xml 2024-12-04 18:06:33 +01:00
Believethehype
a3257a365b hybrid solution nip68 / nip93
it keeps the nip93 gallery as before, but also adds all nip68 media to the gallery
2024-12-04 17:56:06 +01:00
Vitor Pamplona
9180eeb59f Merge pull request #1209 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-12-03 16:10:21 -05:00
Crowdin Bot
b24983b232 New Crowdin translations by GitHub Action 2024-12-03 20:56:03 +00:00
Vitor Pamplona
fe3246c94e Fixes video rotation screen in full size while playing 2024-12-03 15:53:17 -05:00
Vitor Pamplona
b9883093ac Improving performance of the Hex encoder. 2024-12-03 14:07:13 -05:00
Vitor Pamplona
869debaf9d Fixes Satellite's blossom upload 2024-12-02 20:05:13 -05:00
Vitor Pamplona
6a522f5c92 updates AGP 2024-12-02 18:03:47 -05:00
Vitor Pamplona
ae13725db5 Improves the Discovery block UI 2024-12-02 17:45:44 -05:00
Vitor Pamplona
95774ddca5 Merge pull request #1207 from believethehype/main
Content DVMS: show amount and personalized status in feed
2024-12-02 16:04:39 -05:00
Believethehype
56450cf6c5 Merge branch 'main' of https://github.com/believethehype/amethyst 2024-12-02 22:02:49 +01:00
Believethehype
2da1dda019 Merge remote-tracking branch 'upstream/main' 2024-12-02 22:00:24 +01:00
dbth
fb73f6153f Merge branch 'main' into main 2024-12-02 22:00:16 +01:00
Believethehype
62807336fd DVM: show amount and personalized in feed 2024-12-02 21:56:13 +01:00
Vitor Pamplona
fddb9b16ab updates jackson and secp256k1 2024-12-02 15:32:19 -05:00
Vitor Pamplona
0dcce5a987 Fixes lack of reactions on video feeds 2024-12-02 15:31:59 -05:00
Vitor Pamplona
16cf3c850a Merge pull request #1205 from believethehype/main
DVM: adapt nip89 naming, show picture then image (legacy)
2024-12-02 14:09:23 -05:00
Vitor Pamplona
2b17e9303a Merge pull request #1206 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-12-02 14:05:51 -05:00
Crowdin Bot
61d9145310 New Crowdin translations by GitHub Action 2024-12-02 18:59:15 +00:00
Vitor Pamplona
40921d4b03 fixes badge crash 2024-12-02 13:56:38 -05:00
Believethehype
e0e898d4b1 DVM: adapt nip89 naming, show picture then image (legacy) 2024-12-02 19:55:02 +01:00
Vitor Pamplona
bd2005ec6e Fixes screen mispositioning when rotating full screen video/image dialogs. 2024-11-29 16:40:07 -05:00
Vitor Pamplona
2c825d5380 Remove unecessary log 2024-11-29 16:32:04 -05:00
Vitor Pamplona
7fe522307a Fixes the bug on not having the video feed at the top when loading the app from scratch. 2024-11-29 15:12:54 -05:00
Vitor Pamplona
9660c739f3 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-11-29 14:50:39 -05:00
Vitor Pamplona
9025741c13 deletes unecessary logs 2024-11-29 14:50:28 -05:00
Vitor Pamplona
0ef851e4bb Merge pull request #1201 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-11-29 14:41:13 -05:00
Crowdin Bot
7204d337e8 New Crowdin translations by GitHub Action 2024-11-29 19:39:34 +00:00
Vitor Pamplona
cb538bc6a3 Fixes missing reply order when the direct reply is also included as a quote. 2024-11-29 14:31:31 -05:00
Vitor Pamplona
d0b0f441b1 Fixes image testing. 2024-11-27 15:42:31 -05:00
Vitor Pamplona
ddd7f19f38 Merge pull request #1198 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-11-27 12:09:28 -05:00
Crowdin Bot
e46c8f4c15 New Crowdin translations by GitHub Action 2024-11-27 17:02:57 +00:00
Vitor Pamplona
6b390dad30 Merge pull request #1197 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-11-27 12:01:24 -05:00
Crowdin Bot
50e067fbf0 New Crowdin translations by GitHub Action 2024-11-27 16:43:19 +00:00
Vitor Pamplona
04da076d95 Adds NIP-22 as replies to Interactive Stories. 2024-11-27 11:41:13 -05:00
David Kaspar
fd88dfed7d Merge pull request #1196 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-11-27 17:04:41 +01:00
Crowdin Bot
22905bc04e New Crowdin translations by GitHub Action 2024-11-27 15:40:29 +00:00
Vitor Pamplona
c02ced7855 Merge pull request #1195 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-11-27 10:39:14 -05:00
Crowdin Bot
ea1145c890 New Crowdin translations by GitHub Action 2024-11-27 15:36:35 +00:00
Vitor Pamplona
043c8eff57 Merge pull request #1194 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-11-27 10:35:14 -05:00
Vitor Pamplona
fbb036da4a v0.93.0 2024-11-27 10:33:59 -05:00
Crowdin Bot
71d30f83ea New Crowdin translations by GitHub Action 2024-11-27 15:26:37 +00:00
Vitor Pamplona
9a0c998654 Fixes "null" strings on profile fields. 2024-11-27 10:24:09 -05:00
Vitor Pamplona
88082b1ba3 Updates media and coil 2024-11-27 09:19:17 -05:00
Vitor Pamplona
ad2b2e6d02 Merge pull request #1193 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-11-27 09:16:25 -05:00
Crowdin Bot
5044a687fa New Crowdin translations by GitHub Action 2024-11-27 14:02:42 +00:00
Vitor Pamplona
298d4bb237 removes unnecessary metadata 2024-11-27 08:59:23 -05:00
Vitor Pamplona
9c180cb87a Merge pull request #1192 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-11-26 19:10:54 -05:00
Crowdin Bot
2e3f2044d5 New Crowdin translations by GitHub Action 2024-11-27 00:09:32 +00:00
Vitor Pamplona
bdf012f641 Adds support for Interactive Stories 2024-11-26 19:07:12 -05:00
Vitor Pamplona
034ee46543 Refactors additional factories 2024-11-26 09:28:42 -05:00
Vitor Pamplona
6a17f94cb1 Merge pull request #1190 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-11-25 14:31:56 -05:00
Crowdin Bot
233059d544 New Crowdin translations by GitHub Action 2024-11-25 19:31:18 +00:00
Vitor Pamplona
7bd9b6a1ec Moves to the new Android Image/Video Picker 2024-11-25 14:24:17 -05:00
Vitor Pamplona
04e77daaab Light chat bubbles 2024-11-22 19:17:50 -05:00
Vitor Pamplona
308048c352 Adds date separators on chats 2024-11-22 18:08:30 -05:00
Vitor Pamplona
3f1173a42a Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-11-22 17:01:57 -05:00
Vitor Pamplona
39726142ae Fixes account creation that follows itself. 2024-11-22 17:01:50 -05:00
Vitor Pamplona
025cbeed07 Merge pull request #1189 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-11-22 16:33:33 -05:00
Crowdin Bot
8a1550cbd9 New Crowdin translations by GitHub Action 2024-11-22 21:20:34 +00:00
Vitor Pamplona
49148ddc76 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-11-22 16:18:01 -05:00
Vitor Pamplona
d0e870e1b8 Adds Custom Empty Feed Screen for notifications 2024-11-22 16:17:55 -05:00
Vitor Pamplona
dbb2bfa512 Merge pull request #1188 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-11-22 12:26:35 -05:00
Crowdin Bot
d6b66c65fa New Crowdin translations by GitHub Action 2024-11-22 16:36:21 +00:00
Vitor Pamplona
9a3d365243 Fixes: https://github.com/vitorpamplona/amethyst/issues/1186 2024-11-22 11:33:51 -05:00
Vitor Pamplona
3b30d5493d Merge pull request #1184 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-11-21 18:58:17 -05:00
Crowdin Bot
7bfd1a9107 New Crowdin translations by GitHub Action 2024-11-21 23:53:47 +00:00
Vitor Pamplona
2c9e2de524 Adds support for Blossom media servers. 2024-11-21 18:51:43 -05:00
Vitor Pamplona
c89c5eb4b0 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-11-21 15:46:16 -05:00
Vitor Pamplona
5c5eb53395 Fixes translations of http urls 2024-11-21 15:46:07 -05:00
Vitor Pamplona
55f0092e03 Merge pull request #1185 from davotoula/enable-unfollow-in-note-dropdown
Enable unfollow in note dropdown
2024-11-21 15:32:44 -05:00
Vitor Pamplona
54d9ac5730 no need for identifier anymore 2024-11-21 15:15:03 -05:00
David Kaspar
d9a9137d89 cleaner code 2024-11-21 21:02:31 +01:00
David Kaspar
7beff8c835 Add unfollow to NoteDropDownMenu 2024-11-21 20:58:40 +01:00
Vitor Pamplona
4a80a16473 Adds support for pronouns when the user makes them available. 2024-11-21 11:19:13 -05:00
Vitor Pamplona
b3e3b70dd0 Marks which events can receive Comment replies as root scopes. 2024-11-19 18:01:56 -05:00
Vitor Pamplona
03662b9d1b Migrates Video feed new posts from NIP-94 to Video and Picture events. 2024-11-19 17:54:51 -05:00
Vitor Pamplona
d33421fce4 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-11-19 15:37:11 -05:00
Vitor Pamplona
4db6f5531c Adds support for Instagram feeds. https://github.com/nostr-protocol/nips/pull/1551 2024-11-19 15:36:30 -05:00
Vitor Pamplona
72ea4a44a2 Merge pull request #1183 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-11-19 09:31:20 -05:00
Crowdin Bot
022a9f6f6c New Crowdin translations by GitHub Action 2024-11-19 14:25:24 +00:00
Vitor Pamplona
248848799c Fully Deprecates note1, removing the last usages of the standard 2024-11-19 09:22:37 -05:00
Vitor Pamplona
72f317717b Remove the unused encryption field from NIP-94 2024-11-18 17:29:59 -05:00
Vitor Pamplona
4651074774 Fixes bug on searching for geohashes on addresses 2024-11-18 16:48:21 -05:00
Vitor Pamplona
fb058f93b6 Makes NIP-22 posts only visible to the main feed if inside the scope they were placed. 2024-11-18 16:47:47 -05:00
Vitor Pamplona
9e34e9d720 Fixes issue with the order of same-author events in a thread 2024-11-18 16:00:48 -05:00
Vitor Pamplona
04d6da28af Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-11-18 15:39:19 -05:00
Vitor Pamplona
192a43dc21 Updates compose, coil, firebase and navigation 2024-11-18 15:39:12 -05:00
Vitor Pamplona
61510ae7e3 Adds support for NIP-22 exclusive geo posts 2024-11-18 15:38:57 -05:00
Vitor Pamplona
488286ce20 Merge pull request #1181 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-11-18 08:25:31 -05:00
Crowdin Bot
fab6c65e98 New Crowdin translations by GitHub Action 2024-11-18 13:22:15 +00:00
Vitor Pamplona
accde8622c Merge pull request #1179 from davotoula/1172-hide-drafts-from-other-accounts-on-device
Hide drafts from other accounts on device
2024-11-18 08:20:55 -05:00
David Kaspar
4a590d67a6 move filtering of "not your drafts" to ThreadFeedFilter 2024-11-17 10:48:03 +01:00
David Kaspar
6c3200a9cc cleaner code, change cascading ifs to when 2024-11-16 10:34:01 +01:00
David Kaspar
f16143bec3 cleaner code, fewer warnings 2024-11-16 09:29:45 +01:00
David Kaspar
8216476916 cleaner code, fewer warnings 2024-11-16 08:48:30 +01:00
David Kaspar
ffd43e448b filter out drafts that are not same author as current account 2024-11-15 12:54:59 +01:00
Vitor Pamplona
3a566dad6b Improves (Show More) presence to only when it actually makes a difference. 2024-11-12 13:36:59 -05:00
Vitor Pamplona
bf861d6bc5 - Improves thread preloading
- Fixes jumping of scroll when the thread updates
2024-11-12 12:54:41 -05:00
Vitor Pamplona
b31ace79c3 App hangs when switching to an account that was logged into with the npub just because it waits to decrypt the hidden user list. 2024-11-11 18:29:38 -05:00
Vitor Pamplona
37a92c25f0 - Unifies Location Flows and GeoHash Flows into one
- Make them react to changing location permissions
- Adds UI for when the location permission is rejected.
2024-11-11 17:51:42 -05:00
Vitor Pamplona
062e4af118 Updates JNA, Coil, Jackson, and Kotlin Collections 2024-11-11 14:54:38 -05:00
Vitor Pamplona
c083295f6a Fixes error message for the signup page when the display name is blank 2024-11-11 14:53:39 -05:00
Vitor Pamplona
924baf0de3 Merge pull request #1177 from greenart7c3/main
Fix initial decryption of mute lists when using amber
2024-11-11 09:48:46 -05:00
greenart7c3
6015c968f5 Fix initial decryption of mutelists when using amber 2024-11-11 11:33:14 -03:00
Vitor Pamplona
3e85991f19 Merge pull request #1176 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-11-11 09:04:33 -05:00
Crowdin Bot
893b23e4fb New Crowdin translations by GitHub Action 2024-11-11 13:54:10 +00:00
Vitor Pamplona
cb5d69e358 Merge pull request #1171 from davotoula/crashfix-test-for-empty-string-in-mentions
Crashfix: test for empty string in mentions
2024-11-11 08:52:39 -05:00
Vitor Pamplona
43688c4117 Merge pull request #1174 from davotoula/1173-add-nip05-to-hidden-words-filtering
Added nip05 field from user profile to be used as part of hidden words filtering
2024-11-11 08:52:28 -05:00
David Kaspar
4e4521ecef Added nip05 field from user profile to be used as part of hidden words filtering 2024-11-10 06:51:34 +00:00
David Kaspar
7bc9205758 Added a test around NewPostViewModel.load with no mentions, valid mentions and invalid empty mentions 2024-11-08 19:15:04 +00:00
David Kaspar
abf6cc00ae test for empty string in mentions 2024-11-07 09:24:30 +00:00
Vitor Pamplona
7146838f63 Better names for github jobs 2024-11-04 11:56:25 -05:00
Vitor Pamplona
1037ab33e3 fixes names of uploaded files 2024-11-04 11:31:04 -05:00
Vitor Pamplona
230fd553ae fixes paths on github actions 2024-11-04 11:12:40 -05:00
Vitor Pamplona
eac078c42d updates build github action to test and upload the right assets 2024-11-04 10:54:14 -05:00
Vitor Pamplona
39c9b75bf4 Moves zapstore to local image and first in the list 2024-11-04 10:15:31 -05:00
Vitor Pamplona
e076a2dbe3 Merge pull request #1167 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-11-04 10:12:31 -05:00
Crowdin Bot
5705a26836 New Crowdin translations by GitHub Action 2024-11-04 15:12:18 +00:00
Vitor Pamplona
740c279825 Merge pull request #1165 from davotoula/1164-launch-in-scope-to-persist-translation-prefs
Crash fix: Launch in Dispatchers.IO when changing translations prefs in account
2024-11-04 10:10:48 -05:00
Vitor Pamplona
718605e44b Merge pull request #1163 from ilcompratoreconsapevole/banner
Added ZapStore's SVG banner that says "Get it on" linking to its repo
2024-11-04 10:09:49 -05:00
Vitor Pamplona
8df2ff839c Merge pull request #1162 from davotoula/bugfix-images-reported-saved-as-video
Bugfix: images reported saved as video
2024-11-04 10:09:36 -05:00
ilcompratoreconsapevole
00be9fc595 Rewritten connection link to ZapStore's banner image to ensure reliable connection to specific repo 2024-11-03 21:38:01 +01:00
David Kaspar
7d25ab13a9 Launch in Dispatchers.IO when changing translations prefs in account 2024-11-03 16:15:54 +00:00
ilcompratoreconsapevole
d7888096e9 Added ZapStore's SVG banner that says "Get it on" linking to its repository. 2024-11-03 12:50:46 +01:00
David Kaspar
aad5aaa930 rename inner it to avoid shadowed it 2024-11-03 11:48:12 +00:00
David Kaspar
b877e4105a Replace nested ifs with a when 2024-11-03 10:30:07 +00:00
David Kaspar
d1cd15c389 Remove unused val 2024-11-03 10:24:20 +00:00
David Kaspar
69e139e382 Remove unused @OptIn(ExperimentalFoundationApi::class) 2024-11-03 10:23:32 +00:00
David Kaspar
b2628764c9 Remove unused shadowed orientation val 2024-11-03 10:20:30 +00:00
David Kaspar
f7f0d74be1 Correct boolean operation from AND to OR 2024-11-03 10:19:29 +00:00
Vitor Pamplona
b47122d79a Updates accompanist, kotlin serialization and mockk 2024-11-01 18:41:00 -04:00
Vitor Pamplona
635ad30de9 Let it throw in the giftwrap parser to make sure Notifications work 2024-11-01 18:40:34 -04:00
Vitor Pamplona
0884318a55 Merge pull request #1161 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-11-01 18:27:38 -04:00
Crowdin Bot
d8c89317d2 New Crowdin translations by GitHub Action 2024-11-01 22:20:09 +00:00
Vitor Pamplona
772987dffd coroutines test to 1.9 2024-11-01 18:17:32 -04:00
Vitor Pamplona
61c51ee9a8 Updates AGP 2024-11-01 18:17:07 -04:00
Vitor Pamplona
f157f8eb9b - Fixes lack of zap updates when there is a private zap the user cannot decrypt or when a nwc payment fails.
- Moves the parallel processing to a utils class
2024-11-01 18:16:57 -04:00
Vitor Pamplona
d96f5953d5 Moving animation size to a constant. 2024-11-01 17:27:19 -04:00
Vitor Pamplona
ffb5cce509 Merge pull request #1160 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-11-01 10:35:40 -04:00
Crowdin Bot
b441292413 New Crowdin translations by GitHub Action 2024-11-01 14:16:09 +00:00
Vitor Pamplona
91748d5c39 - Adds a cache for reply levels when viewing threads.
- Moves the lazy list state to the view model to saving the scrolling position when navigating between multiple threads.
2024-11-01 10:10:05 -04:00
Vitor Pamplona
a825f575de Fixes rendering of notes when the modifier changes due to new posts found and the reply level gets recalculated. 2024-11-01 10:06:09 -04:00
Vitor Pamplona
0581a3e836 Fixes reply level calculation caching. 2024-11-01 10:05:25 -04:00
Vitor Pamplona
82f0ed8a0d Upgrades to Coil 3 2024-10-31 16:34:22 -04:00
Vitor Pamplona
116bc108c3 Merge pull request #1158 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-10-31 14:07:13 -04:00
Crowdin Bot
44868ac4e6 New Crowdin translations by GitHub Action 2024-10-31 18:05:03 +00:00
Vitor Pamplona
2a24ca0787 Adds support for q tags on addresses 2024-10-31 14:02:39 -04:00
Vitor Pamplona
03225fc696 Merge pull request #1157 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-10-30 18:00:57 -04:00
Crowdin Bot
a0ab4a824b New Crowdin translations by GitHub Action 2024-10-30 21:59:32 +00:00
Vitor Pamplona
0ba4ca13bf Updates compose, corektx, fragment, kotlin, runtime, and android camera libs 2024-10-30 17:56:28 -04:00
Vitor Pamplona
060a242a0f Removes logs 2024-10-30 17:55:35 -04:00
Vitor Pamplona
ae530ed813 adds extra padding for the zap setup screen 2024-10-30 16:02:00 -04:00
Vitor Pamplona
a5c4a53afe - Adds an Around ME feed
- Refactors location to operate as a flow
- Refactors FeedStructures to prepare for custom feeds
- Moves Account to operate feeds with location
2024-10-30 16:01:39 -04:00
Vitor Pamplona
fb6137f99a Missing string 2024-10-29 12:31:07 -04:00
Vitor Pamplona
de99c50639 Adds search.nos.today to bootstrapping relays for search 2024-10-29 12:23:09 -04:00
Vitor Pamplona
d5f8994128 Merge pull request #1156 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-10-29 12:16:33 -04:00
Crowdin Bot
cf02d808d6 New Crowdin translations by GitHub Action 2024-10-29 16:10:36 +00:00
Vitor Pamplona
f6aa732558 Adds DM and Search default buttons to the dialogs. 2024-10-29 12:07:15 -04:00
Vitor Pamplona
d321df79e8 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-10-28 16:11:09 -04:00
Vitor Pamplona
d1b4f81083 Fixes jumpy thread view 2024-10-28 16:10:47 -04:00
Vitor Pamplona
0205f1fd12 Merge pull request #1155 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-10-28 10:14:42 -04:00
Crowdin Bot
d739fdac2d New Crowdin translations by GitHub Action 2024-10-28 14:11:31 +00:00
Vitor Pamplona
4a43a87a79 Moves templates to explain that bounties matter. 2024-10-28 10:08:53 -04:00
Vitor Pamplona
6f31898cdc Updates Firebase 2024-10-24 17:34:13 -04:00
Vitor Pamplona
6ebc878312 Fixes poll's background rendering with the right percentages. 2024-10-24 17:34:00 -04:00
Vitor Pamplona
518e1c88ce Adds hidden words filter to search, hashtag and geotag feeds
Applies hidden words even to hashtags that were not included in the content of the event.
Pre-process search to avoid showing and hiding posts after hidden words where processed by the UI.
2024-10-24 11:00:07 -04:00
Vitor Pamplona
f88985b2bf Adds an icon to the repo 2024-10-23 18:00:23 -04:00
Vitor Pamplona
89e1e20b40 Improves algorithm for placing the clicked note in a visible position when opening a new threads that need to load dynamically 2024-10-22 17:26:53 -04:00
Vitor Pamplona
c2e725ef5f Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-10-22 17:14:36 -04:00
Vitor Pamplona
6e8c348cbc Moves NIP-44 test model classes to a new file 2024-10-22 17:14:29 -04:00
Vitor Pamplona
84316d320d Merge pull request #1150 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-10-22 15:26:36 -04:00
Crowdin Bot
87fb63af06 New Crowdin translations by GitHub Action 2024-10-22 19:00:17 +00:00
Vitor Pamplona
a3b0436d91 Uses NIP-78 to start syncing some data between instances of Amethyst 2024-10-22 14:52:11 -04:00
Vitor Pamplona
bb430605bc Merge pull request #1148 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-10-19 18:50:37 -04:00
Crowdin Bot
4c0d92f89f New Crowdin translations by GitHub Action 2024-10-19 18:19:59 +00:00
Vitor Pamplona
f0b14edef6 v0.92.7 2024-10-19 14:17:42 -04:00
Vitor Pamplona
aae2ffebd7 Fixes the bug of unable to decrypt mute lists. 2024-10-19 14:17:17 -04:00
Vitor Pamplona
7b11d0ce81 v0.92.6 2024-10-17 17:21:20 -04:00
Vitor Pamplona
26ba75c7c9 Fixes array too big because strfry blocks more than 20 filters 2024-10-17 17:18:35 -04:00
Vitor Pamplona
67fb3bf488 Fixes margin of poll options with translation 2024-10-17 15:22:34 -04:00
Vitor Pamplona
24b29396cb Reduces the font size for the translation label 2024-10-17 15:22:19 -04:00
Vitor Pamplona
25c3532637 Fixes poll rendering 2024-10-17 14:55:07 -04:00
Vitor Pamplona
cff6ee457d Fixes zapraiser progress bar 2024-10-17 14:18:40 -04:00
Vitor Pamplona
c0ba6f5b00 If the Share target intent opens with the new post screen already active, just updates the post instead of creating a new one. 2024-10-17 13:59:52 -04:00
Vitor Pamplona
44d8b8ff33 v0.92.5 2024-10-16 17:34:10 -04:00
Vitor Pamplona
f495acb570 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-10-16 17:33:58 -04:00
Vitor Pamplona
ecfc8bcd87 Merge pull request #1144 from geovnn/main
Prevent clicks outside boost popup
2024-10-16 17:33:39 -04:00
Vitor Pamplona
724bea6bbb Updates compose, benchmark, navigation, and activity 2024-10-16 17:32:33 -04:00
Giovanni Gatti
6826db13a4 Prevent clicks outside boost popup 2024-10-16 23:11:51 +02:00
Vitor Pamplona
c5dd2c5651 Fixes recreating the new post screen from intent when switching accounts. 2024-10-16 13:33:46 -04:00
Vitor Pamplona
236ff2d680 v0.92.4 2024-10-16 11:13:56 -04:00
Vitor Pamplona
13e2546d36 Makes Amethyst a share target for texts, images and videos. 2024-10-16 10:54:57 -04:00
Vitor Pamplona
549b9f53e5 Fixes new media post dialog for the edge to edge borders 2024-10-16 09:41:02 -04:00
Vitor Pamplona
974c022aed Fixes padding of the new new post screen 2024-10-15 17:20:16 -04:00
Vitor Pamplona
a57566dd84 Changes the new post screen to use the non-disappearing version of the scaffold. 2024-10-15 16:55:09 -04:00
Vitor Pamplona
72e86cf391 Merge pull request #1143 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-10-15 16:25:21 -04:00
Crowdin Bot
3b23cded56 New Crowdin translations by GitHub Action 2024-10-15 20:04:18 +00:00
Vitor Pamplona
121337eb83 Makes new post screen come in and out from the bottom 2024-10-15 16:02:20 -04:00
Vitor Pamplona
fe87d642c9 Merge branch 'main' of https://github.com/vitorpamplona/amethyst
# Conflicts:
#	amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/NewPostScreen.kt
2024-10-15 15:54:26 -04:00
Vitor Pamplona
b8112ff1aa Correctly maps the write status of the outbox relays. 2024-10-15 15:53:00 -04:00
Vitor Pamplona
1eee0bd1ae Merge pull request #1142 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-10-15 13:55:09 -04:00
Crowdin Bot
f48335e3be New Crowdin translations by GitHub Action 2024-10-15 17:46:27 +00:00
Vitor Pamplona
fcc4befb22 Merge pull request #1141 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-10-15 13:44:54 -04:00
Crowdin Bot
e28a1896ec New Crowdin translations by GitHub Action 2024-10-15 17:38:52 +00:00
Vitor Pamplona
f10e66e6a5 Merge pull request #1137 from geovnn/main
Change NewPostView to NewPostScreen to make it route based
2024-10-15 13:37:33 -04:00
Vitor Pamplona
825a227e2d Merge pull request #1140 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-10-15 12:09:51 -04:00
Crowdin Bot
3446fdaf7f New Crowdin translations by GitHub Action 2024-10-15 16:08:45 +00:00
Vitor Pamplona
9c29bf3f25 v0.92.3 2024-10-15 12:06:36 -04:00
Vitor Pamplona
9642e45775 Merge pull request #1139 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-10-15 12:06:23 -04:00
Crowdin Bot
58788d2cd5 New Crowdin translations by GitHub Action 2024-10-15 16:00:54 +00:00
Vitor Pamplona
d7c18341cd Uses the same Reaction animation to also do Boosts 2024-10-15 11:58:40 -04:00
Vitor Pamplona
ee16f6c143 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-10-15 11:28:41 -04:00
Vitor Pamplona
d78b55d134 Reverts hack for fling behavior on the Vertical Pager 2024-10-15 11:28:33 -04:00
Vitor Pamplona
ff5e7359e2 Merge pull request #1138 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-10-15 11:05:39 -04:00
Crowdin Bot
4fd0f38402 New Crowdin translations by GitHub Action 2024-10-15 14:56:33 +00:00
Vitor Pamplona
5b516f4101 Updates to AGP 8.7.1 and SDK 35 2024-10-15 10:53:21 -04:00
Vitor Pamplona
1fc390c215 Do not bring the keyboard when the search field reappears. 2024-10-15 10:52:54 -04:00
Vitor Pamplona
2bb09f583b Fixes Thread view when loading a reply of a thread that is not cached yet. 2024-10-15 10:45:03 -04:00
Giovanni Gatti
89de272ea1 Change NewPostView to NewPostScreen to make it route based 2024-10-14 23:19:43 +02:00
Vitor Pamplona
b4eba2da02 0.92.2 2024-10-11 19:35:52 -04:00
Vitor Pamplona
786a173ba5 Merge pull request #1133 from greenart7c3/external_signer_result
Check for the result field when using external signer
2024-10-11 08:08:30 -04:00
greenart7c3
5ef3c8f00e Check for the result field when using external signer 2024-10-11 07:22:34 -03:00
Vitor Pamplona
d832351bcd Fixes the ability to see muted lists in Shorts 2024-10-10 17:52:24 -04:00
Vitor Pamplona
9ae611831f Enables new fields for vision prescriptions 2024-10-10 16:48:33 -04:00
Vitor Pamplona
6db287a008 Merge pull request #1131 from davotoula/prioritise-name-when-searching
Prioritise search results with user name starting with search term
2024-10-10 09:47:28 -04:00
David Kaspar
99641e1a12 Added comparison between search term and display name to comparator to prioritise results with search term in name 2024-10-10 14:11:13 +02:00
Vitor Pamplona
abb2f0557d Merge pull request #1118 from davotoula/refactor-media-compressor
Refactor media compressor as prep for replacing 3rd party compression library
2024-10-09 16:38:29 -04:00
David Kaspar
76a66e7bd3 added test for when exception happens during compression 2024-10-09 21:46:15 +02:00
David Kaspar
6cd50a115b Merge branch 'vitorpamplona:main' into refactor-media-compressor 2024-10-09 14:16:14 +01:00
Vitor Pamplona
0ed34cec09 Fixes https://github.com/vitorpamplona/amethyst/issues/1130 2024-10-09 08:42:33 -04:00
David Kaspar
c5e3657bfe added missing dot for file extension 2024-10-09 01:45:50 +02:00
David Kaspar
da47965d76 Merge branch 'main' into refactor-media-compressor 2024-10-09 00:16:35 +01:00
David Kaspar
a66417ec82 Added Unknown media type test 2024-10-09 01:07:28 +02:00
David Kaspar
62c3c93d2e Removed splitFileName function as both file name and extension are known separately 2024-10-09 01:02:41 +02:00
David Kaspar
fbecc8b6d1 Use "use" blocks to close resources automatically 2024-10-09 00:52:35 +02:00
Vitor Pamplona
e95afa89ff Merge pull request #1129 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-10-08 18:38:36 -04:00
Crowdin Bot
d6f2560c1c New Crowdin translations by GitHub Action 2024-10-08 22:33:54 +00:00
Vitor Pamplona
d320b951ae Fixes long term issue with the video in the Shorts feed not aligning with the padding of the screen 2024-10-08 18:31:54 -04:00
David Kaspar
af28e6d466 Use copyTo to copy streams 2024-10-09 00:15:19 +02:00
Vitor Pamplona
86e6d56dcd Removes old logs used for debuging the previous issue 2024-10-08 17:19:35 -04:00
Vitor Pamplona
c66fa1073b Fixes intent reopening the Zap Setup screen because it was saved in the backstack of the Home screen. 2024-10-08 16:09:09 -04:00
Vitor Pamplona
6d9bffe9e7 Disabling #1122 until we solve those little issues. 2024-10-08 15:00:25 -04:00
Vitor Pamplona
04158cec6e Merge pull request #1128 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-10-08 14:43:07 -04:00
Crowdin Bot
76376a7c40 New Crowdin translations by GitHub Action 2024-10-08 18:32:53 +00:00
Vitor Pamplona
67ea0dcf7f Faster logout processing without closing the account switcher dialog. 2024-10-08 13:59:51 -04:00
David Kaspar
cdc8850894 Refactor out file operations into seperate helper
Additional tests for MediaCompressor
2024-10-08 17:47:27 +02:00
David Kaspar
ce0c7c842d Merge branch 'main' into refactor-media-compressor 2024-10-08 14:51:53 +01:00
Vitor Pamplona
f51f929079 Merging 2024-10-08 09:24:10 -04:00
Vitor Pamplona
d87d2e0ef8 Merge pull request #1127 from geovnn/main
Added animations
2024-10-08 09:22:40 -04:00
Giovanni Gatti
a3166f4ff3 Add animation to notification chart 2024-10-08 12:13:47 +02:00
Giovanni Gatti
9340c440f5 Add animation to FABs 2024-10-08 11:54:42 +02:00
Giovanni Gatti
a7343d5b54 Add animation to zap and reaction popups 2024-10-08 11:06:29 +02:00
Vitor Pamplona
0551b82bd9 Updates AGP and compose, fragment, navigation, benchmarking and firebase libraries. 2024-10-07 17:02:09 -04:00
Vitor Pamplona
18fca8adac Merge pull request #1122 from KotlinGeekDev/conditional-rotation
Re-enable tap to fullscreen behaviour with stricter orientation checks.
2024-10-07 12:57:28 -04:00
Vitor Pamplona
5d788ed669 Merge pull request #1125 from geovnn/main
Prevent clicks outside reaction and zap popups
2024-10-07 12:56:57 -04:00
Giovanni Gatti
54d52e0b77 Prevent clicks outside reaction and zap popups 2024-10-07 17:38:05 +02:00
Vitor Pamplona
28c92675b2 Merge pull request #1124 from greenart7c3/main
Support for login with hex key when using amber
2024-10-07 08:32:59 -04:00
greenart7c3
baa9ee0562 Support for login with hex key when using amber 2024-10-07 08:50:06 -03:00
KotlinGeekDev
7326d6be93 Rotation:actually rotate if the device orientation is not locked. 2024-10-05 17:06:36 +01:00
David Kaspar
e187e5392f refactor "from" method 2024-10-03 14:56:03 +02:00
David Kaspar
7c8f6eb239 formatting 2024-10-03 14:56:03 +02:00
David Kaspar
6294c65ad6 Create private functions for image vs video compression and when statement to select on content type 2024-10-03 14:56:03 +02:00
David Kaspar
51d9657371 Use Pair instead of Array to split up file name 2024-10-03 14:56:03 +02:00
David Kaspar
32783794ee Exit early if UNCOMPRESSED is selected 2024-10-03 14:56:03 +02:00
David Kaspar
e3858dc830 added kotlinx.coroutines.test library
added MediaCompressor first tests
2024-10-03 14:56:03 +02:00
Vitor Pamplona
38a9030963 Merge pull request #1117 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-10-03 08:28:43 -04:00
Crowdin Bot
29c0c4cf5f New Crowdin translations by GitHub Action 2024-10-03 12:23:07 +00:00
Vitor Pamplona
dcbde81a23 Merge pull request #1116 from davotoula/update-tests-for-new-forceProxy-parameter
Update tests for new forceProxy param
2024-10-03 08:21:47 -04:00
David Kaspar
56e6f06fe7 add "forceProxy = false" to tests 2024-10-03 10:02:31 +02:00
Vitor Pamplona
342b64f0eb Merge pull request #1114 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-30 19:18:57 -04:00
Crowdin Bot
a64a640165 New Crowdin translations by GitHub Action 2024-09-30 23:05:25 +00:00
Vitor Pamplona
6433830c32 Fixes language setting toggles 2024-09-30 18:47:45 -04:00
Vitor Pamplona
3a58819b52 Merge pull request #1112 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-28 11:54:58 -04:00
Crowdin Bot
5c7be44369 New Crowdin translations by GitHub Action 2024-09-28 15:43:33 +00:00
Vitor Pamplona
6e66d008dc Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-09-28 11:41:30 -04:00
Vitor Pamplona
c61c4ce16c Improves names and icons of the left drawer. 2024-09-28 11:01:56 -04:00
Vitor Pamplona
246ce55253 Merge pull request #1111 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-28 09:49:21 -04:00
Crowdin Bot
a704c81d24 New Crowdin translations by GitHub Action 2024-09-28 13:43:32 +00:00
Vitor Pamplona
9963245ec9 Improves zap store descriptions 2024-09-28 09:40:02 -04:00
Vitor Pamplona
64016aa940 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-09-27 18:02:33 -04:00
Vitor Pamplona
c6462f102a Merge pull request #1110 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-27 17:23:41 -04:00
Vitor Pamplona
b05083863d removes the aab files 2024-09-27 17:13:44 -04:00
Crowdin Bot
86fffe6539 New Crowdin translations by GitHub Action 2024-09-27 21:13:01 +00:00
Vitor Pamplona
f94a4cfa65 Merge pull request #1109 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-27 17:11:24 -04:00
Crowdin Bot
3825642ae7 New Crowdin translations by GitHub Action 2024-09-27 19:40:05 +00:00
Vitor Pamplona
f90f81b2a5 Merge pull request #1108 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-27 15:38:46 -04:00
Crowdin Bot
bc042e52b0 New Crowdin translations by GitHub Action 2024-09-27 19:28:52 +00:00
Vitor Pamplona
d80b22fa29 Merge pull request #1107 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-27 15:27:38 -04:00
Crowdin Bot
b63ed4fdbd New Crowdin translations by GitHub Action 2024-09-27 19:24:11 +00:00
Vitor Pamplona
397acce85b Merge pull request #1106 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-27 15:23:01 -04:00
Crowdin Bot
5305929df3 New Crowdin translations by GitHub Action 2024-09-27 19:22:04 +00:00
Vitor Pamplona
6d4ba6d507 v0.92.1 2024-09-27 15:20:06 -04:00
Vitor Pamplona
a028c2c3fc Fixes missing zaps on the first connection to a NWC wallet with a split payment. 2024-09-27 15:19:59 -04:00
Vitor Pamplona
86e5dfa799 Fixes access to Citrine 2024-09-27 14:38:14 -04:00
Vitor Pamplona
3aa316d262 v0.92.0 2024-09-27 11:14:45 -04:00
Vitor Pamplona
3f4efdb6d9 Merge pull request #1105 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-27 08:26:41 -04:00
Crowdin Bot
a178e5f589 New Crowdin translations by GitHub Action 2024-09-27 12:23:29 +00:00
Vitor Pamplona
cc5a6cdaf2 Merge pull request #1104 from davotoula/update_translations
Update de, cs, se, pt translations
2024-09-27 08:21:49 -04:00
David Kaspar
d9596335de Update de, cs, se, pt translations 2024-09-27 09:51:41 +02:00
Vitor Pamplona
44c600dfa8 Fixes icon position on chat user pictures 2024-09-26 18:36:42 -04:00
Vitor Pamplona
a92fe0bca2 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-09-26 17:20:36 -04:00
Vitor Pamplona
dea9d698df Adds privacy presets for Tor Settings 2024-09-26 17:20:29 -04:00
Vitor Pamplona
94ae7b3da1 Merge pull request #1103 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-26 15:53:03 -04:00
Crowdin Bot
da1c94f77b New Crowdin translations by GitHub Action 2024-09-26 19:26:05 +00:00
Vitor Pamplona
64ff33e745 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-09-26 15:23:47 -04:00
Vitor Pamplona
8810cfde37 Adjusts Login and Sign up screens for the new Tor Settings 2024-09-26 15:23:39 -04:00
Vitor Pamplona
c7b7ad78b7 Adds mempool to verify OTS via Tor. 2024-09-26 15:23:13 -04:00
Vitor Pamplona
ff9f25ccdb Removes unnecessary log 2024-09-26 14:42:40 -04:00
Vitor Pamplona
498595b892 Merge pull request #1102 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-26 13:48:48 -04:00
Vitor Pamplona
56878900b0 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-09-26 13:46:52 -04:00
Vitor Pamplona
d8d6736d55 Caches OTS web calls to avoid pinging the server repeatedly for the same event. 2024-09-26 13:45:01 -04:00
Crowdin Bot
ddc68e61d5 New Crowdin translations by GitHub Action 2024-09-26 17:43:05 +00:00
Vitor Pamplona
d4e8fc5737 Merge pull request #1101 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-26 13:41:24 -04:00
Crowdin Bot
3a7dfe7d03 New Crowdin translations by GitHub Action 2024-09-26 15:57:17 +00:00
Vitor Pamplona
d23a859f34 Improves OTS Verification error message 2024-09-26 11:55:29 -04:00
Vitor Pamplona
824cb4e5f1 @Suppress("ProduceStateDoesNotAssignValue") until we figure out what's wrong with this lint. 2024-09-26 11:36:52 -04:00
Vitor Pamplona
35aeeb571c Fixes setting the value in the main thread 2024-09-26 11:20:51 -04:00
Vitor Pamplona
70d68c89c8 Updates compose, benchmark, firebase, navigation and lifecycle dependencies. 2024-09-26 11:20:33 -04:00
Vitor Pamplona
35a6331da2 Fixes test case 2024-09-26 10:59:50 -04:00
Vitor Pamplona
6229a0ad63 making sure to only use .onion urls if the option is active 2024-09-26 10:41:36 -04:00
Vitor Pamplona
620285596d Show buffering when loading videos 2024-09-26 10:39:12 -04:00
Vitor Pamplona
fd2637ff42 Removes unused tor setting 2024-09-26 10:38:36 -04:00
Vitor Pamplona
afe8a06486 - Adds a new Settings page for Tor
- Adjusts all web calls to use Tor if that setting is enabled.
- Allows .onion urls to use Tor
- Blocks localhost from using Tor
- Moves OTS web calls to use the Tor Proxy as well.
- Starts to build all OkHttp clients from a main root node to keep the same thread pool
- Refactors the URL Preview code
- Changes ammolite to force proxy.
- Changes NIP-47 implementation to force relay for the NWC connection.
2024-09-25 17:58:37 -04:00
Vitor Pamplona
b682e90f81 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-09-23 21:51:23 -04:00
Vitor Pamplona
ec700ca61f Refactoring 2024-09-23 21:51:15 -04:00
Vitor Pamplona
9b26ffd92a Updates to AGP 8.6.1 2024-09-23 21:48:13 -04:00
Vitor Pamplona
a8ca9ab727 Merge pull request #1091 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-20 09:00:43 -04:00
Crowdin Bot
e5832f6a45 New Crowdin translations by GitHub Action 2024-09-20 12:57:12 +00:00
Vitor Pamplona
8b3035f635 Merge pull request #1090 from greenart7c3/main
Fix for notifications when using amber
2024-09-20 08:56:00 -04:00
greenart7c3
9f17cc50f8 Fix for notifications when using amber 2024-09-20 06:48:27 -03:00
Vitor Pamplona
d0633d07fa Fixes inability to go back after opening a nostr link from the web into Amethyst 2024-09-18 19:47:09 -04:00
Vitor Pamplona
97b88c7ceb Merge pull request #1088 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-18 17:38:59 -04:00
Crowdin Bot
4961a22753 New Crowdin translations by GitHub Action 2024-09-18 21:23:22 +00:00
Vitor Pamplona
45b568f6a7 updates amy bg 2024-09-18 17:21:44 -04:00
Vitor Pamplona
446859e8bd adds amy 2024-09-18 17:16:52 -04:00
Vitor Pamplona
e1b24c22b9 adds phone mockups 2024-09-18 17:16:38 -04:00
Vitor Pamplona
e0b1c4dc3f Sending jpg and webp version of the image 2024-09-18 16:28:07 -04:00
Vitor Pamplona
5722507b3d Adds two designed images for the homepage 2024-09-18 16:23:13 -04:00
Vitor Pamplona
74df309527 Improving bug report template 2024-09-17 18:07:41 -04:00
Vitor Pamplona
740c6a8c33 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-09-17 18:07:29 -04:00
Vitor Pamplona
929a263665 Adds zapstore yaml 2024-09-17 18:07:12 -04:00
Vitor Pamplona
6f44c02b5c Makes sure if the d component of an a-tag has :, it stays in the d-tag after parse. 2024-09-16 18:10:54 -04:00
Vitor Pamplona
bce01dc264 Merge pull request #1083 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-16 11:26:36 -04:00
Crowdin Bot
7919637e12 New Crowdin translations by GitHub Action 2024-09-16 15:25:34 +00:00
Vitor Pamplona
28da06ef01 Fixes #1084. Opengraph parser fails when value-less properties are present. 2024-09-16 11:23:41 -04:00
Vitor Pamplona
428ed464af Adds salt to the bloom filter 2024-09-15 14:28:49 -04:00
Vitor Pamplona
5921b712b0 Merge pull request #1082 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-13 14:17:46 -04:00
Crowdin Bot
5c9a37f01c New Crowdin translations by GitHub Action 2024-09-13 18:12:12 +00:00
Vitor Pamplona
514a69deec Bloom filter test case for NIP76 2024-09-13 14:06:45 -04:00
Vitor Pamplona
356cbc24d4 Merge pull request #1081 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-12 16:09:38 -04:00
Crowdin Bot
f4a2f247f7 New Crowdin translations by GitHub Action 2024-09-12 20:05:59 +00:00
Vitor Pamplona
9ee28e28b8 If already logged in and an NFC tag shows up with ncryptsec, logs in as a transient account 2024-09-12 15:57:35 -04:00
Vitor Pamplona
2457429470 Merge pull request #1078 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-12 08:15:27 -04:00
Crowdin Bot
b998381bb6 New Crowdin translations by GitHub Action 2024-09-12 12:04:40 +00:00
Vitor Pamplona
74725235b7 Merge pull request #1074 from davotoula/add-media-compression-level-uncompressed
Add media compression level uncompressed
2024-09-12 08:02:51 -04:00
David Kaspar
ef4d975c7c Merge branch 'vitorpamplona:main' into add-media-compression-level-uncompressed 2024-09-12 12:40:46 +01:00
Vitor Pamplona
3fdd3f9b69 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-09-11 17:15:33 -04:00
Vitor Pamplona
53aa9b0017 Trying to fix upload-artifact. 2024-09-11 17:15:23 -04:00
Vitor Pamplona
a52d87a555 Merge pull request #1076 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-11 17:15:10 -04:00
Crowdin Bot
39f062fe32 New Crowdin translations by GitHub Action 2024-09-11 21:03:20 +00:00
Vitor Pamplona
b2c13089ce adds NFC-Based transient accounts.
Refactors the login screen
2024-09-11 16:49:35 -04:00
David Kaspar
4ddf307b9f added translations 2024-09-11 17:27:08 +02:00
David Kaspar
3db36d8c67 added skipping of media compressor when quality is UNCOMPRESSED
added media compressor logging
2024-09-11 17:27:08 +02:00
David Kaspar
bba7d3455c enhanced nip05 logging 2024-09-11 17:27:08 +02:00
Vitor Pamplona
f086c0fe10 Merge pull request #1043 from greenart7c3/camera
Take pictures with camera
2024-09-10 15:32:01 -04:00
Vitor Pamplona
abc803953e Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-09-09 19:44:33 -04:00
Vitor Pamplona
8841aa9a10 Adds Tor 2024-09-09 19:42:43 -04:00
greenart7c3
7e417f09f7 Merge remote-tracking branch 'origin/camera' into camera 2024-09-09 16:10:47 -03:00
greenart7c3
0fde6ffd30 Move camera dependencies to version catalogs 2024-09-09 16:03:35 -03:00
greenart7c3
6f291139d8 Merge branch 'main' into camera 2024-09-09 15:40:56 -03:00
greenart7c3
1e3104d489 Add camera button in the stories screen 2024-09-09 15:37:30 -03:00
greenart7c3
2e110422c8 after enabling permissions open the camera 2024-09-09 14:59:05 -03:00
Vitor Pamplona
7b7aa1932f Merge pull request #1072 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-09 13:37:59 -04:00
Crowdin Bot
773c96997c New Crowdin translations by GitHub Action 2024-09-09 17:37:07 +00:00
Vitor Pamplona
8f8199f489 Merge pull request #1071 from greenart7c3/main
Fix edit draft not working when using the quick action menu
2024-09-09 13:33:54 -04:00
greenart7c3
a63d50c24f Merge remote-tracking branch 'origin/camera' into camera 2024-09-09 14:32:55 -03:00
greenart7c3
6af2b48d23 Add a button to take a picture from camera 2024-09-09 14:32:37 -03:00
greenart7c3
37197e1f8a Fix edit draft not working when using the quick action menu 2024-09-09 14:25:11 -03:00
Vitor Pamplona
8ede4eb3d6 Updates navigation compose, lifecycle, fragment, activity and composeBoms 2024-09-06 17:29:06 -04:00
Vitor Pamplona
c7fcc47b11 Adds an isRefreshing status for all feeds. 2024-09-06 17:19:10 -04:00
Vitor Pamplona
f12cf93e9f Merge pull request #1065 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-06 14:20:11 -04:00
Crowdin Bot
00e354394f New Crowdin translations by GitHub Action 2024-09-06 18:12:34 +00:00
Vitor Pamplona
bbb548fe21 Fixes the zap options available for the Zap the Devs button. 2024-09-06 11:36:01 -04:00
Vitor Pamplona
c19e1fc56d Fixes #1064 2024-09-06 11:19:01 -04:00
Vitor Pamplona
065cf83b68 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-09-06 11:00:04 -04:00
Vitor Pamplona
ca0da1dcc8 v0.91.0 2024-09-06 10:59:54 -04:00
Vitor Pamplona
58a5cbc624 Merge pull request #1063 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-06 10:12:13 -04:00
Crowdin Bot
554fef9eae New Crowdin translations by GitHub Action 2024-09-06 14:10:20 +00:00
Vitor Pamplona
7dd76f866a Enables the use of hidden words for all visible properties of the user 2024-09-06 10:07:41 -04:00
Vitor Pamplona
84bcc33e87 minor refactoring on variables inside the chat screen rendering. 2024-09-06 10:03:49 -04:00
Vitor Pamplona
6309aa1711 Fixes size of default banner when the profile is not loaded yet. 2024-09-06 10:02:04 -04:00
Vitor Pamplona
a8a3bc8a6b Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-09-05 18:00:25 -04:00
Vitor Pamplona
d2b4a859bf Fixes Community Load up with Global filter 2024-09-05 18:00:17 -04:00
Vitor Pamplona
92d11d84a7 Merge pull request #1061 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-05 17:49:28 -04:00
Crowdin Bot
1cba6e6cdb New Crowdin translations by GitHub Action 2024-09-05 21:41:52 +00:00
Vitor Pamplona
20115c7080 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-09-05 17:39:51 -04:00
Vitor Pamplona
4b3d986c5b Moves has-new-item bottom navigation computations to use the new feed states and last read database in flows. 2024-09-05 17:39:36 -04:00
Vitor Pamplona
21112d3d46 Merge pull request #1060 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-05 15:23:45 -04:00
Crowdin Bot
ec3f307e0b New Crowdin translations by GitHub Action 2024-09-05 19:17:01 +00:00
Vitor Pamplona
e17cfb4fdb Simplifies the "and 2 more" translations 2024-09-05 15:11:00 -04:00
Vitor Pamplona
010305fbeb - Disables saving m3u8 files (streaming can't be saved)
- Changes Error messages to not include stack traces and move them to a copy to clipboard action instead.
2024-09-05 14:36:23 -04:00
Vitor Pamplona
5af473870e Fixes Search layout after the transition to nav 2024-09-05 14:00:39 -04:00
Vitor Pamplona
80f805617a Adds sliding animations in all inner screens 2024-09-05 13:53:52 -04:00
Vitor Pamplona
3e1184562f Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-09-05 13:47:33 -04:00
Vitor Pamplona
39edbd22cc fixes #1058 language update issue 2024-09-05 13:47:23 -04:00
Vitor Pamplona
c90e615d5b Merge pull request #1059 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-05 13:00:43 -04:00
Crowdin Bot
5e6e7a3b5f New Crowdin translations by GitHub Action 2024-09-05 16:08:57 +00:00
Vitor Pamplona
3e23d6e526 Merge pull request #1051 from davotoula/configurable-media-compression
Configurable media compression
2024-09-05 12:07:33 -04:00
David Kaspar
08054e226e Merge branch 'vitorpamplona:main' into configurable-media-compression 2024-09-05 16:02:52 +01:00
David Kaspar
cfe668ab0d move slider value label to above slider 2024-09-05 16:58:39 +02:00
Vitor Pamplona
8f19276fac Fixes blinking on crossfades when the system's light/dark theme is different than the app's theme. 2024-09-05 10:50:16 -04:00
Vitor Pamplona
3a3c0d74d2 Fixes the Messages layout on foldables. 2024-09-05 10:30:58 -04:00
David Kaspar
3ad21e72a9 Clean up by using Int instead of Float for compression level 2024-09-05 16:10:26 +02:00
David Kaspar
790b9359bd Merge branch 'vitorpamplona:main' into configurable-media-compression 2024-09-05 14:32:59 +01:00
David Kaspar
e52e2bfdc9 Localise and add czech, swedish, german and PT translations 2024-09-05 15:09:19 +02:00
Vitor Pamplona
a34c763656 Merge pull request #1056 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-05 08:42:51 -04:00
Crowdin Bot
adf5bbe80f New Crowdin translations by GitHub Action 2024-09-05 12:39:02 +00:00
Vitor Pamplona
c4c542c739 Moves the last npub to hexkey for https://github.com/nostr-protocol/nips/pull/1341 2024-09-05 08:37:15 -04:00
David Kaspar
5f0236c015 change MediaCompressor API: mandatory mediaQuality 2024-09-05 14:28:12 +02:00
David Kaspar
023c0592e8 Add compression configuration to VideoScreen uploads 2024-09-05 13:09:17 +02:00
David Kaspar
c6d2f05f15 Styling 2024-09-05 11:50:52 +02:00
David Kaspar
08e9f6625a Merge branch 'main' into configurable-media-compression 2024-09-05 08:32:49 +01:00
David Kaspar
fcf5e972d6 Passing media quality from Slider to Compressor
setting media quality to MEDIUM where ui has no option for setting it (ChannelScreen, ChatroomScreen, NewUserMetadataViewModel)
2024-09-05 09:09:10 +02:00
Vitor Pamplona
20bf4dbc29 Merge pull request #1053 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-04 22:28:12 -04:00
Crowdin Bot
990c5df2b9 New Crowdin translations by GitHub Action 2024-09-05 02:21:58 +00:00
Vitor Pamplona
71af88725a Fixes play version 2024-09-04 22:19:28 -04:00
Vitor Pamplona
fb5f5c3eba no message 2024-09-04 22:18:00 -04:00
Vitor Pamplona
ead588314e - Inverts Layouts to place Navigation on top of Scaffold and allow custom scaffolds per route.
- Finishes Edge to Edge transition
- Fixes moving buttons on the full screen dialog for images and videos.
- Restructures screens into their own packages.
- Restructures navigation functions as a single object
- Fixes padding of the backup screen
- Refactors all TopBars to use default material 3 ones.
- Refactors navigation to improve clarity
- Removes unnecessary observers from the transition in the bottom nav layouts.
2024-09-04 22:17:42 -04:00
Vitor Pamplona
fb447e441a Merge pull request #1052 from greenart7c3/gcompatup
Fix token sanitization when using gcompatup
2024-09-04 13:37:42 -04:00
greenart7c3
3d61343905 Fix token sanitization when using gcompatup 2024-09-04 13:58:55 -03:00
David Kaspar
7e4d9fb708 added media quality slider 2024-09-04 12:32:33 +02:00
Vitor Pamplona
0217fd3eb3 Moves the profile zap to threads 2024-09-03 17:29:41 -04:00
Vitor Pamplona
96fa6f39b0 Fixes ime padding issues when using physical keyboards on the message screens. 2024-09-03 17:28:07 -04:00
Vitor Pamplona
b6bb214532 Fixes text field recompositions because of new keyboard actions 2024-09-03 15:55:52 -04:00
Vitor Pamplona
ee160b76a8 Updates zoomable and kotlin serialization 2024-09-03 15:54:54 -04:00
Vitor Pamplona
2fd9d6610a Normalizes cache directories in the Application class 2024-09-03 15:31:16 -04:00
David Kaspar
272f99be17 added logging 2024-09-03 20:44:39 +02:00
David Kaspar
b8246d7cd4 fixing type 2024-09-03 19:23:47 +02:00
David Kaspar
981d93f2fc making MediaCompressor configurable 2024-09-03 19:18:10 +02:00
Vitor Pamplona
1166fe92e9 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-09-03 11:45:27 -04:00
Vitor Pamplona
b700d4e9bf Fixes missing Private Home/Outbox relay list after loading from backup 2024-09-03 11:43:17 -04:00
Vitor Pamplona
0b41d09fda Merge pull request #1050 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-02 16:00:29 -04:00
Crowdin Bot
61c145a68f New Crowdin translations by GitHub Action 2024-09-02 19:29:46 +00:00
Vitor Pamplona
4103342f99 Updates to AGP 8.6.0 2024-09-02 15:24:39 -04:00
Vitor Pamplona
e48ed607ff Fixes #1049 2024-09-02 14:56:24 -04:00
Vitor Pamplona
d5a98db67c v0.90.6 2024-09-02 10:05:07 -04:00
Vitor Pamplona
72412b9d03 Merge 2024-09-02 10:04:38 -04:00
Vitor Pamplona
b5b90c80e9 Revert "v0.90.6"
This reverts commit 2ca5186aef.
2024-09-02 10:03:15 -04:00
Vitor Pamplona
c1077f689d Merge pull request #1046 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-02 10:02:32 -04:00
Crowdin Bot
8b26a84564 New Crowdin translations by GitHub Action 2024-09-02 14:00:35 +00:00
Vitor Pamplona
2ca5186aef v0.90.6 2024-09-02 10:00:28 -04:00
Vitor Pamplona
064e211154 Merge pull request #1045 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-02 09:59:23 -04:00
Vitor Pamplona
2e8ab35f05 Merge pull request #1042 from greenart7c3/clickable_url
Long press to copy relay url
2024-09-02 09:59:14 -04:00
Crowdin Bot
df429b976f New Crowdin translations by GitHub Action 2024-09-02 13:59:11 +00:00
Vitor Pamplona
d40995c338 Merge pull request #1039 from davotoula/1038-Profile-Lightning-payment-is-100x-too-large
millisats were incorrectly multiplied by 1000
2024-09-02 09:57:45 -04:00
greenart7c3
bba7c257da long press to copy relay url in the relay icons and relay row 2024-09-02 09:52:39 -03:00
greenart7c3
a03e02bfeb Add a button to take a picture from camera 2024-09-02 08:42:46 -03:00
David Kaspar
a4a753e7b6 Rename amount to amountInMillisats to give visual clue to calling classes that millisats should be used 2024-09-02 12:26:26 +02:00
greenart7c3
53acbd8606 Long press to copy relay url 2024-09-02 07:15:59 -03:00
Vitor Pamplona
f89c1ff391 v0.90.5 2024-09-01 15:07:07 -04:00
Vitor Pamplona
471ee21749 Merge pull request #1041 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-09-01 12:38:26 -04:00
Crowdin Bot
24f7e043af New Crowdin translations by GitHub Action 2024-09-01 16:37:46 +00:00
Vitor Pamplona
34e82dab8b Merge pull request #1040 from davotoula/1037-tor-setting-reset-to-off-after-switching-away
1037 tor setting reset to off after switching away
2024-09-01 12:36:36 -04:00
David Kaspar
9fa1b8c541 Close "needsPassword.value" if statement earlier to make Orbot checkbox visible again 2024-09-01 17:09:03 +02:00
David Kaspar
1e61162f73 change the logic for saving of proxy state 2024-09-01 17:05:20 +02:00
David Kaspar
941266365e millisats were incorrectly multiplied by 1000 2024-08-31 19:24:12 +01:00
Vitor Pamplona
b1f1466e6b v0.90.4 2024-08-30 18:43:34 -04:00
Vitor Pamplona
55d53dbc4f Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-08-30 18:42:50 -04:00
Vitor Pamplona
aeaddf722b - Fixes caching bug of NIP-96 servers
- Allow NIP-96 setups with relative URLs
- Displays error messages if the server has sent in the body
- Adds a test case for both
2024-08-30 18:42:41 -04:00
Vitor Pamplona
b733fbce35 Merge pull request #1036 from Dawn11111111/patch-1
Typo Fix on Lnaddress TextField
2024-08-30 12:05:00 -04:00
Dawn
93e9e23730 Typo Fix on Lnaddress TextField
Removed 'i' from lightining :)
2024-08-30 09:45:13 -06:00
Vitor Pamplona
388ccdbe75 Speeds up the filter for NWC zap payments. 2024-08-29 12:32:34 -04:00
Vitor Pamplona
255f464046 Basic code for dynamic limits 2024-08-29 10:29:46 -04:00
Vitor Pamplona
8be74649ce Protects against empty nip04 content 2024-08-28 17:59:59 -04:00
Vitor Pamplona
b5709f9527 Adds basic support for NIP-46 events. 2024-08-28 17:39:25 -04:00
Vitor Pamplona
7d9efcd1d9 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-08-28 16:07:47 -04:00
Vitor Pamplona
d44f5dad18 Merge pull request #1035 from greenart7c3/main
Show relay ping with the relay icon
2024-08-28 16:06:50 -04:00
greenart7c3
06f37ab81d Fix relay icons when using complete ui 2024-08-28 16:20:55 -03:00
Vitor Pamplona
cb4a73bb9c Enables decryption by nip04 and nip44 on NostrWalletConnect objects, NIP-51 lists and NIP-04 messages 2024-08-28 15:20:25 -04:00
greenart7c3
efde14a348 Show relay ping with the relay icon 2024-08-28 16:17:08 -03:00
Vitor Pamplona
0f86e3d8fb Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-08-28 09:20:48 -04:00
Vitor Pamplona
1407850e81 Fixes push registration with empty token ids 2024-08-28 09:20:40 -04:00
Vitor Pamplona
d9a87f6e7c Merge pull request #1034 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-08-28 08:33:37 -04:00
Crowdin Bot
5e0a49f225 New Crowdin translations by GitHub Action 2024-08-28 12:31:37 +00:00
Vitor Pamplona
3ebaf2bf1e Fixes ZapTheDevs card not disappearing after the donation. 2024-08-28 08:29:53 -04:00
Vitor Pamplona
9ef0ceed9d Merge pull request #1033 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-08-27 17:49:17 -04:00
Crowdin Bot
caa3760fd3 New Crowdin translations by GitHub Action 2024-08-27 21:46:25 +00:00
Vitor Pamplona
0b2a9e67c0 v0.90.3 2024-08-27 17:44:44 -04:00
Vitor Pamplona
931081c5e7 Exposes decryption crashing because it is used by Notification Services to check which account can decrypt a GiftWrap. 2024-08-27 17:43:12 -04:00
Vitor Pamplona
f7237b5666 Improves logs on new Notifications 2024-08-27 17:42:18 -04:00
Vitor Pamplona
d851637ea2 Fixes byte to string decoder for UnifiedPush 2024-08-27 17:41:56 -04:00
Vitor Pamplona
2d39b4edfe Only register for endpoints if it has changed from the one in memory 2024-08-27 17:41:37 -04:00
Vitor Pamplona
5001c5bef8 There is no need to extend onReceive 2024-08-27 17:40:53 -04:00
Vitor Pamplona
6ac1db9fc8 correctly passes the endpoint to remove it 2024-08-27 17:40:35 -04:00
Vitor Pamplona
52f33d79e0 Correctly registering the distributor at startup 2024-08-27 17:38:14 -04:00
Vitor Pamplona
1a9d91cdc0 Fixes correct saving of UnifiedPush endpoints 2024-08-27 17:37:53 -04:00
Vitor Pamplona
2f444e6ec5 Moves ChatMessage components to the chatroom package 2024-08-27 16:03:15 -04:00
Vitor Pamplona
4665c488d5 Adds a small border between the author and the message of a chat bubble 2024-08-27 15:57:56 -04:00
Vitor Pamplona
42ab826d02 v0.90.2 2024-08-27 15:01:50 -04:00
Vitor Pamplona
80a3f7424b fixes conversation tab 2024-08-27 14:52:22 -04:00
Vitor Pamplona
1bd3e347b3 Updates media 3 dependencies. 2024-08-27 14:51:30 -04:00
Vitor Pamplona
a332126e71 Quick fix for to not show error messages on Zap the Devs 2024-08-27 14:33:57 -04:00
Vitor Pamplona
d97abe6af9 v0.90.0 2024-08-27 13:48:36 -04:00
Vitor Pamplona
62d341bd8a Publishing new user's events 2024-08-27 11:49:43 -04:00
Vitor Pamplona
a95d2e903e Merge branch 'main' of https://github.com/vitorpamplona/amethyst
# Conflicts:
#	amethyst/src/main/java/com/vitorpamplona/amethyst/ui/qrcode/QrCodeDrawer.kt
2024-08-27 11:04:36 -04:00
Vitor Pamplona
2b5e62aaf7 - Improves rendering of the QR Code elements
- Makes the QR bigger
- Moves QR Code to rounder corners
- Moves QR Screen to use the arrow icon instead of the close button
2024-08-27 11:04:13 -04:00
Vitor Pamplona
1c3e82913f Merge pull request #1031 from greenart7c3/main
Use white background for qrcodes
2024-08-27 11:02:33 -04:00
Vitor Pamplona
ceaa20fabf Removes galleries live data 2024-08-27 08:34:25 -04:00
Vitor Pamplona
1bbabb747e Deleting Bundled updates for Account. 2024-08-26 19:12:39 -04:00
Vitor Pamplona
914c0a2926 Making sure scopes are cancelled for accountViewModel notification dot updates. 2024-08-26 19:12:28 -04:00
Vitor Pamplona
4b249156f9 Makes sure the accountViewModel is deleted when the user switches the screen, logs off or kills the activity. 2024-08-26 18:22:34 -04:00
Vitor Pamplona
7b8c7a1a78 Simplifies flow collection for new events. 2024-08-26 18:22:12 -04:00
Vitor Pamplona
66ed26dcea Finishes the migration of the service manager to the Application class 2024-08-26 18:21:53 -04:00
Vitor Pamplona
356740479c Moves to hold the feed itself in a stateflow 2024-08-26 17:48:27 -04:00
Vitor Pamplona
c88dded01b Improves stability of composables 2024-08-26 16:45:07 -04:00
Vitor Pamplona
7c974bc8ef adds a directory for metrics as well 2024-08-26 15:27:04 -04:00
Vitor Pamplona
efbc3e3e78 removes unecessary logs 2024-08-26 14:57:16 -04:00
Vitor Pamplona
fac803e208 Merge pull request #1032 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-08-26 14:56:04 -04:00
Crowdin Bot
484a3d6b32 New Crowdin translations by GitHub Action 2024-08-26 18:44:35 +00:00
Vitor Pamplona
4e3b6d0299 - Adds a sync Signer to facilitate library
- Separates Account actions from Account state in two objects
- Changes Startup procedures to start with Account state and not the full account object
- Moves scope for flows in Account from an Application-wide scope to ViewModel scope
- Removes all LiveData objects from Account in favor of flows from the state object
- Migrates settings saving logic to flows
- Migrates PushNotification services to work without Account and only Account Settings.
- Migrates the spam filter from LiveData to Flows
- Adds Default lists for NIP-65 inbox and outbox relays
- Adds Default lists for Search relays
- Adds local backup for UserMetadata objects
- Adds local backup for Mute lists
- Adds local backup for NIP-65 relays
- Adds local backup for DM Relays
- Adds local backup for private home relays
- Rewrites state flows initializers to avoid inconsistent startups
2024-08-26 14:42:55 -04:00
Vitor Pamplona
f3161ada8d Solves crash when opening the Relay screen with empty urls as relays. 2024-08-26 11:13:10 -04:00
greenart7c3
5c9b84476b Use white background for qrcodes 2024-08-26 07:21:19 -03:00
Vitor Pamplona
24ea0cabda Updates benchmark, composeBOM and firebaseBOM to the latest versions 2024-08-23 08:35:44 -04:00
Vitor Pamplona
8b617fbd60 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-08-22 17:27:04 -04:00
Vitor Pamplona
34149e6ce2 Merge pull request #1030 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-08-22 17:13:16 -04:00
Vitor Pamplona
315a662c10 Improve horizontal padding of the chat messages 2024-08-22 17:12:46 -04:00
Crowdin Bot
c373843e0f New Crowdin translations by GitHub Action 2024-08-22 21:03:22 +00:00
Vitor Pamplona
448ea796ef Improves caching of encrypted DMs:
- Migrates caching of decrypted value outside of the Event class
- Removes encrypted parts of NIP-17 from the cache
- Removes old NIP-04 messages from the cache
- Avoids deleting new NIP-17 plain text chats from memory
2024-08-22 17:01:37 -04:00
Vitor Pamplona
71b111ce8b Fixes the download of 1000s of NIP-65 relay lists because some relays consider empty lists as null and return everything. 2024-08-22 12:24:45 -04:00
Vitor Pamplona
ae686671ba Minimizing the number of filters for group chat metadata 2024-08-22 09:55:28 -04:00
Vitor Pamplona
6c45bb1ca1 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-08-21 20:32:06 -04:00
Vitor Pamplona
a05ad6e686 Adds support for NIP-35 torrents and their comments 2024-08-21 20:31:59 -04:00
Vitor Pamplona
485f7becd4 Merge pull request #1029 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-08-21 19:18:29 -04:00
Vitor Pamplona
83f1e523ea Creates links to njump when events can't be found on Amethyst 2024-08-21 17:05:14 -04:00
Vitor Pamplona
a8a3c94115 clear flows before removing notes from the local cache 2024-08-21 16:32:11 -04:00
Vitor Pamplona
4d21857adf moves the processing of nip19 links to the default thread 2024-08-21 16:31:57 -04:00
Crowdin Bot
0e7f41efe8 New Crowdin translations by GitHub Action 2024-08-21 20:09:17 +00:00
Vitor Pamplona
8d9bf60dba Merge pull request #1028 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-08-21 16:08:51 -04:00
Vitor Pamplona
7c67924914 fixes imports 2024-08-21 16:07:42 -04:00
Crowdin Bot
7626839037 New Crowdin translations by GitHub Action 2024-08-21 19:59:14 +00:00
Vitor Pamplona
23825ceed5 Avoids bottom nav recompositions 2024-08-21 15:57:45 -04:00
Vitor Pamplona
8d8016e01b Simplifies nav bar selected calculations 2024-08-21 15:51:01 -04:00
Vitor Pamplona
6668e5a178 Moves accountViewModelMock to a more appropriate file 2024-08-21 15:14:28 -04:00
Vitor Pamplona
7d6bef9576 Moves heavy computations away from IO 2024-08-21 15:00:13 -04:00
Vitor Pamplona
1aea7fbd03 Avoids remembering edit lists that will never exist. 2024-08-21 14:58:01 -04:00
Vitor Pamplona
ef96d296f8 avoids double update to the viewmodel 2024-08-21 14:53:35 -04:00
Vitor Pamplona
d4da58e14a Improves logs when the UserMetadata cannot be parsed 2024-08-21 14:38:17 -04:00
Vitor Pamplona
f646866192 moves markasread from io to default 2024-08-21 09:20:43 -04:00
Vitor Pamplona
e0849b12e7 Merge pull request #1027 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-08-21 07:55:58 -04:00
Crowdin Bot
1271343582 New Crowdin translations by GitHub Action 2024-08-21 11:52:51 +00:00
Vitor Pamplona
d61d14ea75 Merge pull request #1026 from davotoula/chage-twitter-to-x
Change twitter proof to use x.com
2024-08-21 07:51:04 -04:00
David Kaspar
668d604aa9 use original twitter colour in x.xml because I can't get the theme switching working 2024-08-21 11:56:45 +01:00
Vitor Pamplona
6df2c3a0cf improving speed of chatlist rendering 2024-08-20 15:23:15 -04:00
Vitor Pamplona
b0c33808e6 Adds support for MOD reports 2024-08-20 15:07:28 -04:00
Vitor Pamplona
7bd3e0beab Improved padding and spacing for chat messages 2024-08-20 13:05:44 -04:00
Vitor Pamplona
3a70cfb9e2 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-08-20 09:14:56 -04:00
Vitor Pamplona
17c758f8f8 Displays PoW of commitment if present. 2024-08-20 09:14:47 -04:00
Vitor Pamplona
7cb03b939f Merge pull request #1022 from KotlinGeekDev/fix-relay-set
Fix relay set event.
2024-08-20 08:57:34 -04:00
KotlinGeekDev
481ef91cb1 Change relay set kind to be NIP-51 consistent. 2024-08-20 12:13:42 +01:00
Vitor Pamplona
1183aa8d11 Changes fdroid push registration to re-register even if the saved distributor was already selected. 2024-08-19 17:58:50 -04:00
Vitor Pamplona
4023261400 Merge pull request #1020 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-08-19 12:07:35 -04:00
Crowdin Bot
f1433504e9 New Crowdin translations by GitHub Action 2024-08-19 16:00:50 +00:00
Vitor Pamplona
989cbb35d3 Disabling landscape rotation on full screen due to portrait videos. 2024-08-19 11:58:50 -04:00
Vitor Pamplona
9262b90096 Merge pull request #1019 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-08-19 11:40:22 -04:00
Crowdin Bot
ab3b7685cf New Crowdin translations by GitHub Action 2024-08-19 15:40:02 +00:00
Vitor Pamplona
40865ac97d Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-08-19 11:36:39 -04:00
Vitor Pamplona
ded67964b0 Merge pull request #1018 from KotlinGeekDev/fullscreen-video-behavior
Change tap to fullscreen video behavior for livestreams.
2024-08-19 11:34:47 -04:00
Vitor Pamplona
e991707ddf updates runner 2024-08-19 11:32:04 -04:00
KotlinGeekDev
1b429475aa Remove the manual testing/debugging code. Remove the LocalConfiguration API in favour of DeviceUtils.isLandscapeMetric. 2024-08-17 18:51:07 +01:00
KotlinGeekDev
9613afb7ea Fix ZoomableImageDialog. isFoldableOrLarge already takes into account the orientation. 2024-08-17 17:07:43 +01:00
KotlinGeekDev
26a12f2dbe Remove the external config method and use the built-in Compose API.
Add some documentation.
2024-08-17 17:03:07 +01:00
KotlinGeekDev
23da02f932 Merge remote-tracking branch 'origin/fullscreen-video-behavior' into fullscreen-video-behavior 2024-08-17 15:19:47 +01:00
KotlinGeekDev
59ff9007a7 Move DeviceUtils closer to call-site. Copy code from Material3-Adaptive library(to avoid experimental annotation propagation everywhere).
Implement windowIsLarge to take care of device type handling(sort-of). Add some funky debug methods to make sure windowIsLarge works.
2024-08-17 14:18:48 +00:00
KotlinGeekDev
0f817dbf00 Put device in landscape mode when fullscreen button is pressed. 2024-08-17 14:18:48 +00:00
KotlinGeekDev
7ab6322886 Introduce DeviceUtils, and add functions for changing orientation, and checking for Landscape mode. 2024-08-17 14:18:48 +00:00
KotlinGeekDev
223c0c1263 Initial implementation for auto-fullscreen on rotation to landscape mode. 2024-08-17 14:18:48 +00:00
KotlinGeekDev
d3a639a2ee Consistent naming and behavior for the video player controls. 2024-08-17 14:18:48 +00:00
KotlinGeekDev
2fb1cbe11f Move DeviceUtils closer to call-site. Copy code from Material3-Adaptive library(to avoid experimental annotation propagation everywhere).
Implement windowIsLarge to take care of device type handling(sort-of). Add some funky debug methods to make sure windowIsLarge works.
2024-08-17 15:14:24 +01:00
Vitor Pamplona
29c5b45764 Moves the default zap type to a state flow and avoids passing on to the screen when using the default value. 2024-08-16 17:45:53 -04:00
Vitor Pamplona
ec83ad9d20 Removing unecessary livedata objects for translation services 2024-08-16 17:10:02 -04:00
Vitor Pamplona
239f973e89 Moves lastread routes to mutableStateFlow 2024-08-16 16:42:00 -04:00
Vitor Pamplona
6c81fbbcf9 Fixes crash when the relay url of a user is duplicated. 2024-08-16 16:00:03 -04:00
Vitor Pamplona
75e45f37b2 Migrating livedata to flow for contact list updates of the user. 2024-08-16 15:59:43 -04:00
Vitor Pamplona
0bff3462b1 Migrates the pubkeyHex from keypair to the signer. 2024-08-16 15:58:23 -04:00
Vitor Pamplona
990db68a4d Fixes spacing of short quotes 2024-08-16 13:12:05 -04:00
Vitor Pamplona
4343c744db Displaying stacks in error messages if they are present 2024-08-16 11:14:34 -04:00
Vitor Pamplona
5cb6f97178 linting cleanup 2024-08-16 10:48:30 -04:00
KotlinGeekDev
a8efc9d348 Put device in landscape mode when fullscreen button is pressed. 2024-08-16 14:53:40 +01:00
Vitor Pamplona
e0b667fd2d Fixes order for the notification feed after refactoring 2024-08-16 09:41:38 -04:00
Vitor Pamplona
a8ad2437fe refactors the Watch feed to scroll to the top 2024-08-16 09:39:15 -04:00
KotlinGeekDev
83018e621e Introduce DeviceUtils, and add functions for changing orientation, and checking for Landscape mode. 2024-08-16 14:19:55 +01:00
Vitor Pamplona
68b15ba483 Refactors old user zap object. 2024-08-15 17:08:15 -04:00
Vitor Pamplona
7513036d47 Refactors sorting of Notifications 2024-08-15 16:16:36 -04:00
Vitor Pamplona
c82c594926 Fixes slow down when the last message on chat is a base64 image. 2024-08-15 16:02:28 -04:00
Vitor Pamplona
bd18d4b4b2 Adjusts Outbox filter as soon as a new NIP-65 relay list shows up 2024-08-15 15:17:41 -04:00
Vitor Pamplona
2f5b99a1c7 Merge pull request #1016 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-08-15 15:06:50 -04:00
Crowdin Bot
1be6e0ec0f New Crowdin translations by GitHub Action 2024-08-15 18:58:39 +00:00
Vitor Pamplona
f43c0e5cf5 Moves error messages from uploading procedures to the full error dialog instead of just a toast. 2024-08-15 14:55:25 -04:00
Vitor Pamplona
d6d8719c8d Fixes the centralization of the "and more" part of relay recommendations 2024-08-14 18:50:26 -04:00
Vitor Pamplona
7478899388 Fixes miscaching flows of the relay lists from follows. 2024-08-14 18:03:25 -04:00
Vitor Pamplona
6b193894bd Fixes miscache of hashtag following button 2024-08-14 17:16:02 -04:00
Vitor Pamplona
69f5371ab8 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-08-14 17:15:36 -04:00
Vitor Pamplona
526e3db3c1 Adds more information to when error messages are not available in the relay stats. 2024-08-14 15:50:05 -04:00
Vitor Pamplona
3c9e8854eb Merge pull request #1015 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-08-14 15:14:42 -04:00
Crowdin Bot
7ee0aa47a9 New Crowdin translations by GitHub Action 2024-08-14 19:07:04 +00:00
Vitor Pamplona
5fbf0462fa No need to check for the MainThread in every updateFeedWith 2024-08-14 15:04:51 -04:00
Vitor Pamplona
eda5bc50e6 Adds a destroy method to FollowList state for consistency 2024-08-14 10:45:57 -04:00
David Kaspar
d6d26d466b clean up code in MetadataEvent.kt
update x drawable
2024-08-14 08:11:28 +01:00
Vitor Pamplona
6acd3ca091 Moves follow list states to the AccountViewModel 2024-08-13 19:35:04 -04:00
Vitor Pamplona
c64d179f7f Migrates Notification Summary to the new state model 2024-08-13 18:56:53 -04:00
Vitor Pamplona
32bc8fe667 Fixes f-droid flavor after refactoring 2024-08-13 18:35:31 -04:00
Vitor Pamplona
0a8c792d53 Moves the notification screen to the new state model instead of viewModels 2024-08-13 18:32:20 -04:00
Vitor Pamplona
c32dc61ea1 Refactoring Moving feed status from ViewModel to State objects 2024-08-13 17:32:15 -04:00
Vitor Pamplona
3af2cb52cc adds a prune for giftwrapped messages 2024-08-13 15:11:15 -04:00
Vitor Pamplona
ddb1d7ff82 Adds context to highlight events 2024-08-13 15:08:32 -04:00
KotlinGeekDev
fd0523085d Initial implementation for auto-fullscreen on rotation to landscape mode. 2024-08-13 10:42:49 +01:00
Vitor Pamplona
1f9fbb0c86 Revers letter spacing in inline code on Markdow 2024-08-12 15:58:17 -04:00
Vitor Pamplona
5b95a1c177 Improved logs when clearing the cache for DMs 2024-08-12 15:55:25 -04:00
Vitor Pamplona
2e144ebdf8 Adds previews to test markdown rendering 2024-08-12 15:55:01 -04:00
Vitor Pamplona
ac5f550ff3 Fixes heading sizes on markdown 2024-08-12 15:54:20 -04:00
Vitor Pamplona
9af123b709 Improves the look of inlinde code in markdown 2024-08-12 15:53:45 -04:00
Vitor Pamplona
75efd2b372 Improves badge display 2024-08-12 11:18:22 -04:00
Vitor Pamplona
2cface9ac9 Inverts spam logs 2024-08-12 11:11:23 -04:00
Vitor Pamplona
58491a97ac Merge pull request #1012 from greenart7c3/main
show only 3 users in the recommended relays section
2024-08-12 09:07:21 -04:00
greenart7c3
7a86d78c50 show only 3 users in the recommended relays section 2024-08-12 09:05:08 -03:00
David Kaspar
97a00ff83c First pass updating Twitter verification to X 2024-08-12 11:07:48 +02:00
Vitor Pamplona
4c6842faf4 v0.89.10 2024-08-09 18:47:48 -04:00
Vitor Pamplona
fad8b9df0f Improved filter for notifications 2024-08-09 18:47:38 -04:00
Vitor Pamplona
cc52681635 Moves service manager to the Application class 2024-08-09 18:14:09 -04:00
Vitor Pamplona
939c8e95b0 Adds protections against filters with empty arrays because some relays consider that null as opposed to empty. 2024-08-09 18:13:19 -04:00
Vitor Pamplona
312501e527 AGP to 8.5.2 2024-08-09 15:25:52 -04:00
Vitor Pamplona
89638ff261 Deletes all events in maximum chunks of 200 elements to avoid the 65KB stringified JSON limit of many relays. 2024-08-09 14:35:00 -04:00
Vitor Pamplona
27d2e2309a Fixes the clickable regions to open additional relay info on the relay list dialog. 2024-08-09 13:44:44 -04:00
Vitor Pamplona
7eaa553ebe Allows users to select and copy the notice from the relay on the relay list dialog 2024-08-09 13:43:53 -04:00
KotlinGeekDev
8adddd0bdb Consistent naming and behavior for the video player controls. 2024-08-09 15:26:42 +01:00
Vitor Pamplona
d8f084f886 Merge pull request #1009 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-08-08 18:37:10 -04:00
Crowdin Bot
5c5a23dfbb New Crowdin translations by GitHub Action 2024-08-08 22:30:34 +00:00
Vitor Pamplona
282d4614c0 Adds zap amount cache for the memory space calculations 2024-08-08 18:19:48 -04:00
Vitor Pamplona
8ed78ea38f Marks username as deprecated 2024-08-08 18:18:54 -04:00
Vitor Pamplona
2e7b7c5c00 improves wording on the name of relays 2024-08-08 14:35:45 -04:00
Vitor Pamplona
68cad97819 Reducing the amount of CPU memory used for images to the default. 2024-08-08 11:51:35 -04:00
Vitor Pamplona
02f7b54661 Updates translate dependencies 2024-08-08 08:31:38 -04:00
Vitor Pamplona
e887232132 v0.89.9 2024-08-07 18:39:02 -04:00
Vitor Pamplona
7bcf4e3750 Removes logs from previous commit 2024-08-07 18:34:38 -04:00
Vitor Pamplona
ed0676a5f5 Fixes the order of bookmarks (keeps the order of the event, instead of the created at) 2024-08-07 18:24:35 -04:00
Vitor Pamplona
f731c654b0 Improves the async rendering of Base64 content 2024-08-07 18:24:14 -04:00
Vitor Pamplona
b026bffe4a Moves discovery and video lists to Outbox when Follows or relay lists are selected 2024-08-07 16:39:24 -04:00
Vitor Pamplona
a1aaec0b7d Adds support for selecting authors based on their Outbox relays when searching for notes authored by them 2024-08-07 15:46:27 -04:00
Vitor Pamplona
6f59097ac0 Aligns default note comparator to NIP-01's created at descending and then by id ascending 2024-08-07 15:44:35 -04:00
Vitor Pamplona
263df0c895 Renames PerRelayFilter to SincePerRelay
Creates PerRelay interface to allow other types of filters
2024-08-07 15:44:03 -04:00
Vitor Pamplona
1ca5713494 Merge pull request #1008 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-08-07 12:57:34 -04:00
Crowdin Bot
b706c4e871 New Crowdin translations by GitHub Action 2024-08-07 16:04:54 +00:00
Vitor Pamplona
e8574c10bb Keep them public to allow testing in these particular functions 2024-08-07 12:02:48 -04:00
Vitor Pamplona
7cb87ea9c5 Refactors to use native contains instead of custom lambdas on Ammolite's Filter 2024-08-07 11:58:00 -04:00
Vitor Pamplona
07e5132943 Refactors Ammolite Filters to be regular ones and creates a PerRelayFilter for the use on Amethyst. 2024-08-07 11:40:01 -04:00
Vitor Pamplona
2b1e3cfc93 Renames the MinimumRelayList to RecommendationProcessor 2024-08-07 11:39:14 -04:00
Vitor Pamplona
c17e1f0e1f removes logs from previous commit 2024-08-06 17:14:22 -04:00
Vitor Pamplona
e88d1d0d00 Adds haptic feedback to draft deletion swipe 2024-08-06 17:13:06 -04:00
Vitor Pamplona
5fdff97cf8 Moves the ContactList cache lists to AccountViewModel, where it can be disposed more efficiently. 2024-08-06 15:36:04 -04:00
Vitor Pamplona
e5328d7975 Improves the accuracy of the Event memory counter. 2024-08-06 15:35:14 -04:00
Vitor Pamplona
71b45b96fb Adds event factory performance test 2024-08-06 11:04:30 -04:00
Vitor Pamplona
dee28f3aa8 Merge pull request #1006 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-08-05 17:26:13 -04:00
Crowdin Bot
3a118bb939 New Crowdin translations by GitHub Action 2024-08-05 20:59:07 +00:00
Vitor Pamplona
971c92b27a Adds extension possibility to Quartz's event factory 2024-08-05 16:57:21 -04:00
Vitor Pamplona
4c70065843 Moves DataSource dispatcher from IO to Default 2024-08-05 16:02:35 -04:00
Vitor Pamplona
eab69337ff Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-08-05 16:02:19 -04:00
Vitor Pamplona
ab772eb65e Makes stringRes Stable for compose 2024-08-05 15:48:06 -04:00
Vitor Pamplona
7a6720a7ab Merge pull request #1005 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-08-05 15:31:47 -04:00
Crowdin Bot
0f3dc18f7a New Crowdin translations by GitHub Action 2024-08-05 19:16:01 +00:00
Vitor Pamplona
84df86f4b6 Removes mutiny NWC button :( 2024-08-05 15:13:35 -04:00
Vitor Pamplona
a0289a0cb4 Moves Relay viewModels to Default thread 2024-08-05 15:08:08 -04:00
Vitor Pamplona
3c034ca8af v0.89.8 2024-08-02 16:34:51 -04:00
Vitor Pamplona
0c8c3003aa Merge pull request #1004 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-08-02 13:37:05 -04:00
Crowdin Bot
919dabfefa New Crowdin translations by GitHub Action 2024-08-02 16:39:19 +00:00
Vitor Pamplona
fd06193e93 Notifies relay failures after marking them as closed. 2024-08-02 12:36:54 -04:00
Vitor Pamplona
b02fa43628 Print relay writes on benchmark as well. 2024-08-02 12:35:52 -04:00
Vitor Pamplona
7fdf38d17b Normalizes logs for the DataSources 2024-08-02 12:35:25 -04:00
Vitor Pamplona
63e036a9bb Minimizes relay updates when rotating status events for each user. 2024-08-02 12:32:44 -04:00
Vitor Pamplona
fc98442f8b Adds support for CashuB tokens using CBOR 2024-07-31 17:36:48 -04:00
Vitor Pamplona
3bbb780d2b Simplifies the drawing of gallery entires without e tags. 2024-07-31 16:02:18 -04:00
Vitor Pamplona
42ceb0c404 Fixes test case for ImageUploaders 2024-07-31 15:59:07 -04:00
Vitor Pamplona
046bd7a0e9 Merge pull request #1003 from greenart7c3/main
Add delete all drafts button
2024-07-31 14:58:26 -04:00
Vitor Pamplona
0af0f745bf Fixes the need for main thread note loading for galleries 2024-07-31 14:57:44 -04:00
Vitor Pamplona
b24999d78c Basic refactoring to minimize the need for user-space params in the VideoView 2024-07-31 14:43:10 -04:00
Vitor Pamplona
d1278a4477 Better rendering for live streams that are planned but already finished. 2024-07-31 14:16:44 -04:00
greenart7c3
609ccaa635 Add delete all drafts button 2024-07-31 13:51:02 -03:00
Vitor Pamplona
4bae04ad31 Merge pull request #1001 from believethehype/better_gallery_view
Gallery: use FileHeader Info for rendering / faster loading
2024-07-31 10:41:19 -04:00
Believethehype
8bca729edd Merge remote-tracking branch 'upstream/main' into better_gallery_view 2024-07-31 16:36:25 +02:00
Vitor Pamplona
2b2f04f724 Adds the callbackUri to the display uncited hashtags so that it can reuse the previously parsed post. 2024-07-31 10:21:13 -04:00
Vitor Pamplona
231af1d3d8 Fixes #993 2024-07-31 10:17:19 -04:00
Believethehype
d1b44c0ac0 remove print 2024-07-31 12:59:23 +02:00
Believethehype
f06c3f7376 massive speed up of rendering the gallery 2024-07-31 12:55:02 +02:00
Believethehype
b8e10b040d cleanup 2024-07-31 12:02:39 +02:00
Believethehype
1a4396dbe3 removes unneded variable 2024-07-31 11:51:44 +02:00
Believethehype
856eb0da05 create GalleryFeed earlier 2024-07-31 11:40:59 +02:00
Believethehype
ceaeb8e0b9 use GalleryContentView instead of 2024-07-31 11:24:05 +02:00
Vitor Pamplona
b29ccd9746 Refactors the lambda used for content resolvers. 2024-07-30 18:16:28 -04:00
Vitor Pamplona
f82364939f Adds icons in SVG to the docs 2024-07-30 18:16:06 -04:00
Vitor Pamplona
286583bba2 fixing the need for a new coroutine startup 2024-07-30 13:50:08 -04:00
Vitor Pamplona
bc8e5aa458 Merge pull request #997 from VASHvic/fix-clipboard-copy-edited-notes
Fix copying to clipboard edited notes
2024-07-30 13:47:49 -04:00
Vitor Pamplona
b393fb042f Merge pull request #999 from believethehype/nutrendering
Show mint in cashu token rendering
2024-07-30 13:47:14 -04:00
Vitor Pamplona
0258c5aac2 Releasing Flows if not subscribed anymore. 2024-07-30 13:22:48 -04:00
Vitor Pamplona
a03a11c4cc Updates depedencies 2024-07-30 13:17:53 -04:00
Vitor Pamplona
3896bbab34 Merge pull request #1000 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-07-30 09:17:19 -04:00
Crowdin Bot
5459f31000 New Crowdin translations by GitHub Action 2024-07-29 23:24:58 +00:00
Vitor Pamplona
143c3a1444 Testing that both 02 and 03 compressed keys are valid Nostr keys and can encrypt and decrypt to each other. 2024-07-29 19:23:22 -04:00
Believethehype
bfbcf11fa3 Update CashuRedeem.kt 2024-07-29 20:42:17 +02:00
VASH
25823b1f39 Fix copying to clipboard edited notes 2024-07-27 13:05:20 +02:00
Believethehype
cb02955ac6 fix order of Share ImageAction 2024-07-24 07:49:44 +02:00
Vitor Pamplona
b440661e0d Adds the highlight to the base URL so that when the user opens the link, it highlights on the page. 2024-07-23 12:56:53 -04:00
Vitor Pamplona
38ba456a22 Signs for just one auth event to register with the push notification service instead of the dozens of events, one per relay. 2024-07-23 10:15:36 -04:00
Vitor Pamplona
bca941e045 enables crossfading between images 2024-07-23 08:47:20 -04:00
Vitor Pamplona
dbaadb4595 v0.89.7 2024-07-22 18:10:15 -04:00
Vitor Pamplona
231ca44e1c Avoids recomposition of the entire line when changing status. 2024-07-22 18:07:44 -04:00
Vitor Pamplona
ca00c87a6e Prints memory use in descending order by size 2024-07-22 16:59:58 -04:00
Vitor Pamplona
2a28111583 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-07-22 14:27:23 -04:00
Vitor Pamplona
4def80c914 updates the EOSE of users even if no user is found in the relay. 2024-07-22 14:27:10 -04:00
Vitor Pamplona
916ece1edb Merge pull request #992 from greenart7c3/main
Remove focus from status text field when closing the drawer
2024-07-22 14:00:24 -04:00
Vitor Pamplona
3c1f57fac0 Sorts keys before making the filter. 2024-07-22 13:57:31 -04:00
greenart7c3
e166c36731 Remove focus from status text field when closing the drawer 2024-07-22 14:45:39 -03:00
Vitor Pamplona
a636f4a786 updates coil and jackson libs 2024-07-22 11:31:57 -04:00
Vitor Pamplona
bb127506c7 Merge pull request #985 from believethehype/main
Store additional File Metadata in Gallery Entries
2024-07-22 08:10:26 -04:00
Vitor Pamplona
92c704d227 Merge pull request #986 from greenart7c3/main
Add sendAndWaitForResponse to Client.kt
2024-07-22 08:10:11 -04:00
greenart7c3
e764ebbcb2 if the relay just connected send the event 2024-07-22 07:49:54 -03:00
greenart7c3
68fb34a8ad Merge branch 'main' into main 2024-07-22 07:36:43 -03:00
greenart7c3
02683ba829 Merge remote-tracking branch 'origin/main' 2024-07-22 07:34:36 -03:00
greenart7c3
754a1b3a87 change the log of onRelayStateChange 2024-07-22 07:33:21 -03:00
Vitor Pamplona
4b58da7be7 Merge pull request #991 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-07-21 15:22:31 -04:00
Crowdin Bot
1ac9c850e4 New Crowdin translations by GitHub Action 2024-07-21 18:32:48 +00:00
Vitor Pamplona
3cc4dc1414 Merge pull request #990 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-07-21 14:31:54 -04:00
Vitor Pamplona
62ae43e863 v0.89.6 2024-07-21 14:31:17 -04:00
Crowdin Bot
8149a93f2f New Crowdin translations by GitHub Action 2024-07-21 18:31:01 +00:00
Vitor Pamplona
5a60c3a595 Fixes stringResource cache 2024-07-21 14:29:05 -04:00
Vitor Pamplona
2ef2f0d1a5 adds the key to avoid applying to a separate navcontroller 2024-07-21 11:32:08 -04:00
Vitor Pamplona
52fef33662 run faster animations 2024-07-21 11:18:56 -04:00
Vitor Pamplona
a5c6f86b35 v0.89.5 2024-07-20 16:27:27 -04:00
Vitor Pamplona
b80008d695 Adds more memory stat dumping for production apps 2024-07-20 16:27:19 -04:00
Vitor Pamplona
fa06aefbf1 increases disk cache to 1GB and adds a memory cache policy. 2024-07-20 15:32:34 -04:00
Vitor Pamplona
ab9ede1e26 Merge pull request #987 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-07-20 15:08:00 -04:00
Crowdin Bot
479b1ab20a New Crowdin translations by GitHub Action 2024-07-20 19:04:48 +00:00
Vitor Pamplona
8ed3f84cb7 Fixes screen rendering below the 3-button navigation 2024-07-20 15:02:57 -04:00
Vitor Pamplona
c128e43fe5 v0.89.4 2024-07-19 17:10:22 -04:00
Vitor Pamplona
f9ddf76686 action bar fix 2024-07-19 17:09:56 -04:00
Vitor Pamplona
b6cb839fe7 v0.89.3 2024-07-19 16:44:30 -04:00
Vitor Pamplona
2b6a48f391 Fixes issue with super large follow lists. 2024-07-19 16:40:46 -04:00
Vitor Pamplona
d1da863d3c Making sure an empty relay list uses the default list from Amethyst 2024-07-19 16:14:14 -04:00
greenart7c3
99b7a8005a Merge branch 'main' into main 2024-07-19 14:13:36 -03:00
greenart7c3
3f3367258f return true if at least one relay replied with success 2024-07-19 13:29:09 -03:00
Vitor Pamplona
15ab955a7d Fixes alt of NIP-96 server lists 2024-07-19 11:55:46 -04:00
greenart7c3
5cf8b5aa12 change proguard to see if now the client.listener works 2024-07-19 12:49:04 -03:00
greenart7c3
eba6d03b53 check if listeners work now 2024-07-19 12:17:26 -03:00
greenart7c3
de85239046 check if listeners work now 2024-07-19 11:56:30 -03:00
Vitor Pamplona
9176151971 Fixes auth infinite loop with nostr.wine 2024-07-19 10:45:06 -04:00
greenart7c3
cbd8acbd01 check eose too 2024-07-19 11:14:31 -03:00
greenart7c3
19c9bfa819 Merge remote-tracking branch 'origin/main' 2024-07-19 11:14:18 -03:00
greenart7c3
80c369a6ae change default timeout to 15 seconds 2024-07-19 10:56:35 -03:00
greenart7c3
d0190c87a2 add more logs, add optional listener, fix await call 2024-07-19 10:56:35 -03:00
greenart7c3
62a2cba18b fix lint 2024-07-19 10:56:35 -03:00
greenart7c3
59b3ff1b94 Added sendAndWaitForResponse to Client.kt 2024-07-19 10:56:35 -03:00
greenart7c3
35423e1bb6 change default timeout to 15 seconds 2024-07-19 10:52:36 -03:00
greenart7c3
e125690000 add more logs, add optional listener, fix await call 2024-07-19 10:50:59 -03:00
Vitor Pamplona
eba5ecfd91 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-07-19 09:47:04 -04:00
Vitor Pamplona
3e43a75acd Fixes the keyboard overriding parts of the screen 2024-07-19 09:46:58 -04:00
greenart7c3
04bf9c07ac fix lint 2024-07-19 08:05:04 -03:00
greenart7c3
ac58f99560 Added sendAndWaitForResponse to Client.kt 2024-07-19 07:58:12 -03:00
Believethehype
df328ff139 Store additional File Metadata in Gallery Entries 2024-07-18 17:53:37 +02:00
Vitor Pamplona
60ba7786a0 Merge pull request #984 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-07-18 10:54:01 -04:00
Crowdin Bot
1773ad5a88 New Crowdin translations by GitHub Action 2024-07-18 14:30:23 +00:00
Vitor Pamplona
26faa2bc69 Migrating to edge to edge in preparation for Android 15 2024-07-18 10:28:19 -04:00
Vitor Pamplona
75c7d40f4e v0.89.2 2024-07-17 19:34:56 -04:00
Vitor Pamplona
aa4a3fe9af Doesn't show people lists that have 0 people in it. 2024-07-17 19:33:47 -04:00
Vitor Pamplona
a32f907d6c Fixes incorrectly marking EOSEs for addressables 2024-07-17 19:26:46 -04:00
Vitor Pamplona
d30e613b17 Fixes TopNav people lists not loading 2024-07-17 17:24:06 -04:00
Vitor Pamplona
0477f390c2 Merge pull request #983 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-07-17 16:54:43 -04:00
Crowdin Bot
15e5e2834a New Crowdin translations by GitHub Action 2024-07-17 20:39:46 +00:00
Vitor Pamplona
b1399d1c13 Separates init and restart from observables. 2024-07-17 16:35:48 -04:00
Vitor Pamplona
45446b4125 Fixes bug on not updating observablesByKindAndAuthor 2024-07-17 16:35:03 -04:00
Vitor Pamplona
094d7e71e2 Merge pull request #982 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-07-17 09:16:29 -04:00
Crowdin Bot
75423eaaab New Crowdin translations by GitHub Action 2024-07-17 13:13:57 +00:00
Vitor Pamplona
5e42fa5346 Adds additional logs for the size of observables in the Local Cache 2024-07-17 09:09:38 -04:00
Vitor Pamplona
bc6d5060cb Moves frame dropping logs from 20ms to 33ms give than many videos make the UI run at 30fps 2024-07-17 09:09:19 -04:00
Vitor Pamplona
e578327c5b Fixes the inability to click on the relay tab on User Profiles 2024-07-17 09:08:41 -04:00
Vitor Pamplona
ce839ed6d9 v0.89.1 2024-07-16 19:23:37 -04:00
Vitor Pamplona
197484dc1b Removes unnecessary id that was causing crashes. 2024-07-16 19:23:26 -04:00
Vitor Pamplona
60e8ae7b9a v0.89.0 2024-07-16 18:14:04 -04:00
Vitor Pamplona
64ae32d005 Logs when the main looper calls an amethyst handler 2024-07-16 14:54:58 -04:00
Vitor Pamplona
87b8e18f1c Improves logging message for dropped frames 2024-07-16 11:47:41 -04:00
Vitor Pamplona
47a9a6cc4e no message 2024-07-16 09:49:30 -04:00
Vitor Pamplona
1a313a9f78 Adds performance monitors for framedrops in benchmark mode 2024-07-16 09:42:17 -04:00
Vitor Pamplona
3554350ac1 Merge pull request #980 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-07-16 09:10:47 -04:00
Crowdin Bot
e2e912c81f New Crowdin translations by GitHub Action 2024-07-16 12:48:38 +00:00
Vitor Pamplona
fa71161996 Corrects the name of the live data on Local Cache. 2024-07-16 08:42:05 -04:00
Vitor Pamplona
8de4d461d4 Reduces interruptions to the main thread 2024-07-16 08:41:48 -04:00
Vitor Pamplona
f1e3f6a592 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-07-15 18:16:43 -04:00
Vitor Pamplona
234ef679c8 updates mockk 2024-07-15 18:16:32 -04:00
Vitor Pamplona
072000254f Merge pull request #979 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-07-15 18:08:57 -04:00
Crowdin Bot
34321af07a New Crowdin translations by GitHub Action 2024-07-15 21:57:29 +00:00
Vitor Pamplona
7da559a0c9 Fixes tests 2024-07-15 17:55:46 -04:00
Vitor Pamplona
0564a7e1f1 Adds dynamic relay pool recommendations to the relay list. 2024-07-15 17:34:08 -04:00
Vitor Pamplona
347b16ee8b Fixes the post button disappeering when the Relay Settings top label is too large 2024-07-15 15:34:08 -04:00
Vitor Pamplona
edb834db38 Fixes a bug on clicking the user profile but loading the wrong one 2024-07-15 15:32:59 -04:00
Vitor Pamplona
97d0cf56a7 Merge pull request #978 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-07-12 14:00:38 -04:00
Crowdin Bot
ad83d362da New Crowdin translations by GitHub Action 2024-07-12 17:58:49 +00:00
Vitor Pamplona
f15f6df2ae avoids processing anything else than src for spotless linting 2024-07-12 13:55:45 -04:00
Vitor Pamplona
567a86c8a4 Moving compiler to 12GB of ram. 2024-07-12 09:56:46 -04:00
Vitor Pamplona
16c82ed69c Updates firebase dependencies 2024-07-12 08:55:27 -04:00
Vitor Pamplona
a543ee54dc Moves AGP to 8.5.1 2024-07-11 18:27:04 -04:00
Vitor Pamplona
128831109a Merge pull request #977 from believethehype/gallery_alternative_version
GalleryEntryEvent: add relay hint to etag
2024-07-11 12:05:19 -04:00
Vitor Pamplona
9641940bd9 Updates relays that are sending old versions of replaceables or events that have been already deleted. 2024-07-11 11:36:59 -04:00
Vitor Pamplona
ad449ba239 Activates the top nav list building when deletion events are received as well 2024-07-11 11:34:40 -04:00
Vitor Pamplona
31e2fcdc21 Request updates from relays when showing the People Lists in the top bar. 2024-07-11 11:33:31 -04:00
Vitor Pamplona
e28b385038 Removes overloading ambiguity 2024-07-11 10:26:59 -04:00
Vitor Pamplona
8d9ecb2054 Merge pull request #960 from greenart7c3/base64
Convert base64 text to images/gifs
2024-07-11 10:26:15 -04:00
greenart7c3
c57c190344 Merge branch 'main' into base64 2024-07-11 10:42:16 -03:00
Believethehype
7dd319eb25 remove print 2024-07-11 10:40:39 +02:00
Believethehype
b4a059c742 Merge branch 'gallery_alternative_version' of https://github.com/believethehype/amethyst into gallery_alternative_version 2024-07-11 10:08:28 +02:00
Believethehype
43d140175c Merge remote-tracking branch 'upstream/main' into gallery_alternative_version 2024-07-11 08:19:29 +02:00
Vitor Pamplona
1a70a02b44 Fixes scoping issues with flattenMerge 2024-07-10 16:04:39 -04:00
believethehype
a476298c07 Merge branch 'main' into gallery_alternative_version 2024-07-10 21:58:29 +02:00
Believethehype
a0a7f28304 GalleryEntryEvent: add relay hint to etag 2024-07-10 21:53:25 +02:00
Vitor Pamplona
17109e7406 Merge pull request #973 from believethehype/gallery_alternative_version
Profile Gallery
2024-07-10 13:37:14 -04:00
believethehype
c50343cd04 Merge branch 'main' into gallery_alternative_version 2024-07-10 19:35:30 +02:00
Vitor Pamplona
8feac270f4 Removes unnecessary logs. 2024-07-09 18:00:25 -04:00
Vitor Pamplona
c7061066e9 Adds an outbox cache to the Relay class in order to resend events after authentication. 2024-07-09 17:30:16 -04:00
Vitor Pamplona
217870244b No need for material dependencies anymore. 2024-07-09 11:10:34 -04:00
Vitor Pamplona
6fd2282818 increasing memory for kotlin build 2024-07-09 10:55:02 -04:00
Vitor Pamplona
b360c3292f removes unnecessary minification for benchmark's debug flavor 2024-07-09 10:45:51 -04:00
Vitor Pamplona
2a9e1bb08c solves build slowdown on spotless dependencies. 2024-07-09 10:42:50 -04:00
Vitor Pamplona
aa4e6c051e formatting 2024-07-09 10:42:29 -04:00
Vitor Pamplona
f6b947430a Removes the bugfix for reproducible builds since it has been fixed. 2024-07-09 10:42:22 -04:00
Vitor Pamplona
4521317779 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-07-09 09:30:07 -04:00
Vitor Pamplona
25ba353488 Merge pull request #974 from KotlinGeekDev/fix-poll-options-behavior
Fix poll options behavior
2024-07-09 09:29:27 -04:00
Vitor Pamplona
2074b34ec3 Trying maxMetaspaceSize to see if Github Actions can build it. 2024-07-08 13:55:27 -04:00
Vitor Pamplona
f63731c9b6 Merge pull request #976 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-07-08 13:50:13 -04:00
Crowdin Bot
fc057f2b29 New Crowdin translations by GitHub Action 2024-07-08 17:34:57 +00:00
Vitor Pamplona
af4dfbf965 Making sure posts have content to appear in the feed. 2024-07-08 13:33:16 -04:00
Vitor Pamplona
63c5098558 Pausing discovery top nav list watcher. 2024-07-08 13:33:01 -04:00
Believethehype
dcad12f836 load older notes in feed 2024-07-07 22:01:16 +02:00
KotlinGeekDev
08e84b056e Some cleanup. 2024-07-07 00:06:44 +01:00
KotlinGeekDev
f489deb808 Implement custom element removal with reordering. Works nicely, from observation. 2024-07-06 20:57:06 +01:00
Believethehype
511a7030b8 use alternative gallery using 1163 events instead of 10011 lists.
(This might still need some tuning but works in general)
2024-07-06 00:11:35 +02:00
Believethehype
06a1862d17 add relay info 2024-07-05 13:35:36 +02:00
greenart7c3
b730b8c6f6 Fix linter 2024-07-05 06:56:04 -03:00
greenart7c3
21a45844df Merge branch 'main' into base64 2024-07-05 06:35:52 -03:00
greenart7c3
2480b43778 Decode in the io thread 2024-07-05 06:31:58 -03:00
Believethehype
ad6dcfc030 use url tag, add relay hint 2024-07-05 08:29:49 +02:00
Believethehype
c81324843c move to G Tag for Gallery entries 2024-07-04 20:41:14 +02:00
Believethehype
a55da5f62e linting 2024-07-03 23:28:15 +02:00
Believethehype
9b26bdac5c move GalleryUrl to GalleryListEvent, merge recent changes 2024-07-03 23:11:59 +02:00
Believethehype
4bda6fa0cc Merge remote-tracking branch 'upstream/main' into gallery 2024-07-03 23:03:13 +02:00
Vitor Pamplona
1eaa22fe51 increasing gradle's memory to see if CI passes. 2024-07-03 14:37:59 -04:00
Vitor Pamplona
8e212bbb55 changing JVM of actions to zulu to see if java/kotlin compilation errors improve. 2024-07-03 14:16:16 -04:00
Vitor Pamplona
fdf0b69e5d Lint formatting 2024-07-03 13:49:57 -04:00
Vitor Pamplona
4b5ab8eb35 Removes unnecessary dependencies for ammolite 2024-07-03 13:49:43 -04:00
Vitor Pamplona
349d6cfc22 Migrates sdk requirements to the version catalog. 2024-07-03 13:49:18 -04:00
Vitor Pamplona
33b8267de7 Fixes linting 3 2024-07-03 11:35:39 -04:00
Vitor Pamplona
713bd59435 Fixes Linting 2 2024-07-03 11:33:38 -04:00
Vitor Pamplona
8c34394d86 Fixes linting problems 2024-07-03 11:21:22 -04:00
Vitor Pamplona
6e1de6fd26 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-07-03 11:06:10 -04:00
Vitor Pamplona
8d88efd27b Migrating Lint to 1.3.1 2024-07-03 11:06:02 -04:00
Vitor Pamplona
6aeaeea5d1 Merge pull request #970 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-07-03 11:03:30 -04:00
Crowdin Bot
3153296161 New Crowdin translations by GitHub Action 2024-07-03 15:02:50 +00:00
Vitor Pamplona
692f7c4270 Upgrades to Kotlin 2.0.0 2024-07-03 11:00:45 -04:00
believethehype
cc8d73e119 Merge branch 'main' into gallery 2024-07-03 13:35:30 +02:00
Vitor Pamplona
27c2c71879 Merge pull request #967 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-07-02 17:33:10 -04:00
Crowdin Bot
464beccd95 New Crowdin translations by GitHub Action 2024-07-02 21:32:31 +00:00
Vitor Pamplona
7519fc2f10 Adds Malware Report type 2024-07-02 17:30:03 -04:00
Vitor Pamplona
01816b0389 Adds a check to make sure the NIP-96 uploader is a url before adding to the list.
Solves NPE on the model if they are not urls
2024-07-02 17:29:16 -04:00
Believethehype
cc8e432336 make sure only owner of images get delete dialog in Gallery 2024-07-02 11:42:10 +02:00
Believethehype
d1ed73f78b Gallery: get rid of dtag, 2024-07-02 11:36:26 +02:00
Believethehype
7a76bf2ae5 remove unneeded dtag from 10011 2024-07-02 11:31:06 +02:00
KotlinGeekDev
6efb970794 Use keys of map entries, as they are more reliable(from testing). Extract pollViewModel.pollOptions into a separate variable. 2024-07-02 09:51:34 +01:00
believethehype
a0a8010305 Merge branch 'main' into gallery 2024-07-02 08:50:44 +02:00
Vitor Pamplona
9ed1dbac72 Updates lifecycle to 2.8.3 2024-07-01 17:13:37 -04:00
Vitor Pamplona
c7280cf1be Observes and shows only the user's selected NIP96 servers for uploading options 2024-07-01 17:12:01 -04:00
Believethehype
0ed87db3b3 moved to gallery tag 2024-07-01 22:45:50 +02:00
Vitor Pamplona
20bc814211 Fixes tag. From "relay" to "server" on kind 10096 2024-07-01 16:40:37 -04:00
believethehype
0c92c57b79 Merge branch 'main' into gallery 2024-07-01 22:40:31 +02:00
Vitor Pamplona
e61404146b Requests a NIP-96 compliant server 2024-07-01 16:34:44 -04:00
Vitor Pamplona
07dbcbf5c3 Adds FileServer events to be downloaded for the active account. 2024-07-01 16:34:28 -04:00
Believethehype
8421dbfa4c use r tag instead of g (reserved for geotag) 2024-07-01 22:06:40 +02:00
Believethehype
d2af7ba407 Merge remote-tracking branch 'upstream/main' into gallery 2024-07-01 22:03:30 +02:00
Vitor Pamplona
d0718fcda7 Merge pull request #953 from KotlinGeekDev/custom-media-servers
Support for custom media upload servers
2024-07-01 15:30:49 -04:00
believethehype
2372acbb2a Merge branch 'main' into gallery 2024-07-01 20:59:13 +02:00
greenart7c3
9374798f92 Revert "Use Base64Requester"
This reverts commit 2bd05d80b0.
2024-07-01 15:48:22 -03:00
greenart7c3
e96015bcbc Parse base64 inside the wordIdentifier function 2024-07-01 15:07:18 -03:00
greenart7c3
2bd05d80b0 Use Base64Requester 2024-07-01 14:50:19 -03:00
greenart7c3
3a7b503890 Show base64 images 2024-07-01 14:25:29 -03:00
Vitor Pamplona
d20707f4df Removes unused params 2024-07-01 12:51:45 -04:00
Vitor Pamplona
b01d308d65 Merge pull request #966 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-07-01 12:43:21 -04:00
Crowdin Bot
e0f5c730a6 New Crowdin translations by GitHub Action 2024-07-01 15:50:05 +00:00
Vitor Pamplona
b9086de336 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-07-01 11:48:06 -04:00
Vitor Pamplona
405d3d24a0 Removes decryption for DVM responses since it doesn't encrypt statuses 2024-07-01 11:47:58 -04:00
Vitor Pamplona
236de87574 Fixes unable to see original post when clicking on the edit button 2024-07-01 11:47:30 -04:00
Believethehype
b12d14d6f5 add a shortpreview to not mess up grid layout on load 2024-07-01 09:19:16 +02:00
Believethehype
1d42440e26 add gallery entry to dictionary 2024-07-01 08:21:00 +02:00
Believethehype
ec065a6595 readd regular video elements for regular playing, use isVideo funtion to check 2024-06-30 23:14:37 +02:00
Believethehype
0d83511509 Merge branch 'gallery' of https://github.com/believethehype/amethyst into gallery 2024-06-30 22:29:32 +02:00
Believethehype
9fe08f6c45 allow videos in the gallery 2024-06-30 22:29:11 +02:00
Believethehype
557f2e1a83 Merge remote-tracking branch 'upstream/main' into gallery 2024-06-30 18:02:43 +02:00
Vitor Pamplona
efced4670b Merge pull request #961 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-30 10:03:49 -04:00
Crowdin Bot
c89596809a New Crowdin translations by GitHub Action 2024-06-30 14:00:05 +00:00
Vitor Pamplona
7ccc93f17f Merge pull request #959 from greenart7c3/main
add onerror when websocket is null
2024-06-30 09:58:40 -04:00
greenart7c3
f50e511da0 Cut the text when the content length is greater than SHORT_TEXT_LENGTH and theres no spaces and new lines 2024-06-30 10:20:14 -03:00
greenart7c3
3d497ccf4d add onerror when websocket is null 2024-06-30 09:35:17 -03:00
Vitor Pamplona
5c21e219fe v0.88.8 2024-06-29 19:57:53 -04:00
Vitor Pamplona
58796ac31d - Adds created_at as the time of the notification instead of the receiving time
- Displays Zap Push notifications even if the zapped note is not available yet.
2024-06-29 18:51:41 -04:00
Vitor Pamplona
66317f5593 Better nip44 error messages for notifications 2024-06-29 16:20:49 -04:00
KotlinGeekDev
2f276cb155 Remove TODO, since a basic UI is already implemented. 2024-06-29 21:13:17 +01:00
Vitor Pamplona
b1b915b405 Merge pull request #958 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-29 15:43:01 -04:00
Crowdin Bot
052f9fa21f New Crowdin translations by GitHub Action 2024-06-29 19:38:24 +00:00
Vitor Pamplona
893b237d6a v0.88.7 2024-06-29 15:36:33 -04:00
Vitor Pamplona
e367f51458 merge 2024-06-29 15:34:16 -04:00
Vitor Pamplona
fa44b74f09 Adds a try/catch when receiving notifications to make sure it gets decrypted by the correct account. 2024-06-29 15:33:39 -04:00
believethehype
bb00616275 Merge branch 'main' into gallery 2024-06-29 15:31:54 +02:00
Believethehype
581d11702c Merge remote-tracking branch 'upstream/main' into gallery 2024-06-29 15:31:20 +02:00
Believethehype
16eb6097ce actually use the image from the 10011 event 2024-06-29 15:08:58 +02:00
Vitor Pamplona
2051a6b2f3 Merge pull request #956 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-29 08:10:25 -04:00
Crowdin Bot
02320548e3 New Crowdin translations by GitHub Action 2024-06-29 12:00:54 +00:00
Vitor Pamplona
44a0b59989 Merge pull request #955 from davotoula/update_translations
Update translations
2024-06-29 07:59:40 -04:00
Vitor Pamplona
3288c35bcd Merge pull request #954 from davotoula/additional-html-entities-for-url-preview
Additional html entities for url preview
2024-06-29 07:59:14 -04:00
David Kaspar
bbe0b86690 Update SE, CZ, DE, PT translations 2024-06-29 08:59:45 +01:00
David Kaspar
afbabfd2d3 Update SE, CZ, DE, PT translations 2024-06-29 08:55:50 +01:00
David Kaspar
d404a09f8e additional html entities 8220, 8230
"8230
2024-06-29 08:30:05 +01:00
David Kaspar
30e9d4b3cd additional html entities x2d, middot 2024-06-29 08:30:05 +01:00
KotlinGeekDev
4238978373 Merge remote-tracking branch 'origin/custom-media-servers' into custom-media-servers 2024-06-29 01:14:20 +01:00
KotlinGeekDev
7f3c7ea69c Remove unnecessary files. 2024-06-29 01:13:16 +01:00
KotlinGeekDev
a4202c96d2 Merge branch 'main' into custom-media-servers 2024-06-29 00:10:08 +00:00
KotlinGeekDev
593f817b6d Try fix(again). 2024-06-29 00:56:08 +01:00
Vitor Pamplona
2230d1467c Fixes kind3 relay lists connecting with Search and Wallet connect types. 2024-06-28 19:39:56 -04:00
KotlinGeekDev
af3a52c75e Try fixing this again. 2024-06-29 00:22:06 +01:00
KotlinGeekDev
f9b1cbc9ba Merge branch 'vitorpamplona:main' into custom-media-servers 2024-06-28 23:13:24 +00:00
Vitor Pamplona
0df37d6694 v0.88.6 2024-06-28 19:03:23 -04:00
KotlinGeekDev
9aa511b398 Refactor: location of files. 2024-06-29 00:02:44 +01:00
KotlinGeekDev
5257b1e1cc Merge branch 'main' into custom-media-servers 2024-06-28 22:50:59 +00:00
Vitor Pamplona
4e9e123666 The AccountDataSource will already authenticate for the ZapPayment Relay. 2024-06-28 18:44:27 -04:00
KotlinGeekDev
e7fec7caab Merge branch 'main' into custom-media-servers
merge main branch
2024-06-28 23:43:46 +01:00
KotlinGeekDev
9a4d829f73 Remove TODO. Make isModified private. 2024-06-28 23:12:04 +01:00
KotlinGeekDev
2423ad6e87 [Squash] Use string resources. Ugly solution to avoid duplicates. 2024-06-28 23:08:08 +01:00
KotlinGeekDev
dc40856bc2 Ugly solution to avoid duplicates. 2024-06-28 23:04:25 +01:00
believethehype
5cbea6999e Merge pull request #2 from believethehype/gallery2
Gallery2
2024-06-28 23:57:32 +02:00
Believethehype
0d18a89177 cleanup 2024-06-28 23:53:40 +02:00
Believethehype
b935f60fcb Merge remote-tracking branch 'upstream/main' into gallery2 2024-06-28 23:40:37 +02:00
Believethehype
45df7713ce remove text preview from images 2024-06-28 23:38:41 +02:00
KotlinGeekDev
b26355097d Refactor renderMediaServerList to use callbacks. Use addServerList. 2024-06-28 22:26:24 +01:00
KotlinGeekDev
feee845d31 Add convenience function for adding default Amethyst list. 2024-06-28 22:19:21 +01:00
KotlinGeekDev
660be862d6 Merge remote-tracking branch 'origin/custom-media-servers' into custom-media-servers 2024-06-28 22:18:05 +01:00
KotlinGeekDev
b5047f213e Move media server list rendering to separate function. Fix padding for rendered items. Rename onDelete to onAddOrDelete() for component reuse. 2024-06-28 22:17:42 +01:00
Vitor Pamplona
1fafb6a503 updates create release script to match new directories 2024-06-28 16:58:45 -04:00
Vitor Pamplona
7c6ec49312 Merge pull request #952 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-28 16:33:38 -04:00
Crowdin Bot
6eb7b45990 New Crowdin translations by GitHub Action 2024-06-28 20:27:40 +00:00
Vitor Pamplona
7c7f704173 v0.88.5 2024-06-28 16:25:44 -04:00
Believethehype
f331398316 gallery is visualised 2024-06-28 21:13:52 +02:00
KotlinGeekDev
6c88029fe3 Mve media server list rendering to separate function. Fix padding for rendered items. Rename onDelete to onAddOrDelete() for component reuse. 2024-06-28 20:01:41 +01:00
KotlinGeekDev
aae7236106 Introduce MediaServerEdit component. 2024-06-28 19:57:57 +01:00
KotlinGeekDev
963a42becf Make first character in derived name uppercase, for ...aesthetics. 2024-06-28 19:56:05 +01:00
Vitor Pamplona
f0044afeab Fixes bug on string resources. 2024-06-28 14:06:08 -04:00
Vitor Pamplona
f9c3ff22e3 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-06-28 13:28:16 -04:00
Vitor Pamplona
347b82ef7f Fixes when the logged in accounts only include the current account. 2024-06-28 13:28:05 -04:00
Believethehype
a42762de53 alternative attempt.. 2024-06-28 19:14:36 +02:00
Vitor Pamplona
27e5d135bc Merge pull request #949 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-28 11:09:07 -04:00
Believethehype
e073e58241 Update GalleryListEvent.kt 2024-06-28 16:51:09 +02:00
Crowdin Bot
a57ba2550c New Crowdin translations by GitHub Action 2024-06-28 14:43:45 +00:00
Vitor Pamplona
a9cbbf66bd Adds uploading error messages for common HTTP status codes. 2024-06-28 10:40:55 -04:00
Believethehype
91caacd36d added first attempt to add user galleries. can read 10011 events and shows profile tab
What works:
- can load existing 10011 lists and show images in profile tab

What doesn't work:
- gallery view is broken
- can't load notes to click images to get to original note
- adding media to gallery crashes amethyst atm
- no functionality to delete media from gallery yet.
2024-06-28 16:01:56 +02:00
Vitor Pamplona
e181296a91 adds auth.nostr1.com as an option 2024-06-27 20:12:56 -04:00
Vitor Pamplona
6a626c9865 Renders relay lists in the feed. 2024-06-27 20:12:04 -04:00
Vitor Pamplona
7095c475c0 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-06-27 19:03:36 -04:00
Vitor Pamplona
c18df3a157 Fixes extra } when rendering hashtags from Markdown 2024-06-27 19:03:29 -04:00
Vitor Pamplona
aee63de507 Merge pull request #948 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-27 17:03:48 -04:00
Crowdin Bot
2f9438d48d New Crowdin translations by GitHub Action 2024-06-27 21:00:06 +00:00
Vitor Pamplona
700974a5ae Updates testing libs 2024-06-27 16:57:57 -04:00
Vitor Pamplona
15b8a8027c Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-06-27 16:51:39 -04:00
Vitor Pamplona
6c0b22f129 Fixes error when trying to decrypt the PrivateOutboxRelayList event for an account that is not currently active. 2024-06-27 16:51:33 -04:00
Vitor Pamplona
4ee3694292 Fixes error when trying to decrypt the PrivateOutboxRelayList event for an account that is not currently active. 2024-06-27 16:49:05 -04:00
Vitor Pamplona
989099c791 Refactors PlaybackService 2024-06-27 16:47:46 -04:00
Vitor Pamplona
a89440cba2 Moves to non-deterministic signatures 2024-06-27 15:28:09 -04:00
Vitor Pamplona
39c9b4d50f Adjusting default zaps for the Zap the Devs button 2024-06-27 12:19:55 -04:00
KotlinGeekDev
0a6d9a7764 Normalize server URL before adding it, Part 2. 2024-06-27 17:17:49 +01:00
Vitor Pamplona
372eaabb50 Swipe to delete drafts. 2024-06-27 12:13:53 -04:00
KotlinGeekDev
409b63b374 Normalize server URL before adding it. 2024-06-27 16:23:27 +01:00
Vitor Pamplona
ca5c0d6ee4 Adds author picture when writing posts and replies. 2024-06-27 10:00:17 -04:00
Vitor Pamplona
faca3615fc Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-06-26 17:06:35 -04:00
Vitor Pamplona
7e31401b86 updates versions 2024-06-26 17:06:30 -04:00
Vitor Pamplona
0fad7b313b Fixing alignment of the close button on Chat's reply preview 2024-06-26 16:20:25 -04:00
Vitor Pamplona
930d7d0fed Merge pull request #947 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-26 15:51:10 -04:00
Crowdin Bot
fb59499a0d New Crowdin translations by GitHub Action 2024-06-26 19:45:14 +00:00
Vitor Pamplona
6e256e465f Merge pull request #946 from greenart7c3/main
check for localhost when adding a new relay
2024-06-26 15:44:00 -04:00
greenart7c3
e358387ba1 check for localhost when adding a new relay 2024-06-26 16:33:24 -03:00
KotlinGeekDev
cd9ba9befe Use divider to separate custom and hardcoded server options. Introduce new padding value. 2024-06-26 16:09:56 +01:00
Vitor Pamplona
d6ab376f2d Fixes position of the hash verification icon on NIP-95 images. 2024-06-25 18:26:11 -04:00
Vitor Pamplona
cc6551b11b Removes old highlight rendering functions 2024-06-25 18:19:43 -04:00
Vitor Pamplona
5e417dd890 Fixes the rendering of highlights when no user is present and includes options to render by e tags 2024-06-25 18:19:14 -04:00
Vitor Pamplona
95694ac355 Merge pull request #944 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-25 14:53:29 -04:00
Crowdin Bot
215fba83cf New Crowdin translations by GitHub Action 2024-06-25 18:50:11 +00:00
Vitor Pamplona
a8a2bda9af rearranges the crypto package into separate nips and reduces the amount of circular dependencies. 2024-06-25 12:13:17 -04:00
Vitor Pamplona
79ace7f18c Renames JsonFilter to just Filter and adds a matching function 2024-06-25 10:06:06 -04:00
Vitor Pamplona
c448e75953 Updates all dependencies 2024-06-25 08:44:32 -04:00
Vitor Pamplona
683af698c6 Adjusts the size of the reply button on chats 2024-06-24 20:42:22 -04:00
Vitor Pamplona
fe19ddb259 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-06-24 19:22:23 -04:00
Vitor Pamplona
4c3c7e7cba Fixes not showing relay icons when sending messages with Amber. 2024-06-24 19:22:15 -04:00
Vitor Pamplona
f5e08e47a8 Merge pull request #942 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-24 19:14:51 -04:00
Crowdin Bot
782df3bcb5 New Crowdin translations by GitHub Action 2024-06-24 23:12:34 +00:00
Vitor Pamplona
1b2f7e21f6 Makes sure to download the updated list of relays when looking at a user. 2024-06-24 18:52:04 -04:00
Vitor Pamplona
4943e1c7ed Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-06-24 18:07:33 -04:00
Vitor Pamplona
0f066d0817 Saves a copy of the NIP65 and NIP17 relay lists locally 2024-06-24 18:06:53 -04:00
Vitor Pamplona
839cadea35 Saves a copy of the NIP65 and NIP17 relay lists locally 2024-06-24 17:56:24 -04:00
Vitor Pamplona
8cef7bcb75 Logging as a Relay error message when the relay does not accept an event. 2024-06-24 17:55:31 -04:00
Vitor Pamplona
62ac05ae81 Merge pull request #941 from vitorpamplona/changes-app-dir-to-amethyst
changes app directory to amethyst
2024-06-24 17:53:11 -04:00
Vitor Pamplona
4609d6e343 changes app directory to amethyst 2024-06-24 14:13:55 -04:00
Vitor Pamplona
e70e8f8437 Merge pull request #940 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-24 13:39:31 -04:00
Crowdin Bot
1b57c5636d New Crowdin translations by GitHub Action 2024-06-24 17:36:59 +00:00
Vitor Pamplona
9065f8eea2 Merge pull request #939 from greenart7c3/new_package_relay
Moves relay classes to a new package
2024-06-24 13:35:41 -04:00
greenart7c3
8c3e87339a remove commented code 2024-06-24 14:03:01 -03:00
greenart7c3
9ee2452430 Fix build 2024-06-24 11:32:03 -03:00
greenart7c3
266dabdd7a fix shared prefs key 2024-06-24 11:24:13 -03:00
greenart7c3
21898482de Fix merge 2024-06-24 11:22:41 -03:00
greenart7c3
c281654e97 Merge branch 'main' into new_package_relay 2024-06-24 11:16:03 -03:00
greenart7c3
c0ee8e2d61 fix proguard rules 2024-06-24 11:10:13 -03:00
greenart7c3
66e4021d7b Move all relay and datasource to ammolite package 2024-06-24 10:52:34 -03:00
greenart7c3
b00781ec32 check if HttpClientManager appears in the jar 2024-06-24 09:19:14 -03:00
greenart7c3
f08a41d7a5 proguard 2024-06-24 08:33:57 -03:00
greenart7c3
6eb0f153fa fix build 2024-06-24 07:36:11 -03:00
greenart7c3
a6bc40515b Move httpclient to another package 2024-06-24 07:13:06 -03:00
KotlinGeekDev
67ef25f538 Merge branch 'vitorpamplona:main' into custom-media-servers 2024-06-22 18:28:55 +00:00
Vitor Pamplona
c37adfc6a2 v0.88.4 2024-06-21 19:53:49 -04:00
Vitor Pamplona
d6764e08fd Bigger reaction panel 2024-06-21 19:53:02 -04:00
Vitor Pamplona
ed80511cb6 v0.88.3 2024-06-21 19:02:10 -04:00
Vitor Pamplona
08da97e36d Updates version of FirebaseBom 2024-06-21 18:39:27 -04:00
Vitor Pamplona
a14ab59e78 Converts LiveData for Content-Sensitivity and Transitive Hidden Users into Flow to avoid locking the main thread while scrolling.
Requests flows on the Default thread.
2024-06-21 18:38:31 -04:00
Vitor Pamplona
f7c60b3745 Making Metered Wifi behave like Mobile for heavy content. 2024-06-21 17:04:00 -04:00
Vitor Pamplona
f8a77d634c Adds a check to see if the receiver has NIP-17 relays setup and if so activates NIP-17 message. 2024-06-21 15:05:41 -04:00
Vitor Pamplona
fdd1bb9810 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-06-21 13:35:25 -04:00
Vitor Pamplona
8a1aefeda7 Adds an option to change reactions from the popup 2024-06-21 13:31:48 -04:00
Vitor Pamplona
64813a4623 Merge pull request #938 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-21 13:25:56 -04:00
Crowdin Bot
e86f0c54f3 New Crowdin translations by GitHub Action 2024-06-21 17:20:26 +00:00
Vitor Pamplona
d2f06f5310 Removing the X to delete reaction in favor of a Selected background 2024-06-21 13:18:48 -04:00
Vitor Pamplona
7a22b3df71 Realigning reactions 2024-06-21 12:51:16 -04:00
Vitor Pamplona
97671c570c Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-06-21 12:49:47 -04:00
Vitor Pamplona
accad0c77a Adds a Share option with NIP-19 nprofile icon on the User Profile screen
Moves to NProfile instead of NPub to cite users.
Adds Npub or NIP-05 to the QR Screen
2024-06-21 12:49:35 -04:00
KotlinGeekDev
a19deb2076 Merge branch 'vitorpamplona:main' into custom-media-servers 2024-06-21 13:55:16 +00:00
KotlinGeekDev
bba7dba17c Introduce MediaServersListView and add it to Drawer. 2024-06-21 14:52:08 +01:00
Vitor Pamplona
985274980a Merge pull request #937 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-21 09:29:05 -04:00
Crowdin Bot
4470d01229 New Crowdin translations by GitHub Action 2024-06-21 13:26:29 +00:00
Vitor Pamplona
35a9c07636 Adds pubkey to the host filter in live events. 2024-06-21 09:24:01 -04:00
Vitor Pamplona
3fa5877840 Fixes formatting 2024-06-20 17:39:20 -04:00
Vitor Pamplona
56bbfe60bb Merge pull request #923 from VASHvic/redesign_emoji_selector
redesign emoji selector
2024-06-20 17:36:23 -04:00
Vitor Pamplona
d2f604960e Merge branch 'main' into redesign_emoji_selector 2024-06-20 17:35:41 -04:00
Vitor Pamplona
76a4236b70 Merge pull request #933 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-20 16:49:07 -04:00
Crowdin Bot
fece7411c9 New Crowdin translations by GitHub Action 2024-06-20 20:32:46 +00:00
Vitor Pamplona
0e1e379c7d v0.88.2 2024-06-20 16:30:33 -04:00
Vitor Pamplona
b39ac214a5 Limits the amount of zaps on the user profile 2024-06-20 16:30:12 -04:00
Vitor Pamplona
9e9e0667cd Reverts old migration of accounts due the fact that some people were still in the old model 2024-06-20 16:29:48 -04:00
Vitor Pamplona
82f99faec8 Fixes name instead of uri 2024-06-20 12:22:07 -04:00
Vitor Pamplona
d07a767fa5 Merge pull request #931 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-20 09:55:47 -04:00
Crowdin Bot
ec19038e5c New Crowdin translations by GitHub Action 2024-06-20 13:50:41 +00:00
Vitor Pamplona
eaa09055fc v0.88.1 2024-06-20 09:48:10 -04:00
Vitor Pamplona
0d956c2f39 Removes the need to exclude byte-buddy due to jackson's earlier version bug. 2024-06-20 09:47:43 -04:00
Vitor Pamplona
3a4e2e9623 Don't use DM kinds to get information about other logged-in accounts 2024-06-20 09:47:11 -04:00
Vitor Pamplona
d33befe1ad Removes account migration and unused keys for shared preferences. 2024-06-20 09:42:10 -04:00
KotlinGeekDev
b6fd067d48 Merge branch 'vitorpamplona:main' into custom-media-servers 2024-06-20 12:46:25 +00:00
Vitor Pamplona
d28f20519b v0.88.0 2024-06-19 16:34:01 -04:00
Vitor Pamplona
239f390e7c Fixes Fdroid tests 2024-06-19 15:43:10 -04:00
Vitor Pamplona
857d16582a Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-06-19 15:40:23 -04:00
Vitor Pamplona
aae47aa2e1 Fixing Options Button 2024-06-19 15:40:14 -04:00
Vitor Pamplona
f115111c49 Centralizes stringResource calls to cache them. 2024-06-19 15:12:07 -04:00
Vitor Pamplona
83058500d6 Merge pull request #930 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-19 13:08:48 -04:00
Crowdin Bot
2cb1e70170 New Crowdin translations by GitHub Action 2024-06-19 16:38:15 +00:00
Vitor Pamplona
73513713eb Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-06-19 12:36:29 -04:00
Vitor Pamplona
7bf5c03637 removing the state needs for rendering text. 2024-06-19 12:36:22 -04:00
Vitor Pamplona
d39d1239f6 Moves uncited hashtag parsing to a thread 2024-06-19 12:36:09 -04:00
Vitor Pamplona
a0271a2982 Moves ClickableBox to it's own file 2024-06-19 12:35:25 -04:00
Vitor Pamplona
2484927c22 Merge pull request #929 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-19 08:54:42 -04:00
Crowdin Bot
bff662b85d New Crowdin translations by GitHub Action 2024-06-19 12:53:07 +00:00
Vitor Pamplona
f293f6c169 Merge pull request #928 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-19 08:52:07 -04:00
Vitor Pamplona
e9456af15c Fixes the inconsistency of button animations in the reaction row 2024-06-19 08:48:41 -04:00
Crowdin Bot
157fad6a84 New Crowdin translations by GitHub Action 2024-06-19 12:48:33 +00:00
Vitor Pamplona
6c137a5174 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-06-19 08:39:09 -04:00
Vitor Pamplona
6550bdefd5 Thinner Zap button 2024-06-18 19:34:43 -04:00
Vitor Pamplona
614e9ff661 Correctly tints the search button 2024-06-18 19:33:22 -04:00
Vitor Pamplona
5da9e430b0 Get's rid of the view count. 2024-06-18 19:33:04 -04:00
Vitor Pamplona
fbd32bf426 Merge pull request #927 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-18 19:07:45 -04:00
Vitor Pamplona
f28d96d303 removes remember from LoadUrlPreview 2024-06-18 19:00:26 -04:00
Vitor Pamplona
442322f708 Removes the alpha channel for the performance placeholder painter 2024-06-18 19:00:10 -04:00
Vitor Pamplona
a463e8889c Adds an outlined Zap icon to match the other icons 2024-06-18 18:59:41 -04:00
Crowdin Bot
224e54cc72 New Crowdin translations by GitHub Action 2024-06-18 22:23:30 +00:00
Vitor Pamplona
a23cbd1a38 Formatting 2024-06-18 18:21:27 -04:00
Vitor Pamplona
548dd9e34f Makes sure the isAcceptable runs on IO thread 2024-06-18 18:20:58 -04:00
Vitor Pamplona
c27f4a62b6 Switches Social Icons to faster SVG versions 2024-06-18 18:15:02 -04:00
Vitor Pamplona
e18945b378 Adds performance mode for older devices. 2024-06-18 09:13:48 -04:00
Vitor Pamplona
08869ac350 removes derived states and some remember functions for performance. 2024-06-18 09:11:32 -04:00
Vitor Pamplona
5d5c3ae3e3 Faster calculation of uncited hashtags. 2024-06-17 17:22:39 -04:00
Vitor Pamplona
0fa6dce42c Fixes giftwrap date mismatch 2024-06-17 16:20:40 -04:00
Vitor Pamplona
aad95595eb Quick Refactoring of the Author UI components. 2024-06-17 14:37:31 -04:00
Vitor Pamplona
24fede3768 Merge pull request #925 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-16 19:43:00 -04:00
Crowdin Bot
a8b6118e2d New Crowdin translations by GitHub Action 2024-06-16 23:37:55 +00:00
Vitor Pamplona
719be8469f Fix test cases 2024-06-16 19:36:41 -04:00
Vitor Pamplona
1496052bba Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-06-15 12:36:12 -04:00
Vitor Pamplona
545df83177 Simple refactoring 2024-06-15 12:34:03 -04:00
Vitor Pamplona
80d506be37 Allows login with NIP-05 address 2024-06-15 12:33:43 -04:00
Vitor Pamplona
ae0ae413e6 Fixes Go Button on new user screen 2024-06-15 12:33:06 -04:00
VASH
43339b8d36 redesign emoji selector 2024-06-15 18:27:05 +02:00
Vitor Pamplona
6a9f9e3f81 Merge pull request #922 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-15 11:36:25 -04:00
Crowdin Bot
010402ebd5 New Crowdin translations by GitHub Action 2024-06-15 15:31:05 +00:00
Vitor Pamplona
c07a0065a1 Upgrades Compose, Lifecycle and Fragments 2024-06-15 11:28:20 -04:00
Vitor Pamplona
704af55636 Merge pull request #921 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-15 09:48:42 -04:00
Crowdin Bot
475e1c6fe0 New Crowdin translations by GitHub Action 2024-06-15 13:47:01 +00:00
Vitor Pamplona
21c397b5e0 Merge pull request #920 from davotoula/915-NIP05-verification-follows-redirects-against-specification
Set redirects to false for httpclient used during nip05
2024-06-15 09:45:49 -04:00
David Kaspar
29a002e451 Set redirects to false for httpclient used during nip05 2024-06-15 09:51:05 +02:00
Vitor Pamplona
035affadb9 Merge pull request #919 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-14 12:32:49 -04:00
Vitor Pamplona
79e3142f2d Merge branch 'main' into l10n_crowdin_translations 2024-06-14 12:32:41 -04:00
Crowdin Bot
bf880983a7 New Crowdin translations by GitHub Action 2024-06-14 16:30:32 +00:00
Vitor Pamplona
115746353e Merge pull request #917 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-14 12:29:22 -04:00
Vitor Pamplona
2fd4521e1d Merge pull request #918 from davotoula/correct_spelling
Correct the spelling of a few translation keywords
2024-06-14 12:29:05 -04:00
Crowdin Bot
3a8a9e296e New Crowdin translations by GitHub Action 2024-06-14 16:01:39 +00:00
Vitor Pamplona
86ebb78823 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-06-14 11:59:24 -04:00
Vitor Pamplona
bda0e37767 Merge pull request #916 from greenart7c3/main
Fix hidden notes when hidden words is empty
2024-06-14 11:59:07 -04:00
David Kaspar
900cc03e4f correct spelling 2024-06-14 17:55:41 +02:00
David Kaspar
013357ae6b correct spelling 2024-06-14 17:51:33 +02:00
David Kaspar
a58a67d404 correct spelling 2024-06-14 17:50:28 +02:00
Vitor Pamplona
2ded31dd55 Improves the speed of RobohashAsync by avoiding remember and base64 state. 2024-06-14 11:42:27 -04:00
greenart7c3
dad455f9a0 Fix hidden notes when hidden words if empty 2024-06-14 12:35:17 -03:00
Vitor Pamplona
8b87f04268 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-06-14 09:34:59 -04:00
Vitor Pamplona
627c8d1663 Moves to AGP 8.5 and Gradle 8.7 2024-06-14 09:34:48 -04:00
Vitor Pamplona
287a64be11 Merge pull request #914 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-14 08:39:45 -04:00
Crowdin Bot
8f24eeaf4a New Crowdin translations by GitHub Action 2024-06-14 12:33:24 +00:00
Vitor Pamplona
39efc2ef9b Adjusting zap calculations 2024-06-14 08:31:06 -04:00
Vitor Pamplona
52a24d5223 Removing unnecessary modifiers and remember calls 2024-06-14 08:22:38 -04:00
Vitor Pamplona
ca8d32b837 Moves chatroom user group away from immutable sets 2024-06-14 08:22:24 -04:00
Vitor Pamplona
f508f45e16 Fixes Url Preview Crop when the image is too small or to big for the preview card. 2024-06-14 08:16:51 -04:00
Vitor Pamplona
d7a22f609a Small optimizations: removing animations, avoiding remembers 2024-06-13 19:08:20 -04:00
Vitor Pamplona
2503cbaeac - Unifies All Badge rendering
- Constraints badge layouts on Notes
- Creates a flow cache to speed up Note relay layout
- Speeds up NoteQuickActionMenus
- Optimizes NIP-11 pings
- Better error messages when NIP-11 fails
2024-06-13 16:50:19 -04:00
Vitor Pamplona
6bc305dbe6 Refactoring 2024-06-13 16:38:48 -04:00
Vitor Pamplona
26cbc0754e Creates a Loading state to avoid requesting NIP-11 documents twice. 2024-06-13 13:31:51 -04:00
KotlinGeekDev
ed5d7335a0 Simplify addServer() and removeServer(). Introduce saveFileServers() for saving changes, and broadcasting them. 2024-06-13 11:08:44 +01:00
KotlinGeekDev
76e3b5abe7 Add rudimentary implementations for addServer() and removeServer(). 2024-06-13 02:19:18 +01:00
Vitor Pamplona
45445c03e5 - Merges Hidden and Reporting flows
- Removes Report Live data
- Refactors Full Bleed design
- Unifies Hidden and Report checks between the Video Feed, the Full Bleed Design and the Card layout.
2024-06-12 16:54:39 -04:00
Vitor Pamplona
0d00f2f80a No need to remember createdAts 2024-06-12 16:49:10 -04:00
Vitor Pamplona
27f437020e Merge pull request #911 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-12 15:10:24 -04:00
Crowdin Bot
2345c45ebf New Crowdin translations by GitHub Action 2024-06-12 19:07:56 +00:00
Vitor Pamplona
42408978c4 - Moves away from persistent collections (slower)
- Adds a hashcode cash for spam and blocked user public keys
- Adds a cache for isHidden
- Moves isHidden composable from LiveData to Flow
2024-06-12 15:05:46 -04:00
Vitor Pamplona
a716d13c69 Slightly faster is content sensitive method 2024-06-12 14:56:51 -04:00
Vitor Pamplona
77393b433e formatting 2024-06-12 12:41:31 -04:00
Vitor Pamplona
a7c06b46a7 Use navigateUp instead of popBackStack to avoid closing the app on double clicks 2024-06-12 12:40:43 -04:00
Vitor Pamplona
1de55bb16f Migrates to AGP 8.4.2 2024-06-12 08:01:54 -04:00
Vitor Pamplona
20520bbce4 Fixes the centered url on videos without active playback 2024-06-11 19:15:02 -04:00
Vitor Pamplona
42e11d239d Fixes the padding of the reaction row on quotes 2024-06-11 18:51:47 -04:00
Vitor Pamplona
957ad1e0db Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-06-11 18:20:35 -04:00
Vitor Pamplona
3123685f88 Tries to solve notification dots active for hidden posts. 2024-06-11 18:20:27 -04:00
Vitor Pamplona
31e8782b1a adds a native map for tags in the Event class to avoid creating sublists before mapping tags 2024-06-11 18:19:52 -04:00
Vitor Pamplona
cafad6a003 Refactoring 2024-06-11 18:19:07 -04:00
Vitor Pamplona
b785e0d505 Removes old Robohash 2024-06-11 18:17:51 -04:00
Vitor Pamplona
226153a359 Merge pull request #910 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-11 15:23:06 -04:00
Crowdin Bot
b70aa54aa3 New Crowdin translations by GitHub Action 2024-06-11 19:07:46 +00:00
Vitor Pamplona
fc96d89a44 Reducing double launch or co-routines 2024-06-11 15:05:57 -04:00
Vitor Pamplona
dd71b931fc Reducing memory recreation by only setting the current subscription as after EOSE 2024-06-11 15:05:38 -04:00
Vitor Pamplona
d6abdf16e0 Increasing the download limit for reactions to event 2024-06-11 15:05:11 -04:00
Vitor Pamplona
66e18e17c5 Adds relays to zap request:
- sender, receiver, author
2024-06-11 13:32:13 -04:00
Vitor Pamplona
7b2da8312d Adds two extra nevent test cases. 2024-06-11 13:31:45 -04:00
KotlinGeekDev
353a30efe4 Introduce MediaServersViewModel. Basic things for now. 2024-06-11 16:46:49 +01:00
Vitor Pamplona
c71c87e946 Better rounding for zaps 2024-06-11 11:30:55 -04:00
Vitor Pamplona
9ca6151313 - Adds the NIP-65 relay to zap split tag instead of kind3 relays.
- Rounds percentages to the 2 decimals.
2024-06-11 11:23:20 -04:00
Vitor Pamplona
b322efc286 Fixes padding of the zap raiser 2024-06-11 11:22:21 -04:00
Vitor Pamplona
b775c1bf74 Avoids showing error message if devs have removed their lnadress on the Zap the Devs card. 2024-06-11 11:22:09 -04:00
Vitor Pamplona
a6b2671b1c Fixes padding of the zap split section on the master note 2024-06-11 11:20:44 -04:00
Vitor Pamplona
abc5d0ea2f Fixes border of the zap card 2024-06-11 10:46:15 -04:00
Vitor Pamplona
3c25d91b98 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-06-11 10:36:52 -04:00
Vitor Pamplona
3d8aace55a Merge pull request #909 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-11 10:36:44 -04:00
Vitor Pamplona
bd6202f8e1 - Adds support for AVIF images
- Removes gray border in image urls that couldn't be loaded.
2024-06-11 10:25:11 -04:00
Crowdin Bot
c1875e1389 New Crowdin translations by GitHub Action 2024-06-11 14:03:00 +00:00
Vitor Pamplona
3a63c1d1ab Fixes alignment of reactions 2024-06-11 10:00:26 -04:00
Vitor Pamplona
609faf245a Reverts save button 2024-06-10 20:01:37 -04:00
Vitor Pamplona
bfd28c4b44 Reverts save button 2024-06-10 20:01:11 -04:00
Vitor Pamplona
70a8488f12 Merge pull request #907 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-10 19:59:47 -04:00
Crowdin Bot
cda6e4722c New Crowdin translations by GitHub Action 2024-06-10 23:54:07 +00:00
Vitor Pamplona
c4ecf85618 Reverting the spotlight on the Save button 2024-06-10 19:51:52 -04:00
Vitor Pamplona
6ed1f9d369 Merge pull request #906 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-10 09:59:32 -04:00
Crowdin Bot
aea765ec54 New Crowdin translations by GitHub Action 2024-06-10 13:52:45 +00:00
Vitor Pamplona
165c3bb852 Fixes not centered Blank Notes 2024-06-10 09:50:37 -04:00
Vitor Pamplona
2e9683491f Fixes scrollable drawer for all screen sizes 2024-06-10 09:50:24 -04:00
Vitor Pamplona
eea8b99622 v0.87.6 2024-06-07 20:16:52 -04:00
Vitor Pamplona
0db6a0d27b Fixes relay drops and difficulty in connecting.
Refactors the use of relay objects to avoid creating full state relay connections only once
2024-06-07 20:13:15 -04:00
Vitor Pamplona
723e575b4b Fixes the LazyColumn for Hashtags on Profile 2024-06-07 19:28:20 -04:00
Vitor Pamplona
b182d409b6 Fixes benchmark tests 2024-06-07 18:50:32 -04:00
Vitor Pamplona
043e37030e Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-06-07 13:46:11 -04:00
Vitor Pamplona
8d730040b8 Improved description for public inbox 2024-06-07 13:46:04 -04:00
Vitor Pamplona
794a300c74 Merge pull request #904 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-07 12:42:58 -04:00
Crowdin Bot
91fd490ab7 New Crowdin translations by GitHub Action 2024-06-07 15:54:44 +00:00
Vitor Pamplona
0e1de03db8 Only updates video position when the video is ready to play 2024-06-07 11:52:39 -04:00
Vitor Pamplona
7906a94ca0 Moves the video release to a thread without damaging ON_PAUSE, ON_RELEASE order. 2024-06-07 11:42:15 -04:00
Vitor Pamplona
6ce019a86a Larger search limits for profiles 2024-06-07 10:37:13 -04:00
Vitor Pamplona
d8939779e8 Improves UI buttons of the Image Dialog 2024-06-07 10:36:56 -04:00
Vitor Pamplona
313d87a58b Removes debug marker 2024-06-06 18:43:11 -04:00
Vitor Pamplona
057e61bfe1 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-06-06 18:39:48 -04:00
Vitor Pamplona
c94c882c3a restructures video and image views to avoid buttons getting on top of one another. 2024-06-06 18:39:39 -04:00
Vitor Pamplona
673f632563 Refactoring 2024-06-06 12:43:59 -04:00
Vitor Pamplona
1a56b2bf68 Log messages when saving to disk. 2024-06-05 18:21:20 -04:00
Vitor Pamplona
2e9964e0e8 Merge pull request #903 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-05 16:37:28 -04:00
Crowdin Bot
b80eb32991 New Crowdin translations by GitHub Action 2024-06-05 20:30:27 +00:00
Vitor Pamplona
ad281c7607 BugFix crashing with old keyboards: Forces transformations to have middle positions before the last cursor position. 2024-06-05 16:28:44 -04:00
Vitor Pamplona
3c1a918b2d Moving attestations local cache to a flow 2024-06-05 13:24:31 -04:00
Vitor Pamplona
53e6677558 Adds Hashtag search and display to Reposted Notes. 2024-06-05 11:58:02 -04:00
Vitor Pamplona
b8deb34544 Avoid using DM relays to get chats 2024-06-05 09:34:03 -04:00
Vitor Pamplona
d9cffa87ef When broadcasting privately, avoids keeping the connection open for other activities. 2024-06-05 08:33:11 -04:00
Vitor Pamplona
ae418f9d45 v0.87.5 2024-06-04 18:46:45 -04:00
Vitor Pamplona
d10b4c6bde - Re-normalizes all relays urls before connecting to reduce duplications
- Normalizes all new relays in the edit screens.
2024-06-04 18:30:01 -04:00
Vitor Pamplona
f1e516662c Adds flare.pub videos to the media tab on Amethyst 2024-06-04 17:12:14 -04:00
Vitor Pamplona
1bf8165641 Improving the detection of image types on the Media Feed. 2024-06-04 16:38:31 -04:00
Vitor Pamplona
807af3b613 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-06-04 16:01:50 -04:00
Vitor Pamplona
e36ec0a0a3 removes extra char on xml 2024-06-04 16:01:37 -04:00
Vitor Pamplona
3172b69271 Merge pull request #902 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-04 15:55:27 -04:00
Crowdin Bot
81ee13bebc New Crowdin translations by GitHub Action 2024-06-04 19:47:45 +00:00
Vitor Pamplona
a6a8138c7f - Performance Improvements: Simplifies intrinsic size calculations for Image Previews and Videos
- Improves rendering of chat messages
- Fixes the jittering from resizing Videos and Images during loading.
- Fixes video cut off when loading
- Fixes blurhash covering videos in landscape
- Fixes landscape video centralization
- Fixes chat using Two Pane layout for landscape and regular for portrait
2024-06-04 15:45:59 -04:00
Vitor Pamplona
16142f61b8 normalization refactoring 2024-06-04 10:54:06 -04:00
Vitor Pamplona
7193228dd2 Fixes size of the incognitoIcon on chat messages 2024-06-03 19:32:46 -04:00
Vitor Pamplona
29b8f6916b v0.87.4 2024-06-03 17:29:43 -04:00
Vitor Pamplona
a6519d57c6 Passes the video note uri so that when the user clicks in the video popup the app brings it back to the playing screen without breaking the video. 2024-06-03 17:26:40 -04:00
Vitor Pamplona
2b2ee5bbfc Avoids using Video Cache for live streams. 2024-06-03 17:18:38 -04:00
Vitor Pamplona
62a6b7b7e0 Fixes video stream position for live streams. 2024-06-03 17:18:17 -04:00
Vitor Pamplona
5e0a1f9de1 Moves SimpleCache creation to the IO thread. 2024-06-03 17:17:26 -04:00
Vitor Pamplona
571b1bc9cf Merge pull request #900 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-03 14:27:47 -04:00
Crowdin Bot
a3e76225e6 New Crowdin translations by GitHub Action 2024-06-03 18:26:14 +00:00
Vitor Pamplona
4388ceb529 v0.87.3 2024-06-03 14:24:28 -04:00
Vitor Pamplona
5d4fa0d732 Adds the incoming relays to the request. 2024-06-03 14:15:12 -04:00
Vitor Pamplona
ed6825de97 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-06-03 14:04:46 -04:00
Vitor Pamplona
10f623b6b3 Forces URLs to be single line. 2024-06-03 14:04:38 -04:00
Vitor Pamplona
467e5c0e4a Fixes bug that every socket is null 2024-06-03 14:04:29 -04:00
Vitor Pamplona
09d2e9593e Adds error messages to relay information dialog 2024-06-03 14:03:58 -04:00
Vitor Pamplona
cd20c0567b Merge pull request #899 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-03 13:27:05 -04:00
Vitor Pamplona
db15f5e2a6 Uses the user to avoid Java removing the variable due to lack of usage. 2024-06-03 13:25:56 -04:00
Crowdin Bot
18d5c7e3f4 New Crowdin translations by GitHub Action 2024-06-03 16:08:05 +00:00
Vitor Pamplona
d42ae7c9f7 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-06-03 12:06:38 -04:00
Vitor Pamplona
2b741b62e8 Merge pull request #898 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-03 12:06:14 -04:00
Vitor Pamplona
4e1c63d36a allows more replies to filter when using DVMs 2024-06-03 12:05:58 -04:00
Vitor Pamplona
95797171d7 Fixes observer of authors 2024-06-03 12:05:46 -04:00
Crowdin Bot
395ef9695e New Crowdin translations by GitHub Action 2024-06-03 15:49:13 +00:00
Vitor Pamplona
ad1c7088c7 Loads the DVM's NIP65 records. 2024-06-03 11:47:39 -04:00
Vitor Pamplona
eda4569b64 Only shows debug relay writes in DEBUG 2024-06-03 11:47:20 -04:00
Vitor Pamplona
fb5f1e738b Adds a user and max result params to the DVM request. 2024-06-03 11:47:00 -04:00
Vitor Pamplona
e3cca6c691 Pulls NIP-65 relays even in the first lookup for the user. 2024-06-03 11:45:57 -04:00
Vitor Pamplona
ce2b8dfa11 Sends the DVM request to the NIP65 Inbox relays. 2024-06-03 11:15:36 -04:00
Vitor Pamplona
b5faf6ffc5 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-06-03 11:15:07 -04:00
Vitor Pamplona
4ee157f27f Merge pull request #897 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-03 11:14:50 -04:00
Vitor Pamplona
ad8c04b79a Loads user's relays on scrolling. 2024-06-03 11:14:33 -04:00
Crowdin Bot
c0e6273954 New Crowdin translations by GitHub Action 2024-06-03 15:04:13 +00:00
Vitor Pamplona
aebade21a6 Don't display zap splits when the post is short. 2024-06-03 11:02:23 -04:00
Vitor Pamplona
bda24c0101 Separates the Account's relay info to the UI component 2024-06-03 11:01:34 -04:00
Vitor Pamplona
3d0b461550 Moves Relay Stats to it's own cache.
Refactors the isLocalRelay function
Removes unnecessary onError methods from the Relay class
Moves byte counts from Int to Long
2024-06-03 10:42:00 -04:00
Vitor Pamplona
5900e6c49f Merge pull request #896 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-03 08:45:33 -04:00
Crowdin Bot
f29fe3ced5 New Crowdin translations by GitHub Action 2024-06-03 12:38:46 +00:00
Vitor Pamplona
bf17cc8f03 Updating Firebase and Androidx JUnit 2024-06-03 08:36:45 -04:00
Vitor Pamplona
a8d10c22d4 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-06-01 16:14:47 -04:00
Vitor Pamplona
5492ebf43f Merge pull request #893 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-01 16:13:05 -04:00
Vitor Pamplona
0c48366d56 v0.80.2 2024-06-01 16:12:49 -04:00
Crowdin Bot
d66a027270 New Crowdin translations by GitHub Action 2024-06-01 19:33:36 +00:00
Vitor Pamplona
f1834af506 Moves the filter for no subscriptions to the DAL 2024-06-01 15:31:43 -04:00
Vitor Pamplona
f26fa71e49 improves the speed of the kind filter for DVMs 2024-06-01 15:20:26 -04:00
Vitor Pamplona
4faee68174 Filters by supported kinds in the DVM view. 2024-06-01 15:16:35 -04:00
Vitor Pamplona
2326e66382 Solves race conditions when connecting to relays. 2024-06-01 15:16:18 -04:00
Vitor Pamplona
bf71365f51 Merge pull request #892 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-01 13:18:30 -04:00
Crowdin Bot
f45e8d491c New Crowdin translations by GitHub Action 2024-06-01 17:17:09 +00:00
Vitor Pamplona
5a476cab32 v0.87.0 2024-06-01 13:15:27 -04:00
Vitor Pamplona
b5b0a19df5 Fixes the disappearance of the notification icon 2024-06-01 13:14:30 -04:00
Vitor Pamplona
85d26dee08 Merge pull request #891 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-06-01 10:58:27 -04:00
Crowdin Bot
476da07d3d New Crowdin translations by GitHub Action 2024-06-01 14:55:45 +00:00
Vitor Pamplona
3b7344e894 v0.87.0 2024-06-01 10:53:39 -04:00
Vitor Pamplona
d307bb0e49 Fixes missing relays certain internal lists 2024-05-31 19:47:40 -04:00
Vitor Pamplona
1bbcb97d54 Fixes read status between others and the logged in user 2024-05-31 16:54:18 -04:00
Vitor Pamplona
3a9637ccb9 Optimizes Blurhash generation 2024-05-31 14:24:55 -04:00
Vitor Pamplona
071da53a6a Waits 500ms before restarting all connections. 2024-05-30 17:11:11 -04:00
Vitor Pamplona
9d190f93bb deactivate write for search relays (they are read only) 2024-05-30 17:10:56 -04:00
Vitor Pamplona
7c65a93896 - Only updates lists if they were changed.
- Refactoring RelayLists
2024-05-30 17:10:38 -04:00
Vitor Pamplona
d9b96d2fd5 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-05-30 16:20:00 -04:00
Vitor Pamplona
3333fdc237 Layout improvements for the relay screen 2024-05-30 16:19:52 -04:00
Vitor Pamplona
e178ff988d Adds NIP-50 requirements to the Search explainer. 2024-05-30 16:19:39 -04:00
Vitor Pamplona
df649445d0 Merge pull request #890 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-05-30 16:02:37 -04:00
Vitor Pamplona
a38346c7d3 Adds private outbox relays to save Draft events. 2024-05-30 16:02:21 -04:00
Crowdin Bot
71da587426 New Crowdin translations by GitHub Action 2024-05-30 19:58:38 +00:00
Vitor Pamplona
6ecb5ecc47 Merge pull request #889 from believethehype/main
show error messages if dvm status returns error
2024-05-30 15:57:23 -04:00
Believethehype
b2a19efcd0 show error messages, if dvm status returns error 2024-05-30 20:12:06 +02:00
Vitor Pamplona
1123586ef6 Uses DM Relay List to activate nip17 messages in chats. 2024-05-30 14:00:20 -04:00
Vitor Pamplona
ab037e61aa adds local relays to the connecting set 2024-05-30 13:51:31 -04:00
Vitor Pamplona
4a43b57f79 Uses NIP-65 preferably for zap requests. 2024-05-30 13:51:14 -04:00
Vitor Pamplona
f81c83326c Relay screen padding adjustments 2024-05-30 13:33:11 -04:00
Vitor Pamplona
fdd1dd1855 Adds a title to the relay settings screen 2024-05-30 12:44:29 -04:00
Vitor Pamplona
9f3d4db9dd Adds Local Relays to the relay list screen, saving locally in the device. 2024-05-30 12:35:24 -04:00
Vitor Pamplona
c23a9f8ad6 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-05-30 11:21:47 -04:00
Vitor Pamplona
36b0c8acb5 Fixing crash when calling localcache on the main thread. 2024-05-30 11:21:39 -04:00
Vitor Pamplona
dc12789166 Merge pull request #888 from KotlinGeekDev/unifiedpush-updates
UnifiedPush library updates
2024-05-30 11:20:38 -04:00
KotlinGeekDev
942b0fa531 Merge branch 'vitorpamplona:main' into unifiedpush-updates 2024-05-30 15:07:48 +00:00
KotlinGeekDev
8ae7f31c3d Refactor getSavedDistributor(). It uses UnifiedPush.getSavedDistributor underneath to preserve pre-API change behaviour. 2024-05-30 16:04:30 +01:00
KotlinGeekDev
bc1bbc2f70 Update to up-connector to v2.3.1. The JVM toolchain and Kotlin downgrade in 2.4.0 may not be good for Amethyst now. Will upgrade when everything has checked out. 2024-05-30 16:01:22 +01:00
Vitor Pamplona
632c78792a Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-05-30 09:55:00 -04:00
Vitor Pamplona
e2a719164f Migrates Kotlin and dependencies to the latest version 2024-05-30 09:48:45 -04:00
Vitor Pamplona
ff94f45d04 Enabling download and creation of NIP-96 file servers. 2024-05-30 09:38:33 -04:00
Vitor Pamplona
7e1b1c7d2c No need for experimental tag anymore. 2024-05-30 09:37:15 -04:00
Vitor Pamplona
f6f9d82665 Merge pull request #887 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-05-30 08:41:51 -04:00
Crowdin Bot
3638059c23 New Crowdin translations by GitHub Action 2024-05-30 12:41:41 +00:00
Vitor Pamplona
a781e733f2 improving the filter for the request id of the cached response. 2024-05-30 08:39:23 -04:00
Vitor Pamplona
56d6376efc Merge pull request #886 from believethehype/main
Check if NIP90 Result exists before relying on Cache
2024-05-30 08:34:59 -04:00
Vitor Pamplona
3ac9d3a4f7 Merge pull request #885 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-05-30 08:33:49 -04:00
Believethehype
521da9a774 check if NIP90 Result list exists before relying on Cache 2024-05-30 14:23:24 +02:00
Crowdin Bot
18ebdaf96d New Crowdin translations by GitHub Action 2024-05-30 10:50:40 +00:00
Vitor Pamplona
19d394a383 Merge pull request #884 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-05-30 06:49:20 -04:00
Crowdin Bot
b198b4c081 New Crowdin translations by GitHub Action 2024-05-30 10:47:55 +00:00
Vitor Pamplona
28bc46f120 Merge pull request #883 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-05-30 06:46:21 -04:00
Crowdin Bot
7a6de4ea49 New Crowdin translations by GitHub Action 2024-05-30 10:33:52 +00:00
Vitor Pamplona
bc108875e6 Merge pull request #882 from davotoula/update_tr
Update SE, CZ, DE, PT translations
2024-05-30 06:32:33 -04:00
David Kaspar
aa38b41c58 Update SE, CZ, DE, PT translations 2024-05-30 10:01:33 +02:00
Vitor Pamplona
a4c26b1fd8 Reducing the use of backgrounds to improve rendering speeds. 2024-05-29 18:53:26 -04:00
Vitor Pamplona
550cfe8bb4 Fixes relay list assembling 2024-05-29 15:58:47 -04:00
Vitor Pamplona
56664afa4e Show missing relays for DMs when the DMRelayList event is empty. 2024-05-29 15:22:19 -04:00
Vitor Pamplona
90c9deecd4 Removes the forced search relay selection and helps users setup their relay list for search. 2024-05-29 15:21:54 -04:00
Vitor Pamplona
add65b094d updates junit 2024-05-29 14:28:07 -04:00
Vitor Pamplona
c7a4161799 Fixing tests 2024-05-29 12:50:46 -04:00
Vitor Pamplona
f6a16e4394 Fixes date format's year 2024-05-29 12:28:22 -04:00
Vitor Pamplona
44a615020d Improves wording of the relay list 2024-05-29 12:28:10 -04:00
Vitor Pamplona
288aafc3a2 Adds support for search relay lists 2024-05-29 12:06:45 -04:00
Vitor Pamplona
aa97c7ee9b Adds NIP-65 relay settings 2024-05-29 10:39:08 -04:00
Vitor Pamplona
51a6eb4974 - Adds a new observer by kind and author
- Uses NIP-17 relays for DMs
- Changes default connection to account from NIP17 relays
- Only sends wraps to the appropriate relays.
2024-05-28 19:13:03 -04:00
Vitor Pamplona
f8dfc06a06 Saves DMs and All Relays on the relay list 2024-05-28 19:11:23 -04:00
Vitor Pamplona
2d4db9fea8 Refactoring on latestbykindandetag 2024-05-28 19:09:53 -04:00
Vitor Pamplona
34b743146e Making sure the relay list has different keys for different sections. 2024-05-28 18:48:41 -04:00
Vitor Pamplona
13eb8b1abc Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-05-28 11:49:20 -04:00
Vitor Pamplona
e98a77b37f Adds DM relays to the relay list. 2024-05-28 11:49:13 -04:00
Vitor Pamplona
6a17a8a871 Refactors GiftWrap caching to delete encrypted text and reload the wrap if necessary.
- Changes host to a host stub to reduce memory use
- Only download GiftWraps form 2 days past the last EOSE
2024-05-28 11:48:20 -04:00
Vitor Pamplona
3ce726bbb7 Merge pull request #881 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-05-28 08:27:01 -04:00
Crowdin Bot
593bf24f5b New Crowdin translations by GitHub Action 2024-05-28 12:22:25 +00:00
Vitor Pamplona
7a857711eb Merge pull request #880 from davotoula/update_tr
Update SE, CZ, DE, PT translations
2024-05-28 08:20:52 -04:00
David Kaspar
420e325d1f Update SE, CZ, DE, PT translations 2024-05-28 09:04:49 +02:00
Vitor Pamplona
610657a9b6 Merge pull request #877 from greenart7c3/main
add signString method
2024-05-27 08:15:34 -04:00
greenart7c3
ea891367e9 add signString method 2024-05-27 07:56:02 -03:00
Vitor Pamplona
0c22e66e8f Overrides pubkey to avoid impersonators on seals. 2024-05-24 19:27:14 -04:00
Vitor Pamplona
cd008d78a0 Improves the debug of the memory use per event kind 2024-05-24 19:26:39 -04:00
Vitor Pamplona
2c2e4a1694 Clears flows 2024-05-24 19:26:13 -04:00
Vitor Pamplona
d7790cd31e Moves the thread formatter and calculator out of Note 2024-05-24 18:11:57 -04:00
Vitor Pamplona
0bb571b52e Fixes position of the edit field after the relay list 2024-05-24 17:42:42 -04:00
Vitor Pamplona
c65a4b8fe7 Merge pull request #876 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-05-24 14:59:55 -04:00
Crowdin Bot
abb0c73c71 New Crowdin translations by GitHub Action 2024-05-24 18:56:33 +00:00
Vitor Pamplona
224bcf97ec Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-05-24 14:54:48 -04:00
Vitor Pamplona
04c449072a Adds support for NIP-06 seed word key derivation (bip32 and bip39) 2024-05-24 14:54:38 -04:00
Vitor Pamplona
b26aba92a1 Merge pull request #875 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-05-24 09:12:25 -04:00
Crowdin Bot
5ce9df9dce New Crowdin translations by GitHub Action 2024-05-24 12:20:21 +00:00
Vitor Pamplona
7426600dc6 deleting orangepill since it might not come back 2024-05-24 08:18:32 -04:00
Vitor Pamplona
9d4a88d26f Clear up some old unstable api tags 2024-05-23 18:18:46 -04:00
Vitor Pamplona
85aaf25561 Remove unnecessary logs 2024-05-23 17:11:18 -04:00
Vitor Pamplona
1cd5845960 Fixes the rendering of replies on wikipages. 2024-05-23 17:09:16 -04:00
Vitor Pamplona
e38f6be20c Refactoring the composables for the relay list screen 2024-05-23 16:40:24 -04:00
Vitor Pamplona
c78c00acd9 Adds method to create the NIP-65 list 2024-05-22 18:23:52 -04:00
Vitor Pamplona
11fa762028 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-05-22 17:46:45 -04:00
Vitor Pamplona
599fddb369 Adds a card to setup the DM relay list if the user doesn't have one. 2024-05-22 17:46:39 -04:00
Vitor Pamplona
76103ac057 Fixes the padding of the x button on the relay list screen 2024-05-22 17:45:55 -04:00
Vitor Pamplona
6538cbd9da Fixes padding of the chat list elements. 2024-05-22 17:45:18 -04:00
Vitor Pamplona
566ca0e390 Moves Relay URL formatter to Quartz 2024-05-22 17:44:18 -04:00
Vitor Pamplona
c5f7ea801d Update README.md
Adding the most recent feature sets
2024-05-22 14:54:21 -04:00
Vitor Pamplona
469e7abd99 Clears imeta tags that might duplicate for the same post. 2024-05-22 13:43:07 -04:00
Vitor Pamplona
e540954125 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-05-21 15:56:58 -04:00
Vitor Pamplona
f73052ed48 Checks cache before making a new request to DVM 2024-05-21 15:56:51 -04:00
Vitor Pamplona
a9437d9001 Refactors CreatedAt Comparator 2024-05-21 15:56:33 -04:00
Vitor Pamplona
02f6422bab Merge pull request #871 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-05-21 14:53:09 -04:00
Crowdin Bot
da2b59af49 New Crowdin translations by GitHub Action 2024-05-21 18:52:37 +00:00
Vitor Pamplona
7acdf56e68 Slightly improving the threading for badges. 2024-05-21 14:50:36 -04:00
Vitor Pamplona
24be6cd90d No need to launch, just use IO 2024-05-21 12:26:39 -04:00
Vitor Pamplona
afee0ddc53 Merge pull request #869 from believethehype/NIP90-ContentDiscovery
update paid dvms with processing status after payment
2024-05-21 08:41:38 -04:00
Believethehype
c85b8a1d83 update paid dvms with processing status after payment 2024-05-21 12:11:44 +02:00
Vitor Pamplona
cfeedfa4e2 Fixes the use of cache for video files. 2024-05-20 17:42:21 -04:00
Vitor Pamplona
dd112d28ae updating some libraries (others are not ready for the app) 2024-05-20 17:11:03 -04:00
Vitor Pamplona
fc27526113 Removes reposts from the Dot Notification in the home's bottom bar icon 2024-05-20 16:45:08 -04:00
Vitor Pamplona
666635811b Migrating to AGP 8.4.1 2024-05-20 16:42:11 -04:00
Vitor Pamplona
4e43938f96 Can zap DVMs directly on the regular zap button. 2024-05-20 16:22:27 -04:00
Vitor Pamplona
2a744205f0 Merge pull request #868 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-05-20 15:20:33 -04:00
Crowdin Bot
7e6ca34d2a New Crowdin translations by GitHub Action 2024-05-20 19:16:35 +00:00
Vitor Pamplona
24f7991116 Fixes a white space after a new line 2024-05-20 15:15:06 -04:00
Vitor Pamplona
beb901120e Fixes call from main thread 2024-05-20 13:25:53 -04:00
Vitor Pamplona
0936df9851 Fixes sat division and the state changing text. 2024-05-20 13:19:04 -04:00
Vitor Pamplona
9ceb8866ed Refactoring the DVM payment code. 2024-05-20 12:37:55 -04:00
Vitor Pamplona
c88b21b547 Merge pull request #867 from believethehype/NIP90-ContentDiscovery
Nip90 content discovery - Consider status and amount tags
2024-05-20 11:38:13 -04:00
Vitor Pamplona
5c366d5cfc Merge branch 'main' into NIP90-ContentDiscovery 2024-05-20 11:37:07 -04:00
Vitor Pamplona
ea70d44ac7 liniting 2024-05-20 11:24:03 -04:00
Believethehype
67f10920f6 Update NIP90ContentDiscoveryScreen.kt 2024-05-20 00:35:39 +02:00
Believethehype
654632a585 Update NIP90ContentDiscoveryScreen.kt 2024-05-20 00:32:26 +02:00
Believethehype
794b05106b add possibility to zap/pay invoices for dvms 2024-05-20 00:15:30 +02:00
Vitor Pamplona
5812e290c9 Merge pull request #866 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-05-17 18:32:35 -04:00
Crowdin Bot
c279c04858 New Crowdin translations by GitHub Action 2024-05-17 22:32:08 +00:00
Vitor Pamplona
01016525d3 Fixes missing parameter 2024-05-17 18:30:48 -04:00
Vitor Pamplona
72c6e93524 Migrates DVM route from pubkey to AppDefinition eventId and makes sure NFC reading will load the AppDefinition itself before rendering the rest of the screen. 2024-05-17 18:06:20 -04:00
Vitor Pamplona
d6988ad4e1 fixes redirection of routeFor when passing an App Definition Event. 2024-05-17 18:05:38 -04:00
Vitor Pamplona
4c1cd1c9ab adds DVM picture and name to the top bar and the status feed. 2024-05-17 17:18:31 -04:00
Vitor Pamplona
9fb8d4821e Refactoring the DVM codebase
Allows pull to refresh to request the job again.
2024-05-17 17:02:04 -04:00
Vitor Pamplona
8b052567c4 Adds a new observable system to local cache. 2024-05-17 17:01:57 -04:00
Vitor Pamplona
4a6ea550d6 Fixes the spacing in the Like button 2024-05-17 17:00:19 -04:00
Vitor Pamplona
5c88e7993f Fixes some of the missing classes due to R8 2024-05-16 15:14:51 -04:00
Vitor Pamplona
1bd1493bf4 Merge pull request #864 from greenart7c3/main
add paste from clipboard button to nwc
2024-05-16 13:47:19 -04:00
greenart7c3
404278a4e3 add paste from clipboard button to nwc 2024-05-16 14:13:40 -03:00
Vitor Pamplona
edca55b0b6 must not use crypto tools on the benchmark 2024-05-16 13:10:38 -04:00
Vitor Pamplona
738187d32b Making generateID public for testing 2024-05-16 13:05:15 -04:00
Vitor Pamplona
d9de0d2798 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-05-16 13:04:17 -04:00
Vitor Pamplona
b20515b1a0 Merge pull request #862 from believethehype/NIP90-ContentDiscovery
NIP90: cleanup, potential fix endless loop
2024-05-16 13:04:02 -04:00
Vitor Pamplona
e6d8291f07 Trying to unify NIP01 Serialization with SHA-256 procedures to reduce creation of several bytearray at every verification. 2024-05-16 13:03:30 -04:00
Vitor Pamplona
18d08bf6e0 Don't obfuscate data classes. 2024-05-16 13:01:15 -04:00
Believethehype
b2193f48d5 Update NIP90ContentDiscoveryScreen.kt 2024-05-16 16:48:19 +02:00
Vitor Pamplona
de391f03b1 Merge pull request #858 from VASHvic/auto_focus_search_screen
auto focus when entering the search screen
2024-05-16 09:29:21 -04:00
Believethehype
c494cf8ac1 Update NIP90ContentDiscoveryScreen.kt 2024-05-16 15:20:04 +02:00
Believethehype
193e9a5adb add more info on current dvm state 2024-05-16 15:19:19 +02:00
Believethehype
4fb9c93cf0 Merge branch 'NIP90-ContentDiscovery' of https://github.com/believethehype/amethyst into NIP90-ContentDiscovery 2024-05-16 15:16:33 +02:00
Believethehype
6bd98201f8 add DVM not replying message 2024-05-16 15:16:30 +02:00
believethehype
cbc6697631 Merge branch 'main' into NIP90-ContentDiscovery 2024-05-16 15:08:42 +02:00
Vitor Pamplona
d48634ac0e Merge pull request #861 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-05-16 09:03:48 -04:00
believethehype
5e2c8de15e Merge branch 'main' into NIP90-ContentDiscovery 2024-05-16 15:03:34 +02:00
Believethehype
926a721c53 cleanup, potential fix endless loop 2024-05-16 15:02:44 +02:00
Crowdin Bot
5bc6da3bfc New Crowdin translations by GitHub Action 2024-05-16 13:00:51 +00:00
Vitor Pamplona
eae066b003 Merge pull request #860 from believethehype/NIP90-ContentDiscovery
Fix order of events, use proper event content parsing
2024-05-16 08:58:54 -04:00
Believethehype
b74fa975ba Show DVM Status
Limitation: This will only show the first reply from the DVM, if mutliple status updates follow they will be ignored.
2024-05-16 14:24:13 +02:00
Believethehype
7f2b8519f3 improve parsing 2024-05-16 14:07:11 +02:00
Believethehype
51335e06f1 Fix order of Events in DVM feeds 2024-05-16 13:52:22 +02:00
VASH
0b6cd08c4a auto focus when entering the search screen 2024-05-15 21:59:21 +02:00
Vitor Pamplona
1bfe57da63 Fixes benchmark test for the new isDraft parameter 2024-05-15 10:28:01 -04:00
Vitor Pamplona
283d52ac2f Merge pull request #856 from believethehype/NIP90-ContentDiscovery
Nip90 Content Discovery
2024-05-15 10:17:10 -04:00
Vitor Pamplona
d1646761d2 Starts the process of adding a DM Relay list card to setup relays for GiftWraps 2024-05-15 10:00:54 -04:00
Believethehype
dc8209c90d Update NIP90ContentDiscoveryScreen.kt 2024-05-15 15:13:16 +02:00
Believethehype
420323bcb0 adjustments and cleanups 2024-05-15 15:11:36 +02:00
Believethehype
142aca40ce add NIP90 status events, update NIP90 feeds based on request id 2024-05-15 12:06:12 +02:00
Vitor Pamplona
4fa3d60638 Speeding up the url finder in the new post edit text. 2024-05-14 20:32:48 -04:00
Vitor Pamplona
a9eeb04014 Fixes alignment of the like icons after the like event. 2024-05-14 19:26:47 -04:00
Believethehype
f09b00ff01 adding 5301 events to be handled 2024-05-15 00:14:15 +02:00
Believethehype
ceaae398c2 Merge remote-tracking branch 'upstream/main' into NIP90-ContentDiscovery 2024-05-14 23:16:49 +02:00
Believethehype
39f87af072 remove notifications for NIP90 Content events 2024-05-14 23:09:43 +02:00
Vitor Pamplona
a34a3cbc83 Fixes GirtWrap test 2024-05-14 16:34:43 -04:00
Vitor Pamplona
f8afb4b783 Refactor the relay list for chat message event kind 2024-05-14 16:34:32 -04:00
Vitor Pamplona
fad4248539 Moves Zap the Devs card to a better position 2024-05-14 16:33:55 -04:00
Believethehype
13a53876d0 fix sorting 2024-05-14 22:21:03 +02:00
Believethehype
ea8affaebf general (unpolished) workflow works 2024-05-14 22:01:03 +02:00
Believethehype
df44e172ab Update NIP90ContentDiscoveryFilter.kt 2024-05-14 21:48:59 +02:00
Believethehype
8a50b3938d send request, get results (still needs parsing) 2024-05-14 21:41:36 +02:00
Believethehype
0245c907ff add nip90 events to factory 2024-05-14 18:51:38 +02:00
Vitor Pamplona
3bdc75b1be Improves the rendering of Channels and Communities when quoted 2024-05-14 12:40:53 -04:00
Vitor Pamplona
9d02361d01 Fixes wrong display of original and forked notes 2024-05-14 12:40:29 -04:00
Vitor Pamplona
6e6a13c5bf Moves video compressing quality to medium. 2024-05-14 12:12:48 -04:00
Vitor Pamplona
1f45a63081 Makes NIP-17 the default messaging mode
Migrates code from old NIP-24 to NIP-17
2024-05-14 11:34:36 -04:00
Believethehype
11a5f4a67e Merge remote-tracking branch 'upstream/main' into NIP90-ContentDiscovery 2024-05-14 17:06:00 +02:00
Believethehype
52e79580bf attempt to add own filters and event kinds for NIP90 content related events 2024-05-14 17:03:13 +02:00
Vitor Pamplona
561b19c447 Better rendering drafts in the thread 2024-05-14 10:16:41 -04:00
believethehype
9b21c3c964 Merge branch 'vitorpamplona:main' into NIP90-ContentDiscovery 2024-05-14 06:29:19 +02:00
Believethehype
baaa984d0d add nip90 content discovery request 2024-05-13 22:43:38 +02:00
Believethehype
2b7ef79d21 send dvm id to render list 2024-05-13 21:57:33 +02:00
Vitor Pamplona
22c96d2489 Use the default comparator instead of creating a new object every time 2024-05-13 15:40:24 -04:00
Vitor Pamplona
0c1187e4f5 Reducing the creation of new buttons when modifier objects change 2024-05-13 15:39:29 -04:00
Vitor Pamplona
7310ef175f DecimalFormats are not thread safe 2024-05-13 15:39:06 -04:00
Vitor Pamplona
53ba65cac2 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-05-13 13:27:09 -04:00
Vitor Pamplona
58ed27dc75 Adds recommended amounts for the Zap the Devs
Block error messages from closing the Zap split payment screen.
2024-05-13 13:27:03 -04:00
Vitor Pamplona
065ba1c165 Better format zap amounts (don't show .0 if the previous numbers are large) 2024-05-13 13:25:50 -04:00
Believethehype
896d227fea Update DiscoverScreen.kt 2024-05-13 19:25:43 +02:00
Vitor Pamplona
6bac18c5df Fixes the offset position of the payment amounts on the Zap the Devs message 2024-05-13 13:24:53 -04:00
Vitor Pamplona
9ad62ef263 Reduces default zap amounts due to the change of bitcoin price 2024-05-13 13:22:58 -04:00
Believethehype
fe45e188bd hide subscription dvms for now 2024-05-13 18:17:36 +02:00
Believethehype
334b948900 app meta data, show content dvms 2024-05-13 17:27:34 +02:00
Vitor Pamplona
fb9ad2b457 Merge pull request #854 from jeremyd/main
allow relay selection dialog to pick any relays
2024-05-13 10:47:17 -04:00
Vitor Pamplona
921bb41596 Merge pull request #855 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-05-13 10:47:08 -04:00
Crowdin Bot
ab4d01583b New Crowdin translations by GitHub Action 2024-05-13 14:44:00 +00:00
Vitor Pamplona
314531e938 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-05-13 10:42:05 -04:00
Vitor Pamplona
991eed9bdf Merge pull request #845 from davotoula/843-URL-previews-mishandle-HTML-entities
843 url previews mishandle html entities
2024-05-13 10:40:33 -04:00
Believethehype
357981f266 add nip89 filter 2024-05-13 16:12:19 +02:00
Believethehype
119e9b7281 Structure for Content Discovery 2024-05-13 15:42:52 +02:00
Vitor Pamplona
8ca53e9707 Updates jackson 2024-05-10 19:47:40 -04:00
jeremyd
326e38f293 allow relay selection dialog to pick any relays (instead of just write relays) 2024-05-10 15:14:37 -07:00
Vitor Pamplona
6232e2682f Updates firebase 2024-05-09 19:10:19 -04:00
Vitor Pamplona
a2363221c6 Fixes Copy Text function of DraftEvents 2024-05-07 09:58:29 -04:00
Vitor Pamplona
1eef457b4e Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-05-06 11:32:21 -04:00
Vitor Pamplona
fbd88bdeab Fixes top bar lists not updating when following communities and hashtags. 2024-05-06 11:32:14 -04:00
Vitor Pamplona
5d25bec1c9 Merge pull request #851 from VASHvic/hide_words_check
show toast error if unable to hide words
2024-05-04 15:59:36 -04:00
VASH
201a6d4462 show toast error if unable to hide words 2024-05-04 19:38:19 +02:00
Vitor Pamplona
1345ad3745 Merge pull request #847 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-05-01 13:17:55 -04:00
Crowdin Bot
b5f2a2b428 New Crowdin translations by GitHub Action 2024-05-01 17:16:56 +00:00
Vitor Pamplona
fe7b9b7930 Updates AGP 2024-05-01 13:09:29 -04:00
Vitor Pamplona
b24d3d863d ignores new idea file 2024-05-01 13:08:02 -04:00
Vitor Pamplona
3b7252616b Updates dependencies 2024-05-01 13:07:26 -04:00
Vitor Pamplona
c76ed3bb53 Merge pull request #846 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-04-24 17:06:42 -04:00
Crowdin Bot
cf775eebfb New Crowdin translations by GitHub Action 2024-04-24 21:05:58 +00:00
Vitor Pamplona
72018dc208 Base support for Relay lists for DMs. 2024-04-24 17:04:13 -04:00
Vitor Pamplona
fef635ab39 Fixes the use of Global-active relays in the Global Feed. 2024-04-24 13:54:13 -04:00
Vitor Pamplona
7a243af45c Updates compose, kotlin and okhttp 2024-04-24 09:53:17 -04:00
David Kaspar
94af0eb220 incremented matching group due to added matching group
added nbsp entity
2024-04-23 19:59:12 +02:00
David Kaspar
c0aea75c16 added test for html entity numbers to regular expression
added a few common html entities and entity numbers
2024-04-23 17:16:53 +02:00
Vitor Pamplona
175b79b291 Merge pull request #844 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-04-22 16:38:35 -04:00
Crowdin Bot
e5b8523bee New Crowdin translations by GitHub Action 2024-04-22 20:32:36 +00:00
Vitor Pamplona
1aecd9cf45 Minimizes costs of keeping track of the number of events received per subscription 2024-04-22 11:16:17 -04:00
Vitor Pamplona
6600a49564 Fixes the lack of refresh when adding hidden words in the Security filters 2024-04-18 19:34:15 -04:00
Vitor Pamplona
cdb65640ba Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-04-18 17:18:29 -04:00
Vitor Pamplona
0c9e76eeaf adds content type on CardFeedView 2024-04-18 17:17:17 -04:00
Vitor Pamplona
cfdbd0a9b6 Merge pull request #842 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-04-18 16:35:05 -04:00
Crowdin Bot
09b8178a7c New Crowdin translations by GitHub Action 2024-04-18 20:21:04 +00:00
Vitor Pamplona
5ea793eb51 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-04-18 16:19:21 -04:00
Vitor Pamplona
8cf04967c3 Makes sure only one pepare is run for each video view. 2024-04-18 14:46:01 -04:00
Vitor Pamplona
ef363457e8 Moves ClientController executor to a thread 2024-04-18 14:45:28 -04:00
Vitor Pamplona
e87394f3f7 Merge pull request #841 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-04-18 10:49:50 -04:00
Crowdin Bot
86ebfe8564 New Crowdin translations by GitHub Action 2024-04-18 14:24:22 +00:00
Vitor Pamplona
a2b3cfb991 Increases timeout to Tor connections 2024-04-18 10:22:19 -04:00
Vitor Pamplona
1b6aa621cd Merge pull request #840 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-04-17 17:55:02 -04:00
Crowdin Bot
b7f73c6eab New Crowdin translations by GitHub Action 2024-04-17 21:50:53 +00:00
Vitor Pamplona
e35fb88ff1 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-04-17 17:49:00 -04:00
Vitor Pamplona
6ecb3c8e1f - Improves Zap efficiency for large zap splits
- Adds a queue of commands while the relay connects.
- Makes sure only one connection per URL is made when doing splits
- Removes unecessary Amber calls when decrypting private zaps
2024-04-17 17:48:53 -04:00
Vitor Pamplona
ff20f0a266 Deleting unecessary logs 2024-04-17 17:47:17 -04:00
Vitor Pamplona
a4cc6337f9 Don't use DM relays to find metadata 2024-04-17 17:43:40 -04:00
Vitor Pamplona
202b897029 Refactors AppScreen out of Activity. 2024-04-17 16:25:13 -04:00
Vitor Pamplona
79c174b92e Merge pull request #839 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-04-17 12:23:15 -04:00
Crowdin Bot
bdd3f19b2c New Crowdin translations by GitHub Action 2024-04-17 15:16:18 +00:00
Vitor Pamplona
afcc775d1b Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-04-17 11:14:10 -04:00
Vitor Pamplona
8bbf308619 refactors the use of lud16 and lud06 2024-04-17 11:14:03 -04:00
Vitor Pamplona
df378937fe Adds a preview for UserNames with emojis 2024-04-17 11:12:51 -04:00
Vitor Pamplona
02ab7a3f3f Merge pull request #838 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-04-16 17:16:22 -04:00
Crowdin Bot
68ba9b3b91 New Crowdin translations by GitHub Action 2024-04-16 21:14:51 +00:00
Vitor Pamplona
f62833d1be Updates Firebase and Media3 dependencies 2024-04-16 17:11:52 -04:00
Vitor Pamplona
3be246c9cc Merge pull request #835 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-04-12 17:07:41 -04:00
Crowdin Bot
b28546b172 New Crowdin translations by GitHub Action 2024-04-12 21:05:53 +00:00
Vitor Pamplona
0fccfd7f80 clean up 2024-04-12 11:02:25 -04:00
Vitor Pamplona
3f35b57571 Improves Zap error messages to include the lnaddress of the error 2024-04-12 11:02:17 -04:00
Vitor Pamplona
32b9b6c37a Speeds up id calculations for Amber's Intent call.
Only assembles an id if necessary.
2024-04-12 11:01:32 -04:00
Vitor Pamplona
2342da114d Increases Amber signing cache. 2024-04-12 11:00:16 -04:00
Vitor Pamplona
ef0d77f8eb Removes hardcoded amber packages as default 2024-04-12 10:59:59 -04:00
Vitor Pamplona
5559b69bdb Displays Zap Split error messages in sequence instead of in multiple popups. 2024-04-12 10:58:32 -04:00
Vitor Pamplona
eda25b4cfe Callback uri is not necessary 2024-04-12 10:57:33 -04:00
Vitor Pamplona
9ce14e08fd Fixes a bug with signature-null in the sig of events. 2024-04-12 10:56:38 -04:00
Vitor Pamplona
b046fd91cb Only logs external signer calls on debug 2024-04-11 18:30:28 -04:00
Vitor Pamplona
8c9800664f v0.86.5 2024-04-11 18:20:48 -04:00
Vitor Pamplona
b90a57220d Enables Mutiny Wallet NWC 2024-04-11 18:18:54 -04:00
Vitor Pamplona
d16b0f58bb Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-04-11 18:04:53 -04:00
Vitor Pamplona
a538b66db3 Removes the use of DM relays to find events due to private inbox settings 2024-04-11 18:04:02 -04:00
Vitor Pamplona
f04631b0dd Adds vertical scrolling on the Zap page for collaborators. 2024-04-11 18:01:37 -04:00
Vitor Pamplona
6e31cff99c Avoids decrypting existing Nostr events just to add the relay into the relay list. 2024-04-11 18:01:22 -04:00
Vitor Pamplona
1553640c18 Calculates hash in the IO thread from Compose's scope. 2024-04-11 16:34:34 -04:00
Vitor Pamplona
68b8f9c82a Merge pull request #834 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-04-11 13:49:46 -04:00
Crowdin Bot
f6cce42028 New Crowdin translations by GitHub Action 2024-04-11 17:47:21 +00:00
Vitor Pamplona
0cbddad9c0 v0.86.4 2024-04-11 13:45:27 -04:00
Vitor Pamplona
b14154e2b5 Merge pull request #832 from greenart7c3/main
Do not use tor proxy when localhost, fix proxy not being used inside ImageDownloader.kt
2024-04-10 17:30:51 -04:00
greenart7c3
c4250ccd35 fix error when not using proxy 2024-04-10 14:11:11 -03:00
greenart7c3
31516964c8 Do not use tor proxy when localhost, fix proxy not being used inside ImageDownloader.kt 2024-04-10 13:51:48 -03:00
Vitor Pamplona
4722b2a617 Fixes missing Zaps and some DMs on startup 2024-04-10 11:05:21 -04:00
Vitor Pamplona
eca5b47ab0 Updates Kotlin version 2024-04-10 10:20:33 -04:00
Vitor Pamplona
d38b57025c Updates compose BOM 2024-04-10 09:00:57 -04:00
Vitor Pamplona
fa7aa3cf24 Updates AGP 2024-04-10 08:47:05 -04:00
Vitor Pamplona
d8e9b4773b v0.86.3 2024-04-09 19:41:22 -04:00
Vitor Pamplona
f9a7b13ba1 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-04-09 19:36:49 -04:00
Vitor Pamplona
ecbf0e404d Fixes missing notifications 2024-04-09 19:36:40 -04:00
Vitor Pamplona
c2f8df963a Merge pull request #831 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-04-09 12:23:35 -04:00
Crowdin Bot
ff20960bb5 New Crowdin translations by GitHub Action 2024-04-09 16:20:30 +00:00
Vitor Pamplona
8dd1fc2077 Fixing F-droid's Markdown use 2024-04-09 12:18:14 -04:00
Vitor Pamplona
bb2fb2b103 Fixes max width of hidden notes 2024-04-09 12:15:27 -04:00
Vitor Pamplona
00a9c49915 - Migrates to the new Markdown Parser.
- Adds Note previews on Markdown
- Adds Custom hashtag icons to markdown.
- Adds URL preview boxes to markdown
- Performance improvements.
2024-04-08 18:53:55 -04:00
Vitor Pamplona
d2872cc8bb Refactors the url preview state 2024-04-08 18:34:10 -04:00
Vitor Pamplona
d33a1ce14f Fixes clickable route not showing the user 's npub before loading the name. 2024-04-08 18:33:50 -04:00
Vitor Pamplona
31958215be Moves loading of an embed event to thread. 2024-04-08 18:33:31 -04:00
Vitor Pamplona
bbbb614718 Moves added charts after NIP19 uris to being nullable. 2024-04-08 18:32:37 -04:00
Vitor Pamplona
776a23c256 Clearing the secondary button design or the encrypted nsec backup 2024-04-08 11:34:33 -04:00
Vitor Pamplona
0854bd34ff v0.86.2 2024-04-05 14:08:27 -04:00
Vitor Pamplona
1738a775ef Fixes the lack of the Comparator interface for the Deletion Index. 2024-04-05 14:05:04 -04:00
Vitor Pamplona
a6953872ea Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-04-05 11:39:34 -04:00
Vitor Pamplona
d48714456c Fixes check for Deleted Addressable events. 2024-04-05 11:34:50 -04:00
Vitor Pamplona
c25aad482b Merge pull request #829 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-04-05 11:23:19 -04:00
Crowdin Bot
cbebfd263b New Crowdin translations by GitHub Action 2024-04-05 15:21:28 +00:00
Vitor Pamplona
89dbe82191 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-04-05 11:19:23 -04:00
Vitor Pamplona
7bb72d0c2d Adds a Deletion event cache. 2024-04-05 11:19:15 -04:00
Vitor Pamplona
9be4895080 Merge pull request #828 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-04-05 08:19:17 -04:00
Crowdin Bot
6250db01d1 New Crowdin translations by GitHub Action 2024-04-05 12:05:47 +00:00
Vitor Pamplona
48f9045f1b Merge pull request #825 from greenart7c3/onion_url
add ws:// if not present in .onion urls
2024-04-05 08:03:52 -04:00
Vitor Pamplona
818ca7e39e Merge pull request #826 from greenart7c3/draft_decryption_error
fix draft decryption error
2024-04-05 08:03:39 -04:00
Vitor Pamplona
e8675b8e45 Merge pull request #827 from davotoula/update_translations
added  translations for CS, DE, SV
2024-04-05 08:03:11 -04:00
David Kaspar
cef7e17447 added translations for CS, DE, SV 2024-04-05 11:38:51 +01:00
greenart7c3
6b15a0db8e fix draft decryption error 2024-04-05 05:41:03 -03:00
greenart7c3
50c5845a11 add ws:// if not present in .onion urls 2024-04-05 05:30:51 -03:00
Vitor Pamplona
1b7ba3de01 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-04-04 23:06:08 -04:00
Vitor Pamplona
712063f5d2 Avoids double notifications. 2024-04-04 23:05:58 -04:00
Vitor Pamplona
d92f23e274 LargeCache inner map should be private 2024-04-04 23:05:35 -04:00
Vitor Pamplona
3b7f530c0b Merge pull request #824 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-04-04 18:15:14 -04:00
Crowdin Bot
623a8d377c New Crowdin translations by GitHub Action 2024-04-04 22:08:10 +00:00
Vitor Pamplona
79489d0b07 v0.86.1 2024-04-04 18:06:36 -04:00
Vitor Pamplona
827512b225 Avoids circular rendering of Drafts. 2024-04-04 18:06:27 -04:00
Vitor Pamplona
6acfadeb9b Reduces cache for expandable texts. 2024-04-04 18:06:09 -04:00
Vitor Pamplona
e159af2cd7 v0.86.0 2024-04-04 17:21:03 -04:00
Vitor Pamplona
89c2e9d2e0 Changes precision of Zap Splits to 1% steps 2024-04-04 17:19:03 -04:00
Vitor Pamplona
06f6ab6719 Adds button to load Zap Splits from the cited users in the text 2024-04-04 17:18:42 -04:00
Vitor Pamplona
98c48e8b6b Fixes contract violation when sorting users. 2024-04-04 16:54:14 -04:00
Vitor Pamplona
25cde455d8 removes chat bubble animation when size changes 2024-04-04 15:58:19 -04:00
Vitor Pamplona
ef0fdf553c Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-04-04 15:24:59 -04:00
Vitor Pamplona
719b950272 Fixing the use of filters that didn't discriminate the relay type setup 2024-04-04 15:24:04 -04:00
Vitor Pamplona
2d02fad6b9 Merge pull request #823 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-04-04 15:16:49 -04:00
Crowdin Bot
a39db5bf7b New Crowdin translations by GitHub Action 2024-04-04 19:01:46 +00:00
Vitor Pamplona
7fd37367fc refactoring of cache methods in GiftWraps 2024-04-04 14:59:49 -04:00
Vitor Pamplona
e1c134830e Avoiding feed jitter when pressing the notification button twice. 2024-04-04 10:03:28 -04:00
Vitor Pamplona
621d1c7731 Migrating Refreshable feeds to the reusable box 2024-04-04 09:41:51 -04:00
Vitor Pamplona
7475143506 Continues the migration from LiveData to Flow 2024-04-04 08:56:15 -04:00
Vitor Pamplona
2509d639bd Merge pull request #822 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-04-03 13:07:08 -04:00
Crowdin Bot
85dd5cf698 New Crowdin translations by GitHub Action 2024-04-03 17:02:53 +00:00
Vitor Pamplona
274ce6ad77 Fixing the spacing for channels 2024-04-03 12:26:57 -04:00
Vitor Pamplona
0e8d2fc33a adds save when closing the screen on new posts. 2024-04-03 10:20:19 -04:00
Vitor Pamplona
b88723b68b Fixes wrong refactoring 2024-04-03 10:20:05 -04:00
Vitor Pamplona
638dba770d Moves the creation of Draft Notes to the IO Thread 2024-04-02 17:49:52 -04:00
Vitor Pamplona
4d7de6bc19 No need to switch to IO this early in the process 2024-04-02 16:08:59 -04:00
Vitor Pamplona
fbf676bdb2 Reduces recomposition of the hash verification 2024-04-02 16:08:38 -04:00
Vitor Pamplona
793780f02c Merge pull request #821 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-04-02 10:02:21 -04:00
Crowdin Bot
adf31ed115 New Crowdin translations by GitHub Action 2024-04-02 13:54:47 +00:00
Vitor Pamplona
96e434bfcf Fixes the lack of following mark on chats 2024-04-02 09:52:52 -04:00
Vitor Pamplona
c7563c938d Minor refactoring 2024-04-02 09:42:01 -04:00
Vitor Pamplona
4380393c5b No need to update UUID anymore. After deletion the draft can just be updated. 2024-04-02 09:23:08 -04:00
Vitor Pamplona
8125a7dabb Correctly moving the Reply line out of the renderer. 2024-04-01 18:32:36 -04:00
Vitor Pamplona
e898d58239 Finishing the rendering of card notes for DMs and live chats 2024-04-01 17:07:27 -04:00
Vitor Pamplona
29a43f82e6 Fixes lack of blurhash in some videos 2024-04-01 15:26:02 -04:00
Vitor Pamplona
469b9c6acb Only changes the keep playing status if different 2024-04-01 15:25:49 -04:00
Vitor Pamplona
38d1bf9aec Updates firebase 2024-04-01 15:01:39 -04:00
Vitor Pamplona
18b57b8ac8 Reactivating hold to edit draft. 2024-04-01 14:14:58 -04:00
Vitor Pamplona
7fc43c96d6 Merge pull request #819 from jiftechnify/meta-parser-benchmark
Add benchmark for MetaTagsParser
2024-03-29 17:46:35 -04:00
Vitor Pamplona
fc7d3a9519 Merge pull request #820 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-03-29 17:46:12 -04:00
Crowdin Bot
1667a78bb9 New Crowdin translations by GitHub Action 2024-03-29 21:44:07 +00:00
Vitor Pamplona
5fbd6c25d0 Fixes layout of the reply row in chats. 2024-03-29 17:41:13 -04:00
Vitor Pamplona
d079d511e8 Fixes markers for DMs 2024-03-29 17:40:51 -04:00
Vitor Pamplona
6e1418cd54 - Adds a Draft Screen
- Migrating drafts to new architecture where the Draft Event is sent to the screen instead of the inner event.
- Fixes lots of deletion and indexing bugs
2024-03-29 17:38:31 -04:00
Vitor Pamplona
cd84c07fcc Adds k-tag to the Deletion events. 2024-03-28 19:02:23 -04:00
jiftechnify
6eb2fbfa2f reduce creation of StringBuffers in meta tags parsing 2024-03-27 22:54:06 +09:00
jiftechnify
fc6f460063 fix contact link in relay information dialog 2024-03-27 22:52:16 +09:00
jiftechnify
442cdfdf2a move MetaTagsParser to common module 2024-03-27 21:19:52 +09:00
Vitor Pamplona
539433014e Fixes Notification for Follows now showing Zaps 2024-03-26 21:05:24 -04:00
Vitor Pamplona
d3f54a7082 Removes the Draft dependency for signer implementations 2024-03-26 16:56:58 -04:00
Vitor Pamplona
d3a0ae743a Merge pull request #749 from greenart7c3/main
save a draft while you are typing the post
2024-03-26 15:24:59 -04:00
Vitor Pamplona
6690d5391c Fixes controller comparison for keep playing 2024-03-26 15:06:55 -04:00
Vitor Pamplona
d61d684a27 Merge pull request #818 from jiftechnify/url-preview
Fix garbled URL preview for non UTF-8 HTML, with optimization
2024-03-26 13:40:15 -04:00
jiftechnify
4f84fad0cd remove jsoup version 2024-03-27 01:03:29 +09:00
Vitor Pamplona
cd32c4db72 Makes a cache for Media Items 2024-03-26 11:56:10 -04:00
jiftechnify
a71ce69cab support tags in quoted attribute value 2024-03-27 00:47:35 +09:00
Vitor Pamplona
b45f9bd460 Avoids launching coroutines that were just launched. 2024-03-26 09:09:35 -04:00
Vitor Pamplona
75ac17b57d increases the time to notify to 15 minutes 2024-03-26 08:35:15 -04:00
Vitor Pamplona
fa4745038f Uses the cached pool instead of the scheduled pool for translation services. 2024-03-26 08:34:45 -04:00
Vitor Pamplona
0182011487 Fixes NPE with the cached state. 2024-03-25 20:11:23 -04:00
Vitor Pamplona
37fdb8b2aa Removes unecessary parameters in the UserDisplay function 2024-03-25 17:58:54 -04:00
Vitor Pamplona
9ade18e1c1 Adds a bot field to the user info 2024-03-25 17:57:27 -04:00
Vitor Pamplona
aff6588791 Removing unnecessary layouts from the top bar 2024-03-25 17:57:11 -04:00
Vitor Pamplona
4274d2ddbd Blocks previews from being too big 2024-03-25 17:54:41 -04:00
Vitor Pamplona
63600f4782 Removes time measuring log 2024-03-25 16:45:21 -04:00
Vitor Pamplona
5deb9af477 Avoids publishing with two equal hashtags. 2024-03-25 16:41:52 -04:00
Vitor Pamplona
38e701a363 Moves the Following Vector to a native composable. 2024-03-25 16:41:38 -04:00
greenart7c3
6e6fa66c53 Merge branch 'main' into main 2024-03-25 17:34:22 -03:00
Vitor Pamplona
1f60d39cbf turning hashtag icons into programmable vectors 2024-03-25 16:02:36 -04:00
Vitor Pamplona
8ba474e79a Adjusting some of the icon sizes on the galleries 2024-03-25 14:23:36 -04:00
Vitor Pamplona
1123b3b3c1 Removes the need to observe author changes to event. 2024-03-25 13:51:08 -04:00
jiftechnify
bffb9f3778 remove jsoup from dependencies 2024-03-26 02:42:15 +09:00
jiftechnify
e11961695f parse HTML as little as possible 2024-03-26 02:31:06 +09:00
jiftechnify
042579ddfb remove unnecessary items from mata-tag canditates for getting URL info 2024-03-25 23:53:47 +09:00
jiftechnify
d0aa7430ca optimize HTML charset detection 2024-03-25 23:53:47 +09:00
jiftechnify
3434c31487 fix garbled URL preview for non-UTF-8 HTML 2024-03-25 23:53:43 +09:00
Vitor Pamplona
7eefbee0e3 Realigning the reaction icons and texts between main feed and video feed. 2024-03-25 10:44:10 -04:00
greenart7c3
ed4d867622 save draft when toogling nip4 and nip 44 2024-03-25 07:48:30 -03:00
greenart7c3
27db2b91ab save draft when changing options from polls and classifieds 2024-03-25 07:32:31 -03:00
greenart7c3
a2316b6ed0 Merge branch 'main' into main 2024-03-25 07:08:08 -03:00
Vitor Pamplona
a26b5490b2 updates compose 2024-03-24 18:53:11 -04:00
Vitor Pamplona
9990f458bf Moves Channel to LargeCache
Fixes filter for Chat Messages in discovery
2024-03-23 17:21:02 -04:00
Vitor Pamplona
0b40b6d1d8 Sorts chats by the latest message in Discovery 2024-03-23 17:19:54 -04:00
Vitor Pamplona
5a1c9f5a4a Ranks communities by the last post in each community in the discovery screen 2024-03-23 17:18:27 -04:00
Vitor Pamplona
eb6d31cf2b Better filter to bring public chat messages and avoid public chat creation and metadata updates 2024-03-23 17:16:43 -04:00
Vitor Pamplona
2c5e07de87 removes the use of data classes to speed up comparisons. 2024-03-23 17:15:38 -04:00
Vitor Pamplona
8d70664cc1 Fixes the list selection on the Discovery page. 2024-03-23 17:15:19 -04:00
Vitor Pamplona
102a34afca Merge pull request #814 from tyiu/fix-nip44-encrypt-decrypt-test
Fix NIP-44 encryptDecryptTest to decrypt with swapped private and public keys to follow NIP-44 documentation
2024-03-23 08:20:24 -04:00
Terry Yiu
c843e07709 Fix Kotlin encryptDecryptTest to decrypt with swapped private and public keys to follow NIP-44 documentation 2024-03-22 23:51:57 -04:00
Vitor Pamplona
3faa4983f0 Merge pull request #813 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-03-22 14:43:15 -04:00
Crowdin Bot
6f9dbbb8c3 New Crowdin translations by GitHub Action 2024-03-22 18:30:49 +00:00
greenart7c3
62a114b981 Merge branch 'main' into main 2024-03-22 08:48:47 -03:00
Vitor Pamplona
ff5612203d Fixes the width of muted messages on chat feeds. 2024-03-21 17:32:29 -04:00
Vitor Pamplona
6f0e4f1f19 Makes hidden cards full width on the discovery feed 2024-03-21 16:55:11 -04:00
Vitor Pamplona
8f5820f46d Fixes the reply finder for the reply row on compose 2024-03-21 16:54:50 -04:00
Vitor Pamplona
3086d3957d Moves from habla to njump 2024-03-21 09:27:57 -04:00
Vitor Pamplona
c00319812a Reverts to make sure the logged in user's post do not appear in notifications. 2024-03-21 09:25:26 -04:00
Vitor Pamplona
67202c32d4 Migrates channel notes to LargeCache 2024-03-21 08:51:23 -04:00
Vitor Pamplona
64909bfb32 Fixes Chat preview images when no image has been set. 2024-03-21 08:50:37 -04:00
Vitor Pamplona
c1756b75a7 Fixes double mention to Community headers when seeing a reply to a community post. 2024-03-21 08:42:14 -04:00
Vitor Pamplona
bdf41f53fb Removes logs 2024-03-21 08:41:29 -04:00
Vitor Pamplona
3b982b8962 Fixes the centralizing of the counter after the list of participants in a live event. 2024-03-20 17:02:13 -04:00
Vitor Pamplona
fd39ff24e1 Adds a space after the Channel header in the reply rows 2024-03-20 16:48:24 -04:00
Vitor Pamplona
e659153730 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-03-20 16:48:04 -04:00
Vitor Pamplona
f3c4b3255b Fixes missing context in some replies to blog posts. 2024-03-20 16:47:53 -04:00
Vitor Pamplona
f35f54166d Merge pull request #812 from greenart7c3/fix-amber-deep-sleep
add a lifeCycleOwner to register external signer on resume
2024-03-20 16:44:30 -04:00
greenart7c3
538c0493ed add a lifeCycleOwner to register external signer on resume 2024-03-20 17:20:35 -03:00
Vitor Pamplona
ceca149eb7 Doesn't show edits of blog posts in the User's Profile 2024-03-20 16:03:13 -04:00
Vitor Pamplona
97cdc0bc7a Fixes layout issues of LongForm content when the image is not present. 2024-03-20 16:02:49 -04:00
Vitor Pamplona
f2a8e51b20 Refactors horizontal dividers 2024-03-20 15:18:00 -04:00
greenart7c3
8d7a3f4d5e Merge branch 'main' into main 2024-03-20 15:13:33 -03:00
greenart7c3
c087042f7d Merge branch 'main' into main 2024-03-20 15:10:32 -03:00
greenart7c3
644d2fc2bb add generic draft event to default permissions 2024-03-20 14:56:29 -03:00
Vitor Pamplona
b819f24790 Reduces the space between chat bubbles. 2024-03-20 13:55:47 -04:00
greenart7c3
ea33cc77ed add edit draft in the dropdown menu and the long press popup 2024-03-20 14:50:53 -03:00
Vitor Pamplona
27fbf1c1ed Activates the chat simplified mode for the simplified setting. 2024-03-20 13:48:04 -04:00
Vitor Pamplona
3226e4e024 1. Refactors the use of dividers out of components
2. Refactors composables to load events, check hidden and check report
2024-03-20 13:47:47 -04:00
greenart7c3
090b643f43 add edit draft in the dropdown menu and the long press popup 2024-03-20 14:45:45 -03:00
Vitor Pamplona
943a4260ff Testing reduced line height 2024-03-20 11:49:12 -04:00
Vitor Pamplona
9867ac1689 Fixes videos not being able to seekTo the zero position. 2024-03-20 11:35:22 -04:00
Vitor Pamplona
d26de39749 Fixes lack of zap amount refresh after zapping a note. 2024-03-20 11:35:03 -04:00
Vitor Pamplona
1072b7a5c5 Fixes following by geotags 2024-03-20 11:34:40 -04:00
greenart7c3
220ce75f19 add validations to draft notes 2024-03-20 10:25:41 -03:00
greenart7c3
bc180ae210 fix draft delete not working 2024-03-20 09:31:31 -03:00
greenart7c3
5910ef199f fix build after merge 2024-03-20 07:22:55 -03:00
greenart7c3
499939ed68 Merge branch 'main' into main 2024-03-20 07:06:24 -03:00
Vitor Pamplona
d15beb2ae5 Fixes too strict timing constraints for new posts. 2024-03-19 19:55:41 -04:00
Vitor Pamplona
87fafd9451 Reducing the amount of co-routines being launched in each LiveData update. 2024-03-19 19:30:49 -04:00
Vitor Pamplona
bfbfcb6ed2 Avoids triggering an error when decoding invalid hexes. 2024-03-19 19:29:50 -04:00
Vitor Pamplona
ffc0a7c6ed Avoids showing error machine-level details when paying for zaps on external wallets 2024-03-19 17:44:51 -04:00
Vitor Pamplona
77789379c0 Minimizes memory use to calculate zaps. 2024-03-19 17:44:30 -04:00
Vitor Pamplona
a0a10b2cd0 Fixes some warnings 2024-03-19 17:34:26 -04:00
Vitor Pamplona
d59b98089a Aligns the BOM between implementation and tests. 2024-03-19 17:33:54 -04:00
Vitor Pamplona
160e52bd91 Fixes a bug with the latest version of jackson 2024-03-19 17:33:34 -04:00
Vitor Pamplona
d7e1a80465 Might be needed for those importing the AAR. 2024-03-19 17:33:09 -04:00
Vitor Pamplona
a5496445d2 Simple refactoring. 2024-03-19 14:49:56 -04:00
Vitor Pamplona
b75c3e3031 Refactoring caching systems for the Compose layer. 2024-03-19 14:17:15 -04:00
Vitor Pamplona
e9830c61aa Removes unused addMargin param. 2024-03-19 11:50:01 -04:00
Vitor Pamplona
25f28d38d5 Only shows OTS to the respective Edit 2024-03-19 11:49:50 -04:00
Vitor Pamplona
410d6bd690 Fixes binary payloads in the search results. 2024-03-19 11:49:03 -04:00
Vitor Pamplona
99270662ee Optimizing the performance of Highlight rendering 2024-03-19 10:30:21 -04:00
Vitor Pamplona
e40cd8d932 After clearing memory, only trigger liveData when it actually changed. 2024-03-19 10:07:21 -04:00
Vitor Pamplona
9858d98722 Avoids double request to show anyway when the user has hidden a post and ALSO the user's followers have reported the post. 2024-03-19 10:06:53 -04:00
Vitor Pamplona
6ab5488852 Starts with complete to avoid user shock 2024-03-19 10:06:16 -04:00
Vitor Pamplona
9651563b16 Fixing the test cases for nip96 2024-03-18 19:21:16 -04:00
Vitor Pamplona
9012bdad27 Fixes some of the testing cases 2024-03-18 18:19:05 -04:00
Vitor Pamplona
ef859c85a4 Merge pull request #810 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-03-18 18:09:18 -04:00
Crowdin Bot
959b2ac4e4 New Crowdin translations by GitHub Action 2024-03-18 22:08:29 +00:00
Vitor Pamplona
55a6f8829e Adds a large benchmark test for duplicate events. 2024-03-18 18:06:37 -04:00
greenart7c3
940fa2ee8d add debouncer 2024-03-18 17:47:15 -03:00
Vitor Pamplona
92d9c682f8 This should be better than launching a new thread after LaunchedEffect already lauched hers. 2024-03-18 16:38:40 -04:00
Vitor Pamplona
f5a1007f88 Seeing if the performance improves when the factory becomes just another lambda 2024-03-18 16:23:00 -04:00
Vitor Pamplona
d83acab84b - Solves infinite Quotation issue.
- Restructures NoteCompose for performance
- Restructures markAsRead to minimize threading cost.
2024-03-18 15:26:49 -04:00
greenart7c3
f6e5af3e98 support for dms, streams and communities 2024-03-18 16:18:12 -03:00
Vitor Pamplona
ac56d02b9d Updates AGP to 8.3.1 2024-03-18 15:10:39 -04:00
Vitor Pamplona
46a120450e Merge pull request #809 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-03-18 15:10:16 -04:00
Crowdin Bot
33e0107d3b New Crowdin translations by GitHub Action 2024-03-18 19:08:49 +00:00
greenart7c3
8b3e3e7af8 support Classifieds 2024-03-18 14:51:50 -03:00
greenart7c3
84faa7557e add support for polls 2024-03-18 14:37:51 -03:00
greenart7c3
f7ab925b1d fix delete on close 2024-03-18 14:21:58 -03:00
greenart7c3
204eaa4606 fix crash when loading draft from channels or lives 2024-03-18 11:16:13 -03:00
greenart7c3
1c249eed20 load post from draft 2024-03-18 10:56:36 -03:00
greenart7c3
3cc32ecd9a create a loadFromDraft method 2024-03-18 09:09:00 -03:00
greenart7c3
0a20d5484b show drafts as soon as its created 2024-03-18 08:39:55 -03:00
greenart7c3
6e4f1269dd add todo 2024-03-18 07:43:19 -03:00
greenart7c3
eba0837e52 fix draftnotes filter 2024-03-18 07:20:30 -03:00
greenart7c3
d682518ddb Merge branch 'main' into main 2024-03-18 07:07:32 -03:00
Vitor Pamplona
8c43f3492b Fixes some imports for benchmarks 2024-03-16 11:08:31 -04:00
Vitor Pamplona
688abee205 Merge pull request #808 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-03-16 10:35:35 -04:00
Crowdin Bot
d96ea0f8a2 New Crowdin translations by GitHub Action 2024-03-16 14:32:46 +00:00
Vitor Pamplona
b19b60128f Updates to compose and jackson 2024-03-16 10:29:56 -04:00
Vitor Pamplona
78be5a9ecc Reorganizing classes in the commons lib 2024-03-15 21:28:13 -04:00
Vitor Pamplona
36d2a3e42c Isolating the LargeCache forEach method to allow quick time measurements on filters. 2024-03-15 21:14:06 -04:00
Vitor Pamplona
fa7c2efaab Fixing size and alignment of the text when the live stream video is not present. 2024-03-15 21:13:15 -04:00
Vitor Pamplona
6edc634b82 Only download video, image and audio files in NIP-94 2024-03-15 19:55:14 -04:00
Vitor Pamplona
6bdf3e2625 Restructures Data Access filters and LocalCache to use a ConcurrentSkipList instead of ConcurrentHashMap 2024-03-15 19:32:43 -04:00
Vitor Pamplona
2d17200f03 Adds two additional helper methods to ATags and Classifieds. 2024-03-15 19:29:27 -04:00
Vitor Pamplona
c74176684f Preparing to refactor the Relay classes. 2024-03-15 19:28:59 -04:00
Vitor Pamplona
1b9742597a Keeps cache size in 10 to account for recompositions 2024-03-15 19:26:34 -04:00
greenart7c3
f949d5624e add draft support for public chat screen 2024-03-15 13:35:54 -03:00
greenart7c3
2bc2890d08 add draft support for other event kinds 2024-03-15 12:35:14 -03:00
greenart7c3
f3f8bc1b65 show draft in the simplified view 2024-03-15 10:45:53 -03:00
greenart7c3
99e9514d6c remove drafts from shared prefs 2024-03-15 10:38:22 -03:00
greenart7c3
8ade5b7e5f Merge branch 'main' into main 2024-03-15 09:18:38 -03:00
greenart7c3
e292affbe6 add draft in the home feed 2024-03-15 09:08:35 -03:00
Vitor Pamplona
fbf4f6dd08 Small Refactoring 2024-03-14 14:09:13 -04:00
Vitor Pamplona
b2508b3db5 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-03-14 11:55:32 -04:00
Vitor Pamplona
1abdb42552 Sets default to the simplified view. 2024-03-14 11:55:24 -04:00
Vitor Pamplona
2c54ba1a92 Corrects the starting point to show reactions on messages. 2024-03-14 11:55:13 -04:00
Vitor Pamplona
f941397cc4 Fixes tickmarks on dropdowns 2024-03-14 11:54:53 -04:00
Vitor Pamplona
69e31be37f Merge pull request #807 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-03-14 11:14:42 -04:00
Crowdin Bot
86c328c8a7 New Crowdin translations by GitHub Action 2024-03-14 15:13:23 +00:00
Vitor Pamplona
837865a699 Adds simplified views to the video and chat feeds. 2024-03-14 11:11:38 -04:00
Vitor Pamplona
1014e29289 Fixes some contract issues when follow and names are the same. 2024-03-14 09:54:43 -04:00
Vitor Pamplona
c1c5bc2039 Merge pull request #806 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-03-13 18:03:06 -04:00
Crowdin Bot
2d6aab954f New Crowdin translations by GitHub Action 2024-03-13 22:00:20 +00:00
Vitor Pamplona
eadb28321c Adds missing classes to support WebServer conections in the Video Playback 2024-03-13 17:58:26 -04:00
Vitor Pamplona
99850573f7 Reduces video cache from 10 to 4 videos. 2024-03-13 17:58:01 -04:00
Vitor Pamplona
45974fb09b change the isOnlineCheck to prepare for nostr nests websocket-based streaming. 2024-03-13 17:57:31 -04:00
Vitor Pamplona
f2dc2ef0d0 Uses the new default factory instead of the 3 separate methods. 2024-03-13 17:57:08 -04:00
Vitor Pamplona
8641bd36c3 Fixes Scheduled Tag in LiveStreams 2024-03-13 17:28:30 -04:00
Vitor Pamplona
a034d2f96e Updating Jackson 2024-03-13 14:02:50 -04:00
greenart7c3
fa5d992010 add draftevent class 2024-03-13 13:24:22 -03:00
greenart7c3
0d47e8b823 Merge branch 'main' into main 2024-03-13 11:24:12 -03:00
Vitor Pamplona
e289730be5 Fixes the cut off when having massive uncut string chars 2024-03-13 09:42:38 -04:00
greenart7c3
91b0d5b7fc Merge branch 'main' into main 2024-03-13 07:17:52 -03:00
Vitor Pamplona
0dbd58d8d7 Fixing some of the old display name structure 2024-03-12 17:51:27 -04:00
Vitor Pamplona
e094b56b72 Deleting old Settings local db 2024-03-12 17:18:06 -04:00
Vitor Pamplona
efb9d9268b Avoids parsing metadata events several times due to the json parser stopping coroutines. 2024-03-12 17:16:50 -04:00
Vitor Pamplona
82c4bf89df Avoids serializing temporary fields. 2024-03-12 16:32:43 -04:00
Vitor Pamplona
4a069fa73b Simplifies if a chatroom sender intersects with the follow list. 2024-03-12 16:21:18 -04:00
Vitor Pamplona
1cda191035 Moves the play button to the profile page. 2024-03-12 15:51:02 -04:00
Vitor Pamplona
e5d4b2a145 Adds a simplified version to the UI. 2024-03-12 15:50:15 -04:00
Vitor Pamplona
6ff5787e60 Merge pull request #805 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-03-12 11:23:20 -04:00
Crowdin Bot
ffb73b1780 New Crowdin translations by GitHub Action 2024-03-12 15:14:40 +00:00
Vitor Pamplona
9a6a857a11 Brings the ZapForwarding icon to Compose 2024-03-12 11:11:46 -04:00
Vitor Pamplona
abb9edc46b Refreshing the boostrap relay list. 2024-03-12 10:29:52 -04:00
Vitor Pamplona
5d78d9b046 updates dependencies 2024-03-12 10:20:09 -04:00
Vitor Pamplona
f372a256c5 formatting 2024-03-11 19:46:00 -04:00
Vitor Pamplona
e2fe1538b0 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-03-11 19:12:16 -04:00
Vitor Pamplona
7560a737cd Updated hashtag icons for performance 2024-03-11 19:10:22 -04:00
Vitor Pamplona
24a7812432 Merge pull request #804 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-03-11 15:30:34 -04:00
Crowdin Bot
df99c56c4a New Crowdin translations by GitHub Action 2024-03-11 18:38:52 +00:00
Vitor Pamplona
e984487d9e avoids escaping errors from events inside strings 2024-03-11 13:35:56 -04:00
Vitor Pamplona
afb5169ede Fitlers too many reposts out of the main feed. 2024-03-11 13:10:29 -04:00
Vitor Pamplona
64d6d6753c Centers Blank Note when post was hidden by the user. 2024-03-09 11:32:28 -05:00
Vitor Pamplona
0f69030cdf Improves Preview Utilities 2024-03-09 11:32:08 -05:00
Vitor Pamplona
dd81c51fab Removes dependency of the Robohash from CryptoUtils 2024-03-09 11:30:55 -05:00
Vitor Pamplona
6cd04a7617 Fixes space after clickable user display 2024-03-08 21:51:56 -05:00
Vitor Pamplona
632bd77db3 Switches Robohash to Precompiled SVGs in order to reduce the memory burned of creating Strings with SVGs on the fly. 2024-03-08 18:41:07 -05:00
greenart7c3
4938ba03a6 Merge branch 'main' into main 2024-03-08 12:35:23 -03:00
Vitor Pamplona
e6da340879 resets the show full text flag after 20 views. 2024-03-06 15:02:59 -05:00
Vitor Pamplona
c796cbd7be Fixes the fdroid flavor 2024-03-06 14:27:22 -05:00
Vitor Pamplona
2038994613 Holds the state of expanded text button between edits and translations. 2024-03-06 14:25:19 -05:00
Vitor Pamplona
5f76cdf721 Center the text of notes that couldn't be found. 2024-03-06 11:31:03 -05:00
Vitor Pamplona
b8619e3b61 - User Metadata clean up upon receipt instead of in every rendering.
- Simpler/Faster UserDisplay renderings
- Removes co-routing use for Hashtags.
2024-03-06 10:32:08 -05:00
Vitor Pamplona
da41fbb4c9 Updates secp256k1KmpJniAndroid 2024-03-05 19:05:03 -05:00
Vitor Pamplona
0dd553ae55 Fixes search on binary content. 2024-03-05 16:45:41 -05:00
Vitor Pamplona
563663c131 Merge pull request #800 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-03-05 16:20:23 -05:00
Crowdin Bot
dc3574bb6e New Crowdin translations by GitHub Action 2024-03-05 21:12:16 +00:00
Vitor Pamplona
f6ffb87e20 Avoids allocating Strings for the JSON conversion when checking if a filter has changed. 2024-03-05 16:09:50 -05:00
Vitor Pamplona
3b3ca06c1c Massive refactoring to reduce the size of NoteCompose 2024-03-05 09:30:47 -05:00
Vitor Pamplona
f73c9b5773 v0.85.3 2024-03-04 18:09:03 -05:00
Vitor Pamplona
5848255e72 Displaying issues and Patches in the Notification 2024-03-04 18:01:12 -05:00
Vitor Pamplona
1cf828b165 v0.85.2 2024-03-04 17:52:08 -05:00
Vitor Pamplona
2e1f7d6587 Merge pull request #799 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-03-04 17:00:26 -05:00
Crowdin Bot
c6977d97d3 New Crowdin translations by GitHub Action 2024-03-04 21:54:12 +00:00
Vitor Pamplona
d12e886e9e Bringing GitIssues in the Notification 2024-03-04 16:52:38 -05:00
Vitor Pamplona
8299f4cfca Cleans up the fork information on new posts has been canceled or posted. 2024-03-04 16:20:59 -05:00
Vitor Pamplona
432b1e4902 Fixes forking information kept from a previous post. 2024-03-04 16:15:09 -05:00
Vitor Pamplona
e9fd62dc26 Displaying correct edits on the new edit proposal 2024-03-04 15:37:29 -05:00
Vitor Pamplona
f42ec3c149 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-03-04 15:25:43 -05:00
Vitor Pamplona
43e1e0f23e Merge pull request #798 from greenart7c3/multiple-results-crash
fix crash parsing multiple results from amber
2024-03-04 15:17:52 -05:00
Vitor Pamplona
7bc393143c Adds link to the version notes from the drawer 2024-03-04 15:12:17 -05:00
greenart7c3
23718f51dd fix crash parsing multiple results from amber 2024-03-04 17:11:01 -03:00
Vitor Pamplona
8b2efecfbe Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-03-04 14:13:32 -05:00
Vitor Pamplona
9081d5a54b Adds nostr git for issue management software. 2024-03-04 14:13:23 -05:00
Vitor Pamplona
709e3bdd3a Merge pull request #797 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-03-04 13:22:09 -05:00
Crowdin Bot
1f66ef717b New Crowdin translations by GitHub Action 2024-03-04 18:18:38 +00:00
Vitor Pamplona
cd2b5d78a1 Don't show button to edit the post if the author of the original post is not the logged in user 2024-03-04 13:16:34 -05:00
Vitor Pamplona
2f45067949 v0.85.1 2024-03-04 12:00:02 -05:00
Vitor Pamplona
5a680beabb Fixes missing Fhir Classes on Release 2024-03-04 11:58:24 -05:00
Vitor Pamplona
779ce110ba Adding the most recent release features to the Readme. 2024-03-04 11:26:22 -05:00
Vitor Pamplona
43bcee5642 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-03-04 11:03:55 -05:00
Vitor Pamplona
64c4f7dc95 Removes extra new line 2024-03-04 10:29:19 -05:00
Vitor Pamplona
2b6cd07805 Merge pull request #796 from davotoula/accessibility_updates
Accessibility updates
2024-03-04 10:29:05 -05:00
David Kaspar
875d538581 added accessibility translations for CS, DE, SV, PT 2024-03-04 15:03:36 +00:00
David Kaspar
f0c53efebd app logo 2024-03-04 14:56:59 +00:00
David Kaspar
8c5aea46f1 refactor incognito button icon 2024-03-04 14:56:59 +00:00
David Kaspar
e507e0bb6a update Play text 2024-03-04 14:56:59 +00:00
David Kaspar
2f3df616f3 QR code icon 2024-03-04 14:56:59 +00:00
David Kaspar
75934b5b98 Relay list screeen 2024-03-04 14:56:59 +00:00
David Kaspar
4cbdf11ecb Send message button 2024-03-04 14:56:59 +00:00
David Kaspar
bbf0d36cdf Sealed message button on send message 2024-03-04 14:56:59 +00:00
David Kaspar
2bef5f015d change ArrowForwardIos to AutoMirrored 2024-03-04 14:56:59 +00:00
David Kaspar
708bd00d0d updated vertical dots with content descriptions 2024-03-04 14:56:59 +00:00
David Kaspar
2158e36032 Correct spelling 2024-03-04 14:56:59 +00:00
David Kaspar
08a103d332 updated some icons with content descriptions 2024-03-04 14:56:59 +00:00
Vitor Pamplona
57bcae6a0d Merge pull request #795 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-03-04 09:43:33 -05:00
Crowdin Bot
4897c28ed3 New Crowdin translations by GitHub Action 2024-03-04 14:38:48 +00:00
Vitor Pamplona
b3211cbb35 Removes the release drafter plugin on actions. Too buggy 2024-03-04 09:37:32 -05:00
Vitor Pamplona
fa6adcde75 v0.85.0 2024-03-04 09:10:11 -05:00
Vitor Pamplona
ad65e02fc9 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-03-04 09:09:21 -05:00
Vitor Pamplona
249ac4e039 Revert "v0.85.0"
This reverts commit a92ef7a375.
2024-03-04 09:08:20 -05:00
Vitor Pamplona
a92ef7a375 v0.85.0 2024-03-04 09:08:06 -05:00
Vitor Pamplona
e65faa2076 Merge pull request #794 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-03-03 11:14:10 -05:00
Crowdin Bot
5f53fc6aa9 New Crowdin translations by GitHub Action 2024-03-03 16:07:20 +00:00
Vitor Pamplona
218e133857 Merge pull request #793 from davotoula/update_translations
Updated translations. DE, SV, PT
2024-03-03 11:06:06 -05:00
David Kaspar
fcd61d87be Updated translations. DE, SV, PT 2024-03-03 09:28:10 +00:00
Vitor Pamplona
fb280f4880 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-03-02 16:18:33 -05:00
Vitor Pamplona
5342c4cfba updates mockk 2024-03-02 16:18:11 -05:00
Vitor Pamplona
dd106f315f Merge pull request #792 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-03-02 16:14:02 -05:00
Crowdin Bot
3ddd06fafc New Crowdin translations by GitHub Action 2024-03-02 21:13:28 +00:00
Vitor Pamplona
4fb68dd014 Fixes content title for the video playback notification 2024-03-02 16:11:01 -05:00
Vitor Pamplona
a301421915 Adds Home-only empty feed screen. 2024-03-02 15:57:49 -05:00
Vitor Pamplona
16c171ec40 Fixes quote-notes and reposted notes partially disappearing when they contain hidden users or words. 2024-03-02 12:37:02 -05:00
Vitor Pamplona
6725114b48 Avoids changing the showhidden value all the time, triggering recompositions. 2024-03-02 12:35:30 -05:00
Vitor Pamplona
861ad218c8 Fixes bug with NIP-11s with null kinds 2024-03-02 12:03:16 -05:00
Vitor Pamplona
b694ac7259 Visualizing proposed edits from other people 2024-03-01 21:15:43 -05:00
Vitor Pamplona
81cc985e3b Adds the ability to see and reply to Git Issues and Patches. 2024-03-01 18:09:15 -05:00
Vitor Pamplona
786802b708 Presents notifications when a person forks your content. 2024-03-01 17:07:19 -05:00
Vitor Pamplona
c53fc03157 Cache must update before updating the screen. 2024-03-01 16:52:18 -05:00
Vitor Pamplona
48a6923537 Forces edits to be from the same user. 2024-03-01 16:15:18 -05:00
Vitor Pamplona
c34811e05b Tries to highlight that there are two states here for Compose to observe. 2024-03-01 16:15:06 -05:00
Vitor Pamplona
3f500ef5b3 Make sure to add the forked author to the p-tag of a note. 2024-03-01 16:04:26 -05:00
Vitor Pamplona
cbce22c994 Fixes the alt tag 2024-03-01 15:46:58 -05:00
Vitor Pamplona
bc7a578cfe Making forks work with revisions. 2024-03-01 15:39:24 -05:00
Vitor Pamplona
af784a5bda Editting the current version of the post instead of only the original post. 2024-03-01 14:50:28 -05:00
Vitor Pamplona
b1a355691a Fixes another caching issue when multiple posts include the same poll. 2024-03-01 13:41:43 -05:00
Vitor Pamplona
4f2b2992e0 Merge pull request #791 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-03-01 12:41:09 -05:00
Crowdin Bot
77d30b6e7c New Crowdin translations by GitHub Action 2024-03-01 17:30:38 +00:00
Vitor Pamplona
228de99ccf Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-03-01 12:28:48 -05:00
Vitor Pamplona
dfec7ae7f5 Better aligns header elements 2024-03-01 12:28:42 -05:00
Vitor Pamplona
f8c4242843 Merge pull request #790 from davotoula/adding_translations
Updated translations. DE, SV, PT, CS
2024-03-01 12:17:18 -05:00
Vitor Pamplona
34150b6725 Merge branch 'main' into adding_translations 2024-03-01 12:17:12 -05:00
Vitor Pamplona
21a18cfa38 Rotates all versions of a note 2024-03-01 12:15:48 -05:00
David Kaspar
8fa6d1d490 Updated translations. DE, SV, PT, CS 2024-03-01 17:12:06 +00:00
Vitor Pamplona
c23510e05e Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-03-01 10:41:57 -05:00
Vitor Pamplona
1cc4fd5183 Closes popup when finished editing. 2024-03-01 10:40:43 -05:00
Vitor Pamplona
7468352795 Removes warnings from the quartz library. 2024-03-01 10:40:12 -05:00
Vitor Pamplona
238e577b93 avoids changing and reading the state at the same time 2024-03-01 10:39:49 -05:00
Vitor Pamplona
0653a69bbd Replaces deprecated put method 2024-03-01 10:39:32 -05:00
Vitor Pamplona
87fcba02b3 Move project to version catalogs 2024-03-01 10:38:03 -05:00
Vitor Pamplona
3fb8a5938f Updates to Android Studio Iguana 2024-03-01 08:03:58 -05:00
Vitor Pamplona
f2a9c2b34b Merge pull request #789 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-03-01 07:59:24 -05:00
Crowdin Bot
cf1e5f952d New Crowdin translations by GitHub Action 2024-03-01 12:57:52 +00:00
Vitor Pamplona
b6e096ec96 Only display edit option when looking at a text note. 2024-02-29 20:00:19 -05:00
Vitor Pamplona
ee4e20bac8 Fixing alt of git reply 2024-02-29 19:58:18 -05:00
Vitor Pamplona
4d2a7bbc32 Fixes Poll Caching problems. 2024-02-29 18:51:39 -05:00
Vitor Pamplona
600aab5e8d Reverts the ReactionRow change due to misalignments 2024-02-29 18:51:27 -05:00
Vitor Pamplona
1efef5887a Reduces the cache size for parsed posts. 2024-02-29 18:50:55 -05:00
Vitor Pamplona
3495866017 Improving cache of cashu tokens 2024-02-29 18:03:07 -05:00
Vitor Pamplona
0755bd2474 Improving the cache of LnInvoices. 2024-02-29 18:02:52 -05:00
Vitor Pamplona
d257f7e253 Fixes not being able to create an invoice because of an old cache of the lud16
Fixes inserting invoice in the cursor.
2024-02-29 17:35:44 -05:00
Vitor Pamplona
7497237763 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-02-29 17:06:22 -05:00
Vitor Pamplona
d506cf13a9 Adjustments to padding of the last element and the size of the relay box in kind 1 2024-02-29 17:05:41 -05:00
Vitor Pamplona
05454f5420 Merge pull request #788 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-02-29 15:10:18 -05:00
Crowdin Bot
8d8990899b New Crowdin translations by GitHub Action 2024-02-29 19:55:30 +00:00
Vitor Pamplona
fd37826663 Refactoring to improve legibility and compose stability of FhirResources 2024-02-29 14:52:56 -05:00
Vitor Pamplona
0084c2b532 Improves the speed of Location services. 2024-02-29 14:19:50 -05:00
Vitor Pamplona
c686e775bf Deletes unused code 2024-02-29 10:09:19 -05:00
Vitor Pamplona
6e0701b65d Removes unused kotlin serialization 2024-02-29 09:22:15 -05:00
Vitor Pamplona
417c29bd72 Updates Compose UI Version 2024-02-29 09:18:56 -05:00
Vitor Pamplona
3eb6983a94 Support for Kind 1 Edits 2024-02-28 17:42:06 -05:00
Vitor Pamplona
d4ba135368 Second embed bundle tests with nsecs 2024-02-28 16:54:28 -05:00
Vitor Pamplona
7f35d7d416 Improves rendering of prescriptions 2024-02-28 16:52:33 -05:00
Vitor Pamplona
9f4a30657b Fixes Ots Observation check 2024-02-28 16:51:14 -05:00
Vitor Pamplona
86aab2e842 Fixes DM chatroom edit button 2024-02-28 16:50:58 -05:00
Vitor Pamplona
73e3b60721 Fixes missing nsec processing 2024-02-28 16:50:23 -05:00
Vitor Pamplona
fdb0830d1b Refactors extra chars for Bech Links 2024-02-28 11:23:56 -05:00
Vitor Pamplona
bc833fadcf Fixes event loading for nembeds 2024-02-28 11:23:05 -05:00
greenart7c3
4d2c17cd1c fix draft on nip94 2024-02-28 11:16:19 -03:00
greenart7c3
53987336c0 Merge branch 'main' into main 2024-02-28 10:59:39 -03:00
Vitor Pamplona
d36efd6a2c Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-02-27 20:56:31 -05:00
Vitor Pamplona
0d92384d8c Fixes OTS test cases 2024-02-27 19:16:06 -05:00
Vitor Pamplona
466929a0f7 Merge pull request #787 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-02-27 18:56:30 -05:00
Crowdin Bot
85059d775b New Crowdin translations by GitHub Action 2024-02-27 23:52:02 +00:00
Vitor Pamplona
328ed226c6 Basic support for FHIR payloads.
Support for nembed
2024-02-27 18:50:20 -05:00
Vitor Pamplona
e305f3c198 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-02-27 15:40:49 -05:00
Vitor Pamplona
f78a252c8f - Adds nembed
- Redesigns NIP-19 returns to allow nembeds and give more nuance to the UI.
2024-02-27 15:39:15 -05:00
Vitor Pamplona
6e65bdbb91 Merge pull request #786 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-02-27 10:40:49 -05:00
Crowdin Bot
9639514a82 New Crowdin translations by GitHub Action 2024-02-27 15:37:25 +00:00
Vitor Pamplona
87fabd54de Completed OTS Support 2024-02-27 10:34:49 -05:00
Vitor Pamplona
529403d92f Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-02-26 20:52:24 -05:00
Vitor Pamplona
e2d86c1727 Adds a new report option as other 2024-02-26 20:52:15 -05:00
Vitor Pamplona
11ff0736e4 Speeding up the loop through local cache. 2024-02-26 20:51:59 -05:00
Vitor Pamplona
fbc63a6df1 Merge pull request #784 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-02-26 19:04:10 -05:00
Crowdin Bot
7dccac41e9 New Crowdin translations by GitHub Action 2024-02-26 23:53:45 +00:00
Vitor Pamplona
8ebad524ff Adds local cache to wait for OTS confirmations
Presents OTS pending and confirmations on the screen
Adds Menu item to OTS any post.
2024-02-26 18:51:23 -05:00
Vitor Pamplona
bf67ff64b4 Moves the image preview on new posts to the top of additional options for the post. 2024-02-26 15:47:44 -05:00
Vitor Pamplona
85ecaf18cc Sets split zaps for all quotes and forks 2024-02-26 15:47:22 -05:00
Vitor Pamplona
3c36f52baf Visual support for Kind1 forks. 2024-02-26 15:17:17 -05:00
Vitor Pamplona
782926fbea Separates the q filter from the e filter to avoid and moves q to the last position since it can be cut off and won't affect the app. 2024-02-25 18:24:50 -05:00
Vitor Pamplona
21d141c5c2 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-02-25 17:53:23 -05:00
Vitor Pamplona
de17aab7ab Fixing stack overflow with more than 200 zaps in a single note. 2024-02-25 17:53:15 -05:00
Vitor Pamplona
d1b0707b54 Merge pull request #783 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-02-25 17:13:49 -05:00
Crowdin Bot
2ea80272e3 New Crowdin translations by GitHub Action 2024-02-25 22:06:59 +00:00
Vitor Pamplona
6a7d33e58f - Generalizing OTS Calendar access
- Developing OTS access points with OkHttp
2024-02-25 17:04:51 -05:00
Vitor Pamplona
880915e702 Better explains why the fork of javaOTS was needed. 2024-02-25 15:43:59 -05:00
Vitor Pamplona
d6fd407632 Moves external signer from org.json to jackson parser 2024-02-25 15:43:42 -05:00
Vitor Pamplona
1c0854eeaa Moves from org.json to jackson in OTS replies 2024-02-25 15:43:18 -05:00
Vitor Pamplona
9eefb65047 Generalizes the interface for block explorers in OTS 2024-02-25 15:43:01 -05:00
Vitor Pamplona
31c9041461 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-02-25 11:50:01 -05:00
Vitor Pamplona
c4d6b1a5d1 Adds support for OpenTimestamps in Quartz 2024-02-25 11:49:51 -05:00
Vitor Pamplona
ad03d355b0 Adds internet for testing of OTS attestations 2024-02-25 11:45:59 -05:00
Vitor Pamplona
5ad86e5604 Adds support for the q tag together with the support for the mention marker. 2024-02-25 11:40:39 -05:00
Vitor Pamplona
6afd9a0191 Adds note on why the libscrypt was removed. 2024-02-25 11:39:48 -05:00
Vitor Pamplona
58ff0b5500 Merge pull request #782 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-02-24 09:18:08 -05:00
Crowdin Bot
3f33871c9c New Crowdin translations by GitHub Action 2024-02-24 14:16:45 +00:00
Vitor Pamplona
ca4cc93b31 Fix Quartz use 2024-02-24 09:15:41 -05:00
Vitor Pamplona
49c2d4f486 Adding Basic Git Rendering support. 2024-02-23 22:09:06 -05:00
Vitor Pamplona
b9c3123f18 Faster Longform tag filters 2024-02-23 18:08:55 -05:00
Vitor Pamplona
452911bf27 Removes the need to specify nulls for new TextNote creations 2024-02-23 18:08:30 -05:00
Vitor Pamplona
173e82d236 Adds Wikipage Kind 2024-02-23 17:55:39 -05:00
Vitor Pamplona
2819c71e85 Updates Coil and Google Service dependencies 2024-02-23 16:59:47 -05:00
Vitor Pamplona
3eac579638 Fixing Format 2024-02-23 14:29:14 -05:00
Vitor Pamplona
d606cef90e Adds Jitpack instructions for Quartz 2024-02-23 14:27:20 -05:00
Vitor Pamplona
de8870f240 Merge pull request #780 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-02-23 13:45:11 -05:00
Crowdin Bot
13031223a4 New Crowdin translations by GitHub Action 2024-02-23 18:22:53 +00:00
Vitor Pamplona
553500460a Merge pull request #779 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-02-23 13:21:41 -05:00
Vitor Pamplona
a7e601beee Keeping signing and util classes in the final jar 2024-02-23 13:21:25 -05:00
Crowdin Bot
d21792a46f New Crowdin translations by GitHub Action 2024-02-23 17:17:02 +00:00
Vitor Pamplona
b8b9aaf4aa Adds time utils tests to see if jitpack exports it 2024-02-23 12:15:20 -05:00
Vitor Pamplona
dd160ecb71 Improves relay list NIP-11 caching, updates NIP-11 properties in the document and adds icon rendering from the NIP11 document. 2024-02-22 18:43:46 -05:00
Vitor Pamplona
2ee4b24c9b Moves Relay information to Quartz
Renames Nip19 object for better readability
2024-02-22 16:08:36 -05:00
Vitor Pamplona
606c483d09 Moves Wallet Connect to Quartz 2024-02-22 15:40:07 -05:00
Vitor Pamplona
b1d1c4089c Speeds up some of image calculations 2024-02-22 14:46:18 -05:00
Vitor Pamplona
5740b75a64 Adds a few more benchmarks 2024-02-22 14:05:47 -05:00
Vitor Pamplona
8c9971d9f2 Moves benchmark tests to the benchmark release type 2024-02-22 13:59:59 -05:00
Vitor Pamplona
860c3773c3 Moves emoji parsers to commons and 2024-02-22 13:56:56 -05:00
Vitor Pamplona
8ff4ac3709 Inserts uploaded URLs where the cursor is and not at the end of the file. 2024-02-22 09:54:21 -05:00
Vitor Pamplona
5b77e39c8b Improves the speed of the text parser. 2024-02-21 19:18:30 -05:00
Vitor Pamplona
5886c866d3 Makes the name of the test follow the refactored name 2024-02-21 16:24:06 -05:00
Vitor Pamplona
96f29fc5ca Refactoring some names for the parsers. 2024-02-21 16:22:17 -05:00
Vitor Pamplona
90175198f0 Preparing to move Kind1 content parsers to commons. 2024-02-21 15:25:40 -05:00
Vitor Pamplona
4b9a55e178 Increasing the speed of the Robohash SVG to buffer function 2024-02-21 13:51:27 -05:00
Vitor Pamplona
0429c4dc3a Faster comparisons on GiftWrap Benchmarks 2024-02-21 11:25:08 -05:00
Vitor Pamplona
e3f3350c85 Fixes Robohash test 2024-02-21 11:24:51 -05:00
Vitor Pamplona
5cd1c5ab90 Faster hex validation 2024-02-21 11:23:32 -05:00
Vitor Pamplona
d982f029e4 Fixes Ukrainian translation 2024-02-21 10:22:20 -05:00
Vitor Pamplona
f44bc02767 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-02-21 10:13:18 -05:00
Vitor Pamplona
2e096069b9 Merge pull request #778 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-02-21 10:04:53 -05:00
Vitor Pamplona
f10dd38126 refactoring on method names to make them clearer 2024-02-21 10:04:40 -05:00
Crowdin Bot
74b1cad578 New Crowdin translations by GitHub Action 2024-02-21 15:02:57 +00:00
Vitor Pamplona
dbcf59779e Fix benchmark test 2024-02-21 09:59:39 -05:00
Vitor Pamplona
f4cee92702 Fixes the crash on images not being present in the image pager. 2024-02-20 16:51:18 -05:00
Vitor Pamplona
b70407f447 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-02-20 15:52:32 -05:00
Vitor Pamplona
444857ad95 Updating Vico 2024-02-20 15:52:25 -05:00
Vitor Pamplona
ae291d278f Fixes text's vertical alignment when emoji's are present. 2024-02-20 12:28:46 -05:00
Vitor Pamplona
0d44c44c6e Adds release note ID to gradle. 2024-02-20 11:30:27 -05:00
Vitor Pamplona
a03f9d2b98 Fixes position of the notification dot 2024-02-20 11:30:11 -05:00
Vitor Pamplona
49a090da00 Merge pull request #777 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-02-20 11:00:50 -05:00
Crowdin Bot
c8d11fdcac New Crowdin translations by GitHub Action 2024-02-20 15:59:43 +00:00
Vitor Pamplona
33342b85d1 Merge pull request #776 from davotoula/update_translations
Updated translations. DE, SV, PT, CS
2024-02-20 10:58:17 -05:00
David Kaspar
a148da4b7b Updated translations. DE, SV, PT, CS 2024-02-20 11:40:16 +00:00
Vitor Pamplona
1b93fc57cb Creates a way to ask for donations in the Notification page. 2024-02-19 18:57:21 -05:00
Vitor Pamplona
2514b74883 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-02-19 18:55:38 -05:00
Vitor Pamplona
a97ade41fa adds a release drafter to test 2024-02-19 18:55:29 -05:00
Vitor Pamplona
e44ee1e549 Merge pull request #775 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-02-19 08:31:44 -05:00
Crowdin Bot
b170d04d5e New Crowdin translations by GitHub Action 2024-02-19 13:20:13 +00:00
Vitor Pamplona
dc55d71486 Removing the need to recreate modifiers on BottomBar 2024-02-19 08:17:44 -05:00
Vitor Pamplona
dd071dc65a Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-02-17 13:54:45 -05:00
Vitor Pamplona
dd7427971c refactoring 2024-02-17 13:53:53 -05:00
Vitor Pamplona
d715ea44df Typo 2024-02-17 12:39:48 -05:00
Vitor Pamplona
7af2fcdb27 Adds playstore badge 2024-02-17 11:51:42 -05:00
Vitor Pamplona
879f7cf8e3 Smaller download badges 2024-02-17 11:29:18 -05:00
Vitor Pamplona
88033c2acd Update README.md 2024-02-17 11:16:45 -05:00
Vitor Pamplona
e7fc5545ba Update README.md 2024-02-17 11:15:19 -05:00
Vitor Pamplona
e7240c0acf Using an SVG as readme logo 2024-02-17 11:09:40 -05:00
Vitor Pamplona
1fa8cd95dc Improves Layout of Readme 2024-02-17 11:05:40 -05:00
Vitor Pamplona
9424147a08 v0.84.3 2024-02-16 16:00:00 -05:00
Vitor Pamplona
26356d6060 simple refactoring 2024-02-16 15:51:43 -05:00
Vitor Pamplona
56bc10b513 Speeds up set building 2024-02-16 15:49:57 -05:00
Vitor Pamplona
67a1aae1d0 Avoids the need to tag a cited user to count as a citation. 2024-02-16 15:49:42 -05:00
Vitor Pamplona
b88ab06154 Counts quotes as retweets in the notification stats bar 2024-02-16 15:48:54 -05:00
Vitor Pamplona
7d9784ee44 Updates secp256k1 2024-02-16 15:40:53 -05:00
Vitor Pamplona
8034fd0975 Adds normalizing test for emoji passwords in NIP49 2024-02-16 13:53:06 -05:00
Vitor Pamplona
42cc04c194 updates license notice year 2024-02-15 18:31:26 -05:00
Vitor Pamplona
52c6ce4849 Updates scrypt lib to support empty keys. 2024-02-15 17:42:19 -05:00
Vitor Pamplona
6553f3bec5 Normalizes passwords to NFKC in NIP49 2024-02-15 16:05:53 -05:00
Vitor Pamplona
03a9ec8ed2 Refactors clickable text 2024-02-15 11:03:01 -05:00
Vitor Pamplona
133d7d5ce0 v0.84.2 2024-02-15 11:00:23 -05:00
Vitor Pamplona
215989108b Fixes misalignment of Clickable Texts 2024-02-15 11:00:15 -05:00
Vitor Pamplona
ed7dcf94f8 Fixes extra spaces after urls 2024-02-15 10:59:52 -05:00
Vitor Pamplona
b2c7f150ec Merge pull request #774 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-02-15 08:46:02 -05:00
Crowdin Bot
c85d74a688 New Crowdin translations by GitHub Action 2024-02-15 13:41:21 +00:00
Vitor Pamplona
cbf23fedf1 Merge pull request #773 from davotoula/update_translations
Update translations
2024-02-15 08:39:53 -05:00
David Kaspar
5ed64bd5b5 Change to ellipsis character 2024-02-15 12:19:12 +00:00
David Kaspar
b79f9c8395 Updated translations. DE, SV, PT, CS 2024-02-15 12:18:19 +00:00
Vitor Pamplona
02da606461 v0.84.1 2024-02-14 17:49:07 -05:00
Vitor Pamplona
7074446cae Removing scrypt native library that doesn't work on Android 2024-02-14 17:48:57 -05:00
Vitor Pamplona
4746b5b18a removes unneeded translation keys 2024-02-14 17:40:50 -05:00
fiatjaf
103a61f35c useless pt-BR translation changes. 2024-02-14 17:29:28 -05:00
Vitor Pamplona
d9c48d4039 v0.84.0 2024-02-14 17:09:10 -05:00
Vitor Pamplona
9479e86b66 Enabled citation via @ on chats 2024-02-14 16:52:25 -05:00
Vitor Pamplona
bb7ec1ee4b Merge pull request #772 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-02-14 12:59:57 -05:00
Crowdin Bot
7a213545a2 New Crowdin translations by GitHub Action 2024-02-14 17:56:37 +00:00
Vitor Pamplona
48f27f656d Adds NIP49 to login and back up key screens 2024-02-14 12:54:08 -05:00
Vitor Pamplona
47176421e0 Adds copyright sentence. 2024-02-14 09:17:39 -05:00
Vitor Pamplona
9c84a538d6 Removes the NSEC form nip19 2024-02-13 20:49:21 -05:00
Vitor Pamplona
8bc1c2ec68 Removing nip19 test with ncryptosec 2024-02-13 20:44:00 -05:00
Vitor Pamplona
b94c1e2792 Quartz support for NIP-49 encrypted nsecs 2024-02-13 19:51:32 -05:00
Vitor Pamplona
74f0393706 Adds "₿itcoin" to the set of custom hashtags 2024-02-13 12:42:46 -05:00
Vitor Pamplona
0ec4b9b59f Merge pull request #771 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-02-13 11:58:43 -05:00
Crowdin Bot
1592d55db5 New Crowdin translations by GitHub Action 2024-02-13 16:43:27 +00:00
Vitor Pamplona
629c8b8167 Avoids the memory use of the flatten operation 2024-02-13 11:40:42 -05:00
Vitor Pamplona
9d8f70e04b No need to remember this param. 2024-02-13 11:39:54 -05:00
Vitor Pamplona
f75104e616 Updates Compose dependencies 2024-02-13 11:38:55 -05:00
Vitor Pamplona
c9d59fd5ac Adds a check for the main thread when pulling opengraph tags. 2024-02-13 11:38:28 -05:00
Vitor Pamplona
d41eb4ce31 No need to crossfade when expanding content 2024-02-12 18:11:28 -05:00
Vitor Pamplona
60e87d943a v0.83.13 2024-02-12 16:09:03 -05:00
Vitor Pamplona
1deed59d5b Fixes: https://github.com/vitorpamplona/amethyst/issues/740
Displays error messages when the URI sent to Amethyst is invalid
2024-02-12 16:03:37 -05:00
Vitor Pamplona
bbc4ec2625 Fixes thread rendering when "mention" events are added with mentioning the event. 2024-02-12 15:10:48 -05:00
Vitor Pamplona
5109b65e37 Fixes crash when MuteList has e tags that are not valid hexes 2024-02-12 14:21:32 -05:00
Vitor Pamplona
c0a9ce8e21 Small refactoring to focus the encrypted storage procedures to the application context. 2024-02-12 11:52:18 -05:00
Vitor Pamplona
bdff8c6c0d Moves language translation cleanup to the IO thread since it clears disk files as well 2024-02-12 11:15:59 -05:00
Vitor Pamplona
a3ac8a445d Merge pull request #768 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-02-10 10:22:09 -05:00
Crowdin Bot
84d4d68116 New Crowdin translations by GitHub Action 2024-02-10 15:00:43 +00:00
Vitor Pamplona
27248bff17 Invert the order of the hidden users in the screen. 2024-02-10 09:59:01 -05:00
Vitor Pamplona
dc9a9f288b Merge pull request #767 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-02-10 08:40:44 -05:00
Crowdin Bot
88662a4e55 New Crowdin translations by GitHub Action 2024-02-10 13:27:57 +00:00
Vitor Pamplona
9d269f7cba Merge pull request #766 from davotoula/update_translations
Updated translations. DE, SV, PT
2024-02-10 08:26:53 -05:00
David Kaspar
04fe439e0b Updated translations. DE, SV, PT 2024-02-10 09:45:17 +00:00
Vitor Pamplona
72503b9061 Adds community and public chat list events from nip51 2024-02-09 15:54:56 -05:00
Vitor Pamplona
f7ab963db9 Small fixes in the use of modifiers 2024-02-09 14:37:49 -05:00
Vitor Pamplona
f97128e11c Fixing accessibility issues raised on https://github.com/vitorpamplona/amethyst/issues/765 2024-02-08 17:16:54 -05:00
Vitor Pamplona
e2d4107297 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-02-08 14:54:04 -05:00
Vitor Pamplona
18709a1b22 Disables the notification dot in the discovery tab 2024-02-08 14:53:53 -05:00
Vitor Pamplona
ddfe2abb42 Fixes send to Top in marketplaces. 2024-02-08 14:53:35 -05:00
Vitor Pamplona
0cf82f7edd Merge pull request #764 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-02-07 16:37:18 -05:00
Crowdin Bot
d1c40efd90 New Crowdin translations by GitHub Action 2024-02-07 21:16:44 +00:00
Vitor Pamplona
68e90ce3ed Unwrapps the reply message if the GiftWrap was tagged and not the inner message id. 2024-02-07 16:14:48 -05:00
Vitor Pamplona
95e19cf681 v0.83.12 2024-02-05 20:29:43 -05:00
Vitor Pamplona
3298fd4493 BugFix for short lists 2024-02-05 20:26:37 -05:00
Vitor Pamplona
248bdffd50 v0.83.11 2024-02-05 19:49:27 -05:00
Vitor Pamplona
cce7a20918 Speeds up parsing of the event content. 2024-02-05 19:47:33 -05:00
Vitor Pamplona
845c99b798 Faster Expandable Text calculator. 2024-02-05 19:37:21 -05:00
Vitor Pamplona
b13b832696 Starting a new module for app benchmarks 2024-02-05 18:18:33 -05:00
Vitor Pamplona
eb6e235f1b Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-02-05 16:52:57 -05:00
Vitor Pamplona
36c49b2171 Updates Zoomable and Zxing Qr Reader 2024-02-05 16:52:48 -05:00
Vitor Pamplona
5cd3096221 Merge pull request #761 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-02-05 12:43:57 -05:00
Crowdin Bot
5bdc59d0e3 New Crowdin translations by GitHub Action 2024-02-05 17:37:48 +00:00
Vitor Pamplona
be43f2025f v0.83.10 2024-02-05 12:35:42 -05:00
Vitor Pamplona
0bb39f91b9 README typos and formatting 2024-02-02 18:53:36 -05:00
Vitor Pamplona
63a7b44264 Adds crowdin address to the readme 2024-02-02 18:44:10 -05:00
Vitor Pamplona
b5341f67e0 Finally fixes: https://github.com/vitorpamplona/amethyst/issues/436 2024-02-02 18:23:44 -05:00
Vitor Pamplona
3a2045eccc Allows buttons in the New Post screen to scroll horizontally to partially fix https://github.com/vitorpamplona/amethyst/issues/723
We are waiting the default scrollbar implementation from Jetpack Compose
2024-02-02 17:39:48 -05:00
Vitor Pamplona
c78239a6b7 Fixes some connectivity issues by basing the timeout from the last connection tentative instead of the drop out time. 2024-02-02 16:08:36 -05:00
Vitor Pamplona
4be4306540 Merge pull request #759 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-02-02 10:27:22 -05:00
Crowdin Bot
48887f23c1 New Crowdin translations by GitHub Action 2024-02-02 14:37:01 +00:00
Vitor Pamplona
103809d35b Fixes the top padding of the quoted note in a post. 2024-02-02 09:35:17 -05:00
Vitor Pamplona
9d92976eb9 Optimizes memory use of the visual user and url tagger in new posts. 2024-02-02 09:30:36 -05:00
Vitor Pamplona
d3d19b497b Renames from NIP-29 to 92 2024-02-01 19:20:26 -05:00
Vitor Pamplona
316c32f076 v0.83.9 2024-02-01 18:38:25 -05:00
Vitor Pamplona
6f27201244 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-02-01 18:31:36 -05:00
Vitor Pamplona
e56377f8c3 Adds support for NIP-29 in public messages and new DMs. NIP-54 stays in NIP-54 2024-02-01 18:31:28 -05:00
Vitor Pamplona
44e04864ac Merge pull request #758 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-02-01 16:14:42 -05:00
Crowdin Bot
eea727570c New Crowdin translations by GitHub Action 2024-02-01 20:57:56 +00:00
Vitor Pamplona
54155a3c30 Includes the product in the first message of the marketplace. 2024-02-01 15:56:13 -05:00
Vitor Pamplona
34d373c293 Updates to Android Studio Hedgehog | 2023.1.1 Patch 2 2024-01-31 16:05:00 -05:00
Vitor Pamplona
d7563032c4 Merge pull request #756 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-01-31 14:37:59 -05:00
Crowdin Bot
ed75489975 New Crowdin translations by GitHub Action 2024-01-31 19:29:03 +00:00
Vitor Pamplona
145b0d8f0a v0.83.8 2024-01-31 14:26:58 -05:00
Vitor Pamplona
eae07e2fe0 Making sure Cancellation of coroutines stops long processes. 2024-01-30 17:33:44 -05:00
Vitor Pamplona
6b60b1434f Name refactoring 2024-01-30 13:52:02 -05:00
Vitor Pamplona
3ff4db264a Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-01-30 13:40:08 -05:00
Vitor Pamplona
21f042fa95 Fixes secondary buttons theme in the login and signup screens. 2024-01-30 13:38:41 -05:00
Vitor Pamplona
e26bbc2e61 Merge pull request #755 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-01-30 13:16:43 -05:00
Crowdin Bot
5135026e6a New Crowdin translations by GitHub Action 2024-01-30 18:12:06 +00:00
Vitor Pamplona
a72f5ae01f Removing unnecessary logs 2024-01-30 13:09:43 -05:00
Vitor Pamplona
f2ed2d94c4 Update README.md
Fixing Markdown
2024-01-30 12:01:23 -05:00
Vitor Pamplona
75d703ac0a Testing GitStr with a Readme patch 2024-01-30 11:54:01 -05:00
Vitor Pamplona
277bf0a603 Fixes misalignment of some links to users in the middle of the note. 2024-01-30 11:51:02 -05:00
Vitor Pamplona
1ac990b67c Set account to avoid lateinit property account has not been initialized 2024-01-30 11:20:25 -05:00
Vitor Pamplona
e59f676d47 updates secp256k1 2024-01-30 11:00:33 -05:00
Vitor Pamplona
312d82fdf6 moving the order or contributing 2024-01-30 09:47:31 -05:00
Vitor Pamplona
08659738bd Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-01-30 09:46:06 -05:00
Vitor Pamplona
f1b0958903 Merge pull request #754 from davotoula/fix_gr_locale
Correct GR locale config
2024-01-30 09:45:36 -05:00
Vitor Pamplona
998aa2aed1 Adding GitStr 2024-01-30 09:44:48 -05:00
David Kaspar
370a18f716 Correct GR locale config 2024-01-30 13:30:25 +00:00
Vitor Pamplona
6638defbb9 Fixes content sensitivity for NIP-54 images. 2024-01-29 18:26:25 -05:00
Vitor Pamplona
d88eb014b7 Adding the exception to the Zap error message. 2024-01-29 17:14:31 -05:00
Vitor Pamplona
14e9a91d40 Updates dependencies 2024-01-29 16:28:53 -05:00
Vitor Pamplona
3ed45f282c Fixing NIP number for wraps/seals 2024-01-29 11:19:56 -05:00
Vitor Pamplona
2ff090dac1 New NIP available 2024-01-29 11:03:15 -05:00
Vitor Pamplona
281d86b4bf Small refactoring on the HTTP client 2024-01-27 11:58:39 -05:00
Vitor Pamplona
504e55a93f Merge pull request #753 from greenart7c3/proxy_fix
Recreate http client when changing the proxy or timeout
2024-01-27 11:39:29 -05:00
greenart7c3
c7b2c20119 recreate httpclient when changing the proxy or timeout 2024-01-24 17:18:25 -03:00
greenart7c3
cdd620987b implement reply draft 2024-01-24 09:55:31 -03:00
greenart7c3
2c086f76e2 open the post screen after editing the text 2024-01-24 08:40:55 -03:00
greenart7c3
99965ecd2d add an edit draft in the drawer 2024-01-24 08:22:35 -03:00
greenart7c3
ba7c59fdd5 draft was not saving in some places 2024-01-24 08:22:11 -03:00
greenart7c3
76a93f84c3 fix default value for the draft note 2024-01-24 08:21:04 -03:00
Vitor Pamplona
3e102c064b Merge pull request #750 from greenart7c3/queries
remove the need for application package name in the androidManifest for the external signer
2024-01-23 09:22:58 -05:00
greenart7c3
e0ec8a741c remove the need for application package name in the androidManifest for the external signer 2024-01-22 11:29:10 -03:00
greenart7c3
26a1624399 save a draft while you are typing the post 2024-01-22 09:02:44 -03:00
Vitor Pamplona
f1388b46d5 Merge pull request #746 from greenart7c3/main
add a copy url to the url preview card
2024-01-19 06:07:42 -05:00
greenart7c3
0f24e458d8 add a copy url to the url preview card 2024-01-19 07:18:25 -03:00
Vitor Pamplona
b8f3625954 Fixes remember of the wrong hashtag because it's a different post. 2024-01-18 15:57:21 -03:00
Vitor Pamplona
0babc46f7c Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-01-18 13:36:24 -03:00
Vitor Pamplona
6d368148cc makes the benchmark module profileable 2024-01-18 13:35:53 -03:00
Vitor Pamplona
3241f0ada1 formatting 2024-01-18 13:35:38 -03:00
Vitor Pamplona
49ad972af8 activates nostr.mom and nos.lol in the default relay set for global because of the Video feed. 2024-01-18 13:34:30 -03:00
Vitor Pamplona
e061575454 Removes unused imports 2024-01-18 13:33:48 -03:00
Vitor Pamplona
694642b42b Merge pull request #745 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-01-17 07:27:51 -05:00
Crowdin Bot
f4684ed078 New Crowdin translations by GitHub Action 2024-01-17 12:24:41 +00:00
Vitor Pamplona
db12ff0532 Merge pull request #744 from greenart7c3/reject_permission_amber
add support for always rejected permissions from external signer
2024-01-17 07:23:13 -05:00
greenart7c3
13d9c1ab10 add support for always rejected permissions from external signer 2024-01-17 09:05:24 -03:00
Vitor Pamplona
ac8f0e8600 v0.83.7 Testing new build tools 2024-01-11 12:33:55 -05:00
Vitor Pamplona
21472daab5 Uses new build tools to sign releases 2024-01-11 12:32:58 -05:00
Vitor Pamplona
c6a00386c8 adds distribution to github actions 2024-01-11 12:23:36 -05:00
Vitor Pamplona
9e3aa31c25 Updates Github actions scripts. 2024-01-11 12:06:45 -05:00
Vitor Pamplona
47987fac0f Merge pull request #743 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-01-11 10:52:13 -05:00
Crowdin Bot
46c782cf37 New Crowdin translations by GitHub Action 2024-01-11 15:51:24 +00:00
Vitor Pamplona
fd67f4875d Merge pull request #742 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-01-11 10:50:28 -05:00
Vitor Pamplona
4e2ff591e6 v0.83.6 2024-01-11 10:49:37 -05:00
Crowdin Bot
0e46145e2d New Crowdin translations by GitHub Action 2024-01-11 15:45:38 +00:00
Vitor Pamplona
383d859544 Fixes the BookmarkScreen update after adding and removing a bookmark to the list 2024-01-11 10:43:51 -05:00
Vitor Pamplona
81400eb863 Solving viewModel creation bug for Public Bookmarks 2024-01-11 10:36:52 -05:00
Vitor Pamplona
422446f53e Fixes bug when creating bookmarks for the first time. 2024-01-11 10:09:41 -05:00
Vitor Pamplona
f1e721f323 Fixes bug in checking bookmarks without running the onReady. 2024-01-11 10:09:19 -05:00
Vitor Pamplona
0fc72eb84d updates mockk 2024-01-11 09:43:11 -05:00
Vitor Pamplona
9234f4b7a8 Improves previews 2024-01-09 17:47:34 -05:00
Vitor Pamplona
0198d56099 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-01-09 16:35:04 -05:00
Vitor Pamplona
8f31c60cd1 Fixing some of the margins in the login screen. 2024-01-09 16:33:50 -05:00
Vitor Pamplona
7cb17954d9 Merge pull request #741 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2024-01-09 16:26:37 -05:00
Crowdin Bot
baf35b202f New Crowdin translations by GitHub Action 2024-01-09 21:25:47 +00:00
Vitor Pamplona
7b7e3624ac New Signup screen 2024-01-09 16:23:17 -05:00
Vitor Pamplona
d27b9ae5a8 Reducing the size of the following icon 2024-01-06 19:16:15 -05:00
Vitor Pamplona
4c48463091 v0.83.5 2024-01-06 16:53:18 -05:00
Vitor Pamplona
eb08d485e1 Fixing some of the tests due to the line breaks added by spotless 2024-01-06 15:11:12 -05:00
Vitor Pamplona
6e99e6f4a2 Makes sure the relay list contains unique urls. 2024-01-06 14:36:05 -05:00
Vitor Pamplona
d269e9e597 reduces some of the huge lines we have. 2024-01-06 11:59:35 -05:00
Vitor Pamplona
f8e7dd78d9 Reverts to the non-Google kotlin style. 2024-01-06 11:32:41 -05:00
Vitor Pamplona
0be1f89368 Fixes the lack of relay icons in the NIP44 messages 2024-01-06 11:24:52 -05:00
Vitor Pamplona
5c7e9258c1 Fixing some of the minification issues. 2024-01-06 11:13:57 -05:00
Vitor Pamplona
f877b6ff68 Creating the benchmark build type on the modules as well. 2024-01-06 10:53:54 -05:00
Vitor Pamplona
f5f43c5094 Creates a benchmark release type to avoid going back and forth with signing keys on the release 2024-01-06 10:48:11 -05:00
Vitor Pamplona
ec867ae8a2 Spotless fixes. 2024-01-06 10:44:32 -05:00
Vitor Pamplona
de61f7f383 Moves to spotless 2024-01-06 10:44:05 -05:00
Vitor Pamplona
ed6c1e62e4 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2024-01-05 16:46:30 -05:00
Vitor Pamplona
620b2bfa9f Improving the speed of contains 2024-01-05 16:46:18 -05:00
Vitor Pamplona
6715d48a9d Reverts kotlin version change 2024-01-05 16:45:58 -05:00
Vitor Pamplona
4291a58f85 Updates dependencies 2024-01-05 15:28:46 -05:00
Vitor Pamplona
00cffc8b6b fixing the benchmark for Robohash 2024-01-05 15:19:53 -05:00
Vitor Pamplona
7143d78663 Fixing the giftWrap test cases since the migration to v2 2024-01-05 15:18:46 -05:00
Vitor Pamplona
eaaa9a6446 Adjust position of the participant list in live streams. 2024-01-05 09:54:27 -05:00
Vitor Pamplona
41270c3a98 Merge pull request #739 from vuittont60/main
Fix some typos
2024-01-05 00:42:42 -05:00
vuittont60
a08a052b30 Fix typos 2024-01-05 11:27:52 +08:00
vuittont60
9403f12d2d Fix typos 2024-01-05 11:27:48 +08:00
Vitor Pamplona
89fb83cd9a Initializing the isHidden state for the note correctly 2023-12-29 19:44:48 -05:00
Vitor Pamplona
2355a95202 Avoiding the creation of modifiers. 2023-12-29 19:44:21 -05:00
Vitor Pamplona
53a320b4dc no need to remember the showProfilePicture state 2023-12-29 19:43:14 -05:00
Vitor Pamplona
2de3d19a34 Adds support for displaying video events. 2023-12-29 17:24:50 -05:00
Vitor Pamplona
57430c4366 Refactoring some of the old nomenclature of Kind 1 tags. 2023-12-29 14:25:14 -05:00
Vitor Pamplona
941ed77f22 Merge pull request #738 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-12-29 10:37:41 -05:00
Crowdin Bot
005b082873 New Crowdin translations by GitHub Action 2023-12-29 15:27:29 +00:00
Vitor Pamplona
9f219e31ab Merge pull request #737 from tyiu/nip-10-backwards-compatibility
Add write support for NIP-10 deprecated positional tags in text notes to maximize backwards compatibility
2023-12-29 10:26:15 -05:00
Terry Yiu
9101fb1e9e Add write support for NIP-10 deprecated positional tags in text notes to maximize backwards compatibility 2023-12-29 01:56:01 -05:00
Vitor Pamplona
c215beeb8e v0.83.4 2023-12-27 17:38:34 -05:00
Vitor Pamplona
20b730318f Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-12-27 17:00:48 -05:00
Vitor Pamplona
abef3d13f2 Improves the design of the discovery cards for Live Activity and Chats. 2023-12-27 17:00:41 -05:00
Vitor Pamplona
77eb066362 Fixes the loading of reactions and zaps to replaceable events. 2023-12-27 17:00:08 -05:00
Vitor Pamplona
ec4981852b Fixing the zap of live streams to go to the Host and not the pubkey in the event. 2023-12-27 16:59:28 -05:00
Vitor Pamplona
56c2c60c58 reorganizing Event Factory. 2023-12-27 16:58:56 -05:00
Vitor Pamplona
48aa9f950d adds support for NIP-75 events 2023-12-27 16:58:43 -05:00
Vitor Pamplona
37ae06347f Merge pull request #735 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-12-27 11:49:01 -05:00
Crowdin Bot
78616c07b1 New Crowdin translations by GitHub Action 2023-12-27 16:25:05 +00:00
Vitor Pamplona
73eff8a6c3 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-12-27 11:23:06 -05:00
Vitor Pamplona
4afb0027fb Initial support for separate vertical and horizontal videos. 2023-12-26 18:02:13 -05:00
Vitor Pamplona
1cedc8a6c8 Fixes reconnecting issue when DataSources were not active and become active later. 2023-12-26 18:01:31 -05:00
Vitor Pamplona
216ee59fae Merge pull request #732 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-12-26 15:22:19 -05:00
Crowdin Bot
adc4599adf New Crowdin translations by GitHub Action 2023-12-26 19:47:28 +00:00
Vitor Pamplona
8ed960530c Updates dependencies. 2023-12-26 14:43:01 -05:00
Vitor Pamplona
8f13a76870 v0.83.3 2023-12-23 17:45:56 -05:00
Vitor Pamplona
adaab4ced8 v0.83.2 2023-12-23 17:33:47 -05:00
Vitor Pamplona
5a2e149fa0 No need to remember simple state. 2023-12-23 17:28:04 -05:00
Vitor Pamplona
560c1f797c Performance: Reuse of modifiers in ReactionRow and Column 2023-12-23 16:28:02 -05:00
Vitor Pamplona
2d5be92f34 Performance: Improving the use or remember, less jittering when scrolling. 2023-12-23 15:28:04 -05:00
Vitor Pamplona
e9285fdac0 Simplifying the reaction row zap click. 2023-12-23 12:37:10 -05:00
Vitor Pamplona
4f12c127af Adds party, thinking and shock emoji to the default set 2023-12-23 12:04:41 -05:00
Vitor Pamplona
be7522382f Adds a log to debug notification receipts in production. 2023-12-23 11:38:11 -05:00
Vitor Pamplona
987fb02be1 Fixes relay icon size 2023-12-23 11:27:03 -05:00
Vitor Pamplona
bbd8a34f44 Initial refactoring of the elements within a post. 2023-12-22 19:44:01 -05:00
Vitor Pamplona
720ebfd0ea Avoids creating a new byte array at every call of conversation key. 2023-12-22 17:09:36 -05:00
Vitor Pamplona
159228972c Finishing the refactoring of Optout filters 2023-12-22 14:07:37 -05:00
Vitor Pamplona
2a65944eeb Removing unused parameter in this class. 2023-12-22 14:00:47 -05:00
Vitor Pamplona
e7902c4565 Testing new version 2023-12-22 13:49:29 -05:00
Vitor Pamplona
f12588ef7c Merge pull request #730 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-12-22 11:36:14 -05:00
Crowdin Bot
5fc197a40b New Crowdin translations by GitHub Action 2023-12-22 16:35:48 +00:00
Vitor Pamplona
64608f771e v0.83.0 2023-12-22 11:33:40 -05:00
Vitor Pamplona
a9cebaf3d9 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-12-22 11:33:13 -05:00
Vitor Pamplona
6c33dae498 Small refactoring before release. 2023-12-22 11:32:54 -05:00
Vitor Pamplona
e42d2dca04 Updates dependencies 2023-12-22 10:25:28 -05:00
Vitor Pamplona
35cd9cb6c5 Starts relay observers with a non null value 2023-12-22 09:15:21 -05:00
Vitor Pamplona
2ce16325a1 Improving the memory use of hashmaps 2023-12-21 15:26:01 -05:00
Vitor Pamplona
275aeb7833 Merge pull request #729 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-12-21 10:58:23 -05:00
Crowdin Bot
34737be5eb New Crowdin translations by GitHub Action 2023-12-21 15:57:34 +00:00
Vitor Pamplona
6fb5c873cc Removes signingConfig for debug 2023-12-21 10:52:46 -05:00
Vitor Pamplona
e0ffba5295 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-12-21 08:53:29 -05:00
Vitor Pamplona
82f03e0769 Merge pull request #728 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-12-20 19:20:00 -05:00
Vitor Pamplona
b223cc4028 updates okhttp 2023-12-20 19:19:58 -05:00
Crowdin Bot
550a9abdbb New Crowdin translations by GitHub Action 2023-12-20 23:09:16 +00:00
Vitor Pamplona
a121d1b301 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-12-20 18:07:46 -05:00
Vitor Pamplona
e794ff44a1 Moves to NIP-44v2 2023-12-20 18:07:37 -05:00
Vitor Pamplona
a22b6db130 Avoids Concurrent Modification Exception 2023-12-20 14:55:12 -05:00
Vitor Pamplona
1f7fc236db Fixes thread test 2023-12-20 12:47:28 -05:00
Vitor Pamplona
1edaea7905 Fix image uploader test 2023-12-20 11:46:44 -05:00
Vitor Pamplona
e8cae710c7 Merge pull request #726 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-12-19 16:46:57 -05:00
Crowdin Bot
489d92f9bb New Crowdin translations by GitHub Action 2023-12-19 21:29:59 +00:00
Vitor Pamplona
4d4c568afc Updates dependencies 2023-12-19 15:54:18 -05:00
Vitor Pamplona
e452c33a98 Uses primitive instead of object for Float 2023-12-19 15:54:10 -05:00
Vitor Pamplona
fdfd875580 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-12-19 15:53:43 -05:00
Vitor Pamplona
a6e8ee20ae Improves the performance of Robohash 2023-12-19 15:46:55 -05:00
Vitor Pamplona
065dba2431 Add a less memory intensive timeAgo calculation 2023-12-19 15:46:36 -05:00
Vitor Pamplona
5f581c2f5e Merge pull request #722 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-12-17 19:43:23 -05:00
Crowdin Bot
f7bfb68e7c New Crowdin translations by GitHub Action 2023-12-17 23:54:58 +00:00
Vitor Pamplona
2371e0678a Reusing SessionToken for all Playback connections 2023-12-17 18:44:18 -05:00
Vitor Pamplona
97c78aaa3c Moves the creation of the MediaItem to a thread. 2023-12-17 17:26:53 -05:00
Vitor Pamplona
9026c877ac - Adds i18n for error messages when uploading images.
- Forces nip95 to be under 80Kb
- Fixes bug that wouldn't show an error when uploading images in the reels page.
- Only saves default server if not NIP95
2023-12-17 17:26:17 -05:00
Vitor Pamplona
238ade9ccb Removes unused translation phrases. 2023-12-17 14:33:08 -05:00
Vitor Pamplona
016bd1ed81 Does apply the video's dimensions when the user has selected to not automatically start the playback 2023-12-17 14:30:04 -05:00
Vitor Pamplona
ed21d4cafb Detecting images by pinging the server instead of relying on the url. 2023-12-16 11:55:09 -05:00
Vitor Pamplona
ecc0f39f7d Moves relay modifiers to the app's theme 2023-12-16 11:42:11 -05:00
Vitor Pamplona
26846fa91a Refining recompositions of Route. 2023-12-15 22:21:43 -05:00
Vitor Pamplona
fe3a0568f2 Update README.md
Fixing the todo list in readme
2023-12-15 18:46:52 -05:00
Vitor Pamplona
56252d33f1 Updated Readme with the new refactorings from the NIP repo. 2023-12-15 18:38:06 -05:00
Vitor Pamplona
fccfb2aaba Support for NIP-31 alt tags 2023-12-15 18:19:37 -05:00
Vitor Pamplona
7b55b69c12 Adds a k tag to reactions 2023-12-15 18:00:26 -05:00
Vitor Pamplona
23fad2a818 removing some old time measuring code for additional performance. 2023-12-15 15:30:16 -05:00
Vitor Pamplona
2dc23b601a Performance: uses primitive instead of the wrapped object. 2023-12-15 14:58:57 -05:00
Vitor Pamplona
504980d263 Fixes bug with cropped joinToString 2023-12-14 20:17:38 -05:00
Vitor Pamplona
7cf7c9f082 Refactoring 2023-12-14 18:56:53 -05:00
Vitor Pamplona
dd8904de15 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-12-14 18:45:42 -05:00
Vitor Pamplona
d1c43f8147 Avoiding the creation of new sets when looping through maps in User and Note 2023-12-14 18:42:36 -05:00
Vitor Pamplona
68506fd6af Avoiding the creation of new sets when looping through maps in User and Note 2023-12-14 18:31:00 -05:00
Vitor Pamplona
b795ca06d1 Avoids creating another keySet. 2023-12-14 17:41:50 -05:00
Vitor Pamplona
8695acb742 No need to recreate Sets. 2023-12-14 17:41:25 -05:00
Vitor Pamplona
ed491f5e3a Avoids recreating the EOSE array when changing filters. 2023-12-14 15:52:52 -05:00
Vitor Pamplona
3a76c2a2de Minor refactoring 2023-12-14 15:02:49 -05:00
Vitor Pamplona
91b3b9e0e9 Moves to a less memory intensive way to send filters to the server. 2023-12-14 14:33:15 -05:00
Vitor Pamplona
fb280650a5 Ignore app insights local settings for Android studio 2023-12-14 11:03:33 -05:00
Vitor Pamplona
e4baebf2f9 Must be on main. 2023-12-14 11:02:55 -05:00
Vitor Pamplona
1a33da2537 Moving buildConfig to DSL 2023-12-14 10:45:14 -05:00
Vitor Pamplona
3734ee58ea Disabling log messages 2023-12-14 10:39:16 -05:00
Vitor Pamplona
9554b36f80 Updates secp256k1 lib 2023-12-14 10:38:41 -05:00
Vitor Pamplona
5225c6ad07 v0.82.3 2023-12-13 18:57:16 -05:00
Vitor Pamplona
c7be0e4a95 Memory improvements on relay lists and LiveData objects 2023-12-13 18:51:30 -05:00
Vitor Pamplona
d4f060d509 Improvements to the rendering of chat headers 2023-12-13 18:50:36 -05:00
Vitor Pamplona
9ba9ddee50 Using the new ChatHeader layout 2023-12-13 15:23:46 -05:00
Vitor Pamplona
7bbdd5e877 Avoid remembering Modifier 2023-12-13 15:23:32 -05:00
Vitor Pamplona
6cc65ce84a Avoid remembering Modifier 2023-12-13 15:22:23 -05:00
Vitor Pamplona
6c711f8acc v0.82.2 2023-12-13 12:10:06 -05:00
Vitor Pamplona
acefff80ee - Fixes the transition between short preview and full text on markdown.
- Adds NIP-44 metatags to markdown rendering.
- Adds background video rendering on markdown
- Refactors a few class names.
2023-12-13 12:09:59 -05:00
Vitor Pamplona
0e5b5d657f Calculate the text width of a space outside a composable. 2023-12-12 20:31:03 -05:00
Vitor Pamplona
c2532322fd Fixing the image link classification with uppercase extensions. 2023-12-12 20:29:28 -05:00
Vitor Pamplona
dc73aec334 No need to remember this. 2023-12-12 18:57:14 -05:00
Vitor Pamplona
aa909184fd Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-12-12 18:09:27 -05:00
Vitor Pamplona
205dd75e7e Update README.md
Aligning screenshots
2023-12-12 18:09:18 -05:00
Vitor Pamplona
be9100dc5e Minor refactoring. 2023-12-12 18:00:02 -05:00
Vitor Pamplona
b2e35cdb3e v0.82.1 2023-12-12 11:20:33 -05:00
Vitor Pamplona
827e168bf2 Fixing minification issue on release. 2023-12-12 11:16:46 -05:00
Vitor Pamplona
a14d4e6f4e v0.82.0 2023-12-12 09:32:59 -05:00
Vitor Pamplona
de61c0350e Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-12-12 09:31:25 -05:00
Vitor Pamplona
3e3c97076d Formatting 2023-12-12 09:31:14 -05:00
Vitor Pamplona
f62c986016 Improving sizes of blurhashes 2023-12-12 08:50:11 -05:00
Vitor Pamplona
04108e893d Merge pull request #720 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-12-12 08:44:58 -05:00
Crowdin Bot
042394796a New Crowdin translations by GitHub Action 2023-12-12 13:44:16 +00:00
Vitor Pamplona
bfce57f686 Improving the video switching from blurhash to video 2023-12-11 19:58:29 -05:00
Vitor Pamplona
5bb983ba5a Adding blurhash when images are not supposed to be downloaded. 2023-12-11 17:57:19 -05:00
Vitor Pamplona
debae02421 Improves the rendering of inline metadata 2023-12-11 16:22:01 -05:00
Vitor Pamplona
6fe93fdf33 Reverting image comment 2023-12-11 14:26:28 -05:00
Vitor Pamplona
3d225423ef Adds support for nip54 2023-12-11 12:51:53 -05:00
Vitor Pamplona
49e1da8812 Spacing 2023-12-11 12:50:44 -05:00
Vitor Pamplona
04addc4cba Adds support for the FileServers kind 2023-12-10 21:27:47 -05:00
Vitor Pamplona
c5cf2c5442 Adding the delete option for NIP-96 2023-12-10 21:21:00 -05:00
Vitor Pamplona
ddb7e6b7f2 Updates JNA 2023-12-10 18:32:47 -05:00
Vitor Pamplona
e5af34efca Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-12-08 22:08:30 -05:00
Vitor Pamplona
b3bdbbed98 - Migrates the old imageservers to NIP-96 for the main feed, chats, private messages, stories and user metadata uploads.
- Fixes hash calculation of the entire payload.
- Unifies uploads into NIP-94 images.
2023-12-08 22:08:19 -05:00
Vitor Pamplona
656b066d3a Merge pull request #719 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-12-08 19:50:21 -05:00
Crowdin Bot
4248fadc69 New Crowdin translations by GitHub Action 2023-12-09 00:45:17 +00:00
Vitor Pamplona
18281cbc49 Merge pull request #718 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-12-08 19:44:05 -05:00
Crowdin Bot
1d67af328a New Crowdin translations by GitHub Action 2023-12-08 16:23:27 +00:00
Vitor Pamplona
72b4f6acef Merge pull request #715 from davotoula/tr
Correct spelling of localised string reference
2023-12-08 11:21:52 -05:00
Vitor Pamplona
26273270ba Merge branch 'main' into tr 2023-12-08 11:21:46 -05:00
Vitor Pamplona
db3824c3c7 New Cashu Redeeming card. 2023-12-06 18:43:54 -05:00
Vitor Pamplona
d6de1d03d8 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-12-06 15:40:05 -05:00
Vitor Pamplona
8e4b7c66b5 Adds a UserAgent to all HTTP requests. 2023-12-06 15:40:01 -05:00
Vitor Pamplona
45c750069a Refactoring the update of channel information. 2023-12-06 15:38:31 -05:00
Vitor Pamplona
a411a72024 Merge pull request #716 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-12-06 14:59:12 -05:00
Crowdin Bot
219d163680 New Crowdin translations by GitHub Action 2023-12-06 19:38:31 +00:00
Vitor Pamplona
a4c9f42205 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-12-06 14:36:21 -05:00
Vitor Pamplona
a8936c54d8 Adds a Marketplace tab to Discovery 2023-12-06 13:40:54 -05:00
David Kaspar
74875bb564 Correct spelling of localised string reference 2023-12-06 15:07:52 +01:00
Vitor Pamplona
61d412d941 Merge pull request #714 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-12-06 08:14:16 -05:00
Crowdin Bot
5bb1e47edf New Crowdin translations by GitHub Action 2023-12-06 13:13:27 +00:00
Vitor Pamplona
b023614b5f Merge pull request #713 from davotoula/tr
Updated translations for cs/de/sv/pt
2023-12-06 08:11:39 -05:00
David Kaspar
7245718003 Updated translations for cs/de/sv/pt 2023-12-06 12:15:02 +01:00
David Kaspar
ba1f98d930 Updated translations for cs/de/sv/pt 2023-12-06 12:08:20 +01:00
David Kaspar
ceeabffcb7 Correct spelling of localised string reference 2023-12-06 12:04:50 +01:00
David Kaspar
2a943493b3 Updated translations for cs/de/sv/pt 2023-12-06 11:21:41 +01:00
Vitor Pamplona
332a2f41b6 Moves the relay observer and reconnection to Service Manager's scope. 2023-12-05 21:48:43 -05:00
Vitor Pamplona
ce2cfb7c86 fixes bug when updating relay list that used keep the previous list. 2023-12-05 21:48:05 -05:00
Vitor Pamplona
41ef1abf0e Fixes deletion of replaceable events. 2023-12-05 21:47:20 -05:00
Vitor Pamplona
fce27c3c55 Presenting better error messages when the image upload fails. 2023-12-05 21:46:35 -05:00
Vitor Pamplona
6662966ab3 Fixing crash when image is an SVG and tries to compress. 2023-12-05 21:45:56 -05:00
Vitor Pamplona
f458f00edc 1. Adds Classified creation from Amethyst.
2. Adds relay information for Replaceable events.
2023-12-05 21:44:49 -05:00
Vitor Pamplona
8f1fbe10e9 Merge pull request #712 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-12-05 11:41:45 -05:00
Crowdin Bot
69efa78fbc New Crowdin translations by GitHub Action 2023-12-05 16:16:54 +00:00
Vitor Pamplona
64a07d8760 Updates to fix Crash due to malformed video formats. 2023-12-05 09:52:15 -05:00
Vitor Pamplona
cb672d92d0 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-12-04 13:25:54 -05:00
Vitor Pamplona
95bcbfdded Reusing common icons for Cashu's Redemption 2023-12-04 13:23:19 -05:00
Vitor Pamplona
ac269727bc Merge pull request #711 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-12-04 11:57:45 -05:00
Crowdin Bot
b1a7d18c0a New Crowdin translations by GitHub Action 2023-12-04 15:53:21 +00:00
Vitor Pamplona
619b59357b Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-12-04 10:52:23 -05:00
Vitor Pamplona
86dcc3ccd9 Merge pull request #710 from believethehype/main
add a button to cashu preview to redeem on external wallet
2023-12-04 10:51:41 -05:00
Vitor Pamplona
6772360ae7 Fixes bottom bar appearing in chats when the keyboard is open. 2023-12-04 10:48:29 -05:00
Vitor Pamplona
05cbbd79cb Uses nostr.wine instead of filter.nostr.wine as a search relay. 2023-12-04 10:47:38 -05:00
Believethehype
a80c03a2d2 Update CashuRedeem.kt 2023-12-04 16:20:40 +01:00
Believethehype
6c3abe17ed add a button to cashu preview to redeem on external wallet, additional to melting to ln 2023-12-03 15:02:22 +01:00
Vitor Pamplona
7cd09261de Optimizes the rendering of the side bar. 2023-12-02 17:23:15 -05:00
Vitor Pamplona
6ef1bee8a0 Updates EOSE in the same thread of the new event to reduce the amount of coroutine launches. 2023-12-02 14:54:34 -05:00
Vitor Pamplona
66b8b04db3 Updates dependencies. 2023-12-02 14:14:15 -05:00
Vitor Pamplona
3b06abb2bc Upgrades junit benchmark 2023-12-02 14:12:10 -05:00
Vitor Pamplona
138fafa204 Updates gradle 2023-12-02 14:11:19 -05:00
Vitor Pamplona
9cbdbb8592 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-12-02 13:56:53 -05:00
Vitor Pamplona
1c0ec93cbb Testing the use of just one HttpClient for the entire app. 2023-12-02 13:55:55 -05:00
Vitor Pamplona
c6fa2b5f80 Merge pull request #708 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-12-02 13:46:20 -05:00
Crowdin Bot
dd55ad18e3 New Crowdin translations by GitHub Action 2023-12-02 18:39:06 +00:00
Vitor Pamplona
284da365a1 Merge pull request #707 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-12-02 13:37:59 -05:00
Crowdin Bot
7a06c2e9c4 New Crowdin translations by GitHub Action 2023-12-02 16:21:46 +00:00
Vitor Pamplona
61449774a1 Improves the Redeeming feedback
Improves fee calculation from the mint
2023-12-02 11:18:01 -05:00
Vitor Pamplona
81a3baa41c Merge pull request #706 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-12-01 09:35:18 -05:00
Crowdin Bot
4b7e58dd1c New Crowdin translations by GitHub Action 2023-12-01 14:06:41 +00:00
Vitor Pamplona
14ce42401b Merge pull request #705 from greenart7c3/main
fix zap splits when using amber with intents
2023-12-01 09:05:26 -05:00
greenart7c3
ecb8344287 fix zap splits when using amber with intents 2023-12-01 10:52:15 -03:00
Vitor Pamplona
9bc5549d76 v0.81.5 2023-11-30 17:28:58 -05:00
Vitor Pamplona
8ac8894ccd Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-11-30 17:27:03 -05:00
Vitor Pamplona
efb9814f1b Fixes blocked lists on Videos. 2023-11-30 17:18:41 -05:00
Vitor Pamplona
3582f587b3 Merge pull request #704 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-11-30 17:05:19 -05:00
Crowdin Bot
4fbc9f6d53 New Crowdin translations by GitHub Action 2023-11-30 21:26:37 +00:00
Vitor Pamplona
e9ec1c45a0 v0.81.4 2023-11-30 16:25:07 -05:00
Vitor Pamplona
b2b7cba352 Loads basic information for all the accounts in the app. 2023-11-30 16:24:53 -05:00
Vitor Pamplona
393fbd0359 clean up 2023-11-30 15:17:21 -05:00
Vitor Pamplona
47ae42e3fe Avoiding bug when creating accounts in the background and trying to create the live set 2023-11-30 15:16:21 -05:00
Vitor Pamplona
5db3ede09e Makes Client thread safe. Forcing the disconnect of an old relay list before connecting to a new one. 2023-11-30 15:03:58 -05:00
Vitor Pamplona
eca420d789 Fixing the scope in HomeDataSource. 2023-11-30 15:02:16 -05:00
Vitor Pamplona
5347373cde Avoids sending filters with empty lists. 2023-11-30 14:53:59 -05:00
Vitor Pamplona
05596cb9bf Forces websocket closure onFailure 2023-11-30 14:51:55 -05:00
Vitor Pamplona
3d1310295b No need to call two launch functions 2023-11-30 14:51:13 -05:00
Vitor Pamplona
35c780f81b Avoids bug on creating the live set in the IO thread. 2023-11-30 14:50:24 -05:00
Vitor Pamplona
b021920eaa Emitting an empty list if it cannot decrypt it 2023-11-30 11:22:42 -05:00
Vitor Pamplona
2b27ac3aec Cache zap calculations in notification cards. 2023-11-30 11:22:06 -05:00
Vitor Pamplona
c692c9125b Fixes null list names showing before the list is loaded 2023-11-30 10:33:48 -05:00
Vitor Pamplona
7322fd7aae Fixes hidden buttons in the Chat creation screen. 2023-11-30 10:30:12 -05:00
Vitor Pamplona
07a92cd70d Fixes all or nothing decryption of Zaps failing in a few cases. Now it has a fallback when decryption fails. 2023-11-30 10:15:36 -05:00
Vitor Pamplona
21a797be9d v0.81.3 2023-11-29 17:34:15 -05:00
Vitor Pamplona
fe49cbabce Improves the rendering of LN Invoice Previews. 2023-11-29 17:22:04 -05:00
Vitor Pamplona
9f674a0088 Adds flexibility on timeouts between WIFI and mobile connections. 2023-11-29 17:21:40 -05:00
Vitor Pamplona
b44e94cb16 Adds a test case for urls ending with a period. 2023-11-29 16:50:36 -05:00
Vitor Pamplona
a8da645be3 Increasing timeout to account for slower connections. 2023-11-29 16:50:11 -05:00
Vitor Pamplona
c6e6bf6032 Loads the user profile before building the live set. 2023-11-29 16:14:02 -05:00
Vitor Pamplona
7596f2a43e v0.81.2 2023-11-29 15:13:19 -05:00
Vitor Pamplona
6b7bb209d4 Refinements to ShopStr's event rendering. 2023-11-29 14:56:42 -05:00
Vitor Pamplona
fcdb863c2b Merge pull request #701 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-11-29 10:54:19 -05:00
Crowdin Bot
4e5a9f7366 New Crowdin translations by GitHub Action 2023-11-29 15:52:07 +00:00
Vitor Pamplona
758f3636f3 Merge pull request #700 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-11-29 10:50:54 -05:00
Vitor Pamplona
7dafb8317a version 0.81.1 2023-11-29 10:50:22 -05:00
Crowdin Bot
21a5827719 New Crowdin translations by GitHub Action 2023-11-29 15:40:53 +00:00
Vitor Pamplona
b9486eb3e6 Adds back button to the top of the Nav bar of the Thread view. 2023-11-29 10:38:31 -05:00
Vitor Pamplona
dbbfaae02c Fixes video release coroutine being killed by Android 2023-11-29 10:17:57 -05:00
Vitor Pamplona
44b25b7c7c Refines the EOSE strategy to make sure relays that have not replied have a chance to 2023-11-29 10:06:28 -05:00
Vitor Pamplona
0dabf3f2d3 Scopes the service manager into the AccountState ViewModel 2023-11-29 09:14:04 -05:00
Vitor Pamplona
a85ea70e4f Avoids requesting an empty list of chats 2023-11-28 22:23:34 -05:00
Vitor Pamplona
a02519b021 Forces close to happen in an IO thread 2023-11-28 22:22:28 -05:00
Vitor Pamplona
04e70a7886 Make the afterEOSE logic subscription dependent. 2023-11-28 22:22:08 -05:00
Vitor Pamplona
3bfaef2b45 Using the entire event id to filter threads. 2023-11-28 22:17:24 -05:00
Vitor Pamplona
e992e72f4d Making sure the service manager stops the relay subscriptions before disconnecting. 2023-11-28 22:17:01 -05:00
Vitor Pamplona
1c545ee33a Forces the closure. The method close wasn't closing all connections. 2023-11-28 18:00:44 -05:00
Vitor Pamplona
ab93a39ad6 Avoids race conditions when the data source is supposed to have stopped 2023-11-28 18:00:22 -05:00
Vitor Pamplona
7f25e1c434 Limits Notification downloads to 1 week. 2023-11-28 17:59:28 -05:00
Vitor Pamplona
67b7bd3258 Protection against NPEs 2023-11-28 16:36:27 -05:00
Vitor Pamplona
e2aaa8efe0 Migrates from PAY to NOTIFY as per https://github.com/nostr-protocol/nips/pull/901 2023-11-28 16:07:24 -05:00
Vitor Pamplona
5356d869fd Reduces the amount of wasted memory by using Array<Array<List>> as opposed to List<List<String>> for tags. 2023-11-28 15:00:41 -05:00
Vitor Pamplona
d87542a949 Reduces JC usage by creating arrays with the exact amount of bytes when deserializing events. 2023-11-28 09:37:00 -05:00
Vitor Pamplona
98d29ac6dc v0.81.0 2023-11-28 09:05:25 -05:00
Vitor Pamplona
532048c35e Merge pull request #699 from greenart7c3/main
fix crash tryng to decrypt/parse gossip
2023-11-27 12:49:15 -05:00
greenart7c3
386960dc62 fix crash tryng to decrypt/parse gossip 2023-11-27 14:28:15 -03:00
Vitor Pamplona
ae3cc5da2a Fixing benchmark tests after the refactoring. 2023-11-26 21:10:15 -05:00
Vitor Pamplona
34c2ba4922 Typo 2023-11-26 18:30:29 -05:00
Vitor Pamplona
074a7d41fd Adding payment requests from nostr.wine 2023-11-26 18:00:08 -05:00
Vitor Pamplona
7d4fbc3e04 Reducing the precision to load images. 2023-11-26 17:59:10 -05:00
Vitor Pamplona
a2d38381b1 Runs the translation as a UI Scope instead of ViewModel's 2023-11-26 15:02:10 -05:00
Vitor Pamplona
19fb129f7c Fixing test cases after the mega refactoring 2023-11-26 14:59:00 -05:00
Vitor Pamplona
5bfc53136b updates jackson. 2023-11-25 19:49:51 -05:00
Vitor Pamplona
1677606b15 updating via AGP 2023-11-25 19:46:49 -05:00
Vitor Pamplona
8c10173b68 Merge pull request #698 from greenart7c3/main
fix wrong pubkey in encrypt/decrypt nip44 with external signer
2023-11-25 16:31:42 -05:00
greenart7c3
285ae056a2 fix wrong pubkey in encrypt and decrypt nip44 external signer 2023-11-25 14:28:48 -03:00
Vitor Pamplona
8cdd3be085 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-11-24 12:28:01 -05:00
Vitor Pamplona
8f586780a1 Slightly improving performance 2023-11-24 12:27:52 -05:00
Vitor Pamplona
dc3c730e3b adding some labels to crossfades 2023-11-24 11:54:35 -05:00
Vitor Pamplona
df823102da Typo 2023-11-24 11:53:51 -05:00
Vitor Pamplona
1ab857d72b Merge pull request #697 from greenart7c3/main
support for sending/receiving multiple events from external signer
2023-11-24 10:41:06 -05:00
Vitor Pamplona
78863b26d0 Merge pull request #696 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-11-24 10:40:16 -05:00
Crowdin Bot
0f74bc7b74 New Crowdin translations by GitHub Action 2023-11-24 15:37:59 +00:00
Vitor Pamplona
e7893cacd5 Updating coil 2023-11-24 10:35:02 -05:00
greenart7c3
8a18781048 support for sending/receiving multiple events from external signer 2023-11-24 12:33:10 -03:00
Vitor Pamplona
ad52855f5a Merge pull request #695 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-11-23 21:59:47 -05:00
Crowdin Bot
50fbde17df New Crowdin translations by GitHub Action 2023-11-24 02:29:22 +00:00
Vitor Pamplona
c6d47ca9c6 Merge pull request #694 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-11-23 21:26:55 -05:00
Crowdin Bot
072b14bdda New Crowdin translations by GitHub Action 2023-11-23 15:49:32 +00:00
Vitor Pamplona
70964e680a Migrates to MuteList 10000 2023-11-23 10:46:56 -05:00
Vitor Pamplona
954330064d Trying to save from crashes on the signer 2023-11-22 17:04:57 -05:00
Vitor Pamplona
3666a0b980 Fixes race conditions when opening videos. 2023-11-22 16:29:05 -05:00
Vitor Pamplona
61f52ef62e Trimming memory onStop 2023-11-22 16:10:55 -05:00
Vitor Pamplona
74d66f2035 Fixes logging for new events. 2023-11-22 14:39:01 -05:00
Vitor Pamplona
0de4cd5c18 Adding a geohash mipmap to events. 2023-11-22 12:48:19 -05:00
Vitor Pamplona
d1bef11f88 Fixes spacing when drawing POW and Geolocation at the same time. 2023-11-22 12:37:02 -05:00
Vitor Pamplona
3253b8528f Fix URL Preview card when websites blend OG specs 2023-11-22 12:15:09 -05:00
Vitor Pamplona
81661c003a Fixes the writting of nostr addresses in the text with additional words connected to them without a space. It adds a space if the first char is in the bech alphabet. 2023-11-22 11:40:12 -05:00
Vitor Pamplona
fbe395f071 Adds logs for lifetime events. 2023-11-22 11:00:52 -05:00
Vitor Pamplona
d5cf64f048 Removes log message 2023-11-22 09:54:36 -05:00
Vitor Pamplona
7212d566c9 Fixes the blue notification dot appearing when the user receives a notification from a blocked account before downloading the blocklist 2023-11-22 09:10:15 -05:00
Vitor Pamplona
17490e948c Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-11-22 08:44:53 -05:00
Vitor Pamplona
b392ea0dca Merge pull request #691 from greenart7c3/test_external_signer
Fixes/improvements to external signer
2023-11-22 08:44:46 -05:00
greenart7c3
9fc0c37845 fix relay reconnecting when returning from external signer 2023-11-22 08:33:41 -03:00
greenart7c3
6db031b208 fix sending zaps using amber, send some default permissions on login, save the signer package name 2023-11-22 08:33:41 -03:00
Vitor Pamplona
7246a545af Makes sure it doesn't crash on starting. 2023-11-21 14:17:32 -05:00
Vitor Pamplona
c8365439ee Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-11-21 13:29:51 -05:00
Vitor Pamplona
003d6bf018 Updating dependencies. 2023-11-21 13:29:48 -05:00
Vitor Pamplona
060286c292 Merge pull request #692 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-11-21 10:30:16 -05:00
Crowdin Bot
270935a30a New Crowdin translations by GitHub Action 2023-11-21 15:14:23 +00:00
Vitor Pamplona
05e9a1ac3f Fixes issue with cache of disappearing User Zaps in Notifications 2023-11-20 19:03:34 -05:00
Vitor Pamplona
9acad8b3f5 Narrowing the redownloads of reactions down. 2023-11-20 18:58:25 -05:00
Vitor Pamplona
5a9d6929e5 Make local image behave as remove images. 2023-11-20 15:52:18 -05:00
Vitor Pamplona
e45f02c110 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-11-19 17:58:27 -05:00
Vitor Pamplona
4f1ae72ab5 Merge pull request #690 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-11-19 17:47:22 -05:00
Vitor Pamplona
d4ed6661dd Fixes single click login screen 2023-11-19 17:45:00 -05:00
Crowdin Bot
2976349114 New Crowdin translations by GitHub Action 2023-11-19 22:31:15 +00:00
Vitor Pamplona
b1cfa2219d Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-11-19 17:29:20 -05:00
Vitor Pamplona
df9b764c1d Massive refactoring to unify internal signer and the Amber signer. 2023-11-19 17:28:17 -05:00
Vitor Pamplona
69941002df Adds JUnitRunner after upstream changed packages. 2023-11-18 15:26:48 -05:00
Vitor Pamplona
afc6a91c6b Merge pull request #685 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-11-10 09:12:56 -05:00
Crowdin Bot
c8b9858e4d New Crowdin translations by GitHub Action 2023-11-10 14:07:24 +00:00
Vitor Pamplona
c4ea6f3619 Merge pull request #686 from vicariousdrama/20231110-unabbrev-amounts-up-to-4-digit
Display amounts up to 4 digits without abbreviation
2023-11-10 09:05:43 -05:00
vicariousdrama
872d70c175 Allow amounts up to 4 digits without abbreviation 2023-11-10 07:21:06 +00:00
Vitor Pamplona
5ad6a2c70b Moves service manager to an Activity scoped class. 2023-11-09 15:25:59 -05:00
Vitor Pamplona
408b6793c0 Moves image cache to the Application class 2023-11-09 15:25:27 -05:00
Vitor Pamplona
43d03bc109 Caching total Zaps 2023-11-09 14:26:11 -05:00
Vitor Pamplona
9377c902a1 Moves creation of the LiveData set to a Synchronized block to avoid double creations without destruction. 2023-11-09 14:18:54 -05:00
Vitor Pamplona
57d97447f4 Fix error message when parsing LnInvoice 2023-11-09 14:07:50 -05:00
Vitor Pamplona
5493ce0dcf Updating dependencies 2023-11-09 12:02:28 -05:00
Vitor Pamplona
499149b7d9 Speeds up LNInvoice parsing 2023-11-09 10:56:37 -05:00
Vitor Pamplona
3fd0c61c0e Updating to support all crowdin languages 2023-11-08 17:08:23 -05:00
Vitor Pamplona
1d62d8ed73 v0.80.7 2023-11-08 14:41:07 -05:00
Vitor Pamplona
2c3a7daa65 Fixes bug when the app calls this method directly, bypassing the other checks in AccountViewModel 2023-11-08 14:32:54 -05:00
Vitor Pamplona
1771b6e667 v0.80.6 2023-11-07 17:39:18 -05:00
Vitor Pamplona
853dcb2127 minimizes race condition when pausing and restarting relay connections 2023-11-07 17:38:59 -05:00
Vitor Pamplona
b25f346370 v0.80.5 2023-11-07 16:44:49 -05:00
Vitor Pamplona
edd13fbe5b Uses the indexing operator 2023-11-07 16:31:36 -05:00
Vitor Pamplona
92c72e5a7b Merge pull request #669 from VictorieeMan/patch-1
changing externa sharing service for text notes to njump.me
2023-11-07 10:33:24 -05:00
Vitor Pamplona
e8e676afd5 Merge pull request #683 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-11-07 09:31:23 -05:00
Crowdin Bot
bb16ee7f0f New Crowdin translations by GitHub Action 2023-11-07 14:25:33 +00:00
Vitor Pamplona
4eb1c101b9 Merge pull request #682 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-11-07 09:23:49 -05:00
Crowdin Bot
eb67b6e6cf New Crowdin translations by GitHub Action 2023-11-07 02:19:53 +00:00
Vitor Pamplona
29541bd1e3 Merge pull request #681 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-11-06 21:18:43 -05:00
Crowdin Bot
08f94e9199 New Crowdin translations by GitHub Action 2023-11-07 02:18:14 +00:00
Vitor Pamplona
a7c7773a81 Merge pull request #680 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-11-06 21:16:55 -05:00
Crowdin Bot
75f2d5710a New Crowdin translations by GitHub Action 2023-11-07 02:15:40 +00:00
Vitor Pamplona
2bff9fe891 Merge pull request #679 from vitorpamplona/l10n_crowdin_translations
New Greek Translations
2023-11-06 21:14:07 -05:00
Vitor Pamplona
4d2c405aea Removes unnecessary methods 2023-11-06 20:45:53 -05:00
Crowdin Bot
ca24afd23e New Crowdin translations by GitHub Action 2023-11-07 01:15:03 +00:00
Vitor Pamplona
47e124c7fc Correctly highliting a notification when dragged 2023-11-06 20:13:00 -05:00
Vitor Pamplona
885aded701 Merge pull request #678 from vitorpamplona/l10n_crowdin_translations
New Spanish Translations
2023-11-06 16:38:32 -05:00
Crowdin Bot
e0729b7236 New Crowdin translations by GitHub Action 2023-11-06 21:29:19 +00:00
Vitor Pamplona
a058b75ee4 Refining the padding of chat messages and reaction row 2023-11-06 16:26:38 -05:00
Vitor Pamplona
0a5e84fd3c Refining layout of URL Previews 2023-11-05 11:27:30 -05:00
Vitor Pamplona
6fa36255b2 Refining the layout of Author Pictures 2023-11-05 11:27:15 -05:00
Vitor Pamplona
3de52a6c0d Simplifying Compose stack 2023-11-04 16:48:29 -04:00
Vitor Pamplona
6d17c8d79f Fixing translations of the same term but with different case. 2023-11-04 11:29:47 -04:00
Vitor Pamplona
26c4677b75 Forces reconnection when a new service is available. 2023-11-04 11:23:37 -04:00
Vitor Pamplona
c5882a9f05 Migrates the check if stream is online to a single compose object. 2023-11-04 11:23:18 -04:00
Vitor Pamplona
f99dc471a1 Merge pull request #676 from vitorpamplona/l10n_crowdin_translations
Updated Translations for Arabic, Greek, Spanish, Indonesian and Vietnamese
2023-11-03 17:25:13 -04:00
Crowdin Bot
25e31b00d2 New Crowdin translations by GitHub Action 2023-11-03 21:16:29 +00:00
Vitor Pamplona
c1a59a1d21 Improve position of video controlling buttons when top bars are present. 2023-11-03 17:14:41 -04:00
Vitor Pamplona
e0d2a71b47 Remove a compose recomposition between the started state and the isOnline state that is already cached. 2023-11-03 17:14:10 -04:00
Vitor Pamplona
ef90b82396 Updates Kotlin compiler version 2023-11-03 17:11:16 -04:00
Vitor Pamplona
9ec6e6d955 v0.80.4 2023-10-30 17:31:50 -04:00
Vitor Pamplona
6b7ec2caa9 Starting videos from Main, but in a thread. 2023-10-30 17:31:33 -04:00
Vitor Pamplona
17130c81c8 v0.80.3 2023-10-30 17:05:02 -04:00
Vitor Pamplona
0571312dca Fixing new line of Loading Animation and Download buttons for images. 2023-10-30 16:39:39 -04:00
Vitor Pamplona
717c3bc45e Generalizing InnerReaction Row 2023-10-30 15:44:15 -04:00
Vitor Pamplona
c304f7c69d Typo 2023-10-30 15:43:25 -04:00
Vitor Pamplona
6d2a1ec1b9 Remember's modifiers in animations 2023-10-30 14:57:57 -04:00
Vitor Pamplona
59f7f5257b Adds check in main thread to mark as seen on relays 2023-10-30 14:33:22 -04:00
Vitor Pamplona
ba1f2dc17d Minimizes Jittering when loading videos. 2023-10-30 14:05:36 -04:00
Vitor Pamplona
820def620c Improving rendering of reaction types 2023-10-30 12:52:19 -04:00
Vitor Pamplona
9fef3e9e3e Only updates notification dots once at every 3 seconds. 2023-10-30 12:27:59 -04:00
Vitor Pamplona
e8998a26d7 Follow yourself for new users. 2023-10-30 12:10:31 -04:00
Vitor Pamplona
221ab1ca1a Slight performance improvements 2023-10-30 12:04:10 -04:00
Vitor Pamplona
2f1e67779b Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-10-30 09:35:23 -04:00
Vitor Pamplona
96663b822c Fixing colors of edit buttons 2023-10-30 09:34:43 -04:00
Vitor Pamplona
c7895d1cdd Merge pull request #674 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-10-30 08:58:22 -04:00
Crowdin Bot
85762c581a New Crowdin translations by GitHub Action 2023-10-30 12:44:53 +00:00
Vitor Pamplona
e189a4d68d Merge pull request #673 from greenart7c3/main
fix floatingactionbutton not showing again after changing screens
2023-10-30 08:43:19 -04:00
greenart7c3
3306dd88d2 fix floatingactionbutton not showing again after changing screens 2023-10-30 08:11:38 -03:00
Vitor Pamplona
18952bc8a7 Merge pull request #671 from matata2140/patch-1
Update strings.xml // values-nl
2023-10-28 22:31:43 -04:00
Vitor Pamplona
f6cfba6e1f Login and Logout already in IO threads 2023-10-28 21:26:36 -04:00
matata@nostrplebs.com
fb37ccd14f Update strings.xml // values-nl
fixed a couple translations, typo's and shortened a sentence for a nicer ux
2023-10-29 01:33:07 +02:00
Vitor Pamplona
3858c57816 More Stability improvements to Compose 2023-10-28 18:23:12 -04:00
Vitor Pamplona
572c11e847 Adjusting Stability of composables 2023-10-28 18:19:21 -04:00
Vitor Pamplona
bd70bd708b Stabilizing Note LiveData 2023-10-28 17:51:33 -04:00
Vitor Pamplona
9a2ecfc85d Adds images and posts without and extra line. 2023-10-28 16:58:39 -04:00
Vitor Pamplona
f20fd1aebe Fixes: https://github.com/vitorpamplona/amethyst/issues/629 2023-10-28 16:58:17 -04:00
Vitor Pamplona
2f2914077b Speeding up the boost method 2023-10-28 16:38:12 -04:00
Vitor Pamplona
712d498788 Fixing weird alignment of the Hightligh post title. 2023-10-28 15:38:59 -04:00
Vitor Pamplona
0e51731f69 v0.80.2 2023-10-28 12:36:27 -04:00
Vitor Pamplona
2cc9bb8b72 Slight improvement in the performance of Reaction Row's rendering 2023-10-28 12:31:44 -04:00
Vitor Pamplona
553bebb6cf Reducing the size of Subject labels 2023-10-28 12:14:02 -04:00
Vitor Pamplona
e91e5c366d Refining some of the Markdown to match Material3 Style 2023-10-28 12:07:22 -04:00
Vitor Pamplona
3222f88999 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-10-28 11:10:34 -04:00
Vitor Pamplona
9d32718c13 Update Profile Feed when Blocking/Unblocking the user. 2023-10-28 11:08:48 -04:00
Vitor Pamplona
9664e2f042 Removes log line. 2023-10-28 10:51:07 -04:00
Vitor Pamplona
979c04c303 Merge pull request #670 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-10-28 10:25:33 -04:00
Crowdin Bot
725baa8776 New Crowdin translations by GitHub Action 2023-10-28 14:24:43 +00:00
Vitor Pamplona
64c9505620 Reverts the New Post button animation due to bugs of not coming back 2023-10-28 10:22:50 -04:00
Vitor Pamplona
55db7221ad Updates dependencies 2023-10-28 10:22:01 -04:00
Vitor Pamplona
75dc55858c Fixes the use of decimals on Notification's chart 2023-10-28 10:08:06 -04:00
VictorieeMan
1f28d3f32f changing externa sharing service for text notes to njump.me
Changed "https://snort.social/e/" to "https://njump.me/"

Benefits of this change are the link previews that njump.me generates for shared content. The snort social links are just the url root and a long nevent, making different shares difficult to tell apart, and a bit scary to click on for some.

More benefits of njump.me listed on https://njump.me/, hosted by fiatjaf. The included nostr onboarding paired with client agnosticism is also beneficial.
2023-10-28 12:12:31 +02:00
Vitor Pamplona
c606212043 Reverts the hidden note LiveData to make sure the interface doesn't blink with the hidden note that just disappears ms later. 2023-10-27 17:58:40 -04:00
Vitor Pamplona
2ccf7ec2f0 Merge pull request #668 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-10-27 15:27:14 -04:00
Crowdin Bot
2baad54660 New Crowdin translations by GitHub Action 2023-10-27 19:24:26 +00:00
Vitor Pamplona
46cca5fd49 Merge pull request #667 from davotoula/updated_translations
Updated translations cs/de/sv/pt
2023-10-27 15:22:46 -04:00
David Kaspar
bb32477671 Updated translations for cs/de/sv/pt 2023-10-27 20:15:20 +01:00
David Kaspar
e89384ee61 fix typo in resource string name 2023-10-27 20:07:18 +01:00
Vitor Pamplona
b213137e7a v0.80.1 2023-10-27 14:02:40 -04:00
Vitor Pamplona
8fab00300a Fixes Benchmark tests 2023-10-27 14:01:12 -04:00
Vitor Pamplona
92a39c4305 Brings notifications back 2023-10-27 13:58:26 -04:00
Vitor Pamplona
116bb19bc6 v0.80.0 2023-10-27 13:12:50 -04:00
Vitor Pamplona
ce54d47f46 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-10-27 13:06:13 -04:00
Vitor Pamplona
6a8c756f7a Adds an explainer to install UnifiedPush apps if they are not installed. 2023-10-27 13:05:47 -04:00
Vitor Pamplona
64921ab240 Merge pull request #666 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-10-27 09:44:08 -04:00
Crowdin Bot
ab01113d0e New Crowdin translations by GitHub Action 2023-10-27 13:28:47 +00:00
Vitor Pamplona
26752084ae Merge pull request #665 from davotoula/additional_translations
added push notification translations to SV/DE/PT
2023-10-27 09:27:14 -04:00
David Kaspar
84bc9745be added to push notification translations to SV/DE/PT 2023-10-27 12:57:22 +01:00
Vitor Pamplona
b535fde0ff Merge pull request #664 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-10-26 19:31:41 -04:00
Crowdin Bot
424cbfcf1a New Crowdin translations by GitHub Action 2023-10-26 22:56:04 +00:00
Vitor Pamplona
56af44b00b - Makes sure to offer a None option on the PushNotification Distributor List
- Makes sure to not ask again if the person has already replied.
- Makes sure to not ask if there is no Unified Push app installed.
- Moves the code to a Component instead of a Custom Screen.
- Adds i18n messaging.
- Uses the existing Spinner Dialog for consistency
2023-10-26 18:53:42 -04:00
Vitor Pamplona
3b93198219 Removing Stop with Task from PushNotifications 2023-10-26 17:17:46 -04:00
Vitor Pamplona
98bb30fa59 Merge pull request #652 from KotlinGeekDev/oss-push-notifications
Oss push notifications(using UnifiedPush)
2023-10-26 17:16:44 -04:00
Vitor Pamplona
3ffb43539f Merge pull request #663 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-10-26 09:47:37 -04:00
Crowdin Bot
e3e989de53 New Crowdin translations by GitHub Action 2023-10-26 13:33:46 +00:00
Vitor Pamplona
86e34d4681 Merge pull request #662 from davotoula/br_translation
added to BR translations
2023-10-26 09:32:11 -04:00
David Kaspar
a0b79d1d3b added to BR translations 2023-10-26 14:26:55 +01:00
Vitor Pamplona
75ec92aff4 Merge pull request #661 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-10-26 08:56:31 -04:00
Crowdin Bot
ab38a369da New Crowdin translations by GitHub Action 2023-10-26 12:32:49 +00:00
Vitor Pamplona
460a99d95d Avoids creation of the LiveData in every recomposition. 2023-10-25 17:22:26 -04:00
Vitor Pamplona
a66e14f3eb Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-10-25 16:15:48 -04:00
Vitor Pamplona
dd1ade2f99 Avoids recompositions 2023-10-25 16:07:58 -04:00
Vitor Pamplona
177c98efb7 Merge pull request #659 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-10-25 15:35:10 -04:00
Crowdin Bot
8830ad3c27 New Crowdin translations by GitHub Action 2023-10-25 19:01:28 +00:00
Vitor Pamplona
903384d02a Making sure ViewModels are deleted when switching accounts. 2023-10-25 14:55:48 -04:00
Vitor Pamplona
4a8c020c3d Only call flows when there are new events to process. 2023-10-25 14:29:08 -04:00
Vitor Pamplona
4aaf25a384 Adds Lifecycle to all Flow object in compose. 2023-10-25 14:08:26 -04:00
Vitor Pamplona
a2f0c7f548 Merge pull request #657 from greenart7c3/nip-98
fix crash when uploading images/videos using external signer
2023-10-23 15:05:43 -04:00
greenart7c3
75bd97d0ae fix crash when uploading images/videos using external signer 2023-10-23 16:01:43 -03:00
Vitor Pamplona
f072b98fd7 Recreates the viewModel when the Account object changes. 2023-10-23 14:32:22 -04:00
Vitor Pamplona
d3d2845f10 v0.79.13 2023-10-23 13:07:47 -04:00
Vitor Pamplona
6831349f2f Slight adjustment on the rendering of hashtags. 2023-10-23 12:22:42 -04:00
Vitor Pamplona
5b0fc7982b Moves Relay and User Metadata update buttons from Post to Save. 2023-10-23 11:30:33 -04:00
Vitor Pamplona
10a0dc7f8a Fixes status update field when more than one status is available. 2023-10-23 11:29:59 -04:00
Vitor Pamplona
f92e13270d Solves NPE when the TextToSpeech engine isn't ready. 2023-10-23 11:15:33 -04:00
Vitor Pamplona
9dfb4d1a1b Making sure the UI update from language is in the Main thread. 2023-10-23 11:09:47 -04:00
Vitor Pamplona
91bfb60613 Update UI dependencies 2023-10-22 17:29:05 -04:00
Vitor Pamplona
191254d920 Makes sure only one npub is logged in at the same time 2023-10-22 17:16:06 -04:00
KotlinGeekDev
6dc82815b6 Cleanup endpoint URL before sending to push server(and storing it locally). 2023-10-22 17:45:44 +01:00
Vitor Pamplona
eb6e81f81e v0.79.12 2023-10-21 23:53:21 -04:00
Vitor Pamplona
19b3bca86a Uses stable version of accompanist 2023-10-21 23:52:50 -04:00
Vitor Pamplona
80df2eefed v0.79.11: Tablet view on chats 2023-10-21 16:42:41 -04:00
Vitor Pamplona
884a124c7e TwoPane display for chats in tablets and folds. 2023-10-21 16:23:34 -04:00
Vitor Pamplona
a284c1b9c6 Fixes orientation changes when in full screen 2023-10-21 16:22:20 -04:00
Vitor Pamplona
ccf428eff6 Updates Jsoup 2023-10-21 11:33:20 -04:00
Vitor Pamplona
96faac5aad v0.79.10 2023-10-20 21:58:04 -04:00
Vitor Pamplona
7060aa3ed0 Testing full dark 2023-10-20 21:57:48 -04:00
Vitor Pamplona
45a749e4bf v0.79.9 2023-10-20 18:11:53 -04:00
Vitor Pamplona
3321448dd2 Solving one of the OutOfMemory erros (too many translators instantiated at the same time) 2023-10-20 18:11:09 -04:00
Vitor Pamplona
893b88246e v0.79.8 2023-10-20 15:55:59 -04:00
Vitor Pamplona
8065b942bd Fixes the spacing of the account switcher to avoid getting too close to navigation buttons. 2023-10-20 15:54:37 -04:00
Vitor Pamplona
a1a2118b35 Removes debug color 2023-10-20 15:54:00 -04:00
Vitor Pamplona
17e59c5ae8 Fixes full screen dialog 2023-10-20 14:18:12 -04:00
Vitor Pamplona
39d84e33bb Activates singleTap to double zoom in images 2023-10-20 13:54:58 -04:00
Vitor Pamplona
87e8948d9a Fixes caching issue on the list selection in the top bar 2023-10-20 13:27:24 -04:00
Vitor Pamplona
8317a06b6f Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-10-20 13:21:10 -04:00
Vitor Pamplona
1ab93adc22 Reduces the amount of competing threads to restart connections with relays. 2023-10-20 12:37:05 -04:00
Vitor Pamplona
af100fa0b4 Merge pull request #654 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-10-20 10:43:29 -04:00
Crowdin Bot
66443d029b New Crowdin translations by GitHub Action 2023-10-20 14:28:34 +00:00
Vitor Pamplona
6fe713107e Merge pull request #653 from greenart7c3/double_encryption_fix_2
fix double encryption when sending dms, when login with external signer set privKey to null to be sure we have no private keys
2023-10-20 10:27:17 -04:00
greenart7c3
800c0b0131 fix double encryption when sending dms, when login with external signer set privKey to null to be sure we have no private keys 2023-10-20 10:58:56 -03:00
KotlinGeekDev
e1a3975a07 Move NotificationScreen back and rework it in the manner of TranslatableRichTextViewer. 2023-10-20 03:40:33 +01:00
KotlinGeekDev
33bf305ab5 Add some padding to individual list items. 2023-10-19 13:25:09 +01:00
KotlinGeekDev
14ff6f03bf Merge remote-tracking branch 'origin/oss-push-notifications' into oss-push-notifications 2023-10-19 12:34:35 +01:00
KotlinGeekDev
68e91e405a Move NotificationScreen to different flavors to integrate Distributor dialog selection. Make some adjustments for handling changes to push distributors, and other fixes. 2023-10-19 12:33:43 +01:00
KotlinGeekDev
7b22b96968 Change getEndpoint function name to avoid clashing method signatures. 2023-10-19 12:33:43 +01:00
KotlinGeekDev
26107ff5e9 Introduce PushDistributorHandler and wire up PushMessageReceiver and PushNotificationUtils. 2023-10-19 12:33:43 +01:00
KotlinGeekDev
18931fb743 Introduce PushMessageReceiver and set up manifest. 2023-10-19 12:33:43 +01:00
KotlinGeekDev
f68f32f942 Add UnifiedPush dependency. 2023-10-19 12:33:43 +01:00
Vitor Pamplona
2892fa6fca v0.79.7 2023-10-18 18:27:35 -04:00
Vitor Pamplona
27286c7ffe Removing bold titles 2023-10-18 18:26:31 -04:00
Vitor Pamplona
d9b0fbe928 Merge pull request #636 from greenart7c3/main
fix floatingActionButton not hiding when scrolling
2023-10-18 18:11:26 -04:00
Vitor Pamplona
b15f203bc1 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-10-18 18:04:18 -04:00
Vitor Pamplona
5d266cca20 - Moves app startup to an IO thread.
- Upgrades Shared Preferences serialization to a Single JSON object
- Simplifies Shared Preferences state changes
- LazyInitializes Video cache
2023-10-18 18:04:07 -04:00
KotlinGeekDev
904b070306 Move NotificationScreen to different flavors to integrate Distributor dialog selection. Make some adjustments for handling changes to push distributors, and other fixes. 2023-10-18 17:07:26 +01:00
Vitor Pamplona
37d4efd7ba Merge pull request #651 from greenart7c3/test
fix crash when sending giftwraps with amber
2023-10-18 08:22:55 -04:00
greenart7c3
ece8998ba6 fix crash when sending giftwraps with amber 2023-10-18 09:07:08 -03:00
KotlinGeekDev
3f5000f278 Change getEndpoint function name to avoid clashing method signatures. 2023-10-18 03:30:02 +01:00
KotlinGeekDev
68f4752c66 Introduce PushDistributorHandler and wire up PushMessageReceiver and PushNotificationUtils. 2023-10-18 03:20:22 +01:00
Vitor Pamplona
904a50be1f v0.79.6 2023-10-17 18:30:50 -04:00
Vitor Pamplona
35f6ecad59 Stops PushNotifications when the app is killed. 2023-10-17 18:10:10 -04:00
Vitor Pamplona
2a328ca120 Dump memory states to debug OOO 2023-10-17 18:09:58 -04:00
Vitor Pamplona
1e83dbfbe3 Only changes Username if value changes. 2023-10-17 18:09:39 -04:00
Vitor Pamplona
e703c08634 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-10-17 16:33:21 -04:00
Vitor Pamplona
f8a574375a Updating Jackson 2023-10-17 16:33:16 -04:00
Vitor Pamplona
cfcafe5b2c Merge pull request #650 from believethehype/patch-1
Added #thenostr hashtag icon
2023-10-17 16:15:31 -04:00
believethehype
3ea7b8194d Added #thenostr hashtag icon 2023-10-17 22:13:39 +02:00
Vitor Pamplona
1a7ae33fa8 Activates color for the zaps in the Notification chart 2023-10-17 16:13:28 -04:00
Vitor Pamplona
2bbe126c8d Configuration cache was creating a lot of build issues 2023-10-17 15:39:36 -04:00
Vitor Pamplona
f2e6efe2b7 Improving Git hooks 2023-10-17 15:36:26 -04:00
Vitor Pamplona
404e6cd862 Moves playback services to a package 2023-10-17 15:23:43 -04:00
Vitor Pamplona
4ab04477f8 v0.79.5 2023-10-17 11:14:50 -04:00
Vitor Pamplona
611e8f1a6d Forces a filter reset after authentication 2023-10-16 14:39:05 -04:00
Vitor Pamplona
c8fd810bd3 Adds log of bad signature event. 2023-10-16 14:38:31 -04:00
Vitor Pamplona
c619a9000c Resolving a duplicated entry on relay list in Note. 2023-10-16 12:07:17 -04:00
Vitor Pamplona
3d70614797 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-10-16 12:05:52 -04:00
Vitor Pamplona
c29b4b8e5f Avoids testing the signature when the id or sig fields are blank 2023-10-16 12:05:48 -04:00
Vitor Pamplona
4286b64b41 Improves the feedback to messages from relays. 2023-10-16 11:54:14 -04:00
Vitor Pamplona
e8c50cbf54 Merge pull request #649 from jiftechnify/handle-geohash-error
Add exception handling for parsing geohash
2023-10-16 09:22:21 -04:00
jiftechnify
407807d871 add exception handling for parsing geohash 2023-10-16 16:52:28 +09:00
Vitor Pamplona
202af650de v0.79.4 2023-10-15 18:07:57 -04:00
Vitor Pamplona
e1e42ed500 Only adds a border to video controls when in full screen 2023-10-15 18:07:40 -04:00
Vitor Pamplona
1767cc74a9 Activates images controllers on click 2023-10-15 17:15:48 -04:00
Vitor Pamplona
4028018605 Adds a border in the image dialog to avoid overriding controllers. 2023-10-15 17:07:35 -04:00
Vitor Pamplona
33f8b6d6d8 Trying to fix the image bleed into the previous and next page in the Video feed. 2023-10-15 17:07:02 -04:00
Vitor Pamplona
c738436ddc Merge pull request #647 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-10-15 15:43:21 -04:00
Crowdin Bot
467174ebf8 New Crowdin translations by GitHub Action 2023-10-15 19:42:54 +00:00
Vitor Pamplona
f9fed8a04f Update dependencies 2023-10-15 15:41:24 -04:00
Vitor Pamplona
00194c2f0d Organize imports 2023-10-15 15:35:49 -04:00
Vitor Pamplona
37be1e8c46 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-10-14 14:52:24 -04:00
Vitor Pamplona
357f8f6f94 Merge pull request #646 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-10-14 14:51:09 -04:00
Vitor Pamplona
ba4a594a41 Fixes all the other mute list feeds 2023-10-14 14:50:54 -04:00
Crowdin Bot
928a87363d New Crowdin translations by GitHub Action 2023-10-14 18:47:24 +00:00
Vitor Pamplona
1708c48b0c Merge pull request #639 from davotoula/bugfix_mute_feed_is_always_empty
Bugfix mute feed is always empty
2023-10-14 14:46:05 -04:00
KotlinGeekDev
17adbf3603 Introduce PushMessageReceiver and set up manifest. 2023-10-12 19:48:54 +01:00
KotlinGeekDev
57ff5c63b0 Add UnifiedPush dependency. 2023-10-12 18:36:59 +01:00
Vitor Pamplona
4f4cab6a6c Merge pull request #642 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-10-11 15:34:34 -04:00
Crowdin Bot
e848b58a60 New Crowdin translations by GitHub Action 2023-10-11 19:26:44 +00:00
Vitor Pamplona
5c8f0ad5ce Merge pull request #641 from greenart7c3/double_encryption_fix
fix double encryption on nip04 using amber
2023-10-11 15:25:20 -04:00
greenart7c3
173245d900 fix double encryption on nip04 2023-10-11 15:14:10 -03:00
Vitor Pamplona
dd2e590475 Merge pull request #640 from greenart7c3/encryption_amber
try to fix messages being encrypted twice using amber
2023-10-09 12:14:13 -04:00
greenart7c3
5bc4aab8d8 try to fix messages being encrypted twice 2023-10-09 11:38:29 -03:00
greenart7c3
94308a6098 Merge branch 'vitorpamplona:main' into main 2023-10-09 12:45:42 +00:00
David Kaspar
c7861dfac4 change mute test to equality with string including event 30000 and user hex 2023-10-09 13:53:09 +02:00
David Kaspar
071df0b6d3 change equality test of Mute list to regular expression 2023-10-09 13:13:10 +02:00
David Kaspar
ac0fbc7435 change equality test of Mute list from equals "mute" to ends with mute" 2023-10-09 13:01:32 +02:00
Vitor Pamplona
275051ed30 Fixes visibility of the bottom and top bar when the user comes back to the app. 2023-10-06 16:37:55 -04:00
Vitor Pamplona
3c4cf03684 Merge pull request #638 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-10-06 16:37:14 -04:00
Crowdin Bot
2f1c221a7c New Crowdin translations by GitHub Action 2023-10-06 20:29:37 +00:00
Vitor Pamplona
6748abbf70 Fixes failure to load long form content with d tags reserved url chars 2023-10-06 16:27:40 -04:00
Vitor Pamplona
e04a35afed Fixes bug of not immediately loading chat rooms 2023-10-06 16:27:09 -04:00
greenart7c3
f574a1dae5 fix floatingActionButton not hiding 2023-10-06 07:01:49 -03:00
Vitor Pamplona
f67ff43eb3 Moves the Post button on chat screens to a > Button 2023-10-04 09:20:46 -04:00
Vitor Pamplona
55a4b1937f v0.79.3 2023-10-03 11:50:42 -04:00
Vitor Pamplona
b8b41f840a Hide's the Video Full Screen dialog buttons together with video controls. 2023-10-03 11:50:22 -04:00
Vitor Pamplona
9f5a71020d Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-10-03 10:21:15 -04:00
Vitor Pamplona
e8c9e73985 Fixes the saving of the video position between screens 2023-10-03 10:21:06 -04:00
Vitor Pamplona
e0dba87286 Merge pull request #632 from atrifat/update-indonesian-translation
Update Indonesian translation
2023-10-03 09:47:45 -04:00
Vitor Pamplona
3c308788d8 Merge pull request #635 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-10-03 08:55:05 -04:00
Crowdin Bot
3d28715713 New Crowdin translations by GitHub Action 2023-10-03 12:52:46 +00:00
Vitor Pamplona
61d2030934 Merge pull request #634 from davotoula/main
Updated translations for cs/de/sv
2023-10-03 08:51:26 -04:00
David Kaspar
56c67b9ec6 Updated translations for cs/de/sv 2023-10-03 12:07:11 +02:00
David Kaspar
77ed529c26 Updated translations for cs/de/sv 2023-10-03 11:58:38 +02:00
Vitor Pamplona
7eddf4a12a Moves Following icon from crossfade to animatedVisibility. 2023-10-02 18:11:05 -04:00
Vitor Pamplona
ff69a4168b Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-10-02 17:43:43 -04:00
Vitor Pamplona
cec204b7ae Breaks down Compose components in the Discovery tab. 2023-10-02 17:43:38 -04:00
Vitor Pamplona
188ef3762d Allows Base64 images on profiles. 2023-10-02 17:31:34 -04:00
Vitor Pamplona
64c9acb4b2 Removes duplicated method 2023-10-02 17:30:43 -04:00
Vitor Pamplona
c25018bb64 Merge pull request #633 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-10-02 15:27:37 -04:00
Crowdin Bot
c1a5b855df New Crowdin translations by GitHub Action 2023-10-02 19:18:03 +00:00
Vitor Pamplona
0da031fae4 Fixes bug of messages not reappearing after memory trimming. 2023-10-02 15:07:08 -04:00
Vitor Pamplona
72dff060d2 Moves activeOnScreen calculations to a LaunchedEffect 2023-10-02 14:45:04 -04:00
Vitor Pamplona
d6f4ffafa1 Only changes shouldShow if the value is different. 2023-10-02 14:44:29 -04:00
Vitor Pamplona
4b36217699 Moves audiothumbnail loader to the viewModel scope 2023-10-02 14:43:49 -04:00
Rif'at Ahdi R
9a109e6fc1 Update Indonesian translation 2023-10-02 09:17:26 +08:00
Vitor Pamplona
227aac5b76 v0.79.2 2023-10-01 12:07:51 -04:00
Vitor Pamplona
82ea72d2d1 Removes last mention to a string 2023-10-01 12:07:17 -04:00
Vitor Pamplona
f1637c3d20 v0.79.1 2023-10-01 11:42:53 -04:00
Vitor Pamplona
07be841246 waits 3 seconds before starting the rest. 2023-10-01 11:42:47 -04:00
Vitor Pamplona
3ce5d92556 Making sure shared flows don't suspend. 2023-10-01 11:42:31 -04:00
Vitor Pamplona
8f11396e00 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-10-01 11:29:30 -04:00
Vitor Pamplona
2259523387 Merge pull request #630 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-10-01 11:29:25 -04:00
Vitor Pamplona
d67711b123 Speeds up cold startup. 2023-10-01 11:28:59 -04:00
Vitor Pamplona
c89ca51a1b Updates dependencies 2023-10-01 11:10:37 -04:00
Crowdin Bot
c5c951dd59 New Crowdin translations by GitHub Action 2023-10-01 15:09:21 +00:00
Vitor Pamplona
9f68f0227e Moves many Toasts to better designed Information Dialogs. 2023-10-01 11:06:05 -04:00
Vitor Pamplona
7faed2ddd3 stringResource seems to be slower than context.getString 2023-09-30 18:46:21 -04:00
Vitor Pamplona
7dceb701b2 Moves check if it is online to the viewModel scope 2023-09-30 18:45:58 -04:00
Vitor Pamplona
e454ccc326 Uses the "host" property as the creator of the stream. 2023-09-30 17:43:46 -04:00
Vitor Pamplona
bac50668e8 Speeds the composition of the Topbar 2023-09-30 17:23:27 -04:00
Vitor Pamplona
ff9e1556d5 Increases the performance of the Bottom bar's Notification dot calculations 2023-09-30 16:24:51 -04:00
Vitor Pamplona
dffb49b071 Uses Lists name instead of d-tag on the Top Bar 2023-09-30 11:45:46 -04:00
Vitor Pamplona
7387d9060f Improves error zap message screens for Material3 2023-09-30 11:37:23 -04:00
Vitor Pamplona
52e1842174 Fixes the repeat payments when the NWC is not setup correctly. 2023-09-30 11:17:17 -04:00
Vitor Pamplona
d738e5cbaf v0.79.0 2023-09-29 16:27:04 -04:00
Vitor Pamplona
386b6db5ff Fixes relay type loading from the default list when they are not present in the user's account yet. 2023-09-29 16:23:42 -04:00
Vitor Pamplona
47d57e5a44 Only adds search relays if none of the current relays are active for search. 2023-09-29 16:09:11 -04:00
Vitor Pamplona
92068ca64f Fixing the inclusion of search relays 2023-09-29 16:03:59 -04:00
Vitor Pamplona
349510e900 Updates gradle plugin 2023-09-29 15:48:24 -04:00
Vitor Pamplona
948d0f4bea Merge pull request #627 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-09-29 14:41:14 -04:00
Crowdin Bot
b9a5586167 New Crowdin translations by GitHub Action 2023-09-29 18:30:00 +00:00
Vitor Pamplona
54edddbd2d Migrates to Material 3 2023-09-29 13:57:10 -04:00
Vitor Pamplona
b9c83426dc Merge pull request #624 from greenart7c3/main
add settings to load profile pictures only on wifi,never or always
2023-09-27 14:30:44 -04:00
greenart7c3
40dae875b8 Merge branch 'main' of https://github.com/greenart7c3/amethyst 2023-09-27 10:48:53 -03:00
greenart7c3
e762ad5e18 add settings to load profile pictures 2023-09-27 10:48:26 -03:00
Vitor Pamplona
9b1bd2127f Merge pull request #623 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-09-26 11:07:27 -04:00
Crowdin Bot
88701a97c7 New Crowdin translations by GitHub Action 2023-09-26 15:03:50 +00:00
Vitor Pamplona
600c927594 v0.78.2 2023-09-26 11:01:42 -04:00
Vitor Pamplona
1387a0f62b Adds note to make sure we know the callback of a prepare video runs in the main thread. 2023-09-26 10:56:28 -04:00
Vitor Pamplona
e3df94338f Fixes the access to playback state from the wrong thread 2023-09-26 10:55:31 -04:00
Vitor Pamplona
ee466aa1e4 v0.78.1 2023-09-25 18:28:48 -04:00
Vitor Pamplona
9704d61a7a more remembers 2023-09-25 18:28:35 -04:00
Vitor Pamplona
69d7e82b71 Increasing video cache from 90 to 150MB 2023-09-25 17:36:57 -04:00
Vitor Pamplona
288d80d163 only updates reports for a different note 2023-09-25 17:26:41 -04:00
Vitor Pamplona
b1edf4e934 Improving the Stability of VideoView 2023-09-25 17:09:36 -04:00
Vitor Pamplona
af9b0b444c Fix for not clearing the new post message. It adds a delay to allow the composer to save the viewModel after calling cancel 2023-09-25 15:29:13 -04:00
Vitor Pamplona
a3865e68bd Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-09-25 14:27:45 -04:00
Vitor Pamplona
ed70585e90 Merge pull request #620 from jiftechnify/fix-relay-content-link
Fix contact link in relay information dialog
2023-09-25 14:27:38 -04:00
Vitor Pamplona
f707fd007b Merge pull request #622 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-09-25 14:26:39 -04:00
Crowdin Bot
d92e30dba3 New Crowdin translations by GitHub Action 2023-09-25 18:22:35 +00:00
Vitor Pamplona
4afa5c1789 Merge pull request #621 from greenart7c3/main
add notifications for users of amber
2023-09-25 14:21:10 -04:00
Vitor Pamplona
e89e8e5d01 moves mark as read to the AccountViewModel scope. 2023-09-25 14:19:27 -04:00
greenart7c3
52f600485b add notifications for users of amber 2023-09-25 14:55:44 -03:00
jiftechnify
b5a0d65f3c fix contact link in relay information dialog 2023-09-26 00:49:00 +09:00
Vitor Pamplona
fc4433e7ae Adds NIP19 parser to the AccountViewModel thread scope 2023-09-25 11:35:39 -04:00
Vitor Pamplona
f2b6a9bedb Avoids creating nip94 and nip95 events with blank alts 2023-09-25 11:12:02 -04:00
Vitor Pamplona
35f0b1291f Performance Improvements to PreviewCards 2023-09-25 11:04:53 -04:00
Vitor Pamplona
045699ecd9 Disable swipe to change page in the hope page 2023-09-25 10:28:08 -04:00
Vitor Pamplona
74a2b46508 Forces the presence of the name field in kind 1 as per https://github.com/nostr-protocol/nips/pull/794 2023-09-25 10:11:25 -04:00
Vitor Pamplona
feaa594e52 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-09-25 09:55:28 -04:00
Vitor Pamplona
d966541ea7 Updating dependencies 2023-09-25 09:54:58 -04:00
Vitor Pamplona
ecfc287871 Merge pull request #619 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-09-25 08:50:35 -04:00
Crowdin Bot
c10461126a New Crowdin translations by GitHub Action 2023-09-25 12:45:27 +00:00
Vitor Pamplona
20903cefc8 Merge pull request #618 from davotoula/main
Updated translations for cs/de/sv
2023-09-25 08:44:11 -04:00
David Kaspar
e1caf40c3a Updated translations for cs/de/sv 2023-09-25 11:13:05 +02:00
Vitor Pamplona
6e70034758 v0.78.0 2023-09-24 18:40:15 -04:00
Vitor Pamplona
ee30ff28f6 UI Improvements for Hidden Words 2023-09-24 18:36:43 -04:00
Vitor Pamplona
03654b5ebd Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-09-24 18:14:44 -04:00
Vitor Pamplona
7071174aed BugFix for restarting the relay connection when switching accounts after Amber's integration. 2023-09-24 18:12:50 -04:00
Vitor Pamplona
2c27531056 Merge pull request #617 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-09-24 15:27:58 -04:00
Crowdin Bot
57d5556728 New Crowdin translations by GitHub Action 2023-09-24 19:13:23 +00:00
Vitor Pamplona
f4da2ae6be Mute keywords 2023-09-24 15:10:50 -04:00
Vitor Pamplona
57dfe3af8c Reverting to have videos starting from the IO thread. 2023-09-24 10:35:51 -04:00
Vitor Pamplona
618d14a965 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-09-23 14:19:41 -04:00
Vitor Pamplona
ee95942289 Merge pull request #615 from greenart7c3/main
only show backup keys if account has a private key
2023-09-23 12:11:03 -04:00
Vitor Pamplona
c6c15c3ec7 Adding an option to avoid immersive scrolling 2023-09-23 12:10:17 -04:00
greenart7c3
ed4c51b664 Merge branch 'main' of https://github.com/greenart7c3/amethyst 2023-09-23 12:40:17 -03:00
greenart7c3
b3f39434ee only show backup keys if account has a private key 2023-09-23 12:24:17 -03:00
Vitor Pamplona
30ded17581 v0.77.8 2023-09-22 16:57:14 -04:00
Vitor Pamplona
19557bf358 Filters zap payments outside the established min-max parameters on polls. 2023-09-22 16:50:25 -04:00
Vitor Pamplona
bdc2cbbb99 Adds Mutiny button 2023-09-22 16:23:19 -04:00
Vitor Pamplona
82e2d15aaf Moves Live streaming from the top bar to the screen to avoid cancelling the video on scrolling. 2023-09-22 14:51:21 -04:00
Vitor Pamplona
6aff31886e Fixes website URLs without schema (http://, https://, etc) 2023-09-22 14:37:51 -04:00
Vitor Pamplona
7cc089f0ee Video playback creation must be run in the main thread :( 2023-09-22 14:19:29 -04:00
Vitor Pamplona
6c025f7274 Speeding up the display of unused hashtags 2023-09-22 14:19:07 -04:00
Vitor Pamplona
d5220324c4 Turns out the lifecycle owner changes quite a bit and thus it's a requirement to make it the key of a Disposable Effect. 2023-09-22 13:46:30 -04:00
Vitor Pamplona
a0308bd3a1 Merge pull request #614 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-09-22 12:18:34 -04:00
Crowdin Bot
856b4ca2c1 New Crowdin translations by GitHub Action 2023-09-22 15:55:45 +00:00
Vitor Pamplona
8abfd10f0c Merge pull request #613 from greenart7c3/main
update pt-br translations
2023-09-22 11:54:13 -04:00
greenart7c3
1bc4d33bb7 Merge branch 'vitorpamplona:main' into main 2023-09-22 11:27:48 -03:00
greenart7c3
35c67f692a update pt-br translations 2023-09-22 11:11:47 -03:00
Vitor Pamplona
a319902cf7 Merge pull request #612 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-09-22 09:47:54 -04:00
Crowdin Bot
2bc8d26b4f New Crowdin translations by GitHub Action 2023-09-22 13:40:33 +00:00
Vitor Pamplona
402da58391 Merge pull request #611 from greenart7c3/main
fix crash when editing account
2023-09-22 09:39:28 -04:00
Vitor Pamplona
b533afe27f Merge pull request #610 from davotoula/main
Updated translations for cs/de/sv
2023-09-22 09:39:05 -04:00
greenart7c3
6a4afb45dc fix crash when editing account 2023-09-22 05:13:47 -03:00
David Kaspar
73a718e6c7 Updated translations for cs/de/sv 2023-09-22 09:29:58 +02:00
Vitor Pamplona
140f6e3318 Refactoring to move markdown parser away from the Compose Class 2023-09-21 16:57:43 -04:00
Vitor Pamplona
073add9e71 Reduce padding of custom emojis 2023-09-21 14:30:56 -04:00
Vitor Pamplona
35ecf1f7a7 v0.77.7 2023-09-21 14:15:25 -04:00
Vitor Pamplona
71db62e5a5 Resets the bar visibility when switching screens. 2023-09-21 14:14:40 -04:00
Vitor Pamplona
ff82b52a5b Removes the need for the payment popup for only one invoice. 2023-09-21 14:03:38 -04:00
Vitor Pamplona
18e81de26d v0.77.6 2023-09-21 10:38:02 -04:00
Vitor Pamplona
27f37fc158 Removes the flickering on chat screens when the bottom bar disappears. 2023-09-21 10:32:06 -04:00
Vitor Pamplona
6638ae1d7b no need for coroutines on nav anymore 2023-09-21 09:20:11 -04:00
Vitor Pamplona
42094c2a70 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-09-21 09:09:35 -04:00
Vitor Pamplona
932abdd412 Fixes video keep playing bug when pressing the bottom bar twice. 2023-09-21 09:09:24 -04:00
Vitor Pamplona
b4bb6f2b15 Merge pull request #608 from davotoula/main
"show more" text folding enhancement
2023-09-21 08:19:02 -04:00
David Kaspar
4c7b523de1 Merge remote-tracking branch 'origin/show_more_enhancement' into show_more_enhancement 2023-09-21 08:47:40 +02:00
David Kaspar
59608e9acc Combine new line limit with previous character checking (use the smallest) 2023-09-21 08:47:09 +02:00
David Kaspar
77afedb2d0 Introduced line limit in addition to existing character limit for "show more" folding of text 2023-09-21 08:47:09 +02:00
David Kaspar
ccb2c626a7 Combine new line limit with previous character checking (use the smallest) 2023-09-21 08:27:16 +02:00
David Kaspar
9b6eec5fdd Introduced line limit in addition to existing character limit for "show more" folding of text 2023-09-21 08:11:25 +02:00
Vitor Pamplona
02786fb7d3 v0.77.5 2023-09-20 21:22:21 -04:00
Vitor Pamplona
384594ba5c - Inverts the scroll to hide for channels and chats
- Awaits half of the bar to change visibility
2023-09-20 21:21:13 -04:00
Vitor Pamplona
dab02f2cbd v0.77.4 2023-09-20 19:05:00 -04:00
Vitor Pamplona
978f13fbf3 Activates sliding effect for all screens 2023-09-20 18:59:49 -04:00
Vitor Pamplona
831386a656 Using Slide in and out instead of crossfade for the top and bottom bars. 2023-09-20 18:57:11 -04:00
Vitor Pamplona
8b7406e25a Merge pull request #607 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-09-20 18:41:11 -04:00
Crowdin Bot
9e7fed6646 New Crowdin translations by GitHub Action 2023-09-20 22:19:01 +00:00
Vitor Pamplona
89d88326e8 Merge pull request #606 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-09-20 18:18:08 -04:00
Vitor Pamplona
f18dd02161 Merge pull request #605 from greenart7c3/main
immersive scrolling on home feed
2023-09-20 18:17:56 -04:00
Crowdin Bot
e00db19485 New Crowdin translations by GitHub Action 2023-09-20 22:14:39 +00:00
Vitor Pamplona
a706b71d7c Moves reaction calls to the viewModelScope 2023-09-20 18:12:41 -04:00
greenart7c3
a83b26cc6f immersive scrolling on home feed 2023-09-20 18:18:56 -03:00
Vitor Pamplona
dc73843447 Fixes OK string 2023-09-20 16:43:57 -04:00
Vitor Pamplona
3e6aa2b943 Protects against null contact lists 2023-09-20 16:32:38 -04:00
Vitor Pamplona
909d3f4fbe Migrates alt descriptions from .content to alt tag. 2023-09-20 16:18:21 -04:00
Vitor Pamplona
fb0748f4a7 v0.77.3 2023-09-20 15:12:23 -04:00
Vitor Pamplona
1ec4823122 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-09-20 15:11:56 -04:00
Vitor Pamplona
cce5e0bf21 v0.77.2 2023-09-20 15:11:51 -04:00
Vitor Pamplona
0006595786 Quick fix on zap notifications 2023-09-20 15:11:35 -04:00
Vitor Pamplona
6b884f645e Merge pull request #604 from greenart7c3/main
Change nav bar color according to the theme
2023-09-20 14:58:18 -04:00
greenart7c3
946723a80e change nav bar color 2023-09-20 15:42:21 -03:00
Vitor Pamplona
791debbaca v0.77.1 2023-09-20 14:18:07 -04:00
Vitor Pamplona
3bb5a4e50d Fixing F-droid flavor 2023-09-20 14:01:51 -04:00
Vitor Pamplona
3efa3a68fe Adds communities, hashtags and geohashes to the lists on the top navigation bar. 2023-09-20 12:23:50 -04:00
Vitor Pamplona
dc314a94ff Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-09-20 09:38:00 -04:00
Vitor Pamplona
11b062c41f Moves zap decryption to run in a group, avoiding multiple co-routines per zap 2023-09-20 09:37:56 -04:00
Vitor Pamplona
faeb2a3894 Removes the follow unfollow button from the Zap to User Compose 2023-09-20 09:37:23 -04:00
Vitor Pamplona
b1f45a346d Merge pull request #603 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-09-20 08:34:26 -04:00
Crowdin Bot
0b16de6a85 New Crowdin translations by GitHub Action 2023-09-20 12:32:50 +00:00
Vitor Pamplona
66d4b75373 Merge pull request #602 from greenart7c3/main
Login improvements
2023-09-20 08:31:28 -04:00
greenart7c3
3b376a615c disable buttons if terms not accepted, fix a crash when login with amber 2023-09-20 07:46:31 -03:00
Vitor Pamplona
c8da570c89 Fixes IO Calls 2023-09-19 17:44:41 -04:00
Vitor Pamplona
38f4a5b7fc Groups notifications by day first. 2023-09-19 17:32:57 -04:00
Vitor Pamplona
b03ff36cf3 Improvements to the rendering of long form content. 2023-09-19 17:01:33 -04:00
Vitor Pamplona
d145938652 Fixes blank summaries 2023-09-19 16:51:14 -04:00
Vitor Pamplona
1993388d9f Darker Boost Username 2023-09-19 16:47:30 -04:00
Vitor Pamplona
15e7540b26 Code clean up 2023-09-19 16:43:57 -04:00
Vitor Pamplona
c2beaf5f80 Starting a Refactoring of LocalCache away from a Singleton instance. 2023-09-19 15:26:16 -04:00
Vitor Pamplona
5d395419ff Sets up default reactions to be Rocket, Hugs, Watching and Laghuing 2023-09-19 14:58:00 -04:00
Vitor Pamplona
f672a51470 Removes old migration from the old preferences. 2023-09-18 17:20:46 -04:00
Vitor Pamplona
f741239e23 Updates Google Play services 2023-09-18 17:15:17 -04:00
Vitor Pamplona
3442194b01 Creates Daniel's idea for reposted profile icons 2023-09-18 17:07:17 -04:00
Vitor Pamplona
0b025d7679 Adds a ZapSplit view to MasterNodes in Thread 2023-09-18 16:31:05 -04:00
Vitor Pamplona
227de74317 v0.77.0 2023-09-18 13:36:51 -04:00
Vitor Pamplona
0b9fced8bc Quick refactoring to abstract the name Amber for any external signers. 2023-09-18 13:36:36 -04:00
Vitor Pamplona
274e4f7498 Fixes merge issue on NIP24 TextNotes 2023-09-18 11:23:36 -04:00
Vitor Pamplona
f6496b5e7e Merge pull request #601 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-09-18 11:18:57 -04:00
Crowdin Bot
ee5ff1845f New Crowdin translations by GitHub Action 2023-09-18 15:18:18 +00:00
Vitor Pamplona
c84e835ce5 Merge pull request #543 from greenart7c3/amber
Add Amber support
2023-09-18 11:16:55 -04:00
Vitor Pamplona
cdb5be2fe9 Merge branch 'main' into amber 2023-09-18 11:16:47 -04:00
Vitor Pamplona
2d0c356aa5 v0.76.2 2023-09-18 10:53:44 -04:00
Vitor Pamplona
0a92c253b8 Merge pull request #600 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-09-18 10:39:22 -04:00
Crowdin Bot
92347863bc New Crowdin translations by GitHub Action 2023-09-18 14:38:52 +00:00
Vitor Pamplona
a146ec5e1a Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-09-18 10:36:21 -04:00
Vitor Pamplona
83be43e94e Removes the ZapSplit display when the weights are zero or were incorrectly created. 2023-09-18 10:36:05 -04:00
greenart7c3
d726b3b5b5 fix createZapRequestFor userhex 2023-09-18 11:27:05 -03:00
Vitor Pamplona
c845aac8e5 Merge pull request #599 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-09-17 12:03:08 -04:00
Crowdin Bot
1cdf114fff New Crowdin translations by GitHub Action 2023-09-17 15:38:29 +00:00
Vitor Pamplona
4d1a99d076 Adds NIP24 Kind1 create function 2023-09-17 11:32:35 -04:00
Vitor Pamplona
b1debd9879 AnimatedVisibility seems faster than Crossfade 2023-09-17 11:31:24 -04:00
Vitor Pamplona
3843917bd1 Makes sure the account is writeable before signing Auth for notifications 2023-09-16 15:33:42 -04:00
greenart7c3
2fa4281b6f fix sending messages 2023-09-16 09:11:25 -03:00
greenart7c3
c42944e15b removed AmberUtils.signEvent 2023-09-16 08:49:46 -03:00
greenart7c3
9f9f158709 fix zap splits and show message if user uninstall amber 2023-09-16 08:23:56 -03:00
greenart7c3
3a753f0d5d Merge branch 'main' into amber 2023-09-16 08:03:54 -03:00
greenart7c3
13c94112d4 fix private zaps 2023-09-16 07:56:14 -03:00
greenart7c3
dd46f12a05 change amber from debug to release 2023-09-15 21:51:01 -03:00
greenart7c3
9a648d7e84 send the logged in npub to amber 2023-09-15 21:35:32 -03:00
greenart7c3
614dbab1fd refactor some duplicated code 2023-09-15 20:51:13 -03:00
greenart7c3
3d80ee1984 fix decryption of dms whe new message is send 2023-09-15 20:46:29 -03:00
Vitor Pamplona
536fb49bc3 0.76.1 2023-09-15 17:15:54 -04:00
Vitor Pamplona
edd93141bc No need for the @ when adding users to the Split 2023-09-15 17:13:35 -04:00
Vitor Pamplona
20c2d19a9c Refining the Payment via Intent 2023-09-15 17:08:19 -04:00
Vitor Pamplona
17b2fe9cd8 Merge pull request #596 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-09-15 14:22:41 -04:00
Crowdin Bot
134e7cee0c New Crowdin translations by GitHub Action 2023-09-15 16:59:32 +00:00
Vitor Pamplona
108ddffcc7 formatting 2023-09-15 12:56:50 -04:00
Vitor Pamplona
20e76daff8 Adds zap splits 2023-09-15 12:56:24 -04:00
greenart7c3
6876a7f0d2 zaps in background 2023-09-15 13:53:05 -03:00
greenart7c3
87dbf86129 Merge branch 'main' into amber 2023-09-15 13:18:43 -03:00
greenart7c3
175d1ae33b fix zap dialog not closing 2023-09-15 12:58:58 -03:00
greenart7c3
bf9d318209 use content resolvers with amber 2023-09-15 11:56:07 -03:00
Vitor Pamplona
7bee44c5ad Merge pull request #595 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-09-14 14:01:54 -04:00
Crowdin Bot
a32e90aed0 New Crowdin translations by GitHub Action 2023-09-14 17:48:43 +00:00
Vitor Pamplona
310db1008e Fixes bug when verifying the checksum of LNURLs (bech32) in uppercase. 2023-09-14 13:46:29 -04:00
greenart7c3
21560d098e fix upload image 2023-09-13 19:15:00 -03:00
greenart7c3
33f7c5c82e deleted intentutils 2023-09-13 18:06:50 -03:00
greenart7c3
52f17e9f46 nwc support with amber 2023-09-13 16:23:56 -03:00
greenart7c3
1e7ffa365b change relay auth to use signevent 2023-09-13 16:08:38 -03:00
greenart7c3
e00fc83e5c fix reaction row and zaps 2023-09-13 15:54:44 -03:00
greenart7c3
a2fcb3539e Merge branch 'main' into amber 2023-09-13 13:15:45 -03:00
Vitor Pamplona
cb69d056b8 Allowing playback to save any position and not only after 5 seconds. 2023-09-13 12:12:47 -04:00
Vitor Pamplona
e7f950cd32 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-09-13 11:45:27 -04:00
Vitor Pamplona
3b2686ffeb Removes potential bug when the list contains an e tag with an a reference 2023-09-13 11:45:17 -04:00
Vitor Pamplona
2387a609df Merge pull request #593 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-09-13 10:33:47 -04:00
Crowdin Bot
6457a84f4b New Crowdin translations by GitHub Action 2023-09-13 14:30:48 +00:00
Vitor Pamplona
dee231d43a Moves deletion and report to be the last item on the dropdown menu: https://image.nostr.build/709c4f2753cf6a40f9f9322379394d09354acb7e88502b64be348e4a3030734b.png 2023-09-13 10:27:37 -04:00
greenart7c3
8c4af4ac85 only decrypt giftwrap in the dms screen 2023-09-13 11:10:10 -03:00
greenart7c3
58cf0d9f5d fix freeze when going to dms screen 2023-09-13 10:08:43 -03:00
greenart7c3
de5c0d4681 do not try decrypt private zaps for now 2023-09-13 09:32:24 -03:00
greenart7c3
780832d785 fix block/unblock 2023-09-13 09:22:34 -03:00
greenart7c3
b8808a17b5 fix bookmarks decryption 2023-09-13 08:38:20 -03:00
greenart7c3
5001e58c2b improve giftwrap decryption 2023-09-13 08:04:51 -03:00
greenart7c3
95514b66ea improve giftwrap decryption 2023-09-13 08:01:46 -03:00
greenart7c3
90c6d6c8f8 fix login with amber 2023-09-13 06:42:37 -03:00
Vitor Pamplona
88d2ce3ad0 Updating dependencies 2023-09-12 17:53:18 -04:00
Vitor Pamplona
484f3a6842 Merge pull request #590 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-09-12 08:32:16 -04:00
Crowdin Bot
866caf8bc5 New Crowdin translations by GitHub Action 2023-09-12 12:12:41 +00:00
Vitor Pamplona
be9e3c3bf7 Merge pull request #589 from davotoula/main
Updated translations for cs/de/sv
2023-09-12 08:11:02 -04:00
David Kaspar
49a3cb1978 Updated translations for cs/de/sv 2023-09-12 11:41:43 +02:00
greenart7c3
c3ddc4f7ad fix release build not working 2023-09-11 18:12:55 -03:00
greenart7c3
ff4d704bde add support for private zaps 2023-09-11 15:30:00 -03:00
greenart7c3
a773be12c4 decrypt LnZapRequestEvent 2023-09-11 11:52:53 -03:00
greenart7c3
7ff6f16df0 Merge branch 'main' into amber 2023-09-11 07:20:03 -03:00
Vitor Pamplona
d9053f580f Merge pull request #586 from OrigiSize/patch-1
Minor README.md edits
2023-09-09 19:37:57 -04:00
OrigiSize
fee2764338 Minor README.md edits
Fixing grammar and flow
2023-09-09 12:33:09 -07:00
Vitor Pamplona
61cb4fdd74 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-09-09 14:42:59 -04:00
Vitor Pamplona
d89869ebff Merge pull request #585 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-09-09 14:40:45 -04:00
Vitor Pamplona
8518819dfa Forces valid hexes for users and notes 2023-09-09 14:39:41 -04:00
Crowdin Bot
0a8923be6b New Crowdin translations by GitHub Action 2023-09-09 18:34:33 +00:00
Vitor Pamplona
cda821e5af Stops accepting space as a Valid hex char and requires an even number of chars (padding) 2023-09-09 14:33:19 -04:00
Vitor Pamplona
be2402702f Forces the ZapRequest to exist when processing the LnZapEvent. 2023-09-09 14:32:27 -04:00
Vitor Pamplona
d723a8ab5c Refactors the split between nip19 and the rest of the text. 2023-09-09 14:26:20 -04:00
Vitor Pamplona
5c882c81c8 Account is never null here. 2023-09-09 14:24:29 -04:00
Vitor Pamplona
24d2709564 Merge pull request #584 from atrifat/move-broadcast-button-away
Fix vitorpamplona/amethyst#550 - change broadcast button position
2023-09-08 20:54:46 -04:00
Rif'at Ahdi R
ce15bc46a7 Fix vitorpamplona/amethyst#550 - change broadcast button position 2023-09-09 08:24:17 +08:00
Vitor Pamplona
de4bc30730 Merge pull request #583 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-09-08 16:19:48 -04:00
Crowdin Bot
64f6811c00 New Crowdin translations by GitHub Action 2023-09-08 20:18:47 +00:00
Vitor Pamplona
e05ab104b9 0.76.0 2023-09-08 16:16:53 -04:00
Vitor Pamplona
b4f1c4d13e Migrates to Encrypted Push Notifications 2023-09-08 16:16:26 -04:00
greenart7c3
36a3c4123c Merge branch 'main' into amber 2023-09-08 15:48:13 -03:00
Vitor Pamplona
939eb1bd8d Fixes the lack of permission when using Android's PhotoPicker to upload videos (thumbnail fails to load and videos don't play because the Playback service doesn't have permission to run) 2023-09-08 11:39:14 -04:00
Vitor Pamplona
854469cc7d Merge pull request #582 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-09-08 09:21:01 -04:00
Crowdin Bot
338ae41baa New Crowdin translations by GitHub Action 2023-09-08 12:42:58 +00:00
Vitor Pamplona
6cae89d276 Adds indonesian to crowdin 2023-09-08 08:41:07 -04:00
Vitor Pamplona
15c1e25122 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-09-08 08:37:20 -04:00
Vitor Pamplona
c5716416b6 Merge pull request #581 from atrifat/add-indonesian-translation
Add Indonesian Translation
2023-09-08 08:36:56 -04:00
Rif'at Ahdi R
65e4a766ab Add Indonesian Translation 2023-09-08 11:39:27 +08:00
Vitor Pamplona
c2a4c9bbb3 Improvements to the relay settings page. 2023-09-07 19:07:33 -04:00
Vitor Pamplona
b042110154 Merge pull request #579 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-09-07 15:39:07 -04:00
Crowdin Bot
da97b5593b New Crowdin translations by GitHub Action 2023-09-07 18:42:45 +00:00
Vitor Pamplona
44b4b0cdb9 Makes sure only valid lnurl withdraws get highlighted. 2023-09-07 14:40:42 -04:00
Vitor Pamplona
190b7fe819 Using the correct observer for picture profile in the Top bar. 2023-09-07 12:53:19 -04:00
Vitor Pamplona
8eb89f0fe9 Adds nostr.wine and noswhere.com as two new NIP-50 relays. 2023-09-07 12:52:44 -04:00
Vitor Pamplona
3085353729 Adds SeenOn relays when successfully broadcasting a note. 2023-09-07 12:52:14 -04:00
Vitor Pamplona
1465ce112c Refines relay icon row compose 2023-09-07 11:11:10 -04:00
Vitor Pamplona
5c797858ba Merge pull request #578 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-09-07 10:23:12 -04:00
Crowdin Bot
8c51c4be0c New Crowdin translations by GitHub Action 2023-09-07 13:57:52 +00:00
Vitor Pamplona
4e8ecff67b Fixes the missing channel header in conversations. 2023-09-07 09:55:43 -04:00
greenart7c3
6303573dd9 support for sending and receiving nip 44 dms 2023-09-06 18:53:11 -03:00
Vitor Pamplona
83f8c51aca Merge pull request #577 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-09-06 10:14:04 -04:00
Crowdin Bot
e675348461 New Crowdin translations by GitHub Action 2023-09-06 14:04:55 +00:00
Vitor Pamplona
9026f5bf07 Merge pull request #574 from davotoula/main
Updated translations for cs/de
2023-09-06 10:03:30 -04:00
greenart7c3
a7aa3705ef fix crash on reaction 2023-09-06 10:43:59 -03:00
greenart7c3
a64c941f36 add cache to decrypted dms 2023-09-06 09:21:55 -03:00
David Kaspar
02f18b5b35 Updated translations for cs/de 2023-09-06 13:35:45 +02:00
Vitor Pamplona
db740f4747 Upgrades the RelayPoolStatus to a Flow 2023-09-05 17:21:36 -04:00
Vitor Pamplona
6a3206b938 Avoids race condition when update EOSEs 2023-09-05 17:20:37 -04:00
Vitor Pamplona
23414b0bc6 Merge pull request #573 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-09-05 09:39:11 -04:00
Crowdin Bot
0234cfca30 New Crowdin translations by GitHub Action 2023-09-05 13:03:08 +00:00
Vitor Pamplona
f707714611 Merge pull request #569 from atrifat/add-arm64-armeabi-target
Add arm64-v8a and armeabi-v7a build target
2023-09-05 09:01:46 -04:00
Vitor Pamplona
7b90230c45 Merge pull request #572 from davotoula/main
Updated translations for cs/de
2023-09-05 09:01:05 -04:00
David Kaspar
d3468f3eba Added new translations for cs/de 2023-09-05 12:52:59 +02:00
Rif'at Ahdi R
fc9500b45c Update create-release.yml to suppport arm64-v8a and armeabi-v7a 2023-09-05 10:39:36 +08:00
Rif'at Ahdi R
df0b5fcd19 Add arm64-v8a and armeabi-v7a build target 2023-09-05 10:03:35 +08:00
greenart7c3
59cde5699e add support for status 2023-09-04 18:28:11 -03:00
greenart7c3
bd836a9580 Merge branch 'main' into amber 2023-09-04 18:09:29 -03:00
greenart7c3
90aade338c sign event in background 2023-09-04 18:06:09 -03:00
Vitor Pamplona
40e2dba490 v0.75.14 2023-09-02 13:43:15 -04:00
Vitor Pamplona
d13e8bacec Fixes thread ordering issues with two notes with the same idHex 2023-09-02 12:46:24 -04:00
Vitor Pamplona
d3fa05a4df Remeber should be based on the Note 2023-09-02 12:28:16 -04:00
Vitor Pamplona
734dd2e119 Adds UI Feedback for Custom Zaps 2023-09-02 12:27:24 -04:00
Vitor Pamplona
a9ea9ea2ae Improves error message from LN Invoice servers. 2023-09-02 12:26:36 -04:00
Vitor Pamplona
1b521bc140 Grammar adjustment 2023-09-02 12:25:41 -04:00
Vitor Pamplona
364e3c5f5f 0.75.13 2023-09-01 14:28:40 -04:00
Vitor Pamplona
647cda3f90 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-09-01 14:27:52 -04:00
Vitor Pamplona
bcca4d4bcc Adds idHex to the date sorting in replies and comments to make sure the order is correct when 2 posts are placed within the same second. 2023-09-01 14:25:48 -04:00
Vitor Pamplona
0b038dca17 Merge pull request #565 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-09-01 14:10:07 -04:00
Crowdin Bot
ad6f63df56 New Crowdin translations by GitHub Action 2023-09-01 17:53:20 +00:00
Vitor Pamplona
b5b8b62a16 Only trigger notification of events within 5minutes from the current time (avoids annoying notifications when rebroadcasting events) 2023-09-01 13:51:23 -04:00
Vitor Pamplona
8d3066b377 Marks which relays are using compression 2023-09-01 12:36:19 -04:00
Vitor Pamplona
18933b4326 Ignores brb.io if in the relay list. It's crashing the app too much with a weird implementation of the WebSockets protocol 2023-09-01 12:36:03 -04:00
Vitor Pamplona
672841c0ed Doesn't notify if the GiftWrap's inner message came from the user. 2023-09-01 12:35:21 -04:00
Vitor Pamplona
872c7cb257 Fixes testing of thread ordering 2023-09-01 12:34:46 -04:00
greenart7c3
6d691c4741 add support for reports 2023-09-01 13:32:39 -03:00
greenart7c3
bbba27752d support for public and anon zaps 2023-09-01 12:25:42 -03:00
greenart7c3
d9cf090cc9 add support for nip94 2023-09-01 10:46:50 -03:00
greenart7c3
46effa572c refactor default values in signEvent variables 2023-09-01 10:18:49 -03:00
greenart7c3
f76ab01c11 Merge branch 'main' into amber 2023-09-01 05:12:29 -03:00
Vitor Pamplona
bfae5871c8 v0.75.12 2023-08-31 19:05:12 -04:00
Vitor Pamplona
451c5d1648 Removing LiveData Redirections 2023-08-31 19:04:07 -04:00
Vitor Pamplona
3423626c60 Fixes global feed 2023-08-31 19:02:54 -04:00
Vitor Pamplona
8982f02a4a v0.75.11 2023-08-31 17:13:32 -04:00
Vitor Pamplona
f06b5fdacf New thread ordering scheme:
1. Thread author, ascending order by date.
2. My replies, descending by date.
3. My follow's replies, descending by date.
4. Everybody else, descending by date.
2023-08-31 16:41:02 -04:00
Vitor Pamplona
8ea8cf2985 Marks keep screen on to false when leaving a video player. 2023-08-31 15:23:30 -04:00
Vitor Pamplona
2771d34951 Fixes the report card when the author has been blocked by the logged in user but the list loaded before the block user list. 2023-08-31 14:53:43 -04:00
Vitor Pamplona
669b33a3e1 Reducing the height of the banner in the drawer 2023-08-31 13:43:57 -04:00
Vitor Pamplona
c934a1cdfe Reduce the space between display name and status. 2023-08-31 13:36:46 -04:00
Vitor Pamplona
0ccd41f5e8 Fixes wrong EOSE updates. 2023-08-31 13:21:08 -04:00
Vitor Pamplona
1af3bb7dfc Improve cohesiveness of the pruning system. 2023-08-31 11:48:22 -04:00
Vitor Pamplona
f0fcf1ea8a Fixes the grammar in the nip05 error messages 2023-08-31 09:04:09 -04:00
Vitor Pamplona
5325542c81 update vico 2023-08-30 19:56:37 -04:00
Vitor Pamplona
3d9675841b Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-08-30 19:32:31 -04:00
Vitor Pamplona
0d475fba0e Merge pull request #564 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-08-30 17:31:45 -04:00
Crowdin Bot
05714de945 New Crowdin translations by GitHub Action 2023-08-30 21:14:24 +00:00
Vitor Pamplona
89c1b53c95 Merge pull request #563 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-08-30 17:13:08 -04:00
greenart7c3
d1cb699027 support for nip95 2023-08-30 16:40:11 -03:00
greenart7c3
9ee1250f3a unblock users 2023-08-30 14:15:20 -03:00
greenart7c3
7a68cf867e block users using amber 2023-08-30 11:54:36 -03:00
Vitor Pamplona
1c9041f12b Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-08-30 10:12:23 -04:00
Crowdin Bot
d3de5e0a42 New Crowdin translations by GitHub Action 2023-08-30 12:50:26 +00:00
Vitor Pamplona
b1bd21533d Merge pull request #562 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-08-30 08:49:11 -04:00
Crowdin Bot
51f997a34a New Crowdin translations by GitHub Action 2023-08-30 12:48:43 +00:00
Vitor Pamplona
d5607faadd Requires 10 sat zaps to trigger notifications 2023-08-30 08:47:25 -04:00
Vitor Pamplona
1a9c3ccb79 Must have a valid ZapRequest to process. 2023-08-30 08:44:14 -04:00
greenart7c3
bc8fa00608 move openAmber to AmberUtils 2023-08-30 08:29:56 -03:00
greenart7c3
329d806ffd decrypt dms of notifications 2023-08-30 08:07:45 -03:00
greenart7c3
e040d0f971 Merge branch 'main' into amber 2023-08-30 07:03:55 -03:00
Vitor Pamplona
053de4d06f Removes unnecessary checks since the dual LiveData structure was activated 2023-08-29 17:57:47 -04:00
Vitor Pamplona
4016458540 v0.75.10 2023-08-29 17:40:51 -04:00
Vitor Pamplona
8b98efaad7 Refines zap and report pruning. 2023-08-29 17:24:48 -04:00
Vitor Pamplona
217ed90d9a Fix the deletion of reports from authors 2023-08-29 17:14:25 -04:00
Vitor Pamplona
b82aefbd5d Merge pull request #559 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-08-29 16:54:41 -04:00
Crowdin Bot
63b954d38d New Crowdin translations by GitHub Action 2023-08-29 20:54:17 +00:00
Vitor Pamplona
76cdea0087 Fixing xml 2023-08-29 16:53:09 -04:00
Vitor Pamplona
da1a3a8f85 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-08-29 16:51:05 -04:00
Vitor Pamplona
d11e92e166 v0.75.9 2023-08-29 16:46:34 -04:00
Vitor Pamplona
61efd237c2 Fixes: https://github.com/vitorpamplona/amethyst/issues/495 and https://github.com/vitorpamplona/amethyst/issues/398 2023-08-29 16:46:27 -04:00
Vitor Pamplona
6099948605 Migrates from Toast Message to a Dialog when Zap fails in the reaction row. 2023-08-29 16:43:45 -04:00
Vitor Pamplona
45b743e7c8 Merge pull request #557 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-08-29 16:42:50 -04:00
Crowdin Bot
108c6cbeb4 New Crowdin translations by GitHub Action 2023-08-28 21:18:41 +00:00
Vitor Pamplona
da02891c6a Correct an xml issue from crowdin 2023-08-28 17:12:48 -04:00
Vitor Pamplona
a03e9ea946 Merge pull request #556 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2023-08-28 16:59:51 -04:00
Crowdin Bot
dd4a6f8da0 New Crowdin translations by GitHub Action 2023-08-28 20:57:58 +00:00
Vitor Pamplona
c01033cbb0 Fixes case 2023-08-28 16:56:52 -04:00
Vitor Pamplona
1fe93395c5 gotta choose one 2023-08-28 16:51:05 -04:00
Vitor Pamplona
cf960fe59d Avoid creating english files when they have not been translated yet. 2023-08-28 16:49:12 -04:00
Vitor Pamplona
2416d41131 removes filter to only run crowdin when strings are updated 2023-08-28 16:41:53 -04:00
Vitor Pamplona
0699095d77 triggers crowdin 2023-08-28 16:32:00 -04:00
Vitor Pamplona
6ed3e84d95 This might work 2023-08-28 16:31:09 -04:00
Vitor Pamplona
6c196cfeb7 triggering crowdin 2023-08-28 16:27:26 -04:00
Vitor Pamplona
987784fb89 Fixing yaml again 2023-08-28 16:26:59 -04:00
Vitor Pamplona
d60ac5d73b updates strings 2023-08-28 16:24:04 -04:00
Vitor Pamplona
c2361c034c corrects yaml 2023-08-28 16:23:51 -04:00
Vitor Pamplona
199514e7f3 trigger crowdin 2023-08-28 16:22:07 -04:00
Vitor Pamplona
a1364d19c2 correctly identifies mapping languages. 2023-08-28 16:21:47 -04:00
Vitor Pamplona
e73428b156 updates to strings.xml 2023-08-28 16:09:28 -04:00
Vitor Pamplona
a684a222cb runs github action on any updates to source or dst translations 2023-08-28 16:08:32 -04:00
Vitor Pamplona
1646cbbd68 mapping language codes to crowdin 2023-08-28 16:07:26 -04:00
Vitor Pamplona
035a48a0cd adds a type android 2023-08-28 15:55:32 -04:00
Vitor Pamplona
71be8ce239 testing update to strings.xml 2023-08-28 15:43:49 -04:00
Vitor Pamplona
1ccf9bf467 only runs with strings change 2023-08-28 15:14:47 -04:00
Vitor Pamplona
42a0cd0b1b adding the configuration file for crowdin 2023-08-28 15:12:39 -04:00
Vitor Pamplona
39547b1d11 Adds Crowin 2023-08-28 14:43:22 -04:00
greenart7c3
c223c1372b add support for amber in the follow dropdown menu 2023-08-28 14:31:20 -03:00
greenart7c3
a450dcbac1 add support for add/remove public bookmarks 2023-08-28 11:58:48 -03:00
greenart7c3
ee5fbce2ce refactor mainactivity to use IntentUtils.start 2023-08-28 09:56:12 -03:00
greenart7c3
559b88be18 fix build after merge 2023-08-28 07:18:04 -03:00
greenart7c3
dfbc5fa556 Merge branch 'main' into amber 2023-08-28 07:06:52 -03:00
Vitor Pamplona
c69969947b v0.75.8: Fixes status's cache update crash. 2023-08-27 19:33:08 -04:00
Vitor Pamplona
e1738a25a1 Do a warning log and not an error log for verification fails (it usually happens in stringified JSON inside .content) 2023-08-27 19:17:58 -04:00
Vitor Pamplona
6c54082a12 clears the index cache when changing status fields. 2023-08-27 19:16:58 -04:00
Vitor Pamplona
bc5500731d v0.75.7 2023-08-27 18:12:41 -04:00
Vitor Pamplona
0665c552aa BugFix for a crash when receiving a new notification 2023-08-27 18:11:14 -04:00
Vitor Pamplona
1ab8463578 v0.75.6 2023-08-27 17:13:29 -04:00
Vitor Pamplona
e016e68e42 removing unused sentence. 2023-08-27 17:11:49 -04:00
Vitor Pamplona
d116159ed9 v0.75.5 2023-08-27 16:49:31 -04:00
Vitor Pamplona
3c24c011e3 Avoids rebuilding the channel object in DataSource. 2023-08-27 16:45:12 -04:00
Vitor Pamplona
536bdfe43a - When All Follows, the live tab will load any event with a follow in the participant list.
- Removes prefix filters
2023-08-27 16:32:35 -04:00
Vitor Pamplona
0b41110938 Fixes formatting 2023-08-27 15:53:41 -04:00
Vitor Pamplona
da1d4018cf Fixes crash when more than 1 status 2023-08-27 15:52:35 -04:00
Vitor Pamplona
b569c67d3b Fixes Hungarian labels 2023-08-27 15:33:18 -04:00
Vitor Pamplona
50a5a68b71 Merge pull request #554 from anthony-robin/translations
Update french translations
2023-08-27 15:30:42 -04:00
Vitor Pamplona
23a4d80ddb v0.75.4 2023-08-27 12:25:53 -04:00
Vitor Pamplona
6a64ebcc5b migrates to a double layer observer structure for the memory cache 2023-08-27 12:18:11 -04:00
Vitor Pamplona
8e622bfbb1 Updates to debugging logs 2023-08-27 12:16:36 -04:00
Vitor Pamplona
d189dce7f0 Extracts chatroom from user file 2023-08-27 12:16:13 -04:00
Vitor Pamplona
43ac1bf555 Allows cleaning up on App Pause to perform separately from memory pruning functions 2023-08-27 12:10:12 -04:00
Anthony Robin
d2d26e4e57 Update french translations
Update french translations according to newly added english ones.
2023-08-27 07:52:15 +02:00
Vitor Pamplona
de1f13d64c Faster crossfade animation between screens 2023-08-26 13:04:35 -04:00
Vitor Pamplona
2be04bfbe2 Better error handling when Zaps fail 2023-08-26 13:00:53 -04:00
Vitor Pamplona
57c33ae06a Improves User filters by merging lastEOSEs into a single filter. 2023-08-26 12:59:41 -04:00
Vitor Pamplona
99e545f0b8 Adds polls to the hashtag screen 2023-08-26 11:32:37 -04:00
Vitor Pamplona
accb115a20 Making statuses filter just one with the minimum of all observing users. 2023-08-26 10:36:44 -04:00
Vitor Pamplona
9de1cec160 Merge pull request #553 from ZsZolee/main
Additional Hungarian translation
2023-08-26 09:34:36 -04:00
Zoltan
f7774700db Additional Hungarian translation 2023-08-26 13:22:27 +02:00
Vitor Pamplona
ffb81c6246 v0.75.3 2023-08-25 17:51:38 -04:00
Vitor Pamplona
b7c9b14b1f Allowing any BaseTextNote on the reply window 2023-08-25 17:47:01 -04:00
Vitor Pamplona
53b0db61ea Moves isAcceptableNote calculations to viewModel 2023-08-25 17:32:19 -04:00
Vitor Pamplona
6c09e47e4f Moves coroutine of NIP-05 verification to the viewModel 2023-08-25 17:26:47 -04:00
Vitor Pamplona
9d9ad63b4d BugFix deleting status 2023-08-25 17:15:17 -04:00
Vitor Pamplona
7ef46a2662 Continues to move away from starting co-routines directly in composables 2023-08-25 17:14:33 -04:00
Vitor Pamplona
a7d8c87c47 1. Triggers a Toast when no wallet is found to pay the invoice
2. Starts the wallet in a separate task to allow people to come back to Amethyst switching apps instead of the back button.
2023-08-25 15:18:01 -04:00
Vitor Pamplona
1bb2459277 Activates min/max values for polls 2023-08-25 15:08:10 -04:00
Vitor Pamplona
6b39562925 Allows the keyboard action to be used as commit in the status field. 2023-08-25 13:55:41 -04:00
Vitor Pamplona
3d34e1fc4e Reduces the icon to the music and adds space before the status 2023-08-25 13:41:17 -04:00
Vitor Pamplona
469e1241d5 Updates some dependencies 2023-08-25 13:28:17 -04:00
Vitor Pamplona
86c0ca975b Moves the User DataSource invalidation to the right channel 2023-08-25 13:27:57 -04:00
Vitor Pamplona
53eeea3225 Removes unused time 2023-08-25 13:26:56 -04:00
Vitor Pamplona
e9ff9d3b37 Adds a space between the status and the clickable icon 2023-08-25 13:24:47 -04:00
Vitor Pamplona
e2c011ec60 Avoids lists with the same hexId because the app was pruning events while loading them 2023-08-25 13:01:49 -04:00
Vitor Pamplona
5328740bff Improves blinking when loading a thread. 2023-08-25 13:01:08 -04:00
Vitor Pamplona
017df9845d Fixes r filter in tags 2023-08-25 12:59:21 -04:00
Vitor Pamplona
ed70658be9 Removes unecessary @ExperimentalTime tag 2023-08-25 11:52:44 -04:00
Vitor Pamplona
dc74c3014f updates cached content when note changes 2023-08-25 11:51:41 -04:00
Vitor Pamplona
53d5c5f354 BugFix for serialization filter 2023-08-25 11:49:41 -04:00
greenart7c3
df1a017eb3 refactor PackageUtils.isAmberInstalled to account.loggedinwithamber 2023-08-25 11:51:22 -03:00
Vitor Pamplona
63ab2a9fbe Moves NIP315 to NIP38 2023-08-25 10:31:51 -04:00
greenart7c3
b2b7799a0f add support for deletion events 2023-08-25 09:29:13 -03:00
greenart7c3
e817f94045 add/remove private bookmarks 2023-08-25 08:51:23 -03:00
greenart7c3
46571a6029 decrypt private bookmark 2023-08-25 06:56:49 -03:00
greenart7c3
4f4d689f5a fix build, use keyPair in textnoteevent, check if loggedInWithAmber in newpostview 2023-08-25 05:45:39 -03:00
greenart7c3
a0308938de Merge branch 'main' into amber 2023-08-25 05:27:14 -03:00
Vitor Pamplona
30391160da v0.75.2 2023-08-24 18:56:39 -04:00
Vitor Pamplona
3273aa32a5 Removes the debug r tag used to test. 2023-08-24 18:54:48 -04:00
Vitor Pamplona
1e358d31d5 v0.75.1 2023-08-24 17:59:26 -04:00
Vitor Pamplona
b57dd98059 Displays links in the Status if they are present. 2023-08-24 17:58:34 -04:00
Vitor Pamplona
5b596d2a56 - Updating Status on the Drawer
- Reducing font size for statuses and nip05s
2023-08-24 17:34:02 -04:00
Vitor Pamplona
62db68c7b2 Correctly display status 2023-08-24 16:17:20 -04:00
Vitor Pamplona
b3bb85cd53 Display statuses if NIP05 succeeds. 2023-08-24 15:57:18 -04:00
Vitor Pamplona
fe6fb8470d Adds isExpired method in events. 2023-08-24 15:56:43 -04:00
Vitor Pamplona
ee97eac00c Downloads Statuses from Relays 2023-08-24 15:56:08 -04:00
Vitor Pamplona
48e3ccc165 Allow changing message status 2023-08-24 15:55:32 -04:00
Vitor Pamplona
52c0503b6d Support for pruning expired events. 2023-08-24 13:13:30 -04:00
Vitor Pamplona
c052399a16 Adds support to consume Status Events 2023-08-24 13:12:10 -04:00
Vitor Pamplona
76faf7ae35 Moving livedata creation to long-lived objects 2023-08-24 12:53:07 -04:00
Vitor Pamplona
36ea33a919 Adds StatusEvent support 2023-08-24 08:56:51 -04:00
Vitor Pamplona
8aad4d8030 Moves Manifest to target API 34 2023-08-24 08:56:37 -04:00
Vitor Pamplona
a23c8c5c04 v0.75.0 2023-08-23 18:22:38 -04:00
Vitor Pamplona
0434ef6ec6 Fixing quotes and boosts for NIP94 and NIP95 content 2023-08-23 17:31:11 -04:00
Vitor Pamplona
4d85a2f6fb Correct imePadding of the NewPostView 2023-08-23 17:08:46 -04:00
Vitor Pamplona
e9b235f748 Don't show zaps on search. 2023-08-23 16:27:04 -04:00
greenart7c3
b10e875941 created loggedInWithAmber in accountViewModel, changed some events to use keypair 2023-08-23 15:56:31 -03:00
greenart7c3
632400f52c add login with amber button 2023-08-23 13:43:25 -03:00
Vitor Pamplona
30320805da Adds Thai translation 2023-08-23 10:19:00 -04:00
greenart7c3
b63479c45f fix build 2023-08-23 07:33:49 -03:00
greenart7c3
7ea6495f28 Merge branch 'main' into amber 2023-08-23 07:28:58 -03:00
Vitor Pamplona
8e913ef974 Adds replies and boosts to Stories 2023-08-22 17:49:44 -04:00
Vitor Pamplona
eb191406e6 Vertical Arrangement not working as intended. 2023-08-22 17:32:59 -04:00
Vitor Pamplona
ca89b70150 Activates pruning of old replaceable versions 2023-08-22 17:07:59 -04:00
Vitor Pamplona
6bcd6950ef Refactors replaceable consumers into a single function
Activates calendar consumers
2023-08-22 16:59:58 -04:00
Vitor Pamplona
dfa9c77e3e Migrates Addressable Events to a Base class 2023-08-22 16:39:23 -04:00
Vitor Pamplona
af143f2ea1 Base support for Calendar events 2023-08-22 16:19:59 -04:00
Vitor Pamplona
52761b3901 Activates pull to refresh on the Stories feed. 2023-08-22 16:19:37 -04:00
Vitor Pamplona
f027d23fcf Small refactoring to create the PrivateZap Event 2023-08-22 16:10:32 -04:00
Vitor Pamplona
2d30f3e9d2 Finishing the prune clean up to make sure we don't delete post from other accounts logged in. 2023-08-22 16:01:59 -04:00
Vitor Pamplona
a63b383425 BugFix Force Relay Reconnection when writing a new events. 2023-08-22 14:06:02 -04:00
Vitor Pamplona
e04eb733e7 - Protecting contact lists of all accounts in the device.
- Pruning events that are not from or cite an account.
2023-08-22 14:04:49 -04:00
Vitor Pamplona
0a49298ec2 Faster ReactionRow compositions 2023-08-22 12:23:45 -04:00
Vitor Pamplona
1121cfcaf9 BugFix on bundled update dispatchers. 2023-08-22 12:23:26 -04:00
Vitor Pamplona
66b5fad6c2 Saves some loading time by moving the check if notification was already asked forward. 2023-08-22 11:23:11 -04:00
Vitor Pamplona
5d352f1b6c Updates compose navigation, exoplayer and vico dependencies to the latest. 2023-08-22 11:16:31 -04:00
Vitor Pamplona
9018175f54 Removes unecessary import. 2023-08-22 11:06:10 -04:00
Vitor Pamplona
98c55661e8 Migrates to Compose 1.5.0 2023-08-22 11:05:17 -04:00
Vitor Pamplona
521407f879 Updates Gradle plugin 2023-08-22 10:07:40 -04:00
Vitor Pamplona
fa4257ad7d Separating NIP24 into the encryption NIP 44 and the messaging NIP 24 2023-08-22 09:41:40 -04:00
Vitor Pamplona
d73dec8f0b v0.74.5 2023-08-21 18:31:00 -04:00
Vitor Pamplona
c6124376df Merge pull request #552 from greenart7c3/fix-crash
fix crash when getting firebase token without play services
2023-08-21 18:30:02 -04:00
Vitor Pamplona
87c19f4232 BugFix for ClassCastException when the event changes 2023-08-21 18:21:28 -04:00
greenart7c3
a1f116909f fix crash when not using play services 2023-08-21 19:20:14 -03:00
Vitor Pamplona
ca9951f9b8 Fixes the loading of GiftWraps as intents in the app. 2023-08-21 18:19:10 -04:00
Vitor Pamplona
2bedd79e6f Fixing search for root to go backwards in the etag-stack. 2023-08-21 18:17:21 -04:00
Vitor Pamplona
a9af2d8982 v0.74.4 2023-08-21 17:30:37 -04:00
Vitor Pamplona
655a563f61 Moves community description and rules to a single Translateable text 2023-08-21 16:09:22 -04:00
Vitor Pamplona
9777c709a1 - Fixes some of the TopBar padding issues.
- Adds more info tap on single-user chat rooms
- Moves creation date to a new line.
2023-08-21 15:42:45 -04:00
greenart7c3
453e63025d fix crash in PushNotificationUtils when theres no google play services 2023-08-21 15:58:01 -03:00
Vitor Pamplona
251f4854fc Copies to Clipboard the GiftWrap ID and not the inner message ID 2023-08-21 14:23:36 -04:00
greenart7c3
17ecc98e1e Merge branch 'main' into amber 2023-08-21 14:59:20 -03:00
Vitor Pamplona
43c32f0b0e Moves last scope to a class-bound variable. 2023-08-21 13:51:03 -04:00
greenart7c3
f9272f5cfc implemented amber support for auth event and the notifications 2023-08-21 14:48:11 -03:00
Vitor Pamplona
ec3b07147c Avoids creating new corotine scopes 2023-08-21 13:34:18 -04:00
greenart7c3
348e07a307 fix missing navScrollToTop parameter 2023-08-21 09:00:45 -03:00
greenart7c3
2009f5bd7b Merge branch 'main' into amber 2023-08-21 08:50:56 -03:00
Vitor Pamplona
0e6a2c339e Fixes the update of the feed after adding an image on stories. 2023-08-20 21:24:57 -04:00
Vitor Pamplona
844f7cd478 Reports on the number of observers to the cache. 2023-08-20 21:24:23 -04:00
Vitor Pamplona
a2edc9f3b2 Fixes the divider presence in Live Activities and Notifications 2023-08-20 17:31:36 -04:00
Vitor Pamplona
35d09aee77 - Filter follows in the list of participants
- Uses KIND3 follows for the notification dot in the bottom nav bar
2023-08-20 17:08:24 -04:00
Vitor Pamplona
a79d1d5bd6 Fixes issue with unfollowing hashtag written in a different case 2023-08-20 16:46:44 -04:00
Vitor Pamplona
ba9315fcd1 Moves coroutines of BundledUpdate and BundledInsert to a managed model. 2023-08-20 16:37:49 -04:00
Vitor Pamplona
f5c71b4f90 Broadcasts a note when a person replies to it. 2023-08-20 16:35:34 -04:00
Vitor Pamplona
5a40b39952 v0.74.3 2023-08-20 11:36:00 -04:00
Vitor Pamplona
2ac3b42d4d Correctly gets the Global Relays being used. 2023-08-20 11:33:56 -04:00
Vitor Pamplona
7cfad373f2 Adds Copy URL and Copy Note ID popups for images and videos 2023-08-20 11:18:31 -04:00
Vitor Pamplona
5d061a79e2 Explanation on why the Global and All Follows code have spaces 2023-08-20 10:29:35 -04:00
Vitor Pamplona
eb59a9d505 Keeps track of a message's GiftWrap host in order to broadcast later. 2023-08-20 10:24:11 -04:00
Vitor Pamplona
784f867a8e Updating media controls to the next version 2023-08-20 01:16:08 -04:00
Vitor Pamplona
954a9d66fb Fixes the crash when opening a malformed thread with a wrong root marker 2023-08-20 01:15:46 -04:00
Vitor Pamplona
dfdced3e8c Includes the zaps from the user's own key in the Summary Chart 2023-08-19 14:57:24 -04:00
Vitor Pamplona
0af141c5b7 Fixes generateForegroundServiceDidNotStartInTimeException on Samsung phones 2023-08-19 14:44:39 -04:00
Vitor Pamplona
70c4c69bbf v0.74.2 2023-08-19 12:40:26 -04:00
Vitor Pamplona
5597189ea5 Allowing null values as a result of the mapper 2023-08-19 12:38:44 -04:00
Vitor Pamplona
8884adcefb Testing new build to find bug on Account loading: 0.74.1 2023-08-19 11:58:08 -04:00
Vitor Pamplona
92be03ca51 v0.74.0 2023-08-19 11:16:13 -04:00
Vitor Pamplona
b4f9103b62 refacctoring 2023-08-19 11:14:10 -04:00
Vitor Pamplona
63f3a6cdf9 Implements contextual rounded corners for images and videos 2023-08-19 11:08:55 -04:00
Vitor Pamplona
d8ce3b9d37 Migrates to prefixes of 8 because more relays seem to work with this 2023-08-18 23:43:16 -04:00
Vitor Pamplona
2ac5742b0e Adds a waveform to audio files 2023-08-18 23:42:24 -04:00
Vitor Pamplona
58dd69091e Adds support for Stemstr 2023-08-18 20:36:32 -04:00
Vitor Pamplona
7a93f9956f Updating SDK to the latest 2023-08-18 19:32:30 -04:00
Vitor Pamplona
8dbded0185 Single method to test performance of receiving a GiftWrap. 2023-08-18 11:52:54 -04:00
Vitor Pamplona
41b93e3860 Caches shared key for performance. 2023-08-18 10:55:28 -04:00
Vitor Pamplona
2f741779fa Improves BechUtils performance. 2023-08-18 10:55:06 -04:00
greenart7c3
7ea92bc068 send dms using amber 2023-08-18 10:57:17 -03:00
greenart7c3
3b07b5d8dd Refactor SignerDialog to use the rawJson and type 2023-08-18 07:55:14 -03:00
greenart7c3
f06e79cfd3 Merge branch 'main' into amber 2023-08-18 06:33:02 -03:00
Vitor Pamplona
918273d825 showing debug when pausing the app. 2023-08-17 17:08:02 -04:00
Vitor Pamplona
eef534617c Fixing ThreadAssembler with two roots 2023-08-17 15:15:13 -04:00
Vitor Pamplona
4e89b1494d Removes experimental time from ThreadAssembler 2023-08-17 10:23:18 -04:00
Vitor Pamplona
be1ae35a60 Fixing Proguard from latest refactoring 2023-08-17 10:23:00 -04:00
Vitor Pamplona
47395465bb Automatically activates NIP24 chats when users have received NIP24 messages from the counterparty 2023-08-16 21:16:32 -04:00
Vitor Pamplona
c49f89f711 Fixes the color of the chart for changes in the Apps theme in settings 2023-08-16 21:03:50 -04:00
Vitor Pamplona
6721c83266 Back button was too bright. 2023-08-16 18:28:08 -04:00
Vitor Pamplona
ce27be2053 Fixes room names when clients send the same user twice in the ptags. 2023-08-16 18:10:56 -04:00
Vitor Pamplona
fee2a0e4f8 Fixes an incorrect import. 2023-08-16 18:05:10 -04:00
Vitor Pamplona
52fcfebe38 Fixes references in F-droid 2023-08-16 18:03:56 -04:00
Vitor Pamplona
0e1a856555 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-08-16 17:58:40 -04:00
Vitor Pamplona
255b48d126 - Creates a Quartz Module for Nostr Events
- Creates a Benchmark Module to test Performance
- Migrates from GSon to Jackson for Performance Gains, adapts all serializers accordingly
- Recreates Hex encoding/decoding classes for Performance.
- Migrates NIP24 to the new ByteArray Concat encoding.
- Removes support for Lenient choices in the. events.
- Reorganizes Nostr Events dependencies.
- Refactors TLV's and NIP-19 dependencies.
- Adds a Large DB for signature checks.
2023-08-16 17:58:25 -04:00
greenart7c3
584ceb1f0f Merge branch 'main' into amber 2023-08-16 17:21:47 -03:00
greenart7c3
8053119d42 decrypt dms using amber 2023-08-16 16:39:42 -03:00
greenart7c3
b8e97525eb add signer support whem replying 2023-08-16 14:34:11 -03:00
Vitor Pamplona
99adbf6691 Merge pull request #549 from ShinoharaTa/fix_broken_url
fix url regex pattern.
2023-08-16 10:39:32 -04:00
Vitor Pamplona
a96760d1a4 Merge pull request #551 from davotoula/update_translations
Added new translations for cs/de/se
2023-08-16 09:47:25 -04:00
David Kaspar
dd9e51e31c Added new translations for cs/de/se 2023-08-16 13:57:56 +01:00
tshinohara
a5b607b30b fix url regax pattern. 2023-08-16 02:48:50 +09:00
Vitor Pamplona
f7e9898637 Testing image uploads with Account info 2023-08-15 11:57:28 -04:00
Vitor Pamplona
1ad1d233cd Refactoring TLV's code 2023-08-15 11:13:01 -04:00
Vitor Pamplona
52687a48df Fixes image uploading tests without account. 2023-08-15 11:10:17 -04:00
Vitor Pamplona
dca4f827fe Moves navigation's top bar to use the ArrowBack 2023-08-14 23:07:08 -04:00
Vitor Pamplona
2726011126 Trim display names when possible 2023-08-14 23:06:33 -04:00
Vitor Pamplona
77bd646b1d Don't display username if display name is available. 2023-08-14 23:06:18 -04:00
Vitor Pamplona
d664d9ff19 Moves Relay List to a surface 2023-08-14 23:05:50 -04:00
Vitor Pamplona
5d24950d7f Starts NIP-65 implementation 2023-08-14 23:05:16 -04:00
Vitor Pamplona
3a8a50006d Improvements to the Settings Interface 2023-08-14 21:25:12 -04:00
Vitor Pamplona
decd6ef627 BugFix for HighlightEvent.create event. 2023-08-14 16:38:54 -04:00
Vitor Pamplona
6ab061a5a2 Avoids displaying a NIP-94 event without a url tag 2023-08-14 16:33:47 -04:00
Vitor Pamplona
d934e28b3a Updates some dependencies while we wait for Android 34's Gradle plugin to be released. 2023-08-14 16:10:43 -04:00
Vitor Pamplona
57588fd6ac no need for these idea files in GitHub 2023-08-14 16:05:01 -04:00
greenart7c3
66b1e4b15d add signer dialog to communities and public chats 2023-08-14 16:34:40 -03:00
Vitor Pamplona
921d52cb8c Moderated communities was renamed. 2023-08-14 15:12:18 -04:00
Vitor Pamplona
4a2d673cce Updates Readme for the new Private DMs 2023-08-14 15:02:57 -04:00
greenart7c3
e6f6f64512 add signer dialog in the relay screen 2023-08-14 13:53:10 -03:00
greenart7c3
d2eea9f0ae fix merge 2023-08-14 10:51:14 -03:00
greenart7c3
012fdc8cc6 add signer support in the user metadata screen 2023-08-14 10:46:03 -03:00
greenart7c3
74054aab5a add signer support for sending notes 2023-08-14 10:46:02 -03:00
greenart7c3
11908b9e0c if amber is installed show floatingActionButton 2023-08-14 10:43:10 -03:00
greenart7c3
570cccfc62 add signer support in the profile tabs 2023-08-14 10:42:57 -03:00
greenart7c3
de9d6877e1 fix merge 2023-08-14 10:42:57 -03:00
greenart7c3
c31fa116ca add signerdialog to boosts 2023-08-14 10:42:57 -03:00
greenart7c3
10b15226a1 added SignerDialog in the like reaction 2023-08-14 10:42:57 -03:00
greenart7c3
7a46376bc1 added SignerDialog in the hashtagscreen 2023-08-14 10:42:57 -03:00
greenart7c3
b761aaf970 sign unfollow event 2023-08-14 10:42:57 -03:00
greenart7c3
3a08db2dfb add signerDialog in the profile screen follow button 2023-08-14 10:42:57 -03:00
greenart7c3
41fd2e087c use rememberLauncherForActivityResult to send the intent and get the result back 2023-08-14 10:42:57 -03:00
greenart7c3
ba476bcdca created SignerDialog 2023-08-14 10:42:56 -03:00
Vitor Pamplona
c7a3a74d5a v0.73.3 2023-08-13 17:52:13 -04:00
Vitor Pamplona
eed2f6abaf Unused null section 2023-08-13 17:51:55 -04:00
Vitor Pamplona
80f0b14c02 BugFix for blank screen when pressing the message button without any history of chats 2023-08-13 17:38:44 -04:00
Vitor Pamplona
b12b81282c BugFix for the route in the DM Notification 2023-08-13 17:24:30 -04:00
Vitor Pamplona
07d661ea00 Only updates the Bookmarks and Follows flag when the sensitive content property of the account changes. 2023-08-12 21:40:09 -04:00
Vitor Pamplona
a15263eeb9 Moves zaps from Compose scope to ViewModel Scope 2023-08-12 21:38:14 -04:00
Vitor Pamplona
6f19bccc54 Observes the user's follow list and not the local account state to update TagLists on the screen 2023-08-12 21:37:31 -04:00
Vitor Pamplona
547d567431 Avoids account state redirections 2023-08-12 21:36:31 -04:00
Vitor Pamplona
ece4e9074a Updates the isHidden function to the same version the NoteCompose uses. 2023-08-12 21:36:13 -04:00
Vitor Pamplona
0737c6ddc3 Avoids a redirection of account State 2023-08-12 21:35:50 -04:00
Vitor Pamplona
2aa9458aa1 Moves Show And Hide user functions from ComposeScoped to ViewModel Scoped 2023-08-12 21:35:34 -04:00
Vitor Pamplona
cb3b898e29 Moves the creation of the TopBar livedata for lists into the AccountViewModel 2023-08-12 21:33:29 -04:00
Vitor Pamplona
ceac61eb19 Avoiding live data updates 2023-08-12 21:32:15 -04:00
Vitor Pamplona
bc9f5e5328 Moves HTTP regex compilation to outside the inner method 2023-08-12 21:31:49 -04:00
Vitor Pamplona
a293800897 Moves Regex compilation to outside the state class. 2023-08-12 21:31:10 -04:00
Vitor Pamplona
3be34d0d40 Speeding up regex 2023-08-12 18:15:45 -04:00
Vitor Pamplona
eec87f017a v0.73.2 2023-08-12 15:18:26 -04:00
Vitor Pamplona
799037502f Correctly displaying/hiding pictures in Chat Compose 2023-08-12 15:17:05 -04:00
Vitor Pamplona
f2b727c587 Fixes the PushNotification of GiftWrapped Messages 2023-08-12 15:00:30 -04:00
Vitor Pamplona
b255d1827e Forces the creation of Notification Channels to see if they show up on Samsung phones. 2023-08-12 14:59:53 -04:00
Vitor Pamplona
d9e01da7e2 Removes unnecessary code 2023-08-12 14:59:14 -04:00
Vitor Pamplona
99a98439cd Uses the right account to decrypt GiftWraps 2023-08-12 14:56:29 -04:00
Vitor Pamplona
724e7e2378 Merge pull request #547 from KotlinGeekDev/fix-landscape-issue
Fix menu drawer in landscape mode issue
2023-08-12 14:15:43 -04:00
Vitor Pamplona
0619c9ffac Displays GiftWraps as Messages in the Notification Screen 2023-08-12 14:12:46 -04:00
Vitor Pamplona
cb7b51e8d1 BugFix for marking chat as read 2023-08-12 13:50:40 -04:00
Vitor Pamplona
c8172265dd v0.73.1 2023-08-12 11:20:13 -04:00
Vitor Pamplona
cce9d424bc Fixes green color for incognito mode 2023-08-12 11:20:01 -04:00
Vitor Pamplona
45227b75dc Fixed ProGuard for libsodium 2023-08-12 11:15:20 -04:00
Vitor Pamplona
6eaba7956c Sets releases as pre-release by default. 2023-08-12 10:31:08 -04:00
Vitor Pamplona
cc4b94f738 v0.73.0 2023-08-12 10:10:09 -04:00
Vitor Pamplona
423628a104 Adding ways to update the subject 2023-08-12 10:04:15 -04:00
Vitor Pamplona
d262b48f31 BugFix: Chat List updating immediately when new messages arrive. 2023-08-11 20:04:37 -04:00
Vitor Pamplona
f97a0468cc BugFix for when the private room is with yourself. 2023-08-11 19:47:17 -04:00
Vitor Pamplona
b4d87686ac Adds an incognito badge in every msg 2023-08-11 19:46:59 -04:00
Vitor Pamplona
8cbf07c917 Moves GiftCard filter to Account filters and not Chats 2023-08-11 19:46:26 -04:00
Vitor Pamplona
30fc4c35f4 Only requests notification once. 2023-08-11 19:44:34 -04:00
Vitor Pamplona
7912d492e5 Makes sure replies of NIP24 are also NIP24 2023-08-11 19:43:36 -04:00
KotlinGeekDev
d921eb6138 Preserve behaviour pre-fix(i.e if a user opened the drawer and landscaped by choice). 2023-08-11 23:32:27 +01:00
KotlinGeekDev
6875fdc4d0 Watch orientation change, and close drawer in landscape mode. 2023-08-11 23:27:04 +01:00
Vitor Pamplona
0bc701f5c9 Adding a way to visualize all members of a group 2023-08-10 21:27:30 -04:00
Vitor Pamplona
5de0808b1e Merge pull request #545 from jeremyd/fix_global_relay_selection
fixing global relays selection
2023-08-10 20:06:59 -04:00
Vitor Pamplona
9d680c9f82 Merge pull request #546 from Bardesss/main-1
Update strings.xml (NL)
2023-08-10 20:06:06 -04:00
Vitor Pamplona
63fc4c570d Fixed Alby NWC link 2023-08-10 18:04:38 -04:00
Vitor Pamplona
ab2fff0194 Support for NIP24- Trustless GiftWrapped Sealed Private Direct Messages and Small Private Groups 2023-08-10 18:04:23 -04:00
Bardesss
c644ba9a3e Update strings.xml (NL)
Added missing strings.
2023-08-10 09:17:32 +00:00
jeremyd
2791873048 fixing global relays selection 2023-08-08 19:42:19 -07:00
Vitor Pamplona
89266bc76f Merge pull request #542 from frnandu/main
fix signed byte used for array slice with + added test
2023-08-07 09:14:27 -04:00
Fernando Martins
9573b4abec fix signed byte used for array slice with + added test 2023-08-07 11:56:11 +02:00
Vitor Pamplona
ddcff8fa15 don't return reposts and reactions in Search 2023-08-05 10:44:20 -04:00
Vitor Pamplona
d36f6f4a7e v0.72.2 2023-08-04 21:06:14 -04:00
Vitor Pamplona
c2b72f1e45 TimeAgo refactoring 2023-08-04 21:04:13 -04:00
Vitor Pamplona
28e6471ade Puts marked as read on chat to an IO thread 2023-08-04 21:03:19 -04:00
Vitor Pamplona
c3b8eb5087 Puts an invalidate data on an IO thread 2023-08-04 21:02:45 -04:00
Vitor Pamplona
75779e7ddc simple refactoring 2023-08-04 21:00:07 -04:00
Vitor Pamplona
118bc7b73c Don't invalidate data on channels if it is already invalidating 2023-08-04 20:58:10 -04:00
Vitor Pamplona
e6a0fdedd9 Removes unnecessary signing step 2023-08-04 20:57:21 -04:00
Vitor Pamplona
28098fafd7 Don't push to invalidate unless there is an observer. 2023-08-04 20:56:22 -04:00
Vitor Pamplona
0c0e87af21 Moves headers to the top nav bar 2023-08-04 16:50:23 -04:00
Vitor Pamplona
8abfd7149b Removes the need for .0 when on base sats. 2023-08-04 15:24:41 -04:00
Vitor Pamplona
674896cea4 Moves coroutine creation to the viewModel 2023-08-04 15:20:31 -04:00
Vitor Pamplona
ec514651fc Makes the New Channel creation scrollable. 2023-08-04 15:18:30 -04:00
Vitor Pamplona
8071d48911 updates github action to support minified versions of the app 2023-08-04 14:24:11 -04:00
Vitor Pamplona
69daa3835b v0.72.1 2023-08-04 13:18:15 -04:00
Vitor Pamplona
57dac276b2 Simple refactoring of the zap author and comment calculator function 2023-08-04 13:11:35 -04:00
Vitor Pamplona
3a84595aac Expanded DiskCache for images 2023-08-04 12:35:42 -04:00
Vitor Pamplona
7b591c84f8 Moves NIP95 cache to internal/secure folders 2023-08-04 12:32:36 -04:00
Vitor Pamplona
e8c8167451 Fixes the interference between simplecache and image chaces. 2023-08-04 12:25:12 -04:00
Vitor Pamplona
ec93fc53b2 Adds a cache forever tag to robohashes 2023-08-04 12:17:19 -04:00
Vitor Pamplona
ba2902b725 Moves URL Previews into suspend functions 2023-08-04 10:47:01 -04:00
Vitor Pamplona
e7defa14b9 Adds a little border for Long Form Content 2023-08-04 10:38:10 -04:00
Vitor Pamplona
4fbc3f25b3 Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-08-04 10:25:42 -04:00
Vitor Pamplona
4ae88d5cc8 Fixes an invalid string in values-fr 2023-08-04 10:25:34 -04:00
Vitor Pamplona
1aea0720df Merge pull request #540 from believethehype/nostrbuildv2
Nostr.build API v2, NIP98 support
2023-08-04 10:21:14 -04:00
believethehype
846f340f84 Merge branch 'vitorpamplona:main' into nostrbuildv2 2023-08-04 11:56:05 +02:00
Vitor Pamplona
cb137205c0 Fixes french translations 2023-08-03 17:16:55 -04:00
Vitor Pamplona
f910709e1b Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2023-08-03 17:05:26 -04:00
Vitor Pamplona
1d78dd6b19 Merge pull request #537 from anthony-robin/update-french-translations
[Translations] Update french texts
2023-08-03 17:05:19 -04:00
Anthony
3197be8a75 Remove translatable="false" keys 2023-08-03 22:00:51 +02:00
Anthony
91ed4128fe More french translations tweaks 2023-08-03 21:59:39 +02:00
Anthony
f415490fcd Update more french translations 2023-08-03 21:41:58 +02:00
Vitor Pamplona
4bdb5a28d0 - Fixes new lines after images
- Fixes urls with - https://github.com/vitorpamplona/amethyst/issues/536
2023-08-02 18:56:01 -04:00
Anthony
58efe0b3c0 Update french translations 2023-08-02 23:47:28 +02:00
Vitor Pamplona
da3cecd324 Displaying a bytecounter for events in memory when the app pauses. 2023-08-02 16:34:18 -04:00
Vitor Pamplona
09b1451dc1 Sets and Maps are 5x more memory intensive than Lists. This should help with memory management. 2023-08-02 16:33:53 -04:00
Vitor Pamplona
9ae31a3429 Reverting the commented galleries 2023-08-02 16:28:17 -04:00
Vitor Pamplona
b5258f89c1 Correcting the acceptable filter 2023-08-02 16:27:41 -04:00
Vitor Pamplona
fcc67fc4f2 Faster Galleries 2023-08-02 14:32:35 -04:00
Vitor Pamplona
579465ac6c Avoids null model errors that might be delaying some of the rendering. 2023-08-02 13:29:44 -04:00
Vitor Pamplona
6cbee81e72 Moves onCreate intent evaluation to the App Navigation 2023-08-02 13:29:04 -04:00
Believethehype
ad683ed444 added nostr.build api v2 / nip98
replaced nostr.build api with v2

Added NIP98 to nostr.build so images get added to premium account galleries, if available.
2023-08-02 04:14:35 +02:00
Vitor Pamplona
c53b1571a3 Additional classes to be serialized 2023-08-01 21:56:30 -04:00
Vitor Pamplona
2c19b2ffef Moves Geolocation search to the IO thread 2023-08-01 21:52:18 -04:00
Vitor Pamplona
3694d1b0f5 Avoids using String format. 2023-08-01 21:51:47 -04:00
Vitor Pamplona
e7a4746d22 Faster method to generate the hex of a url 2023-08-01 21:51:15 -04:00
Vitor Pamplona
7961f6f065 Removes unnecessary onIntent override 2023-08-01 21:50:49 -04:00
Vitor Pamplona
7c1c500990 Prepares for a minified release. 2023-08-01 21:49:30 -04:00
2913 changed files with 301941 additions and 80001 deletions

14
.editorconfig Normal file
View File

@@ -0,0 +1,14 @@
root = true
[*]
charset = utf-8
trim_trailing_whitespace = true
[*.{kt,kts}]
max_line_length = 5000
ij_kotlin_allow_trailing_comma=true
ij_kotlin_allow_trailing_comma_on_call_site=true
ktlint_function_naming_ignore_when_annotated_with=Composable, Test
[*.gradle]
indent_size = 4

View File

@@ -24,9 +24,13 @@ A clear and concise description of what you expected to happen.
If applicable, add a video and/or screenshots to help explain your problem.
**Device (please complete the following information):**
- Phone Brand/Model [e.g. Pixel 7 Pro]:
- Android Version [e.g. 33]:
- App Version [e.g. v0.20.3]:
- Phone Brand/Model [e.g. Pixel 7 Pro]:
- Android Version [e.g. 34]:
- App Version [e.g. v0.94.3]:
- App Flavour [e.g. Google Play or FDroid]:
- Amber Version (if using it to sign):
**Bounty (in Bitcoin sats) offered for a solution**
Incentivize developers to work on your issue. Describe clear milestones to claim payment.
The size of the bounty is proportional to how much this matters to you. If no bounty is offered,
not even a small one, this bug will not be worked on because it doesn't matter to you. We prioritize
bug fixing to issues that have bounties, even small ones.

View File

@@ -7,14 +7,10 @@ assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Bounty (in Bitcoin sats) offered for the implementation**
Incentivize developers to work on your feature. Describe clear milestones to claim payment.
**Additional context**
Add any other context, video, or screenshots about the feature request here.
The size of the bounty is proportional to how much this matters to you. If no bounty is offered,
not even a small one, this feature will not be coded because it doesn't actually matter to you.
We prioritize feature development by its bounty size compared to how much work is required to get it done.

View File

@@ -12,15 +12,17 @@ jobs:
timeout-minutes: 30
steps:
- uses: actions/checkout@v2
- name: Checkout code
uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v1
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: 17
distribution: 'zulu'
java-version: 21
- name: Cache gradle
uses: actions/cache@v1
uses: actions/cache@v4
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
@@ -28,7 +30,7 @@ jobs:
${{ runner.os }}-gradle-
- name: Linter (gradle)
run: ./gradlew ktlintCheck
run: ./gradlew spotlessCheck
- name: Test (gradle)
run: ./gradlew test --no-daemon
@@ -38,17 +40,47 @@ jobs:
if: ${{ always() }} # IMPORTANT: run Android Test Report regardless
- name: Build APK (gradle)
run: ./gradlew assembleDebug --no-daemon
run: ./gradlew assembleDebug
- name: Upload APK
uses: actions/upload-artifact@v2
- name: Upload Play APK
uses: actions/upload-artifact@v4
with:
name: Debug APK
path: app/build/outputs/apk/debug/app-debug.apk
name: Play Debug APK
path: amethyst/build/outputs/apk/play/debug/amethyst-play-universal-debug.apk
- name: Upload FDroid APK
uses: actions/upload-artifact@v4
with:
name: FDroid Debug APK
path: amethyst/build/outputs/apk/fdroid/debug/amethyst-fdroid-universal-debug.apk
- name: Build APK (gradle)
run: ./gradlew assembleBenchmark
- name: Upload Play APK Benchmark
uses: actions/upload-artifact@v4
with:
name: Play Benchmark APK
path: amethyst/build/outputs/apk/play/debug/amethyst-play-universal-benchmark.apk
- name: Upload FDroid APK Benchmark
uses: actions/upload-artifact@v4
with:
name: FDroid Benchmark APK
path: amethyst/build/outputs/apk/fdroid/debug/amethyst-fdroid-universal-benchmark.apk
- name: Upload Compose Reports
uses: actions/upload-artifact@v4
with:
name: Compose Reports
path: amethyst/build/compose_compiler
- name: Tests
run: ./gradlew test --no-daemon
- name: Upload Test Results
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: Build Reports
path: app/build/reports
name: Test Reports
path: amethyst/build/reports

View File

@@ -10,15 +10,16 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v1
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: 17
distribution: 'zulu'
java-version: 21
- name: Cache gradle
uses: actions/cache@v1
uses: actions/cache@v4
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
@@ -31,20 +32,26 @@ jobs:
- name: Sign AAB (Google Play)
uses: r0adkll/sign-android-release@v1
with:
releaseDirectory: app/build/outputs/bundle/playRelease
releaseDirectory: amethyst/build/outputs/bundle/playRelease
signingKeyBase64: ${{ secrets.SIGNING_KEY }}
alias: ${{ secrets.KEY_ALIAS }}
keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }}
keyPassword: ${{ secrets.KEY_PASSWORD }}
env:
# override default build-tools version (29.0.3) -- optional
BUILD_TOOLS_VERSION: "36.0.0"
- name: Sign AAB (F-Droid)
uses: r0adkll/sign-android-release@v1
with:
releaseDirectory: app/build/outputs/bundle/fdroidRelease
releaseDirectory: amethyst/build/outputs/bundle/fdroidRelease
signingKeyBase64: ${{ secrets.SIGNING_KEY }}
alias: ${{ secrets.KEY_ALIAS }}
keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }}
keyPassword: ${{ secrets.KEY_PASSWORD }}
env:
# override default build-tools version (29.0.3) -- optional
BUILD_TOOLS_VERSION: "36.0.0"
- name: Build APK
run: ./gradlew assembleRelease --stacktrace
@@ -52,20 +59,26 @@ jobs:
- name: Sign APK (Google Play)
uses: r0adkll/sign-android-release@v1
with:
releaseDirectory: app/build/outputs/apk/play/release
releaseDirectory: amethyst/build/outputs/apk/play/release
signingKeyBase64: ${{ secrets.SIGNING_KEY }}
alias: ${{ secrets.KEY_ALIAS }}
keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }}
keyPassword: ${{ secrets.KEY_PASSWORD }}
env:
# override default build-tools version (29.0.3) -- optional
BUILD_TOOLS_VERSION: "36.0.0"
- name: Sign APK (F-Droid)
uses: r0adkll/sign-android-release@v1
with:
releaseDirectory: app/build/outputs/apk/fdroid/release
releaseDirectory: amethyst/build/outputs/apk/fdroid/release
signingKeyBase64: ${{ secrets.SIGNING_KEY }}
alias: ${{ secrets.KEY_ALIAS }}
keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }}
keyPassword: ${{ secrets.KEY_PASSWORD }}
env:
# override default build-tools version (29.0.3) -- optional
BUILD_TOOLS_VERSION: "36.0.0"
- name: Create Release
id: create_release
@@ -76,7 +89,7 @@ jobs:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
draft: false
prerelease: false
prerelease: true
# Google Play APK
- name: Upload Play APK Universal Asset
@@ -85,8 +98,8 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: app/build/outputs/apk/play/release/app-play-universal-release-unsigned-signed.apk
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: amethyst/build/outputs/apk/play/release/amethyst-play-universal-release-unsigned-signed.apk
asset_name: amethyst-googleplay-universal-${{ github.ref_name }}.apk
asset_content_type: application/zip
@@ -97,7 +110,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: app/build/outputs/apk/play/release/app-play-x86-release-unsigned-signed.apk
asset_path: amethyst/build/outputs/apk/play/release/amethyst-play-x86-release-unsigned-signed.apk
asset_name: amethyst-googleplay-x86-${{ github.ref_name }}.apk
asset_content_type: application/zip
@@ -108,10 +121,32 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: app/build/outputs/apk/play/release/app-play-x86_64-release-unsigned-signed.apk
asset_path: amethyst/build/outputs/apk/play/release/amethyst-play-x86_64-release-unsigned-signed.apk
asset_name: amethyst-googleplay-x86_64-${{ github.ref_name }}.apk
asset_content_type: application/zip
- name: Upload Play APK arm64-v8a Asset
id: upload-release-asset-play-arm64-v8a-apk
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: amethyst/build/outputs/apk/play/release/amethyst-play-arm64-v8a-release-unsigned-signed.apk
asset_name: amethyst-googleplay-arm64-v8a-${{ github.ref_name }}.apk
asset_content_type: application/zip
- name: Upload Play APK armeabi-v7a Asset
id: upload-release-asset-play-armeabi-v7a-apk
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: amethyst/build/outputs/apk/play/release/amethyst-play-armeabi-v7a-release-unsigned-signed.apk
asset_name: amethyst-googleplay-armeabi-v7a-${{ github.ref_name }}.apk
asset_content_type: application/zip
# F-Droid APK
- name: Upload F-Droid APK Universal Asset
id: upload-release-asset-fdroid-universal-apk
@@ -120,7 +155,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: app/build/outputs/apk/fdroid/release/app-fdroid-universal-release-unsigned-signed.apk
asset_path: amethyst/build/outputs/apk/fdroid/release/amethyst-fdroid-universal-release-unsigned-signed.apk
asset_name: amethyst-fdroid-universal-${{ github.ref_name }}.apk
asset_content_type: application/zip
@@ -131,7 +166,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: app/build/outputs/apk/fdroid/release/app-fdroid-x86-release-unsigned-signed.apk
asset_path: amethyst/build/outputs/apk/fdroid/release/amethyst-fdroid-x86-release-unsigned-signed.apk
asset_name: amethyst-fdroid-x86-${{ github.ref_name }}.apk
asset_content_type: application/zip
@@ -142,10 +177,32 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: app/build/outputs/apk/fdroid/release/app-fdroid-x86_64-release-unsigned-signed.apk
asset_path: amethyst/build/outputs/apk/fdroid/release/amethyst-fdroid-x86_64-release-unsigned-signed.apk
asset_name: amethyst-fdroid-x86_64-${{ github.ref_name }}.apk
asset_content_type: application/zip
- name: Upload F-Droid APK arm64-v8a Asset
id: upload-release-asset-fdroid-arm64-v8a-apk
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: amethyst/build/outputs/apk/fdroid/release/amethyst-fdroid-arm64-v8a-release-unsigned-signed.apk
asset_name: amethyst-fdroid-arm64-v8a-${{ github.ref_name }}.apk
asset_content_type: application/zip
- name: Upload F-Droid APK armeabi-v7a Asset
id: upload-release-asset-fdroid-armeabi-v7a-apk
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: amethyst/build/outputs/apk/fdroid/release/amethyst-fdroid-armeabi-v7a-release-unsigned-signed.apk
asset_name: amethyst-fdroid-armeabi-v7a-${{ github.ref_name }}.apk
asset_content_type: application/zip
# Google Play AAB
@@ -156,7 +213,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: app/build/outputs/bundle/playRelease/app-play-release.aab
asset_path: amethyst/build/outputs/bundle/playRelease/amethyst-play-release.aab
asset_name: amethyst-googleplay-${{ github.ref_name }}.aab
asset_content_type: application/zip
@@ -168,6 +225,6 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: app/build/outputs/bundle/fdroidRelease/app-fdroid-release.aab
asset_path: amethyst/build/outputs/bundle/fdroidRelease/amethyst-fdroid-release.aab
asset_name: amethyst-fdroid-${{ github.ref_name }}.aab
asset_content_type: application/zip
asset_content_type: application/zip

30
.github/workflows/crowdin.yml vendored Normal file
View File

@@ -0,0 +1,30 @@
name: Crowdin Action
on:
push:
# paths: ["app/src/main/res/**/strings.xml"] // removes filter to allow downloads at any moment.
branches: [ main ]
jobs:
synchronize-with-crowdin:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: crowdin action
uses: crowdin/github-action@v2
with:
upload_sources: true
upload_translations: true
download_translations: true
localization_branch_name: l10n_crowdin_translations
create_pull_request: true
pull_request_title: 'New Crowdin Translations'
pull_request_body: 'New Crowdin translations by [Crowdin GH Action](https://github.com/crowdin/github-action)'
pull_request_base_branch_name: 'main'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}

11
.gitignore vendored
View File

@@ -7,6 +7,16 @@
/.idea/assetWizardSettings.xml
/.idea/androidTestResultsUserPreferences.xml
/.idea/deploymentTargetDropDown.xml
/.idea/deploymentTargetSelector.xml
/.idea/appInsightsSettings.xml
/.idea/ktlint-plugin.xml
/.idea/ktfmt.xml
/.idea/studiobot.xml
/.idea/other.xml
/.idea/runConfigurations.xml
/.idea/ChatHistory_schema_v2.xml
/.idea/artifacts/*
/.idea/kotlinNotebook.xml
.DS_Store
/build
/captures
@@ -36,6 +46,7 @@ out/
.gradle
.gradle/
build/
.kotlin/
# Local configuration file (sdk path, etc)
local.properties

3
.idea/.gitignore generated vendored
View File

@@ -1,3 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml

1
.idea/.name generated
View File

@@ -1 +0,0 @@
Amethyst

6
.idea/AndroidProjectSystem.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AndroidProjectSystem">
<option name="providerId" value="com.android.tools.idea.GradleProjectSystem" />
</component>
</project>

13
.idea/deviceManager.xml generated Normal file
View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DeviceTable">
<option name="columnSorters">
<list>
<ColumnSorterState>
<option name="column" value="Name" />
<option name="order" value="ASCENDING" />
</ColumnSorterState>
</list>
</option>
</component>
</project>

1
.idea/icon.svg generated Normal file
View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 170.16 186.2"><defs><style>.cls-1{fill:url(#linear-gradient);}.cls-2{fill:url(#linear-gradient-2);}</style><linearGradient id="linear-gradient" x1="80.19" y1="57.17" x2="91.66" y2="57.17" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#652d80"/><stop offset="1" stop-color="#2598cf"/></linearGradient><linearGradient id="linear-gradient-2" x1="335.87" y1="297.64" x2="506.02" y2="297.64" xlink:href="#linear-gradient"/></defs><title>Amethyst_svg_monogram</title><ellipse class="cls-1" cx="85.93" cy="57.17" rx="5.74" ry="5.64"/><path class="cls-2" d="M506,347.08c-.2-.61-46.85-111.69-59.68-142.5-15.62,0-48.61,0-71.88,0-6.83,16.89-24.46,59.94-38.6,94.62,7.75,18.49,14.71,35.1,20.08,47.91l29.27,0a2,2,0,0,0,1.87-2.35c-.25-5.91-16.34-27.39-11.54-50.63,1.28-5,2.26-10.08,3.66-15.06a175.77,175.77,0,0,1,13.44-34.8c.89-1.69,1.3-2.45,3.35-1.17,4.37,2.72,9.25,2.56,14.11,2.21,4.19-.91,6.23-2.92,13.91-.88,1.52,0,3,0,4.55.14,3.69.29,7.15,1.17,9.37,4.51,2.42,3.65,2.81,7.78,2.42,12-.59,6.31-.17,12.19,5.17,16.64a57.52,57.52,0,0,0,6,4c2.65,1.7,5.85,2.44,8.12,4.8,1.34,1.39,2.13,2.87,1.55,4.85s-2.13,2.91-4.17,3.13c-5.16.56-10.2-.49-15.27-1.1-.66-.08-1.31-.13-2-.17a11.47,11.47,0,0,1-3.81.13l-1.19,0a26.7,26.7,0,0,0-5.9,1.41c-4.78,1.74-9.13,3.66-14.77,3.56a4.32,4.32,0,0,0-2.05.89c-4.42,3.93-7.08,8.89-4.87,16.14,6.06,16.93,21.61,57.77,28.29,75.4-.19-11.94-.24-33.32-.28-43.7C461.83,347.1,502.74,347.08,506,347.08Z" transform="translate(-335.87 -204.54)"/></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -1,12 +1,45 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="ComposePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="ComposePreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="ComposePreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="ComposePreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="GlancePreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
<option name="composableFile" value="true" />
</inspection_tool>
<inspection_tool class="GlancePreviewMustBeTopLevelFunction" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
</inspection_tool>
<inspection_tool class="GlancePreviewNeedsComposableAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
</inspection_tool>
<inspection_tool class="GlancePreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewAnnotationInFunctionWithParameters" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewApiLevelMustBeValid" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewDeviceShouldUseNewSpec" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
<option name="composableFile" value="true" />
@@ -32,6 +65,10 @@
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewParameterProviderOnFirstParameter" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />
</inspection_tool>
<inspection_tool class="PreviewPickerAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
<option name="composableFile" value="true" />
<option name="previewFile" value="true" />

6
.idea/kotlinNotebook.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KotlinNotebookOptionsProvider">
<option name="shouldAddProjectLibrariesToClasspath" value="true" />
</component>
</project>

8
.idea/kotlinc.xml generated
View File

@@ -1,6 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Kotlin2JsCompilerArguments">
<option name="moduleKind" value="plain" />
</component>
<component name="Kotlin2JvmCompilerArguments">
<option name="jvmTarget" value="1.8" />
</component>
<component name="KotlinJpsPluginSettings">
<option name="version" value="1.9.0" />
<option name="version" value="2.1.0" />
</component>
</project>

View File

@@ -4,33 +4,39 @@
Effective as of Jun 12, 2023
The Amethyst app for Android does not collect or process any personal information from its users. The app is used to connect to third-party Nostr servers (also called Relays) that may or may not collect personal information and are not covered by this privacy policy. Each third-party relay server comes equipped with its own privacy policy and terms of use that can be viewed through the app or through that server's website. The developers of this open-source project or maintainers of the distribution channels (app stores) do not have access to the data located in the user's phone. Accounts are fully maintained by the user. We do not have control over them.
The Amethyst app for Android does not collect or process any personal information from its users.
The app may collect a per-device token, your public key, and a preferred Relay to connect to and provide push notification services through Google's Firebase Cloud Messaging. Other than that, the data from connected accounts are only stored locally on the device when it's required for the functionality and performance of Amethyst. This data is strictly confidential and cannot be accessed by other apps (on non-rooted devices). Phone data can be deleted by clearing Amethyst's local storage or uninstalling the app.
The app is used to browse third-party Nostr servers (called Relays) that may or may not collect personal information and are not covered by this privacy policy. Each third-party relay server comes equipped with its own privacy policy and terms of use that can be viewed through the app or through that server's website. The developers of this open-source project or maintainers of the distribution channels (app stores) do not have access to the data located in the user's phone. Accounts are fully maintained by the user. We do not have control over them.
Amethyst offers a few options to upload pictures and videos in order to post them online. You can choose the server at your discretion. Similar to relays, such services are independent of the app and have their own privacy policy and terms of use.
The app may collect a per-device token, your public key, and a preferred Relay to connect to and provide push notification services through Google's Firebase Cloud Messaging. Other than that, the data from connected accounts is only stored locally on the device when it's required for the functionality and performance of Amethyst. This data is strictly confidential and cannot be accessed by other apps (on non-rooted devices). Phone data can be deleted by clearing Amethyst's local storage or uninstalling the app.
### Privacy with Relays services
Amethyst offers several options for uploading pictures and videos to post online. You can choose the server at your discretion. Similar to relays, such services are independent of the app and have their own privacy policy and terms of use.
Your internet protocol (IP) address is exposed to the relays you connect to. If you want to improve your privacy, consider utilizing a service that masks your IP address (e.g. a VPN) from trackers online.
### Privacy with Relay services
Your Internet Protocol (IP) address is exposed to the relays you connect to. If you want to improve your privacy, consider utilizing a service that masks your IP address (e.g., a VPN) from trackers online.
The relay can also see which public keys you are using and what information you are requesting from the network. Your public key is tied to your IP address and your relay filters.
Relays have all your data in raw text. They know your IP, your name, your location (guessed from IP), your pub key, all your contacts, and other relays, and can read every action you do (post, like, boost, quote, report, etc) with the exception of the content inside Private Zaps and Private DMs.
While the content of direct messages (DMs) is only visible to you, and your DM Nostr counterparty, everyone can see when you and your counterparty are DM-ing each other. Image uploads in the DM screen use one of the chosen image servers and simply paste the image link on the DM text. Your uploaded pictures are available to anyone with that direct link.
While the content of direct messages (DMs) is only visible to you and your DM Nostr counterparty, everyone can see when you and your counterparty are DM-ing each other. Image uploads in the DM screen use one of the chosen image servers and simply paste the image link into the DM text. Your uploaded pictures are available to anyone with that direct link.
### Visibility & Permanence of Your Content on Nostr Relays
#### Information Visibility
Content that you share can be shared with other relays by any user of the network.
Information that you share is publicly visible to anyone reading from relays that have your information. Your information may also be visible to Nostr users who do not share relays with you.
The information you share is publicly visible to anyone reading from relays that have access to your information. Your information may also be visible to Nostr users who do not share relays with you.
#### Information Permanence
Information shared on Nostr should be assumed permanent for privacy purposes. There is no way to guarantee deleting or editing any content once posted.
## Child safety standards
Amethyst does not knowingly collect information from children. The app has no age verification because it collects no personal information from anyone. The application is 17+. We rely on Google Play's age verification to make sure the user downloading the app is an adult. Since we do not control which relays the user connects to, there is no content moderation beyond the standard block post, block account, and report post and/or account that will hide the content from the user.
## Terms of Use
### For versions downloaded from Google's Play Store

365
README.md
View File

@@ -1,135 +1,190 @@
# Amethyst: Nostr client for Android
<div align="center">
<img align="right" src="./docs/screenshots/home.png" data-canonical-src="./docs/screenshots/home.png" width="350px"/>
<a href="https://amethyst.social">
<img src="./docs/design/3rd%20Logo%20-%20Zitron/amethyst.svg" alt="Amethyst Logo" title="Amethyst logo" width="80"/>
</a>
Amethyst brings the best social network to your Android phone. Just insert your Nostr private key and start posting.
# Amethyst
## Nostr Client for Android
Join the social network you control.
[![GitHub downloads](https://img.shields.io/github/downloads/vitorpamplona/amethyst/total?label=Downloads&labelColor=27303D&color=0D1117&logo=github&logoColor=FFFFFF&style=flat)](https://github.com/vitorpamplona/amethyst/releases)
[![PlayStore downloads](https://img.shields.io/endpoint?color=green&logo=google-play&logoColor=green&url=https%3A%2F%2Fplay.cuzi.workers.dev%2Fplay%3Fi%3Dcom.vitorpamplona.amethyst%26gl%3DUS%26hl%3Den%26l%3DPlayStore%26m%3D%24shortinstalls)](https://play.google.com/store/apps/details?id=com.vitorpamplona.amethyst)
[![Last Version](https://img.shields.io/github/release/vitorpamplona/amethyst.svg?maxAge=3600&label=Stable&labelColor=06599d&color=043b69)](https://github.com/vitorpamplona/amethyst)
[![JitPack version](https://jitpack.io/v/vitorpamplona/amethyst.svg)](https://jitpack.io/#vitorpamplona/amethyst)
[![CI](https://img.shields.io/github/actions/workflow/status/vitorpamplona/amethyst/build.yml?labelColor=27303D)](https://github.com/vitorpamplona/amethyst/actions/workflows/build.yml)
[![License: Apache-2.0](https://img.shields.io/github/license/vitorpamplona/amethyst?labelColor=27303D&color=0877d2)](/LICENSE)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/vitorpamplona/amethyst)
## Download and Install
[<img src="./docs/design/zapstore.svg"
alt="Get it on Zap Store"
height="70">](https://github.com/zapstore/zapstore/releases)
[<img src="./docs/design/obtainium.png"
alt="Get it on Obtaininum"
height="80">](https://github.com/ImranR98/Obtainium)
height="70">](https://github.com/ImranR98/Obtainium)
[<img src="https://github.com/machiav3lli/oandbackupx/raw/034b226cea5c1b30eb4f6a6f313e4dadcbb0ece4/badge_github.png" alt="Get it on GitHub"
height="80">](https://github.com/vitorpamplona/amethyst/releases)
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
alt="Get it on F-Droid"
height="80">](https://f-droid.org/packages/com.vitorpamplona.amethyst/)
height="70">](https://github.com/vitorpamplona/amethyst/releases)
[<img src="https://play.google.com/intl/en_us/badges/images/generic/en-play-badge.png"
alt="Get it on Google Play"
height="80">](https://play.google.com/store/apps/details?id=com.vitorpamplona.amethyst)
height="70">](https://play.google.com/store/apps/details?id=com.vitorpamplona.amethyst)
# Current Features
</div>
- [x] Event Builders / WebSocket Subscriptions (NIP-01)
- [x] Home Feed
- [x] Notifications Feed
- [x] Global Feed
- [x] Replies and mentions (NIP-10)
- [x] Reactions (NIP-25)
- [x] Reposts (NIP-18)
- [x] Image/Video/Url/LnInvoice Previews
- [x] View Threads
## Supported Features
<img align="right" src="./docs/screenshots/home.png" data-canonical-src="./docs/screenshots/home.png" width="350px">
- [x] Events / Relay Subscriptions (NIP-01)
- [x] Follow List (NIP-02)
- [x] OpenTimestamps Attestations (NIP-03)
- [x] Private Messages (NIP-04)
- [x] User Profiles (edit/follow/unfollow - NIP-02)
- [x] Public Chats (NIP-28)
- [x] Bech Encoding support (NIP-19)
- [x] Notification Dots
- [x] Reporting and Hide User capability (NIP-56)
- [x] Automatic Translations
- [x] Relay Sets (home, dms, public chats, global)
- [x] User/Note Tagging (NIP-08, NIP-10)
- [x] Lightning Tips
- [x] Zaps (private, public, anon, non-zap) (NIP-57)
- [x] URI Support (NIP-21)
- [x] Created_at Limits (NIP-22)
- [x] DNS Address (NIP-05)
- [x] Mnemonic seed phrase (NIP-06)
- [ ] WebBrowser Signer (NIP-07, Not applicable)
- [x] Old-style mentions (NIP-08)
- [x] Event Deletion (NIP-09)
- [x] Nostr Address (NIP-05)
- [x] Long-form Content (NIP-23)
- [x] Replies, mentions, Threads, and Notifications (NIP-10)
- [x] Relay Information Document (NIP-11)
- [x] Generic Tag Queries (NIP-12)
- [x] Proof of Work Display (NIP-13)
- [ ] Proof of Work Calculations (NIP-13)
- [x] Events with a Subject (NIP-14)
- [ ] Marketplace (NIP-15)
- [x] Event Treatment (NIP-16)
- [x] Private Direct Messages (NIP-17)
- [x] Image/Video/Url/LnInvoice Previews
- [x] Reposts, Quotes, Generic Reposts (NIP-18)
- [x] Bech Encoding support (NIP-19)
- [x] Command Results (NIP-20)
- [x] URI Support (NIP-21)
- [x] Long-form Content (NIP-23) (view only)
- [x] User Profile Fields / Relay list (NIP-24)
- [x] Reactions (NIP-25)
- [ ] Delegated Event Signing (NIP-26, Will not implement)
- [x] Text Note References (NIP-27)
- [x] Public Chats (NIP-28)
- [ ] Relay-based Groups (NIP-29)
- [x] Custom Emoji (NIP-30)
- [x] Event kind summaries (NIP-31)
- [ ] Labeling (NIP-32)
- [x] Parameterized Replaceable Events (NIP-33)
- [x] Online Relay Search (NIP-50)
- [x] Internationalization
- [x] Badges (NIP-58)
- [x] Hashtag Following and Custom Hashtags
- [x] Polls (NIP-69)
- [x] Verifiable static content in URLs (NIP-94)
- [x] Login with QR
- [x] Git Stuff (NIP-34)
- [ ] Torrents (NIP-35)
- [x] Sensitive Content (NIP-36)
- [x] Edits (NIP-37/Draft)
- [x] User Status Event (NIP-38)
- [x] External Identities (NIP-39)
- [x] Expiration Support (NIP-40)
- [x] Relay Authentication (NIP-42)
- [x] Versioned Encrypted Payloads (NIP-44)
- [ ] Event Counts (NIP-45, Will not implement)
- [ ] Nostr Connect (NIP-46)
- [x] Wallet Connect API (NIP-47)
- [x] Accessible uploads
- [ ] Proxy Tags (NIP-48, Not applicable)
- [x] Private key encryption for import/export (NIP-49)
- [x] Online Relay Search (NIP-50)
- [x] Lists (NIP-51)
- [ ] Calendar Events (NIP-52)
- [x] Live Activities & Live Chats (NIP-53)
- [x] Wiki (NIP-54)
- [x] Inline Metadata (NIP-55 - Draft)
- [x] Reporting (NIP-56)
- [x] Lightning Tips
- [x] Zaps (NIP-57)
- [x] Private Zaps
- [x] Zap Splits (NIP-57)
- [x] Badges (NIP-58)
- [x] Gift Wraps & Seals (NIP-59)
- [x] Zapraiser (NIP-TBD)
- [ ] Relay List Metadata (NIP-65)
- [x] Polls (NIP-69)
- [x] Video Events (NIP-71)
- [x] Moderated Communities (NIP-72)
- [ ] Zap Goals (NIP-75)
- [x] Arbitrary Custom App Data (NIP-78)
- [x] Highlights (NIP-84)
- [x] Notify Request (NIP-88/Draft)
- [x] Recommended Application Handlers (NIP-89)
- [x] Data Vending Machine (NIP-90)
- [x] Inline Metadata (NIP-92)
- [x] Verifiable file URLs (NIP-94)
- [x] Binary Blobs (NIP-95/Draft)
- [x] HTTP File Storage Integration (NIP-96)
- [x] HTTP Auth (NIP-98)
- [x] Classifieds (NIP-99)
- [x] Audio Tracks (zapstr.live) (kind:31337)
- [x] Push Notifications (Google and Unified Push)
- [x] In-Device Automatic Translations
- [x] Hashtag Following and Custom Hashtags
- [x] Login with QR
- [x] Bounty support (nostrbounties.com)
- [x] De-googled F-Droid flavor
- [x] External Identity Support (NIP-39)
- [x] Multiple Accounts
- [x] Markdown Support
- [x] Relay Authentication (NIP-42)
- [x] Content stored in relays themselves (NIP-95)
- [x] Custom Emoji (NIP-30)
- [x] Zap Forwarding (NIP-57)
- [x] Text Note References (NIP-27)
- [x] Audio Tracks (zapstr.live) (Kind:31337)
- [x] Push Notifications (Zaps and Messages)
- [x] Generic Tags (NIP-12)
- [x] Sensitive Content (NIP-36)
- [x] View Individual Reactions (Like, Boost, Zaps, Reports) per Post
- [x] Recommended Application Handlers (NIP-89)
- [x] Events with a Subject (NIP-14)
- [x] Generic Reposts (kind:16)
- [x] Live Activities & Live Chats (NIP-53)
- [x] Relay Pages (NIP-11)
- [x] HTTP Auth (NIP-98)
- [x] Zapraiser (NIP-TBD)
- [x] Moderated Communities (NIP-172)
- [x] Emoji Packs (Kind:30030)
- [x] Personal Emoji Lists (Kind:10030)
- [x] Classifieds (Kind:30403)
- [ ] Marketplace (NIP-15)
- [ ] Image/Video Capture in the app
- [x] Medical Data (NIP-xx/Draft)
- [x] Embed events (NIP-xx/Draft)
- [x] Draft Events (NIP-xx/Draft)
- [ ] Event Sets (NIP-xx/Draft)
- [ ] Topical Notes (NIP-xx/Draft)
- [ ] Relationship Status (NIP-xx/Draft)
- [ ] Signed Filters (NIP-xx/Draft)
- [ ] Key Migration (NIP-xx/Draft)
- [ ] Time-based Sync (NIP-xx/Draft)
- [x] Image Capture in the app
- [ ] Video Capture in the app
- [ ] Local Database
- [ ] Bookmarks, Pinned Posts, Muted Events (NIP-51)
- [ ] Proof of Work in the Phone (NIP-13, NIP-20)
- [ ] Workspaces
- [ ] Expiration Support (NIP-40)
- [ ] Infinity Scroll
- [ ] Relay List Metadata (NIP-65)
- [ ] Signing Requests (NIP-46)
- [ ] Delegated Event Signing (NIP-26)
- [ ] Account Creation / Backup Guidance
- [ ] Mnemonic seed phrase (NIP-06)
- [ ] Message Sent feedback (NIP-20)
- [ ] OpenTimestamps Attestations (NIP-03)
## Privacy and Information Permanence
Relays know your IP address, your name, your location (guessed from IP), your pub key, all your contacts, and other relays, and can read every action you do (post, like, boost, quote, report, etc) except for Private Zaps and Private DMs. While the content of direct messages (DMs) is only visible to you and your DM counterparty, everyone can see when you and your counterparty DM each other.
If you want to improve your privacy, consider utilizing a service that masks your IP address (e.g. a VPN or Tor) from trackers online.
The relay also learns which public keys you are requesting, meaning your public key will be tied to your IP address.
Information shared on Nostr can be re-broadcasted to other servers and should be assumed permanent for privacy purposes. There is no way to guarantee the deletion of any content once posted.
# Development Overview
## Overall Architecture
This repository is split between Amethyst and Quartz:
- Amethyst is a native Android app made with Kotlin and Jetpack Compose.
- Quartz is our own Nostr-commons library to host classes that are of interest to other Nostr Clients.
This is a native Android app made with Kotlin and Jetpack Compose.
The app uses a modified version of the [nostrpostrlib](https://github.com/Giszmo/NostrPostr/tree/master/nostrpostrlib) to talk to Nostr relays.
The overall architecture consists in the UI, which uses the usual State/ViewModel/Composition, the service layer that connects with Nostr relays,
The app architecture consists of the UI, which uses the usual State/ViewModel/Composition, the service layer that connects with Nostr relays,
and the model/repository layer, which keeps all Nostr objects in memory, in a full OO graph.
The repository layer stores Nostr Events as Notes and Users separately. Those classes use LiveData objects to
allow the UI and other parts of the app to subscribe to each individual Note/User and receive updates when they happen.
They are also responsible for updating viewModels when needed. Filters react to changes in the screen. As the user
sees different Events, the Datasource classes are used to receive more information about those particular Events.
The repository layer stores Nostr Events as Notes and Users separately. Those classes use LiveData and Flow objects to
allow the UI and other parts of the app to subscribe to each Note/User and receive updates when they happen.
They are also responsible for updating viewModels when needed. As the user scrolls through Events, the Datasource classes
are updated to receive more information about those particular Events.
Most of the UI is reactive to changes in the repository classes. The service layer assembles Nostr filters for each need of the app,
receives the data from the Relay, and sends it to the repository. Connection with relays is never closed during the use of the app.
The UI receives a notification that objects were updated. Instances of User and Notes are mutable directly.
The UI receives a notification that objects have been updated. Instances of User and Notes are mutable directly.
There will never be two Notes with the same ID or two User instances with the same pubkey.
Lastly, the user's account information (priv key/pub key) is stored in the Android KeyStore for security.
Lastly, the user's account information (private key/pub key) is stored in the Android KeyStore for security.
## Setup
Make sure to have the following pre-requisites installed:
1. Java 17
1. Java 21+
2. Android Studio
3. Android 8.0+ Phone or Emulation setup
Fork and clone this repository and import into Android Studio
Fork and clone this repository and import it into Android Studio
```bash
git clone https://github.com/vitorpamplona/amethyst.git
```
Use one of the Android Studio builds to install and run the app in your device or a simulator.
Use an Android Studio build action to install and run the app on your device or a simulator.
## Building
Build the app:
@@ -145,8 +200,8 @@ Build the app:
## Linting
```bash
./gradlew ktlintCheck
./gradlew ktlintFormat
./gradlew spotlessCheck
./gradlew spotlessApply
```
## Installing on device
@@ -161,54 +216,138 @@ For the Play build:
./gradlew installPlayDebug
```
## How to Deploy
## Deploying
1. Generate a new signing key
```
keytool -genkey -v -keystore <my-release-key.keystore> -alias <alias_name> -keyalg RSA -keysize 2048 -validity 10000
openssl base64 < <my-release-key.keystore> | tr -d '\n' | tee some_signing_key.jks.base64.txt
```
2. Create 4 Secret Key variables on your GitHub repository and fill in with the signing key information
2. Create four Secret Key variables on your GitHub repository and fill in the signing key information
- `KEY_ALIAS` <- `<alias_name>`
- `KEY_PASSWORD` <- `<your password>`
- `KEY_STORE_PASSWORD` <- `<your key store password>`
- `SIGNING_KEY` <- the data from `<my-release-key.keystore>`
3. Change the `versionCode` and `versionName` on `app/build.gradle`
3. Change the `versionCode` and `versionName` on `amethyst/build.gradle`
4. Commit and push.
5. Tag the commit with `v{x.x.x}`
6. Let the [Create Release GitHub Action](https://github.com/vitorpamplona/amethyst/actions/workflows/create-release.yml) build a new `aab` file.
7. Add your CHANGE LOG to the description of the new release
8. Download the `aab` file and upload it to the` PlayStore.
8. Download the `aab` file and upload it to the PlayStore.
# Privacy on Relays & nostr
Your internet protocol (IP) address is exposed to the relays you connect to. If you want to improve your privacy, consider utilizing a service that masks your IP address (e.g. a VPN) from trackers online.
## Using the Quartz library
The relay also learns which public keys you are requesting, meaning your public key will be tied to your IP address.
Setup [JitPack.io](https://jitpack.io/#vitorpamplona/amethyst/v0.84.3) to your build file
Relays have all your data in raw text. They know your IP, your name, your location (guessed from IP), your pub key, all your contacts, and other relays, and can read every action you do (post, like, boost, quote, report, etc) with the exception of Private Zaps and Private DMs.
Add `maven { url 'https://jitpack.io' }` to settings.gradle at the end of repositories:
# DM Privacy #
While the content of direct messages (DMs) is only visible to you, and your DM nostr counterparty, everyone can see that and when you and your counterparty are DM-ing each other.
```gradle
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
maven { url 'https://jitpack.io' }
}
}
```
# Visibility & Permanence of Your Content on nostr
## Information Visibility ##
Content that you share can be shared to other relays.
Information that you share is publicly visible to anyone reading from relays that have your information. Your information may also be visible to nostr users who do not share relays with you.
Add the dependency by using one of the versions [here](https://jitpack.io/#vitorpamplona/amethyst/)
## Information Permanence ##
Information shared on nostr should be assumed permanent for privacy purposes. There is no way to guarantee deleting or editing any content once posted.
```gradle
implementation('com.github.vitorpamplona.amethyst:quartz:<tag, commit, -SNAPSHOT>')
```
Manage logged in users with the `KeyPair` class
```kt
val keys = KeyPair() // creates a random key
val keys = KeyPair("hex...".hexToByteArray())
val keys = KeyPair("nsec1...".bechToBytes())
val keys = KeyPair(Nip06().privateKeyFromMnemonic("<mnemonic>"))
val readOnly = KeyPair(pubKey = "hex...".hexToByteArray())
val readOnly = KeyPair(pubKey = "npub1...".bechToBytes())
```
Create signers that can be internal, when you have the private key or when it is a read-only user
or external, when it is controlled by Amber in NIP-55
the `NostrSignerInternal` and `NostrSignerExternal` classes.
```kt
val signer = NostrSignerInternal(keyPair)
val amberSigner = NostrSignerExternal(
pubKey = keyPair.pubKey.toHexKey(),
packageName = signerPackageName,
contentResolver = appContext.contentResolver,
)
```
Create a single NostrClient for the entire application and control which relays it will access by
registering subscriptions and sending events. The pool will automatically changed based on filters +
outbox events.
You will need a coroutine scope to process events and if you are using OKHttp, we offer a basic
wrapper to create the socket connections themselves.
```kt
val appScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
val rootClient = OkHttpClient.Builder().build()
val socketBuilder = BasicOkHttpWebSocket.Builder { url -> rootClient }
val client = NostrClient(socketBuilder, appScope)
```
If you want to auth, given a logged-in `signer`:
```kt
val authCoordinator = RelayAuthenticator(client, applicationIOScope) { challenge, relay ->
val authedEvent = RelayAuthEvent.create(relayUrl, challenge, signer)
client.sendIfExists(authedEvent, relay.url)
}
```
To manage subscriptions, the suggested approach is to use subscriptions in the Application class.
```kt
val metadataSub = RelayClientSubscription(
client = client,
filter = {
val filters = listOf(
Filter(
kinds = listOf(MetadataEvent.KIND),
authors = listOf(signer.pubkey)
)
)
val signerOutboxRelays = listOfNotNull(
RelayUrlNormalizer.normalizeOrNull("wss://relay1.com"),
RelayUrlNormalizer.normalizeOrNull("wss://relay2.com")
)
signerOutboxRelays.associateWith { filters }
}
) { event ->
/* consume event */
}
```
## Contributing
Issues can be logged on: [https://gitworkshop.dev/repo/amethyst](https://gitworkshop.dev/repo/amethyst)
[GitHub issues](https://github.com/vitorpamplona/amethyst/issues) and [pull requests](https://github.com/vitorpamplona/amethyst/pulls) here are also welcome. Translations can be provided via [Crowdin](https://crowdin.com/project/amethyst-social)
You can also send patches through Nostr using [GitStr](https://github.com/fiatjaf/gitstr) to [this nostr address](https://patch34.pages.dev/naddr1qqyxzmt9w358jum5qyg8v6t5daezumn0wd68yvfwvdhk6qg7waehxw309ahx7um5wgkhqatz9emk2mrvdaexgetj9ehx2ap0qy2hwumn8ghj7un9d3shjtnwdaehgu3wvfnj7q3qgcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqxpqqqpmej720gac)
By contributing to this repository, you agree to license your work under the MIT license. Any work contributed where you are not the original author must contain its license header with the original author(s) and source.
# Screenshots
| Home Feed | Messages | Live Streams | Notifications |
| FollowFeeds | ChatsGroup | LiveStreams | Notifications |
|-------------------------------------------|----------------------------------------------|-------------------------------------------------|--------------------------------------------------------|
| ![Home Feed](./docs/screenshots/home.png) | ![Messages](./docs/screenshots/messages.png) | ![Live Streams](./docs/screenshots/replies.png) | ![Notifications](./docs/screenshots/notifications.png) |
# Contributing
[Issues](https://github.com/vitorpamplona/amethyst/issues) and [pull requests](https://github.com/vitorpamplona/amethyst/pulls) are very welcome.
## Contributors
# Contributors
<a align="center" href="https://github.com/vitorpamplona/amethyst/graphs/contributors">
<img src="https://contrib.rocks/image?repo=vitorpamplona/amethyst" />
@@ -216,6 +355,7 @@ Information shared on nostr should be assumed permanent for privacy purposes. Th
# MIT License
<pre>
Copyright (c) 2023 Vitor Pamplona
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -235,3 +375,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
</pre>

363
amethyst/build.gradle Normal file
View File

@@ -0,0 +1,363 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
alias(libs.plugins.androidApplication)
alias(libs.plugins.jetbrainsKotlinAndroid)
alias(libs.plugins.googleServices)
alias(libs.plugins.jetbrainsComposeCompiler)
alias(libs.plugins.serialization)
}
def getCurrentBranch() {
try {
def branch = 'git rev-parse --abbrev-ref HEAD'.execute().text.trim()
return branch
} catch (Exception e) {
println "Could not determine git branch: ${e.message}"
return "unknown"
}
}
def generateVersionName(String baseVersion) {
def currentBranch = getCurrentBranch()
if (currentBranch == "main" || currentBranch == "master" || currentBranch == "unknown" || currentBranch == "HEAD") {
return baseVersion
} else {
// Clean branch name for version (replace special characters)
def cleanBranch = currentBranch.replaceAll(/[^a-zA-Z0-9\-_]/, "-")
// Limit branch name to maximum 20 characters
if (cleanBranch.length() > 20) {
cleanBranch = cleanBranch.substring(0, 20)
}
return "${baseVersion}-${cleanBranch}"
}
}
android {
namespace = 'com.vitorpamplona.amethyst'
compileSdk = libs.versions.android.compileSdk.get().toInteger()
defaultConfig {
applicationId = "com.vitorpamplona.amethyst"
minSdk = libs.versions.android.minSdk.get().toInteger()
targetSdk = libs.versions.android.targetSdk.get().toInteger()
versionCode = 426
versionName = generateVersionName("1.02.0")
buildConfigField "String", "RELEASE_NOTES_ID", "\"08abe267baf5d7ce14db7975866f929e2794cc23484171aef0816c60a2416597\""
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary = true
}
resourceConfigurations += [
'ar',
'ar-rSA',
'bn-rBD',
'cs',
'cs-rCZ',
'cy-rGB',
'da-rDK',
'de',
'de-rDE',
'el-rGR',
'en-rGB',
'eo',
'eo-rUY',
'es',
'es-rES',
'es-rMX',
'es-rUS',
'et-rEE',
'fa',
'fa-rIR',
'fi-rFI',
'fo-rFO',
'fr',
'fr-rCA',
'fr-rFR',
'gu-rIN',
'hi-rIN',
'hr-rHR',
'hu',
'hu-rHU',
'in',
'in-rID',
'it-rIT',
'iw-rIL',
'ja',
'ja-rJP',
'kk-rKZ',
'ko-rKR',
'ks-rIN',
'ku-rTR',
'lt-rLT',
'ne-rNP',
'nl',
'nl-rBE',
'nl-rNL',
'pcm-rNG',
'pl-rPL',
'pt-rBR',
'pt-rPT',
'ru',
'ru-rRU',
'ru-rUA',
'sa-rIN',
'sl-rSI',
'so-rSO',
'sr-rSP',
'ss-rZA',
'sv-rSE',
'sw-rKE',
'sw-rTZ',
'ta',
'ta-rIN',
'th',
'th-rTH',
'tr',
'tr-rTR',
'uk',
'uk-rUA',
'ur-rIN',
'uz-rUZ',
'vi-rVN',
'zh',
'zh-rCN',
'zh-rHK',
'zh-rSG',
'zh-rTW'
]
}
buildTypes {
release {
proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), 'proguard-rules.pro'
minifyEnabled = true
}
debug {
applicationIdSuffix '.debug'
versionNameSuffix '-DEBUG'
resValue "string", "app_name", "@string/app_name_debug"
}
create("benchmark") {
initWith(getByName("release"))
applicationIdSuffix '.benchmark'
versionNameSuffix '-BENCHMARK'
resValue "string", "app_name", "@string/app_name_benchmark"
profileable = true
signingConfig = signingConfigs.debug
}
}
flavorDimensions = ["channel"]
productFlavors {
play {
getIsDefault().set(true)
dimension "channel"
}
fdroid {
dimension "channel"
}
}
splits {
abi {
enable = true
reset()
include "x86", "x86_64", "arm64-v8a", "armeabi-v7a"
universalApk = true
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_21
targetCompatibility JavaVersion.VERSION_21
}
buildFeatures {
compose = true
buildConfig = true
}
packagingOptions {
resources {
excludes += ['/META-INF/{AL2.0,LGPL2.1}', '**/libscrypt.dylib']
}
}
lint {
disable 'MissingTranslation'
}
testOptions {
unitTests.returnDefaultValues = true
}
}
// TODO: until google merges and unifiedpush updates https://github.com/tink-crypto/tink-java-apps/pull/5
configurations.all {
def tink = "com.google.crypto.tink:tink-android:1.17.0"
resolutionStrategy {
force(tink)
dependencySubstitution {
substitute module('com.google.crypto.tink:tink') using module(tink)
}
}
}
kotlin {
compilerOptions {
jvmTarget = JvmTarget.JVM_21
}
}
composeCompiler {
reportsDestination = layout.buildDirectory.dir("compose_compiler")
metricsDestination = layout.buildDirectory.dir("compose_compiler")
}
dependencies {
implementation platform(libs.androidx.compose.bom)
implementation project(path: ':quartz')
implementation project(path: ':commons')
implementation project(path: ':ammolite')
implementation libs.androidx.core.ktx
implementation libs.androidx.activity.compose
implementation libs.androidx.ui
implementation libs.androidx.ui.graphics
implementation libs.androidx.ui.tooling.preview
// Needs this to open gallery / image upload
implementation libs.androidx.fragment.ktx
// Navigation
implementation libs.androidx.navigation.compose
// Material 3 Design
implementation libs.androidx.material3
implementation libs.androidx.material.icons
// Adaptive Layout / Two Pane
implementation libs.androidx.material3.windowSize
implementation libs.accompanist.adaptive
// Lifecycle
implementation libs.androidx.lifecycle.runtime.ktx
implementation libs.androidx.lifecycle.runtime.compose
implementation libs.androidx.lifecycle.viewmodel.compose
// Zoomable images
implementation libs.zoomable
// Biometrics
implementation libs.androidx.biometric.ktx
// Websockets API
implementation libs.okhttp
implementation libs.okhttpCoroutines
// Encrypted Key Storage
implementation libs.androidx.security.crypto.ktx
implementation libs.androidx.datastore.preferences
// view videos
implementation libs.androidx.media3.exoplayer
implementation libs.androidx.media3.exoplayer.hls
implementation libs.androidx.media3.ui
implementation libs.androidx.media3.session
// important for proxy / tor
implementation libs.androidx.media3.datasource.okhttp
// Load images from the web.
implementation libs.coil.compose
// view gifs
implementation libs.coil.gif
// view svgs
implementation libs.coil.svg
// enables network for coil
implementation libs.coil.okhttp
// Permission to upload pictures:
implementation libs.accompanist.permissions
// For QR generation
implementation libs.zxing
implementation libs.zxing.embedded
// Markdown
//implementation "com.halilibo.compose-richtext:richtext-ui:0.16.0"
//implementation "com.halilibo.compose-richtext:richtext-ui-material:0.16.0"
//implementation "com.halilibo.compose-richtext:richtext-commonmark:0.16.0"
// Markdown (With fix for full-image bleeds)
implementation libs.markdown.ui
implementation libs.markdown.ui.material3
implementation libs.markdown.commonmark
// Language picker and Theme chooser
implementation libs.androidx.appcompat
implementation libs.androidx.window.core.android
// Local model for language identification
playImplementation libs.google.mlkit.language.id
// Google services model the translate text
playImplementation libs.google.mlkit.translate
// PushNotifications
playImplementation platform(libs.firebase.bom)
playImplementation libs.firebase.messaging
//PushNotifications(FDroid)
fdroidImplementation libs.unifiedpush
// Charts
implementation libs.vico.charts.core
implementation libs.vico.charts.compose
implementation libs.vico.charts.views
implementation libs.vico.charts.m3
// GeoHash
implementation libs.drfonfon.geohash
// Waveform visualizer
implementation libs.audiowaveform
// Video compression lib
implementation libs.abedElazizShe.image.compressor
// Image compression lib
implementation libs.zelory.video.compressor
// Cbor for cashuB format
implementation libs.kotlinx.serialization.cbor
implementation libs.tor.android
implementation libs.jtorctl
testImplementation libs.junit
testImplementation libs.mockk
testImplementation libs.kotlinx.coroutines.test
androidTestImplementation platform(libs.androidx.compose.bom)
androidTestImplementation libs.androidx.junit
androidTestImplementation libs.androidx.junit.ktx
androidTestImplementation libs.androidx.espresso.core
debugImplementation platform(libs.androidx.compose.bom)
debugImplementation libs.androidx.ui.tooling
debugImplementation libs.androidx.ui.test.manifest
implementation libs.androidx.camera.core
implementation libs.androidx.camera.camera2
implementation libs.androidx.camera.lifecycle
implementation libs.androidx.camera.view
implementation libs.androidx.camera.extensions
}

View File

@@ -0,0 +1,67 @@
{
"project_info": {
"project_number": "768341258853",
"project_id": "amethyst-3057a",
"storage_bucket": "amethyst-3057a.firebasestorage.app"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:768341258853:android:5d07c35a37b24ff36b8c8c",
"android_client_info": {
"package_name": "com.vitorpamplona.amethyst"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "AIzaSyB7ZxgdpgrN6R223HCFdfv4ulP8Egp7trE"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:768341258853:android:3270514bee61de546b8c8c",
"android_client_info": {
"package_name": "com.vitorpamplona.amethyst.benchmark"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "AIzaSyB7ZxgdpgrN6R223HCFdfv4ulP8Egp7trE"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:768341258853:android:e0200680f552484d6b8c8c",
"android_client_info": {
"package_name": "com.vitorpamplona.amethyst.debug"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "AIzaSyB7ZxgdpgrN6R223HCFdfv4ulP8Egp7trE"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
}
],
"configuration_version": "1"
}

65
amethyst/proguard-rules.pro vendored Normal file
View File

@@ -0,0 +1,65 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# preserve the line number information for debugging stack traces.
-dontobfuscate
-keepattributes LocalVariableTable
-keepattributes LocalVariableTypeTable
-keepattributes *Annotation*
-keepattributes SourceFile
-keepattributes LineNumberTable
-keepattributes Signature
-keepattributes Exceptions
-keepattributes InnerClasses
-keepattributes EnclosingMethod
-keepattributes MethodParameters
-keepparameternames
-keepdirectories libs
# Keep all names
-keepnames class ** { *; }
# Keep All enums
-keep enum ** { *; }
# preserve access to native classses
-keep class fr.acinq.secp256k1.** { *; }
# JNA For Libsodium
-keep class com.goterl.lazysodium.** { *; }
# libscrypt
-keep class com.lambdaworks.codec.** { *; }
-keep class com.lambdaworks.crypto.** { *; }
-keep class com.lambdaworks.jni.** { *; }
-keep class info.guardianproject.** { *; }
# JNA also requires AWT, which Android does not have. So the classes are broken down to filter AWT out
-keep class com.sun.jna.ToNativeConverter { *; }
-keep class com.sun.jna.NativeMapped { *; }
-keep class com.sun.jna.CallbackReference { *; }
-keep class com.sun.jna.ptr.IntByReference { *; }
-keep class com.sun.jna.NativeLong { *; }
-keep class com.sun.jna.Structure { *; }
-keep class com.sun.jna.Structure$* { *; }
-keep class com.sun.jna.Native$ffi_callback { *; }
-keep class * implements com.sun.jna.Structure$* { *; }
-keep class * implements com.sun.jna.Native$* { *; }
-keep class com.sun.jna.Native {
private static com.sun.jna.NativeMapped fromNative(java.lang.Class, java.lang.Object);
private static com.sun.jna.NativeMapped fromNative(java.lang.reflect.Method, java.lang.Object);
private static java.lang.Class nativeType(java.lang.Class);
private static java.lang.Object toNative(com.sun.jna.ToNativeConverter, java.lang.Object);
private static java.lang.Object fromNative(com.sun.jna.FromNativeConverter, java.lang.Object, java.lang.reflect.Method);
}
# JSON parsing
-keep class com.vitorpamplona.quartz.** { *; }
-keep class com.vitorpamplona.amethyst.** { *; }
-keep class com.vitorpamplona.ammolite.** { *; }

View File

@@ -0,0 +1,102 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.vitorpamplona.amethyst.service.cashu.CashuParser
import com.vitorpamplona.amethyst.service.cashu.CashuToken
import com.vitorpamplona.amethyst.ui.components.GenericLoadable
import junit.framework.TestCase.assertEquals
import kotlinx.coroutines.runBlocking
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class CashuBTest {
val cashuTokenA = "cashuAeyJ0b2tlbiI6W3sibWludCI6Imh0dHBzOi8vODMzMy5zcGFjZTozMzM4IiwicHJvb2ZzIjpbeyJhbW91bnQiOjIsImlkIjoiMDA5YTFmMjkzMjUzZTQxZSIsInNlY3JldCI6IjQwNzkxNWJjMjEyYmU2MWE3N2UzZTZkMmFlYjRjNzI3OTgwYmRhNTFjZDA2YTZhZmMyOWUyODYxNzY4YTc4MzciLCJDIjoiMDJiYzkwOTc5OTdkODFhZmIyY2M3MzQ2YjVlNDM0NWE5MzQ2YmQyYTUwNmViNzk1ODU5OGE3MmYwY2Y4NTE2M2VhIn0seyJhbW91bnQiOjgsImlkIjoiMDA5YTFmMjkzMjUzZTQxZSIsInNlY3JldCI6ImZlMTUxMDkzMTRlNjFkNzc1NmIwZjhlZTBmMjNhNjI0YWNhYTNmNGUwNDJmNjE0MzNjNzI4YzcwNTdiOTMxYmUiLCJDIjoiMDI5ZThlNTA1MGI4OTBhN2Q2YzA5NjhkYjE2YmMxZDVkNWZhMDQwZWExZGUyODRmNmVjNjlkNjEyOTlmNjcxMDU5In1dfV0sInVuaXQiOiJzYXQiLCJtZW1vIjoiVGhhbmsgeW91LiJ9"
val cashuTokenB1 = "cashuBo2F0gqJhaUgA_9SLj17PgGFwgaNhYQFhc3hAYWNjMTI0MzVlN2I4NDg0YzNjZjE4NTAxNDkyMThhZjkwZjcxNmE1MmJmNGE1ZWQzNDdlNDhlY2MxM2Y3NzM4OGFjWCECRFODGd5IXVW-07KaZCvuWHk3WrnnpiDhHki6SCQh88-iYWlIAK0mjE0fWCZhcIKjYWECYXN4QDEzMjNkM2Q0NzA3YTU4YWQyZTIzYWRhNGU5ZjFmNDlmNWE1YjRhYzdiNzA4ZWIwZDYxZjczOGY0ODMwN2U4ZWVhY1ghAjRWqhENhLSsdHrr2Cw7AFrKUL9Ffr1XN6RBT6w659lNo2FhAWFzeEA1NmJjYmNiYjdjYzY0MDZiM2ZhNWQ1N2QyMTc0ZjRlZmY4YjQ0MDJiMTc2OTI2ZDNhNTdkM2MzZGNiYjU5ZDU3YWNYIQJzEpxXGeWZN5qXSmJjY8MzxWyvwObQGr5G1YCCgHicY2FtdWh0dHA6Ly9sb2NhbGhvc3Q6MzMzOGF1Y3NhdA"
val cashuTokenB2 = "cashuBpGFkb01pbmliaXRzIHJ1bGVzIWFteEpodHRwOi8vbGJ1dGxoNWxmZ2dxNXI3eHBpd2hyYWpkbDdzeHB1cGdhZ2F6eGw2NXc0YzVjZzcyd3RvZmFzYWQub25pb246MzMzOGF0gaJhaUgAm7I9OpEuTmFwg6NhYRhAYWNYIQPfWR0mG80XbGnj6DO8q1NIyjHSGGIEkoWTA6H16HTpx2FzeEA3YThkY2Y5YjNlOGEyNDdjZTMzOWU3MzY5ZTliNGExOWYzMWVhY2I2OWQ4YjBjNjVkYWFlYjcyZDFhY2I5YWQzo2FhGCBhY1ghA55SwCFBc46dwnjbkb87Mzo30T2EE9Ws_nemuFneDegGYXN4QDlkODFjMWEyNjE2ODUzYWQ4MDQ5Y2JjZDFjN2MyNDdhZGQ4M2IzNzM4Mjg2MjBiYWMyZmQ3ZjNlNWE1OGFjZWKjYWEEYWNYIQM-yAQQTR2t6pIAmfmGM8Wxy7ajKVLOaUg7TrV8o-EdVWFzeEBmNmViMTI4ZmJlMDM3MTEzZTkzZjM3NjllYTYwMTk1NmY1N2NkZWNhNTYwOGY0NWUzMDhhZDU0ZmQ4YTQxNWVhYXVjc2F0"
@Test()
fun parseCashuA() {
runBlocking {
val parsed = (CashuParser().parse(cashuTokenA) as GenericLoadable.Loaded<List<CashuToken>>).loaded[0]
assertEquals(cashuTokenA, parsed.token)
assertEquals("https://8333.space:3338", parsed.mint)
assertEquals(10, parsed.totalAmount)
assertEquals(2, parsed.proofs[0].amount)
assertEquals("407915bc212be61a77e3e6d2aeb4c727980bda51cd06a6afc29e2861768a7837", parsed.proofs[0].secret)
assertEquals("009a1f293253e41e", parsed.proofs[0].id)
assertEquals("02bc9097997d81afb2cc7346b5e4345a9346bd2a506eb7958598a72f0cf85163ea", parsed.proofs[0].C)
assertEquals(8, parsed.proofs[1].amount)
assertEquals("fe15109314e61d7756b0f8ee0f23a624acaa3f4e042f61433c728c7057b931be", parsed.proofs[1].secret)
assertEquals("009a1f293253e41e", parsed.proofs[1].id)
assertEquals("029e8e5050b890a7d6c0968db16bc1d5d5fa040ea1de284f6ec69d61299f671059", parsed.proofs[1].C)
}
}
@Test()
fun parseCashuB() =
runBlocking {
val parsed = (CashuParser().parse(cashuTokenB1) as GenericLoadable.Loaded<List<CashuToken>>).loaded
assertEquals(cashuTokenB1, parsed[0].token)
assertEquals("http://localhost:3338", parsed[0].mint)
assertEquals(1, parsed[0].totalAmount)
assertEquals(1, parsed[0].proofs[0].amount)
assertEquals("acc12435e7b8484c3cf1850149218af90f716a52bf4a5ed347e48ecc13f77388", parsed[0].proofs[0].secret)
assertEquals("00ffd48b8f5ecf80", parsed[0].proofs[0].id)
assertEquals("0244538319de485d55bed3b29a642bee5879375ab9e7a620e11e48ba482421f3cf", parsed[0].proofs[0].C)
assertEquals(3, parsed[1].totalAmount)
assertEquals(2, parsed[1].proofs[0].amount)
assertEquals("1323d3d4707a58ad2e23ada4e9f1f49f5a5b4ac7b708eb0d61f738f48307e8ee", parsed[1].proofs[0].secret)
assertEquals("00ad268c4d1f5826", parsed[1].proofs[0].id)
assertEquals("023456aa110d84b4ac747aebd82c3b005aca50bf457ebd5737a4414fac3ae7d94d", parsed[1].proofs[0].C)
assertEquals(1, parsed[1].proofs[1].amount)
assertEquals("56bcbcbb7cc6406b3fa5d57d2174f4eff8b4402b176926d3a57d3c3dcbb59d57", parsed[1].proofs[1].secret)
assertEquals("00ad268c4d1f5826", parsed[1].proofs[1].id)
assertEquals("0273129c5719e599379a974a626363c333c56cafc0e6d01abe46d5808280789c63", parsed[1].proofs[1].C)
}
@Test()
fun parseCashuB2() =
runBlocking {
val parsed = (CashuParser().parse(cashuTokenB2) as GenericLoadable.Loaded<List<CashuToken>>).loaded
assertEquals(cashuTokenB2, parsed[0].token)
assertEquals("http://lbutlh5lfggq5r7xpiwhrajdl7sxpupgagazxl65w4c5cg72wtofasad.onion:3338", parsed[0].mint)
assertEquals(100, parsed[0].totalAmount)
assertEquals(64, parsed[0].proofs[0].amount)
assertEquals("7a8dcf9b3e8a247ce339e7369e9b4a19f31eacb69d8b0c65daaeb72d1acb9ad3", parsed[0].proofs[0].secret)
assertEquals("009bb23d3a912e4e", parsed[0].proofs[0].id)
assertEquals("03df591d261bcd176c69e3e833bcab5348ca31d218620492859303a1f5e874e9c7", parsed[0].proofs[0].C)
assertEquals(32, parsed[0].proofs[1].amount)
assertEquals("9d81c1a2616853ad8049cbcd1c7c247add83b373828620bac2fd7f3e5a58aceb", parsed[0].proofs[1].secret)
assertEquals("009bb23d3a912e4e", parsed[0].proofs[1].id)
assertEquals("039e52c02141738e9dc278db91bf3b333a37d13d8413d5acfe77a6b859de0de806", parsed[0].proofs[1].C)
}
}

View File

@@ -0,0 +1,70 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.vitorpamplona.amethyst.service.okhttp.EncryptedBlobInterceptor
import com.vitorpamplona.amethyst.service.okhttp.EncryptionKeyCache
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import com.vitorpamplona.quartz.nip17Dm.files.encryption.AESGCM
import junit.framework.TestCase.assertEquals
import okhttp3.OkHttpClient
import okhttp3.Request
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class DMFileDecryptionTest {
// Key cache to download and decrypt encrypted files before caching them.
val keyCache = EncryptionKeyCache()
val url = "https://cdn.satellite.earth/812fd4cf9d4d4b59c141ecd6a6c08c7571b5872237ad6477916cb2d119b5cacd"
val cipher =
AESGCM(
"7b184b3849e161027bab1aac9f2d96eb22bfe02c8dc34cad5d2cc436a64f191d".hexToByteArray(),
"3936923383652e3f0d72bfd40568b435".hexToByteArray(),
)
val decryptedSize = 1277122
val expectedMimeType = "video/mp4"
@Test
fun runDownloadAndDecryptVideo() {
val client =
OkHttpClient
.Builder()
.addNetworkInterceptor(EncryptedBlobInterceptor(keyCache))
.build()
keyCache.add(url, cipher, "video/mp4")
val request =
Request
.Builder()
.url(url)
.get()
.build()
client.newCall(request).execute().use {
assertEquals(decryptedSize, it.body.bytes().size)
assertEquals(expectedMimeType, it.body.contentType().toString())
}
}
}

View File

@@ -0,0 +1,296 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst
import android.graphics.Bitmap
import android.graphics.Color
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.nipB7Blossom.BlossomServerListState
import com.vitorpamplona.amethyst.service.okhttp.DefaultContentTypeInterceptor
import com.vitorpamplona.amethyst.service.uploads.FileHeader
import com.vitorpamplona.amethyst.service.uploads.ImageDownloader
import com.vitorpamplona.amethyst.service.uploads.blossom.BlossomUploader
import com.vitorpamplona.amethyst.service.uploads.nip96.Nip96Uploader
import com.vitorpamplona.amethyst.service.uploads.nip96.ServerInfoRetriever
import com.vitorpamplona.amethyst.ui.actions.mediaServers.DEFAULT_MEDIA_SERVERS
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
import com.vitorpamplona.quartz.nip98HttpAuth.HTTPAuthorizationEvent
import com.vitorpamplona.quartz.utils.sha256.sha256
import junit.framework.TestCase.assertEquals
import junit.framework.TestCase.fail
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.runBlocking
import okhttp3.OkHttpClient
import org.junit.Assert
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.Request.method
import org.junit.runner.RunWith
import java.io.ByteArrayOutputStream
import kotlin.random.Random
@RunWith(AndroidJUnit4::class)
class ImageUploadTesting {
companion object {
val accountSettings = AccountSettings(KeyPair())
val signer = NostrSignerInternal(accountSettings.keyPair)
val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
val cache = LocalCache
val blossomServerListState =
BlossomServerListState(
signer = signer,
cache = cache,
scope = scope,
settings = accountSettings,
)
}
val client =
OkHttpClient
.Builder()
.followRedirects(true)
.followSslRedirects(true)
.addInterceptor(DefaultContentTypeInterceptor("Amethyst/${BuildConfig.VERSION_NAME}"))
.build()
private suspend fun getBitmap(): ByteArray {
val bitmap = Bitmap.createBitmap(200, 300, Bitmap.Config.ARGB_8888)
for (x in 0 until bitmap.width) {
for (y in 0 until bitmap.height) {
bitmap.setPixel(x, y, Color.rgb(Random.nextInt(), Random.nextInt(), Random.nextInt()))
}
}
val baos = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos)
return baos.toByteArray()
}
private suspend fun testBase(server: ServerName) {
if (server.type == ServerType.NIP96) {
testNip96(server)
} else {
testBlossom(server)
}
}
private suspend fun testBlossom(server: ServerName) {
val paylod = getBitmap()
val initialHash = sha256(paylod).toHexKey()
val inputStream = paylod.inputStream()
val result =
BlossomUploader()
.upload(
inputStream = inputStream,
hash = initialHash,
length = paylod.size,
baseFileName = "filename.png",
contentType = "image/png",
alt = null,
sensitiveContent = null,
serverBaseUrl = server.baseUrl,
okHttpClient = { client },
httpAuth = blossomServerListState::createBlossomUploadAuth,
context = InstrumentationRegistry.getInstrumentation().targetContext,
)
assertEquals("image/png", result.type)
assertEquals(paylod.size.toLong(), result.size)
assertEquals(initialHash, result.sha256)
assertEquals("${server.baseUrl}/$initialHash", result.url?.removeSuffix(".png"))
val imageData: ByteArray =
ImageDownloader().waitAndGetImage(result.url!!, { client })?.bytes
?: run {
fail("${server.name}: Should not be null")
return
}
val downloadedHash = sha256(imageData).toHexKey()
assertEquals(initialHash, downloadedHash)
}
private suspend fun testNip96(server: ServerName) {
val serverInfo =
ServerInfoRetriever()
.loadInfo(
server.baseUrl,
{ client },
)
val payload = getBitmap()
val inputStream = payload.inputStream()
val result =
Nip96Uploader()
.upload(
inputStream = inputStream,
length = payload.size.toLong(),
contentType = "image/png",
alt = null,
sensitiveContent = null,
server = serverInfo,
okHttpClient = { client },
onProgress = {},
httpAuth = { url, method, body ->
signer.sign(HTTPAuthorizationEvent.build(url, method, body))
},
context = InstrumentationRegistry.getInstrumentation().targetContext,
)
val url = result.url!!
val size = result.size?.toInt()
val dim = result.dimension
val hash = result.sha256
Assert.assertTrue("${server.name}: Invalid result url", url.startsWith("http"))
val imageData: ByteArray =
ImageDownloader().waitAndGetImage(url, { client })?.bytes
?: run {
fail("${server.name}: Should not be null")
return
}
val prepared =
FileHeader.prepare(
imageData,
"image/png",
null,
)
prepared.fold(
onSuccess = {
if (dim != null) {
assertEquals("${server.name}: Invalid dimensions", it.dim.toString(), dim.toString())
}
if (size != null) {
assertEquals("${server.name}: Invalid size", it.size, size)
}
},
onFailure = { fail("${server.name}: It should not fail") },
)
// delay(1000)
// assertTrue(Nip96Uploader(account).delete(ox, contentType, serverInfo))
}
@Test
fun runTestOnDefaultServers() =
runBlocking {
DEFAULT_MEDIA_SERVERS.forEach {
// skip paid servers and primal server is buggy.
if (!it.name.contains("Paid") && !it.name.contains("Primal")) {
testBase(it)
}
}
}
@Test()
fun testNostrCheck() =
runBlocking {
testBase(ServerName("nostrcheck.me", "https://nostrcheck.me", ServerType.NIP96))
}
@Test()
@Ignore("Not Working anymore")
fun testNostrage() =
runBlocking {
testBase(ServerName("nostrage", "https://nostrage.com", ServerType.NIP96))
}
@Test()
@Ignore("Not Working anymore")
fun testSove() =
runBlocking {
testBase(ServerName("sove", "https://sove.rent", ServerType.NIP96))
}
@Ignore("Not Working anymore")
@Test()
fun testNostrBuild() =
runBlocking {
testBase(ServerName("nostr.build", "https://nostr.build", ServerType.NIP96))
}
@Test()
@Ignore("Not Working anymore")
fun testSovbit() =
runBlocking {
testBase(ServerName("sovbit", "https://files.sovbit.host", ServerType.NIP96))
}
@Test()
@Ignore("Not Working anymore")
fun testVoidCat() =
runBlocking {
testBase(ServerName("void.cat", "https://void.cat", ServerType.NIP96))
}
@Test()
@Ignore("Returns invalid image size")
fun testNostrPic() =
runBlocking {
testBase(ServerName("nostpic.com", "https://nostpic.com", ServerType.NIP96))
}
@Test(expected = RuntimeException::class)
fun testSprovoostNl() =
runBlocking {
testBase(ServerName("sprovoost.nl", "https://img.sprovoost.nl/", ServerType.NIP96))
}
@Test()
@Ignore("Not Working anymore")
fun testNostrOnch() =
runBlocking {
testBase(ServerName("nostr.onch.services", "https://nostr.onch.services", ServerType.NIP96))
}
@Ignore("Changes sha256")
fun testPrimalBlossom() =
runBlocking {
testBase(ServerName("primal.net", "https://blossom.primal.net", ServerType.Blossom))
}
@Test()
@Ignore("Not Working anymore/ Timeout")
fun testNostrCheckBlossom() =
runBlocking {
testBase(ServerName("nostrcheck", "https://cdn.nostrcheck.me", ServerType.Blossom))
}
@Ignore("Requires Payment")
fun testSatelliteBlossom() =
runBlocking {
testBase(ServerName("satellite", "https://cdn.satellite.earth", ServerType.Blossom))
}
}

View File

@@ -0,0 +1,95 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
import com.vitorpamplona.quartz.nip01Core.jackson.JsonMapper
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
import com.vitorpamplona.quartz.nip03Timestamp.OtsEvent
import com.vitorpamplona.quartz.nip03Timestamp.OtsResolver
import com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp.OkHttpBitcoinExplorer
import com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp.OkHttpCalendarBuilder
import com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp.OtsBlockHeightCache
import junit.framework.TestCase.assertEquals
import kotlinx.coroutines.runBlocking
import okhttp3.OkHttpClient
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class OkHttpOtsTest {
val otsEvent = "{\"content\":\"AE9wZW5UaW1lc3RhbXBzAABQcm9vZgC/ieLohOiSlAEIqCiiW0FlsU9lqK5f1A+cL6CGJ1Ah4V/A1yNJY/stUE3wECJz6ng/QxU5Z6xwaMx97qkI//AQqJv8bEMrGTplGWRv5qm4DgjxIHkcQqzpL0Fjr9VBAAijDe0IsQYpOhw1SIjZIgQa6i16CPEEZck7CvAIxR0AloJzCZoAg9/jDS75DI4uLWh0dHBzOi8vYWxpY2UuYnRjLmNhbGVuZGFyLm9wZW50aW1lc3RhbXBzLm9yZ//wEOwPtjIkKI1hmtv9t1kuxZcI8QRlyTsK8Ahl0wrCSggZzgCD3+MNLvkMjiwraHR0cHM6Ly9ib2IuYnRjLmNhbGVuZGFyLm9wZW50aW1lc3RhbXBzLm9yZ//wEE1dVGa8JCuf2ek0c5ybDKII8SCBoVz8Sal45Kd1O8STWIGJTcl5JPtAZBZitqk3BE9MqAjxBGXJOwrwCHoGVgAZi9q9AIPf4w0u+QyOKShodHRwczovL2Zpbm5leS5jYWxlbmRhci5ldGVybml0eXdhbGwuY29t8BAFZFXFYg7DJJ0OzjmJ0FKWCPEEZck7CvAI0M49IcBR5bf/AIPf4w0u+QyOIyJodHRwczovL2J0Yy5jYWxlbmRhci5jYXRhbGxheHkuY29tCPEgoE3IfYTmxxo4W/x/QYp/NGX6Wu93gSQkwbpjpOhZORcI8SDWLLurVQaXHdUuwivCfTfuxYCaq+AzypSGqLDAVocrEgjwIBfgjta16y13Gp4etQOCa9YiKEcM+/9AieG/vZolr3IDCPAgMR2zFCb384CEi8tVuI2fHgLT3I9zpe7oqJTzCcEqxWEI8SAJSdgeeosr7IxdOt8r7f0ipWc8FI6GAhgep8zSRgWikAjxIGxYmtCsC79Tx4z4YsT1WuMo+ycMkwhGQsQltF597cchCPAgCLrBf9vR1Aex6yY+vSkXAvLjMKdMqM/a1g8zNPwLeJcI8SBDCbTk4CczTuiIyZeUyYRVh31BZdjaSd2nU/pBQxu+6QjwIOwqE9/WqGC6CHH0i+tr7edvYX5PstSDf08KmnMqsqCoCPEgQIdEBg358vfek3Qjfyrgl51iCU6WUWmThsGLPDTcB0QI8SAX4dp64iI8pBx+zBqAQwUN6XgZ1cEfT8+2vha/9I1vzwjxWQEAAAAB8YJxvxJJth8OnxIV6UOXveIZAcJPTHcAkWgnucpuYqYAAAAAAP3///8CRhoMAAAAAAAWABTUUZK82uAvbU3vVyaaPIOddZBicwAAAAAAAAAAImog8ARCqgwACAjwIB9TcMDLhzgeS1Uw647lNvCfWECkkUvfrrOe6nay0sGdCAjwICYfs90sbPggoMICyOHGYbmOzop2L9mlnh4xqiBLY7yPCAjxINDiVWOBHnRmGJleQdB9myvJAJbNJ9kciZlTOkgJy89mCAjwIHfxqDLdwycj1Vtyth2CaSDdLQwiey9oV6Xov4stLpWNCAjxIGurJYpKJnKp9+y7MAdC+gXgHOiAu5P3RRUFW9l5hGaCCAjxICXqs9hdY0QMP/MNeqlt6s7xaIYtEXZ1CLvou5gaZNEICAjxIHdYxVeI76NXbT2zHcv6lw+v819Ooib7KWxc1GAsiX2fCAjwICPWdi3uBXOlIdmYi+V9C7wAqLyGE4DMoHD+GtvLizqiCAjwIOF2vENtWN5okEMMS+JSf1SGTY9yYP9j0JjXLbC1s+N1CAjxINWsgCtsPxhRNbe372k8/20WDbiL9e8934hGF256DvRECAjwII3mi+Li06j10ORxg0dYMkcsyGb115Jiqq1YEV3K/u+aCAgABYiWDXPXGQEDw9Qy\",\"created_at\":1707690688,\"id\":\"759f9da5846e936fab06766a524b36ba71c03bbc69ad0944fb8ee4bb1f3dd705\",\"kind\":1040,\"pubkey\":\"82fbb08c8ef45c4d71c88368d0ae805bc62fb92f166ab04a0b7a0c83d8cbc29a\",\"sig\":\"07c7896c8cbb97b5d7483097590c9d31b73f35c1ad9e752002bb5c1776cbd852e1d32704333d6930c9bc3e40f8b899a1f2e9f91cc3bf797d86acdecba7792576\",\"tags\":[[\"e\",\"a828a25b4165b14f65a8ae5fd40f9c2fa086275021e15fc0d7234963fb2d504d\"],[\"p\",\"595ca8eaace5899cb6ab7e2542bfc972136376f2eabc09287f1857eb8f167e53\"],[\"alt\",\"NIP-03 time stamp\"]]}"
val otsEvent2 = "{\"content\":\"AE9wZW5UaW1lc3RhbXBzAABQcm9vZgC/ieLohOiSlAEIqGNPU2jhd4no+zg2ytDkuf5PIoivr8KHI8BL68aKGNbwENyCNtiEN98IzIZgEu3cl6YI//AQ6TkSRd3BTGhDHCK1KkJc+AjxIAHaizG++NNL3Vm13BJrIhT7Br6tEYpb0TVRGaadgiUMCPAgOSDREH9v1Y50UHu79LfC4Lcd9WklQJzRQpw+Unb/pyII8QRltDD58AgqrxfAVrLw7QCD3+MNLvkMji4taHR0cHM6Ly9hbGljZS5idGMuY2FsZW5kYXIub3BlbnRpbWVzdGFtcHMub3Jn//AQQMq/CLpGwY60nmddPS7OVgjxIDKxqd9nl+Mej41vP52Wd7gv7004r3n1rFGDObS8icRvCPAgH9TB/kwvXJEEw+h9Ce6fLaI3MORjtTEge0GbAefT6W4I8QRltDD58AhRcoU3gAo/swCD3+MNLvkMjiwraHR0cHM6Ly9ib2IuYnRjLmNhbGVuZGFyLm9wZW50aW1lc3RhbXBzLm9yZ//wECWtWsKo0uvSr8BYonjs3DEI8CBlsh2ng1Spl0K4oStYElGuMJsjd2uo5nXB+apo5A7ipwjxIM8oxynBwNA+QS/X7Ebtl1kyhFgfoOQioASNfCBzZ4gaCPEEZbQw+fAId6Yd5cw5gioAg9/jDS75DI4pKGh0dHBzOi8vZmlubmV5LmNhbGVuZGFyLmV0ZXJuaXR5d2FsbC5jb23wEJmPzXQbxv0AFTIyjTWjMskI8CAurbkrfrBtlinZXSDxj+m/oIkze57hGjTSxu1Xs87XYQjwIPk/LMD0zIgKoEE2dfeoYrrdHuO6dwmghTwUFajH2QzkCPEEZbQw+fAIE+Pq1/Wmdpj/AIPf4w0u+QyOIyJodHRwczovL2J0Yy5jYWxlbmRhci5jYXRhbGxheHkuY29tCPAgB2CbqkV7VpjRKIl3Ea6cBmB/EHcSN/YCgcc1E+mc07QI8CAfpkZ2Hh4Rukz3x4il3tZqQtlDlbna+I6so2t2YSEmMQjwIJOv32jbsMa2HJwpleRCKLEhgYOoHCSfpv1ZO0YNNNFsCPAgLMM7eFfCjokQfU4gdU5WpG/wBLkO9lDRF0GktL6ujt8I8SCRxJ0bC1PQ8qFmI/1jh8AS5d1/6VRJNMt1Hz41QmNr3QjwIBmgrKBF+OZ3y+XOMv2E7IZ4WwLr2u2H+ehsBfy7cPlICPEgm4ZMCSXzZVWu40d+zk2edaur6KOauo8X7V2KaFBR1VoI8SBKVVOiyq6IFqGn/15kLwk7L8upMAIZ0znjhYxYqSTQCQjwIMBD1twPZ33GxbwTiuOCeJPkoP++6R2wYpCii8UBTdgwCPAg84VkgMXwrt2xxRoeC1/6CtsFctki+w3m8Rs5/6g/IhEI8CCnzZQDhJyicX7bS7U8PMUObuC9Y4TXe+4THoXBMMXkxwjxIMZ0oAvshpcwowR3qPEDbwKZ6B4NPSU4Hz/+4PnD74gnCPAgIfLZEKqAvkMNXfakXoNq1UVqGSzL4Z86z5GzUfbvw8UI8SC8KoIeLvjd4vJ/xhNVphakPRd80YKeNkeYEuVH8k2EtAjwIPRtinLLxzt8iuw0XZtpTDzEstZOTNYVm+Bi3fEzdeIuCPFZAQAAAAE8vsasINN5DKon0KakX2HNdCB126ZLKXrw4PfvyEfqbwAAAAAA/f///wLPGw8AAAAAABYAFCvgxlh6msa4ZOtgvlc5KiZCx7IvAAAAAAAAAAAiaiDwBKygDAAICPEgB/2DJ3s6gMky/PceGZocTFRXjZUiCCAhHGYwQk/8yrUICPEgDuSd6+PJHUMuEHyLcKFxw7xfvRHRfInjkV3/Zy3BxqAICPEgZDgQ+4VXzlOIkGoO8EVxDgs2cWaeh4EEiaqa/y50gKAICPAgFI+zIuYcMF69GmPQVsXa9oy8eng7MeRZdIxArQyeX3oICPEgX5HYIuImpiSTEapgEssEW4l+W+4aRfNCG3pZf7z0hCoICPEgPkAbOSjFdtS4NT7MXgMYVQoQhI1JZtdFxUu4J3NTt7IICPEguW3qyuyGjctu5d9rM9P9ZCs/ZK4vAc+z21b9ygklgWAICPEgu4e2645xtvGhI1Zzuiv23vRhwE8uC9vj1TAgNg/C8UcICPAgwoQX8X0nY4HoQLRsJ0z8JCWQDzRh2iL2QXEb8z3gbjIICPAgzTwlPRtStsLJWhz3Q/0l8tMnrPSHVuh+zCiGk95dW2MICPAgGcBEuYZyzFNapHOfnJ9Q515QzO2VbIRhlVI0vIhd4jwICPAgidRMoM2pA+KmVJenVrLcbollsbUg9lL9bmv1C1dSxswICPAgZinGakwhbHdanTaRJeBkEUlbhfNokvj8b5KneyG+wzIICAAFiJYNc9cZAQOtwTI=\",\"created_at\":1706324334,\"id\":\"2ad074ddb7724eb13b4244b49cf2321b1057f37fdf8ce102e6329b839cf763a9\",\"kind\":1040,\"pubkey\":\"82fbb08c8ef45c4d71c88368d0ae805bc62fb92f166ab04a0b7a0c83d8cbc29a\",\"sig\":\"ad7274bb32ba9e9cfdbd52f4887e8a2fda1047c75a7185b2ab7ff254ebac14ed48a2b60737494d655e24c9400eeeec7e29293a77bfcaafaecd94b350c9a2c22b\",\"tags\":[[\"e\",\"a8634f5368e17789e8fb3836cad0e4b9fe4f2288afafc28723c04bebc68a18d6\"],[\"p\",\"c31e22c3715c1bde5608b7e0d04904f22f5fc453ba1806d21c9f2382e1e58c6c\"],[\"alt\",\"NIP-03 time stamp\"]]}"
val otsPendingEvent = "{\"id\":\"12fa15ad4b4cf9dc5940389325b69b93c5c1f59c049c701ee669b275299fdaf1\",\"pubkey\":\"dcaa6c8a2f47b6fef4a34b20e8843c59dbe7c5f07a402338c09fd147dd01d22b\",\"created_at\":1708877521,\"kind\":1040,\"tags\":[[\"e\",\"a8634f5368e17789e8fb3836cad0e4b9fe4f2288afafc28723c04bebc68a18d6\"],[\"alt\",\"Opentimestamps Attestation\"]],\"content\":\"AE9wZW5UaW1lc3RhbXBzAABQcm9vZgC/ieLohOiSlAEIqGNPU2jhd4no+zg2ytDkuf5PIoivr8KHI8BL68aKGNbwELidvzr0usf55CkpKf6OABQI//AQK3sWd2tq+7KO8YNJIARJugjxBGXbZtPwCL0H4/7GL5+SAIPf4w0u+QyOLCtodHRwczovL2JvYi5idGMuY2FsZW5kYXIub3BlbnRpbWVzdGFtcHMub3Jn//AQPDZsJgN1TnJXoUzlsgo93wjwIIfBc7LUqkCbC1BLZRZ+6LXztK50UdH5xe7fn40bupkrCPEEZdtm0/AI0CADXN5ZIncAg9/jDS75DI4uLWh0dHBzOi8vYWxpY2UuYnRjLmNhbGVuZGFyLm9wZW50aW1lc3RhbXBzLm9yZ/AQcELcSrE04cuGKlZQf2LeVwjwILUDSf9vK2GaefKTpn/LV2oUsQaA5WbqaP3C+1ZxQfRNCPEEZdtm0/AIbCtb+yRXFqUAg9/jDS75DI4pKGh0dHBzOi8vZmlubmV5LmNhbGVuZGFyLmV0ZXJuaXR5d2FsbC5jb20=\",\"sig\":\"f6854c0228c15c08aeb70bbabe9ed87bbb7289fab31b13cabac15138bb71179553e06080b83f4a813fbdaf614f63293beea3fc73fe865da6551193fa4d38de04\"}"
val otsEvent2Digest = "a8634f5368e17789e8fb3836cad0e4b9fe4f2288afafc28723c04bebc68a18d6"
val otsCache = OtsBlockHeightCache()
val resolver =
OtsResolver(
OkHttpBitcoinExplorer(
baseAPI = OkHttpBitcoinExplorer.MEMPOOL_API_URL,
client = OkHttpClient.Builder().build(),
cache = otsCache,
),
OkHttpCalendarBuilder { OkHttpClient.Builder().build() },
)
@Test
fun verifyNostrEvent() {
val ots = JsonMapper.fromJson(otsEvent) as OtsEvent
println(resolver.info(ots.otsByteArray()))
assertEquals(1707688818L, ots.verify(resolver))
}
@Test
fun verifyNostrEvent2() {
val ots = JsonMapper.fromJson(otsEvent2) as OtsEvent
println(resolver.info(ots.otsByteArray()))
assertEquals(1706322179L, ots.verify(resolver))
}
@Test
fun verifyNostrPendingEvent() {
val ots = JsonMapper.fromJson(otsPendingEvent) as OtsEvent
println(resolver.info(ots.otsByteArray()))
assertEquals(null, ots.verify(resolver))
}
@Test
fun createOTSEventAndVerify() {
val signer = NostrSignerInternal(KeyPair())
val otsFile = OtsEvent.stamp(otsEvent2Digest, resolver)
val ots =
runBlocking {
signer.sign(OtsEvent.build(otsEvent2Digest, otsFile))
}
println(ots.toJson())
println(resolver.info(ots.otsByteArray()))
// Should not be valid because we need to wait for confirmations
assertEquals(null, ots.verify(resolver))
}
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,62 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst
import com.vitorpamplona.amethyst.ui.navigation.findParameterValue
import junit.framework.TestCase.assertEquals
import org.junit.Test
import java.net.URI
class URIParserTest {
@Test
fun testNEventWithAccount() {
val test = "nevent1qqsp9wg5r3vkuv5al0459h3h44yxh6r0y7chgvu3pkdxhcj99t3msrgpzdmhxue69uhhwmm59e6hg7r09ehkuef0qgsdhcrqt2w8x9et446j8ge8kgmd2h4ykc6wsrnc4yqnmdu3lr74ktqrqsqqqqqp578kku?account=npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z"
val testUri = URI(test)
// assertEquals("nostr", testUri.scheme)
assertEquals(null, testUri.authority)
assertEquals(null, testUri.host)
assertEquals(-1, testUri.port)
assertEquals(null, testUri.userInfo)
assertEquals("nevent1qqsp9wg5r3vkuv5al0459h3h44yxh6r0y7chgvu3pkdxhcj99t3msrgpzdmhxue69uhhwmm59e6hg7r09ehkuef0qgsdhcrqt2w8x9et446j8ge8kgmd2h4ykc6wsrnc4yqnmdu3lr74ktqrqsqqqqqp578kku", testUri.path)
assertEquals(null, testUri.fragment)
assertEquals("account=npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z", testUri.rawQuery)
assertEquals("npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z", testUri.findParameterValue("account"))
}
@Test
fun testNotificationsWithAccount() {
val test = "notifications?account=npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z"
val testUri = URI(test)
// assertEquals("nostr", testUri.scheme)
assertEquals(null, testUri.authority)
assertEquals(null, testUri.host)
assertEquals(-1, testUri.port)
assertEquals(null, testUri.userInfo)
assertEquals("notifications", testUri.path)
assertEquals(null, testUri.fragment)
assertEquals("account=npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z", testUri.rawQuery)
assertEquals("npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z", testUri.findParameterValue("account"))
}
}

View File

@@ -0,0 +1,262 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.input.TransformedText
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.ui.actions.buildAnnotatedStringWithUrlHighlighting
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
import com.vitorpamplona.quartz.nip01Core.metadata.UserMetadata
import com.vitorpamplona.quartz.nip19Bech32.decodePublicKey
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class UrlUserTagTransformationTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.vitorpamplona.amethyst", appContext.packageName.removeSuffix(".debug"))
}
fun debugCursor(
original: String,
transformedText: TransformedText,
offset: Int,
): String {
val offsetTransformed = transformedText.offsetMapping.originalToTransformed(offset)
val originalWithCursor = original.substring(0, offset) + "|" + original.substring(offset, original.length)
val transformedWithCursor = transformedText.text.text.substring(0, offsetTransformed) + "|" + transformedText.text.text.substring(offsetTransformed, transformedText.text.text.length)
return "$originalWithCursor $transformedWithCursor"
}
fun debugCursorReverse(
original: String,
transformedText: TransformedText,
offsetTransformed: Int,
): String {
val offset = transformedText.offsetMapping.transformedToOriginal(offsetTransformed)
val originalWithCursor = original.substring(0, offset) + "|" + original.substring(offset, original.length)
val transformedWithCursor = transformedText.text.text.substring(0, offsetTransformed) + "|" + transformedText.text.text.substring(offsetTransformed, transformedText.text.text.length)
return "$originalWithCursor $transformedWithCursor"
}
@Test
fun testKeepTransformedIndexFullyInsideTransformedText() {
val user =
LocalCache.getOrCreateUser(
decodePublicKey("npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z")
.toHexKey(),
)
user.info = UserMetadata()
user.info?.displayName = "Vitor Pamplona"
val original = "@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z"
val transformedText =
buildAnnotatedStringWithUrlHighlighting(
AnnotatedString(original),
Color.Red,
)
val expected = "@Vitor Pamplona"
assertEquals(expected, transformedText.text.text)
assertEquals("|@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z |@Vitor Pamplona", debugCursor(original, transformedText, 0))
assertEquals("@|npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z |@Vitor Pamplona", debugCursor(original, transformedText, 1))
assertEquals("@n|pub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z |@Vitor Pamplona", debugCursor(original, transformedText, 2))
assertEquals("@np|ub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z |@Vitor Pamplona", debugCursor(original, transformedText, 3))
assertEquals("@npu|b1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z |@Vitor Pamplona", debugCursor(original, transformedText, 4))
assertEquals("@npub|1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @|Vitor Pamplona", debugCursor(original, transformedText, 5))
assertEquals("@npub1|gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @|Vitor Pamplona", debugCursor(original, transformedText, 6))
assertEquals("@npub1g|cxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @|Vitor Pamplona", debugCursor(original, transformedText, 7))
assertEquals("@npub1gc|xzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @|Vitor Pamplona", debugCursor(original, transformedText, 8))
assertEquals("@npub1gcx|zte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @V|itor Pamplona", debugCursor(original, transformedText, 9))
assertEquals("@npub1gcxz|te5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @V|itor Pamplona", debugCursor(original, transformedText, 10))
assertEquals("@npub1gcxzt|e5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @V|itor Pamplona", debugCursor(original, transformedText, 11))
assertEquals("@npub1gcxzte|5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @V|itor Pamplona", debugCursor(original, transformedText, 12))
assertEquals("@npub1gcxzte5|zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vi|tor Pamplona", debugCursor(original, transformedText, 13))
assertEquals("@npub1gcxzte5z|lkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vi|tor Pamplona", debugCursor(original, transformedText, 14))
assertEquals("@npub1gcxzte5zl|kncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vi|tor Pamplona", debugCursor(original, transformedText, 15))
assertEquals("@npub1gcxzte5zlk|ncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vi|tor Pamplona", debugCursor(original, transformedText, 16))
assertEquals("@npub1gcxzte5zlkn|cx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vi|tor Pamplona", debugCursor(original, transformedText, 17))
assertEquals("@npub1gcxzte5zlknc|x26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vit|or Pamplona", debugCursor(original, transformedText, 18))
assertEquals("@npub1gcxzte5zlkncx|26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vit|or Pamplona", debugCursor(original, transformedText, 19))
assertEquals("@npub1gcxzte5zlkncx2|6j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vit|or Pamplona", debugCursor(original, transformedText, 20))
assertEquals("@npub1gcxzte5zlkncx26|j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vit|or Pamplona", debugCursor(original, transformedText, 21))
assertEquals("@npub1gcxzte5zlkncx26j|68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vito|r Pamplona", debugCursor(original, transformedText, 22))
assertEquals("@npub1gcxzte5zlkncx26j6|8ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vito|r Pamplona", debugCursor(original, transformedText, 23))
assertEquals("@npub1gcxzte5zlkncx26j68|ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vito|r Pamplona", debugCursor(original, transformedText, 24))
assertEquals("@npub1gcxzte5zlkncx26j68e|z60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vito|r Pamplona", debugCursor(original, transformedText, 25))
assertEquals("@npub1gcxzte5zlkncx26j68ez|60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor| Pamplona", debugCursor(original, transformedText, 26))
assertEquals("@npub1gcxzte5zlkncx26j68ez6|0fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor| Pamplona", debugCursor(original, transformedText, 27))
assertEquals("@npub1gcxzte5zlkncx26j68ez60|fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor| Pamplona", debugCursor(original, transformedText, 28))
assertEquals("@npub1gcxzte5zlkncx26j68ez60f|zkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor| Pamplona", debugCursor(original, transformedText, 29))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fz|kvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor |Pamplona", debugCursor(original, transformedText, 30))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzk|vtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor |Pamplona", debugCursor(original, transformedText, 31))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkv|tkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor |Pamplona", debugCursor(original, transformedText, 32))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvt|km9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor |Pamplona", debugCursor(original, transformedText, 33))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtk|m9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor |Pamplona", debugCursor(original, transformedText, 34))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm|9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor P|amplona", debugCursor(original, transformedText, 35))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9|e0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor P|amplona", debugCursor(original, transformedText, 36))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e|0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor P|amplona", debugCursor(original, transformedText, 37))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0|vrwdcvsjakxf9mu9qewqlfnj5z @Vitor P|amplona", debugCursor(original, transformedText, 38))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0v|rwdcvsjakxf9mu9qewqlfnj5z @Vitor Pa|mplona", debugCursor(original, transformedText, 39))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vr|wdcvsjakxf9mu9qewqlfnj5z @Vitor Pa|mplona", debugCursor(original, transformedText, 40))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrw|dcvsjakxf9mu9qewqlfnj5z @Vitor Pa|mplona", debugCursor(original, transformedText, 41))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwd|cvsjakxf9mu9qewqlfnj5z @Vitor Pa|mplona", debugCursor(original, transformedText, 42))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdc|vsjakxf9mu9qewqlfnj5z @Vitor Pam|plona", debugCursor(original, transformedText, 43))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcv|sjakxf9mu9qewqlfnj5z @Vitor Pam|plona", debugCursor(original, transformedText, 44))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvs|jakxf9mu9qewqlfnj5z @Vitor Pam|plona", debugCursor(original, transformedText, 45))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsj|akxf9mu9qewqlfnj5z @Vitor Pam|plona", debugCursor(original, transformedText, 46))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsja|kxf9mu9qewqlfnj5z @Vitor Pamp|lona", debugCursor(original, transformedText, 47))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjak|xf9mu9qewqlfnj5z @Vitor Pamp|lona", debugCursor(original, transformedText, 48))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakx|f9mu9qewqlfnj5z @Vitor Pamp|lona", debugCursor(original, transformedText, 49))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf|9mu9qewqlfnj5z @Vitor Pamp|lona", debugCursor(original, transformedText, 50))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9|mu9qewqlfnj5z @Vitor Pamp|lona", debugCursor(original, transformedText, 51))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9m|u9qewqlfnj5z @Vitor Pampl|ona", debugCursor(original, transformedText, 52))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu|9qewqlfnj5z @Vitor Pampl|ona", debugCursor(original, transformedText, 53))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9|qewqlfnj5z @Vitor Pampl|ona", debugCursor(original, transformedText, 54))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9q|ewqlfnj5z @Vitor Pampl|ona", debugCursor(original, transformedText, 55))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qe|wqlfnj5z @Vitor Pamplo|na", debugCursor(original, transformedText, 56))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qew|qlfnj5z @Vitor Pamplo|na", debugCursor(original, transformedText, 57))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewq|lfnj5z @Vitor Pamplo|na", debugCursor(original, transformedText, 58))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewql|fnj5z @Vitor Pamplo|na", debugCursor(original, transformedText, 59))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlf|nj5z @Vitor Pamplon|a", debugCursor(original, transformedText, 60))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfn|j5z @Vitor Pamplon|a", debugCursor(original, transformedText, 61))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj|5z @Vitor Pamplon|a", debugCursor(original, transformedText, 62))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5|z @Vitor Pamplon|a", debugCursor(original, transformedText, 63))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z| @Vitor Pamplona|", debugCursor(original, transformedText, 64))
assertEquals("|@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z |@Vitor Pamplona", debugCursorReverse(original, transformedText, 0))
assertEquals("@npu|b1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @|Vitor Pamplona", debugCursorReverse(original, transformedText, 1))
assertEquals("@npub1gc|xzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @V|itor Pamplona", debugCursorReverse(original, transformedText, 2))
assertEquals("@npub1gcxzte|5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vi|tor Pamplona", debugCursorReverse(original, transformedText, 3))
assertEquals("@npub1gcxzte5zlkn|cx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vit|or Pamplona", debugCursorReverse(original, transformedText, 4))
assertEquals("@npub1gcxzte5zlkncx26|j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vito|r Pamplona", debugCursorReverse(original, transformedText, 5))
assertEquals("@npub1gcxzte5zlkncx26j68e|z60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor| Pamplona", debugCursorReverse(original, transformedText, 6))
assertEquals("@npub1gcxzte5zlkncx26j68ez60f|zkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor |Pamplona", debugCursorReverse(original, transformedText, 7))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtk|m9e0vrwdcvsjakxf9mu9qewqlfnj5z @Vitor P|amplona", debugCursorReverse(original, transformedText, 8))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0|vrwdcvsjakxf9mu9qewqlfnj5z @Vitor Pa|mplona", debugCursorReverse(original, transformedText, 9))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwd|cvsjakxf9mu9qewqlfnj5z @Vitor Pam|plona", debugCursorReverse(original, transformedText, 10))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsj|akxf9mu9qewqlfnj5z @Vitor Pamp|lona", debugCursorReverse(original, transformedText, 11))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9|mu9qewqlfnj5z @Vitor Pampl|ona", debugCursorReverse(original, transformedText, 12))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9q|ewqlfnj5z @Vitor Pamplo|na", debugCursorReverse(original, transformedText, 13))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewql|fnj5z @Vitor Pamplon|a", debugCursorReverse(original, transformedText, 14))
assertEquals("@npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z| @Vitor Pamplona|", debugCursorReverse(original, transformedText, 15))
assertEquals(0, transformedText.offsetMapping.originalToTransformed(0))
assertEquals(15, transformedText.offsetMapping.originalToTransformed(64))
}
@Test
fun transformationText() {
val user =
LocalCache.getOrCreateUser(
decodePublicKey("npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z")
.toHexKey(),
)
user.info = UserMetadata()
user.info?.displayName = "Vitor Pamplona"
val transformedText =
buildAnnotatedStringWithUrlHighlighting(
AnnotatedString("New Hey @npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z"),
Color.Red,
)
assertEquals("New Hey @Vitor Pamplona", transformedText.text.text)
assertEquals(0, transformedText.offsetMapping.originalToTransformed(0)) // Before N
assertEquals(4, transformedText.offsetMapping.originalToTransformed(4)) // Before H
assertEquals(8, transformedText.offsetMapping.originalToTransformed(8)) // Before @
assertEquals(8, transformedText.offsetMapping.originalToTransformed(9)) // Before n
assertEquals(8, transformedText.offsetMapping.originalToTransformed(10)) // Before p
assertEquals(8, transformedText.offsetMapping.originalToTransformed(11)) // Before u
assertEquals(8, transformedText.offsetMapping.originalToTransformed(12)) // Before b
assertEquals(9, transformedText.offsetMapping.originalToTransformed(13)) // Before 1
assertEquals(22, transformedText.offsetMapping.originalToTransformed(71))
assertEquals(23, transformedText.offsetMapping.originalToTransformed(72))
assertEquals(0, transformedText.offsetMapping.transformedToOriginal(0))
assertEquals(4, transformedText.offsetMapping.transformedToOriginal(4))
assertEquals(8, transformedText.offsetMapping.transformedToOriginal(8))
assertEquals(12, transformedText.offsetMapping.transformedToOriginal(9))
assertEquals(72, transformedText.offsetMapping.transformedToOriginal(23))
assertEquals(73, transformedText.offsetMapping.transformedToOriginal(24))
}
@Test
fun transformationTextTwoKeys() {
val user =
LocalCache.getOrCreateUser(
decodePublicKey("npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z")
.toHexKey(),
)
user.info = UserMetadata()
user.info?.displayName = "Vitor Pamplona"
val transformedText =
buildAnnotatedStringWithUrlHighlighting(
AnnotatedString(
"New Hey @npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z and @npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z",
),
Color.Red,
)
assertEquals("New Hey @Vitor Pamplona and @Vitor Pamplona", transformedText.text.text)
assertEquals(8, transformedText.offsetMapping.originalToTransformed(11))
assertEquals(8, transformedText.offsetMapping.originalToTransformed(12))
assertEquals(9, transformedText.offsetMapping.originalToTransformed(13))
assertEquals(22, transformedText.offsetMapping.originalToTransformed(70)) // Before 5
assertEquals(22, transformedText.offsetMapping.originalToTransformed(71)) // Before z
assertEquals(23, transformedText.offsetMapping.originalToTransformed(72)) // Before <space>
assertEquals(24, transformedText.offsetMapping.originalToTransformed(73)) // Before a
assertEquals(25, transformedText.offsetMapping.originalToTransformed(74)) // Before n
assertEquals(26, transformedText.offsetMapping.originalToTransformed(75)) // Before d
assertEquals(27, transformedText.offsetMapping.originalToTransformed(76)) // Before <space>
assertEquals(28, transformedText.offsetMapping.originalToTransformed(77)) // Before @
assertEquals(28, transformedText.offsetMapping.originalToTransformed(78)) // Before n
assertEquals(67, transformedText.offsetMapping.transformedToOriginal(22)) // Before a
assertEquals(72, transformedText.offsetMapping.transformedToOriginal(23)) // Before <space>
assertEquals(73, transformedText.offsetMapping.transformedToOriginal(24)) // Before a
assertEquals(74, transformedText.offsetMapping.transformedToOriginal(25)) // Before n
assertEquals(75, transformedText.offsetMapping.transformedToOriginal(26)) // Before d
assertEquals(76, transformedText.offsetMapping.transformedToOriginal(27)) // Before <space>
assertEquals(77, transformedText.offsetMapping.transformedToOriginal(28)) // Before @
}
}

View File

@@ -0,0 +1,5 @@
<resources>
<string name="app_name">Amethyst</string>
<string name="app_name_debug">Amy Debug</string>
<string name="app_name_benchmark">Amy Benchmark</string>
</resources>

View File

@@ -0,0 +1,180 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.android.gms.tasks.Tasks
import com.vitorpamplona.amethyst.service.lang.LanguageTranslatorService
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith
import java.util.concurrent.CancellationException
@RunWith(AndroidJUnit4::class)
class TranslationsTest {
fun translateTo(
text: String,
translateTo: String,
): String? {
val task = LanguageTranslatorService.autoTranslate(text, emptySet(), translateTo)
return Tasks.await(task).result
}
fun assertTranslate(
expected: String,
input: String,
translateTo: String,
) {
assertEquals(null, expected, translateTo(input, translateTo))
}
fun assertTranslateContains(
expected: String,
input: String,
translateTo: String,
) {
val translated = translateTo(input, translateTo)!!
assertTrue("'$translated' does not contain '$expected'", translated.contains(expected))
}
@Test
fun testTranslation() {
assertTranslate("Olá mundo", "Hello World", "pt")
}
@Test
fun testTranslationName() {
assertTranslate("Olá Vitor, como você está?", "Hello Vitor, how are you doing?", "pt")
}
@Test
fun testTranslationTag() {
assertTranslate("Você já viu isso, #[0]", "Have you seen this, #[0]", "pt")
}
@Test
fun testTranslationUrl() {
assertTranslateContains("https://t.me/mygroup", "Have you seen this https://t.me/mygroup", "pt")
assertTranslateContains("http://bananas.com", "Have you seen this http://bananas.com", "pt")
assertTranslateContains(
"http://bananas.com/myimage.jpg",
"Have you seen this http://bananas.com/myimage.jpg",
"pt",
)
assertTranslateContains(
"http://bananas.com?search=true&image=myimage.jpg",
"Have you seen this http://bananas.com?search=true&image=myimage.jpg",
"pt",
)
assertTranslate("https://i.imgur.com/EZ3QPsw.jpg", "https://i.imgur.com/EZ3QPsw.jpg", "pt")
assertTranslate("https://HaveYouSeenThis.com", "https://HaveYouSeenThis.com", "pt")
assertTranslate("https://haveyouseenthis.com", "https://haveyouseenthis.com", "pt")
assertTranslate(
"https://i.imgur.com/asdEZ3QPsw.jpg",
"https://i.imgur.com/asdEZ3QPsw.jpg",
"pt",
)
assertTranslateContains(
"https://i.imgur.com/asdEZ3QPswadfj2389rioasdjf9834riofaj9834aKLL.jpg",
"Hi there! \n How are you doing? \n https://i.imgur.com/asdEZ3QPswadfj2389rioasdjf9834riofaj9834aKLL.jpg",
"pt",
)
}
@Test
fun testChineseWithUrlDetector() {
assertTranslate(
"I entered your home page is very carton, perhaps your attention or other data is too much, and the homepage of others is not so carton. From aMethyst client",
"我进入你的主页很卡顿也许是你的关注人数或者其他数据太多了其他人主页没有这么卡顿。来自amethyst客户端",
"en",
)
}
@Test
fun testTranslationEmail() {
assertTranslateContains(
"vitor@amethyst.social",
"Have you seen this vitor@amethyst.social",
"pt",
)
}
@Test
fun testTranslationLnInvoice() {
assertTranslateContains(
"lnbc12u1p3lvjeupp5a5ecgp45k6pa8tu7rnkgzfuwdy3l5ylv3k5tdzrg4cr8rj2f364sdq5g9kxy7fqd9h8vmmfvdjscqzpgxqyz5vqsp5zuzyetf33aphetf0e80w7tztw6dfsjs4lmvya4cyk8umfsx00qts9qyyssqke9hphcr36zvcav8wr502g0mhfhxpy8m9tt36zttg8vldm2qxw039ulccr8nwy3hjg2sw5vk65e99lwuhrhw0nuya2u57qszltvx7egp74jydn",
"Have you seen this: lnbc12u1p3lvjeupp5a5ecgp45k6pa8tu7rnkgzfuwdy3l5ylv3k5tdzrg4cr8rj2f364sdq5g9kxy7fqd9h8vmmfvdjscqzpgxqyz5vqsp5zuzyetf33aphetf0e80w7tztw6dfsjs4lmvya4cyk8umfsx00qts9qyyssqke9hphcr36zvcav8wr502g0mhfhxpy8m9tt36zttg8vldm2qxw039ulccr8nwy3hjg2sw5vk65e99lwuhrhw0nuya2u57qszltvx7egp74jydn I think I have to pay",
"pt",
)
}
@Test(expected = CancellationException::class)
fun testTranslationLnInvoice2() {
assertTranslateContains(
"lnbc10u1p3l0wg0pp5y5y3vxt3429m28uuq56uqhwxadftn67yaarq06h3y9nqapz72n6sdqqxqyjw5q9q7sqqqqqqqqqqqqqqqqqqqqqqqqq9qsqsp5y2tazp42xde3c0tdsz30zqcekrt0lzrneszdtagy2qn7vs0d3p5qrzjqwryaup9lh50kkranzgcdnn2fgvx390wgj5jd07rwr3vxeje0glcll7jdvcln4lhw5qqqqlgqqqqqeqqjqdau9jzseecmvmh03h88xyf5f980xx45fmn0cej654v5jr79ye36pww90jwdda38damlmgt54v8rn6q9kywtw057rh4v3wwrmn8fajagqnssr7v",
"Test lnbc10u1p3l0wg0pp5y5y3vxt3429m28uuq56uqhwxadftn67yaarq06h3y9nqapz72n6sdqqxqyjw5q9q7sqqqqqqqqqqqqqqqqqqqqqqqqq9qsqsp5y2tazp42xde3c0tdsz30zqcekrt0lzrneszdtagy2qn7vs0d3p5qrzjqwryaup9lh50kkranzgcdnn2fgvx390wgj5jd07rwr3vxeje0glcll7jdvcln4lhw5qqqqlgqqqqqeqqjqdau9jzseecmvmh03h88xyf5f980xx45fmn0cej654v5jr79ye36pww90jwdda38damlmgt54v8rn6q9kywtw057rh4v3wwrmn8fajagqnssr7v",
"pt",
)
}
@Test(expected = CancellationException::class)
fun testNostrEvents() {
assertTranslateContains(
"nostr:nevent1qqs0tsw8hjacs4fppgdg7f5yhgwwfkyua4xcs3re9wwkpkk2qeu6mhql22rcy",
"sure, nostr:nevent1qqs0tsw8hjacs4fppgdg7f5yhgwwfkyua4xcs3re9wwkpkk2qeu6mhql22rcy",
"en",
)
}
@Test
fun testJapaneseTranslationsOfUrl() {
assertTranslateContains(
"https://youtu.be/wMYFmCDy_Eg",
"うちの会社の小さい先輩の話 第1話「うちの会社の先輩は小さくて可愛い」\n" +
"\n" +
"https://youtu.be/wMYFmCDy_Eg\n" +
"\n" +
"先輩がうざい後輩の話と似たような話かと思ったけど、もっとオタクの妄想あるある的なものを詰め込んだやつだ。ワードとかシチュエーションとか、ヒロインのサイズ感とか。知らんけど",
"en",
)
}
@Test
fun testEmoji() {
assertTranslateContains(
"https://cdn.nostr.build/i/df3783dcdf7dd289ba02ba538dc039c8fe1d4db055e580b81604ed88c6af4ee0.jpg",
"\uD83E\uDD23 https://cdn.nostr.build/i/df3783dcdf7dd289ba02ba538dc039c8fe1d4db055e580b81604ed88c6af4ee0.jpg ",
"pt",
)
}
@Test
fun testHttp() {
val text = "https://m.primal.net/MdDd.png \nRunning... \uD83D\uDE01 nostr:npub126ntw5mnermmj0znhjhgdk8lh2af72sm8qfzq48umdlnhaj9kuns3le9ll nostr:npub1getal6ykt05fsz5nqu4uld09nfj3y3qxmv8crys4aeut53unfvlqr80nfm"
assertTranslateContains(
"https://m.primal.net/MdDd.png",
text,
"pt",
)
}
}

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:name=".Amethyst">
<receiver
android:exported="true"
android:enabled="true"
android:name=".service.notifications.PushMessageReceiver">
<intent-filter>
<action android:name="org.unifiedpush.android.connector.MESSAGE"/>
<action android:name="org.unifiedpush.android.connector.UNREGISTERED"/>
<action android:name="org.unifiedpush.android.connector.NEW_ENDPOINT"/>
<action android:name="org.unifiedpush.android.connector.REGISTRATION_FAILED"/>
<action android:name="org.unifiedpush.android.connector.REGISTRATION_REFUSED"/>
</intent-filter>
</receiver>
</application>
</manifest>

View File

@@ -0,0 +1,25 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.service.lang
object LanguageTranslatorService {
fun clear() {}
}

View File

@@ -0,0 +1,102 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.service.notifications
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import android.util.Log
import com.vitorpamplona.amethyst.Amethyst
import org.unifiedpush.android.connector.UnifiedPush
interface PushDistributorActions {
fun getSavedDistributor(): String
fun getInstalledDistributors(): List<String>
fun saveDistributor(distributor: String)
fun removeSavedDistributor()
}
object PushDistributorHandler : PushDistributorActions {
private val unifiedPush: UnifiedPush = UnifiedPush
private var endpointInternal = ""
fun getSavedEndpoint() = endpointInternal
fun setEndpoint(newEndpoint: String) {
endpointInternal = newEndpoint
Log.d("PushHandler", "New endpoint saved : $endpointInternal")
}
fun removeEndpoint() {
endpointInternal = ""
}
fun appContext(): Context = Amethyst.instance.applicationContext
override fun getSavedDistributor(): String = unifiedPush.getSavedDistributor(appContext()) ?: ""
fun savedDistributorExists(): Boolean = getSavedDistributor().isNotEmpty()
override fun getInstalledDistributors(): List<String> = unifiedPush.getDistributors(appContext())
fun formattedDistributorNames(): List<String> {
val distributorsArray = getInstalledDistributors().toTypedArray()
val distributorsNameArray =
distributorsArray
.map {
try {
val ai =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
appContext().packageManager.getApplicationInfo(
it,
PackageManager.ApplicationInfoFlags.of(
PackageManager.GET_META_DATA.toLong(),
),
)
} else {
appContext().packageManager.getApplicationInfo(it, 0)
}
appContext().packageManager.getApplicationLabel(ai)
} catch (e: PackageManager.NameNotFoundException) {
it
}
as String
}.toTypedArray()
return distributorsNameArray.toList()
}
override fun saveDistributor(distributor: String) {
unifiedPush.saveDistributor(appContext(), distributor)
unifiedPush.register(appContext())
}
override fun removeSavedDistributor() {
unifiedPush.removeDistributor(appContext())
}
fun forceRemoveDistributor(context: Context) {
UnifiedPush.removeDistributor(context)
}
}

View File

@@ -0,0 +1,129 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.service.notifications
import android.app.NotificationManager
import android.content.Context
import android.util.Log
import android.util.LruCache
import androidx.core.content.ContextCompat
import com.vitorpamplona.amethyst.Amethyst
import com.vitorpamplona.amethyst.LocalPreferences
import com.vitorpamplona.amethyst.service.notifications.NotificationUtils.getOrCreateDMChannel
import com.vitorpamplona.amethyst.service.notifications.NotificationUtils.getOrCreateZapChannel
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip59Giftwrap.wraps.GiftWrapEvent
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.unifiedpush.android.connector.FailedReason
import org.unifiedpush.android.connector.MessagingReceiver
import org.unifiedpush.android.connector.data.PushEndpoint
import org.unifiedpush.android.connector.data.PushMessage
class PushMessageReceiver : MessagingReceiver() {
companion object {
private val TAG = "Amethyst-OSSPushReceiver"
}
private val appContext = Amethyst.instance.applicationContext
private val scope = Amethyst.instance.applicationIOScope
private val eventCache = LruCache<String, String>(100)
private val pushHandler = PushDistributorHandler
override fun onMessage(
context: Context,
message: PushMessage,
instance: String,
) {
val messageStr = message.content.decodeToString()
Log.d(TAG, "New message $messageStr for Instance: $instance")
scope.launch {
try {
parseMessage(messageStr)?.let {
receiveIfNew(it)
}
} catch (e: Exception) {
if (e is CancellationException) throw e
Log.d(TAG, "Message could not be parsed: ${e.message}")
}
}
}
private suspend fun parseMessage(message: String): GiftWrapEvent? {
(Event.fromJson(message) as? GiftWrapEvent)?.let {
return it
}
return null
}
private suspend fun receiveIfNew(event: GiftWrapEvent) {
if (eventCache.get(event.id) == null) {
eventCache.put(event.id, event.id)
EventNotificationConsumer(appContext).consume(event)
}
}
override fun onNewEndpoint(
context: Context,
endpoint: PushEndpoint,
instance: String,
) {
val sanitizedEndpoint = if (endpoint.url.endsWith("?up=1")) endpoint.url.dropLast(5) else endpoint.url
if (sanitizedEndpoint != pushHandler.getSavedEndpoint()) {
Log.d(TAG, "New endpoint provided:- $endpoint for Instance: $instance ${pushHandler.getSavedEndpoint()} $sanitizedEndpoint")
pushHandler.setEndpoint(sanitizedEndpoint)
scope.launch(Dispatchers.IO) {
PushNotificationUtils.checkAndInit(sanitizedEndpoint, LocalPreferences.allSavedAccounts()) {
Amethyst.instance.okHttpClients.getHttpClient(Amethyst.instance.torManager.isSocksReady())
}
notificationManager().getOrCreateZapChannel(appContext)
notificationManager().getOrCreateDMChannel(appContext)
}
} else {
Log.d(TAG, "Same endpoint provided:- $endpoint for Instance: $instance $sanitizedEndpoint")
}
}
override fun onRegistrationFailed(
context: Context,
reason: FailedReason,
instance: String,
) {
Log.d(TAG, "Registration failed for Instance: $instance")
pushHandler.forceRemoveDistributor(context)
}
override fun onUnregistered(
context: Context,
instance: String,
) {
val removedEndpoint = pushHandler.getSavedEndpoint()
Log.d(TAG, "Endpoint: $removedEndpoint removed for Instance: $instance")
Log.d(TAG, "App is unregistered. ")
pushHandler.forceRemoveDistributor(context)
pushHandler.removeEndpoint()
}
fun notificationManager(): NotificationManager =
ContextCompat.getSystemService(appContext, NotificationManager::class.java)
as NotificationManager
}

View File

@@ -0,0 +1,72 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.service.notifications
import com.vitorpamplona.amethyst.AccountInfo
import com.vitorpamplona.amethyst.service.retryIfException
import kotlinx.coroutines.Dispatchers
import okhttp3.OkHttpClient
object PushNotificationUtils {
var lastToken: String? = null
var hasInit: List<AccountInfo>? = null
private val pushHandler = PushDistributorHandler
suspend fun checkAndInit(
accounts: List<AccountInfo>,
okHttpClient: (String) -> OkHttpClient,
) = with(Dispatchers.IO) {
if (!pushHandler.savedDistributorExists()) return
val currentDistributor = PushDistributorHandler.getSavedDistributor()
PushDistributorHandler.saveDistributor(currentDistributor)
val token = pushHandler.getSavedEndpoint()
if (hasInit?.equals(accounts) == true && lastToken == token) {
return@with
}
registerToken(token, accounts, okHttpClient)
}
suspend fun checkAndInit(
token: String,
accounts: List<AccountInfo>,
okHttpClient: (String) -> OkHttpClient,
) = with(Dispatchers.IO) {
// initializes if the accounts are different or if the token has changed
if (hasInit?.equals(accounts) == true && lastToken == token) {
return@with
}
registerToken(token, accounts, okHttpClient)
}
private suspend fun registerToken(
token: String,
accounts: List<AccountInfo>,
okHttpClient: (String) -> OkHttpClient,
) = retryIfException("RegisterAccounts") {
RegisterAccounts(accounts, okHttpClient).go(token)
lastToken = token
hasInit = accounts.toList()
}
}

View File

@@ -0,0 +1,209 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.ui.components
import android.util.Log
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.isGranted
import com.halilibo.richtext.commonmark.CommonmarkAstNodeParser
import com.halilibo.richtext.commonmark.MarkdownParseOptions
import com.halilibo.richtext.markdown.BasicMarkdown
import com.halilibo.richtext.ui.RichTextStyle
import com.halilibo.richtext.ui.material3.RichText
import com.halilibo.richtext.ui.resolveDefaults
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.service.notifications.PushDistributorHandler
import com.vitorpamplona.amethyst.ui.components.SpinnerSelectionDialog
import com.vitorpamplona.amethyst.ui.components.TitleExplainer
import com.vitorpamplona.amethyst.ui.screen.SharedPreferencesViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.notifications.checkifItNeedsToRequestNotificationPermission
import com.vitorpamplona.amethyst.ui.screen.loggedIn.settings.SettingsRow
import com.vitorpamplona.amethyst.ui.stringRes
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun SelectNotificationProvider(sharedPreferencesViewModel: SharedPreferencesViewModel) {
val notificationPermissionState =
checkifItNeedsToRequestNotificationPermission(sharedPreferencesViewModel)
if (notificationPermissionState.status.isGranted) {
if (!sharedPreferencesViewModel.sharedPrefs.dontShowPushNotificationSelector) {
val context = LocalContext.current
var distributorPresent by remember {
mutableStateOf(PushDistributorHandler.savedDistributorExists())
}
if (!distributorPresent) {
LoadDistributors { currentDistributor, list, readableListWithExplainer ->
if (readableListWithExplainer.size > 1) {
SpinnerSelectionDialog(
title = stringRes(id = R.string.select_push_server),
options = readableListWithExplainer,
onSelect = { index ->
if (list[index] == "None") {
PushDistributorHandler.forceRemoveDistributor(context)
sharedPreferencesViewModel.dontAskForNotificationPermissions()
sharedPreferencesViewModel.dontShowPushNotificationSelector()
} else {
val fullDistributorName = list[index]
PushDistributorHandler.saveDistributor(fullDistributorName)
}
distributorPresent = true
Log.d("Amethyst", "NotificationScreen: Distributor registered.")
},
onDismiss = {
distributorPresent = true
Log.d("Amethyst", "NotificationScreen: Distributor dialog dismissed.")
},
)
} else {
AlertDialog(
onDismissRequest = { distributorPresent = true },
title = { Text(stringRes(R.string.push_server_install_app)) },
text = {
val content = stringRes(R.string.push_server_install_app_description)
val astNode =
remember {
CommonmarkAstNodeParser(MarkdownParseOptions.MarkdownWithLinks).parse(content)
}
RichText(
style = RichTextStyle().resolveDefaults(),
renderer = null,
) {
BasicMarkdown(astNode)
}
},
confirmButton = {
Row(
modifier = Modifier.padding(all = 8.dp).fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
) {
TextButton(
onClick = {
distributorPresent = true
sharedPreferencesViewModel.dontShowPushNotificationSelector()
},
) {
Text(stringRes(R.string.quick_action_dont_show_again_button))
}
Button(
onClick = { distributorPresent = true },
contentPadding = PaddingValues(horizontal = 16.dp),
) {
Row(
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
imageVector = Icons.Default.Check,
contentDescription = null,
)
Spacer(Modifier.width(8.dp))
Text(stringRes(R.string.error_dialog_button_ok))
}
}
}
},
)
}
}
}
}
}
}
@Composable
fun LoadDistributors(onInner: @Composable (String, ImmutableList<String>, ImmutableList<TitleExplainer>) -> Unit) {
val currentDistributor = PushDistributorHandler.getSavedDistributor().ifBlank { null } ?: "None"
val list =
remember {
PushDistributorHandler.getInstalledDistributors().plus("None").toImmutableList()
}
val readableListWithExplainer =
PushDistributorHandler
.formattedDistributorNames()
.mapIndexed { index, name ->
TitleExplainer(
name,
stringRes(id = R.string.push_server_uses_app_explainer, list[index]),
)
}.plus(
TitleExplainer(
stringRes(id = R.string.push_server_none),
stringRes(id = R.string.push_server_none_explainer),
),
).toImmutableList()
onInner(
currentDistributor,
list,
readableListWithExplainer,
)
}
@Composable
fun PushNotificationSettingsRow(sharedPreferencesViewModel: SharedPreferencesViewModel) {
val context = LocalContext.current
LoadDistributors { currentDistributor, list, readableListWithExplainer ->
SettingsRow(
R.string.push_server_title,
R.string.push_server_explainer,
selectedItens = readableListWithExplainer,
selectedIndex = list.indexOf(currentDistributor),
) { index ->
if (list[index] == "None") {
sharedPreferencesViewModel.dontAskForNotificationPermissions()
sharedPreferencesViewModel.dontShowPushNotificationSelector()
PushDistributorHandler.forceRemoveDistributor(context)
} else {
PushDistributorHandler.saveDistributor(list[index])
}
}
}
}

View File

@@ -0,0 +1,64 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.ui.components
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.quartz.nip02FollowList.ImmutableListOfLists
@Composable
fun TranslatableRichTextViewer(
content: String,
canPreview: Boolean,
quotesLeft: Int,
modifier: Modifier = Modifier,
tags: ImmutableListOfLists<String>,
backgroundColor: MutableState<Color>,
id: String,
callbackUri: String? = null,
accountViewModel: AccountViewModel,
nav: INav,
) = ExpandableRichTextViewer(
content,
canPreview,
quotesLeft,
modifier,
tags,
backgroundColor,
id,
callbackUri,
accountViewModel,
nav,
)
@Composable
fun TranslatableRichTextViewer(
content: String,
id: String,
accountViewModel: AccountViewModel,
displayText: @Composable (String) -> Unit,
) = displayText(content)

View File

@@ -0,0 +1,205 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<queries>
<package android:name="org.torproject.android"/>
<intent>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="nostrsigner" />
</intent>
</queries>
<!-- Doesn't require a camera -->
<uses-feature android:name="android.hardware.camera" android:required="false" />
<!-- To connect with relays -->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- To Upload media (old devices) -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<!-- To read QRs that contain nostr:<NIP19> -->
<!-- To take pictures -->
<uses-permission android:name="android.permission.CAMERA" />
<!-- To record audio messages -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!-- To read NFCs that contain nostr:<NIP19> -->
<uses-permission android:name="android.permission.NFC" />
<!-- To know receive notifications when the app connects/disconnects from the web -->
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<!-- Audio/Video Playback -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
<!-- Keeps screen on while playing videos -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- This notification permission is needed for some phones -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<!-- Adds Geohash to posts if active -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- Old permission to access media -->
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28"
tools:ignore="ScopedStorage" />
<application
android:allowBackup="false"
android:name=".Amethyst"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:enableOnBackInvokedCallback="true"
android:supportsRtl="true"
android:theme="@style/Theme.Amethyst"
android:largeHeap="true"
android:usesCleartextTraffic="true"
android:hardwareAccelerated="true"
android:localeConfig="@xml/locales_config"
tools:targetApi="34">
<activity
android:name=".ui.MainActivity"
android:exported="true"
android:launchMode="singleInstance"
android:windowSoftInputMode="adjustResize"
android:configChanges="orientation|screenSize|screenLayout"
android:taskAffinity=".service.playback.pip.PipVideoActivity"
android:theme="@style/Theme.Amethyst">
<intent-filter android:label="Amethyst">
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter android:label="Amethyst">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="nostr" />
</intent-filter>
<intent-filter android:label="Amethyst">
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="nostr" />
</intent-filter>
<intent-filter android:label="Amethyst">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="nostrwalletconnect" />
<data android:scheme="nostr+walletconnect" />
</intent-filter>
<intent-filter android:label="New Post">
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter android:label="New Post">
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="video/*" />
</intent-filter>
<intent-filter android:label="New Post">
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
<intent-filter android:label="njump.me">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="njump.me" />
</intent-filter>
<intent-filter android:label="Primal">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="primal.net" />
<data android:pathPrefix="/e/" />
<data android:pathPrefix="/p/" />
<data android:pathPrefix="/a/" />
</intent-filter>
<intent-filter android:label="Yakihonne">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="yakihonne.com" />
<data android:pathPrefix="/notes/" />
<data android:pathPrefix="/users/" />
<data android:pathPrefix="/videos/" />
<data android:pathPrefix="/article/" />
</intent-filter>
</activity>
<activity
android:name="com.journeyapps.barcodescanner.CaptureActivity"
android:screenOrientation="fullSensor"
tools:replace="screenOrientation"
tools:ignore="DiscouragedApi" />
<activity
android:name=".service.playback.pip.PipVideoActivity"
android:autoRemoveFromRecents="true"
android:configChanges="orientation|screenLayout|screenSize|smallestScreenSize|keyboardHidden|keyboard|uiMode"
android:supportsPictureInPicture="true"
android:launchMode="singleInstance"
android:exported="false"
android:resizeableActivity="true"
android:theme="@style/noAnimTheme"
/>
<service
android:name=".service.playback.service.PlaybackService"
android:foregroundServiceType="mediaPlayback"
android:stopWithTask="true"
android:exported="true"
tools:ignore="ExportedService">
<intent-filter>
<action android:name="androidx.media3.session.MediaSessionService"/>
<action android:name="android.media.browse.MediaBrowserService"/>
</intent-filter>
</service>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
<receiver
android:name=".service.notifications.PokeyReceiver"
android:exported="true"
tools:ignore="ExportedReceiver"
>
<intent-filter>
<action android:name="com.shared.NOSTR" />
</intent-filter>
</receiver>
</application>
</manifest>

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -0,0 +1,233 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst
import android.app.Application
import android.content.ContentResolver
import android.util.Log
import androidx.security.crypto.EncryptedSharedPreferences
import coil3.disk.DiskCache
import coil3.memory.MemoryCache
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.service.connectivity.ConnectivityManager
import com.vitorpamplona.amethyst.service.crashreports.CrashReportCache
import com.vitorpamplona.amethyst.service.crashreports.UnexpectedCrashSaver
import com.vitorpamplona.amethyst.service.eventCache.MemoryTrimmingService
import com.vitorpamplona.amethyst.service.images.ImageCacheFactory
import com.vitorpamplona.amethyst.service.images.ImageLoaderSetup
import com.vitorpamplona.amethyst.service.location.LocationState
import com.vitorpamplona.amethyst.service.logging.Logging
import com.vitorpamplona.amethyst.service.notifications.PokeyReceiver
import com.vitorpamplona.amethyst.service.okhttp.DualHttpClientManager
import com.vitorpamplona.amethyst.service.okhttp.EncryptionKeyCache
import com.vitorpamplona.amethyst.service.okhttp.OkHttpWebSocket
import com.vitorpamplona.amethyst.service.okhttp.ProxySettingsAnchor
import com.vitorpamplona.amethyst.service.playback.diskCache.VideoCache
import com.vitorpamplona.amethyst.service.playback.diskCache.VideoCacheFactory
import com.vitorpamplona.amethyst.service.relayClient.CacheClientConnector
import com.vitorpamplona.amethyst.service.relayClient.RelayProxyClientConnector
import com.vitorpamplona.amethyst.service.relayClient.authCommand.model.AuthCoordinator
import com.vitorpamplona.amethyst.service.relayClient.notifyCommand.model.NotifyCoordinator
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.RelaySubscriptionsCoordinator
import com.vitorpamplona.amethyst.service.relayClient.speedLogger.RelaySpeedLogger
import com.vitorpamplona.amethyst.service.uploads.nip95.Nip95CacheFactory
import com.vitorpamplona.amethyst.ui.tor.TorManager
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
import com.vitorpamplona.quartz.nip03Timestamp.VerificationStateCache
import com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp.OtsBlockHeightCache
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import java.io.File
class Amethyst : Application() {
val appAgent = "Amethyst/${BuildConfig.VERSION_NAME}"
// Exists to avoid exceptions stopping the coroutine
val exceptionHandler =
CoroutineExceptionHandler { _, throwable ->
Log.e("AmethystCoroutine", "Caught exception: ${throwable.message}", throwable)
}
val applicationIOScope = CoroutineScope(Dispatchers.IO + SupervisorJob() + exceptionHandler)
// Key cache service to download and decrypt encrypted files before caching them.
val keyCache = EncryptionKeyCache()
// App services that should be run as soon as there are subscribers to their flows
val locationManager = LocationState(this, applicationIOScope)
val connManager = ConnectivityManager(this, applicationIOScope)
val torManager = TorManager(this, applicationIOScope)
// Service that will run at all times to receive events from Pokey
val pokeyReceiver = PokeyReceiver()
// manages all the other connections separately from relays.
val okHttpClients =
DualHttpClientManager(
userAgent = appAgent,
proxyPortProvider = torManager.activePortOrNull,
isMobileDataProvider = connManager.isMobileOrNull,
keyCache = keyCache,
scope = applicationIOScope,
)
// manages all relay connections
val okHttpClientForRelays =
DualHttpClientManager(
userAgent = appAgent,
proxyPortProvider = torManager.activePortOrNull,
isMobileDataProvider = connManager.isMobileOrNull,
keyCache = keyCache,
scope = applicationIOScope,
)
// manages all relay connections
val okHttpClientForRelaysForDms =
DualHttpClientManager(
userAgent = appAgent,
proxyPortProvider = torManager.activePortOrNull,
isMobileDataProvider = connManager.isMobileOrNull,
keyCache = keyCache,
scope = applicationIOScope,
)
val torProxySettingsAnchor = ProxySettingsAnchor()
// Connects the NostrClient class with okHttp
val websocketBuilder =
OkHttpWebSocket.Builder { url ->
val useTor = torProxySettingsAnchor.useProxy(url)
if (torProxySettingsAnchor.isDM(url)) {
okHttpClientForRelaysForDms.getHttpClient(useTor)
} else {
okHttpClientForRelays.getHttpClient(useTor)
}
}
// Caches all events in Memory
val cache: LocalCache = LocalCache
// Organizes cache clearing
val trimmingService = MemoryTrimmingService(cache)
// Provides a relay pool
val client: NostrClient = NostrClient(websocketBuilder, applicationIOScope)
// Watches for changes on Tor and Relay List Settings
val relayProxyClientConnector = RelayProxyClientConnector(torProxySettingsAnchor, okHttpClients, connManager, client, torManager, applicationIOScope)
// Verifies and inserts in the cache from all relays, all subscriptions
val cacheClientConnector = CacheClientConnector(client, cache)
// Show messages from the Relay and controls their dismissal
val notifyCoordinator = NotifyCoordinator(client)
// Authenticates with relays.
val authCoordinator = AuthCoordinator(client, applicationIOScope)
val logger = if (isDebug) RelaySpeedLogger(client) else null
// Coordinates all subscriptions for the Nostr Client
val sources: RelaySubscriptionsCoordinator = RelaySubscriptionsCoordinator(LocalCache, client, applicationIOScope)
// saves the .content of NIP-95 blobs in disk to save memory
val nip95cache: File by lazy { Nip95CacheFactory.new(this) }
// local video cache with disk + memory
val videoCache: VideoCache by lazy { VideoCacheFactory.new(this) }
// image cache in disk for coil
val diskCache: DiskCache by lazy { ImageCacheFactory.newDisk(this) }
// image cache in memory for coil
val memoryCache: MemoryCache by lazy { ImageCacheFactory.newMemory(this) }
val crashReportCache: CrashReportCache by lazy { CrashReportCache(this) }
// Application-wide ots verification cache
val otsVerifCache by lazy { VerificationStateCache() }
// Application-wide block height request cache
val otsBlockHeightCache by lazy { OtsBlockHeightCache() }
override fun onCreate() {
super.onCreate()
Log.d("AmethystApp", "onCreate $this")
Thread.setDefaultUncaughtExceptionHandler(UnexpectedCrashSaver(crashReportCache, applicationIOScope))
instance = this
if (isDebug) {
Logging.setup()
}
// initializes diskcache on an IO thread.
applicationIOScope.launch {
diskCache
videoCache
}
// registers to receive events
pokeyReceiver.register(this)
}
override fun onTerminate() {
super.onTerminate()
Log.d("AmethystApp", "onTerminate $this")
pokeyReceiver.unregister(this)
applicationIOScope.cancel("Application onTerminate $this")
}
fun contentResolverFn(): ContentResolver = contentResolver
fun setImageLoader(shouldUseTor: (String) -> Boolean?) {
ImageLoaderSetup.setup(this, diskCache, memoryCache) { url ->
shouldUseTor(url)?.let { okHttpClients.getHttpClient(it) } ?: okHttpClients.getHttpClient(false)
}
}
fun encryptedStorage(npub: String? = null): EncryptedSharedPreferences = EncryptedStorage.preferences(instance, npub)
/**
* Release memory when the UI becomes hidden or when system resources become low.
*
* @param level the memory-related event that was raised.
*/
override fun onTrimMemory(level: Int) {
super.onTrimMemory(level)
Log.d("AmethystApp", "onTrimMemory $level")
applicationIOScope.launch(Dispatchers.Default) {
trimmingService.run(null, LocalPreferences.allSavedAccounts())
}
}
companion object {
lateinit var instance: Amethyst
private set
}
}

View File

@@ -0,0 +1,199 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst
import android.app.ActivityManager
import android.content.Context
import android.content.pm.ApplicationInfo
import android.os.Debug
import android.util.Log
import androidx.core.content.getSystemService
import com.vitorpamplona.amethyst.model.LocalCache
import kotlin.time.DurationUnit
import kotlin.time.measureTimedValue
@Suppress("SENSELESS_COMPARISON")
val isDebug = BuildConfig.DEBUG || BuildConfig.BUILD_TYPE == "benchmark"
fun debugState(context: Context) {
// Amethyst.instance.client
// .allSubscriptions()
// .forEach { Log.d("STATE DUMP", "${it.key} ${it.value.filters.joinToString { it.filter.toJson() }}") }
val totalMemoryMb = Runtime.getRuntime().totalMemory() / (1024 * 1024)
val freeMemoryMb = Runtime.getRuntime().freeMemory() / (1024 * 1024)
val maxMemoryMb = Runtime.getRuntime().maxMemory() / (1024 * 1024)
val jvmHeapAllocatedMb = totalMemoryMb - freeMemoryMb
Log.d("STATE DUMP", "Total Heap Allocated: $jvmHeapAllocatedMb/$maxMemoryMb MB")
val nativeHeap = Debug.getNativeHeapAllocatedSize() / (1024 * 1024)
val maxNative = Debug.getNativeHeapSize() / (1024 * 1024)
Log.d("STATE DUMP", "Total Native Heap Allocated: $nativeHeap/$maxNative MB")
val activityManager: ActivityManager? = context.getSystemService()
if (activityManager != null) {
val isLargeHeap = (context.applicationInfo.flags and ApplicationInfo.FLAG_LARGE_HEAP) != 0
val memClass = if (isLargeHeap) activityManager.largeMemoryClass else activityManager.memoryClass
Log.d("STATE DUMP", "Memory Class $memClass MB (largeHeap $isLargeHeap)")
}
Log.d(
"STATE DUMP",
"Connected Relays: " +
Amethyst.instance.client
.relayStatusFlow()
.value.connected.size + "/" +
Amethyst.instance.client
.relayStatusFlow()
.value.available.size,
)
Log.d(
"STATE DUMP",
"Image Disk Cache ${(Amethyst.instance.diskCache.size) / (1024 * 1024)}/${(Amethyst.instance.diskCache.maxSize) / (1024 * 1024)} MB",
)
Log.d(
"STATE DUMP",
"Image Memory Cache ${(Amethyst.instance.memoryCache.size) / (1024 * 1024)}/${(Amethyst.instance.memoryCache.maxSize) / (1024 * 1024)} MB",
)
Log.d(
"STATE DUMP",
"Notes: " +
LocalCache.notes.filter { _, it -> it.flowSet != null }.size +
" / " +
LocalCache.notes.filter { _, it -> it.event != null }.size +
" / " +
LocalCache.notes.size(),
)
Log.d(
"STATE DUMP",
"Addressables: " +
LocalCache.addressables.filter { _, it -> it.flowSet != null }.size +
" / " +
LocalCache.addressables.filter { _, it -> it.event != null }.size +
" / " +
LocalCache.addressables.size(),
)
Log.d(
"STATE DUMP",
"Users: " +
LocalCache.users.filter { _, it -> it.flowSet != null }.size +
" / " +
LocalCache.users.filter { _, it -> it.latestMetadata != null }.size +
" / " +
LocalCache.users.size(),
)
Log.d(
"STATE DUMP",
"Deletion Events: " +
LocalCache.deletionIndex.size(),
)
Log.d(
"STATE DUMP",
"Observable Events: " +
LocalCache.observablesByKindAndETag.size +
" / " +
LocalCache.observablesByKindAndAuthor.size,
)
Log.d(
"STATE DUMP",
"Spam: " +
LocalCache.antiSpam.spamMessages.size() + " / " + LocalCache.antiSpam.recentEventIds.size() + " / " + LocalCache.antiSpam.recentAddressables.size(),
)
Log.d(
"STATE DUMP",
"Memory used by Events: " +
LocalCache.notes.sumOfLong { _, note -> note.event?.countMemory() ?: 0L } / (1024 * 1024) +
" MB",
)
val qttNotes = LocalCache.notes.countByGroup { _, it -> it.event?.kind }
val qttAddressables = LocalCache.addressables.countByGroup { _, it -> it.event?.kind }
val bytesNotes =
LocalCache.notes
.sumByGroup(groupMap = { _, it -> it.event?.kind }, sumOf = { _, it -> it.event?.countMemory() ?: 0L })
val bytesAddressables =
LocalCache.addressables
.sumByGroup(groupMap = { _, it -> it.event?.kind }, sumOf = { _, it -> it.event?.countMemory() ?: 0L })
qttNotes.toList().sortedByDescending { bytesNotes[it.first] }.forEach { (kind, qtt) ->
Log.d("STATE DUMP", "Kind ${kind.toString().padStart(5,' ')}:\t${qtt.toString().padStart(6,' ')} elements\t${bytesNotes[kind]?.div((1024 * 1024))}MB ")
}
qttAddressables.toList().sortedByDescending { bytesNotes[it.first] }.forEach { (kind, qtt) ->
Log.d("STATE DUMP", "Kind ${kind.toString().padStart(5,' ')}:\t${qtt.toString().padStart(6,' ')} elements\t${bytesAddressables[kind]?.div((1024 * 1024))}MB ")
}
}
inline fun <T> logTime(
debugMessage: String,
minToReportMs: Int = 1,
block: () -> T,
): T =
if (isDebug) {
val (result, elapsed) = measureTimedValue(block)
if (elapsed.inWholeMilliseconds > minToReportMs) {
Log.d("DEBUG-TIME", "${elapsed.toString(DurationUnit.MILLISECONDS, 3).padStart(12)}: $debugMessage")
}
result
} else {
block()
}
inline fun <T> logTime(
debugMessage: (T) -> String,
minToReportMs: Int = 1,
block: () -> T,
): T =
if (isDebug) {
val (result, elapsed) = measureTimedValue(block)
if (elapsed.inWholeMilliseconds > minToReportMs) {
Log.d("DEBUG-TIME", "${elapsed.toString(DurationUnit.MILLISECONDS, 3).padStart(12)}: ${debugMessage(result)}")
}
result
} else {
block()
}
fun debug(
tag: String,
debugMessage: String,
) {
if (isDebug) {
Log.d(tag, debugMessage)
}
}
inline fun debug(
tag: String,
debugMessage: () -> String,
) {
if (isDebug) {
Log.d(tag, debugMessage())
}
}

View File

@@ -0,0 +1,53 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst
import android.content.Context
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKey
class EncryptedStorage {
companion object {
private const val PREFERENCES_NAME = "secret_keeper"
// returns the preferences for each account or a global file if null.
fun prefsFileName(npub: String? = null): String = if (npub == null) PREFERENCES_NAME else "${PREFERENCES_NAME}_$npub"
fun preferences(
applicationContext: Context,
npub: String? = null,
): EncryptedSharedPreferences {
val masterKey: MasterKey =
MasterKey
.Builder(applicationContext, MasterKey.DEFAULT_MASTER_KEY_ALIAS)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()
return EncryptedSharedPreferences.create(
applicationContext,
prefsFileName(npub),
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM,
) as EncryptedSharedPreferences
}
}
}

View File

@@ -0,0 +1,682 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst
import android.annotation.SuppressLint
import android.content.Context
import android.content.SharedPreferences
import android.util.Log
import androidx.compose.runtime.Immutable
import androidx.core.content.edit
import com.fasterxml.jackson.module.kotlin.readValue
import com.vitorpamplona.amethyst.model.ALL_FOLLOWS
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.GLOBAL_FOLLOWS
import com.vitorpamplona.amethyst.model.Settings
import com.vitorpamplona.amethyst.service.checkNotInMainThread
import com.vitorpamplona.amethyst.ui.actions.mediaServers.DEFAULT_MEDIA_SERVERS
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName
import com.vitorpamplona.amethyst.ui.tor.TorSettings
import com.vitorpamplona.amethyst.ui.tor.TorSettingsFlow
import com.vitorpamplona.quartz.experimental.ephemChat.list.EphemeralChatListEvent
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
import com.vitorpamplona.quartz.nip01Core.jackson.JsonMapper
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent
import com.vitorpamplona.quartz.nip17Dm.settings.ChatMessageRelayListEvent
import com.vitorpamplona.quartz.nip19Bech32.toNpub
import com.vitorpamplona.quartz.nip28PublicChat.list.ChannelListEvent
import com.vitorpamplona.quartz.nip37Drafts.privateOutbox.PrivateOutboxRelayListEvent
import com.vitorpamplona.quartz.nip47WalletConnect.Nip47WalletConnect
import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent
import com.vitorpamplona.quartz.nip51Lists.geohashList.GeohashListEvent
import com.vitorpamplona.quartz.nip51Lists.hashtagList.HashtagListEvent
import com.vitorpamplona.quartz.nip51Lists.muteList.MuteListEvent
import com.vitorpamplona.quartz.nip51Lists.relayLists.BlockedRelayListEvent
import com.vitorpamplona.quartz.nip51Lists.relayLists.TrustedRelayListEvent
import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListEvent
import com.vitorpamplona.quartz.nip72ModCommunities.follow.CommunityListEvent
import com.vitorpamplona.quartz.nip78AppData.AppSpecificDataEvent
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import java.io.File
// Release mode (!BuildConfig.DEBUG) always uses encrypted preferences
// To use plaintext SharedPreferences for debugging, set this to true
// It will only apply in Debug builds
private const val DEBUG_PLAINTEXT_PREFERENCES = false
private const val DEBUG_PREFERENCES_NAME = "debug_prefs"
@Immutable
data class AccountInfo(
val npub: String,
val hasPrivKey: Boolean,
val loggedInWithExternalSigner: Boolean,
val isTransient: Boolean,
)
private object PrefKeys {
const val CURRENT_ACCOUNT = "currently_logged_in_account"
const val SAVED_ACCOUNTS = "all_saved_accounts"
const val NOSTR_PRIVKEY = "nostr_privkey"
const val NOSTR_PUBKEY = "nostr_pubkey"
const val LOCAL_RELAY_SERVERS = "localRelayServers"
const val DEFAULT_FILE_SERVER = "defaultFileServer"
const val DEFAULT_HOME_FOLLOW_LIST = "defaultHomeFollowList"
const val DEFAULT_STORIES_FOLLOW_LIST = "defaultStoriesFollowList"
const val DEFAULT_NOTIFICATION_FOLLOW_LIST = "defaultNotificationFollowList"
const val DEFAULT_DISCOVERY_FOLLOW_LIST = "defaultDiscoveryFollowList"
const val ZAP_PAYMENT_REQUEST_SERVER = "zapPaymentServer"
const val LATEST_USER_METADATA = "latestUserMetadata"
const val LATEST_CONTACT_LIST = "latestContactList"
const val LATEST_DM_RELAY_LIST = "latestDMRelayList"
const val LATEST_NIP65_RELAY_LIST = "latestNIP65RelayList"
const val LATEST_SEARCH_RELAY_LIST = "latestSearchRelayList"
const val LATEST_BLOCKED_RELAY_LIST = "latestBlockedRelayList"
const val LATEST_TRUSTED_RELAY_LIST = "latestTrustedRelayList"
const val LATEST_MUTE_LIST = "latestMuteList"
const val LATEST_PRIVATE_HOME_RELAY_LIST = "latestPrivateHomeRelayList"
const val LATEST_APP_SPECIFIC_DATA = "latestAppSpecificData"
const val LATEST_CHANNEL_LIST = "latestChannelList"
const val LATEST_COMMUNITY_LIST = "latestCommunityList"
const val LATEST_HASHTAG_LIST = "latestHashtagList"
const val LATEST_GEOHASH_LIST = "latestGeohashList"
const val LATEST_EPHEMERAL_LIST = "latestEphemeralChatList"
const val HIDE_DELETE_REQUEST_DIALOG = "hide_delete_request_dialog"
const val HIDE_BLOCK_ALERT_DIALOG = "hide_block_alert_dialog"
const val HIDE_NIP_17_WARNING_DIALOG = "hide_nip24_warning_dialog" // delete later
const val TOR_SETTINGS = "tor_settings"
const val USE_PROXY = "use_proxy"
const val PROXY_PORT = "proxy_port"
const val LAST_READ_PER_ROUTE = "last_read_route_per_route"
const val LOGIN_WITH_EXTERNAL_SIGNER = "login_with_external_signer"
const val SIGNER_PACKAGE_NAME = "signer_package_name"
const val HAS_DONATED_IN_VERSION = "has_donated_in_version"
const val PENDING_ATTESTATIONS = "pending_attestations"
const val ALL_ACCOUNT_INFO = "all_saved_accounts_info"
const val SHARED_SETTINGS = "shared_settings"
}
object LocalPreferences {
private const val COMMA = ","
private var currentAccount: String? = null
private val savedAccounts: MutableStateFlow<List<AccountInfo>?> = MutableStateFlow(null)
private val cachedAccounts: MutableMap<String, AccountSettings?> = mutableMapOf()
suspend fun currentAccount(): String? {
if (currentAccount == null) {
currentAccount =
withContext(Dispatchers.IO) {
encryptedPreferences().getString(PrefKeys.CURRENT_ACCOUNT, null)
}
}
return currentAccount
}
private suspend fun updateCurrentAccount(info: AccountInfo?) {
if (info == null) {
currentAccount = null
withContext(Dispatchers.IO) {
encryptedPreferences().edit { clear() }
}
} else if (currentAccount != info.npub) {
currentAccount = info.npub
if (!info.isTransient) {
withContext(Dispatchers.IO) {
encryptedPreferences().edit { putString(PrefKeys.CURRENT_ACCOUNT, info.npub) }
}
}
}
}
private suspend fun savedAccounts(): List<AccountInfo> {
if (savedAccounts.value == null) {
withContext(Dispatchers.IO) {
with(encryptedPreferences()) {
val newSystemOfAccounts =
getString(PrefKeys.ALL_ACCOUNT_INFO, "[]")?.let {
JsonMapper.mapper.readValue<List<AccountInfo>>(it)
}
if (!newSystemOfAccounts.isNullOrEmpty()) {
savedAccounts.emit(newSystemOfAccounts)
} else {
val oldAccounts = getString(PrefKeys.SAVED_ACCOUNTS, null)?.split(COMMA) ?: listOf()
val migrated =
oldAccounts.map { npub ->
AccountInfo(
npub,
encryptedPreferences(npub).getBoolean(PrefKeys.LOGIN_WITH_EXTERNAL_SIGNER, false),
(encryptedPreferences(npub).getString(PrefKeys.NOSTR_PRIVKEY, "") ?: "").isNotBlank(),
false,
)
}
savedAccounts.emit(migrated)
edit { putString(PrefKeys.ALL_ACCOUNT_INFO, JsonMapper.mapper.writeValueAsString(savedAccounts.value)) }
}
}
}
}
// it's always not null when it gets here.
return savedAccounts.value!!
}
fun accountsFlow() = savedAccounts
private suspend fun updateSavedAccounts(accounts: List<AccountInfo>) =
withContext(Dispatchers.IO) {
if (savedAccounts != accounts) {
savedAccounts.emit(accounts)
encryptedPreferences()
.edit {
putString(
PrefKeys.ALL_ACCOUNT_INFO,
JsonMapper.mapper.writeValueAsString(accounts.filter { !it.isTransient }),
)
}
}
}
private val prefsDirPath: String
get() = "${Amethyst.instance.filesDir.parent}/shared_prefs/"
private suspend fun addAccount(accInfo: AccountInfo) {
val accounts = savedAccounts().filter { it.npub != accInfo.npub }.plus(accInfo)
updateSavedAccounts(accounts)
}
private suspend fun setCurrentAccount(accountSettings: AccountSettings) {
val npub = accountSettings.keyPair.pubKey.toNpub()
val accInfo =
AccountInfo(
npub,
accountSettings.isWriteable(),
accountSettings.externalSignerPackageName != null,
accountSettings.transientAccount,
)
updateCurrentAccount(accInfo)
addAccount(accInfo)
}
suspend fun switchToAccount(accountInfo: AccountInfo) = updateCurrentAccount(accountInfo)
/** Removes the account from the app level shared preferences */
private suspend fun removeAccount(accountInfo: AccountInfo) {
updateSavedAccounts(savedAccounts().filter { it.npub != accountInfo.npub })
}
/** Deletes the npub-specific shared preference file */
private suspend fun deleteUserPreferenceFile(npub: String) {
withContext(Dispatchers.IO) {
val prefsDir = File(prefsDirPath)
prefsDir.list()?.forEach {
if (it.contains(npub)) {
File(prefsDir, it).delete()
}
}
}
}
private fun encryptedPreferences(npub: String? = null): SharedPreferences {
checkNotInMainThread()
return if (BuildConfig.DEBUG && DEBUG_PLAINTEXT_PREFERENCES) {
val preferenceFile =
if (npub == null) DEBUG_PREFERENCES_NAME else "${DEBUG_PREFERENCES_NAME}_$npub"
Amethyst.instance.getSharedPreferences(preferenceFile, Context.MODE_PRIVATE)
} else {
Amethyst.instance.encryptedStorage(npub)
}
}
/**
* Clears the preferences for a given npub, deletes the preferences xml file, and switches the
* user to the first account in the list if it exists
*
* We need to use `commit()` to write changes to disk and release the file lock so that it can be
* deleted. If we use `apply()` there is a race condition and the file will probably not be
* deleted
*/
@SuppressLint("ApplySharedPref")
suspend fun deleteAccount(accountInfo: AccountInfo) {
Log.d("LocalPreferences", "Saving to encrypted storage updatePrefsForLogout ${accountInfo.npub}")
withContext(Dispatchers.IO) {
encryptedPreferences(accountInfo.npub).edit(commit = true) { clear() }
removeAccount(accountInfo)
deleteUserPreferenceFile(accountInfo.npub)
if (savedAccounts().isEmpty()) {
updateCurrentAccount(null)
} else if (currentAccount() == accountInfo.npub) {
updateCurrentAccount(savedAccounts().elementAt(0))
}
}
}
suspend fun setDefaultAccount(accountSettings: AccountSettings) {
setCurrentAccount(accountSettings)
saveToEncryptedStorage(accountSettings)
}
suspend fun allSavedAccounts(): List<AccountInfo> = savedAccounts()
suspend fun saveToEncryptedStorage(settings: AccountSettings) {
Log.d("LocalPreferences", "Saving to encrypted storage")
if (!settings.transientAccount) {
withContext(Dispatchers.IO) {
val prefs = encryptedPreferences(settings.keyPair.pubKey.toNpub())
prefs.edit {
putBoolean(PrefKeys.LOGIN_WITH_EXTERNAL_SIGNER, settings.externalSignerPackageName != null)
if (settings.externalSignerPackageName != null) {
remove(PrefKeys.NOSTR_PRIVKEY)
putString(PrefKeys.SIGNER_PACKAGE_NAME, settings.externalSignerPackageName)
} else {
remove(PrefKeys.SIGNER_PACKAGE_NAME)
settings.keyPair.privKey?.let { putString(PrefKeys.NOSTR_PRIVKEY, it.toHexKey()) }
}
settings.keyPair.pubKey.let { putString(PrefKeys.NOSTR_PUBKEY, it.toHexKey()) }
putString(
PrefKeys.DEFAULT_FILE_SERVER,
JsonMapper.mapper.writeValueAsString(settings.defaultFileServer),
)
putString(PrefKeys.DEFAULT_HOME_FOLLOW_LIST, settings.defaultHomeFollowList.value)
putString(PrefKeys.DEFAULT_STORIES_FOLLOW_LIST, settings.defaultStoriesFollowList.value)
putString(
PrefKeys.DEFAULT_NOTIFICATION_FOLLOW_LIST,
settings.defaultNotificationFollowList.value,
)
putString(
PrefKeys.DEFAULT_DISCOVERY_FOLLOW_LIST,
settings.defaultDiscoveryFollowList.value,
)
putString(
PrefKeys.ZAP_PAYMENT_REQUEST_SERVER,
JsonMapper.mapper.writeValueAsString(settings.zapPaymentRequest.value?.denormalize()),
)
if (settings.backupContactList != null) {
putString(
PrefKeys.LATEST_CONTACT_LIST,
JsonMapper.mapper.writeValueAsString(settings.backupContactList),
)
} else {
remove(PrefKeys.LATEST_CONTACT_LIST)
}
if (settings.backupUserMetadata != null) {
putString(
PrefKeys.LATEST_USER_METADATA,
JsonMapper.mapper.writeValueAsString(settings.backupUserMetadata),
)
} else {
remove(PrefKeys.LATEST_USER_METADATA)
}
if (settings.backupDMRelayList != null) {
putString(
PrefKeys.LATEST_DM_RELAY_LIST,
JsonMapper.mapper.writeValueAsString(settings.backupDMRelayList),
)
} else {
remove(PrefKeys.LATEST_DM_RELAY_LIST)
}
if (settings.backupNIP65RelayList != null) {
putString(
PrefKeys.LATEST_NIP65_RELAY_LIST,
JsonMapper.mapper.writeValueAsString(settings.backupNIP65RelayList),
)
} else {
remove(PrefKeys.LATEST_NIP65_RELAY_LIST)
}
if (settings.backupSearchRelayList != null) {
putString(
PrefKeys.LATEST_SEARCH_RELAY_LIST,
JsonMapper.mapper.writeValueAsString(settings.backupSearchRelayList),
)
} else {
remove(PrefKeys.LATEST_SEARCH_RELAY_LIST)
}
if (settings.backupBlockedRelayList != null) {
putString(
PrefKeys.LATEST_BLOCKED_RELAY_LIST,
JsonMapper.mapper.writeValueAsString(settings.backupBlockedRelayList),
)
} else {
remove(PrefKeys.LATEST_BLOCKED_RELAY_LIST)
}
if (settings.backupTrustedRelayList != null) {
putString(
PrefKeys.LATEST_TRUSTED_RELAY_LIST,
JsonMapper.mapper.writeValueAsString(settings.backupTrustedRelayList),
)
} else {
remove(PrefKeys.LATEST_TRUSTED_RELAY_LIST)
}
if (settings.localRelayServers.value.isNotEmpty()) {
putStringSet(PrefKeys.LOCAL_RELAY_SERVERS, settings.localRelayServers.value)
} else {
remove(PrefKeys.LOCAL_RELAY_SERVERS)
}
if (settings.backupMuteList != null) {
putString(
PrefKeys.LATEST_MUTE_LIST,
JsonMapper.mapper.writeValueAsString(settings.backupMuteList),
)
} else {
remove(PrefKeys.LATEST_MUTE_LIST)
}
if (settings.backupPrivateHomeRelayList != null) {
putString(
PrefKeys.LATEST_PRIVATE_HOME_RELAY_LIST,
JsonMapper.mapper.writeValueAsString(settings.backupPrivateHomeRelayList),
)
} else {
remove(PrefKeys.LATEST_PRIVATE_HOME_RELAY_LIST)
}
if (settings.backupAppSpecificData != null) {
putString(
PrefKeys.LATEST_APP_SPECIFIC_DATA,
JsonMapper.mapper.writeValueAsString(settings.backupAppSpecificData),
)
} else {
remove(PrefKeys.LATEST_APP_SPECIFIC_DATA)
}
if (settings.backupChannelList != null) {
putString(
PrefKeys.LATEST_CHANNEL_LIST,
JsonMapper.mapper.writeValueAsString(settings.backupChannelList),
)
} else {
remove(PrefKeys.LATEST_CHANNEL_LIST)
}
if (settings.backupCommunityList != null) {
putString(
PrefKeys.LATEST_COMMUNITY_LIST,
JsonMapper.mapper.writeValueAsString(settings.backupCommunityList),
)
} else {
remove(PrefKeys.LATEST_COMMUNITY_LIST)
}
if (settings.backupHashtagList != null) {
putString(
PrefKeys.LATEST_HASHTAG_LIST,
JsonMapper.mapper.writeValueAsString(settings.backupHashtagList),
)
} else {
remove(PrefKeys.LATEST_HASHTAG_LIST)
}
if (settings.backupGeohashList != null) {
putString(
PrefKeys.LATEST_GEOHASH_LIST,
JsonMapper.mapper.writeValueAsString(settings.backupGeohashList),
)
} else {
remove(PrefKeys.LATEST_GEOHASH_LIST)
}
if (settings.backupEphemeralChatList != null) {
putString(
PrefKeys.LATEST_EPHEMERAL_LIST,
JsonMapper.mapper.writeValueAsString(settings.backupEphemeralChatList),
)
} else {
remove(PrefKeys.LATEST_EPHEMERAL_LIST)
}
putBoolean(PrefKeys.HIDE_DELETE_REQUEST_DIALOG, settings.hideDeleteRequestDialog)
putBoolean(PrefKeys.HIDE_NIP_17_WARNING_DIALOG, settings.hideNIP17WarningDialog)
putBoolean(PrefKeys.HIDE_BLOCK_ALERT_DIALOG, settings.hideBlockAlertDialog)
// migrating from previous design
remove(PrefKeys.USE_PROXY)
remove(PrefKeys.PROXY_PORT)
putString(PrefKeys.TOR_SETTINGS, JsonMapper.mapper.writeValueAsString(settings.torSettings.toSettings()))
val regularMap =
settings.lastReadPerRoute.value.mapValues {
it.value.value
}
putString(
PrefKeys.LAST_READ_PER_ROUTE,
JsonMapper.mapper.writeValueAsString(regularMap),
)
putStringSet(PrefKeys.HAS_DONATED_IN_VERSION, settings.hasDonatedInVersion.value)
putString(
PrefKeys.PENDING_ATTESTATIONS,
JsonMapper.mapper.writeValueAsString(settings.pendingAttestations.value),
)
}
}
}
Log.d("LocalPreferences", "Saved to encrypted storage")
}
suspend fun loadCurrentAccountFromEncryptedStorage(): AccountSettings? = currentAccount()?.let { loadCurrentAccountFromEncryptedStorage(it) }
suspend fun saveSharedSettings(
sharedSettings: Settings,
prefs: SharedPreferences = encryptedPreferences(),
) {
Log.d("LocalPreferences", "Saving to shared settings")
prefs.edit {
putString(PrefKeys.SHARED_SETTINGS, JsonMapper.mapper.writeValueAsString(sharedSettings))
}
}
suspend fun loadSharedSettings(prefs: SharedPreferences = encryptedPreferences()): Settings? {
Log.d("LocalPreferences", "Load shared settings")
with(prefs) {
return try {
getString(PrefKeys.SHARED_SETTINGS, "{}")?.let { JsonMapper.mapper.readValue<Settings>(it) }
} catch (e: Throwable) {
if (e is CancellationException) throw e
Log.w(
"LocalPreferences",
"Unable to decode shared preferences: ${getString(PrefKeys.SHARED_SETTINGS, null)}",
e,
)
null
}
}
}
val mutex = Mutex()
suspend fun loadCurrentAccountFromEncryptedStorage(npub: String): AccountSettings? {
// if already loaded, return right away
if (cachedAccounts.containsKey(npub)) {
return cachedAccounts[npub]
}
return withContext(Dispatchers.IO) {
mutex.withLock {
if (cachedAccounts.containsKey(npub)) {
return@withContext cachedAccounts.get(npub)
}
val accountSettings = innerLoadCurrentAccountFromEncryptedStorage(npub)
cachedAccounts.put(npub, accountSettings)
return@withContext accountSettings
}
}
}
private suspend fun innerLoadCurrentAccountFromEncryptedStorage(npub: String?): AccountSettings? {
Log.d("LocalPreferences", "Load account from file $npub")
val result =
withContext(Dispatchers.IO) {
checkNotInMainThread()
return@withContext with(encryptedPreferences(npub)) {
val privKey = getString(PrefKeys.NOSTR_PRIVKEY, null)
val pubKey = getString(PrefKeys.NOSTR_PUBKEY, null) ?: return@with null
val externalSignerPackageName =
getString(PrefKeys.SIGNER_PACKAGE_NAME, null)
?: if (getBoolean(PrefKeys.LOGIN_WITH_EXTERNAL_SIGNER, false)) "com.greenart7c3.nostrsigner" else null
val defaultHomeFollowList =
getString(PrefKeys.DEFAULT_HOME_FOLLOW_LIST, null) ?: ALL_FOLLOWS
val defaultStoriesFollowList =
getString(PrefKeys.DEFAULT_STORIES_FOLLOW_LIST, null) ?: GLOBAL_FOLLOWS
val defaultNotificationFollowList =
getString(PrefKeys.DEFAULT_NOTIFICATION_FOLLOW_LIST, null) ?: GLOBAL_FOLLOWS
val defaultDiscoveryFollowList =
getString(PrefKeys.DEFAULT_DISCOVERY_FOLLOW_LIST, null) ?: GLOBAL_FOLLOWS
val zapPaymentRequestServer = parseOrNull<Nip47WalletConnect.Nip47URI>(PrefKeys.ZAP_PAYMENT_REQUEST_SERVER)
val defaultFileServer = parseOrNull<ServerName>(PrefKeys.DEFAULT_FILE_SERVER) ?: DEFAULT_MEDIA_SERVERS[0]
val pendingAttestations = parseOrNull<Map<HexKey, String>>(PrefKeys.PENDING_ATTESTATIONS) ?: mapOf()
val localRelayServers = getStringSet(PrefKeys.LOCAL_RELAY_SERVERS, null) ?: setOf()
val latestUserMetadata = parseEventOrNull<MetadataEvent>(PrefKeys.LATEST_USER_METADATA)
val latestContactList = parseEventOrNull<ContactListEvent>(PrefKeys.LATEST_CONTACT_LIST)
val latestDmRelayList = parseEventOrNull<ChatMessageRelayListEvent>(PrefKeys.LATEST_DM_RELAY_LIST)
val latestNip65RelayList = parseEventOrNull<AdvertisedRelayListEvent>(PrefKeys.LATEST_NIP65_RELAY_LIST)
val latestSearchRelayList = parseEventOrNull<SearchRelayListEvent>(PrefKeys.LATEST_SEARCH_RELAY_LIST)
val latestBlockedRelayList = parseEventOrNull<BlockedRelayListEvent>(PrefKeys.LATEST_BLOCKED_RELAY_LIST)
val latestTrustedRelayList = parseEventOrNull<TrustedRelayListEvent>(PrefKeys.LATEST_TRUSTED_RELAY_LIST)
val latestMuteList = parseEventOrNull<MuteListEvent>(PrefKeys.LATEST_MUTE_LIST)
val latestPrivateHomeRelayList = parseEventOrNull<PrivateOutboxRelayListEvent>(PrefKeys.LATEST_PRIVATE_HOME_RELAY_LIST)
val latestAppSpecificData = parseEventOrNull<AppSpecificDataEvent>(PrefKeys.LATEST_APP_SPECIFIC_DATA)
val latestChannelList = parseEventOrNull<ChannelListEvent>(PrefKeys.LATEST_CHANNEL_LIST)
val latestCommunityList = parseEventOrNull<CommunityListEvent>(PrefKeys.LATEST_COMMUNITY_LIST)
val latestHashtagList = parseEventOrNull<HashtagListEvent>(PrefKeys.LATEST_HASHTAG_LIST)
val latestGeohashList = parseEventOrNull<GeohashListEvent>(PrefKeys.LATEST_GEOHASH_LIST)
val latestEphemeralList = parseEventOrNull<EphemeralChatListEvent>(PrefKeys.LATEST_EPHEMERAL_LIST)
val hideDeleteRequestDialog = getBoolean(PrefKeys.HIDE_DELETE_REQUEST_DIALOG, false)
val hideBlockAlertDialog = getBoolean(PrefKeys.HIDE_BLOCK_ALERT_DIALOG, false)
val hideNIP17WarningDialog = getBoolean(PrefKeys.HIDE_NIP_17_WARNING_DIALOG, false)
val torSettings = parseOrNull<TorSettings>(PrefKeys.TOR_SETTINGS) ?: TorSettings()
val lastReadPerRoute =
parseOrNull<Map<String, Long>>(PrefKeys.LAST_READ_PER_ROUTE)?.mapValues {
MutableStateFlow(it.value)
} ?: mapOf()
val keyPair = KeyPair(privKey = privKey?.hexToByteArray(), pubKey = pubKey.hexToByteArray())
val hasDonatedInVersion = getStringSet(PrefKeys.HAS_DONATED_IN_VERSION, null) ?: setOf()
return@with AccountSettings(
keyPair = keyPair,
transientAccount = false,
externalSignerPackageName = externalSignerPackageName,
localRelayServers = MutableStateFlow(localRelayServers),
defaultFileServer = defaultFileServer,
defaultHomeFollowList = MutableStateFlow(defaultHomeFollowList),
defaultStoriesFollowList = MutableStateFlow(defaultStoriesFollowList),
defaultNotificationFollowList = MutableStateFlow(defaultNotificationFollowList),
defaultDiscoveryFollowList = MutableStateFlow(defaultDiscoveryFollowList),
zapPaymentRequest = MutableStateFlow(zapPaymentRequestServer?.normalize()),
hideDeleteRequestDialog = hideDeleteRequestDialog,
hideBlockAlertDialog = hideBlockAlertDialog,
hideNIP17WarningDialog = hideNIP17WarningDialog,
backupUserMetadata = latestUserMetadata,
backupContactList = latestContactList,
backupNIP65RelayList = latestNip65RelayList,
backupDMRelayList = latestDmRelayList,
backupSearchRelayList = latestSearchRelayList,
backupBlockedRelayList = latestBlockedRelayList,
backupTrustedRelayList = latestTrustedRelayList,
backupPrivateHomeRelayList = latestPrivateHomeRelayList,
backupMuteList = latestMuteList,
backupAppSpecificData = latestAppSpecificData,
backupChannelList = latestChannelList,
backupCommunityList = latestCommunityList,
backupHashtagList = latestHashtagList,
backupGeohashList = latestGeohashList,
backupEphemeralChatList = latestEphemeralList,
torSettings = TorSettingsFlow.build(torSettings),
lastReadPerRoute = MutableStateFlow(lastReadPerRoute),
hasDonatedInVersion = MutableStateFlow(hasDonatedInVersion),
pendingAttestations = MutableStateFlow(pendingAttestations),
)
}
}
Log.d("LocalPreferences", "Loaded account from file $npub")
return result
}
private inline fun <reified T> SharedPreferences.parseOrNull(key: String): T? {
val value = getString(key, null)
if (value.isNullOrEmpty() || value == "null") {
return null
}
return try {
if (T::class.java.isInstance(Event::class.java)) {
Event.fromJson(value) as T?
} else {
JsonMapper.mapper.readValue<T?>(value)
}
} catch (e: Throwable) {
if (e is CancellationException) throw e
Log.w("LocalPreferences", "Error Decoding $key from Preferences with value $value", e)
null
}
}
private inline fun <reified T> SharedPreferences.parseEventOrNull(key: String): T? {
val value = getString(key, null)
if (value.isNullOrEmpty() || value == "null") {
return null
}
return try {
Event.fromJson(value) as T?
} catch (e: Throwable) {
if (e is CancellationException) throw e
Log.w("LocalPreferences", "Error Decoding $key from Preferences with value $value", e)
null
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,610 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model
import android.content.ContentResolver
import androidx.compose.runtime.Stable
import com.vitorpamplona.amethyst.ui.actions.mediaServers.DEFAULT_MEDIA_SERVERS
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName
import com.vitorpamplona.amethyst.ui.screen.FeedDefinition
import com.vitorpamplona.amethyst.ui.tor.TorSettings
import com.vitorpamplona.amethyst.ui.tor.TorSettingsFlow
import com.vitorpamplona.quartz.experimental.ephemChat.list.EphemeralChatListEvent
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent
import com.vitorpamplona.quartz.nip17Dm.settings.ChatMessageRelayListEvent
import com.vitorpamplona.quartz.nip28PublicChat.list.ChannelListEvent
import com.vitorpamplona.quartz.nip28PublicChat.list.tags.ChannelTag
import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent
import com.vitorpamplona.quartz.nip37Drafts.privateOutbox.PrivateOutboxRelayListEvent
import com.vitorpamplona.quartz.nip42RelayAuth.RelayAuthEvent
import com.vitorpamplona.quartz.nip47WalletConnect.Nip47WalletConnect
import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent
import com.vitorpamplona.quartz.nip51Lists.geohashList.GeohashListEvent
import com.vitorpamplona.quartz.nip51Lists.hashtagList.HashtagListEvent
import com.vitorpamplona.quartz.nip51Lists.muteList.MuteListEvent
import com.vitorpamplona.quartz.nip51Lists.relayLists.BlockedRelayListEvent
import com.vitorpamplona.quartz.nip51Lists.relayLists.TrustedRelayListEvent
import com.vitorpamplona.quartz.nip55AndroidSigner.api.CommandType
import com.vitorpamplona.quartz.nip55AndroidSigner.api.permission.Permission
import com.vitorpamplona.quartz.nip55AndroidSigner.client.NostrSignerExternal
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListEvent
import com.vitorpamplona.quartz.nip65RelayList.tags.AdvertisedRelayInfo
import com.vitorpamplona.quartz.nip65RelayList.tags.AdvertisedRelayType
import com.vitorpamplona.quartz.nip72ModCommunities.follow.CommunityListEvent
import com.vitorpamplona.quartz.nip78AppData.AppSpecificDataEvent
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.update
import java.util.Locale
val DefaultChannels =
listOf(
// Anigma's Nostr
ChannelTag("25e5c82273a271cb1a840d0060391a0bf4965cafeb029d5ab55350b418953fbb", Constants.nos),
// Amethyst's Group
ChannelTag("42224859763652914db53052103f0b744df79dfc4efef7e950fc0802fc3df3c5", Constants.nos),
)
val DefaultNIP65RelaySet = setOf(Constants.mom, Constants.nos, Constants.bitcoiner)
val DefaultNIP65List =
listOf(
AdvertisedRelayInfo(Constants.mom, AdvertisedRelayType.BOTH),
AdvertisedRelayInfo(Constants.nos, AdvertisedRelayType.BOTH),
AdvertisedRelayInfo(Constants.bitcoiner, AdvertisedRelayType.BOTH),
)
val DefaultDMRelayList = listOf(Constants.auth, Constants.oxchat, Constants.nos)
val DefaultSearchRelayList = setOf(Constants.band, Constants.wine, Constants.where, Constants.nostoday)
val DefaultIndexerRelayList = setOf(Constants.purplepages, Constants.coracle, Constants.userkinds)
val DefaultSignerPermissions =
listOf(
Permission(CommandType.SIGN_EVENT, RelayAuthEvent.KIND),
Permission(CommandType.SIGN_EVENT, DraftWrapEvent.KIND),
Permission(CommandType.NIP04_ENCRYPT),
Permission(CommandType.NIP04_DECRYPT),
Permission(CommandType.NIP44_DECRYPT),
Permission(CommandType.NIP44_DECRYPT),
Permission(CommandType.DECRYPT_ZAP_EVENT),
)
// This has spaces to avoid mixing with a potential NIP-51 list with the same name.
val GLOBAL_FOLLOWS = " Global "
// This has spaces to avoid mixing with a potential NIP-51 list with the same name.
val ALL_FOLLOWS = " All Follows "
// This has spaces to avoid mixing with a potential NIP-51 list with the same name.
val AROUND_ME = " Around Me "
@Stable
class AccountSettings(
val keyPair: KeyPair,
val transientAccount: Boolean = false,
var externalSignerPackageName: String? = null,
var localRelayServers: MutableStateFlow<Set<String>> = MutableStateFlow(setOf()),
var defaultFileServer: ServerName = DEFAULT_MEDIA_SERVERS[0],
val defaultHomeFollowList: MutableStateFlow<String> = MutableStateFlow(ALL_FOLLOWS),
val defaultStoriesFollowList: MutableStateFlow<String> = MutableStateFlow(GLOBAL_FOLLOWS),
val defaultNotificationFollowList: MutableStateFlow<String> = MutableStateFlow(GLOBAL_FOLLOWS),
val defaultDiscoveryFollowList: MutableStateFlow<String> = MutableStateFlow(GLOBAL_FOLLOWS),
var zapPaymentRequest: MutableStateFlow<Nip47WalletConnect.Nip47URINorm?> = MutableStateFlow(null),
var hideDeleteRequestDialog: Boolean = false,
var hideBlockAlertDialog: Boolean = false,
var hideNIP17WarningDialog: Boolean = false,
var backupUserMetadata: MetadataEvent? = null,
var backupContactList: ContactListEvent? = null,
var backupDMRelayList: ChatMessageRelayListEvent? = null,
var backupNIP65RelayList: AdvertisedRelayListEvent? = null,
var backupSearchRelayList: SearchRelayListEvent? = null,
var backupBlockedRelayList: BlockedRelayListEvent? = null,
var backupTrustedRelayList: TrustedRelayListEvent? = null,
var backupMuteList: MuteListEvent? = null,
var backupPrivateHomeRelayList: PrivateOutboxRelayListEvent? = null,
var backupAppSpecificData: AppSpecificDataEvent? = null,
var backupChannelList: ChannelListEvent? = null,
var backupCommunityList: CommunityListEvent? = null,
var backupHashtagList: HashtagListEvent? = null,
var backupGeohashList: GeohashListEvent? = null,
var backupEphemeralChatList: EphemeralChatListEvent? = null,
val torSettings: TorSettingsFlow = TorSettingsFlow(),
val lastReadPerRoute: MutableStateFlow<Map<String, MutableStateFlow<Long>>> = MutableStateFlow(mapOf()),
var hasDonatedInVersion: MutableStateFlow<Set<String>> = MutableStateFlow(setOf<String>()),
val pendingAttestations: MutableStateFlow<Map<HexKey, String>> = MutableStateFlow<Map<HexKey, String>>(mapOf()),
) {
val saveable = MutableStateFlow(AccountSettingsUpdater(null))
val syncedSettings: AccountSyncedSettings = AccountSyncedSettings(AccountSyncedSettingsInternal())
class AccountSettingsUpdater(
val accountSettings: AccountSettings?,
)
fun saveAccountSettings() {
saveable.update { AccountSettingsUpdater(this) }
}
fun isWriteable(): Boolean = keyPair.privKey != null || externalSignerPackageName != null
fun createSigner(contentResolver: ContentResolver) =
if (keyPair.privKey != null) {
NostrSignerInternal(keyPair)
} else {
when (val packageName = externalSignerPackageName) {
null -> NostrSignerInternal(keyPair)
else ->
NostrSignerExternal(
pubKey = keyPair.pubKey.toHexKey(),
packageName = packageName,
contentResolver = contentResolver,
)
}
}
// ---
// Zaps and Reactions
// ---
fun changeDefaultZapType(zapType: LnZapEvent.ZapType): Boolean {
if (syncedSettings.zaps.defaultZapType.value != zapType) {
syncedSettings.zaps.defaultZapType.tryEmit(zapType)
saveAccountSettings()
return true
}
return false
}
fun changeZapAmounts(newAmounts: List<Long>): Boolean {
if (syncedSettings.zaps.zapAmountChoices.value != newAmounts) {
syncedSettings.zaps.zapAmountChoices.tryEmit(newAmounts.toImmutableList())
saveAccountSettings()
return true
}
return false
}
fun changeReactionTypes(newTypes: List<String>): Boolean {
if (syncedSettings.reactions.reactionChoices.value != newTypes) {
syncedSettings.reactions.reactionChoices.tryEmit(newTypes.toImmutableList())
saveAccountSettings()
return true
}
return false
}
fun changeZapPaymentRequest(newServer: Nip47WalletConnect.Nip47URINorm?): Boolean {
if (zapPaymentRequest.value != newServer) {
zapPaymentRequest.tryEmit(newServer)
saveAccountSettings()
return true
}
return false
}
// ---
// file servers
// ---
fun changeDefaultFileServer(server: ServerName) {
if (defaultFileServer != server) {
defaultFileServer = server
saveAccountSettings()
}
}
// ---
// list names
// ---
fun changeDefaultHomeFollowList(name: FeedDefinition) {
changeDefaultHomeFollowList(name.code)
}
fun changeDefaultHomeFollowList(name: String) {
if (defaultHomeFollowList.value != name) {
defaultHomeFollowList.tryEmit(name)
saveAccountSettings()
}
}
fun changeDefaultStoriesFollowList(name: FeedDefinition) {
changeDefaultStoriesFollowList(name.code)
}
fun changeDefaultStoriesFollowList(name: String) {
if (defaultStoriesFollowList.value != name) {
defaultStoriesFollowList.tryEmit(name)
saveAccountSettings()
}
}
fun changeDefaultNotificationFollowList(name: FeedDefinition) {
changeDefaultNotificationFollowList(name.code)
}
fun changeDefaultNotificationFollowList(name: String) {
if (defaultNotificationFollowList.value != name) {
defaultNotificationFollowList.tryEmit(name)
saveAccountSettings()
}
}
fun changeDefaultDiscoveryFollowList(name: FeedDefinition) {
changeDefaultDiscoveryFollowList(name.code)
}
fun changeDefaultDiscoveryFollowList(name: String) {
if (defaultDiscoveryFollowList.value != name) {
defaultDiscoveryFollowList.tryEmit(name)
saveAccountSettings()
}
}
// ---
// proxy settings
// ---
fun setTorSettings(newTorSettings: TorSettings): Boolean =
if (torSettings.update(newTorSettings)) {
saveAccountSettings()
true
} else {
false
}
// ---
// language services
// ---
fun toggleDontTranslateFrom(languageCode: String) {
syncedSettings.languages.toggleDontTranslateFrom(languageCode)
saveAccountSettings()
}
fun translateToContains(languageCode: Locale) = syncedSettings.languages.translateTo.contains(languageCode.language)
fun updateTranslateTo(languageCode: Locale): Boolean {
if (syncedSettings.languages.updateTranslateTo(languageCode)) {
saveAccountSettings()
return true
}
return false
}
fun prefer(
source: String,
target: String,
preference: String,
) {
syncedSettings.languages.prefer(source, target, preference)
saveAccountSettings()
}
fun preferenceBetween(
source: String,
target: String,
): String? = syncedSettings.languages.preferenceBetween(source, target)
// ----
// Backup Lists
// ----
fun updateLocalRelayServers(servers: Set<String>) {
if (localRelayServers.value != servers) {
localRelayServers.update { servers }
saveAccountSettings()
}
}
fun updateUserMetadata(newMetadata: MetadataEvent?) {
if (newMetadata == null) return
// Events might be different objects, we have to compare their ids.
if (backupUserMetadata?.id != newMetadata.id) {
backupUserMetadata = newMetadata
saveAccountSettings()
}
}
fun updateContactListTo(newContactList: ContactListEvent?) {
if (newContactList == null || newContactList.tags.isEmpty()) return
// Events might be different objects, we have to compare their ids.
if (backupContactList?.id != newContactList.id) {
backupContactList = newContactList
saveAccountSettings()
}
}
fun updateDMRelayList(newDMRelayList: ChatMessageRelayListEvent?) {
if (newDMRelayList == null || newDMRelayList.tags.isEmpty()) return
// Events might be different objects, we have to compare their ids.
if (backupDMRelayList?.id != newDMRelayList.id) {
backupDMRelayList = newDMRelayList
saveAccountSettings()
}
}
fun updateNIP65RelayList(newNIP65RelayList: AdvertisedRelayListEvent?) {
if (newNIP65RelayList == null || newNIP65RelayList.tags.isEmpty()) return
// Events might be different objects, we have to compare their ids.
if (backupNIP65RelayList?.id != newNIP65RelayList.id) {
backupNIP65RelayList = newNIP65RelayList
saveAccountSettings()
}
}
fun updateSearchRelayList(newSearchRelayList: SearchRelayListEvent?) {
if (newSearchRelayList == null || newSearchRelayList.tags.isEmpty()) return
// Events might be different objects, we have to compare their ids.
if (backupSearchRelayList?.id != newSearchRelayList.id) {
backupSearchRelayList = newSearchRelayList
saveAccountSettings()
}
}
fun updateBlockedRelayList(newBlockedRelayList: BlockedRelayListEvent?) {
if (newBlockedRelayList == null || newBlockedRelayList.tags.isEmpty()) return
// Events might be different objects, we have to compare their ids.
if (backupBlockedRelayList?.id != newBlockedRelayList.id) {
backupBlockedRelayList = newBlockedRelayList
saveAccountSettings()
}
}
fun updateTrustedRelayList(newTrustedRelayList: TrustedRelayListEvent?) {
if (newTrustedRelayList == null || newTrustedRelayList.tags.isEmpty()) return
// Events might be different objects, we have to compare their ids.
if (backupTrustedRelayList?.id != newTrustedRelayList.id) {
backupTrustedRelayList = newTrustedRelayList
saveAccountSettings()
}
}
fun updatePrivateHomeRelayList(newPrivateHomeRelayList: PrivateOutboxRelayListEvent?) {
if (newPrivateHomeRelayList == null || newPrivateHomeRelayList.tags.isEmpty()) return
// Events might be different objects, we have to compare their ids.
if (backupPrivateHomeRelayList?.id != newPrivateHomeRelayList.id) {
backupPrivateHomeRelayList = newPrivateHomeRelayList
saveAccountSettings()
}
}
fun updateChannelListTo(newChannelList: ChannelListEvent?) {
if (newChannelList == null || newChannelList.tags.isEmpty()) return
// Events might be different objects, we have to compare their ids.
if (backupChannelList?.id != newChannelList.id) {
backupChannelList = newChannelList
saveAccountSettings()
}
}
fun updateGeohashListTo(newGeohashList: GeohashListEvent?) {
if (newGeohashList == null || newGeohashList.tags.isEmpty()) return
// Events might be different objects, we have to compare their ids.
if (backupGeohashList?.id != newGeohashList.id) {
backupGeohashList = newGeohashList
saveAccountSettings()
}
}
fun updateHashtagListTo(newHashtagList: HashtagListEvent?) {
if (newHashtagList == null || newHashtagList.tags.isEmpty()) return
// Events might be different objects, we have to compare their ids.
if (backupHashtagList?.id != newHashtagList.id) {
backupHashtagList = newHashtagList
saveAccountSettings()
}
}
fun updateCommunityListTo(newCommunityList: CommunityListEvent?) {
if (newCommunityList == null || newCommunityList.tags.isEmpty()) return
// Events might be different objects, we have to compare their ids.
if (backupCommunityList?.id != newCommunityList.id) {
backupCommunityList = newCommunityList
saveAccountSettings()
}
}
fun updateEphemeralChatListTo(newEphemeralChatList: EphemeralChatListEvent?) {
if (newEphemeralChatList == null || newEphemeralChatList.tags.isEmpty()) return
// Events might be different objects, we have to compare their ids.
if (backupEphemeralChatList?.id != newEphemeralChatList.id) {
backupEphemeralChatList = newEphemeralChatList
saveAccountSettings()
}
}
fun updateMuteList(newMuteList: MuteListEvent?) {
if (newMuteList == null || newMuteList.tags.isEmpty()) return
// Events might be different objects, we have to compare their ids.
if (backupMuteList?.id != newMuteList.id) {
backupMuteList = newMuteList
saveAccountSettings()
}
}
fun updateAppSpecificData(
appSettings: AppSpecificDataEvent?,
newSyncedSettings: AccountSyncedSettingsInternal,
) {
if (appSettings == null || appSettings.content.isEmpty()) return
// Events might be different objects, we have to compare their ids.
if (backupAppSpecificData?.id != appSettings.id) {
backupAppSpecificData = appSettings
syncedSettings.updateFrom(newSyncedSettings)
saveAccountSettings()
}
}
// ----
// Warning dialogs
// ----
fun setHideDeleteRequestDialog() {
if (!hideDeleteRequestDialog) {
hideDeleteRequestDialog = true
saveAccountSettings()
}
}
fun setHideNIP17WarningDialog() {
if (!hideNIP17WarningDialog) {
hideNIP17WarningDialog = true
saveAccountSettings()
}
}
fun setHideBlockAlertDialog() {
if (!hideBlockAlertDialog) {
hideBlockAlertDialog = true
saveAccountSettings()
}
}
// ---
// donations
// ---
fun hasDonatedInVersion(versionName: String) = hasDonatedInVersion.value.contains(versionName)
fun observeDonatedInVersion(versionName: String) =
hasDonatedInVersion
.map {
it.contains(versionName)
}
fun markDonatedInThisVersion(versionName: String): Boolean {
if (!hasDonatedInVersion.value.contains(versionName)) {
hasDonatedInVersion.update {
it + versionName
}
saveAccountSettings()
return true
}
return false
}
// ----
// last read flows
// ----
fun getLastReadFlow(route: String): StateFlow<Long> = lastReadPerRoute.value[route] ?: addLastRead(route, 0)
private fun addLastRead(
route: String,
timestampInSecs: Long,
): MutableStateFlow<Long> =
MutableStateFlow<Long>(timestampInSecs).also { newFlow ->
lastReadPerRoute.update { it + Pair(route, newFlow) }
saveAccountSettings()
}
fun markAsRead(
route: String,
timestampInSecs: Long,
): Boolean {
val lastTime = lastReadPerRoute.value[route]
return if (lastTime == null) {
addLastRead(route, timestampInSecs)
true
} else if (timestampInSecs > lastTime.value) {
lastTime.tryEmit(timestampInSecs)
saveAccountSettings()
true
} else {
false
}
}
// ---
// attestations
// ---
fun addPendingAttestation(
id: HexKey,
stamp: String,
) {
val current = pendingAttestations.value.get(id)
if (current == null) {
pendingAttestations.update {
it + Pair(id, stamp)
}
saveAccountSettings()
} else {
if (current != stamp) {
pendingAttestations.update {
it + Pair(id, stamp)
}
saveAccountSettings()
}
}
}
// ---
// filters
// ---
fun updateShowSensitiveContent(show: Boolean?): Boolean {
if (syncedSettings.security.updateShowSensitiveContent(show)) {
saveAccountSettings()
return true
}
return false
}
fun updateWarnReports(warnReports: Boolean): Boolean =
if (syncedSettings.security.updateWarnReports(warnReports)) {
saveAccountSettings()
true
} else {
false
}
fun updateFilterSpam(filterSpam: Boolean): Boolean =
if (syncedSettings.security.updateFilterSpam(filterSpam)) {
saveAccountSettings()
true
} else {
false
}
}

View File

@@ -0,0 +1,211 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model
import androidx.compose.runtime.Stable
import com.vitorpamplona.amethyst.ui.screen.loggedIn.notifications.equalImmutableLists
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.update
import java.util.Locale
@Stable
class AccountSyncedSettings(
internalSettings: AccountSyncedSettingsInternal,
) {
val reactions = AccountReactionPreferences(MutableStateFlow(internalSettings.reactions.reactionChoices.toImmutableList()))
val zaps =
AccountZapPreferences(
MutableStateFlow(internalSettings.zaps.zapAmountChoices.toImmutableList()),
MutableStateFlow(internalSettings.zaps.defaultZapType),
)
val languages =
AccountLanguagePreferences(
internalSettings.languages.dontTranslateFrom,
internalSettings.languages.languagePreferences,
internalSettings.languages.translateTo,
)
val security =
AccountSecurityPreferences(
MutableStateFlow(internalSettings.security.showSensitiveContent),
internalSettings.security.warnAboutPostsWithReports,
MutableStateFlow(internalSettings.security.filterSpamFromStrangers),
)
fun toInternal(): AccountSyncedSettingsInternal =
AccountSyncedSettingsInternal(
reactions = AccountReactionPreferencesInternal(reactions.reactionChoices.value),
zaps =
AccountZapPreferencesInternal(
zaps.zapAmountChoices.value,
zaps.defaultZapType.value,
),
languages =
AccountLanguagePreferencesInternal(
languages.dontTranslateFrom,
languages.languagePreferences,
languages.translateTo,
),
security =
AccountSecurityPreferencesInternal(
security.showSensitiveContent.value,
security.warnAboutPostsWithReports,
security.filterSpamFromStrangers.value,
),
)
fun updateFrom(syncedSettingsInternal: AccountSyncedSettingsInternal) {
val newReactionChoices = syncedSettingsInternal.reactions.reactionChoices.toImmutableList()
if (!equalImmutableLists(reactions.reactionChoices.value, newReactionChoices)) {
reactions.reactionChoices.tryEmit(newReactionChoices)
}
val newZapChoices = syncedSettingsInternal.zaps.zapAmountChoices.toImmutableList()
if (!equalImmutableLists(zaps.zapAmountChoices.value, newZapChoices)) {
zaps.zapAmountChoices.tryEmit(newZapChoices)
}
if (zaps.defaultZapType.value != syncedSettingsInternal.zaps.defaultZapType) {
zaps.defaultZapType.tryEmit(syncedSettingsInternal.zaps.defaultZapType)
}
if (languages.dontTranslateFrom != syncedSettingsInternal.languages.dontTranslateFrom) {
languages.dontTranslateFrom = syncedSettingsInternal.languages.dontTranslateFrom
}
if (languages.languagePreferences != syncedSettingsInternal.languages.languagePreferences) {
languages.languagePreferences = syncedSettingsInternal.languages.languagePreferences
}
if (languages.translateTo != syncedSettingsInternal.languages.translateTo) {
languages.translateTo = syncedSettingsInternal.languages.translateTo
}
if (security.showSensitiveContent.value != syncedSettingsInternal.security.showSensitiveContent) {
security.showSensitiveContent.tryEmit(syncedSettingsInternal.security.showSensitiveContent)
}
if (security.filterSpamFromStrangers.value != syncedSettingsInternal.security.filterSpamFromStrangers) {
security.filterSpamFromStrangers.tryEmit(syncedSettingsInternal.security.filterSpamFromStrangers)
}
if (security.warnAboutPostsWithReports != syncedSettingsInternal.security.warnAboutPostsWithReports) {
security.warnAboutPostsWithReports = syncedSettingsInternal.security.warnAboutPostsWithReports
}
}
fun dontTranslateFromFilteredBySpokenLanguages(): Set<String> = languages.dontTranslateFrom - getLanguagesSpokenByUser()
}
@Stable
class AccountReactionPreferences(
var reactionChoices: MutableStateFlow<ImmutableList<String>>,
)
@Stable
class AccountZapPreferences(
var zapAmountChoices: MutableStateFlow<ImmutableList<Long>>,
val defaultZapType: MutableStateFlow<LnZapEvent.ZapType>,
)
@Stable
class AccountLanguagePreferences(
var dontTranslateFrom: Set<String>,
var languagePreferences: Map<String, String>,
var translateTo: String,
) {
// ---
// language services
// ---
fun toggleDontTranslateFrom(languageCode: String) {
dontTranslateFrom =
if (!dontTranslateFrom.contains(languageCode)) {
dontTranslateFrom.plus(languageCode)
} else {
dontTranslateFrom.minus(languageCode)
}
}
fun translateToContains(languageCode: Locale) = translateTo.contains(languageCode.language)
fun updateTranslateTo(languageCode: Locale): Boolean {
if (translateTo != languageCode.language) {
translateTo = languageCode.language
return true
}
return false
}
fun prefer(
source: String,
target: String,
preference: String,
) {
val key = "$source,$target"
if (key !in languagePreferences) {
languagePreferences = languagePreferences + Pair(key, preference)
} else {
if (languagePreferences.get(key) == preference) {
languagePreferences = languagePreferences.minus(key)
} else {
languagePreferences = languagePreferences + Pair(key, preference)
}
}
}
fun preferenceBetween(
source: String,
target: String,
): String? = languagePreferences["$source,$target"]
}
@Stable
class AccountSecurityPreferences(
val showSensitiveContent: MutableStateFlow<Boolean?> = MutableStateFlow(null),
var warnAboutPostsWithReports: Boolean = true,
var filterSpamFromStrangers: MutableStateFlow<Boolean> = MutableStateFlow(true),
) {
fun updateShowSensitiveContent(show: Boolean?): Boolean {
if (showSensitiveContent.value != show) {
showSensitiveContent.update { show }
return true
}
return false
}
fun updateWarnReports(warnReports: Boolean): Boolean =
if (warnAboutPostsWithReports != warnReports) {
warnAboutPostsWithReports = warnReports
true
} else {
false
}
fun updateFilterSpam(filterSpam: Boolean): Boolean =
if (filterSpam != filterSpamFromStrangers.value) {
filterSpamFromStrangers.tryEmit(filterSpam)
true
} else {
false
}
}

View File

@@ -0,0 +1,76 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model
import android.content.res.Resources
import androidx.core.os.ConfigurationCompat
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
import java.util.Locale
val DefaultReactions =
listOf(
"\uD83D\uDE80",
"\uD83E\uDEC2",
"\uD83D\uDC40",
"\uD83D\uDE02",
"\uD83C\uDF89",
"\uD83E\uDD14",
"\uD83D\uDE31",
)
val DefaultZapAmounts = listOf(100L, 500L, 1000L)
fun getLanguagesSpokenByUser(): Set<String> {
val languageList = ConfigurationCompat.getLocales(Resources.getSystem().getConfiguration())
val codedList = mutableSetOf<String>()
for (i in 0 until languageList.size()) {
languageList.get(i)?.let { codedList.add(it.language) }
}
return codedList
}
class AccountSyncedSettingsInternal(
val reactions: AccountReactionPreferencesInternal = AccountReactionPreferencesInternal(),
val zaps: AccountZapPreferencesInternal = AccountZapPreferencesInternal(),
val languages: AccountLanguagePreferencesInternal = AccountLanguagePreferencesInternal(),
val security: AccountSecurityPreferencesInternal = AccountSecurityPreferencesInternal(),
)
class AccountReactionPreferencesInternal(
var reactionChoices: List<String> = DefaultReactions,
)
class AccountZapPreferencesInternal(
var zapAmountChoices: List<Long> = DefaultZapAmounts,
val defaultZapType: LnZapEvent.ZapType = LnZapEvent.ZapType.PUBLIC,
)
class AccountLanguagePreferencesInternal(
var dontTranslateFrom: Set<String> = getLanguagesSpokenByUser(),
var languagePreferences: Map<String, String> = mapOf(),
var translateTo: String = Locale.getDefault().language,
)
class AccountSecurityPreferencesInternal(
val showSensitiveContent: Boolean? = null,
var warnAboutPostsWithReports: Boolean = true,
var filterSpamFromStrangers: Boolean = true,
)

View File

@@ -0,0 +1,175 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model
import android.util.Log
import android.util.LruCache
import com.vitorpamplona.amethyst.ui.note.njumpLink
import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.relay.client.stats.RelayStats
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address
import com.vitorpamplona.quartz.nip19Bech32.Nip19Parser
import com.vitorpamplona.quartz.nip19Bech32.entities.NAddress
import com.vitorpamplona.quartz.nip19Bech32.entities.NEvent
import kotlinx.coroutines.flow.MutableStateFlow
data class Spammer(
val pubkeyHex: HexKey,
var duplicatedEventIds: Set<HexKey>,
var duplicatedEventAddresses: Set<Address>,
) {
fun shouldHide() = duplicatedEventIds.size >= 5 || duplicatedEventAddresses.size >= 5
}
class AntiSpamFilter {
val recentEventIds = LruCache<Int, String>(2000)
val recentAddressables = LruCache<Int, Address>(2000)
val spamMessages = LruCache<Int, Spammer>(1000)
var active: Boolean = true
fun spamHashCode(event: Event): Int = 31 * event.content.hashCode() + event.tags.contentDeepHashCode()
fun isSpam(
event: Event,
relay: NormalizedRelayUrl?,
): Boolean {
if (!active) return false
// if short message, ok
// The idea here is to avoid considering repeated "GM" messages spam.
if (event.content.length < 60) return false
// if the message is actually short but because it cites a user/event, the nostr: string is
// really long, make it ok.
// The idea here is to avoid considering repeated "@Bot, command" messages spam, while still
// blocking repeated "lnbc..." invoices or fishing urls
if (event.content.length < 180 && event.content.startsWith("nostr:") && Nip19Parser.nip19regex.matcher(event.content).find()) return false
// double list strategy:
// if duplicated, it goes into spam. 1000 spam messages are saved into the spam list.
// Considers tags so that same replies to different people don't count.
val hash = spamHashCode(event)
// ignores multiple versions of the same addressable.
if (event is AddressableEvent) {
val address = event.address()
// normal event
if (
(recentAddressables[hash] != null && recentAddressables[hash] != address) ||
(spamMessages[hash] != null && !spamMessages[hash].duplicatedEventAddresses.contains(address))
) {
val existingAddress = recentAddressables[hash]
val link1 = njumpLink(NAddress.create(existingAddress.kind, existingAddress.pubKeyHex, existingAddress.dTag, relay))
val link2 = njumpLink(NAddress.create(event.kind, event.pubKey, event.dTag(), relay))
Log.w("Duplicated/SPAM", "${relay?.url} $link1 $link2")
// Log down offenders
val spammer = logOffender(hash, event)
if (spammer.shouldHide() && relay != null) {
RelayStats.newSpam(relay, "$link1 $link2")
}
flowSpam.tryEmit(AntiSpamState(this))
return true
}
recentAddressables.put(hash, address)
} else {
// normal event
if (
(recentEventIds[hash] != null && recentEventIds[hash] != event.id) ||
(spamMessages[hash] != null && !spamMessages[hash].duplicatedEventIds.contains(event.id))
) {
val existingEvent = recentEventIds[hash]
val link1 = njumpLink(NEvent.create(existingEvent, null, null, relay))
val link2 = njumpLink(NEvent.create(event.id, null, null, relay))
Log.w("Duplicated/SPAM", "${relay?.url} $link1 $link2")
// Log down offenders
val spammer = logOffender(hash, event)
if (spammer.shouldHide() && relay != null) {
RelayStats.newSpam(relay, "$link1 $link2")
}
flowSpam.tryEmit(AntiSpamState(this))
return true
}
recentEventIds.put(hash, event.id)
}
return false
}
@Synchronized
private fun logOffender(
hashCode: Int,
event: Event,
): Spammer {
val spammer = spamMessages.get(hashCode)
if (spammer == null) {
val newSpammer =
if (event is AddressableEvent) {
Spammer(
pubkeyHex = event.pubKey,
duplicatedEventIds = setOf(),
duplicatedEventAddresses = setOf(recentAddressables[hashCode], event.address()),
)
} else {
Spammer(
pubkeyHex = event.pubKey,
duplicatedEventIds = setOf(recentEventIds[hashCode], event.id),
duplicatedEventAddresses = setOf(),
)
}
spamMessages.put(hashCode, newSpammer)
return newSpammer
} else {
if (event is AddressableEvent) {
spammer.duplicatedEventAddresses += event.address()
} else {
spammer.duplicatedEventIds += event.id
}
return spammer
}
}
val flowSpam = MutableStateFlow<AntiSpamState>(AntiSpamState(this))
}
class AntiSpamState(
val cache: AntiSpamFilter,
)

View File

@@ -0,0 +1,213 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model
import androidx.compose.runtime.Stable
import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder
import com.vitorpamplona.amethyst.ui.dal.ListChange
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.utils.LargeCache
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import java.lang.ref.WeakReference
@Stable
abstract class Channel : NotesGatherer {
val notes = LargeCache<HexKey, Note>()
var lastNote: Note? = null
private var relays = mapOf<NormalizedRelayUrl, Counter>()
private var changesFlow: WeakReference<MutableSharedFlow<ListChange<Note>>> = WeakReference(null)
fun changesFlow(): MutableSharedFlow<ListChange<Note>> {
val current = changesFlow.get()
if (current != null) return current
val new = MutableSharedFlow<ListChange<Note>>(0, 100, BufferOverflow.DROP_OLDEST)
changesFlow = WeakReference(new)
return new
}
abstract fun toBestDisplayName(): String
open fun relays(): Set<NormalizedRelayUrl> =
relays.keys
.toSortedSet { o1, o2 ->
val o1Count = relays[o1]?.number ?: 0
val o2Count = relays[o2]?.number ?: 0
o2Count.compareTo(o1Count) // descending
}
fun updateChannelInfo() {
flowSet?.metadata?.invalidateData()
}
@Synchronized
fun addRelaySync(briefInfo: NormalizedRelayUrl) {
if (briefInfo !in relays) {
relays = relays + Pair(briefInfo, Counter(1))
}
}
fun addRelay(relay: NormalizedRelayUrl) {
val counter = relays[relay]
if (counter != null) {
counter.number++
} else {
addRelaySync(relay)
}
}
fun addNote(
note: Note,
relay: NormalizedRelayUrl? = null,
) {
if (!notes.containsKey(note.idHex)) {
notes.put(note.idHex, note)
note.addGatherer(this)
if ((note.createdAt() ?: 0) > (lastNote?.createdAt() ?: 0)) {
lastNote = note
}
if (relay != null) {
addRelay(relay)
}
changesFlow.get()?.tryEmit(ListChange.Addition(note))
flowSet?.notes?.invalidateData()
}
}
override fun removeNote(note: Note) {
if (notes.containsKey(note.idHex)) {
notes.remove(note.idHex)
note.removeGatherer(this)
if (note == lastNote) {
lastNote = notes.values().sortedWith(DefaultFeedOrder).firstOrNull()
}
changesFlow.get()?.tryEmit(ListChange.Deletion(note))
flowSet?.notes?.invalidateData()
}
}
fun pruneOldMessages(): Set<Note> {
val important =
notes
.values()
.sortedWith(DefaultFeedOrder)
.take(500)
.toSet()
val toBeRemoved = notes.filter { key, it -> it !in important }
toBeRemoved.forEach { notes.remove(it.idHex) }
changesFlow.get()?.tryEmit(ListChange.SetDeletion(toBeRemoved.toSet()))
flowSet?.notes?.invalidateData()
return toBeRemoved.toSet()
}
fun pruneHiddenMessages(account: Account): Set<Note> {
val hidden =
notes
.filter { key, it ->
it.author?.let { author -> account.isHidden(author) } == true
}.toSet()
hidden.forEach { notes.remove(it.idHex) }
changesFlow.get()?.tryEmit(ListChange.SetDeletion(hidden))
flowSet?.notes?.invalidateData()
return hidden.toSet()
}
var flowSet: ChannelFlowSet? = null
@Synchronized
fun createOrDestroyFlowSync(create: Boolean) {
if (create) {
if (flowSet == null) {
flowSet = ChannelFlowSet(this)
}
} else {
if (flowSet != null && flowSet?.isInUse() == false) {
flowSet = null
}
}
}
fun flow(): ChannelFlowSet {
if (flowSet == null) {
createOrDestroyFlowSync(true)
}
return flowSet!!
}
fun clearFlow() {
if (flowSet != null && flowSet?.isInUse() == false) {
createOrDestroyFlowSync(false)
}
}
}
data class Counter(
var number: Int = 0,
)
@Stable
class ChannelFlowSet(
u: Channel,
) {
// Observers line up here.
val metadata = ChannelFlow(u)
val notes = ChannelFlow(u)
fun isInUse(): Boolean =
metadata.hasObservers() ||
notes.hasObservers()
}
class ChannelFlow(
val channel: Channel,
) {
val stateFlow = MutableStateFlow(ChannelState(channel))
fun invalidateData() {
stateFlow.tryEmit(ChannelState(channel))
}
fun hasObservers() = stateFlow.subscriptionCount.value > 0
}
class ChannelState(
val channel: Channel,
)

View File

@@ -0,0 +1,52 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.RelayUrlNormalizer
object Constants {
val nos = RelayUrlNormalizer.normalize("wss://nos.lol")
val mom = RelayUrlNormalizer.normalize("wss://nostr.mom")
val primal = RelayUrlNormalizer.normalize("wss://relay.primal.net")
val damus = RelayUrlNormalizer.normalize("wss://relay.damus.io")
val wine = RelayUrlNormalizer.normalize("wss://nostr.wine")
val band = RelayUrlNormalizer.normalize("wss://relay.nostr.band")
val where = RelayUrlNormalizer.normalize("wss://relay.noswhere.com")
val elites = RelayUrlNormalizer.normalize("wss://nostrelites.org")
val bitcoiner = RelayUrlNormalizer.normalize("wss://nostr.bitcoiner.social")
val oxtr = RelayUrlNormalizer.normalize("wss://nostr.oxtr.dev")
val fmtwiz = RelayUrlNormalizer.normalize("wss://nostr.fmt.wiz.biz")
val nostoday = RelayUrlNormalizer.normalize("wss://search.nos.today")
val auth = RelayUrlNormalizer.normalize("wss://auth.nostr1.com")
val oxchat = RelayUrlNormalizer.normalize("wss://relay.0xchat.com")
val purplepages = RelayUrlNormalizer.normalize("wss://purplepag.es")
val coracle = RelayUrlNormalizer.normalize("wss://indexer.coracle.social")
val userkinds = RelayUrlNormalizer.normalize("wss://user.kindpag.es")
val eventFinderRelays = setOf(band, wine, damus, primal, mom, nos, bitcoiner, oxtr, fmtwiz)
val defaultSearchRelaySet = setOf(band, wine, where)
}

View File

@@ -0,0 +1,117 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.commons.hashtags.Amethyst
import com.vitorpamplona.amethyst.commons.hashtags.Btc
import com.vitorpamplona.amethyst.commons.hashtags.Cashu
import com.vitorpamplona.amethyst.commons.hashtags.Coffee
import com.vitorpamplona.amethyst.commons.hashtags.CustomHashTagIcons
import com.vitorpamplona.amethyst.commons.hashtags.Flowerstr
import com.vitorpamplona.amethyst.commons.hashtags.Footstr
import com.vitorpamplona.amethyst.commons.hashtags.Gamestr
import com.vitorpamplona.amethyst.commons.hashtags.Grownostr
import com.vitorpamplona.amethyst.commons.hashtags.Lightning
import com.vitorpamplona.amethyst.commons.hashtags.Mate
import com.vitorpamplona.amethyst.commons.hashtags.Nostr
import com.vitorpamplona.amethyst.commons.hashtags.Plebs
import com.vitorpamplona.amethyst.commons.hashtags.Skull
import com.vitorpamplona.amethyst.commons.hashtags.Tunestr
import com.vitorpamplona.amethyst.commons.hashtags.Weed
import com.vitorpamplona.amethyst.commons.hashtags.Zap
import com.vitorpamplona.amethyst.commons.richtext.HashTagSegment
import com.vitorpamplona.amethyst.commons.richtext.RegularTextSegment
import com.vitorpamplona.amethyst.ui.components.HashTag
import com.vitorpamplona.amethyst.ui.components.RenderRegular
import com.vitorpamplona.amethyst.ui.navigation.navs.EmptyNav
import com.vitorpamplona.amethyst.ui.screen.loggedIn.mockAccountViewModel
import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonColumn
import com.vitorpamplona.quartz.nip02FollowList.EmptyTagList
@Preview
@Composable
fun RenderHashTagIconsPreview() {
val accountViewModel = mockAccountViewModel()
ThemeComparisonColumn {
RenderRegular(
"Testing rendering of hashtags: #flowerstr #Bitcoin, #nostr, #lightning, #zap, #amethyst, #cashu, #plebs, #coffee, #skullofsatoshi, #grownostr, #footstr, #tunestr, #weed, #mate, #gamestr, #gamechain",
EmptyTagList,
) { word, state ->
when (word) {
is HashTagSegment -> HashTag(word, accountViewModel, EmptyNav)
is RegularTextSegment -> Text(word.segmentText)
}
}
}
}
fun checkForHashtagWithIcon(tag: String): HashtagIcon? =
when (tag.lowercase()) {
"₿itcoin", "bitcoin", "btc", "timechain", "bitcoiner", "bitcoiners" -> bitcoin
"nostr", "nostrich", "nostriches", "thenostr" -> nostr
"lightning", "lightningnetwork" -> lightning
"zap", "zaps", "zapper", "zappers", "zapping", "zapped", "zapathon", "zapraiser", "zaplife", "zapchain" -> zap
"amethyst" -> amethyst
"cashu", "ecash", "nut", "nuts", "deeznuts" -> cashu
"plebs", "pleb", "plebchain" -> plebs
"coffee", "coffeechain", "cafe" -> coffee
"skullofsatoshi" -> skull
"grownostr", "gardening", "garden" -> growstr
"footstr" -> footstr
"flowerstr" -> flowerstr
"tunestr", "music", "nowplaying" -> tunestr
"mate", "matechain", "matestr" -> matestr
"weed", "weedstr", "420", "cannabis", "marijuana" -> weed
"gamestr", "gaming", "gamechain" -> gamestr
else -> null
}
val bitcoin = HashtagIcon(CustomHashTagIcons.Btc, "Bitcoin", Modifier.padding(start = 1.dp, bottom = 1.dp, top = 1.dp))
val nostr = HashtagIcon(CustomHashTagIcons.Nostr, "Nostr", Modifier.padding(start = 1.dp, bottom = 1.dp, top = 1.dp))
val lightning = HashtagIcon(CustomHashTagIcons.Lightning, "Lightning", Modifier.padding(start = 1.dp, bottom = 1.dp, top = 1.dp))
val zap = HashtagIcon(CustomHashTagIcons.Zap, "Zap", Modifier.padding(start = 1.dp, bottom = 1.dp, top = 1.dp))
val amethyst = HashtagIcon(CustomHashTagIcons.Amethyst, "Amethyst", Modifier.padding(start = 2.dp, bottom = 1.dp, top = 1.dp))
val cashu = HashtagIcon(CustomHashTagIcons.Cashu, "Cashu", Modifier.padding(start = 1.dp, bottom = 1.dp, top = 1.dp))
val plebs = HashtagIcon(CustomHashTagIcons.Plebs, "Pleb", Modifier.padding(start = 2.dp, bottom = 1.dp, top = 1.dp))
val coffee = HashtagIcon(CustomHashTagIcons.Coffee, "Coffee", Modifier.padding(start = 3.dp, bottom = 1.dp, top = 1.dp))
val skull = HashtagIcon(CustomHashTagIcons.Skull, "SkullofSatoshi", Modifier.padding(start = 1.dp, bottom = 1.dp, top = 1.dp))
val growstr = HashtagIcon(CustomHashTagIcons.Grownostr, "GrowNostr", Modifier.padding(start = 1.dp, bottom = 1.dp, top = 1.dp))
val footstr = HashtagIcon(CustomHashTagIcons.Footstr, "Footstr", Modifier.padding(start = 2.dp, bottom = 1.dp, top = 1.dp))
val flowerstr = HashtagIcon(CustomHashTagIcons.Flowerstr, "Flowerstr", Modifier.padding(start = 2.dp, bottom = 1.dp, top = 1.dp))
val tunestr = HashtagIcon(CustomHashTagIcons.Tunestr, "Tunestr", Modifier.padding(start = 1.dp, bottom = 1.dp, top = 1.dp))
val weed = HashtagIcon(CustomHashTagIcons.Weed, "Weed", Modifier.padding(start = 1.dp, bottom = 0.dp, top = 0.dp))
val matestr = HashtagIcon(CustomHashTagIcons.Mate, "Mate", Modifier.padding(start = 1.dp, bottom = 0.dp, top = 0.dp))
val gamestr = HashtagIcon(CustomHashTagIcons.Gamestr, "GameStr", Modifier.padding(start = 1.dp, bottom = 0.dp, top = 0.dp))
@Immutable
class HashtagIcon(
val icon: ImageVector,
val description: String,
val modifier: Modifier = Modifier,
)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,49 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model
import android.util.LruCache
interface MutableMediaAspectRatioCache {
fun get(url: String): Float?
fun add(
url: String,
width: Int,
height: Int,
)
}
object MediaAspectRatioCache : MutableMediaAspectRatioCache {
val mediaAspectRatioCacheByUrl = LruCache<String, Float>(1000)
override fun get(url: String): Float? = mediaAspectRatioCacheByUrl.get(url)
override fun add(
url: String,
width: Int,
height: Int,
) {
if (height > 1) {
mediaAspectRatioCacheByUrl.put(url, width.toFloat() / height.toFloat())
}
}
}

View File

@@ -0,0 +1,183 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model
import android.util.Log
import androidx.compose.runtime.Stable
import com.fasterxml.jackson.annotation.JsonSubTypes
import com.fasterxml.jackson.annotation.JsonTypeInfo
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import kotlinx.collections.immutable.ImmutableMap
import kotlinx.collections.immutable.persistentMapOf
import kotlinx.collections.immutable.toImmutableMap
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "resourceType",
)
@JsonSubTypes(
JsonSubTypes.Type(value = Practitioner::class, name = "Practitioner"),
JsonSubTypes.Type(value = Patient::class, name = "Patient"),
JsonSubTypes.Type(value = Bundle::class, name = "Bundle"),
JsonSubTypes.Type(value = VisionPrescription::class, name = "VisionPrescription"),
)
@Stable
open class Resource(
var resourceType: String? = null,
var id: String = "",
)
@Stable
class Practitioner(
resourceType: String? = null,
id: String = "",
var active: Boolean? = null,
var name: ArrayList<HumanName> = arrayListOf(),
var gender: String? = null,
) : Resource(resourceType, id)
@Stable
class Patient(
resourceType: String? = null,
id: String = "",
var active: Boolean? = null,
var name: ArrayList<HumanName> = arrayListOf(),
var gender: String? = null,
) : Resource(resourceType, id)
@Stable
class HumanName(
var use: String? = null,
var family: String? = null,
var given: ArrayList<String> = arrayListOf(),
) {
fun assembleName(): String = given.joinToString(" ") + " " + family
}
@Stable
class Bundle(
resourceType: String? = null,
id: String = "",
var type: String? = null,
var created: String? = null,
var entry: List<Resource> = arrayListOf(),
) : Resource(resourceType, id)
@Stable
class VisionPrescription(
resourceType: String? = null,
id: String = "",
var status: String? = null,
var created: String? = null,
var patient: Reference? = Reference(),
var encounter: Reference? = Reference(),
var dateWritten: String? = null,
var prescriber: Reference? = Reference(),
var lensSpecification: List<LensSpecification> = arrayListOf(),
) : Resource(resourceType, id) {
fun glasses() = lensSpecification.filter { it.product == "lens" }
fun contacts() = lensSpecification.filter { it.product == "contacts" }
fun glassesRightEyes() = lensSpecification.filter { it.product == "lens" && it.eye == "right" }
fun glassesLeftEyes() = lensSpecification.filter { it.product == "lens" && it.eye == "left" }
fun contactsRightEyes() = lensSpecification.filter { it.product == "contacts" && it.eye == "right" }
fun contactsLeftEyes() = lensSpecification.filter { it.product == "contacts" && it.eye == "left" }
}
@Stable
class LensSpecification(
var product: String? = null,
var eye: String? = null,
var sphere: Double? = null,
var cylinder: Double? = null,
var axis: Double? = null,
var pd: Double? = null,
var interAdd: Double? = null,
var add: Double? = null,
var prism: Prism? = null,
// contact lenses
var power: Double? = null,
var backCurve: Double? = null,
var diameter: Double? = null,
var color: String? = null,
var brand: String? = null,
var note: String? = null,
)
@Stable
class Prism(
var amount: Double? = null,
var base: String? = null,
)
class Reference(
var reference: String? = null,
)
data class FhirElementDatabase(
var baseResource: Resource? = null,
var localDb: ImmutableMap<String, Resource> = persistentMapOf(),
)
fun findReferenceInDb(
it: String,
db: Map<String, Resource>,
): Resource? {
val parts = it.split("/")
return if (parts.size == 2) {
db.get(parts[1].removePrefix("#"))
} else {
db.get(it.removePrefix("#"))
}
}
fun parseResourceBundleOrNull(json: String): FhirElementDatabase? {
val mapper =
jacksonObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
return try {
val resource = mapper.readValue(json, Resource::class.java)
val db =
when (resource) {
is Bundle -> {
resource.entry.associateBy { it.id }.toImmutableMap()
}
else -> {
persistentMapOf(resource.id to resource)
}
}
FhirElementDatabase(
localDb = db,
baseResource = resource,
)
} catch (e: Exception) {
Log.e("RenderEyeGlassesPrescription", "Parser error", e)
null
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,116 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model
import com.vitorpamplona.quartz.nip01Core.core.HexKey
class ParticipantListBuilder {
private fun addFollowsThatDirectlyParticipateOnToSet(
baseNote: Note,
followingSet: Set<HexKey>?,
set: MutableSet<User>,
) {
baseNote.author?.let { author ->
if (author !in set && (followingSet == null || author.pubkeyHex in followingSet)) {
set.add(author)
}
}
// Breaks these searchers down to avoid the memory use of creating multiple lists
baseNote.replies.forEach { reply ->
reply.author?.let { author ->
if (author !in set && (followingSet == null || author.pubkeyHex in followingSet)) {
set.add(author)
}
}
}
baseNote.boosts.forEach { boost ->
boost.author?.let { author ->
if (author !in set && (followingSet == null || author.pubkeyHex in followingSet)) {
set.add(author)
}
}
}
baseNote.zaps.forEach { zapPair ->
zapPair.key.author?.let { author ->
if (author !in set && (followingSet == null || author.pubkeyHex in followingSet)) {
set.add(author)
}
}
}
baseNote.reactions.forEach { reactionSet ->
reactionSet.value.forEach { reaction ->
reaction.author?.let { author ->
if (author !in set && (followingSet == null || author.pubkeyHex in followingSet)) {
set.add(author)
}
}
}
}
}
fun followsThatParticipateOnDirect(
baseNote: Note?,
followingSet: Set<HexKey>?,
): Set<User> {
if (baseNote == null) return mutableSetOf()
val set = mutableSetOf<User>()
addFollowsThatDirectlyParticipateOnToSet(baseNote, followingSet, set)
return set
}
fun followsThatParticipateOn(
baseNote: Note?,
followingSet: Set<HexKey>?,
): Set<User> {
if (baseNote == null) return mutableSetOf()
val mySet = mutableSetOf<User>()
addFollowsThatDirectlyParticipateOnToSet(baseNote, followingSet, mySet)
baseNote.replies.forEach { addFollowsThatDirectlyParticipateOnToSet(it, followingSet, mySet) }
baseNote.boosts.forEach {
it.replyTo?.forEach { addFollowsThatDirectlyParticipateOnToSet(it, followingSet, mySet) }
}
LocalCache.getPublicChatChannelIfExists(baseNote.idHex)?.notes?.forEach { key, it ->
addFollowsThatDirectlyParticipateOnToSet(it, followingSet, mySet)
}
return mySet
}
fun countFollowsThatParticipateOn(
baseNote: Note?,
followingSet: Set<HexKey>?,
): Int {
if (baseNote == null) return 0
val list = followsThatParticipateOn(baseNote, followingSet)
return list.size
}
}

View File

@@ -0,0 +1,181 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model
import androidx.compose.runtime.Stable
import com.vitorpamplona.amethyst.R
@Stable
data class Settings(
val theme: ThemeType = ThemeType.SYSTEM,
val preferredLanguage: String? = null,
val automaticallyShowImages: ConnectivityType = ConnectivityType.ALWAYS,
val automaticallyStartPlayback: ConnectivityType = ConnectivityType.ALWAYS,
val automaticallyShowUrlPreview: ConnectivityType = ConnectivityType.ALWAYS,
val automaticallyHideNavigationBars: BooleanType = BooleanType.ALWAYS,
val automaticallyShowProfilePictures: ConnectivityType = ConnectivityType.ALWAYS,
val dontShowPushNotificationSelector: Boolean = false,
val dontAskForNotificationPermissions: Boolean = false,
val featureSet: FeatureSetType = FeatureSetType.SIMPLIFIED,
val gallerySet: ProfileGalleryType = ProfileGalleryType.CLASSIC,
)
enum class ThemeType(
val screenCode: Int,
val resourceId: Int,
) {
SYSTEM(0, R.string.system),
LIGHT(1, R.string.light),
DARK(2, R.string.dark),
}
fun parseThemeType(code: Int?): ThemeType =
when (code) {
ThemeType.SYSTEM.screenCode -> ThemeType.SYSTEM
ThemeType.LIGHT.screenCode -> ThemeType.LIGHT
ThemeType.DARK.screenCode -> ThemeType.DARK
else -> {
ThemeType.SYSTEM
}
}
enum class ConnectivityType(
val prefCode: Boolean?,
val screenCode: Int,
val resourceId: Int,
) {
ALWAYS(null, 0, R.string.connectivity_type_always),
WIFI_ONLY(true, 1, R.string.connectivity_type_unmetered_wifi_only),
NEVER(false, 2, R.string.connectivity_type_never),
}
enum class FeatureSetType(
val screenCode: Int,
val resourceId: Int,
) {
COMPLETE(0, R.string.ui_feature_set_type_complete),
SIMPLIFIED(1, R.string.ui_feature_set_type_simplified),
PERFORMANCE(2, R.string.ui_feature_set_type_performance),
}
enum class ProfileGalleryType(
val screenCode: Int,
val resourceId: Int,
) {
CLASSIC(0, R.string.gallery_type_classic),
MODERN(1, R.string.gallery_type_modern),
}
fun parseConnectivityType(code: Boolean?): ConnectivityType =
when (code) {
ConnectivityType.ALWAYS.prefCode -> ConnectivityType.ALWAYS
ConnectivityType.WIFI_ONLY.prefCode -> ConnectivityType.WIFI_ONLY
ConnectivityType.NEVER.prefCode -> ConnectivityType.NEVER
else -> {
ConnectivityType.ALWAYS
}
}
fun parseConnectivityType(screenCode: Int): ConnectivityType =
when (screenCode) {
ConnectivityType.ALWAYS.screenCode -> ConnectivityType.ALWAYS
ConnectivityType.WIFI_ONLY.screenCode -> ConnectivityType.WIFI_ONLY
ConnectivityType.NEVER.screenCode -> ConnectivityType.NEVER
else -> {
ConnectivityType.ALWAYS
}
}
fun parseFeatureSetType(screenCode: Int): FeatureSetType =
when (screenCode) {
FeatureSetType.COMPLETE.screenCode -> FeatureSetType.COMPLETE
FeatureSetType.SIMPLIFIED.screenCode -> FeatureSetType.SIMPLIFIED
FeatureSetType.PERFORMANCE.screenCode -> FeatureSetType.PERFORMANCE
else -> {
FeatureSetType.COMPLETE
}
}
fun parseGalleryType(screenCode: Int): ProfileGalleryType =
when (screenCode) {
ProfileGalleryType.CLASSIC.screenCode -> ProfileGalleryType.CLASSIC
ProfileGalleryType.MODERN.screenCode -> ProfileGalleryType.MODERN
else -> {
ProfileGalleryType.CLASSIC
}
}
enum class BooleanType(
val prefCode: Boolean?,
val screenCode: Int,
val reourceId: Int,
) {
ALWAYS(null, 0, R.string.connectivity_type_always),
NEVER(false, 1, R.string.connectivity_type_never),
}
fun parseBooleanType(code: Boolean?): BooleanType =
when (code) {
BooleanType.ALWAYS.prefCode -> BooleanType.ALWAYS
BooleanType.NEVER.prefCode -> BooleanType.NEVER
else -> {
BooleanType.ALWAYS
}
}
fun parseBooleanType(screenCode: Int): BooleanType =
when (screenCode) {
BooleanType.ALWAYS.screenCode -> BooleanType.ALWAYS
BooleanType.NEVER.screenCode -> BooleanType.NEVER
else -> {
BooleanType.ALWAYS
}
}
enum class WarningType(
val prefCode: Boolean?,
val screenCode: Int,
val resourceId: Int,
) {
WARN(null, 0, R.string.content_warning_see_warnings_option),
SHOW(true, 1, R.string.content_warning_show_all_sensitive_content_option),
HIDE(false, 2, R.string.content_warning_hide_all_sensitive_content_option),
}
fun parseWarningType(screenCode: Int): WarningType =
when (screenCode) {
WarningType.WARN.screenCode -> WarningType.WARN
WarningType.SHOW.screenCode -> WarningType.SHOW
WarningType.HIDE.screenCode -> WarningType.HIDE
else -> {
WarningType.WARN
}
}
fun parseWarningType(code: Boolean?): WarningType =
when (code) {
WarningType.WARN.prefCode -> WarningType.WARN
WarningType.HIDE.prefCode -> WarningType.HIDE
WarningType.SHOW.prefCode -> WarningType.SHOW
else -> {
WarningType.WARN
}
}

View File

@@ -0,0 +1,218 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model
import androidx.compose.runtime.Stable
import com.vitorpamplona.amethyst.service.checkNotInMainThread
import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent
import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address
import com.vitorpamplona.quartz.nip18Reposts.GenericRepostEvent
import com.vitorpamplona.quartz.nip18Reposts.RepostEvent
import kotlinx.collections.immutable.ImmutableSet
import kotlinx.collections.immutable.toImmutableSet
class ThreadAssembler {
private fun searchRoot(
note: Note,
testedNotes: MutableSet<Note> = mutableSetOf(),
): Note? {
if (note.replyTo == null || note.replyTo?.isEmpty() == true) return note
val noteEvent = note.event
if (noteEvent is RepostEvent || noteEvent is GenericRepostEvent) return note
testedNotes.add(note)
val markedAsRoot =
noteEvent
?.tags
?.firstOrNull { it[0] == "e" && it.size > 3 && it[3] == "root" }
?.getOrNull(1)
if (markedAsRoot != null) {
// Check to ssee if there is an error in the tag and the root has replies
if (LocalCache.getNoteIfExists(markedAsRoot)?.replyTo?.isEmpty() == true) {
return LocalCache.checkGetOrCreateNote(markedAsRoot)
}
}
val hasNoReplyTo =
note.replyTo?.lastOrNull {
it.replyTo?.isEmpty() == true
}
if (hasNoReplyTo != null) return hasNoReplyTo
// recursive
val roots =
note.replyTo?.mapNotNull {
if (it !in testedNotes) {
searchRoot(it, testedNotes)
} else {
null
}
}
if (roots != null && roots.isNotEmpty()) {
return roots[0]
}
return null
}
@Stable
class ThreadInfo(
val root: Note,
val allNotes: ImmutableSet<Note>,
)
fun findRoot(noteId: String): Note? {
val note = LocalCache.checkGetOrCreateNote(noteId) ?: return null
return if (note.event != null) {
val thread = OnlyLatestVersionSet()
searchRoot(note, thread) ?: note
} else {
note
}
}
fun findThreadFor(noteId: String): ThreadInfo? {
checkNotInMainThread()
val note = LocalCache.checkGetOrCreateNote(noteId) ?: return null
return if (note.event != null) {
val thread = OnlyLatestVersionSet()
val threadRoot = searchRoot(note, thread) ?: note
loadUp(note, thread)
loadDown(threadRoot, thread)
// adds the replies of the note in case the search for Root
// did not added them.
note.replies.forEach { loadDown(it, thread) }
ThreadInfo(
root = note,
allNotes = thread.toImmutableSet(),
)
} else {
ThreadInfo(
root = note,
allNotes = setOf(note).toImmutableSet(),
)
}
}
fun loadUp(
note: Note,
thread: MutableSet<Note>,
) {
if (note !in thread) {
thread.add(note)
note.replyTo?.forEach { loadUp(it, thread) }
}
}
fun loadDown(
note: Note,
thread: MutableSet<Note>,
) {
if (note !in thread) {
thread.add(note)
note.replies.forEach { loadDown(it, thread) }
}
}
}
class OnlyLatestVersionSet : MutableSet<Note> {
val map = hashMapOf<Address, Long>()
val set = hashSetOf<Note>()
override fun add(element: Note): Boolean {
val loadedCreatedAt = element.createdAt()
val noteEvent = element.event
return if (element is AddressableNote && loadedCreatedAt != null) {
innerAdd(element.address, element, loadedCreatedAt)
} else if (noteEvent is AddressableEvent && loadedCreatedAt != null) {
innerAdd(noteEvent.address(), element, loadedCreatedAt)
} else {
set.add(element)
}
}
private fun innerAdd(
address: Address,
element: Note,
loadedCreatedAt: Long,
): Boolean {
val existing = map.get(address)
return if (existing == null) {
map.put(address, loadedCreatedAt)
set.add(element)
} else {
if (loadedCreatedAt > existing) {
map.put(address, loadedCreatedAt)
set.add(element)
} else {
false
}
}
}
override fun addAll(elements: Collection<Note>): Boolean = elements.map { add(it) }.any()
override val size: Int
get() = set.size
override fun clear() {
set.clear()
map.clear()
}
override fun isEmpty(): Boolean = set.isEmpty()
override fun containsAll(elements: Collection<Note>): Boolean = set.containsAll(elements)
override fun contains(element: Note): Boolean = set.contains(element)
override fun iterator(): MutableIterator<Note> = set.iterator()
override fun retainAll(elements: Collection<Note>): Boolean = set.retainAll(elements)
override fun removeAll(elements: Collection<Note>): Boolean = elements.map { remove(it) }.any()
override fun remove(element: Note): Boolean {
element.address()?.let {
map.remove(it)
}
(element.event as? AddressableEvent)?.address()?.let {
map.remove(it)
}
return set.remove(element)
}
}

View File

@@ -0,0 +1,143 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip18Reposts.GenericRepostEvent
import com.vitorpamplona.quartz.nip18Reposts.RepostEvent
import java.lang.Long.min
import java.time.Instant
import java.time.ZoneId
import java.time.format.DateTimeFormatter
data class LevelSignature(
val signature: String,
val createdAt: Long?,
val author: User?,
)
object ThreadLevelCalculator {
val levelFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd-HH:mm:ss")
private fun formattedDateTime(timestamp: Long): String =
Instant
.ofEpochSecond(timestamp)
.atZone(ZoneId.systemDefault())
.format(levelFormatter)
/**
* This method caches signatures during each execution to avoid recalculation in longer threads
*/
fun replyLevelSignature(
note: Note,
eventsToConsider: Set<HexKey>,
cachedSignatures: MutableMap<Note, LevelSignature>,
account: User,
accountFollowingSet: Set<String>,
now: Long,
): LevelSignature {
val replyTo = note.replyTo
// estimates the min date by replies if it doesn't exist.
val createdAt =
note.createdAt() ?: min(
note.replies.minOfOrNull { it.createdAt() ?: now } ?: now,
note.reactions.values.minOfOrNull { it.minOfOrNull { it.createdAt() ?: now } ?: now } ?: now,
)
val noteAuthor = note.author
if (
note.event is RepostEvent || note.event is GenericRepostEvent || replyTo == null || replyTo.isEmpty()
) {
return LevelSignature(
signature = "/" + formattedDateTime(createdAt) + note.idHex.substring(0, 8) + ";",
createdAt = createdAt,
author = noteAuthor,
)
}
val parent =
(
replyTo
.filter {
it.idHex in eventsToConsider
} // This forces the signature to be based on a branch, avoiding two roots
.map {
cachedSignatures[it]
?: replyLevelSignature(
it,
eventsToConsider,
cachedSignatures,
account,
accountFollowingSet,
now,
).apply { cachedSignatures.put(it, this) }
}.maxByOrNull { it.signature.length }
)
val parentSignature = parent?.signature?.removeSuffix(";") ?: ""
val threadOrder =
if (noteAuthor != null && parent?.author == noteAuthor) {
// author of the thread first, in **ascending** order
"9" + formattedDateTime((parent.createdAt ?: 0) + (now - createdAt)) + note.idHex.substring(0, 8)
} else if (noteAuthor != null && noteAuthor.pubkeyHex == account.pubkeyHex) {
"8" + formattedDateTime(createdAt) + note.idHex.substring(0, 8) // my replies
} else if (noteAuthor != null && noteAuthor.pubkeyHex in accountFollowingSet) {
"7" + formattedDateTime(createdAt) + note.idHex.substring(0, 8) // my follows replies.
} else {
"0" + formattedDateTime(createdAt) + note.idHex.substring(0, 8) // everyone else.
}
val mySignature =
LevelSignature(
signature = "$parentSignature/$threadOrder;",
createdAt = createdAt,
author = note.author,
)
cachedSignatures[note] = mySignature
return mySignature
}
fun replyLevel(
note: Note,
cachedLevels: MutableMap<Note, Int> = mutableMapOf(),
): Int {
val replyTo = note.replyTo
if (
note.event is RepostEvent || note.event is GenericRepostEvent || replyTo == null || replyTo.isEmpty()
) {
cachedLevels[note] = 0
return 0
}
val thisLevel =
replyTo.maxOf {
cachedLevels[it] ?: replyLevel(it, cachedLevels)
} + 1
cachedLevels[note] = thisLevel
return thisLevel
}
}

View File

@@ -0,0 +1,77 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model
import android.util.LruCache
import androidx.compose.runtime.Stable
import com.vitorpamplona.amethyst.service.previews.UrlPreview
import com.vitorpamplona.amethyst.ui.components.UrlPreviewState
import okhttp3.OkHttpClient
@Stable
object UrlCachedPreviewer {
var cache = LruCache<String, UrlPreviewState>(100)
private set
suspend fun previewInfo(
url: String,
okHttpClient: (String) -> OkHttpClient,
onReady: suspend (UrlPreviewState) -> Unit,
) {
cache[url]?.let {
onReady(it)
return
}
UrlPreview().fetch(
url,
okHttpClient,
onComplete = { urlInfo ->
cache[url]?.let {
if (it is UrlPreviewState.Loaded || it is UrlPreviewState.Empty) {
onReady(it)
return@fetch
}
}
val state =
if (urlInfo.fetchComplete() && urlInfo.url == url) {
UrlPreviewState.Loaded(urlInfo)
} else {
UrlPreviewState.Empty
}
cache.put(url, state)
onReady(state)
},
onFailed = { throwable ->
cache[url]?.let {
onReady(it)
return@fetch
}
val state = UrlPreviewState.Error(throwable.message ?: "Error Loading url preview")
cache.put(url, state)
onReady(state)
},
)
}
}

View File

@@ -0,0 +1,383 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.Stable
import com.vitorpamplona.amethyst.ui.note.toShortDisplay
import com.vitorpamplona.quartz.lightning.Lud06
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
import com.vitorpamplona.quartz.nip01Core.metadata.UserMetadata
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.tags.geohash.isTaggedGeoHash
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.isTaggedHash
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
import com.vitorpamplona.quartz.nip01Core.tags.people.isTaggedUser
import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent
import com.vitorpamplona.quartz.nip02FollowList.toImmutableListOfLists
import com.vitorpamplona.quartz.nip17Dm.settings.ChatMessageRelayListEvent
import com.vitorpamplona.quartz.nip19Bech32.entities.NProfile
import com.vitorpamplona.quartz.nip19Bech32.toNpub
import com.vitorpamplona.quartz.nip56Reports.ReportEvent
import com.vitorpamplona.quartz.nip56Reports.ReportType
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListEvent
import com.vitorpamplona.quartz.utils.DualCase
import com.vitorpamplona.quartz.utils.Hex
import com.vitorpamplona.quartz.utils.containsAny
import kotlinx.coroutines.flow.MutableStateFlow
import java.math.BigDecimal
@Stable
class User(
val pubkeyHex: String,
) {
var info: UserMetadata? = null
var latestMetadata: MetadataEvent? = null
var latestMetadataRelay: NormalizedRelayUrl? = null
var latestContactList: ContactListEvent? = null
var reports = mapOf<User, Set<Note>>()
private set
var zaps = mapOf<Note, Note?>()
private set
var relaysBeingUsed = mapOf<NormalizedRelayUrl, RelayInfo>()
private set
fun pubkey() = Hex.decode(pubkeyHex)
fun pubkeyNpub() = pubkey().toNpub()
fun pubkeyDisplayHex() = pubkeyNpub().toShortDisplay()
fun dmInboxRelayList() = (LocalCache.getAddressableNoteIfExists(ChatMessageRelayListEvent.createAddressTag(pubkeyHex))?.event as? ChatMessageRelayListEvent)
fun authorRelayList() = (LocalCache.getAddressableNoteIfExists(AdvertisedRelayListEvent.createAddressTag(pubkeyHex))?.event as? AdvertisedRelayListEvent)
fun toNProfile() = NProfile.create(pubkeyHex, relayHints())
fun outboxRelays() = authorRelayList()?.writeRelaysNorm()
fun relayHints() = authorRelayList()?.writeRelaysNorm()?.take(3) ?: listOfNotNull(latestMetadataRelay)
fun inboxRelays() = authorRelayList()?.readRelaysNorm()
fun dmInboxRelays() = dmInboxRelayList()?.relays()?.ifEmpty { null } ?: inboxRelays()
fun bestRelayHint() = authorRelayList()?.writeRelaysNorm()?.firstOrNull() ?: latestMetadataRelay
fun toPTag() = PTag(pubkeyHex, bestRelayHint())
fun toNostrUri() = "nostr:${toNProfile()}"
fun toBestShortFirstName(): String {
val fullName = toBestDisplayName()
val names = fullName.split(' ')
val firstName =
if (names[0].length <= 3) {
// too short. Remove Dr.
"${names[0]} ${names.getOrNull(1) ?: ""}"
} else {
names[0]
}
return firstName
}
fun toBestDisplayName(): String = info?.bestName() ?: pubkeyDisplayHex()
fun nip05(): String? = info?.nip05
fun profilePicture(): String? = info?.picture
fun updateContactList(event: ContactListEvent) {
if (event.id == latestContactList?.id) return
val oldContactListEvent = latestContactList
latestContactList = event
// Update following of the current user
flowSet?.follows?.invalidateData()
// Update Followers of the past user list
// Update Followers of the new contact list
(oldContactListEvent)?.unverifiedFollowKeySet()?.forEach {
LocalCache
.getUserIfExists(it)
?.flowSet
?.followers
?.invalidateData()
}
(latestContactList)?.unverifiedFollowKeySet()?.forEach {
LocalCache
.getUserIfExists(it)
?.flowSet
?.followers
?.invalidateData()
}
flowSet?.relays?.invalidateData()
}
fun addReport(note: Note) {
val author = note.author ?: return
val reportsBy = reports[author]
if (reportsBy == null) {
reports = reports + Pair(author, setOf(note))
flowSet?.reports?.invalidateData()
} else if (!reportsBy.contains(note)) {
reports = reports + Pair(author, reportsBy + note)
flowSet?.reports?.invalidateData()
}
}
fun removeReport(deleteNote: Note) {
val author = deleteNote.author ?: return
if (reports[author]?.contains(deleteNote) == true) {
reports[author]?.let {
reports = reports + Pair(author, it.minus(deleteNote))
flowSet?.reports?.invalidateData()
}
}
}
fun addZap(
zapRequest: Note,
zap: Note?,
) {
if (zaps[zapRequest] == null) {
zaps = zaps + Pair(zapRequest, zap)
flowSet?.zaps?.invalidateData()
}
}
fun removeZap(zapRequestOrZapEvent: Note) {
if (zaps.containsKey(zapRequestOrZapEvent)) {
zaps = zaps.minus(zapRequestOrZapEvent)
flowSet?.zaps?.invalidateData()
} else if (zaps.containsValue(zapRequestOrZapEvent)) {
zaps = zaps.filter { it.value != zapRequestOrZapEvent }
flowSet?.zaps?.invalidateData()
}
}
fun zappedAmount(): BigDecimal {
var amount = BigDecimal.ZERO
zaps.forEach {
val itemValue = (it.value?.event as? LnZapEvent)?.amount
if (itemValue != null) {
amount += itemValue
}
}
return amount
}
fun reportsBy(user: User): Set<Note> = reports[user] ?: emptySet()
fun countReportAuthorsBy(users: Set<HexKey>): Int = reports.count { it.key.pubkeyHex in users }
fun reportsBy(users: Set<HexKey>): List<Note> =
reports
.mapNotNull {
if (it.key.pubkeyHex in users) {
it.value
} else {
null
}
}.flatten()
fun addRelayBeingUsed(
relay: NormalizedRelayUrl,
eventTime: Long,
) {
val here = relaysBeingUsed[relay]
if (here == null) {
relaysBeingUsed = relaysBeingUsed + Pair(relay, RelayInfo(relay, eventTime, 1))
} else {
if (eventTime > here.lastEvent) {
here.lastEvent = eventTime
}
here.counter++
}
flowSet?.relayInfo?.invalidateData()
}
fun updateUserInfo(
newUserInfo: UserMetadata,
latestMetadata: MetadataEvent,
) {
info = newUserInfo
info?.tags = latestMetadata.tags.toImmutableListOfLists()
info?.cleanBlankNames()
if (newUserInfo.lud16.isNullOrBlank()) {
info?.lud06?.let {
if (it.lowercase().startsWith("lnurl")) {
info?.lud16 = Lud06().toLud16(it)
}
}
}
flowSet?.metadata?.invalidateData()
}
fun isFollowing(user: User): Boolean = latestContactList?.isTaggedUser(user.pubkeyHex) ?: false
fun isFollowingHashtag(tag: String) = latestContactList?.isTaggedHash(tag) ?: false
fun isFollowingGeohash(geoTag: String) = latestContactList?.isTaggedGeoHash(geoTag) ?: false
fun transientFollowCount(): Int? = latestContactList?.unverifiedFollowKeySet()?.size
suspend fun transientFollowerCount(): Int = LocalCache.users.count { _, it -> it.latestContactList?.isTaggedUser(pubkeyHex) ?: false }
fun hasReport(
loggedIn: User,
type: ReportType,
): Boolean =
reports[loggedIn]?.firstOrNull {
(it.event as? ReportEvent)?.reportedAuthor()?.any { it.type == type } ?: false
} != null
fun containsAny(hiddenWordsCase: List<DualCase>): Boolean {
if (hiddenWordsCase.isEmpty()) return false
if (toBestDisplayName().containsAny(hiddenWordsCase)) {
return true
}
if (profilePicture()?.containsAny(hiddenWordsCase) == true) {
return true
}
if (info?.banner?.containsAny(hiddenWordsCase) == true) {
return true
}
if (info?.about?.containsAny(hiddenWordsCase) == true) {
return true
}
if (info?.lud06?.containsAny(hiddenWordsCase) == true) {
return true
}
if (info?.lud16?.containsAny(hiddenWordsCase) == true) {
return true
}
if (info?.nip05?.containsAny(hiddenWordsCase) == true) {
return true
}
return false
}
fun anyNameStartsWith(username: String): Boolean = info?.anyNameStartsWith(username) ?: false
var flowSet: UserFlowSet? = null
@Synchronized
fun createOrDestroyFlowSync(create: Boolean) {
if (create) {
if (flowSet == null) {
flowSet = UserFlowSet(this)
}
} else {
if (flowSet != null && flowSet?.isInUse() == false) {
flowSet = null
}
}
}
fun flow(): UserFlowSet {
if (flowSet == null) {
createOrDestroyFlowSync(true)
}
return flowSet!!
}
fun clearFlow() {
if (flowSet != null && flowSet?.isInUse() == false) {
createOrDestroyFlowSync(false)
}
}
}
@Stable
class UserFlowSet(
u: User,
) {
// Observers line up here.
val metadata = UserBundledRefresherFlow(u)
val follows = UserBundledRefresherFlow(u)
val relays = UserBundledRefresherFlow(u)
val followers = UserBundledRefresherFlow(u)
val reports = UserBundledRefresherFlow(u)
val relayInfo = UserBundledRefresherFlow(u)
val zaps = UserBundledRefresherFlow(u)
val statuses = UserBundledRefresherFlow(u)
fun isInUse(): Boolean =
metadata.hasObservers() ||
relays.hasObservers() ||
follows.hasObservers() ||
followers.hasObservers() ||
reports.hasObservers() ||
relayInfo.hasObservers() ||
zaps.hasObservers() ||
statuses.hasObservers()
}
@Immutable
data class RelayInfo(
val url: NormalizedRelayUrl,
var lastEvent: Long,
var counter: Long,
)
@Stable
class UserBundledRefresherFlow(
val user: User,
) {
val stateFlow = MutableStateFlow(UserState(user))
fun invalidateData() {
stateFlow.tryEmit(UserState(user))
}
fun hasObservers() = stateFlow.subscriptionCount.value > 0
}
@Immutable
class UserState(
val user: User,
)

View File

@@ -0,0 +1,29 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.edits
import com.vitorpamplona.amethyst.model.nip51Lists.relayLists.GenericRelayListCache
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip37Drafts.privateOutbox.PrivateOutboxRelayListEvent
class PrivateStorageRelayListDecryptionCache(
signer: NostrSigner,
) : GenericRelayListCache<PrivateOutboxRelayListEvent>(signer)

View File

@@ -0,0 +1,112 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.edits
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip37Drafts.privateOutbox.PrivateOutboxRelayListEvent
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
class PrivateStorageRelayListState(
val signer: NostrSigner,
val cache: LocalCache,
val decryptionCache: PrivateStorageRelayListDecryptionCache,
val scope: CoroutineScope,
val settings: AccountSettings,
) {
fun getPrivateOutboxRelayListAddress() = PrivateOutboxRelayListEvent.createAddress(signer.pubKey)
fun getPrivateOutboxRelayListNote(): AddressableNote = LocalCache.getOrCreateAddressableNote(getPrivateOutboxRelayListAddress())
fun getPrivateOutboxRelayListFlow(): StateFlow<NoteState> = getPrivateOutboxRelayListNote().flow().metadata.stateFlow
fun getPrivateOutboxRelayList(): PrivateOutboxRelayListEvent? = getPrivateOutboxRelayListNote().event as? PrivateOutboxRelayListEvent
suspend fun normalizePrivateOutboxRelayListWithBackup(note: Note): Set<NormalizedRelayUrl> {
val event = note.event as? PrivateOutboxRelayListEvent ?: settings.backupPrivateHomeRelayList
return event?.let { decryptionCache.relays(it) } ?: emptySet()
}
val flow =
getPrivateOutboxRelayListFlow()
.map { normalizePrivateOutboxRelayListWithBackup(it.note) }
.onStart {
emit(normalizePrivateOutboxRelayListWithBackup(getPrivateOutboxRelayListNote()))
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
emptySet(),
)
suspend fun saveRelayList(relays: List<NormalizedRelayUrl>): PrivateOutboxRelayListEvent {
val relayListForPrivateOutbox = getPrivateOutboxRelayList()
return if (relayListForPrivateOutbox != null) {
PrivateOutboxRelayListEvent.updateRelayList(
earlierVersion = relayListForPrivateOutbox,
relays = relays,
signer = signer,
)
} else {
PrivateOutboxRelayListEvent.create(
relays = relays,
signer = signer,
)
}
}
init {
settings.backupPrivateHomeRelayList?.let { event ->
Log.d("AccountRegisterObservers", "Loading saved private home relay list ${event.toJson()}")
@OptIn(DelicateCoroutinesApi::class)
GlobalScope.launch(Dispatchers.IO) {
LocalCache.justConsumeMyOwnEvent(event)
}
}
scope.launch(Dispatchers.Default) {
Log.d("AccountRegisterObservers", "Private Home Relay List Collector Start")
getPrivateOutboxRelayListFlow().collect { noteState ->
Log.d("AccountRegisterObservers", "Updating Private Home Relay List for ${signer.pubKey}")
(noteState.note.event as? PrivateOutboxRelayListEvent)?.let {
settings.updatePrivateHomeRelayList(it)
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.emphChat
import androidx.compose.runtime.Stable
import com.vitorpamplona.amethyst.model.Channel
import com.vitorpamplona.quartz.experimental.ephemChat.chat.RoomId
@Stable
class EphemeralChatChannel(
val roomId: RoomId,
) : Channel() {
override fun relays() = setOf(roomId.relayUrl)
override fun toBestDisplayName() = roomId.toDisplayKey()
fun anyNameStartsWith(prefix: String): Boolean = roomId.id.contains(prefix, true)
}

View File

@@ -0,0 +1,41 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.emphChat
import com.vitorpamplona.quartz.experimental.ephemChat.list.EphemeralChatListEvent
import com.vitorpamplona.quartz.experimental.ephemChat.list.roomSet
import com.vitorpamplona.quartz.experimental.ephemChat.list.rooms
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip51Lists.PrivateTagArrayEventCache
class EphemeralChatListDecryptionCache(
val signer: NostrSigner,
) {
val cachedPrivateLists = PrivateTagArrayEventCache<EphemeralChatListEvent>(signer)
fun cachedRoomSet(event: EphemeralChatListEvent) = cachedPrivateLists.mergeTagListPrecached(event).roomSet()
fun cachedRooms(event: EphemeralChatListEvent) = cachedPrivateLists.mergeTagListPrecached(event).rooms()
suspend fun roomSet(event: EphemeralChatListEvent) = cachedPrivateLists.mergeTagList(event).roomSet()
suspend fun rooms(event: EphemeralChatListEvent) = cachedPrivateLists.mergeTagList(event).rooms()
}

View File

@@ -0,0 +1,130 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.emphChat
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
import com.vitorpamplona.quartz.experimental.ephemChat.chat.RoomId
import com.vitorpamplona.quartz.experimental.ephemChat.list.EphemeralChatListEvent
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.transformLatest
import kotlinx.coroutines.launch
class EphemeralChatListState(
val signer: NostrSigner,
val cache: LocalCache,
val decryptionCache: EphemeralChatListDecryptionCache,
val scope: CoroutineScope,
val settings: AccountSettings,
) {
fun getEphemeralChatListAddress() = EphemeralChatListEvent.createAddress(signer.pubKey)
fun getEphemeralChatListNote(): AddressableNote = cache.getOrCreateAddressableNote(getEphemeralChatListAddress())
fun getEphemeralChatListFlow(): StateFlow<NoteState> = getEphemeralChatListNote().flow().metadata.stateFlow
fun getEphemeralChatList(): EphemeralChatListEvent? = getEphemeralChatListNote().event as? EphemeralChatListEvent
suspend fun ephemeralChatListWithBackup(note: Note): Set<RoomId> {
val event = note.event as? EphemeralChatListEvent ?: settings.backupEphemeralChatList
return event?.let { decryptionCache.roomSet(it) } ?: emptySet()
}
@OptIn(ExperimentalCoroutinesApi::class)
val liveEphemeralChatList: StateFlow<Set<RoomId>> =
getEphemeralChatListFlow()
.transformLatest { noteState ->
emit(ephemeralChatListWithBackup(noteState.note))
}.onStart {
emit(ephemeralChatListWithBackup(getEphemeralChatListNote()))
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
emptySet(),
)
suspend fun follow(channel: EphemeralChatChannel): EphemeralChatListEvent {
val ephemeralChatList = getEphemeralChatList()
return if (ephemeralChatList == null) {
EphemeralChatListEvent.create(
room = channel.roomId,
isPrivate = true,
signer = signer,
)
} else {
EphemeralChatListEvent.add(
earlierVersion = ephemeralChatList,
room = channel.roomId,
isPrivate = true,
signer = signer,
)
}
}
suspend fun unfollow(channel: EphemeralChatChannel): EphemeralChatListEvent? {
val ephemeralChatList = getEphemeralChatList()
return if (ephemeralChatList != null) {
EphemeralChatListEvent.remove(
earlierVersion = ephemeralChatList,
room = channel.roomId,
signer = signer,
)
} else {
null
}
}
init {
settings.backupEphemeralChatList?.let { event ->
Log.d("AccountRegisterObservers", "Loading saved ephemeral chat list")
@OptIn(DelicateCoroutinesApi::class)
GlobalScope.launch(Dispatchers.IO) {
LocalCache.justConsumeMyOwnEvent(event)
}
}
scope.launch(Dispatchers.Default) {
Log.d("AccountRegisterObservers", "EphemeralChatList Collector Start")
getEphemeralChatListFlow().collect { noteState ->
Log.d("AccountRegisterObservers", "EphemeralChatList List for ${signer.pubKey}")
(noteState.note.event as? EphemeralChatListEvent)?.let {
settings.updateEphemeralChatListTo(it)
}
}
}
}
}

View File

@@ -0,0 +1,60 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.localRelays
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.RelayUrlNormalizer
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
class LocalRelayListState(
val signer: NostrSigner,
val cache: LocalCache,
val scope: CoroutineScope,
val settings: AccountSettings,
) {
fun normalizeLocalRelayListWithBackup(relayList: Set<String>): Set<NormalizedRelayUrl> = relayList.mapNotNull { RelayUrlNormalizer.normalizeOrNull(it) }.toSet()
val flow =
settings.localRelayServers
.map { normalizeLocalRelayListWithBackup(it) }
.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
normalizeLocalRelayListWithBackup(settings.localRelayServers.value),
)
fun saveRelayList(
relays: List<NormalizedRelayUrl>,
onDone: () -> Unit,
) {
settings.updateLocalRelayServers(relays.map { it.url }.toSet())
onDone()
}
}

View File

@@ -0,0 +1,54 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip01UserMetadata
import com.vitorpamplona.amethyst.model.edits.PrivateStorageRelayListState
import com.vitorpamplona.amethyst.model.localRelays.LocalRelayListState
import com.vitorpamplona.amethyst.model.nip65RelayList.Nip65RelayListState
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.stateIn
class AccountHomeRelayState(
nip65: Nip65RelayListState,
privateStorage: PrivateStorageRelayListState,
local: LocalRelayListState,
scope: CoroutineScope,
) {
val flow =
combine(
nip65.outboxFlow,
privateStorage.flow,
local.flow,
) { nip65Outbox, privateOutBox, localRelays ->
nip65Outbox + privateOutBox + localRelays
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
nip65.outboxFlow.value +
privateStorage.flow.value +
local.flow.value,
)
}

View File

@@ -0,0 +1,58 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip01UserMetadata
import com.vitorpamplona.amethyst.model.edits.PrivateStorageRelayListState
import com.vitorpamplona.amethyst.model.localRelays.LocalRelayListState
import com.vitorpamplona.amethyst.model.nip51Lists.broadcastRelays.BroadcastRelayListState
import com.vitorpamplona.amethyst.model.nip65RelayList.Nip65RelayListState
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.stateIn
class AccountOutboxRelayState(
nip65: Nip65RelayListState,
privateStorage: PrivateStorageRelayListState,
local: LocalRelayListState,
broadcast: BroadcastRelayListState,
scope: CoroutineScope,
) {
val flow =
combine(
nip65.outboxFlow,
privateStorage.flow,
local.flow,
broadcast.flow,
) { nip65Outbox, privateOutBox, localRelays, broadcastRelays ->
nip65Outbox + privateOutBox + localRelays + broadcastRelays
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
nip65.outboxFlow.value +
privateStorage.flow.value +
local.flow.value +
broadcast.flow.value,
)
}

View File

@@ -0,0 +1,49 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip01UserMetadata
import com.vitorpamplona.amethyst.model.localRelays.LocalRelayListState
import com.vitorpamplona.amethyst.model.nip65RelayList.Nip65RelayListState
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.stateIn
class NotificationInboxRelayState(
nip65RelayList: Nip65RelayListState,
localRelayList: LocalRelayListState,
scope: CoroutineScope,
) {
val flow =
combine(
nip65RelayList.inboxFlow,
localRelayList.flow,
) { nip65Inbox, localRelays ->
nip65Inbox + localRelays
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
nip65RelayList.inboxFlow.value + localRelayList.flow.value,
)
}

View File

@@ -0,0 +1,123 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip01UserMetadata
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.model.UserState
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
class UserMetadataState(
val signer: NostrSigner,
val cache: LocalCache,
val scope: CoroutineScope,
val settings: AccountSettings,
) {
// fun getEphemeralChatListAddress() = cache.getOrCreateUser(signer.pubKey)
fun getUserMetadataUser(): User = cache.getOrCreateUser(signer.pubKey)
fun getUserMetadataFlow(): StateFlow<UserState> = getUserMetadataUser().flow().metadata.stateFlow
fun getUserMetadataEvent(): MetadataEvent? = getUserMetadataUser().latestMetadata
suspend fun sendNewUserMetadata(
name: String? = null,
picture: String? = null,
banner: String? = null,
website: String? = null,
pronouns: String? = null,
about: String? = null,
nip05: String? = null,
lnAddress: String? = null,
lnURL: String? = null,
twitter: String? = null,
mastodon: String? = null,
github: String? = null,
): MetadataEvent {
val latest = getUserMetadataEvent()
val template =
if (latest != null) {
MetadataEvent.updateFromPast(
latest = latest,
name = name,
displayName = name,
picture = picture,
banner = banner,
website = website,
pronouns = pronouns,
about = about,
nip05 = nip05,
lnAddress = lnAddress,
lnURL = lnURL,
twitter = twitter,
mastodon = mastodon,
github = github,
)
} else {
MetadataEvent.createNew(
name = name,
displayName = name,
picture = picture,
banner = banner,
website = website,
pronouns = pronouns,
about = about,
nip05 = nip05,
lnAddress = lnAddress,
lnURL = lnURL,
twitter = twitter,
mastodon = mastodon,
github = github,
)
}
return signer.sign(template)
}
init {
settings.backupUserMetadata?.let {
Log.d("AccountRegisterObservers", "Loading saved user metadata ${it.toJson()}")
@OptIn(DelicateCoroutinesApi::class)
GlobalScope.launch(Dispatchers.IO) { LocalCache.justConsumeMyOwnEvent(it) }
}
// saves contact list for the next time.
scope.launch(Dispatchers.Default) {
Log.d("AccountRegisterObservers", "Kind 0 Collector Start")
getUserMetadataFlow().collect {
Log.d("AccountRegisterObservers", "Updating Kind 0 ${it.user.toBestDisplayName()}")
settings.updateUserMetadata(it.user.latestMetadata)
}
}
}
}

View File

@@ -0,0 +1,143 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip02FollowLists
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.NoteState
import com.vitorpamplona.amethyst.model.nip51Lists.blockedRelays.BlockedRelayListState
import com.vitorpamplona.amethyst.model.nip51Lists.proxyRelays.ProxyRelayListState
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListEvent
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.emitAll
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.transformLatest
import kotlin.collections.flatten
class FollowListOutboxOrProxyRelays(
kind3Follows: FollowListState,
blockedRelayList: BlockedRelayListState,
proxyRelayList: ProxyRelayListState,
val cache: LocalCache,
scope: CoroutineScope,
) {
fun getNIP65RelayListAddress(pubkey: HexKey) = AdvertisedRelayListEvent.createAddress(pubkey)
fun getNIP65RelayListNote(pubkey: HexKey): AddressableNote = cache.getOrCreateAddressableNote(getNIP65RelayListAddress(pubkey))
fun getNIP65RelayListFlow(pubkey: HexKey): StateFlow<NoteState> = getNIP65RelayListNote(pubkey).flow().metadata.stateFlow
fun getNIP65RelayList(pubkey: HexKey): AdvertisedRelayListEvent? = getNIP65RelayListNote(pubkey).event as? AdvertisedRelayListEvent
fun allRelayListFlows(followList: Set<HexKey>): List<StateFlow<NoteState>> = followList.map { getNIP65RelayListFlow(it) }
fun combineAllFlows(flows: List<StateFlow<NoteState>>): Flow<Set<NormalizedRelayUrl>> =
combine(flows) { relayListNotes: Array<NoteState> ->
relayListNotes
.mapNotNull {
(it.note.event as? AdvertisedRelayListEvent)?.writeRelaysNorm()
}.flatten()
.toSet()
}
@OptIn(ExperimentalCoroutinesApi::class)
val outboxRelayFlow: StateFlow<Set<NormalizedRelayUrl>> =
kind3Follows.flow
.transformLatest {
emitAll(combineAllFlows(allRelayListFlows(it.authors)))
}.onStart {
emit(
kind3Follows.flow.value.authors
.mapNotNull {
getNIP65RelayList(it)?.writeRelaysNorm()
}.flatten()
.toSet(),
)
}.distinctUntilChanged()
.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
emptySet(),
)
val outboxRelayMinusBlockedFlow: StateFlow<Set<NormalizedRelayUrl>> =
combine(outboxRelayFlow, blockedRelayList.flow) { followList, blockedRelays ->
followList.minus(blockedRelays)
}.onStart {
emit(outboxRelayFlow.value.minus(blockedRelayList.flow.value.toSet()))
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
emptySet(),
)
@OptIn(ExperimentalCoroutinesApi::class)
val flow: StateFlow<Set<NormalizedRelayUrl>> =
proxyRelayList.flow
.flatMapLatest { proxyRelays ->
if (proxyRelays.isEmpty()) {
outboxRelayMinusBlockedFlow
} else {
MutableStateFlow(proxyRelays)
}
}.onStart {
emit(
proxyRelayList.flow.value.ifEmpty {
outboxRelayMinusBlockedFlow.value
},
)
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
emptySet(),
)
@OptIn(ExperimentalCoroutinesApi::class)
val flowSet: StateFlow<Set<String>> =
flow
.map { relayList ->
relayList.mapTo(mutableSetOf()) { it.url }
}.onStart {
emit(flow.value.mapTo(mutableSetOf()) { it.url })
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
emptySet(),
)
}

View File

@@ -0,0 +1,161 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip02FollowLists
import android.util.Log
import androidx.compose.runtime.Immutable
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.model.UserState
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip01Core.tags.geohash.geohashes
import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent
import com.vitorpamplona.quartz.nip02FollowList.tags.ContactTag
import com.vitorpamplona.quartz.nip73ExternalIds.location.GeohashId
import com.vitorpamplona.quartz.nip73ExternalIds.topics.HashtagId
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.transformLatest
import kotlinx.coroutines.launch
class FollowListState(
val signer: NostrSigner,
val cache: LocalCache,
val scope: CoroutineScope,
val settings: AccountSettings,
) {
// fun getEphemeralChatListAddress() = cache.getOrCreateUser(signer.pubKey)
fun getFollowListUser(): User = cache.getOrCreateUser(signer.pubKey)
fun getFollowListFlow(): StateFlow<UserState> = getFollowListUser().flow().follows.stateFlow
fun getFollowListEvent(): ContactListEvent? = getFollowListUser().latestContactList
@OptIn(ExperimentalCoroutinesApi::class)
private val innerFlow: Flow<Kind3Follows> =
getFollowListFlow().transformLatest {
emit(buildKind3Follows(it.user.latestContactList ?: settings.backupContactList))
}
val flow =
innerFlow
.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
// this has priority.
buildKind3Follows(getFollowListEvent() ?: settings.backupContactList),
)
/**
This contains a big OR of everything the user wants to see in the a single feed.
*/
@Immutable
class Kind3Follows(
val authors: Set<String> = emptySet(),
val authorsPlusMe: Set<String>,
val hashtags: Set<String> = emptySet(),
val geotags: Set<String> = emptySet(),
val communities: Set<String> = emptySet(),
) {
val geotagScopes: Set<String> = geotags.mapTo(mutableSetOf<String>()) { GeohashId.toScope(it) }
val hashtagScopes: Set<String> = hashtags.mapTo(mutableSetOf<String>()) { HashtagId.toScope(it) }
}
fun buildKind3Follows(latestContactList: ContactListEvent?): Kind3Follows {
// makes sure the output include only valid p tags
val verifiedFollowingUsers = latestContactList?.verifiedFollowKeySet() ?: emptySet()
return Kind3Follows(
authors = verifiedFollowingUsers,
authorsPlusMe = verifiedFollowingUsers + signer.pubKey,
hashtags =
latestContactList
?.unverifiedFollowTagSet()
?.map { it.lowercase() }
?.toSet() ?: emptySet(),
geotags =
latestContactList
?.geohashes()
?.toSet() ?: emptySet(),
communities =
latestContactList
?.verifiedFollowAddressSet()
?.toSet() ?: emptySet(),
)
}
suspend fun follow(user: User): ContactListEvent {
val contactList = getFollowListEvent()
return if (contactList != null) {
ContactListEvent.followUser(contactList, user.pubkeyHex, signer)
} else {
ContactListEvent.createFromScratch(
followUsers = listOf(ContactTag(user.pubkeyHex, user.bestRelayHint(), null)),
relayUse = emptyMap(),
signer = signer,
)
}
}
suspend fun unfollow(user: User): ContactListEvent? {
val contactList = getFollowListEvent()
return if (contactList != null && contactList.tags.isNotEmpty()) {
ContactListEvent.unfollowUser(
contactList,
user.pubkeyHex,
signer,
)
} else {
null
}
}
init {
settings.backupContactList?.let {
Log.d("AccountRegisterObservers", "Loading saved contacts ${it.toJson()}")
@OptIn(DelicateCoroutinesApi::class)
GlobalScope.launch(Dispatchers.IO) { LocalCache.justConsumeMyOwnEvent(it) }
}
// saves contact list for the next time.
scope.launch(Dispatchers.Default) {
Log.d("AccountRegisterObservers", "Kind 3 Collector Start")
getFollowListFlow().collect {
Log.d("AccountRegisterObservers", "Updating Kind 3 ${signer.pubKey}")
settings.updateContactListTo(it.user.latestContactList)
}
}
}
}

View File

@@ -0,0 +1,146 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip02FollowLists
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.Constants
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.NoteState
import com.vitorpamplona.amethyst.model.nip51Lists.blockedRelays.BlockedRelayListState
import com.vitorpamplona.amethyst.model.nip51Lists.proxyRelays.ProxyRelayListState
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListEvent
import com.vitorpamplona.quartz.utils.mapOfSet
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.emitAll
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.transformLatest
import kotlin.collections.ifEmpty
class FollowsPerOutboxRelay(
kind3Follows: FollowListState,
blockedRelayList: BlockedRelayListState,
proxyRelayList: ProxyRelayListState,
val cache: LocalCache,
scope: CoroutineScope,
) {
fun getNIP65RelayListAddress(pubkey: HexKey) = AdvertisedRelayListEvent.createAddress(pubkey)
fun getNIP65RelayListNote(pubkey: HexKey): AddressableNote = cache.getOrCreateAddressableNote(getNIP65RelayListAddress(pubkey))
fun getNIP65RelayListFlow(pubkey: HexKey): StateFlow<NoteState> = getNIP65RelayListNote(pubkey).flow().metadata.stateFlow
fun getNIP65RelayList(pubkey: HexKey): AdvertisedRelayListEvent? = getNIP65RelayListNote(pubkey).event as? AdvertisedRelayListEvent
fun allRelayListFlows(followList: Set<HexKey>): List<StateFlow<NoteState>> = followList.map { getNIP65RelayListFlow(it) }
fun combineAllRelayListFlows(flows: List<StateFlow<NoteState>>): Flow<Map<NormalizedRelayUrl, Set<HexKey>>> =
combine(flows) { relayListNotes: Array<NoteState> ->
mapOfSet {
relayListNotes.forEach { noteState ->
noteState.note.author?.pubkeyHex?.let { authorHex ->
val outboxRelayList =
getNIP65RelayList(authorHex)?.writeRelaysNorm()
?: LocalCache.relayHints.hintsForKey(authorHex).ifEmpty { null }
?: Constants.eventFinderRelays
outboxRelayList.forEach { relay ->
add(relay, authorHex)
}
}
}
}
}
@OptIn(ExperimentalCoroutinesApi::class)
val outboxPerRelayFlow: StateFlow<Map<NormalizedRelayUrl, Set<HexKey>>> =
kind3Follows.flow
.transformLatest {
emitAll(combineAllRelayListFlows(allRelayListFlows(it.authors)))
}.onStart {
emit(
mapOfSet {
kind3Follows.flow.value.authors.map { authorHex ->
val outboxRelayList =
getNIP65RelayList(authorHex)?.writeRelaysNorm()
?: LocalCache.relayHints.hintsForKey(authorHex).ifEmpty { null }
?: Constants.eventFinderRelays
outboxRelayList.forEach { relay ->
add(relay, authorHex)
}
}
},
)
}.distinctUntilChanged()
.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
emptyMap(),
)
val outboxPerRelayMinusBlockedFlow: StateFlow<Map<NormalizedRelayUrl, Set<HexKey>>> =
combine(outboxPerRelayFlow, blockedRelayList.flow) { followList, blockedRelays ->
followList.minus(blockedRelays)
}.onStart {
emit(outboxPerRelayFlow.value.minus(blockedRelayList.flow.value.toSet()))
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
emptyMap(),
)
@OptIn(ExperimentalCoroutinesApi::class)
val flow: StateFlow<Map<NormalizedRelayUrl, Set<HexKey>>> =
proxyRelayList.flow
.flatMapLatest { proxyRelays ->
if (proxyRelays.isEmpty()) {
outboxPerRelayMinusBlockedFlow
} else {
kind3Follows.flow.map { follows ->
proxyRelays.associateWith { follows.authors }
}
}
}.onStart {
if (proxyRelayList.flow.value.isEmpty()) {
emit(outboxPerRelayMinusBlockedFlow.value)
} else {
emit(proxyRelayList.flow.value.associateWith { kind3Follows.flow.value.authors })
}
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
emptyMap(),
)
}

View File

@@ -0,0 +1,89 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip03Timestamp
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip03Timestamp.OtsEvent
import com.vitorpamplona.quartz.nip03Timestamp.ots.okhttp.OkHttpOtsResolverBuilder
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.update
import java.util.Base64
class OtsState(
val signer: NostrSigner,
val cache: LocalCache,
val otsResolver: OkHttpOtsResolverBuilder,
val scope: CoroutineScope,
val settings: AccountSettings,
) {
suspend fun updateAttestations(): List<OtsEvent> {
Log.d("Pending Attestations", "Updating ${settings.pendingAttestations.value.size} pending attestations")
return settings.pendingAttestations.value.toList().mapNotNull { (key, value) ->
val otsState = OtsEvent.upgrade(Base64.getDecoder().decode(value), key, otsResolver.build())
if (otsState != null) {
val hint = cache.getNoteIfExists(key)?.toEventHint<Event>()
val template =
if (hint != null) {
OtsEvent.build(hint, otsState)
} else {
OtsEvent.build(key, otsState)
}
val otsEvent = signer.sign(template)
settings.pendingAttestations.update { it - key }
otsEvent
} else {
null
}
}
}
fun hasPendingAttestations(note: Note): Boolean {
val id = note.event?.id ?: note.idHex
return settings.pendingAttestations.value[id] != null
}
fun timestamp(note: Note) {
if (note.isDraft()) return
val id = note.event?.id ?: note.idHex
settings.addPendingAttestation(
id = id,
stamp =
Base64.getEncoder().encodeToString(
OtsEvent.stamp(
id,
otsResolver.build(),
),
),
)
}
}

View File

@@ -0,0 +1,59 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip17Dms
import com.vitorpamplona.amethyst.model.edits.PrivateStorageRelayListState
import com.vitorpamplona.amethyst.model.localRelays.LocalRelayListState
import com.vitorpamplona.amethyst.model.nip65RelayList.Nip65RelayListState
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.stateIn
class DmInboxRelayState(
// main relay
dmRelayList: DmRelayListState,
// backup relays
nip65RelayList: Nip65RelayListState,
privateOutbox: PrivateStorageRelayListState,
localRelayList: LocalRelayListState,
scope: CoroutineScope,
) {
val flow =
combine(
nip65RelayList.inboxFlow,
dmRelayList.flow,
privateOutbox.flow,
localRelayList.flow,
) { nip65Inbox, dmRelayList, privateOutBox, localRelays ->
nip65Inbox + dmRelayList + privateOutBox + localRelays
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
nip65RelayList.inboxFlow.value +
dmRelayList.flow.value +
privateOutbox.flow.value +
localRelayList.flow.value,
)
}

View File

@@ -0,0 +1,109 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip17Dms
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip17Dm.settings.ChatMessageRelayListEvent
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
class DmRelayListState(
val signer: NostrSigner,
val cache: LocalCache,
val scope: CoroutineScope,
val settings: AccountSettings,
) {
fun getDMRelayListAddress() = ChatMessageRelayListEvent.createAddress(signer.pubKey)
fun getDMRelayListNote(): AddressableNote = LocalCache.getOrCreateAddressableNote(getDMRelayListAddress())
fun getDMRelayListFlow(): StateFlow<NoteState> = getDMRelayListNote().flow().metadata.stateFlow
fun getDMRelayList(): ChatMessageRelayListEvent? = getDMRelayListNote().event as? ChatMessageRelayListEvent
fun normalizeDMRelayListWithBackup(note: Note): Set<NormalizedRelayUrl> {
val event = note.event as? ChatMessageRelayListEvent ?: settings.backupDMRelayList
return event?.relays()?.toSet() ?: emptySet()
}
val flow =
getDMRelayListFlow()
.map { normalizeDMRelayListWithBackup(it.note) }
.onStart { emit(normalizeDMRelayListWithBackup(getDMRelayListNote())) }
.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
emptySet(),
)
suspend fun saveRelayList(dmRelays: List<NormalizedRelayUrl>): ChatMessageRelayListEvent {
val relayListForDMs = getDMRelayList()
return if (relayListForDMs != null && relayListForDMs.tags.isNotEmpty()) {
ChatMessageRelayListEvent.updateRelayList(
earlierVersion = relayListForDMs,
relays = dmRelays,
signer = signer,
)
} else {
ChatMessageRelayListEvent.create(
relays = dmRelays,
signer = signer,
)
}
}
init {
settings.backupDMRelayList?.let {
Log.d("AccountRegisterObservers", "Loading saved DM Relay List ${it.toJson()}")
@OptIn(DelicateCoroutinesApi::class)
GlobalScope.launch(Dispatchers.IO) {
LocalCache.justConsumeMyOwnEvent(it)
}
}
scope.launch(Dispatchers.Default) {
Log.d("AccountRegisterObservers", "NIP-17 Relay List Collector Start")
getDMRelayListFlow().collect {
Log.d("AccountRegisterObservers", "Updating DM Relay List for ${signer.pubKey}")
(it.note.event as? ChatMessageRelayListEvent)?.let {
settings.updateDMRelayList(it)
}
}
}
}
}

View File

@@ -0,0 +1,55 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip18Reposts
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip18Reposts.GenericRepostEvent
import com.vitorpamplona.quartz.nip18Reposts.RepostEvent
class RepostAction {
companion object {
suspend fun repost(
note: Note,
signer: NostrSigner,
): Event? {
val noteEvent = note.event ?: return null
if (note.hasBoostedInTheLast5Minutes(signer.pubKey)) {
// has already bosted in the past 5mins
return null
}
val noteHint = note.relayHintUrl()
val authorHint = note.author?.bestRelayHint()
val template =
if (noteEvent.kind == 1) {
RepostEvent.build(noteEvent, noteHint, authorHint)
} else {
GenericRepostEvent.build(noteEvent, noteHint, authorHint)
}
return signer.sign(template)
}
}
}

View File

@@ -0,0 +1,103 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip25Reactions
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip17Dm.NIP17Factory
import com.vitorpamplona.quartz.nip17Dm.base.NIP17Group
import com.vitorpamplona.quartz.nip25Reactions.ReactionEvent
import com.vitorpamplona.quartz.nip30CustomEmoji.EmojiUrlTag
class ReactionAction {
companion object {
suspend fun reactTo(
note: Note,
reaction: String,
by: User,
signer: NostrSigner,
onPublic: (ReactionEvent) -> Unit,
onPrivate: suspend (NIP17Factory.Result) -> Unit,
) {
if (!signer.isWriteable()) return
if (note.hasReacted(by, reaction)) {
// has already liked this note
return
}
val noteEvent = note.event
if (noteEvent is NIP17Group) {
val users = noteEvent.groupMembers().toList()
if (reaction.startsWith(":")) {
val emojiUrl = EmojiUrlTag.decode(reaction)
if (emojiUrl != null) {
note.toEventHint<Event>()?.let {
onPrivate(
NIP17Factory().createReactionWithinGroup(
emojiUrl = emojiUrl,
originalNote = it,
to = users,
signer = signer,
),
)
}
return
}
}
note.toEventHint<Event>()?.let {
onPrivate(
NIP17Factory().createReactionWithinGroup(
content = reaction,
originalNote = it,
to = users,
signer = signer,
),
)
}
return
} else {
if (reaction.startsWith(":")) {
val emojiUrl = EmojiUrlTag.decode(reaction)
if (emojiUrl != null) {
note.event?.let {
val template = ReactionEvent.build(emojiUrl, EventHintBundle(it, note.relayHintUrl()))
onPublic(signer.sign(template))
}
return
}
}
note.toEventHint<Event>()?.let {
onPublic(signer.sign(ReactionEvent.build(reaction, it)))
}
}
}
}
}

View File

@@ -0,0 +1,105 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip28PublicChats
import androidx.compose.runtime.Stable
import com.vitorpamplona.amethyst.model.Channel
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.ui.note.toShortDisplay
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
import com.vitorpamplona.quartz.nip01Core.hints.types.EventIdHintOptional
import com.vitorpamplona.quartz.nip02FollowList.EmptyTagList
import com.vitorpamplona.quartz.nip02FollowList.toImmutableListOfLists
import com.vitorpamplona.quartz.nip19Bech32.entities.NEvent
import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelCreateEvent
import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelMetadataEvent
import com.vitorpamplona.quartz.nip28PublicChat.base.ChannelDataNorm
@Stable
class PublicChatChannel(
val idHex: String,
) : Channel() {
var creator: User? = null
var event: ChannelCreateEvent? = null
var eventNote: Note? = null
var info = ChannelDataNorm(null, null, null, null)
var infoTags = EmptyTagList
var updatedMetadataAt: Long = 0
override fun relays() = info.relays?.toSet() ?: super.relays()
fun relayHintUrls() = relays().take(3)
fun relayHintUrl() = relays().firstOrNull()
fun toNEvent() = NEvent.create(idHex, event?.pubKey, ChannelCreateEvent.KIND, relayHintUrls())
fun toNostrUri() = "nostr:${toNEvent()}"
fun toEventHint() = event?.let { EventHintBundle(it, relayHintUrl(), null) }
fun toEventId() = EventIdHintOptional(idHex, relayHintUrl())
fun updateChannelInfo(
creator: User,
event: ChannelCreateEvent,
eventNote: Note? = null,
) {
this.creator = creator
this.event = event
this.info = event.channelInfo()
this.infoTags = event.tags.toImmutableListOfLists()
this.updatedMetadataAt = event.createdAt
this.eventNote = eventNote
updateChannelInfo()
}
fun updateChannelInfo(
creator: User,
event: ChannelMetadataEvent,
) {
this.creator = creator
this.info = event.channelInfo()
this.infoTags = event.tags.toImmutableListOfLists()
this.updatedMetadataAt = event.createdAt
super.updateChannelInfo()
}
override fun toBestDisplayName(): String = info.name ?: toNEvent().toShortDisplay()
fun summary(): String? = info.about
fun profilePicture(): String? {
if (info.picture.isNullOrBlank()) return creator?.info?.banner
return info.picture ?: creator?.info?.banner
}
fun anyNameStartsWith(prefix: String): Boolean =
idHex.startsWith(prefix) ||
info.name?.contains(prefix, true) == true ||
info.about?.contains(prefix, true) == true
}

View File

@@ -0,0 +1,41 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip28PublicChats
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip28PublicChat.list.ChannelListEvent
import com.vitorpamplona.quartz.nip28PublicChat.list.channelSet
import com.vitorpamplona.quartz.nip28PublicChat.list.channels
import com.vitorpamplona.quartz.nip51Lists.PrivateTagArrayEventCache
class PublicChatListDecryptionCache(
val signer: NostrSigner,
) {
val cachedPrivateLists = PrivateTagArrayEventCache<ChannelListEvent>(signer)
fun cachedChannelSet(event: ChannelListEvent) = cachedPrivateLists.mergeTagListPrecached(event).channelSet()
fun cachedChannels(event: ChannelListEvent) = cachedPrivateLists.mergeTagListPrecached(event).channels()
suspend fun channelSet(event: ChannelListEvent) = cachedPrivateLists.mergeTagList(event).channelSet()
suspend fun channels(event: ChannelListEvent) = cachedPrivateLists.mergeTagList(event).channels()
}

View File

@@ -0,0 +1,145 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip28PublicChats
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip28PublicChat.list.ChannelListEvent
import com.vitorpamplona.quartz.nip28PublicChat.list.tags.ChannelTag
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.transformLatest
import kotlinx.coroutines.launch
class PublicChatListState(
val signer: NostrSigner,
val cache: LocalCache,
val decryptionCache: PublicChatListDecryptionCache,
val scope: CoroutineScope,
val settings: AccountSettings,
) {
fun getChannelListAddress() = ChannelListEvent.createAddress(signer.pubKey)
fun getChannelListNote(): AddressableNote = cache.getOrCreateAddressableNote(getChannelListAddress())
fun getChannelListFlow(): StateFlow<NoteState> = getChannelListNote().flow().metadata.stateFlow
fun getChannelList(): ChannelListEvent? = getChannelListNote().event as? ChannelListEvent
suspend fun publicChatListWithBackup(note: Note): Set<ChannelTag> {
val event = note.event as? ChannelListEvent ?: settings.backupChannelList
return event?.let { decryptionCache.channelSet(it) } ?: emptySet()
}
@OptIn(ExperimentalCoroutinesApi::class)
val flow: StateFlow<Set<ChannelTag>> =
getChannelListFlow()
.transformLatest { noteState ->
emit(publicChatListWithBackup(noteState.note))
}.onStart {
emit(publicChatListWithBackup(getChannelListNote()))
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
emptySet(),
)
@OptIn(ExperimentalCoroutinesApi::class)
val flowSet: StateFlow<Set<HexKey>> =
flow
.map {
it.mapTo(mutableSetOf()) { it.eventId }
}.onStart {
emit(flow.value.mapTo(mutableSetOf()) { it.eventId })
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
emptySet(),
)
suspend fun follow(channel: PublicChatChannel): ChannelListEvent {
val publicChatList = getChannelList()
return if (publicChatList == null) {
ChannelListEvent.create(ChannelTag(channel.idHex, channel.relayHintUrl()), true, signer)
} else {
ChannelListEvent.add(publicChatList, ChannelTag(channel.idHex, channel.relayHintUrl()), true, signer)
}
}
suspend fun follow(channels: List<PublicChatChannel>): ChannelListEvent {
val publicChatList = getChannelList()
val channelTags = channels.map { ChannelTag(it.idHex, it.relayHintUrl()) }
return if (publicChatList == null) {
ChannelListEvent.create(channelTags, true, signer)
} else {
ChannelListEvent.add(publicChatList, channelTags, true, signer)
}
}
suspend fun unfollow(channel: PublicChatChannel): ChannelListEvent? {
val publicChatList = getChannelList()
return if (publicChatList != null) {
ChannelListEvent.remove(publicChatList, ChannelTag(channel.idHex, channel.relayHintUrl()), signer)
} else {
null
}
}
init {
settings.backupChannelList?.let { event ->
Log.d("AccountRegisterObservers", "Loading saved channel list ${event.toJson()}")
@OptIn(DelicateCoroutinesApi::class)
GlobalScope.launch(Dispatchers.IO) {
LocalCache.justConsumeMyOwnEvent(event)
}
}
scope.launch(Dispatchers.Default) {
Log.d("AccountRegisterObservers", "Channel List Collector Start")
getChannelListFlow().collect {
Log.d("AccountRegisterObservers", "Channel List for ${signer.pubKey}")
(it.note.event as? ChannelListEvent)?.let {
settings.updateChannelListTo(it)
}
}
}
}
}

View File

@@ -0,0 +1,155 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip30CustomEmojis
import com.vitorpamplona.amethyst.commons.richtext.MediaUrlImage
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip01Core.tags.addressables.taggedAddresses
import com.vitorpamplona.quartz.nip30CustomEmoji.pack.EmojiPackEvent
import com.vitorpamplona.quartz.nip30CustomEmoji.selection.EmojiPackSelectionEvent
import com.vitorpamplona.quartz.nip30CustomEmoji.taggedEmojis
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combineTransform
import kotlinx.coroutines.flow.emitAll
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.transformLatest
class EmojiPackState(
val signer: NostrSigner,
val cache: LocalCache,
val scope: CoroutineScope,
) {
class EmojiMedia(
val code: String,
val link: MediaUrlImage,
)
fun getEmojiPackSelectionAddress() = EmojiPackSelectionEvent.createAddress(signer.pubKey)
fun getEmojiPackSelection(): EmojiPackSelectionEvent? = getEmojiPackSelectionNote().event as? EmojiPackSelectionEvent
fun getEmojiPackSelectionFlow(): StateFlow<NoteState> = getEmojiPackSelectionNote().flow().metadata.stateFlow
fun getEmojiPackSelectionNote(): AddressableNote = cache.getOrCreateAddressableNote(getEmojiPackSelectionAddress())
fun convertEmojiSelectionPack(selection: EmojiPackSelectionEvent?): List<StateFlow<NoteState>>? =
selection?.taggedAddresses()?.map {
cache
.getOrCreateAddressableNote(it)
.flow()
.metadata.stateFlow
}
@OptIn(ExperimentalCoroutinesApi::class)
val flow: StateFlow<List<StateFlow<NoteState>>?> =
getEmojiPackSelectionFlow()
.transformLatest {
emit(convertEmojiSelectionPack(it.note.event as? EmojiPackSelectionEvent))
}.onStart {
emit(convertEmojiSelectionPack(getEmojiPackSelection()))
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
emptyList(),
)
fun convertEmojiPack(pack: EmojiPackEvent): List<EmojiMedia> =
pack.taggedEmojis().map {
EmojiMedia(it.code, MediaUrlImage(it.url))
}
fun mergePack(list: Array<NoteState>): List<EmojiMedia> =
list
.mapNotNull {
val ev = it.note.event as? EmojiPackEvent
if (ev != null) {
convertEmojiPack(ev)
} else {
null
}
}.flatten()
.distinctBy { it.link }
@OptIn(ExperimentalCoroutinesApi::class)
val myEmojis =
flow
.transformLatest { emojiList ->
if (emojiList != null) {
emitAll(
combineTransform(emojiList) {
emit(mergePack(it))
},
)
} else {
emit(emptyList())
}
}.onStart {
emit(
mergePack(
convertEmojiSelectionPack(
getEmojiPackSelection(),
)?.map { it.value }?.toTypedArray() ?: emptyArray(),
),
)
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
emptyList(),
)
suspend fun addEmojiPack(emojiPack: Note): EmojiPackSelectionEvent {
val emojiPackEvent = emojiPack.event
if (emojiPackEvent !is EmojiPackEvent) throw IllegalArgumentException("Cannot add an emoji pack to this kind of event.")
val eventHint = emojiPack.toEventHint<EmojiPackEvent>() ?: throw IllegalArgumentException("Cannot add an emoji pack to this kind of event.")
val usersEmojiList = getEmojiPackSelection()
return if (usersEmojiList == null) {
val template = EmojiPackSelectionEvent.build(listOf(eventHint))
signer.sign(template)
} else {
val template = EmojiPackSelectionEvent.add(usersEmojiList, eventHint)
signer.sign(template)
}
}
suspend fun removeEmojiPack(emojiPack: Note): EmojiPackSelectionEvent? {
val usersEmojiList = getEmojiPackSelection() ?: throw IllegalArgumentException("Cannot remove an emoji pack to this kind of event.")
val emojiPackEvent = emojiPack.event
if (emojiPackEvent !is EmojiPackEvent) return null
val template = EmojiPackSelectionEvent.remove(usersEmojiList, emojiPackEvent)
return signer.sign(template)
}
}

View File

@@ -0,0 +1,62 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip38UserStatuses
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip09Deletions.DeletionEvent
import com.vitorpamplona.quartz.nip38UserStatus.StatusEvent
class UserStatusAction {
companion object {
suspend fun create(
newStatus: String,
signer: NostrSigner,
): StatusEvent = StatusEvent.create(newStatus, "general", expiration = null, signer)
suspend fun update(
oldStatus: AddressableNote,
newStatus: String,
signer: NostrSigner,
): StatusEvent {
val oldEvent = oldStatus.event as? StatusEvent ?: throw IllegalStateException("Tried to update a non-status event")
return StatusEvent.update(oldEvent, newStatus, signer)
}
suspend fun delete(
oldStatus: AddressableNote,
signer: NostrSigner,
): List<Event> {
val oldEvent = oldStatus.event as? StatusEvent ?: throw IllegalStateException("Tried to update a non-status event")
val event = StatusEvent.clear(oldEvent, signer)
val deletion =
signer.sign(
DeletionEvent.buildForVersionOnly(listOf(event)),
)
return listOf(event, deletion)
}
}
}

View File

@@ -0,0 +1,181 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip47WalletConnect
import com.vitorpamplona.amethyst.Amethyst
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.nwc.NWCPaymentQueryState
import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
import com.vitorpamplona.quartz.nip47WalletConnect.LnZapPaymentRequestEvent
import com.vitorpamplona.quartz.nip47WalletConnect.LnZapPaymentResponseEvent
import com.vitorpamplona.quartz.nip47WalletConnect.Nip47WalletConnect
import com.vitorpamplona.quartz.nip47WalletConnect.NostrWalletConnectRequestCache
import com.vitorpamplona.quartz.nip47WalletConnect.NostrWalletConnectResponseCache
import com.vitorpamplona.quartz.nip47WalletConnect.Request
import com.vitorpamplona.quartz.nip47WalletConnect.Response
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
/**
* Manages NIP-47 (Nostr Wallet Connect) related signing operations and decryption cache for a given account.
*
* Key Responsibilities:
*
* - Dynamically creates a NIP-47 signer if the wallet setup changes in the account settings.
* - Provides decryption caches to manage decrypted NIP-47 requests and responses efficiently.
* - Handles creating of zap payment requests and waits for responses.
*
* @property signer the main Nostr signer used for general Nostr operations
* @property cache the local cache for handling notes and events
* @property scope the coroutine scope used for async operations
* @property settings the account settings containing NIP-47 configuration
*/
class NwcSignerState(
val signer: NostrSigner,
val cache: LocalCache,
val scope: CoroutineScope,
val settings: AccountSettings,
) {
/**
* Derives a NIP-47 signer from the zap payment request in settings.
* If there's no valid configuration, it defaults to the main signer.
* Flows updates whenever settings change.
*/
val nip47Signer =
settings.zapPaymentRequest
.map {
buildSigner(it) ?: signer
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
buildSigner(settings.zapPaymentRequest.value) ?: signer,
)
/**
* Creates a dedicated request decryption cache for the NIP-47 signer.
* Flows updates whenever the signer changes.
*/
val zapPaymentRequestDecryptionCache =
nip47Signer
.map {
NostrWalletConnectRequestCache(it)
}.flowOn(Dispatchers.Default)
.stateIn(scope, SharingStarted.Eagerly, NostrWalletConnectRequestCache(nip47Signer.value))
/**
* Creates a dedicated response decryption cache for the NIP-47 signer.
* Flows updates whenever the signer changes.
*/
val zapPaymentResponseDecryptionCache =
nip47Signer
.map {
NostrWalletConnectResponseCache(it)
}.flowOn(Dispatchers.Default)
.stateIn(scope, SharingStarted.Eagerly, NostrWalletConnectResponseCache(nip47Signer.value))
fun buildSigner(uri: Nip47WalletConnect.Nip47URINorm?) =
uri?.secret?.hexToByteArray()?.let {
NostrSignerInternal(KeyPair(it))
}
fun hasWalletConnectSetup(): Boolean = settings.zapPaymentRequest.value != null
fun isNIP47Author(pubkeyHex: String?): Boolean = nip47Signer.value.pubKey == pubkeyHex
/**
* Decrypts a NIP-47 payment request using the current signer.
*
* @param nwcRequest the NIP-47 payment request event to decrypt
* @return the decrypted request or null if not set up or decryption fails
*/
suspend fun decryptRequest(nwcRequest: LnZapPaymentRequestEvent): Request? {
if (!hasWalletConnectSetup()) return null
return zapPaymentRequestDecryptionCache.value.decryptRequest(nwcRequest)
}
/**
* Decrypts a NIP-47 payment response using the current signer.
*
* @param nwsResponse the NIP-47 payment response event to decrypt
* @return the decrypted response or null if not set up or decryption fails
*/
suspend fun decryptResponse(nwsResponse: LnZapPaymentResponseEvent): Response? {
if (!hasWalletConnectSetup()) return null
return zapPaymentResponseDecryptionCache.value.decryptResponse(nwsResponse)
}
/**
* Sends a zap payment request to a connected Lightning wallet.
* Subscribes to responses and waits up to 60s for a reply.
*
* @param bolt11 the BOLT-11 invoice to pay
* @param zappedNote the note being zapped (if any)
* @param onResponse callback to handle the response from the wallet
* @return a pair containing the payment request event and target relay URL
* @throws IllegalArgumentException if no NIP-47 wallet is set up
*/
suspend fun sendZapPaymentRequestFor(
bolt11: String,
zappedNote: Note?,
onResponse: (Response?) -> Unit,
): Pair<LnZapPaymentRequestEvent, NormalizedRelayUrl> {
val walletService = settings.zapPaymentRequest.value
if (walletService == null) throw IllegalArgumentException("No NIP47 setup")
val event = LnZapPaymentRequestEvent.create(bolt11, walletService.pubKeyHex, nip47Signer.value)
val filter =
NWCPaymentQueryState(
fromServiceHex = walletService.pubKeyHex,
toUserHex = event.pubKey,
replyingToHex = event.id,
relay = walletService.relayUri,
)
Amethyst.instance.sources.nwc
.subscribe(filter)
scope.launch(Dispatchers.IO) {
delay(60000) // waits 1 minute to complete payment.
Amethyst.instance.sources.nwc
.unsubscribe(filter)
}
cache.consume(event, zappedNote, true, walletService.relayUri) {
onResponse(decryptResponse(it))
}
return Pair(event, walletService.relayUri)
}
}

View File

@@ -0,0 +1,276 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip51Lists
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip51Lists.bookmarkList.BookmarkListEvent
import com.vitorpamplona.quartz.nip51Lists.bookmarkList.tags.AddressBookmark
import com.vitorpamplona.quartz.nip51Lists.bookmarkList.tags.BookmarkIdTag
import com.vitorpamplona.quartz.nip51Lists.bookmarkList.tags.EventBookmark
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combineTransform
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
class BookmarkListState(
val signer: NostrSigner,
val cache: LocalCache,
val scope: CoroutineScope,
) {
class BookmarkList(
val public: List<Note> = emptyList(),
val private: List<Note> = emptyList(),
)
fun getBookmarkListAddress() = BookmarkListEvent.createBookmarkAddress(signer.pubKey)
fun getBookmarkListNote() = cache.getOrCreateAddressableNote(getBookmarkListAddress())
fun getBookmarkListFlow(): StateFlow<NoteState> = getBookmarkListNote().flow().metadata.stateFlow
fun getBookmarkList(): BookmarkListEvent? = getBookmarkListNote().event as? BookmarkListEvent
suspend fun publicBookmarks(note: Note): List<BookmarkIdTag> {
val noteEvent = note.event as? BookmarkListEvent
return noteEvent?.publicBookmarks() ?: emptyList()
}
suspend fun privateBookmarks(note: Note): List<BookmarkIdTag> {
val noteEvent = note.event as? BookmarkListEvent
return noteEvent?.privateBookmarks(signer) ?: emptyList()
}
@OptIn(FlowPreview::class)
val publicBookmarks: StateFlow<List<BookmarkIdTag>> =
getBookmarkListFlow()
.map { noteState ->
publicBookmarks(noteState.note)
}.onStart {
emit(publicBookmarks(getBookmarkListNote()))
}.debounce(100)
.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
emptyList(),
)
@OptIn(FlowPreview::class)
val privateBookmarks: StateFlow<List<BookmarkIdTag>> =
getBookmarkListFlow()
.map { noteState ->
privateBookmarks(noteState.note)
}.onStart {
emit(privateBookmarks(getBookmarkListNote()))
}.debounce(100)
.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
emptyList(),
)
val publicBookmarkEventIdSet =
publicBookmarks
.map { bookmark ->
bookmark
.mapNotNull {
if (it is EventBookmark) it.eventId else null
}.toSet()
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
emptyList(),
)
val publicBookmarkAddressIdSet =
publicBookmarks
.map { bookmark ->
bookmark
.mapNotNull {
if (it is AddressBookmark) it.address else null
}.toSet()
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
emptyList(),
)
val privateBookmarkEventIdSet =
privateBookmarks
.map { bookmark ->
bookmark
.mapNotNull {
if (it is EventBookmark) it.eventId else null
}.toSet()
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
emptyList(),
)
val privateBookmarkAddressIdSet =
privateBookmarks
.map { bookmark ->
bookmark
.mapNotNull {
if (it is AddressBookmark) it.address else null
}.toSet()
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
emptyList(),
)
fun bookmarkList(
privateBookmarks: List<BookmarkIdTag>,
publicBookmarks: List<BookmarkIdTag>,
): BookmarkList =
BookmarkList(
public =
publicBookmarks
.mapNotNull {
when (it) {
is EventBookmark -> cache.checkGetOrCreateNote(it.eventId)
is AddressBookmark -> cache.getOrCreateAddressableNote(it.address)
}
}.reversed(),
private =
privateBookmarks
.mapNotNull {
when (it) {
is EventBookmark -> cache.checkGetOrCreateNote(it.eventId)
is AddressBookmark -> cache.getOrCreateAddressableNote(it.address)
}
}.reversed(),
)
@OptIn(FlowPreview::class)
val bookmarks: StateFlow<BookmarkList> =
combineTransform(privateBookmarks, publicBookmarks) { private, public ->
emit(bookmarkList(private, public))
}.onStart {
emit(bookmarkList(privateBookmarks.value, publicBookmarks.value))
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
BookmarkList(),
)
fun isInPrivateBookmarks(note: Note): Boolean {
if (!signer.isWriteable()) return false
return if (note is AddressableNote) {
privateBookmarkAddressIdSet.value.contains(note.address)
} else {
privateBookmarkEventIdSet.value.contains(note.idHex)
}
}
fun isInPublicBookmarks(note: Note): Boolean =
if (note is AddressableNote) {
publicBookmarkAddressIdSet.value.contains(note.address)
} else {
publicBookmarkEventIdSet.value.contains(note.idHex)
}
suspend fun addBookmark(
note: Note,
isPrivate: Boolean,
): BookmarkListEvent {
val bookmarkList = getBookmarkList()
return if (bookmarkList == null) {
if (note is AddressableNote) {
BookmarkListEvent.create(
bookmarkIdTag = AddressBookmark(note.address, note.relayHintUrl()),
isPrivate = isPrivate,
signer = signer,
)
} else {
BookmarkListEvent.create(
bookmarkIdTag = EventBookmark(note.idHex, note.relayHintUrl()),
isPrivate = isPrivate,
signer = signer,
)
}
} else {
if (note is AddressableNote) {
BookmarkListEvent.add(
earlierVersion = bookmarkList,
bookmarkIdTag = AddressBookmark(note.address, note.relayHintUrl()),
isPrivate = isPrivate,
signer = signer,
)
} else {
BookmarkListEvent.add(
earlierVersion = bookmarkList,
bookmarkIdTag = EventBookmark(note.idHex, note.relayHintUrl()),
isPrivate = isPrivate,
signer = signer,
)
}
}
}
suspend fun removeBookmark(
note: Note,
isPrivate: Boolean,
): BookmarkListEvent? {
val bookmarkList = getBookmarkList()
return if (bookmarkList != null) {
if (note is AddressableNote) {
BookmarkListEvent.remove(
earlierVersion = bookmarkList,
bookmarkIdTag = AddressBookmark(note.address, note.relayHintUrl()),
isPrivate = isPrivate,
signer = signer,
)
} else {
BookmarkListEvent.remove(
earlierVersion = bookmarkList,
bookmarkIdTag = EventBookmark(note.idHex, note.relayHintUrl()),
isPrivate = isPrivate,
signer = signer,
)
}
} else {
null
}
}
}

View File

@@ -0,0 +1,118 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip51Lists
import androidx.compose.runtime.Immutable
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.service.checkNotInMainThread
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip51Lists.muteList.tags.MuteTag
import com.vitorpamplona.quartz.nip51Lists.muteList.tags.UserTag
import com.vitorpamplona.quartz.nip51Lists.muteList.tags.WordTag
import com.vitorpamplona.quartz.utils.DualCase
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combineTransform
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
class HiddenUsersState(
val muteList: StateFlow<List<MuteTag>>,
val blockList: StateFlow<List<MuteTag>>,
val scope: CoroutineScope,
val settings: AccountSettings,
) {
var transientHiddenUsers: MutableStateFlow<Set<String>> = MutableStateFlow(setOf())
@Immutable
class LiveHiddenUsers(
val hiddenUsers: Set<String>,
val spammers: Set<String>,
val hiddenWords: Set<String>,
val showSensitiveContent: Boolean?,
) {
// speeds up isHidden calculations
val hiddenUsersHashCodes = hiddenUsers.mapTo(HashSet()) { it.hashCode() }
val spammersHashCodes = spammers.mapTo(HashSet()) { it.hashCode() }
val hiddenWordsCase = hiddenWords.map { DualCase(it.lowercase(), it.uppercase()) }
fun isUserHidden(userHex: HexKey) = hiddenUsers.contains(userHex) || spammers.contains(userHex)
}
suspend fun assembleLiveHiddenUsers(
blockList: List<MuteTag>,
muteList: List<MuteTag>,
transientHiddenUsers: Set<String>,
showSensitiveContent: Boolean?,
): LiveHiddenUsers =
LiveHiddenUsers(
hiddenUsers = blockList.mapNotNullTo(mutableSetOf()) { if (it is UserTag) it.pubKey else null } + muteList.mapNotNull { if (it is UserTag) it.pubKey else null },
hiddenWords = blockList.mapNotNullTo(mutableSetOf()) { if (it is WordTag) it.word else null } + muteList.mapNotNull { if (it is WordTag) it.word else null },
spammers = transientHiddenUsers,
showSensitiveContent = showSensitiveContent,
)
val flow: StateFlow<LiveHiddenUsers> =
combineTransform(
blockList,
muteList,
transientHiddenUsers,
settings.syncedSettings.security.showSensitiveContent,
) { blockList, muteList, transientHiddenUsers, showSensitiveContent ->
checkNotInMainThread()
emit(assembleLiveHiddenUsers(blockList, muteList, transientHiddenUsers, showSensitiveContent))
}.onStart {
emit(
assembleLiveHiddenUsers(
blockList.value,
muteList.value,
transientHiddenUsers.value,
settings.syncedSettings.security.showSensitiveContent.value,
),
)
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
LiveHiddenUsers(emptySet(), emptySet(), emptySet(), null),
)
fun resetTransientUsers() {
transientHiddenUsers.update {
emptySet()
}
}
fun showUser(pubkeyHex: HexKey) {
transientHiddenUsers.update { it - pubkeyHex }
}
fun hideUser(pubkeyHex: HexKey) {
transientHiddenUsers.update { it + pubkeyHex }
}
fun isHidden(pubkeyHex: HexKey) = pubkeyHex in transientHiddenUsers.value
}

View File

@@ -0,0 +1,118 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip51Lists.blockPeopleList
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip51Lists.muteList.tags.MuteTag
import com.vitorpamplona.quartz.nip51Lists.muteList.tags.UserTag
import com.vitorpamplona.quartz.nip51Lists.muteList.tags.WordTag
import com.vitorpamplona.quartz.nip51Lists.peopleList.PeopleListEvent
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
class BlockPeopleListState(
val signer: NostrSigner,
val cache: LocalCache,
val decryptionCache: PeopleListDecryptionCache,
val scope: CoroutineScope,
) {
fun getBlockListAddress() = PeopleListEvent.createBlockAddress(signer.pubKey)
fun getBlockListNote() = LocalCache.getOrCreateAddressableNote(getBlockListAddress())
fun getBlockListFlow(): StateFlow<NoteState> = getBlockListNote().flow().metadata.stateFlow
fun getBlockList(): PeopleListEvent? = getBlockListNote().event as? PeopleListEvent
suspend fun blockListWithBackup(note: Note): List<MuteTag> {
val event = note.event as? PeopleListEvent
return event?.let { decryptionCache.usersAndWords(it) } ?: emptyList()
}
val flow =
getBlockListFlow()
.map { blockListWithBackup(it.note) }
.onStart { emit(blockListWithBackup(getBlockListNote())) }
.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
emptyList(),
)
suspend fun hideUser(pubkeyHex: String): PeopleListEvent {
val blockList = getBlockList()
return if (blockList != null) {
PeopleListEvent.add(
earlierVersion = blockList,
person = UserTag(pubkeyHex),
isPrivate = true,
signer = signer,
)
} else {
PeopleListEvent.create(
name = PeopleListEvent.BLOCK_LIST_D_TAG,
person = UserTag(pubkeyHex),
isPrivate = true,
signer = signer,
dTag = PeopleListEvent.BLOCK_LIST_D_TAG,
)
}
}
suspend fun showUser(pubkeyHex: String): PeopleListEvent? {
val blockList = getBlockList()
return if (blockList != null) {
PeopleListEvent.remove(
earlierVersion = blockList,
person = UserTag(pubkeyHex),
signer = signer,
)
} else {
null
}
}
suspend fun showWord(word: String): PeopleListEvent? {
val blockList = getBlockList()
return if (blockList != null) {
PeopleListEvent.remove(
earlierVersion = blockList,
person = WordTag(word),
signer = signer,
)
} else {
null
}
}
}

View File

@@ -0,0 +1,56 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip51Lists.blockPeopleList
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip51Lists.PrivateTagArrayEventCache
import com.vitorpamplona.quartz.nip51Lists.muteList.mutedUserIdSet
import com.vitorpamplona.quartz.nip51Lists.muteList.mutedUsers
import com.vitorpamplona.quartz.nip51Lists.muteList.mutedUsersAndWords
import com.vitorpamplona.quartz.nip51Lists.muteList.mutedWordSet
import com.vitorpamplona.quartz.nip51Lists.muteList.mutedWords
import com.vitorpamplona.quartz.nip51Lists.peopleList.PeopleListEvent
class PeopleListDecryptionCache(
val signer: NostrSigner,
) {
val cachedPrivateLists = PrivateTagArrayEventCache<PeopleListEvent>(signer)
fun cachedUsersAndWords(event: PeopleListEvent) = cachedPrivateLists.mergeTagListPrecached(event).mutedUsersAndWords()
fun cachedUsers(event: PeopleListEvent) = cachedPrivateLists.mergeTagListPrecached(event).mutedUsers()
fun cachedUserIdSet(event: PeopleListEvent) = cachedPrivateLists.mergeTagListPrecached(event).mutedUserIdSet()
fun cachedWords(event: PeopleListEvent) = cachedPrivateLists.mergeTagListPrecached(event).mutedWords()
fun cachedWordSet(event: PeopleListEvent) = cachedPrivateLists.mergeTagListPrecached(event).mutedWordSet()
suspend fun usersAndWords(event: PeopleListEvent) = cachedPrivateLists.mergeTagList(event).mutedUsersAndWords()
suspend fun users(event: PeopleListEvent) = cachedPrivateLists.mergeTagList(event).mutedUsers()
suspend fun userIdSet(event: PeopleListEvent) = cachedPrivateLists.mergeTagList(event).mutedUserIdSet()
suspend fun words(event: PeopleListEvent) = cachedPrivateLists.mergeTagList(event).mutedWords()
suspend fun wordSet(event: PeopleListEvent) = cachedPrivateLists.mergeTagList(event).mutedWordSet()
}

View File

@@ -0,0 +1,29 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip51Lists.blockedRelays
import com.vitorpamplona.amethyst.model.nip51Lists.relayLists.GenericRelayListCache
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip51Lists.relayLists.BlockedRelayListEvent
class BlockedRelayListDecryptionCache(
signer: NostrSigner,
) : GenericRelayListCache<BlockedRelayListEvent>(signer)

View File

@@ -0,0 +1,112 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip51Lists.blockedRelays
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip01Core.signers.SignerExceptions
import com.vitorpamplona.quartz.nip51Lists.relayLists.BlockedRelayListEvent
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
class BlockedRelayListState(
val signer: NostrSigner,
val cache: LocalCache,
val decryptionCache: BlockedRelayListDecryptionCache,
val scope: CoroutineScope,
val settings: AccountSettings,
) {
fun getBlockedRelayListAddress() = BlockedRelayListEvent.createAddress(signer.pubKey)
fun getBlockedRelayListNote(): AddressableNote = LocalCache.getOrCreateAddressableNote(getBlockedRelayListAddress())
fun getBlockedRelayListFlow(): StateFlow<NoteState> = getBlockedRelayListNote().flow().metadata.stateFlow
fun getBlockedRelayList(): BlockedRelayListEvent? = getBlockedRelayListNote().event as? BlockedRelayListEvent
suspend fun normalizeBlockedRelayListWithBackup(note: Note): Set<NormalizedRelayUrl> {
val event = note.event as? BlockedRelayListEvent ?: settings.backupBlockedRelayList
return event?.let { decryptionCache.relays(it) } ?: emptySet()
}
val flow =
getBlockedRelayListFlow()
.map {
normalizeBlockedRelayListWithBackup(it.note)
}.onStart { emit(normalizeBlockedRelayListWithBackup(getBlockedRelayListNote())) }
.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
emptySet(),
)
suspend fun saveRelayList(blockedRelays: List<NormalizedRelayUrl>): BlockedRelayListEvent {
if (!signer.isWriteable()) throw SignerExceptions.ReadOnlyException()
val relayListForBlocked = getBlockedRelayList()
return if (relayListForBlocked != null && relayListForBlocked.tags.isNotEmpty()) {
BlockedRelayListEvent.updateRelayList(
earlierVersion = relayListForBlocked,
relays = blockedRelays,
signer = signer,
)
} else {
BlockedRelayListEvent.create(
relays = blockedRelays,
signer = signer,
)
}
}
init {
settings.backupBlockedRelayList?.let {
Log.d("AccountRegisterObservers", "Loading saved Blocked relay list ${it.toJson()}")
@OptIn(DelicateCoroutinesApi::class)
GlobalScope.launch(Dispatchers.IO) { LocalCache.justConsumeMyOwnEvent(it) }
}
scope.launch(Dispatchers.Default) {
Log.d("AccountRegisterObservers", "Blocked Relay List Collector Start")
getBlockedRelayListFlow().collect {
Log.d("AccountRegisterObservers", "Updating Blocked Relay List for ${signer.pubKey}")
(it.note.event as? BlockedRelayListEvent)?.let {
settings.updateBlockedRelayList(it)
}
}
}
}
}

View File

@@ -0,0 +1,29 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip51Lists.broadcastRelays
import com.vitorpamplona.amethyst.model.nip51Lists.relayLists.GenericRelayListCache
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip51Lists.relayLists.BroadcastRelayListEvent
class BroadcastRelayListDecryptionCache(
signer: NostrSigner,
) : GenericRelayListCache<BroadcastRelayListEvent>(signer)

View File

@@ -0,0 +1,87 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip51Lists.broadcastRelays
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip51Lists.relayLists.BroadcastRelayListEvent
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
class BroadcastRelayListState(
val signer: NostrSigner,
val cache: LocalCache,
val decryptionCache: BroadcastRelayListDecryptionCache,
val scope: CoroutineScope,
val settings: AccountSettings,
) {
fun getBroadcastRelayListAddress() = BroadcastRelayListEvent.createAddress(signer.pubKey)
fun getBroadcastRelayListNote(): AddressableNote = cache.getOrCreateAddressableNote(getBroadcastRelayListAddress())
fun getBroadcastRelayListFlow(): StateFlow<NoteState> = getBroadcastRelayListNote().flow().metadata.stateFlow
fun getBroadcastRelayList(): BroadcastRelayListEvent? = getBroadcastRelayListNote().event as? BroadcastRelayListEvent
suspend fun normalizeBroadcastRelayListWithBackup(note: Note): Set<NormalizedRelayUrl> {
val event = note.event as? BroadcastRelayListEvent
return event?.let { decryptionCache.relays(it) } ?: emptySet()
}
val flow =
getBroadcastRelayListFlow()
.map { normalizeBroadcastRelayListWithBackup(it.note) }
.onStart { emit(normalizeBroadcastRelayListWithBackup(getBroadcastRelayListNote())) }
.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
emptySet(),
)
suspend fun saveRelayList(broadcastRelays: List<NormalizedRelayUrl>): BroadcastRelayListEvent {
val relayListForBroadcast = getBroadcastRelayList()
return if (relayListForBroadcast != null && relayListForBroadcast.tags.isNotEmpty()) {
BroadcastRelayListEvent.updateRelayList(
earlierVersion = relayListForBroadcast,
relays = broadcastRelays,
signer = signer,
)
} else {
BroadcastRelayListEvent.create(
relays = broadcastRelays,
signer = signer,
)
}
}
}

View File

@@ -0,0 +1,27 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip51Lists.geohashLists
data class GeohashListCard(
val relays: List<String>,
)
val EmptyGeohashListCard = GeohashListCard(emptyList())

View File

@@ -0,0 +1,76 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip51Lists.geohashLists
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip51Lists.PrivateTagArrayEventCache
import com.vitorpamplona.quartz.nip51Lists.geohashList.GeohashListEvent
import com.vitorpamplona.quartz.nip51Lists.geohashList.geohashSet
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.onStart
class GeohashListDecryptionCache(
val signer: NostrSigner,
) {
val cachedPrivateLists = PrivateTagArrayEventCache<GeohashListEvent>(signer)
fun cachedGeohashes(event: GeohashListEvent) = cachedPrivateLists.mergeTagListPrecached(event).geohashSet()
suspend fun geohashes(event: GeohashListEvent) = cachedPrivateLists.mergeTagList(event).geohashSet()
fun fastStartValueForGeohashList(note: Note): GeohashListCard {
val noteEvent = note.event as? GeohashListEvent
return if (noteEvent != null) {
GeohashListCard(cachedGeohashes(noteEvent).toList())
} else {
EmptyGeohashListCard
}
}
@OptIn(ExperimentalCoroutinesApi::class)
fun observeDecryptedGeohashList(note: Note): Flow<GeohashListCard> =
note
.flow()
.metadata.stateFlow
.mapLatest { noteState ->
val event = noteState.note.event as? GeohashListEvent
GeohashListCard(event?.let { geohashes(it).toList() } ?: emptyList())
}.onStart {
val event = note.event as? GeohashListEvent
if (event != null) {
val list = geohashes(event)
if (list.isNotEmpty()) {
emit(GeohashListCard(list.toList()))
} else {
emit(EmptyGeohashListCard)
}
} else {
emit(EmptyGeohashListCard)
}
}.distinctUntilChanged()
.flowOn(Dispatchers.Default)
}

View File

@@ -0,0 +1,127 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip51Lists.geohashLists
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip51Lists.geohashList.GeohashListEvent
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.transformLatest
import kotlinx.coroutines.launch
class GeohashListState(
val signer: NostrSigner,
val cache: LocalCache,
val decryptionCache: GeohashListDecryptionCache,
val scope: CoroutineScope,
val settings: AccountSettings,
) {
fun getGeohashListAddress() = GeohashListEvent.createAddress(signer.pubKey)
fun getGeohashListNote(): AddressableNote = cache.getOrCreateAddressableNote(getGeohashListAddress())
fun getGeohashListFlow(): StateFlow<NoteState> = getGeohashListNote().flow().metadata.stateFlow
fun getGeohashList(): GeohashListEvent? = getGeohashListNote().event as? GeohashListEvent
suspend fun geohashListWithBackup(note: Note): Set<String> {
val event = note.event as? GeohashListEvent ?: settings.backupGeohashList
return event?.let { decryptionCache.geohashes(it) } ?: emptySet()
}
@OptIn(ExperimentalCoroutinesApi::class)
val flow: StateFlow<Set<String>> =
getGeohashListFlow()
.transformLatest { noteState ->
emit(geohashListWithBackup(noteState.note))
}.onStart {
emit(geohashListWithBackup(getGeohashListNote()))
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
emptySet(),
)
suspend fun follow(geohashes: List<String>): GeohashListEvent {
val geohashList = getGeohashList()
return if (geohashList == null) {
GeohashListEvent.create(geohashes, true, signer)
} else {
GeohashListEvent.add(geohashList, geohashes, true, signer)
}
}
suspend fun follow(geohash: String): GeohashListEvent {
val geohashList = getGeohashList()
return if (geohashList == null) {
GeohashListEvent.create(geohash, true, signer)
} else {
GeohashListEvent.add(geohashList, geohash, true, signer)
}
}
suspend fun unfollow(geohash: String): GeohashListEvent? {
val geohashList = getGeohashList()
return if (geohashList != null) {
GeohashListEvent.remove(geohashList, geohash, signer)
} else {
null
}
}
init {
settings.backupGeohashList?.let { event ->
Log.d("AccountRegisterObservers", "Loading saved Geohash list ${event.toJson()}")
@OptIn(DelicateCoroutinesApi::class)
GlobalScope.launch(Dispatchers.IO) {
LocalCache.justConsumeMyOwnEvent(event)
}
}
scope.launch(Dispatchers.Default) {
Log.d("AccountRegisterObservers", "Geohash List Collector Start")
getGeohashListFlow().collect { noteState ->
Log.d("AccountRegisterObservers", "Geohash List for ${signer.pubKey}")
(noteState.note.event as? GeohashListEvent)?.let {
settings.updateGeohashListTo(it)
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip51Lists.hashtagLists
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip51Lists.PrivateTagArrayEventCache
import com.vitorpamplona.quartz.nip51Lists.hashtagList.HashtagListEvent
import com.vitorpamplona.quartz.nip51Lists.hashtagList.hashtagSet
class HashtagListDecryptionCache(
val signer: NostrSigner,
) {
val cachedPrivateLists = PrivateTagArrayEventCache<HashtagListEvent>(signer)
fun cachedHashtags(event: HashtagListEvent) = cachedPrivateLists.mergeTagListPrecached(event).hashtagSet()
suspend fun hashtags(event: HashtagListEvent) = cachedPrivateLists.mergeTagList(event).hashtagSet()
}

View File

@@ -0,0 +1,127 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip51Lists.hashtagLists
import android.util.Log
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip51Lists.hashtagList.HashtagListEvent
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.transformLatest
import kotlinx.coroutines.launch
class HashtagListState(
val signer: NostrSigner,
val cache: LocalCache,
val decryptionCache: HashtagListDecryptionCache,
val scope: CoroutineScope,
val settings: AccountSettings,
) {
fun getHashtagListAddress() = HashtagListEvent.createAddress(signer.pubKey)
fun getHashtagListNote(): AddressableNote = cache.getOrCreateAddressableNote(getHashtagListAddress())
fun getHashtagListFlow(): StateFlow<NoteState> = getHashtagListNote().flow().metadata.stateFlow
fun getHashtagList(): HashtagListEvent? = getHashtagListNote().event as? HashtagListEvent
suspend fun hashtagListWithBackup(note: Note): Set<String> {
val event = note.event as? HashtagListEvent ?: settings.backupHashtagList
return event?.let { decryptionCache.hashtags(it) } ?: emptySet()
}
@OptIn(ExperimentalCoroutinesApi::class)
val flow: StateFlow<Set<String>> =
getHashtagListFlow()
.transformLatest { noteState ->
emit(hashtagListWithBackup(noteState.note))
}.onStart {
emit(hashtagListWithBackup(getHashtagListNote()))
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Companion.Eagerly,
emptySet(),
)
suspend fun follow(hashtags: List<String>): HashtagListEvent {
val hashtagList = getHashtagList()
return if (hashtagList == null) {
HashtagListEvent.Companion.create(hashtags, true, signer)
} else {
HashtagListEvent.Companion.add(hashtagList, hashtags, true, signer)
}
}
suspend fun follow(hashtag: String): HashtagListEvent {
val hashtagList = getHashtagList()
return if (hashtagList == null) {
HashtagListEvent.Companion.create(hashtag, true, signer)
} else {
HashtagListEvent.Companion.add(hashtagList, hashtag, true, signer)
}
}
suspend fun unfollow(hashtag: String): HashtagListEvent? {
val hashtagList = getHashtagList()
return if (hashtagList != null) {
HashtagListEvent.Companion.remove(hashtagList, hashtag, signer)
} else {
null
}
}
init {
settings.backupHashtagList?.let { event ->
Log.d("AccountRegisterObservers", "Loading saved Hashtag list ${event.toJson()}")
@OptIn(DelicateCoroutinesApi::class)
GlobalScope.launch(Dispatchers.IO) {
LocalCache.justConsumeMyOwnEvent(event)
}
}
scope.launch(Dispatchers.Default) {
Log.d("AccountRegisterObservers", "Hashtag List Collector Start")
getHashtagListFlow().collect {
Log.d("AccountRegisterObservers", "Hashtag List for ${signer.pubKey}")
(it.note.event as? HashtagListEvent)?.let {
settings.updateHashtagListTo(it)
}
}
}
}
}

View File

@@ -0,0 +1,29 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip51Lists.indexerRelays
import com.vitorpamplona.amethyst.model.nip51Lists.relayLists.GenericRelayListCache
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip51Lists.relayLists.IndexerRelayListEvent
class IndexerRelayListDecryptionCache(
signer: NostrSigner,
) : GenericRelayListCache<IndexerRelayListEvent>(signer)

View File

@@ -0,0 +1,88 @@
/**
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.model.nip51Lists.indexerRelays
import com.vitorpamplona.amethyst.model.AccountSettings
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.NoteState
import com.vitorpamplona.amethyst.model.nip51Lists.indexerRelays.IndexerRelayListDecryptionCache
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip51Lists.relayLists.IndexerRelayListEvent
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
class IndexerRelayListState(
val signer: NostrSigner,
val cache: LocalCache,
val decryptionCache: IndexerRelayListDecryptionCache,
val scope: CoroutineScope,
val settings: AccountSettings,
) {
fun getIndexerRelayListAddress() = IndexerRelayListEvent.createAddress(signer.pubKey)
fun getIndexerRelayListNote(): AddressableNote = cache.getOrCreateAddressableNote(getIndexerRelayListAddress())
fun getIndexerRelayListFlow(): StateFlow<NoteState> = getIndexerRelayListNote().flow().metadata.stateFlow
fun getIndexerRelayList(): IndexerRelayListEvent? = getIndexerRelayListNote().event as? IndexerRelayListEvent
suspend fun normalizeIndexerRelayListWithBackup(note: Note): Set<NormalizedRelayUrl> {
val event = note.event as? IndexerRelayListEvent
return event?.let { decryptionCache.relays(it) } ?: emptySet()
}
val flow =
getIndexerRelayListFlow()
.map { normalizeIndexerRelayListWithBackup(it.note) }
.onStart { emit(normalizeIndexerRelayListWithBackup(getIndexerRelayListNote())) }
.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
emptySet(),
)
suspend fun saveRelayList(indexerRelays: List<NormalizedRelayUrl>): IndexerRelayListEvent {
val relayListForIndexer = getIndexerRelayList()
return if (relayListForIndexer != null && relayListForIndexer.tags.isNotEmpty()) {
IndexerRelayListEvent.updateRelayList(
earlierVersion = relayListForIndexer,
relays = indexerRelays,
signer = signer,
)
} else {
IndexerRelayListEvent.create(
relays = indexerRelays,
signer = signer,
)
}
}
}

Some files were not shown because too many files have changed in this diff Show More