agora-appbuilder-core 4.1.29 → 4.1.30-beta.1

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.
Files changed (42) hide show
  1. package/Readme.md +2 -0
  2. package/package.json +1 -1
  3. package/template/Gulpfile.js +34 -0
  4. package/template/_package-lock.json +2491 -3084
  5. package/template/android/app/build.gradle +33 -23
  6. package/template/android/app/src/main/AndroidManifest.xml +5 -3
  7. package/template/android/app/src/main/java/com/helloworld/MainApplication.java +14 -2
  8. package/template/android/build.gradle +42 -7
  9. package/template/android/gradle/wrapper/gradle-wrapper.properties +3 -3
  10. package/template/android/gradle.properties +0 -3
  11. package/template/android/settings.gradle +4 -2
  12. package/template/babel.config.js +1 -1
  13. package/template/defaultConfig.js +2 -2
  14. package/template/ios/HelloWorld.xcodeproj/project.pbxproj +2 -0
  15. package/template/metro.config.js +6 -1
  16. package/template/package.json +28 -20
  17. package/template/patches/@supersami+rn-foreground-service+1.1.1.patch +12 -0
  18. package/template/scripts/verify-android-native-libs.py +106 -0
  19. package/template/src/AppWrapper.tsx +2 -7
  20. package/template/src/atoms/Carousel.native.tsx +22 -5
  21. package/template/src/atoms/CustomSwitch.tsx +0 -1
  22. package/template/src/atoms/Dropdown.tsx +0 -1
  23. package/template/src/atoms/MeetingLink.tsx +5 -12
  24. package/template/src/atoms/Popup.tsx +26 -2
  25. package/template/src/components/AppSafeAreaView.android.tsx +15 -0
  26. package/template/src/components/AppSafeAreaView.tsx +1 -0
  27. package/template/src/components/Precall.native.tsx +40 -10
  28. package/template/src/components/Share.tsx +27 -6
  29. package/template/src/components/meeting-info-invite/MeetingInfo.tsx +21 -3
  30. package/template/src/components/meeting-info-invite/MeetingInfoGridTile.tsx +11 -2
  31. package/template/src/components/useVideoCall.tsx +35 -1
  32. package/template/src/language/default-labels/joinScreenLabels.ts +2 -2
  33. package/template/src/pages/Create.tsx +26 -3
  34. package/template/src/pages/video-call/ActionSheet.native.tsx +11 -11
  35. package/template/src/pages/video-call/VideoCallScreen.native.tsx +34 -5
  36. package/template/src/pages/video-call/__tests__/VideoCallScreen.native.test.tsx +95 -0
  37. package/template/src/subComponents/Clipboard.native.tsx +1 -1
  38. package/template/src/subComponents/caption/CaptionIcon.tsx +11 -14
  39. package/template/src/subComponents/caption/TranscriptIcon.tsx +10 -14
  40. package/template/src/utils/useIsTablet.ts +10 -0
  41. package/template/android/app/src/debug/java/com/helloworld/ReactNativeFlipper.java +0 -75
  42. package/template/android/app/src/release/java/com/helloworld/ReactNativeFlipper.java +0 -20
@@ -1,11 +1,21 @@
1
1
  apply plugin: "com.android.application"
2
2
  apply plugin: "com.facebook.react"
3
3
 
4
+ dependencies {
5
+ // Declare before autolinking: pickFirst must select this shared AOSL version,
6
+ // rather than the older copy bundled in RTM. RTC and Chat need its new symbols.
7
+ // https://doc.shengwang.cn/faq/integration-issues/rtm2-rtc-integration-issue
8
+ implementation("io.agora.infra:aosl:1.3.5")
9
+ }
10
+
4
11
  /**
5
12
  * This is the configuration block to customize your React Native Android app.
6
13
  * By default you don't need to apply any configuration, just uncomment the lines you need.
7
14
  */
