4 Commits

Author SHA1 Message Date
billisdead c43b913dde fix: exclude reanimated/worklets native build, disable New Architecture
Release APK / build (push) Has been cancelled
react-native.config.js excludes react-native-reanimated and
react-native-worklets from Android native linking — neither is used in
the app and react-native-gesture-handler has a dedicated noreanimated
codepath for exactly this case.

build-apk.sh step 4.6 forces newArchEnabled=false in gradle.properties
after expo prebuild, as a fallback for New Architecture init issues
on Android 15.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 15:16:37 +02:00
billisdead 256b338ae3 fix: patch worklets and reanimated for Android 15 16KB page size support
Release APK / build (push) Has been cancelled
react-native-worklets and react-native-reanimated compile .so files
without -Wl,-z,max-page-size=16384, causing a native crash at startup
on Android 15 devices that use 16KB memory pages (Pixel 9+, Galaxy S25+).
Patch applied in build-apk.sh and CI workflow after npm install, before
the Gradle build. Guard prevents double-patching on repeated runs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 14:23:38 +02:00
billisdead ec95406305 debug: add crash boundary and global error handler to surface release crashes
Release APK / build (push) Has been cancelled
Catches React render errors (ErrorBoundary) and fatal JS errors
(ErrorUtils.setGlobalHandler) and displays the stacktrace on-screen
instead of crashing to desktop. Temporary — remove after crash identified.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 13:10:01 +02:00
billisdead 6bd1dc8358 revert: remove all splash screen overrides, revert app.json to v0.1.5 state
Release APK / build (push) Has been cancelled
SplashScreen.hideAsync() and the splash section in app.json were both
introduced after v0.1.5 and are common to every crashing build.
Reverting to the exact v0.1.5 baseline to isolate the crash source.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 12:21:10 +02:00
5 changed files with 127 additions and 26 deletions
+11
View File
@@ -89,6 +89,17 @@ jobs:
[ -n "$KEYSTORE_STORE_PASSWORD" ] && echo "KEYSTORE_STORE_PASSWORD: set" || echo "KEYSTORE_STORE_PASSWORD: EMPTY"
[ -n "$KEYSTORE_KEY_PASSWORD" ] && echo "KEYSTORE_KEY_PASSWORD: set" || echo "KEYSTORE_KEY_PASSWORD: EMPTY"
- name: Patch native modules for Android 15 16KB page size
run: |
WORKLETS="node_modules/react-native-worklets/android/CMakeLists.txt"
REANIMATED="node_modules/react-native-reanimated/android/CMakeLists.txt"
if [ -f "$WORKLETS" ] && ! grep -q "max-page-size" "$WORKLETS"; then
printf '\ntarget_link_options(worklets PRIVATE "-Wl,-z,max-page-size=16384")\n' >> "$WORKLETS"
fi
if [ -f "$REANIMATED" ] && ! grep -q "max-page-size" "$REANIMATED"; then
printf '\ntarget_link_options(reanimated PRIVATE "-Wl,-z,max-page-size=16384")\n' >> "$REANIMATED"
fi
- name: Build signed APK
run: ./build-apk.sh
-3
View File
@@ -6,9 +6,6 @@
"orientation": "portrait",
"userInterfaceStyle": "dark",
"backgroundColor": "#0f1117",
"splash": {
"backgroundColor": "#0f1117"
},
"scheme": "sheethappens",
"android": {
"adaptiveIcon": {
+59 -5
View File
@@ -1,18 +1,55 @@
import { useEffect } from "react";
import { Stack, router, SplashScreen } from "expo-router";
import { useEffect, useState, Component } from "react";
import type { ReactNode } from "react";
import { Stack, router } from "expo-router";
import { StatusBar } from "expo-status-bar";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import { View, Text, ScrollView } from "react-native";
import "../global.css";
import { Colors } from "@/constants/theme";
import { useSettings } from "@/hooks/useSettings";
// Catch JS errors in release mode and show them on-screen instead of
// silently crashing to desktop. Remove once the crash is identified.
class CrashBoundary extends Component<
{ children: ReactNode },
{ error: Error | null }
> {
state = { error: null };
static getDerivedStateFromError(e: Error) {
return { error: e };
}
render() {
const { error } = this.state;
if (error) {
return (
<View style={{ flex: 1, backgroundColor: "#0f1117", padding: 20, paddingTop: 60 }}>
<Text style={{ color: "#ef4444", fontSize: 16, fontWeight: "700", marginBottom: 12 }}>
CRASH copie ce texte
</Text>
<ScrollView>
<Text style={{ color: "#fff", fontSize: 11, fontFamily: "monospace" }}>
{String(error)}{"\n\n"}{(error as any).stack}
</Text>
</ScrollView>
</View>
);
}
return this.props.children;
}
}
export default function RootLayout() {
const { settings, ready } = useSettings();
const [jsError, setJsError] = useState<string | null>(null);
useEffect(() => {
if (!ready) return;
SplashScreen.hideAsync();
}, [ready]);
const prev = (ErrorUtils as any).getGlobalHandler();
(ErrorUtils as any).setGlobalHandler((e: Error, isFatal: boolean) => {
if (isFatal) setJsError(`${String(e)}\n\n${(e as any).stack ?? ""}`);
prev?.(e, isFatal);
});
return () => (ErrorUtils as any).setGlobalHandler(prev);
}, []);
useEffect(() => {
if (!ready) return;
@@ -21,7 +58,23 @@ export default function RootLayout() {
}
}, [ready, settings.onboardingDone]);
if (jsError) {
return (
<View style={{ flex: 1, backgroundColor: "#0f1117", padding: 20, paddingTop: 60 }}>
<Text style={{ color: "#ef4444", fontSize: 16, fontWeight: "700", marginBottom: 12 }}>
FATAL JS ERROR copie ce texte
</Text>
<ScrollView>
<Text style={{ color: "#fff", fontSize: 11, fontFamily: "monospace" }}>
{jsError}
</Text>
</ScrollView>
</View>
);
}
return (
<CrashBoundary>
<GestureHandlerRootView style={{ flex: 1, backgroundColor: Colors.bg }}>
<StatusBar style="light" />
<Stack
@@ -40,5 +93,6 @@ export default function RootLayout() {
<Stack.Screen name="onboarding" options={{ headerShown: false }} />
</Stack>
</GestureHandlerRootView>
</CrashBoundary>
);
}
+26
View File
@@ -77,6 +77,32 @@ info "Running expo prebuild (Android)…"
cd "$SCRIPT_DIR"
npx expo prebuild --platform android --clean --no-install
# ─── 4.5. Patch native modules — 16KB page size (Android 15) ──────────────
info "Patching native modules for 16KB page size support (Android 15)…"
WORKLETS_CMAKE="$SCRIPT_DIR/node_modules/react-native-worklets/android/CMakeLists.txt"
REANIMATED_CMAKE="$SCRIPT_DIR/node_modules/react-native-reanimated/android/CMakeLists.txt"
if [ -f "$WORKLETS_CMAKE" ] && ! grep -q "max-page-size" "$WORKLETS_CMAKE"; then
printf '\ntarget_link_options(worklets PRIVATE "-Wl,-z,max-page-size=16384")\n' >> "$WORKLETS_CMAKE"
info "Patched react-native-worklets for 16KB pages"
fi
if [ -f "$REANIMATED_CMAKE" ] && ! grep -q "max-page-size" "$REANIMATED_CMAKE"; then
printf '\ntarget_link_options(reanimated PRIVATE "-Wl,-z,max-page-size=16384")\n' >> "$REANIMATED_CMAKE"
info "Patched react-native-reanimated for 16KB pages"
fi
# ─── 4.6. Disable New Architecture (Android 15 compat) ────────────────────
GRADLE_PROPS_NEWARCH="$SCRIPT_DIR/android/gradle.properties"
if [ -f "$GRADLE_PROPS_NEWARCH" ]; then
sed -i 's/^newArchEnabled=true/newArchEnabled=false/' "$GRADLE_PROPS_NEWARCH"
if ! grep -q "^newArchEnabled=" "$GRADLE_PROPS_NEWARCH"; then
echo "newArchEnabled=false" >> "$GRADLE_PROPS_NEWARCH"
fi
info "New Architecture disabled in gradle.properties"
fi
# ─── 5. Patch build.gradle — inject release signingConfig ──────────────────
info "Patching android/app/build.gradle for release signing…"
+13
View File
@@ -0,0 +1,13 @@
// Exclude native build for packages not used in this project.
// react-native-gesture-handler detects their absence and falls back to its
// noreanimated codepath, so GestureHandlerRootView continues to work.
module.exports = {
dependencies: {
'react-native-reanimated': {
platforms: { android: null },
},
'react-native-worklets': {
platforms: { android: null },
},
},
};