From e3024a78184d6dbcca460aab363724f001fd42a7 Mon Sep 17 00:00:00 2001 From: Andre Padez Date: Sat, 15 Aug 2026 00:21:12 +0100 Subject: [PATCH] fix(settings): read the build number from expo-application MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The row said '1.0.0 (dev)' on a build stamped 2026081502. Constants.nativeBuildVersion is deprecated in SDK 57 and returns nothing — not an error, not a throw, just undefined, so the fallback fired and the screen reported the opposite of the truth with complete confidence. A deprecation that quietly returns undefined is the worst kind: everything looks like it is working. expo-application is the documented replacement and reads the value from the bundle at runtime, which is the number OAS stamps before signing. Also removes the last use of expo-constants here, and with it the '1.0.0' half — the marketing string that has never changed and cannot tell two builds apart. Co-Authored-By: Claude Opus 5 --- bun.lock | 3 +++ package.json | 1 + src/settings/SettingsScreen.tsx | 12 ++++++++++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/bun.lock b/bun.lock index b88c6ee..92bf80d 100644 --- a/bun.lock +++ b/bun.lock @@ -8,6 +8,7 @@ "@expo/vector-icons": "15.1.1", "@react-native-async-storage/async-storage": "2.2.0", "expo": "57.0.8", + "expo-application": "^57.0.2", "expo-clipboard": "57.0.1", "expo-constants": "57.0.7", "expo-dev-client": "57.0.9", @@ -515,6 +516,8 @@ "expo": ["expo@57.0.8", "", { "dependencies": { "@babel/runtime": "^7.20.0", "@expo/cli": "^57.0.10", "@expo/config": "~57.0.6", "@expo/config-plugins": "~57.0.6", "@expo/devtools": "~57.0.1", "@expo/dom-webview": "~57.0.1", "@expo/fingerprint": "^0.20.6", "@expo/local-build-cache-provider": "^57.0.4", "@expo/log-box": "^57.0.1", "@expo/metro": "~56.0.0", "@expo/metro-config": "~57.0.7", "@ungap/structured-clone": "^1.3.0", "babel-preset-expo": "~57.0.4", "expo-asset": "~57.0.7", "expo-constants": "~57.0.7", "expo-file-system": "~57.0.1", "expo-font": "~57.0.1", "expo-keep-awake": "~57.0.1", "expo-modules-autolinking": "~57.0.9", "expo-modules-core": "~57.0.7", "pretty-format": "^29.7.0", "react-refresh": "^0.14.2", "whatwg-url-minimum": "^0.1.2" }, "peerDependencies": { "@expo/metro-runtime": "*", "react": "*", "react-dom": "*", "react-native": "*", "react-native-web": "*", "react-native-webview": "*" }, "optionalPeers": ["@expo/metro-runtime", "react-dom", "react-native-web", "react-native-webview"], "bin": { "expo": "bin/cli", "fingerprint": "bin/fingerprint", "expo-modules-autolinking": "bin/autolinking" } }, "sha512-0IxxoPZbT54IH4fHL5NihkvED9HBVQx3uNdPvyv8pFUHWJ81RdFjL0aJys1IB7hbo09KTz4xW4I2aWVOXKAcJQ=="], + "expo-application": ["expo-application@57.0.2", "", { "peerDependencies": { "expo": "*" } }, "sha512-q31YwcXyymviAmdrtDfAg3Dld4VMxLCNAfgMHip7vZpPX4lzF/AfwsywqBJUAjQnJknzaNAkzqvMVjO5XmKYDA=="], + "expo-asset": ["expo-asset@57.0.7", "", { "dependencies": { "@expo/image-utils": "^0.11.4", "expo-constants": "~57.0.7" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-TA6MRQq1HL0N6KGvNMzL6djdH5tGJ/eHPIhML+6bVu52mnXldmup2swdvP37zDnvoMUUXRVGsvwVHFmvhCbW6Q=="], "expo-clipboard": ["expo-clipboard@57.0.1", "", { "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-HWICri4+1ao7S6QEfcorxVumXDiDnx1guGGewjZgGJWLGxFYs0RgH8ujBs+lkTzBkMmlwADaWSlaesR+nDJt5Q=="], diff --git a/package.json b/package.json index 8eb1460..c147198 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "@expo/vector-icons": "15.1.1", "@react-native-async-storage/async-storage": "2.2.0", "expo": "57.0.8", + "expo-application": "^57.0.2", "expo-clipboard": "57.0.1", "expo-constants": "57.0.7", "expo-dev-client": "57.0.9", diff --git a/src/settings/SettingsScreen.tsx b/src/settings/SettingsScreen.tsx index 39ee3e0..e34adb2 100644 --- a/src/settings/SettingsScreen.tsx +++ b/src/settings/SettingsScreen.tsx @@ -3,7 +3,7 @@ import type { ImageSourcePropType } from 'react-native'; import { View, Text, Pressable, ScrollView, Image } from 'react-native'; import { Ionicons } from '@expo/vector-icons'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; -import Constants from 'expo-constants'; +import * as Application from 'expo-application'; import { useTheme } from '../ui/useTheme'; import { Card } from '../ui/Card'; @@ -91,7 +91,15 @@ export type SettingsScreenProps = { * that is not exactly ten digits is shown verbatim instead of being mangled into a fake date. */ function buildLabel(): string { - const raw = Constants.nativeBuildVersion ?? ''; + /* + `expo-application`, NOT `Constants.nativeBuildVersion`. + + That property is deprecated in SDK 57 and returns nothing — which is not an error, just an empty + string, so the row rendered a confident "1.0.0 (dev)" on a build that had been stamped 2026081502. + A deprecation that returns undefined rather than throwing is the worst kind: the screen looked like + it was working and was reporting the opposite of the truth. + */ + const raw = Application.nativeBuildVersion ?? ''; if (!/^\d{10}$/.test(raw)) return raw ? `dev (${raw})` : 'dev'; return `${raw.slice(0, 4)}.${raw.slice(4, 6)}.${raw.slice(6, 8)}.${raw.slice(8)}`; }