fix(settings): read the build number from expo-application

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 <noreply@anthropic.com>
This commit is contained in:
2026-08-15 00:21:12 +01:00
co-authored by Claude Opus 5
parent e7e2d8c6b7
commit e3024a7818
3 changed files with 14 additions and 2 deletions
+3
View File
@@ -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=="],
+1
View File
@@ -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",
+10 -2
View File
@@ -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)}`;
}