Skip to content

Commit 5aceaff

Browse files
committed
Add ktor js client to experiments. Restructuring application
1 parent 3ba4e8f commit 5aceaff

File tree

9 files changed

+171
-36
lines changed

9 files changed

+171
-36
lines changed

build.gradle.kts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ kotlin {
4242
implementation(compose.runtime)
4343
implementation(compose.html.core)
4444
implementation(libs.router)
45+
implementation(libs.ktor.client.core)
46+
implementation(libs.ktor.client.js)
47+
implementation(libs.ktor.client.logging)
48+
implementation(libs.ktor.client.content.negotiation)
49+
implementation(libs.ktor.serialization.kotlinx.json)
4550
implementation(npm("hiq", "4.2.11"))
4651
}
4752

gradle/libs.versions.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ compose = "1.6.11"
44
kotlinx-html = "0.11.0"
55
kotlinx-serialization = "1.6.0"
66
router = "0.2.14"
7+
ktor = "2.3.12"
78

89
[libraries]
910
kotlin-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.strictly = "1.8.0" }
@@ -18,6 +19,12 @@ kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serializa
1819

1920
router = { module = "app.softwork:routing-compose", version.ref = "router" }
2021

22+
ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
23+
ktor-client-js = { module = "io.ktor:ktor-client-js", version.ref = "ktor" }
24+
ktor-client-logging = { module = "io.ktor:ktor-client-logging", version.ref = "ktor" }
25+
ktor-client-content-negotiation = { module = "io.ktor:ktor-client-content-negotiation", version.ref = "ktor" }
26+
ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" }
27+
2128
[plugins]
2229
jetbrains-compose = { id = "org.jetbrains.compose", version.ref = "compose" }
2330
jetbrains-compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }

src/jsMain/kotlin/Application.kt

Lines changed: 33 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
1-
import androidx.compose.runtime.getValue
2-
import androidx.compose.runtime.mutableStateOf
3-
import androidx.compose.runtime.remember
4-
import androidx.compose.runtime.setValue
51
import app.softwork.routingcompose.BrowserRouter
6-
import app.softwork.routingcompose.NavLink
7-
import app.softwork.routingcompose.Router
82
import common.BaseStyles
93
import common.Theme
104
import common.ThemeProvider
@@ -13,12 +7,34 @@ import components.Layout
137
import components.PageContent
148
import components.PageFooter
159
import components.PageHeader
10+
import domain.cat.CatServiceKtor
11+
import domain.cat.CatServiceMock
12+
import io.ktor.client.*
13+
import io.ktor.client.engine.js.*
14+
import io.ktor.client.plugins.contentnegotiation.*
15+
import io.ktor.client.plugins.logging.*
16+
import io.ktor.serialization.kotlinx.json.*
17+
import kotlinx.serialization.json.Json
1618
import org.jetbrains.compose.web.css.Color
1719
import org.jetbrains.compose.web.css.Style
18-
import org.jetbrains.compose.web.dom.*
20+
import org.jetbrains.compose.web.dom.Div
21+
import org.jetbrains.compose.web.dom.H1
22+
import org.jetbrains.compose.web.dom.Style
23+
import org.jetbrains.compose.web.dom.Text
1924
import org.jetbrains.compose.web.renderComposableInBody
25+
import pages.CatFactPage
26+
import pages.HelloWorldPage
27+
import pages.HomePage
2028

