@umituz/react-native-design-system 2.3.1 → 2.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/package.json +15 -3
  2. package/src/atoms/AtomicInput.tsx +0 -1
  3. package/src/atoms/AtomicPicker.tsx +0 -1
  4. package/src/atoms/picker/components/PickerChips.tsx +0 -1
  5. package/src/atoms/picker/components/PickerModal.tsx +1 -3
  6. package/src/atoms/picker/styles/pickerStyles.ts +1 -1
  7. package/src/device/domain/entities/Device.ts +207 -0
  8. package/src/device/domain/entities/DeviceMemoryUtils.ts +62 -0
  9. package/src/device/domain/entities/DeviceTypeUtils.ts +66 -0
  10. package/src/device/domain/entities/__tests__/DeviceMemoryUtils.test.ts +118 -0
  11. package/src/device/domain/entities/__tests__/DeviceTypeUtils.test.ts +104 -0
  12. package/src/device/domain/entities/__tests__/DeviceUtils.test.ts +167 -0
  13. package/src/device/index.ts +51 -0
  14. package/src/device/infrastructure/services/ApplicationInfoService.ts +86 -0
  15. package/src/device/infrastructure/services/DeviceCapabilityService.ts +60 -0
  16. package/src/device/infrastructure/services/DeviceIdService.ts +70 -0
  17. package/src/device/infrastructure/services/DeviceInfoService.ts +95 -0
  18. package/src/device/infrastructure/services/DeviceService.ts +104 -0
  19. package/src/device/infrastructure/services/PersistentDeviceIdService.ts +132 -0
  20. package/src/device/infrastructure/services/UserFriendlyIdService.ts +68 -0
  21. package/src/device/infrastructure/utils/__tests__/nativeModuleUtils.test.ts +158 -0
  22. package/src/device/infrastructure/utils/__tests__/stringUtils.test.ts +120 -0
  23. package/src/device/infrastructure/utils/nativeModuleUtils.ts +69 -0
  24. package/src/device/infrastructure/utils/stringUtils.ts +59 -0
  25. package/src/device/presentation/hooks/useAnonymousUser.ts +117 -0
  26. package/src/device/presentation/hooks/useDeviceInfo.ts +222 -0
  27. package/src/molecules/ConfirmationModalContent.tsx +4 -4
  28. package/src/molecules/ConfirmationModalMain.tsx +1 -1
  29. package/src/molecules/ScreenHeader.tsx +2 -2
  30. package/src/molecules/confirmation-modal/components.tsx +1 -1
  31. package/src/molecules/confirmation-modal/styles/confirmationModalStyles.ts +6 -7
  32. package/src/presentation/utils/variants/__tests__/core.test.ts +0 -1
  33. package/src/responsive/deviceDetection.ts +5 -5
  34. package/src/responsive/iPadBreakpoints.ts +55 -0
  35. package/src/responsive/iPadDetection.ts +48 -0
  36. package/src/responsive/iPadLayoutUtils.ts +95 -0
  37. package/src/responsive/iPadModalUtils.ts +98 -0
  38. package/src/responsive/index.ts +31 -0
  39. package/src/safe-area/__tests__/components/SafeAreaProvider.test.tsx +2 -2
  40. package/src/safe-area/__tests__/hooks/useContentSafeAreaPadding.test.tsx +2 -2
  41. package/src/safe-area/__tests__/hooks/useHeaderSafeAreaPadding.test.tsx +2 -2
  42. package/src/safe-area/__tests__/hooks/useSafeAreaInsets.test.tsx +2 -2
  43. package/src/safe-area/__tests__/hooks/useStatusBarSafeAreaPadding.test.tsx +2 -2
  44. package/src/safe-area/__tests__/integration/completeFlow.test.tsx +5 -4
  45. package/src/safe-area/__tests__/utils/testUtils.tsx +5 -4
  46. package/src/theme/infrastructure/stores/themeStore.ts +0 -2
  47. package/src/typography/presentation/utils/textColorUtils.ts +0 -1
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Device Utils Tests
3
+ */
4
+
5
+ import { DeviceUtils, DEVICE_CONSTANTS } from '../Device';
6
+
7
+ describe('DeviceUtils', () => {
8
+ const mockDeviceInfo = {
9
+ brand: 'Apple',
10
+ manufacturer: 'Apple',
11
+ modelName: 'iPhone 14',
12
+ modelId: 'iPhone14,1',
13
+ deviceName: 'Test iPhone',
14
+ deviceYearClass: 2022,
15
+ deviceType: DEVICE_CONSTANTS.DEVICE_TYPE.PHONE,
16
+ isDevice: true,
17
+ osName: 'iOS',
18
+ osVersion: '16.0',
19
+ osBuildId: '20A362',
20
+ platformApiLevel: null,
21
+ totalMemory: 6442450944, // 6GB
22
+ platform: 'ios' as const,
23
+ };
24
+
25
+ const mockAppInfo = {
26
+ applicationName: 'Test App',
27
+ applicationId: 'com.test.app',
28
+ nativeApplicationVersion: '1.0.0',
29
+ nativeBuildVersion: '100',
30
+ installTime: new Date('2023-01-01'),
31
+ lastUpdateTime: new Date('2023-01-15'),
32
+ androidId: null,
33
+ iosIdForVendor: 'test-ios-id',
34
+ };
35
+
36
+ describe('isPhysicalDevice', () => {
37
+ it('should return true for physical device', () => {
38
+ expect(DeviceUtils.isPhysicalDevice(true)).toBe(true);
39
+ });
40
+
41
+ it('should return false for simulator', () => {
42
+ expect(DeviceUtils.isPhysicalDevice(false)).toBe(false);
43
+ });
44
+ });
45
+
46
+ describe('getDeviceDisplayName', () => {
47
+ it('should return device name when available', () => {
48
+ const result = DeviceUtils.getDeviceDisplayName(mockDeviceInfo);
49
+ expect(result).toBe('Test iPhone');
50
+ });
51
+
52
+ it('should return model name when device name is null', () => {
53
+ const info = { ...mockDeviceInfo, deviceName: null };
54
+ const result = DeviceUtils.getDeviceDisplayName(info);
55
+ expect(result).toBe('iPhone 14');
56
+ });
57
+
58
+ it('should return brand and manufacturer when model name is null', () => {
59
+ const info = { ...mockDeviceInfo, deviceName: null, modelName: null };
60
+ const result = DeviceUtils.getDeviceDisplayName(info);
61
+ expect(result).toBe('Apple Apple');
62
+ });
63
+
64
+ it('should return Unknown Device when all info is null', () => {
65
+ const info = { ...mockDeviceInfo, deviceName: null, modelName: null, brand: null, manufacturer: null };
66
+ const result = DeviceUtils.getDeviceDisplayName(info);
67
+ expect(result).toBe('Unknown Device');
68
+ });
69
+ });
70
+
71
+ describe('getOSDisplayString', () => {
72
+ it('should return OS name and version', () => {
73
+ const result = DeviceUtils.getOSDisplayString(mockDeviceInfo);
74
+ expect(result).toBe('iOS 16.0');
75
+ });
76
+
77
+ it('should return OS name only when version is null', () => {
78
+ const info = { ...mockDeviceInfo, osVersion: null };
79
+ const result = DeviceUtils.getOSDisplayString(info);
80
+ expect(result).toBe('iOS');
81
+ });
82
+
83
+ it('should return Unknown OS when OS name is null', () => {
84
+ const info = { ...mockDeviceInfo, osName: null };
85
+ const result = DeviceUtils.getOSDisplayString(info);
86
+ expect(result).toBe('Unknown OS');
87
+ });
88
+ });
89
+
90
+ describe('getAppVersionString', () => {
91
+ it('should return version and build number', () => {
92
+ const result = DeviceUtils.getAppVersionString(mockAppInfo);
93
+ expect(result).toBe('1.0.0 (100)');
94
+ });
95
+
96
+ it('should return version only when build is null', () => {
97
+ const info = { ...mockAppInfo, nativeBuildVersion: null };
98
+ const result = DeviceUtils.getAppVersionString(info);
99
+ expect(result).toBe('1.0.0');
100
+ });
101
+
102
+ it('should return Unknown Version when version is null', () => {
103
+ const info = { ...mockAppInfo, nativeApplicationVersion: null };
104
+ const result = DeviceUtils.getAppVersionString(info);
105
+ expect(result).toBe('Unknown Version');
106
+ });
107
+ });
108
+
109
+ describe('meetsMinimumRequirements', () => {
110
+ it('should pass for device meeting all requirements', () => {
111
+ const result = DeviceUtils.meetsMinimumRequirements(mockDeviceInfo, 4);
112
+ expect(result.meets).toBe(true);
113
+ expect(result.reasons).toHaveLength(0);
114
+ });
115
+
116
+ it('should fail for simulator', () => {
117
+ const info = { ...mockDeviceInfo, isDevice: false };
118
+ const result = DeviceUtils.meetsMinimumRequirements(info, 1);
119
+ expect(result.meets).toBe(false);
120
+ expect(result.reasons).toContain('Running on simulator/emulator');
121
+ });
122
+
123
+ it('should fail for insufficient memory', () => {
124
+ const result = DeviceUtils.meetsMinimumRequirements(mockDeviceInfo, 8);
125
+ expect(result.meets).toBe(false);
126
+ expect(result.reasons[0]).toContain('Insufficient memory');
127
+ });
128
+
129
+ it('should fail for old device', () => {
130
+ const info = { ...mockDeviceInfo, deviceYearClass: 2016 };
131
+ const result = DeviceUtils.meetsMinimumRequirements(info, 1);
132
+ expect(result.meets).toBe(false);
133
+ expect(result.reasons[0]).toContain('Device too old: 2016');
134
+ });
135
+ });
136
+
137
+ describe('getDeviceTier', () => {
138
+ it('should return high for new device', () => {
139
+ const result = DeviceUtils.getDeviceTier(mockDeviceInfo);
140
+ expect(result).toBe('high');
141
+ });
142
+
143
+ it('should return mid for 2020 device', () => {
144
+ const info = { ...mockDeviceInfo, deviceYearClass: 2020 };
145
+ const result = DeviceUtils.getDeviceTier(info);
146
+ expect(result).toBe('mid');
147
+ });
148
+
149
+ it('should return low for old device', () => {
150
+ const info = { ...mockDeviceInfo, deviceYearClass: 2017 };
151
+ const result = DeviceUtils.getDeviceTier(info);
152
+ expect(result).toBe('low');
153
+ });
154
+
155
+ it('should classify by memory when year is null', () => {
156
+ const info = { ...mockDeviceInfo, deviceYearClass: null, totalMemory: 8589934592 }; // 8GB
157
+ const result = DeviceUtils.getDeviceTier(info);
158
+ expect(result).toBe('high');
159
+ });
160
+
161
+ it('should return mid when no info available', () => {
162
+ const info = { ...mockDeviceInfo, deviceYearClass: null, totalMemory: null };
163
+ const result = DeviceUtils.getDeviceTier(info);
164
+ expect(result).toBe('mid');
165
+ });
166
+ });
167
+ });
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Device Module - Public API
3
+ *
4
+ * Device and application information utilities.
5
+ * Provides device detection, capabilities, and system info.
6
+ */
7
+
8
+ // Domain entities
9
+ export type {
10
+ DeviceInfo,
11
+ ApplicationInfo,
12
+ SystemInfo,
13
+ DeviceType,
14
+ } from './domain/entities/Device';
15
+
16
+ export {
17
+ DEVICE_CONSTANTS,
18
+ DeviceUtils,
19
+ } from './domain/entities/Device';
20
+
21
+ export { DeviceTypeUtils } from './domain/entities/DeviceTypeUtils';
22
+ export { DeviceMemoryUtils } from './domain/entities/DeviceMemoryUtils';
23
+
24
+ // Infrastructure services
25
+ export { DeviceService } from './infrastructure/services/DeviceService';
26
+ export { UserFriendlyIdService } from './infrastructure/services/UserFriendlyIdService';
27
+ import { PersistentDeviceIdService } from './infrastructure/services/PersistentDeviceIdService';
28
+ export { PersistentDeviceIdService };
29
+
30
+ // Presentation hooks
31
+ export {
32
+ useDeviceInfo,
33
+ useDeviceCapabilities,
34
+ useDeviceId,
35
+ } from './presentation/hooks/useDeviceInfo';
36
+
37
+ export {
38
+ useAnonymousUser,
39
+ } from './presentation/hooks/useAnonymousUser';
40
+
41
+ export type {
42
+ AnonymousUser,
43
+ UseAnonymousUserOptions,
44
+ } from './presentation/hooks/useAnonymousUser';
45
+
46
+ /**
47
+ * Get anonymous user ID for services
48
+ */
49
+ export async function getAnonymousUserId(): Promise<string> {
50
+ return PersistentDeviceIdService.getDeviceId();
51
+ }
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Application Info Service
3
+ *
4
+ * Single Responsibility: Get application information from native modules
5
+ * Follows SOLID principles - only handles application info retrieval
6
+ */
7
+
8
+ import * as Application from 'expo-application';
9
+ import { Platform } from 'react-native';
10
+ import type { ApplicationInfo } from '../../domain/entities/Device';
11
+ import { safeAccess, withTimeout } from '../utils/nativeModuleUtils';
12
+
13
+ /**
14
+ * Service for retrieving application information
15
+ */
16
+ export class ApplicationInfoService {
17
+ /**
18
+ * Get application information
19
+ * SAFE: Returns minimal info if native modules are not ready
20
+ */
21
+ static async getApplicationInfo(): Promise<ApplicationInfo> {
22
+ try {
23
+ const [installTime, lastUpdateTime] = await Promise.all([
24
+ withTimeout(() => Application.getInstallationTimeAsync(), 1000),
25
+ withTimeout(() => Application.getLastUpdateTimeAsync(), 1000),
26
+ ]);
27
+
28
+ const applicationName = safeAccess(() => Application.applicationName, 'Unknown');
29
+ const applicationId = safeAccess(() => Application.applicationId, 'Unknown');
30
+ const nativeApplicationVersion = safeAccess(
31
+ () => Application.nativeApplicationVersion,
32
+ null,
33
+ );
34
+ const nativeBuildVersion = safeAccess(
35
+ () => Application.nativeBuildVersion,
36
+ null,
37
+ );
38
+
39
+ let androidId: string | null = null;
40
+ let iosIdForVendor: string | null = null;
41
+
42
+ if (Platform.OS === 'android') {
43
+ const result = await withTimeout(async () => Application.getAndroidId(), 1000);
44
+ androidId = result || null;
45
+ }
46
+
47
+ if (Platform.OS === 'ios') {
48
+ const result = await withTimeout(
49
+ async () => Application.getIosIdForVendorAsync(),
50
+ 1000,
51
+ );
52
+ iosIdForVendor = result || null;
53
+ }
54
+
55
+ return {
56
+ applicationName: applicationName || 'Unknown',
57
+ applicationId: applicationId || 'Unknown',
58
+ nativeApplicationVersion,
59
+ nativeBuildVersion,
60
+ installTime,
61
+ lastUpdateTime,
62
+ androidId,
63
+ iosIdForVendor,
64
+ };
65
+ } catch {
66
+ return this.getMinimalApplicationInfo();
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Get minimal application info (fallback)
72
+ */
73
+ private static getMinimalApplicationInfo(): ApplicationInfo {
74
+ return {
75
+ applicationName: 'Unknown',
76
+ applicationId: 'Unknown',
77
+ nativeApplicationVersion: null,
78
+ nativeBuildVersion: null,
79
+ installTime: null,
80
+ lastUpdateTime: null,
81
+ androidId: null,
82
+ iosIdForVendor: null,
83
+ };
84
+ }
85
+ }
86
+
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Device Capability Service
3
+ *
4
+ * Single Responsibility: Check device capabilities and features
5
+ * Follows SOLID principles - only handles capability checks
6
+ */
7
+
8
+ import * as Device from 'expo-device';
9
+ import { Platform } from 'react-native';
10
+ import { DeviceInfoService } from './DeviceInfoService';
11
+ import { safeAccess } from '../utils/nativeModuleUtils';
12
+
13
+ /**
14
+ * Service for checking device capabilities
15
+ */
16
+ export class DeviceCapabilityService {
17
+ /**
18
+ * Check if device supports specific features
19
+ */
20
+ static async getDeviceCapabilities(): Promise<{
21
+ isDevice: boolean;
22
+ isTablet: boolean;
23
+ hasNotch: boolean;
24
+ totalMemoryGB: number | null;
25
+ }> {
26
+ const info = await DeviceInfoService.getDeviceInfo();
27
+
28
+ return {
29
+ isDevice: info.isDevice,
30
+ isTablet: info.deviceType === Device.DeviceType.TABLET,
31
+ hasNotch: await this.hasNotch(),
32
+ totalMemoryGB: info.totalMemory
33
+ ? info.totalMemory / (1024 * 1024 * 1024)
34
+ : null,
35
+ };
36
+ }
37
+
38
+ /**
39
+ * Check if device has notch/dynamic island
40
+ */
41
+ static async hasNotch(): Promise<boolean> {
42
+ try {
43
+ if (Platform.OS !== 'ios') {
44
+ return false;
45
+ }
46
+
47
+ const modelName = safeAccess(() => Device.modelName?.toLowerCase() || '', '');
48
+
49
+ // iPhone X and newer (with notch or dynamic island)
50
+ return (
51
+ modelName.includes('iphone x') ||
52
+ modelName.includes('iphone 1') || // 11, 12, 13, 14, 15
53
+ modelName.includes('pro')
54
+ );
55
+ } catch {
56
+ return false;
57
+ }
58
+ }
59
+ }
60
+
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Device ID Service
3
+ *
4
+ * Single Responsibility: Get device unique identifiers
5
+ * Follows SOLID principles - only handles device ID retrieval
6
+ */
7
+
8
+ import * as Application from 'expo-application';
9
+ import { Platform } from 'react-native';
10
+ import { withTimeout } from '../utils/nativeModuleUtils';
11
+
12
+ /**
13
+ * Service for retrieving device unique identifiers
14
+ */
15
+ export class DeviceIdService {
16
+ /**
17
+ * Get device unique identifier (platform-specific)
18
+ *
19
+ * WARNING: Use with caution - user privacy considerations!
20
+ * Android: androidId (can be reset)
21
+ * iOS: iosIdForVendor (changes on reinstall)
22
+ * Web: null (not supported)
23
+ *
24
+ * SAFE: Returns null if native modules are not ready
25
+ */
26
+ static async getDeviceId(): Promise<string | null> {
27
+ try {
28
+ let deviceId: string | null = null;
29
+
30
+ if (Platform.OS === 'android') {
31
+ const result = await withTimeout(async () => Application.getAndroidId(), 1000);
32
+ deviceId = result || null;
33
+ }
34
+
35
+ if (Platform.OS === 'ios') {
36
+ const result = await withTimeout(
37
+ async () => Application.getIosIdForVendorAsync(),
38
+ 1000,
39
+ );
40
+ deviceId = result || null;
41
+ }
42
+
43
+ return deviceId;
44
+ } catch {
45
+ return null;
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Get offline user ID with fallback (iOS/Android only)
51
+ *
52
+ * For offline apps that need a persistent user ID:
53
+ * 1. Try to get platform-specific device ID (iOS/Android)
54
+ * 2. Fallback to a default offline user ID if device ID not available
55
+ *
56
+ * NOTE: Returns null for web platform (not supported)
57
+ */
58
+ static async getOfflineUserId(fallbackId: string = 'offline_user'): Promise<string | null> {
59
+ if (Platform.OS === 'web') {
60
+ return null;
61
+ }
62
+
63
+ const deviceId = await this.getDeviceId();
64
+ if (deviceId) {
65
+ return `offline_${deviceId}`;
66
+ }
67
+ return fallbackId;
68
+ }
69
+ }
70
+
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Device Info Service
3
+ *
4
+ * Single Responsibility: Get device information from native modules
5
+ * Follows SOLID principles - only handles device info retrieval
6
+ */
7
+
8
+ import * as Device from 'expo-device';
9
+ import { Platform } from 'react-native';
10
+ import * as Localization from 'expo-localization';
11
+ import type { DeviceInfo } from '../../domain/entities/Device';
12
+ import { safeAccess, withTimeout } from '../utils/nativeModuleUtils';
13
+
14
+ /**
15
+ * Service for retrieving device information
16
+ */
17
+ export class DeviceInfoService {
18
+ /**
19
+ * Get device information
20
+ * SAFE: Returns minimal info if native modules are not ready
21
+ */
22
+ static async getDeviceInfo(): Promise<DeviceInfo> {
23
+ try {
24
+ const totalMemory = await withTimeout(
25
+ () => Device.getMaxMemoryAsync(),
26
+ 1000,
27
+ );
28
+
29
+ const brand = safeAccess(() => Device.brand, null);
30
+ const manufacturer = safeAccess(() => Device.manufacturer, null);
31
+ const modelName = safeAccess(() => Device.modelName, null);
32
+ const modelId = safeAccess(() => Device.modelId, null);
33
+ const deviceName = safeAccess(() => Device.deviceName, null);
34
+ const deviceYearClass = safeAccess(() => Device.deviceYearClass, null);
35
+ const deviceType = safeAccess(() => Device.deviceType, null);
36
+ const isDevice = safeAccess(() => Device.isDevice, false);
37
+ const osName = safeAccess(() => Device.osName, null);
38
+ const osVersion = safeAccess(() => Device.osVersion, null);
39
+ const osBuildId = safeAccess(() => Device.osBuildId, null);
40
+ const platformApiLevel = safeAccess(() => Device.platformApiLevel, null);
41
+
42
+ // Localization
43
+ const calendars = Localization.getCalendars();
44
+ const locales = Localization.getLocales();
45
+ const timezone = calendars?.[0]?.timeZone ?? null;
46
+ const region = locales?.[0]?.regionCode ?? null;
47
+
48
+ return {
49
+ brand,
50
+ manufacturer,
51
+ modelName,
52
+ modelId,
53
+ deviceName,
54
+ deviceYearClass,
55
+ deviceType,
56
+ isDevice,
57
+ osName,
58
+ osVersion,
59
+ osBuildId,
60
+ platformApiLevel,
61
+ totalMemory,
62
+ platform: Platform.OS as 'ios' | 'android' | 'web',
63
+ timezone,
64
+ region,
65
+ };
66
+ } catch {
67
+ return this.getMinimalDeviceInfo();
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Get minimal device info (fallback)
73
+ */
74
+ private static getMinimalDeviceInfo(): DeviceInfo {
75
+ return {
76
+ brand: null,
77
+ manufacturer: null,
78
+ modelName: null,
79
+ modelId: null,
80
+ deviceName: null,
81
+ deviceYearClass: null,
82
+ deviceType: null,
83
+ isDevice: false,
84
+ osName: null,
85
+ osVersion: null,
86
+ osBuildId: null,
87
+ platformApiLevel: null,
88
+ totalMemory: null,
89
+ platform: Platform.OS as 'ios' | 'android' | 'web',
90
+ timezone: null,
91
+ region: null,
92
+ };
93
+ }
94
+ }
95
+
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Device Service - Facade/Orchestrator
3
+ *
4
+ * Main entry point for device operations.
5
+ * Delegates to specialized services following Single Responsibility Principle.
6
+ *
7
+ * @domain device
8
+ * @layer infrastructure/services
9
+ */
10
+
11
+ import type { DeviceInfo, ApplicationInfo, SystemInfo } from '../../domain/entities/Device';
12
+ import { DeviceInfoService } from './DeviceInfoService';
13
+ import { ApplicationInfoService } from './ApplicationInfoService';
14
+ import { DeviceIdService } from './DeviceIdService';
15
+ import { DeviceCapabilityService } from './DeviceCapabilityService';
16
+ import { UserFriendlyIdService } from './UserFriendlyIdService';
17
+
18
+ /**
19
+ * Device Service - Facade for all device operations
20
+ *
21
+ * This is a facade that delegates to specialized services.
22
+ * Each service has a single responsibility (SOLID principles).
23
+ */
24
+ export class DeviceService {
25
+ /**
26
+ * Get device information
27
+ * Delegates to DeviceInfoService
28
+ */
29
+ static async getDeviceInfo(): Promise<DeviceInfo> {
30
+ return DeviceInfoService.getDeviceInfo();
31
+ }
32
+
33
+ /**
34
+ * Get application information
35
+ * Delegates to ApplicationInfoService
36
+ */
37
+ static async getApplicationInfo(): Promise<ApplicationInfo> {
38
+ return ApplicationInfoService.getApplicationInfo();
39
+ }
40
+
41
+ /**
42
+ * Get complete system information (device + app)
43
+ * @param options - Optional configuration
44
+ * @param options.userId - Optional user ID to include in system info
45
+ */
46
+ static async getSystemInfo(options?: { userId?: string }): Promise<SystemInfo> {
47
+ const [device, application] = await Promise.all([
48
+ DeviceInfoService.getDeviceInfo(),
49
+ ApplicationInfoService.getApplicationInfo(),
50
+ ]);
51
+
52
+ return {
53
+ device,
54
+ application,
55
+ timestamp: Date.now(),
56
+ ...(options?.userId && { userId: options.userId }),
57
+ };
58
+ }
59
+
60
+ /**
61
+ * Get device unique identifier (platform-specific)
62
+ * Delegates to DeviceIdService
63
+ */
64
+ static async getDeviceId(): Promise<string | null> {
65
+ return DeviceIdService.getDeviceId();
66
+ }
67
+
68
+ /**
69
+ * Get offline user ID with fallback
70
+ * Delegates to DeviceIdService
71
+ */
72
+ static async getOfflineUserId(fallbackId: string = 'offline_user'): Promise<string | null> {
73
+ return DeviceIdService.getOfflineUserId(fallbackId);
74
+ }
75
+
76
+ /**
77
+ * Check if device supports specific features
78
+ * Delegates to DeviceCapabilityService
79
+ */
80
+ static async getDeviceCapabilities(): Promise<{
81
+ isDevice: boolean;
82
+ isTablet: boolean;
83
+ hasNotch: boolean;
84
+ totalMemoryGB: number | null;
85
+ }> {
86
+ return DeviceCapabilityService.getDeviceCapabilities();
87
+ }
88
+
89
+ /**
90
+ * Check if device has notch/dynamic island
91
+ * Delegates to DeviceCapabilityService
92
+ */
93
+ static async hasNotch(): Promise<boolean> {
94
+ return DeviceCapabilityService.hasNotch();
95
+ }
96
+
97
+ /**
98
+ * Get user friendly device ID
99
+ * Delegates to UserFriendlyIdService
100
+ */
101
+ static async getUserFriendlyId(): Promise<string> {
102
+ return UserFriendlyIdService.getUserFriendlyId();
103
+ }
104
+ }