From 61ec3692b74b1328f55c2b9fd28498296460cd9f Mon Sep 17 00:00:00 2001 From: jjbrunton Date: Fri, 28 Aug 2026 20:28:31 +0100 Subject: [PATCH] chore(android): target API 36 with Expo 54 Upgrade the mobile native toolchain and Expo dependencies for Android 16 compatibility while preserving web and admin runtime isolation. --- .nvmrc | 2 +- apps/mobile/android/app/build.gradle | 27 +- .../android/app/src/main/AndroidManifest.xml | 6 +- .../java/com/sauci/app/MainApplication.kt | 15 +- .../app/src/main/res/values/styles.xml | 1 + apps/mobile/android/build.gradle | 21 +- apps/mobile/android/gradle.properties | 18 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- apps/mobile/android/settings.gradle | 49 +- apps/mobile/app.json | 9 +- apps/mobile/app/(app)/_layout.tsx | 2 +- apps/mobile/eas.json | 6 +- apps/mobile/metro.config.js | 32 +- apps/mobile/package.json | 87 +- .../src/__tests__/hooks/useMediaSaver.test.ts | 4 +- .../components/share/SharePreviewModal.tsx | 2 +- .../IntensitySlider/IntensitySliderTrack.tsx | 4 +- .../components/DrawingShareModal.tsx | 2 +- .../live-draw/hooks/useCanvasCapture.ts | 2 +- apps/mobile/src/hooks/useAvatarPicker.ts | 2 +- apps/mobile/src/hooks/useMediaSaver.ts | 2 +- apps/mobile/src/lib/imageCache.ts | 2 +- apps/mobile/src/lib/mediaApi.ts | 2 +- apps/mobile/src/lib/notifications.ts | 33 +- apps/mobile/src/test/setup.ts | 15 +- package-lock.json | 9039 +++++++---------- package.json | 16 +- 27 files changed, 3867 insertions(+), 5535 deletions(-) diff --git a/.nvmrc b/.nvmrc index d5a1596..f5b3751 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -20.10.0 +20.19.4 diff --git a/apps/mobile/android/app/build.gradle b/apps/mobile/android/app/build.gradle index 7dadd75..9abf19e 100644 --- a/apps/mobile/android/app/build.gradle +++ b/apps/mobile/android/app/build.gradle @@ -14,6 +14,7 @@ react { hermesCommand = new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsolutePath() + "/sdks/hermesc/%OS-BIN%/hermesc" codegenDir = new File(["node", "--print", "require.resolve('@react-native/codegen/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim()).getParentFile().getAbsoluteFile() + enableBundleCompression = (findProperty('android.enableBundleCompression') ?: false).toBoolean() // Use Expo CLI to bundle the app, this ensures the Metro config // works correctly with Expo projects. cliFile = new File(["node", "--print", "require.resolve('@expo/cli', { paths: [require.resolve('expo/package.json')] })"].execute(null, rootDir).text.trim()) @@ -63,9 +64,9 @@ react { } /** - * Set this to true to Run Proguard on Release builds to minify the Java bytecode. + * Set this to true in release builds to optimize the app using R8. */ -def enableProguardInReleaseBuilds = (findProperty('android.enableProguardInReleaseBuilds') ?: false).toBoolean() +def enableMinifyInReleaseBuilds = (findProperty('android.enableMinifyInReleaseBuilds') ?: false).toBoolean() /** * The preferred build flavor of JavaScriptCore (JSC) @@ -78,7 +79,7 @@ def enableProguardInReleaseBuilds = (findProperty('android.enableProguardInRelea * give correct results when using with locales other than en-US. Note that * this variant is about 6MiB larger per architecture than default. */ -def jscFlavor = 'org.webkit:android-jsc:+' +def jscFlavor = 'io.github.react-native-community:jsc-android:2026004.+' android { ndkVersion rootProject.ext.ndkVersion @@ -93,6 +94,7 @@ android { targetSdkVersion rootProject.ext.targetSdkVersion versionCode 46 versionName "1.0.5" + buildConfigField "String", "REACT_NATIVE_RELEASE_LEVEL", "\"${findProperty('reactNativeReleaseLevel') ?: 'stable'}\"" } signingConfigs { debug { @@ -110,15 +112,18 @@ android { // Caution! In production, you need to generate your own keystore file. // see https://reactnative.dev/docs/signed-apk-android. signingConfig signingConfigs.debug - shrinkResources (findProperty('android.enableShrinkResourcesInReleaseBuilds')?.toBoolean() ?: false) - minifyEnabled enableProguardInReleaseBuilds + def enableShrinkResources = findProperty('android.enableShrinkResourcesInReleaseBuilds') ?: 'false' + shrinkResources enableShrinkResources.toBoolean() + minifyEnabled enableMinifyInReleaseBuilds proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" - crunchPngs (findProperty('android.enablePngCrunchInReleaseBuilds')?.toBoolean() ?: true) + def enablePngCrunchInRelease = findProperty('android.enablePngCrunchInReleaseBuilds') ?: 'true' + crunchPngs enablePngCrunchInRelease.toBoolean() } } packagingOptions { jniLibs { - useLegacyPackaging (findProperty('expo.useLegacyPackaging')?.toBoolean() ?: false) + def enableLegacyPackaging = findProperty('expo.useLegacyPackaging') ?: 'false' + useLegacyPackaging enableLegacyPackaging.toBoolean() } } androidResources { @@ -156,15 +161,15 @@ dependencies { if (isGifEnabled) { // For animated gif support - implementation("com.facebook.fresco:animated-gif:${reactAndroidLibs.versions.fresco.get()}") + implementation("com.facebook.fresco:animated-gif:${expoLibs.versions.fresco.get()}") } if (isWebpEnabled) { // For webp support - implementation("com.facebook.fresco:webpsupport:${reactAndroidLibs.versions.fresco.get()}") + implementation("com.facebook.fresco:webpsupport:${expoLibs.versions.fresco.get()}") if (isWebpAnimatedEnabled) { // Animated webp support - implementation("com.facebook.fresco:animated-webp:${reactAndroidLibs.versions.fresco.get()}") + implementation("com.facebook.fresco:animated-webp:${expoLibs.versions.fresco.get()}") } } @@ -176,4 +181,4 @@ dependencies { } apply plugin: 'com.google.gms.google-services' -apply plugin: 'com.google.firebase.crashlytics' \ No newline at end of file +apply plugin: 'com.google.firebase.crashlytics' diff --git a/apps/mobile/android/app/src/main/AndroidManifest.xml b/apps/mobile/android/app/src/main/AndroidManifest.xml index 0895015..36c65e1 100644 --- a/apps/mobile/android/app/src/main/AndroidManifest.xml +++ b/apps/mobile/android/app/src/main/AndroidManifest.xml @@ -2,6 +2,10 @@ + + + + @@ -17,7 +21,7 @@ - + diff --git a/apps/mobile/android/app/src/main/java/com/sauci/app/MainApplication.kt b/apps/mobile/android/app/src/main/java/com/sauci/app/MainApplication.kt index 644f608..d691313 100644 --- a/apps/mobile/android/app/src/main/java/com/sauci/app/MainApplication.kt +++ b/apps/mobile/android/app/src/main/java/com/sauci/app/MainApplication.kt @@ -8,10 +8,10 @@ import com.facebook.react.ReactApplication import com.facebook.react.ReactNativeHost import com.facebook.react.ReactPackage import com.facebook.react.ReactHost -import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load +import com.facebook.react.ReactNativeApplicationEntryPoint.loadReactNative +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint import com.facebook.react.defaults.DefaultReactNativeHost -import com.facebook.react.soloader.OpenSourceMergedSoMapping -import com.facebook.soloader.SoLoader +import com.facebook.react.common.ReleaseLevel import expo.modules.ApplicationLifecycleDispatcher import expo.modules.ReactNativeHostWrapper @@ -42,11 +42,12 @@ class MainApplication : Application(), ReactApplication { override fun onCreate() { super.onCreate() - SoLoader.init(this, OpenSourceMergedSoMapping) - if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { - // If you opted-in for the New Architecture, we load the native entry point for this app. - load() + DefaultNewArchitectureEntryPoint.releaseLevel = try { + ReleaseLevel.valueOf(BuildConfig.REACT_NATIVE_RELEASE_LEVEL.uppercase()) + } catch (e: IllegalArgumentException) { + ReleaseLevel.STABLE } + loadReactNative(this) ApplicationLifecycleDispatcher.onApplicationCreate(this) } diff --git a/apps/mobile/android/app/src/main/res/values/styles.xml b/apps/mobile/android/app/src/main/res/values/styles.xml index b226501..85c39a6 100644 --- a/apps/mobile/android/app/src/main/res/values/styles.xml +++ b/apps/mobile/android/app/src/main/res/values/styles.xml @@ -1,5 +1,6 @@