package info.mechyrdia.mapviewer
-import kotlinx.coroutines.*
-
-val AppScope = MainScope() + CoroutineExceptionHandler { ctx, ex ->
- val coroName = ctx[CoroutineName]?.name?.let { "coroutine $it" } ?: "unnamed coroutine"
- console.warn("Unhandled exception in $coroName", ex)
- ex.printStackTrace()
-}
+import kotlinx.coroutines.async
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.supervisorScope
lateinit var galaxyMap: GalaxyMap
lateinit var galaxyLore: GalaxyLore
-fun main() {
- AppScope.launch {
+suspend fun main() {
+ supervisorScope {
val ptrProvider = initPopHistoryEntryHandler()
val (map, lore) = showLoadingScreen {
- coroutineScope {
- launch { loadFlags() }
- launch { loadUiImages() }
- launch { loadCelestialBodyFactories() }
- launch { loadSpaceboxes() }
-
- val loreJson = async { loadJson("/assets/map/lore.json", GalaxyLore.serializer()) }
- loadJson("/assets/map/map.json", GalaxyMap.serializer()).also {
- launch {
- loadGalaxyBgTextures(it.background)
- }
- } to loreJson.await()
- }
+ launch { loadFlags() }
+ launch { loadUiImages() }
+ launch { loadCelestialBodyFactories() }
+ launch { loadSpaceboxes() }
+
+ val loreJson = async { loadJson("/assets/map/lore.json", GalaxyLore.serializer()) }
+ loadJson("/assets/map/map.json", GalaxyMap.serializer()).also {
+ launch {
+ loadGalaxyBgTextures(it.background)
+ }
+ } to loreJson.await()
}
galaxyMap = map
lateinit var ptr: MapObjectPtr
}
-private var isHandlingPopState = true
+private var shouldNotPushHistoryEntry = true
fun doneInitialRender() {
- isHandlingPopState = false
+ shouldNotPushHistoryEntry = false
}
fun URLSearchParams.toMapObjectPtr(): MapObjectPtr {
val statePtr = JsonCodec.decodeFromDynamic(MapObjectPtr.serializer(), ev.state)
if (isRenderActive) {
- isHandlingPopState = true
+ shouldNotPushHistoryEntry = true
renderMap(statePtr)
- isHandlingPopState = false
+ shouldNotPushHistoryEntry = false
} else
ptrHolder.ptr = statePtr
})
@OptIn(ExperimentalSerializationApi::class)
fun pushHistoryEntry(ptr: MapObjectPtr) {
- if (isHandlingPopState)
+ if (shouldNotPushHistoryEntry)
return
val state = JsonCodec.encodeToDynamic(MapObjectPtr.serializer(), ptr)
package info.mechyrdia.mapviewer
import kotlinx.browser.document
-import kotlinx.coroutines.cancelAndJoin
-import kotlinx.coroutines.coroutineScope
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.suspendCancellableCoroutine
+import kotlinx.coroutines.*
import kotlinx.dom.clear
import kotlinx.html.*
import kotlinx.html.dom.append
}
}
-suspend fun <T> showLoadingScreen(label: String = "Loading...", loader: suspend () -> T): T {
+suspend fun <T> showLoadingScreen(label: String = "Loading...", loader: suspend CoroutineScope.() -> T): T {
return coroutineScope {
val showingBox = launch {
showModalBox { _ ->
const val MAX_QUERY_RESULTS = 10
private fun getMatches(name: String, query: String): List<IntRange> {
- return Regex.fromLiteral(query).findAll(name).map { it.range }.toList()
+ return Regex.fromLiteral(query).findAll(name).map { it.range }.toList().sortedBy { it.first }
}
suspend fun searchGalaxy(query: String): List<SearchResult> {