Merge pull request #3377 from vitorpamplona/claude/amethyst-git-notifications-rqfkux

Add Git pull request event rendering support (NIP-34)
This commit is contained in:
Vitor Pamplona
2026-06-26 10:53:30 -04:00
committed by GitHub
10 changed files with 404 additions and 123 deletions
@@ -72,6 +72,8 @@ import com.vitorpamplona.quartz.nip28PublicChat.message.ChannelMessageEvent
import com.vitorpamplona.quartz.nip30CustomEmoji.CustomEmoji
import com.vitorpamplona.quartz.nip34Git.issue.GitIssueEvent
import com.vitorpamplona.quartz.nip34Git.patch.GitPatchEvent
import com.vitorpamplona.quartz.nip34Git.pr.GitPullRequestEvent
import com.vitorpamplona.quartz.nip34Git.pr.GitPullRequestUpdateEvent
import com.vitorpamplona.quartz.nip54Wiki.WikiNoteEvent
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent
@@ -268,6 +270,8 @@ class EventNotificationConsumer(
is PollEvent,
is GitPatchEvent,
is GitIssueEvent,
is GitPullRequestEvent,
is GitPullRequestUpdateEvent,
is HighlightEvent,
is LongTextNoteEvent,
is WikiNoteEvent,
@@ -40,6 +40,8 @@ import com.vitorpamplona.quartz.nip25Reactions.ReactionEvent
import com.vitorpamplona.quartz.nip28PublicChat.message.ChannelMessageEvent
import com.vitorpamplona.quartz.nip34Git.issue.GitIssueEvent
import com.vitorpamplona.quartz.nip34Git.patch.GitPatchEvent
import com.vitorpamplona.quartz.nip34Git.pr.GitPullRequestEvent
import com.vitorpamplona.quartz.nip34Git.pr.GitPullRequestUpdateEvent
import com.vitorpamplona.quartz.nip34Git.reply.GitReplyEvent
import com.vitorpamplona.quartz.nip47WalletConnect.events.LnZapPaymentResponseEvent
import com.vitorpamplona.quartz.nip52Calendar.appt.day.CalendarDateSlotEvent
@@ -84,6 +86,8 @@ val NotificationsPerKeyKinds2 =
GitReplyEvent.KIND,
GitIssueEvent.KIND,
GitPatchEvent.KIND,
GitPullRequestEvent.KIND,
GitPullRequestUpdateEvent.KIND,
HighlightEvent.KIND,
CommentEvent.KIND,
CalendarDateSlotEvent.KIND,
@@ -138,6 +138,8 @@ import com.vitorpamplona.amethyst.ui.note.types.RenderFhirResource
import com.vitorpamplona.amethyst.ui.note.types.RenderFundraiser
import com.vitorpamplona.amethyst.ui.note.types.RenderGitIssueEvent
import com.vitorpamplona.amethyst.ui.note.types.RenderGitPatchEvent
import com.vitorpamplona.amethyst.ui.note.types.RenderGitPullRequestEvent
import com.vitorpamplona.amethyst.ui.note.types.RenderGitPullRequestUpdateEvent
import com.vitorpamplona.amethyst.ui.note.types.RenderGitRepositoryEvent
import com.vitorpamplona.amethyst.ui.note.types.RenderGoal
import com.vitorpamplona.amethyst.ui.note.types.RenderHighlight
@@ -264,6 +266,8 @@ import com.vitorpamplona.quartz.nip28PublicChat.message.ChannelMessageEvent
import com.vitorpamplona.quartz.nip30CustomEmoji.pack.EmojiPackEvent
import com.vitorpamplona.quartz.nip34Git.issue.GitIssueEvent
import com.vitorpamplona.quartz.nip34Git.patch.GitPatchEvent
import com.vitorpamplona.quartz.nip34Git.pr.GitPullRequestEvent
import com.vitorpamplona.quartz.nip34Git.pr.GitPullRequestUpdateEvent
import com.vitorpamplona.quartz.nip34Git.repository.GitRepositoryEvent
import com.vitorpamplona.quartz.nip35Torrents.TorrentCommentEvent
import com.vitorpamplona.quartz.nip35Torrents.TorrentEvent
@@ -1203,6 +1207,30 @@ private fun RenderNoteRow(
)
}
is GitPullRequestEvent -> {
RenderGitPullRequestEvent(
baseNote,
makeItShort,
canPreview,
quotesLeft,
backgroundColor,
accountViewModel,
nav,
)
}
is GitPullRequestUpdateEvent -> {
RenderGitPullRequestUpdateEvent(
baseNote,
makeItShort,
canPreview,
quotesLeft,
backgroundColor,
accountViewModel,
nav,
)
}
is PrivateDmEvent -> {
RenderPrivateMessage(
baseNote,
@@ -37,7 +37,6 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
@@ -79,10 +78,10 @@ import com.vitorpamplona.amethyst.ui.theme.grayText
import com.vitorpamplona.amethyst.ui.theme.placeholderText
import com.vitorpamplona.amethyst.ui.theme.subtleBorder
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.hasHashtags
import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
import com.vitorpamplona.quartz.nip14Subject.subject
import com.vitorpamplona.quartz.nip34Git.issue.GitIssueEvent
import com.vitorpamplona.quartz.nip34Git.patch.GitPatchEvent
import com.vitorpamplona.quartz.nip34Git.pr.GitPullRequestEvent
import com.vitorpamplona.quartz.nip34Git.pr.GitPullRequestUpdateEvent
import com.vitorpamplona.quartz.nip34Git.repository.GitRepositoryEvent
private val CardShape = QuoteBorder
@@ -141,19 +140,33 @@ private fun TypeChip(
text: String,
background: Color,
contentColor: Color,
symbol: MaterialSymbol? = null,
) {
Text(
text = text,
style = MaterialTheme.typography.labelMedium,
fontWeight = FontWeight.SemiBold,
color = contentColor,
maxLines = 1,
Row(
modifier =
Modifier
.clip(ChipShape)
.background(background)
.padding(horizontal = Size8dp, vertical = 2.dp),
)
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(Size5dp),
) {
symbol?.let {
Icon(
symbol = it,
contentDescription = null,
modifier = Modifier.size(14.dp),
tint = contentColor,
)
}
Text(
text = text,
style = MaterialTheme.typography.labelMedium,
fontWeight = FontWeight.SemiBold,
color = contentColor,
maxLines = 1,
)
}
}
@Composable
@@ -180,6 +193,119 @@ private fun LinkRow(
}
}
@Composable
private fun GitSubjectTitle(text: String) {
Spacer(modifier = StdVertSpacer)
Text(
text = text,
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.SemiBold,
color = MaterialTheme.colorScheme.onSurface,
overflow = TextOverflow.Ellipsis,
maxLines = 3,
)
}
/**
* A small icon + value line for a piece of git metadata such as a branch name,
* commit hash or merge base. [value] is shown verbatim; commit-like hashes are
* expected to be shortened by the caller via [shortCommit].
*/
@Composable
private fun GitMetaRow(
symbol: MaterialSymbol,
contentDescription: String?,
value: String,
) {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = LinkRowSpacing,
) {
Icon(
symbol = symbol,
contentDescription = contentDescription,
modifier = Modifier.size(Size16dp),
tint = MaterialTheme.colorScheme.grayText,
)
Text(
text = value,
style = MaterialTheme.typography.labelMedium.copy(fontSize = Font12SP),
color = MaterialTheme.colorScheme.grayText,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}
}
/** Shortens a 40-char git object id to its 7-char prefix for display. */
private fun String.shortCommit(): String = if (length > 7) take(7) else this
/**
* The shared markdown body used by patches, issues and pull requests: honors
* the collapsed [makeItShort] preview for the logged-in user's own posts and
* otherwise renders the full content with sensitivity warnings and uncited
* hashtags. The subject, when present, is rendered separately as a title by the
* caller, so it is not inlined here.
*/
@Composable
private fun GitMarkdownBody(
note: Note,
makeItShort: Boolean,
canPreview: Boolean,
quotesLeft: Int,
backgroundColor: MutableState<Color>,
accountViewModel: AccountViewModel,
nav: INav,
) {
LoadDecryptedContent(note, accountViewModel) { body ->
val isAuthorTheLoggedUser =
remember(note.event) { accountViewModel.isLoggedUser(note.author) }
if (makeItShort && isAuthorTheLoggedUser) {
Text(
text = body,
color = MaterialTheme.colorScheme.placeholderText,
maxLines = 2,
overflow = TextOverflow.Ellipsis,
)
} else {
val callbackUri = remember(note) { note.toNostrUri() }
SensitivityWarning(
note = note,
accountViewModel = accountViewModel,
) {
val tags = remember(note) { note.event?.tags?.toImmutableListOfLists() ?: EmptyTagList }
TranslatableRichTextViewer(
content = body,
canPreview = canPreview && !makeItShort,
quotesLeft = quotesLeft,
modifier = Modifier.fillMaxWidth(),
tags = tags,
backgroundColor = backgroundColor,
id = note.idHex,
callbackUri = callbackUri,
accountViewModel = accountViewModel,
nav = nav,
)
}
val event = note.event
if (event?.hasHashtags() == true) {
DisplayUncitedHashtags(
event = event,
content = body,
callbackUri = callbackUri,
accountViewModel = accountViewModel,
nav = nav,
)
}
}
}
}
@Composable
fun RenderGitPatchEvent(
baseNote: Note,
@@ -278,16 +404,6 @@ private fun RenderGitPatchEvent(
)
GitStatusPill(targetIdHex = note.idHex, defaultIfMissing = StatusKind.OPEN)
val commit = remember(noteEvent) { noteEvent.commit() }
commit?.takeIf { it.isNotBlank() }?.let { hash ->
Text(
text = hash.take(7),
style = MaterialTheme.typography.labelMedium.copy(fontSize = Font12SP),
color = MaterialTheme.colorScheme.grayText,
maxLines = 1,
)
}
}
val repository = remember(noteEvent) { noteEvent.repositoryAddress() }
@@ -300,66 +416,19 @@ private fun RenderGitPatchEvent(
}
}
val commit = remember(noteEvent) { noteEvent.commit()?.takeIf { it.isNotBlank() } }
if (commit != null) {
Spacer(modifier = StdVertSpacer)
GitMetaRow(
symbol = MaterialSymbols.Commit,
contentDescription = stringRes(id = R.string.git_commit),
value = commit.shortCommit(),
)
}
Spacer(modifier = HalfDoubleVertSpacer)
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 {
val callbackUri = remember(note) { note.toNostrUri() }
SensitivityWarning(
note = note,
accountViewModel = accountViewModel,
) {
val tags = remember(note) { note.event?.tags?.toImmutableListOfLists() ?: EmptyTagList }
TranslatableRichTextViewer(
content = eventContent,
canPreview = canPreview && !makeItShort,
quotesLeft = quotesLeft,
modifier = Modifier.fillMaxWidth(),
tags = tags,
backgroundColor = backgroundColor,
id = note.idHex,
callbackUri = callbackUri,
accountViewModel = accountViewModel,
nav = nav,
)
}
if (note.event?.hasHashtags() == true) {
DisplayUncitedHashtags(
event = noteEvent,
content = eventContent,
callbackUri = callbackUri,
accountViewModel = accountViewModel,
nav = nav,
)
}
}
}
GitMarkdownBody(note, makeItShort, canPreview, quotesLeft, backgroundColor, accountViewModel, nav)
}
}
@@ -412,6 +481,11 @@ private fun RenderGitIssueEvent(
GitStatusPill(targetIdHex = note.idHex, defaultIfMissing = StatusKind.OPEN)
}
val subject = remember(noteEvent) { noteEvent.subject()?.takeIf { it.isNotBlank() } }
if (subject != null) {
GitSubjectTitle(subject)
}
val repository = remember(noteEvent) { noteEvent.repositoryAddress() }
if (repository != null) {
Spacer(modifier = StdVertSpacer)
@@ -424,56 +498,204 @@ private fun RenderGitIssueEvent(
Spacer(modifier = HalfDoubleVertSpacer)
LoadDecryptedContent(note, accountViewModel) { body ->
val eventContent by
remember(note.event) {
derivedStateOf {
val subject = (note.event as? TextNoteEvent)?.subject()?.ifEmpty { null }
GitMarkdownBody(note, makeItShort, canPreview, quotesLeft, backgroundColor, accountViewModel, nav)
}
}
if (!subject.isNullOrBlank() && !body.split("\n")[0].contains(subject)) {
"### $subject\n$body"
} else {
body
}
}
@Composable
fun RenderGitPullRequestEvent(
baseNote: Note,
makeItShort: Boolean,
canPreview: Boolean,
quotesLeft: Int,
backgroundColor: MutableState<Color>,
accountViewModel: AccountViewModel,
nav: INav,
) {
val event = baseNote.event as? GitPullRequestEvent ?: return
RenderGitPullRequestEvent(
event,
baseNote,
makeItShort,
canPreview,
quotesLeft,
backgroundColor,
accountViewModel,
nav,
)
}
@Composable
private fun RenderGitPullRequestEvent(
noteEvent: GitPullRequestEvent,
note: Note,
makeItShort: Boolean,
canPreview: Boolean,
quotesLeft: Int,
backgroundColor: MutableState<Color>,
accountViewModel: AccountViewModel,
nav: INav,
) {
GitCardContainer {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = HeaderSpacing,
) {
TypeChip(
text = stringRes(id = R.string.kind_git_pr),
background = MaterialTheme.colorScheme.secondary.copy(alpha = 0.15f),
contentColor = MaterialTheme.colorScheme.secondary,
symbol = MaterialSymbols.CallMerge,
)
GitStatusPill(targetIdHex = note.idHex, defaultIfMissing = StatusKind.OPEN)
}
val subject = remember(noteEvent) { noteEvent.subject()?.takeIf { it.isNotBlank() } }
if (subject != null) {
GitSubjectTitle(subject)
}
val repository = remember(noteEvent) { noteEvent.repositoryAddress() }
if (repository != null) {
Spacer(modifier = StdVertSpacer)
LoadAddressableNote(repository, accountViewModel) {
if (it != null) {
RenderShortRepositoryHeader(it, accountViewModel, nav)
}
}
}
val isAuthorTheLoggedUser =
remember(note.event) { accountViewModel.isLoggedUser(note.author) }
val branch = remember(noteEvent) { noteEvent.branchName()?.takeIf { it.isNotBlank() } }
val currentCommit = remember(noteEvent) { noteEvent.currentCommit()?.takeIf { it.isNotBlank() } }
val mergeBase = remember(noteEvent) { noteEvent.mergeBase()?.takeIf { it.isNotBlank() } }
val cloneUrls = remember(noteEvent) { noteEvent.cloneUrls().filter { it.isNotBlank() } }
if (makeItShort && isAuthorTheLoggedUser) {
Text(
text = eventContent,
color = MaterialTheme.colorScheme.placeholderText,
maxLines = 2,
overflow = TextOverflow.Ellipsis,
)
} else {
val callbackUri = remember(note) { note.toNostrUri() }
if (branch != null || currentCommit != null || mergeBase != null) {
Spacer(modifier = StdVertSpacer)
Column(verticalArrangement = Arrangement.spacedBy(Size5dp)) {
branch?.let {
GitMetaRow(MaterialSymbols.AltRoute, stringRes(id = R.string.git_branch), it)
}
currentCommit?.let {
GitMetaRow(MaterialSymbols.Commit, stringRes(id = R.string.git_commit), it.shortCommit())
}
mergeBase?.let {
GitMetaRow(MaterialSymbols.CallMerge, stringRes(id = R.string.git_merge_base), it.shortCommit())
}
}
}
SensitivityWarning(
note = note,
accountViewModel = accountViewModel,
) {
val tags =
remember(note) { note.event?.tags?.toImmutableListOfLists() ?: EmptyTagList }
TranslatableRichTextViewer(
content = eventContent,
canPreview = canPreview && !makeItShort,
quotesLeft = quotesLeft,
modifier = Modifier.fillMaxWidth(),
tags = tags,
backgroundColor = backgroundColor,
id = note.idHex,
callbackUri = callbackUri,
accountViewModel = accountViewModel,
nav = nav,
if (cloneUrls.isNotEmpty()) {
Spacer(modifier = StdVertSpacer)
Column(verticalArrangement = Arrangement.spacedBy(Size5dp)) {
cloneUrls.forEach { url ->
LinkRow(
symbol = MaterialSymbols.CloudDownload,
contentDescription = stringRes(id = R.string.git_clone_address),
url = url,
)
}
}
}
if (note.event?.hasHashtags() == true) {
DisplayUncitedHashtags(noteEvent, eventContent, callbackUri, accountViewModel, nav)
Spacer(modifier = HalfDoubleVertSpacer)
GitMarkdownBody(note, makeItShort, canPreview, quotesLeft, backgroundColor, accountViewModel, nav)
}
}
@Composable
fun RenderGitPullRequestUpdateEvent(
baseNote: Note,
makeItShort: Boolean,
canPreview: Boolean,
quotesLeft: Int,
backgroundColor: MutableState<Color>,
accountViewModel: AccountViewModel,
nav: INav,
) {
val event = baseNote.event as? GitPullRequestUpdateEvent ?: return
RenderGitPullRequestUpdateEvent(
event,
baseNote,
makeItShort,
canPreview,
quotesLeft,
backgroundColor,
accountViewModel,
nav,
)
}
@Composable
private fun RenderGitPullRequestUpdateEvent(
noteEvent: GitPullRequestUpdateEvent,
note: Note,
makeItShort: Boolean,
canPreview: Boolean,
quotesLeft: Int,
backgroundColor: MutableState<Color>,
accountViewModel: AccountViewModel,
nav: INav,
) {
GitCardContainer {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = HeaderSpacing,
) {
TypeChip(
text = stringRes(id = R.string.kind_git_pr_update),
background = MaterialTheme.colorScheme.surfaceVariant,
contentColor = MaterialTheme.colorScheme.onSurfaceVariant,
symbol = MaterialSymbols.Sync,
)
}
val repository = remember(noteEvent) { noteEvent.repositoryAddress() }
if (repository != null) {
Spacer(modifier = StdVertSpacer)
LoadAddressableNote(repository, accountViewModel) {
if (it != null) {
RenderShortRepositoryHeader(it, accountViewModel, nav)
}
}
}
Spacer(modifier = HalfDoubleVertSpacer)
Text(
text = stringRes(id = R.string.git_pr_update_description),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.grayText,
)
val currentCommit = remember(noteEvent) { noteEvent.currentCommit()?.takeIf { it.isNotBlank() } }
val mergeBase = remember(noteEvent) { noteEvent.mergeBase()?.takeIf { it.isNotBlank() } }
val cloneUrls = remember(noteEvent) { noteEvent.cloneUrls().filter { it.isNotBlank() } }
if (currentCommit != null || mergeBase != null) {
Spacer(modifier = StdVertSpacer)
Column(verticalArrangement = Arrangement.spacedBy(Size5dp)) {
currentCommit?.let {
GitMetaRow(MaterialSymbols.Commit, stringRes(id = R.string.git_commit), it.shortCommit())
}
mergeBase?.let {
GitMetaRow(MaterialSymbols.CallMerge, stringRes(id = R.string.git_merge_base), it.shortCommit())
}
}
}
if (cloneUrls.isNotEmpty()) {
Spacer(modifier = StdVertSpacer)
Column(verticalArrangement = Arrangement.spacedBy(Size5dp)) {
cloneUrls.forEach { url ->
LinkRow(
symbol = MaterialSymbols.CloudDownload,
contentDescription = stringRes(id = R.string.git_clone_address),
url = url,
)
}
}
}
@@ -54,6 +54,8 @@ import com.vitorpamplona.quartz.nip25Reactions.ReactionEvent
import com.vitorpamplona.quartz.nip28PublicChat.message.ChannelMessageEvent
import com.vitorpamplona.quartz.nip34Git.issue.GitIssueEvent
import com.vitorpamplona.quartz.nip34Git.patch.GitPatchEvent
import com.vitorpamplona.quartz.nip34Git.pr.GitPullRequestEvent
import com.vitorpamplona.quartz.nip34Git.pr.GitPullRequestUpdateEvent
import com.vitorpamplona.quartz.nip52Calendar.appt.day.CalendarDateSlotEvent
import com.vitorpamplona.quartz.nip52Calendar.appt.time.CalendarTimeSlotEvent
import com.vitorpamplona.quartz.nip52Calendar.rsvp.CalendarRSVPEvent
@@ -128,6 +130,8 @@ class NotificationFeedFilter(
GenericRepostEvent.KIND,
GitIssueEvent.KIND,
GitPatchEvent.KIND,
GitPullRequestEvent.KIND,
GitPullRequestUpdateEvent.KIND,
HighlightEvent.KIND,
TextNoteEvent.KIND,
ReactionEvent.KIND,
@@ -205,7 +209,9 @@ class NotificationFeedFilter(
return true
}
if (event is GitIssueEvent || event is GitPatchEvent) {
if (event is GitIssueEvent || event is GitPatchEvent ||
event is GitPullRequestEvent || event is GitPullRequestUpdateEvent
) {
return true
}
@@ -169,6 +169,8 @@ import com.vitorpamplona.amethyst.ui.note.types.RenderFhirResource
import com.vitorpamplona.amethyst.ui.note.types.RenderFundraiser
import com.vitorpamplona.amethyst.ui.note.types.RenderGitIssueEvent
import com.vitorpamplona.amethyst.ui.note.types.RenderGitPatchEvent
import com.vitorpamplona.amethyst.ui.note.types.RenderGitPullRequestEvent
import com.vitorpamplona.amethyst.ui.note.types.RenderGitPullRequestUpdateEvent
import com.vitorpamplona.amethyst.ui.note.types.RenderGitRepositoryEvent
import com.vitorpamplona.amethyst.ui.note.types.RenderGoal
import com.vitorpamplona.amethyst.ui.note.types.RenderHighlight
@@ -279,6 +281,8 @@ import com.vitorpamplona.quartz.nip28PublicChat.message.ChannelMessageEvent
import com.vitorpamplona.quartz.nip30CustomEmoji.pack.EmojiPackEvent
import com.vitorpamplona.quartz.nip34Git.issue.GitIssueEvent
import com.vitorpamplona.quartz.nip34Git.patch.GitPatchEvent
import com.vitorpamplona.quartz.nip34Git.pr.GitPullRequestEvent
import com.vitorpamplona.quartz.nip34Git.pr.GitPullRequestUpdateEvent
import com.vitorpamplona.quartz.nip34Git.repository.GitRepositoryEvent
import com.vitorpamplona.quartz.nip35Torrents.TorrentCommentEvent
import com.vitorpamplona.quartz.nip35Torrents.TorrentEvent
@@ -926,6 +930,10 @@ private fun FullBleedNoteCompose(
RenderGitPatchEvent(baseNote, makeItShort = false, canPreview = true, quotesLeft = 3, backgroundColor = backgroundColor, accountViewModel = accountViewModel, nav = nav)
} else if (noteEvent is GitIssueEvent) {
RenderGitIssueEvent(baseNote, makeItShort = false, canPreview = true, quotesLeft = 3, backgroundColor = backgroundColor, accountViewModel = accountViewModel, nav = nav)
} else if (noteEvent is GitPullRequestEvent) {
RenderGitPullRequestEvent(baseNote, makeItShort = false, canPreview = true, quotesLeft = 3, backgroundColor = backgroundColor, accountViewModel = accountViewModel, nav = nav)
} else if (noteEvent is GitPullRequestUpdateEvent) {
RenderGitPullRequestUpdateEvent(baseNote, makeItShort = false, canPreview = true, quotesLeft = 3, backgroundColor = backgroundColor, accountViewModel = accountViewModel, nav = nav)
} else if (noteEvent is AppDefinitionEvent) {
RenderAppDefinition(baseNote, accountViewModel, nav)
} else if (noteEvent is AppRecommendationEvent) {
@@ -44,7 +44,7 @@
<string name="timestamp_pending_short">OTS : En attente</string>
<string name="request_deletion">Demande de suppression</string>
<string name="block_report">Bloquer / Signaler</string>
<string name="block_hide_user"><![CDATA[Bloquer et cacher l'utilisateur]]></string>
<string name="block_hide_user"><![CDATA[Bloquer et cacher l\'utilisateur]]></string>
<string name="report_spam_scam">Signaler Spam / Arnaque</string>
<string name="report_impersonation">Signaler une falsification d\'identité</string>
<string name="report_illegal_behaviour">Signaler un comportement illégal</string>
@@ -401,7 +401,7 @@
<string name="report_dialog_nudity">Nudité ou contenu graphique</string>
<string name="report_dialog_illegal">Comportement illégal</string>
<string name="report_dialog_blocking_a_user">Bloquer un utilisateur cachera son contenu dans votre application. Vos notes sont toujours visibles publiquement, y compris pour les personnes que vous bloquez. Les utilisateurs bloqués sont listés sur l\'écran Filtres de Sécurité.</string>
<string name="report_dialog_block_hide_user_btn"><![CDATA[Bloquer et Masquer l'Utilisateur]]></string>
<string name="report_dialog_block_hide_user_btn"><![CDATA[Bloquer et Masquer l\'Utilisateur]]></string>
<string name="report_dialog_report_btn">Signaler un Abus</string>
<string name="report_dialog_reminder_public">Tous les rapports publiés seront visibles publiquement.</string>
<string name="report_dialog_additional_reason_placeholder">Fournir un contexte optionnel supplémentaire sur votre signalement…</string>
+6
View File
@@ -2534,6 +2534,10 @@
<string name="forked_from">Forked from</string>
<string name="git_web_address">Web:</string>
<string name="git_clone_address">Clone:</string>
<string name="git_branch">Branch</string>
<string name="git_commit">Commit</string>
<string name="git_merge_base">Merge base</string>
<string name="git_pr_update_description">Updated the pull request to a new commit.</string>
<string name="git_status_open">Open</string>
<string name="git_status_merged">Merged</string>
<string name="git_status_closed">Closed</string>
@@ -2868,6 +2872,8 @@
<string name="kind_git_patch">Git Patch</string>
<string name="kind_git_repo">Git Repo</string>
<string name="kind_git_reply">Git Reply</string>
<string name="kind_git_pr">Pull Request</string>
<string name="kind_git_pr_update">PR Update</string>
<string name="kind_zap_goals">Zap Goals</string>
<string name="kind_hashtag_follows">Hashtag Follows</string>
<string name="kind_highlights">Highlights</string>
@@ -31,6 +31,7 @@ object MaterialSymbols {
val AddPhotoAlternate = MaterialSymbol("\uE43E")
val AddReaction = MaterialSymbol("\uE1D3")
val AlternateEmail = MaterialSymbol("\uE0E6")
val AltRoute = MaterialSymbol("\uF184")
val Apps = MaterialSymbol("\uE5C3")
val ArrowDownward = MaterialSymbol("\uE5DB")
val ArrowUpward = MaterialSymbol("\uE5D8")
@@ -52,6 +53,7 @@ object MaterialSymbols {
val CalendarMonth = MaterialSymbol("\uEBCC")
val Call = MaterialSymbol("\uF0D4")
val CallEnd = MaterialSymbol("\uF0BC")
val CallMerge = MaterialSymbol("\uE0B3")
val CameraAlt = MaterialSymbol("\uE412")
val CameraFront = MaterialSymbol("\uF2C9")
val CameraRear = MaterialSymbol("\uF2C8")
@@ -74,6 +76,7 @@ object MaterialSymbols {
val Code = MaterialSymbol("\uE86F")
val Collections = MaterialSymbol("\uE3D3")
val CollectionsBookmark = MaterialSymbol("\uE431")
val Commit = MaterialSymbol("\uEAF5")
val ContentCopy = MaterialSymbol("\uE14D")
val ContentPaste = MaterialSymbol("\uE14F")
val CurrencyBitcoin = MaterialSymbol("\uEBC5")