Constants.platform.ios.model returns only generic "iPhone" instead of
"iPhone 15 Pro" + osVersion was unreliable. Switched lib/deviceId.ts to
expo-device which exposes Device.deviceName ("iPhone von Chahine"),
Device.modelName ("iPhone 15 Pro") and Device.osVersion ("26.4.2") on real
devices. Constants stays as fallback for Simulator/Web.
Backend touchDevice + auto-register already backfill these fields from the
x-device-* headers (commit 60f608d) — but only with proper Frontend values
which Constants couldn't provide.
Requires new native build (versionCode 8) since expo-device is a native
module — current TestFlight build (7) still ships with old Constants logic.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
91 lines
2.3 KiB
TypeScript
91 lines
2.3 KiB
TypeScript
import { Platform } from 'react-native';
|
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
import * as Application from 'expo-application';
|
|
import * as Device from 'expo-device';
|
|
import Constants from 'expo-constants';
|
|
|
|
const STORAGE_KEY = 'rebreak_device_id';
|
|
|
|
let cached: string | null = null;
|
|
|
|
export async function getDeviceId(): Promise<string> {
|
|
if (cached) return cached;
|
|
|
|
if (Platform.OS === 'ios') {
|
|
const vendor = await Application.getIosIdForVendorAsync();
|
|
if (vendor) {
|
|
cached = vendor;
|
|
return vendor;
|
|
}
|
|
}
|
|
|
|
if (Platform.OS === 'android') {
|
|
const androidId = Application.getAndroidId();
|
|
if (androidId) {
|
|
cached = androidId;
|
|
return androidId;
|
|
}
|
|
}
|
|
|
|
// Fallback: persisted UUID via AsyncStorage (web / simulator edge cases)
|
|
const stored = await AsyncStorage.getItem(STORAGE_KEY).catch(() => null);
|
|
if (stored) {
|
|
cached = stored;
|
|
return stored;
|
|
}
|
|
|
|
const uuid =
|
|
'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
const r = (Math.random() * 16) | 0;
|
|
return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16);
|
|
});
|
|
|
|
await AsyncStorage.setItem(STORAGE_KEY, uuid).catch(() => {});
|
|
cached = uuid;
|
|
return uuid;
|
|
}
|
|
|
|
export function getPlatformName(): string {
|
|
if (Platform.OS === 'ios') return 'ios';
|
|
if (Platform.OS === 'android') return 'android';
|
|
return 'web';
|
|
}
|
|
|
|
export interface DeviceInfo {
|
|
deviceId: string;
|
|
platform: string;
|
|
name: string;
|
|
model: string;
|
|
osVersion: string;
|
|
appVersion: string;
|
|
}
|
|
|
|
export async function getDeviceInfo(): Promise<DeviceInfo> {
|
|
const deviceId = await getDeviceId();
|
|
const platform = getPlatformName();
|
|
|
|
// expo-device returnt zuverlässige Hardware-Infos auf realen Devices.
|
|
// Constants ist Fallback für Simulator/Web (Device-APIs sind dort null).
|
|
const name =
|
|
Device.deviceName ||
|
|
(Constants as any).deviceName ||
|
|
Device.modelName ||
|
|
platform;
|
|
|
|
const model =
|
|
Device.modelName ||
|
|
Device.modelId ||
|
|
Constants.platform?.ios?.model ||
|
|
platform;
|
|
|
|
const osVersion =
|
|
Device.osVersion ||
|
|
Constants.platform?.ios?.systemVersion?.toString() ||
|
|
(Platform.Version as string | number)?.toString() ||
|
|
'';
|
|
|
|
const appVersion = Application.nativeApplicationVersion || '';
|
|
|
|
return { deviceId, platform, name, model, osVersion, appVersion };
|
|
}
|