Skip to content

Commit 2025cd7

Browse files
committed
feat(web): add resource preloading for fonts and markdown files
- Add <link rel="preload"> tags in HTML for browser-level caching of all fonts and markdown resources - Implement preloadFont() API in Kotlin to prevent FOUT during app startup - Preload markdown files via produceState() to warm Compose resource cache - Manrope fonts (macosui) preload via separate webMain composable to respect internal visibility - Only render App() after all resources (fonts + markdown) are ready Implements Method 1 (HTML preload) and Method 2 (Compose Multiplatform API) from Kotlin docs: https://kotlinlang.org/docs/multiplatform/compose-web-resources.html#preloading-of-resources-for-web-targets
1 parent 14f668f commit 2025cd7

3 files changed

Lines changed: 60 additions & 2 deletions

File tree

  • macosui/src/webMain/kotlin/io/github/kdroidfilter/nucleus/ui/apple/macos/theme
  • sample/src/webMain
    • kotlin/io/github/kdroidfilter/nucleus/ui/apple/macos/sample
    • resources
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package io.github.kdroidfilter.nucleus.ui.apple.macos.theme
2+
3+
import androidx.compose.runtime.Composable
4+
import androidx.compose.runtime.getValue
5+
import composemacosui.macosui.generated.resources.Res
6+
import composemacosui.macosui.generated.resources.manrope_bold
7+
import composemacosui.macosui.generated.resources.manrope_medium
8+
import composemacosui.macosui.generated.resources.manrope_regular
9+
import composemacosui.macosui.generated.resources.manrope_semibold
10+
import org.jetbrains.compose.resources.ExperimentalResourceApi
11+
import org.jetbrains.compose.resources.preloadFont
12+
13+
@OptIn(ExperimentalResourceApi::class)
14+
@Composable
15+
fun preloadMacosResources(): Boolean {
16+
val regular by preloadFont(Res.font.manrope_regular)
17+
val medium by preloadFont(Res.font.manrope_medium)
18+
val semibold by preloadFont(Res.font.manrope_semibold)
19+
val bold by preloadFont(Res.font.manrope_bold)
20+
return regular != null && medium != null && semibold != null && bold != null
21+
}
Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,36 @@
11
package io.github.kdroidfilter.nucleus.ui.apple.macos.sample
22

3+
import androidx.compose.runtime.getValue
4+
import androidx.compose.runtime.produceState
35
import androidx.compose.ui.ExperimentalComposeUiApi
46
import androidx.compose.ui.window.ComposeViewport
7+
import composemacosui.sample.generated.resources.jetbrains_mono_bold
8+
import composemacosui.sample.generated.resources.jetbrains_mono_regular
9+
import io.github.kdroidfilter.nucleus.ui.apple.macos.theme.preloadMacosResources
10+
import org.jetbrains.compose.resources.ExperimentalResourceApi
11+
import org.jetbrains.compose.resources.preloadFont
12+
import composemacosui.sample.generated.resources.Res as SampleRes
513

6-
@OptIn(ExperimentalComposeUiApi::class)
14+
@OptIn(ExperimentalComposeUiApi::class, ExperimentalResourceApi::class)
715
fun main() {
8-
ComposeViewport { App() }
16+
ComposeViewport {
17+
val macosReady = preloadMacosResources()
18+
val jbMonoRegular by preloadFont(SampleRes.font.jetbrains_mono_regular)
19+
val jbMonoBold by preloadFont(SampleRes.font.jetbrains_mono_bold)
20+
21+
val mdGettingStarted by produceState<ByteArray?>(null) {
22+
value = SampleRes.readBytes("files/getting_started.md")
23+
}
24+
val mdLicense by produceState<ByteArray?>(null) {
25+
value = SampleRes.readBytes("files/license.md")
26+
}
27+
28+
val allReady = macosReady &&
29+
jbMonoRegular != null && jbMonoBold != null &&
30+
mdGettingStarted != null && mdLicense != null
31+
32+
if (allReady) {
33+
App()
34+
}
35+
}
936
}

sample/src/webMain/resources/index.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
66
<title>Compose Mac OS 26 UI</title>
77
<link type="text/css" rel="stylesheet" href="styles.css">
8+
<!-- Fonts -->
9+
<link rel="preload" href="./composeResources/composemacosui.macosui.generated.resources/font/manrope_regular.ttf" as="fetch" type="font/ttf" crossorigin/>
10+
<link rel="preload" href="./composeResources/composemacosui.macosui.generated.resources/font/manrope_medium.ttf" as="fetch" type="font/ttf" crossorigin/>
11+
<link rel="preload" href="./composeResources/composemacosui.macosui.generated.resources/font/manrope_semibold.ttf" as="fetch" type="font/ttf" crossorigin/>
12+
<link rel="preload" href="./composeResources/composemacosui.macosui.generated.resources/font/manrope_bold.ttf" as="fetch" type="font/ttf" crossorigin/>
13+
<link rel="preload" href="./composeResources/composemacosui.sample.generated.resources/font/jetbrains_mono_regular.ttf" as="fetch" type="font/ttf" crossorigin/>
14+
<link rel="preload" href="./composeResources/composemacosui.sample.generated.resources/font/jetbrains_mono_bold.ttf" as="fetch" type="font/ttf" crossorigin/>
15+
<!-- Markdown files -->
16+
<link rel="preload" href="./composeResources/composemacosui.sample.generated.resources/files/getting_started.md" as="fetch" crossorigin/>
17+
<link rel="preload" href="./composeResources/composemacosui.sample.generated.resources/files/license.md" as="fetch" crossorigin/>
818
<style>
919
#boot-screen {
1020
position: fixed;

0 commit comments

Comments
 (0)