Skip to content
Open
Show file tree
Hide file tree
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
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,30 @@ All notable changes to this project will be documented in this file.

## [Unreleased]

## [3.0.104] - 2026-09-04

### Bug Fixes
- **image (Android)**: Bind rendered-image Glide requests to the host Activity so temporary ScreenStack Fragment teardown preserves visible images while backgrounding and Activity destruction retain bounded lifecycle cleanup.

### Chores
- Bump all publishable packages to 3.0.104.

## [3.0.103] - 2026-09-04

### Bug Fixes
- **background-thread (Android)**: Load the reusable DevSession common HBC from its restored file path while preserving the packaged asset fallback.

### Chores
- Bump all publishable packages to 3.0.103.

## [3.0.102] - 2026-09-04

### Bug Fixes
- **image (Android)**: Keep Glide requests independent of temporary native-stack Fragment teardown so images retained by React remain visible after closing an opaque task modal.

### Chores
- Bump all publishable packages to 3.0.102.

## [3.0.95] - 2026-08-31

### Features
Expand Down
2 changes: 1 addition & 1 deletion native-modules/native-logger/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-native-logger",
"version": "3.0.101",
"version": "3.0.104",
"description": "react-native-native-logger",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion native-modules/react-native-aes-crypto/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-aes-crypto",
"version": "3.0.101",
"version": "3.0.104",
"description": "react-native-aes-crypto",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion native-modules/react-native-app-update/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-app-update",
"version": "3.0.101",
"version": "3.0.104",
"description": "react-native-app-update",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion native-modules/react-native-async-storage/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-async-storage",
"version": "3.0.101",
"version": "3.0.104",
"description": "react-native-async-storage",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class BackgroundThreadManager private constructor() {
// OneKey patch: background uses the same local dev-vendor HBC as main,
// then evaluates its own modulesOnly Metro delta in the isolated runtime.
private data class DevVendorConfig(
val commonAssetName: String,
val commonBundleLocation: String,
val fingerprint: String,
val backgroundHMREnabled: Boolean,
val runtimeGeneration: Long = 0,
Expand Down Expand Up @@ -411,11 +411,20 @@ class BackgroundThreadManager private constructor() {
return object : JSBundleLoader() {
override fun loadScript(delegate: com.facebook.react.bridge.JSBundleLoaderDelegate): String {
val totalStart = System.nanoTime()
delegate.loadScriptFromAssets(
appContext.assets,
"assets://${config.commonAssetName}",
false,
)
val commonFile = File(config.commonBundleLocation)
if (commonFile.isFile) {
delegate.loadScriptFromFile(
commonFile.absolutePath,
"onekey-dev-vendor://common.hbc",
false,
)
} else {
delegate.loadScriptFromAssets(
appContext.assets,
"assets://${config.commonBundleLocation}",
false,
)
}
val assertionFile = File(appContext.cacheDir, "onekey-dev-vendor-assert-background.js")
val quotedEntryURL = org.json.JSONObject.quote(entryURL)
assertionFile.writeText(
Expand Down Expand Up @@ -501,14 +510,14 @@ class BackgroundThreadManager private constructor() {
fun ensureBackgroundRunnerWithDevVendor(
context: Context,
entryURL: String,
commonAssetName: String,
commonBundleLocation: String,
fingerprint: String,
backgroundHMREnabled: Boolean,
): Boolean {
return ensureBackgroundRunner(
context,
entryURL,
DevVendorConfig(commonAssetName, fingerprint, backgroundHMREnabled),
DevVendorConfig(commonBundleLocation, fingerprint, backgroundHMREnabled),
)
}

Expand Down
2 changes: 1 addition & 1 deletion native-modules/react-native-background-thread/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-background-thread",
"version": "3.0.101",
"version": "3.0.104",
"description": "react-native-background-thread",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion native-modules/react-native-bundle-crypto/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-bundle-crypto",
"version": "3.0.101",
"version": "3.0.104",
"description": "react-native-bundle-crypto",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion native-modules/react-native-bundle-update/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-bundle-update",
"version": "3.0.101",
"version": "3.0.104",
"description": "react-native-bundle-update",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-check-biometric-auth-changed",
"version": "3.0.101",
"version": "3.0.104",
"description": "react-native-check-biometric-auth-changed",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion native-modules/react-native-cloud-fs/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-cloud-fs",
"version": "3.0.101",
"version": "3.0.104",
"description": "react-native-cloud-fs TurboModule for OneKey",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion native-modules/react-native-cloud-kit-module/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-cloud-kit-module",
"version": "3.0.101",
"version": "3.0.104",
"description": "react-native-cloud-kit-module",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion native-modules/react-native-device-utils/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-device-utils",
"version": "3.0.101",
"version": "3.0.104",
"description": "react-native-device-utils",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion native-modules/react-native-dns-lookup/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-dns-lookup",
"version": "3.0.101",
"version": "3.0.104",
"description": "react-native-dns-lookup",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion native-modules/react-native-get-random-values/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-get-random-values",
"version": "3.0.101",
"version": "3.0.104",
"description": "react-native-get-random-values",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion native-modules/react-native-keychain-module/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-keychain-module",
"version": "3.0.101",
"version": "3.0.104",
"description": "react-native-keychain-module",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion native-modules/react-native-lite-card/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-lite-card",
"version": "3.0.101",
"version": "3.0.104",
"description": "lite card",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion native-modules/react-native-network-info/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-network-info",
"version": "3.0.101",
"version": "3.0.104",
"description": "react-native-network-info",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion native-modules/react-native-network-throttle/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-network-throttle",
"version": "3.0.101",
"version": "3.0.104",
"description": "react-native-network-throttle",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion native-modules/react-native-pbkdf2/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-pbkdf2",
"version": "3.0.101",
"version": "3.0.104",
"description": "react-native-pbkdf2",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion native-modules/react-native-perf-memory/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-perf-memory",
"version": "3.0.101",
"version": "3.0.104",
"description": "react-native-perf-memory",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion native-modules/react-native-perf-stats/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-perf-stats",
"version": "3.0.101",
"version": "3.0.104",
"description": "react-native-perf-stats",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion native-modules/react-native-ping/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-ping",
"version": "3.0.101",
"version": "3.0.104",
"description": "react-native-ping TurboModule for OneKey",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion native-modules/react-native-range-downloader/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-range-downloader",
"version": "3.0.101",
"version": "3.0.104",
"description": "react-native-range-downloader",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion native-modules/react-native-sni-connect/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-sni-connect",
"version": "3.0.101",
"version": "3.0.104",
"description": "A React Native library for SNI-based HTTP requests with DNS caching and request management",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion native-modules/react-native-splash-screen/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-splash-screen",
"version": "3.0.101",
"version": "3.0.104",
"description": "react-native-splash-screen",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-split-bundle-loader",
"version": "3.0.101",
"version": "3.0.104",
"description": "react-native-split-bundle-loader",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion native-modules/react-native-tcp-socket/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-tcp-socket",
"version": "3.0.101",
"version": "3.0.104",
"description": "react-native-tcp-socket",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion native-modules/react-native-zip-archive/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-zip-archive",
"version": "3.0.101",
"version": "3.0.104",
"description": "react-native-zip-archive Nitro HybridObject for OneKey",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion native-views/react-native-auto-size-input/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-auto-size-input",
"version": "3.0.101",
"version": "3.0.104",
"description": "Auto-sizing text input with font scaling, prefix and suffix support",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion native-views/react-native-chart-webview/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@onekeyfe/react-native-chart-webview",
"version": "3.0.101",
"version": "3.0.104",
"description": "react-native-chart-webview",
"main": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package com.margelo.nitro.onekeyimage

import android.content.Context
import android.content.ContextWrapper
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.drawable.Animatable
import android.graphics.drawable.Drawable
import android.view.View
import android.widget.ImageView
import androidx.fragment.app.FragmentActivity
import com.bumptech.glide.Glide
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.DiskCacheStrategy
Expand All @@ -22,6 +25,17 @@ import com.margelo.nitro.skeleton.OneKeySkeletonRenderer
import com.margelo.nitro.views.RecyclableView
import kotlin.math.ceil

private fun Context.findFragmentActivity(): FragmentActivity? {
var currentContext: Context? = this
while (currentContext is ContextWrapper) {
if (currentContext is FragmentActivity) return currentContext
val baseContext = currentContext.baseContext
if (baseContext === currentContext) return null
currentContext = baseContext
}
return currentContext as? FragmentActivity
}

private class OneKeyImageHostView(context: ThemedReactContext) : ImageView(context) {
private val fallbackPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
color = Color.rgb(110, 110, 120)
Expand Down Expand Up @@ -123,6 +137,13 @@ class HybridOneKeyImage(private val context: ThemedReactContext) :
private enum class DisplayState { LOADING, IMAGE, ERROR, FALLBACK }

private val hostView = OneKeyImageHostView(context)
// The Activity outlives ScreenStack Fragments but still provides bounded
// background and destruction lifecycle handling for image requests.
private val requestManager by lazy(LazyThreadSafetyMode.NONE) {
val activity = context.findFragmentActivity()
?: (context.currentActivity as? FragmentActivity)
Glide.with(requireNotNull(activity) { "A FragmentActivity is required to load images" })

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: [Default ReactActivity hosts cannot initialize the image request manager]

When this package runs in a standard React Native host such as the repository example's MainActivity : ReactActivity(), that Activity is not a FragmentActivity. Both lookups therefore return null, and requireNotNull throws when the first image request accesses requestManager, so the component crashes instead of loading the image.

Please unwrap or read the host as android.app.Activity and pass that Activity to Glide's Activity overload. This preserves Activity-scoped cleanup without excluding standard React Native hosts.

}
private var loadRunnable: Runnable? = null
private var currentTarget: CustomViewTarget<OneKeyImageHostView, Drawable>? = null
private var generation = 0L
Expand Down Expand Up @@ -208,6 +229,7 @@ class HybridOneKeyImage(private val context: ThemedReactContext) :
hostView.onReadyForRequest = { scheduleLoad() }
hostView.onAttachmentChanged = { attached ->
if (attached) {
scheduleLoad()
schedulePendingDisplayIfNeeded()
} else {
displayRunnable?.let(hostView::removeCallbacks)
Expand Down Expand Up @@ -406,6 +428,8 @@ class HybridOneKeyImage(private val context: ThemedReactContext) :

override fun onResourceCleared(placeholder: Drawable?) {
if (requestGeneration == generation && currentTarget === this) {
currentTarget = null
lastSignature = null
requestActive = false
hostView.skeletonRequested = false
hostView.setImageDrawable(null)
Expand Down Expand Up @@ -446,7 +470,7 @@ class HybridOneKeyImage(private val context: ThemedReactContext) :
}
}
currentTarget = target
Glide.with(hostView)
requestManager
.asDrawable()
.load(OneKeyImageModel.build(requestUrl, headersJson))
.apply(requestOptions(policy))
Expand Down Expand Up @@ -523,7 +547,7 @@ class HybridOneKeyImage(private val context: ThemedReactContext) :
// Clear the field first so onResourceCleared from our own cancellation
// cannot erase state belonging to the next generation/request.
currentTarget = null
Glide.with(hostView).clear(target)
requestManager.clear(target)
}

private fun scheduleOnDisplay(requestGeneration: Long) {
Expand Down
Loading