mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-03-18 05:41:56 +01:00
Adding Basic Git Rendering support.
This commit is contained in:
parent
b9c3123f18
commit
49c2d4f486
@ -71,6 +71,10 @@ import com.vitorpamplona.quartz.events.FileStorageEvent
|
||||
import com.vitorpamplona.quartz.events.FileStorageHeaderEvent
|
||||
import com.vitorpamplona.quartz.events.GenericRepostEvent
|
||||
import com.vitorpamplona.quartz.events.GiftWrapEvent
|
||||
import com.vitorpamplona.quartz.events.GitIssueEvent
|
||||
import com.vitorpamplona.quartz.events.GitPatchEvent
|
||||
import com.vitorpamplona.quartz.events.GitReplyEvent
|
||||
import com.vitorpamplona.quartz.events.GitRepositoryEvent
|
||||
import com.vitorpamplona.quartz.events.HighlightEvent
|
||||
import com.vitorpamplona.quartz.events.LiveActivitiesChatMessageEvent
|
||||
import com.vitorpamplona.quartz.events.LiveActivitiesEvent
|
||||
@ -361,6 +365,87 @@ object LocalCache {
|
||||
refreshObservers(note)
|
||||
}
|
||||
|
||||
fun consume(
|
||||
event: GitPatchEvent,
|
||||
relay: Relay? = null,
|
||||
) {
|
||||
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
|
||||
|
||||
if (antiSpam.isSpam(event, relay)) {
|
||||
relay?.let { it.spamCounter++ }
|
||||
return
|
||||
}
|
||||
|
||||
note.loadEvent(event, author, emptyList())
|
||||
|
||||
refreshObservers(note)
|
||||
}
|
||||
|
||||
fun consume(
|
||||
event: GitIssueEvent,
|
||||
relay: Relay? = null,
|
||||
) {
|
||||
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
|
||||
|
||||
if (antiSpam.isSpam(event, relay)) {
|
||||
relay?.let { it.spamCounter++ }
|
||||
return
|
||||
}
|
||||
|
||||
note.loadEvent(event, author, emptyList())
|
||||
|
||||
refreshObservers(note)
|
||||
}
|
||||
|
||||
fun consume(
|
||||
event: GitReplyEvent,
|
||||
relay: Relay? = null,
|
||||
) {
|
||||
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
|
||||
|
||||
if (antiSpam.isSpam(event, relay)) {
|
||||
relay?.let { it.spamCounter++ }
|
||||
return
|
||||
}
|
||||
|
||||
val replyTo =
|
||||
event
|
||||
.tagsWithoutCitations()
|
||||
.filter { it != event.repository()?.toTag() }
|
||||
.mapNotNull { checkGetOrCreateNote(it) }
|
||||
|
||||
note.loadEvent(event, author, replyTo)
|
||||
|
||||
refreshObservers(note)
|
||||
}
|
||||
|
||||
fun consume(
|
||||
event: LongTextNoteEvent,
|
||||
relay: Relay?,
|
||||
@ -508,6 +593,13 @@ object LocalCache {
|
||||
consumeBaseReplaceable(event, relay)
|
||||
}
|
||||
|
||||
fun consume(
|
||||
event: GitRepositoryEvent,
|
||||
relay: Relay?,
|
||||
) {
|
||||
consumeBaseReplaceable(event, relay)
|
||||
}
|
||||
|
||||
fun consume(
|
||||
event: ChannelListEvent,
|
||||
relay: Relay?,
|
||||
@ -1847,6 +1939,10 @@ object LocalCache {
|
||||
is FileStorageEvent -> consume(event, relay)
|
||||
is FileStorageHeaderEvent -> consume(event, relay)
|
||||
is GiftWrapEvent -> consume(event, relay)
|
||||
is GitIssueEvent -> consume(event, relay)
|
||||
is GitReplyEvent -> consume(event, relay)
|
||||
is GitPatchEvent -> consume(event, relay)
|
||||
is GitRepositoryEvent -> consume(event, relay)
|
||||
is HighlightEvent -> consume(event, relay)
|
||||
is LiveActivitiesEvent -> consume(event, relay)
|
||||
is LiveActivitiesChatMessageEvent -> consume(event, relay)
|
||||
|
@ -48,6 +48,7 @@ import androidx.compose.foundation.shape.CutCornerShape
|
||||
import androidx.compose.foundation.text.ClickableText
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.Divider
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@ -204,6 +205,8 @@ import com.vitorpamplona.quartz.events.EmptyTagList
|
||||
import com.vitorpamplona.quartz.events.FileHeaderEvent
|
||||
import com.vitorpamplona.quartz.events.FileStorageHeaderEvent
|
||||
import com.vitorpamplona.quartz.events.GenericRepostEvent
|
||||
import com.vitorpamplona.quartz.events.GitPatchEvent
|
||||
import com.vitorpamplona.quartz.events.GitRepositoryEvent
|
||||
import com.vitorpamplona.quartz.events.HighlightEvent
|
||||
import com.vitorpamplona.quartz.events.LiveActivitiesChatMessageEvent
|
||||
import com.vitorpamplona.quartz.events.LiveActivitiesEvent
|
||||
@ -1182,6 +1185,19 @@ private fun RenderNoteRow(
|
||||
is LiveActivitiesEvent -> {
|
||||
RenderLiveActivityEvent(baseNote, accountViewModel, nav)
|
||||
}
|
||||
is GitRepositoryEvent -> {
|
||||
RenderGitRepositoryEvent(baseNote, accountViewModel, nav)
|
||||
}
|
||||
is GitPatchEvent -> {
|
||||
RenderGitPatchEvent(
|
||||
baseNote,
|
||||
makeItShort,
|
||||
canPreview,
|
||||
backgroundColor,
|
||||
accountViewModel,
|
||||
nav,
|
||||
)
|
||||
}
|
||||
is PrivateDmEvent -> {
|
||||
RenderPrivateMessage(
|
||||
baseNote,
|
||||
@ -3464,6 +3480,211 @@ fun AudioHeader(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun RenderGitPatchEvent(
|
||||
baseNote: Note,
|
||||
makeItShort: Boolean,
|
||||
canPreview: Boolean,
|
||||
backgroundColor: MutableState<Color>,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
) {
|
||||
val event = baseNote.event as? GitPatchEvent ?: return
|
||||
|
||||
RenderGitPatchEvent(event, baseNote, makeItShort, canPreview, backgroundColor, accountViewModel, nav)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RenderShortRepositoryHeader(
|
||||
baseNote: AddressableNote,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
) {
|
||||
val noteState = baseNote.live().metadata.observeAsState()
|
||||
val note = remember(noteState) { noteState.value?.note } ?: return
|
||||
val noteEvent = note.event as? GitRepositoryEvent ?: return
|
||||
|
||||
Column(
|
||||
modifier = MaterialTheme.colorScheme.replyModifier.padding(10.dp),
|
||||
) {
|
||||
val title = remember(noteEvent) { noteEvent.name() ?: noteEvent.dTag() }
|
||||
Text(
|
||||
text = stringResource(id = R.string.git_repository, title),
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
|
||||
noteEvent.description()?.let {
|
||||
Spacer(modifier = DoubleVertSpacer)
|
||||
Text(
|
||||
text = it,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RenderGitPatchEvent(
|
||||
noteEvent: GitPatchEvent,
|
||||
note: Note,
|
||||
makeItShort: Boolean,
|
||||
canPreview: Boolean,
|
||||
backgroundColor: MutableState<Color>,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
) {
|
||||
val repository = remember(noteEvent) { noteEvent.repository() }
|
||||
|
||||
if (repository != null) {
|
||||
LoadAddressableNote(aTag = repository, accountViewModel = accountViewModel) {
|
||||
if (it != null) {
|
||||
RenderShortRepositoryHeader(it, accountViewModel, nav)
|
||||
Spacer(modifier = DoubleVertSpacer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LoadDecryptedContent(note, accountViewModel) { body ->
|
||||
val eventContent by
|
||||
remember(note.event) {
|
||||
derivedStateOf {
|
||||
val subject = (note.event as? TextNoteEvent)?.subject()?.ifEmpty { null }
|
||||
|
||||
if (!subject.isNullOrBlank() && !body.split("\n")[0].contains(subject)) {
|
||||
"### $subject\n$body"
|
||||
} else {
|
||||
body
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val isAuthorTheLoggedUser = remember(note.event) { accountViewModel.isLoggedUser(note.author) }
|
||||
|
||||
if (makeItShort && isAuthorTheLoggedUser) {
|
||||
Text(
|
||||
text = eventContent,
|
||||
color = MaterialTheme.colorScheme.placeholderText,
|
||||
maxLines = 2,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
} else {
|
||||
SensitivityWarning(
|
||||
note = note,
|
||||
accountViewModel = accountViewModel,
|
||||
) {
|
||||
val modifier = remember(note) { Modifier.fillMaxWidth() }
|
||||
val tags = remember(note) { note.event?.tags()?.toImmutableListOfLists() ?: EmptyTagList }
|
||||
|
||||
TranslatableRichTextViewer(
|
||||
content = eventContent,
|
||||
canPreview = canPreview && !makeItShort,
|
||||
modifier = modifier,
|
||||
tags = tags,
|
||||
backgroundColor = backgroundColor,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
)
|
||||
}
|
||||
|
||||
if (note.event?.hasHashtags() == true) {
|
||||
val hashtags =
|
||||
remember(note.event) { note.event?.hashtags()?.toImmutableList() ?: persistentListOf() }
|
||||
DisplayUncitedHashtags(hashtags, eventContent, nav)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun RenderGitRepositoryEvent(
|
||||
baseNote: Note,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
) {
|
||||
val event = baseNote.event as? GitRepositoryEvent ?: return
|
||||
|
||||
RenderGitRepositoryEvent(event, baseNote, accountViewModel, nav)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RenderGitRepositoryEvent(
|
||||
noteEvent: GitRepositoryEvent,
|
||||
note: Note,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
) {
|
||||
val title = remember(noteEvent) { noteEvent.name() ?: noteEvent.dTag() }
|
||||
val summary = remember(noteEvent) { noteEvent.description() }
|
||||
val web = remember(noteEvent) { noteEvent.web() }
|
||||
val clone = remember(noteEvent) { noteEvent.clone() }
|
||||
|
||||
Row(
|
||||
modifier =
|
||||
Modifier
|
||||
.clip(shape = QuoteBorder)
|
||||
.border(
|
||||
1.dp,
|
||||
MaterialTheme.colorScheme.subtleBorder,
|
||||
QuoteBorder,
|
||||
).padding(Size10dp),
|
||||
) {
|
||||
Column {
|
||||
Text(
|
||||
text = stringResource(id = R.string.git_repository, title),
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
|
||||
summary?.let {
|
||||
Text(
|
||||
text = it,
|
||||
modifier = Modifier.fillMaxWidth().padding(vertical = Size5dp),
|
||||
maxLines = 3,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
}
|
||||
|
||||
HorizontalDivider(thickness = DividerThickness)
|
||||
|
||||
web?.let {
|
||||
Row(Modifier.fillMaxWidth().padding(top = Size5dp)) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.git_web_address),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
Spacer(modifier = StdHorzSpacer)
|
||||
ClickableUrl(
|
||||
url = it,
|
||||
urlText = it.removePrefix("https://").removePrefix("http://"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
clone?.let {
|
||||
Row(Modifier.fillMaxWidth().padding(top = Size5dp)) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.git_clone_address),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
Spacer(modifier = StdHorzSpacer)
|
||||
ClickableUrl(
|
||||
url = it,
|
||||
urlText = it.removePrefix("https://").removePrefix("http://"),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun RenderLiveActivityEvent(
|
||||
baseNote: Note,
|
||||
|
@ -120,6 +120,8 @@ import com.vitorpamplona.amethyst.ui.note.NoteUsernameDisplay
|
||||
import com.vitorpamplona.amethyst.ui.note.ReactionsRow
|
||||
import com.vitorpamplona.amethyst.ui.note.RenderAppDefinition
|
||||
import com.vitorpamplona.amethyst.ui.note.RenderEmojiPack
|
||||
import com.vitorpamplona.amethyst.ui.note.RenderGitPatchEvent
|
||||
import com.vitorpamplona.amethyst.ui.note.RenderGitRepositoryEvent
|
||||
import com.vitorpamplona.amethyst.ui.note.RenderPinListEvent
|
||||
import com.vitorpamplona.amethyst.ui.note.RenderPoll
|
||||
import com.vitorpamplona.amethyst.ui.note.RenderPostApproval
|
||||
@ -157,6 +159,8 @@ import com.vitorpamplona.quartz.events.Event
|
||||
import com.vitorpamplona.quartz.events.FileHeaderEvent
|
||||
import com.vitorpamplona.quartz.events.FileStorageHeaderEvent
|
||||
import com.vitorpamplona.quartz.events.GenericRepostEvent
|
||||
import com.vitorpamplona.quartz.events.GitPatchEvent
|
||||
import com.vitorpamplona.quartz.events.GitRepositoryEvent
|
||||
import com.vitorpamplona.quartz.events.HighlightEvent
|
||||
import com.vitorpamplona.quartz.events.LongTextNoteEvent
|
||||
import com.vitorpamplona.quartz.events.PeopleListEvent
|
||||
@ -526,6 +530,10 @@ fun NoteMaster(
|
||||
accountViewModel,
|
||||
nav,
|
||||
)
|
||||
} else if (noteEvent is GitRepositoryEvent) {
|
||||
RenderGitRepositoryEvent(baseNote, accountViewModel, nav)
|
||||
} else if (noteEvent is GitPatchEvent) {
|
||||
RenderGitPatchEvent(baseNote, false, true, backgroundColor, accountViewModel, nav)
|
||||
} else if (noteEvent is AppDefinitionEvent) {
|
||||
RenderAppDefinition(baseNote, accountViewModel, nav)
|
||||
} else if (noteEvent is HighlightEvent) {
|
||||
|
@ -777,4 +777,7 @@
|
||||
<string name="max_limit">Max Limit</string>
|
||||
<string name="restricted_writes">Restricted Writes</string>
|
||||
<string name="forked_from">Forked from</string>
|
||||
<string name="git_repository">Git Repository: %1$s</string>
|
||||
<string name="git_web_address">Web:</string>
|
||||
<string name="git_clone_address">Clone:</string>
|
||||
</resources>
|
||||
|
@ -89,6 +89,10 @@ class EventFactory {
|
||||
FileStorageHeaderEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
GenericRepostEvent.KIND -> GenericRepostEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
GiftWrapEvent.KIND -> GiftWrapEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
GitIssueEvent.KIND -> GitIssueEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
GitReplyEvent.KIND -> GitReplyEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
GitPatchEvent.KIND -> GitPatchEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
GitRepositoryEvent.KIND -> GitRepositoryEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
GoalEvent.KIND -> GoalEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
HighlightEvent.KIND -> HighlightEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
HTTPAuthorizationEvent.KIND ->
|
||||
|
@ -0,0 +1,79 @@
|
||||
/**
|
||||
* 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.ATag
|
||||
import com.vitorpamplona.quartz.encoders.HexKey
|
||||
import com.vitorpamplona.quartz.signers.NostrSigner
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
|
||||
@Immutable
|
||||
class GitIssueEvent(
|
||||
id: HexKey,
|
||||
pubKey: HexKey,
|
||||
createdAt: Long,
|
||||
tags: Array<Array<String>>,
|
||||
content: String,
|
||||
sig: HexKey,
|
||||
) : BaseTextNoteEvent(id, pubKey, createdAt, KIND, tags, content, sig) {
|
||||
private fun innerRepository() =
|
||||
tags.firstOrNull { it.size > 3 && it[0] == "a" && it[3] == "root" }
|
||||
?: tags.firstOrNull { it.size > 1 && it[0] == "a" }
|
||||
|
||||
private fun repositoryHex() = innerRepository()?.getOrNull(1)
|
||||
|
||||
fun rootIssueOrPath() = tags.lastOrNull { it.size > 3 && it[0] == "e" && it[3] == "root" }?.get(1)
|
||||
|
||||
fun repository() =
|
||||
innerRepository()?.let {
|
||||
if (it.size > 1) {
|
||||
val aTagValue = it[1]
|
||||
val relay = it.getOrNull(2)
|
||||
|
||||
ATag.parse(aTagValue, relay)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val KIND = 1621
|
||||
const val ALT = "A Git Issue"
|
||||
|
||||
fun create(
|
||||
patch: String,
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
signer: NostrSigner,
|
||||
onReady: (GitIssueEvent) -> Unit,
|
||||
) {
|
||||
val content = patch
|
||||
val tags =
|
||||
mutableListOf(
|
||||
arrayOf<String>(),
|
||||
)
|
||||
|
||||
tags.add(arrayOf("alt", ALT))
|
||||
|
||||
signer.sign(createdAt, KIND, tags.toTypedArray(), content, onReady)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
/**
|
||||
* 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.ATag
|
||||
import com.vitorpamplona.quartz.encoders.HexKey
|
||||
import com.vitorpamplona.quartz.signers.NostrSigner
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
|
||||
@Immutable
|
||||
class GitPatchEvent(
|
||||
id: HexKey,
|
||||
pubKey: HexKey,
|
||||
createdAt: Long,
|
||||
tags: Array<Array<String>>,
|
||||
content: String,
|
||||
sig: HexKey,
|
||||
) : Event(id, pubKey, createdAt, KIND, tags, content, sig) {
|
||||
private fun innerRepository() =
|
||||
tags.firstOrNull { it.size > 3 && it[0] == "a" && it[3] == "root" }
|
||||
?: tags.firstOrNull { it.size > 1 && it[0] == "a" }
|
||||
|
||||
private fun repositoryHex() = innerRepository()?.getOrNull(1)
|
||||
|
||||
fun repository() =
|
||||
innerRepository()?.let {
|
||||
if (it.size > 1) {
|
||||
val aTagValue = it[1]
|
||||
val relay = it.getOrNull(2)
|
||||
|
||||
ATag.parse(aTagValue, relay)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun commit() = tags.firstOrNull { it.size > 1 && it[0] == "commit" }?.get(1)
|
||||
|
||||
fun parentCommit() = tags.firstOrNull { it.size > 1 && it[0] == "parent-commit" }?.get(1)
|
||||
|
||||
fun commitPGPSig() = tags.firstOrNull { it.size > 1 && it[0] == "commit-pgp-sig" }?.get(1)
|
||||
|
||||
fun committer() =
|
||||
tags.filter { it.size > 1 && it[0] == "committer" }?.mapNotNull {
|
||||
Committer(it.getOrNull(1), it.getOrNull(2), it.getOrNull(3), it.getOrNull(4))
|
||||
}
|
||||
|
||||
data class Committer(
|
||||
val name: String?,
|
||||
val email: String?,
|
||||
val timestamp: String?,
|
||||
val timezoneInMinutes: String?,
|
||||
)
|
||||
|
||||
companion object {
|
||||
const val KIND = 1617
|
||||
const val ALT = "A Git Patch"
|
||||
|
||||
fun create(
|
||||
patch: String,
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
signer: NostrSigner,
|
||||
onReady: (GitPatchEvent) -> Unit,
|
||||
) {
|
||||
val content = patch
|
||||
val tags =
|
||||
mutableListOf(
|
||||
arrayOf<String>(),
|
||||
)
|
||||
|
||||
tags.add(arrayOf("alt", ALT))
|
||||
|
||||
signer.sign(createdAt, KIND, tags.toTypedArray(), content, onReady)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
/**
|
||||
* 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.ATag
|
||||
import com.vitorpamplona.quartz.encoders.HexKey
|
||||
import com.vitorpamplona.quartz.signers.NostrSigner
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
|
||||
@Immutable
|
||||
class GitReplyEvent(
|
||||
id: HexKey,
|
||||
pubKey: HexKey,
|
||||
createdAt: Long,
|
||||
tags: Array<Array<String>>,
|
||||
content: String,
|
||||
sig: HexKey,
|
||||
) : BaseTextNoteEvent(id, pubKey, createdAt, KIND, tags, content, sig) {
|
||||
private fun innerRepository() =
|
||||
tags.firstOrNull { it.size > 3 && it[0] == "a" && it[3] == "root" }
|
||||
?: tags.firstOrNull { it.size > 1 && it[0] == "a" }
|
||||
|
||||
private fun repositoryHex() = innerRepository()?.getOrNull(1)
|
||||
|
||||
fun repository() =
|
||||
innerRepository()?.let {
|
||||
if (it.size > 1) {
|
||||
val aTagValue = it[1]
|
||||
val relay = it.getOrNull(2)
|
||||
|
||||
ATag.parse(aTagValue, relay)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun rootIssueOrPath() = tags.lastOrNull { it.size > 3 && it[0] == "e" && it[3] == "root" }?.get(1)
|
||||
|
||||
companion object {
|
||||
const val KIND = 1622
|
||||
const val ALT = "A Git Issue"
|
||||
|
||||
fun create(
|
||||
patch: String,
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
signer: NostrSigner,
|
||||
onReady: (GitReplyEvent) -> Unit,
|
||||
) {
|
||||
val content = patch
|
||||
val tags =
|
||||
mutableListOf(
|
||||
arrayOf<String>(),
|
||||
)
|
||||
|
||||
tags.add(arrayOf("alt", ALT))
|
||||
|
||||
signer.sign(createdAt, KIND, tags.toTypedArray(), content, onReady)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/**
|
||||
* 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 GitRepositoryEvent(
|
||||
id: HexKey,
|
||||
pubKey: HexKey,
|
||||
createdAt: Long,
|
||||
tags: Array<Array<String>>,
|
||||
content: String,
|
||||
sig: HexKey,
|
||||
) : BaseAddressableEvent(id, pubKey, createdAt, KIND, tags, content, sig) {
|
||||
fun name() = tags.firstOrNull { it.size > 1 && it[0] == "name" }?.get(1)
|
||||
|
||||
fun description() = tags.firstOrNull { it.size > 1 && it[0] == "description" }?.get(1)
|
||||
|
||||
fun web() = tags.firstOrNull { it.size > 1 && it[0] == "web" }?.get(1)
|
||||
|
||||
fun clone() = tags.firstOrNull { it.size > 1 && it[0] == "clone" }?.get(1)
|
||||
|
||||
companion object {
|
||||
const val KIND = 30617
|
||||
const val ALT = "Git Repository"
|
||||
|
||||
fun create(
|
||||
signer: NostrSigner,
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
onReady: (GitRepositoryEvent) -> Unit,
|
||||
) {
|
||||
val tags = mutableListOf<Array<String>>()
|
||||
tags.add(arrayOf("alt", ALT))
|
||||
signer.sign(createdAt, KIND, tags.toTypedArray(), "", onReady)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user