1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2026-08-22 08:56:30 +00:00

improvements in rich messages

This commit is contained in:
2026-08-17 23:30:37 +06:00
parent 8bee8982bb
commit 5755724569
10 changed files with 337 additions and 35 deletions

View File

@@ -56,7 +56,7 @@ class InputRichBlockTableRowBuilder {
fun cell(
align: RichBlockTableCellAlign,
valign: String,
valign: RichBlockTableCellVAlign,
colspan: Int? = null,
rowspan: Int? = null,
block: RichTextBuilder.() -> Unit
@@ -66,7 +66,7 @@ class InputRichBlockTableRowBuilder {
fun headerCell(
align: RichBlockTableCellAlign,
valign: String,
valign: RichBlockTableCellVAlign,
colspan: Int? = null,
rowspan: Int? = null,
block: RichTextBuilder.() -> Unit

View File

@@ -45,7 +45,7 @@ sealed interface RichBlockTableCell {
val colspan: Int?
val rowspan: Int?
val align: RichBlockTableCellAlign
val valign: String
val valign: RichBlockTableCellVAlign
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
@Serializable(Serializer::class)
@@ -59,7 +59,7 @@ sealed interface RichBlockTableCell {
@SerialName(alignField)
override val align: RichBlockTableCellAlign,
@SerialName(valignField)
override val valign: String
override val valign: RichBlockTableCellVAlign
) : RichBlockTableCell
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
@@ -74,7 +74,7 @@ sealed interface RichBlockTableCell {
@SerialName(alignField)
override val align: RichBlockTableCellAlign,
@SerialName(valignField)
override val valign: String
override val valign: RichBlockTableCellVAlign
) : RichBlockTableCell
object Serializer : KSerializer<RichBlockTableCell> {
@@ -92,7 +92,7 @@ sealed interface RichBlockTableCell {
@SerialName(alignField)
val align: RichBlockTableCellAlign,
@SerialName(valignField)
val valign: String
val valign: RichBlockTableCellVAlign
)
override val descriptor: SerialDescriptor = Surrogate.serializer().descriptor

View File

@@ -0,0 +1,52 @@
package dev.inmo.tgbotapi.types.rich
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.SerializationException
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
/** Vertical alignment of a [RichBlockTableCell]. */
@Serializable(RichBlockTableCellVAlign.Serializer::class)
sealed interface RichBlockTableCellVAlign {
val name: String
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
@Serializable(Serializer::class)
data object Top : RichBlockTableCellVAlign {
override val name: String = "top"
}
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
@Serializable(Serializer::class)
data object Middle : RichBlockTableCellVAlign {
override val name: String = "middle"
}
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
@Serializable(Serializer::class)
data object Bottom : RichBlockTableCellVAlign {
override val name: String = "bottom"
}
object Serializer : KSerializer<RichBlockTableCellVAlign> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor(
"RichBlockTableCellVAlign",
PrimitiveKind.STRING
)
override fun deserialize(decoder: Decoder): RichBlockTableCellVAlign = when (val name = decoder.decodeString()) {
Top.name -> Top
Middle.name -> Middle
Bottom.name -> Bottom
else -> throw SerializationException("Unknown RichBlockTableCell vertical alignment: $name")
}
override fun serialize(encoder: Encoder, value: RichBlockTableCellVAlign) {
encoder.encodeString(value.name)
}
}
}

View File

@@ -437,7 +437,7 @@ data class RichBlockTable(
cell.colspan?.let { append(" colspan=\"$it\"") }
cell.rowspan?.let { append(" rowspan=\"$it\"") }
append(" align=\"${cell.align.name}\"")
append(" valign=\"${cell.valign}\"")
append(" valign=\"${cell.valign.name}\"")
}
"<$tag$cellAttributes>${cell.text?.html ?: ""}</$tag>"
}

View File

@@ -84,12 +84,12 @@ class InputRichBlocksDslTest {
val blocks = buildInputRichBlocks {
table(isBordered = true, isStriped = false, caption = RichTextPlain("caption")) {
row {
headerCell(align = RichBlockTableCellAlign.Left, valign = "top", colspan = 2) {
headerCell(align = RichBlockTableCellAlign.Left, valign = RichBlockTableCellVAlign.Top, colspan = 2) {
bold("heading")
}
}
row {
cell(align = RichBlockTableCellAlign.Center, valign = "middle", rowspan = 2) {
cell(align = RichBlockTableCellAlign.Center, valign = RichBlockTableCellVAlign.Middle, rowspan = 2) {
plain("value")
}
}
@@ -105,7 +105,7 @@ class InputRichBlocksDslTest {
text = RichTextBold(RichTextPlain("heading")),
colspan = 2,
align = RichBlockTableCellAlign.Left,
valign = "top"
valign = RichBlockTableCellVAlign.Top
)
),
listOf(
@@ -113,7 +113,7 @@ class InputRichBlocksDslTest {
text = RichTextPlain("value"),
rowspan = 2,
align = RichBlockTableCellAlign.Center,
valign = "middle"
valign = RichBlockTableCellVAlign.Middle
)
)
),

View File

@@ -61,7 +61,7 @@ class InputRichMessageSerializationTest {
fun encodesTableReusingReceivedCellType() {
val table = InputRichBlockTable(
cells = listOf(
listOf(RichBlockTableCell.Header(RichTextPlain("h1"), align = RichBlockTableCellAlign.Left, valign = "top"))
listOf(RichBlockTableCell.Header(RichTextPlain("h1"), align = RichBlockTableCellAlign.Left, valign = RichBlockTableCellVAlign.Top))
)
)
val message = InputRichMessageBlocks(blocks = listOf(table))
@@ -69,13 +69,14 @@ class InputRichMessageSerializationTest {
val tableJson = json.encodeToJsonElement(InputRichMessage.serializer(), message).jsonObject["blocks"]!!.jsonArray[0].jsonObject
val cell = tableJson["cells"]!!.jsonArray[0].jsonArray[0].jsonObject
assertEquals("left", cell["align"]?.jsonPrimitive?.content)
assertEquals("top", cell["valign"]?.jsonPrimitive?.content)
assertEquals(true, cell["is_header"]?.jsonPrimitive?.boolean)
}
@Test
fun serializesTableCellVariantsWithSharedFlatShape() {
val header: RichBlockTableCell = RichBlockTableCell.Header(RichTextPlain("h"), align = RichBlockTableCellAlign.Left, valign = "top")
val regular: RichBlockTableCell = RichBlockTableCell.Regular(RichTextPlain("v"), align = RichBlockTableCellAlign.Right, valign = "bottom")
val header: RichBlockTableCell = RichBlockTableCell.Header(RichTextPlain("h"), align = RichBlockTableCellAlign.Left, valign = RichBlockTableCellVAlign.Top)
val regular: RichBlockTableCell = RichBlockTableCell.Regular(RichTextPlain("v"), align = RichBlockTableCellAlign.Right, valign = RichBlockTableCellVAlign.Bottom)
val headerElement = json.encodeToJsonElement(RichBlockTableCell.Serializer, header).jsonObject
val regularElement = json.encodeToJsonElement(RichBlockTableCell.Serializer, regular).jsonObject
@@ -108,6 +109,28 @@ class InputRichMessageSerializationTest {
}
}
@Test
fun serializesEveryTableCellVerticalAlignmentAsItsName() {
val alignments = listOf(
RichBlockTableCellVAlign.Top,
RichBlockTableCellVAlign.Middle,
RichBlockTableCellVAlign.Bottom
)
alignments.forEach { alignment ->
val encoded = json.encodeToString(RichBlockTableCellVAlign.Serializer, alignment)
assertEquals("\"${alignment.name}\"", encoded)
assertEquals(alignment, json.decodeFromString(RichBlockTableCellVAlign.Serializer, encoded))
}
}
@Test
fun rejectsUnknownTableCellVerticalAlignment() {
assertFailsWith<SerializationException> {
json.decodeFromString(RichBlockTableCellVAlign.Serializer, "\"baseline\"")
}
}
@Test
fun encodesPhotoBlockMedia() {
val photoBlock = InputRichBlockPhoto(TelegramMediaPhoto(FileId("photo_file_id")))

View File

@@ -108,12 +108,12 @@ class RichBlockFormattingTest {
val block = RichBlockTable(
listOf(
listOf(
RichBlockTableCell.Header(text = RichTextPlain("H1"), align = RichBlockTableCellAlign.Left, valign = "top"),
RichBlockTableCell.Header(text = RichTextPlain("H2"), align = RichBlockTableCellAlign.Center, valign = "top")
RichBlockTableCell.Header(text = RichTextPlain("H1"), align = RichBlockTableCellAlign.Left, valign = RichBlockTableCellVAlign.Top),
RichBlockTableCell.Header(text = RichTextPlain("H2"), align = RichBlockTableCellAlign.Center, valign = RichBlockTableCellVAlign.Top)
),
listOf(
RichBlockTableCell.Regular(text = RichTextPlain("a"), align = RichBlockTableCellAlign.Left, valign = "top"),
RichBlockTableCell.Regular(text = RichTextPlain("b"), align = RichBlockTableCellAlign.Center, valign = "top")
RichBlockTableCell.Regular(text = RichTextPlain("a"), align = RichBlockTableCellAlign.Left, valign = RichBlockTableCellVAlign.Top),
RichBlockTableCell.Regular(text = RichTextPlain("b"), align = RichBlockTableCellAlign.Center, valign = RichBlockTableCellVAlign.Top)
)
)
)