mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-10-05 19:28:25 +00:00
- Updates several libraries
- Reformats code to the newest Klint - Fixes isEmpty bug on Filters
This commit is contained in:
Generated
+1
-1
@@ -11,6 +11,6 @@
|
||||
<option name="languageVersion" value="2.3" />
|
||||
</component>
|
||||
<component name="KotlinJpsPluginSettings">
|
||||
<option name="version" value="2.3.0" />
|
||||
<option name="version" value="2.3.10" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -898,59 +898,101 @@ object LocalCache : ILocalCache, ICacheProvider {
|
||||
@Suppress("DEPRECATION")
|
||||
fun computeReplyTo(event: Event): List<Note> =
|
||||
when (event) {
|
||||
is PollNoteEvent -> event.tagsWithoutCitations().mapNotNull { checkGetOrCreateNote(it) }
|
||||
is LongTextNoteEvent -> event.tagsWithoutCitations().mapNotNull { checkGetOrCreateNote(it) }
|
||||
is GitReplyEvent -> event.tagsWithoutCitations().filter { it != event.repository()?.toTag() }.mapNotNull { checkGetOrCreateNote(it) }
|
||||
is TextNoteEvent -> event.tagsWithoutCitations().mapNotNull { checkGetOrCreateNote(it) }
|
||||
is CommentEvent -> event.tagsWithoutCitations().mapNotNull { checkGetOrCreateNote(it) }
|
||||
is PollNoteEvent -> {
|
||||
event.tagsWithoutCitations().mapNotNull { checkGetOrCreateNote(it) }
|
||||
}
|
||||
|
||||
is VoiceReplyEvent -> event.markedReplyTos().mapNotNull { checkGetOrCreateNote(it) }
|
||||
is LongTextNoteEvent -> {
|
||||
event.tagsWithoutCitations().mapNotNull { checkGetOrCreateNote(it) }
|
||||
}
|
||||
|
||||
is ChatMessageEvent -> event.taggedEvents().mapNotNull { checkGetOrCreateNote(it) }
|
||||
is ChatMessageEncryptedFileHeaderEvent -> event.taggedEvents().mapNotNull { checkGetOrCreateNote(it) }
|
||||
is GitReplyEvent -> {
|
||||
event.tagsWithoutCitations().filter { it != event.repository()?.toTag() }.mapNotNull { checkGetOrCreateNote(it) }
|
||||
}
|
||||
|
||||
is LnZapEvent ->
|
||||
is TextNoteEvent -> {
|
||||
event.tagsWithoutCitations().mapNotNull { checkGetOrCreateNote(it) }
|
||||
}
|
||||
|
||||
is CommentEvent -> {
|
||||
event.tagsWithoutCitations().mapNotNull { checkGetOrCreateNote(it) }
|
||||
}
|
||||
|
||||
is VoiceReplyEvent -> {
|
||||
event.markedReplyTos().mapNotNull { checkGetOrCreateNote(it) }
|
||||
}
|
||||
|
||||
is ChatMessageEvent -> {
|
||||
event.taggedEvents().mapNotNull { checkGetOrCreateNote(it) }
|
||||
}
|
||||
|
||||
is ChatMessageEncryptedFileHeaderEvent -> {
|
||||
event.taggedEvents().mapNotNull { checkGetOrCreateNote(it) }
|
||||
}
|
||||
|
||||
is LnZapEvent -> {
|
||||
event.zappedPost().mapNotNull { checkGetOrCreateNote(it) } +
|
||||
event.taggedAddresses().map { getOrCreateAddressableNote(it) } +
|
||||
(event.zapRequest?.taggedAddresses()?.map { getOrCreateAddressableNote(it) } ?: emptyList())
|
||||
is LnZapRequestEvent ->
|
||||
}
|
||||
|
||||
is LnZapRequestEvent -> {
|
||||
event.zappedPost().mapNotNull { checkGetOrCreateNote(it) } +
|
||||
event.taggedAddresses().map { getOrCreateAddressableNote(it) }
|
||||
is BadgeProfilesEvent ->
|
||||
}
|
||||
|
||||
is BadgeProfilesEvent -> {
|
||||
event.badgeAwardEvents().mapNotNull { checkGetOrCreateNote(it) } +
|
||||
event.badgeAwardDefinitions().map { getOrCreateAddressableNote(it) }
|
||||
is BadgeAwardEvent -> event.awardDefinition().map { getOrCreateAddressableNote(it) }
|
||||
is PrivateDmEvent -> event.taggedEvents().mapNotNull { checkGetOrCreateNote(it) }
|
||||
is RepostEvent ->
|
||||
}
|
||||
|
||||
is BadgeAwardEvent -> {
|
||||
event.awardDefinition().map { getOrCreateAddressableNote(it) }
|
||||
}
|
||||
|
||||
is PrivateDmEvent -> {
|
||||
event.taggedEvents().mapNotNull { checkGetOrCreateNote(it) }
|
||||
}
|
||||
|
||||
is RepostEvent -> {
|
||||
listOfNotNull(
|
||||
event.boostedEventId()?.let { checkGetOrCreateNote(it) },
|
||||
event.boostedAddress()?.let { getOrCreateAddressableNote(it) },
|
||||
)
|
||||
is GenericRepostEvent ->
|
||||
}
|
||||
|
||||
is GenericRepostEvent -> {
|
||||
listOfNotNull(
|
||||
event.boostedEventId()?.let { checkGetOrCreateNote(it) },
|
||||
event.boostedAddress()?.let { getOrCreateAddressableNote(it) },
|
||||
)
|
||||
is CommunityPostApprovalEvent ->
|
||||
}
|
||||
|
||||
is CommunityPostApprovalEvent -> {
|
||||
event.approvedEvents().mapNotNull { checkGetOrCreateNote(it) } +
|
||||
event.approvedAddresses().map { getOrCreateAddressableNote(it) }
|
||||
is ReactionEvent ->
|
||||
}
|
||||
|
||||
is ReactionEvent -> {
|
||||
event.originalPost().mapNotNull { checkGetOrCreateNote(it) } +
|
||||
event.taggedAddresses().map { getOrCreateAddressableNote(it) }
|
||||
is ChannelMessageEvent ->
|
||||
event
|
||||
.tagsWithoutCitations()
|
||||
.filter { it != event.channelId() }
|
||||
.mapNotNull { checkGetOrCreateNote(it) }
|
||||
is LiveActivitiesChatMessageEvent ->
|
||||
event
|
||||
.tagsWithoutCitations()
|
||||
.filter { it != event.activity()?.toTag() }
|
||||
.mapNotNull { checkGetOrCreateNote(it) }
|
||||
is TorrentCommentEvent ->
|
||||
event.tagsWithoutCitations().mapNotNull { checkGetOrCreateNote(it) }
|
||||
}
|
||||
|
||||
else -> emptyList()
|
||||
is ChannelMessageEvent -> {
|
||||
event.tagsWithoutCitations().filter { it != event.channelId() }.mapNotNull { checkGetOrCreateNote(it) }
|
||||
}
|
||||
|
||||
is LiveActivitiesChatMessageEvent -> {
|
||||
event.tagsWithoutCitations().filter { it != event.activity()?.toTag() }.mapNotNull { checkGetOrCreateNote(it) }
|
||||
}
|
||||
|
||||
is TorrentCommentEvent -> {
|
||||
event.tagsWithoutCitations().mapNotNull { checkGetOrCreateNote(it) }
|
||||
}
|
||||
|
||||
else -> {
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
fun consume(
|
||||
@@ -2691,27 +2733,38 @@ object LocalCache : ILocalCache, ICacheProvider {
|
||||
|
||||
fun consume(nip19: Entity) {
|
||||
when (nip19) {
|
||||
is NSec -> getOrCreateUser(nip19.toPubKeyHex())
|
||||
is NPub -> getOrCreateUser(nip19.hex)
|
||||
is NSec -> {
|
||||
getOrCreateUser(nip19.toPubKeyHex())
|
||||
}
|
||||
|
||||
is NPub -> {
|
||||
getOrCreateUser(nip19.hex)
|
||||
}
|
||||
|
||||
is NProfile -> {
|
||||
nip19.relay.forEach { relayHint ->
|
||||
relayHints.addKey(nip19.hex, relayHint)
|
||||
}
|
||||
getOrCreateUser(nip19.hex)
|
||||
}
|
||||
|
||||
is NNote -> {
|
||||
getOrCreateNote(nip19.hex)
|
||||
}
|
||||
|
||||
is NEvent -> {
|
||||
nip19.relay.forEach { relayHint ->
|
||||
relayHints.addEvent(nip19.hex, relayHint)
|
||||
}
|
||||
getOrCreateNote(nip19.hex)
|
||||
}
|
||||
|
||||
is NEmbed -> {
|
||||
justConsume(nip19.event, null, false)
|
||||
}
|
||||
|
||||
is NRelay -> {}
|
||||
|
||||
is NAddress -> {
|
||||
val aTag = nip19.aTag()
|
||||
nip19.relay.forEach { relayHint ->
|
||||
@@ -2719,6 +2772,7 @@ object LocalCache : ILocalCache, ICacheProvider {
|
||||
}
|
||||
getOrCreateAddressableNote(nip19.address())
|
||||
}
|
||||
|
||||
else -> { }
|
||||
}
|
||||
}
|
||||
@@ -2966,10 +3020,7 @@ object LocalCache : ILocalCache, ICacheProvider {
|
||||
is VoiceReplyEvent -> consume(event, relay, wasVerified)
|
||||
is WikiNoteEvent -> consume(event, relay, wasVerified)
|
||||
is PaymentTargetsEvent -> consume(event, relay, wasVerified)
|
||||
else -> {
|
||||
Log.w("Event Not Supported", "From ${relay?.url}: ${event.toJson()}")
|
||||
false
|
||||
}
|
||||
else -> Log.w("Event Not Supported", "From ${relay?.url}: ${event.toJson()}").let { false }
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
if (e is CancellationException) throw e
|
||||
|
||||
@@ -168,6 +168,7 @@ fun parseResourceBundleOrNull(json: String): FhirElementDatabase? {
|
||||
is Bundle -> {
|
||||
resource.entry.associateBy { it.id }.toImmutableMap()
|
||||
}
|
||||
|
||||
else -> {
|
||||
persistentMapOf(resource.id to resource)
|
||||
}
|
||||
|
||||
@@ -54,9 +54,7 @@ fun parseThemeType(code: Int?): ThemeType =
|
||||
ThemeType.SYSTEM.screenCode -> ThemeType.SYSTEM
|
||||
ThemeType.LIGHT.screenCode -> ThemeType.LIGHT
|
||||
ThemeType.DARK.screenCode -> ThemeType.DARK
|
||||
else -> {
|
||||
ThemeType.SYSTEM
|
||||
}
|
||||
else -> ThemeType.SYSTEM
|
||||
}
|
||||
|
||||
enum class ConnectivityType(
|
||||
@@ -91,9 +89,7 @@ fun parseConnectivityType(code: Boolean?): ConnectivityType =
|
||||
ConnectivityType.ALWAYS.prefCode -> ConnectivityType.ALWAYS
|
||||
ConnectivityType.WIFI_ONLY.prefCode -> ConnectivityType.WIFI_ONLY
|
||||
ConnectivityType.NEVER.prefCode -> ConnectivityType.NEVER
|
||||
else -> {
|
||||
ConnectivityType.ALWAYS
|
||||
}
|
||||
else -> ConnectivityType.ALWAYS
|
||||
}
|
||||
|
||||
fun parseConnectivityType(screenCode: Int): ConnectivityType =
|
||||
@@ -101,9 +97,7 @@ fun parseConnectivityType(screenCode: Int): ConnectivityType =
|
||||
ConnectivityType.ALWAYS.screenCode -> ConnectivityType.ALWAYS
|
||||
ConnectivityType.WIFI_ONLY.screenCode -> ConnectivityType.WIFI_ONLY
|
||||
ConnectivityType.NEVER.screenCode -> ConnectivityType.NEVER
|
||||
else -> {
|
||||
ConnectivityType.ALWAYS
|
||||
}
|
||||
else -> ConnectivityType.ALWAYS
|
||||
}
|
||||
|
||||
fun parseFeatureSetType(screenCode: Int): FeatureSetType =
|
||||
@@ -111,18 +105,14 @@ fun parseFeatureSetType(screenCode: Int): FeatureSetType =
|
||||
FeatureSetType.COMPLETE.screenCode -> FeatureSetType.COMPLETE
|
||||
FeatureSetType.SIMPLIFIED.screenCode -> FeatureSetType.SIMPLIFIED
|
||||
FeatureSetType.PERFORMANCE.screenCode -> FeatureSetType.PERFORMANCE
|
||||
else -> {
|
||||
FeatureSetType.COMPLETE
|
||||
}
|
||||
else -> FeatureSetType.COMPLETE
|
||||
}
|
||||
|
||||
fun parseGalleryType(screenCode: Int): ProfileGalleryType =
|
||||
when (screenCode) {
|
||||
ProfileGalleryType.CLASSIC.screenCode -> ProfileGalleryType.CLASSIC
|
||||
ProfileGalleryType.MODERN.screenCode -> ProfileGalleryType.MODERN
|
||||
else -> {
|
||||
ProfileGalleryType.CLASSIC
|
||||
}
|
||||
else -> ProfileGalleryType.CLASSIC
|
||||
}
|
||||
|
||||
enum class BooleanType(
|
||||
@@ -138,18 +128,14 @@ fun parseBooleanType(code: Boolean?): BooleanType =
|
||||
when (code) {
|
||||
BooleanType.ALWAYS.prefCode -> BooleanType.ALWAYS
|
||||
BooleanType.NEVER.prefCode -> BooleanType.NEVER
|
||||
else -> {
|
||||
BooleanType.ALWAYS
|
||||
}
|
||||
else -> BooleanType.ALWAYS
|
||||
}
|
||||
|
||||
fun parseBooleanType(screenCode: Int): BooleanType =
|
||||
when (screenCode) {
|
||||
BooleanType.ALWAYS.screenCode -> BooleanType.ALWAYS
|
||||
BooleanType.NEVER.screenCode -> BooleanType.NEVER
|
||||
else -> {
|
||||
BooleanType.ALWAYS
|
||||
}
|
||||
else -> BooleanType.ALWAYS
|
||||
}
|
||||
|
||||
enum class WarningType(
|
||||
@@ -167,9 +153,7 @@ fun parseWarningType(screenCode: Int): WarningType =
|
||||
WarningType.WARN.screenCode -> WarningType.WARN
|
||||
WarningType.SHOW.screenCode -> WarningType.SHOW
|
||||
WarningType.HIDE.screenCode -> WarningType.HIDE
|
||||
else -> {
|
||||
WarningType.WARN
|
||||
}
|
||||
else -> WarningType.WARN
|
||||
}
|
||||
|
||||
fun parseWarningType(code: Boolean?): WarningType =
|
||||
@@ -177,7 +161,5 @@ fun parseWarningType(code: Boolean?): WarningType =
|
||||
WarningType.WARN.prefCode -> WarningType.WARN
|
||||
WarningType.HIDE.prefCode -> WarningType.HIDE
|
||||
WarningType.SHOW.prefCode -> WarningType.SHOW
|
||||
else -> {
|
||||
WarningType.WARN
|
||||
}
|
||||
else -> WarningType.WARN
|
||||
}
|
||||
|
||||
+6
-2
@@ -68,13 +68,17 @@ class AccountCacheState(
|
||||
NostrSignerInternal(accountSettings.keyPair)
|
||||
} else {
|
||||
when (val packageName = accountSettings.externalSignerPackageName) {
|
||||
null -> NostrSignerInternal(accountSettings.keyPair)
|
||||
else ->
|
||||
null -> {
|
||||
NostrSignerInternal(accountSettings.keyPair)
|
||||
}
|
||||
|
||||
else -> {
|
||||
NostrSignerExternal(
|
||||
pubKey = accountSettings.keyPair.pubKey.toHexKey(),
|
||||
packageName = packageName,
|
||||
contentResolver = contentResolverFn(),
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
accountSettings = accountSettings,
|
||||
|
||||
+9
-2
@@ -74,7 +74,10 @@ class Nip11CachedRetriever(
|
||||
val doc = relayInformationDocumentCache.get(relay)
|
||||
if (doc != null) {
|
||||
when (doc) {
|
||||
is RetrieveResult.Success -> onInfo(doc.data)
|
||||
is RetrieveResult.Success -> {
|
||||
onInfo(doc.data)
|
||||
}
|
||||
|
||||
is RetrieveResult.Loading -> {
|
||||
if (doc.isValid()) {
|
||||
// just wait.
|
||||
@@ -82,6 +85,7 @@ class Nip11CachedRetriever(
|
||||
retrieve(relay, onInfo, onError)
|
||||
}
|
||||
}
|
||||
|
||||
is RetrieveResult.Error -> {
|
||||
if (doc.isValid()) {
|
||||
onError(relay, doc.error, null)
|
||||
@@ -89,7 +93,10 @@ class Nip11CachedRetriever(
|
||||
retrieve(relay, onInfo, onError)
|
||||
}
|
||||
}
|
||||
is RetrieveResult.Empty -> retrieve(relay, onInfo, onError)
|
||||
|
||||
is RetrieveResult.Empty -> {
|
||||
retrieve(relay, onInfo, onError)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
retrieve(relay, onInfo, onError)
|
||||
|
||||
+20
-5
@@ -64,11 +64,26 @@ class FeedTopNavFilterState(
|
||||
) {
|
||||
fun loadFlowsFor(listName: String): IFeedFlowsType =
|
||||
when (listName) {
|
||||
GLOBAL_FOLLOWS -> GlobalFeedFlow(followsRelays, proxyRelays)
|
||||
ALL_FOLLOWS -> AllFollowsFeedFlow(allFollows, followsRelays, blockedRelays, proxyRelays)
|
||||
ALL_USER_FOLLOWS -> AllUserFollowsFeedFlow(allFollows, followsRelays, blockedRelays, proxyRelays)
|
||||
KIND3_FOLLOWS -> Kind3UserFollowsFeedFlow(kind3Follows, followsRelays, blockedRelays, proxyRelays)
|
||||
AROUND_ME -> AroundMeFeedFlow(locationFlow, followsRelays, proxyRelays)
|
||||
GLOBAL_FOLLOWS -> {
|
||||
GlobalFeedFlow(followsRelays, proxyRelays)
|
||||
}
|
||||
|
||||
ALL_FOLLOWS -> {
|
||||
AllFollowsFeedFlow(allFollows, followsRelays, blockedRelays, proxyRelays)
|
||||
}
|
||||
|
||||
ALL_USER_FOLLOWS -> {
|
||||
AllUserFollowsFeedFlow(allFollows, followsRelays, blockedRelays, proxyRelays)
|
||||
}
|
||||
|
||||
KIND3_FOLLOWS -> {
|
||||
Kind3UserFollowsFeedFlow(kind3Follows, followsRelays, blockedRelays, proxyRelays)
|
||||
}
|
||||
|
||||
AROUND_ME -> {
|
||||
AroundMeFeedFlow(locationFlow, followsRelays, proxyRelays)
|
||||
}
|
||||
|
||||
else -> {
|
||||
val note = LocalCache.checkGetOrCreateAddressableNote(listName)
|
||||
if (note != null) {
|
||||
|
||||
+38
-4
@@ -68,21 +68,27 @@ class NoteFeedFlow(
|
||||
AuthorsByOutboxTopNavFilter(caches.peopleListCache.cachedUserIdSet(noteEvent), blockedRelays)
|
||||
}
|
||||
}
|
||||
|
||||
is MuteListEvent -> {
|
||||
MutedAuthorsByOutboxTopNavFilter(caches.muteListCache.cachedUserIdSet(noteEvent), blockedRelays)
|
||||
}
|
||||
|
||||
is FollowListEvent -> {
|
||||
AuthorsByOutboxTopNavFilter(noteEvent.followIdSet(), blockedRelays)
|
||||
}
|
||||
|
||||
is CommunityListEvent -> {
|
||||
AllCommunitiesTopNavFilter(caches.communityListCache.cachedCommunityIdSet(noteEvent), blockedRelays)
|
||||
}
|
||||
|
||||
is HashtagListEvent -> {
|
||||
HashtagTopNavFilter(caches.hashtagCache.cachedHashtags(noteEvent), outboxRelays)
|
||||
}
|
||||
|
||||
is GeohashListEvent -> {
|
||||
LocationTopNavFilter(caches.geohashCache.cachedGeohashes(noteEvent), outboxRelays)
|
||||
}
|
||||
|
||||
is CommunityDefinitionEvent -> {
|
||||
SingleCommunityTopNavFilter(
|
||||
community = noteEvent.addressTag(),
|
||||
@@ -91,7 +97,10 @@ class NoteFeedFlow(
|
||||
blockedRelays = blockedRelays,
|
||||
)
|
||||
}
|
||||
else -> AuthorsByOutboxTopNavFilter(emptySet(), blockedRelays)
|
||||
|
||||
else -> {
|
||||
AuthorsByOutboxTopNavFilter(emptySet(), blockedRelays)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun FlowCollector<IFeedTopNavFilter>.processByOutbox(
|
||||
@@ -106,21 +115,27 @@ class NoteFeedFlow(
|
||||
emit(AuthorsByOutboxTopNavFilter(caches.peopleListCache.userIdSet(noteEvent), blockedRelays))
|
||||
}
|
||||
}
|
||||
|
||||
is MuteListEvent -> {
|
||||
emit(MutedAuthorsByOutboxTopNavFilter(caches.muteListCache.mutedUserIdSet(noteEvent), blockedRelays))
|
||||
}
|
||||
|
||||
is FollowListEvent -> {
|
||||
emit(AuthorsByOutboxTopNavFilter(noteEvent.followIdSet(), blockedRelays))
|
||||
}
|
||||
|
||||
is CommunityListEvent -> {
|
||||
emit(AllCommunitiesTopNavFilter(caches.communityListCache.communityIdSet(noteEvent), blockedRelays))
|
||||
}
|
||||
|
||||
is HashtagListEvent -> {
|
||||
emit(HashtagTopNavFilter(caches.hashtagCache.hashtags(noteEvent), outboxRelays))
|
||||
}
|
||||
|
||||
is GeohashListEvent -> {
|
||||
emit(LocationTopNavFilter(caches.geohashCache.geohashes(noteEvent), outboxRelays))
|
||||
}
|
||||
|
||||
is CommunityDefinitionEvent -> {
|
||||
emit(
|
||||
SingleCommunityTopNavFilter(
|
||||
@@ -131,10 +146,12 @@ class NoteFeedFlow(
|
||||
),
|
||||
)
|
||||
}
|
||||
else ->
|
||||
|
||||
else -> {
|
||||
emit(
|
||||
AuthorsByOutboxTopNavFilter(emptySet(), blockedRelays),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,21 +167,27 @@ class NoteFeedFlow(
|
||||
AuthorsByProxyTopNavFilter(caches.peopleListCache.cachedUserIdSet(noteEvent), proxyRelays)
|
||||
}
|
||||
}
|
||||
|
||||
is MuteListEvent -> {
|
||||
MutedAuthorsByProxyTopNavFilter(caches.muteListCache.cachedUserIdSet(noteEvent), proxyRelays)
|
||||
}
|
||||
|
||||
is FollowListEvent -> {
|
||||
AuthorsByProxyTopNavFilter(noteEvent.followIdSet(), proxyRelays)
|
||||
}
|
||||
|
||||
is CommunityListEvent -> {
|
||||
AllCommunitiesTopNavFilter(caches.communityListCache.cachedCommunityIdSet(noteEvent), blockedRelays)
|
||||
}
|
||||
|
||||
is HashtagListEvent -> {
|
||||
HashtagTopNavFilter(caches.hashtagCache.cachedHashtags(noteEvent), proxyRelays)
|
||||
}
|
||||
|
||||
is GeohashListEvent -> {
|
||||
LocationTopNavFilter(caches.geohashCache.cachedGeohashes(noteEvent), proxyRelays)
|
||||
}
|
||||
|
||||
is CommunityDefinitionEvent -> {
|
||||
SingleCommunityTopNavFilter(
|
||||
community = noteEvent.addressTag(),
|
||||
@@ -173,7 +196,10 @@ class NoteFeedFlow(
|
||||
blockedRelays = blockedRelays,
|
||||
)
|
||||
}
|
||||
else -> AuthorsByProxyTopNavFilter(emptySet(), proxyRelays)
|
||||
|
||||
else -> {
|
||||
AuthorsByProxyTopNavFilter(emptySet(), proxyRelays)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun FlowCollector<IFeedTopNavFilter>.processByProxy(
|
||||
@@ -188,21 +214,27 @@ class NoteFeedFlow(
|
||||
emit(AuthorsByProxyTopNavFilter(caches.peopleListCache.userIdSet(noteEvent), proxyRelays))
|
||||
}
|
||||
}
|
||||
|
||||
is MuteListEvent -> {
|
||||
emit(MutedAuthorsByProxyTopNavFilter(caches.muteListCache.mutedUserIdSet(noteEvent), proxyRelays))
|
||||
}
|
||||
|
||||
is FollowListEvent -> {
|
||||
emit(AuthorsByProxyTopNavFilter(noteEvent.followIdSet(), proxyRelays))
|
||||
}
|
||||
|
||||
is CommunityListEvent -> {
|
||||
emit(AllCommunitiesTopNavFilter(caches.communityListCache.communityIdSet(noteEvent), blockedRelays))
|
||||
}
|
||||
|
||||
is HashtagListEvent -> {
|
||||
emit(HashtagTopNavFilter(caches.hashtagCache.hashtags(noteEvent), proxyRelays))
|
||||
}
|
||||
|
||||
is GeohashListEvent -> {
|
||||
emit(LocationTopNavFilter(caches.geohashCache.geohashes(noteEvent), proxyRelays))
|
||||
}
|
||||
|
||||
is CommunityDefinitionEvent -> {
|
||||
emit(
|
||||
SingleCommunityTopNavFilter(
|
||||
@@ -213,10 +245,12 @@ class NoteFeedFlow(
|
||||
),
|
||||
)
|
||||
}
|
||||
else ->
|
||||
|
||||
else -> {
|
||||
emit(
|
||||
AuthorsByProxyTopNavFilter(emptySet(), proxyRelays),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,14 +25,16 @@ import com.vitorpamplona.amethyst.commons.model.ImmutableListOfLists
|
||||
|
||||
fun String.isUTF16Char(pos: Int): Boolean = Character.charCount(this.codePointAt(pos)) == 2
|
||||
|
||||
fun String.firstFullCharOld(): String {
|
||||
return when (this.length) {
|
||||
0,
|
||||
1,
|
||||
-> return this
|
||||
2,
|
||||
3,
|
||||
-> return if (isUTF16Char(0)) this.take(2) else this.take(1)
|
||||
fun String.firstFullCharOld(): String =
|
||||
when (this.length) {
|
||||
0, 1 -> {
|
||||
this
|
||||
}
|
||||
|
||||
2, 3 -> {
|
||||
if (isUTF16Char(0)) this.take(2) else this.take(1)
|
||||
}
|
||||
|
||||
else -> {
|
||||
val first = isUTF16Char(0)
|
||||
val second = isUTF16Char(2)
|
||||
@@ -45,7 +47,6 @@ fun String.firstFullCharOld(): String {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun String.firstFullChar(): String {
|
||||
var isInJoin = false
|
||||
|
||||
@@ -45,7 +45,6 @@ class HttpStatusMessages {
|
||||
416 -> R.string.http_status_416
|
||||
417 -> R.string.http_status_417
|
||||
426 -> R.string.http_status_426
|
||||
|
||||
500 -> R.string.http_status_500
|
||||
501 -> R.string.http_status_501
|
||||
502 -> R.string.http_status_502
|
||||
@@ -56,7 +55,6 @@ class HttpStatusMessages {
|
||||
507 -> R.string.http_status_507
|
||||
508 -> R.string.http_status_508
|
||||
511 -> R.string.http_status_511
|
||||
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +97,7 @@ class ZapPaymentHandler(
|
||||
weight = setup.weight,
|
||||
)
|
||||
}
|
||||
|
||||
is ZapSplitSetup -> {
|
||||
val user = LocalCache.checkGetOrCreateUser(setup.pubKeyHex)
|
||||
UnverifiedZapSplitSetup(
|
||||
|
||||
+12
-4
@@ -366,13 +366,21 @@ class BroadcastTracker {
|
||||
// Recalculate status
|
||||
val newStatus =
|
||||
when {
|
||||
currentBroadcast.results.values.any { it is RelayResult.Pending || it is RelayResult.Retrying } ->
|
||||
currentBroadcast.results.values.any { it is RelayResult.Pending || it is RelayResult.Retrying } -> {
|
||||
BroadcastStatus.IN_PROGRESS
|
||||
currentBroadcast.results.all { it.value is RelayResult.Success } ->
|
||||
}
|
||||
|
||||
currentBroadcast.results.all { it.value is RelayResult.Success } -> {
|
||||
BroadcastStatus.SUCCESS
|
||||
currentBroadcast.results.none { it.value is RelayResult.Success } ->
|
||||
}
|
||||
|
||||
currentBroadcast.results.none { it.value is RelayResult.Success } -> {
|
||||
BroadcastStatus.FAILED
|
||||
else -> BroadcastStatus.PARTIAL
|
||||
}
|
||||
|
||||
else -> {
|
||||
BroadcastStatus.PARTIAL
|
||||
}
|
||||
}
|
||||
currentBroadcast.copy(status = newStatus)
|
||||
}
|
||||
|
||||
+2
@@ -157,6 +157,7 @@ class EventNotificationConsumer(
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
is SealedRumorEvent -> {
|
||||
if (LocalCache.justConsume(event, null, false)) {
|
||||
// new event
|
||||
@@ -174,6 +175,7 @@ class EventNotificationConsumer(
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
LocalCache.justConsume(event, null, false)
|
||||
event
|
||||
|
||||
-85
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
* 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.playback.composable
|
||||
|
||||
import android.view.Surface
|
||||
import android.view.SurfaceView
|
||||
import android.view.TextureView
|
||||
import androidx.annotation.IntDef
|
||||
import androidx.compose.foundation.AndroidEmbeddedExternalSurface
|
||||
import androidx.compose.foundation.AndroidExternalSurface
|
||||
import androidx.compose.foundation.AndroidExternalSurfaceScope
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.media3.common.Player
|
||||
|
||||
/**
|
||||
* Provides a dedicated drawing [Surface] for media playbacks using a [Player].
|
||||
*
|
||||
* The player's video output is displayed with either a [SurfaceView]/[AndroidExternalSurface] or a
|
||||
* [TextureView]/[AndroidEmbeddedExternalSurface].
|
||||
*
|
||||
* [Player] takes care of attaching the rendered output to the [Surface] and clearing it, when it is
|
||||
* destroyed.
|
||||
*
|
||||
* See
|
||||
* [Choosing a surface type](https://developer.android.com/media/media3/ui/playerview#surfacetype)
|
||||
* for more information.
|
||||
*/
|
||||
@Composable
|
||||
fun PlayerSurface(
|
||||
player: Player,
|
||||
surfaceType: @SurfaceType Int = SURFACE_TYPE_SURFACE_VIEW,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val onSurfaceCreated: (Surface) -> Unit = { surface -> player.setVideoSurface(surface) }
|
||||
val onSurfaceDestroyed: () -> Unit = { player.setVideoSurface(null) }
|
||||
val onSurfaceInitialized: AndroidExternalSurfaceScope.() -> Unit = {
|
||||
onSurface { surface, _, _ ->
|
||||
onSurfaceCreated(surface)
|
||||
surface.onDestroyed { onSurfaceDestroyed() }
|
||||
}
|
||||
}
|
||||
|
||||
when (surfaceType) {
|
||||
SURFACE_TYPE_SURFACE_VIEW ->
|
||||
AndroidExternalSurface(modifier = modifier, onInit = onSurfaceInitialized)
|
||||
SURFACE_TYPE_TEXTURE_VIEW ->
|
||||
AndroidEmbeddedExternalSurface(modifier = modifier, onInit = onSurfaceInitialized)
|
||||
else -> throw IllegalArgumentException("Unrecognized surface type: $surfaceType")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of surface view used for media playbacks. One of [SURFACE_TYPE_SURFACE_VIEW] or
|
||||
* [SURFACE_TYPE_TEXTURE_VIEW].
|
||||
*/
|
||||
@MustBeDocumented
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
@Target(AnnotationTarget.CLASS, AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER)
|
||||
@IntDef(SURFACE_TYPE_SURFACE_VIEW, SURFACE_TYPE_TEXTURE_VIEW)
|
||||
annotation class SurfaceType
|
||||
|
||||
/** Surface type equivalent to [SurfaceView] . */
|
||||
const val SURFACE_TYPE_SURFACE_VIEW = 1
|
||||
|
||||
/** Surface type equivalent to [TextureView]. */
|
||||
const val SURFACE_TYPE_TEXTURE_VIEW = 2
|
||||
+10
-3
@@ -60,6 +60,7 @@ object BlurhashMetadataCalculator {
|
||||
val bitmap = BitmapFactory.decodeByteArray(data, 0, data.size, createBitmapOptions())
|
||||
processImage(bitmap, dimPrecomputed)
|
||||
}
|
||||
|
||||
isVideo(mimeType) -> {
|
||||
val retriever = MediaMetadataRetriever()
|
||||
try {
|
||||
@@ -69,7 +70,10 @@ object BlurhashMetadataCalculator {
|
||||
retriever.release()
|
||||
}
|
||||
}
|
||||
else -> null to dimPrecomputed
|
||||
|
||||
else -> {
|
||||
null to dimPrecomputed
|
||||
}
|
||||
}
|
||||
|
||||
fun computeFromUri(
|
||||
@@ -82,11 +86,12 @@ object BlurhashMetadataCalculator {
|
||||
|
||||
return try {
|
||||
when {
|
||||
isImage(mimeType) ->
|
||||
isImage(mimeType) -> {
|
||||
context.contentResolver.openInputStream(uri)?.use { stream ->
|
||||
val bitmap = BitmapFactory.decodeStream(stream, null, createBitmapOptions())
|
||||
processImage(bitmap, dimPrecomputed)
|
||||
} ?: (null to dimPrecomputed)
|
||||
}
|
||||
|
||||
isVideo(mimeType) -> {
|
||||
val retriever = MediaMetadataRetriever()
|
||||
@@ -98,7 +103,9 @@ object BlurhashMetadataCalculator {
|
||||
}
|
||||
}
|
||||
|
||||
else -> null
|
||||
else -> {
|
||||
null
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.w("BlurhashMetadataCalc", "Failed to compute metadata from uri", e)
|
||||
|
||||
+7
-2
@@ -60,11 +60,16 @@ class MediaCompressor {
|
||||
contentType?.startsWith("video", ignoreCase = true) == true -> {
|
||||
VideoCompressionHelper.compressVideo(uri, contentType, applicationContext, mediaQuality, useH265)
|
||||
}
|
||||
|
||||
contentType?.startsWith("image", ignoreCase = true) == true &&
|
||||
!contentType.contains("gif") &&
|
||||
!contentType.contains("svg") ->
|
||||
!contentType.contains("svg") -> {
|
||||
compressImage(uri, contentType, applicationContext, mediaQuality)
|
||||
else -> MediaCompressorResult(uri, contentType, null)
|
||||
}
|
||||
|
||||
else -> {
|
||||
MediaCompressorResult(uri, contentType, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -150,9 +150,18 @@ fun uriToRoute(
|
||||
|
||||
val route =
|
||||
when (nip19) {
|
||||
is NPub -> Route.Profile(nip19.hex)
|
||||
is NProfile -> Route.Profile(nip19.hex)
|
||||
is NNote -> Route.Note(nip19.hex)
|
||||
is NPub -> {
|
||||
Route.Profile(nip19.hex)
|
||||
}
|
||||
|
||||
is NProfile -> {
|
||||
Route.Profile(nip19.hex)
|
||||
}
|
||||
|
||||
is NNote -> {
|
||||
Route.Note(nip19.hex)
|
||||
}
|
||||
|
||||
is NEvent -> {
|
||||
routeFor(
|
||||
note = LocalCache.getOrCreateNote(nip19.hex),
|
||||
@@ -182,7 +191,9 @@ fun uriToRoute(
|
||||
}
|
||||
}
|
||||
|
||||
else -> null
|
||||
else -> {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
if (route != null) {
|
||||
|
||||
@@ -57,8 +57,11 @@ object MediaSaverToDisk {
|
||||
onError: (Throwable) -> Any?,
|
||||
) = withContext(Dispatchers.IO) {
|
||||
when {
|
||||
videoUri.isNullOrBlank() -> return@withContext
|
||||
videoUri.startsWith("file") ->
|
||||
videoUri.isNullOrBlank() -> {
|
||||
return@withContext
|
||||
}
|
||||
|
||||
videoUri.startsWith("file") -> {
|
||||
save(
|
||||
localFile = videoUri.toUri().toFile(),
|
||||
mimeType = mimeType,
|
||||
@@ -66,7 +69,9 @@ object MediaSaverToDisk {
|
||||
onSuccess = onSuccess,
|
||||
onError = onError,
|
||||
)
|
||||
else ->
|
||||
}
|
||||
|
||||
else -> {
|
||||
downloadAndSave(
|
||||
url = videoUri,
|
||||
mimeType = mimeType,
|
||||
@@ -75,6 +80,7 @@ object MediaSaverToDisk {
|
||||
onSuccess = onSuccess,
|
||||
onError = onError,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,12 +71,25 @@ class NewMessageTagger(
|
||||
val results = parseDirtyWordForKey(word)
|
||||
|
||||
when (val entity = results?.key?.entity) {
|
||||
is NPub -> addUserToMentions(dao.getOrCreateUser(entity.hex))
|
||||
is NProfile -> addUserToMentions(dao.getOrCreateUser(entity.hex))
|
||||
is NPub -> {
|
||||
addUserToMentions(dao.getOrCreateUser(entity.hex))
|
||||
}
|
||||
|
||||
is com.vitorpamplona.quartz.nip19Bech32.entities.NNote -> addNoteToReplyTos(dao.getOrCreateNote(entity.hex))
|
||||
is NEvent -> addNoteToReplyTos(dao.getOrCreateNote(entity.hex))
|
||||
is NEmbed -> addNoteToReplyTos(dao.getOrCreateNote(entity.event.id))
|
||||
is NProfile -> {
|
||||
addUserToMentions(dao.getOrCreateUser(entity.hex))
|
||||
}
|
||||
|
||||
is com.vitorpamplona.quartz.nip19Bech32.entities.NNote -> {
|
||||
addNoteToReplyTos(dao.getOrCreateNote(entity.hex))
|
||||
}
|
||||
|
||||
is NEvent -> {
|
||||
addNoteToReplyTos(dao.getOrCreateNote(entity.hex))
|
||||
}
|
||||
|
||||
is NEmbed -> {
|
||||
addNoteToReplyTos(dao.getOrCreateNote(entity.event.id))
|
||||
}
|
||||
|
||||
is NAddress -> {
|
||||
val note = dao.getOrCreateAddressableNote(entity.address())
|
||||
@@ -86,6 +99,7 @@ class NewMessageTagger(
|
||||
}
|
||||
|
||||
is NSec -> {}
|
||||
|
||||
is NRelay -> {}
|
||||
}
|
||||
}
|
||||
@@ -104,6 +118,7 @@ class NewMessageTagger(
|
||||
is NPub -> {
|
||||
getNostrAddress(dao.getOrCreateUser(entity.hex).toNProfile(), results.restOfWord)
|
||||
}
|
||||
|
||||
is NProfile -> {
|
||||
getNostrAddress(dao.getOrCreateUser(entity.hex).toNProfile(), results.restOfWord)
|
||||
}
|
||||
@@ -111,6 +126,7 @@ class NewMessageTagger(
|
||||
is com.vitorpamplona.quartz.nip19Bech32.entities.NNote -> {
|
||||
getNostrAddress(dao.getOrCreateNote(entity.hex).toNEvent(), results.restOfWord)
|
||||
}
|
||||
|
||||
is NEvent -> {
|
||||
getNostrAddress(dao.getOrCreateNote(entity.hex).toNEvent(), results.restOfWord)
|
||||
}
|
||||
|
||||
+4
-1
@@ -306,7 +306,10 @@ class VoiceAnonymizer {
|
||||
val randomShift = 0.9 + (Math.random() * 0.2)
|
||||
baseFactor * randomShift
|
||||
}
|
||||
else -> baseFactor
|
||||
|
||||
else -> {
|
||||
baseFactor
|
||||
}
|
||||
}
|
||||
val totalSamples = pcmData.size
|
||||
val processedSamples = ArrayList<Float>(totalSamples)
|
||||
|
||||
+3
@@ -476,6 +476,7 @@ private fun RelayResultRow(
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
}
|
||||
|
||||
is RelayResult.Timeout -> {
|
||||
Text(
|
||||
text = "Timeout",
|
||||
@@ -483,6 +484,7 @@ private fun RelayResultRow(
|
||||
color = warningColor,
|
||||
)
|
||||
}
|
||||
|
||||
is RelayResult.Retrying -> {
|
||||
Text(
|
||||
text = "Retrying...",
|
||||
@@ -490,6 +492,7 @@ private fun RelayResultRow(
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@ fun BroadcastSnackbarHost(
|
||||
onViewDetails(broadcast)
|
||||
}
|
||||
}
|
||||
|
||||
SnackbarResult.Dismissed -> { /* No action */ }
|
||||
}
|
||||
}
|
||||
@@ -104,8 +105,12 @@ private fun BroadcastSnackbarContent(snackbarData: SnackbarData) {
|
||||
|
||||
val containerColor =
|
||||
when (broadcastVisuals?.broadcast?.status) {
|
||||
BroadcastStatus.FAILED -> Color(0xFF7F1D1D) // Dark red
|
||||
BroadcastStatus.PARTIAL -> Color(0xFF78350F) // Dark amber
|
||||
BroadcastStatus.FAILED -> Color(0xFF7F1D1D)
|
||||
|
||||
// Dark red
|
||||
BroadcastStatus.PARTIAL -> Color(0xFF78350F)
|
||||
|
||||
// Dark amber
|
||||
else -> Color(0xFF1E3A5F) // Dark blue (default)
|
||||
}
|
||||
|
||||
|
||||
@@ -93,12 +93,17 @@ fun CashuPreview(
|
||||
|
||||
CrossfadeIfEnabled(targetState = cashuData, label = "CashuPreview", accountViewModel = accountViewModel) {
|
||||
when (it) {
|
||||
is GenericLoadable.Loaded<ImmutableList<CashuToken>> -> CashuPreview(it.loaded, accountViewModel)
|
||||
is GenericLoadable.Error<ImmutableList<CashuToken>> ->
|
||||
is GenericLoadable.Loaded<ImmutableList<CashuToken>> -> {
|
||||
CashuPreview(it.loaded, accountViewModel)
|
||||
}
|
||||
|
||||
is GenericLoadable.Error<ImmutableList<CashuToken>> -> {
|
||||
Text(
|
||||
text = "$cashutoken ",
|
||||
style = LocalTextStyle.current.copy(textDirection = TextDirection.Content),
|
||||
)
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,11 +73,13 @@ fun LoadUrlPreviewDirect(
|
||||
is UrlPreviewState.Loaded -> {
|
||||
RenderLoaded(state, url, callbackUri, accountViewModel)
|
||||
}
|
||||
|
||||
is UrlPreviewState.Loading -> {
|
||||
WaitAndDisplay {
|
||||
DisplayUrlWithLoadingSymbol(url)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
ClickableUrl(urlText, url)
|
||||
}
|
||||
|
||||
@@ -87,6 +87,7 @@ fun MyAsyncImage(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is AsyncImagePainter.State.Error -> {
|
||||
if (onError != null) {
|
||||
if (ratio != null) {
|
||||
@@ -102,6 +103,7 @@ fun MyAsyncImage(
|
||||
ClickableUrl(urlText = imageUrl, url = imageUrl)
|
||||
}
|
||||
}
|
||||
|
||||
is AsyncImagePainter.State.Success -> {
|
||||
SubcomposeAsyncImageContent(loadedImageModifier)
|
||||
|
||||
@@ -110,6 +112,7 @@ fun MyAsyncImage(
|
||||
MediaAspectRatioCache.add(imageUrl, drawable.width, drawable.height)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,7 +160,9 @@ fun RenderStrangeNamePreview() {
|
||||
)
|
||||
}
|
||||
|
||||
is RegularTextSegment -> Text(word.segmentText)
|
||||
is RegularTextSegment -> {
|
||||
Text(word.segmentText)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -180,12 +182,21 @@ fun RenderRegularPreview() {
|
||||
when (word) {
|
||||
// is ImageSegment -> ZoomableContentView(word.segmentText, state, accountViewModel)
|
||||
// is LinkSegment -> LoadUrlPreview(word.segmentText, word.segmentText, accountViewModel)
|
||||
is EmojiSegment -> RenderCustomEmoji(word.segmentText, state)
|
||||
is EmojiSegment -> {
|
||||
RenderCustomEmoji(word.segmentText, state)
|
||||
}
|
||||
|
||||
// is InvoiceSegment -> MayBeInvoicePreview(word.segmentText)
|
||||
// is WithdrawSegment -> MayBeWithdrawal(word.segmentText)
|
||||
// is CashuSegment -> CashuPreview(word.segmentText, accountViewModel)
|
||||
is EmailSegment -> ClickableEmail(word.segmentText)
|
||||
is PhoneSegment -> ClickablePhone(word.segmentText)
|
||||
is EmailSegment -> {
|
||||
ClickableEmail(word.segmentText)
|
||||
}
|
||||
|
||||
is PhoneSegment -> {
|
||||
ClickablePhone(word.segmentText)
|
||||
}
|
||||
|
||||
is BechSegment -> {
|
||||
CreateClickableText(
|
||||
word.segmentText.substring(0, 10),
|
||||
@@ -196,11 +207,19 @@ fun RenderRegularPreview() {
|
||||
)
|
||||
}
|
||||
|
||||
is HashTagSegment -> HashTag(word, EmptyNav())
|
||||
is HashTagSegment -> {
|
||||
HashTag(word, EmptyNav())
|
||||
}
|
||||
|
||||
// is HashIndexUserSegment -> TagLink(word, accountViewModel, nav)
|
||||
// is HashIndexEventSegment -> TagLink(word, true, backgroundColorState, accountViewModel, nav)
|
||||
is SchemelessUrlSegment -> NoProtocolUrlRenderer(word)
|
||||
is RegularTextSegment -> Text(word.segmentText)
|
||||
is SchemelessUrlSegment -> {
|
||||
NoProtocolUrlRenderer(word)
|
||||
}
|
||||
|
||||
is RegularTextSegment -> {
|
||||
Text(word.segmentText)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -219,16 +238,21 @@ fun RenderRegularPreview2() {
|
||||
// is ImageSegment -> ZoomableContentView(word.segmentText, state, accountViewModel)
|
||||
// is LinkSegment -> LoadUrlPreview(word.segmentText, word.segmentText, accountViewModel)
|
||||
is EmojiSegment -> RenderCustomEmoji(word.segmentText, state)
|
||||
|
||||
// is InvoiceSegment -> MayBeInvoicePreview(word.segmentText)
|
||||
// is WithdrawSegment -> MayBeWithdrawal(word.segmentText)
|
||||
// is CashuSegment -> CashuPreview(word.segmentText, accountViewModel)
|
||||
is EmailSegment -> ClickableEmail(word.segmentText)
|
||||
|
||||
is PhoneSegment -> ClickablePhone(word.segmentText)
|
||||
|
||||
// is BechSegment -> BechLink(word.segmentText, true, backgroundColor, accountViewModel, nav)
|
||||
is HashTagSegment -> HashTag(word, EmptyNav())
|
||||
|
||||
// is HashIndexUserSegment -> TagLink(word, accountViewModel, nav)
|
||||
// is HashIndexEventSegment -> TagLink(word, true, backgroundColorState, accountViewModel, nav)
|
||||
is SchemelessUrlSegment -> NoProtocolUrlRenderer(word)
|
||||
|
||||
is RegularTextSegment -> Text(word.segmentText)
|
||||
}
|
||||
}
|
||||
@@ -260,17 +284,23 @@ fun RenderRegularPreview3() {
|
||||
when (word) {
|
||||
// is ImageSegment -> ZoomableContentView(word.segmentText, state, accountViewModel)
|
||||
is LinkSegment -> LoadUrlPreview(word.segmentText, word.segmentText, null, accountViewModel)
|
||||
|
||||
is EmojiSegment -> RenderCustomEmoji(word.segmentText, state)
|
||||
|
||||
// is InvoiceSegment -> MayBeInvoicePreview(word.segmentText)
|
||||
// is WithdrawSegment -> MayBeWithdrawal(word.segmentText)
|
||||
// is CashuSegment -> CashuPreview(word.segmentText, accountViewModel)
|
||||
is EmailSegment -> ClickableEmail(word.segmentText)
|
||||
|
||||
is PhoneSegment -> ClickablePhone(word.segmentText)
|
||||
|
||||
// is BechSegment -> BechLink(word.segmentText, true, backgroundColor, accountViewModel, nav)
|
||||
is HashTagSegment -> HashTag(word, EmptyNav())
|
||||
|
||||
// is HashIndexUserSegment -> TagLink(word, accountViewModel, nav)
|
||||
// is HashIndexEventSegment -> TagLink(word, true, backgroundColorState, accountViewModel, nav)
|
||||
is SchemelessUrlSegment -> NoProtocolUrlRenderer(word)
|
||||
|
||||
is RegularTextSegment -> Text(word.segmentText)
|
||||
}
|
||||
}
|
||||
@@ -415,23 +445,38 @@ private fun RenderWordWithoutPreview(
|
||||
when (word) {
|
||||
// Don't preview Images
|
||||
is ImageSegment -> ClickableUrl(word.segmentText, word.segmentText)
|
||||
|
||||
// Don't preview Videos
|
||||
is VideoSegment -> ClickableUrl(word.segmentText, word.segmentText)
|
||||
|
||||
is LinkSegment -> ClickableUrl(word.segmentText, word.segmentText)
|
||||
|
||||
is EmojiSegment -> RenderCustomEmoji(word.segmentText, state)
|
||||
|
||||
// Don't offer to pay invoices
|
||||
is InvoiceSegment -> Text(word.segmentText)
|
||||
|
||||
// Don't offer to withdraw
|
||||
is WithdrawSegment -> Text(word.segmentText)
|
||||
|
||||
is CashuSegment -> Text(word.segmentText)
|
||||
|
||||
is EmailSegment -> ClickableEmail(word.segmentText)
|
||||
|
||||
is SecretEmoji -> Text(word.segmentText)
|
||||
|
||||
is PhoneSegment -> ClickablePhone(word.segmentText)
|
||||
|
||||
is BechSegment -> BechLink(word.segmentText, false, 0, backgroundColor, accountViewModel, nav)
|
||||
|
||||
is HashTagSegment -> HashTag(word, nav)
|
||||
|
||||
is HashIndexUserSegment -> TagLink(word, accountViewModel, nav)
|
||||
|
||||
is HashIndexEventSegment -> TagLink(word, false, 0, backgroundColor, accountViewModel, nav)
|
||||
|
||||
is SchemelessUrlSegment -> NoProtocolUrlRenderer(word)
|
||||
|
||||
is RegularTextSegment -> Text(word.segmentText)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,8 +65,14 @@ fun SwipeToDeleteContainer(
|
||||
StartToEnd -> {
|
||||
onStartToEnd()
|
||||
}
|
||||
EndToStart -> return@rememberSwipeToDismissBoxState false
|
||||
Settled -> return@rememberSwipeToDismissBoxState false
|
||||
|
||||
EndToStart -> {
|
||||
return@rememberSwipeToDismissBoxState false
|
||||
}
|
||||
|
||||
Settled -> {
|
||||
return@rememberSwipeToDismissBoxState false
|
||||
}
|
||||
}
|
||||
return@rememberSwipeToDismissBoxState true
|
||||
},
|
||||
|
||||
+20
-4
@@ -139,7 +139,7 @@ fun ZoomableContentView(
|
||||
var dialogOpen by remember(content) { mutableStateOf(false) }
|
||||
|
||||
when (content) {
|
||||
is MediaUrlImage ->
|
||||
is MediaUrlImage -> {
|
||||
SensitivityWarning(content.contentWarning != null, accountViewModel) {
|
||||
TwoSecondController(content) { controllerVisible ->
|
||||
val mainImageModifier =
|
||||
@@ -150,7 +150,9 @@ fun ZoomableContentView(
|
||||
UrlImageView(content, contentScale, mainImageModifier, loadedImageModifier, controllerVisible, accountViewModel = accountViewModel)
|
||||
}
|
||||
}
|
||||
is MediaUrlVideo ->
|
||||
}
|
||||
|
||||
is MediaUrlVideo -> {
|
||||
SensitivityWarning(content.contentWarning != null, accountViewModel) {
|
||||
Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
|
||||
VideoView(
|
||||
@@ -171,7 +173,9 @@ fun ZoomableContentView(
|
||||
)
|
||||
}
|
||||
}
|
||||
is MediaLocalImage ->
|
||||
}
|
||||
|
||||
is MediaLocalImage -> {
|
||||
TwoSecondController(content) { controllerVisible ->
|
||||
val mainImageModifier =
|
||||
Modifier
|
||||
@@ -181,7 +185,9 @@ fun ZoomableContentView(
|
||||
|
||||
LocalImageView(content, contentScale, mainImageModifier, loadedImageModifier, controllerVisible, accountViewModel = accountViewModel)
|
||||
}
|
||||
is MediaLocalVideo ->
|
||||
}
|
||||
|
||||
is MediaLocalVideo -> {
|
||||
content.localFile?.let {
|
||||
Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
|
||||
VideoView(
|
||||
@@ -198,6 +204,7 @@ fun ZoomableContentView(
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dialogOpen) {
|
||||
@@ -286,9 +293,11 @@ fun LocalImageView(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is AsyncImagePainter.State.Error -> {
|
||||
BlankNote(loadedImageModifier)
|
||||
}
|
||||
|
||||
is AsyncImagePainter.State.Success -> {
|
||||
SubcomposeAsyncImageContent(loadedImageModifier)
|
||||
|
||||
@@ -310,6 +319,7 @@ fun LocalImageView(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
@@ -405,9 +415,11 @@ fun UrlImageView(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is AsyncImagePainter.State.Error -> {
|
||||
ClickableUrl(urlText = "${content.url} ", url = content.url)
|
||||
}
|
||||
|
||||
is AsyncImagePainter.State.Success -> {
|
||||
SubcomposeAsyncImageContent(loadedImageModifier)
|
||||
|
||||
@@ -418,6 +430,7 @@ fun UrlImageView(
|
||||
MediaAspectRatioCache.add(content.url, drawable.width, drawable.height)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
@@ -794,6 +807,7 @@ fun ShareMediaAction(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is MediaUrlVideo -> {
|
||||
videoUri?.let {
|
||||
if (videoUri.isNotEmpty()) {
|
||||
@@ -832,6 +846,7 @@ fun ShareMediaAction(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is MediaLocalVideo -> {
|
||||
content.localFile?.let { localFile ->
|
||||
DropdownMenuItem(
|
||||
@@ -843,6 +858,7 @@ fun ShareMediaAction(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
else -> { /* No share option for other types */ }
|
||||
}
|
||||
}
|
||||
|
||||
+11
-5
@@ -39,7 +39,7 @@ fun DisplayErrorMessages(
|
||||
|
||||
openDialogMsg.value?.let { obj ->
|
||||
when (obj) {
|
||||
is ResourceToastMsg ->
|
||||
is ResourceToastMsg -> {
|
||||
if (obj.params != null) {
|
||||
InformationDialog(
|
||||
stringRes(obj.titleResId),
|
||||
@@ -55,16 +55,18 @@ fun DisplayErrorMessages(
|
||||
toastManager.clearToasts()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is StringToastMsg ->
|
||||
is StringToastMsg -> {
|
||||
InformationDialog(
|
||||
obj.title,
|
||||
obj.msg,
|
||||
) {
|
||||
toastManager.clearToasts()
|
||||
}
|
||||
}
|
||||
|
||||
is ActionableStringToastMsg ->
|
||||
is ActionableStringToastMsg -> {
|
||||
InformationDialog(
|
||||
obj.title,
|
||||
obj.msg,
|
||||
@@ -72,8 +74,9 @@ fun DisplayErrorMessages(
|
||||
obj.action()
|
||||
toastManager.clearToasts()
|
||||
}
|
||||
}
|
||||
|
||||
is ThrowableToastMsg ->
|
||||
is ThrowableToastMsg -> {
|
||||
InformationDialog(
|
||||
stringRes(obj.titleResId),
|
||||
obj.msg,
|
||||
@@ -81,8 +84,11 @@ fun DisplayErrorMessages(
|
||||
) {
|
||||
toastManager.clearToasts()
|
||||
}
|
||||
}
|
||||
|
||||
is MultiErrorToastMsg -> MultiUserErrorMessageDialog(obj, accountViewModel, nav)
|
||||
is MultiErrorToastMsg -> {
|
||||
MultiUserErrorMessageDialog(obj, accountViewModel, nav)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+44
-10
@@ -87,24 +87,29 @@ fun routeForInner(
|
||||
is AppDefinitionEvent -> {
|
||||
Route.ContentDiscovery(noteEvent.id)
|
||||
}
|
||||
|
||||
is IsInPublicChatChannel -> {
|
||||
noteEvent.channelId()?.let {
|
||||
Route.PublicChatChannel(it)
|
||||
}
|
||||
}
|
||||
|
||||
is ChannelCreateEvent -> {
|
||||
Route.PublicChatChannel(noteEvent.id)
|
||||
}
|
||||
|
||||
is LiveActivitiesEvent -> {
|
||||
noteEvent.address().let {
|
||||
Route.LiveActivityChannel(it.kind, it.pubKeyHex, it.dTag)
|
||||
}
|
||||
}
|
||||
|
||||
is LiveActivitiesChatMessageEvent -> {
|
||||
noteEvent.activityAddress()?.let {
|
||||
Route.LiveActivityChannel(it.kind, it.pubKeyHex, it.dTag)
|
||||
}
|
||||
}
|
||||
|
||||
is EphemeralChatEvent -> {
|
||||
noteEvent.roomId()?.let {
|
||||
Route.EphemeralChat(it.id, it.relayUrl.url)
|
||||
@@ -124,16 +129,19 @@ fun routeForInner(
|
||||
is CommunityDefinitionEvent -> {
|
||||
Route.Community(noteEvent.kind, noteEvent.pubKey, noteEvent.dTag())
|
||||
}
|
||||
|
||||
is GiftWrapEvent -> {
|
||||
noteEvent.innerEventId?.let {
|
||||
routeFor(LocalCache.getOrCreateNote(it), loggedIn)
|
||||
}
|
||||
}
|
||||
|
||||
is SealedRumorEvent -> {
|
||||
noteEvent.innerEventId?.let {
|
||||
routeFor(LocalCache.getOrCreateNote(it), loggedIn)
|
||||
}
|
||||
}
|
||||
|
||||
is AddressableEvent -> {
|
||||
Route.Note(noteEvent.aTag().toTag())
|
||||
}
|
||||
@@ -232,23 +240,31 @@ fun routeReplyTo(
|
||||
Route.PublicChatChannel(channelId, replyTo = note.idHex)
|
||||
}
|
||||
}
|
||||
|
||||
is LiveActivitiesChatMessageEvent -> {
|
||||
noteEvent.activityAddress()?.let {
|
||||
Route.LiveActivityChannel(it.kind, it.pubKeyHex, it.dTag, replyTo = note.idHex)
|
||||
}
|
||||
}
|
||||
|
||||
is EphemeralChatEvent -> {
|
||||
noteEvent.roomId()?.let {
|
||||
Route.EphemeralChat(it.id, it.relayUrl.url, replyTo = note.idHex)
|
||||
}
|
||||
}
|
||||
is PublicMessageEvent ->
|
||||
|
||||
is PublicMessageEvent -> {
|
||||
Route.NewPublicMessage(
|
||||
users = noteEvent.groupKeySet() - account.userProfile().pubkeyHex,
|
||||
parentId = noteEvent.id,
|
||||
)
|
||||
is TextNoteEvent -> Route.NewShortNote(baseReplyTo = note.idHex)
|
||||
is PrivateDmEvent ->
|
||||
}
|
||||
|
||||
is TextNoteEvent -> {
|
||||
Route.NewShortNote(baseReplyTo = note.idHex)
|
||||
}
|
||||
|
||||
is PrivateDmEvent -> {
|
||||
routeToMessage(
|
||||
room = noteEvent.chatroomKey(account.userProfile().pubkeyHex),
|
||||
draftMessage = null,
|
||||
@@ -256,7 +272,9 @@ fun routeReplyTo(
|
||||
draftId = null,
|
||||
account = account,
|
||||
)
|
||||
is ChatroomKeyable ->
|
||||
}
|
||||
|
||||
is ChatroomKeyable -> {
|
||||
routeToMessage(
|
||||
room = noteEvent.chatroomKey(account.userProfile().pubkeyHex),
|
||||
draftMessage = null,
|
||||
@@ -264,6 +282,8 @@ fun routeReplyTo(
|
||||
draftId = null,
|
||||
account = account,
|
||||
)
|
||||
}
|
||||
|
||||
is CommentEvent -> {
|
||||
if (noteEvent.isGeohashedScoped()) {
|
||||
Route.GeoPost(replyTo = note.idHex)
|
||||
@@ -274,7 +294,9 @@ fun routeReplyTo(
|
||||
}
|
||||
}
|
||||
|
||||
else -> Route.GenericCommentPost(replyTo = note.idHex)
|
||||
else -> {
|
||||
Route.GenericCommentPost(replyTo = note.idHex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,10 +308,14 @@ suspend fun routeEditDraftTo(
|
||||
val draft = account.draftsDecryptionCache.cachedDraft(noteEvent)
|
||||
|
||||
return when (draft) {
|
||||
is ChannelMessageEvent -> draft.channelId()?.let { Route.PublicChatChannel(it, draftId = note.idHex) }
|
||||
is ChannelMessageEvent -> {
|
||||
draft.channelId()?.let { Route.PublicChatChannel(it, draftId = note.idHex) }
|
||||
}
|
||||
|
||||
is LiveActivitiesChatMessageEvent -> {
|
||||
draft.activityAddress()?.let { Route.LiveActivityChannel(it.kind, it.pubKeyHex, it.dTag, draftId = note.idHex) }
|
||||
}
|
||||
|
||||
is EphemeralChatEvent -> {
|
||||
draft.roomId()?.let { Route.EphemeralChat(it.id, it.relayUrl.url, draftId = note.idHex) }
|
||||
}
|
||||
@@ -300,15 +326,21 @@ suspend fun routeEditDraftTo(
|
||||
return Route.Room(room, draftId = note.idHex)
|
||||
}
|
||||
|
||||
is TextNoteEvent -> Route.NewShortNote(draft = note.idHex)
|
||||
is ClassifiedsEvent -> Route.NewProduct(draft = note.idHex)
|
||||
is TextNoteEvent -> {
|
||||
Route.NewShortNote(draft = note.idHex)
|
||||
}
|
||||
|
||||
is PublicMessageEvent ->
|
||||
is ClassifiedsEvent -> {
|
||||
Route.NewProduct(draft = note.idHex)
|
||||
}
|
||||
|
||||
is PublicMessageEvent -> {
|
||||
Route.NewPublicMessage(
|
||||
users = draft.groupKeySet() - account.userProfile().pubkeyHex,
|
||||
parentId = noteEvent.id,
|
||||
draftId = note.idHex,
|
||||
)
|
||||
}
|
||||
|
||||
is CommentEvent -> {
|
||||
if (draft.isGeohashedScoped()) {
|
||||
@@ -320,6 +352,8 @@ suspend fun routeEditDraftTo(
|
||||
}
|
||||
}
|
||||
|
||||
else -> null
|
||||
else -> {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,7 +312,6 @@ fun getRouteWithArguments(navController: NavHostController): Route? {
|
||||
dest.hasRoute<Route.Video>() -> entry.toRoute<Route.Video>()
|
||||
dest.hasRoute<Route.Discover>() -> entry.toRoute<Route.Discover>()
|
||||
dest.hasRoute<Route.Notification>() -> entry.toRoute<Route.Notification>()
|
||||
|
||||
dest.hasRoute<Route.Search>() -> entry.toRoute<Route.Search>()
|
||||
dest.hasRoute<Route.SecurityFilters>() -> entry.toRoute<Route.SecurityFilters>()
|
||||
dest.hasRoute<Route.PrivacyOptions>() -> entry.toRoute<Route.PrivacyOptions>()
|
||||
@@ -321,16 +320,13 @@ fun getRouteWithArguments(navController: NavHostController): Route? {
|
||||
dest.hasRoute<Route.Drafts>() -> entry.toRoute<Route.Drafts>()
|
||||
dest.hasRoute<Route.Settings>() -> entry.toRoute<Route.Settings>()
|
||||
dest.hasRoute<Route.EditProfile>() -> entry.toRoute<Route.EditProfile>()
|
||||
|
||||
dest.hasRoute<Route.Profile>() -> entry.toRoute<Route.Profile>()
|
||||
dest.hasRoute<Route.Note>() -> entry.toRoute<Route.Note>()
|
||||
dest.hasRoute<Route.Hashtag>() -> entry.toRoute<Route.Hashtag>()
|
||||
dest.hasRoute<Route.Geohash>() -> entry.toRoute<Route.Geohash>()
|
||||
dest.hasRoute<Route.Community>() -> entry.toRoute<Route.Community>()
|
||||
|
||||
dest.hasRoute<Route.QRDisplay>() -> entry.toRoute<Route.QRDisplay>()
|
||||
dest.hasRoute<Route.RelayInfo>() -> entry.toRoute<Route.RelayInfo>()
|
||||
|
||||
dest.hasRoute<Route.RoomByAuthor>() -> entry.toRoute<Route.RoomByAuthor>()
|
||||
dest.hasRoute<Route.PublicChatChannel>() -> entry.toRoute<Route.PublicChatChannel>()
|
||||
dest.hasRoute<Route.LiveActivityChannel>() -> entry.toRoute<Route.LiveActivityChannel>()
|
||||
@@ -349,7 +345,6 @@ fun getRouteWithArguments(navController: NavHostController): Route? {
|
||||
dest.hasRoute<Route.HashtagPost>() -> entry.toRoute<Route.HashtagPost>()
|
||||
dest.hasRoute<Route.GenericCommentPost>() -> entry.toRoute<Route.GenericCommentPost>()
|
||||
dest.hasRoute<Route.NewPublicMessage>() -> entry.toRoute<Route.NewPublicMessage>()
|
||||
|
||||
dest.hasRoute<Route.Lists>() -> entry.toRoute<Route.Lists>()
|
||||
dest.hasRoute<Route.MyPeopleListView>() -> entry.toRoute<Route.MyPeopleListView>()
|
||||
dest.hasRoute<Route.MyFollowPackView>() -> entry.toRoute<Route.MyFollowPackView>()
|
||||
@@ -359,10 +354,7 @@ fun getRouteWithArguments(navController: NavHostController): Route? {
|
||||
dest.hasRoute<Route.NewGroupDM>() -> entry.toRoute<Route.NewGroupDM>()
|
||||
dest.hasRoute<Route.UserSettings>() -> entry.toRoute<Route.UserSettings>()
|
||||
dest.hasRoute<Route.ManualZapSplitPayment>() -> entry.toRoute<Route.ManualZapSplitPayment>()
|
||||
|
||||
else -> {
|
||||
null
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
@@ -179,6 +179,7 @@ fun FeedFilterSpinner(
|
||||
lineHeight = 12.sp,
|
||||
)
|
||||
}
|
||||
|
||||
LocationState.LocationResult.Loading -> {
|
||||
Text(
|
||||
text = stringRes(R.string.loading_location),
|
||||
@@ -252,6 +253,7 @@ fun RenderOption(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is HashtagName -> {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
@@ -260,6 +262,7 @@ fun RenderOption(
|
||||
Text(text = option.name(), color = MaterialTheme.colorScheme.onSurface)
|
||||
}
|
||||
}
|
||||
|
||||
is ResourceName -> {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
@@ -271,6 +274,7 @@ fun RenderOption(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
is PeopleListName -> {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
@@ -297,6 +301,7 @@ fun RenderOption(
|
||||
Text(text = name, color = MaterialTheme.colorScheme.onSurface)
|
||||
}
|
||||
}
|
||||
|
||||
is CommunityName -> {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
|
||||
@@ -221,8 +221,14 @@ fun RenderLikeGallery(
|
||||
)
|
||||
} else {
|
||||
when (val shortReaction = reactionType) {
|
||||
"+" -> LikedIcon(modifier.size(Size19dp))
|
||||
"-" -> Text(text = "\uD83D\uDC4E", modifier = modifier)
|
||||
"+" -> {
|
||||
LikedIcon(modifier.size(Size19dp))
|
||||
}
|
||||
|
||||
"-" -> {
|
||||
Text(text = "\uD83D\uDC4E", modifier = modifier)
|
||||
}
|
||||
|
||||
else -> {
|
||||
if (EmojiCoder.isCoded(shortReaction)) {
|
||||
DisplaySecretEmojiAsReaction(
|
||||
|
||||
+17
-6
@@ -243,13 +243,15 @@ fun DisplayStatusInner(
|
||||
nav: INav,
|
||||
) {
|
||||
when (type) {
|
||||
"music" ->
|
||||
"music" -> {
|
||||
Icon(
|
||||
imageVector = CustomHashTagIcons.Tunestr,
|
||||
null,
|
||||
modifier = Size15Modifier.padding(end = Size5dp),
|
||||
tint = MaterialTheme.colorScheme.placeholderText,
|
||||
)
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
|
||||
@@ -408,41 +410,50 @@ fun RenderNIP05VerifiedSymbol(
|
||||
) {
|
||||
CrossfadeIfEnabled(targetState = state, accountViewModel = accountViewModel) {
|
||||
when (it) {
|
||||
is Nip05VerifState.Verifying ->
|
||||
is Nip05VerifState.Verifying -> {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Downloading,
|
||||
contentDescription = stringRes(id = R.string.nip05_checking),
|
||||
modifier = modifier,
|
||||
tint = Color.Yellow,
|
||||
)
|
||||
is Nip05VerifState.NotStarted ->
|
||||
}
|
||||
|
||||
is Nip05VerifState.NotStarted -> {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Downloading,
|
||||
contentDescription = stringRes(id = R.string.nip05_checking),
|
||||
modifier = modifier,
|
||||
tint = Color.Yellow,
|
||||
)
|
||||
is Nip05VerifState.Verified ->
|
||||
}
|
||||
|
||||
is Nip05VerifState.Verified -> {
|
||||
Icon(
|
||||
painter = painterRes(R.drawable.nip_05, compositionSizeReference),
|
||||
contentDescription = stringRes(id = R.string.nip05_verified),
|
||||
modifier = modifier,
|
||||
tint = Color.Unspecified,
|
||||
)
|
||||
is Nip05VerifState.Failed ->
|
||||
}
|
||||
|
||||
is Nip05VerifState.Failed -> {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Report,
|
||||
contentDescription = stringRes(id = R.string.nip05_failed),
|
||||
modifier = modifier,
|
||||
tint = Color.Red,
|
||||
)
|
||||
is Nip05VerifState.Error ->
|
||||
}
|
||||
|
||||
is Nip05VerifState.Error -> {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Report,
|
||||
contentDescription = stringRes(id = R.string.nip05_failed),
|
||||
modifier = modifier,
|
||||
tint = Color.Red,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,14 +297,16 @@ fun AcceptableNote(
|
||||
if (isQuotedNote || isBoostedNote) {
|
||||
val noteEvent = baseNote.event
|
||||
when (noteEvent) {
|
||||
is ChannelCreateEvent ->
|
||||
is ChannelCreateEvent -> {
|
||||
RenderPublicChatChannelHeader(
|
||||
channelId = noteEvent.id,
|
||||
sendToChannel = true,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
)
|
||||
is ChannelMetadataEvent ->
|
||||
}
|
||||
|
||||
is ChannelMetadataEvent -> {
|
||||
noteEvent.channelId()?.let {
|
||||
RenderPublicChatChannelHeader(
|
||||
channelId = it,
|
||||
@@ -313,7 +315,9 @@ fun AcceptableNote(
|
||||
nav = nav,
|
||||
)
|
||||
}
|
||||
is CommunityDefinitionEvent ->
|
||||
}
|
||||
|
||||
is CommunityDefinitionEvent -> {
|
||||
(baseNote as? AddressableNote)?.let {
|
||||
RenderCommunity(
|
||||
baseNote = it,
|
||||
@@ -321,8 +325,13 @@ fun AcceptableNote(
|
||||
nav = nav,
|
||||
)
|
||||
}
|
||||
is BadgeDefinitionEvent -> BadgeDisplay(baseNote = baseNote, accountViewModel)
|
||||
else ->
|
||||
}
|
||||
|
||||
is BadgeDefinitionEvent -> {
|
||||
BadgeDisplay(baseNote = baseNote, accountViewModel)
|
||||
}
|
||||
|
||||
else -> {
|
||||
LongPressToQuickAction(baseNote = baseNote, accountViewModel = accountViewModel, nav) { showPopup ->
|
||||
CheckNewAndRenderNote(
|
||||
baseNote = baseNote,
|
||||
@@ -341,17 +350,20 @@ fun AcceptableNote(
|
||||
moreOptions = moreOptions,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
when (val noteEvent = baseNote.event) {
|
||||
is ChannelCreateEvent ->
|
||||
is ChannelCreateEvent -> {
|
||||
RenderPublicChatChannelHeader(
|
||||
channelId = noteEvent.id,
|
||||
sendToChannel = true,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
)
|
||||
is ChannelMetadataEvent ->
|
||||
}
|
||||
|
||||
is ChannelMetadataEvent -> {
|
||||
noteEvent.channelId()?.let {
|
||||
RenderPublicChatChannelHeader(
|
||||
channelId = it,
|
||||
@@ -360,7 +372,9 @@ fun AcceptableNote(
|
||||
nav = nav,
|
||||
)
|
||||
}
|
||||
is CommunityDefinitionEvent ->
|
||||
}
|
||||
|
||||
is CommunityDefinitionEvent -> {
|
||||
(baseNote as? AddressableNote)?.let {
|
||||
RenderCommunity(
|
||||
baseNote = it,
|
||||
@@ -368,8 +382,13 @@ fun AcceptableNote(
|
||||
nav = nav,
|
||||
)
|
||||
}
|
||||
is BadgeDefinitionEvent -> BadgeDisplay(baseNote, accountViewModel)
|
||||
else ->
|
||||
}
|
||||
|
||||
is BadgeDefinitionEvent -> {
|
||||
BadgeDisplay(baseNote, accountViewModel)
|
||||
}
|
||||
|
||||
else -> {
|
||||
LongPressToQuickAction(baseNote, accountViewModel, nav) { showPopup ->
|
||||
CheckNewAndRenderNote(
|
||||
baseNote = baseNote,
|
||||
@@ -388,6 +407,7 @@ fun AcceptableNote(
|
||||
moreOptions = moreOptions,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -717,34 +737,118 @@ private fun RenderNoteRow(
|
||||
nav: INav,
|
||||
) {
|
||||
when (val noteEvent = baseNote.event) {
|
||||
is AppDefinitionEvent -> RenderAppDefinition(baseNote, accountViewModel, nav)
|
||||
is AudioTrackEvent -> RenderAudioTrack(baseNote, ContentScale.FillWidth, accountViewModel, nav)
|
||||
is AudioHeaderEvent -> RenderAudioHeader(baseNote, ContentScale.FillWidth, accountViewModel, nav)
|
||||
is DraftWrapEvent -> RenderDraft(baseNote, quotesLeft, unPackReply, backgroundColor, accountViewModel, nav)
|
||||
is ReactionEvent -> RenderReaction(baseNote, quotesLeft, backgroundColor, accountViewModel, nav)
|
||||
is RepostEvent -> RenderRepost(baseNote, quotesLeft, backgroundColor, accountViewModel, nav)
|
||||
is GenericRepostEvent -> RenderRepost(baseNote, quotesLeft, backgroundColor, accountViewModel, nav)
|
||||
is ReportEvent -> RenderReport(baseNote, quotesLeft, backgroundColor, accountViewModel, nav)
|
||||
is LongTextNoteEvent -> RenderLongFormContent(baseNote, accountViewModel, nav)
|
||||
is WikiNoteEvent -> RenderWikiContent(baseNote, accountViewModel, nav)
|
||||
is NipTextEvent -> RenderNipContent(baseNote, accountViewModel, nav)
|
||||
is BadgeAwardEvent -> RenderBadgeAward(baseNote, backgroundColor, accountViewModel, nav)
|
||||
is FhirResourceEvent -> RenderFhirResource(baseNote, accountViewModel, nav)
|
||||
is PeopleListEvent -> DisplayPeopleList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
is FollowListEvent -> DisplayFollowList(baseNote, true, accountViewModel, nav)
|
||||
is RelaySetEvent -> DisplayRelaySet(baseNote, backgroundColor, accountViewModel, nav)
|
||||
is ChatMessageRelayListEvent -> DisplayDMRelayList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
is AdvertisedRelayListEvent -> DisplayNIP65RelayList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
is SearchRelayListEvent -> DisplaySearchRelayList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
is BlockedRelayListEvent -> DisplayBlockedRelayList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
is TrustedRelayListEvent -> DisplayTrustedRelayList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
is IndexerRelayListEvent -> DisplayIndexerRelayList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
is ProxyRelayListEvent -> DisplayProxyRelayList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
is BroadcastRelayListEvent -> DisplayBroadcastRelayList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
is PinListEvent -> RenderPinListEvent(baseNote, backgroundColor, accountViewModel, nav)
|
||||
is EmojiPackEvent -> RenderEmojiPack(baseNote, true, backgroundColor, accountViewModel)
|
||||
is LiveActivitiesEvent -> RenderLiveActivityEvent(baseNote, accountViewModel, nav)
|
||||
is GitRepositoryEvent -> RenderGitRepositoryEvent(baseNote, accountViewModel, nav)
|
||||
is AppDefinitionEvent -> {
|
||||
RenderAppDefinition(baseNote, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is AudioTrackEvent -> {
|
||||
RenderAudioTrack(baseNote, ContentScale.FillWidth, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is AudioHeaderEvent -> {
|
||||
RenderAudioHeader(baseNote, ContentScale.FillWidth, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is DraftWrapEvent -> {
|
||||
RenderDraft(baseNote, quotesLeft, unPackReply, backgroundColor, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is ReactionEvent -> {
|
||||
RenderReaction(baseNote, quotesLeft, backgroundColor, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is RepostEvent -> {
|
||||
RenderRepost(baseNote, quotesLeft, backgroundColor, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is GenericRepostEvent -> {
|
||||
RenderRepost(baseNote, quotesLeft, backgroundColor, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is ReportEvent -> {
|
||||
RenderReport(baseNote, quotesLeft, backgroundColor, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is LongTextNoteEvent -> {
|
||||
RenderLongFormContent(baseNote, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is WikiNoteEvent -> {
|
||||
RenderWikiContent(baseNote, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is NipTextEvent -> {
|
||||
RenderNipContent(baseNote, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is BadgeAwardEvent -> {
|
||||
RenderBadgeAward(baseNote, backgroundColor, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is FhirResourceEvent -> {
|
||||
RenderFhirResource(baseNote, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is PeopleListEvent -> {
|
||||
DisplayPeopleList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is FollowListEvent -> {
|
||||
DisplayFollowList(baseNote, true, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is RelaySetEvent -> {
|
||||
DisplayRelaySet(baseNote, backgroundColor, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is ChatMessageRelayListEvent -> {
|
||||
DisplayDMRelayList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is AdvertisedRelayListEvent -> {
|
||||
DisplayNIP65RelayList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is SearchRelayListEvent -> {
|
||||
DisplaySearchRelayList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is BlockedRelayListEvent -> {
|
||||
DisplayBlockedRelayList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is TrustedRelayListEvent -> {
|
||||
DisplayTrustedRelayList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is IndexerRelayListEvent -> {
|
||||
DisplayIndexerRelayList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is ProxyRelayListEvent -> {
|
||||
DisplayProxyRelayList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is BroadcastRelayListEvent -> {
|
||||
DisplayBroadcastRelayList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is PinListEvent -> {
|
||||
RenderPinListEvent(baseNote, backgroundColor, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is EmojiPackEvent -> {
|
||||
RenderEmojiPack(baseNote, true, backgroundColor, accountViewModel)
|
||||
}
|
||||
|
||||
is LiveActivitiesEvent -> {
|
||||
RenderLiveActivityEvent(baseNote, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is GitRepositoryEvent -> {
|
||||
RenderGitRepositoryEvent(baseNote, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is GitPatchEvent -> {
|
||||
RenderGitPatchEvent(
|
||||
baseNote,
|
||||
@@ -756,6 +860,7 @@ private fun RenderNoteRow(
|
||||
nav,
|
||||
)
|
||||
}
|
||||
|
||||
is GitIssueEvent -> {
|
||||
RenderGitIssueEvent(
|
||||
baseNote,
|
||||
@@ -767,6 +872,7 @@ private fun RenderNoteRow(
|
||||
nav,
|
||||
)
|
||||
}
|
||||
|
||||
is PrivateDmEvent -> {
|
||||
RenderPrivateMessage(
|
||||
baseNote,
|
||||
@@ -778,6 +884,7 @@ private fun RenderNoteRow(
|
||||
nav,
|
||||
)
|
||||
}
|
||||
|
||||
is ChatMessageEvent -> {
|
||||
RenderChatMessage(
|
||||
baseNote,
|
||||
@@ -790,6 +897,7 @@ private fun RenderNoteRow(
|
||||
nav,
|
||||
)
|
||||
}
|
||||
|
||||
is ChatMessageEncryptedFileHeaderEvent -> {
|
||||
RenderChatMessageEncryptedFile(
|
||||
baseNote,
|
||||
@@ -802,6 +910,7 @@ private fun RenderNoteRow(
|
||||
nav,
|
||||
)
|
||||
}
|
||||
|
||||
is ClassifiedsEvent -> {
|
||||
RenderClassifieds(
|
||||
noteEvent,
|
||||
@@ -810,6 +919,7 @@ private fun RenderNoteRow(
|
||||
nav,
|
||||
)
|
||||
}
|
||||
|
||||
is HighlightEvent -> {
|
||||
RenderHighlight(
|
||||
baseNote,
|
||||
@@ -821,6 +931,7 @@ private fun RenderNoteRow(
|
||||
nav,
|
||||
)
|
||||
}
|
||||
|
||||
is CommentEvent -> {
|
||||
RenderTextEvent(
|
||||
baseNote,
|
||||
@@ -834,7 +945,8 @@ private fun RenderNoteRow(
|
||||
nav,
|
||||
)
|
||||
}
|
||||
is NIP90ContentDiscoveryResponseEvent ->
|
||||
|
||||
is NIP90ContentDiscoveryResponseEvent -> {
|
||||
RenderNIP90ContentDiscoveryResponse(
|
||||
baseNote,
|
||||
makeItShort,
|
||||
@@ -844,13 +956,15 @@ private fun RenderNoteRow(
|
||||
accountViewModel,
|
||||
nav,
|
||||
)
|
||||
}
|
||||
|
||||
is NIP90StatusEvent ->
|
||||
is NIP90StatusEvent -> {
|
||||
RenderNIP90Status(
|
||||
baseNote,
|
||||
accountViewModel,
|
||||
nav,
|
||||
)
|
||||
}
|
||||
|
||||
is PollNoteEvent -> {
|
||||
RenderPoll(
|
||||
@@ -864,14 +978,39 @@ private fun RenderNoteRow(
|
||||
nav,
|
||||
)
|
||||
}
|
||||
is FileHeaderEvent -> FileHeaderDisplay(baseNote, true, ContentScale.FillWidth, accountViewModel)
|
||||
is VideoHorizontalEvent -> VideoDisplay(baseNote, makeItShort, canPreview, backgroundColor, ContentScale.FillWidth, accountViewModel, nav)
|
||||
is VideoVerticalEvent -> VideoDisplay(baseNote, makeItShort, canPreview, backgroundColor, ContentScale.FillWidth, accountViewModel, nav)
|
||||
is VideoNormalEvent -> VideoDisplay(baseNote, makeItShort, canPreview, backgroundColor, ContentScale.FillWidth, accountViewModel, nav)
|
||||
is VideoShortEvent -> VideoDisplay(baseNote, makeItShort, canPreview, backgroundColor, ContentScale.FillWidth, accountViewModel, nav)
|
||||
is PictureEvent -> PictureDisplay(baseNote, true, ContentScale.FillWidth, PaddingValues(vertical = 5.dp), backgroundColor, accountViewModel, nav)
|
||||
is BaseVoiceEvent -> RenderVoiceTrack(baseNote, accountViewModel, nav)
|
||||
is FileStorageHeaderEvent -> FileStorageHeaderDisplay(baseNote, true, ContentScale.FillWidth, accountViewModel)
|
||||
|
||||
is FileHeaderEvent -> {
|
||||
FileHeaderDisplay(baseNote, true, ContentScale.FillWidth, accountViewModel)
|
||||
}
|
||||
|
||||
is VideoHorizontalEvent -> {
|
||||
VideoDisplay(baseNote, makeItShort, canPreview, backgroundColor, ContentScale.FillWidth, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is VideoVerticalEvent -> {
|
||||
VideoDisplay(baseNote, makeItShort, canPreview, backgroundColor, ContentScale.FillWidth, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is VideoNormalEvent -> {
|
||||
VideoDisplay(baseNote, makeItShort, canPreview, backgroundColor, ContentScale.FillWidth, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is VideoShortEvent -> {
|
||||
VideoDisplay(baseNote, makeItShort, canPreview, backgroundColor, ContentScale.FillWidth, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is PictureEvent -> {
|
||||
PictureDisplay(baseNote, true, ContentScale.FillWidth, PaddingValues(vertical = 5.dp), backgroundColor, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is BaseVoiceEvent -> {
|
||||
RenderVoiceTrack(baseNote, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is FileStorageHeaderEvent -> {
|
||||
FileStorageHeaderDisplay(baseNote, true, ContentScale.FillWidth, accountViewModel)
|
||||
}
|
||||
|
||||
is CommunityPostApprovalEvent -> {
|
||||
RenderPostApproval(
|
||||
baseNote,
|
||||
@@ -881,6 +1020,7 @@ private fun RenderNoteRow(
|
||||
nav,
|
||||
)
|
||||
}
|
||||
|
||||
is TextNoteModificationEvent -> {
|
||||
RenderTextModificationEvent(
|
||||
baseNote,
|
||||
@@ -892,7 +1032,8 @@ private fun RenderNoteRow(
|
||||
nav,
|
||||
)
|
||||
}
|
||||
is ChannelMessageEvent ->
|
||||
|
||||
is ChannelMessageEvent -> {
|
||||
RenderChannelMessage(
|
||||
baseNote,
|
||||
makeItShort,
|
||||
@@ -903,7 +1044,9 @@ private fun RenderNoteRow(
|
||||
accountViewModel,
|
||||
nav,
|
||||
)
|
||||
is LiveActivitiesChatMessageEvent ->
|
||||
}
|
||||
|
||||
is LiveActivitiesChatMessageEvent -> {
|
||||
RenderLiveActivityChatMessage(
|
||||
baseNote,
|
||||
makeItShort,
|
||||
@@ -914,15 +1057,18 @@ private fun RenderNoteRow(
|
||||
accountViewModel,
|
||||
nav,
|
||||
)
|
||||
is TorrentEvent ->
|
||||
}
|
||||
|
||||
is TorrentEvent -> {
|
||||
RenderTorrent(
|
||||
baseNote,
|
||||
backgroundColor,
|
||||
accountViewModel,
|
||||
nav,
|
||||
)
|
||||
}
|
||||
|
||||
is TorrentCommentEvent ->
|
||||
is TorrentCommentEvent -> {
|
||||
RenderTorrentComment(
|
||||
baseNote,
|
||||
makeItShort,
|
||||
@@ -934,8 +1080,9 @@ private fun RenderNoteRow(
|
||||
accountViewModel,
|
||||
nav,
|
||||
)
|
||||
}
|
||||
|
||||
is InteractiveStoryBaseEvent ->
|
||||
is InteractiveStoryBaseEvent -> {
|
||||
RenderInteractiveStory(
|
||||
baseNote,
|
||||
makeItShort,
|
||||
@@ -945,7 +1092,9 @@ private fun RenderNoteRow(
|
||||
accountViewModel,
|
||||
nav,
|
||||
)
|
||||
is PublicMessageEvent ->
|
||||
}
|
||||
|
||||
is PublicMessageEvent -> {
|
||||
RenderPublicMessage(
|
||||
baseNote,
|
||||
makeItShort,
|
||||
@@ -955,6 +1104,8 @@ private fun RenderNoteRow(
|
||||
accountViewModel,
|
||||
nav,
|
||||
)
|
||||
}
|
||||
|
||||
else -> {
|
||||
RenderTextEvent(
|
||||
baseNote,
|
||||
|
||||
@@ -962,8 +962,14 @@ private fun RenderReactionType(
|
||||
)
|
||||
} else {
|
||||
when (reactionType) {
|
||||
"+" -> LikedIcon(iconSizeModifier)
|
||||
"-" -> Text(text = "\uD83D\uDC4E", maxLines = 1, fontSize = iconFontSize)
|
||||
"+" -> {
|
||||
LikedIcon(iconSizeModifier)
|
||||
}
|
||||
|
||||
"-" -> {
|
||||
Text(text = "\uD83D\uDC4E", maxLines = 1, fontSize = iconFontSize)
|
||||
}
|
||||
|
||||
else -> {
|
||||
if (EmojiCoder.isCoded(reactionType)) {
|
||||
AnimatedBorderTextCornerRadius(
|
||||
@@ -1611,6 +1617,7 @@ fun RenderReaction(reactionType: String) {
|
||||
fontSize = 22.sp,
|
||||
)
|
||||
}
|
||||
|
||||
else -> {
|
||||
if (EmojiCoder.isCoded(reactionType)) {
|
||||
AnimatedBorderTextCornerRadius(
|
||||
|
||||
+4
-1
@@ -326,12 +326,15 @@ private fun RenderReactionOption(
|
||||
)
|
||||
}
|
||||
}
|
||||
"-" ->
|
||||
|
||||
"-" -> {
|
||||
Text(
|
||||
text = "\uD83D\uDC4E ✖",
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
}
|
||||
|
||||
else -> {
|
||||
if (EmojiCoder.isCoded(reactionType)) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
|
||||
@@ -584,9 +584,15 @@ fun authenticate(
|
||||
super.onAuthenticationError(errorCode, errString)
|
||||
|
||||
when (errorCode) {
|
||||
BiometricPrompt.ERROR_NEGATIVE_BUTTON -> keyguardPrompt()
|
||||
BiometricPrompt.ERROR_LOCKOUT -> keyguardPrompt()
|
||||
else ->
|
||||
BiometricPrompt.ERROR_NEGATIVE_BUTTON -> {
|
||||
keyguardPrompt()
|
||||
}
|
||||
|
||||
BiometricPrompt.ERROR_LOCKOUT -> {
|
||||
keyguardPrompt()
|
||||
}
|
||||
|
||||
else -> {
|
||||
onError(
|
||||
stringRes(context, R.string.biometric_authentication_failed),
|
||||
stringRes(
|
||||
@@ -595,6 +601,7 @@ fun authenticate(
|
||||
errString.toString(),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -235,10 +235,13 @@ fun NonClickableUserPictures(
|
||||
Box(Modifier.size(size), contentAlignment = Alignment.TopEnd) {
|
||||
when (room.users.size) {
|
||||
0 -> {}
|
||||
1 ->
|
||||
|
||||
1 -> {
|
||||
LoadUser(baseUserHex = room.users.first(), accountViewModel) {
|
||||
it?.let { BaseUserPicture(it, size, accountViewModel, outerModifier = Modifier) }
|
||||
}
|
||||
}
|
||||
|
||||
2 -> {
|
||||
val userList = room.users.toList()
|
||||
|
||||
@@ -263,6 +266,7 @@ fun NonClickableUserPictures(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
3 -> {
|
||||
val userList = room.users.toList()
|
||||
|
||||
@@ -297,6 +301,7 @@ fun NonClickableUserPictures(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
val userList = room.users.toList()
|
||||
|
||||
|
||||
@@ -238,9 +238,11 @@ fun ZapCustomDialog(
|
||||
LnZapEvent.ZapType.PUBLIC, LnZapEvent.ZapType.ANONYMOUS -> {
|
||||
Text(text = stringRes(id = R.string.custom_zaps_add_a_message))
|
||||
}
|
||||
|
||||
LnZapEvent.ZapType.PRIVATE -> {
|
||||
Text(text = stringRes(id = R.string.custom_zaps_add_a_message_private))
|
||||
}
|
||||
|
||||
LnZapEvent.ZapType.NONZAP -> {
|
||||
Text(text = stringRes(id = R.string.custom_zaps_add_a_message_nonzap))
|
||||
}
|
||||
|
||||
+1
@@ -52,6 +52,7 @@ fun DisplayLocationObserver(viewModel: ILocationGrabber) {
|
||||
lineHeight = 12.sp,
|
||||
)
|
||||
}
|
||||
|
||||
LocationState.LocationResult.Loading -> {
|
||||
Text(
|
||||
text = stringRes(R.string.loading_location),
|
||||
|
||||
+3
@@ -235,6 +235,7 @@ private fun MyLoadUrlPreviewDirect(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
Box(contentAlignment = Alignment.BottomCenter, modifier = Modifier.aspectRatio(1f)) {
|
||||
ClickableUrl(urlText, url)
|
||||
@@ -288,11 +289,13 @@ private fun MyLoadUrlPreviewDirectFillWidth(
|
||||
UrlPreviewCard(url, previewInfo = state.previewInfo)
|
||||
}
|
||||
}
|
||||
|
||||
is UrlPreviewState.Loading -> {
|
||||
WaitAndDisplay {
|
||||
DisplayUrlWithLoadingSymbol(url)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
ClickableUrl(urlText, url)
|
||||
}
|
||||
|
||||
+5
-2
@@ -72,15 +72,18 @@ fun DisplayZapSplits(
|
||||
FlowRow {
|
||||
list.forEach {
|
||||
when (it) {
|
||||
is ZapSplitSetupLnAddress ->
|
||||
is ZapSplitSetupLnAddress -> {
|
||||
ClickableTextPrimary(it.lnAddress) { }
|
||||
is ZapSplitSetup ->
|
||||
}
|
||||
|
||||
is ZapSplitSetup -> {
|
||||
UserPicture(
|
||||
userHex = it.pubKeyHex,
|
||||
size = Size25dp,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-2
@@ -34,8 +34,14 @@ fun DisplayExternalId(
|
||||
nav: INav,
|
||||
) {
|
||||
when (externalId) {
|
||||
is GeohashId -> DisplayGeohashExternalId(externalId, accountViewModel, nav)
|
||||
is HashtagId -> DisplayHashtagExternalId(externalId, accountViewModel, nav)
|
||||
is GeohashId -> {
|
||||
DisplayGeohashExternalId(externalId, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is HashtagId -> {
|
||||
DisplayHashtagExternalId(externalId, accountViewModel, nav)
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,6 +176,7 @@ fun RenderLiveActivityEventInner(
|
||||
}
|
||||
|
||||
StatusTag.STATUS.ENDED -> {}
|
||||
|
||||
null -> {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,9 +201,11 @@ fun RenderFhirResource(event: FhirResourceEvent) {
|
||||
RenderEyeGlassesPrescription(it, state.localDb)
|
||||
}
|
||||
}
|
||||
|
||||
is VisionPrescription -> {
|
||||
RenderEyeGlassesPrescription(resource, state.localDb)
|
||||
}
|
||||
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
|
||||
+7
-8
@@ -119,12 +119,7 @@ class AccountStateViewModel : ViewModel() {
|
||||
is NEmbed -> null
|
||||
is NRelay -> null
|
||||
is NAddress -> null
|
||||
else ->
|
||||
try {
|
||||
if (loginWithExternalSigner) Hex.decode(key) else null
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
else -> runCatching { if (loginWithExternalSigner) Hex.decode(key) else null }
|
||||
}
|
||||
|
||||
if (loginWithExternalSigner && pubKeyParsed == null) {
|
||||
@@ -350,11 +345,15 @@ class AccountStateViewModel : ViewModel() {
|
||||
|
||||
fun currentAccountNPub() =
|
||||
when (val state = _accountContent.value) {
|
||||
is AccountState.LoggedIn ->
|
||||
is AccountState.LoggedIn -> {
|
||||
state.account.signer.pubKey
|
||||
.hexToByteArray()
|
||||
.toNpub()
|
||||
else -> null
|
||||
}
|
||||
|
||||
else -> {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun logOff(accountInfo: AccountInfo) {
|
||||
|
||||
@@ -64,12 +64,15 @@ fun UserFeedView(
|
||||
is UserFeedState.Empty -> {
|
||||
FeedEmpty { viewModel.invalidateData() }
|
||||
}
|
||||
|
||||
is UserFeedState.FeedError -> {
|
||||
FeedError(state.errorMessage) { viewModel.invalidateData() }
|
||||
}
|
||||
|
||||
is UserFeedState.Loaded -> {
|
||||
FeedLoaded(state, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is UserFeedState.Loading -> {
|
||||
LoadingFeed()
|
||||
}
|
||||
|
||||
+9
-1
@@ -1637,19 +1637,24 @@ class AccountViewModel(
|
||||
|
||||
when (val parsed = it.entity) {
|
||||
is NSec -> {}
|
||||
|
||||
is NPub -> {}
|
||||
|
||||
is NProfile -> {}
|
||||
|
||||
is NNote -> {
|
||||
LocalCache.checkGetOrCreateNote(parsed.hex)?.let { note ->
|
||||
returningNote = note
|
||||
}
|
||||
}
|
||||
|
||||
is NEvent -> {
|
||||
LocalCache.checkGetOrCreateNote(parsed.hex)?.let { note ->
|
||||
returningNote = note
|
||||
}
|
||||
}
|
||||
is NEmbed ->
|
||||
|
||||
is NEmbed -> {
|
||||
withContext(Dispatchers.IO) {
|
||||
val baseNote = LocalCache.getOrCreateNote(parsed.event)
|
||||
if (baseNote.event == null) {
|
||||
@@ -1660,13 +1665,16 @@ class AccountViewModel(
|
||||
|
||||
returningNote = baseNote
|
||||
}
|
||||
}
|
||||
|
||||
is NRelay -> {}
|
||||
|
||||
is NAddress -> {
|
||||
LocalCache.checkGetOrCreateNote(parsed.aTag())?.let { note ->
|
||||
returningNote = note
|
||||
}
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
|
||||
|
||||
+6
-1
@@ -195,19 +195,24 @@ class DraftEventHandler(
|
||||
draftEventWrap.replyTo?.forEach { it.addReply(draftEventWrap) }
|
||||
|
||||
when (rumor) {
|
||||
is ChatroomKeyable -> account.chatroomList.add(rumor, draftEventWrap)
|
||||
is ChatroomKeyable -> {
|
||||
account.chatroomList.add(rumor, draftEventWrap)
|
||||
}
|
||||
|
||||
is EphemeralChatEvent -> {
|
||||
rumor.roomId()?.let { roomId ->
|
||||
val channel = cache.getOrCreateEphemeralChannel(roomId)
|
||||
channel.addNote(draftEventWrap, null)
|
||||
}
|
||||
}
|
||||
|
||||
is ChannelMessageEvent -> {
|
||||
rumor.channelId()?.let { channelId ->
|
||||
val channel = cache.checkGetOrCreatePublicChatChannel(channelId)
|
||||
channel?.addNote(draftEventWrap, null)
|
||||
}
|
||||
}
|
||||
|
||||
is LiveActivitiesChatMessageEvent -> {
|
||||
rumor.activityAddress()?.let { channelId ->
|
||||
val channel = cache.getOrCreateLiveChannel(channelId)
|
||||
|
||||
+4
-2
@@ -118,21 +118,23 @@ private fun RenderBookmarkScreen(
|
||||
Column(Modifier.padding(it).fillMaxHeight()) {
|
||||
HorizontalPager(state = pagerState) { page ->
|
||||
when (page) {
|
||||
0 ->
|
||||
0 -> {
|
||||
RefresheableFeedView(
|
||||
privateFeedViewModel,
|
||||
null,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
)
|
||||
}
|
||||
|
||||
1 ->
|
||||
1 -> {
|
||||
RefresheableFeedView(
|
||||
publicFeedViewModel,
|
||||
null,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-2
@@ -53,7 +53,7 @@ fun RenderArticleList(
|
||||
|
||||
HorizontalPager(pagerState, modifier) { page ->
|
||||
when (page) {
|
||||
0 ->
|
||||
0 -> {
|
||||
ArticleList(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
articles = publicArticles,
|
||||
@@ -67,7 +67,9 @@ fun RenderArticleList(
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
)
|
||||
1 ->
|
||||
}
|
||||
|
||||
1 -> {
|
||||
ArticleList(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
articles = privateArticles,
|
||||
@@ -81,6 +83,7 @@ fun RenderArticleList(
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-6
@@ -157,7 +157,7 @@ fun BookmarkGroupScreenView(
|
||||
.imePadding(),
|
||||
) {
|
||||
when (bookmarkType) {
|
||||
BookmarkType.PostBookmark ->
|
||||
BookmarkType.PostBookmark -> {
|
||||
RenderPostList(
|
||||
bookmarkGroupViewModel,
|
||||
pagerState,
|
||||
@@ -182,7 +182,9 @@ fun BookmarkGroupScreenView(
|
||||
},
|
||||
nav,
|
||||
)
|
||||
BookmarkType.ArticleBookmark ->
|
||||
}
|
||||
|
||||
BookmarkType.ArticleBookmark -> {
|
||||
RenderArticleList(
|
||||
bookmarkGroupViewModel,
|
||||
pagerState,
|
||||
@@ -207,6 +209,7 @@ fun BookmarkGroupScreenView(
|
||||
},
|
||||
nav,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -246,26 +249,32 @@ fun BookmarkGroupHeaderTabs(
|
||||
val bookmarkGroup by bookmarkGroupViewModel.selectedBookmarkGroupFlow.collectAsStateWithLifecycle()
|
||||
val privateItemTypeLabel =
|
||||
when (bookmarkType) {
|
||||
BookmarkType.PostBookmark ->
|
||||
BookmarkType.PostBookmark -> {
|
||||
bookmarkGroup?.let {
|
||||
stringRes(R.string.private_posts_count, it.privatePostBookmarks.size)
|
||||
} ?: stringRes(R.string.private_posts_label)
|
||||
BookmarkType.ArticleBookmark ->
|
||||
}
|
||||
|
||||
BookmarkType.ArticleBookmark -> {
|
||||
bookmarkGroup?.let {
|
||||
stringRes(R.string.private_articles_count, it.privateArticleBookmarks.size)
|
||||
} ?: stringRes(R.string.private_posts_label)
|
||||
}
|
||||
}
|
||||
|
||||
val publicItemTypeLabel =
|
||||
when (bookmarkType) {
|
||||
BookmarkType.PostBookmark ->
|
||||
BookmarkType.PostBookmark -> {
|
||||
bookmarkGroup?.let {
|
||||
stringRes(R.string.public_posts_count, it.publicPostBookmarks.size)
|
||||
} ?: stringRes(R.string.public_posts_label)
|
||||
BookmarkType.ArticleBookmark ->
|
||||
}
|
||||
|
||||
BookmarkType.ArticleBookmark -> {
|
||||
bookmarkGroup?.let {
|
||||
stringRes(R.string.public_articles_count, it.publicArticleBookmarks.size)
|
||||
} ?: stringRes(R.string.public_articles_label)
|
||||
}
|
||||
}
|
||||
|
||||
TabRow(
|
||||
|
||||
+5
-2
@@ -52,7 +52,7 @@ fun RenderPostList(
|
||||
|
||||
HorizontalPager(pagerState, modifier) { page ->
|
||||
when (page) {
|
||||
0 ->
|
||||
0 -> {
|
||||
PostList(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
posts = publicPosts,
|
||||
@@ -66,7 +66,9 @@ fun RenderPostList(
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
)
|
||||
1 ->
|
||||
}
|
||||
|
||||
1 -> {
|
||||
PostList(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
posts = privatePosts,
|
||||
@@ -80,6 +82,7 @@ fun RenderPostList(
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
-4
@@ -84,10 +84,19 @@ fun RenderChatFeedView(
|
||||
|
||||
CrossfadeIfEnabled(targetState = feedState, animationSpec = tween(durationMillis = 100), accountViewModel = accountViewModel) { state ->
|
||||
when (state) {
|
||||
is FeedState.Loading -> LoadingFeed()
|
||||
is FeedState.Empty -> FeedEmpty { feed.invalidateData() }
|
||||
is FeedState.FeedError -> FeedError(state.errorMessage) { feed.invalidateData() }
|
||||
is FeedState.Loaded ->
|
||||
is FeedState.Loading -> {
|
||||
LoadingFeed()
|
||||
}
|
||||
|
||||
is FeedState.Empty -> {
|
||||
FeedEmpty { feed.invalidateData() }
|
||||
}
|
||||
|
||||
is FeedState.FeedError -> {
|
||||
FeedError(state.errorMessage) { feed.invalidateData() }
|
||||
}
|
||||
|
||||
is FeedState.Loaded -> {
|
||||
ChatFeedLoaded(
|
||||
state,
|
||||
accountViewModel,
|
||||
@@ -98,6 +107,7 @@ fun RenderChatFeedView(
|
||||
onWantsToEditDraft,
|
||||
avoidDraft,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -93,6 +93,7 @@ fun ChannelFileUploadDialog(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is LiveActivitiesChannel -> {
|
||||
channel.creator?.let {
|
||||
UserPicture(
|
||||
|
||||
+14
-4
@@ -120,26 +120,33 @@ private fun ChatroomEntry(
|
||||
) {
|
||||
val baseNoteEvent = lastMessage.event
|
||||
when (baseNoteEvent) {
|
||||
is ChannelMessageEvent ->
|
||||
is ChannelMessageEvent -> {
|
||||
baseNoteEvent.channelId()?.let {
|
||||
LoadPublicChatChannel(it, accountViewModel) { channel ->
|
||||
ChannelRoomCompose(lastMessage, channel, accountViewModel, nav)
|
||||
}
|
||||
}
|
||||
is ChannelMetadataEvent ->
|
||||
}
|
||||
|
||||
is ChannelMetadataEvent -> {
|
||||
baseNoteEvent.channelId()?.let {
|
||||
LoadPublicChatChannel(it, accountViewModel) { channel ->
|
||||
ChannelRoomCompose(lastMessage, channel, accountViewModel, nav)
|
||||
}
|
||||
}
|
||||
is ChannelCreateEvent ->
|
||||
}
|
||||
|
||||
is ChannelCreateEvent -> {
|
||||
LoadPublicChatChannel(baseNoteEvent.id, accountViewModel) { channel ->
|
||||
ChannelRoomCompose(lastMessage, channel, accountViewModel, nav)
|
||||
}
|
||||
}
|
||||
|
||||
is ChatroomKeyable -> {
|
||||
val room = baseNoteEvent.chatroomKey(accountViewModel.userProfile().pubkeyHex)
|
||||
UserRoomCompose(room, lastMessage, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is EphemeralChatEvent -> {
|
||||
baseNoteEvent.roomId()?.let {
|
||||
LoadEphemeralChatChannel(it, accountViewModel) { channel ->
|
||||
@@ -147,7 +154,10 @@ private fun ChatroomEntry(
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> BlankNote()
|
||||
|
||||
else -> {
|
||||
BlankNote()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -47,9 +47,11 @@ fun MessagesScreen(
|
||||
derivedStateOf {
|
||||
when (windowSizeClass.widthSizeClass) {
|
||||
WindowWidthSizeClass.Compact -> false
|
||||
|
||||
WindowWidthSizeClass.Expanded,
|
||||
WindowWidthSizeClass.Medium,
|
||||
-> true
|
||||
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
+3
@@ -77,12 +77,15 @@ private fun CrossFadeState(
|
||||
is FeedState.Empty -> {
|
||||
FeedEmpty { feedContentState.invalidateData() }
|
||||
}
|
||||
|
||||
is FeedState.FeedError -> {
|
||||
FeedError(state.errorMessage) { feedContentState.invalidateData() }
|
||||
}
|
||||
|
||||
is FeedState.Loaded -> {
|
||||
FeedLoaded(state, listState, accountViewModel, nav)
|
||||
}
|
||||
|
||||
FeedState.Loading -> {
|
||||
LoadingFeed()
|
||||
}
|
||||
|
||||
+5
-2
@@ -196,20 +196,23 @@ fun CommunityScreen(
|
||||
state = pagerState,
|
||||
) { page ->
|
||||
when (page) {
|
||||
0 ->
|
||||
0 -> {
|
||||
RefresheableFeedView(
|
||||
feedViewModel,
|
||||
null,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
)
|
||||
1 ->
|
||||
}
|
||||
|
||||
1 -> {
|
||||
RefresheableFeedView(
|
||||
modFeedViewModel,
|
||||
null,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
@@ -305,9 +305,11 @@ private fun RenderDiscoverFeed(
|
||||
is FeedState.Empty -> {
|
||||
FeedEmpty(feedContentState::invalidateData)
|
||||
}
|
||||
|
||||
is FeedState.FeedError -> {
|
||||
FeedError(state.errorMessage, feedContentState::invalidateData)
|
||||
}
|
||||
|
||||
is FeedState.Loaded -> {
|
||||
DiscoverFeedColumnsLoaded(
|
||||
state,
|
||||
@@ -318,6 +320,7 @@ private fun RenderDiscoverFeed(
|
||||
nav,
|
||||
)
|
||||
}
|
||||
|
||||
is FeedState.Loading -> {
|
||||
LoadingFeed()
|
||||
}
|
||||
@@ -368,9 +371,11 @@ private fun RenderDiscoverFeed(
|
||||
is FeedState.Empty -> {
|
||||
FeedEmpty(feedContentState::invalidateData)
|
||||
}
|
||||
|
||||
is FeedState.FeedError -> {
|
||||
FeedError(state.errorMessage, feedContentState::invalidateData)
|
||||
}
|
||||
|
||||
is FeedState.Loaded -> {
|
||||
DiscoverFeedLoaded(
|
||||
state,
|
||||
@@ -381,6 +386,7 @@ private fun RenderDiscoverFeed(
|
||||
nav,
|
||||
)
|
||||
}
|
||||
|
||||
is FeedState.Loading -> {
|
||||
LoadingFeed()
|
||||
}
|
||||
|
||||
+12
-3
@@ -124,9 +124,18 @@ open class DiscoverLiveFeedFilter(
|
||||
2
|
||||
}
|
||||
}
|
||||
StatusTag.STATUS.PLANNED -> 1
|
||||
StatusTag.STATUS.ENDED -> 0
|
||||
else -> 0
|
||||
|
||||
StatusTag.STATUS.PLANNED -> {
|
||||
1
|
||||
}
|
||||
|
||||
StatusTag.STATUS.ENDED -> {
|
||||
0
|
||||
}
|
||||
|
||||
else -> {
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
@@ -167,12 +167,15 @@ fun RenderLiveActivityThumb(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusTag.STATUS.ENDED -> {
|
||||
EndedFlag()
|
||||
}
|
||||
|
||||
StatusTag.STATUS.PLANNED -> {
|
||||
ScheduledFlag(card.starts)
|
||||
}
|
||||
|
||||
else -> {
|
||||
EndedFlag()
|
||||
}
|
||||
|
||||
+8
-3
@@ -176,26 +176,31 @@ fun FollowPackFeedScreen(
|
||||
state = pagerState,
|
||||
) { page ->
|
||||
when (page) {
|
||||
0 ->
|
||||
0 -> {
|
||||
RefresheableFeedView(
|
||||
newThreadFeedViewModel,
|
||||
null,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
)
|
||||
1 ->
|
||||
}
|
||||
|
||||
1 -> {
|
||||
RefresheableFeedView(
|
||||
conversationsFeedViewModel,
|
||||
null,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
)
|
||||
2 ->
|
||||
}
|
||||
|
||||
2 -> {
|
||||
UserFeedView(
|
||||
membersFeedViewModel,
|
||||
accountViewModel,
|
||||
nav,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-1
@@ -239,8 +239,12 @@ fun HomeScreenFloatingButton(
|
||||
.collectAsStateWithLifecycle()
|
||||
|
||||
when (val myLocation = location) {
|
||||
is LocationState.LocationResult.Success -> NewGeoPostButton(myLocation.geoHash.toString(), accountViewModel, nav)
|
||||
is LocationState.LocationResult.Success -> {
|
||||
NewGeoPostButton(myLocation.geoHash.toString(), accountViewModel, nav)
|
||||
}
|
||||
|
||||
is LocationState.LocationResult.LackPermission -> { }
|
||||
|
||||
is LocationState.LocationResult.Loading -> { }
|
||||
}
|
||||
} else {
|
||||
|
||||
+18
-4
@@ -581,10 +581,22 @@ open class ShortNotePostViewModel :
|
||||
val quotes = event.taggedQuotes()
|
||||
if (quotes.isNotEmpty()) "Quote" else "Post"
|
||||
}
|
||||
is PollNoteEvent -> "Poll"
|
||||
is VoiceEvent -> "Voice"
|
||||
is VoiceReplyEvent -> "Voice Reply"
|
||||
else -> "Post"
|
||||
|
||||
is PollNoteEvent -> {
|
||||
"Poll"
|
||||
}
|
||||
|
||||
is VoiceEvent -> {
|
||||
"Voice"
|
||||
}
|
||||
|
||||
is VoiceReplyEvent -> {
|
||||
"Voice Reply"
|
||||
}
|
||||
|
||||
else -> {
|
||||
"Post"
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun sendDraftSync() {
|
||||
@@ -1115,6 +1127,7 @@ open class ShortNotePostViewModel :
|
||||
voiceLocalFile = null
|
||||
voiceRecording = null
|
||||
}
|
||||
|
||||
is UploadOrchestrator.OrchestratorResult.NIP95Result -> {
|
||||
// For NIP95, we need to create the event and get the nevent URL
|
||||
// This is handled differently - skip for now
|
||||
@@ -1122,6 +1135,7 @@ open class ShortNotePostViewModel :
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is UploadingState.Error -> {
|
||||
onError(uploadErrorTitle, uploadVoiceFailed)
|
||||
voiceRecording = null
|
||||
|
||||
+3
@@ -286,14 +286,17 @@ class VoiceReplyViewModel : ViewModel() {
|
||||
|
||||
onSuccess()
|
||||
}
|
||||
|
||||
is UploadOrchestrator.OrchestratorResult.NIP95Result -> {
|
||||
accountViewModel.toastManager.toast(uploadErrorTitle, uploadVoiceNip95NotSupported)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is UploadingState.Error -> {
|
||||
accountViewModel.toastManager.toast(uploadErrorTitle, uploadVoiceFailed)
|
||||
}
|
||||
|
||||
else -> {
|
||||
accountViewModel.toastManager.toast(uploadErrorTitle, uploadVoiceFailed)
|
||||
}
|
||||
|
||||
+5
-1
@@ -94,12 +94,16 @@ private suspend fun checkChannelIsOnline(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is EphemeralChatChannel -> {
|
||||
// Check relay connection for ephemeral chat
|
||||
val relayUrl = channel.roomId.relayUrl
|
||||
OnlineChecker.isOnline(relayUrl.url, accountViewModel.httpClientBuilder::okHttpClientForVideo)
|
||||
}
|
||||
else -> false
|
||||
|
||||
else -> {
|
||||
false
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.d("LiveStatusIndicator", "Network error checking channel ${channel.toBestDisplayName()}: ${e.message}")
|
||||
|
||||
+4
-2
@@ -268,7 +268,7 @@ private fun PeopleListPager(
|
||||
selectedSetState.value?.let { selectedSet ->
|
||||
HorizontalPager(state = pagerState, modifier) { page ->
|
||||
when (page) {
|
||||
0 ->
|
||||
0 -> {
|
||||
PeopleListView(
|
||||
memberList = selectedSet.publicMembersList,
|
||||
onDeleteUser = { user ->
|
||||
@@ -278,8 +278,9 @@ private fun PeopleListPager(
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
)
|
||||
}
|
||||
|
||||
1 ->
|
||||
1 -> {
|
||||
PeopleListView(
|
||||
memberList = selectedSet.privateMembersList,
|
||||
onDeleteUser = { user ->
|
||||
@@ -289,6 +290,7 @@ private fun PeopleListPager(
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+17
-5
@@ -119,9 +119,11 @@ fun RenderCardFeed(
|
||||
is CardFeedState.Empty -> {
|
||||
NotificationFeedEmpty(feedContent::invalidateData)
|
||||
}
|
||||
|
||||
is CardFeedState.FeedError -> {
|
||||
FeedError(state.errorMessage, feedContent::invalidateData)
|
||||
}
|
||||
|
||||
is CardFeedState.Loaded -> {
|
||||
FeedLoaded(
|
||||
loaded = state,
|
||||
@@ -131,6 +133,7 @@ fun RenderCardFeed(
|
||||
nav = nav,
|
||||
)
|
||||
}
|
||||
|
||||
CardFeedState.Loading -> {
|
||||
LoadingFeed()
|
||||
}
|
||||
@@ -205,7 +208,7 @@ private fun RenderCardItem(
|
||||
nav: INav,
|
||||
) {
|
||||
when (item) {
|
||||
is NoteCard ->
|
||||
is NoteCard -> {
|
||||
NoteCardCompose(
|
||||
item,
|
||||
routeForLastRead = routeForLastRead,
|
||||
@@ -214,7 +217,9 @@ private fun RenderCardItem(
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
)
|
||||
is ZapUserSetCard ->
|
||||
}
|
||||
|
||||
is ZapUserSetCard -> {
|
||||
ZapUserSetCompose(
|
||||
item,
|
||||
isInnerNote = false,
|
||||
@@ -222,7 +227,9 @@ private fun RenderCardItem(
|
||||
nav = nav,
|
||||
routeForLastRead = routeForLastRead,
|
||||
)
|
||||
is MultiSetCard ->
|
||||
}
|
||||
|
||||
is MultiSetCard -> {
|
||||
MultiSetCompose(
|
||||
item,
|
||||
accountViewModel = accountViewModel,
|
||||
@@ -230,14 +237,18 @@ private fun RenderCardItem(
|
||||
nav = nav,
|
||||
routeForLastRead = routeForLastRead,
|
||||
)
|
||||
is BadgeCard ->
|
||||
}
|
||||
|
||||
is BadgeCard -> {
|
||||
BadgeCompose(
|
||||
item,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
routeForLastRead = routeForLastRead,
|
||||
)
|
||||
is MessageSetCard ->
|
||||
}
|
||||
|
||||
is MessageSetCard -> {
|
||||
MessageSetCompose(
|
||||
messageSetCard = item,
|
||||
routeForLastRead = routeForLastRead,
|
||||
@@ -245,6 +256,7 @@ private fun RenderCardItem(
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
-2
@@ -173,14 +173,17 @@ fun GalleryContentView(
|
||||
) {
|
||||
AutoNonlazyGrid(contentList.size) { contentIndex ->
|
||||
when (val content = contentList[contentIndex]) {
|
||||
is MediaUrlImage ->
|
||||
is MediaUrlImage -> {
|
||||
SensitivityWarning(content.contentWarning != null, accountViewModel) {
|
||||
UrlImageView(content, accountViewModel, ratio = ratio)
|
||||
}
|
||||
is MediaUrlVideo ->
|
||||
}
|
||||
|
||||
is MediaUrlVideo -> {
|
||||
SensitivityWarning(content.contentWarning != null, accountViewModel) {
|
||||
UrlVideoView(content, accountViewModel, ratio = ratio)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -226,12 +229,15 @@ fun UrlImageView(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is AsyncImagePainter.State.Error -> {
|
||||
ClickableUrl(urlText = "${content.url} ", url = content.url)
|
||||
}
|
||||
|
||||
is AsyncImagePainter.State.Success -> {
|
||||
SubcomposeAsyncImageContent(defaultModifier)
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
+3
@@ -61,9 +61,11 @@ fun RenderGalleryFeed(
|
||||
is FeedState.Empty -> {
|
||||
FeedEmpty { viewModel.invalidateData() }
|
||||
}
|
||||
|
||||
is FeedState.FeedError -> {
|
||||
FeedError(state.errorMessage) { viewModel.invalidateData() }
|
||||
}
|
||||
|
||||
is FeedState.Loaded -> {
|
||||
GalleryFeedLoaded(
|
||||
state,
|
||||
@@ -72,6 +74,7 @@ fun RenderGalleryFeed(
|
||||
nav,
|
||||
)
|
||||
}
|
||||
|
||||
is FeedState.Loading -> {
|
||||
LoadingFeed()
|
||||
}
|
||||
|
||||
+8
-3
@@ -51,8 +51,7 @@ class UserProfileGalleryFeedFilter(
|
||||
acceptableEvent(it, params, user)
|
||||
}
|
||||
|
||||
var sorted = sort(notes)
|
||||
return sorted.toList()
|
||||
return sort(notes).toList()
|
||||
}
|
||||
|
||||
override fun applyFilter(newItems: Set<Note>): Set<Note> = innerApplyFilter(newItems)
|
||||
@@ -70,7 +69,13 @@ class UserProfileGalleryFeedFilter(
|
||||
): Boolean {
|
||||
val noteEvent = it.event
|
||||
return (
|
||||
(it.event?.pubKey == user.pubkeyHex && (noteEvent is PictureEvent || noteEvent is VideoEvent || (noteEvent is ProfileGalleryEntryEvent) && noteEvent.hasUrl() && noteEvent.hasFromEvent())) // && noteEvent.isOneOf(SUPPORTED_VIDEO_FEED_MIME_TYPES_SET))
|
||||
(
|
||||
it.event?.pubKey == user.pubkeyHex && (
|
||||
noteEvent is PictureEvent ||
|
||||
noteEvent is VideoEvent ||
|
||||
(noteEvent is ProfileGalleryEntryEvent && noteEvent.hasUrl() && noteEvent.hasFromEvent())
|
||||
)
|
||||
) // && noteEvent.isOneOf(SUPPORTED_VIDEO_FEED_MIME_TYPES_SET))
|
||||
) &&
|
||||
params.match(noteEvent, it.relays) &&
|
||||
account.isAcceptable(it)
|
||||
|
||||
+1
@@ -261,6 +261,7 @@ fun DisplayNip05ProfileStatus(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
else -> { }
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -63,6 +63,7 @@ fun DisplayAppRecommendations(
|
||||
Recommends(state, accountViewModel, nav)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-2
@@ -263,13 +263,17 @@ fun WatchAndDisplayNip05Row(
|
||||
val nip05StateMetadata by user.nip05State().flow.collectAsStateWithLifecycle()
|
||||
|
||||
when (val nip05State = nip05StateMetadata) {
|
||||
is Nip05State.Exists -> ObserveAndDisplayNIP05(nip05State, accountViewModel)
|
||||
else ->
|
||||
is Nip05State.Exists -> {
|
||||
ObserveAndDisplayNIP05(nip05State, accountViewModel)
|
||||
}
|
||||
|
||||
else -> {
|
||||
Text(
|
||||
text = user.pubkeyDisplayHex(),
|
||||
fontSize = Font14SP,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-3
@@ -316,7 +316,7 @@ private fun RenderDebugMessage(msg: IRelayDebugMessage) {
|
||||
}
|
||||
|
||||
when (msg) {
|
||||
is ErrorDebugMessage ->
|
||||
is ErrorDebugMessage -> {
|
||||
SelectionContainer {
|
||||
Text(
|
||||
text = msg.message,
|
||||
@@ -324,7 +324,9 @@ private fun RenderDebugMessage(msg: IRelayDebugMessage) {
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
)
|
||||
}
|
||||
is NoticeDebugMessage ->
|
||||
}
|
||||
|
||||
is NoticeDebugMessage -> {
|
||||
SelectionContainer {
|
||||
Text(
|
||||
text = msg.message,
|
||||
@@ -332,7 +334,9 @@ private fun RenderDebugMessage(msg: IRelayDebugMessage) {
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
)
|
||||
}
|
||||
is SpamDebugMessage ->
|
||||
}
|
||||
|
||||
is SpamDebugMessage -> {
|
||||
SelectionContainer {
|
||||
val uri = LocalUriHandler.current
|
||||
val start = stringRes(R.string.duplicated_post)
|
||||
@@ -358,6 +362,7 @@ private fun RenderDebugMessage(msg: IRelayDebugMessage) {
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
@@ -59,12 +59,15 @@ fun StringFeedView(
|
||||
is StringFeedState.Empty -> {
|
||||
StringFeedEmpty(pre, post) { viewModel.invalidateData() }
|
||||
}
|
||||
|
||||
is StringFeedState.FeedError -> {
|
||||
FeedError(state.errorMessage) { viewModel.invalidateData() }
|
||||
}
|
||||
|
||||
is StringFeedState.Loaded -> {
|
||||
FeedLoaded(state, pre, post, inner)
|
||||
}
|
||||
|
||||
is StringFeedState.Loading -> {
|
||||
LoadingFeed()
|
||||
}
|
||||
|
||||
+3
@@ -190,12 +190,15 @@ fun RenderPage(
|
||||
is FeedState.Empty -> {
|
||||
FeedEmpty(videoFeedContentState::invalidateData)
|
||||
}
|
||||
|
||||
is FeedState.FeedError -> {
|
||||
FeedError(state.errorMessage, videoFeedContentState::invalidateData)
|
||||
}
|
||||
|
||||
is FeedState.Loaded -> {
|
||||
LoadedState(state, pagerStateKey, videoFeedContentState, accountViewModel, nav)
|
||||
}
|
||||
|
||||
is FeedState.Loading -> {
|
||||
LoadingFeed()
|
||||
}
|
||||
|
||||
+6
-2
@@ -155,18 +155,22 @@ fun LoginPage(
|
||||
|
||||
loginViewModel.errorManager.error?.let { error ->
|
||||
when (error) {
|
||||
is LoginErrorManager.SingleErrorMsg ->
|
||||
is LoginErrorManager.SingleErrorMsg -> {
|
||||
Text(
|
||||
text = stringRes(error.errorResId),
|
||||
color = MaterialTheme.colorScheme.error,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
)
|
||||
is LoginErrorManager.ParamsErrorMsg ->
|
||||
}
|
||||
|
||||
is LoginErrorManager.ParamsErrorMsg -> {
|
||||
Text(
|
||||
text = stringRes(error.errorResId, *error.params),
|
||||
color = MaterialTheme.colorScheme.error,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
)
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-2
@@ -148,18 +148,22 @@ fun SignUpPage(
|
||||
|
||||
signUpViewModel.errorManager.error?.let { error ->
|
||||
when (error) {
|
||||
is LoginErrorManager.SingleErrorMsg ->
|
||||
is LoginErrorManager.SingleErrorMsg -> {
|
||||
Text(
|
||||
text = stringRes(error.errorResId),
|
||||
color = MaterialTheme.colorScheme.error,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
)
|
||||
is LoginErrorManager.ParamsErrorMsg ->
|
||||
}
|
||||
|
||||
is LoginErrorManager.ParamsErrorMsg -> {
|
||||
Text(
|
||||
text = stringRes(error.errorResId, *error.params),
|
||||
color = MaterialTheme.colorScheme.error,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
)
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -540,12 +540,16 @@ fun AmethystTheme(
|
||||
uiManager.nightMode = UiModeManager.MODE_NIGHT_YES
|
||||
true
|
||||
}
|
||||
|
||||
ThemeType.LIGHT -> {
|
||||
val uiManager = context.getSystemService(Context.UI_MODE_SERVICE) as UiModeManager
|
||||
uiManager.nightMode = UiModeManager.MODE_NIGHT_NO
|
||||
false
|
||||
}
|
||||
else -> isSystemInDarkTheme()
|
||||
|
||||
else -> {
|
||||
isSystemInDarkTheme()
|
||||
}
|
||||
}
|
||||
val colors = if (darkTheme) DarkColorPalette else LightColorPalette
|
||||
|
||||
|
||||
@@ -67,41 +67,57 @@ val DefaultParagraphSpacing: TextUnit = 18.sp
|
||||
|
||||
internal val DefaultHeadingStyle: HeadingStyle = { level, textStyle ->
|
||||
when (level) {
|
||||
0 ->
|
||||
0 -> {
|
||||
Typography.displayLarge.copy(
|
||||
fontSize = 32.sp,
|
||||
lineHeight = 40.sp,
|
||||
)
|
||||
1 ->
|
||||
}
|
||||
|
||||
1 -> {
|
||||
Typography.displayMedium.copy(
|
||||
fontSize = 28.sp,
|
||||
lineHeight = 36.sp,
|
||||
)
|
||||
2 ->
|
||||
}
|
||||
|
||||
2 -> {
|
||||
Typography.displaySmall.copy(
|
||||
fontSize = 26.sp,
|
||||
lineHeight = 34.sp,
|
||||
)
|
||||
3 ->
|
||||
}
|
||||
|
||||
3 -> {
|
||||
Typography.displaySmall.copy(
|
||||
fontSize = 24.sp,
|
||||
lineHeight = 32.sp,
|
||||
)
|
||||
4 ->
|
||||
}
|
||||
|
||||
4 -> {
|
||||
Typography.headlineLarge.copy(
|
||||
fontSize = 22.sp,
|
||||
lineHeight = 26.sp,
|
||||
)
|
||||
5 ->
|
||||
}
|
||||
|
||||
5 -> {
|
||||
Typography.headlineMedium.copy(
|
||||
fontSize = 20.sp,
|
||||
lineHeight = 24.sp,
|
||||
)
|
||||
6 ->
|
||||
}
|
||||
|
||||
6 -> {
|
||||
Typography.headlineSmall.copy(
|
||||
fontSize = 18.sp,
|
||||
lineHeight = 22.sp,
|
||||
)
|
||||
else -> textStyle
|
||||
}
|
||||
|
||||
else -> {
|
||||
textStyle
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,10 +20,12 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.tor
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.lifecycle.ViewModel
|
||||
|
||||
@Stable
|
||||
class TorDialogViewModel : ViewModel() {
|
||||
val torType = mutableStateOf(TorType.INTERNAL)
|
||||
val socksPortStr = mutableStateOf("9050")
|
||||
@@ -102,7 +104,7 @@ class TorDialogViewModel : ViewModel() {
|
||||
TorPresetType.ONLY_WHEN_NEEDED -> resetOnlyFlags(torOnlyWhenNeededPreset)
|
||||
TorPresetType.SMALL_PAYLOADS -> resetOnlyFlags(torSmallPayloadsPreset)
|
||||
TorPresetType.FULL_PRIVACY -> resetOnlyFlags(torFullyPrivate)
|
||||
TorPresetType.CUSTOM -> { }
|
||||
TorPresetType.CUSTOM -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -58,9 +58,11 @@ class TorManager(
|
||||
TorType.INTERNAL -> {
|
||||
emitAll(service.status)
|
||||
}
|
||||
|
||||
TorType.OFF -> {
|
||||
emit(TorServiceStatus.Off)
|
||||
}
|
||||
|
||||
TorType.EXTERNAL -> {
|
||||
if (externalSocksPort > 0) {
|
||||
emit(TorServiceStatus.Active(externalSocksPort))
|
||||
|
||||
@@ -52,9 +52,7 @@ fun parseTorType(code: Int?): TorType =
|
||||
TorType.OFF.screenCode -> TorType.OFF
|
||||
TorType.INTERNAL.screenCode -> TorType.INTERNAL
|
||||
TorType.EXTERNAL.screenCode -> TorType.EXTERNAL
|
||||
else -> {
|
||||
TorType.INTERNAL
|
||||
}
|
||||
else -> TorType.INTERNAL
|
||||
}
|
||||
|
||||
enum class TorPresetType(
|
||||
@@ -75,9 +73,7 @@ fun parseTorPresetType(code: Int?): TorPresetType =
|
||||
TorPresetType.DEFAULT.screenCode -> TorPresetType.DEFAULT
|
||||
TorPresetType.SMALL_PAYLOADS.screenCode -> TorPresetType.SMALL_PAYLOADS
|
||||
TorPresetType.FULL_PRIVACY.screenCode -> TorPresetType.FULL_PRIVACY
|
||||
else -> {
|
||||
TorPresetType.CUSTOM
|
||||
}
|
||||
else -> TorPresetType.CUSTOM
|
||||
}
|
||||
|
||||
fun isPreset(
|
||||
|
||||
@@ -257,7 +257,7 @@ fun PrivacySettingsBody(dialogViewModel: TorDialogViewModel) {
|
||||
dialogViewModel.moneyOperationsViaTor,
|
||||
)
|
||||
|
||||
/**
|
||||
/*
|
||||
* Too hard to separate Coil into regular images and profile pics
|
||||
SwitchSettingsRow(
|
||||
R.string.tor_use_profile_pictures,
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.quartz.nip01Core.relay.filters
|
||||
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
class FilterTest {
|
||||
@Test
|
||||
fun testIsEmpty() {
|
||||
assertTrue(Filter().isEmpty())
|
||||
assertTrue(Filter(ids = listOf()).isEmpty())
|
||||
assertTrue(Filter(authors = listOf()).isEmpty())
|
||||
assertTrue(Filter(kinds = listOf()).isEmpty())
|
||||
assertTrue(Filter(tags = mapOf()).isEmpty())
|
||||
assertTrue(Filter(tagsAll = mapOf()).isEmpty())
|
||||
assertTrue(Filter(tags = mapOf("e" to listOf())).isEmpty())
|
||||
assertTrue(Filter(tagsAll = mapOf("e" to listOf())).isEmpty())
|
||||
assertTrue(Filter(search = "").isEmpty())
|
||||
}
|
||||
}
|
||||
@@ -93,6 +93,7 @@ class EnsureTest {
|
||||
(args[1].length == KEY_SIZE),
|
||||
(args[1].isHex()),
|
||||
-> null
|
||||
|
||||
else -> args[0] + args[1]
|
||||
}
|
||||
|
||||
|
||||
+5
-1
@@ -189,6 +189,7 @@ object BlurHashDecoderOld {
|
||||
calculate -> {
|
||||
DoubleArray(height * numCompY).also { cacheCosinesY[height * numCompY] = it }
|
||||
}
|
||||
|
||||
else -> {
|
||||
cacheCosinesY[height * numCompY]!!
|
||||
}
|
||||
@@ -202,7 +203,10 @@ object BlurHashDecoderOld {
|
||||
calculate -> {
|
||||
DoubleArray(width * numCompX).also { cacheCosinesX[width * numCompX] = it }
|
||||
}
|
||||
else -> cacheCosinesX[width * numCompX]!!
|
||||
|
||||
else -> {
|
||||
cacheCosinesX[width * numCompX]!!
|
||||
}
|
||||
}
|
||||
|
||||
private fun DoubleArray.getCos(
|
||||
|
||||
+5
-1
@@ -60,6 +60,7 @@ object CosineCache {
|
||||
cacheCosinesY.put(height * numCompY, it)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
cacheCosinesY[height * numCompY]!!
|
||||
}
|
||||
@@ -77,6 +78,9 @@ object CosineCache {
|
||||
cos(PI * x * i / width)
|
||||
}.also { cacheCosinesX.put(width * numCompX, it) }
|
||||
}
|
||||
else -> cacheCosinesX[width * numCompX]!!
|
||||
|
||||
else -> {
|
||||
cacheCosinesX[width * numCompX]!!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,7 +191,10 @@ open class Note(
|
||||
fun relayHintUrl(): NormalizedRelayUrl? {
|
||||
// checks Community Events first
|
||||
when (val noteEvent = event) {
|
||||
is CommunityDefinitionEvent -> noteEvent.relayUrls().firstOrNull()?.let { return it }
|
||||
is CommunityDefinitionEvent -> {
|
||||
noteEvent.relayUrls().firstOrNull()?.let { return it }
|
||||
}
|
||||
|
||||
is IsInPublicChatChannel -> {
|
||||
inGatherers?.forEach {
|
||||
if (it is com.vitorpamplona.amethyst.commons.model.Channel) {
|
||||
@@ -199,9 +202,11 @@ open class Note(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is LiveActivitiesEvent -> {
|
||||
noteEvent.relays().ifEmpty { null }?.toSet()
|
||||
}
|
||||
|
||||
is LiveActivitiesChatMessageEvent -> {
|
||||
inGatherers?.forEach {
|
||||
if (it is com.vitorpamplona.amethyst.commons.model.Channel) {
|
||||
@@ -209,7 +214,10 @@ open class Note(
|
||||
}
|
||||
}
|
||||
}
|
||||
is EphemeralChatEvent -> noteEvent.roomId()?.let { return it.relayUrl }
|
||||
|
||||
is EphemeralChatEvent -> {
|
||||
noteEvent.roomId()?.let { return it.relayUrl }
|
||||
}
|
||||
}
|
||||
|
||||
val currentOutbox = author?.outboxRelays()?.toSet()
|
||||
|
||||
+4
@@ -108,14 +108,17 @@ object MetaTagsParser {
|
||||
consume()
|
||||
break
|
||||
}
|
||||
|
||||
// `>` out of quote -> end of tag
|
||||
quote == null && c == '>' -> {
|
||||
break
|
||||
}
|
||||
|
||||
// entering quote
|
||||
quote == null && (c == '\'' || c == '"') -> {
|
||||
quote = c
|
||||
}
|
||||
|
||||
// leaving quote
|
||||
quote != null && c == quote -> {
|
||||
quote = null
|
||||
@@ -263,6 +266,7 @@ object MetaTagsParser {
|
||||
State.AFTER_EQ -> {
|
||||
when {
|
||||
c.isWhitespace() -> {}
|
||||
|
||||
c == '\'' || c == '"' -> {
|
||||
valueBegin = i + 1
|
||||
valueQuote = c
|
||||
|
||||
+18
-9
@@ -66,54 +66,63 @@ class OpenGraphParser {
|
||||
|
||||
metaTags.forEach {
|
||||
when (it.attr(ATTRIBUTE_VALUE_PROPERTY)) {
|
||||
in META_X_TITLE ->
|
||||
in META_X_TITLE -> {
|
||||
if (title.isEmpty()) {
|
||||
title = it.attr(CONTENT)
|
||||
}
|
||||
}
|
||||
|
||||
in META_X_DESCRIPTION ->
|
||||
in META_X_DESCRIPTION -> {
|
||||
if (description.isEmpty()) {
|
||||
description = it.attr(CONTENT)
|
||||
}
|
||||
}
|
||||
|
||||
in META_X_IMAGE ->
|
||||
in META_X_IMAGE -> {
|
||||
if (image.isEmpty()) {
|
||||
image = it.attr(CONTENT)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when (it.attr(ATTRIBUTE_VALUE_NAME)) {
|
||||
in META_X_TITLE ->
|
||||
in META_X_TITLE -> {
|
||||
if (title.isEmpty()) {
|
||||
title = it.attr(CONTENT)
|
||||
}
|
||||
}
|
||||
|
||||
in META_X_DESCRIPTION ->
|
||||
in META_X_DESCRIPTION -> {
|
||||
if (description.isEmpty()) {
|
||||
description = it.attr(CONTENT)
|
||||
}
|
||||
}
|
||||
|
||||
in META_X_IMAGE ->
|
||||
in META_X_IMAGE -> {
|
||||
if (image.isEmpty()) {
|
||||
image = it.attr(CONTENT)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when (it.attr(ATTRIBUTE_VALUE_ITEMPROP)) {
|
||||
in META_X_TITLE ->
|
||||
in META_X_TITLE -> {
|
||||
if (title.isEmpty()) {
|
||||
title = it.attr(CONTENT)
|
||||
}
|
||||
}
|
||||
|
||||
in META_X_DESCRIPTION ->
|
||||
in META_X_DESCRIPTION -> {
|
||||
if (description.isEmpty()) {
|
||||
description = it.attr(CONTENT)
|
||||
}
|
||||
}
|
||||
|
||||
in META_X_IMAGE ->
|
||||
in META_X_IMAGE -> {
|
||||
if (image.isEmpty()) {
|
||||
image = it.attr(CONTENT)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (title.isNotEmpty() && description.isNotEmpty() && image.isNotEmpty()) {
|
||||
|
||||
+22
-5
@@ -36,14 +36,24 @@ class GalleryParser {
|
||||
|
||||
paragraph.words.forEach { word ->
|
||||
when (word) {
|
||||
is ImageSegment, is Base64Segment -> imageCount++
|
||||
is VideoSegment -> hasNonWhitespaceNonImageContent = true // Videos are not images
|
||||
is ImageSegment, is Base64Segment -> {
|
||||
imageCount++
|
||||
}
|
||||
|
||||
is VideoSegment -> {
|
||||
hasNonWhitespaceNonImageContent = true
|
||||
}
|
||||
|
||||
// Videos are not images
|
||||
is RegularTextSegment -> {
|
||||
if (word.segmentText.isNotBlank()) {
|
||||
hasNonWhitespaceNonImageContent = true
|
||||
}
|
||||
}
|
||||
else -> hasNonWhitespaceNonImageContent = true // Links, emojis, etc.
|
||||
|
||||
else -> {
|
||||
hasNonWhitespaceNonImageContent = true
|
||||
} // Links, emojis, etc.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,9 +169,16 @@ class GalleryParser {
|
||||
hasVideo = true
|
||||
break
|
||||
}
|
||||
seg is ImageSegment || seg is Base64Segment -> imageSegments.add(seg)
|
||||
|
||||
seg is ImageSegment || seg is Base64Segment -> {
|
||||
imageSegments.add(seg)
|
||||
}
|
||||
|
||||
seg is RegularTextSegment && seg.segmentText.isBlank() -> { /* skip whitespace */ }
|
||||
else -> break
|
||||
|
||||
else -> {
|
||||
break
|
||||
}
|
||||
}
|
||||
j++
|
||||
}
|
||||
|
||||
+6
@@ -59,6 +59,7 @@ fun parseSearchInput(input: String): List<SearchResult> {
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
is NProfile -> {
|
||||
results.add(
|
||||
SearchResult.UserResult(
|
||||
@@ -67,6 +68,7 @@ fun parseSearchInput(input: String): List<SearchResult> {
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
is NSec -> {
|
||||
results.add(
|
||||
SearchResult.UserResult(
|
||||
@@ -75,6 +77,7 @@ fun parseSearchInput(input: String): List<SearchResult> {
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
is NNote -> {
|
||||
results.add(
|
||||
SearchResult.NoteResult(
|
||||
@@ -83,6 +86,7 @@ fun parseSearchInput(input: String): List<SearchResult> {
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
is NEvent -> {
|
||||
results.add(
|
||||
SearchResult.NoteResult(
|
||||
@@ -91,6 +95,7 @@ fun parseSearchInput(input: String): List<SearchResult> {
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
is NAddress -> {
|
||||
results.add(
|
||||
SearchResult.AddressResult(
|
||||
@@ -101,6 +106,7 @@ fun parseSearchInput(input: String): List<SearchResult> {
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
else -> { }
|
||||
}
|
||||
return results
|
||||
|
||||
@@ -29,10 +29,16 @@ fun String.firstFullCharOld(): String {
|
||||
return when (this.length) {
|
||||
0,
|
||||
1,
|
||||
-> return this
|
||||
-> {
|
||||
return this
|
||||
}
|
||||
|
||||
2,
|
||||
3,
|
||||
-> return if (isUTF16Char(0)) this.take(2) else this.take(1)
|
||||
-> {
|
||||
return if (isUTF16Char(0)) this.take(2) else this.take(1)
|
||||
}
|
||||
|
||||
else -> {
|
||||
val first = isUTF16Char(0)
|
||||
val second = isUTF16Char(2)
|
||||
|
||||
+22
-37
@@ -62,19 +62,24 @@ fun timeAgo(
|
||||
updateFormattersIfNeeded()
|
||||
prefix + yearFormatter.format(time * 1000)
|
||||
}
|
||||
|
||||
timeDifference > TimeUtils.ONE_MONTH -> {
|
||||
updateFormattersIfNeeded()
|
||||
prefix + monthFormatter.format(time * 1000)
|
||||
}
|
||||
|
||||
timeDifference > TimeUtils.ONE_DAY -> {
|
||||
prefix + (timeDifference / TimeUtils.ONE_DAY).toString() + "d"
|
||||
}
|
||||
|
||||
timeDifference > TimeUtils.ONE_HOUR -> {
|
||||
prefix + (timeDifference / TimeUtils.ONE_HOUR).toString() + "h"
|
||||
}
|
||||
|
||||
timeDifference > TimeUtils.ONE_MINUTE -> {
|
||||
prefix + (timeDifference / TimeUtils.ONE_MINUTE).toString() + "m"
|
||||
}
|
||||
|
||||
else -> {
|
||||
prefix + "now"
|
||||
}
|
||||
@@ -83,46 +88,22 @@ fun timeAgo(
|
||||
|
||||
fun timeDiffAgoLong(timeDifference: Int): String =
|
||||
when {
|
||||
timeDifference > TimeUtils.ONE_YEAR -> {
|
||||
(timeDifference / TimeUtils.ONE_YEAR).toString() + " years"
|
||||
}
|
||||
timeDifference > TimeUtils.ONE_MONTH -> {
|
||||
(timeDifference / TimeUtils.ONE_MONTH).toString() + " months"
|
||||
}
|
||||
timeDifference > TimeUtils.ONE_DAY -> {
|
||||
(timeDifference / TimeUtils.ONE_DAY).toString() + " days"
|
||||
}
|
||||
timeDifference > TimeUtils.ONE_HOUR -> {
|
||||
(timeDifference / TimeUtils.ONE_HOUR).toString() + " hours"
|
||||
}
|
||||
timeDifference > TimeUtils.ONE_MINUTE -> {
|
||||
(timeDifference / TimeUtils.ONE_MINUTE).toString() + " minutes"
|
||||
}
|
||||
else -> {
|
||||
"now"
|
||||
}
|
||||
timeDifference > TimeUtils.ONE_YEAR -> (timeDifference / TimeUtils.ONE_YEAR).toString() + " years"
|
||||
timeDifference > TimeUtils.ONE_MONTH -> (timeDifference / TimeUtils.ONE_MONTH).toString() + " months"
|
||||
timeDifference > TimeUtils.ONE_DAY -> (timeDifference / TimeUtils.ONE_DAY).toString() + " days"
|
||||
timeDifference > TimeUtils.ONE_HOUR -> (timeDifference / TimeUtils.ONE_HOUR).toString() + " hours"
|
||||
timeDifference > TimeUtils.ONE_MINUTE -> (timeDifference / TimeUtils.ONE_MINUTE).toString() + " minutes"
|
||||
else -> "now"
|
||||
}
|
||||
|
||||
fun timeDiffAgoShortish(timeDifference: Int): String =
|
||||
when {
|
||||
timeDifference > TimeUtils.ONE_YEAR -> {
|
||||
(timeDifference / TimeUtils.ONE_YEAR).toString() + " yrs"
|
||||
}
|
||||
timeDifference > TimeUtils.ONE_MONTH -> {
|
||||
(timeDifference / TimeUtils.ONE_MONTH).toString() + " mos"
|
||||
}
|
||||
timeDifference > TimeUtils.ONE_DAY -> {
|
||||
(timeDifference / TimeUtils.ONE_DAY).toString() + " days"
|
||||
}
|
||||
timeDifference > TimeUtils.ONE_HOUR -> {
|
||||
(timeDifference / TimeUtils.ONE_HOUR).toString() + " hrs"
|
||||
}
|
||||
timeDifference > TimeUtils.ONE_MINUTE -> {
|
||||
(timeDifference / TimeUtils.ONE_MINUTE).toString() + " mins"
|
||||
}
|
||||
else -> {
|
||||
"now"
|
||||
}
|
||||
timeDifference > TimeUtils.ONE_YEAR -> (timeDifference / TimeUtils.ONE_YEAR).toString() + " yrs"
|
||||
timeDifference > TimeUtils.ONE_MONTH -> (timeDifference / TimeUtils.ONE_MONTH).toString() + " mos"
|
||||
timeDifference > TimeUtils.ONE_DAY -> (timeDifference / TimeUtils.ONE_DAY).toString() + " days"
|
||||
timeDifference > TimeUtils.ONE_HOUR -> (timeDifference / TimeUtils.ONE_HOUR).toString() + " hrs"
|
||||
timeDifference > TimeUtils.ONE_MINUTE -> (timeDifference / TimeUtils.ONE_MINUTE).toString() + " mins"
|
||||
else -> "now"
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,11 +129,15 @@ fun dateFormatter(
|
||||
updateFormattersIfNeeded()
|
||||
yearFormatter.format(time * 1000)
|
||||
}
|
||||
|
||||
timeDifference > TimeUtils.ONE_DAY -> {
|
||||
updateFormattersIfNeeded()
|
||||
monthFormatter.format(time * 1000)
|
||||
}
|
||||
else -> today
|
||||
|
||||
else -> {
|
||||
today
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -296,6 +296,7 @@ fun App(
|
||||
onLoginSuccess = { onScreenChange(DesktopScreen.Feed) },
|
||||
)
|
||||
}
|
||||
|
||||
is AccountState.LoggedIn -> {
|
||||
val account = accountState as AccountState.LoggedIn
|
||||
val nwcConnection by accountManager.nwcConnection.collectAsState()
|
||||
@@ -442,7 +443,7 @@ fun MainContent(
|
||||
modifier = Modifier.weight(1f).fillMaxHeight().padding(24.dp),
|
||||
) {
|
||||
when (currentScreen) {
|
||||
DesktopScreen.Feed ->
|
||||
DesktopScreen.Feed -> {
|
||||
FeedScreen(
|
||||
relayManager = relayManager,
|
||||
localCache = localCache,
|
||||
@@ -458,7 +459,9 @@ fun MainContent(
|
||||
},
|
||||
onZapFeedback = onZapFeedback,
|
||||
)
|
||||
DesktopScreen.Reads ->
|
||||
}
|
||||
|
||||
DesktopScreen.Reads -> {
|
||||
ReadsScreen(
|
||||
relayManager = relayManager,
|
||||
localCache = localCache,
|
||||
@@ -470,7 +473,9 @@ fun MainContent(
|
||||
onScreenChange(DesktopScreen.Thread(noteId))
|
||||
},
|
||||
)
|
||||
DesktopScreen.Search ->
|
||||
}
|
||||
|
||||
DesktopScreen.Search -> {
|
||||
SearchScreen(
|
||||
localCache = localCache,
|
||||
relayManager = relayManager,
|
||||
@@ -482,7 +487,9 @@ fun MainContent(
|
||||
onScreenChange(DesktopScreen.Thread(noteId))
|
||||
},
|
||||
)
|
||||
DesktopScreen.Bookmarks ->
|
||||
}
|
||||
|
||||
DesktopScreen.Bookmarks -> {
|
||||
BookmarksScreen(
|
||||
relayManager = relayManager,
|
||||
localCache = localCache,
|
||||
@@ -497,9 +504,17 @@ fun MainContent(
|
||||
},
|
||||
onZapFeedback = onZapFeedback,
|
||||
)
|
||||
DesktopScreen.Messages -> MessagesPlaceholder()
|
||||
DesktopScreen.Notifications -> NotificationsScreen(relayManager, account, subscriptionsCoordinator)
|
||||
DesktopScreen.MyProfile ->
|
||||
}
|
||||
|
||||
DesktopScreen.Messages -> {
|
||||
MessagesPlaceholder()
|
||||
}
|
||||
|
||||
DesktopScreen.Notifications -> {
|
||||
NotificationsScreen(relayManager, account, subscriptionsCoordinator)
|
||||
}
|
||||
|
||||
DesktopScreen.MyProfile -> {
|
||||
UserProfileScreen(
|
||||
pubKeyHex = account.pubKeyHex,
|
||||
relayManager = relayManager,
|
||||
@@ -514,7 +529,9 @@ fun MainContent(
|
||||
},
|
||||
onZapFeedback = onZapFeedback,
|
||||
)
|
||||
is DesktopScreen.UserProfile ->
|
||||
}
|
||||
|
||||
is DesktopScreen.UserProfile -> {
|
||||
UserProfileScreen(
|
||||
pubKeyHex = currentScreen.pubKeyHex,
|
||||
relayManager = relayManager,
|
||||
@@ -529,7 +546,9 @@ fun MainContent(
|
||||
},
|
||||
onZapFeedback = onZapFeedback,
|
||||
)
|
||||
is DesktopScreen.Thread ->
|
||||
}
|
||||
|
||||
is DesktopScreen.Thread -> {
|
||||
ThreadScreen(
|
||||
noteId = currentScreen.noteId,
|
||||
relayManager = relayManager,
|
||||
@@ -547,7 +566,11 @@ fun MainContent(
|
||||
onZapFeedback = onZapFeedback,
|
||||
onReply = onShowReplyDialog,
|
||||
)
|
||||
DesktopScreen.Settings -> RelaySettingsScreen(relayManager, account, accountManager)
|
||||
}
|
||||
|
||||
DesktopScreen.Settings -> {
|
||||
RelaySettingsScreen(relayManager, account, accountManager)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -171,9 +171,11 @@ class NwcPaymentHandler(
|
||||
is PayInvoiceSuccessResponse -> {
|
||||
PaymentResult.Success(response.result?.preimage)
|
||||
}
|
||||
|
||||
is PayInvoiceErrorResponse -> {
|
||||
PaymentResult.Error(response.error?.message ?: "Unknown error")
|
||||
}
|
||||
|
||||
else -> {
|
||||
PaymentResult.Error("Unexpected response type: ${response.resultType}")
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user