mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-09-25 18:21:20 +02:00
Makes the new Video events non replaceable, while keeping the old ones in the replaceable
This commit is contained in:
@@ -1044,13 +1044,13 @@ object LocalCache : ILocalCache {
|
||||
event: VideoNormalEvent,
|
||||
relay: NormalizedRelayUrl?,
|
||||
wasVerified: Boolean,
|
||||
) = consumeBaseReplaceable(event, relay, wasVerified)
|
||||
) = consumeRegularEvent(event, relay, wasVerified)
|
||||
|
||||
private fun consume(
|
||||
event: VideoShortEvent,
|
||||
relay: NormalizedRelayUrl?,
|
||||
wasVerified: Boolean,
|
||||
) = consumeBaseReplaceable(event, relay, wasVerified)
|
||||
) = consumeRegularEvent(event, relay, wasVerified)
|
||||
|
||||
fun consume(
|
||||
event: StatusEvent,
|
||||
|
@@ -59,6 +59,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size5dp
|
||||
import com.vitorpamplona.amethyst.ui.theme.imageModifier
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.hasHashtags
|
||||
import com.vitorpamplona.quartz.nip02FollowList.EmptyTagList
|
||||
import com.vitorpamplona.quartz.nip02FollowList.toImmutableListOfLists
|
||||
@@ -75,18 +76,20 @@ fun VideoDisplay(
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: INav,
|
||||
) {
|
||||
val event = (note.event as? VideoEvent) ?: return
|
||||
val imeta = event.imetaTags().firstOrNull() ?: return
|
||||
val videoEvent = (note.event as? VideoEvent) ?: return
|
||||
val event = (videoEvent as? Event) ?: return
|
||||
|
||||
val title = event.title()
|
||||
val summary = event.content.ifBlank { null }?.takeIf { title != it }
|
||||
val imeta = videoEvent.imetaTags().firstOrNull() ?: return
|
||||
|
||||
val title = videoEvent.title()
|
||||
val summary = videoEvent.content.ifBlank { null }?.takeIf { title != it }
|
||||
val image = imeta.image.firstOrNull()
|
||||
val isYouTube = imeta.url.contains("youtube.com") || imeta.url.contains("youtu.be")
|
||||
val tags = remember(note) { note.event?.tags?.toImmutableListOfLists() ?: EmptyTagList }
|
||||
|
||||
val content by
|
||||
remember(note) {
|
||||
val description = event.content.ifBlank { null } ?: event.alt()
|
||||
val description = videoEvent.content.ifBlank { null } ?: event.alt()
|
||||
val isImage = imeta.mimeType?.startsWith("image/") == true || RichTextParser.isImageUrl(imeta.url)
|
||||
val uri = note.toNostrUri()
|
||||
|
||||
@@ -187,11 +190,11 @@ fun VideoDisplay(
|
||||
nav = nav,
|
||||
)
|
||||
|
||||
if (event.hasHashtags()) {
|
||||
if (videoEvent.hasHashtags()) {
|
||||
Row(
|
||||
Modifier.fillMaxWidth(),
|
||||
) {
|
||||
DisplayUncitedHashtags(event, summary, callbackUri, accountViewModel, nav)
|
||||
DisplayUncitedHashtags(videoEvent, summary, callbackUri, accountViewModel, nav)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -33,6 +33,7 @@ import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.ui.components.SensitivityWarning
|
||||
import com.vitorpamplona.amethyst.ui.components.ZoomableContentView
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip31Alts.alt
|
||||
import com.vitorpamplona.quartz.nip71Video.VideoEvent
|
||||
|
||||
@@ -43,8 +44,10 @@ fun JustVideoDisplay(
|
||||
contentScale: ContentScale,
|
||||
accountViewModel: AccountViewModel,
|
||||
) {
|
||||
val event = (note.event as? VideoEvent) ?: return
|
||||
val imeta = event.imetaTags().getOrNull(0) ?: return
|
||||
val videoEvent = (note.event as? VideoEvent) ?: return
|
||||
val event = (videoEvent as? Event) ?: return
|
||||
|
||||
val imeta = videoEvent.imetaTags().getOrNull(0) ?: return
|
||||
|
||||
val content by
|
||||
remember(note) {
|
||||
|
@@ -237,6 +237,9 @@ open class BasicRelayClient(
|
||||
text: String,
|
||||
onConnected: () -> Unit,
|
||||
) {
|
||||
if (text.contains("2e9244f75b36d47116b8c8bd5c4ea4d29fb1a3d64688d2524156af34c6124dc3")) {
|
||||
Log.d(logTag, "AABBCC Receiving: $text")
|
||||
}
|
||||
// Log.d(logTag, "Receiving: $text")
|
||||
stats.addBytesReceived(text.bytesUsedInMemory())
|
||||
|
||||
|
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* 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.nip71Video
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.hashtags
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.publishedAt.PublishedAtProvider
|
||||
import com.vitorpamplona.quartz.nip22Comments.RootScope
|
||||
import com.vitorpamplona.quartz.nip23LongContent.tags.PublishedAtTag
|
||||
import com.vitorpamplona.quartz.nip23LongContent.tags.TitleTag
|
||||
import com.vitorpamplona.quartz.nip71Video.tags.DurationTag
|
||||
import com.vitorpamplona.quartz.nip71Video.tags.SegmentTag
|
||||
import com.vitorpamplona.quartz.nip92IMeta.imetas
|
||||
import com.vitorpamplona.quartz.nip94FileMetadata.tags.HashSha256Tag
|
||||
import com.vitorpamplona.quartz.nip94FileMetadata.tags.MimeTypeTag
|
||||
|
||||
@Immutable
|
||||
abstract class RegularVideoEvent(
|
||||
id: HexKey,
|
||||
pubKey: HexKey,
|
||||
createdAt: Long,
|
||||
kind: Int,
|
||||
tags: Array<Array<String>>,
|
||||
content: String,
|
||||
sig: HexKey,
|
||||
) : Event(id, pubKey, createdAt, kind, tags, content, sig),
|
||||
PublishedAtProvider,
|
||||
VideoEvent,
|
||||
RootScope {
|
||||
@Transient var iMetas: List<VideoMeta>? = null
|
||||
|
||||
override fun title() = tags.firstNotNullOfOrNull(TitleTag::parse)
|
||||
|
||||
override fun publishedAt() = tags.firstNotNullOfOrNull(PublishedAtTag::parse)
|
||||
|
||||
override fun duration() = tags.firstNotNullOfOrNull(DurationTag::parse)
|
||||
|
||||
override fun textTrack() = tags.mapNotNull(ETag::parse)
|
||||
|
||||
override fun segments() = tags.mapNotNull(SegmentTag::parse)
|
||||
|
||||
override fun participants() = tags.mapNotNull(PTag::parse)
|
||||
|
||||
override fun hashtags() = tags.hashtags()
|
||||
|
||||
override fun mimeType() = tags.firstNotNullOfOrNull(MimeTypeTag::parse)
|
||||
|
||||
override fun hash() = tags.firstNotNullOfOrNull(HashSha256Tag::parse)
|
||||
|
||||
override fun imetaTags() = iMetas ?: imetas().map { VideoMeta.parse(it) }.also { iMetas = it }
|
||||
}
|
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* 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.nip71Video
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.nip01Core.core.BaseReplaceableEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.hashtags
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.publishedAt.PublishedAtProvider
|
||||
import com.vitorpamplona.quartz.nip22Comments.RootScope
|
||||
import com.vitorpamplona.quartz.nip23LongContent.tags.PublishedAtTag
|
||||
import com.vitorpamplona.quartz.nip23LongContent.tags.TitleTag
|
||||
import com.vitorpamplona.quartz.nip71Video.tags.DurationTag
|
||||
import com.vitorpamplona.quartz.nip71Video.tags.SegmentTag
|
||||
import com.vitorpamplona.quartz.nip92IMeta.imetas
|
||||
import com.vitorpamplona.quartz.nip94FileMetadata.tags.HashSha256Tag
|
||||
import com.vitorpamplona.quartz.nip94FileMetadata.tags.MimeTypeTag
|
||||
|
||||
@Immutable
|
||||
abstract class ReplaceableVideoEvent(
|
||||
id: HexKey,
|
||||
pubKey: HexKey,
|
||||
createdAt: Long,
|
||||
kind: Int,
|
||||
tags: Array<Array<String>>,
|
||||
content: String,
|
||||
sig: HexKey,
|
||||
) : BaseReplaceableEvent(id, pubKey, createdAt, kind, tags, content, sig),
|
||||
PublishedAtProvider,
|
||||
VideoEvent,
|
||||
RootScope {
|
||||
@Transient var iMetas: List<VideoMeta>? = null
|
||||
|
||||
override fun title() = tags.firstNotNullOfOrNull(TitleTag::parse)
|
||||
|
||||
override fun publishedAt() = tags.firstNotNullOfOrNull(PublishedAtTag::parse)
|
||||
|
||||
override fun duration() = tags.firstNotNullOfOrNull(DurationTag::parse)
|
||||
|
||||
override fun textTrack() = tags.mapNotNull(ETag::parse)
|
||||
|
||||
override fun segments() = tags.mapNotNull(SegmentTag::parse)
|
||||
|
||||
override fun participants() = tags.mapNotNull(PTag::parse)
|
||||
|
||||
override fun hashtags() = tags.hashtags()
|
||||
|
||||
override fun mimeType() = tags.firstNotNullOfOrNull(MimeTypeTag::parse)
|
||||
|
||||
override fun hash() = tags.firstNotNullOfOrNull(HashSha256Tag::parse)
|
||||
|
||||
override fun imetaTags() = iMetas ?: imetas().map { VideoMeta.parse(it) }.also { iMetas = it }
|
||||
}
|
@@ -21,52 +21,30 @@
|
||||
package com.vitorpamplona.quartz.nip71Video
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.nip01Core.core.BaseAddressableEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.IEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.hashtags
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.publishedAt.PublishedAtProvider
|
||||
import com.vitorpamplona.quartz.nip22Comments.RootScope
|
||||
import com.vitorpamplona.quartz.nip23LongContent.tags.PublishedAtTag
|
||||
import com.vitorpamplona.quartz.nip23LongContent.tags.TitleTag
|
||||
import com.vitorpamplona.quartz.nip71Video.tags.DurationTag
|
||||
import com.vitorpamplona.quartz.nip71Video.tags.SegmentTag
|
||||
import com.vitorpamplona.quartz.nip92IMeta.imetas
|
||||
import com.vitorpamplona.quartz.nip94FileMetadata.tags.HashSha256Tag
|
||||
import com.vitorpamplona.quartz.nip94FileMetadata.tags.MimeTypeTag
|
||||
|
||||
@Immutable
|
||||
abstract class VideoEvent(
|
||||
id: HexKey,
|
||||
pubKey: HexKey,
|
||||
createdAt: Long,
|
||||
kind: Int,
|
||||
tags: Array<Array<String>>,
|
||||
content: String,
|
||||
sig: HexKey,
|
||||
) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig),
|
||||
PublishedAtProvider,
|
||||
RootScope {
|
||||
@Transient var iMetas: List<VideoMeta>? = null
|
||||
interface VideoEvent : IEvent {
|
||||
fun title(): String?
|
||||
|
||||
fun title() = tags.firstNotNullOfOrNull(TitleTag::parse)
|
||||
fun publishedAt(): Long?
|
||||
|
||||
override fun publishedAt() = tags.firstNotNullOfOrNull(PublishedAtTag::parse)
|
||||
fun duration(): Int?
|
||||
|
||||
fun duration() = tags.firstNotNullOfOrNull(DurationTag::parse)
|
||||
fun textTrack(): List<ETag>
|
||||
|
||||
fun textTrack() = tags.mapNotNull(ETag::parse)
|
||||
fun segments(): List<SegmentTag>
|
||||
|
||||
fun segments() = tags.mapNotNull(SegmentTag::parse)
|
||||
fun participants(): List<PTag>
|
||||
|
||||
fun participants() = tags.mapNotNull(PTag::parse)
|
||||
fun hashtags(): List<String>
|
||||
|
||||
fun hashtags() = tags.hashtags()
|
||||
fun mimeType(): String?
|
||||
|
||||
private fun mimeType() = tags.firstNotNullOfOrNull(MimeTypeTag::parse)
|
||||
fun hash(): String?
|
||||
|
||||
private fun hash() = tags.firstNotNullOfOrNull(HashSha256Tag::parse)
|
||||
|
||||
fun imetaTags() = iMetas ?: imetas().map { VideoMeta.parse(it) }.also { iMetas = it }
|
||||
fun imetaTags(): List<VideoMeta>
|
||||
}
|
||||
|
@@ -27,6 +27,7 @@ import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.dTags.dTag
|
||||
import com.vitorpamplona.quartz.nip22Comments.RootScope
|
||||
import com.vitorpamplona.quartz.nip31Alts.alt
|
||||
import com.vitorpamplona.quartz.nip71Video.videoIMetas
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
import java.util.UUID
|
||||
|
||||
@@ -38,7 +39,7 @@ class VideoHorizontalEvent(
|
||||
tags: Array<Array<String>>,
|
||||
content: String,
|
||||
sig: HexKey,
|
||||
) : VideoEvent(id, pubKey, createdAt, KIND, tags, content, sig),
|
||||
) : ReplaceableVideoEvent(id, pubKey, createdAt, KIND, tags, content, sig),
|
||||
RootScope {
|
||||
companion object {
|
||||
const val KIND = 34235
|
||||
|
@@ -24,11 +24,9 @@ import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.dTags.dTag
|
||||
import com.vitorpamplona.quartz.nip22Comments.RootScope
|
||||
import com.vitorpamplona.quartz.nip31Alts.alt
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
import java.util.UUID
|
||||
|
||||
@Immutable
|
||||
class VideoNormalEvent(
|
||||
@@ -38,7 +36,7 @@ class VideoNormalEvent(
|
||||
tags: Array<Array<String>>,
|
||||
content: String,
|
||||
sig: HexKey,
|
||||
) : VideoEvent(id, pubKey, createdAt, KIND, tags, content, sig),
|
||||
) : RegularVideoEvent(id, pubKey, createdAt, KIND, tags, content, sig),
|
||||
RootScope {
|
||||
companion object {
|
||||
const val KIND = 21
|
||||
@@ -47,10 +45,9 @@ class VideoNormalEvent(
|
||||
fun build(
|
||||
video: VideoMeta,
|
||||
description: String,
|
||||
dTag: String = UUID.randomUUID().toString(),
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
initializer: TagArrayBuilder<VideoNormalEvent>.() -> Unit = {},
|
||||
) = build(description, dTag, createdAt) {
|
||||
) = build(description, createdAt) {
|
||||
videoIMeta(video)
|
||||
initializer()
|
||||
}
|
||||
@@ -58,21 +55,18 @@ class VideoNormalEvent(
|
||||
fun build(
|
||||
video: List<VideoMeta>,
|
||||
description: String,
|
||||
dTag: String = UUID.randomUUID().toString(),
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
initializer: TagArrayBuilder<VideoNormalEvent>.() -> Unit = {},
|
||||
) = build(description, dTag, createdAt) {
|
||||
) = build(description, createdAt) {
|
||||
videoIMetas(video)
|
||||
initializer()
|
||||
}
|
||||
|
||||
fun build(
|
||||
description: String,
|
||||
dTag: String = UUID.randomUUID().toString(),
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
initializer: TagArrayBuilder<VideoNormalEvent>.() -> Unit = {},
|
||||
) = eventTemplate(KIND, description, createdAt) {
|
||||
dTag(dTag)
|
||||
alt(ALT_DESCRIPTION)
|
||||
initializer()
|
||||
}
|
||||
|
@@ -24,11 +24,9 @@ import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.dTags.dTag
|
||||
import com.vitorpamplona.quartz.nip22Comments.RootScope
|
||||
import com.vitorpamplona.quartz.nip31Alts.alt
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
import java.util.UUID
|
||||
|
||||
@Immutable
|
||||
class VideoShortEvent(
|
||||
@@ -38,7 +36,7 @@ class VideoShortEvent(
|
||||
tags: Array<Array<String>>,
|
||||
content: String,
|
||||
sig: HexKey,
|
||||
) : VideoEvent(id, pubKey, createdAt, KIND, tags, content, sig),
|
||||
) : RegularVideoEvent(id, pubKey, createdAt, KIND, tags, content, sig),
|
||||
RootScope {
|
||||
companion object {
|
||||
const val KIND = 22
|
||||
@@ -47,21 +45,18 @@ class VideoShortEvent(
|
||||
fun build(
|
||||
video: VideoMeta,
|
||||
description: String,
|
||||
dTag: String = UUID.randomUUID().toString(),
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
initializer: TagArrayBuilder<VideoShortEvent>.() -> Unit = {},
|
||||
) = build(description, dTag, createdAt) {
|
||||
) = build(description, createdAt) {
|
||||
videoIMeta(video)
|
||||
initializer()
|
||||
}
|
||||
|
||||
fun build(
|
||||
description: String,
|
||||
dTag: String = UUID.randomUUID().toString(),
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
initializer: TagArrayBuilder<VideoShortEvent>.() -> Unit = {},
|
||||
) = eventTemplate(KIND, description, createdAt) {
|
||||
dTag(dTag)
|
||||
alt(ALT_DESCRIPTION)
|
||||
initializer()
|
||||
}
|
||||
|
@@ -38,7 +38,7 @@ class VideoVerticalEvent(
|
||||
tags: Array<Array<String>>,
|
||||
content: String,
|
||||
sig: HexKey,
|
||||
) : VideoEvent(id, pubKey, createdAt, KIND, tags, content, sig),
|
||||
) : ReplaceableVideoEvent(id, pubKey, createdAt, KIND, tags, content, sig),
|
||||
RootScope {
|
||||
companion object {
|
||||
const val KIND = 34236
|
||||
|
Reference in New Issue
Block a user