Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
package com.th3rdwave.safeareacontext

import android.content.Context
import android.util.Log
import android.view.View
import android.view.ViewTreeObserver
import com.facebook.react.bridge.Arguments
import com.facebook.react.uimanager.StateWrapper
import com.facebook.react.uimanager.UIManagerModule
import com.facebook.react.views.view.ReactViewGroup
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock

private const val MAX_WAIT_TIME_NANO = 500000000L // 500ms

class SafeAreaView(context: Context?) :
ReactViewGroup(context), ViewTreeObserver.OnPreDrawListener {
Expand Down Expand Up @@ -50,54 +45,9 @@ class SafeAreaView(context: Context?) :
val uiManager = reactContext.getNativeModule(UIManagerModule::class.java)
if (uiManager != null) {
uiManager.setViewLocalData(id, localData)
// Sadly there doesn't seem to be a way to properly dirty a yoga node from java, so if we
// are in
// the middle of a layout, we need to recompute it. There is also no way to know whether
// we
// are in the middle of a layout so always do it.
reactContext.runOnNativeModulesQueueThread {
uiManager.uiImplementation.dispatchViewUpdates(-1)
}
waitForReactLayout()
}
}
}
}

private fun waitForReactLayout() {
// Block the main thread until the native module thread is finished with
// its current tasks. To do this we use the done boolean as a lock and enqueue
// a task on the native modules thread. When the task runs we can unblock the
// main thread. This should be safe as long as the native modules thread
// does not block waiting on the main thread.
var done = false
val lock = ReentrantLock()
val condition = lock.newCondition()
val startTime = System.nanoTime()
var waitTime = 0L
getReactContext(this).runOnNativeModulesQueueThread {
lock.withLock {
if (!done) {
done = true
condition.signal()
}
}
}
lock.withLock {
while (!done && waitTime < MAX_WAIT_TIME_NANO) {
try {
condition.awaitNanos(MAX_WAIT_TIME_NANO)
} catch (ex: InterruptedException) {
// In case of an interrupt just give up waiting.
done = true
}
waitTime += System.nanoTime() - startTime
}
}
// Timed out waiting.
if (waitTime >= MAX_WAIT_TIME_NANO) {
Log.w("SafeAreaView", "Timed out waiting for layout.")
}
}

fun setMode(mode: SafeAreaViewMode) {
Expand Down
Loading