Skip to content

Commit e5e1372

Browse files
feat: some TODO implementation
1 parent b4dc27d commit e5e1372

File tree

14 files changed

+1077
-51
lines changed

14 files changed

+1077
-51
lines changed

call-logging/common/src/dev/programadorthi/routing/callloging/MDC.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package dev.programadorthi.routing.callloging
22

3-
// TODO: Do I need MDC in a context like JS and others?
43
public expect object MDC {
54
public fun clear()
65

call-logging/js/src/dev/programadorthi/routing/callloging/MDC.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
package dev.programadorthi.routing.callloging
22

33
public actual object MDC {
4-
// TODO: Is javascript multi thread? I don't know
54
private val current = mutableMapOf<String, String>()
65

76
public actual fun clear() {
87
current.clear()
98
}
109

1110
public actual fun getCopyOfContextMap(): Map<String, String>? {
12-
return current
11+
return current.toMap()
1312
}
1413

1514
public actual fun remove(key: String) {

events-resources/common/test/dev/programadorthi/routing/events/EventResourcesRoutingTest.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,6 @@ class EventResourcesRoutingTest {
279279
}
280280

281281
// WHEN
282-
// TODO: For now, typed event is not supported by parent looking for child. We need to use path based
283282
parent.emitEvent(name = "/child/event_child")
284283
advanceTimeBy(99)
285284

integration/compose-animation/build.gradle.kts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ configureCommon()
1111
configureJvm()
1212
setupJvmToolchain()
1313

14-
// TODO: org.jetbrains.compose.animation has targets limitation. That is the reason to duplicate configs below
1514
kotlin {
1615
explicitApi()
1716

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
package dev.programadorthi.routing.javascript
22

3-
import dev.programadorthi.routing.core.RouteMethod
43
import dev.programadorthi.routing.core.Routing
54
import dev.programadorthi.routing.core.application
6-
import dev.programadorthi.routing.core.application.ApplicationCall
7-
import io.ktor.http.parametersOf
8-
import kotlinx.browser.window
95
import kotlinx.coroutines.flow.MutableStateFlow
106
import kotlinx.coroutines.launch
117
import kotlinx.dom.clear
@@ -27,24 +23,5 @@ public fun render(
2723
}
2824
}
2925

30-
// First time or page refresh we try continue from last state
31-
routing.tryNotifyTheRoute(state = window.history.state)
32-
33-
window.onpopstate = { event ->
34-
routing.tryNotifyTheRoute(state = event.state)
35-
}
36-
}
37-
38-
private fun Routing.tryNotifyTheRoute(state: Any?) {
39-
val javascriptState = state.deserialize() ?: return
40-
val call =
41-
ApplicationCall(
42-
application = application,
43-
name = javascriptState.name,
44-
uri = javascriptState.uri,
45-
routeMethod = RouteMethod.parse(javascriptState.routeMethod),
46-
parameters = parametersOf(javascriptState.parameters),
47-
)
48-
call.neglect = true
49-
execute(call)
26+
JavascriptRoutingStateManager.init(routing)
5027
}

integration/javascript/js/src/dev/programadorthi/routing/javascript/JavascriptRoutingBuilder.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import dev.programadorthi.routing.core.RouteMethod
55
import dev.programadorthi.routing.core.application.ApplicationCall
66
import dev.programadorthi.routing.core.application.application
77
import dev.programadorthi.routing.core.application.call
8+
import dev.programadorthi.routing.core.asRouting
89
import dev.programadorthi.routing.core.route
910
import io.ktor.util.pipeline.PipelineContext
1011
import io.ktor.utils.io.KtorDsl
@@ -28,6 +29,8 @@ public fun Route.jsRoute(
2829

2930
@KtorDsl
3031
public fun Route.jsRoute(body: PipelineContext<Unit, ApplicationCall>.() -> Element) {
32+
val routing = asRouting ?: error("A route must be a Routing child")
33+
3134
handle {
3235
application.routingFlow.emit(body(this))
3336

@@ -50,7 +53,7 @@ public fun Route.jsRoute(body: PipelineContext<Unit, ApplicationCall>.() -> Elem
5053
data = call.serialize(),
5154
)
5255

53-
// TODO: Add support to replace all route method
56+
RouteMethod.ReplaceAll -> JavascriptRoutingStateManager.replaceAll(call, routing)
5457
}
5558
}
5659
}

integration/javascript/js/src/dev/programadorthi/routing/javascript/JavascriptRoutingState.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ internal fun ApplicationCall.serialize(): String {
2727

2828
internal fun Any?.deserialize(): JavascriptRoutingState? =
2929
when (this) {
30-
is String -> Json.decodeFromString(this)
30+
is String -> toState()
3131
else -> null
3232
}
33+
34+
private fun String.toState(): JavascriptRoutingState? =
35+
runCatching {
36+
Json.decodeFromString<JavascriptRoutingState>(this)
37+
}.getOrNull()
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package dev.programadorthi.routing.javascript
2+
3+
import dev.programadorthi.routing.core.RouteMethod
4+
import dev.programadorthi.routing.core.Routing
5+
import dev.programadorthi.routing.core.application
6+
import dev.programadorthi.routing.core.application.ApplicationCall
7+
import io.ktor.http.parametersOf
8+
import kotlinx.browser.window
9+
import kotlinx.coroutines.withTimeout
10+
import kotlin.coroutines.resume
11+
import kotlin.coroutines.suspendCoroutine
12+
13+
internal object JavascriptRoutingStateManager {
14+
fun init(routing: Routing) {
15+
// First time or page refresh we try continue from last state
16+
routing.tryNotifyTheRoute(state = window.history.state)
17+
18+
resetOnPopStateEvent(routing)
19+
}
20+
21+
suspend fun replaceAll(
22+
call: ApplicationCall,
23+
routing: Routing,
24+
) {
25+
while (true) {
26+
window.history.replaceState(
27+
title = "",
28+
url = null,
29+
data = null,
30+
)
31+
window.history.go(-1)
32+
val forceBreak =
33+
runCatching {
34+
withTimeout(1_000) {
35+
suspendCoroutine { continuation ->
36+
window.onpopstate = { event ->
37+
val state = event.state.deserialize()
38+
continuation.resume(state == null)
39+
}
40+
}
41+
}
42+
}.getOrDefault(true)
43+
if (forceBreak) {
44+
break
45+
}
46+
}
47+
48+
window.history.replaceState(
49+
title = "routing",
50+
url = call.uri,
51+
data = call.serialize(),
52+
)
53+
54+
resetOnPopStateEvent(routing)
55+
}
56+
57+
private fun resetOnPopStateEvent(routing: Routing) {
58+
window.onpopstate = { event ->
59+
routing.tryNotifyTheRoute(state = event.state)
60+
}
61+
}
62+
63+
private fun Routing.tryNotifyTheRoute(state: Any?) {
64+
val javascriptState = state.deserialize() ?: return
65+
val call =
66+
ApplicationCall(
67+
application = application,
68+
name = javascriptState.name,
69+
uri = javascriptState.uri,
70+
routeMethod = RouteMethod.parse(javascriptState.routeMethod),
71+
parameters = parametersOf(javascriptState.parameters),
72+
)
73+
call.neglect = true
74+
execute(call)
75+
}
76+
}

integration/voyager/build.gradle.kts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ configureCommon()
1111
configureJvm()
1212
setupJvmToolchain()
1313

14-
// TODO: Voyager has targets limitation. That is the reason to duplicate configs below
1514
kotlin {
1615
explicitApi()
1716

0 commit comments

Comments
 (0)