mirror of
https://github.com/InsanusMokrassar/TelegramBotAPI-examples.git
synced 2024-12-22 08:37:18 +00:00
start migration to compose in webapp
This commit is contained in:
parent
1c437690e4
commit
76f151586e
@ -11,6 +11,9 @@ buildscript {
|
|||||||
plugins {
|
plugins {
|
||||||
id "org.jetbrains.kotlin.multiplatform"
|
id "org.jetbrains.kotlin.multiplatform"
|
||||||
id "org.jetbrains.kotlin.plugin.serialization"
|
id "org.jetbrains.kotlin.plugin.serialization"
|
||||||
|
|
||||||
|
id "org.jetbrains.kotlin.plugin.compose" version "$kotlin_version"
|
||||||
|
id "org.jetbrains.compose" version "$compose_version"
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'application'
|
apply plugin: 'application'
|
||||||
@ -27,12 +30,14 @@ kotlin {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation kotlin('stdlib')
|
implementation kotlin('stdlib')
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:$serialization_version"
|
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:$serialization_version"
|
||||||
|
implementation compose.runtime
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
jsMain {
|
jsMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation "dev.inmo:tgbotapi.webapps:$telegram_bot_api_version"
|
implementation "dev.inmo:tgbotapi.webapps:$telegram_bot_api_version"
|
||||||
|
implementation compose.web.core
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,6 +46,7 @@ kotlin {
|
|||||||
implementation "dev.inmo:tgbotapi:$telegram_bot_api_version"
|
implementation "dev.inmo:tgbotapi:$telegram_bot_api_version"
|
||||||
implementation "dev.inmo:micro_utils.ktor.server:$micro_utils_version"
|
implementation "dev.inmo:micro_utils.ktor.server:$micro_utils_version"
|
||||||
implementation "io.ktor:ktor-server-cio:$ktor_version"
|
implementation "io.ktor:ktor-server-cio:$ktor_version"
|
||||||
|
implementation compose.desktop.currentOs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import androidx.compose.runtime.*
|
||||||
import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions
|
import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions
|
||||||
import dev.inmo.tgbotapi.types.webAppQueryIdField
|
import dev.inmo.tgbotapi.types.webAppQueryIdField
|
||||||
import dev.inmo.tgbotapi.webapps.*
|
import dev.inmo.tgbotapi.webapps.*
|
||||||
@ -18,6 +19,10 @@ import kotlinx.dom.appendElement
|
|||||||
import kotlinx.dom.appendText
|
import kotlinx.dom.appendText
|
||||||
import kotlinx.dom.clear
|
import kotlinx.dom.clear
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
|
import org.jetbrains.compose.web.dom.Button
|
||||||
|
import org.jetbrains.compose.web.dom.P
|
||||||
|
import org.jetbrains.compose.web.dom.Text
|
||||||
|
import org.jetbrains.compose.web.renderComposable
|
||||||
import org.w3c.dom.*
|
import org.w3c.dom.*
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
import kotlin.random.nextUBytes
|
import kotlin.random.nextUBytes
|
||||||
@ -33,118 +38,146 @@ fun main() {
|
|||||||
val client = HttpClient()
|
val client = HttpClient()
|
||||||
val baseUrl = window.location.origin.removeSuffix("/")
|
val baseUrl = window.location.origin.removeSuffix("/")
|
||||||
|
|
||||||
|
renderComposable("root") {
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
val isSafeState = remember { mutableStateOf<Boolean?>(null) }
|
||||||
|
val logsState = remember { mutableStateListOf<String>() }
|
||||||
|
LaunchedEffect(baseUrl) {
|
||||||
|
val response = client.post("$baseUrl/check") {
|
||||||
|
setBody(
|
||||||
|
Json.encodeToString(
|
||||||
|
WebAppDataWrapper.serializer(),
|
||||||
|
WebAppDataWrapper(webApp.initData, webApp.initDataUnsafe.hash)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val dataIsSafe = response.bodyAsText().toBoolean()
|
||||||
|
|
||||||
|
document.body ?.log(
|
||||||
|
if (dataIsSafe) {
|
||||||
|
"Data is safe"
|
||||||
|
} else {
|
||||||
|
"Data is unsafe"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
document.body ?.log(
|
||||||
|
webApp.initDataUnsafe.chat.toString()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Text(
|
||||||
|
when (isSafeState.value) {
|
||||||
|
null -> "Checking safe state..."
|
||||||
|
true -> "Data is safe"
|
||||||
|
false -> "Data is unsafe"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Text(webApp.initDataUnsafe.chat.toString())
|
||||||
|
|
||||||
|
Button({
|
||||||
|
onClick {
|
||||||
|
scope.launchSafelyWithoutExceptions {
|
||||||
|
handleResult({ "Clicked" }) {
|
||||||
|
client.post("${window.location.origin.removeSuffix("/")}/inline") {
|
||||||
|
parameter(webAppQueryIdField, it)
|
||||||
|
setBody(TextContent("Clicked", ContentType.Text.Plain))
|
||||||
|
logsState.add(url.build().toString())
|
||||||
|
}.coroutineContext.job.join()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Text("Answer in chat button")
|
||||||
|
}
|
||||||
|
|
||||||
|
P()
|
||||||
|
Text("Allow to write in private messages: ${webApp.initDataUnsafe.user ?.allowsWriteToPM ?: "User unavailable"}")
|
||||||
|
|
||||||
|
P()
|
||||||
|
Text("Alerts:")
|
||||||
|
Button({
|
||||||
|
onClick {
|
||||||
|
webApp.showPopup(
|
||||||
|
PopupParams(
|
||||||
|
"It is sample title of default button",
|
||||||
|
"It is sample message of default button",
|
||||||
|
DefaultPopupButton("default", "Default button"),
|
||||||
|
OkPopupButton("ok"),
|
||||||
|
DestructivePopupButton("destructive", "Destructive button")
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
logsState.add(
|
||||||
|
when (it) {
|
||||||
|
"default" -> "You have clicked default button in popup"
|
||||||
|
"ok" -> "You have clicked ok button in popup"
|
||||||
|
"destructive" -> "You have clicked destructive button in popup"
|
||||||
|
else -> "I can't imagine where you take button with id $it"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Text("Popup")
|
||||||
|
}
|
||||||
|
Button({
|
||||||
|
onClick {
|
||||||
|
webApp.showAlert(
|
||||||
|
"This is alert message"
|
||||||
|
) {
|
||||||
|
logsState.add(
|
||||||
|
"You have closed alert"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Text("Alert")
|
||||||
|
}
|
||||||
|
|
||||||
|
P()
|
||||||
|
Button({
|
||||||
|
onClick {
|
||||||
|
webApp.requestWriteAccess()
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Text("Request write access without callback")
|
||||||
|
}
|
||||||
|
Button({
|
||||||
|
onClick {
|
||||||
|
webApp.requestWriteAccess {
|
||||||
|
logsState.add("Write access request result: $it")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Text("Request write access with callback")
|
||||||
|
}
|
||||||
|
|
||||||
|
P()
|
||||||
|
Button({
|
||||||
|
onClick {
|
||||||
|
webApp.requestContact()
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Text("Request contact without callback")
|
||||||
|
}
|
||||||
|
Button({
|
||||||
|
onClick {
|
||||||
|
webApp.requestContact { logsState.add("Contact request result: $it") }
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Text("Request contact with callback")
|
||||||
|
}
|
||||||
|
P()
|
||||||
|
|
||||||
|
logsState.forEach {
|
||||||
|
P { Text(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
window.onload = {
|
window.onload = {
|
||||||
val scope = CoroutineScope(Dispatchers.Default)
|
val scope = CoroutineScope(Dispatchers.Default)
|
||||||
runCatching {
|
runCatching {
|
||||||
|
|
||||||
scope.launchSafelyWithoutExceptions {
|
|
||||||
val response = client.post("$baseUrl/check") {
|
|
||||||
setBody(
|
|
||||||
Json.encodeToString(
|
|
||||||
WebAppDataWrapper.serializer(),
|
|
||||||
WebAppDataWrapper(webApp.initData, webApp.initDataUnsafe.hash)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
val dataIsSafe = response.bodyAsText().toBoolean()
|
|
||||||
|
|
||||||
document.body ?.log(
|
|
||||||
if (dataIsSafe) {
|
|
||||||
"Data is safe"
|
|
||||||
} else {
|
|
||||||
"Data is unsafe"
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
document.body ?.log(
|
|
||||||
webApp.initDataUnsafe.chat.toString()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
document.body ?.appendElement("button") {
|
|
||||||
addEventListener("click", {
|
|
||||||
scope.launchSafelyWithoutExceptions {
|
|
||||||
handleResult({ "Clicked" }) {
|
|
||||||
client.post("${window.location.origin.removeSuffix("/")}/inline") {
|
|
||||||
parameter(webAppQueryIdField, it)
|
|
||||||
setBody(TextContent("Clicked", ContentType.Text.Plain))
|
|
||||||
document.body ?.log(url.build().toString())
|
|
||||||
}.coroutineContext.job.join()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
appendText("Answer in chat button")
|
|
||||||
} ?: window.alert("Unable to load body")
|
|
||||||
|
|
||||||
document.body ?.appendElement("p", {})
|
|
||||||
document.body ?.appendText("Allow to write in private messages: ${webApp.initDataUnsafe.user ?.allowsWriteToPM ?: "User unavailable"}")
|
|
||||||
|
|
||||||
document.body ?.appendElement("p", {})
|
|
||||||
document.body ?.appendText("Alerts:")
|
|
||||||
|
|
||||||
document.body ?.appendElement("button") {
|
|
||||||
addEventListener("click", {
|
|
||||||
webApp.showPopup(
|
|
||||||
PopupParams(
|
|
||||||
"It is sample title of default button",
|
|
||||||
"It is sample message of default button",
|
|
||||||
DefaultPopupButton("default", "Default button"),
|
|
||||||
OkPopupButton("ok"),
|
|
||||||
DestructivePopupButton("destructive", "Destructive button")
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
document.body ?.log(
|
|
||||||
when (it) {
|
|
||||||
"default" -> "You have clicked default button in popup"
|
|
||||||
"ok" -> "You have clicked ok button in popup"
|
|
||||||
"destructive" -> "You have clicked destructive button in popup"
|
|
||||||
else -> "I can't imagine where you take button with id $it"
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
appendText("Popup")
|
|
||||||
} ?: window.alert("Unable to load body")
|
|
||||||
|
|
||||||
document.body ?.appendElement("button") {
|
|
||||||
addEventListener("click", {
|
|
||||||
webApp.showAlert(
|
|
||||||
"This is alert message"
|
|
||||||
) {
|
|
||||||
document.body ?.log(
|
|
||||||
"You have closed alert"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
appendText("Alert")
|
|
||||||
} ?: window.alert("Unable to load body")
|
|
||||||
|
|
||||||
document.body ?.appendElement("p", {})
|
|
||||||
|
|
||||||
document.body ?.appendElement("button") {
|
|
||||||
addEventListener("click", { webApp.requestWriteAccess() })
|
|
||||||
appendText("Request write access without callback")
|
|
||||||
} ?: window.alert("Unable to load body")
|
|
||||||
|
|
||||||
document.body ?.appendElement("button") {
|
|
||||||
addEventListener("click", { webApp.requestWriteAccess { document.body ?.log("Write access request result: $it") } })
|
|
||||||
appendText("Request write access with callback")
|
|
||||||
} ?: window.alert("Unable to load body")
|
|
||||||
|
|
||||||
document.body ?.appendElement("p", {})
|
|
||||||
|
|
||||||
document.body ?.appendElement("button") {
|
|
||||||
addEventListener("click", { webApp.requestContact() })
|
|
||||||
appendText("Request contact without callback")
|
|
||||||
} ?: window.alert("Unable to load body")
|
|
||||||
|
|
||||||
document.body ?.appendElement("button") {
|
|
||||||
addEventListener("click", { webApp.requestContact { document.body ?.log("Contact request result: $it") } })
|
|
||||||
appendText("Request contact with callback")
|
|
||||||
} ?: window.alert("Unable to load body")
|
|
||||||
|
|
||||||
document.body ?.appendElement("p", {})
|
|
||||||
|
|
||||||
document.body ?.appendElement("button") {
|
document.body ?.appendElement("button") {
|
||||||
addEventListener("click", {
|
addEventListener("click", {
|
||||||
webApp.showConfirm(
|
webApp.showConfirm(
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
<title>Web App Example</title>
|
<title>Web App Example</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
<script type="application/javascript" src="https://telegram.org/js/telegram-web-app.js"></script>
|
<script type="application/javascript" src="https://telegram.org/js/telegram-web-app.js"></script>
|
||||||
<script type="application/javascript" src="WebApp.js"></script>
|
<script type="application/javascript" src="WebApp.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
@ -29,3 +29,8 @@ allprojects {
|
|||||||
maven { url "https://nexus.inmo.dev/repository/maven-releases/" }
|
maven { url "https://nexus.inmo.dev/repository/maven-releases/" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fix of https://youtrack.jetbrains.com/issue/KTOR-7912/Module-not-found-errors-when-executing-browserProductionWebpack-task-since-3.0.2
|
||||||
|
rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin.class) {
|
||||||
|
rootProject.kotlinYarn.resolution("ws", "8.18.0")
|
||||||
|
}
|
||||||
|
@ -10,3 +10,4 @@ telegram_bot_api_version=22.0.0
|
|||||||
micro_utils_version=0.23.2
|
micro_utils_version=0.23.2
|
||||||
serialization_version=1.7.3
|
serialization_version=1.7.3
|
||||||
ktor_version=3.0.2
|
ktor_version=3.0.2
|
||||||
|
compose_version=1.7.1
|
||||||
|
Loading…
Reference in New Issue
Block a user