From f35114dc7767d75b506263e363f6b5ad4bc2bdbc Mon Sep 17 00:00:00 2001 From: jjbrunton Date: Fri, 28 Aug 2026 19:54:05 +0100 Subject: [PATCH] chore(android): target API 36 with Expo 54 Upgrade the mobile runtime and tracked Android project to compile and target API 36. Align Expo modules, React Native, Node, Gradle, and Android build tooling while preserving the custom widget sources.\n\nAdapt file-system, notification, animation, test, and Metro compatibility for the SDK 54 runtime. --- .nvmrc | 2 +- apps/admin/package.json | 4 +- 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 +- apps/web/package.json | 4 +- package-lock.json | 9323 +++++++---------- package.json | 16 +- scripts/fix-hoisting.js | 23 + 30 files changed, 4072 insertions(+), 5645 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/admin/package.json b/apps/admin/package.json index 6dcd995..7680d32 100755 --- a/apps/admin/package.json +++ b/apps/admin/package.json @@ -44,8 +44,8 @@ "tailwind-merge": "^2.2.0" }, "devDependencies": { - "@types/react": "^18.2.0", - "@types/react-dom": "^18.2.0", + "@types/react": "~19.1.10", + "@types/react-dom": "~19.1.7", "@vitejs/plugin-react": "^4.2.0", "autoprefixer": "^10.4.16", "postcss": "^8.4.32", 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 @@