From d5de3374ee5dc4dc8ca8c5477b2861d0e16ca5fb Mon Sep 17 00:00:00 2001 From: tafelnl <35837839+tafelnl@users.noreply.github.com> Date: Tue, 7 May 2024 14:26:02 +0200 Subject: [PATCH] fix: execute methods on UI thread --- .../community/safearea/SafeArea.kt | 93 +++++++++++-------- 1 file changed, 53 insertions(+), 40 deletions(-) diff --git a/android/src/main/java/com/getcapacitor/community/safearea/SafeArea.kt b/android/src/main/java/com/getcapacitor/community/safearea/SafeArea.kt index 1914f185..2f0d907d 100644 --- a/android/src/main/java/com/getcapacitor/community/safearea/SafeArea.kt +++ b/android/src/main/java/com/getcapacitor/community/safearea/SafeArea.kt @@ -11,15 +11,20 @@ import androidx.core.view.WindowInsetsCompat class SafeArea(private val activity: Activity, private val webView: WebView) { var offset = 0 + private var appearanceUpdatedInListener = false fun enable(updateInsets: Boolean, appearanceConfig: AppearanceConfig) { activity.window.decorView.getRootView().setOnApplyWindowInsetsListener { view, insets -> updateInsets() - // @TODO: appearance is sometimes not updated on app load - // probably because it is superseded by another plugin or native thing that updates the appearance - // This is probably not the best way to override that behaviour - // So we should think of something better than simply calling `updateAppearance` here - updateAppearance(appearanceConfig) + if (!appearanceUpdatedInListener) { + // @TODO: appearance is sometimes not updated on app load + // probably because it is superseded by another plugin or native thing that updates the appearance + // This is probably not the best way to override that behaviour + // So we should think of something better than simply calling `updateAppearance` here + updateAppearance(appearanceConfig) + // Only update it once, to prevent an infinite loop + appearanceUpdatedInListener = true + } view.onApplyWindowInsets(insets) } @@ -31,7 +36,9 @@ class SafeArea(private val activity: Activity, private val webView: WebView) { } fun disable(appearanceConfig: AppearanceConfig) { - WindowCompat.setDecorFitsSystemWindows(activity.window, true) + activity.runOnUiThread { + WindowCompat.setDecorFitsSystemWindows(activity.window, true) + } activity.window.decorView.getRootView().setOnApplyWindowInsetsListener(null) resetProperties() @@ -39,44 +46,48 @@ class SafeArea(private val activity: Activity, private val webView: WebView) { } private fun updateAppearance(appearanceConfig: AppearanceConfig) { - val windowInsetsControllerCompat = - WindowCompat.getInsetsController(activity.window, activity.window.decorView) - windowInsetsControllerCompat.isAppearanceLightStatusBars = - appearanceConfig.statusBarContent == "dark" - windowInsetsControllerCompat.isAppearanceLightNavigationBars = - appearanceConfig.navigationBarContent == "dark" - - val window = activity.window - - if (appearanceConfig.customColorsForSystemBars) { - window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) - window.statusBarColor = Color.parseColor(appearanceConfig.statusBarColor) - window.navigationBarColor = Color.parseColor(appearanceConfig.navigationBarColor) - } else { - window.clearFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) + activity.runOnUiThread { + val windowInsetsControllerCompat = + WindowCompat.getInsetsController(activity.window, activity.window.decorView) + windowInsetsControllerCompat.isAppearanceLightStatusBars = + appearanceConfig.statusBarContent == "dark" + windowInsetsControllerCompat.isAppearanceLightNavigationBars = + appearanceConfig.navigationBarContent == "dark" + + val window = activity.window + + if (appearanceConfig.customColorsForSystemBars) { + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) + window.statusBarColor = Color.parseColor(appearanceConfig.statusBarColor) + window.navigationBarColor = Color.parseColor(appearanceConfig.navigationBarColor) + } else { + window.clearFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) + } } } private fun updateInsets() { - WindowCompat.setDecorFitsSystemWindows(activity.window, false) - - val windowInsets = ViewCompat.getRootWindowInsets(activity.window.decorView) - val systemBarsInsets = - windowInsets?.getInsets(WindowInsetsCompat.Type.systemBars()) ?: Insets.NONE - val imeInsets = windowInsets?.getInsets(WindowInsetsCompat.Type.ime()) ?: Insets.NONE - - val density = activity.resources.displayMetrics.density - - setProperty("top", Math.round(systemBarsInsets.top / density) + offset) - setProperty("left", Math.round(systemBarsInsets.left / density)) - if (imeInsets.bottom > 0) { - setProperty("bottom", 0) - } else { - setProperty("bottom", Math.round(systemBarsInsets.bottom / density) + offset) + activity.runOnUiThread { + WindowCompat.setDecorFitsSystemWindows(activity.window, false) + + val windowInsets = ViewCompat.getRootWindowInsets(activity.window.decorView) + val systemBarsInsets = + windowInsets?.getInsets(WindowInsetsCompat.Type.systemBars()) ?: Insets.NONE + val imeInsets = windowInsets?.getInsets(WindowInsetsCompat.Type.ime()) ?: Insets.NONE + + val density = activity.resources.displayMetrics.density + + setProperty("top", Math.round(systemBarsInsets.top / density) + offset) + setProperty("left", Math.round(systemBarsInsets.left / density)) + if (imeInsets.bottom > 0) { + setProperty("bottom", 0) + } else { + setProperty("bottom", Math.round(systemBarsInsets.bottom / density) + offset) + } + setProperty("right", Math.round(systemBarsInsets.right / density)) + + activity.window.decorView.setPadding(0, 0, 0, imeInsets.bottom) } - setProperty("right", Math.round(systemBarsInsets.right / density)) - - activity.window.decorView.setPadding(0, 0, 0, imeInsets.bottom) } private fun resetProperties() { @@ -87,6 +98,8 @@ class SafeArea(private val activity: Activity, private val webView: WebView) { } private fun setProperty(position: String, size: Int) { - webView.loadUrl("javascript:document.querySelector(':root')?.style.setProperty('--safe-area-inset-" + position + "', 'max(env(safe-area-inset-" + position + "), " + size + "px)');void(0);") + activity.runOnUiThread { + webView.loadUrl("javascript:document.querySelector(':root')?.style.setProperty('--safe-area-inset-" + position + "', 'max(env(safe-area-inset-" + position + "), " + size + "px)');void(0);") + } } }