From 31d679c1edf49df76ea37a561871af1f5d13572d Mon Sep 17 00:00:00 2001
From: sychic <47618543+Sychic@users.noreply.github.com>
Date: Sun, 31 Dec 2023 14:13:54 -0500
Subject: [PATCH] feat: async states
---
.../gg/skytils/skytilsmod/gui/view/state.kt | 66 +++++++++++++++++++
1 file changed, 66 insertions(+)
create mode 100644 src/main/kotlin/gg/skytils/skytilsmod/gui/view/state.kt
diff --git a/src/main/kotlin/gg/skytils/skytilsmod/gui/view/state.kt b/src/main/kotlin/gg/skytils/skytilsmod/gui/view/state.kt
new file mode 100644
index 000000000..19b5fe341
--- /dev/null
+++ b/src/main/kotlin/gg/skytils/skytilsmod/gui/view/state.kt
@@ -0,0 +1,66 @@
+/*
+ * Skytils - Hypixel Skyblock Quality of Life Mod
+ * Copyright (C) 2020-2023 Skytils
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package gg.skytils.skytilsmod.gui.view
+
+import gg.essential.elementa.state.BasicState
+import gg.essential.elementa.state.MappedState
+import gg.essential.elementa.state.State
+import gg.skytils.skytilsmod.core.mcScope
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
+
+open class LateinitState : State() {
+ internal open var backer: T? = null
+ override fun get(): T =
+ backer ?: error("State should be initialized before get")
+
+ override fun set(value: T) {
+ backer = value
+ super.set(value)
+ }
+}
+
+class AsyncMappedState(val state: State, val scope: CoroutineScope = mcScope, val mapper: suspend (T) -> U, initialValue: U? = null) : LateinitState() {
+ override var backer: U? = initialValue
+
+ private var removeListener = state.onSetValue {
+ scope.launch {
+ set(mapper(it))
+ }
+ }
+
+ init {
+ if (state !is LateinitState) {
+ scope.launch {
+ set(mapper(state.get()))
+ }
+ }
+ }
+
+ fun rebind(newState: State) {
+ removeListener()
+ removeListener = state.onSetValue {
+ scope.launch {
+ set(mapper(it))
+ }
+ }
+ }
+}
+
+fun State.asyncMap(initialValue: U? = null, scope: CoroutineScope = mcScope, mapper: suspend (T) -> U) = AsyncMappedState(this, scope, mapper, initialValue)
\ No newline at end of file