Compare commits

...

8 Commits

Author SHA1 Message Date
Vitor Pamplona
1d5ff5bea9 v0.49.2 2023-05-16 10:24:45 -04:00
Vitor Pamplona
1767d4a3a3 Enabling a log to help NIP95 relay developers track what the app is doing with their images. 2023-05-16 10:24:05 -04:00
Vitor Pamplona
f2d87b78b1 Fixing emoji's on chat handles 2023-05-16 10:12:31 -04:00
Vitor Pamplona
4bf76d1b79 v0.49.1 2023-05-16 09:47:18 -04:00
Vitor Pamplona
17fbf8c01f BugFix for incorrect caching of NIP95 2023-05-16 09:47:10 -04:00
Vitor Pamplona
332490376b Adjustments to Markdown detection and rendering. 2023-05-16 08:52:59 -04:00
Vitor Pamplona
14e670cd9a Avoid color-filtering the emoji 2023-05-16 08:32:25 -04:00
Vitor Pamplona
d29e6b4d0b Better shade for Pins 2023-05-16 08:32:03 -04:00
6 changed files with 104 additions and 97 deletions

View File

@@ -13,8 +13,8 @@ android {
applicationId "com.vitorpamplona.amethyst"
minSdk 26
targetSdk 33
versionCode 163
versionName "0.49.0"
versionCode 165
versionName "0.49.2"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {

View File

@@ -1,7 +1,6 @@
package com.vitorpamplona.amethyst.model
import android.util.Log
import androidx.core.net.toUri
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.vitorpamplona.amethyst.Amethyst
@@ -763,19 +762,18 @@ object LocalCache {
note.addRelay(relay)
}
val file = File(Amethyst.instance.applicationContext.externalCacheDir, "NIP95")
if (!file.exists()) {
try {
val cachePath = File(Amethyst.instance.applicationContext.externalCacheDir, "NIP95")
cachePath.mkdirs()
val stream = FileOutputStream(File(cachePath, event.id))
try {
val cachePath = File(Amethyst.instance.applicationContext.externalCacheDir, "NIP95")
cachePath.mkdirs()
val file = File(cachePath, event.id)
if (!file.exists()) {
val stream = FileOutputStream(file)
stream.write(event.decode())
stream.close()
Log.e("EventLogger", "Saved to disk as ${File(cachePath, event.id).toUri()}")
} catch (e: IOException) {
Log.e("FileSotrageEvent", "FileStorageEvent save to disk error: " + event.id, e)
Log.i("FileStorageEvent", "NIP95 File received from ${relay?.url} and saved to disk as $file")
}
} catch (e: IOException) {
Log.e("FileStorageEvent", "FileStorageEvent save to disk error: " + event.id, e)
}
// Already processed this event.

View File

@@ -21,7 +21,6 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.takeOrElse
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.text.AnnotatedString
@@ -90,31 +89,31 @@ private fun DisplayEvent(
if (note.event is ChannelCreateEvent) {
CreateClickableText(
note.idDisplayNote(),
"${nip19.additionalChars} ",
"Channel/${nip19.hex}",
navController
clickablePart = "@${note.idDisplayNote()}",
suffix = "${nip19.additionalChars} ",
route = "Channel/${nip19.hex}",
navController = navController
)
} else if (note.event is PrivateDmEvent) {
CreateClickableText(
note.idDisplayNote(),
"${nip19.additionalChars} ",
"Room/${note.author?.pubkeyHex}",
navController
clickablePart = "@${note.idDisplayNote()}",
suffix = "${nip19.additionalChars} ",
route = "Room/${note.author?.pubkeyHex}",
navController = navController
)
} else if (channel != null) {
CreateClickableText(
channel.toBestDisplayName(),
"${nip19.additionalChars} ",
"Channel/${note.channel()?.idHex}",
navController
clickablePart = channel.toBestDisplayName(),
suffix = "${nip19.additionalChars} ",
route = "Channel/${note.channel()?.idHex}",
navController = navController
)
} else {
CreateClickableText(
note.idDisplayNote(),
"${nip19.additionalChars} ",
"Event/${nip19.hex}",
navController
clickablePart = "@${note.idDisplayNote()}",
suffix = "${nip19.additionalChars} ",
route = "Event/${nip19.hex}",
navController = navController
)
}
}
@@ -146,31 +145,31 @@ private fun DisplayNote(
if (note.event is ChannelCreateEvent) {
CreateClickableText(
note.idDisplayNote(),
"${nip19.additionalChars} ",
"Channel/${nip19.hex}",
navController
clickablePart = "@${note.idDisplayNote()}",
suffix = "${nip19.additionalChars} ",
route = "Channel/${nip19.hex}",
navController = navController
)
} else if (note.event is PrivateDmEvent) {
CreateClickableText(
note.idDisplayNote(),
"${nip19.additionalChars} ",
"Room/${note.author?.pubkeyHex}",
navController
clickablePart = "@${note.idDisplayNote()}",
suffix = "${nip19.additionalChars} ",
route = "Room/${note.author?.pubkeyHex}",
navController = navController
)
} else if (channel != null) {
CreateClickableText(
channel.toBestDisplayName(),
"${nip19.additionalChars} ",
"Channel/${note.channel()?.idHex}",
navController
clickablePart = channel.toBestDisplayName(),
suffix = "${nip19.additionalChars} ",
route = "Channel/${note.channel()?.idHex}",
navController = navController
)
} else {
CreateClickableText(
note.idDisplayNote(),
"${nip19.additionalChars} ",
"Note/${nip19.hex}",
navController
clickablePart = "@${note.idDisplayNote()}",
suffix = "${nip19.additionalChars} ",
route = "Note/${nip19.hex}",
navController = navController
)
}
}
@@ -200,10 +199,10 @@ private fun DisplayAddress(
val note = noteState?.note ?: return
CreateClickableText(
note.idDisplayNote(),
"${nip19.additionalChars} ",
"Note/${nip19.hex}",
navController
clickablePart = "@${note.idDisplayNote()}",
suffix = "${nip19.additionalChars} ",
route = "Note/${nip19.hex}",
navController = navController
)
}
@@ -252,16 +251,23 @@ private fun DisplayUser(
}
@Composable
fun CreateClickableText(clickablePart: String, suffix: String, route: String, navController: NavController) {
fun CreateClickableText(
clickablePart: String,
suffix: String,
overrideColor: Color? = null,
fontWeight: FontWeight = FontWeight.Normal,
route: String,
navController: NavController
) {
ClickableText(
text = buildAnnotatedString {
withStyle(
LocalTextStyle.current.copy(color = MaterialTheme.colors.primary).toSpanStyle()
LocalTextStyle.current.copy(color = overrideColor ?: MaterialTheme.colors.primary, fontWeight = fontWeight).toSpanStyle()
) {
append("@$clickablePart")
append(clickablePart)
}
withStyle(
LocalTextStyle.current.copy(color = MaterialTheme.colors.onBackground).toSpanStyle()
LocalTextStyle.current.copy(color = overrideColor ?: MaterialTheme.colors.onBackground, fontWeight = fontWeight).toSpanStyle()
) {
append(suffix)
}
@@ -369,6 +375,7 @@ fun CreateClickableTextWithEmoji(
clickablePart: String,
suffix: String,
tags: List<List<String>>?,
overrideColor: Color? = null,
fontWeight: FontWeight = FontWeight.Normal,
route: String,
navController: NavController
@@ -378,13 +385,13 @@ fun CreateClickableTextWithEmoji(
}
if (emojis.isEmpty()) {
CreateClickableText(clickablePart, suffix, route, navController)
CreateClickableText(clickablePart, suffix, overrideColor, fontWeight, route, navController)
} else {
val myList = remember {
assembleAnnotatedList(clickablePart, emojis)
}
ClickableInLineIconRenderer(myList, LocalTextStyle.current.copy(color = MaterialTheme.colors.primary, fontWeight = fontWeight).toSpanStyle()) {
ClickableInLineIconRenderer(myList, LocalTextStyle.current.copy(color = overrideColor ?: MaterialTheme.colors.primary, fontWeight = fontWeight).toSpanStyle()) {
navController.navigate(route)
}
@@ -392,7 +399,7 @@ fun CreateClickableTextWithEmoji(
assembleAnnotatedList(suffix, emojis)
}
InLineIconRenderer(myList2, LocalTextStyle.current.copy(color = MaterialTheme.colors.onBackground, fontWeight = fontWeight).toSpanStyle())
InLineIconRenderer(myList2, LocalTextStyle.current.copy(color = overrideColor ?: MaterialTheme.colors.onBackground, fontWeight = fontWeight).toSpanStyle())
}
}
@@ -427,8 +434,7 @@ fun ClickableInLineIconRenderer(wordsInOrder: List<Renderable>, style: SpanStyle
AsyncImage(
model = value.url,
contentDescription = null,
modifier = Modifier.fillMaxSize().padding(1.dp),
colorFilter = ColorFilter.tint(style.color)
modifier = Modifier.fillMaxSize().padding(1.dp)
)
}
)
@@ -492,8 +498,7 @@ fun InLineIconRenderer(
AsyncImage(
model = value.url,
contentDescription = null,
modifier = Modifier.fillMaxSize().padding(1.dp),
colorFilter = ColorFilter.tint(style.color)
modifier = Modifier.fillMaxSize().padding(1.dp)
)
}
)

View File

@@ -81,7 +81,8 @@ fun isMarkdown(content: String): Boolean {
content.startsWith("# ") ||
content.contains("##") ||
content.contains("__") ||
content.contains("```")
content.contains("```") ||
content.contains("](")
}
@Composable
@@ -413,7 +414,7 @@ private fun RenderContentAsMarkdown(content: String, backgroundColor: Color) {
private fun getDisplayNameFromNip19(nip19: Nip19.Return): String? {
if (nip19.type == Nip19.Type.USER) {
return LocalCache.users[nip19.hex]?.bestDisplayName()
return LocalCache.users[nip19.hex]?.toBestDisplayName()
} else if (nip19.type == Nip19.Type.NOTE) {
return LocalCache.notes[nip19.hex]?.idDisplayNote()
} else if (nip19.type == Nip19.Type.ADDRESS) {

View File

@@ -225,6 +225,7 @@ fun ChatroomMessageCompose(
suffix = "",
tags = author.info?.latestMetadata?.tags,
fontWeight = FontWeight.Bold,
overrideColor = MaterialTheme.colors.onBackground,
route = "User/${author.pubkeyHex}",
navController = navController
)

View File

@@ -942,7 +942,7 @@ fun PinListHeader(
Icon(
imageVector = Icons.Default.PushPin,
contentDescription = null,
tint = MaterialTheme.colors.onBackground.copy(0.12f),
tint = MaterialTheme.colors.onBackground.copy(0.32f),
modifier = Modifier.size(15.dp)
)
@@ -1657,45 +1657,47 @@ fun FileStorageHeaderDisplay(baseNote: Note) {
}
}
val noteState = fileNote?.live()?.metadata?.observeAsState()
val note = noteState?.value?.note
fileNote?.let { fileNote2 ->
val noteState by fileNote2.live().metadata.observeAsState()
val note = remember(noteState) { noteState?.note }
var content by remember { mutableStateOf<ZoomableContent?>(null) }
var content by remember { mutableStateOf<ZoomableContent?>(null) }
LaunchedEffect(key1 = eventHeader.id, key2 = noteState, key3 = note?.event) {
withContext(Dispatchers.IO) {
val uri = "nostr:" + baseNote.toNEvent()
val localDir = note?.idHex?.let { File(File(appContext.externalCacheDir, "NIP95"), it) }
val blurHash = eventHeader.blurhash()
val dimensions = eventHeader.dimensions()
val description = eventHeader.content
val mimeType = eventHeader.mimeType()
LaunchedEffect(key1 = eventHeader.id, key2 = noteState, key3 = note?.event) {
withContext(Dispatchers.IO) {
val uri = "nostr:" + baseNote.toNEvent()
val localDir = note?.idHex?.let { File(File(appContext.externalCacheDir, "NIP95"), it) }
val blurHash = eventHeader.blurhash()
val dimensions = eventHeader.dimensions()
val description = eventHeader.content
val mimeType = eventHeader.mimeType()
content = if (mimeType?.startsWith("image") == true) {
ZoomableLocalImage(
localFile = localDir,
mimeType = mimeType,
description = description,
blurhash = blurHash,
dim = dimensions,
isVerified = true,
uri = uri
)
} else {
ZoomableLocalVideo(
localFile = localDir,
mimeType = mimeType,
description = description,
dim = dimensions,
isVerified = true,
uri = uri
)
content = if (mimeType?.startsWith("image") == true) {
ZoomableLocalImage(
localFile = localDir,
mimeType = mimeType,
description = description,
blurhash = blurHash,
dim = dimensions,
isVerified = true,
uri = uri
)
} else {
ZoomableLocalVideo(
localFile = localDir,
mimeType = mimeType,
description = description,
dim = dimensions,
isVerified = true,
uri = uri
)
}
}
}
}
content?.let {
ZoomableContentView(content = it, listOf(it))
content?.let {
ZoomableContentView(content = it, listOf(it))
}
}
}