Adding Basic Git Rendering support.
This commit is contained in:
@@ -71,6 +71,10 @@ import com.vitorpamplona.quartz.events.FileStorageEvent
|
|||||||
import com.vitorpamplona.quartz.events.FileStorageHeaderEvent
|
import com.vitorpamplona.quartz.events.FileStorageHeaderEvent
|
||||||
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.GitPatchEvent
|
||||||
|
import com.vitorpamplona.quartz.events.GitReplyEvent
|
||||||
|
import com.vitorpamplona.quartz.events.GitRepositoryEvent
|
||||||
import com.vitorpamplona.quartz.events.HighlightEvent
|
import com.vitorpamplona.quartz.events.HighlightEvent
|
||||||
import com.vitorpamplona.quartz.events.LiveActivitiesChatMessageEvent
|
import com.vitorpamplona.quartz.events.LiveActivitiesChatMessageEvent
|
||||||
import com.vitorpamplona.quartz.events.LiveActivitiesEvent
|
import com.vitorpamplona.quartz.events.LiveActivitiesEvent
|
||||||
@@ -361,6 +365,87 @@ object LocalCache {
|
|||||||
refreshObservers(note)
|
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(
|
fun consume(
|
||||||
event: LongTextNoteEvent,
|
event: LongTextNoteEvent,
|
||||||
relay: Relay?,
|
relay: Relay?,
|
||||||
@@ -508,6 +593,13 @@ object LocalCache {
|
|||||||
consumeBaseReplaceable(event, relay)
|
consumeBaseReplaceable(event, relay)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun consume(
|
||||||
|
event: GitRepositoryEvent,
|
||||||
|
relay: Relay?,
|
||||||
|
) {
|
||||||
|
consumeBaseReplaceable(event, relay)
|
||||||
|
}
|
||||||
|
|
||||||
fun consume(
|
fun consume(
|
||||||
event: ChannelListEvent,
|
event: ChannelListEvent,
|
||||||
relay: Relay?,
|
relay: Relay?,
|
||||||
@@ -1847,6 +1939,10 @@ object LocalCache {
|
|||||||
is FileStorageEvent -> consume(event, relay)
|
is FileStorageEvent -> consume(event, relay)
|
||||||
is FileStorageHeaderEvent -> consume(event, relay)
|
is FileStorageHeaderEvent -> consume(event, relay)
|
||||||
is GiftWrapEvent -> 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 HighlightEvent -> consume(event, relay)
|
||||||
is LiveActivitiesEvent -> consume(event, relay)
|
is LiveActivitiesEvent -> consume(event, relay)
|
||||||
is LiveActivitiesChatMessageEvent -> 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.text.ClickableText
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material3.Divider
|
import androidx.compose.material3.Divider
|
||||||
|
import androidx.compose.material3.HorizontalDivider
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.LocalTextStyle
|
import androidx.compose.material3.LocalTextStyle
|
||||||
import androidx.compose.material3.MaterialTheme
|
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.FileHeaderEvent
|
||||||
import com.vitorpamplona.quartz.events.FileStorageHeaderEvent
|
import com.vitorpamplona.quartz.events.FileStorageHeaderEvent
|
||||||
import com.vitorpamplona.quartz.events.GenericRepostEvent
|
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.HighlightEvent
|
||||||
import com.vitorpamplona.quartz.events.LiveActivitiesChatMessageEvent
|
import com.vitorpamplona.quartz.events.LiveActivitiesChatMessageEvent
|
||||||
import com.vitorpamplona.quartz.events.LiveActivitiesEvent
|
import com.vitorpamplona.quartz.events.LiveActivitiesEvent
|
||||||
@@ -1182,6 +1185,19 @@ private fun RenderNoteRow(
|
|||||||
is LiveActivitiesEvent -> {
|
is LiveActivitiesEvent -> {
|
||||||
RenderLiveActivityEvent(baseNote, accountViewModel, nav)
|
RenderLiveActivityEvent(baseNote, accountViewModel, nav)
|
||||||
}
|
}
|
||||||
|
is GitRepositoryEvent -> {
|
||||||
|
RenderGitRepositoryEvent(baseNote, accountViewModel, nav)
|
||||||
|
}
|
||||||
|
is GitPatchEvent -> {
|
||||||
|
RenderGitPatchEvent(
|
||||||
|
baseNote,
|
||||||
|
makeItShort,
|
||||||
|
canPreview,
|
||||||
|
backgroundColor,
|
||||||
|
accountViewModel,
|
||||||
|
nav,
|
||||||
|
)
|
||||||
|
}
|
||||||
is PrivateDmEvent -> {
|
is PrivateDmEvent -> {
|
||||||
RenderPrivateMessage(
|
RenderPrivateMessage(
|
||||||
baseNote,
|
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
|
@Composable
|
||||||
fun RenderLiveActivityEvent(
|
fun RenderLiveActivityEvent(
|
||||||
baseNote: Note,
|
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.ReactionsRow
|
||||||
import com.vitorpamplona.amethyst.ui.note.RenderAppDefinition
|
import com.vitorpamplona.amethyst.ui.note.RenderAppDefinition
|
||||||
import com.vitorpamplona.amethyst.ui.note.RenderEmojiPack
|
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.RenderPinListEvent
|
||||||
import com.vitorpamplona.amethyst.ui.note.RenderPoll
|
import com.vitorpamplona.amethyst.ui.note.RenderPoll
|
||||||
import com.vitorpamplona.amethyst.ui.note.RenderPostApproval
|
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.FileHeaderEvent
|
||||||
import com.vitorpamplona.quartz.events.FileStorageHeaderEvent
|
import com.vitorpamplona.quartz.events.FileStorageHeaderEvent
|
||||||
import com.vitorpamplona.quartz.events.GenericRepostEvent
|
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.HighlightEvent
|
||||||
import com.vitorpamplona.quartz.events.LongTextNoteEvent
|
import com.vitorpamplona.quartz.events.LongTextNoteEvent
|
||||||
import com.vitorpamplona.quartz.events.PeopleListEvent
|
import com.vitorpamplona.quartz.events.PeopleListEvent
|
||||||
@@ -526,6 +530,10 @@ fun NoteMaster(
|
|||||||
accountViewModel,
|
accountViewModel,
|
||||||
nav,
|
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) {
|
} else if (noteEvent is AppDefinitionEvent) {
|
||||||
RenderAppDefinition(baseNote, accountViewModel, nav)
|
RenderAppDefinition(baseNote, accountViewModel, nav)
|
||||||
} else if (noteEvent is HighlightEvent) {
|
} else if (noteEvent is HighlightEvent) {
|
||||||
|
|||||||
@@ -777,4 +777,7 @@
|
|||||||
<string name="max_limit">Max Limit</string>
|
<string name="max_limit">Max Limit</string>
|
||||||
<string name="restricted_writes">Restricted Writes</string>
|
<string name="restricted_writes">Restricted Writes</string>
|
||||||
<string name="forked_from">Forked from</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>
|
</resources>
|
||||||
|
|||||||
@@ -89,6 +89,10 @@ class EventFactory {
|
|||||||
FileStorageHeaderEvent(id, pubKey, createdAt, tags, content, sig)
|
FileStorageHeaderEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
GenericRepostEvent.KIND -> GenericRepostEvent(id, pubKey, createdAt, tags, content, sig)
|
GenericRepostEvent.KIND -> GenericRepostEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
GiftWrapEvent.KIND -> GiftWrapEvent(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)
|
GoalEvent.KIND -> GoalEvent(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 ->
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user