use alternative gallery using 1163 events instead of 10011 lists.
(This might still need some tuning but works in general)
This commit is contained in:
@@ -71,7 +71,6 @@ import com.vitorpamplona.quartz.events.FileHeaderEvent
|
|||||||
import com.vitorpamplona.quartz.events.FileServersEvent
|
import com.vitorpamplona.quartz.events.FileServersEvent
|
||||||
import com.vitorpamplona.quartz.events.FileStorageEvent
|
import com.vitorpamplona.quartz.events.FileStorageEvent
|
||||||
import com.vitorpamplona.quartz.events.FileStorageHeaderEvent
|
import com.vitorpamplona.quartz.events.FileStorageHeaderEvent
|
||||||
import com.vitorpamplona.quartz.events.GalleryListEvent
|
|
||||||
import com.vitorpamplona.quartz.events.GeneralListEvent
|
import com.vitorpamplona.quartz.events.GeneralListEvent
|
||||||
import com.vitorpamplona.quartz.events.GenericRepostEvent
|
import com.vitorpamplona.quartz.events.GenericRepostEvent
|
||||||
import com.vitorpamplona.quartz.events.GiftWrapEvent
|
import com.vitorpamplona.quartz.events.GiftWrapEvent
|
||||||
@@ -92,6 +91,7 @@ import com.vitorpamplona.quartz.events.PollNoteEvent
|
|||||||
import com.vitorpamplona.quartz.events.Price
|
import com.vitorpamplona.quartz.events.Price
|
||||||
import com.vitorpamplona.quartz.events.PrivateDmEvent
|
import com.vitorpamplona.quartz.events.PrivateDmEvent
|
||||||
import com.vitorpamplona.quartz.events.PrivateOutboxRelayListEvent
|
import com.vitorpamplona.quartz.events.PrivateOutboxRelayListEvent
|
||||||
|
import com.vitorpamplona.quartz.events.ProfileGalleryEntryEvent
|
||||||
import com.vitorpamplona.quartz.events.ReactionEvent
|
import com.vitorpamplona.quartz.events.ReactionEvent
|
||||||
import com.vitorpamplona.quartz.events.RelayAuthEvent
|
import com.vitorpamplona.quartz.events.RelayAuthEvent
|
||||||
import com.vitorpamplona.quartz.events.ReportEvent
|
import com.vitorpamplona.quartz.events.ReportEvent
|
||||||
@@ -2204,48 +2204,27 @@ class Account(
|
|||||||
relay: String?,
|
relay: String?,
|
||||||
) {
|
) {
|
||||||
if (!isWriteable()) return
|
if (!isWriteable()) return
|
||||||
|
ProfileGalleryEntryEvent.create(
|
||||||
GalleryListEvent.addEvent(
|
url = url,
|
||||||
userProfile().latestGalleryList,
|
eventid = idHex,
|
||||||
idHex,
|
/*magnetUri = magnetUri,
|
||||||
url,
|
mimeType = headerInfo.mimeType,
|
||||||
relay,
|
hash = headerInfo.hash,
|
||||||
signer,
|
size = headerInfo.size.toString(),
|
||||||
) {
|
dimensions = headerInfo.dim,
|
||||||
Client.send(it)
|
blurhash = headerInfo.blurHash,
|
||||||
LocalCache.consume(it)
|
alt = alt,
|
||||||
|
originalHash = originalHash,
|
||||||
|
sensitiveContent = sensitiveContent, */
|
||||||
|
signer = signer,
|
||||||
|
) { event ->
|
||||||
|
Client.send(event)
|
||||||
|
LocalCache.consume(event, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeFromGallery(
|
fun removeFromGallery(note: Note) {
|
||||||
note: Note,
|
delete(note)
|
||||||
url: String,
|
|
||||||
) {
|
|
||||||
if (!isWriteable()) return
|
|
||||||
|
|
||||||
val galleryentries = userProfile().latestGalleryList ?: return
|
|
||||||
|
|
||||||
if (note is AddressableNote) {
|
|
||||||
GalleryListEvent.removeReplaceable(
|
|
||||||
galleryentries,
|
|
||||||
note.address,
|
|
||||||
url,
|
|
||||||
signer,
|
|
||||||
) {
|
|
||||||
Client.send(it)
|
|
||||||
LocalCache.consume(it)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
GalleryListEvent.removeEvent(
|
|
||||||
galleryentries,
|
|
||||||
note.idHex,
|
|
||||||
url,
|
|
||||||
signer,
|
|
||||||
) {
|
|
||||||
Client.send(it)
|
|
||||||
LocalCache.consume(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addBookmark(
|
fun addBookmark(
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ import com.vitorpamplona.quartz.events.FileHeaderEvent
|
|||||||
import com.vitorpamplona.quartz.events.FileServersEvent
|
import com.vitorpamplona.quartz.events.FileServersEvent
|
||||||
import com.vitorpamplona.quartz.events.FileStorageEvent
|
import com.vitorpamplona.quartz.events.FileStorageEvent
|
||||||
import com.vitorpamplona.quartz.events.FileStorageHeaderEvent
|
import com.vitorpamplona.quartz.events.FileStorageHeaderEvent
|
||||||
import com.vitorpamplona.quartz.events.GalleryListEvent
|
|
||||||
import com.vitorpamplona.quartz.events.GenericRepostEvent
|
import com.vitorpamplona.quartz.events.GenericRepostEvent
|
||||||
import com.vitorpamplona.quartz.events.GiftWrapEvent
|
import com.vitorpamplona.quartz.events.GiftWrapEvent
|
||||||
import com.vitorpamplona.quartz.events.GitIssueEvent
|
import com.vitorpamplona.quartz.events.GitIssueEvent
|
||||||
@@ -104,6 +103,7 @@ import com.vitorpamplona.quartz.events.PinListEvent
|
|||||||
import com.vitorpamplona.quartz.events.PollNoteEvent
|
import com.vitorpamplona.quartz.events.PollNoteEvent
|
||||||
import com.vitorpamplona.quartz.events.PrivateDmEvent
|
import com.vitorpamplona.quartz.events.PrivateDmEvent
|
||||||
import com.vitorpamplona.quartz.events.PrivateOutboxRelayListEvent
|
import com.vitorpamplona.quartz.events.PrivateOutboxRelayListEvent
|
||||||
|
import com.vitorpamplona.quartz.events.ProfileGalleryEntryEvent
|
||||||
import com.vitorpamplona.quartz.events.ReactionEvent
|
import com.vitorpamplona.quartz.events.ReactionEvent
|
||||||
import com.vitorpamplona.quartz.events.RecommendRelayEvent
|
import com.vitorpamplona.quartz.events.RecommendRelayEvent
|
||||||
import com.vitorpamplona.quartz.events.RelaySetEvent
|
import com.vitorpamplona.quartz.events.RelaySetEvent
|
||||||
@@ -424,17 +424,6 @@ object LocalCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun consume(event: GalleryListEvent) {
|
|
||||||
val user = getOrCreateUser(event.pubKey)
|
|
||||||
if (user.latestGalleryList == null || event.createdAt > user.latestGalleryList!!.createdAt) {
|
|
||||||
user.updateGallery(event)
|
|
||||||
// Log.d("MT", "New User Metadata ${oldUser.pubkeyDisplayHex} ${oldUser.toBestDisplayName()}")
|
|
||||||
} else {
|
|
||||||
// Log.d("MT","Relay sent a previous Metadata Event ${oldUser.toBestDisplayName()}
|
|
||||||
// ${formattedDateTime(event.createdAt)} > ${formattedDateTime(oldUser.updatedAt)}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun formattedDateTime(timestamp: Long): String =
|
fun formattedDateTime(timestamp: Long): String =
|
||||||
Instant
|
Instant
|
||||||
.ofEpochSecond(timestamp)
|
.ofEpochSecond(timestamp)
|
||||||
@@ -1680,6 +1669,26 @@ object LocalCache {
|
|||||||
refreshObservers(note)
|
refreshObservers(note)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun consume(
|
||||||
|
event: ProfileGalleryEntryEvent,
|
||||||
|
relay: Relay?,
|
||||||
|
) {
|
||||||
|
val note = getOrCreateNote(event.id)
|
||||||
|
val author = getOrCreateUser(event.pubKey)
|
||||||
|
|
||||||
|
if (relay != null) {
|
||||||
|
author.addRelayBeingUsed(relay, event.createdAt)
|
||||||
|
note.addRelay(relay)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Already processed this event.
|
||||||
|
if (note.event != null) return
|
||||||
|
|
||||||
|
note.loadEvent(event, author, emptyList())
|
||||||
|
|
||||||
|
refreshObservers(note)
|
||||||
|
}
|
||||||
|
|
||||||
fun consume(
|
fun consume(
|
||||||
event: FileStorageHeaderEvent,
|
event: FileStorageHeaderEvent,
|
||||||
relay: Relay?,
|
relay: Relay?,
|
||||||
@@ -2535,13 +2544,13 @@ object LocalCache {
|
|||||||
is DraftEvent -> consume(event, relay)
|
is DraftEvent -> consume(event, relay)
|
||||||
is EmojiPackEvent -> consume(event, relay)
|
is EmojiPackEvent -> consume(event, relay)
|
||||||
is EmojiPackSelectionEvent -> consume(event, relay)
|
is EmojiPackSelectionEvent -> consume(event, relay)
|
||||||
is GalleryListEvent -> consume(event)
|
|
||||||
is GenericRepostEvent -> {
|
is GenericRepostEvent -> {
|
||||||
event.containedPost()?.let { verifyAndConsume(it, relay) }
|
event.containedPost()?.let { verifyAndConsume(it, relay) }
|
||||||
consume(event)
|
consume(event)
|
||||||
}
|
}
|
||||||
is FhirResourceEvent -> consume(event, relay)
|
is FhirResourceEvent -> consume(event, relay)
|
||||||
is FileHeaderEvent -> consume(event, relay)
|
is FileHeaderEvent -> consume(event, relay)
|
||||||
|
is ProfileGalleryEntryEvent -> consume(event, relay)
|
||||||
is FileServersEvent -> consume(event, relay)
|
is FileServersEvent -> consume(event, relay)
|
||||||
is FileStorageEvent -> consume(event, relay)
|
is FileStorageEvent -> consume(event, relay)
|
||||||
is FileStorageHeaderEvent -> consume(event, relay)
|
is FileStorageHeaderEvent -> consume(event, relay)
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ open class Note(
|
|||||||
var relays = listOf<RelayBriefInfoCache.RelayBriefInfo>()
|
var relays = listOf<RelayBriefInfoCache.RelayBriefInfo>()
|
||||||
private set
|
private set
|
||||||
|
|
||||||
var headerImage: String? = null
|
var associatedNote: Note? = null
|
||||||
|
|
||||||
var lastReactionsDownloadTime: Map<String, EOSETime> = emptyMap()
|
var lastReactionsDownloadTime: Map<String, EOSETime> = emptyMap()
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ import com.vitorpamplona.quartz.events.AdvertisedRelayListEvent
|
|||||||
import com.vitorpamplona.quartz.events.BookmarkListEvent
|
import com.vitorpamplona.quartz.events.BookmarkListEvent
|
||||||
import com.vitorpamplona.quartz.events.ChatroomKey
|
import com.vitorpamplona.quartz.events.ChatroomKey
|
||||||
import com.vitorpamplona.quartz.events.ContactListEvent
|
import com.vitorpamplona.quartz.events.ContactListEvent
|
||||||
import com.vitorpamplona.quartz.events.GalleryListEvent
|
|
||||||
import com.vitorpamplona.quartz.events.LnZapEvent
|
import com.vitorpamplona.quartz.events.LnZapEvent
|
||||||
import com.vitorpamplona.quartz.events.MetadataEvent
|
import com.vitorpamplona.quartz.events.MetadataEvent
|
||||||
import com.vitorpamplona.quartz.events.ReportEvent
|
import com.vitorpamplona.quartz.events.ReportEvent
|
||||||
@@ -61,7 +60,6 @@ class User(
|
|||||||
var latestMetadataRelay: String? = null
|
var latestMetadataRelay: String? = null
|
||||||
var latestContactList: ContactListEvent? = null
|
var latestContactList: ContactListEvent? = null
|
||||||
var latestBookmarkList: BookmarkListEvent? = null
|
var latestBookmarkList: BookmarkListEvent? = null
|
||||||
var latestGalleryList: GalleryListEvent? = null
|
|
||||||
|
|
||||||
var reports = mapOf<User, Set<Note>>()
|
var reports = mapOf<User, Set<Note>>()
|
||||||
private set
|
private set
|
||||||
@@ -125,13 +123,6 @@ class User(
|
|||||||
liveSet?.innerBookmarks?.invalidateData()
|
liveSet?.innerBookmarks?.invalidateData()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateGallery(event: GalleryListEvent) {
|
|
||||||
if (event.id == latestGalleryList?.id) return
|
|
||||||
print("GALLERY " + event.id())
|
|
||||||
latestGalleryList = event
|
|
||||||
liveSet?.innerGallery?.invalidateData()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun clearEOSE() {
|
fun clearEOSE() {
|
||||||
latestEOSEs = emptyMap()
|
latestEOSEs = emptyMap()
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-3
@@ -31,7 +31,6 @@ import com.vitorpamplona.quartz.events.BadgeAwardEvent
|
|||||||
import com.vitorpamplona.quartz.events.BadgeProfilesEvent
|
import com.vitorpamplona.quartz.events.BadgeProfilesEvent
|
||||||
import com.vitorpamplona.quartz.events.BookmarkListEvent
|
import com.vitorpamplona.quartz.events.BookmarkListEvent
|
||||||
import com.vitorpamplona.quartz.events.ContactListEvent
|
import com.vitorpamplona.quartz.events.ContactListEvent
|
||||||
import com.vitorpamplona.quartz.events.GalleryListEvent
|
|
||||||
import com.vitorpamplona.quartz.events.GenericRepostEvent
|
import com.vitorpamplona.quartz.events.GenericRepostEvent
|
||||||
import com.vitorpamplona.quartz.events.HighlightEvent
|
import com.vitorpamplona.quartz.events.HighlightEvent
|
||||||
import com.vitorpamplona.quartz.events.LnZapEvent
|
import com.vitorpamplona.quartz.events.LnZapEvent
|
||||||
@@ -40,6 +39,7 @@ import com.vitorpamplona.quartz.events.MetadataEvent
|
|||||||
import com.vitorpamplona.quartz.events.PeopleListEvent
|
import com.vitorpamplona.quartz.events.PeopleListEvent
|
||||||
import com.vitorpamplona.quartz.events.PinListEvent
|
import com.vitorpamplona.quartz.events.PinListEvent
|
||||||
import com.vitorpamplona.quartz.events.PollNoteEvent
|
import com.vitorpamplona.quartz.events.PollNoteEvent
|
||||||
|
import com.vitorpamplona.quartz.events.ProfileGalleryEntryEvent
|
||||||
import com.vitorpamplona.quartz.events.RepostEvent
|
import com.vitorpamplona.quartz.events.RepostEvent
|
||||||
import com.vitorpamplona.quartz.events.TextNoteEvent
|
import com.vitorpamplona.quartz.events.TextNoteEvent
|
||||||
import com.vitorpamplona.quartz.events.WikiNoteEvent
|
import com.vitorpamplona.quartz.events.WikiNoteEvent
|
||||||
@@ -84,7 +84,7 @@ object NostrUserProfileDataSource : AmethystNostrDataSource("UserProfileFeed") {
|
|||||||
WikiNoteEvent.KIND,
|
WikiNoteEvent.KIND,
|
||||||
),
|
),
|
||||||
authors = listOf(it.pubkeyHex),
|
authors = listOf(it.pubkeyHex),
|
||||||
limit = 200,
|
limit = 500,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -147,13 +147,27 @@ object NostrUserProfileDataSource : AmethystNostrDataSource("UserProfileFeed") {
|
|||||||
filter =
|
filter =
|
||||||
Filter(
|
Filter(
|
||||||
kinds =
|
kinds =
|
||||||
listOf(BookmarkListEvent.KIND, PeopleListEvent.KIND, AppRecommendationEvent.KIND, GalleryListEvent.KIND),
|
listOf(BookmarkListEvent.KIND, PeopleListEvent.KIND, AppRecommendationEvent.KIND),
|
||||||
authors = listOf(it.pubkeyHex),
|
authors = listOf(it.pubkeyHex),
|
||||||
limit = 100,
|
limit = 100,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun createProfileGalleryFilter() =
|
||||||
|
user?.let {
|
||||||
|
TypedFilter(
|
||||||
|
types = COMMON_FEED_TYPES,
|
||||||
|
filter =
|
||||||
|
Filter(
|
||||||
|
kinds =
|
||||||
|
listOf(ProfileGalleryEntryEvent.KIND),
|
||||||
|
authors = listOf(it.pubkeyHex),
|
||||||
|
limit = 1000,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun createReceivedAwardsFilter() =
|
fun createReceivedAwardsFilter() =
|
||||||
user?.let {
|
user?.let {
|
||||||
TypedFilter(
|
TypedFilter(
|
||||||
@@ -174,6 +188,7 @@ object NostrUserProfileDataSource : AmethystNostrDataSource("UserProfileFeed") {
|
|||||||
listOfNotNull(
|
listOfNotNull(
|
||||||
createUserInfoFilter(),
|
createUserInfoFilter(),
|
||||||
createUserPostsFilter(),
|
createUserPostsFilter(),
|
||||||
|
createProfileGalleryFilter(),
|
||||||
createFollowFilter(),
|
createFollowFilter(),
|
||||||
createFollowersFilter(),
|
createFollowersFilter(),
|
||||||
createUserReceivedZapsFilter(),
|
createUserReceivedZapsFilter(),
|
||||||
|
|||||||
+49
-31
@@ -24,47 +24,65 @@ import com.vitorpamplona.amethyst.model.Account
|
|||||||
import com.vitorpamplona.amethyst.model.LocalCache
|
import com.vitorpamplona.amethyst.model.LocalCache
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.model.User
|
import com.vitorpamplona.amethyst.model.User
|
||||||
import com.vitorpamplona.ammolite.relays.FeedType
|
import com.vitorpamplona.quartz.events.MuteListEvent
|
||||||
import com.vitorpamplona.ammolite.relays.Relay
|
import com.vitorpamplona.quartz.events.PeopleListEvent
|
||||||
|
import com.vitorpamplona.quartz.events.ProfileGalleryEntryEvent
|
||||||
|
|
||||||
class UserProfileGalleryFeedFilter(
|
class UserProfileGalleryFeedFilter(
|
||||||
val user: User,
|
val user: User,
|
||||||
val account: Account,
|
val account: Account,
|
||||||
) : FeedFilter<Note>() {
|
) : AdditiveFeedFilter<Note>() {
|
||||||
override fun feedKey(): String = account.userProfile().pubkeyHex + "-Gallery-" + user.pubkeyHex
|
override fun feedKey(): String = account.userProfile().pubkeyHex + "-" + account.defaultStoriesFollowList.value
|
||||||
|
|
||||||
|
override fun showHiddenKey(): Boolean =
|
||||||
|
account.defaultStoriesFollowList.value == PeopleListEvent.blockListFor(account.userProfile().pubkeyHex) ||
|
||||||
|
account.defaultStoriesFollowList.value == MuteListEvent.blockListFor(account.userProfile().pubkeyHex)
|
||||||
|
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
|
val params = buildFilterParams(account)
|
||||||
|
|
||||||
val notes =
|
val notes =
|
||||||
user.latestGalleryList
|
LocalCache.notes.filterIntoSet { _, it ->
|
||||||
?.taggedGalleryEntries()
|
acceptableEvent(it, params, user)
|
||||||
?.map {
|
}
|
||||||
Triple(
|
|
||||||
// (
|
|
||||||
// if (ATag.isATag(it.id)) {
|
|
||||||
// ATag.parse(it.id, null)?.let { it1 -> LocalCache.getOrCreateAddressableNote(it1) }
|
|
||||||
// } else {
|
|
||||||
LocalCache.getOrCreateNote(it.id),
|
|
||||||
// }
|
|
||||||
// )!!
|
|
||||||
it.url,
|
|
||||||
it.relay,
|
|
||||||
)
|
|
||||||
}?.toSet()
|
|
||||||
?: emptySet()
|
|
||||||
|
|
||||||
var finalnotes = setOf<Note>()
|
var finalnotes = setOf<Note>()
|
||||||
for (pair in notes) {
|
for (item in notes) {
|
||||||
pair.first.headerImage = pair.second
|
item.associatedNote = (item.event as ProfileGalleryEntryEvent).event()?.let { LocalCache.getOrCreateNote(it) }
|
||||||
if (pair.third != null) {
|
finalnotes = finalnotes + item
|
||||||
val relay = Relay(pair.third!!, true, false, setOf(FeedType.GLOBAL))
|
|
||||||
pair.first.createdAt()?.let { user.addRelayBeingUsed(relay, it) }
|
|
||||||
pair.first.addRelay(relay)
|
|
||||||
}
|
|
||||||
finalnotes = finalnotes + pair.first
|
|
||||||
}
|
}
|
||||||
println(finalnotes)
|
|
||||||
|
|
||||||
return (finalnotes)
|
return sort(finalnotes)
|
||||||
.filter { account.isAcceptable(it) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun applyFilter(collection: Set<Note>): Set<Note> = innerApplyFilter(collection)
|
||||||
|
|
||||||
|
private fun innerApplyFilter(collection: Collection<Note>): Set<Note> {
|
||||||
|
val params = buildFilterParams(account)
|
||||||
|
|
||||||
|
return collection.filterTo(HashSet()) { acceptableEvent(it, params, user) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun acceptableEvent(
|
||||||
|
it: Note,
|
||||||
|
params: FilterByListParams,
|
||||||
|
user: User,
|
||||||
|
): Boolean {
|
||||||
|
val noteEvent = it.event
|
||||||
|
return (
|
||||||
|
(it.event?.pubKey() == user.pubkeyHex && noteEvent is ProfileGalleryEntryEvent) && noteEvent.hasUrl() && noteEvent.hasEvent() // && noteEvent.isOneOf(SUPPORTED_VIDEO_FEED_MIME_TYPES_SET))
|
||||||
|
) &&
|
||||||
|
params.match(noteEvent) &&
|
||||||
|
account.isAcceptable(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun buildFilterParams(account: Account): FilterByListParams =
|
||||||
|
FilterByListParams.create(
|
||||||
|
userHex = account.userProfile().pubkeyHex,
|
||||||
|
selectedListName = account.defaultStoriesFollowList.value,
|
||||||
|
followLists = account.liveStoriesFollowLists.value,
|
||||||
|
hiddenUsers = account.flowHiddenUsers.value,
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun sort(collection: Set<Note>): List<Note> = collection.sortedWith(DefaultFeedOrder)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -671,11 +671,7 @@ fun DeleteFromGalleryDialog(
|
|||||||
buttonIcon = Icons.Default.Delete,
|
buttonIcon = Icons.Default.Delete,
|
||||||
buttonText = stringRes(R.string.quick_action_delete_dialog_btn),
|
buttonText = stringRes(R.string.quick_action_delete_dialog_btn),
|
||||||
onClickDoOnce = {
|
onClickDoOnce = {
|
||||||
note.headerImage.let {
|
accountViewModel.removefromMediaGallery(note)
|
||||||
if (it != null) {
|
|
||||||
accountViewModel.removefromMediaGallery(note, it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onDismiss()
|
onDismiss()
|
||||||
},
|
},
|
||||||
onDismiss = onDismiss,
|
onDismiss = onDismiss,
|
||||||
|
|||||||
+2
-5
@@ -677,11 +677,8 @@ class AccountViewModel(
|
|||||||
viewModelScope.launch(Dispatchers.IO) { account.addToGallery(hex, url, relay) }
|
viewModelScope.launch(Dispatchers.IO) { account.addToGallery(hex, url, relay) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removefromMediaGallery(
|
fun removefromMediaGallery(note: Note) {
|
||||||
note: Note,
|
viewModelScope.launch(Dispatchers.IO) { account.removeFromGallery(note) }
|
||||||
url: String,
|
|
||||||
) {
|
|
||||||
viewModelScope.launch(Dispatchers.IO) { account.removeFromGallery(note, url) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addPrivateBookmark(note: Note) {
|
fun addPrivateBookmark(note: Note) {
|
||||||
|
|||||||
+48
-41
@@ -33,7 +33,6 @@ import androidx.compose.foundation.lazy.grid.GridCells
|
|||||||
import androidx.compose.foundation.lazy.grid.LazyGridState
|
import androidx.compose.foundation.lazy.grid.LazyGridState
|
||||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||||
import androidx.compose.foundation.lazy.grid.itemsIndexed
|
import androidx.compose.foundation.lazy.grid.itemsIndexed
|
||||||
import androidx.compose.foundation.lazy.itemsIndexed
|
|
||||||
import androidx.compose.material3.HorizontalDivider
|
import androidx.compose.material3.HorizontalDivider
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@@ -74,7 +73,7 @@ import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
|||||||
import com.vitorpamplona.amethyst.ui.theme.FeedPadding
|
import com.vitorpamplona.amethyst.ui.theme.FeedPadding
|
||||||
import com.vitorpamplona.amethyst.ui.theme.HalfPadding
|
import com.vitorpamplona.amethyst.ui.theme.HalfPadding
|
||||||
import com.vitorpamplona.amethyst.ui.theme.QuoteBorder
|
import com.vitorpamplona.amethyst.ui.theme.QuoteBorder
|
||||||
import com.vitorpamplona.quartz.events.TextNoteEvent
|
import com.vitorpamplona.quartz.events.ProfileGalleryEntryEvent
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RenderGalleryFeed(
|
fun RenderGalleryFeed(
|
||||||
@@ -134,27 +133,45 @@ private fun GalleryFeedLoaded(
|
|||||||
itemsIndexed(state.feed.value, key = { _, item -> item.idHex }) { _, item ->
|
itemsIndexed(state.feed.value, key = { _, item -> item.idHex }) { _, item ->
|
||||||
val defaultModifier = remember { Modifier.fillMaxWidth().animateItemPlacement() }
|
val defaultModifier = remember { Modifier.fillMaxWidth().animateItemPlacement() }
|
||||||
|
|
||||||
Row(defaultModifier) {
|
if (item.associatedNote != null) {
|
||||||
GalleryCardCompose(
|
if (item.associatedNote!!.event != null) {
|
||||||
baseNote = item,
|
if ((item.event as ProfileGalleryEntryEvent).hasUrl() &&
|
||||||
routeForLastRead = routeForLastRead,
|
(item.event as ProfileGalleryEntryEvent).hasEvent()
|
||||||
modifier = Modifier,
|
) {
|
||||||
forceEventKind = forceEventKind,
|
val image = (item.event as ProfileGalleryEntryEvent).url()
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
nav = nav,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
HorizontalDivider(
|
Row(defaultModifier) {
|
||||||
thickness = DividerThickness,
|
if (image != null) {
|
||||||
)
|
GalleryCardCompose(
|
||||||
|
galleryNote = item,
|
||||||
|
image = image,
|
||||||
|
baseNote = item.associatedNote!!,
|
||||||
|
routeForLastRead = routeForLastRead,
|
||||||
|
modifier = Modifier,
|
||||||
|
forceEventKind = forceEventKind,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
nav = nav,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HorizontalDivider(
|
||||||
|
thickness = DividerThickness,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
accountViewModel.delete(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun GalleryCardCompose(
|
fun GalleryCardCompose(
|
||||||
|
galleryNote: Note,
|
||||||
baseNote: Note,
|
baseNote: Note,
|
||||||
|
image: String,
|
||||||
routeForLastRead: String? = null,
|
routeForLastRead: String? = null,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
parentBackgroundColor: MutableState<Color>? = null,
|
parentBackgroundColor: MutableState<Color>? = null,
|
||||||
@@ -172,8 +189,11 @@ fun GalleryCardCompose(
|
|||||||
accountViewModel = accountViewModel,
|
accountViewModel = accountViewModel,
|
||||||
nav = nav,
|
nav = nav,
|
||||||
) { canPreview ->
|
) { canPreview ->
|
||||||
|
|
||||||
GalleryCard(
|
GalleryCard(
|
||||||
|
galleryNote = galleryNote,
|
||||||
baseNote = baseNote,
|
baseNote = baseNote,
|
||||||
|
image = image,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
parentBackgroundColor = parentBackgroundColor,
|
parentBackgroundColor = parentBackgroundColor,
|
||||||
accountViewModel = accountViewModel,
|
accountViewModel = accountViewModel,
|
||||||
@@ -185,16 +205,19 @@ fun GalleryCardCompose(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun GalleryCard(
|
fun GalleryCard(
|
||||||
|
galleryNote: Note,
|
||||||
baseNote: Note,
|
baseNote: Note,
|
||||||
|
image: String,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
parentBackgroundColor: MutableState<Color>? = null,
|
parentBackgroundColor: MutableState<Color>? = null,
|
||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
nav: (String) -> Unit,
|
nav: (String) -> Unit,
|
||||||
) {
|
) {
|
||||||
// baseNote.event?.let { Text(text = it.pubKey()) }
|
// baseNote.event?.let { Text(text = it.pubKey()) }
|
||||||
LongPressToQuickActionGallery(baseNote = baseNote, accountViewModel = accountViewModel) { showPopup ->
|
LongPressToQuickActionGallery(baseNote = galleryNote, accountViewModel = accountViewModel) { showPopup ->
|
||||||
CheckNewAndRenderChannelCard(
|
CheckNewAndRenderChannelCard(
|
||||||
baseNote,
|
baseNote,
|
||||||
|
image,
|
||||||
modifier,
|
modifier,
|
||||||
parentBackgroundColor,
|
parentBackgroundColor,
|
||||||
accountViewModel,
|
accountViewModel,
|
||||||
@@ -207,6 +230,7 @@ fun GalleryCard(
|
|||||||
@Composable
|
@Composable
|
||||||
private fun CheckNewAndRenderChannelCard(
|
private fun CheckNewAndRenderChannelCard(
|
||||||
baseNote: Note,
|
baseNote: Note,
|
||||||
|
image: String,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
parentBackgroundColor: MutableState<Color>? = null,
|
parentBackgroundColor: MutableState<Color>? = null,
|
||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
@@ -228,26 +252,14 @@ private fun CheckNewAndRenderChannelCard(
|
|||||||
showPopup = showPopup,
|
showPopup = showPopup,
|
||||||
nav = nav,
|
nav = nav,
|
||||||
) {
|
) {
|
||||||
InnerGalleryCardWithReactions(
|
InnerGalleryCardBox(baseNote, image, accountViewModel, nav)
|
||||||
baseNote = baseNote,
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
nav = nav,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun InnerGalleryCardWithReactions(
|
|
||||||
baseNote: Note,
|
|
||||||
accountViewModel: AccountViewModel,
|
|
||||||
nav: (String) -> Unit,
|
|
||||||
) {
|
|
||||||
InnerGalleryCardBox(baseNote, accountViewModel, nav)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun InnerGalleryCardBox(
|
fun InnerGalleryCardBox(
|
||||||
baseNote: Note,
|
baseNote: Note,
|
||||||
|
image: String,
|
||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
nav: (String) -> Unit,
|
nav: (String) -> Unit,
|
||||||
) {
|
) {
|
||||||
@@ -256,7 +268,7 @@ fun InnerGalleryCardBox(
|
|||||||
note = baseNote,
|
note = baseNote,
|
||||||
accountViewModel = accountViewModel,
|
accountViewModel = accountViewModel,
|
||||||
) {
|
) {
|
||||||
RenderGalleryThumb(baseNote, accountViewModel, nav)
|
RenderGalleryThumb(baseNote, image, accountViewModel, nav)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -272,21 +284,19 @@ data class GalleryThumb(
|
|||||||
@Composable
|
@Composable
|
||||||
fun RenderGalleryThumb(
|
fun RenderGalleryThumb(
|
||||||
baseNote: Note,
|
baseNote: Note,
|
||||||
|
image: String,
|
||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
nav: (String) -> Unit,
|
nav: (String) -> Unit,
|
||||||
) {
|
) {
|
||||||
val noteEvent = baseNote.event as? TextNoteEvent ?: return
|
|
||||||
|
|
||||||
val card by
|
val card by
|
||||||
baseNote
|
baseNote
|
||||||
.live()
|
.live()
|
||||||
.metadata
|
.metadata
|
||||||
.map {
|
.map {
|
||||||
val noteEvent = baseNote.event as TextNoteEvent
|
|
||||||
GalleryThumb(
|
GalleryThumb(
|
||||||
id = "",
|
id = "",
|
||||||
image = baseNote.headerImage,
|
image = image,
|
||||||
title = noteEvent.content(),
|
title = "",
|
||||||
// noteEvent?.title(),
|
// noteEvent?.title(),
|
||||||
// price = noteEvent?.price(),
|
// price = noteEvent?.price(),
|
||||||
)
|
)
|
||||||
@@ -294,11 +304,8 @@ fun RenderGalleryThumb(
|
|||||||
.observeAsState(
|
.observeAsState(
|
||||||
GalleryThumb(
|
GalleryThumb(
|
||||||
id = "",
|
id = "",
|
||||||
image = baseNote.headerImage,
|
image = image,
|
||||||
title = noteEvent.content(),
|
title = "",
|
||||||
// image = noteEvent.image(),
|
|
||||||
// title = noteEvent.title(),
|
|
||||||
// price = noteEvent.price(),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -119,11 +119,6 @@ open class Event(
|
|||||||
|
|
||||||
override fun taggedEvents() = tags.filter { it.size > 1 && it[0] == "e" }.map { it[1] }
|
override fun taggedEvents() = tags.filter { it.size > 1 && it[0] == "e" }.map { it[1] }
|
||||||
|
|
||||||
override fun taggedGalleryEntries() =
|
|
||||||
tags.filter { it.size > 2 && it[0] == GalleryListEvent.GALLERYTAGNAME }.map {
|
|
||||||
GalleryListEvent.GalleryUrl(it[1], it[2], it.getOrNull(3))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun taggedUrls() = tags.filter { it.size > 1 && it[0] == "r" }.map { it[1] }
|
override fun taggedUrls() = tags.filter { it.size > 1 && it[0] == "r" }.map { it[1] }
|
||||||
|
|
||||||
override fun firstTagFor(vararg key: String) = tags.firstOrNull { it.size > 1 && it[0] in key }?.let { it[1] }
|
override fun firstTagFor(vararg key: String) = tags.firstOrNull { it.size > 1 && it[0] in key }?.let { it[1] }
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ class EventFactory {
|
|||||||
EmojiPackSelectionEvent.KIND ->
|
EmojiPackSelectionEvent.KIND ->
|
||||||
EmojiPackSelectionEvent(id, pubKey, createdAt, tags, content, sig)
|
EmojiPackSelectionEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
FileHeaderEvent.KIND -> FileHeaderEvent(id, pubKey, createdAt, tags, content, sig)
|
FileHeaderEvent.KIND -> FileHeaderEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
|
ProfileGalleryEntryEvent.KIND -> ProfileGalleryEntryEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
FileServersEvent.KIND -> FileServersEvent(id, pubKey, createdAt, tags, content, sig)
|
FileServersEvent.KIND -> FileServersEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
FileStorageEvent.KIND -> FileStorageEvent(id, pubKey, createdAt, tags, content, sig)
|
FileStorageEvent.KIND -> FileStorageEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
FileStorageHeaderEvent.KIND ->
|
FileStorageHeaderEvent.KIND ->
|
||||||
@@ -97,7 +98,6 @@ class EventFactory {
|
|||||||
GitPatchEvent.KIND -> GitPatchEvent(id, pubKey, createdAt, tags, content, sig)
|
GitPatchEvent.KIND -> GitPatchEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
GitRepositoryEvent.KIND -> GitRepositoryEvent(id, pubKey, createdAt, tags, content, sig)
|
GitRepositoryEvent.KIND -> GitRepositoryEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
GoalEvent.KIND -> GoalEvent(id, pubKey, createdAt, tags, content, sig)
|
GoalEvent.KIND -> GoalEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
GalleryListEvent.KIND -> GalleryListEvent(id, pubKey, createdAt, tags, content, sig)
|
|
||||||
HighlightEvent.KIND -> HighlightEvent(id, pubKey, createdAt, tags, content, sig)
|
HighlightEvent.KIND -> HighlightEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
HTTPAuthorizationEvent.KIND ->
|
HTTPAuthorizationEvent.KIND ->
|
||||||
HTTPAuthorizationEvent(id, pubKey, createdAt, tags, content, sig)
|
HTTPAuthorizationEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
|
|||||||
@@ -145,8 +145,6 @@ interface EventInterface {
|
|||||||
|
|
||||||
fun firstTaggedK(): Int?
|
fun firstTaggedK(): Int?
|
||||||
|
|
||||||
fun taggedGalleryEntries(): List<GalleryListEvent.GalleryUrl>
|
|
||||||
|
|
||||||
fun taggedEmojis(): List<EmojiUrl>
|
fun taggedEmojis(): List<EmojiUrl>
|
||||||
|
|
||||||
fun matchTag1With(text: String): Boolean
|
fun matchTag1With(text: String): Boolean
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 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.events
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
|
import com.vitorpamplona.quartz.encoders.HexKey
|
||||||
|
import com.vitorpamplona.quartz.signers.NostrSigner
|
||||||
|
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
class ProfileGalleryEntryEvent(
|
||||||
|
id: HexKey,
|
||||||
|
pubKey: HexKey,
|
||||||
|
createdAt: Long,
|
||||||
|
tags: Array<Array<String>>,
|
||||||
|
content: String,
|
||||||
|
sig: HexKey,
|
||||||
|
) : Event(id, pubKey, createdAt, KIND, tags, content, sig) {
|
||||||
|
fun url() = tags.firstOrNull { it.size > 1 && it[0] == URL }?.get(1)
|
||||||
|
|
||||||
|
fun urls() = tags.filter { it.size > 1 && it[0] == URL }.map { it[1] }
|
||||||
|
|
||||||
|
fun encryptionKey() = tags.firstOrNull { it.size > 2 && it[0] == ENCRYPTION_KEY }?.let { AESGCM(it[1], it[2]) }
|
||||||
|
|
||||||
|
fun mimeType() = tags.firstOrNull { it.size > 1 && it[0] == MIME_TYPE }?.get(1)
|
||||||
|
|
||||||
|
fun hash() = tags.firstOrNull { it.size > 1 && it[0] == HASH }?.get(1)
|
||||||
|
|
||||||
|
fun size() = tags.firstOrNull { it.size > 1 && it[0] == FILE_SIZE }?.get(1)
|
||||||
|
|
||||||
|
fun alt() = tags.firstOrNull { it.size > 1 && it[0] == ALT }?.get(1)
|
||||||
|
|
||||||
|
fun dimensions() = tags.firstOrNull { it.size > 1 && it[0] == DIMENSION }?.get(1)
|
||||||
|
|
||||||
|
fun magnetURI() = tags.firstOrNull { it.size > 1 && it[0] == MAGNET_URI }?.get(1)
|
||||||
|
|
||||||
|
fun torrentInfoHash() = tags.firstOrNull { it.size > 1 && it[0] == TORRENT_INFOHASH }?.get(1)
|
||||||
|
|
||||||
|
fun blurhash() = tags.firstOrNull { it.size > 1 && it[0] == BLUR_HASH }?.get(1)
|
||||||
|
|
||||||
|
fun hasUrl() = tags.any { it.size > 1 && it[0] == URL }
|
||||||
|
|
||||||
|
fun event() = tags.firstOrNull { it.size > 1 && it[0] == "e" }?.get(1)
|
||||||
|
|
||||||
|
fun hasEvent() = tags.any { it.size > 1 && it[0] == "e" }
|
||||||
|
|
||||||
|
fun isOneOf(mimeTypes: Set<String>) = tags.any { it.size > 1 && it[0] == MIME_TYPE && mimeTypes.contains(it[1]) }
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val KIND = 1163
|
||||||
|
const val ALT_DESCRIPTION = "Profile Gallery Entry"
|
||||||
|
|
||||||
|
const val URL = "url"
|
||||||
|
const val ENCRYPTION_KEY = "aes-256-gcm"
|
||||||
|
const val MIME_TYPE = "m"
|
||||||
|
const val FILE_SIZE = "size"
|
||||||
|
const val DIMENSION = "dim"
|
||||||
|
const val HASH = "x"
|
||||||
|
const val MAGNET_URI = "magnet"
|
||||||
|
const val TORRENT_INFOHASH = "i"
|
||||||
|
const val BLUR_HASH = "blurhash"
|
||||||
|
const val ORIGINAL_HASH = "ox"
|
||||||
|
const val ALT = "alt"
|
||||||
|
|
||||||
|
fun create(
|
||||||
|
url: String,
|
||||||
|
eventid: String? = null,
|
||||||
|
magnetUri: String? = null,
|
||||||
|
mimeType: String? = null,
|
||||||
|
alt: String? = null,
|
||||||
|
hash: String? = null,
|
||||||
|
size: String? = null,
|
||||||
|
dimensions: String? = null,
|
||||||
|
blurhash: String? = null,
|
||||||
|
originalHash: String? = null,
|
||||||
|
magnetURI: String? = null,
|
||||||
|
torrentInfoHash: String? = null,
|
||||||
|
encryptionKey: AESGCM? = null,
|
||||||
|
sensitiveContent: Boolean? = null,
|
||||||
|
signer: NostrSigner,
|
||||||
|
createdAt: Long = TimeUtils.now(),
|
||||||
|
onReady: (ProfileGalleryEntryEvent) -> Unit,
|
||||||
|
) {
|
||||||
|
val tags =
|
||||||
|
listOfNotNull(
|
||||||
|
arrayOf(URL, url),
|
||||||
|
eventid?.let { arrayOf("e", it) },
|
||||||
|
magnetUri?.let { arrayOf(MAGNET_URI, it) },
|
||||||
|
mimeType?.let { arrayOf(MIME_TYPE, it) },
|
||||||
|
alt?.ifBlank { null }?.let { arrayOf(ALT, it) } ?: arrayOf("alt", ALT_DESCRIPTION),
|
||||||
|
hash?.let { arrayOf(HASH, it) },
|
||||||
|
size?.let { arrayOf(FILE_SIZE, it) },
|
||||||
|
dimensions?.let { arrayOf(DIMENSION, it) },
|
||||||
|
blurhash?.let { arrayOf(BLUR_HASH, it) },
|
||||||
|
originalHash?.let { arrayOf(ORIGINAL_HASH, it) },
|
||||||
|
magnetURI?.let { arrayOf(MAGNET_URI, it) },
|
||||||
|
torrentInfoHash?.let { arrayOf(TORRENT_INFOHASH, it) },
|
||||||
|
encryptionKey?.let { arrayOf(ENCRYPTION_KEY, it.key, it.nonce) },
|
||||||
|
sensitiveContent?.let {
|
||||||
|
if (it) {
|
||||||
|
arrayOf("content-warning", "")
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
val content = alt ?: ""
|
||||||
|
signer.sign(createdAt, KIND, tags.toTypedArray(), content, onReady)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user