Fixing the markdown for user mentions (#6)
This commit is contained in:
parent
cf575ab598
commit
8208981c66
|
|
@ -1,10 +1,10 @@
|
|||
name: Android CI
|
||||
name: Build Android APKs
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
buildReleaseAPK:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
|
@ -18,7 +18,6 @@ jobs:
|
|||
distribution: 'oracle'
|
||||
cache: gradle
|
||||
|
||||
|
||||
- name: Setup Android SDK
|
||||
uses: android-actions/setup-android@v2
|
||||
|
||||
|
|
@ -37,7 +36,7 @@ jobs:
|
|||
- name: Add revoltbuild.properties from the revoltbuildPropertiesbase64 secret
|
||||
run: echo "${{ secrets.REVOLTBUILD_PROPERTIES_BASE64 }}" | base64 --decode > revoltbuild.properties
|
||||
|
||||
- name: Build with Gradle
|
||||
- name: Build Release APK
|
||||
run: ./gradlew --no-daemon assembleRelease -x app:uploadSentryProguardMappingsRelease
|
||||
|
||||
- name: Archive release APK
|
||||
|
|
@ -46,4 +45,41 @@ jobs:
|
|||
name: release-apk
|
||||
retention-days: 5
|
||||
path: |
|
||||
app/build/outputs/apk/release/app-release.apk
|
||||
app/build/outputs/apk/release/app-release.apk
|
||||
|
||||
buildDebugAPK:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- name: set up JDK 21
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '21'
|
||||
distribution: 'oracle'
|
||||
cache: gradle
|
||||
|
||||
- name: Setup Android SDK
|
||||
uses: android-actions/setup-android@v2
|
||||
|
||||
- uses: denoland/setup-deno@v2
|
||||
with:
|
||||
# setting `cache-hash` implies `cache: true` and will replace
|
||||
# the default cache-hash of `${{ hashFiles('**/deno.lock') }}`
|
||||
cache-hash: ${{ hashFiles('**/deno.json') }}
|
||||
|
||||
- name: Set up repo
|
||||
run: chmod +x gradlew && deno run -A scripts/download_deps.ts --yes && cp revoltbuild.properties.example revoltbuild.properties && cp sentry.properties.example sentry.properties && cp app/google-services.json.example app/google-services.json && git submodule update --init --recursive
|
||||
|
||||
- name: Build Debug APK
|
||||
run: ./gradlew --no-daemon assembleDebug
|
||||
|
||||
- name: Archive debug APK
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: debug-apk
|
||||
retention-days: 5
|
||||
path: |
|
||||
app/build/outputs/apk/debug/app-debug.apk
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ android {
|
|||
minSdk = 24
|
||||
targetSdk = 36
|
||||
versionCode = Integer.parseInt("001_003_206".replace("_", ""), 10)
|
||||
versionName = "1.3.6bb-forked"
|
||||
versionName = "1.3.6bc-forked"
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables {
|
||||
|
|
|
|||
|
|
@ -156,18 +156,29 @@ val avatarPadding = 2.dp
|
|||
@JBM
|
||||
fun JBMRenderer(content: String, modifier: Modifier = Modifier) {
|
||||
val state = LocalJBMarkdownTreeState.current
|
||||
val flavor = if (state.enhanced) RSMEnhancedFlavourDescriptor() else RSMFlavourDescriptor()
|
||||
android.util.Log.d("JBMRenderer", "JBMRenderer called with content: '${content.take(50)}...', enhanced: ${state.enhanced}")
|
||||
|
||||
var tree by remember { mutableStateOf(JBMApi.parse(content, flavor)) }
|
||||
val preprocessedContent = content.replace(Regex("<@([0-9A-HJKMNP-TV-Z]{26})>")) { match ->
|
||||
"ZZUSERMENTION${match.groupValues[1]}ZZ"
|
||||
}
|
||||
android.util.Log.d("JBMRenderer", "Preprocessed content: '${preprocessedContent.take(50)}...'")
|
||||
|
||||
val flavor = if (state.enhanced) RSMEnhancedFlavourDescriptor() else RSMFlavourDescriptor()
|
||||
android.util.Log.d("JBMRenderer", "Using flavor: ${flavor.javaClass.simpleName}")
|
||||
|
||||
var tree by remember { mutableStateOf(JBMApi.parse(preprocessedContent, flavor)) }
|
||||
var revealedSpoilers by remember { mutableStateOf(setOf<String>()) }
|
||||
|
||||
LaunchedEffect(content, state.enhanced) {
|
||||
tree = JBMApi.parse(content, flavor)
|
||||
val preprocessedContent = content.replace(Regex("<@([0-9A-HJKMNP-TV-Z]{26})>")) { match ->
|
||||
"ZZUSERMENTION${match.groupValues[1]}ZZ"
|
||||
}
|
||||
tree = JBMApi.parse(preprocessedContent, flavor)
|
||||
}
|
||||
|
||||
CompositionLocalProvider(
|
||||
LocalJBMarkdownTreeState provides LocalJBMarkdownTreeState.current.copy(
|
||||
sourceText = content,
|
||||
sourceText = preprocessedContent,
|
||||
revealedSpoilers = revealedSpoilers,
|
||||
onSpoilerToggle = { spoilerId ->
|
||||
revealedSpoilers = if (revealedSpoilers.contains(spoilerId)) {
|
||||
|
|
@ -213,6 +224,7 @@ private fun annotateText(
|
|||
val sourceText = state.sourceText
|
||||
|
||||
return buildAnnotatedString {
|
||||
android.util.Log.d("JBMRenderer", "annotateText called with node type: ${node.type}")
|
||||
if (node.type.toString().contains("SPOILER", ignoreCase = true) ||
|
||||
sourceText.contains("||")) {
|
||||
android.util.Log.d("JBMRenderer", "Processing node: ${node.type}, text contains spoilers: ${sourceText.contains("||")}")
|
||||
|
|
@ -224,18 +236,67 @@ private fun annotateText(
|
|||
} else {
|
||||
node.getTextInNode(sourceText)
|
||||
}
|
||||
append(source)
|
||||
|
||||
val text = source.toString()
|
||||
val mentionRegex = Regex("(ZZUSERMENTION([0-9A-HJKMNP-TV-Z]{26})ZZ)")
|
||||
|
||||
android.util.Log.d("JBMRenderer", "Processing TEXT: '$text'")
|
||||
android.util.Log.d("JBMRenderer", "Contains mention: ${mentionRegex.containsMatchIn(text)}")
|
||||
|
||||
if (mentionRegex.containsMatchIn(text)) {
|
||||
android.util.Log.d("JBMRenderer", "Found mentions in text")
|
||||
var lastIndex = 0
|
||||
mentionRegex.findAll(text).forEach { match ->
|
||||
android.util.Log.d("JBMRenderer", "Match: '${match.value}', groups: ${match.groupValues}")
|
||||
|
||||
if (match.range.first > lastIndex) {
|
||||
append(text.substring(lastIndex, match.range.first))
|
||||
}
|
||||
|
||||
val userId = match.groupValues[2]
|
||||
android.util.Log.d("JBMRenderer", "Processing mention for userId: '$userId'")
|
||||
|
||||
pushStringAnnotation(
|
||||
tag = JBMAnnotations.UserMention.tag,
|
||||
annotation = userId
|
||||
)
|
||||
pushStyle(
|
||||
SpanStyle(
|
||||
color = state.colors.clickable,
|
||||
background = state.colors.clickableBackground
|
||||
)
|
||||
)
|
||||
append(" ")
|
||||
appendInlineContent(JBMAnnotations.UserAvatar.tag, userId)
|
||||
append(" ")
|
||||
append(MentionResolver.resolveUser(userId, state.currentServer))
|
||||
append(" ")
|
||||
pop()
|
||||
pop()
|
||||
|
||||
lastIndex = match.range.last + 1
|
||||
}
|
||||
|
||||
if (lastIndex < text.length) {
|
||||
append(text.substring(lastIndex))
|
||||
}
|
||||
} else {
|
||||
append(text)
|
||||
}
|
||||
}
|
||||
|
||||
RSMElementTypes.USER_MENTION -> {
|
||||
val contents = node.getTextInNode(sourceText).toString()
|
||||
android.util.Log.d("JBMRenderer", "Processing USER_MENTION: '$contents'")
|
||||
val userId = contents.removeSurrounding("<@", ">")
|
||||
android.util.Log.d("JBMRenderer", "Extracted userId: '$userId', isUlid: ${userId.isUlid()}")
|
||||
if (userId == contents || !userId.isUlid()) {
|
||||
// Invalid user mention. Append as if it were regular text.
|
||||
android.util.Log.d("JBMRenderer", "Invalid user mention, treating as text")
|
||||
for (child in node.children) {
|
||||
append(annotateText(state, child, revealedSpoilers))
|
||||
}
|
||||
} else {
|
||||
android.util.Log.d("JBMRenderer", "Valid user mention, resolving to: ${MentionResolver.resolveUser(userId, state.currentServer)}")
|
||||
pushStringAnnotation(
|
||||
tag = JBMAnnotations.UserMention.tag,
|
||||
annotation = userId
|
||||
|
|
@ -329,6 +390,22 @@ private fun annotateText(
|
|||
}
|
||||
}
|
||||
|
||||
RSMElementTypes.CUSTOM_EMOTE -> {
|
||||
val contents = node.getTextInNode(sourceText).toString()
|
||||
val emoteId = contents.removeSurrounding(":", ":")
|
||||
if (emoteId == contents || !emoteId.isUlid()) {
|
||||
for (child in node.children) {
|
||||
append(annotateText(state, child, revealedSpoilers))
|
||||
}
|
||||
} else {
|
||||
pushStringAnnotation(
|
||||
tag = JBMAnnotations.CustomEmote.tag,
|
||||
annotation = emoteId
|
||||
)
|
||||
appendInlineContent(JBMAnnotations.CustomEmote.tag, emoteId)
|
||||
pop()
|
||||
}
|
||||
}
|
||||
|
||||
RSMElementTypes.SPOILER -> {
|
||||
android.util.Log.d("JBMRenderer", "Found SPOILER node with ${node.children.size} children")
|
||||
|
|
@ -543,6 +620,7 @@ private fun annotateText(
|
|||
append(node.getTextInNode(sourceText))
|
||||
}
|
||||
|
||||
|
||||
else -> {
|
||||
withStyle(SpanStyle(color = Color.Cyan)) {
|
||||
append("[${node.type.name}]{\n")
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package chat.revolt.markdown.jbm
|
||||
|
||||
import chat.revolt.markdown.jbm.sequentialparsers.CustomEmoteParser
|
||||
import chat.revolt.markdown.jbm.sequentialparsers.SpoilerParser
|
||||
import org.intellij.markdown.parser.sequentialparsers.SequentialParser
|
||||
import org.intellij.markdown.parser.sequentialparsers.SequentialParserManager
|
||||
|
|
@ -14,7 +15,7 @@ class RSMEnhancedFlavourDescriptor : RSMFlavourDescriptor() {
|
|||
override fun getParserSequence(): List<SequentialParser> {
|
||||
val originalParsers = super@RSMEnhancedFlavourDescriptor.sequentialParserManager.getParserSequence()
|
||||
|
||||
return originalParsers + SpoilerParser()
|
||||
return originalParsers + CustomEmoteParser() + SpoilerParser()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -166,6 +166,8 @@ class ChatRouterViewModel @Inject constructor(
|
|||
val current = kvStorage.get("currentDestination")
|
||||
setSaveDestination(ChatRouterDestination.fromString(current ?: ""))
|
||||
|
||||
// Disabled for forked version might use later ;)
|
||||
/*
|
||||
latestChangelogRead = changelogs.hasSeenCurrent()
|
||||
latestChangelog = changelogs.getLatestChangelogCode()
|
||||
latestChangelogBody =
|
||||
|
|
@ -173,7 +175,12 @@ class ChatRouterViewModel @Inject constructor(
|
|||
if (!latestChangelogRead) {
|
||||
changelogs.markAsSeen()
|
||||
}
|
||||
*/
|
||||
// Always mark changelog as read to prevent popup
|
||||
latestChangelogRead = true
|
||||
|
||||
// Disabled for forked version
|
||||
/*
|
||||
val seenEarlyAccess = kvStorage.getBoolean("spark/earlyAccess/dismissed")
|
||||
val seenSwipeToReply = kvStorage.getBoolean("spark/swipeToReply/dismissed")
|
||||
if (seenEarlyAccess == null) {
|
||||
|
|
@ -186,6 +193,7 @@ class ChatRouterViewModel @Inject constructor(
|
|||
if (seenEarlyAccess == true && seenSwipeToReply != true) {
|
||||
showSwipeToReplySpark = true
|
||||
}
|
||||
*/
|
||||
|
||||
val hasNotificationPermission =
|
||||
NotificationManagerCompat.from(context).areNotificationsEnabled()
|
||||
|
|
|
|||
Loading…
Reference in New Issue