fix: move ML Kit translation off the UI dispatcher

LaunchedEffect runs on Dispatchers.Main by default. The first call to
LanguageTranslatorService triggers its class init, which loads a Properties
file from inside the play-services AAR via ZipFile/RandomAccessFile and
trips StrictMode's DiskReadViolation on the UI thread.

Wrap the translateAndCache call in withContext(Dispatchers.IO) so MLKit's
first-touch init happens off the UI dispatcher.
This commit is contained in:
Claude
2026-05-28 15:52:21 +00:00
parent b9bc21d78e
commit b1da3c2161
@@ -39,8 +39,10 @@ import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.theme.MaxWidthPaddingTop5dp
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.tasks.await
import kotlinx.coroutines.withContext
import kotlin.coroutines.coroutineContext
@Composable
@@ -101,7 +103,13 @@ fun TranslatableRichTextViewer(
LaunchedEffect(content, translateTo, dontTranslateFrom) {
try {
translatedTextState.value = translateAndCache(content, translateTo, dontTranslateFrom)
// ML Kit's first-touch class init reads a Properties file out of the play-services AAR
// via ZipFile/RandomAccessFile, which trips StrictMode if it runs on the UI dispatcher
// that LaunchedEffect uses by default.
translatedTextState.value =
withContext(Dispatchers.IO) {
translateAndCache(content, translateTo, dontTranslateFrom)
}
} catch (e: CancellationException) {
throw e
} catch (_: Exception) {