@rejourneyco/react-native 1.0.0
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/android/build.gradle.kts +135 -0
- package/android/consumer-rules.pro +10 -0
- package/android/proguard-rules.pro +1 -0
- package/android/src/main/AndroidManifest.xml +15 -0
- package/android/src/main/java/com/rejourney/RejourneyModuleImpl.kt +2981 -0
- package/android/src/main/java/com/rejourney/capture/ANRHandler.kt +206 -0
- package/android/src/main/java/com/rejourney/capture/ActivityTracker.kt +98 -0
- package/android/src/main/java/com/rejourney/capture/CaptureEngine.kt +1553 -0
- package/android/src/main/java/com/rejourney/capture/CaptureHeuristics.kt +375 -0
- package/android/src/main/java/com/rejourney/capture/CrashHandler.kt +153 -0
- package/android/src/main/java/com/rejourney/capture/MotionEvent.kt +215 -0
- package/android/src/main/java/com/rejourney/capture/SegmentUploader.kt +512 -0
- package/android/src/main/java/com/rejourney/capture/VideoEncoder.kt +773 -0
- package/android/src/main/java/com/rejourney/capture/ViewHierarchyScanner.kt +633 -0
- package/android/src/main/java/com/rejourney/capture/ViewSerializer.kt +286 -0
- package/android/src/main/java/com/rejourney/core/Constants.kt +117 -0
- package/android/src/main/java/com/rejourney/core/Logger.kt +93 -0
- package/android/src/main/java/com/rejourney/core/Types.kt +124 -0
- package/android/src/main/java/com/rejourney/lifecycle/SessionLifecycleService.kt +162 -0
- package/android/src/main/java/com/rejourney/network/DeviceAuthManager.kt +747 -0
- package/android/src/main/java/com/rejourney/network/HttpClientProvider.kt +16 -0
- package/android/src/main/java/com/rejourney/network/NetworkMonitor.kt +272 -0
- package/android/src/main/java/com/rejourney/network/UploadManager.kt +1363 -0
- package/android/src/main/java/com/rejourney/network/UploadWorker.kt +492 -0
- package/android/src/main/java/com/rejourney/privacy/PrivacyMask.kt +645 -0
- package/android/src/main/java/com/rejourney/touch/GestureClassifier.kt +233 -0
- package/android/src/main/java/com/rejourney/touch/KeyboardTracker.kt +158 -0
- package/android/src/main/java/com/rejourney/touch/TextInputTracker.kt +181 -0
- package/android/src/main/java/com/rejourney/touch/TouchInterceptor.kt +591 -0
- package/android/src/main/java/com/rejourney/utils/EventBuffer.kt +284 -0
- package/android/src/main/java/com/rejourney/utils/OEMDetector.kt +154 -0
- package/android/src/main/java/com/rejourney/utils/PerfTiming.kt +235 -0
- package/android/src/main/java/com/rejourney/utils/Telemetry.kt +297 -0
- package/android/src/main/java/com/rejourney/utils/WindowUtils.kt +84 -0
- package/android/src/newarch/java/com/rejourney/RejourneyModule.kt +187 -0
- package/android/src/newarch/java/com/rejourney/RejourneyPackage.kt +40 -0
- package/android/src/oldarch/java/com/rejourney/RejourneyModule.kt +218 -0
- package/android/src/oldarch/java/com/rejourney/RejourneyPackage.kt +23 -0
- package/ios/Capture/RJANRHandler.h +42 -0
- package/ios/Capture/RJANRHandler.m +328 -0
- package/ios/Capture/RJCaptureEngine.h +275 -0
- package/ios/Capture/RJCaptureEngine.m +2062 -0
- package/ios/Capture/RJCaptureHeuristics.h +80 -0
- package/ios/Capture/RJCaptureHeuristics.m +903 -0
- package/ios/Capture/RJCrashHandler.h +46 -0
- package/ios/Capture/RJCrashHandler.m +313 -0
- package/ios/Capture/RJMotionEvent.h +183 -0
- package/ios/Capture/RJMotionEvent.m +183 -0
- package/ios/Capture/RJPerformanceManager.h +100 -0
- package/ios/Capture/RJPerformanceManager.m +373 -0
- package/ios/Capture/RJPixelBufferDownscaler.h +42 -0
- package/ios/Capture/RJPixelBufferDownscaler.m +85 -0
- package/ios/Capture/RJSegmentUploader.h +146 -0
- package/ios/Capture/RJSegmentUploader.m +778 -0
- package/ios/Capture/RJVideoEncoder.h +247 -0
- package/ios/Capture/RJVideoEncoder.m +1036 -0
- package/ios/Capture/RJViewControllerTracker.h +73 -0
- package/ios/Capture/RJViewControllerTracker.m +508 -0
- package/ios/Capture/RJViewHierarchyScanner.h +215 -0
- package/ios/Capture/RJViewHierarchyScanner.m +1464 -0
- package/ios/Capture/RJViewSerializer.h +119 -0
- package/ios/Capture/RJViewSerializer.m +498 -0
- package/ios/Core/RJConstants.h +124 -0
- package/ios/Core/RJConstants.m +88 -0
- package/ios/Core/RJLifecycleManager.h +85 -0
- package/ios/Core/RJLifecycleManager.m +308 -0
- package/ios/Core/RJLogger.h +61 -0
- package/ios/Core/RJLogger.m +211 -0
- package/ios/Core/RJTypes.h +176 -0
- package/ios/Core/RJTypes.m +66 -0
- package/ios/Core/Rejourney.h +64 -0
- package/ios/Core/Rejourney.mm +2495 -0
- package/ios/Network/RJDeviceAuthManager.h +94 -0
- package/ios/Network/RJDeviceAuthManager.m +967 -0
- package/ios/Network/RJNetworkMonitor.h +68 -0
- package/ios/Network/RJNetworkMonitor.m +267 -0
- package/ios/Network/RJRetryManager.h +73 -0
- package/ios/Network/RJRetryManager.m +325 -0
- package/ios/Network/RJUploadManager.h +267 -0
- package/ios/Network/RJUploadManager.m +2296 -0
- package/ios/Privacy/RJPrivacyMask.h +163 -0
- package/ios/Privacy/RJPrivacyMask.m +922 -0
- package/ios/Rejourney.h +63 -0
- package/ios/Touch/RJGestureClassifier.h +130 -0
- package/ios/Touch/RJGestureClassifier.m +333 -0
- package/ios/Touch/RJTouchInterceptor.h +169 -0
- package/ios/Touch/RJTouchInterceptor.m +772 -0
- package/ios/Utils/RJEventBuffer.h +112 -0
- package/ios/Utils/RJEventBuffer.m +358 -0
- package/ios/Utils/RJGzipUtils.h +33 -0
- package/ios/Utils/RJGzipUtils.m +89 -0
- package/ios/Utils/RJKeychainManager.h +48 -0
- package/ios/Utils/RJKeychainManager.m +111 -0
- package/ios/Utils/RJPerfTiming.h +209 -0
- package/ios/Utils/RJPerfTiming.m +264 -0
- package/ios/Utils/RJTelemetry.h +92 -0
- package/ios/Utils/RJTelemetry.m +320 -0
- package/ios/Utils/RJWindowUtils.h +66 -0
- package/ios/Utils/RJWindowUtils.m +133 -0
- package/lib/commonjs/NativeRejourney.js +40 -0
- package/lib/commonjs/components/Mask.js +79 -0
- package/lib/commonjs/index.js +1381 -0
- package/lib/commonjs/sdk/autoTracking.js +1259 -0
- package/lib/commonjs/sdk/constants.js +151 -0
- package/lib/commonjs/sdk/errorTracking.js +199 -0
- package/lib/commonjs/sdk/index.js +50 -0
- package/lib/commonjs/sdk/metricsTracking.js +204 -0
- package/lib/commonjs/sdk/navigation.js +151 -0
- package/lib/commonjs/sdk/networkInterceptor.js +412 -0
- package/lib/commonjs/sdk/utils.js +363 -0
- package/lib/commonjs/types/expo-router.d.js +2 -0
- package/lib/commonjs/types/index.js +2 -0
- package/lib/module/NativeRejourney.js +38 -0
- package/lib/module/components/Mask.js +72 -0
- package/lib/module/index.js +1284 -0
- package/lib/module/sdk/autoTracking.js +1233 -0
- package/lib/module/sdk/constants.js +145 -0
- package/lib/module/sdk/errorTracking.js +189 -0
- package/lib/module/sdk/index.js +12 -0
- package/lib/module/sdk/metricsTracking.js +187 -0
- package/lib/module/sdk/navigation.js +143 -0
- package/lib/module/sdk/networkInterceptor.js +401 -0
- package/lib/module/sdk/utils.js +342 -0
- package/lib/module/types/expo-router.d.js +2 -0
- package/lib/module/types/index.js +2 -0
- package/lib/typescript/NativeRejourney.d.ts +147 -0
- package/lib/typescript/components/Mask.d.ts +39 -0
- package/lib/typescript/index.d.ts +117 -0
- package/lib/typescript/sdk/autoTracking.d.ts +204 -0
- package/lib/typescript/sdk/constants.d.ts +120 -0
- package/lib/typescript/sdk/errorTracking.d.ts +32 -0
- package/lib/typescript/sdk/index.d.ts +9 -0
- package/lib/typescript/sdk/metricsTracking.d.ts +58 -0
- package/lib/typescript/sdk/navigation.d.ts +33 -0
- package/lib/typescript/sdk/networkInterceptor.d.ts +47 -0
- package/lib/typescript/sdk/utils.d.ts +148 -0
- package/lib/typescript/types/index.d.ts +624 -0
- package/package.json +102 -0
- package/rejourney.podspec +21 -0
- package/src/NativeRejourney.ts +165 -0
- package/src/components/Mask.tsx +80 -0
- package/src/index.ts +1459 -0
- package/src/sdk/autoTracking.ts +1373 -0
- package/src/sdk/constants.ts +134 -0
- package/src/sdk/errorTracking.ts +231 -0
- package/src/sdk/index.ts +11 -0
- package/src/sdk/metricsTracking.ts +232 -0
- package/src/sdk/navigation.ts +157 -0
- package/src/sdk/networkInterceptor.ts +440 -0
- package/src/sdk/utils.ts +369 -0
- package/src/types/expo-router.d.ts +7 -0
- package/src/types/index.ts +739 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
//
|
|
2
|
+
// RJCrashHandler.h
|
|
3
|
+
// Rejourney
|
|
4
|
+
//
|
|
5
|
+
// Handles uncaught exceptions and signals to generate crash reports.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#import <Foundation/Foundation.h>
|
|
9
|
+
|
|
10
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Block type for pre-crash callbacks.
|
|
14
|
+
* These are called synchronously before the crash report is written.
|
|
15
|
+
* Use sparingly - only for critical cleanup like flushing video segments.
|
|
16
|
+
*/
|
|
17
|
+
typedef void (^RJPreCrashCallback)(void);
|
|
18
|
+
|
|
19
|
+
@interface RJCrashHandler : NSObject
|
|
20
|
+
|
|
21
|
+
+ (instancetype)sharedInstance;
|
|
22
|
+
|
|
23
|
+
/// Starts monitoring for crashes
|
|
24
|
+
- (void)startMonitoring;
|
|
25
|
+
|
|
26
|
+
/// Checks if there is a pending crash report from a previous launch
|
|
27
|
+
- (BOOL)hasPendingCrashReport;
|
|
28
|
+
|
|
29
|
+
/// Loads the pending crash report and clears it from disk
|
|
30
|
+
- (nullable NSDictionary *)loadAndPurgePendingCrashReport;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Registers a callback to be invoked immediately when a crash is detected,
|
|
34
|
+
* before the crash report is written. This allows critical cleanup operations
|
|
35
|
+
* like flushing video segments.
|
|
36
|
+
*
|
|
37
|
+
* @warning Callbacks must be extremely fast and async-signal-safe for signal handlers.
|
|
38
|
+
* Exception handlers have more flexibility but should still be quick.
|
|
39
|
+
*
|
|
40
|
+
* @param callback The callback block to invoke on crash.
|
|
41
|
+
*/
|
|
42
|
+
- (void)registerPreCrashCallback:(RJPreCrashCallback)callback;
|
|
43
|
+
|
|
44
|
+
@end
|
|
45
|
+
|
|
46
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
//
|
|
2
|
+
// RJCrashHandler.m
|
|
3
|
+
// Rejourney
|
|
4
|
+
//
|
|
5
|
+
// Industry-standard crash handling with proper signal handling and
|
|
6
|
+
// fingerprinting.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
#import "RJCrashHandler.h"
|
|
10
|
+
#import "../Core/RJLogger.h"
|
|
11
|
+
#import <CommonCrypto/CommonDigest.h>
|
|
12
|
+
#import <UIKit/UIKit.h>
|
|
13
|
+
#include <execinfo.h>
|
|
14
|
+
#include <signal.h>
|
|
15
|
+
|
|
16
|
+
static NSUncaughtExceptionHandler *originalExceptionHandler = NULL;
|
|
17
|
+
static NSString *const kRJCrashReportFileName = @"rj_crash_report.json";
|
|
18
|
+
static NSString *const kRJCurrentSessionIdKey = @"rj_current_session_id";
|
|
19
|
+
|
|
20
|
+
static struct sigaction originalSigActions[32];
|
|
21
|
+
static volatile sig_atomic_t handlingSignal = 0;
|
|
22
|
+
|
|
23
|
+
static RJPreCrashCallback rj_preCrashCallback = nil;
|
|
24
|
+
|
|
25
|
+
static void rj_invokePreCrashCallback(void);
|
|
26
|
+
|
|
27
|
+
@implementation RJCrashHandler
|
|
28
|
+
|
|
29
|
+
+ (instancetype)sharedInstance {
|
|
30
|
+
static RJCrashHandler *sharedInstance = nil;
|
|
31
|
+
static dispatch_once_t onceToken;
|
|
32
|
+
dispatch_once(&onceToken, ^{
|
|
33
|
+
sharedInstance = [[self alloc] init];
|
|
34
|
+
});
|
|
35
|
+
return sharedInstance;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
- (void)registerPreCrashCallback:(RJPreCrashCallback)callback {
|
|
39
|
+
rj_preCrashCallback = [callback copy];
|
|
40
|
+
RJLogDebug(@"Registered pre-crash callback for video segment recovery");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
- (void)startMonitoring {
|
|
44
|
+
|
|
45
|
+
originalExceptionHandler = NSGetUncaughtExceptionHandler();
|
|
46
|
+
NSSetUncaughtExceptionHandler(&rj_uncaughtExceptionHandler);
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
int signals[] = {SIGABRT, SIGILL, SIGSEGV, SIGFPE, SIGBUS, SIGPIPE, SIGTRAP};
|
|
51
|
+
int numSignals = sizeof(signals) / sizeof(signals[0]);
|
|
52
|
+
|
|
53
|
+
for (int i = 0; i < numSignals; i++) {
|
|
54
|
+
struct sigaction action;
|
|
55
|
+
memset(&action, 0, sizeof(action));
|
|
56
|
+
action.sa_sigaction = rj_signalActionHandler;
|
|
57
|
+
action.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
|
58
|
+
sigemptyset(&action.sa_mask);
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
sigaction(signals[i], &action, &originalSigActions[signals[i]]);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
RJLogDebug(@"RJCrashHandler started monitoring (using sigaction)");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
static void rj_invokePreCrashCallback(void) {
|
|
68
|
+
if (rj_preCrashCallback) {
|
|
69
|
+
@try {
|
|
70
|
+
rj_preCrashCallback();
|
|
71
|
+
} @catch (NSException *e) {
|
|
72
|
+
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
- (BOOL)hasPendingCrashReport {
|
|
78
|
+
NSString *path = [self crashReportPath];
|
|
79
|
+
return [[NSFileManager defaultManager] fileExistsAtPath:path];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
- (NSDictionary *)loadAndPurgePendingCrashReport {
|
|
83
|
+
NSString *path = [self crashReportPath];
|
|
84
|
+
if (![[NSFileManager defaultManager] fileExistsAtPath:path]) {
|
|
85
|
+
return nil;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
NSData *data = [NSData dataWithContentsOfFile:path];
|
|
89
|
+
if (!data)
|
|
90
|
+
return nil;
|
|
91
|
+
|
|
92
|
+
NSDictionary *report = [NSJSONSerialization JSONObjectWithData:data
|
|
93
|
+
options:0
|
|
94
|
+
error:nil];
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
[[NSFileManager defaultManager] removeItemAtPath:path error:nil];
|
|
98
|
+
|
|
99
|
+
return report;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
#pragma mark - Private Methods
|
|
103
|
+
|
|
104
|
+
- (NSString *)crashReportPath {
|
|
105
|
+
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory,
|
|
106
|
+
NSUserDomainMask, YES);
|
|
107
|
+
NSString *cacheDir = [paths objectAtIndex:0];
|
|
108
|
+
return [cacheDir stringByAppendingPathComponent:kRJCrashReportFileName];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
#pragma mark - Fingerprinting
|
|
112
|
+
|
|
113
|
+
+ (NSString *)generateFingerprintForException:(NSString *)exceptionName
|
|
114
|
+
stackTrace:(NSArray *)stackTrace {
|
|
115
|
+
NSMutableString *input =
|
|
116
|
+
[NSMutableString stringWithString:exceptionName ?: @""];
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
NSInteger frameCount = MIN(5, stackTrace.count);
|
|
120
|
+
for (NSInteger i = 0; i < frameCount; i++) {
|
|
121
|
+
NSString *frame = stackTrace[i];
|
|
122
|
+
|
|
123
|
+
NSString *cleaned = [frame
|
|
124
|
+
stringByReplacingOccurrencesOfString:@"0x[0-9a-fA-F]+"
|
|
125
|
+
withString:@""
|
|
126
|
+
options:NSRegularExpressionSearch
|
|
127
|
+
range:NSMakeRange(0, frame.length)];
|
|
128
|
+
[input appendString:cleaned];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
const char *cStr = [input UTF8String];
|
|
133
|
+
unsigned char digest[CC_SHA256_DIGEST_LENGTH];
|
|
134
|
+
CC_SHA256(cStr, (CC_LONG)strlen(cStr), digest);
|
|
135
|
+
|
|
136
|
+
NSMutableString *fingerprint =
|
|
137
|
+
[NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
|
|
138
|
+
for (int i = 0; i < 8; i++) {
|
|
139
|
+
[fingerprint appendFormat:@"%02x", digest[i]];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return fingerprint;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
#pragma mark - Handlers
|
|
146
|
+
|
|
147
|
+
void rj_uncaughtExceptionHandler(NSException *exception) {
|
|
148
|
+
RJLogDebug(@"[CRASH] EXCEPTION DETECTED: %@ - %@", exception.name,
|
|
149
|
+
exception.reason);
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
rj_invokePreCrashCallback();
|
|
154
|
+
|
|
155
|
+
NSString *sessionId = [[NSUserDefaults standardUserDefaults]
|
|
156
|
+
stringForKey:kRJCurrentSessionIdKey];
|
|
157
|
+
|
|
158
|
+
NSMutableDictionary *report = [NSMutableDictionary new];
|
|
159
|
+
report[@"timestamp"] = @([[NSDate date] timeIntervalSince1970] * 1000);
|
|
160
|
+
report[@"exceptionName"] = exception.name;
|
|
161
|
+
report[@"reason"] = exception.reason ?: @"";
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
NSArray *stackSymbols = exception.callStackSymbols;
|
|
166
|
+
if (!stackSymbols || stackSymbols.count == 0) {
|
|
167
|
+
|
|
168
|
+
void *callstack[128];
|
|
169
|
+
int frames = backtrace(callstack, 128);
|
|
170
|
+
char **strs = backtrace_symbols(callstack, frames);
|
|
171
|
+
NSMutableArray *stack = [NSMutableArray arrayWithCapacity:frames];
|
|
172
|
+
for (int i = 0; i < frames; i++) {
|
|
173
|
+
[stack addObject:[NSString stringWithUTF8String:strs[i]]];
|
|
174
|
+
}
|
|
175
|
+
free(strs);
|
|
176
|
+
stackSymbols = stack;
|
|
177
|
+
RJLogDebug(@"[CRASH] Used backtrace() fallback for stack trace (%d frames)",
|
|
178
|
+
frames);
|
|
179
|
+
} else {
|
|
180
|
+
RJLogDebug(@"[CRASH] Using exception.callStackSymbols (%lu frames)",
|
|
181
|
+
(unsigned long)stackSymbols.count);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
report[@"stackTrace"] = stackSymbols ?: @[];
|
|
185
|
+
|
|
186
|
+
if (sessionId) {
|
|
187
|
+
report[@"sessionId"] = sessionId;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
report[@"fingerprint"] =
|
|
192
|
+
[RJCrashHandler generateFingerprintForException:exception.name
|
|
193
|
+
stackTrace:stackSymbols ?: @[]];
|
|
194
|
+
|
|
195
|
+
UIDevice *device = [UIDevice currentDevice];
|
|
196
|
+
report[@"deviceMetadata"] = @{
|
|
197
|
+
@"model" : device.model,
|
|
198
|
+
@"systemName" : device.systemName,
|
|
199
|
+
@"systemVersion" : device.systemVersion,
|
|
200
|
+
@"identifierForVendor" : device.identifierForVendor.UUIDString ?: @"unknown"
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
NSData *jsonData =
|
|
204
|
+
[NSJSONSerialization dataWithJSONObject:report
|
|
205
|
+
options:NSJSONWritingPrettyPrinted
|
|
206
|
+
error:nil];
|
|
207
|
+
|
|
208
|
+
NSString *path = [[RJCrashHandler sharedInstance] crashReportPath];
|
|
209
|
+
[jsonData writeToFile:path atomically:YES];
|
|
210
|
+
|
|
211
|
+
RJLogDebug(@"[CRASH] Crash report saved to %@", path);
|
|
212
|
+
|
|
213
|
+
if (originalExceptionHandler) {
|
|
214
|
+
originalExceptionHandler(exception);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
void rj_signalActionHandler(int signal, siginfo_t *info, void *context) {
|
|
219
|
+
|
|
220
|
+
if (handlingSignal) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
handlingSignal = 1;
|
|
224
|
+
|
|
225
|
+
RJLogDebug(@"[CRASH] SIGNAL DETECTED: %d at address %p", signal,
|
|
226
|
+
info->si_addr);
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
rj_invokePreCrashCallback();
|
|
234
|
+
|
|
235
|
+
NSString *sessionId = [[NSUserDefaults standardUserDefaults]
|
|
236
|
+
stringForKey:kRJCurrentSessionIdKey];
|
|
237
|
+
|
|
238
|
+
NSMutableDictionary *report = [NSMutableDictionary new];
|
|
239
|
+
report[@"timestamp"] = @([[NSDate date] timeIntervalSince1970] * 1000);
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
NSString *signalName;
|
|
243
|
+
switch (signal) {
|
|
244
|
+
case SIGABRT:
|
|
245
|
+
signalName = @"SIGABRT (Abort)";
|
|
246
|
+
break;
|
|
247
|
+
case SIGSEGV:
|
|
248
|
+
signalName = @"SIGSEGV (Segmentation Fault)";
|
|
249
|
+
break;
|
|
250
|
+
case SIGBUS:
|
|
251
|
+
signalName = @"SIGBUS (Bus Error)";
|
|
252
|
+
break;
|
|
253
|
+
case SIGFPE:
|
|
254
|
+
signalName = @"SIGFPE (Floating Point Exception)";
|
|
255
|
+
break;
|
|
256
|
+
case SIGILL:
|
|
257
|
+
signalName = @"SIGILL (Illegal Instruction)";
|
|
258
|
+
break;
|
|
259
|
+
case SIGPIPE:
|
|
260
|
+
signalName = @"SIGPIPE (Broken Pipe)";
|
|
261
|
+
break;
|
|
262
|
+
case SIGTRAP:
|
|
263
|
+
signalName = @"SIGTRAP (Trace Trap)";
|
|
264
|
+
break;
|
|
265
|
+
default:
|
|
266
|
+
signalName = [NSString stringWithFormat:@"Signal %d", signal];
|
|
267
|
+
break;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
report[@"exceptionName"] = signalName;
|
|
271
|
+
report[@"reason"] = [NSString
|
|
272
|
+
stringWithFormat:@"%@ at address %p", signalName, info->si_addr];
|
|
273
|
+
if (sessionId) {
|
|
274
|
+
report[@"sessionId"] = sessionId;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
void *callstack[128];
|
|
279
|
+
int frames = backtrace(callstack, 128);
|
|
280
|
+
char **strs = backtrace_symbols(callstack, frames);
|
|
281
|
+
NSMutableArray *stack = [NSMutableArray arrayWithCapacity:frames];
|
|
282
|
+
for (int i = 0; i < frames; i++) {
|
|
283
|
+
[stack addObject:[NSString stringWithUTF8String:strs[i]]];
|
|
284
|
+
}
|
|
285
|
+
free(strs);
|
|
286
|
+
report[@"stackTrace"] = stack;
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
report[@"fingerprint"] =
|
|
290
|
+
[RJCrashHandler generateFingerprintForException:signalName
|
|
291
|
+
stackTrace:stack];
|
|
292
|
+
|
|
293
|
+
UIDevice *device = [UIDevice currentDevice];
|
|
294
|
+
report[@"deviceMetadata"] = @{
|
|
295
|
+
@"model" : device.model,
|
|
296
|
+
@"systemName" : device.systemName,
|
|
297
|
+
@"systemVersion" : device.systemVersion
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
NSData *jsonData =
|
|
301
|
+
[NSJSONSerialization dataWithJSONObject:report
|
|
302
|
+
options:NSJSONWritingPrettyPrinted
|
|
303
|
+
error:nil];
|
|
304
|
+
NSString *path = [[RJCrashHandler sharedInstance] crashReportPath];
|
|
305
|
+
[jsonData writeToFile:path atomically:YES];
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
struct sigaction *original = &originalSigActions[signal];
|
|
309
|
+
sigaction(signal, original, NULL);
|
|
310
|
+
raise(signal);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
@end
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
//
|
|
2
|
+
// RJMotionEvent.h
|
|
3
|
+
// Rejourney
|
|
4
|
+
//
|
|
5
|
+
// Motion event data structure for gesture replay reconstruction.
|
|
6
|
+
// Motion events capture scroll/pan/swipe dynamics for timeline events.
|
|
7
|
+
//
|
|
8
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
9
|
+
// you may not use this file except in compliance with the License.
|
|
10
|
+
// You may obtain a copy of the License at
|
|
11
|
+
//
|
|
12
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
13
|
+
//
|
|
14
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
15
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
16
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17
|
+
// See the License for the specific language governing permissions and
|
|
18
|
+
// limitations under the License.
|
|
19
|
+
//
|
|
20
|
+
// Copyright (c) 2026 Rejourney
|
|
21
|
+
//
|
|
22
|
+
|
|
23
|
+
#import <CoreGraphics/CoreGraphics.h>
|
|
24
|
+
#import <Foundation/Foundation.h>
|
|
25
|
+
|
|
26
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Motion curve types for animation reconstruction.
|
|
30
|
+
*/
|
|
31
|
+
typedef NS_ENUM(NSInteger, RJMotionCurve) {
|
|
32
|
+
/// Linear motion (constant velocity)
|
|
33
|
+
RJMotionCurveLinear = 0,
|
|
34
|
+
|
|
35
|
+
/// Exponential decay (iOS scroll deceleration)
|
|
36
|
+
RJMotionCurveExponentialDecay = 1,
|
|
37
|
+
|
|
38
|
+
/// Ease out (quick start, slow end)
|
|
39
|
+
RJMotionCurveEaseOut = 2,
|
|
40
|
+
|
|
41
|
+
/// Bounce (overshoots then settles)
|
|
42
|
+
RJMotionCurveBounce = 3,
|
|
43
|
+
|
|
44
|
+
/// Spring (elastic oscillation)
|
|
45
|
+
RJMotionCurveSpring = 4
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Motion event types.
|
|
50
|
+
*/
|
|
51
|
+
typedef NS_ENUM(NSInteger, RJMotionType) {
|
|
52
|
+
/// Scroll gesture motion
|
|
53
|
+
RJMotionTypeScroll = 0,
|
|
54
|
+
|
|
55
|
+
/// Pan gesture motion
|
|
56
|
+
RJMotionTypePan = 1,
|
|
57
|
+
|
|
58
|
+
/// Swipe gesture motion
|
|
59
|
+
RJMotionTypeSwipe = 2,
|
|
60
|
+
|
|
61
|
+
/// Fling (momentum) motion
|
|
62
|
+
RJMotionTypeFling = 3
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Represents a motion event for replay reconstruction.
|
|
67
|
+
*
|
|
68
|
+
* Motion events capture the dynamics of scroll/pan/swipe gestures
|
|
69
|
+
* so that the player can reconstruct smooth motion between sparse keyframes.
|
|
70
|
+
*
|
|
71
|
+
* ## Usage
|
|
72
|
+
* @code
|
|
73
|
+
* RJMotionEvent *event = [[RJMotionEvent alloc] init];
|
|
74
|
+
* event.type = RJMotionTypeScroll;
|
|
75
|
+
* event.t0 = 1234.0; // start time in ms
|
|
76
|
+
* event.t1 = 1560.0; // end time in ms
|
|
77
|
+
* event.dx = 0; // horizontal displacement
|
|
78
|
+
* event.dy = -820; // vertical displacement
|
|
79
|
+
* event.v0 = 2.1; // initial velocity
|
|
80
|
+
* event.curve = RJMotionCurveExponentialDecay;
|
|
81
|
+
*
|
|
82
|
+
* NSDictionary *dict = [event toDictionary];
|
|
83
|
+
* @endcode
|
|
84
|
+
*/
|
|
85
|
+
@interface RJMotionEvent : NSObject
|
|
86
|
+
|
|
87
|
+
#pragma mark - Motion Properties
|
|
88
|
+
|
|
89
|
+
/// Type of motion (scroll, pan, swipe, fling)
|
|
90
|
+
@property(nonatomic, assign) RJMotionType type;
|
|
91
|
+
|
|
92
|
+
/// Start timestamp in milliseconds
|
|
93
|
+
@property(nonatomic, assign) NSTimeInterval t0;
|
|
94
|
+
|
|
95
|
+
/// End timestamp in milliseconds
|
|
96
|
+
@property(nonatomic, assign) NSTimeInterval t1;
|
|
97
|
+
|
|
98
|
+
/// Horizontal displacement in points
|
|
99
|
+
@property(nonatomic, assign) CGFloat dx;
|
|
100
|
+
|
|
101
|
+
/// Vertical displacement in points
|
|
102
|
+
@property(nonatomic, assign) CGFloat dy;
|
|
103
|
+
|
|
104
|
+
/// Initial velocity in points per second
|
|
105
|
+
@property(nonatomic, assign) CGFloat v0;
|
|
106
|
+
|
|
107
|
+
/// Final velocity in points per second (usually 0 for deceleration)
|
|
108
|
+
@property(nonatomic, assign) CGFloat v1;
|
|
109
|
+
|
|
110
|
+
/// Motion curve for interpolation
|
|
111
|
+
@property(nonatomic, assign) RJMotionCurve curve;
|
|
112
|
+
|
|
113
|
+
/// Target view identifier (optional)
|
|
114
|
+
@property(nonatomic, copy, nullable) NSString *targetId;
|
|
115
|
+
|
|
116
|
+
#pragma mark - Computed Properties
|
|
117
|
+
|
|
118
|
+
/// Duration in milliseconds
|
|
119
|
+
@property(nonatomic, readonly) NSTimeInterval duration;
|
|
120
|
+
|
|
121
|
+
/// Total distance traveled
|
|
122
|
+
@property(nonatomic, readonly) CGFloat distance;
|
|
123
|
+
|
|
124
|
+
/// Average velocity
|
|
125
|
+
@property(nonatomic, readonly) CGFloat averageVelocity;
|
|
126
|
+
|
|
127
|
+
/// Direction angle in radians
|
|
128
|
+
@property(nonatomic, readonly) CGFloat direction;
|
|
129
|
+
|
|
130
|
+
#pragma mark - Serialization
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Converts the motion event to a dictionary for JSON serialization.
|
|
134
|
+
*
|
|
135
|
+
* @return Dictionary with all motion event properties.
|
|
136
|
+
*/
|
|
137
|
+
- (NSDictionary *)toDictionary;
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Creates a motion event from a dictionary.
|
|
141
|
+
*
|
|
142
|
+
* @param dict Dictionary with motion event properties.
|
|
143
|
+
* @return Motion event or nil if dictionary is invalid.
|
|
144
|
+
*/
|
|
145
|
+
+ (nullable instancetype)eventFromDictionary:(NSDictionary *)dict;
|
|
146
|
+
|
|
147
|
+
#pragma mark - Curve Helpers
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Returns the string name for a motion curve.
|
|
151
|
+
*/
|
|
152
|
+
+ (NSString *)curveNameForType:(RJMotionCurve)curve;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Parses a curve name string to enum value.
|
|
156
|
+
*/
|
|
157
|
+
+ (RJMotionCurve)curveTypeFromName:(NSString *)name;
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Returns the string name for a motion type.
|
|
161
|
+
*/
|
|
162
|
+
+ (NSString *)motionTypeName:(RJMotionType)type;
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Parses a motion type name string to enum value.
|
|
166
|
+
*/
|
|
167
|
+
+ (RJMotionType)motionTypeFromName:(NSString *)name;
|
|
168
|
+
|
|
169
|
+
#pragma mark - Instance Convenience Methods
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Returns the string name for this event's motion type.
|
|
173
|
+
*/
|
|
174
|
+
- (NSString *)typeName;
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Returns the string name for this event's curve type.
|
|
178
|
+
*/
|
|
179
|
+
- (NSString *)curveName;
|
|
180
|
+
|
|
181
|
+
@end
|
|
182
|
+
|
|
183
|
+
NS_ASSUME_NONNULL_END
|