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
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,20 @@ class NitroFetch : HybridNitroFetchSpec() {
val nativeProvider = providers.firstOrNull { it.name.contains("Native", ignoreCase = true) }

val cacheDir = File(app.cacheDir, "nitrofetch_cronet_cache").apply { mkdirs() }

val builder = (nativeProvider?.createBuilder() ?: CronetEngine.Builder(app))
.enableHttp2(true)
.enableQuic(true)
.enableBrotli(true)
.setStoragePath(cacheDir.absolutePath)
.enableHttpCache(CronetEngine.Builder.HTTP_CACHE_DISK, 50 * 1024 * 1024)
.setUserAgent("NitroFetch/0.1")
.enableNetworkQualityEstimator(true)

// Note: NQE experimental options can be configured via setExperimentalOptions() if needed:
// val nqeOptions = """{"NetworkQualityEstimator":{"effective_connection_type_algorithm":"TransportRTTAndDownstreamThroughput"}}"""
// builder.setExperimentalOptions(nqeOptions)
// This requires Cronet 119+ or embedded Cronet with the method available


// --- Optional debugging knobs (uncomment temporarily) ---
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,5 +252,50 @@ class NitroFetchClient(private val engine: CronetEngine, private val executor: E
return promise
}

override fun getNetworkQualityEstimate(): NetworkQualityEstimate {
try {
// Note: NQE values are based on observations from actual network requests.
// Values update as the app makes network calls and Cronet learns about network conditions.

// Get RTT estimates (in milliseconds, -1 if unknown)
val httpRttMs = engine.httpRttMs
val transportRttMs = engine.transportRttMs

// Get throughput estimates (in kbps, -1 if unknown)
val downstreamKbps = engine.downstreamThroughputKbps

// Get effective connection type
val effectiveConnectionType = when (engine.effectiveConnectionType) {
CronetEngine.EFFECTIVE_CONNECTION_TYPE_UNKNOWN -> "unknown"
CronetEngine.EFFECTIVE_CONNECTION_TYPE_OFFLINE -> "offline"
CronetEngine.EFFECTIVE_CONNECTION_TYPE_SLOW_2G -> "slow-2G"
CronetEngine.EFFECTIVE_CONNECTION_TYPE_2G -> "2G"
CronetEngine.EFFECTIVE_CONNECTION_TYPE_3G -> "3G"
CronetEngine.EFFECTIVE_CONNECTION_TYPE_4G -> "4G"
else -> "unknown"
}

Log.i("NitroFetchClient", "NQESnapshot - httpRtt: ${httpRttMs}ms, transportRtt: ${transportRttMs}ms, downstream: ${downstreamKbps}kbps, effectiveType: ${effectiveConnectionType}")

return NetworkQualityEstimate(
downstreamThroughputKbps = if (downstreamKbps != -1) downstreamKbps.toDouble() else null,
upstreamThroughputKbps = null, // Cronet doesn't provide upstream throughput
httpRttMs = if (httpRttMs != -1) httpRttMs.toDouble() else null,
transportRttMs = if (transportRttMs != -1) transportRttMs.toDouble() else null,
effectiveConnectionType = effectiveConnectionType
)
} catch (e: Exception) {
Log.e("NitroFetchClient", "Error getting network quality estimate", e)
// Return empty estimate on error
return NetworkQualityEstimate(
downstreamThroughputKbps = null,
upstreamThroughputKbps = null,
httpRttMs = null,
transportRttMs = null,
effectiveConnectionType = "unknown"
)
}
}


}
4 changes: 2 additions & 2 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ PODS:
- hermes-engine (0.81.0):
- hermes-engine/Pre-built (= 0.81.0)
- hermes-engine/Pre-built (0.81.0)
- NitroFetch (0.1.1):
- NitroFetch (0.1.3):
- boost
- DoubleConversion
- fast_float
Expand Down Expand Up @@ -2644,7 +2644,7 @@ SPEC CHECKSUMS:
fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd
glog: 5683914934d5b6e4240e497e0f4a3b42d1854183
hermes-engine: e7491a2038f2618c8cd444ed411a6deb350a3742
NitroFetch: 3653fb32c838befe759159a7b22e83a89344b191
NitroFetch: d99e3c3dad9f70317525c4fad230dff507857720
NitroModules: 33aca4acd8fd5c2a29dc99976680cd99e7263573
RCT-Folly: 846fda9475e61ec7bcbf8a3fe81edfcaeb090669
RCTDeprecation: 0735ab4f6b3ec93a7f98187b5da74d7916e2cf4c
Expand Down
7 changes: 7 additions & 0 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
prefetch,
prefetchOnAppStart,
removeAllFromAutoprefetch,
getNetworkQualityEstimate,
} from 'react-native-nitro-fetch';

