1+ import androidx.compose.runtime.*
12import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions
23import dev.inmo.tgbotapi.types.webAppQueryIdField
34import dev.inmo.tgbotapi.webapps.*
@@ -18,6 +19,10 @@ import kotlinx.dom.appendElement
1819import kotlinx.dom.appendText
1920import kotlinx.dom.clear
2021import kotlinx.serialization.json.Json
22+ import org.jetbrains.compose.web.dom.Button
23+ import org.jetbrains.compose.web.dom.P
24+ import org.jetbrains.compose.web.dom.Text
25+ import org.jetbrains.compose.web.renderComposable
2126import org.w3c.dom.*
2227import kotlin.random.Random
2328import kotlin.random.nextUBytes
@@ -33,117 +38,145 @@ fun main() {
3338 val client = HttpClient ()
3439 val baseUrl = window.location.origin.removeSuffix(" /" )
3540
36- window.onload = {
37- val scope = CoroutineScope (Dispatchers .Default )
38- runCatching {
39-
40- scope.launchSafelyWithoutExceptions {
41- val response = client.post(" $baseUrl /check" ) {
42- setBody(
43- Json .encodeToString(
44- WebAppDataWrapper .serializer(),
45- WebAppDataWrapper (webApp.initData, webApp.initDataUnsafe.hash)
46- )
41+ renderComposable(" root" ) {
42+ val scope = rememberCoroutineScope()
43+ val isSafeState = remember { mutableStateOf<Boolean ?>(null ) }
44+ val logsState = remember { mutableStateListOf<String >() }
45+ LaunchedEffect (baseUrl) {
46+ val response = client.post(" $baseUrl /check" ) {
47+ setBody(
48+ Json .encodeToString(
49+ WebAppDataWrapper .serializer(),
50+ WebAppDataWrapper (webApp.initData, webApp.initDataUnsafe.hash)
4751 )
48- }
49- val dataIsSafe = response.bodyAsText().toBoolean()
50-
51- document.body ?.log(
52- if (dataIsSafe) {
53- " Data is safe"
54- } else {
55- " Data is unsafe"
56- }
57- )
58-
59- document.body ?.log(
60- webApp.initDataUnsafe.chat.toString()
6152 )
6253 }
54+ val dataIsSafe = response.bodyAsText().toBoolean()
6355
64- document.body ?.appendElement(" button" ) {
65- addEventListener(" click" , {
66- scope.launchSafelyWithoutExceptions {
67- handleResult({ " Clicked" }) {
68- client.post(" ${window.location.origin.removeSuffix(" /" )} /inline" ) {
69- parameter(webAppQueryIdField, it)
70- setBody(TextContent (" Clicked" , ContentType .Text .Plain ))
71- document.body ?.log(url.build().toString())
72- }.coroutineContext.job.join()
73- }
74- }
75- })
76- appendText(" Answer in chat button" )
77- } ? : window.alert(" Unable to load body" )
78-
79- document.body ?.appendElement(" p" , {})
80- document.body ?.appendText(" Allow to write in private messages: ${webApp.initDataUnsafe.user ?.allowsWriteToPM ? : " User unavailable" } " )
81-
82- document.body ?.appendElement(" p" , {})
83- document.body ?.appendText(" Alerts:" )
56+ document.body ?.log(
57+ if (dataIsSafe) {
58+ " Data is safe"
59+ } else {
60+ " Data is unsafe"
61+ }
62+ )
8463
85- document.body ?.appendElement(" button" ) {
86- addEventListener(" click" , {
87- webApp.showPopup(
88- PopupParams (
89- " It is sample title of default button" ,
90- " It is sample message of default button" ,
91- DefaultPopupButton (" default" , " Default button" ),
92- OkPopupButton (" ok" ),
93- DestructivePopupButton (" destructive" , " Destructive button" )
94- )
95- ) {
96- document.body ?.log(
97- when (it) {
98- " default" -> " You have clicked default button in popup"
99- " ok" -> " You have clicked ok button in popup"
100- " destructive" -> " You have clicked destructive button in popup"
101- else -> " I can't imagine where you take button with id $it "
102- }
103- )
104- }
105- })
106- appendText(" Popup" )
107- } ? : window.alert(" Unable to load body" )
64+ document.body ?.log(
65+ webApp.initDataUnsafe.chat.toString()
66+ )
67+ }
10868
109- document.body ?.appendElement(" button" ) {
110- addEventListener(" click" , {
111- webApp.showAlert(
112- " This is alert message"
113- ) {
114- document.body ?.log(
115- " You have closed alert"
116- )
69+ Text (
70+ when (isSafeState.value) {
71+ null -> " Checking safe state..."
72+ true -> " Data is safe"
73+ false -> " Data is unsafe"
74+ }
75+ )
76+ Text (webApp.initDataUnsafe.chat.toString())
77+
78+ Button ({
79+ onClick {
80+ scope.launchSafelyWithoutExceptions {
81+ handleResult({ " Clicked" }) {
82+ client.post(" ${window.location.origin.removeSuffix(" /" )} /inline" ) {
83+ parameter(webAppQueryIdField, it)
84+ setBody(TextContent (" Clicked" , ContentType .Text .Plain ))
85+ logsState.add(url.build().toString())
86+ }.coroutineContext.job.join()
11787 }
118- })
119- appendText(" Alert" )
120- } ? : window.alert(" Unable to load body" )
121-
122- document.body ?.appendElement(" p" , {})
123-
124- document.body ?.appendElement(" button" ) {
125- addEventListener(" click" , { webApp.requestWriteAccess() })
126- appendText(" Request write access without callback" )
127- } ? : window.alert(" Unable to load body" )
88+ }
89+ }
90+ }) {
91+ Text (" Answer in chat button" )
92+ }
12893
129- document.body ?.appendElement(" button" ) {
130- addEventListener(" click" , { webApp.requestWriteAccess { document.body ?.log(" Write access request result: $it " ) } })
131- appendText(" Request write access with callback" )
132- } ? : window.alert(" Unable to load body" )
94+ P ()
95+ Text (" Allow to write in private messages: ${webApp.initDataUnsafe.user ?.allowsWriteToPM ? : " User unavailable" } " )
96+
97+ P ()
98+ Text (" Alerts:" )
99+ Button ({
100+ onClick {
101+ webApp.showPopup(
102+ PopupParams (
103+ " It is sample title of default button" ,
104+ " It is sample message of default button" ,
105+ DefaultPopupButton (" default" , " Default button" ),
106+ OkPopupButton (" ok" ),
107+ DestructivePopupButton (" destructive" , " Destructive button" )
108+ )
109+ ) {
110+ logsState.add(
111+ when (it) {
112+ " default" -> " You have clicked default button in popup"
113+ " ok" -> " You have clicked ok button in popup"
114+ " destructive" -> " You have clicked destructive button in popup"
115+ else -> " I can't imagine where you take button with id $it "
116+ }
117+ )
118+ }
119+ }
120+ }) {
121+ Text (" Popup" )
122+ }
123+ Button ({
124+ onClick {
125+ webApp.showAlert(
126+ " This is alert message"
127+ ) {
128+ logsState.add(
129+ " You have closed alert"
130+ )
131+ }
132+ }
133+ }) {
134+ Text (" Alert" )
135+ }
133136
134- document.body ?.appendElement(" p" , {})
137+ P ()
138+ Button ({
139+ onClick {
140+ webApp.requestWriteAccess()
141+ }
142+ }) {
143+ Text (" Request write access without callback" )
144+ }
145+ Button ({
146+ onClick {
147+ webApp.requestWriteAccess {
148+ logsState.add(" Write access request result: $it " )
149+ }
150+ }
151+ }) {
152+ Text (" Request write access with callback" )
153+ }
135154
136- document.body ?.appendElement(" button" ) {
137- addEventListener(" click" , { webApp.requestContact() })
138- appendText(" Request contact without callback" )
139- } ? : window.alert(" Unable to load body" )
155+ P ()
156+ Button ({
157+ onClick {
158+ webApp.requestContact()
159+ }
160+ }) {
161+ Text (" Request contact without callback" )
162+ }
163+ Button ({
164+ onClick {
165+ webApp.requestContact { logsState.add(" Contact request result: $it " ) }
166+ }
167+ }) {
168+ Text (" Request contact with callback" )
169+ }
170+ P ()
140171
141- document.body ?.appendElement( " button " ) {
142- addEventListener( " click " , { webApp.requestContact { document.body ?.log( " Contact request result: $it " ) } })
143- appendText( " Request contact with callback " )
144- } ? : window.alert( " Unable to load body " )
172+ logsState.forEach {
173+ P { Text (it ) }
174+ }
175+ }
145176
146- document.body ?.appendElement(" p" , {})
177+ window.onload = {
178+ val scope = CoroutineScope (Dispatchers .Default )
179+ runCatching {
147180
148181 document.body ?.appendElement(" button" ) {
149182 addEventListener(" click" , {
0 commit comments