mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-06-05 06:09:18 +02:00
Migrates Video feed new posts from NIP-94 to Video and Picture events.
This commit is contained in:
parent
d33421fce4
commit
03662b9d1b
@ -30,6 +30,7 @@ import androidx.lifecycle.switchMap
|
||||
import com.fasterxml.jackson.module.kotlin.readValue
|
||||
import com.vitorpamplona.amethyst.Amethyst
|
||||
import com.vitorpamplona.amethyst.BuildConfig
|
||||
import com.vitorpamplona.amethyst.commons.richtext.RichTextParser
|
||||
import com.vitorpamplona.amethyst.service.FileHeader
|
||||
import com.vitorpamplona.amethyst.service.LocationState
|
||||
import com.vitorpamplona.amethyst.service.NostrLnZapPaymentResponseDataSource
|
||||
@ -94,6 +95,7 @@ import com.vitorpamplona.quartz.events.NIP17Factory
|
||||
import com.vitorpamplona.quartz.events.NIP90ContentDiscoveryRequestEvent
|
||||
import com.vitorpamplona.quartz.events.OtsEvent
|
||||
import com.vitorpamplona.quartz.events.PeopleListEvent
|
||||
import com.vitorpamplona.quartz.events.PictureEvent
|
||||
import com.vitorpamplona.quartz.events.PollNoteEvent
|
||||
import com.vitorpamplona.quartz.events.Price
|
||||
import com.vitorpamplona.quartz.events.PrivateDmEvent
|
||||
@ -110,6 +112,8 @@ import com.vitorpamplona.quartz.events.StatusEvent
|
||||
import com.vitorpamplona.quartz.events.TextNoteEvent
|
||||
import com.vitorpamplona.quartz.events.TextNoteModificationEvent
|
||||
import com.vitorpamplona.quartz.events.TorrentCommentEvent
|
||||
import com.vitorpamplona.quartz.events.VideoHorizontalEvent
|
||||
import com.vitorpamplona.quartz.events.VideoVerticalEvent
|
||||
import com.vitorpamplona.quartz.events.WrappedEvent
|
||||
import com.vitorpamplona.quartz.events.ZapSplitSetup
|
||||
import com.vitorpamplona.quartz.signers.NostrSigner
|
||||
@ -1855,12 +1859,12 @@ class Account(
|
||||
}
|
||||
|
||||
fun sendHeader(
|
||||
signedEvent: FileHeaderEvent,
|
||||
signedEvent: Event,
|
||||
relayList: List<RelaySetupInfo>,
|
||||
onReady: (Note) -> Unit,
|
||||
) {
|
||||
Client.send(signedEvent, relayList = relayList)
|
||||
LocalCache.consume(signedEvent, null)
|
||||
LocalCache.justConsume(signedEvent, null)
|
||||
|
||||
LocalCache.getNoteIfExists(signedEvent.id)?.let { onReady(it) }
|
||||
}
|
||||
@ -1894,7 +1898,7 @@ class Account(
|
||||
}
|
||||
|
||||
fun sendHeader(
|
||||
imageUrl: String,
|
||||
url: String,
|
||||
magnetUri: String?,
|
||||
headerInfo: FileHeader,
|
||||
alt: String?,
|
||||
@ -1905,20 +1909,72 @@ class Account(
|
||||
) {
|
||||
if (!isWriteable()) return
|
||||
|
||||
FileHeaderEvent.create(
|
||||
url = imageUrl,
|
||||
magnetUri = magnetUri,
|
||||
mimeType = headerInfo.mimeType,
|
||||
hash = headerInfo.hash,
|
||||
size = headerInfo.size.toString(),
|
||||
dimensions = headerInfo.dim,
|
||||
blurhash = headerInfo.blurHash,
|
||||
alt = alt,
|
||||
originalHash = originalHash,
|
||||
sensitiveContent = sensitiveContent,
|
||||
signer = signer,
|
||||
) { event ->
|
||||
sendHeader(event, relayList = relayList, onReady)
|
||||
val isImage = headerInfo.mimeType?.startsWith("image/") == true || RichTextParser.isImageUrl(url)
|
||||
val isVideo = headerInfo.mimeType?.startsWith("video/") == true || RichTextParser.isVideoUrl(url)
|
||||
|
||||
if (isImage) {
|
||||
PictureEvent.create(
|
||||
url = url,
|
||||
mimeType = headerInfo.mimeType,
|
||||
hash = headerInfo.hash,
|
||||
size = headerInfo.size.toLong(),
|
||||
dimensions = headerInfo.dim,
|
||||
blurhash = headerInfo.blurHash,
|
||||
alt = alt,
|
||||
signer = signer,
|
||||
) { event ->
|
||||
sendHeader(event, relayList = relayList, onReady)
|
||||
}
|
||||
} else if (isVideo && headerInfo.dim != null) {
|
||||
if (headerInfo.dim.height > headerInfo.dim.width) {
|
||||
VideoVerticalEvent.create(
|
||||
url = url,
|
||||
magnetUri = magnetUri,
|
||||
mimeType = headerInfo.mimeType,
|
||||
hash = headerInfo.hash,
|
||||
size = headerInfo.size.toString(),
|
||||
dimensions = headerInfo.dim,
|
||||
blurhash = headerInfo.blurHash,
|
||||
alt = alt,
|
||||
originalHash = originalHash,
|
||||
sensitiveContent = sensitiveContent,
|
||||
signer = signer,
|
||||
) { event ->
|
||||
sendHeader(event, relayList = relayList, onReady)
|
||||
}
|
||||
} else {
|
||||
VideoHorizontalEvent.create(
|
||||
url = url,
|
||||
magnetUri = magnetUri,
|
||||
mimeType = headerInfo.mimeType,
|
||||
hash = headerInfo.hash,
|
||||
size = headerInfo.size.toString(),
|
||||
dimensions = headerInfo.dim,
|
||||
blurhash = headerInfo.blurHash,
|
||||
alt = alt,
|
||||
originalHash = originalHash,
|
||||
sensitiveContent = sensitiveContent,
|
||||
signer = signer,
|
||||
) { event ->
|
||||
sendHeader(event, relayList = relayList, onReady)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
FileHeaderEvent.create(
|
||||
url = url,
|
||||
magnetUri = magnetUri,
|
||||
mimeType = headerInfo.mimeType,
|
||||
hash = headerInfo.hash,
|
||||
size = headerInfo.size.toString(),
|
||||
dimensions = headerInfo.dim,
|
||||
blurhash = headerInfo.blurHash,
|
||||
alt = alt,
|
||||
originalHash = originalHash,
|
||||
sensitiveContent = sensitiveContent,
|
||||
signer = signer,
|
||||
) { event ->
|
||||
sendHeader(event, relayList = relayList, onReady)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@ import android.util.Log
|
||||
import com.vitorpamplona.amethyst.ui.actions.ImageDownloader
|
||||
import com.vitorpamplona.quartz.crypto.CryptoUtils
|
||||
import com.vitorpamplona.quartz.encoders.toHexKey
|
||||
import com.vitorpamplona.quartz.events.Dimension
|
||||
import io.trbl.blurhash.BlurHash
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import java.io.IOException
|
||||
@ -40,14 +41,14 @@ class FileHeader(
|
||||
val mimeType: String?,
|
||||
val hash: String,
|
||||
val size: Int,
|
||||
val dim: String?,
|
||||
val dim: Dimension?,
|
||||
val blurHash: String?,
|
||||
) {
|
||||
companion object {
|
||||
suspend fun prepare(
|
||||
fileUrl: String,
|
||||
mimeType: String?,
|
||||
dimPrecomputed: String?,
|
||||
dimPrecomputed: Dimension?,
|
||||
forceProxy: Boolean,
|
||||
onReady: (FileHeader) -> Unit,
|
||||
onError: (String) -> Unit,
|
||||
@ -70,7 +71,7 @@ class FileHeader(
|
||||
fun prepare(
|
||||
data: ByteArray,
|
||||
mimeType: String?,
|
||||
dimPrecomputed: String?,
|
||||
dimPrecomputed: Dimension?,
|
||||
onReady: (FileHeader) -> Unit,
|
||||
onError: (String) -> Unit,
|
||||
) {
|
||||
@ -95,7 +96,7 @@ class FileHeader(
|
||||
mBitmap.height,
|
||||
)
|
||||
|
||||
val dim = "${mBitmap.width}x${mBitmap.height}"
|
||||
val dim = Dimension(mBitmap.width, mBitmap.height)
|
||||
|
||||
val aspectRatio = (mBitmap.width).toFloat() / (mBitmap.height).toFloat()
|
||||
|
||||
@ -166,7 +167,7 @@ class FileHeader(
|
||||
}
|
||||
}
|
||||
|
||||
if (newDim != "0x0") {
|
||||
if (newDim?.hasSize() == true) {
|
||||
Pair(blurhash, newDim)
|
||||
} else {
|
||||
Pair(blurhash, null)
|
||||
@ -212,11 +213,15 @@ fun MediaMetadataRetriever.getThumbnail(): Bitmap? {
|
||||
}
|
||||
}
|
||||
|
||||
fun MediaMetadataRetriever.prepareDimFromVideo(): String? {
|
||||
fun MediaMetadataRetriever.prepareDimFromVideo(): Dimension? {
|
||||
val width = prepareVideoWidth() ?: return null
|
||||
val height = prepareVideoHeight() ?: return null
|
||||
|
||||
return "${width}x$height"
|
||||
return if (width > 0 && height > 0) {
|
||||
Dimension(width, height)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun MediaMetadataRetriever.prepareVideoWidth(): Int? {
|
||||
|
@ -45,6 +45,7 @@ import com.vitorpamplona.amethyst.ui.components.MediaCompressor
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.ammolite.relays.RelaySetupInfo
|
||||
import com.vitorpamplona.quartz.events.Dimension
|
||||
import com.vitorpamplona.quartz.events.FileHeaderEvent
|
||||
import com.vitorpamplona.quartz.events.FileStorageEvent
|
||||
import com.vitorpamplona.quartz.events.FileStorageHeaderEvent
|
||||
@ -341,6 +342,7 @@ open class EditPostViewModel : ViewModel() {
|
||||
?.firstOrNull { it.size > 1 && it[0] == "dim" }
|
||||
?.get(1)
|
||||
?.ifBlank { null }
|
||||
?.let { Dimension.parse(it) }
|
||||
val magnet =
|
||||
uploadingResult.tags
|
||||
?.firstOrNull { it.size > 1 && it[0] == "magnet" }
|
||||
|
@ -37,6 +37,7 @@ import com.vitorpamplona.amethyst.service.Nip96Uploader
|
||||
import com.vitorpamplona.amethyst.ui.components.MediaCompressor
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.ammolite.relays.RelaySetupInfo
|
||||
import com.vitorpamplona.quartz.events.Dimension
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
@ -217,6 +218,7 @@ open class NewMediaModel : ViewModel() {
|
||||
?.firstOrNull { it.size > 1 && it[0] == "dim" }
|
||||
?.get(1)
|
||||
?.ifBlank { null }
|
||||
?.let { Dimension.parse(it) }
|
||||
val magnet =
|
||||
uploadingResult.tags
|
||||
?.firstOrNull { it.size > 1 && it[0] == "magnet" }
|
||||
|
@ -61,6 +61,7 @@ import com.vitorpamplona.quartz.events.ChatMessageEvent
|
||||
import com.vitorpamplona.quartz.events.ClassifiedsEvent
|
||||
import com.vitorpamplona.quartz.events.CommentEvent
|
||||
import com.vitorpamplona.quartz.events.CommunityDefinitionEvent
|
||||
import com.vitorpamplona.quartz.events.Dimension
|
||||
import com.vitorpamplona.quartz.events.DraftEvent
|
||||
import com.vitorpamplona.quartz.events.Event
|
||||
import com.vitorpamplona.quartz.events.FileHeaderEvent
|
||||
@ -1205,6 +1206,7 @@ open class NewPostViewModel : ViewModel() {
|
||||
?.firstOrNull { it.size > 1 && it[0] == "dim" }
|
||||
?.get(1)
|
||||
?.ifBlank { null }
|
||||
?.let { Dimension.parse(it) }
|
||||
val magnet =
|
||||
uploadingResult.tags
|
||||
?.firstOrNull { it.size > 1 && it[0] == "magnet" }
|
||||
|
@ -60,7 +60,7 @@ data class ATag(
|
||||
TlvBuilder()
|
||||
.apply {
|
||||
addString(Nip19Bech32.TlvTypes.SPECIAL, dTag)
|
||||
addStringIfNotNull(Nip19Bech32.TlvTypes.RELAY, overrideRelay)
|
||||
addStringIfNotNull(Nip19Bech32.TlvTypes.RELAY, overrideRelay ?: relay)
|
||||
addHex(Nip19Bech32.TlvTypes.AUTHOR, pubKeyHex)
|
||||
addInt(Nip19Bech32.TlvTypes.KIND, kind)
|
||||
}.build()
|
||||
|
@ -81,7 +81,7 @@ class FileHeaderEvent(
|
||||
alt: String? = null,
|
||||
hash: String? = null,
|
||||
size: String? = null,
|
||||
dimensions: String? = null,
|
||||
dimensions: Dimension? = null,
|
||||
blurhash: String? = null,
|
||||
originalHash: String? = null,
|
||||
magnetURI: String? = null,
|
||||
@ -99,7 +99,7 @@ class FileHeaderEvent(
|
||||
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) },
|
||||
dimensions?.let { arrayOf(DIMENSION, it.toString()) },
|
||||
blurhash?.let { arrayOf(BLUR_HASH, it) },
|
||||
originalHash?.let { arrayOf(ORIGINAL_HASH, it) },
|
||||
magnetURI?.let { arrayOf(MAGNET_URI, it) },
|
||||
|
@ -74,7 +74,7 @@ class FileStorageHeaderEvent(
|
||||
alt: String? = null,
|
||||
hash: String? = null,
|
||||
size: String? = null,
|
||||
dimensions: String? = null,
|
||||
dimensions: Dimension? = null,
|
||||
blurhash: String? = null,
|
||||
magnetURI: String? = null,
|
||||
torrentInfoHash: String? = null,
|
||||
@ -90,7 +90,7 @@ class FileStorageHeaderEvent(
|
||||
hash?.let { arrayOf(HASH, it) },
|
||||
alt?.let { arrayOf(ALT, it) } ?: arrayOf("alt", ALT_DESCRIPTION),
|
||||
size?.let { arrayOf(FILE_SIZE, it) },
|
||||
dimensions?.let { arrayOf(DIMENSION, it) },
|
||||
dimensions?.let { arrayOf(DIMENSION, it.toString()) },
|
||||
blurhash?.let { arrayOf(BLUR_HASH, it) },
|
||||
magnetURI?.let { arrayOf(MAGNET_URI, it) },
|
||||
torrentInfoHash?.let { arrayOf(TORRENT_INFOHASH, it) },
|
||||
|
@ -24,16 +24,8 @@ import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.encoders.ATag
|
||||
import com.vitorpamplona.quartz.encoders.ETag
|
||||
import com.vitorpamplona.quartz.encoders.HexKey
|
||||
import com.vitorpamplona.quartz.encoders.Nip92MediaAttachments
|
||||
import com.vitorpamplona.quartz.encoders.Nip92MediaAttachments.Companion.IMETA
|
||||
import com.vitorpamplona.quartz.encoders.PTag
|
||||
import com.vitorpamplona.quartz.events.FileHeaderEvent.Companion.ALT
|
||||
import com.vitorpamplona.quartz.events.FileHeaderEvent.Companion.BLUR_HASH
|
||||
import com.vitorpamplona.quartz.events.FileHeaderEvent.Companion.DIMENSION
|
||||
import com.vitorpamplona.quartz.events.FileHeaderEvent.Companion.FILE_SIZE
|
||||
import com.vitorpamplona.quartz.events.FileHeaderEvent.Companion.MAGNET_URI
|
||||
import com.vitorpamplona.quartz.events.FileHeaderEvent.Companion.TORRENT_INFOHASH
|
||||
import com.vitorpamplona.quartz.events.FileHeaderEvent.Companion.URL
|
||||
import com.vitorpamplona.quartz.signers.NostrSigner
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
import kotlin.coroutines.cancellation.CancellationException
|
||||
@ -53,27 +45,23 @@ class PictureEvent(
|
||||
|
||||
fun title() = tags.firstOrNull { it.size > 1 && it[0] == TITLE }?.get(1)
|
||||
|
||||
fun url() = tags.firstOrNull { it.size > 1 && it[0] == URL }?.get(1)
|
||||
fun url() = tags.firstOrNull { it.size > 1 && it[0] == PictureMeta.URL }?.get(1)
|
||||
|
||||
fun urls() = tags.filter { it.size > 1 && it[0] == URL }.map { it[1] }
|
||||
fun urls() = tags.filter { it.size > 1 && it[0] == PictureMeta.URL }.map { it[1] }
|
||||
|
||||
fun mimeType() = tags.firstOrNull { it.size > 1 && it[0] == FileHeaderEvent.MIME_TYPE }?.get(1)
|
||||
fun mimeType() = tags.firstOrNull { it.size > 1 && it[0] == PictureMeta.MIME_TYPE }?.get(1)
|
||||
|
||||
fun hash() = tags.firstOrNull { it.size > 1 && it[0] == FileHeaderEvent.HASH }?.get(1)
|
||||
fun hash() = tags.firstOrNull { it.size > 1 && it[0] == PictureMeta.HASH }?.get(1)
|
||||
|
||||
fun size() = tags.firstOrNull { it.size > 1 && it[0] == FILE_SIZE }?.get(1)
|
||||
fun size() = tags.firstOrNull { it.size > 1 && it[0] == PictureMeta.FILE_SIZE }?.get(1)
|
||||
|
||||
fun alt() = tags.firstOrNull { it.size > 1 && it[0] == ALT }?.get(1)
|
||||
fun alt() = tags.firstOrNull { it.size > 1 && it[0] == PictureMeta.ALT }?.get(1)
|
||||
|
||||
fun dimensions() = tags.firstOrNull { it.size > 1 && it[0] == DIMENSION }?.get(1)?.let { Dimension.parse(it) }
|
||||
fun dimensions() = tags.firstOrNull { it.size > 1 && it[0] == PictureMeta.DIMENSION }?.get(1)?.let { Dimension.parse(it) }
|
||||
|
||||
fun magnetURI() = tags.firstOrNull { it.size > 1 && it[0] == MAGNET_URI }?.get(1)
|
||||
fun blurhash() = tags.firstOrNull { it.size > 1 && it[0] == PictureMeta.BLUR_HASH }?.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 hasUrl() = tags.any { it.size > 1 && it[0] == PictureMeta.URL }
|
||||
|
||||
// hack to fix pablo's bug
|
||||
fun rootImage() =
|
||||
@ -104,41 +92,99 @@ class PictureEvent(
|
||||
|
||||
companion object {
|
||||
const val KIND = 20
|
||||
const val ALT_DESCRIPTION = "Picture"
|
||||
const val ALT_DESCRIPTION = "List of pictures"
|
||||
|
||||
private const val MIME_TYPE = "m"
|
||||
private const val HASH = "x"
|
||||
private const val TITLE = "title"
|
||||
|
||||
private fun create(
|
||||
msg: String,
|
||||
tags: MutableList<Array<String>>,
|
||||
fun create(
|
||||
url: String,
|
||||
msg: String? = null,
|
||||
title: String? = null,
|
||||
mimeType: String? = null,
|
||||
alt: String? = null,
|
||||
hash: String? = null,
|
||||
size: Long? = null,
|
||||
dimensions: Dimension? = null,
|
||||
blurhash: String? = null,
|
||||
usersMentioned: Set<PTag> = emptySet(),
|
||||
addressesMentioned: Set<ATag> = emptySet(),
|
||||
eventsMentioned: Set<ETag> = emptySet(),
|
||||
nip94attachments: List<FileHeaderEvent>? = null,
|
||||
geohash: String? = null,
|
||||
zapReceiver: List<ZapSplitSetup>? = null,
|
||||
markAsSensitive: Boolean = false,
|
||||
zapRaiserAmount: Long? = null,
|
||||
isDraft: Boolean,
|
||||
signer: NostrSigner,
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
onReady: (PictureEvent) -> Unit,
|
||||
) {
|
||||
val image =
|
||||
PictureMeta(
|
||||
url,
|
||||
mimeType,
|
||||
blurhash,
|
||||
dimensions,
|
||||
alt,
|
||||
hash,
|
||||
size,
|
||||
emptyList(),
|
||||
emptyList(),
|
||||
)
|
||||
|
||||
create(listOf(image), msg, title, usersMentioned, addressesMentioned, eventsMentioned, geohash, zapReceiver, markAsSensitive, zapRaiserAmount, signer, createdAt, onReady)
|
||||
}
|
||||
|
||||
fun create(
|
||||
images: List<PictureMeta>,
|
||||
msg: String? = null,
|
||||
title: String? = null,
|
||||
usersMentioned: Set<PTag> = emptySet(),
|
||||
addressesMentioned: Set<ATag> = emptySet(),
|
||||
eventsMentioned: Set<ETag> = emptySet(),
|
||||
geohash: String? = null,
|
||||
zapReceiver: List<ZapSplitSetup>? = null,
|
||||
markAsSensitive: Boolean = false,
|
||||
zapRaiserAmount: Long? = null,
|
||||
signer: NostrSigner,
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
onReady: (PictureEvent) -> Unit,
|
||||
) {
|
||||
val tags = mutableListOf(arrayOf<String>("alt", ALT_DESCRIPTION))
|
||||
|
||||
images.forEach {
|
||||
tags.add(it.toIMetaArray())
|
||||
}
|
||||
|
||||
title?.let { tags.add(arrayOf("title", it)) }
|
||||
|
||||
images.distinctBy { it.hash }.forEach {
|
||||
if (it.hash != null) {
|
||||
tags.add(arrayOf("x", it.hash))
|
||||
}
|
||||
}
|
||||
|
||||
images.distinctBy { it.mimeType }.forEach {
|
||||
if (it.mimeType != null) {
|
||||
tags.add(arrayOf("m", it.mimeType))
|
||||
}
|
||||
}
|
||||
|
||||
usersMentioned.forEach { tags.add(it.toPTagArray()) }
|
||||
addressesMentioned.forEach { tags.add(it.toQTagArray()) }
|
||||
eventsMentioned.forEach { tags.add(it.toQTagArray()) }
|
||||
|
||||
findHashtags(msg).forEach {
|
||||
val lowercaseTag = it.lowercase()
|
||||
tags.add(arrayOf("t", it))
|
||||
if (it != lowercaseTag) {
|
||||
tags.add(arrayOf("t", it.lowercase()))
|
||||
if (msg != null) {
|
||||
findHashtags(msg).forEach {
|
||||
val lowercaseTag = it.lowercase()
|
||||
tags.add(arrayOf("t", it))
|
||||
if (it != lowercaseTag) {
|
||||
tags.add(arrayOf("t", it.lowercase()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
findURLs(msg).forEach { tags.add(arrayOf("r", it)) }
|
||||
findURLs(msg).forEach { tags.add(arrayOf("r", it)) }
|
||||
}
|
||||
|
||||
zapReceiver?.forEach {
|
||||
tags.add(arrayOf("zap", it.lnAddressOrPubKeyHex, it.relay ?: "", it.weight.toString()))
|
||||
@ -148,19 +194,8 @@ class PictureEvent(
|
||||
}
|
||||
zapRaiserAmount?.let { tags.add(arrayOf("zapraiser", "$it")) }
|
||||
geohash?.let { tags.addAll(geohashMipMap(it)) }
|
||||
nip94attachments?.let {
|
||||
it.forEach {
|
||||
Nip92MediaAttachments().convertFromFileHeader(it)?.let {
|
||||
tags.add(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isDraft) {
|
||||
signer.assembleRumor(createdAt, KIND, tags.toTypedArray(), msg, onReady)
|
||||
} else {
|
||||
signer.sign(createdAt, KIND, tags.toTypedArray(), msg, onReady)
|
||||
}
|
||||
signer.sign(createdAt, KIND, tags.toTypedArray(), msg ?: "", onReady)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -176,7 +211,33 @@ class PictureMeta(
|
||||
val fallback: List<String>,
|
||||
val annotations: List<UserAnnotation>,
|
||||
) {
|
||||
fun toIMetaArray(): Array<String> =
|
||||
(
|
||||
listOfNotNull(
|
||||
"imeta",
|
||||
"$URL $url",
|
||||
mimeType?.let { "$MIME_TYPE $it" },
|
||||
alt?.let { "$ALT $it" },
|
||||
hash?.let { "$HASH $it" },
|
||||
size?.let { "$FILE_SIZE $it" },
|
||||
dimension?.let { "$DIMENSION $it" },
|
||||
blurhash?.let { "$BLUR_HASH $it" },
|
||||
) +
|
||||
fallback.map { "$FALLBACK $it" } +
|
||||
annotations.map { "$ANNOTATIONS $it" }
|
||||
).toTypedArray()
|
||||
|
||||
companion object {
|
||||
const val URL = "url"
|
||||
const val MIME_TYPE = "m"
|
||||
const val FILE_SIZE = "size"
|
||||
const val DIMENSION = "dim"
|
||||
const val HASH = "x"
|
||||
const val BLUR_HASH = "blurhash"
|
||||
const val ALT = "alt"
|
||||
const val FALLBACK = "fallback"
|
||||
const val ANNOTATIONS = "annotate-user"
|
||||
|
||||
fun parse(tagArray: Array<String>): PictureMeta? {
|
||||
var url: String? = null
|
||||
var mimeType: String? = null
|
||||
@ -188,9 +249,9 @@ class PictureMeta(
|
||||
val fallback = mutableListOf<String>()
|
||||
val annotations = mutableListOf<UserAnnotation>()
|
||||
|
||||
if (tagArray.size == 2 && tagArray[1].contains("url") && (tagArray[1].contains("blurhash") || tagArray[1].contains("size"))) {
|
||||
if (tagArray.size == 2 && tagArray[1].contains(URL) && (tagArray[1].contains(BLUR_HASH) || tagArray[1].contains(FILE_SIZE))) {
|
||||
// hack to fix pablo's bug
|
||||
val keys = setOf("url", "m", "blurhash", "dim", "alt", "x", "size", "fallback", "annotate-user")
|
||||
val keys = setOf(URL, MIME_TYPE, BLUR_HASH, DIMENSION, ALT, HASH, FILE_SIZE, FALLBACK, ANNOTATIONS)
|
||||
var keyNextValue: String? = null
|
||||
val values = mutableListOf<String>()
|
||||
|
||||
@ -198,15 +259,15 @@ class PictureMeta(
|
||||
if (it in keys) {
|
||||
if (keyNextValue != null && values.isNotEmpty()) {
|
||||
when (keyNextValue) {
|
||||
"url" -> url = values.joinToString(" ")
|
||||
"m" -> mimeType = values.joinToString(" ")
|
||||
"blurhash" -> blurhash = values.joinToString(" ")
|
||||
"dim" -> dim = Dimension.parse(values.joinToString(" "))
|
||||
"alt" -> alt = values.joinToString(" ")
|
||||
"x" -> hash = values.joinToString(" ")
|
||||
"size" -> size = values.joinToString(" ").toLongOrNull()
|
||||
"fallback" -> fallback.add(values.joinToString(" "))
|
||||
"annotate-user" -> {
|
||||
URL -> url = values.joinToString(" ")
|
||||
MIME_TYPE -> mimeType = values.joinToString(" ")
|
||||
BLUR_HASH -> blurhash = values.joinToString(" ")
|
||||
DIMENSION -> dim = Dimension.parse(values.joinToString(" "))
|
||||
ALT -> alt = values.joinToString(" ")
|
||||
HASH -> hash = values.joinToString(" ")
|
||||
FILE_SIZE -> size = values.joinToString(" ").toLongOrNull()
|
||||
FALLBACK -> fallback.add(values.joinToString(" "))
|
||||
ANNOTATIONS -> {
|
||||
UserAnnotation.parse(values.joinToString(" "))?.let {
|
||||
annotations.add(it)
|
||||
}
|
||||
@ -222,15 +283,15 @@ class PictureMeta(
|
||||
|
||||
if (keyNextValue != null && values.isNotEmpty()) {
|
||||
when (keyNextValue) {
|
||||
"url" -> url = values.joinToString(" ")
|
||||
"m" -> mimeType = values.joinToString(" ")
|
||||
"blurhash" -> blurhash = values.joinToString(" ")
|
||||
"dim" -> dim = Dimension.parse(values.joinToString(" "))
|
||||
"alt" -> alt = values.joinToString(" ")
|
||||
"x" -> hash = values.joinToString(" ")
|
||||
"size" -> size = values.joinToString(" ").toLongOrNull()
|
||||
"fallback" -> fallback.add(values.joinToString(" "))
|
||||
"annotate-user" -> {
|
||||
URL -> url = values.joinToString(" ")
|
||||
MIME_TYPE -> mimeType = values.joinToString(" ")
|
||||
BLUR_HASH -> blurhash = values.joinToString(" ")
|
||||
DIMENSION -> dim = Dimension.parse(values.joinToString(" "))
|
||||
ALT -> alt = values.joinToString(" ")
|
||||
HASH -> hash = values.joinToString(" ")
|
||||
FILE_SIZE -> size = values.joinToString(" ").toLongOrNull()
|
||||
FALLBACK -> fallback.add(values.joinToString(" "))
|
||||
ANNOTATIONS -> {
|
||||
UserAnnotation.parse(values.joinToString(" "))?.let {
|
||||
annotations.add(it)
|
||||
}
|
||||
@ -247,15 +308,15 @@ class PictureMeta(
|
||||
|
||||
if (value.isNotBlank()) {
|
||||
when (key) {
|
||||
"url" -> url = value
|
||||
"m" -> mimeType = value
|
||||
"blurhash" -> blurhash = value
|
||||
"dim" -> dim = Dimension.parse(value)
|
||||
"alt" -> alt = value
|
||||
"x" -> hash = value
|
||||
"size" -> size = value.toLongOrNull()
|
||||
"fallback" -> fallback.add(value)
|
||||
"annotate-user" -> {
|
||||
URL -> url = value
|
||||
MIME_TYPE -> mimeType = value
|
||||
BLUR_HASH -> blurhash = value
|
||||
DIMENSION -> dim = Dimension.parse(value)
|
||||
ALT -> alt = value
|
||||
HASH -> hash = value
|
||||
FILE_SIZE -> size = value.toLongOrNull()
|
||||
FALLBACK -> fallback.add(value)
|
||||
ANNOTATIONS -> {
|
||||
UserAnnotation.parse(value)?.let {
|
||||
annotations.add(it)
|
||||
}
|
||||
@ -278,6 +339,8 @@ class Dimension(
|
||||
) {
|
||||
fun aspectRatio() = width.toFloat() / height.toFloat()
|
||||
|
||||
fun hasSize() = width > 0 && height > 0
|
||||
|
||||
override fun toString() = "${width}x$height"
|
||||
|
||||
companion object {
|
||||
@ -305,6 +368,8 @@ class UserAnnotation(
|
||||
val x: Int,
|
||||
val y: Int,
|
||||
) {
|
||||
override fun toString() = "$pubkey:$x:$y"
|
||||
|
||||
companion object {
|
||||
fun parse(value: String): UserAnnotation? {
|
||||
val ann = value.split(":")
|
||||
|
@ -88,13 +88,14 @@ abstract class VideoEvent(
|
||||
|
||||
fun <T : VideoEvent> create(
|
||||
kind: Int,
|
||||
dTag: String,
|
||||
url: String,
|
||||
magnetUri: String? = null,
|
||||
mimeType: String? = null,
|
||||
alt: String? = null,
|
||||
hash: String? = null,
|
||||
size: String? = null,
|
||||
dimensions: String? = null,
|
||||
dimensions: Dimension? = null,
|
||||
blurhash: String? = null,
|
||||
originalHash: String? = null,
|
||||
magnetURI: String? = null,
|
||||
@ -107,13 +108,14 @@ abstract class VideoEvent(
|
||||
) {
|
||||
val tags =
|
||||
listOfNotNull(
|
||||
arrayOf("d", dTag),
|
||||
arrayOf(URL, url),
|
||||
magnetUri?.let { arrayOf(MAGNET_URI, it) },
|
||||
mimeType?.let { arrayOf(MIME_TYPE, it) },
|
||||
alt?.ifBlank { null }?.let { arrayOf(ALT, it) } ?: arrayOf("alt", altDescription),
|
||||
hash?.let { arrayOf(HASH, it) },
|
||||
size?.let { arrayOf(FILE_SIZE, it) },
|
||||
dimensions?.let { arrayOf(DIMENSION, it) },
|
||||
dimensions?.let { arrayOf(DIMENSION, it.toString()) },
|
||||
blurhash?.let { arrayOf(BLUR_HASH, it) },
|
||||
originalHash?.let { arrayOf(ORIGINAL_HASH, it) },
|
||||
magnetURI?.let { arrayOf(MAGNET_URI, it) },
|
||||
|
@ -24,6 +24,7 @@ import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.encoders.HexKey
|
||||
import com.vitorpamplona.quartz.signers.NostrSigner
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
import java.util.UUID
|
||||
|
||||
@Immutable
|
||||
class VideoHorizontalEvent(
|
||||
@ -45,18 +46,20 @@ class VideoHorizontalEvent(
|
||||
alt: String? = null,
|
||||
hash: String? = null,
|
||||
size: String? = null,
|
||||
dimensions: String? = null,
|
||||
dimensions: Dimension? = null,
|
||||
blurhash: String? = null,
|
||||
originalHash: String? = null,
|
||||
magnetURI: String? = null,
|
||||
torrentInfoHash: String? = null,
|
||||
sensitiveContent: Boolean? = null,
|
||||
dTag: String = UUID.randomUUID().toString(),
|
||||
signer: NostrSigner,
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
onReady: (VideoHorizontalEvent) -> Unit,
|
||||
) {
|
||||
create(
|
||||
KIND,
|
||||
dTag,
|
||||
url,
|
||||
magnetUri,
|
||||
mimeType,
|
||||
|
@ -24,6 +24,7 @@ import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.encoders.HexKey
|
||||
import com.vitorpamplona.quartz.signers.NostrSigner
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
import java.util.UUID
|
||||
|
||||
@Immutable
|
||||
class VideoVerticalEvent(
|
||||
@ -45,18 +46,20 @@ class VideoVerticalEvent(
|
||||
alt: String? = null,
|
||||
hash: String? = null,
|
||||
size: String? = null,
|
||||
dimensions: String? = null,
|
||||
dimensions: Dimension? = null,
|
||||
blurhash: String? = null,
|
||||
originalHash: String? = null,
|
||||
magnetURI: String? = null,
|
||||
torrentInfoHash: String? = null,
|
||||
sensitiveContent: Boolean? = null,
|
||||
dTag: String = UUID.randomUUID().toString(),
|
||||
signer: NostrSigner,
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
onReady: (VideoVerticalEvent) -> Unit,
|
||||
) {
|
||||
create(
|
||||
KIND,
|
||||
dTag,
|
||||
url,
|
||||
magnetUri,
|
||||
mimeType,
|
||||
|
Loading…
x
Reference in New Issue
Block a user