feat: experimental message sending time view
This commit is contained in:
parent
c7e5795ca9
commit
56d1c4ff57
|
|
@ -88,4 +88,25 @@ object ULID {
|
||||||
fun makeNext(): String {
|
fun makeNext(): String {
|
||||||
return makeSpecial(System.currentTimeMillis(), fetchEntropy())
|
return makeSpecial(System.currentTimeMillis(), fetchEntropy())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun asTimestamp(ulid: String): Long {
|
||||||
|
if (ulid.length != len) {
|
||||||
|
throw IllegalArgumentException("ULID must be exactly $len characters")
|
||||||
|
}
|
||||||
|
|
||||||
|
var timestamp = 0L
|
||||||
|
|
||||||
|
for (i in 0..9) {
|
||||||
|
val char = ulid[i]
|
||||||
|
val value = b32chars.indexOf(char)
|
||||||
|
|
||||||
|
if (value == -1) {
|
||||||
|
throw IllegalArgumentException("Invalid character '$char' at position $i")
|
||||||
|
}
|
||||||
|
|
||||||
|
timestamp = timestamp or (value.toLong() shl (9 - i) * 5)
|
||||||
|
}
|
||||||
|
|
||||||
|
return timestamp
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -21,7 +21,7 @@ data class ServerUserChoice(
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Member(
|
data class Member(
|
||||||
@SerialName("_id")
|
@SerialName("_id")
|
||||||
val id: ServerUserChoice? = null,
|
val id: ServerUserChoice,
|
||||||
|
|
||||||
@SerialName("joined_at")
|
@SerialName("joined_at")
|
||||||
val joinedAt: String? = null,
|
val joinedAt: String? = null,
|
||||||
|
|
|
||||||
|
|
@ -10,15 +10,19 @@ import androidx.compose.material3.CircularProgressIndicator
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
import chat.revolt.api.REVOLT_BASE
|
import chat.revolt.api.REVOLT_BASE
|
||||||
import chat.revolt.api.REVOLT_FILES
|
import chat.revolt.api.REVOLT_FILES
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.revolt.api.RevoltAPI
|
||||||
|
import chat.revolt.api.internals.ULID
|
||||||
import chat.revolt.api.schemas.AutumnResource
|
import chat.revolt.api.schemas.AutumnResource
|
||||||
import chat.revolt.components.generic.RemoteImage
|
import chat.revolt.components.generic.RemoteImage
|
||||||
import chat.revolt.api.schemas.Message as MessageSchema
|
import chat.revolt.api.schemas.Message as MessageSchema
|
||||||
|
|
@ -33,6 +37,15 @@ fun viewAttachmentInBrowser(ctx: android.content.Context, attachment: AutumnReso
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun formatLongAsTime(time: Long): String {
|
||||||
|
// TODO: look into using a library like kotlinx.datetime
|
||||||
|
val date = java.util.Date(time)
|
||||||
|
val format =
|
||||||
|
java.text.SimpleDateFormat("dd.MM.yyyy HH:mm:ss", java.util.Locale.getDefault())
|
||||||
|
return format.format(date)
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun Message(
|
fun Message(
|
||||||
message: MessageSchema
|
message: MessageSchema
|
||||||
|
|
@ -47,6 +60,7 @@ fun Message(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(50.dp)
|
.size(50.dp)
|
||||||
.clip(CircleShape),
|
.clip(CircleShape),
|
||||||
|
crossfade = false,
|
||||||
description = "Avatar for ${author.username}"
|
description = "Avatar for ${author.username}"
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -55,17 +69,31 @@ fun Message(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(50.dp)
|
.size(50.dp)
|
||||||
.clip(CircleShape),
|
.clip(CircleShape),
|
||||||
|
crossfade = false,
|
||||||
description = "Avatar for ${author.username}"
|
description = "Avatar for ${author.username}"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Column(modifier = Modifier.padding(start = 10.dp)) {
|
Column(modifier = Modifier.padding(start = 10.dp)) {
|
||||||
author.username?.let {
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
author.username?.let {
|
||||||
|
Text(
|
||||||
|
text = it,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.width(5.dp))
|
||||||
Text(
|
Text(
|
||||||
text = it,
|
text = formatLongAsTime(ULID.asTimestamp(message.id!!)),
|
||||||
fontWeight = FontWeight.Bold
|
fontSize = 12.sp,
|
||||||
|
color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.5f),
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
message.content?.let {
|
message.content?.let {
|
||||||
Text(
|
Text(
|
||||||
text = it
|
text = it
|
||||||
|
|
@ -86,6 +114,7 @@ fun Message(
|
||||||
width = attachment.metadata.width?.toInt() ?: 0,
|
width = attachment.metadata.width?.toInt() ?: 0,
|
||||||
height = attachment.metadata.height?.toInt() ?: 0,
|
height = attachment.metadata.height?.toInt() ?: 0,
|
||||||
contentScale = ContentScale.Fit,
|
contentScale = ContentScale.Fit,
|
||||||
|
crossfade = true,
|
||||||
description = "Attached image ${attachment.filename}"
|
description = "Attached image ${attachment.filename}"
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue