diff --git a/WebApp/src/jsMain/kotlin/main.kt b/WebApp/src/jsMain/kotlin/main.kt index b5206e7..609850c 100644 --- a/WebApp/src/jsMain/kotlin/main.kt +++ b/WebApp/src/jsMain/kotlin/main.kt @@ -1,7 +1,5 @@ import androidx.compose.runtime.* import dev.inmo.micro_utils.coroutines.launchLoggingDropExceptions -import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions -import dev.inmo.tgbotapi.types.CustomEmojiId import dev.inmo.tgbotapi.types.userIdField import dev.inmo.tgbotapi.types.webAppQueryIdField import dev.inmo.tgbotapi.webapps.* @@ -13,7 +11,6 @@ import dev.inmo.tgbotapi.webapps.haptic.HapticFeedbackStyle import dev.inmo.tgbotapi.webapps.haptic.HapticFeedbackType import dev.inmo.tgbotapi.webapps.orientation.DeviceOrientationStartParams import dev.inmo.tgbotapi.webapps.popup.* -import dev.inmo.tgbotapi.webapps.storage.getWithResult import io.ktor.client.HttpClient import io.ktor.client.request.* import io.ktor.client.statement.bodyAsText @@ -26,13 +23,11 @@ import kotlinx.dom.appendText import kotlinx.serialization.json.Json import org.jetbrains.compose.web.attributes.InputType import org.jetbrains.compose.web.attributes.placeholder -import org.jetbrains.compose.web.css.DisplayStyle import org.jetbrains.compose.web.css.Style import org.jetbrains.compose.web.css.StyleSheet import org.jetbrains.compose.web.css.Color as ComposeColor import org.jetbrains.compose.web.css.backgroundColor import org.jetbrains.compose.web.css.color -import org.jetbrains.compose.web.css.display import org.jetbrains.compose.web.dom.* import org.jetbrains.compose.web.dom.Text import org.jetbrains.compose.web.renderComposable @@ -108,6 +103,7 @@ fun main() { P() Text("Chat from WebAppInitData: ${webApp.initDataUnsafe.chat}") + H3 { Text("Emoji status management") } val emojiStatusAccessState = remember { mutableStateOf(false) } webApp.onEmojiStatusAccessRequested { emojiStatusAccessState.value = it.isAllowed @@ -148,7 +144,9 @@ fun main() { } } } + P() + H3 { Text("Call server method with webAppQueryIdField") } Button({ onClick { scope.launchLoggingDropExceptions { @@ -166,10 +164,11 @@ fun main() { } P() + H3 { Text("User info") } Text("Allow to write in private messages: ${webApp.initDataUnsafe.user ?.allowsWriteToPM ?: "User unavailable"}") P() - Text("Alerts:") + H3 { Text("Alerts") } Button({ onClick { webApp.showPopup( @@ -207,8 +206,22 @@ fun main() { }) { Text("Alert") } + Button({ + onClick { + webApp.showConfirm( + "This is confirm message" + ) { + logsState.add( + "You have pressed \"${if (it) "Ok" else "Cancel"}\" in confirm" + ) + } + } + }) { + Text("Confirm") + } P() + H3 { Text("Write access callbacks") } Button({ onClick { webApp.requestWriteAccess() @@ -227,6 +240,7 @@ fun main() { } P() + H3 { Text("Request contact") } Button({ onClick { webApp.requestContact() @@ -241,24 +255,9 @@ fun main() { }) { Text("Request contact with callback") } - P() - - Button({ - onClick { - webApp.showConfirm( - "This is confirm message" - ) { - logsState.add( - "You have pressed \"${if (it) "Ok" else "Cancel"}\" in confirm" - ) - } - } - }) { - Text("Confirm") - } P() - + H3 { Text("Closing confirmation") } val isClosingConfirmationEnabledState = remember { mutableStateOf(webApp.isClosingConfirmationEnabled) } Button({ onClick { @@ -276,7 +275,7 @@ fun main() { } P() - + H3 { Text("Colors") } val headerColor = remember { mutableStateOf(Color.Hex("#000000")) } fun updateHeaderColor() { val (r, g, b) = Random.nextUBytes(3) @@ -301,7 +300,6 @@ fun main() { } P() - val backgroundColor = remember { mutableStateOf(Color.Hex("#000000")) } fun updateBackgroundColor() { val (r, g, b) = Random.nextUBytes(3) @@ -326,7 +324,6 @@ fun main() { } P() - val bottomBarColor = remember { mutableStateOf(Color.Hex("#000000")) } fun updateBottomBarColor() { val (r, g, b) = Random.nextUBytes(3) @@ -350,60 +347,6 @@ fun main() { } } - P() - - val storageTrigger = remember { mutableStateOf>>(emptyList()) } - fun updateCloudStorage() { - webApp.cloudStorage.getAll { - it.onSuccess { - storageTrigger.value = it.toList().sortedBy { it.first.key } - } - } - } - key(storageTrigger.value) { - storageTrigger.value.forEach { (key, value) -> - val keyState = remember { mutableStateOf(key.key) } - val valueState = remember { mutableStateOf(value.value) } - Input(InputType.Text) { - value(key.key) - onInput { keyState.value = it.value } - } - Input(InputType.Text) { - value(value.value) - onInput { valueState.value = it.value } - } - Button({ - onClick { - if (key.key != keyState.value) { - webApp.cloudStorage.remove(key) - } - webApp.cloudStorage.set(keyState.value, valueState.value) - updateCloudStorage() - } - }) { - Text("Save") - } - } - let { // new element adding - val keyState = remember { mutableStateOf("") } - val valueState = remember { mutableStateOf("") } - Input(InputType.Text) { - onInput { keyState.value = it.value } - } - Input(InputType.Text) { - onInput { valueState.value = it.value } - } - Button({ - onClick { - webApp.cloudStorage.set(keyState.value, valueState.value) - updateCloudStorage() - } - }) { - Text("Save") - } - } - } - remember { webApp.apply { @@ -453,9 +396,10 @@ fun main() { } } } - P() - let { // Accelerometer + P() + let { + H3 { Text("Accelerometer") } val enabledState = remember { mutableStateOf(webApp.accelerometer.isStarted) } webApp.onAccelerometerStarted { enabledState.value = true } webApp.onAccelerometerStopped { enabledState.value = false } @@ -496,7 +440,8 @@ fun main() { } P() - let { // Gyroscope + let { + H3 { Text("Gyroscope") } val enabledState = remember { mutableStateOf(webApp.gyroscope.isStarted) } webApp.onGyroscopeStarted { enabledState.value = true } webApp.onGyroscopeStopped { enabledState.value = false } @@ -535,9 +480,10 @@ fun main() { Text("z: ${zState.value}") } } - P() - let { // DeviceOrientation + P() + let { + H3 { Text("Device Orientation") } val enabledState = remember { mutableStateOf(webApp.deviceOrientation.isStarted) } webApp.onDeviceOrientationStarted { enabledState.value = true } webApp.onDeviceOrientationStopped { enabledState.value = false } @@ -576,9 +522,64 @@ fun main() { Text("gamma: ${gammaState.value}") } } - P() + P() + H3 { Text("Cloud storage") } + val storageTrigger = remember { mutableStateOf>>(emptyList()) } + fun updateCloudStorage() { + webApp.cloudStorage.getAll { + it.onSuccess { + storageTrigger.value = it.toList().sortedBy { it.first.key } + } + } + } + key(storageTrigger.value) { + storageTrigger.value.forEach { (key, value) -> + val keyState = remember { mutableStateOf(key.key) } + val valueState = remember { mutableStateOf(value.value) } + Input(InputType.Text) { + value(key.key) + onInput { keyState.value = it.value } + } + Input(InputType.Text) { + value(value.value) + onInput { valueState.value = it.value } + } + Button({ + onClick { + if (key.key != keyState.value) { + webApp.cloudStorage.remove(key) + } + webApp.cloudStorage.set(keyState.value, valueState.value) + updateCloudStorage() + } + }) { + Text("Save") + } + } + let { // new element adding + val keyState = remember { mutableStateOf("") } + val valueState = remember { mutableStateOf("") } + Input(InputType.Text) { + onInput { keyState.value = it.value } + } + Input(InputType.Text) { + onInput { valueState.value = it.value } + } + Button({ + onClick { + webApp.cloudStorage.set(keyState.value, valueState.value) + updateCloudStorage() + } + }) { + Text("Save") + } + } + } + + P() let { // DeviceStorage + H3 { Text("Device storage") } val fieldKey = remember { mutableStateOf("") } val fieldValue = remember { mutableStateOf("") } val message = remember { mutableStateOf("") } @@ -624,6 +625,78 @@ fun main() { } P() + let { // DeviceStorage + H3 { Text("Secure storage") } + val fieldKey = remember { mutableStateOf("") } + val fieldValue = remember { mutableStateOf("") } + val message = remember { mutableStateOf("") } + val restorableState = remember { mutableStateOf(false) } + Div { + Text("Start type title of key. If value will be found in device storage, it will be shown in value input") + } + + Input(InputType.Text) { + placeholder("Key") + value(fieldKey.value) + onInput { + fieldKey.value = it.value + webApp.secureStorage.getItem(it.value) { e, v, restorable -> + fieldValue.value = v ?: "" + restorableState.value = restorable == true + if (v == null) { + if (restorable == true) { + message.value = "Value for key \"${it.value}\" has not been found, but can be restored" + } else { + message.value = "Value for key \"${it.value}\" has not been found. Error: $e" + } + } else { + message.value = "Value for key \"${it.value}\" has been found: \"$v\"" + } + } + } + } + if (restorableState.value) { + Button({ + onClick { + webApp.secureStorage.restoreItem(fieldKey.value) { e, v -> + fieldValue.value = v ?: "" + if (v == null) { + message.value = "Value for key \"${fieldKey.value}\" has not been restored. Error: $e" + } else { + message.value = "Value for key \"${fieldKey.value}\" has been restored: \"$v\"" + } + } + } + }) { + Text("Restore") + } + } + Div { + Text("If you want to change value if typed key - just put it here") + } + Input(InputType.Text) { + placeholder("Value") + value(fieldValue.value) + onInput { + fieldValue.value = it.value + webApp.secureStorage.setItem(fieldKey.value, it.value) { e, v -> + if (v) { + fieldValue.value = it.value + message.value = "Value \"${it.value}\" has been saved" + } else { + message.value = "Value \"${it.value}\" has not been saved. Error: $e" + } + } + } + } + + if (message.value.isNotEmpty()) { + Div { Text(message.value) } + } + } + P() + + H3 { Text("Events") } EventType.values().forEach { eventType -> when (eventType) { EventType.AccelerometerChanged -> webApp.onAccelerometerChanged { /*logsState.add("AccelerometerChanged") /* see accelerometer block */ */ } diff --git a/gradle.properties b/gradle.properties index 32a639e..44428a1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ kotlin.daemon.jvmargs=-Xmx3g -Xms500m kotlin_version=2.1.20 -telegram_bot_api_version=25.0.0-rc2 +telegram_bot_api_version=25.0.0-rc3 micro_utils_version=0.25.3 serialization_version=1.8.0 ktor_version=3.1.1