diff --git a/.sol-migration-run-20260817T110101Z/inventory/logical-branches.txt b/.sol-migration-run-20260817T110101Z/inventory/logical-branches.txt new file mode 100644 index 0000000000..c479c188e8 --- /dev/null +++ b/.sol-migration-run-20260817T110101Z/inventory/logical-branches.txt @@ -0,0 +1,402 @@ +0.12.1 +0.12.2 +0.12.3 +0.12.4 +0.12.5 +0.12.6 +0.12.7 +0.13.0 +0.13.1 +0.14.0 +0.14.1 +0.15.0 +0.16.0 +0.16.1 +0.17.0 +0.18.0 +0.18.1 +0.19.0 +0.2.2 +0.20.0 +0.20.1 +0.20.4 +0.21.0 +0.22.0 +0.22.1 +0.22.2 +0.23.0 +0.23.1 +0.23.3 +0.23.4 +0.24.0 +0.24.1 +0.25.0 +0.25.1 +0.25.2 +0.26.0 +0.26.1 +0.26.2 +0.26.3 +0.26.4 +0.27.0 +0.27.1 +0.27.10 +0.27.11 +0.27.2 +0.27.3 +0.27.4 +0.27.5 +0.27.6 +0.27.7 +0.27.8 +0.27.9 +0.28.0 +0.28.0-rc +0.28.1 +0.28.2 +0.28.3 +0.28.4 +0.28.5 +0.29.0 +0.29.1 +0.29.2 +0.29.3 +0.29.4 +0.29.5 +0.3.12 +0.30.0 +0.30.1 +0.30.10 +0.30.11 +0.30.12 +0.30.13 +0.30.2 +0.30.3 +0.30.4 +0.30.5 +0.30.6 +0.30.7 +0.30.8 +0.30.9 +0.31.0 +0.31.1 +0.32.0 +0.32.1 +0.32.10 +0.32.2 +0.32.3 +0.32.4 +0.32.5 +0.32.6 +0.32.7 +0.32.8 +0.32.9 +0.33.0 +0.33.1 +0.33.2 +0.33.3 +0.33.4 +0.34.0 +0.34.1 +0.35.0 +0.35.1 +0.35.2 +0.35.3 +0.35.4 +0.35.5 +0.35.6 +0.35.7 +0.35.8 +0.35.9 +0.36.0 +0.36.1 +0.36.2 +0.37.0 +0.37.1 +0.37.2 +0.37.3 +0.37.4 +0.38.0 +0.38.1 +0.38.10 +0.38.11 +0.38.12 +0.38.13 +0.38.14 +0.38.15 +0.38.16 +0.38.17 +0.38.18 +0.38.19 +0.38.2 +0.38.20 +0.38.21 +0.38.22 +0.38.23 +0.38.3 +0.38.33 +0.38.4 +0.38.5 +0.38.6 +0.38.7 +0.38.8 +0.38.9 +0.39.0 +0.5.1 +1.0.0 +1.0.1 +1.1.0 +1.1.1 +1.1.2 +1.1.3 +1.1.4 +1.2.0 +10.0.0 +10.0.1 +10.1.0 +10.1.1 +10.1.2 +11.0.0 +12.0.0 +12.0.1 +12.1.0 +13.0.0 +13.1.0 +14.0.0 +14.0.1 +14.0.2 +14.1.0 +15.0.0 +15.1.0 +15.1.1 +15.2.0 +15.3.0 +16.0.0 +17.0.0 +17.1.0 +18.0.0 +18.1.0 +18.2.0 +18.2.1 +18.2.2 +18.2.3 +19.0.0 +19.1.0 +2.0.0 +2.0.1 +2.0.2 +2.0.3 +2.1.0 +2.1.1 +2.1.2 +2.1.3 +2.2.0 +2.2.1 +2.2.2 +20.0.0 +20.0.1 +20.1.0 +21.0.0 +21.0.1 +22.0.0 +23.0.0 +23.1.0 +23.1.1 +23.1.2 +23.2.0 +23.2.1 +24.0.0 +24.0.1 +24.0.2 +25.0.0 +25.0.1 +25.0.2 +26.0.0 +26.1.0 +26.2.0 +27.0.0 +27.1.0 +27.1.1 +27.1.2 +28.0.0 +28.0.1 +28.0.2 +28.0.3 +29.0.0 +29.0.1 +29.1.0 +3.0.0 +3.0.1 +3.0.2 +3.0.3 +3.1.0 +3.1.1 +3.1.2 +3.2.0 +3.2.1 +3.2.2 +3.2.3 +3.2.4 +3.2.5 +3.2.6 +3.2.7 +3.3.0 +3.3.1 +30.0.0 +30.0.1 +30.0.2 +31.0.0 +31.0.1 +31.1.0 +31.2.0 +32.0.0 +33.0.0 +33.1.0 +33.2.0 +34.0.0 +35.0.0 +35.0.1 +35.1.0 +35.1.1 +36.0.0 +4.0.0 +4.1.0 +4.1.1 +4.1.2 +4.1.3 +4.2.0 +4.2.1 +4.2.2 +4.2.3 +4.2.4 +5.0.0 +5.0.1 +5.0.2 +5.1.0 +5.1.1 +5.2.0 +5.2.1 +6.0.0 +6.0.1 +6.0.2 +6.0.3 +6.1.0 +6.2.0 +7.0.0 +7.0.1 +7.0.2 +7.1.0 +7.1.1 +7.1.2 +7.1.3 +8.0.0 +8.0.1 +8.0.2 +8.1.0 +8.1.1 +9.0.0 +9.1.0 +9.1.1 +9.1.2 +9.2.0 +9.2.1 +9.2.2 +9.2.3 +9.2.4 +9.3.0 +9.3.0-RC +9.4.0 +9.4.1 +9.4.2 +9.4.3 +HEAD +feature/fsm +feature/passport +garbage +gradle-wrapper/6.9 +implement_telegram_passport +init_kdocs +kdocs +klassindex +lib_to_common +master +new_branch +play_with_dependabot +renovate/com.benasher44-uuid-0.x +renovate/com.jfrog.bintray.gradle-gradle-bintray-plugin-1.x +renovate/com.soywiz.korlibs.klock-klock-1.x +renovate/com.soywiz.korlibs.klock-klock-2.x +renovate/dev.inmo-micro_utils.coroutines-0.x +renovate/dev.inmo-micro_utils.crypto-0.x +renovate/dev.inmo-micro_utils.serialization.base64-0.x +renovate/dev.inmo-micro_utils.serialization.encapsulator-0.x +renovate/dev.inmo-micro_utils.serialization.typed_serializer-0.x +renovate/dokka +renovate/dokka_version +renovate/github.release.plugin +renovate/github_release_plugin_version +renovate/gradle-6.x +renovate/gradle-7.x +renovate/gradle-8.x +renovate/gradle-9.x +renovate/io.ktor-ktor-client-cio-1.x +renovate/io.ktor-ktor-client-core-1.x +renovate/io.ktor-ktor-server-1.x +renovate/io.ktor-ktor-server-host-common-1.x +renovate/klock_version +renovate/korlibs +renovate/kotlin +renovate/kotlin-coroutines +renovate/kotlin-monorepo +renovate/kotlin-poet +renovate/kotlin-serialization +renovate/kotlin.coroutines +renovate/kotlin.poet +renovate/kotlin.serialization +renovate/kotlin_coroutines_version +renovate/kotlin_serialisation_runtime_version +renovate/kotlin_version +renovate/kotlinx-coroutines-monorepo +renovate/kslog +renovate/ksp +renovate/ksp-monorepo +renovate/ktor +renovate/ktor-monorepo +renovate/ktor_version +renovate/major-dokka +renovate/major-kotlin +renovate/major-kotlin-monorepo +renovate/major-kotlin.poet +renovate/major-ksp +renovate/major-ktor-monorepo +renovate/major-ktor_version +renovate/micro_utils_version +renovate/microutils +renovate/nmcp +renovate/org.jetbrains.dokka-1.x +renovate/org.jetbrains.dokka-dokka-gradle-plugin-0.x +renovate/org.jetbrains.dokka-dokka-gradle-plugin-1.x +renovate/org.jetbrains.dokka-gfm-plugin-1.x +renovate/org.jetbrains.dokka-org.jetbrains.dokka.gradle.plugin-0.x +renovate/org.jetbrains.dokka-org.jetbrains.dokka.gradle.plugin-1.x +renovate/org.jetbrains.kotlin-kotlin-gradle-plugin-1.x +renovate/org.jetbrains.kotlin-kotlin-serialization-1.x +renovate/org.jetbrains.kotlin.multiplatform-1.x +renovate/org.jetbrains.kotlin.multiplatform-org.jetbrains.kotlin.multiplatform.gradle.plugin-1.x +renovate/org.jetbrains.kotlin.plugin.serialization-1.x +renovate/org.jetbrains.kotlin.plugin.serialization-org.jetbrains.kotlin.plugin.serialization.gradle.plugin-1.x +renovate/org.jetbrains.kotlinx-kotlinx-coroutines-core-1.x +renovate/org.jetbrains.kotlinx-kotlinx-serialization-json-1.x +renovate/org.jetbrains.kotlinx-kotlinx-serialization-properties-1.x +renovate/org.jetbrains.kotlinx-kotlinx-serialization-properties-common-0.x +renovate/org.jetbrains.kotlinx-kotlinx-serialization-properties-js-0.x +renovate/org.jetbrains.kotlinx-kotlinx-serialization-runtime-0.x +renovate/org.jetbrains.kotlinx-kotlinx-serialization-runtime-common-0.x +renovate/org.jetbrains.kotlinx-kotlinx-serialization-runtime-js-0.x +renovate/uuid +renovate/uuid_version +renovate/validator +renovate/versions +task/28-migration_to_mpp +task/676-rework_of_media_groups +tg_channel_imh diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d200f17b1..c2c8b8d93c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ **Breaking changes**: +* `RichBlockTableCell.align` now uses the string-serialized `RichBlockTableCellAlign` sealed hierarchy (`Left`, `Center`, or `Right`) instead of `String` +* `RichBlockTableCell` is now a sealed interface with `Header` and `Regular` implementations; the input table DSL uses `headerCell` and `cell` respectively * `InputRichBlockListItem` is now a sealed interface with `Ordered` and `Unordered` implementations; ordered items require a non-null `value` and typed `LabelType`, while `LabelType.Decimals` is the default; `InputRichBlocksBuilder` now exposes separate `orderedList` and `unorderedList` DSL functions with matching item builders * `ReplyParameters` is now a sealed interface with nested `ReplyParameters.Chat` and `ReplyParameters.Ephemeral` implementations; overloaded `ReplyParameters(...)` companion factories construct both regular-message and ephemeral-message variants * The 4 group-family message implementations (`CommonGroupContentMessageImpl`, `CommonForumContentMessageImpl`, `CommonChannelDirectMessagesContentMessageImpl`, `CommonSuggestedChannelDirectMessagesContentMessageImpl`) gained trailing `receiverUser`/`ephemeralMessageId` primary-constructor parameters (defaulted to `null`) — positional construction of these classes must be updated @@ -14,6 +16,8 @@ **Migration advice**: Keep `ReplyParameters(...)` for both chat-message and ephemeral-message targets; explicit `ReplyParameters.Ephemeral(...)` subtype construction also remains available; pass `receiverUser`/`ephemeralMessageId` explicitly (or rely on their `null` default) when constructing the 4 group-family message implementations positionally * `Core`: + * (`Rich Messages`) Added the raw-string-serialized `RichBlockTableCellAlign` hierarchy and migrated table-cell alignment from `String` to `RichBlockTableCellAlign` + * (`Rich Messages`) Split `RichBlockTableCell` into header/regular variants with a shared flat surrogate serializer; added `headerCell` to the input table DSL * (`Rich Messages`) Added `h1` through `h6` shortcuts for plain and rich-text headings in `InputRichBlocksBuilder` * (`Rich Messages`) Reworked the input table DSL to build cells through nested `table { row { cell(...) { } } }` builders * (`Rich Messages`) Replaced the flat `InputRichBlockListItem` data class with ordered/unordered variants, added the string-serialized `LabelType` hierarchy (`A`, `a`, `I`, `i`, `1`), and split the list DSL into `InputRichBlockOrderedListBuilder`/`InputRichBlockUnorderedListBuilder` diff --git a/codex-master-baseline b/codex-master-baseline new file mode 160000 index 0000000000..c7761fd294 --- /dev/null +++ b/codex-master-baseline @@ -0,0 +1 @@ +Subproject commit c7761fd29494e6586a449163a2e48cd7a70a6cef diff --git a/tgbotapi.core/api/tgbotapi.core.api b/tgbotapi.core/api/tgbotapi.core.api index 126ac39336..0567164bb8 100644 --- a/tgbotapi.core/api/tgbotapi.core.api +++ b/tgbotapi.core/api/tgbotapi.core.api @@ -35863,8 +35863,10 @@ public final class dev/inmo/tgbotapi/types/rich/InputRichBlockTableBuilder { public final class dev/inmo/tgbotapi/types/rich/InputRichBlockTableRowBuilder { public fun ()V public final fun build ()Ljava/util/List; - public final fun cell (Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Integer;Ljava/lang/Integer;Lkotlin/jvm/functions/Function1;)V - public static synthetic fun cell$default (Ldev/inmo/tgbotapi/types/rich/InputRichBlockTableRowBuilder;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/Integer;Ljava/lang/Integer;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V + public final fun cell (Ldev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Integer;Lkotlin/jvm/functions/Function1;)V + public static synthetic fun cell$default (Ldev/inmo/tgbotapi/types/rich/InputRichBlockTableRowBuilder;Ldev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Integer;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V + public final fun headerCell (Ldev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Integer;Lkotlin/jvm/functions/Function1;)V + public static synthetic fun headerCell$default (Ldev/inmo/tgbotapi/types/rich/InputRichBlockTableRowBuilder;Ldev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Integer;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V } public final class dev/inmo/tgbotapi/types/rich/InputRichBlockThinking : dev/inmo/tgbotapi/types/rich/InputRichBlock { @@ -36929,44 +36931,123 @@ public final class dev/inmo/tgbotapi/types/rich/RichBlockTable$Companion { public final fun serializer ()Lkotlinx/serialization/KSerializer; } -public final class dev/inmo/tgbotapi/types/rich/RichBlockTableCell { +public abstract interface class dev/inmo/tgbotapi/types/rich/RichBlockTableCell { public static final field Companion Ldev/inmo/tgbotapi/types/rich/RichBlockTableCell$Companion; - public fun (Ldev/inmo/tgbotapi/types/rich/RichText;Ljava/lang/Boolean;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;)V - public synthetic fun (Ldev/inmo/tgbotapi/types/rich/RichText;Ljava/lang/Boolean;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun component1 ()Ldev/inmo/tgbotapi/types/rich/RichText; - public final fun component2 ()Ljava/lang/Boolean; - public final fun component3 ()Ljava/lang/Integer; - public final fun component4 ()Ljava/lang/Integer; - public final fun component5 ()Ljava/lang/String; - public final fun component6 ()Ljava/lang/String; - public final fun copy (Ldev/inmo/tgbotapi/types/rich/RichText;Ljava/lang/Boolean;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;)Ldev/inmo/tgbotapi/types/rich/RichBlockTableCell; - public static synthetic fun copy$default (Ldev/inmo/tgbotapi/types/rich/RichBlockTableCell;Ldev/inmo/tgbotapi/types/rich/RichText;Ljava/lang/Boolean;Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ldev/inmo/tgbotapi/types/rich/RichBlockTableCell; - public fun equals (Ljava/lang/Object;)Z - public final fun getAlign ()Ljava/lang/String; - public final fun getColspan ()Ljava/lang/Integer; - public final fun getRowspan ()Ljava/lang/Integer; - public final fun getText ()Ldev/inmo/tgbotapi/types/rich/RichText; - public final fun getValign ()Ljava/lang/String; - public fun hashCode ()I - public final fun isHeader ()Ljava/lang/Boolean; - public fun toString ()Ljava/lang/String; -} - -public final synthetic class dev/inmo/tgbotapi/types/rich/RichBlockTableCell$$serializer : kotlinx/serialization/internal/GeneratedSerializer { - public static final field INSTANCE Ldev/inmo/tgbotapi/types/rich/RichBlockTableCell$$serializer; - public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; - public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ldev/inmo/tgbotapi/types/rich/RichBlockTableCell; - public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; - public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; - public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Ldev/inmo/tgbotapi/types/rich/RichBlockTableCell;)V - public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V - public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; + public abstract fun getAlign ()Ldev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign; + public abstract fun getColspan ()Ljava/lang/Integer; + public abstract fun getRowspan ()Ljava/lang/Integer; + public abstract fun getText ()Ldev/inmo/tgbotapi/types/rich/RichText; + public abstract fun getValign ()Ljava/lang/String; } public final class dev/inmo/tgbotapi/types/rich/RichBlockTableCell$Companion { public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public final class dev/inmo/tgbotapi/types/rich/RichBlockTableCell$Header : dev/inmo/tgbotapi/types/rich/RichBlockTableCell { + public static final field Companion Ldev/inmo/tgbotapi/types/rich/RichBlockTableCell$Header$Companion; + public fun (Ldev/inmo/tgbotapi/types/rich/RichText;Ljava/lang/Integer;Ljava/lang/Integer;Ldev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign;Ljava/lang/String;)V + public synthetic fun (Ldev/inmo/tgbotapi/types/rich/RichText;Ljava/lang/Integer;Ljava/lang/Integer;Ldev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Ldev/inmo/tgbotapi/types/rich/RichText; + public final fun component2 ()Ljava/lang/Integer; + public final fun component3 ()Ljava/lang/Integer; + public final fun component4 ()Ldev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign; + public final fun component5 ()Ljava/lang/String; + public final fun copy (Ldev/inmo/tgbotapi/types/rich/RichText;Ljava/lang/Integer;Ljava/lang/Integer;Ldev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign;Ljava/lang/String;)Ldev/inmo/tgbotapi/types/rich/RichBlockTableCell$Header; + public static synthetic fun copy$default (Ldev/inmo/tgbotapi/types/rich/RichBlockTableCell$Header;Ldev/inmo/tgbotapi/types/rich/RichText;Ljava/lang/Integer;Ljava/lang/Integer;Ldev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign;Ljava/lang/String;ILjava/lang/Object;)Ldev/inmo/tgbotapi/types/rich/RichBlockTableCell$Header; + public fun equals (Ljava/lang/Object;)Z + public fun getAlign ()Ldev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign; + public fun getColspan ()Ljava/lang/Integer; + public fun getRowspan ()Ljava/lang/Integer; + public fun getText ()Ldev/inmo/tgbotapi/types/rich/RichText; + public fun getValign ()Ljava/lang/String; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final class dev/inmo/tgbotapi/types/rich/RichBlockTableCell$Header$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class dev/inmo/tgbotapi/types/rich/RichBlockTableCell$Regular : dev/inmo/tgbotapi/types/rich/RichBlockTableCell { + public static final field Companion Ldev/inmo/tgbotapi/types/rich/RichBlockTableCell$Regular$Companion; + public fun (Ldev/inmo/tgbotapi/types/rich/RichText;Ljava/lang/Integer;Ljava/lang/Integer;Ldev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign;Ljava/lang/String;)V + public synthetic fun (Ldev/inmo/tgbotapi/types/rich/RichText;Ljava/lang/Integer;Ljava/lang/Integer;Ldev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Ldev/inmo/tgbotapi/types/rich/RichText; + public final fun component2 ()Ljava/lang/Integer; + public final fun component3 ()Ljava/lang/Integer; + public final fun component4 ()Ldev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign; + public final fun component5 ()Ljava/lang/String; + public final fun copy (Ldev/inmo/tgbotapi/types/rich/RichText;Ljava/lang/Integer;Ljava/lang/Integer;Ldev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign;Ljava/lang/String;)Ldev/inmo/tgbotapi/types/rich/RichBlockTableCell$Regular; + public static synthetic fun copy$default (Ldev/inmo/tgbotapi/types/rich/RichBlockTableCell$Regular;Ldev/inmo/tgbotapi/types/rich/RichText;Ljava/lang/Integer;Ljava/lang/Integer;Ldev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign;Ljava/lang/String;ILjava/lang/Object;)Ldev/inmo/tgbotapi/types/rich/RichBlockTableCell$Regular; + public fun equals (Ljava/lang/Object;)Z + public fun getAlign ()Ldev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign; + public fun getColspan ()Ljava/lang/Integer; + public fun getRowspan ()Ljava/lang/Integer; + public fun getText ()Ldev/inmo/tgbotapi/types/rich/RichText; + public fun getValign ()Ljava/lang/String; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final class dev/inmo/tgbotapi/types/rich/RichBlockTableCell$Regular$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class dev/inmo/tgbotapi/types/rich/RichBlockTableCell$Serializer : kotlinx/serialization/KSerializer { + public static final field INSTANCE Ldev/inmo/tgbotapi/types/rich/RichBlockTableCell$Serializer; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ldev/inmo/tgbotapi/types/rich/RichBlockTableCell; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Ldev/inmo/tgbotapi/types/rich/RichBlockTableCell;)V + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V +} + +public abstract interface class dev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign { + public static final field Companion Ldev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign$Companion; + public abstract fun getName ()Ljava/lang/String; +} + +public final class dev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign$Center : dev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign { + public static final field INSTANCE Ldev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign$Center; + public fun equals (Ljava/lang/Object;)Z + public fun getName ()Ljava/lang/String; + public fun hashCode ()I + public final fun serializer ()Lkotlinx/serialization/KSerializer; + public fun toString ()Ljava/lang/String; +} + +public final class dev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class dev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign$Left : dev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign { + public static final field INSTANCE Ldev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign$Left; + public fun equals (Ljava/lang/Object;)Z + public fun getName ()Ljava/lang/String; + public fun hashCode ()I + public final fun serializer ()Lkotlinx/serialization/KSerializer; + public fun toString ()Ljava/lang/String; +} + +public final class dev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign$Right : dev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign { + public static final field INSTANCE Ldev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign$Right; + public fun equals (Ljava/lang/Object;)Z + public fun getName ()Ljava/lang/String; + public fun hashCode ()I + public final fun serializer ()Lkotlinx/serialization/KSerializer; + public fun toString ()Ljava/lang/String; +} + +public final class dev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign$Serializer : kotlinx/serialization/KSerializer { + public static final field INSTANCE Ldev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign$Serializer; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ldev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Ldev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign;)V + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V +} + public final class dev/inmo/tgbotapi/types/rich/RichBlockThinking : dev/inmo/tgbotapi/types/rich/RichBlock { public static final field Companion Ldev/inmo/tgbotapi/types/rich/RichBlockThinking$Companion; public static final field TYPE Ljava/lang/String; diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/InputRichBlocksDsl.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/InputRichBlocksDsl.kt index eddaece652..0c049b8c24 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/InputRichBlocksDsl.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/InputRichBlocksDsl.kt @@ -55,14 +55,23 @@ class InputRichBlockTableRowBuilder { private val cells = mutableListOf() fun cell( - align: String, + align: RichBlockTableCellAlign, valign: String, - isHeader: Boolean? = null, colspan: Int? = null, rowspan: Int? = null, block: RichTextBuilder.() -> Unit ) { - cells.add(RichBlockTableCell(buildRichText(block), isHeader, colspan, rowspan, align, valign)) + cells.add(RichBlockTableCell.Regular(buildRichText(block), colspan, rowspan, align, valign)) + } + + fun headerCell( + align: RichBlockTableCellAlign, + valign: String, + colspan: Int? = null, + rowspan: Int? = null, + block: RichTextBuilder.() -> Unit + ) { + cells.add(RichBlockTableCell.Header(buildRichText(block), colspan, rowspan, align, valign)) } fun build(): List = cells.toList() diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichBlockParts.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichBlockParts.kt index 79c8d6bec9..17d5610e6e 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichBlockParts.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichBlockParts.kt @@ -15,6 +15,11 @@ import dev.inmo.tgbotapi.types.valignField import dev.inmo.tgbotapi.types.valueField import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable +import kotlinx.serialization.KSerializer +import kotlinx.serialization.EncodeDefault +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder /** * Caption of a rich formatted block. @@ -34,21 +39,86 @@ data class RichBlockCaption( * * @see RichBlockTableCell */ -@Serializable -data class RichBlockTableCell( - @SerialName(textField) - val text: RichText? = null, - @SerialName(isHeaderField) - val isHeader: Boolean? = null, - @SerialName(colspanField) - val colspan: Int? = null, - @SerialName(rowspanField) - val rowspan: Int? = null, - @SerialName(alignField) - val align: String, - @SerialName(valignField) +@Serializable(RichBlockTableCell.Serializer::class) +sealed interface RichBlockTableCell { + val text: RichText? + val colspan: Int? + val rowspan: Int? + val align: RichBlockTableCellAlign val valign: String -) + + @Suppress("SERIALIZER_TYPE_INCOMPATIBLE") + @Serializable(Serializer::class) + data class Header( + @SerialName(textField) + override val text: RichText? = null, + @SerialName(colspanField) + override val colspan: Int? = null, + @SerialName(rowspanField) + override val rowspan: Int? = null, + @SerialName(alignField) + override val align: RichBlockTableCellAlign, + @SerialName(valignField) + override val valign: String + ) : RichBlockTableCell + + @Suppress("SERIALIZER_TYPE_INCOMPATIBLE") + @Serializable(Serializer::class) + data class Regular( + @SerialName(textField) + override val text: RichText? = null, + @SerialName(colspanField) + override val colspan: Int? = null, + @SerialName(rowspanField) + override val rowspan: Int? = null, + @SerialName(alignField) + override val align: RichBlockTableCellAlign, + @SerialName(valignField) + override val valign: String + ) : RichBlockTableCell + + object Serializer : KSerializer { + @Serializable + private data class Surrogate( + @SerialName(textField) + val text: RichText? = null, + @SerialName(isHeaderField) + @EncodeDefault(EncodeDefault.Mode.NEVER) + val isHeader: Boolean? = null, + @SerialName(colspanField) + val colspan: Int? = null, + @SerialName(rowspanField) + val rowspan: Int? = null, + @SerialName(alignField) + val align: RichBlockTableCellAlign, + @SerialName(valignField) + val valign: String + ) + + override val descriptor: SerialDescriptor = Surrogate.serializer().descriptor + + override fun deserialize(decoder: Decoder): RichBlockTableCell { + val surrogate = decoder.decodeSerializableValue(Surrogate.serializer()) + return if (surrogate.isHeader == true) { + Header(surrogate.text, surrogate.colspan, surrogate.rowspan, surrogate.align, surrogate.valign) + } else { + Regular(surrogate.text, surrogate.colspan, surrogate.rowspan, surrogate.align, surrogate.valign) + } + } + + override fun serialize(encoder: Encoder, value: RichBlockTableCell) { + val surrogate = Surrogate( + value.text, + true.takeIf { value is Header }, + value.colspan, + value.rowspan, + value.align, + value.valign + ) + encoder.encodeSerializableValue(Surrogate.serializer(), surrogate) + } + } +} /** * An item of a [RichBlockList]. diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign.kt new file mode 100644 index 0000000000..d3202982bc --- /dev/null +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichBlockTableCellAlign.kt @@ -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 + +/** Horizontal alignment of a [RichBlockTableCell]. */ +@Serializable(RichBlockTableCellAlign.Serializer::class) +sealed interface RichBlockTableCellAlign { + val name: String + + @Suppress("SERIALIZER_TYPE_INCOMPATIBLE") + @Serializable(Serializer::class) + data object Left : RichBlockTableCellAlign { + override val name: String = "left" + } + + @Suppress("SERIALIZER_TYPE_INCOMPATIBLE") + @Serializable(Serializer::class) + data object Center : RichBlockTableCellAlign { + override val name: String = "center" + } + + @Suppress("SERIALIZER_TYPE_INCOMPATIBLE") + @Serializable(Serializer::class) + data object Right : RichBlockTableCellAlign { + override val name: String = "right" + } + + object Serializer : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor( + "RichBlockTableCellAlign", + PrimitiveKind.STRING + ) + + override fun deserialize(decoder: Decoder): RichBlockTableCellAlign = when (val name = decoder.decodeString()) { + Left.name -> Left + Center.name -> Center + Right.name -> Right + else -> throw SerializationException("Unknown RichBlockTableCell alignment: $name") + } + + override fun serialize(encoder: Encoder, value: RichBlockTableCellAlign) { + encoder.encodeString(value.name) + } + } +} diff --git a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichBlocks.kt b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichBlocks.kt index 8310ae8bdc..bb61ebabb1 100644 --- a/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichBlocks.kt +++ b/tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/rich/RichBlocks.kt @@ -411,10 +411,9 @@ data class RichBlockTable( fun renderRow(row: List): String = row.joinToString(separator = " | ", prefix = "| ", postfix = " |") { it.text?.markdown ?: "" } fun alignment(cell: RichBlockTableCell): String = when (cell.align) { - "left" -> ":---" - "center" -> ":--:" - "right" -> "---:" - else -> "---" + RichBlockTableCellAlign.Left -> ":---" + RichBlockTableCellAlign.Center -> ":--:" + RichBlockTableCellAlign.Right -> "---:" } val header = cells.first() val lines = mutableListOf( @@ -433,11 +432,11 @@ data class RichBlockTable( val captionPart = caption?.let { "${it.html}" } ?: "" val rows = cells.joinToString(separator = "") { row -> val renderedCells = row.joinToString(separator = "") { cell -> - val tag = if (cell.isHeader == true) "th" else "td" + val tag = if (cell is RichBlockTableCell.Header) "th" else "td" val cellAttributes = buildString { cell.colspan?.let { append(" colspan=\"$it\"") } cell.rowspan?.let { append(" rowspan=\"$it\"") } - append(" align=\"${cell.align}\"") + append(" align=\"${cell.align.name}\"") append(" valign=\"${cell.valign}\"") } "<$tag$cellAttributes>${cell.text?.html ?: ""}" diff --git a/tgbotapi.core/src/commonTest/kotlin/dev/inmo/tgbotapi/types/rich/InputRichBlocksDslTest.kt b/tgbotapi.core/src/commonTest/kotlin/dev/inmo/tgbotapi/types/rich/InputRichBlocksDslTest.kt index 5f981764fd..5ee157b09b 100644 --- a/tgbotapi.core/src/commonTest/kotlin/dev/inmo/tgbotapi/types/rich/InputRichBlocksDslTest.kt +++ b/tgbotapi.core/src/commonTest/kotlin/dev/inmo/tgbotapi/types/rich/InputRichBlocksDslTest.kt @@ -84,12 +84,12 @@ class InputRichBlocksDslTest { val blocks = buildInputRichBlocks { table(isBordered = true, isStriped = false, caption = RichTextPlain("caption")) { row { - cell(align = "left", valign = "top", isHeader = true, colspan = 2) { + headerCell(align = RichBlockTableCellAlign.Left, valign = "top", colspan = 2) { bold("heading") } } row { - cell(align = "center", valign = "middle", rowspan = 2) { + cell(align = RichBlockTableCellAlign.Center, valign = "middle", rowspan = 2) { plain("value") } } @@ -101,19 +101,18 @@ class InputRichBlocksDslTest { InputRichBlockTable( cells = listOf( listOf( - RichBlockTableCell( + RichBlockTableCell.Header( text = RichTextBold(RichTextPlain("heading")), - isHeader = true, colspan = 2, - align = "left", + align = RichBlockTableCellAlign.Left, valign = "top" ) ), listOf( - RichBlockTableCell( + RichBlockTableCell.Regular( text = RichTextPlain("value"), rowspan = 2, - align = "center", + align = RichBlockTableCellAlign.Center, valign = "middle" ) ) diff --git a/tgbotapi.core/src/commonTest/kotlin/dev/inmo/tgbotapi/types/rich/InputRichMessageSerializationTest.kt b/tgbotapi.core/src/commonTest/kotlin/dev/inmo/tgbotapi/types/rich/InputRichMessageSerializationTest.kt index bb36cb2ae4..afd9617e14 100644 --- a/tgbotapi.core/src/commonTest/kotlin/dev/inmo/tgbotapi/types/rich/InputRichMessageSerializationTest.kt +++ b/tgbotapi.core/src/commonTest/kotlin/dev/inmo/tgbotapi/types/rich/InputRichMessageSerializationTest.kt @@ -61,7 +61,7 @@ class InputRichMessageSerializationTest { fun encodesTableReusingReceivedCellType() { val table = InputRichBlockTable( cells = listOf( - listOf(RichBlockTableCell(RichTextPlain("h1"), isHeader = true, align = "left", valign = "top")) + listOf(RichBlockTableCell.Header(RichTextPlain("h1"), align = RichBlockTableCellAlign.Left, valign = "top")) ) ) val message = InputRichMessageBlocks(blocks = listOf(table)) @@ -72,6 +72,42 @@ class InputRichMessageSerializationTest { 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 headerElement = json.encodeToJsonElement(RichBlockTableCell.Serializer, header).jsonObject + val regularElement = json.encodeToJsonElement(RichBlockTableCell.Serializer, regular).jsonObject + assertEquals(true, headerElement["is_header"]?.jsonPrimitive?.boolean) + assertTrue("is_header" !in regularElement) + assertEquals(header, json.decodeFromJsonElement(RichBlockTableCell.Serializer, headerElement)) + assertEquals(regular, json.decodeFromJsonElement(RichBlockTableCell.Serializer, regularElement)) + assertTrue(json.decodeFromString(RichBlockTableCell.Serializer, "{\"align\":\"left\",\"valign\":\"top\",\"is_header\":false}") is RichBlockTableCell.Regular) + } + + @Test + fun serializesEveryTableCellAlignmentAsItsName() { + val alignments = listOf( + RichBlockTableCellAlign.Left, + RichBlockTableCellAlign.Center, + RichBlockTableCellAlign.Right + ) + + alignments.forEach { alignment -> + val encoded = json.encodeToString(RichBlockTableCellAlign.Serializer, alignment) + assertEquals("\"${alignment.name}\"", encoded) + assertEquals(alignment, json.decodeFromString(RichBlockTableCellAlign.Serializer, encoded)) + } + } + + @Test + fun rejectsUnknownTableCellAlignment() { + assertFailsWith { + json.decodeFromString(RichBlockTableCellAlign.Serializer, "\"justify\"") + } + } + @Test fun encodesPhotoBlockMedia() { val photoBlock = InputRichBlockPhoto(TelegramMediaPhoto(FileId("photo_file_id"))) diff --git a/tgbotapi.core/src/commonTest/kotlin/dev/inmo/tgbotapi/types/rich/RichBlockFormattingTest.kt b/tgbotapi.core/src/commonTest/kotlin/dev/inmo/tgbotapi/types/rich/RichBlockFormattingTest.kt index 95dea255e6..fb8a155592 100644 --- a/tgbotapi.core/src/commonTest/kotlin/dev/inmo/tgbotapi/types/rich/RichBlockFormattingTest.kt +++ b/tgbotapi.core/src/commonTest/kotlin/dev/inmo/tgbotapi/types/rich/RichBlockFormattingTest.kt @@ -108,12 +108,12 @@ class RichBlockFormattingTest { val block = RichBlockTable( listOf( listOf( - RichBlockTableCell(text = RichTextPlain("H1"), isHeader = true, align = "left", valign = "top"), - RichBlockTableCell(text = RichTextPlain("H2"), isHeader = true, align = "center", valign = "top") + RichBlockTableCell.Header(text = RichTextPlain("H1"), align = RichBlockTableCellAlign.Left, valign = "top"), + RichBlockTableCell.Header(text = RichTextPlain("H2"), align = RichBlockTableCellAlign.Center, valign = "top") ), listOf( - RichBlockTableCell(text = RichTextPlain("a"), align = "left", valign = "top"), - RichBlockTableCell(text = RichTextPlain("b"), align = "center", valign = "top") + RichBlockTableCell.Regular(text = RichTextPlain("a"), align = RichBlockTableCellAlign.Left, valign = "top"), + RichBlockTableCell.Regular(text = RichTextPlain("b"), align = RichBlockTableCellAlign.Center, valign = "top") ) ) )