2129
fun main() {
30+
val client =
31+
HttpClient(Js) {
32+
install(ContentNegotiation) {
33+
json(Json { ignoreUnknownKeys = true })
34+
}
35+
install(Logging)
36+
}
37+
2238
renderComposableInBody {
2339
Style {
2440
root {
@@ -52,38 +68,19 @@ fun main() {
5268
PageContent {
5369
BrowserRouter("/") {
5470
route("/") {
55-
NavLink("/hello-world") {
56-
Text("To Hello world!")
57-
}
71+
HomePage()
5872
}
5973
route("/hello-world") {
60-
val params = parameters?.map
61-
var counter: Int by remember { mutableStateOf(0) }
62-
Div {
63-
params?.map {
64-
Div {
65-
Span { Text("Param: ${it.key}: ${it.value}") }
66-
}
67-
}
68-
}
69-
Div {
70-
Text("Hello World $counter")
71-
}
72-
Div {
73-
Span {
74-
components.Button("Increment") {
75-
counter++
76-
}
77-
}
78-
}
79-
Div {
80-
Span {
81-
val router = Router.current
82-
components.Button("Back") {
83-
router.navigate("/")
84-
}
74+
HelloWorldPage()
75+
}
76+
route("/cat-fact") {
77+
val catServiceType = parameters?.map?.get("type")?.firstOrNull() ?: "impl"
78+
val catService =
79+
when (catServiceType) {
80+
"mock" -> CatServiceMock()
81+
else -> CatServiceKtor(client)
8582
}
86-
}
83+
CatFactPage(catService)
8784
}
8885
}
8986
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package domain.cat
2+
3+
import kotlinx.serialization.Serializable
4+
5+
interface CatService {
6+
suspend fun getRandomCatFact(): CatFact
7+
}
8+
9+
@Serializable
10+
data class CatFact(
11+
val fact: String,
12+
)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package domain.cat
2+
3+
import io.ktor.client.*
4+
import io.ktor.client.call.*
5+
import io.ktor.client.request.*
6+
7+
class CatServiceKtor(
8+
val client: HttpClient,
9+
) : CatService {
10+
override suspend fun getRandomCatFact(): CatFact = client.get("https://catfact.ninja/fact").body()
11+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package domain.cat
2+
3+
class CatServiceMock : CatService {
4+
override suspend fun getRandomCatFact(): CatFact = CatFact("Cat has 9 lives")
5+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package pages
2+
3+
import androidx.compose.runtime.*
4+
import app.softwork.routingcompose.Router
5+
import domain.cat.CatFact
6+
import domain.cat.CatService
7+
import kotlinx.coroutines.launch
8+
import org.jetbrains.compose.web.dom.Div
9+
import org.jetbrains.compose.web.dom.Span
10+
import org.jetbrains.compose.web.dom.Text
11+
12+
@Composable
13+
fun CatFactPage(catService: CatService) {
14+
val coroutineScope = rememberCoroutineScope()
15+
var catFact by remember { mutableStateOf<CatFact?>(null) }
16+
17+
fun updateFact() {
18+
coroutineScope.launch {
19+
catFact = catService.getRandomCatFact()
20+
}
21+
}
22+
23+
updateFact()
24+
25+
Div {
26+
Text("Cat fact: ${catFact?.fact ?: "Not loaded yet"}")
27+
}
28+
Div {
29+
Span {
30+
components.Button("Get new fact") {
31+
updateFact()
32+
}
33+
}
34+
}
35+
Div {
36+
Span {
37+
val router = Router.current
38+
components.Button("Back") {
39+
router.navigate("/")
40+
}
41+
}
42+
}
43+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package pages
2+
3+
import androidx.compose.runtime.*
4+
import app.softwork.routingcompose.RouteBuilder
5+
import app.softwork.routingcompose.Router
6+
import org.jetbrains.compose.web.dom.Div
7+
import org.jetbrains.compose.web.dom.Span
8+
import org.jetbrains.compose.web.dom.Text
9+
10+
context(RouteBuilder)
11+
@Composable
12+
fun HelloWorldPage() {
13+
val params = parameters?.map
14+
var counter: Int by remember { mutableStateOf(0) }
15+
Div {
16+
params?.map {
17+
Div {
18+
Span { Text("Param: ${it.key}: ${it.value}") }
19+
}
20+
}
21+
}
22+
Div {
23+
Text("Hello World $counter")
24+
}
25+
Div {
26+
Span {
27+
components.Button("Increment") {
28+
counter++
29+
}
30+
}
31+
}
32+
Div {
33+
Span {
34+
val router = Router.current
35+
components.Button("Back") {
36+
router.navigate("/")
37+
}
38+
}
39+
}
40+
}

src/jsMain/kotlin/pages/HomePage.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package pages
2+
3+
import androidx.compose.runtime.Composable
4+
import app.softwork.routingcompose.NavLink
5+
import org.jetbrains.compose.web.dom.Text
6+
7+
@Composable
8+
fun HomePage() {
9+
NavLink("/hello-world") {
10+
Text("To Hello world!")
11+
}
12+
NavLink("/cat-fact") {
13+
Text("To Cat Facts!")
14+
}
15+
}

0 commit comments

Comments
 (0)