react-native-frame-capture 1.0.1
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/FrameCapture.podspec +21 -0
- package/LICENSE +20 -0
- package/README.md +158 -0
- package/android/build.gradle +77 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +20 -0
- package/android/src/main/java/com/framecapture/CaptureManager.kt +831 -0
- package/android/src/main/java/com/framecapture/Constants.kt +196 -0
- package/android/src/main/java/com/framecapture/ErrorHandler.kt +165 -0
- package/android/src/main/java/com/framecapture/FrameCaptureModule.kt +653 -0
- package/android/src/main/java/com/framecapture/FrameCapturePackage.kt +32 -0
- package/android/src/main/java/com/framecapture/OverlayRenderer.kt +423 -0
- package/android/src/main/java/com/framecapture/PermissionHandler.kt +150 -0
- package/android/src/main/java/com/framecapture/ScreenCaptureService.kt +366 -0
- package/android/src/main/java/com/framecapture/StorageManager.kt +221 -0
- package/android/src/main/java/com/framecapture/capture/BitmapProcessor.kt +157 -0
- package/android/src/main/java/com/framecapture/capture/CaptureEventEmitter.kt +120 -0
- package/android/src/main/java/com/framecapture/models/CaptureModels.kt +302 -0
- package/android/src/main/java/com/framecapture/models/EnumsAndExtensions.kt +60 -0
- package/android/src/main/java/com/framecapture/models/OverlayModels.kt +154 -0
- package/android/src/main/java/com/framecapture/service/CaptureNotificationManager.kt +286 -0
- package/android/src/main/java/com/framecapture/storage/StorageStrategies.kt +317 -0
- package/android/src/main/java/com/framecapture/utils/ValidationUtils.kt +379 -0
- package/app.plugin.js +1 -0
- package/ios/FrameCapture.h +5 -0
- package/ios/FrameCapture.mm +21 -0
- package/lib/module/NativeFrameCapture.js +24 -0
- package/lib/module/NativeFrameCapture.js.map +1 -0
- package/lib/module/api.js +146 -0
- package/lib/module/api.js.map +1 -0
- package/lib/module/constants.js +67 -0
- package/lib/module/constants.js.map +1 -0
- package/lib/module/errors.js +19 -0
- package/lib/module/errors.js.map +1 -0
- package/lib/module/events.js +58 -0
- package/lib/module/events.js.map +1 -0
- package/lib/module/index.js +24 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/normalize.js +51 -0
- package/lib/module/normalize.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/types.js +165 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/validation.js +190 -0
- package/lib/module/validation.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/plugin/src/index.d.ts +4 -0
- package/lib/typescript/plugin/src/index.d.ts.map +1 -0
- package/lib/typescript/src/NativeFrameCapture.d.ts +75 -0
- package/lib/typescript/src/NativeFrameCapture.d.ts.map +1 -0
- package/lib/typescript/src/api.d.ts +66 -0
- package/lib/typescript/src/api.d.ts.map +1 -0
- package/lib/typescript/src/constants.d.ts +41 -0
- package/lib/typescript/src/constants.d.ts.map +1 -0
- package/lib/typescript/src/errors.d.ts +14 -0
- package/lib/typescript/src/errors.d.ts.map +1 -0
- package/lib/typescript/src/events.d.ts +30 -0
- package/lib/typescript/src/events.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +12 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/normalize.d.ts +43 -0
- package/lib/typescript/src/normalize.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +247 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/lib/typescript/src/validation.d.ts +15 -0
- package/lib/typescript/src/validation.d.ts.map +1 -0
- package/package.json +196 -0
- package/plugin/build/index.js +48 -0
- package/src/NativeFrameCapture.ts +86 -0
- package/src/api.ts +189 -0
- package/src/constants.ts +69 -0
- package/src/errors.ts +21 -0
- package/src/events.ts +61 -0
- package/src/index.tsx +31 -0
- package/src/normalize.ts +81 -0
- package/src/types.ts +327 -0
- package/src/validation.ts +321 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
package com.framecapture
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Constants for the FrameCapture library
|
|
5
|
+
*
|
|
6
|
+
* Centralized configuration values including:
|
|
7
|
+
* - Capture constraints (intervals, quality, formats)
|
|
8
|
+
* - Storage thresholds
|
|
9
|
+
* - Notification configuration
|
|
10
|
+
* - Service actions and intent extras
|
|
11
|
+
* - Event names for JavaScript communication
|
|
12
|
+
* - Resource management timeouts
|
|
13
|
+
*/
|
|
14
|
+
object Constants {
|
|
15
|
+
|
|
16
|
+
// Capture interval constraints (in milliseconds)
|
|
17
|
+
const val MIN_INTERVAL = 100L
|
|
18
|
+
const val MAX_INTERVAL = 60000L
|
|
19
|
+
const val DEFAULT_INTERVAL = 1000L
|
|
20
|
+
|
|
21
|
+
// Image quality constraints (0-100)
|
|
22
|
+
const val MIN_QUALITY = 0
|
|
23
|
+
const val MAX_QUALITY = 100
|
|
24
|
+
const val DEFAULT_QUALITY = 80
|
|
25
|
+
|
|
26
|
+
// Default image format
|
|
27
|
+
const val DEFAULT_FORMAT = "jpeg"
|
|
28
|
+
|
|
29
|
+
// Capture mode strings
|
|
30
|
+
const val CAPTURE_MODE_INTERVAL = "interval"
|
|
31
|
+
|
|
32
|
+
// Storage warning threshold (100MB in bytes) - DEFAULT VALUE
|
|
33
|
+
const val DEFAULT_STORAGE_WARNING_THRESHOLD = 100L * 1024L * 1024L
|
|
34
|
+
|
|
35
|
+
// Storage location identifiers
|
|
36
|
+
const val STORAGE_LOCATION_PUBLIC = "public"
|
|
37
|
+
const val STORAGE_LOCATION_PRIVATE = "private"
|
|
38
|
+
|
|
39
|
+
// File naming - DEFAULT VALUES
|
|
40
|
+
const val DEFAULT_FILENAME_PREFIX = "capture_"
|
|
41
|
+
const val DEFAULT_FILENAME_DATE_FORMAT = "yyyyMMdd_HHmmss_SSS"
|
|
42
|
+
const val DEFAULT_FILENAME_FRAME_PADDING = 5 // Number of digits for frame number
|
|
43
|
+
|
|
44
|
+
// Image format extensions
|
|
45
|
+
const val FORMAT_EXTENSION_PNG = "png"
|
|
46
|
+
const val FORMAT_EXTENSION_JPEG = "jpg"
|
|
47
|
+
|
|
48
|
+
// MIME types
|
|
49
|
+
const val MIME_TYPE_PNG = "image/png"
|
|
50
|
+
const val MIME_TYPE_JPEG = "image/jpeg"
|
|
51
|
+
|
|
52
|
+
// Storage directories
|
|
53
|
+
const val TEMP_FRAMES_DIRECTORY = "captured_frames"
|
|
54
|
+
|
|
55
|
+
// Foreground service notification
|
|
56
|
+
const val NOTIFICATION_ID = 1001
|
|
57
|
+
const val CHANNEL_ID = "screen_capture_channel"
|
|
58
|
+
const val CHANNEL_NAME = "Screen Capture"
|
|
59
|
+
const val CHANNEL_DESCRIPTION = "Notifications for screen capture service"
|
|
60
|
+
const val CUSTOM_CHANNEL_ID_PREFIX = "screen_capture_custom_"
|
|
61
|
+
|
|
62
|
+
// Notification priority levels
|
|
63
|
+
const val NOTIFICATION_PRIORITY_HIGH = "high"
|
|
64
|
+
const val NOTIFICATION_PRIORITY_DEFAULT = "default"
|
|
65
|
+
const val NOTIFICATION_PRIORITY_LOW = "low"
|
|
66
|
+
|
|
67
|
+
// Notification action labels
|
|
68
|
+
const val NOTIFICATION_ACTION_PAUSE = "Pause"
|
|
69
|
+
const val NOTIFICATION_ACTION_RESUME = "Resume"
|
|
70
|
+
const val NOTIFICATION_ACTION_STOP = "Stop"
|
|
71
|
+
|
|
72
|
+
// Notification default values
|
|
73
|
+
const val NOTIFICATION_DEFAULT_TITLE = "Screen Capture Active"
|
|
74
|
+
const val NOTIFICATION_DEFAULT_DESCRIPTION = "Capturing frames..."
|
|
75
|
+
const val NOTIFICATION_DEFAULT_PAUSED_TITLE = "Screen Capture Paused"
|
|
76
|
+
const val NOTIFICATION_DEFAULT_PAUSED_DESCRIPTION = "{frameCount} frames captured"
|
|
77
|
+
const val NOTIFICATION_DEFAULT_UPDATE_INTERVAL = 10
|
|
78
|
+
|
|
79
|
+
// Notification action request codes
|
|
80
|
+
const val NOTIFICATION_REQUEST_CODE_STOP = 0
|
|
81
|
+
const val NOTIFICATION_REQUEST_CODE_PAUSE_RESUME = 1
|
|
82
|
+
|
|
83
|
+
// Notification template variable
|
|
84
|
+
const val NOTIFICATION_TEMPLATE_FRAME_COUNT = "{frameCount}"
|
|
85
|
+
|
|
86
|
+
// Service actions
|
|
87
|
+
const val ACTION_START_CAPTURE = "com.framecapture.START_CAPTURE"
|
|
88
|
+
const val ACTION_STOP_CAPTURE = "com.framecapture.STOP_CAPTURE"
|
|
89
|
+
const val ACTION_PAUSE_CAPTURE = "com.framecapture.PAUSE_CAPTURE"
|
|
90
|
+
const val ACTION_RESUME_CAPTURE = "com.framecapture.RESUME_CAPTURE"
|
|
91
|
+
|
|
92
|
+
// Intent extras
|
|
93
|
+
const val EXTRA_CAPTURE_OPTIONS = "capture_options"
|
|
94
|
+
const val EXTRA_PROJECTION_DATA = "projection_data"
|
|
95
|
+
|
|
96
|
+
// MediaProjection request code
|
|
97
|
+
const val REQUEST_MEDIA_PROJECTION = 1001
|
|
98
|
+
|
|
99
|
+
// Module name
|
|
100
|
+
const val MODULE_NAME = "FrameCapture"
|
|
101
|
+
|
|
102
|
+
// Event names
|
|
103
|
+
const val EVENT_FRAME_CAPTURED = "onFrameCaptured"
|
|
104
|
+
const val EVENT_CAPTURE_ERROR = "onCaptureError"
|
|
105
|
+
const val EVENT_CAPTURE_STOP = "onCaptureStop"
|
|
106
|
+
const val EVENT_CAPTURE_START = "onCaptureStart"
|
|
107
|
+
const val EVENT_STORAGE_WARNING = "onStorageWarning"
|
|
108
|
+
const val EVENT_CAPTURE_PAUSE = "onCapturePause"
|
|
109
|
+
const val EVENT_CAPTURE_RESUME = "onCaptureResume"
|
|
110
|
+
const val EVENT_OVERLAY_ERROR = "onOverlayError"
|
|
111
|
+
|
|
112
|
+
// Resource cleanup timeout (in milliseconds) - DEFAULT VALUES
|
|
113
|
+
const val DEFAULT_EXECUTOR_SHUTDOWN_TIMEOUT = 5000L
|
|
114
|
+
const val DEFAULT_EXECUTOR_FORCED_SHUTDOWN_TIMEOUT = 1000L
|
|
115
|
+
|
|
116
|
+
// ImageReader buffer count - DEFAULT VALUE
|
|
117
|
+
const val DEFAULT_IMAGE_READER_MAX_IMAGES = 2
|
|
118
|
+
|
|
119
|
+
// Image format constants
|
|
120
|
+
const val RGBA_BYTES_PER_PIXEL = 4
|
|
121
|
+
|
|
122
|
+
// Resolution scaling constraints
|
|
123
|
+
const val MIN_SCALE_RESOLUTION = 0.1f
|
|
124
|
+
const val MAX_SCALE_RESOLUTION = 1.0f
|
|
125
|
+
|
|
126
|
+
// Overlay rendering - DEFAULT VALUES
|
|
127
|
+
const val DEFAULT_OVERLAY_IMAGE_CACHE_SIZE = 10 * 1024 * 1024 // 10MB in bytes
|
|
128
|
+
const val OVERLAY_DEFAULT_PADDING = 10 // Padding from edges in pixels
|
|
129
|
+
const val MIN_OVERLAY_OPACITY = 0.0f
|
|
130
|
+
const val MAX_OVERLAY_OPACITY = 1.0f
|
|
131
|
+
|
|
132
|
+
// Overlay types
|
|
133
|
+
const val OVERLAY_TYPE_TEXT = "text"
|
|
134
|
+
const val OVERLAY_TYPE_IMAGE = "image"
|
|
135
|
+
|
|
136
|
+
// Overlay position presets
|
|
137
|
+
const val POSITION_TOP_LEFT = "top-left"
|
|
138
|
+
const val POSITION_TOP_RIGHT = "top-right"
|
|
139
|
+
const val POSITION_BOTTOM_LEFT = "bottom-left"
|
|
140
|
+
const val POSITION_BOTTOM_RIGHT = "bottom-right"
|
|
141
|
+
const val POSITION_CENTER = "center"
|
|
142
|
+
|
|
143
|
+
// Overlay position units
|
|
144
|
+
const val POSITION_UNIT_PERCENTAGE = "percentage"
|
|
145
|
+
const val POSITION_UNIT_PIXELS = "pixels"
|
|
146
|
+
|
|
147
|
+
// Template variables
|
|
148
|
+
const val TEMPLATE_VAR_FRAME_NUMBER = "{frameNumber}"
|
|
149
|
+
const val TEMPLATE_VAR_SESSION_ID = "{sessionId}"
|
|
150
|
+
const val TEMPLATE_VAR_TIMESTAMP = "{timestamp}"
|
|
151
|
+
|
|
152
|
+
// Timestamp format for overlays
|
|
153
|
+
const val OVERLAY_TIMESTAMP_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
|
|
154
|
+
const val OVERLAY_TIMESTAMP_TIMEZONE = "UTC"
|
|
155
|
+
|
|
156
|
+
// Text style values
|
|
157
|
+
const val TEXT_WEIGHT_BOLD = "bold"
|
|
158
|
+
const val TEXT_WEIGHT_NORMAL = "normal"
|
|
159
|
+
const val TEXT_ALIGN_LEFT = "left"
|
|
160
|
+
const val TEXT_ALIGN_CENTER = "center"
|
|
161
|
+
const val TEXT_ALIGN_RIGHT = "right"
|
|
162
|
+
|
|
163
|
+
// Text style defaults
|
|
164
|
+
const val TEXT_DEFAULT_FONT_SIZE = 14
|
|
165
|
+
const val TEXT_DEFAULT_COLOR = "#FFFFFF"
|
|
166
|
+
const val TEXT_DEFAULT_BACKGROUND_COLOR = "#00000080"
|
|
167
|
+
const val TEXT_DEFAULT_PADDING = 8
|
|
168
|
+
|
|
169
|
+
// Image overlay defaults
|
|
170
|
+
const val IMAGE_DEFAULT_OPACITY = 1.0f
|
|
171
|
+
|
|
172
|
+
// URI schemes
|
|
173
|
+
const val URI_SCHEME_FILE = "file"
|
|
174
|
+
const val URI_SCHEME_CONTENT = "content"
|
|
175
|
+
|
|
176
|
+
// Resource types
|
|
177
|
+
const val RESOURCE_TYPE_DRAWABLE = "drawable"
|
|
178
|
+
|
|
179
|
+
// Hex color validation
|
|
180
|
+
const val HEX_COLOR_LENGTH_SHORT = 3 // #RGB
|
|
181
|
+
const val HEX_COLOR_LENGTH_MEDIUM = 6 // #RRGGBB
|
|
182
|
+
const val HEX_COLOR_LENGTH_LONG = 8 // #AARRGGBB
|
|
183
|
+
|
|
184
|
+
// Error detail keys
|
|
185
|
+
const val ERROR_DETAIL_PERMISSION = "permission"
|
|
186
|
+
const val ERROR_DETAIL_CURRENT_STATE = "currentState"
|
|
187
|
+
const val ERROR_DETAIL_AVAILABLE_SPACE = "availableSpace"
|
|
188
|
+
const val ERROR_DETAIL_HEAP_SIZE = "heapSize"
|
|
189
|
+
const val ERROR_DETAIL_USED_MEMORY = "usedMemory"
|
|
190
|
+
const val ERROR_DETAIL_ERRORS = "errors"
|
|
191
|
+
const val ERROR_DETAIL_ERROR_TYPE = "errorType"
|
|
192
|
+
|
|
193
|
+
// Event payload keys
|
|
194
|
+
const val EVENT_KEY_AVAILABLE_SPACE = "availableSpace"
|
|
195
|
+
const val EVENT_KEY_THRESHOLD = "threshold"
|
|
196
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
package com.framecapture
|
|
2
|
+
|
|
3
|
+
import android.util.Log
|
|
4
|
+
import com.facebook.react.bridge.Arguments
|
|
5
|
+
import com.facebook.react.bridge.Promise
|
|
6
|
+
import com.facebook.react.bridge.WritableMap
|
|
7
|
+
import com.framecapture.models.CaptureState
|
|
8
|
+
import com.framecapture.models.ErrorCode
|
|
9
|
+
import java.io.IOException
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Handles error classification, formatting, and reporting
|
|
13
|
+
*
|
|
14
|
+
* Provides consistent error handling across the module by:
|
|
15
|
+
* - Classifying exceptions into appropriate ErrorCode values
|
|
16
|
+
* - Formatting error details for JavaScript consumption
|
|
17
|
+
* - Coordinating error emission and cleanup
|
|
18
|
+
*
|
|
19
|
+
* Uses dependency injection for storage space and capture state checks
|
|
20
|
+
* to avoid tight coupling with other components.
|
|
21
|
+
*/
|
|
22
|
+
class ErrorHandler(
|
|
23
|
+
private val getStorageSpace: () -> Long,
|
|
24
|
+
private val getCaptureState: () -> CaptureState
|
|
25
|
+
) {
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Classifies exception into error code, message, and details
|
|
29
|
+
*
|
|
30
|
+
* Maps common exceptions to appropriate ErrorCode values and provides
|
|
31
|
+
* contextual details for debugging (e.g., available storage, current state).
|
|
32
|
+
*
|
|
33
|
+
* @param error The exception to classify
|
|
34
|
+
* @return Triple of (ErrorCode, error message, optional details map)
|
|
35
|
+
*/
|
|
36
|
+
fun classifyError(error: Exception): Triple<ErrorCode, String, Map<String, Any>?> {
|
|
37
|
+
return when (error) {
|
|
38
|
+
is SecurityException -> Triple(
|
|
39
|
+
ErrorCode.PERMISSION_DENIED,
|
|
40
|
+
"Required permission not granted: ${error.message}",
|
|
41
|
+
mapOf(Constants.ERROR_DETAIL_PERMISSION to "MEDIA_PROJECTION")
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
is IllegalStateException -> Triple(
|
|
45
|
+
ErrorCode.ALREADY_CAPTURING,
|
|
46
|
+
"Capture session is already active: ${error.message}",
|
|
47
|
+
mapOf(Constants.ERROR_DETAIL_CURRENT_STATE to getCaptureState().value)
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
is IllegalArgumentException -> Triple(
|
|
51
|
+
ErrorCode.INVALID_OPTIONS,
|
|
52
|
+
"Invalid configuration: ${error.message}",
|
|
53
|
+
null
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
is IOException -> Triple(
|
|
57
|
+
ErrorCode.STORAGE_ERROR,
|
|
58
|
+
"Failed to save frame: ${error.message}",
|
|
59
|
+
mapOf(Constants.ERROR_DETAIL_AVAILABLE_SPACE to getStorageSpace())
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
is OutOfMemoryError -> Triple(
|
|
63
|
+
ErrorCode.SYSTEM_ERROR,
|
|
64
|
+
"Out of memory during capture",
|
|
65
|
+
mapOf(Constants.ERROR_DETAIL_HEAP_SIZE to Runtime.getRuntime().maxMemory())
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
else -> Triple(
|
|
69
|
+
ErrorCode.SYSTEM_ERROR,
|
|
70
|
+
"Unexpected error: ${error.message ?: "Unknown error"}",
|
|
71
|
+
null
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Creates error map for promise rejection and event emission
|
|
78
|
+
*
|
|
79
|
+
* Formats error information into a WritableMap that can be sent to JavaScript.
|
|
80
|
+
* Handles various data types in the details map (String, Int, Long, Boolean, List).
|
|
81
|
+
*
|
|
82
|
+
* @param code Error code enum value
|
|
83
|
+
* @param message Human-readable error message
|
|
84
|
+
* @param details Optional map of additional error context
|
|
85
|
+
* @return WritableMap formatted for React Native bridge
|
|
86
|
+
*/
|
|
87
|
+
fun createErrorMap(
|
|
88
|
+
code: ErrorCode,
|
|
89
|
+
message: String,
|
|
90
|
+
details: Map<String, Any>?
|
|
91
|
+
): WritableMap {
|
|
92
|
+
return Arguments.createMap().apply {
|
|
93
|
+
putString("code", code.value)
|
|
94
|
+
putString("message", message)
|
|
95
|
+
details?.let { detailsMap ->
|
|
96
|
+
val detailsWritableMap = Arguments.createMap()
|
|
97
|
+
detailsMap.forEach { (key, value) ->
|
|
98
|
+
when (value) {
|
|
99
|
+
is String -> detailsWritableMap.putString(key, value)
|
|
100
|
+
is Int -> detailsWritableMap.putInt(key, value)
|
|
101
|
+
is Double -> detailsWritableMap.putDouble(key, value)
|
|
102
|
+
is Long -> detailsWritableMap.putDouble(key, value.toDouble())
|
|
103
|
+
is Boolean -> detailsWritableMap.putBoolean(key, value)
|
|
104
|
+
is List<*> -> {
|
|
105
|
+
val array = Arguments.createArray()
|
|
106
|
+
value.forEach { item ->
|
|
107
|
+
when (item) {
|
|
108
|
+
is String -> array.pushString(item)
|
|
109
|
+
else -> array.pushString(item.toString())
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
detailsWritableMap.putArray(key, array)
|
|
113
|
+
}
|
|
114
|
+
else -> detailsWritableMap.putString(key, value.toString())
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
putMap("details", detailsWritableMap)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Handles error with logging, classification, and promise rejection
|
|
124
|
+
*
|
|
125
|
+
* Orchestrates the complete error handling flow:
|
|
126
|
+
* 1. Classifies the error
|
|
127
|
+
* 2. Logs for debugging
|
|
128
|
+
* 3. Performs cleanup via callback
|
|
129
|
+
* 4. Emits error event to JavaScript
|
|
130
|
+
* 5. Rejects promise if provided
|
|
131
|
+
*
|
|
132
|
+
* @param error The exception that occurred
|
|
133
|
+
* @param promise Optional promise to reject
|
|
134
|
+
* @param onEmitError Callback to emit error event
|
|
135
|
+
* @param onCleanup Callback to perform cleanup
|
|
136
|
+
*/
|
|
137
|
+
fun handleError(
|
|
138
|
+
error: Exception,
|
|
139
|
+
promise: Promise?,
|
|
140
|
+
onEmitError: (ErrorCode, String, Map<String, Any>?) -> Unit,
|
|
141
|
+
onCleanup: () -> Unit
|
|
142
|
+
) {
|
|
143
|
+
val (code, message, details) = classifyError(error)
|
|
144
|
+
|
|
145
|
+
// Log for debugging
|
|
146
|
+
Log.e(TAG, "Capture error: $message", error)
|
|
147
|
+
|
|
148
|
+
// Clean up resources on error
|
|
149
|
+
try {
|
|
150
|
+
onCleanup()
|
|
151
|
+
} catch (cleanupError: Exception) {
|
|
152
|
+
Log.e(TAG, "Error during cleanup: ${cleanupError.message}", cleanupError)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Emit error event
|
|
156
|
+
onEmitError(code, message, details)
|
|
157
|
+
|
|
158
|
+
// Reject promise if provided
|
|
159
|
+
promise?.reject(code.value, message, createErrorMap(code, message, details))
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
companion object {
|
|
163
|
+
private const val TAG = "ErrorHandler"
|
|
164
|
+
}
|
|
165
|
+
}
|