Skip to content

Commit 7b5d9e4

Browse files
committed
chore: built time improvement by disabling release frameworks
1 parent 9214b3d commit 7b5d9e4

5 files changed

Lines changed: 33 additions & 138 deletions

File tree

example/holder/compose-sample-app/composeApp/build.gradle.kts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import co.touchlab.skie.configuration.SealedInterop
2121
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
2222
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
2323
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFramework
24+
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
2425

2526
plugins {
2627
alias(sphereonplug.plugins.org.jetbrains.kotlin.multiplatform)
@@ -70,7 +71,8 @@ kotlin {
7071
iosArm64(),
7172
iosSimulatorArm64()
7273
).forEach { iosTarget ->
73-
iosTarget.binaries.framework {
74+
// Only build debug framework to avoid slow release linking
75+
iosTarget.binaries.framework(listOf(NativeBuildType.DEBUG)) {
7476
baseName = "KiwaSampleApp"
7577
isStatic = true
7678
xcFramework.add(this)

example/holder/compose-sample-app/composeApp/src/commonMain/kotlin/com/sphereon/kiwa/sample/app/RootPresenterImpl.kt

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package com.sphereon.kiwa.sample.app
1919

2020
import androidx.compose.runtime.Composable
21+
import androidx.compose.runtime.DisposableEffect
2122
import androidx.compose.runtime.LaunchedEffect
2223
import androidx.compose.runtime.collectAsState
2324
import androidx.compose.runtime.remember
@@ -75,9 +76,16 @@ class RootPresenterImpl(
7576

7677
// Set up the navigation trigger with the current backstack scope
7778
// This allows background NFC services to push presenters directly to the backstack
78-
println("RootPresenter: Setting backstack scope on navigation trigger: $backstackRegistry")
79-
println("RootPresenter: Navigation trigger hashCode: ${backstackRegistry.hashCode()}")
80-
backstackRegistry.setBackstackScope(backstackScope)
79+
// IMPORTANT: Use DisposableEffect to avoid recomposition loops and ensure cleanup
80+
DisposableEffect(backstackScope) {
81+
println("RootPresenter: Setting backstack scope on navigation trigger: $backstackRegistry")
82+
println("RootPresenter: Navigation trigger hashCode: ${backstackRegistry.hashCode()}")
83+
backstackRegistry.setBackstackScope(backstackScope)
84+
onDispose {
85+
println("RootPresenter: Clearing backstack scope from navigation trigger")
86+
backstackRegistry.setBackstackScope(null)
87+
}
88+
}
8189

8290
backstackModelToTemplate(backstackModel)
8391
}

example/holder/compose-sample-app/iosApp/iosApp.xcodeproj/project.pbxproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@
152152
);
153153
runOnlyForDeploymentPostprocessing = 0;
154154
shellPath = /bin/sh;
155-
shellScript = "if [ \"YES\" = \"$OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED\" ]; then\n echo \"Skipping Gradle build task invocation due to OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED environment variable set to \\\"YES\\\"\"\n exit 0\nfi\ncd \"$SRCROOT/../../../..\"\n./gradlew :example:holder:app:kiwa-example-holder-app-composeApp:embedAndSignAppleFrameworkForXcode\n";
155+
shellScript = "if [ \"YES\" = \"$OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED\" ]; then\n echo \"Skipping Gradle build task invocation due to OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED environment variable set to \\\"YES\\\"\"\n exit 0\nfi\ncd \"$SRCROOT/../../../..\"\n# Force debug framework to avoid slow release linking\nexport CONFIGURATION=Debug\n./gradlew :example:holder:compose-sample-app:kiwa-example-holder-compose-sample-app-composeApp:embedAndSignAppleFrameworkForXcode\n";
156156
};
157157
/* End PBXShellScriptBuildPhase section */
158158

@@ -334,7 +334,7 @@
334334
ENABLE_PREVIEWS = YES;
335335
FRAMEWORK_SEARCH_PATHS = (
336336
"$(inherited)",
337-
"$(SRCROOT)/../composeApp/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)",
337+
"$(SRCROOT)/../composeApp/build/xcode-frameworks/Debug/$(SDK_NAME)",
338338
);
339339
GENERATE_INFOPLIST_FILE = YES;
340340
INFOPLIST_FILE = iosApp/Info.plist;

example/holder/swift-sample-app/kiwa-swift-sample.xcodeproj/xcshareddata/xcschemes/kiwa-swift-sample.xcscheme

Lines changed: 0 additions & 119 deletions
This file was deleted.

example/holder/ui/elicense/impl/src/commonMain/kotlin/com/sphereon/kiwa/sample/ui/elicense/engagement/qr/MdocEngagementPresenterImpl.kt

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -81,19 +81,22 @@ class MdocEngagementPresenterImpl(
8181
var sessionState by remember { mutableStateOf(engagementManager.eventHub.sessionState.value) }
8282
var activeEngagement by remember { mutableStateOf(engagementManager.activeEngagement.value) }
8383

84-
// Collect session state - the renderer has a keepalive animation that keeps
85-
// CADisplayLink firing, ensuring state changes trigger Molecule recomposition
84+
// Collect session state from the engagement manager
85+
// StateFlow already guarantees distinct values by design
8686
LaunchedEffect(engagementManager) {
87-
engagementManager.eventHub.sessionState.collect { state ->
88-
sessionState = state
89-
}
87+
engagementManager.eventHub.sessionState
88+
.collect { state ->
89+
sessionState = state
90+
}
9091
}
9192

9293
// Collect active engagement
94+
// StateFlow already guarantees distinct values by design
9395
LaunchedEffect(engagementManager) {
94-
engagementManager.activeEngagement.collect { eng ->
95-
activeEngagement = eng
96-
}
96+
engagementManager.activeEngagement
97+
.collect { eng ->
98+
activeEngagement = eng
99+
}
97100
}
98101

99102
// Log the current values on every recomposition for debugging
@@ -102,12 +105,12 @@ class MdocEngagementPresenterImpl(
102105
// Track QR scanner mode - use rememberSaveable like BackstackChildPresenter for proper state tracking on iOS
103106
var showQrScanner by rememberSaveable { mutableStateOf(false) }
104107

105-
// Track recomposition count for debugging - use rememberSaveable for consistency
106-
var recompositionCount by rememberSaveable { mutableStateOf(0) }
107-
recompositionCount++
108+
// Track recomposition count for debugging - use remember with a holder object to avoid state mutation
109+
val recompositionCounter = remember { object { var count = 0 } }
110+
recompositionCounter.count++
108111

109112
// Log state on every recomposition to understand state transitions
110-
log.debug("=== PRESENTER RECOMPOSITION #$recompositionCount ===")
113+
log.debug("=== PRESENTER RECOMPOSITION #${recompositionCounter.count} ===")
111114
log.debug("Engagement Manager Instance: ${engagementManager.hashCode()}")
112115
log.debug("SessionUiState: phase=${sessionState.phase}, qrMode=${sessionState.qrMode}, nfcMode=${sessionState.nfcMode}, userInteractionRequired=${sessionState.userInteractionRequired}, terminalOutcome=${sessionState.terminalOutcome}")
113116
log.debug("ActiveEngagement: ${activeEngagement?.id ?: "null"}")
@@ -347,7 +350,8 @@ class MdocEngagementPresenterImpl(
347350
}
348351

349352
// Track if we've ever had an active engagement in this presenter session
350-
val hasHadEngagement = remember { mutableStateOf(false) }
353+
// Use a holder object to avoid triggering recomposition when tracking this value
354+
val hasHadEngagement = remember { object { var value = false } }
351355
if (activeEngagement != null && !hasHadEngagement.value) {
352356
hasHadEngagement.value = true
353357
}

0 commit comments

Comments
 (0)