8
15
  react {
16
+ autolinkLibrariesWithApp()
17
+ // Bound Metro's memory use while Gradle compiles native modules in parallel.
18
+ extraPackagerArgs = ["--max-workers", "4"]
9
19
  /* Folders */
10
20
  // The root of your project, i.e. where "package.json" lives. Default is '..'
11
21
  // root = file("../")
@@ -68,6 +78,18 @@ def enableProguardInReleaseBuilds = false
68
78
  */
69
79
  def jscFlavor = 'org.webkit:android-jsc:+'
70
80
 
81
+ // Supply these through ~/.gradle/gradle.properties or environment variables.
82
+ def uploadSigning = [
83
+ storeFile: providers.gradleProperty('APPBUILDER_UPLOAD_STORE_FILE').orElse(providers.environmentVariable('APPBUILDER_UPLOAD_STORE_FILE')).orNull,
84
+ storePassword: providers.gradleProperty('APPBUILDER_UPLOAD_STORE_PASSWORD').orElse(providers.environmentVariable('APPBUILDER_UPLOAD_STORE_PASSWORD')).orNull,
85
+ keyAlias: providers.gradleProperty('APPBUILDER_UPLOAD_KEY_ALIAS').orElse(providers.environmentVariable('APPBUILDER_UPLOAD_KEY_ALIAS')).orNull,
86
+ keyPassword: providers.gradleProperty('APPBUILDER_UPLOAD_KEY_PASSWORD').orElse(providers.environmentVariable('APPBUILDER_UPLOAD_KEY_PASSWORD')).orNull,
87
+ ]
88
+ def hasUploadSigning = uploadSigning.values().every { it != null && !it.isEmpty() }
89
+ if (uploadSigning.values().any { it != null } && !hasUploadSigning) {
90
+ throw new GradleException('Set all four APPBUILDER_UPLOAD_* signing properties to sign a Play release.')
91
+ }
92
+
71
93
  android {
72
94
  ndkVersion rootProject.ext.ndkVersion
73
95
 
@@ -88,25 +110,29 @@ android {
88
110
  keyAlias 'androiddebugkey'
89
111
  keyPassword 'android'
90
112
  }
113
+ if (hasUploadSigning) {
114
+ release {
115
+ storeFile file(uploadSigning.storeFile)
116
+ storePassword uploadSigning.storePassword
117
+ keyAlias uploadSigning.keyAlias
118
+ keyPassword uploadSigning.keyPassword
119
+ }
120
+ }
91
121
  }
92
122
  buildTypes {
93
123
  debug {
94
124
  signingConfig signingConfigs.debug
95
125
  }
96
126
  release {
97
- // Caution! In production, you need to generate your own keystore file.
98
- // see https://reactnative.dev/docs/signed-apk-android.
99
- signingConfig signingConfigs.debug
127
+ // Without an upload key, release artifacts are signed for local QA only.
128
+ signingConfig hasUploadSigning ? signingConfigs.release : signingConfigs.debug
100
129
  minifyEnabled enableProguardInReleaseBuilds
101
130
  proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
102
131
  }
103
132
  }
104
133
 
105
134
  packagingOptions {
106
- pickFirst '**/lib/arm64-v8a/libaosl.so'
107
- pickFirst '**/lib/armeabi-v7a/libaosl.so'
108
- pickFirst '**/lib/x86/libaosl.so'
109
- pickFirst '**/lib/x86_64/libaosl.so'
135
+ pickFirst 'lib/**/libaosl.so'
110
136
  }
111
137
  }
112
138
 
@@ -114,25 +140,9 @@ dependencies {
114
140
  // The version of react-native is set by the React Native Gradle Plugin
115
141
  implementation("com.facebook.react:react-android")
116
142
 
117
- debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}")
118
- debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
119
- exclude group:'com.squareup.okhttp3', module:'okhttp'
120
- }
121
-
122
- debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}")
123
143
  if (hermesEnabled.toBoolean()) {
124
144
  implementation("com.facebook.react:hermes-android")
125
145
  } else {
126
146
  implementation jscFlavor
127
147
  }
128
- constraints {
129
- implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.21") {
130
- because("kotlin-stdlib-jdk7 is now a part of kotlin-stdlib")
131
- }
132
- implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.21") {
133
- because("kotlin-stdlib-jdk8 is now a part of kotlin-stdlib")
134
- }
135
- }
136
148
  }
137
-
138
- apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
@@ -1,10 +1,12 @@
1
1
  <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
2
  <uses-permission android:name="android.permission.INTERNET" />
3
3
  <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
4
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />
5
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
4
6
  <uses-permission android:name="android.permission.WAKE_LOCK" />
5
7
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
6
8
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
7
- <application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="false" android:theme="@style/AppTheme">
9
+ <application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="false" android:theme="@style/AppTheme" android:enableOnBackInvokedCallback="false">
8
10
  <activity android:name=".MainActivity" android:label="@string/app_name" android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize" android:screenOrientation="portrait" android:exported="true">
9
11
  <intent-filter>
10
12
  <action android:name="android.intent.action.MAIN" />
@@ -15,7 +17,7 @@
15
17
  <meta-data android:name="com.supersami.foregroundservice.notification_channel_name" android:value="AppBuilder"/>
16
18
  <meta-data android:name="com.supersami.foregroundservice.notification_channel_description" android:value="AppBuilder is running"/>
17
19
  <meta-data android:name="com.supersami.foregroundservice.notification_color" android:resource="@color/blue"/>
18
- <service android:name="com.supersami.foregroundservice.ForegroundService" />
20
+ <service android:name="com.supersami.foregroundservice.ForegroundService" android:foregroundServiceType="microphone|mediaPlayback" />
19
21
  <service android:name="com.supersami.foregroundservice.ForegroundServiceTask" />
20
22
  </application>
21
- </manifest>
23
+ </manifest>
@@ -3,11 +3,15 @@ package com.helloworld;
3
3
  import android.app.Application;
4
4
  import com.facebook.react.PackageList;
5
5
  import com.facebook.react.ReactApplication;
6
+ import com.facebook.react.ReactHost;
6
7
  import com.facebook.react.ReactNativeHost;
7
8
  import com.facebook.react.ReactPackage;
8
9
  import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
9
10
  import com.facebook.react.defaults.DefaultReactNativeHost;
11
+ import com.facebook.react.defaults.DefaultReactHost;
12
+ import com.facebook.react.soloader.OpenSourceMergedSoMapping;
10
13
  import com.facebook.soloader.SoLoader;
14
+ import java.io.IOException;
11
15
  import java.util.List;
12
16
  import com.facebook.react.modules.network.OkHttpClientProvider;
13
17
 
@@ -51,15 +55,23 @@ public class MainApplication extends Application implements ReactApplication {
51
55
  return mReactNativeHost;
52
56
  }
53
57
 
58
+ @Override
59
+ public ReactHost getReactHost() {
60
+ return DefaultReactHost.getDefaultReactHost(getApplicationContext(), mReactNativeHost);
61
+ }
62
+
54
63
  @Override
55
64
  public void onCreate() {
56
65
  super.onCreate();
57
- SoLoader.init(this, /* native exopackage */ false);
66
+ try {
67
+ SoLoader.init(this, OpenSourceMergedSoMapping.INSTANCE);
68
+ } catch (IOException error) {
69
+ throw new RuntimeException("Unable to initialize React Native libraries", error);
70
+ }
58
71
  if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
59
72
  // If you opted-in for the New Architecture, we load the native entry point for this app.
60
73
  DefaultNewArchitectureEntryPoint.load();
61
74
  }
62
- ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
63
75
  SSLPinningFactory sslPinningFactory = new SSLPinningFactory(getApplicationContext());
64
76
  OkHttpClientProvider.setOkHttpClientFactory(sslPinningFactory);
65
77
  }
@@ -2,23 +2,48 @@
2
2
 
3
3
  buildscript {
4
4
  ext {
5
- buildToolsVersion = "33.0.0"
5
+ buildToolsVersion = "35.0.0"
6
6
  minSdkVersion = 24
7
- compileSdkVersion = 34
8
- targetSdkVersion = 34
7
+ compileSdkVersion = 36
8
+ targetSdkVersion = 36
9
9
 
10
- // We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP.
11
- ndkVersion = "23.1.7779620"
12
- kotlinVersion = "1.8.21" // added this for datadog logs - https://docs.datadoghq.com/real_user_monitoring/mobile_and_tv_monitoring/setup/reactnative/#setup
10
+ ndkVersion = "27.1.12297006"
11
+ kotlinVersion = "2.0.21"
13
12
  androidXAnnotation = "1.2.0"
14
13
  androidXBrowser = "1.3.0"
15
14
  }
16
15
  subprojects { subproject ->
16
+ // Older native modules declare obsolete AGP versions in their own builds.
17
+ subproject.buildscript.repositories {
18
+ google()
19
+ mavenCentral()
20
+ }
21
+ subproject.buildscript.configurations.configureEach {
22
+ resolutionStrategy.force 'com.android.tools.build:gradle:8.10.1'
23
+ }
24
+ subproject.plugins.withId('com.android.library') {
25
+ subproject.android.ndkVersion = rootProject.ext.ndkVersion
26
+ subproject.android.buildFeatures.buildConfig = true
27
+ // NDK 27 needs this flag when compiling native libraries for 16 KB devices.
28
+ subproject.android.defaultConfig.externalNativeBuild.cmake.arguments.add('-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON')
29
+ // AGP 8 requires a namespace; legacy modules still put it in the manifest.
30
+ if (subproject.android.namespace == null) {
31
+ def manifest = subproject.file('src/main/AndroidManifest.xml')
32
+ if (manifest.exists()) {
33
+ def packageName = (manifest.text =~ /package\s*=\s*["']([^"']+)["']/)
34
+ if (packageName.find()) {
35
+ subproject.android.namespace = packageName.group(1)
36
+ }
37
+ }
38
+ }
39
+ }
17
40
  afterEvaluate{
18
41
  if((subproject.plugins.hasPlugin('android') || subproject.plugins.hasPlugin('android-library'))) {
19
42
  android {
20
43
  compileSdkVersion rootProject.ext.compileSdkVersion
21
44
  buildToolsVersion rootProject.ext.buildToolsVersion
45
+ ndkVersion rootProject.ext.ndkVersion
46
+ externalNativeBuild.cmake.version = '3.22.1'
22
47
  }
23
48
  }
24
49
  }
@@ -28,9 +53,19 @@ buildscript {
28
53
  mavenCentral()
29
54
  }
30
55
  dependencies {
31
- classpath("com.android.tools.build:gradle")
56
+ classpath("com.android.tools.build:gradle:8.10.1")
32
57
  classpath("com.facebook.react:react-native-gradle-plugin")
58
+ classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
33
59
  }
34
60
  }
35
61
 
62
+ apply plugin: "com.facebook.react.rootproject"
36
63
 
64
+ allprojects {
65
+ repositories {
66
+ maven {
67
+ url 'https://download.agora.io/maven/'
68
+ content { includeGroupByRegex 'io\\.agora\\.rtc.*' }
69
+ }
70
+ }
71
+ }
@@ -1,6 +1,6 @@
1
1
  distributionBase=GRADLE_USER_HOME
2
2
  distributionPath=wrapper/dists
3
- distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-all.zip
4
- networkTimeout=10000
3
+ distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
4
+ networkTimeout=60000
5
5
  zipStoreBase=GRADLE_USER_HOME
6
- zipStorePath=wrapper/dists
6
+ zipStorePath=wrapper/dists
@@ -24,9 +24,6 @@ android.useAndroidX=true
24
24
  # Automatically convert third-party libraries to use AndroidX
25
25
  android.enableJetifier=true
26
26
 
27
- # Version of flipper SDK to use with React Native
28
- FLIPPER_VERSION=0.182.0
29
-
30
27
  # Use this property to specify which architecture you want to build.
31
28
  # You can also override it from the CLI using
32
29
  # ./gradlew <task> -PreactNativeArchitectures=x86_64
@@ -1,4 +1,6 @@
1
+ pluginManagement { includeBuild("../node_modules/@react-native/gradle-plugin") }
2
+ plugins { id("com.facebook.react.settings") }
3
+ extensions.configure(com.facebook.react.ReactSettingsExtension) { ex -> ex.autolinkLibrariesFromCommand() }
1
4
  rootProject.name = 'HelloWorld'
2
- apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
3
5
  include ':app'
4
- includeBuild('../node_modules/@react-native/gradle-plugin')
6
+ includeBuild('../node_modules/@react-native/gradle-plugin')
@@ -14,7 +14,7 @@ const { getCustomizationApiPath } = require('./customization.config');
14
14
 
15
15
  // This file is read only by react native for IOS & Android. Doesn't apply to electron, Web targets
16
16
  module.exports = {
17
- presets: ['module:metro-react-native-babel-preset'],
17
+ presets: ['module:@react-native/babel-preset'],
18
18
  plugins: [
19
19
  ['transform-define', configVars],
20
20
  [
@@ -77,8 +77,8 @@ const DefaultConfig = {
77
77
  CHAT_ORG_NAME: "",
78
78
  CHAT_APP_NAME: "",
79
79
  CHAT_URL: "",
80
- CLI_VERSION: "3.1.29",
81
- CORE_VERSION: "4.1.29",
80
+ CLI_VERSION: "3.1.30-beta.1",
81
+ CORE_VERSION: "4.1.30-beta.1",
82
82
  DISABLE_LANDSCAPE_MODE: false,
83
83
  STT_AUTO_START: false,
84
84
  CLOUD_RECORDING_AUTO_START: false,
@@ -1003,6 +1003,7 @@
1003
1003
  SWIFT_OBJC_BRIDGING_HEADER = "HelloWorld-Bridging-Header.h";
1004
1004
  SWIFT_OPTIMIZATION_LEVEL = "-Onone";
1005
1005
  SWIFT_VERSION = 5.0;
1006
+ TARGETED_DEVICE_FAMILY = "1,2";
1006
1007
  VERSIONING_SYSTEM = "apple-generic";
1007
1008
  };
1008
1009
  name = Debug;
@@ -1032,6 +1033,7 @@
1032
1033
  PROVISIONING_PROFILE_SPECIFIER = "";
1033
1034
  SWIFT_OBJC_BRIDGING_HEADER = "HelloWorld-Bridging-Header.h";
1034
1035
  SWIFT_VERSION = 5.0;
1036
+ TARGETED_DEVICE_FAMILY = "1,2";
1035
1037
  VERSIONING_SYSTEM = "apple-generic";
1036
1038
  };
1037
1039
  name = Release;
@@ -6,6 +6,11 @@ const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
6
6
  *
7
7
  * @type {import('metro-config').MetroConfig}
8
8
  */
9
- const config = {};
9
+ const config = {
10
+ resolver: {
11
+ // CI builds should not depend on a running Watchman service.
12
+ useWatchman: process.env.CI !== 'true',
13
+ },
14
+ };
10
15
 
11
16
  module.exports = mergeConfig(getDefaultConfig(__dirname), config);
@@ -8,6 +8,9 @@
8
8
  "android:build": "npm run android:build:unix",
9
9
  "android:build:unix": "cross-env TARGET=android gulp androidUnix",
10
10
  "android:build:windows": "cross-env TARGET=android gulp androidWin",
11
+ "android:bundle": "npm run android:bundle:unix",
12
+ "android:bundle:unix": "cross-env TARGET=android gulp androidBundleUnix",
13
+ "android:bundle:windows": "cross-env TARGET=android gulp androidBundleWin",
11
14
  "ios": "cd ios && ls | grep .xcworkspace | xargs open",
12
15
  "ios:build": "cd ios && ls | grep .xcworkspace | xargs open",
13
16
  "start": "react-native start",
@@ -34,7 +37,8 @@
34
37
  "package:mac": "npm run mac:build && electron-builder --publish=always",
35
38
  "release": "electron-builder --mac --windows --linux --publish always --config ./electron-builder.js ",
36
39
  "make-rsdk-ts-defs": "cross-env TARGET=rsdk NODE_ENV=production gulp makeRsdkTsDefs",
37
- "make-wsdk-ts-defs": "cross-env TARGET=wsdk NODE_ENV=production gulp makeWsdkTsDefs"
40
+ "make-wsdk-ts-defs": "cross-env TARGET=wsdk NODE_ENV=production gulp makeWsdkTsDefs",
41
+ "postinstall": "patch-package --error-on-fail"
38
42
  },
39
43
  "publish": [
40
44
  {
@@ -54,10 +58,10 @@
54
58
  "@netless/react-native-whiteboard": "^0.0.14",
55
59
  "@openspacelabs/react-native-zoomable-view": "^2.1.1",
56
60
  "@react-native-async-storage/async-storage": "1.19.2",
61
+ "@react-native-clipboard/clipboard": "1.16.3",
57
62
  "@react-native-community/checkbox": "0.5.16",
58
- "@react-native-community/clipboard": "1.5.1",
59
63
  "@splinetool/runtime": "^1.9.69",
60
- "@supersami/rn-foreground-service": "^1.1.1",
64
+ "@supersami/rn-foreground-service": "1.1.1",
61
65
  "add": "^2.0.6",
62
66
  "agora-agent-client-toolkit": "2.9.0",
63
67
  "agora-chat": "1.2.2-3",
@@ -84,29 +88,30 @@
84
88
  "npm": "^9.7.2",
85
89
  "p-queue": "^7.3.4",
86
90
  "protobufjs": "^7.2.5",
87
- "react": "18.2.0",
88
- "react-dom": "18.2.0",
91
+ "react": "18.3.1",
92
+ "react-dom": "18.3.1",
89
93
  "react-is": "18.0.0",
90
- "react-native": "0.72.4",
94
+ "react-native": "0.77.3",
91
95
  "react-native-agora": "4.6.4",
92
- "react-native-agora-chat": "1.2.1",
96
+ "react-native-agora-chat": "1.4.1",
93
97
  "react-native-document-picker": "^9.1.0",
94
98
  "react-native-exit-app": "1.1.0",
95
99
  "react-native-fs": "^2.20.0",
96
- "react-native-gesture-handler": "2.8.0",
100
+ "react-native-gesture-handler": "2.25.0",
97
101
  "react-native-get-random-values": "^1.11.0",
98
102
  "react-native-hyperlink": "0.0.19",
99
103
  "react-native-inappbrowser-reborn": "3.5.1",
100
104
  "react-native-keep-awake": "4.0.0",
101
105
  "react-native-keyboard-manager": "6.5.4-1",
102
- "react-native-reanimated": "3.4.2",
106
+ "react-native-reanimated": "3.17.5",
103
107
  "react-native-responsive-fontsize": "0.5.1",
108
+ "react-native-safe-area-context": "5.4.0",
104
109
  "react-native-share": "10.0.2",
105
- "react-native-svg": "13.6.0",
110
+ "react-native-svg": "15.11.2",
106
111
  "react-native-vector-icons": "9.2.0",
107
112
  "react-native-walkthrough-tooltip": "1.4.0",
108
113
  "react-native-web": "0.19.7",
109
- "react-native-webview": "13.8.1",
114
+ "react-native-webview": "13.13.5",
110
115
  "react-router-dom": "5.2.0",
111
116
  "react-router-native": "5.2.0",
112
117
  "react-spring-bottom-sheet": "3.4.1",
@@ -117,24 +122,27 @@
117
122
  "white-web-sdk": "2.16.42"
118
123
  },
119
124
  "devDependencies": {
120
- "@babel/core": "^7.20.0",
125
+ "@babel/core": "^7.25.2",
121
126
  "@babel/plugin-proposal-class-properties": "7.14.5",
122
127
  "@babel/plugin-proposal-optional-chaining": "7.16.0",
123
128
  "@babel/preset-env": "^7.20.0",
124
129
  "@babel/preset-react": "7.13.13",
125
130
  "@babel/preset-typescript": "7.13.0",
126
- "@babel/runtime": "^7.20.0",
131
+ "@babel/runtime": "^7.25.0",
127
132
  "@bam.tech/react-native-make": "3.0.3",
128
133
  "@pmmmwh/react-refresh-webpack-plugin": "0.5.5",
134
+ "@react-native-community/cli": "15.0.1",
135
+ "@react-native-community/cli-platform-android": "15.0.1",
136
+ "@react-native-community/cli-platform-ios": "15.0.1",
129
137
  "@react-native-community/eslint-config": "1.1.0",
130
- "@react-native/eslint-config": "^0.72.2",
131
- "@react-native/metro-config": "^0.72.11",
138
+ "@react-native/babel-preset": "0.77.3",
139
+ "@react-native/eslint-config": "0.77.3",
140
+ "@react-native/metro-config": "0.77.3",
132
141
  "@tsconfig/react-native": "^3.0.0",
133
142
  "@types/hark": "^1.2.2",
134
143
  "@types/jest": "25.2.3",
135
- "@types/react": "17.0.2",
144
+ "@types/react": "^18.3.1",
136
145
  "@types/react-is": "17.0.3",
137
- "@types/react-native": "0.67.6",
138
146
  "@types/react-native-keep-awake": "2.0.2",
139
147
  "@types/react-router-dom": "5.1.7",
140
148
  "@types/react-router-native": "5.1.0",
@@ -162,12 +170,12 @@
162
170
  "html-webpack-plugin": "4.5.2",
163
171
  "ignore-loader": "^0.1.2",
164
172
  "jest": "^29.2.1",
165
- "metro-react-native-babel-preset": "0.76.8",
173
+ "patch-package": "8.0.0",
166
174
  "prettier": "^2.4.1",
167
175
  "react-devtools-electron": "4.7.0",
168
176
  "react-native-url-polyfill": "^2.0.0",
169
177
  "react-refresh": "0.12.0",
170
- "react-test-renderer": "18.2.0",
178
+ "react-test-renderer": "18.3.1",
171
179
  "style-loader": "3.3.1",
172
180
  "ts-loader": "^8.3.0",
173
181
  "typescript": "4.8.4",
@@ -180,7 +188,7 @@
180
188
  },
181
189
  "overrides": {
182
190
  "@netless/react-native-whiteboard": {
183
- "react-native-webview": "13.8.1"
191
+ "react-native-webview": "13.13.5"
184
192
  },
185
193
  "agora-extension-ai-denoiser": {
186
194
  "agora-rtc-sdk-ng": "4.20.1-1"
@@ -0,0 +1,12 @@
1
+ diff --git a/node_modules/@supersami/rn-foreground-service/android/src/main/java/com/supersami/foregroundservice/NotificationHelper.java b/node_modules/@supersami/rn-foreground-service/android/src/main/java/com/supersami/foregroundservice/NotificationHelper.java
2
+ --- a/node_modules/@supersami/rn-foreground-service/android/src/main/java/com/supersami/foregroundservice/NotificationHelper.java
3
+ +++ b/node_modules/@supersami/rn-foreground-service/android/src/main/java/com/supersami/foregroundservice/NotificationHelper.java
4
+ @@ -59 +59 @@
5
+ - PendingIntent pendingIntent = PendingIntent.getActivity(context, uniqueInt1, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
6
+ + PendingIntent pendingIntent = PendingIntent.getActivity(context, uniqueInt1, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
7
+ @@ -66 +66 @@
8
+ - pendingBtnIntent = PendingIntent.getActivity(context, uniqueInt, notificationBtnIntent, PendingIntent.FLAG_UPDATE_CURRENT);
9
+ + pendingBtnIntent = PendingIntent.getActivity(context, uniqueInt, notificationBtnIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
10
+ @@ -125 +125 @@
11
+ - notificationBuilder.addAction(R.drawable.redbox_top_border_background, bundle.getString("buttonText", "Button"), pendingBtnIntent);
12
+ + notificationBuilder.addAction(android.R.drawable.ic_media_play, bundle.getString("buttonText", "Button"), pendingBtnIntent);
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env python3
2
+ """Check 64-bit ELF/APK alignment and shared Agora AOSL symbol compatibility."""
3
+ import argparse
4
+ import struct
5
+ import sys
6
+ import zipfile
7
+ from pathlib import Path
8
+
9
+ PAGE_SIZE = 16384
10
+
11
+
12
+ def aosl_symbols(data):
13
+ """Read required and exported AOSL symbols from ELF32/ELF64 dynamic tables."""
14
+ if data[:4] != b'\x7fELF':
15
+ raise ValueError('expected an ELF library')
16
+ is_64 = data[4] == 2
17
+ endian = '<' if data[5] == 1 else '>'
18
+ table_offset = struct.unpack_from(endian + ('Q' if is_64 else 'I'), data, 40 if is_64 else 32)[0]
19
+ entry_size, entry_count = struct.unpack_from(endian + 'HH', data, 58 if is_64 else 46)
20
+ section_format = endian + ('IIQQQQIIQQ' if is_64 else 'IIIIIIIIII')
21
+ sections = [struct.unpack_from(section_format, data, table_offset + i * entry_size)
22
+ for i in range(entry_count)]
23
+ required, exported = set(), set()
24
+ for section in sections:
25
+ if section[1] != 11: # SHT_DYNSYM
26
+ continue
27
+ strings = sections[section[6]]
28
+ string_data = data[strings[4]:strings[4] + strings[5]]
29
+ for offset in range(section[4], section[4] + section[5], section[9]):
30
+ symbol = struct.unpack_from(endian + ('IBBHQQ' if is_64 else 'IIIBBH'), data, offset)
31
+ name_offset = symbol[0]
32
+ name_bytes = string_data[name_offset:string_data.find(b'\0', name_offset)]
33
+ if not name_bytes.startswith(b'aosl_'):
34
+ continue
35
+ name = name_bytes.decode('ascii')
36
+ info, section_index = (symbol[1], symbol[3]) if is_64 else (symbol[3], symbol[5])
37
+ if section_index == 0:
38
+ if info >> 4 == 1: # Undefined GLOBAL symbols; WEAK imports are optional.
39
+ required.add(name)
40
+ elif info >> 4 in (1, 2):
41
+ exported.add(name)
42
+ return required, exported
43
+
44
+
45
+ def check_artifact(path):
46
+ failures = []
47
+ checked = 0
48
+ aosl_providers = {}
49
+ aosl_consumers = []
50
+ with zipfile.ZipFile(path) as archive, path.open('rb') as artifact:
51
+ for entry in archive.infolist():
52
+ name = entry.filename
53
+ if name.endswith('.so'):
54
+ data = archive.read(entry)
55
+ required, exported = aosl_symbols(data)
56
+ abi = name.split('/')[-2]
57
+ if name.endswith('/libaosl.so'):
58
+ aosl_providers[abi] = exported
59
+ if required:
60
+ aosl_consumers.append((name, abi, required))
61
+ if not name.endswith('.so') or not any(
62
+ f'/{abi}/' in name for abi in ('arm64-v8a', 'x86_64')
63
+ ):
64
+ continue
65
+ checked += 1
66
+ data = archive.read(entry)
67
+ if data[:5] != b'\x7fELF\x02':
68
+ failures.append(f'{name}: expected a 64-bit ELF library')
69
+ continue
70
+ endian = '<' if data[5] == 1 else '>'
71
+ table_offset = struct.unpack_from(endian + 'Q', data, 32)[0]
72
+ entry_size, entry_count = struct.unpack_from(endian + 'HH', data, 54)
73
+ for index in range(entry_count):
74
+ offset = table_offset + index * entry_size
75
+ segment_type = struct.unpack_from(endian + 'I', data, offset)[0]
76
+ if segment_type == 1: # PT_LOAD
77
+ alignment = struct.unpack_from(endian + 'Q', data, offset + 48)[0]
78
+ if alignment < PAGE_SIZE:
79
+ failures.append(f'{name}: ELF load segment is aligned to {alignment} bytes')
80
+ break
81
+ if path.suffix == '.apk' and entry.compress_type == zipfile.ZIP_STORED:
82
+ artifact.seek(entry.header_offset + 26)
83
+ name_size, extra_size = struct.unpack('<HH', artifact.read(4))
84
+ data_offset = entry.header_offset + 30 + name_size + extra_size
85
+ if data_offset % PAGE_SIZE:
86
+ failures.append(f'{name}: uncompressed APK entry lacks 16 KB ZIP alignment')
87
+ if not checked:
88
+ failures.append('No 64-bit native libraries found')
89
+ for name, abi, required in aosl_consumers:
90
+ missing = required - aosl_providers.get(abi, set())
91
+ if missing:
92
+ failures.append(f'{name}: packaged libaosl.so lacks symbols: {", ".join(sorted(missing))}')
93
+ for failure in failures:
94
+ print(f'FAIL: {failure}', file=sys.stderr)
95
+ print(f'{path.name}: checked alignment of {checked} native libraries and '
96
+ f'AOSL imports in {len(aosl_consumers)} libraries; {len(failures)} failures')
97
+ if path.suffix == '.aab':
98
+ print('AAB check covers ELF alignment. Also verify ZIP alignment in generated APKs.')
99
+ return bool(failures)
100
+
101
+
102
+ if __name__ == '__main__':
103
+ parser = argparse.ArgumentParser(description=__doc__)
104
+ parser.add_argument('artifact', type=Path)
105
+ args = parser.parse_args()
106
+ sys.exit(check_artifact(args.artifact))
@@ -14,13 +14,7 @@ import {Router} from './components/Router';
14
14
  import Navigation from './components/Navigation';
15
15
  import {StorageProvider} from './components/StorageContext';
16
16
  import {SessionProvider} from './components/SessionContext';
17
- import {
18
- ImageBackground,
19
- SafeAreaView,
20
- StatusBar,
21
- Platform,
22
- View,
23
- } from 'react-native';
17
+ import {ImageBackground, StatusBar, Platform, View} from 'react-native';
24
18
  import ColorConfigure from './components/ColorConfigure';
25
19
  import {isValidReactComponent} from './utils/common';
26
20
  import DimensionProvider from './components/dimension/DimensionProvider';
@@ -35,6 +29,7 @@ import {ToastContext, ToastProvider} from './components/useToast';
35
29
  import {SdkApiContext} from './components/SdkApiContext';
36
30
  import isSDK from './utils/isSDK';
37
31
  import BlockUI from './subComponents/BlockUI';
32
+ import SafeAreaView from './components/AppSafeAreaView';
38
33
 
39
34
  interface AppWrapperProps {
40
35
  children: React.ReactNode;
@@ -1,9 +1,7 @@
1
- import React, {useState} from 'react';
2
- import {View, StyleSheet, Dimensions, Pressable} from 'react-native';
1
+ import React, {useEffect, useState} from 'react';
2
+ import {View, StyleSheet, useWindowDimensions, Pressable} from 'react-native';
3
3
  import {FlatList} from 'react-native-gesture-handler';
4
4
 
5
- const {width} = Dimensions.get('window');
6
-
7
5
  interface CarouselItem {
8
6
  id: string;
9
7
  component: React.ReactNode;
@@ -14,9 +12,22 @@ interface CarouselProps {
14
12
  }
15
13
 
16
14
  const Carousel: React.FC<CarouselProps> = ({data}) => {
15
+ const {width: windowWidth} = useWindowDimensions();
16
+ const [width, setWidth] = useState(windowWidth);
17
17
  const [activeIndex, setActiveIndex] = useState(0);
18
18
 
19
19
  const flatListRef = React.useRef<FlatList | null>(null);
20
+ const previousWidth = React.useRef(width);
21
+
22
+ useEffect(() => {
23
+ if (previousWidth.current !== width) {
24
+ previousWidth.current = width;
25
+ flatListRef.current?.scrollToOffset({
26
+ offset: activeIndex * width,
27
+ animated: false,
28
+ });
29
+ }
30
+ }, [width, activeIndex]);
20
31
 
21
32
  const handleScroll = event => {
22
33
  const {contentOffset} = event.nativeEvent;
@@ -37,7 +48,13 @@ const Carousel: React.FC<CarouselProps> = ({data}) => {
37
48
  };
38
49
 
39
50
  return (
40
- <View style={styles.container}>
51
+ <View
52
+ style={styles.container}
53
+ onLayout={({nativeEvent: {layout}}) => {
54
+ if (layout.width > 0) {
55
+ setWidth(layout.width);
56
+ }
57
+ }}>
41
58
  <FlatList
42
59
  ref={flatListRef}
43
60
  data={data}