From 60226b6f3b7bfd7356149082c4d7178bde240a54 Mon Sep 17 00:00:00 2001 From: floydkim Date: Wed, 18 Feb 2026 20:01:05 +0900 Subject: [PATCH 1/7] chore(e2e): harden AndroidManifest cleartext patch for RN/Expo example setup --- scripts/setupExampleApp/runSetupExampleApp.ts | 43 +++++++-------- .../runSetupExpoExampleApp.ts | 52 ++++++++++++++++++- 2 files changed, 71 insertions(+), 24 deletions(-) diff --git a/scripts/setupExampleApp/runSetupExampleApp.ts b/scripts/setupExampleApp/runSetupExampleApp.ts index 7c6ef841..3830eada 100644 --- a/scripts/setupExampleApp/runSetupExampleApp.ts +++ b/scripts/setupExampleApp/runSetupExampleApp.ts @@ -153,7 +153,7 @@ function buildCodePushBundleIdentifier(projectName: string): string { if (normalized.length === 0) { throw new Error(`Invalid project name for bundle identifier: ${projectName}`); } - return `com.codepush.${normalized}`; + return `com.${normalized}`; } async function createReactNativeTemplateApp(context: SetupContext): Promise { @@ -242,7 +242,6 @@ async function configureIosVersioning(context: SetupContext): Promise { } async function configureAndroidVersioning(context: SetupContext): Promise { - const bundleIdentifier = buildCodePushBundleIdentifier(context.projectName); const buildGradlePath = path.join( context.projectPath, "android", @@ -253,7 +252,7 @@ async function configureAndroidVersioning(context: SetupContext): Promise updateTextFile(buildGradlePath, (content) => { let next = replaceAllOrThrow( content, - /versionName\s+"[^"]+"/g, + /versionName\s*=?\s*["'][^"']+["']/g, "versionName \"1.0.0\"", "versionName" ); @@ -263,18 +262,6 @@ async function configureAndroidVersioning(context: SetupContext): Promise "def enableProguardInReleaseBuilds = true", "enableProguardInReleaseBuilds flag" ); - next = replaceAllOrThrow( - next, - /namespace\s+"[^"]+"/g, - `namespace "${bundleIdentifier}"`, - "namespace" - ); - next = replaceAllOrThrow( - next, - /applicationId\s+"[^"]+"/g, - `applicationId "${bundleIdentifier}"`, - "applicationId" - ); return next; }); @@ -286,14 +273,24 @@ async function configureAndroidVersioning(context: SetupContext): Promise "main", "AndroidManifest.xml" ); - updateTextFile(manifestPath, (content) => - replaceAllOrThrow( - content, - /android:usesCleartextTraffic="\$\{usesCleartextTraffic\}"/, - 'android:usesCleartextTraffic="true"', - "usesCleartextTraffic" - ) - ); + updateTextFile(manifestPath, (content) => { + const replaced = content.replace( + /android:usesCleartextTraffic="(?:\$\{usesCleartextTraffic\}|[^"]*)"/, + 'android:usesCleartextTraffic="true"' + ); + if (replaced !== content) { + return replaced; + } + + const applicationTagMatch = content.match(/]*>/); + if (!applicationTagMatch) { + throw new Error("No tag found in AndroidManifest.xml"); + } + return content.replace( + applicationTagMatch[0], + applicationTagMatch[0].replace(/>$/, ' android:usesCleartextTraffic="true">') + ); + }); } async function configureLocalCodeLink(context: SetupContext): Promise { diff --git a/scripts/setupExpoExampleApp/runSetupExpoExampleApp.ts b/scripts/setupExpoExampleApp/runSetupExpoExampleApp.ts index 17137d52..a7859c52 100644 --- a/scripts/setupExpoExampleApp/runSetupExpoExampleApp.ts +++ b/scripts/setupExpoExampleApp/runSetupExpoExampleApp.ts @@ -134,6 +134,11 @@ const setupSteps: SetupStep[] = [ name: "configure-ios-min-deployment-target", description: "Raise iOS minimum deployment target", run: configureIosMinDeploymentTarget + }, + { + name: "configure-android-cleartext-traffic", + description: "Allow Android cleartext HTTP traffic for local mock server", + run: configureAndroidCleartextTraffic } ]; @@ -541,6 +546,51 @@ async function configureIosMinDeploymentTarget(context: SetupContext): Promise { + const manifestPath = path.join( + context.projectPath, + "android", + "app", + "src", + "main", + "AndroidManifest.xml" + ); + + if (!fs.existsSync(manifestPath)) { + console.log("[skip] AndroidManifest.xml does not exist"); + return; + } + + const originalContent = fs.readFileSync(manifestPath, "utf8"); + const applicationTagMatch = originalContent.match(/]*>/); + if (!applicationTagMatch) { + console.log("[skip] tag not found in AndroidManifest.xml"); + return; + } + + let updatedApplicationTag = applicationTagMatch[0]; + if (/android:usesCleartextTraffic\s*=/.test(updatedApplicationTag)) { + updatedApplicationTag = updatedApplicationTag.replace( + /android:usesCleartextTraffic\s*=\s*"[^"]*"/, + 'android:usesCleartextTraffic="true"' + ); + } else { + updatedApplicationTag = updatedApplicationTag.replace( + />$/, + ' android:usesCleartextTraffic="true">' + ); + } + + const updatedContent = originalContent.replace( + applicationTagMatch[0], + updatedApplicationTag + ); + + if (updatedContent !== originalContent) { + fs.writeFileSync(manifestPath, updatedContent, "utf8"); + } +} + function findFirstXcodeProjProjectPath(iosPath: string): string | null { const entries = fs.readdirSync(iosPath); const xcodeProj = entries.find((entry) => entry.endsWith(".xcodeproj")); @@ -578,7 +628,7 @@ function buildExpoBundleIdentifier(projectName: string): string { if (normalized.length === 0) { throw new Error(`Invalid project name for bundle identifier: ${projectName}`); } - return `com.codepush.${normalized}`; + return `com.${normalized}`; } function ensureDirectory(targetDir: string) { From 4594dd8bba55c998a4b6d719d8523cc89b0cdfc1 Mon Sep 17 00:00:00 2001 From: floydkim Date: Wed, 18 Feb 2026 20:02:34 +0900 Subject: [PATCH 2/7] chore(e2e): keep release identifier in sync with app IDENTIFIER during CodePush release --- e2e/run.ts | 134 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 126 insertions(+), 8 deletions(-) diff --git a/e2e/run.ts b/e2e/run.ts index 39a0a2cd..b1e2d22d 100644 --- a/e2e/run.ts +++ b/e2e/run.ts @@ -35,6 +35,10 @@ async function main() { return; } + await syncLocalLibraryIfAvailable(appPath, options.maestroOnly ?? false); + + const releaseIdentifier = getCodePushReleaseIdentifier(appPath); + try { // 1. Prepare config console.log("\n=== [prepare] ==="); @@ -49,15 +53,17 @@ async function main() { // 3. Prepare update bundle console.log("\n=== [prepare-bundle] ==="); cleanMockData(); - await prepareBundle(appPath, options.platform, options.app, options.framework); + await prepareBundle(appPath, options.platform, releaseIdentifier, options.framework); // 4. Start mock server console.log("\n=== [start-mock-server] ==="); await startMockServer(); + const appId = getAppId(appPath, options.platform); + await resetAppStateBeforeFlows(options.platform, appId); + // 5. Run Maestro — Phase 1: main flows console.log("\n=== [run-maestro: phase 1] ==="); - const appId = getAppId(appPath, options.platform); const flowsDir = path.resolve(__dirname, "flows"); await runMaestro(flowsDir, options.platform, appId); @@ -69,7 +75,7 @@ async function main() { "-b", "1.0.0", "-v", "1.0.1", "-p", options.platform, - "-i", options.app, + "-i", releaseIdentifier, "-e", "false", ]); @@ -89,7 +95,7 @@ async function main() { "-c", "code-push.config.local.ts", "-b", "1.0.0", "-p", options.platform, - "-i", options.app, + "-i", releaseIdentifier, ]); setReleaseMarker(appPath, "1.0.1"); await runCodePushCommand(appPath, options.platform, options.app, [ @@ -97,7 +103,7 @@ async function main() { "-c", "code-push.config.local.ts", "-b", "1.0.0", "-v", "1.0.1", ...frameworkArgs, - "-p", options.platform, "-i", options.app, + "-p", options.platform, "-i", releaseIdentifier, "-e", entryFile, "-m", "true", ]); setReleaseMarker(appPath, "1.0.2"); @@ -106,7 +112,7 @@ async function main() { "-c", "code-push.config.local.ts", "-b", "1.0.0", "-v", "1.0.2", ...frameworkArgs, - "-p", options.platform, "-i", options.app, + "-p", options.platform, "-i", releaseIdentifier, "-e", entryFile, "-m", "true", ]); } finally { @@ -125,7 +131,7 @@ async function main() { "code-push", "update-history", "-c", "code-push.config.local.ts", "-b", "1.0.0", "-v", "1.0.2", - "-p", options.platform, "-i", options.app, + "-p", options.platform, "-i", releaseIdentifier, "-e", "false", ]); @@ -154,6 +160,19 @@ function cleanMockData(): void { fs.mkdirSync(MOCK_DATA_DIR, { recursive: true }); } +// npx code-push release/create-history must use the same identifier that the app uses when fetching history. +function getCodePushReleaseIdentifier(appPath: string): string { + const appTsxPath = path.join(appPath, "App.tsx"); + const content = fs.readFileSync(appTsxPath, "utf8"); + const match = content.match(/const IDENTIFIER = ['"]([^'"]+)['"]/); + + if (!match) { + throw new Error(`Could not find CodePush IDENTIFIER in ${appTsxPath}`); + } + + return match[1]; +} + function getAppId(appPath: string, platform: "ios" | "android"): string { const appJsonPath = path.join(appPath, "app.json"); const appJson = JSON.parse(fs.readFileSync(appJsonPath, "utf8")) as { @@ -207,7 +226,7 @@ function buildCodePushBundleIdentifier(appName: string): string { if (normalized.length === 0) { throw new Error(`Invalid app name for bundle identifier: ${appName}`); } - return `com.codepush.${normalized}`; + return `com.${normalized}`; } function runMaestro(flowsDir: string, platform: "ios" | "android", appId: string): Promise { @@ -232,3 +251,102 @@ function runMaestro(flowsDir: string, platform: "ios" | "android", appId: string } void main(); + +function resetAppStateBeforeFlows( + platform: "ios" | "android", + appId: string, +): Promise { + if (platform !== "android") { + return Promise.resolve(); + } + + const args = ["shell", "pm", "clear", appId]; + console.log(`[command] adb ${args.join(" ")}`); + return new Promise((resolve, reject) => { + const child = spawn("adb", args, { stdio: "inherit" }); + child.on("error", reject); + child.on("close", (code) => { + if (code === 0) { + resolve(); + } else { + reject(new Error(`adb pm clear failed (exit code: ${code})`)); + } + }); + }); +} + +function syncLocalLibraryIfAvailable(appPath: string, maestroOnly: boolean): Promise { + const packageJsonPath = path.join(appPath, "package.json"); + if (!fs.existsSync(packageJsonPath)) { + return Promise.resolve(); + } + + const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8")) as { + scripts?: Record; + }; + const hasSyncScript = Boolean(packageJson.scripts?.["sync-local-library"]); + + if (!hasSyncScript) { + return Promise.resolve(); + } + + if (maestroOnly) { + console.log( + "[warn] --maestro-only mode: native library changes require rebuilding the app binary.", + ); + } + + const args = ["run", "sync-local-library"]; + console.log(`[command] npm ${args.join(" ")} (cwd: ${appPath})`); + + const verbose = process.env.E2E_VERBOSE_SYNC === "1"; + if (verbose) { + return new Promise((resolve, reject) => { + const child = spawn("npm", args, { cwd: appPath, stdio: "inherit" }); + child.on("error", reject); + child.on("close", (code) => { + if (code === 0) { + resolve(); + } else { + reject(new Error(`npm run sync-local-library failed (exit code: ${code})`)); + } + }); + }); + } + + return new Promise((resolve, reject) => { + const child = spawn("npm", args, { + cwd: appPath, + stdio: ["ignore", "pipe", "pipe"], + env: { + ...process.env, + npm_config_loglevel: "error", + }, + }); + let output = ""; + child.stdout?.on("data", (chunk) => { + output += chunk.toString(); + if (output.length > 12000) { + output = output.slice(output.length - 12000); + } + }); + child.stderr?.on("data", (chunk) => { + output += chunk.toString(); + if (output.length > 12000) { + output = output.slice(output.length - 12000); + } + }); + child.on("error", reject); + child.on("close", (code) => { + if (code === 0) { + console.log("[sync-local-library] done"); + resolve(); + } else { + if (output.trim().length > 0) { + console.error("[sync-local-library] output:\n" + output.trim()); + } + reject(new Error(`npm run sync-local-library failed (exit code: ${code})`)); + } + }); + }); +} From 326503d58876227e5f09203cbefde0f33d97e1ca Mon Sep 17 00:00:00 2001 From: floydkim Date: Wed, 18 Feb 2026 20:03:31 +0900 Subject: [PATCH 3/7] chore(e2e): allow mock server host override via platform env vars --- e2e/config.ts | 6 ++++-- e2e/mock-server/server.ts | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/e2e/config.ts b/e2e/config.ts index adf45012..d367f0f6 100644 --- a/e2e/config.ts +++ b/e2e/config.ts @@ -5,10 +5,12 @@ export const EXAMPLES_DIR = path.resolve(__dirname, "../Examples"); export const MOCK_DATA_DIR = path.resolve(__dirname, "mock-server/data"); export function getMockServerHost(platform: "ios" | "android"): string { - const host = platform === "android" ? "10.0.2.2" : "localhost"; + const host = platform === "android" + ? process.env.E2E_ANDROID_MOCK_SERVER_HOST ?? "10.0.2.2" + : process.env.E2E_IOS_MOCK_SERVER_HOST ?? "localhost"; return `http://${host}:${MOCK_SERVER_PORT}`; } export function getAppPath(appName: string): string { return path.join(EXAMPLES_DIR, appName); -} \ No newline at end of file +} diff --git a/e2e/mock-server/server.ts b/e2e/mock-server/server.ts index f137e775..b4d435e7 100644 --- a/e2e/mock-server/server.ts +++ b/e2e/mock-server/server.ts @@ -42,4 +42,4 @@ export function stopMockServer(): Promise { resolve(); } }); -} \ No newline at end of file +} From 53b3ed55339b130a7ee46236b3ab41ffabcb78f8 Mon Sep 17 00:00:00 2001 From: floydkim Date: Wed, 18 Feb 2026 20:12:25 +0900 Subject: [PATCH 4/7] remove: RN 0.84.0 app will be replaced with 0.84.1 --- Examples/RN0840/.bundle/config | 2 - Examples/RN0840/.eslintrc.js | 4 - Examples/RN0840/.gitignore | 75 - Examples/RN0840/.prettierrc.js | 5 - Examples/RN0840/.watchmanconfig | 1 - Examples/RN0840/App.tsx | 188 - Examples/RN0840/Gemfile | 16 - Examples/RN0840/Gemfile.lock | 111 - Examples/RN0840/README.md | 97 - Examples/RN0840/__tests__/App.test.tsx | 13 - Examples/RN0840/android/app/build.gradle | 119 - Examples/RN0840/android/app/debug.keystore | Bin 2257 -> 0 bytes .../RN0840/android/app/proguard-rules.pro | 10 - .../android/app/src/main/AndroidManifest.xml | 27 - .../src/main/java/com/rn0840/MainActivity.kt | 22 - .../main/java/com/rn0840/MainApplication.kt | 29 - .../res/drawable/rn_edit_text_material.xml | 37 - .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 3056 -> 0 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 5024 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 2096 -> 0 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 2858 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 4569 -> 0 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 7098 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 6464 -> 0 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 10676 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 9250 -> 0 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 15523 -> 0 bytes .../app/src/main/res/values/strings.xml | 3 - .../app/src/main/res/values/styles.xml | 9 - Examples/RN0840/android/build.gradle | 21 - Examples/RN0840/android/gradle.properties | 44 - .../android/gradle/wrapper/gradle-wrapper.jar | Bin 45457 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 - Examples/RN0840/android/gradlew | 251 - Examples/RN0840/android/gradlew.bat | 99 - Examples/RN0840/android/settings.gradle | 6 - Examples/RN0840/app.json | 4 - Examples/RN0840/babel.config.js | 3 - Examples/RN0840/code-push.config.ts | 116 - Examples/RN0840/index.js | 9 - Examples/RN0840/ios/.xcode.env | 11 - Examples/RN0840/ios/Podfile | 34 - Examples/RN0840/ios/Podfile.lock | 2187 --- .../ios/RN0840.xcodeproj/project.pbxproj | 504 - .../xcshareddata/xcschemes/RN0840.xcscheme | 88 - .../contents.xcworkspacedata | 10 - Examples/RN0840/ios/RN0840/AppDelegate.swift | 48 - .../AppIcon.appiconset/Contents.json | 53 - .../ios/RN0840/Images.xcassets/Contents.json | 6 - Examples/RN0840/ios/RN0840/Info.plist | 60 - .../RN0840/ios/RN0840/LaunchScreen.storyboard | 47 - .../RN0840/ios/RN0840/PrivacyInfo.xcprivacy | 37 - .../ios/RN0840/RN0840-Bridging-Header.h | 1 - Examples/RN0840/jest.config.js | 3 - Examples/RN0840/metro.config.js | 11 - Examples/RN0840/package-lock.json | 12430 ---------------- Examples/RN0840/package.json | 49 - Examples/RN0840/tsconfig.json | 25 - 58 files changed, 16932 deletions(-) delete mode 100644 Examples/RN0840/.bundle/config delete mode 100644 Examples/RN0840/.eslintrc.js delete mode 100644 Examples/RN0840/.gitignore delete mode 100644 Examples/RN0840/.prettierrc.js delete mode 100644 Examples/RN0840/.watchmanconfig delete mode 100644 Examples/RN0840/App.tsx delete mode 100644 Examples/RN0840/Gemfile delete mode 100644 Examples/RN0840/Gemfile.lock delete mode 100644 Examples/RN0840/README.md delete mode 100644 Examples/RN0840/__tests__/App.test.tsx delete mode 100644 Examples/RN0840/android/app/build.gradle delete mode 100644 Examples/RN0840/android/app/debug.keystore delete mode 100644 Examples/RN0840/android/app/proguard-rules.pro delete mode 100644 Examples/RN0840/android/app/src/main/AndroidManifest.xml delete mode 100644 Examples/RN0840/android/app/src/main/java/com/rn0840/MainActivity.kt delete mode 100644 Examples/RN0840/android/app/src/main/java/com/rn0840/MainApplication.kt delete mode 100644 Examples/RN0840/android/app/src/main/res/drawable/rn_edit_text_material.xml delete mode 100644 Examples/RN0840/android/app/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100644 Examples/RN0840/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png delete mode 100644 Examples/RN0840/android/app/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100644 Examples/RN0840/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png delete mode 100644 Examples/RN0840/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 Examples/RN0840/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png delete mode 100644 Examples/RN0840/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 Examples/RN0840/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png delete mode 100644 Examples/RN0840/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 Examples/RN0840/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png delete mode 100644 Examples/RN0840/android/app/src/main/res/values/strings.xml delete mode 100644 Examples/RN0840/android/app/src/main/res/values/styles.xml delete mode 100644 Examples/RN0840/android/build.gradle delete mode 100644 Examples/RN0840/android/gradle.properties delete mode 100644 Examples/RN0840/android/gradle/wrapper/gradle-wrapper.jar delete mode 100644 Examples/RN0840/android/gradle/wrapper/gradle-wrapper.properties delete mode 100755 Examples/RN0840/android/gradlew delete mode 100644 Examples/RN0840/android/gradlew.bat delete mode 100644 Examples/RN0840/android/settings.gradle delete mode 100644 Examples/RN0840/app.json delete mode 100644 Examples/RN0840/babel.config.js delete mode 100644 Examples/RN0840/code-push.config.ts delete mode 100644 Examples/RN0840/index.js delete mode 100644 Examples/RN0840/ios/.xcode.env delete mode 100644 Examples/RN0840/ios/Podfile delete mode 100644 Examples/RN0840/ios/Podfile.lock delete mode 100644 Examples/RN0840/ios/RN0840.xcodeproj/project.pbxproj delete mode 100644 Examples/RN0840/ios/RN0840.xcodeproj/xcshareddata/xcschemes/RN0840.xcscheme delete mode 100644 Examples/RN0840/ios/RN0840.xcworkspace/contents.xcworkspacedata delete mode 100644 Examples/RN0840/ios/RN0840/AppDelegate.swift delete mode 100644 Examples/RN0840/ios/RN0840/Images.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 Examples/RN0840/ios/RN0840/Images.xcassets/Contents.json delete mode 100644 Examples/RN0840/ios/RN0840/Info.plist delete mode 100644 Examples/RN0840/ios/RN0840/LaunchScreen.storyboard delete mode 100644 Examples/RN0840/ios/RN0840/PrivacyInfo.xcprivacy delete mode 100644 Examples/RN0840/ios/RN0840/RN0840-Bridging-Header.h delete mode 100644 Examples/RN0840/jest.config.js delete mode 100644 Examples/RN0840/metro.config.js delete mode 100644 Examples/RN0840/package-lock.json delete mode 100644 Examples/RN0840/package.json delete mode 100644 Examples/RN0840/tsconfig.json diff --git a/Examples/RN0840/.bundle/config b/Examples/RN0840/.bundle/config deleted file mode 100644 index 848943bb..00000000 --- a/Examples/RN0840/.bundle/config +++ /dev/null @@ -1,2 +0,0 @@ -BUNDLE_PATH: "vendor/bundle" -BUNDLE_FORCE_RUBY_PLATFORM: 1 diff --git a/Examples/RN0840/.eslintrc.js b/Examples/RN0840/.eslintrc.js deleted file mode 100644 index 187894b6..00000000 --- a/Examples/RN0840/.eslintrc.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - root: true, - extends: '@react-native', -}; diff --git a/Examples/RN0840/.gitignore b/Examples/RN0840/.gitignore deleted file mode 100644 index de999559..00000000 --- a/Examples/RN0840/.gitignore +++ /dev/null @@ -1,75 +0,0 @@ -# OSX -# -.DS_Store - -# Xcode -# -build/ -*.pbxuser -!default.pbxuser -*.mode1v3 -!default.mode1v3 -*.mode2v3 -!default.mode2v3 -*.perspectivev3 -!default.perspectivev3 -xcuserdata -*.xccheckout -*.moved-aside -DerivedData -*.hmap -*.ipa -*.xcuserstate -**/.xcode.env.local - -# Android/IntelliJ -# -build/ -.idea -.gradle -local.properties -*.iml -*.hprof -.cxx/ -*.keystore -!debug.keystore -.kotlin/ - -# node.js -# -node_modules/ -npm-debug.log -yarn-error.log - -# fastlane -# -# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the -# screenshots whenever they are needed. -# For more information about the recommended setup visit: -# https://docs.fastlane.tools/best-practices/source-control/ - -**/fastlane/report.xml -**/fastlane/Preview.html -**/fastlane/screenshots -**/fastlane/test_output - -# Bundle artifact -*.jsbundle - -# Ruby / CocoaPods -**/Pods/ -/vendor/bundle/ - -# Temporary files created by Metro to check the health of the file watcher -.metro-health-check* - -# testing -/coverage - -# Yarn -.yarn/* -!.yarn/patches -!.yarn/plugins -!.yarn/releases -!.yarn/sdks -!.yarn/versions diff --git a/Examples/RN0840/.prettierrc.js b/Examples/RN0840/.prettierrc.js deleted file mode 100644 index 06860c8d..00000000 --- a/Examples/RN0840/.prettierrc.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - arrowParens: 'avoid', - singleQuote: true, - trailingComma: 'all', -}; diff --git a/Examples/RN0840/.watchmanconfig b/Examples/RN0840/.watchmanconfig deleted file mode 100644 index 0967ef42..00000000 --- a/Examples/RN0840/.watchmanconfig +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/Examples/RN0840/App.tsx b/Examples/RN0840/App.tsx deleted file mode 100644 index d65b485b..00000000 --- a/Examples/RN0840/App.tsx +++ /dev/null @@ -1,188 +0,0 @@ -import React, { useCallback, useState } from 'react'; -import { - Button, - Platform, - ScrollView, - StatusBar, - Text, - TextInput, - View, -} from 'react-native'; -import CodePush, { - ReleaseHistoryInterface, - UpdateCheckRequest, -} from '@bravemobile/react-native-code-push'; -import axios from 'axios'; -import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context'; - -// Set this to true before run `npx code-push release` to release a new bundle -const IS_RELEASING_BUNDLE = false; - -const REACT_NATIVE_VERSION = (() => { - const { major, minor, patch, prerelease } = Platform.constants.reactNativeVersion; - return `${major}.${minor}.${patch}` + (prerelease ? `-${prerelease}` : ''); -})(); - -function App() { - const { top } = useSafeAreaInsets(); - const [syncResult, setSyncResult] = useState(''); - const [progress, setProgress] = useState(0); - const [runningMetadata, setRunningMetadata] = useState(''); - const [pendingMetadata, setPendingMetadata] = useState(''); - const [latestMetadata, setLatestMetadata] = useState(''); - - const handleSync = useCallback(() => { - CodePush.sync( - {}, - status => { - setSyncResult(findKeyByValue(CodePush.SyncStatus, status) ?? ''); - }, - ({ receivedBytes, totalBytes }) => { - setProgress(Math.round((receivedBytes / totalBytes) * 100)); - }, - mismatch => { - console.log('CodePush mismatch', JSON.stringify(mismatch, null, 2)); - }, - ).catch(error => { - console.error(error); - console.log('Sync failed', error.message ?? 'Unknown error'); - }); - }, []); - - const handleMetadata = useCallback(async () => { - const [running, pending, latest] = await Promise.all([ - CodePush.getUpdateMetadata(CodePush.UpdateState.RUNNING), - CodePush.getUpdateMetadata(CodePush.UpdateState.PENDING), - CodePush.getUpdateMetadata(CodePush.UpdateState.LATEST), - ]); - setRunningMetadata(JSON.stringify(running ?? null, null, 2)); - setPendingMetadata(JSON.stringify(pending ?? null, null, 2)); - setLatestMetadata(JSON.stringify(latest ?? null, null, 2)); - }, []); - - return ( - - - {`React Native ${REACT_NATIVE_VERSION}`} - - {IS_RELEASING_BUNDLE && - {'UPDATED!'} - } - - - -