@multiplayer-app/session-recorder-react-native 0.0.1-beta.7 → 0.0.1-beta.9
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.
- package/app.plugin.js +42 -0
- package/docs/NATIVE_MODULE_SETUP.md +177 -0
- package/ios/SessionRecorderNative.podspec +5 -0
- package/package.json +10 -1
- package/plugin/package.json +20 -0
- package/plugin/src/index.js +42 -0
- package/android/src/main/AndroidManifest.xml +0 -2
- package/android/src/main/java/com/multiplayer/sessionrecorder/ScreenMaskingModule.kt +0 -202
- package/android/src/main/java/com/multiplayer/sessionrecorder/ScreenMaskingPackage.kt +0 -16
- package/android/src/main/java/com/multiplayer/sessionrecorder/SessionRecorderModule.kt +0 -202
- package/android/src/main/java/com/multiplayer/sessionrecorder/SessionRecorderPackage.kt +0 -16
- package/babel.config.js +0 -13
- package/docs/AUTO_METADATA_DETECTION.md +0 -108
- package/docs/TROUBLESHOOTING.md +0 -168
- package/ios/ScreenMasking.m +0 -12
- package/ios/ScreenMasking.podspec +0 -21
- package/ios/ScreenMasking.swift +0 -205
- package/ios/SessionRecorder.podspec +0 -21
- package/scripts/generate-app-metadata.js +0 -173
- package/src/components/GestureCaptureWrapper/GestureCaptureWrapper.tsx +0 -86
- package/src/components/GestureCaptureWrapper/index.ts +0 -1
- package/src/components/ScreenRecorderView/ScreenRecorderView.tsx +0 -72
- package/src/components/ScreenRecorderView/index.ts +0 -1
- package/src/components/SessionRecorderWidget/FinalPopover.tsx +0 -62
- package/src/components/SessionRecorderWidget/FloatingButton.tsx +0 -136
- package/src/components/SessionRecorderWidget/InitialPopover.tsx +0 -89
- package/src/components/SessionRecorderWidget/ModalContainer.tsx +0 -128
- package/src/components/SessionRecorderWidget/ModalHeader.tsx +0 -24
- package/src/components/SessionRecorderWidget/SessionRecorderWidget.tsx +0 -109
- package/src/components/SessionRecorderWidget/icons.tsx +0 -52
- package/src/components/SessionRecorderWidget/index.ts +0 -3
- package/src/components/SessionRecorderWidget/styles.ts +0 -150
- package/src/components/index.ts +0 -3
- package/src/config/constants.ts +0 -60
- package/src/config/defaults.ts +0 -83
- package/src/config/index.ts +0 -6
- package/src/config/masking.ts +0 -28
- package/src/config/session-recorder.ts +0 -55
- package/src/config/validators.ts +0 -31
- package/src/context/SessionRecorderContext.tsx +0 -53
- package/src/index.ts +0 -9
- package/src/native/ScreenMasking.ts +0 -34
- package/src/native/SessionRecorderNative.ts +0 -34
- package/src/otel/helpers.ts +0 -275
- package/src/otel/index.ts +0 -138
- package/src/otel/instrumentations/index.ts +0 -115
- package/src/patch/index.ts +0 -1
- package/src/patch/xhr.ts +0 -141
- package/src/recorder/eventExporter.ts +0 -141
- package/src/recorder/gestureRecorder.ts +0 -498
- package/src/recorder/index.ts +0 -179
- package/src/recorder/navigationTracker.ts +0 -449
- package/src/recorder/screenRecorder.ts +0 -527
- package/src/services/api.service.ts +0 -203
- package/src/services/screenMaskingService.ts +0 -118
- package/src/services/storage.service.ts +0 -199
- package/src/session-recorder.ts +0 -606
- package/src/types/expo.d.ts +0 -23
- package/src/types/index.ts +0 -28
- package/src/types/session-recorder.ts +0 -429
- package/src/types/session.ts +0 -65
- package/src/utils/app-metadata.ts +0 -31
- package/src/utils/index.ts +0 -8
- package/src/utils/logger.ts +0 -225
- package/src/utils/nativeModuleTest.ts +0 -60
- package/src/utils/platform.ts +0 -384
- package/src/utils/request-utils.ts +0 -61
- package/src/utils/rrweb-events.ts +0 -309
- package/src/utils/session.ts +0 -18
- package/src/utils/time.ts +0 -17
- package/src/utils/type-utils.ts +0 -75
- package/src/version.ts +0 -1
- package/tsconfig.json +0 -24
- /package/ios/{SessionRecorder.m → SessionRecorderNative.m} +0 -0
- /package/ios/{SessionRecorder.swift → SessionRecorderNative.swift} +0 -0
package/src/utils/logger.ts
DELETED
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Centralized logger utility for the session recorder
|
|
3
|
-
* Provides consistent logging across all components
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export enum LogLevel {
|
|
7
|
-
DEBUG = 0,
|
|
8
|
-
INFO = 1,
|
|
9
|
-
WARN = 2,
|
|
10
|
-
ERROR = 3
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface LoggerConfig {
|
|
14
|
-
level: LogLevel
|
|
15
|
-
enableConsole: boolean
|
|
16
|
-
enablePrefix: boolean
|
|
17
|
-
prefix: string
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
class Logger {
|
|
21
|
-
private config: LoggerConfig = {
|
|
22
|
-
level: LogLevel.INFO,
|
|
23
|
-
enableConsole: true,
|
|
24
|
-
enablePrefix: true,
|
|
25
|
-
prefix: '[SessionRecorder]',
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
private componentPrefixes: Map<string, string> = new Map([
|
|
29
|
-
['ScreenRecorder', '📸'],
|
|
30
|
-
['GestureRecorder', '👆'],
|
|
31
|
-
['GestureCaptureWrapper', '📸'],
|
|
32
|
-
['SessionRecorderContext', '🎯'],
|
|
33
|
-
['EventExporter', '📤'],
|
|
34
|
-
['NavigationTracker', '📸'],
|
|
35
|
-
['RecorderReactNativeSDK', '📤'],
|
|
36
|
-
['DEBUGGER_LIB', '🔍'],
|
|
37
|
-
])
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Configure the logger
|
|
41
|
-
* @param config - Logger configuration
|
|
42
|
-
*/
|
|
43
|
-
configure(config: Partial<LoggerConfig>): void {
|
|
44
|
-
this.config = { ...this.config, ...config }
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Set the log level
|
|
49
|
-
* @param level - Log level to set
|
|
50
|
-
*/
|
|
51
|
-
setLevel(level: LogLevel): void {
|
|
52
|
-
this.config.level = level
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Enable or disable console output
|
|
57
|
-
* @param enabled - Whether to enable console output
|
|
58
|
-
*/
|
|
59
|
-
setConsoleEnabled(enabled: boolean): void {
|
|
60
|
-
this.config.enableConsole = enabled
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Add or update a component prefix
|
|
65
|
-
* @param component - Component name
|
|
66
|
-
* @param emoji - Emoji prefix for the component
|
|
67
|
-
*/
|
|
68
|
-
setComponentPrefix(component: string, emoji: string): void {
|
|
69
|
-
this.componentPrefixes.set(component, emoji)
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Get the formatted prefix for a component
|
|
74
|
-
* @param component - Component name
|
|
75
|
-
* @returns Formatted prefix string
|
|
76
|
-
*/
|
|
77
|
-
private getPrefix(component: string): string {
|
|
78
|
-
if (!this.config.enablePrefix) return ''
|
|
79
|
-
|
|
80
|
-
const emoji = this.componentPrefixes.get(component) || '📝'
|
|
81
|
-
return `${this.config.prefix} ${emoji} [${component}]`
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Check if a log level should be output
|
|
86
|
-
* @param level - Log level to check
|
|
87
|
-
* @returns True if should output
|
|
88
|
-
*/
|
|
89
|
-
private shouldLog(level: LogLevel): boolean {
|
|
90
|
-
return level >= this.config.level && this.config.enableConsole
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Format the log message
|
|
95
|
-
* @param component - Component name
|
|
96
|
-
* @param level - Log level
|
|
97
|
-
* @param message - Log message
|
|
98
|
-
* @param data - Additional data to log
|
|
99
|
-
* @returns Formatted log message
|
|
100
|
-
*/
|
|
101
|
-
private formatMessage(component: string, level: LogLevel, message: string, data?: any): string {
|
|
102
|
-
const prefix = this.getPrefix(component)
|
|
103
|
-
const timestamp = new Date().toISOString()
|
|
104
|
-
const levelName = LogLevel[level]
|
|
105
|
-
|
|
106
|
-
let formattedMessage = `${prefix} ${levelName} ${message}`
|
|
107
|
-
|
|
108
|
-
if (data !== undefined) {
|
|
109
|
-
formattedMessage += ` ${JSON.stringify(data)}`
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return formattedMessage
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Log a debug message
|
|
117
|
-
* @param component - Component name
|
|
118
|
-
* @param message - Log message
|
|
119
|
-
* @param data - Additional data to log
|
|
120
|
-
*/
|
|
121
|
-
debug(component: string, message: string, data?: any): void {
|
|
122
|
-
if (!this.shouldLog(LogLevel.DEBUG)) return
|
|
123
|
-
|
|
124
|
-
const formattedMessage = this.formatMessage(component, LogLevel.DEBUG, message, data)
|
|
125
|
-
// eslint-disable-next-line no-console
|
|
126
|
-
console.log(formattedMessage)
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Log an info message
|
|
131
|
-
* @param component - Component name
|
|
132
|
-
* @param message - Log message
|
|
133
|
-
* @param data - Additional data to log
|
|
134
|
-
*/
|
|
135
|
-
info(component: string, message: string, data?: any): void {
|
|
136
|
-
if (!this.shouldLog(LogLevel.INFO)) return
|
|
137
|
-
|
|
138
|
-
const formattedMessage = this.formatMessage(component, LogLevel.INFO, message, data)
|
|
139
|
-
// eslint-disable-next-line no-console
|
|
140
|
-
console.log(formattedMessage)
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Log a warning message
|
|
145
|
-
* @param component - Component name
|
|
146
|
-
* @param message - Log message
|
|
147
|
-
* @param data - Additional data to log
|
|
148
|
-
*/
|
|
149
|
-
warn(component: string, message: string, data?: any): void {
|
|
150
|
-
if (!this.shouldLog(LogLevel.WARN)) return
|
|
151
|
-
|
|
152
|
-
const formattedMessage = this.formatMessage(component, LogLevel.WARN, message, data)
|
|
153
|
-
// eslint-disable-next-line no-console
|
|
154
|
-
console.warn(formattedMessage)
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Log an error message
|
|
159
|
-
* @param component - Component name
|
|
160
|
-
* @param message - Log message
|
|
161
|
-
* @param data - Additional data to log
|
|
162
|
-
*/
|
|
163
|
-
error(component: string, message: string, data?: any): void {
|
|
164
|
-
if (!this.shouldLog(LogLevel.ERROR)) return
|
|
165
|
-
|
|
166
|
-
const formattedMessage = this.formatMessage(component, LogLevel.ERROR, message, data)
|
|
167
|
-
// eslint-disable-next-line no-console
|
|
168
|
-
console.error(formattedMessage)
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Log a success message (info level with success emoji)
|
|
173
|
-
* @param component - Component name
|
|
174
|
-
* @param message - Log message
|
|
175
|
-
* @param data - Additional data to log
|
|
176
|
-
*/
|
|
177
|
-
success(component: string, message: string, data?: any): void {
|
|
178
|
-
if (!this.shouldLog(LogLevel.INFO)) return
|
|
179
|
-
|
|
180
|
-
const prefix = this.getPrefix(component)
|
|
181
|
-
const timestamp = new Date().toISOString()
|
|
182
|
-
const formattedMessage = `${prefix} ✅ ${message}`
|
|
183
|
-
|
|
184
|
-
let fullMessage = formattedMessage
|
|
185
|
-
if (data !== undefined) {
|
|
186
|
-
fullMessage += ` ${JSON.stringify(data)}`
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// eslint-disable-next-line no-console
|
|
190
|
-
console.log(fullMessage)
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Log a failure message (error level with failure emoji)
|
|
195
|
-
* @param component - Component name
|
|
196
|
-
* @param message - Log message
|
|
197
|
-
* @param data - Additional data to log
|
|
198
|
-
*/
|
|
199
|
-
failure(component: string, message: string, data?: any): void {
|
|
200
|
-
if (!this.shouldLog(LogLevel.ERROR)) return
|
|
201
|
-
|
|
202
|
-
const prefix = this.getPrefix(component)
|
|
203
|
-
const timestamp = new Date().toISOString()
|
|
204
|
-
const formattedMessage = `${prefix} ❌ ${message}`
|
|
205
|
-
|
|
206
|
-
let fullMessage = formattedMessage
|
|
207
|
-
if (data !== undefined) {
|
|
208
|
-
fullMessage += ` ${JSON.stringify(data)}`
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// eslint-disable-next-line no-console
|
|
212
|
-
console.error(fullMessage)
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// Export a singleton instance
|
|
217
|
-
export const logger = new Logger()
|
|
218
|
-
|
|
219
|
-
// Export convenience functions for common use cases
|
|
220
|
-
export const logDebug = (component: string, message: string, data?: any) => logger.debug(component, message, data)
|
|
221
|
-
export const logInfo = (component: string, message: string, data?: any) => logger.info(component, message, data)
|
|
222
|
-
export const logWarn = (component: string, message: string, data?: any) => logger.warn(component, message, data)
|
|
223
|
-
export const logError = (component: string, message: string, data?: any) => logger.error(component, message, data)
|
|
224
|
-
export const logSuccess = (component: string, message: string, data?: any) => logger.success(component, message, data)
|
|
225
|
-
export const logFailure = (component: string, message: string, data?: any) => logger.failure(component, message, data)
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { NativeModules } from 'react-native'
|
|
2
|
-
import { logger } from './logger'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Test function to verify native module availability
|
|
6
|
-
*/
|
|
7
|
-
export function testNativeModuleAvailability(): void {
|
|
8
|
-
logger.info('NativeModuleTest', 'Testing native module availability...')
|
|
9
|
-
|
|
10
|
-
// Log all available native modules
|
|
11
|
-
const availableModules = Object.keys(NativeModules)
|
|
12
|
-
logger.info('NativeModuleTest', `Available native modules: ${availableModules.join(', ')}`)
|
|
13
|
-
|
|
14
|
-
// Check specifically for SessionRecorderNative
|
|
15
|
-
const { SessionRecorderNative } = NativeModules
|
|
16
|
-
|
|
17
|
-
if (SessionRecorderNative) {
|
|
18
|
-
logger.info('NativeModuleTest', '✅ SessionRecorderNative module is available!')
|
|
19
|
-
|
|
20
|
-
// Test if the methods exist
|
|
21
|
-
if (typeof SessionRecorderNative.captureAndMask === 'function') {
|
|
22
|
-
logger.info('NativeModuleTest', '✅ captureAndMask method is available!')
|
|
23
|
-
} else {
|
|
24
|
-
logger.warn('NativeModuleTest', '❌ captureAndMask method is not available')
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (typeof SessionRecorderNative.captureAndMaskWithOptions === 'function') {
|
|
28
|
-
logger.info('NativeModuleTest', '✅ captureAndMaskWithOptions method is available!')
|
|
29
|
-
} else {
|
|
30
|
-
logger.warn('NativeModuleTest', '❌ captureAndMaskWithOptions method is not available')
|
|
31
|
-
}
|
|
32
|
-
} else {
|
|
33
|
-
logger.error('NativeModuleTest', '❌ SessionRecorderNative module is not available')
|
|
34
|
-
logger.info('NativeModuleTest', 'This could mean:')
|
|
35
|
-
logger.info('NativeModuleTest', '1. Auto-linking has not completed yet')
|
|
36
|
-
logger.info('NativeModuleTest', '2. The native module was not properly built')
|
|
37
|
-
logger.info('NativeModuleTest', '3. The module name does not match')
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Test function to verify auto-linking configuration
|
|
43
|
-
*/
|
|
44
|
-
export function testAutoLinkingConfig(): void {
|
|
45
|
-
logger.info('NativeModuleTest', 'Testing auto-linking configuration...')
|
|
46
|
-
|
|
47
|
-
// Check if react-native.config.js exists and is properly configured
|
|
48
|
-
try {
|
|
49
|
-
const config = require('../../react-native.config.js')
|
|
50
|
-
logger.info('NativeModuleTest', '✅ react-native.config.js found')
|
|
51
|
-
|
|
52
|
-
if (config.dependencies && config.dependencies['react-native-session-recorder']) {
|
|
53
|
-
logger.info('NativeModuleTest', '✅ Auto-linking configuration found for react-native-session-recorder')
|
|
54
|
-
} else {
|
|
55
|
-
logger.warn('NativeModuleTest', '❌ Auto-linking configuration not found for react-native-session-recorder')
|
|
56
|
-
}
|
|
57
|
-
} catch (error) {
|
|
58
|
-
logger.warn('NativeModuleTest', '❌ react-native.config.js not found or invalid')
|
|
59
|
-
}
|
|
60
|
-
}
|
package/src/utils/platform.ts
DELETED
|
@@ -1,384 +0,0 @@
|
|
|
1
|
-
import { IResourceAttributes } from '../types'
|
|
2
|
-
import Constants from 'expo-constants'
|
|
3
|
-
import { Platform, Dimensions, PixelRatio } from 'react-native'
|
|
4
|
-
import { version } from '../version'
|
|
5
|
-
import { getAutoDetectedAppMetadata } from './app-metadata'
|
|
6
|
-
|
|
7
|
-
// Global app metadata configuration for non-Expo apps
|
|
8
|
-
let globalAppMetadata: { name?: string; version?: string; bundleId?: string } = {}
|
|
9
|
-
|
|
10
|
-
// Cache for auto-detected metadata to avoid repeated file reads
|
|
11
|
-
let autoDetectedMetadata: { name?: string; version?: string; bundleId?: string } | null = null
|
|
12
|
-
|
|
13
|
-
export interface PlatformInfo {
|
|
14
|
-
isExpo: boolean
|
|
15
|
-
isReactNative: boolean
|
|
16
|
-
platform: 'ios' | 'android' | 'web' | 'unknown'
|
|
17
|
-
platformVersion?: string
|
|
18
|
-
expoVersion?: string
|
|
19
|
-
deviceType: string
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function detectPlatform(): PlatformInfo {
|
|
23
|
-
try {
|
|
24
|
-
// Check if we're in an Expo environment
|
|
25
|
-
const isExpo = !!Constants.default?.expoVersion || !!Constants.expoVersion
|
|
26
|
-
|
|
27
|
-
if (isExpo) {
|
|
28
|
-
const expoVersion = Constants.default?.expoVersion || Constants.expoVersion
|
|
29
|
-
const platform = Constants.default?.platform || Constants.platform
|
|
30
|
-
|
|
31
|
-
return {
|
|
32
|
-
isExpo: true,
|
|
33
|
-
isReactNative: true,
|
|
34
|
-
platform: platform?.ios ? 'ios' : platform?.android ? 'android' : 'unknown',
|
|
35
|
-
expoVersion,
|
|
36
|
-
deviceType: 'expo',
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Fallback to React Native detection
|
|
41
|
-
return {
|
|
42
|
-
isExpo: false,
|
|
43
|
-
isReactNative: true,
|
|
44
|
-
platform: Platform.OS as 'ios' | 'android' | 'web' | 'unknown',
|
|
45
|
-
platformVersion: Platform.Version?.toString(),
|
|
46
|
-
deviceType: Platform.OS,
|
|
47
|
-
}
|
|
48
|
-
} catch (error) {
|
|
49
|
-
// Fallback for web or other environments
|
|
50
|
-
return {
|
|
51
|
-
isExpo: false,
|
|
52
|
-
isReactNative: false,
|
|
53
|
-
platform: 'unknown',
|
|
54
|
-
deviceType: 'unknown',
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export function getPlatformAttributes(): Record<string, any> {
|
|
60
|
-
const platformInfo = detectPlatform()
|
|
61
|
-
|
|
62
|
-
const attributes: Record<string, any> = {
|
|
63
|
-
platform: platformInfo.isExpo ? 'expo' : 'react-native',
|
|
64
|
-
'device.type': platformInfo.deviceType,
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (platformInfo.platformVersion) {
|
|
68
|
-
attributes['platform.version'] = platformInfo.platformVersion
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (platformInfo.expoVersion) {
|
|
72
|
-
attributes['expo.version'] = platformInfo.expoVersion
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return attributes
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export function isExpoEnvironment(): boolean {
|
|
79
|
-
return detectPlatform().isExpo
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export function isReactNativeEnvironment(): boolean {
|
|
83
|
-
return detectPlatform().isReactNative
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Configure app metadata for non-Expo React Native apps
|
|
88
|
-
* Call this function in your app initialization to provide app information
|
|
89
|
-
*
|
|
90
|
-
* @example
|
|
91
|
-
* ```typescript
|
|
92
|
-
* import { configureAppMetadata } from '@multiplayer-app/session-recorder-react-native'
|
|
93
|
-
*
|
|
94
|
-
* // In your App.tsx or index.js
|
|
95
|
-
* configureAppMetadata({
|
|
96
|
-
* name: 'My Awesome App',
|
|
97
|
-
* version: '1.2.3',
|
|
98
|
-
* bundleId: 'com.mycompany.myapp',
|
|
99
|
-
* buildNumber: '123',
|
|
100
|
-
* displayName: 'My App',
|
|
101
|
-
* })
|
|
102
|
-
* ```
|
|
103
|
-
*/
|
|
104
|
-
export function configureAppMetadata(metadata: {
|
|
105
|
-
name?: string
|
|
106
|
-
version?: string
|
|
107
|
-
bundleId?: string
|
|
108
|
-
buildNumber?: string
|
|
109
|
-
displayName?: string
|
|
110
|
-
}): void {
|
|
111
|
-
globalAppMetadata = { ...globalAppMetadata, ...metadata }
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Get configured app metadata
|
|
116
|
-
*/
|
|
117
|
-
export function getConfiguredAppMetadata(): { name?: string, version?: string, bundleId?: string, buildNumber?: string, displayName?: string, } {
|
|
118
|
-
return { ...globalAppMetadata }
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Automatically detect app metadata from common configuration files
|
|
123
|
-
* This runs without developer intervention
|
|
124
|
-
*/
|
|
125
|
-
function autoDetectAppMetadata(): { name?: string; version?: string; bundleId?: string } {
|
|
126
|
-
if (autoDetectedMetadata) {
|
|
127
|
-
return autoDetectedMetadata
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
try {
|
|
131
|
-
// Get auto-detected metadata from build-time generated file
|
|
132
|
-
const autoMetadata = getAutoDetectedAppMetadata()
|
|
133
|
-
|
|
134
|
-
// Filter out undefined values
|
|
135
|
-
const metadata: { name?: string; version?: string; bundleId?: string } = {}
|
|
136
|
-
if (autoMetadata.name) metadata.name = autoMetadata.name
|
|
137
|
-
if (autoMetadata.version) metadata.version = autoMetadata.version
|
|
138
|
-
if (autoMetadata.bundleId) metadata.bundleId = autoMetadata.bundleId
|
|
139
|
-
|
|
140
|
-
autoDetectedMetadata = metadata
|
|
141
|
-
return metadata
|
|
142
|
-
} catch (error) {
|
|
143
|
-
// Silently fail - this is optional auto-detection
|
|
144
|
-
autoDetectedMetadata = {}
|
|
145
|
-
return {}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Enhanced app metadata detection with automatic fallbacks
|
|
151
|
-
*/
|
|
152
|
-
function getAppMetadata(): { name?: string; version?: string; bundleId?: string } {
|
|
153
|
-
// Priority order:
|
|
154
|
-
// 1. Expo config (if available)
|
|
155
|
-
// 2. Manually configured metadata
|
|
156
|
-
// 3. Auto-detected metadata
|
|
157
|
-
// 4. Fallbacks
|
|
158
|
-
|
|
159
|
-
const expoMetadata = getExpoMetadata()
|
|
160
|
-
const configuredMetadata = getConfiguredAppMetadata()
|
|
161
|
-
const autoMetadata = autoDetectAppMetadata()
|
|
162
|
-
|
|
163
|
-
return {
|
|
164
|
-
name: expoMetadata.name || configuredMetadata.name || autoMetadata.name,
|
|
165
|
-
version: expoMetadata.version || configuredMetadata.version || autoMetadata.version,
|
|
166
|
-
bundleId: expoMetadata.bundleId || configuredMetadata.bundleId || autoMetadata.bundleId,
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Get metadata from Expo config
|
|
172
|
-
*/
|
|
173
|
-
function getExpoMetadata(): { name?: string; version?: string; bundleId?: string } {
|
|
174
|
-
const expoConfig = Constants.default?.expoConfig || Constants.expoConfig
|
|
175
|
-
if (!expoConfig) return {}
|
|
176
|
-
|
|
177
|
-
return {
|
|
178
|
-
name: expoConfig.name,
|
|
179
|
-
version: expoConfig.version,
|
|
180
|
-
bundleId: expoConfig.ios?.bundleIdentifier || expoConfig.android?.package,
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
export const getNavigatorInfo = (): IResourceAttributes => {
|
|
185
|
-
const platformInfo = detectPlatform()
|
|
186
|
-
const screenData = Dimensions.get('window')
|
|
187
|
-
const screenDataScreen = Dimensions.get('screen')
|
|
188
|
-
const pixelRatio = PixelRatio.get()
|
|
189
|
-
|
|
190
|
-
// Get device type based on screen dimensions
|
|
191
|
-
const getDeviceType = (): string => {
|
|
192
|
-
const { width, height } = screenData
|
|
193
|
-
const minDimension = Math.min(width, height)
|
|
194
|
-
const maxDimension = Math.max(width, height)
|
|
195
|
-
|
|
196
|
-
// Rough device type detection based on screen size
|
|
197
|
-
if (maxDimension >= 1024) {
|
|
198
|
-
return 'Tablet'
|
|
199
|
-
} else if (minDimension >= 600) {
|
|
200
|
-
return 'Large Phone'
|
|
201
|
-
} else {
|
|
202
|
-
return 'Phone'
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// Get orientation
|
|
207
|
-
const getOrientation = (): string => {
|
|
208
|
-
const { width, height } = screenData
|
|
209
|
-
return width > height ? 'Landscape' : 'Portrait'
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// Get OS version details
|
|
213
|
-
const getOSInfo = (): string => {
|
|
214
|
-
if (platformInfo.isExpo) {
|
|
215
|
-
const platform = Constants.default?.platform || Constants.platform
|
|
216
|
-
if (platform?.ios) {
|
|
217
|
-
return `iOS ${Platform.Version}`
|
|
218
|
-
} else if (platform?.android) {
|
|
219
|
-
return `Android ${Platform.Version}`
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
if (Platform.OS === 'ios') {
|
|
224
|
-
return `iOS ${Platform.Version}`
|
|
225
|
-
} else if (Platform.OS === 'android') {
|
|
226
|
-
return `Android ${Platform.Version}`
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
return `${Platform.OS} ${Platform.Version || 'Unknown'}`
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// Get device info string
|
|
233
|
-
const getDeviceInfo = (): string => {
|
|
234
|
-
const deviceType = getDeviceType()
|
|
235
|
-
const osInfo = getOSInfo()
|
|
236
|
-
return `${deviceType} - ${osInfo}`
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// Get browser/runtime info
|
|
240
|
-
const getBrowserInfo = (): string => {
|
|
241
|
-
if (platformInfo.isExpo) {
|
|
242
|
-
return `Expo ${platformInfo.expoVersion || 'Unknown'} - React Native`
|
|
243
|
-
}
|
|
244
|
-
return 'React Native'
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// Get screen size string
|
|
248
|
-
const getScreenSize = (): string => {
|
|
249
|
-
return `${Math.round(screenData.width)}x${Math.round(screenData.height)}`
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
// Get app info with fallbacks for non-Expo apps
|
|
253
|
-
const getAppInfo = (): string => {
|
|
254
|
-
const appName = getAppName()
|
|
255
|
-
const appVersion = getAppVersion()
|
|
256
|
-
return `${appName} v${appVersion}`
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// Get app name with automatic detection
|
|
260
|
-
const getAppName = (): string => {
|
|
261
|
-
const metadata = getAppMetadata()
|
|
262
|
-
if (metadata.name) return metadata.name
|
|
263
|
-
|
|
264
|
-
// Try configured display name as fallback
|
|
265
|
-
const configuredMetadata = getConfiguredAppMetadata()
|
|
266
|
-
if (configuredMetadata.displayName) return configuredMetadata.displayName
|
|
267
|
-
|
|
268
|
-
// Final fallback
|
|
269
|
-
return 'React Native App'
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// Get app version with automatic detection
|
|
273
|
-
const getAppVersion = (): string => {
|
|
274
|
-
const metadata = getAppMetadata()
|
|
275
|
-
if (metadata.version) return metadata.version
|
|
276
|
-
|
|
277
|
-
// Final fallback
|
|
278
|
-
return 'Unknown'
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
// Get bundle ID with automatic detection
|
|
282
|
-
const getBundleId = (): string => {
|
|
283
|
-
const metadata = getAppMetadata()
|
|
284
|
-
if (metadata.bundleId) return metadata.bundleId
|
|
285
|
-
|
|
286
|
-
// Fallback
|
|
287
|
-
return 'com.reactnative.app'
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
// Get build number with multiple fallback strategies
|
|
291
|
-
const getBuildNumber = (): string => {
|
|
292
|
-
// Try Expo config first
|
|
293
|
-
const expoBuildNumber =
|
|
294
|
-
Constants.default?.expoConfig?.ios?.buildNumber ||
|
|
295
|
-
Constants.expoConfig?.ios?.buildNumber ||
|
|
296
|
-
Constants.default?.expoConfig?.android?.versionCode ||
|
|
297
|
-
Constants.expoConfig?.android?.versionCode
|
|
298
|
-
if (expoBuildNumber) return expoBuildNumber.toString()
|
|
299
|
-
|
|
300
|
-
// Try configured metadata for non-Expo apps
|
|
301
|
-
const configuredMetadata = getConfiguredAppMetadata()
|
|
302
|
-
if (configuredMetadata.buildNumber) return configuredMetadata.buildNumber
|
|
303
|
-
|
|
304
|
-
// Fallback
|
|
305
|
-
return '1'
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
// Get network info (basic)
|
|
309
|
-
const getNetworkInfo = (): string => {
|
|
310
|
-
// This is a basic implementation - in a real app you might want to use @react-native-community/netinfo
|
|
311
|
-
return 'Unknown'
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
// Get hardware info
|
|
315
|
-
const getHardwareInfo = (): string => {
|
|
316
|
-
const pixelRatioInfo = `Pixel Ratio: ${pixelRatio}`
|
|
317
|
-
const screenDensity = PixelRatio.getFontScale()
|
|
318
|
-
return `${pixelRatioInfo}, Font Scale: ${screenDensity}`
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
return {
|
|
322
|
-
// Core platform info
|
|
323
|
-
platform: platformInfo.isExpo ? 'expo' : 'react-native',
|
|
324
|
-
userAgent: getBrowserInfo(),
|
|
325
|
-
language: 'en', // Could be enhanced with react-native-localize if available
|
|
326
|
-
timestamp: new Date().toISOString(),
|
|
327
|
-
|
|
328
|
-
// Device and OS information
|
|
329
|
-
deviceInfo: getDeviceInfo(),
|
|
330
|
-
osInfo: getOSInfo(),
|
|
331
|
-
browserInfo: getBrowserInfo(),
|
|
332
|
-
|
|
333
|
-
// Screen information
|
|
334
|
-
screenSize: getScreenSize(),
|
|
335
|
-
pixelRatio: pixelRatio,
|
|
336
|
-
orientation: getOrientation(),
|
|
337
|
-
screenWidth: Math.round(screenData.width),
|
|
338
|
-
screenHeight: Math.round(screenData.height),
|
|
339
|
-
screenScale: pixelRatio,
|
|
340
|
-
|
|
341
|
-
// Device capabilities
|
|
342
|
-
hardwareConcurrency: 1, // React Native doesn't expose CPU cores directly
|
|
343
|
-
cookiesEnabled: 'N/A', // Not applicable in React Native
|
|
344
|
-
|
|
345
|
-
// App information
|
|
346
|
-
packageVersion: version,
|
|
347
|
-
appInfo: getAppInfo(),
|
|
348
|
-
appName: getAppName(),
|
|
349
|
-
appVersion: getAppVersion(),
|
|
350
|
-
bundleId: getBundleId(),
|
|
351
|
-
buildNumber: getBuildNumber(),
|
|
352
|
-
|
|
353
|
-
// Platform specific
|
|
354
|
-
platformType: platformInfo.platform,
|
|
355
|
-
platformVersion: platformInfo.platformVersion,
|
|
356
|
-
expoVersion: platformInfo.expoVersion,
|
|
357
|
-
deviceType: getDeviceType(),
|
|
358
|
-
|
|
359
|
-
// Additional device info
|
|
360
|
-
deviceModel: Platform.OS === 'ios' ? 'iOS Device' : 'Android Device',
|
|
361
|
-
deviceManufacturer: Platform.OS === 'ios' ? 'Apple' : 'Android Manufacturer',
|
|
362
|
-
deviceBrand: Platform.OS === 'ios' ? 'Apple' : 'Android Brand',
|
|
363
|
-
|
|
364
|
-
// Performance and hardware
|
|
365
|
-
hardwareInfo: getHardwareInfo(),
|
|
366
|
-
networkInfo: getNetworkInfo(),
|
|
367
|
-
|
|
368
|
-
// Screen details
|
|
369
|
-
screenDensity: PixelRatio.getFontScale(),
|
|
370
|
-
screenScaleFactor: pixelRatio,
|
|
371
|
-
windowWidth: Math.round(screenData.width),
|
|
372
|
-
windowHeight: Math.round(screenData.height),
|
|
373
|
-
fullScreenWidth: Math.round(screenDataScreen.width),
|
|
374
|
-
fullScreenHeight: Math.round(screenDataScreen.height),
|
|
375
|
-
|
|
376
|
-
// Environment info
|
|
377
|
-
isExpo: platformInfo.isExpo,
|
|
378
|
-
isReactNative: platformInfo.isReactNative,
|
|
379
|
-
environment: platformInfo.isExpo ? 'expo' : 'react-native',
|
|
380
|
-
|
|
381
|
-
// Additional platform attributes
|
|
382
|
-
...getPlatformAttributes(),
|
|
383
|
-
}
|
|
384
|
-
}
|