type Row = {
Expand Down Expand Up @@ -185,6 +186,12 @@

const loadPrices = React.useCallback(async () => {
console.log('Loading crypto prices from coingecko start');
try{

Check failure on line 189 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Insert `·`
const networkQuality = await getNetworkQualityEstimate();
console.log('Network quality:', networkQuality);
} catch (e: any) {
console.error('Error getting network quality:', e);
}
const ids = [
'bitcoin',
'ethereum',
Expand Down Expand Up @@ -266,7 +273,7 @@

React.useEffect(() => {
run();
}, []);

Check failure on line 276 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

React Hook React.useEffect has a missing dependency: 'run'. Either include it or remove the dependency array

return (
<View style={styles.container}>
Expand All @@ -277,7 +284,7 @@
onPress={run}
disabled={running}
/>
<View style={{ width: 12 }} />

Check warning on line 287 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Inline style: { width: 12 }
<Button
title="Show Crypto Prices"
onPress={() => {
Expand All @@ -286,7 +293,7 @@
}}
/>
</View>
<View style={[styles.actions, { marginTop: 0 }]}>

Check warning on line 296 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Inline style: { marginTop: 0 }
<Button
title="Prefetch UUID"
onPress={async () => {
Expand All @@ -300,7 +307,7 @@
}
}}
/>
<View style={{ width: 12 }} />

Check warning on line 310 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Inline style: { width: 12 }
<Button
title="Fetch Prefetched"
onPress={async () => {
Expand All @@ -319,7 +326,7 @@
}}
/>
</View>
<View style={[styles.actions, { marginTop: 0 }]}>

Check warning on line 329 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Inline style: { marginTop: 0 }
<Button
title="Schedule Auto-Prefetch (MMKV)"
onPress={async () => {
Expand All @@ -333,7 +340,7 @@
}
}}
/>
<View style={{ width: 12 }} />

Check warning on line 343 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Inline style: { width: 12 }
<Button
title="Clear Auto-Prefetch"
onPress={async () => {
Expand All @@ -347,7 +354,7 @@
/>
</View>
{!!prefetchInfo && (
<Text style={{ textAlign: 'center', marginBottom: 8 }}>

Check warning on line 357 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Inline style: { textAlign: 'center', marginBottom: 8 }
{prefetchInfo}
</Text>
)}
Expand Down Expand Up @@ -434,9 +441,9 @@
<Text style={styles.sheetTitle}>Crypto Prices (USD)</Text>
<Button title="Close" onPress={() => setShowSheet(false)} />
</View>
<ScrollView style={{ maxHeight: 360 }}>

Check warning on line 444 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Inline style: { maxHeight: 360 }
{prices.length === 0 ? (
<Text style={{ padding: 12 }}>Loading…</Text>

Check warning on line 446 in example/src/App.tsx

View workflow job for this annotation

GitHub Actions / lint

Inline style: { padding: 12 }
) : (
prices.map((p) => (
<View key={p.id} style={styles.priceRow}>
Expand Down
14 changes: 14 additions & 0 deletions ios/NitroFetchClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,20 @@ final class NitroFetchClient: HybridNitroFetchClientSpec {
return promise
}

func getNetworkQualityEstimate() throws -> NetworkQualityEstimate {
// NQE is not supported on iOS yet - requires Cronet integration
NSLog("[NitroFetch] Network Quality Estimator (NQE) is not supported on iOS yet. It will be available once iOS uses Cronet.")

// Return empty estimate
return NetworkQualityEstimate(
downstreamThroughputKbps: nil,
upstreamThroughputKbps: nil,
httpRttMs: nil,
transportRttMs: nil,
effectiveConnectionType: "unknown"
)
}

// Shared URLSession for static operations
private static let session: URLSession = {
let config = URLSessionConfiguration.default
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

70 changes: 70 additions & 0 deletions nitrogen/generated/android/c++/JNetworkQualityEstimate.hpp

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 4 additions & 7 deletions nitrogen/generated/android/nitrofetch+autolinking.cmake

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions nitrogen/generated/ios/NitroFetch-Swift-Cxx-Bridge.hpp

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions nitrogen/generated/ios/NitroFetch-Swift-Cxx-Umbrella.hpp

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading