@onekeyfe/react-native-network-throttle 3.0.69
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -0
- package/README.md +5 -0
- package/ReactNativeNetworkThrottle.podspec +19 -0
- package/android/build.gradle +65 -0
- package/android/src/main/AndroidManifest.xml +8 -0
- package/android/src/main/java/com/onekeyfe/reactnativenetworkthrottle/NetworkThrottle.kt +84 -0
- package/android/src/main/java/com/onekeyfe/reactnativenetworkthrottle/NetworkThrottleInitProvider.kt +31 -0
- package/android/src/main/java/com/onekeyfe/reactnativenetworkthrottle/NetworkThrottleModule.kt +33 -0
- package/android/src/main/java/com/onekeyfe/reactnativenetworkthrottle/NetworkThrottlePackage.kt +16 -0
- package/ios/OneKeyNetworkThrottle.m +206 -0
- package/lib/module/index.js +16 -0
- package/lib/module/package.json +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/index.d.ts +14 -0
- package/package.json +146 -0
- package/src/index.tsx +40 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 @onekeyhq
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
in the Software without restriction, including without limitation the rights
|
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = "ReactNativeNetworkThrottle"
|
|
7
|
+
s.version = package["version"]
|
|
8
|
+
s.summary = package["description"]
|
|
9
|
+
s.homepage = package["homepage"]
|
|
10
|
+
s.license = package["license"]
|
|
11
|
+
s.authors = package["author"]
|
|
12
|
+
|
|
13
|
+
s.platforms = { :ios => min_ios_version_supported }
|
|
14
|
+
s.source = { :git => "https://github.com/OneKeyHQ/app-modules/react-native-network-throttle.git", :tag => "#{s.version}" }
|
|
15
|
+
|
|
16
|
+
s.source_files = "ios/**/*.{h,m,mm,swift}"
|
|
17
|
+
|
|
18
|
+
install_modules_dependencies(s)
|
|
19
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
buildscript {
|
|
2
|
+
ext.getExtOrDefault = {name ->
|
|
3
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['ReactNativeNetworkThrottle_' + name]
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
repositories {
|
|
7
|
+
google()
|
|
8
|
+
mavenCentral()
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
dependencies {
|
|
12
|
+
classpath "com.android.tools.build:gradle:8.7.2"
|
|
13
|
+
// noinspection DifferentKotlinGradleVersion
|
|
14
|
+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
apply plugin: "com.android.library"
|
|
19
|
+
apply plugin: "kotlin-android"
|
|
20
|
+
|
|
21
|
+
def getExtOrIntegerDefault(name) {
|
|
22
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["ReactNativeNetworkThrottle_" + name]).toInteger()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
android {
|
|
26
|
+
namespace "com.onekeyfe.reactnativenetworkthrottle"
|
|
27
|
+
|
|
28
|
+
compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
|
|
29
|
+
|
|
30
|
+
defaultConfig {
|
|
31
|
+
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
|
32
|
+
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
buildFeatures {
|
|
36
|
+
buildConfig true
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
buildTypes {
|
|
40
|
+
release {
|
|
41
|
+
minifyEnabled false
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
lintOptions {
|
|
46
|
+
disable "GradleCompatible"
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
compileOptions {
|
|
50
|
+
sourceCompatibility JavaVersion.VERSION_1_8
|
|
51
|
+
targetCompatibility JavaVersion.VERSION_1_8
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
repositories {
|
|
56
|
+
mavenCentral()
|
|
57
|
+
google()
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
def kotlin_version = getExtOrDefault("kotlinVersion")
|
|
61
|
+
|
|
62
|
+
dependencies {
|
|
63
|
+
implementation "com.facebook.react:react-android"
|
|
64
|
+
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
65
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
2
|
+
<application>
|
|
3
|
+
<provider
|
|
4
|
+
android:name=".NetworkThrottleInitProvider"
|
|
5
|
+
android:authorities="${applicationId}.network-throttle-init"
|
|
6
|
+
android:exported="false" />
|
|
7
|
+
</application>
|
|
8
|
+
</manifest>
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
package com.onekeyfe.reactnativenetworkthrottle
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.util.Log
|
|
5
|
+
import com.facebook.react.bridge.Arguments
|
|
6
|
+
import com.facebook.react.bridge.ReadableMap
|
|
7
|
+
import com.facebook.react.bridge.WritableMap
|
|
8
|
+
import com.facebook.react.modules.network.OkHttpClientProvider
|
|
9
|
+
import java.io.IOException
|
|
10
|
+
import java.util.concurrent.TimeUnit
|
|
11
|
+
import java.util.concurrent.atomic.AtomicBoolean
|
|
12
|
+
import java.util.concurrent.atomic.AtomicLong
|
|
13
|
+
import okhttp3.Interceptor
|
|
14
|
+
import okhttp3.OkHttpClient
|
|
15
|
+
import okhttp3.Response
|
|
16
|
+
|
|
17
|
+
internal object NetworkThrottle {
|
|
18
|
+
private const val TAG = "OneKeyNetworkThrottle"
|
|
19
|
+
private const val PROFILE_SLOW_4G = "slow4g"
|
|
20
|
+
private const val DEFAULT_LATENCY_MS = 562.5
|
|
21
|
+
|
|
22
|
+
private val enabled = AtomicBoolean(false)
|
|
23
|
+
private val latencyNanos = AtomicLong((DEFAULT_LATENCY_MS * 1_000_000.0).toLong())
|
|
24
|
+
private val installed = AtomicBoolean(false)
|
|
25
|
+
|
|
26
|
+
fun install(context: Context) {
|
|
27
|
+
if (!installed.compareAndSet(false, true)) {
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
val applicationContext = context.applicationContext
|
|
31
|
+
OkHttpClientProvider.setOkHttpClientFactory {
|
|
32
|
+
val builder: OkHttpClient.Builder =
|
|
33
|
+
OkHttpClientProvider.createClientBuilder(applicationContext)
|
|
34
|
+
builder.addInterceptor(LatencyInterceptor())
|
|
35
|
+
builder.build()
|
|
36
|
+
}
|
|
37
|
+
Log.i(TAG, "[onekey-network-throttle] installed RN OkHttp latency interceptor")
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
fun setConfig(config: ReadableMap): WritableMap {
|
|
41
|
+
val nextEnabled = config.hasKey("enabled") && config.getBoolean("enabled")
|
|
42
|
+
var nextLatencyMs =
|
|
43
|
+
if (config.hasKey("latencyMs")) config.getDouble("latencyMs") else DEFAULT_LATENCY_MS
|
|
44
|
+
if (nextLatencyMs <= 0) {
|
|
45
|
+
nextLatencyMs = DEFAULT_LATENCY_MS
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
enabled.set(nextEnabled)
|
|
49
|
+
latencyNanos.set((nextLatencyMs * 1_000_000.0).toLong())
|
|
50
|
+
Log.i(
|
|
51
|
+
TAG,
|
|
52
|
+
"[onekey-network-throttle] native config enabled=$nextEnabled profile=$PROFILE_SLOW_4G latencyMs=$nextLatencyMs"
|
|
53
|
+
)
|
|
54
|
+
return getConfig()
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
fun getConfig(): WritableMap {
|
|
58
|
+
val map = Arguments.createMap()
|
|
59
|
+
map.putBoolean("enabled", enabled.get())
|
|
60
|
+
map.putString("profile", PROFILE_SLOW_4G)
|
|
61
|
+
map.putDouble("latencyMs", latencyNanos.get() / 1_000_000.0)
|
|
62
|
+
return map
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private fun getLatencyNanos(): Long = if (enabled.get()) latencyNanos.get() else 0L
|
|
66
|
+
|
|
67
|
+
private class LatencyInterceptor : Interceptor {
|
|
68
|
+
override fun intercept(chain: Interceptor.Chain): Response {
|
|
69
|
+
val delayNanos = getLatencyNanos()
|
|
70
|
+
if (delayNanos > 0) {
|
|
71
|
+
try {
|
|
72
|
+
val delayMs = TimeUnit.NANOSECONDS.toMillis(delayNanos)
|
|
73
|
+
val remainingNanos =
|
|
74
|
+
(delayNanos - TimeUnit.MILLISECONDS.toNanos(delayMs)).toInt()
|
|
75
|
+
Thread.sleep(delayMs, remainingNanos)
|
|
76
|
+
} catch (error: InterruptedException) {
|
|
77
|
+
Thread.currentThread().interrupt()
|
|
78
|
+
throw IOException("Interrupted while applying OneKey network throttle", error)
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return chain.proceed(chain.request())
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
package/android/src/main/java/com/onekeyfe/reactnativenetworkthrottle/NetworkThrottleInitProvider.kt
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
package com.onekeyfe.reactnativenetworkthrottle
|
|
2
|
+
|
|
3
|
+
import android.content.ContentProvider
|
|
4
|
+
import android.content.ContentValues
|
|
5
|
+
import android.database.Cursor
|
|
6
|
+
import android.net.Uri
|
|
7
|
+
|
|
8
|
+
class NetworkThrottleInitProvider : ContentProvider() {
|
|
9
|
+
override fun onCreate(): Boolean {
|
|
10
|
+
context?.let { NetworkThrottle.install(it) }
|
|
11
|
+
return true
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
override fun query(
|
|
15
|
+
uri: Uri,
|
|
16
|
+
projection: Array<String>?,
|
|
17
|
+
selection: String?,
|
|
18
|
+
selectionArgs: Array<String>?,
|
|
19
|
+
sortOrder: String?
|
|
20
|
+
): Cursor? = null
|
|
21
|
+
|
|
22
|
+
override fun getType(uri: Uri): String? = null
|
|
23
|
+
override fun insert(uri: Uri, values: ContentValues?): Uri? = null
|
|
24
|
+
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int = 0
|
|
25
|
+
override fun update(
|
|
26
|
+
uri: Uri,
|
|
27
|
+
values: ContentValues?,
|
|
28
|
+
selection: String?,
|
|
29
|
+
selectionArgs: Array<String>?
|
|
30
|
+
): Int = 0
|
|
31
|
+
}
|
package/android/src/main/java/com/onekeyfe/reactnativenetworkthrottle/NetworkThrottleModule.kt
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
package com.onekeyfe.reactnativenetworkthrottle
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Promise
|
|
4
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
5
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
6
|
+
import com.facebook.react.bridge.ReactMethod
|
|
7
|
+
import com.facebook.react.bridge.ReadableMap
|
|
8
|
+
import com.facebook.react.module.annotations.ReactModule
|
|
9
|
+
|
|
10
|
+
@ReactModule(name = NetworkThrottleModule.NAME)
|
|
11
|
+
class NetworkThrottleModule(private val reactContext: ReactApplicationContext) :
|
|
12
|
+
ReactContextBaseJavaModule(reactContext) {
|
|
13
|
+
|
|
14
|
+
companion object {
|
|
15
|
+
const val NAME = "OneKeyNetworkThrottle"
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
init {
|
|
19
|
+
NetworkThrottle.install(reactContext)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
override fun getName(): String = NAME
|
|
23
|
+
|
|
24
|
+
@ReactMethod
|
|
25
|
+
fun getConfig(promise: Promise) {
|
|
26
|
+
promise.resolve(NetworkThrottle.getConfig())
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@ReactMethod
|
|
30
|
+
fun setConfig(config: ReadableMap, promise: Promise) {
|
|
31
|
+
promise.resolve(NetworkThrottle.setConfig(config))
|
|
32
|
+
}
|
|
33
|
+
}
|
package/android/src/main/java/com/onekeyfe/reactnativenetworkthrottle/NetworkThrottlePackage.kt
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
package com.onekeyfe.reactnativenetworkthrottle
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.ReactPackage
|
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.uimanager.ViewManager
|
|
7
|
+
|
|
8
|
+
@Suppress("OVERRIDE_DEPRECATION")
|
|
9
|
+
class NetworkThrottlePackage : ReactPackage {
|
|
10
|
+
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> =
|
|
11
|
+
listOf(NetworkThrottleModule(reactContext))
|
|
12
|
+
|
|
13
|
+
override fun createViewManagers(
|
|
14
|
+
reactContext: ReactApplicationContext
|
|
15
|
+
): List<ViewManager<*, *>> = emptyList()
|
|
16
|
+
}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
#import <Foundation/Foundation.h>
|
|
2
|
+
#import <React/RCTBridgeModule.h>
|
|
3
|
+
#import <React/RCTHTTPRequestHandler.h>
|
|
4
|
+
#import <math.h>
|
|
5
|
+
#import <stdatomic.h>
|
|
6
|
+
|
|
7
|
+
static NSString *const OneKeyNetworkThrottleHandledKey = @"OneKeyNetworkThrottleHandled";
|
|
8
|
+
static NSString *const OneKeyNetworkThrottleProfileSlow4G = @"slow4g";
|
|
9
|
+
static const NSTimeInterval OneKeyNetworkThrottleDefaultLatencyMs = 562.5;
|
|
10
|
+
|
|
11
|
+
@interface OneKeyNetworkThrottleState : NSObject
|
|
12
|
+
+ (NSDictionary *)currentConfig;
|
|
13
|
+
+ (BOOL)isEnabled;
|
|
14
|
+
+ (NSTimeInterval)latencyMs;
|
|
15
|
+
+ (NSDictionary *)setEnabled:(BOOL)enabled latencyMs:(NSTimeInterval)latencyMs;
|
|
16
|
+
@end
|
|
17
|
+
|
|
18
|
+
@implementation OneKeyNetworkThrottleState
|
|
19
|
+
|
|
20
|
+
static atomic_bool _oneKeyNetworkThrottleEnabled = ATOMIC_VAR_INIT(false);
|
|
21
|
+
static atomic_llong _oneKeyNetworkThrottleLatencyMicros = ATOMIC_VAR_INIT(562500);
|
|
22
|
+
|
|
23
|
+
+ (NSDictionary *)currentConfig
|
|
24
|
+
{
|
|
25
|
+
BOOL enabled = atomic_load_explicit(&_oneKeyNetworkThrottleEnabled, memory_order_acquire);
|
|
26
|
+
NSTimeInterval latencyMs =
|
|
27
|
+
((NSTimeInterval)atomic_load_explicit(&_oneKeyNetworkThrottleLatencyMicros, memory_order_relaxed)) / 1000.0;
|
|
28
|
+
return @{
|
|
29
|
+
@"enabled": @(enabled),
|
|
30
|
+
@"profile": OneKeyNetworkThrottleProfileSlow4G,
|
|
31
|
+
@"latencyMs": @(latencyMs)
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
+ (BOOL)isEnabled
|
|
36
|
+
{
|
|
37
|
+
return atomic_load_explicit(&_oneKeyNetworkThrottleEnabled, memory_order_acquire);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
+ (NSTimeInterval)latencyMs
|
|
41
|
+
{
|
|
42
|
+
return ((NSTimeInterval)atomic_load_explicit(&_oneKeyNetworkThrottleLatencyMicros, memory_order_relaxed)) / 1000.0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
+ (NSDictionary *)setEnabled:(BOOL)enabled latencyMs:(NSTimeInterval)latencyMs
|
|
46
|
+
{
|
|
47
|
+
NSTimeInterval normalizedLatencyMs = latencyMs > 0 ? latencyMs : OneKeyNetworkThrottleDefaultLatencyMs;
|
|
48
|
+
atomic_store_explicit(
|
|
49
|
+
&_oneKeyNetworkThrottleLatencyMicros,
|
|
50
|
+
(long long)llround(normalizedLatencyMs * 1000.0),
|
|
51
|
+
memory_order_relaxed
|
|
52
|
+
);
|
|
53
|
+
atomic_store_explicit(&_oneKeyNetworkThrottleEnabled, enabled, memory_order_release);
|
|
54
|
+
NSLog(
|
|
55
|
+
@"[onekey-network-throttle] native config enabled=%@ profile=%@ latencyMs=%.1f",
|
|
56
|
+
enabled ? @"true" : @"false",
|
|
57
|
+
OneKeyNetworkThrottleProfileSlow4G,
|
|
58
|
+
normalizedLatencyMs
|
|
59
|
+
);
|
|
60
|
+
return [self currentConfig];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@end
|
|
64
|
+
|
|
65
|
+
@interface OneKeyNetworkThrottleURLProtocol : NSURLProtocol <NSURLSessionDataDelegate>
|
|
66
|
+
@property (nonatomic, strong) NSURLSessionDataTask *task;
|
|
67
|
+
@property (nonatomic, strong) NSURLSession *session;
|
|
68
|
+
@property (atomic, assign) BOOL stopped;
|
|
69
|
+
@end
|
|
70
|
+
|
|
71
|
+
@implementation OneKeyNetworkThrottleURLProtocol
|
|
72
|
+
|
|
73
|
+
+ (BOOL)canInitWithRequest:(NSURLRequest *)request
|
|
74
|
+
{
|
|
75
|
+
if (![OneKeyNetworkThrottleState isEnabled]) {
|
|
76
|
+
return NO;
|
|
77
|
+
}
|
|
78
|
+
if ([NSURLProtocol propertyForKey:OneKeyNetworkThrottleHandledKey inRequest:request]) {
|
|
79
|
+
return NO;
|
|
80
|
+
}
|
|
81
|
+
NSString *scheme = request.URL.scheme.lowercaseString;
|
|
82
|
+
return [scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request
|
|
86
|
+
{
|
|
87
|
+
return request;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
- (void)startLoading
|
|
91
|
+
{
|
|
92
|
+
NSMutableURLRequest *request = [self.request mutableCopy];
|
|
93
|
+
[NSURLProtocol setProperty:@YES forKey:OneKeyNetworkThrottleHandledKey inRequest:request];
|
|
94
|
+
|
|
95
|
+
NSTimeInterval delay = [OneKeyNetworkThrottleState latencyMs] / 1000.0;
|
|
96
|
+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_global_queue(QOS_CLASS_UTILITY, 0), ^{
|
|
97
|
+
if (self.stopped) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
|
|
101
|
+
configuration.HTTPShouldSetCookies = YES;
|
|
102
|
+
configuration.HTTPCookieAcceptPolicy = NSHTTPCookieAcceptPolicyAlways;
|
|
103
|
+
configuration.HTTPCookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
|
|
104
|
+
self.session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
|
|
105
|
+
self.task = [self.session dataTaskWithRequest:request];
|
|
106
|
+
[self.task resume];
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
- (void)stopLoading
|
|
111
|
+
{
|
|
112
|
+
self.stopped = YES;
|
|
113
|
+
[self.task cancel];
|
|
114
|
+
[self.session invalidateAndCancel];
|
|
115
|
+
self.task = nil;
|
|
116
|
+
self.session = nil;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
- (void)URLSession:(NSURLSession *)session
|
|
120
|
+
task:(NSURLSessionTask *)task
|
|
121
|
+
willPerformHTTPRedirection:(NSHTTPURLResponse *)response
|
|
122
|
+
newRequest:(NSURLRequest *)request
|
|
123
|
+
completionHandler:(void (^)(NSURLRequest * _Nullable))completionHandler
|
|
124
|
+
{
|
|
125
|
+
[self.client URLProtocol:self wasRedirectedToRequest:request redirectResponse:response];
|
|
126
|
+
completionHandler(nil);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
- (void)URLSession:(NSURLSession *)session
|
|
130
|
+
dataTask:(NSURLSessionDataTask *)dataTask
|
|
131
|
+
didReceiveResponse:(NSURLResponse *)response
|
|
132
|
+
completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
|
|
133
|
+
{
|
|
134
|
+
[self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
|
|
135
|
+
completionHandler(NSURLSessionResponseAllow);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
|
|
139
|
+
{
|
|
140
|
+
[self.client URLProtocol:self didLoadData:data];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
|
|
144
|
+
{
|
|
145
|
+
if (error) {
|
|
146
|
+
[self.client URLProtocol:self didFailWithError:error];
|
|
147
|
+
} else {
|
|
148
|
+
[self.client URLProtocolDidFinishLoading:self];
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
@end
|
|
153
|
+
|
|
154
|
+
@interface OneKeyNetworkThrottleInstaller : NSObject
|
|
155
|
+
@end
|
|
156
|
+
|
|
157
|
+
@implementation OneKeyNetworkThrottleInstaller
|
|
158
|
+
|
|
159
|
+
+ (void)load
|
|
160
|
+
{
|
|
161
|
+
RCTSetCustomNSURLSessionConfigurationProvider(^NSURLSessionConfiguration *{
|
|
162
|
+
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
|
|
163
|
+
NSNumber *useWifiOnly = [[NSBundle mainBundle].infoDictionary objectForKey:@"ReactNetworkForceWifiOnly"];
|
|
164
|
+
if (useWifiOnly) {
|
|
165
|
+
configuration.allowsCellularAccess = ![useWifiOnly boolValue];
|
|
166
|
+
}
|
|
167
|
+
configuration.HTTPShouldSetCookies = YES;
|
|
168
|
+
configuration.HTTPCookieAcceptPolicy = NSHTTPCookieAcceptPolicyAlways;
|
|
169
|
+
configuration.HTTPCookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
|
|
170
|
+
|
|
171
|
+
NSArray<Class> *existingProtocolClasses = configuration.protocolClasses ?: @[];
|
|
172
|
+
if (![existingProtocolClasses containsObject:[OneKeyNetworkThrottleURLProtocol class]]) {
|
|
173
|
+
configuration.protocolClasses = [[@[ [OneKeyNetworkThrottleURLProtocol class] ] arrayByAddingObjectsFromArray:existingProtocolClasses] copy];
|
|
174
|
+
}
|
|
175
|
+
return configuration;
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
@end
|
|
180
|
+
|
|
181
|
+
@interface OneKeyNetworkThrottle : NSObject <RCTBridgeModule>
|
|
182
|
+
@end
|
|
183
|
+
|
|
184
|
+
@implementation OneKeyNetworkThrottle
|
|
185
|
+
|
|
186
|
+
RCT_EXPORT_MODULE(OneKeyNetworkThrottle)
|
|
187
|
+
|
|
188
|
+
+ (BOOL)requiresMainQueueSetup
|
|
189
|
+
{
|
|
190
|
+
return NO;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
RCT_REMAP_METHOD(getConfig, getConfigWithResolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
194
|
+
{
|
|
195
|
+
resolve([OneKeyNetworkThrottleState currentConfig]);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
RCT_REMAP_METHOD(setConfig, setConfig:(NSDictionary *)config resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
199
|
+
{
|
|
200
|
+
BOOL enabled = [config[@"enabled"] boolValue];
|
|
201
|
+
NSNumber *latencyValue = config[@"latencyMs"];
|
|
202
|
+
NSTimeInterval latencyMs = latencyValue != nil ? [latencyValue doubleValue] : OneKeyNetworkThrottleDefaultLatencyMs;
|
|
203
|
+
resolve([OneKeyNetworkThrottleState setEnabled:enabled latencyMs:latencyMs]);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
@end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { NativeModules, Platform } from 'react-native';
|
|
4
|
+
export const NETWORK_THROTTLE_SLOW_4G_LATENCY_MS = 562.5;
|
|
5
|
+
const LINKING_ERROR = `The package '@onekeyfe/react-native-network-throttle' doesn't seem to be linked. ` + Platform.select({
|
|
6
|
+
ios: "- run 'pod install'\n",
|
|
7
|
+
default: ''
|
|
8
|
+
}) + '- rebuild the app after installing the package';
|
|
9
|
+
const nativeModule = NativeModules.OneKeyNetworkThrottle;
|
|
10
|
+
export const NetworkThrottle = nativeModule ? nativeModule : new Proxy({}, {
|
|
11
|
+
get() {
|
|
12
|
+
throw new Error(LINKING_ERROR);
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
export default NetworkThrottle;
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"module"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"module"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type NetworkThrottleProfile = 'slow4g';
|
|
2
|
+
export type NetworkThrottleConfig = {
|
|
3
|
+
enabled: boolean;
|
|
4
|
+
profile: NetworkThrottleProfile;
|
|
5
|
+
latencyMs: number;
|
|
6
|
+
};
|
|
7
|
+
export declare const NETWORK_THROTTLE_SLOW_4G_LATENCY_MS = 562.5;
|
|
8
|
+
type NativeNetworkThrottleModule = {
|
|
9
|
+
getConfig: () => Promise<NetworkThrottleConfig>;
|
|
10
|
+
setConfig: (config: Partial<NetworkThrottleConfig>) => Promise<NetworkThrottleConfig>;
|
|
11
|
+
};
|
|
12
|
+
export declare const NetworkThrottle: NativeNetworkThrottleModule;
|
|
13
|
+
export default NetworkThrottle;
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
package/package.json
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@onekeyfe/react-native-network-throttle",
|
|
3
|
+
"version": "3.0.69",
|
|
4
|
+
"description": "react-native-network-throttle",
|
|
5
|
+
"main": "./lib/module/index.js",
|
|
6
|
+
"types": "./lib/typescript/src/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"source": "./src/index.tsx",
|
|
10
|
+
"types": "./lib/typescript/src/index.d.ts",
|
|
11
|
+
"default": "./lib/module/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./package.json": "./package.json"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"src",
|
|
17
|
+
"lib",
|
|
18
|
+
"android",
|
|
19
|
+
"ios",
|
|
20
|
+
"*.podspec",
|
|
21
|
+
"!ios/build",
|
|
22
|
+
"!android/build",
|
|
23
|
+
"!android/gradle",
|
|
24
|
+
"!android/gradlew",
|
|
25
|
+
"!android/gradlew.bat",
|
|
26
|
+
"!android/local.properties",
|
|
27
|
+
"!**/__tests__",
|
|
28
|
+
"!**/__fixtures__",
|
|
29
|
+
"!**/__mocks__",
|
|
30
|
+
"!**/.*",
|
|
31
|
+
"!**/*.map"
|
|
32
|
+
],
|
|
33
|
+
"scripts": {
|
|
34
|
+
"clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
|
|
35
|
+
"prepare": "bob build",
|
|
36
|
+
"typecheck": "tsc",
|
|
37
|
+
"lint": "eslint \"**/*.{js,ts,tsx}\"",
|
|
38
|
+
"test": "jest",
|
|
39
|
+
"release": "yarn prepare && npm whoami && npm publish --access public"
|
|
40
|
+
},
|
|
41
|
+
"keywords": [
|
|
42
|
+
"react-native",
|
|
43
|
+
"ios",
|
|
44
|
+
"android",
|
|
45
|
+
"network",
|
|
46
|
+
"throttle"
|
|
47
|
+
],
|
|
48
|
+
"repository": {
|
|
49
|
+
"type": "git",
|
|
50
|
+
"url": "git+https://github.com/OneKeyHQ/app-modules/react-native-network-throttle.git"
|
|
51
|
+
},
|
|
52
|
+
"author": "@onekeyhq <huanming@onekey.so> (https://github.com/OneKeyHQ/app-modules)",
|
|
53
|
+
"license": "MIT",
|
|
54
|
+
"bugs": {
|
|
55
|
+
"url": "https://github.com/OneKeyHQ/app-modules/react-native-network-throttle/issues"
|
|
56
|
+
},
|
|
57
|
+
"homepage": "https://github.com/OneKeyHQ/app-modules/react-native-network-throttle#readme",
|
|
58
|
+
"publishConfig": {
|
|
59
|
+
"registry": "https://registry.npmjs.org/"
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"@commitlint/config-conventional": "^19.8.1",
|
|
63
|
+
"@eslint/compat": "^1.3.2",
|
|
64
|
+
"@eslint/eslintrc": "^3.3.1",
|
|
65
|
+
"@eslint/js": "^9.35.0",
|
|
66
|
+
"@react-native/babel-preset": "0.83.0",
|
|
67
|
+
"@react-native/eslint-config": "0.83.0",
|
|
68
|
+
"@release-it/conventional-changelog": "^10.0.1",
|
|
69
|
+
"@types/jest": "^29.5.14",
|
|
70
|
+
"@types/react": "^19.2.0",
|
|
71
|
+
"commitlint": "^19.8.1",
|
|
72
|
+
"del-cli": "^6.0.0",
|
|
73
|
+
"eslint": "^9.35.0",
|
|
74
|
+
"eslint-config-prettier": "^10.1.8",
|
|
75
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
76
|
+
"jest": "^29.7.0",
|
|
77
|
+
"lefthook": "^2.0.3",
|
|
78
|
+
"prettier": "^2.8.8",
|
|
79
|
+
"react": "19.2.0",
|
|
80
|
+
"react-native": "patch:react-native@npm%3A0.83.0#~/.yarn/patches/react-native-npm-0.83.0-577d0f2d83.patch",
|
|
81
|
+
"react-native-builder-bob": "^0.40.17",
|
|
82
|
+
"release-it": "^19.0.4",
|
|
83
|
+
"turbo": "^2.5.6",
|
|
84
|
+
"typescript": "^5.9.2"
|
|
85
|
+
},
|
|
86
|
+
"peerDependencies": {
|
|
87
|
+
"react": "*",
|
|
88
|
+
"react-native": "*"
|
|
89
|
+
},
|
|
90
|
+
"react-native-builder-bob": {
|
|
91
|
+
"source": "src",
|
|
92
|
+
"output": "lib",
|
|
93
|
+
"targets": [
|
|
94
|
+
[
|
|
95
|
+
"module",
|
|
96
|
+
{
|
|
97
|
+
"esm": true
|
|
98
|
+
}
|
|
99
|
+
],
|
|
100
|
+
[
|
|
101
|
+
"typescript",
|
|
102
|
+
{
|
|
103
|
+
"project": "tsconfig.build.json"
|
|
104
|
+
}
|
|
105
|
+
]
|
|
106
|
+
]
|
|
107
|
+
},
|
|
108
|
+
"prettier": {
|
|
109
|
+
"quoteProps": "consistent",
|
|
110
|
+
"singleQuote": true,
|
|
111
|
+
"tabWidth": 2,
|
|
112
|
+
"trailingComma": "es5",
|
|
113
|
+
"useTabs": false
|
|
114
|
+
},
|
|
115
|
+
"jest": {
|
|
116
|
+
"preset": "react-native",
|
|
117
|
+
"modulePathIgnorePatterns": [
|
|
118
|
+
"<rootDir>/example/node_modules",
|
|
119
|
+
"<rootDir>/lib/"
|
|
120
|
+
]
|
|
121
|
+
},
|
|
122
|
+
"commitlint": {
|
|
123
|
+
"extends": [
|
|
124
|
+
"@commitlint/config-conventional"
|
|
125
|
+
]
|
|
126
|
+
},
|
|
127
|
+
"release-it": {
|
|
128
|
+
"git": {
|
|
129
|
+
"commitMessage": "chore: release ${version}",
|
|
130
|
+
"tagName": "v${version}"
|
|
131
|
+
},
|
|
132
|
+
"npm": {
|
|
133
|
+
"publish": true
|
|
134
|
+
},
|
|
135
|
+
"github": {
|
|
136
|
+
"release": true
|
|
137
|
+
},
|
|
138
|
+
"plugins": {
|
|
139
|
+
"@release-it/conventional-changelog": {
|
|
140
|
+
"preset": {
|
|
141
|
+
"name": "angular"
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
package/src/index.tsx
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { NativeModules, Platform } from 'react-native';
|
|
2
|
+
|
|
3
|
+
export type NetworkThrottleProfile = 'slow4g';
|
|
4
|
+
|
|
5
|
+
export type NetworkThrottleConfig = {
|
|
6
|
+
enabled: boolean;
|
|
7
|
+
profile: NetworkThrottleProfile;
|
|
8
|
+
latencyMs: number;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const NETWORK_THROTTLE_SLOW_4G_LATENCY_MS = 562.5;
|
|
12
|
+
|
|
13
|
+
type NativeNetworkThrottleModule = {
|
|
14
|
+
getConfig: () => Promise<NetworkThrottleConfig>;
|
|
15
|
+
setConfig: (
|
|
16
|
+
config: Partial<NetworkThrottleConfig>
|
|
17
|
+
) => Promise<NetworkThrottleConfig>;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const LINKING_ERROR =
|
|
21
|
+
`The package '@onekeyfe/react-native-network-throttle' doesn't seem to be linked. ` +
|
|
22
|
+
Platform.select({ ios: "- run 'pod install'\n", default: '' }) +
|
|
23
|
+
'- rebuild the app after installing the package';
|
|
24
|
+
|
|
25
|
+
const nativeModule = NativeModules.OneKeyNetworkThrottle as
|
|
26
|
+
| NativeNetworkThrottleModule
|
|
27
|
+
| undefined;
|
|
28
|
+
|
|
29
|
+
export const NetworkThrottle: NativeNetworkThrottleModule = nativeModule
|
|
30
|
+
? nativeModule
|
|
31
|
+
: (new Proxy(
|
|
32
|
+
{},
|
|
33
|
+
{
|
|
34
|
+
get() {
|
|
35
|
+
throw new Error(LINKING_ERROR);
|
|
36
|
+
},
|
|
37
|
+
}
|
|
38
|
+
) as NativeNetworkThrottleModule);
|
|
39
|
+
|
|
40
|
+
export default NetworkThrottle;
|