Skip to content

Commit 8a0881e

Browse files
fix(android): move validateAndGetIterations before launchers, fix stale state capture
Two issues fixed: 1. validateAndGetIterations() was defined AFTER the CreateDocument launchers that reference it — Kotlin/K2 compiler may reject forward references to local functions from within Composable lambda captures. Move the function (and isZh) before the launcher declarations. 2. Launcher callbacks captured password/algorithm from outer val (snapshot at composition time = empty string). Use homeViewModel.password.value / .algorithm.value to read the latest values when the callback actually fires. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 5def9e5 commit 8a0881e

1 file changed

Lines changed: 31 additions & 19 deletions

File tree

  • android/app/src/main/java/com/example/encryptapp/ui/screens

android/app/src/main/java/com/example/encryptapp/ui/screens/HomeScreen.kt

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,37 @@ fun HomeScreen(
6161
var decFileUri by remember { mutableStateOf<Uri?>(null) }
6262
var decFileName by remember { mutableStateOf("") }
6363

64+
val isZh = language == "zh"
65+
66+
// Shared helper — must be defined BEFORE the CreateDocument launchers below
67+
fun validateAndGetIterations(): Int? {
68+
val v = homeViewModel.validateIterations()
69+
return if (v is IterationsValidation.Valid) {
70+
v.value
71+
} else {
72+
Toast.makeText(
73+
context,
74+
if (isZh) "无效的迭代次数!" else "Invalid iterations!",
75+
Toast.LENGTH_SHORT
76+
).show()
77+
null
78+
}
79+
}
80+
6481
// CreateDocument launchers for output file selection (SAF write permission)
6582
val encOutputLauncher = rememberLauncherForActivityResult(
6683
contract = ActivityResultContracts.CreateDocument("application/octet-stream")
6784
) { outputUri: Uri? ->
6885
outputUri?.let { outUri ->
6986
encFileUri?.let { inUri ->
7087
validateAndGetIterations()?.let { iters ->
71-
fileOpsViewModel.encryptFile(inUri, outUri, password, algorithm, iters) { success, path ->
88+
// Read latest values from ViewModel to avoid stale captured vars
89+
fileOpsViewModel.encryptFile(
90+
inUri, outUri,
91+
homeViewModel.password.value,
92+
homeViewModel.algorithm.value,
93+
iters
94+
) { success, path ->
7295
if (success) {
7396
val msg = if (isZh) "保存至: $path" else "Saved to: $path"
7497
Toast.makeText(context, msg, Toast.LENGTH_LONG).show()
@@ -85,7 +108,13 @@ fun HomeScreen(
85108
outputUri?.let { outUri ->
86109
decFileUri?.let { inUri ->
87110
validateAndGetIterations()?.let { iters ->
88-
fileOpsViewModel.decryptFile(inUri, outUri, password, algorithm, iters) { success, path ->
111+
// Read latest values from ViewModel to avoid stale captured vars
112+
fileOpsViewModel.decryptFile(
113+
inUri, outUri,
114+
homeViewModel.password.value,
115+
homeViewModel.algorithm.value,
116+
iters
117+
) { success, path ->
89118
if (success) {
90119
val msg = if (isZh) "保存至: $path" else "Saved to: $path"
91120
Toast.makeText(context, msg, Toast.LENGTH_LONG).show()
@@ -96,23 +125,6 @@ fun HomeScreen(
96125
}
97126
}
98127

99-
val isZh = language == "zh"
100-
101-
// Shared helper to validate and get iterations (used by launchers and panels)
102-
fun validateAndGetIterations(): Int? {
103-
val v = homeViewModel.validateIterations()
104-
return if (v is IterationsValidation.Valid) {
105-
v.value
106-
} else {
107-
Toast.makeText(
108-
context,
109-
if (isZh) "无效的迭代次数!" else "Invalid iterations!",
110-
Toast.LENGTH_SHORT
111-
).show()
112-
null
113-
}
114-
}
115-
116128
BoxWithConstraints(
117129
modifier = Modifier.fillMaxSize(),
118130
contentAlignment = Alignment.TopStart

0 commit comments

Comments
 (0)